Software Design - Paradigms of Software Engineering
Paradigms = 20 cents.
Actually, a Paradigm is a way of thinking. This section gives an overview of the major paradigms in software engineering:
In the beginning, all branching was done using GOTO. Assembly language, Fortran, and BASIC are perfect examples of unstructured programming. An unstructured program might look like this:
In the 1960's, Thomas McCabe identified two fundamental design structures: Decision Blocks and Loops. He also correlated high program complexity and high defect rates with the breaking of those structures. As a result, newer programming languages like Pascal implemented the concept of structured programming. A structured language has constructs like IF-THEN-ELSE and WHILE-NEXT, and possibly variants such SWITCH-CASE, DO-WHILE, and FOR-NEXT. (These variants are all simply variations of McCabe's two fundamental constructs.)
What If My Language Isn't Structured?
Structured concepts are a high-level language concept - they do not exist at the machine level. So, if the language is not structured, then we can still choose to create those same structures -we just have to do it explicitly. Most unstructured languages have some sort of conditional Jump instruction, which can be used to create a decision block (after all, that's how the compilers really do it under the hood when they create the machine code).
Here's another example of explicitly using structured methods, for error handling in Basic. Lines 10 through 110 form a single decision block.
** Probable source of error, such as file missing, though actually an On Error Goto will be in force throughout the entire function. But that's not important for demonstrating the concept of introducing structure to an unstructured language.
Functional Decomposition, which was introduced at about the same time as structured programming. A Structural Language made it easier to implement a Functional Decomposition design, so they complemented each other well. Therefore, while the two concepts are unrelated, they became merged in many minds.
One of the best uses I have seen of Functional Decomposition is to use it at the single function level and do design-by-comments. The programmer designs the function in comments, defining the subtasks in detail. This allows the logic to be debugged prior to coding. Then, the code is written below each comment. This way, the comments show the overall design of the function. For example (comment symbols omitted for easier reading):
This method allows the programmer to capture the intent and the design of the function prior to writing the code. Once the programmer is certain that the logic will perform the desired task and is robust at handling errors, the code can be written beneath the comments.
Object-Oriented Design (OOD)
Many books on Object-Oriented Design begin with the ritual debunking of Functional Decomposition. Of course, Functional Decomposition was popular when people knew that they would never need more than 640K of memory! But as program size grew, defects grew even faster. A new paradigm was needed.
OOD was created primarily to overcome most of the problems that continued to create high program complexity and correspondingly high defect rates. While Functional Decomposition was not directly to blame for the problems, it did nothing to discourage many error-prone programming practices - such as the ubiquitous use of global variables. OOD also afforded a better breakdown of the program than did Functional Decomposition.
The point of OOD is to first define the Interfaces to the Objects, then code to the Interfaces. As long as the Interface remains the same, the implementation behind the interface is free to change without impacting the rest of the program. And, if you add the polymorphism of a language like C++, you can make an object change its behavior on the fly without the rest of the code being any the wiser! Let's see Functional Decomposition do that!
By the way - you can still use Functional Decomposition within a Method, using the design-by-comments process discussed above. Within a single Method you are working at the low level of detail that was characteristic of the time when Functional Decomposition was originally developed - so I'm not surprised that it can still find a good home as a tool in OOD.
Object-Oriented Design and Object-Oriented Languages are two different things. An Object-Oriented Language (like C++) makes it easier to implement an Object-Oriented Design, but Object-Oriented Design can be done in any programming language - even Assembly language! Obviously, Object-Oriented Languages also use Structured Language constructs - not GOTOs. (Although the careless use of try...catch and throw can have the same destructive effect as an army of GOTOs.)