May 25, 2011

Software Principles

Yesterday’s post, Software Reviews, demonstrated how to measure the quality of a software product based upon business needs. Before we can discuss how to review the software to measure its performance against the specified quality criteria we first must understand what makes a good quality program good in the first place. Today’s post will review foundational software principles that make possible the construction of solid software products.

The Value of Software Principles

To demonstrate the value of software principles I’d like to review how to patch a hole in the wall. First, you begin by cutting around the hole taking care to make a square that extends just above and below the hole and to the center of the joists to each side of the hole. Next you cut a piece of sheetrock that will fit into the hole using drywall screws to secure the sheet to the studs. Once the hole is covered the cracks between the new sheetrock and the original sheetrock must be taped and filled with mud. The mud is used to cover the cracks so that the wall appears seamless to the human eye.

When I first began mudding I naturally followed the line filling it in mud. I would use three coats as recommended but when finished the location of the cracks stood out like a sore thumb. You could see where the mud was applied to the cracks. Even with the lights off you could tell!

I hired a professional to resolve the problem and that’s when I learned what I did wrong. As my new, expensive friend began patching I noticed that after filling the cracks with the first coat, on the second coat he applied a circular motion. He didn’t follow the lines after the first coat. On the third application it was nearly a perfect circle. The mud couldn’t be seen because the circular pattern was much more difficult for the human eye to detect!

Often we write programs in the same way. We follow the crack not realizing that we are making the system fragile. The code works but the patch work can be easily seen. When mudding the wall the way that I applied the mud was just as important as the tools that I used. Likewise, in programming the way that we write software has just as much impact on the solution as the tool that we use.

Software Principles define how to use programming languages to construct a quality software product. The objective of these best practice concepts is to provide guidance on how to design a program so that it is inheritably efficient, flexible, extensible, secure, reliable, repeatable, and verifiable. Use of these best practices results in an application that is easier to transition to new support staff, easier to maintain, has fewer bugs and a greatly reduced cost of ownership over the life of the system.

All code patterns utilize one or more software principles while all code anti-patterns will break one or more principles. While designing and coding software special consideration should be given to these best practices. These concepts should always be used to measure the quality of a program during both the design review and the code review. A program should be immediately refactored when it is discovered that it violates any of these concepts.

I’m in no way implying that a perfect software solution can or should be created. Sometimes a database needs to be denormalized to make it more efficient and usable for real world scenarios. Likewise, sometimes an application’s design needs to be designed in a less than perfect manner to turn it into a feasable solution.

Design Pitfalls to Avoid

Coupling indicates the degree of integration between two entities. Tight coupling implies that a change to one component will have a rippling effect of changes to another component. Low coupling implies that a change to one component will have little effect on another. Highly coupled entities tend to be fragile.

Cohesion measures the degree of purpose in the relationship between two entities. Low cohesion implies that activities performed in a component are unrelated to it’s intended purpose. High cohesion implies that the work is specifically related to the purpose of the component and the entities it is consuming. Low cohesion results in work that is more costly to enhance.

In a nutshell programmers should strive to build programs that are loosely coupled but highly cohesive.

Inheritance vs Interface

Interestingly one of the programmers favorite tools violates the loose coupling, high cohesion guideline. Inheritance automatically infers tight coupling! However, when used correctly inheritance can be highly cohesive. So care must be taken to identify when inheritance truly benefits the system.

I prefer the use of interfaces to establish contracts between components. Interfaces encourage well thought out designs that are more likely to align with the loose coupling, tight cohesion guideline.

After implementing an interface a few times it becomes obvious where code is duplicated and could benefit from inheritance. Interface driven design helps drive out proper use of inheritance. It is after we have proven that inheritance offers value to the design that the code should be refactored.

So begin the design with interfaces. Allow the implementation of those interfaces to define when inheritance truly adds value to the code.

Software Principles

Without further ado here is a list of software principles that I have compiled from wikipedia.org.

Any source code and files are provided to the reader as free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3.

All code is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details at http://www.gnu.org/licenses/.

Disclaimer

The posts and projects on this site are meant for instructional purposes only. Never use any code from this site in a production environment without proper testing and validation.