Despite the fact that abstraction is such a natural process for human beings, developing an appropriate model for a software system is perhaps the most difficult aspect of software engineering, because
There are an unlimited number of possibilities. Abstraction is to a certain extent in the eye of the beholder: several different observers working independently are almost guaranteed to arrive at different models. Whose is the best? Passionate arguments have ensued!
To further complicate matters, there is virtually never only one "best" or "correct" model, only "better" or "worse" models relative to the problem to be solved. The same situation can be modeled in a variety of different, equally valid ways. As you'll see when we get into actually doing some modeling in Part Two of this book, we'll look at a number of valid alternative abstractions for our Student Registration System (SRS) case study that was presented at the end of the Introduction.
Note, however, that there is such a thing as an incorrect model: namely, one that misrepresents the real-world situation (for example, modeling a person as having two different blood types).
There is no acid test to determine if a model has adequately captured all of a user's requirements. The ultimate evidence of whether or not an abstraction was appropriate is in how successful the resultant software system turns out to be. We don't want to wait until the end of a project before finding out that we've gone astray. Because of this, it's critical that we learn ways of communicating our model concisely and unambiguously to the following people:
The intended future users of our application, so that they may sanity check our understanding of the problem to be solved before we embark upon software development
Our fellow software engineers, so that team members can share a common vision of what we're to build collaboratively
Despite all of these challenges, it's critical to get the up-front abstraction "right" before beginning to build a system. Fixing mistakes in the abstraction once a system is modeled, designed, coded, documented, and undergoing acceptance testing is much more costly (by orders of magnitude) than correcting the abstraction when it's still a gleam in the project team's eye. This isn't to imply that an abstraction should be rigid—quite the contrary! The art and science of object modeling, when properly applied, yields a model that is flexible enough to withstand a wide variety of functional changes. In addition, the special properties of objects further lend themselves to flexible software solutions, as you'll learn throughout the rest of the book. However, all things being equal, we'd like to harness this flexibility in expanding a system's capabilities over time, rather than in repairing mistakes.
Coming up with an appropriate abstraction as the basis for a software system model requires
Insight into the problem domain: Ideally, you'll be able to draw upon your own real-world experience, such as your former or current experience as a student, which will come in handy when determining the requirements for the SRS.
Creativity: We must be able to think "outside the box," in case the future users that we're interviewing have been immersed in the problem area for so long that they fail to see innovations that might be made.
Good listening skills: These will come in handy as future users of the system describe how they do their jobs currently, or how they envision doing their jobs in the future, with the aid of the system that we're about to develop.
Good observational skills: Actions often speak louder than words; just by observing users going about their daily business, we may pick up an essential detail that they have neglected to mention because they do it so routinely that it has become a habit.
But all this isn't enough; we also need
An organized process for determining what the abstraction should be. If we follow a proven checklist of steps for producing a model, then we greatly reduce the probability that we'll omit some important feature or neglect a critical requirement.
A way to communicate the resultant model concisely and unambiguously to our fellow software developers and to the intended users of our application. While it's certainly possible to describe an abstraction in narrative text, a picture is worth 1,000 words, and so the language with which we communicate a model is often a graphical notation. Throughout this book, we'll focus on the Unified Modeling Language (UML—see Figure 2-8) notation as our model communication language (you'll learn the basics of UML in Chapters 9, 10, and 11). Think of a graphical model as a blueprint of the software application to be built.
You'll learn how to interpret UML diagrams in Part Two of the book.
Ideally, we'll also have a software tool to help us automate the process of producing such a blueprint.
Part Two of this book covers these three aspects of modeling—process, notation, and tool—in detail; for starters, however, we'll make sure that you understand the basics of objects, which is the focus of the remainder of Part One.