In software systems, non-functional requirements (NFRs) define attributes such as security, reliability, performance, maintainability, scalability, and usability. NFRs serve as constraints or restrictions on the software design.
If requirements are the most volatile elements and if software design is failing due to the constantly changing requirements, it is the design and related practices that are at fault.?There is a need to make software design resilient to such changes and employ practices that prevent them from rotting.
In the book “Agile Software Development – Principles, Patterns and Practices”, Robert Cecil Martin writes about the different odors of software rotting – Rigidity, Fragility, Immobility, Viscosity, Needless Complexity, Needless Repetition, and Opacity.
Here, it is pertinent to recall the contrarian view offered by Jack W. Reeves - a perspective that programming is fundamentally a design activity and that the only final and true representation of “the design” is the source code itself.??He insisted that the design process is not completed until you have written and tested the code.??
The following are excerpts from Jack’s seminal article “What Is Software Design?” and his follow-through essay “What is Software Design: 13 Years Later”.
- Everybody that has been in this business any length of time has seen plenty of examples where someone obviously sat down and coded the first thing that popped into their mind. Later, when it became obvious that there were shortcomings with the approach, there was too much blood, sweat, and “skin” invested in the code to scrap it and do something better. Fine, we all know a little thought can go a long way.
- On the other hand, any of us who has spent time on a traditional development project with its strict rules forbidding the writing of a single line of code until the “design” is completed and reviewed and approved, etc. knows you can waste a hell of a lot of time producing documents that are out of date literally days after the actual coding starts. Why bother?
- We need good architectures (top level design), good abstractions (class design), and good implementations (low level design).
- We must keep in mind, however, that these tools and notations are not a software design. Eventually, we have to create the real software design, and it will be in some programming language. Therefore, we should not be afraid to code our designs as we derive them.
- You think we could find some happy medium of “enough” design effort, but not too much. There is no such thing. The only way we validate a software design is by building it and testing it. There is no silver bullet, and no “right way” to do design.?Sometimes an hour, a day, or even a week spent thinking about a problem can make a big difference when the coding actually starts. Other times, 5 minutes of testing will reveal something you never would have thought about no matter how long you tried. We do the best we can under the circumstances, and then refine it.
- Auxiliary documentation is as important for a software project as it is for a hardware project.?The source code may be the master design document, but it is seldom the only one necessary.
- The issue seems to be that only the very best programmers can “design” and “code” at the same time. To offset this, we must have all those intermediate design steps and products mentioned above to make up for the lack of experience and talent of the average programmer.
- In software development, questions about the less able programmer really come down to trying to substitute a process for intelligence, aptitude, and experience. Apparently, a lot of people think that if we force people to create enough UML diagrams (or whatever), have enough reviews, and otherwise follow a detailed process, that eventually they will figure out what they are doing and code it correctly. There is no evidence that such approaches have worked in the past, and I see no reason to believe they will work in the future. In fact, my own experience says that properly using tools such as UML involves a considerable level of expertise and experience in its own right.
- So, while it might be true that a lot of engineers do things besides producing design documents, anyone who calls himself an engineer knows what a design document in his field looks like, and probably produces such more often than not. Can we say the same for “software engineers”?
- In software development, the design document is a source code listing.
- Programming is a design activity – a good software design process recognizes this and does not hesitate to code when coding makes sense.?Testing and debugging are design activities – they are the software equivalent of the design validation and refinement processes of other engineering disciplines.
- This is the fact that software is cheap to build. It does not qualify as inexpensive; it is so cheap it is almost free. If source code is a software design, then actually building software is done by compilers and linkers. We often refer to the process of compiling and linking a complete software system as "doing a build". The capital investment in software construction equipment is low -- all it really takes is a computer, an editor, a compiler, and a linker. Once a build environment is available, then actually doing a software build just takes a little time.
- When the document is detailed enough, complete enough, and unambiguous enough that it can be interpreted mechanistically, whether by a computer or by an assembly line worker, then you have a design document. If it still requires creative human interpretation, then you don’t.