The Road to Software Success
There are many ways to measure success or to determine failure. In practice there are few things which are a complete success or an utter failure. But whichever it may be, one must understand the metrics of success and the implications of failure by which the distinction is made.
This article presents the metrics used by successful software development teams today. It starts at the base with Construction and finishes at the top with Architecture. It† includes an appended presentation of the distinction between Analysis, Architecture and Design.
A good line of code or code snippet must be correct before being further qualified. Correctness is a provable measure which should never involve philosophical or religious excursions to justify or defend it. Once correct, lines of code or code snippets should measures high on the qualitative scales of:
Further quantitative measures that can apply include:
It can be shown that the first seven qualities are obtained by consistently applying the principles of (1) high cohesion and (2) low coupling between elements of the design being rendered, and establishing the process of code inspections and code reviews. A strong stylistic standard (allowing for degrees of freedom) does much to guide novice members in the construction of quality code.
When there is any discussion as to the need for scoring high on any of these measures, one must consign themselves to solvitur ambulando.
When a line of code or code snippet scores low on the above measures a defect can be claimed. The class of the defect varies and in fact may not be considered a defect in all possible venues.
Correctness defects are the primary defects looked for and resolved in the debugging process.
Efficiency, Time and Space are the secondary defects generally pursued when a timing constraint or a memory constraint is exceeded.
All other defects are the results of various violations of design and construction principles and best practices that lead to a violations of a system invariant or a programming contract. This class of defect are the hardest to detect and correct and in many cases indicate the presence of a design defect. It can be shown that adhering to design & construction principles and applying best practices consistently will yield a low defect injection rate of defects of this kind.
A correct design is one that achieves the desired outcome for a given condition and state across the entire state set and under all possible conditions. Correctness is a provable measure which should never involve philosophical or religious excursions to justify or defend it.
A good design generally has high deterministic qualities. It is capable of† reaching itís limits yet remaining reliable if not available. It is resilient to external stimuli that doesnít meet itís interface or service requirements.
A design must be correct before being further qualified. Once correct, a design† should measures high on the qualitative scales of:
1. High Cohesion
2. Low Coupling
3. Knowledge Hiding
4. Knowledge Encapsulation by Domain
5. Use of Domain Data Abstraction
6. Data Hiding
7. Interaction by Interface
8. Contract Specifications (Explicit Pre and Post Conditions on interface usage)
It can be shown that all eight qualities are obtained by consistently applying the principles of (1) architecture first, (2) iterative life cycles, (3) model based development, (4) analysis descent, (5) component based software, and (6) contract & constraint interface specification.
When there is any discussion as to the need for scoring high on any of these measures, one only need compare and contrast software projects that have succeeded with those that have not - panem est probandi.
When a design scores low on the above measures a defect can be claimed. The class of the defect varies and in fact may not be considered a defect in all venues. Correctness defects are provable defects and may be mistaken for code defects during the code test process.
Without adherence to the above qualities - especially (2), (3), (6) and (8) - it is extremely difficult to distinguish a code defect from a design defect.
Secondary defects are claimed when a code base derived from the design cannot easily be modified to accommodate additional requirements. The analysis process which yields an architecture is primarily carried out by an engineering team to avoid and/or mitigate this class of defect.
It should be understood that a bad design generally means a design derived from the bottom up that after several iterations of requirements creep and feature evolution causes a major increase in the defect injection rate. It can be shown that adhering to certain design principles and applying best practices consistently can actually prevent the failure of a design in this way.
A good architecture is one that achieves one or more designs and constructions with very low defect injection rates during product enhancement, evolution and reuse. A very low defect injection rate by todayís industry standards is less than 1 per 1000 lines of code.
A good architecture is one that also supports highly efficient development projects. A highly efficient development project by todayís industry standards is better than 30 net lines of code per day over the duration of the effort, increasing to better than 300 net lines of code per day in the final iterations of the construction phase. It additionally promotes code and design reuse on the order of† 30% to 70% reuse of artifacts obtained from prior design and construction efforts.
A good architecture responds well to changes in technologies commonly used to solve or address problems within itís own problem domain. It vests more in the constancy of why a solution ought to be provided than in what solution must be provided.
Finally, a good architecture delivers on promoting high degrees of reliability, resilience, robustness, availability and usability in the designs and constructions derived from them. (Performance is actually a sub-metric of availability & usability.)
A correct architecture is generally not provable. It may lend itself to statistical proof over time and then only across a population of designs and constructions derived from it.
The consequences of an architecture are much easier to deduce, and from them a measure of the quality can be obtained. A good architecture has the following consequences:
1. Derives designs consistent with the problem domain.
2. Responds well to changes in the range (i.e. extension of limits or bounds) of a problem domain requirement.
3. Maintains problem domain terminology at the level of analysis fostering a natural descent to the design domain terminology.
4. Possesses problem domain generalization and specialization distinctions that form the central entities within the solution domain.
5. Possesses problem domain roles and behavior distinctions that form the primary interaction patterns within the solution domain.
6. Exposes the primary and secondary boundary interactions, and functional enumeration by which a system is expected to be measured.
It can be demonstrated that the Object Oriented Analysis & Design methodology does lead to the best system architectures. This is due to the method lending itself to delivering highly on the above six qualities. The results of† such architectures simplify the process of yielding design and constructions which score high on the design and coding metrics described above.
When there is any discussion as to the need for seeking these particular consequences of an architecture, remember that experientia docet stultos.
The biggest architectural defect prevalent in todayís engineering projects is the lack of one. Often confused as the structure of a given product instance, many engineers see an architecture where there is only an instance of structure - one that may or may not remain intact after iterations of product enhancements or product evolutions.
Other architectural defects derive from the failure to adhere to the above desired consequences which, with thought, can be seen to as taking away from those things we understand lead to correct and good designs.
In architecture we are at the boundary of art and science and rely greatly on team experience and heuristics. We strive to learn from both development successes and failures and to utilize those architectures that consistently demonstrate their advantages and out weight any of their disadvantages.
The distinction between Analysis, Architecture and Design
The tracing of things to their source, and the resolving of knowledge into its original principles.
A resolution of anything, whether an object of the senses or of the intellect, into its constituent or original elements; an examination of the component parts of a subject, each separately, as the words which compose a sentence, the tones of a tune, or the simple propositions which enter into an argument.
An investigation of the component parts of a whole.
The abstract separation of a whole into its constituent parts for study.
The resolving of problems by reducing the conditions that are in them to equations.
The method of proof in which a known truth is sought as a consequence of a series of deductions from that which is the thing to be proved.
The art or science of designing and building systems.
The discipline dealing with the principles of design and construction.
The overall design or structure of a computer system, including the hardware and the software required to run it, especially the internal structure of the microprocessor.
[Inclusive]The resolution of the tensions and energies between requirement constraints, technology constraints, cost constraints, development, deployment, evolution and disposition in the formation of† a system.
To create or contrive for a particular purpose or effect.
A plan or scheme formed in the mind of something to be done.
Idea intended to be expressed in a visible form or carried into action.
The act of working out the form of something.
From the above definitions, derived from various sources, it can be seen that the three terms are not the same yet they are related. In fact, Construction flows from a Design which flows from an Architecture which flows from an Analysis.
Figure 1 DiPasquali's Model
When any of the prior elements are missing from the developmental process, the results is often referred to as an ad hoc approach (Contrived purely for the purpose in hand rather than planned carefully in advance). Difficulties with such approaches is the breakdown in ďcognitive extensionĒ from requirements to constructions which source many of the defects that we have historically dealt with in systems since the our first engineering project (fire - shall cook food, people are not food).
It is not uncommon in engineering circles today to frequently find ad hoc analysis and ad hoc architectures leading to the chosen design and construction. In a rapid application development cycle (RAD) this is effective since the resulting prototype is used to recursively form the architecture and analysis explicitly. Failure to mentor this always leads to failure in the long run (evolution). It must be emphasized that RAD is distinct from simply not doing analysis and architectural formations. RAD is an iterative technique that forms the analysis and architecture in very tight spirals measured in hours to days.