There is a great modeler in all of us waiting to break out and mold a software effort. But how do you become a great modeler? Where do you start? Start by applying this collection of key philosophies to any software project for immediate benefit.
1. People are far more important than technology.
You build software for people—without users, software is a meaningless collection of bits. Many software professionals plateau early in their careers because they focus solely on technology. Yes, components, Enterprise Java Beans (EJB), and agents are all really interesting, but it won’t matter what’s on the back end if your software is difficult to use or doesn’t meet user needs. Invest time in learning your software’s requirements and designing a user interface that your users can understand.
2. Understand the technology that you are designing for.
The best designers spend the majority of their time modeling, but occasionally write source code for the environment in question. This increases the likelihood that their designs will be feasible.
3. Humility is a qualification.
You can’t know everything, and even knowing enough is often a struggle. Software development is a complex endeavor in which the tools and technologies are constantly changing. The process cannot be completely understood by a single person. You can learn something new every day of your life—and with software development, many things every day—but only if you choose to do so.
4. Requirements are a requirement.
If you don’t have any requirements, you have nothing to build. Successful software is on time, on budget, and meets the needs of its users. If you don’t know what those needs are or what your software’s requirements are, your project is guaranteed to fail.
5. Requirements rarely change, but your understanding of them often does.
Doug Smith of Object ToolSmiths (www.objecttoolsmiths.com) likes to say, “Analysis is a science, design is an art.” He means there is only one “correct” analysis model—one that fully models the problem space—and many “correct” design models—those that model a good solution to the problem space.
Requirements often appear to change because you did a poor job of gathering them, not because they actually changed. It’s easy to claim that your users can’t tell you what they want, but it’s your job to gather requirements. You can claim that the arrival of a new group of people has invalidated your existing work, but you should have been talking to them from day one. You can claim that your organization does not give you access to your users, but that means senior management doesn’t truly support your project. You can also blame new legislation, but you should’ve kept track of what was going on outside of your company. It’s easy to blame your competitors for coming up with a new idea, but why didn’t your organization come up with it first? There are few true instances of requirements that change, but many excuses for not gathering requirements properly.
6. Read constantly.
In an industry that changes daily, you can’t sit on your laurels for long. Try to read two or three magazines and at least one book per month. The significant commitment of time and money pays off dramatically because by staying current, you become an attractive candidate for new and exciting projects within your organization.
7. Reduce the coupling within your software.
Systems that exhibit high coupling are difficult to maintain; a change in one place requires another change, which in turn requires another, and then another—you get the point. You can reduce coupling by hiding implementation details, enforcing a defined interface to your components, not having shared data structures, and not letting applications directly access data stores (my rule of thumb is that when application programmers are writing SQL code, you’ve lost the battle). The advantage of loosely coupled software is that it is easier to reuse, maintain, and enhance.
8. Increase the cohesion within your software.
A software component is cohesive if it fulfills only one function, which means that highly cohesive software is easier to maintain and enhance. To determine whether or not a component is cohesive, see if you can describe it in one simple sentence. If it takes a paragraph, or you need to use a conjunction such as “and” or “or,” then you should probably refactor it into several portions. Highly cohesive software is also more likely to be reused.
9. Expect to port your software.
Porting is a reality of software development, regardless of software tool marketing hype. You can count on having to port your software to another operating system or database, even if it’s only an upgraded version. Remember how much fun it was porting from Windows 16 to Windows 32? Every time you take advantage of an operating system’s unique feature, such as its inter-process communication (IPC) strategy, or a feature unique to a database, such as writing stored procedures in its proprietary language, you couple your design to that specific product. Successful modelers design wrappers that hide these features’ implementation details, so when they do change, your organization merely needs to update its wrappers.
10. Accept that change happens.
It’s a cliché, but the only constant is change. You can plan for it by documenting “change cases,” future requirements that your system could potentially fulfill (see “Architecting for Change,” Thinking Objectively, May 1999). By considering these scenarios while modeling, you will likely develop a design robust enough to easily support them—and designing robust software should be your primary goal.
11. Never underestimate the need to scale.
The Internet’s most important lesson is that you must consider scalability from the beginning of development. An application used today by a 100-person department will be deployed to an organization of tens of thousands tomorrow, and next month on the Internet by millions. You can design scalable software by examining the basic business transactions that your software must support, which are often captured in use case models. Then build your system, so you can expand it to perform these transactions in high-load situations. Considering scalability at the beginning of design can avoid significant rework when you discover that your system suddenly has a much larger user base.
12. Performance is only one of many design factors.
Focusing on one design factor—performance seems to be the favorite—inevitably leads to a poor design that results in rework for your team. Your designs must take issues such as scalability, usability, portability, and extensibility, into account. You should prioritize these design factors at the beginning of your project and then work to them appropriately. Performance may or may not be your number one priority; the point is that you should give each design factor the consideration it deserves.
13. Manage the seams.
One of the pearls of wisdom from The UML User Guide by Grady Booch, Ivar Jacobson, and Jim Rumbaugh (Addison Wesley, 1999) is that you should define your components’ interfaces early in development. This helps your team agree on your overall software architecture and lets separate subteams work on “their piece” in isolation. As long as the interface to a component remains stable, it shouldn’t matter how that component is built. Fundamentally, if you can’t define what something will look like on the outside, you likely don’t understand it enough to begin working on the internals.
14. Shortcuts always take longer.
There is no such thing as a shortcut in software development, period. Shortening your requirement gathering efforts will result in software that doesn’t meet your users’ needs, and must be rewritten. Every week you save by not modeling results in several weeks of needless programming because developers acted before they thought. Each day you save by reducing your testing efforts results in weeks and sometimes months of fixing the corrupted data caused by the bugs that you missed, then redeploying the fixed software and data once more. Avoid shortcuts—do it once by doing it right.
15. Trust no one.
Product and service vendors are not your friends, nor are most of your coworkers and senior managers. Most product companies want to lock you into their product, be it an operating system, database, or development tool. Most consultants and contractors care about your money, not your project (stop paying them and see how long they stick around). Most programmers think they know better than everyone else, and will jettison your models in favor of their own approach given the first opportunity. Improved communication is often the solution to these problems. Let it be known that vendor independence is important to you, and that your organization has invested heavily in developing models, documentation, and a proven process for software development.
16. Show that your design works in practice.
You should always create a technical prototype, also known as an end-to-end prototype, to prove that your approach actually works. You should do this as early as possible during development, because if your design doesn’t work from the start, no amount of coding will save it later in the life cycle. Your technical prototype will prove that your architecture works, making it easier for you to garner support for it.
17. Apply known patterns.
There is a wealth of available analysis and design patterns, descriptions of solutions to recurring problems that you can reuse in your models. Good modelers, and good developers in general, avoid reinventing the wheel. For links and references to a wide variety of patterns, visit http://www.ambysoft.com/processPatternsPage.html.
18. Learn each model’s strengths and weaknesses.
You have a variety of models to work with, as shown in Figure 1. Use case models capture behavioral requirements, whereas data models capture the persistent data needed to support a system. You could attempt to model your persistent data within your use cases, but this won’t be very useful for developers. Likewise, a data model is useless for describing software requirements. Each model has its place in your modeling toolkit, and you need to understand where and when not to apply them.
|Figure 1. The Detailed Modeling Process Pattern|
19. Apply several models to a given task.
When you gather requirements, consider developing a use case model, a user interface model, and a domain-level class model. When you design software, consider creating a class model, a collection of sequence diagrams, some state charts, some collaboration diagrams, and eventually even a physical persistence model. Modelers who focus solely on one model will create software that isn’t robust enough to meet user needs or can’t be enhanced easily over time.
20. Educate your audience.
There is no value in producing sophisticated models if your audience doesn’t understand them—or even worse, doesn’t understand why you need them in the first place. Teach your co-workers the fundamentals of modeling; otherwise, they might look at the pretty pictures and then go back to hacking out source code. You might also need to teach your users the basics of requirements modeling. Walk them through your use case and user interface models, so they understand what you are trying to communicate. When everyone speaks a common language, your team can share a common vision.
21. A fool with a tool is still a fool.
You could give me a CAD/CAM tool and ask me to design a bridge, but I’d be the last person willing to drive across it because I know nothing about civil engineering. Having access to a fancy CASE tool doesn’t make you an expert modeler, it makes you someone with access to a fancy CASE tool. It takes years to become a great modeler, not a week of training on a several-thousand-dollar tool. A good CASE tool is important, but you also must learn how to use the tool and develop the models it supports.
22. Understand the entire process.
Good developers understand the entire software process, although they might not be proficient at all aspects of it. Consider the object-oriented software process shown on page 36—pretty complex, isn’t it? It shows that there is more to software than programming, modeling, testing, or whatever you’ve chosen to specialize in. The best modelers consider the overall picture. They think long term and consider their users’ needs, as well as how to maintain and support the software that they develop.
23. Test often and early.
If your software isn’t important enough to test, it probably isn’t worth creating. You can test your models by developing technical prototypes and performing technical reviews of them. The later you test in the life cycle, the harder and more expensive it is to fix the errors you find. It pays to test your work as early as possible.
24. Document your work.
If it isn’t important enough to document, it probably isn’t worth creating. You should document your decisions, the assumptions they’re based on, each portion of your model (especially those that aren’t obvious), and create an overview of each model, so others can quickly determine what’s being shown.
25. Technology changes, fundamentals don’t.
It’s a sure sign that a developer needs more experience when he or she says something inane like “with language, tool, or technique XYZ, we don’t need to do requirements, modeling, coding, or testing on this project.” Regardless of the technologies and people on the project, today’s software development fundamentals are the same as they were in the 1970s. You still must define requirements, model, program, test, deploy, manage risk, manage deliverables, manage staff, and so on.
Software modeling is a skill that takes years to master. The good news is that you can start with the advice I presented here and build on it with your own development experiences. Start with the chicken soup, add your own vegetables, and you’ve got a meal fit for a modeling king.