Skip to main content

Software Quality

Lately I have been following a lot of discussions on software code quality. There seems to be a lack of consensus on what quality means. This is not very surprising, since quality is a very subjective term, it means different things to different people. Here's what it means to me:
I believe every software is created for a specific purpose. The purpose usually defines the forces that act on the software. Most common forces that usually act on any software from a bsiness perspective are:
1. Adaptability - How well will the software adapt to changes
2. Reliability - How often will the software crash
3. Timeliness - How fast can we ship the software
4. Economy - How much will the software cost
5. Performance - Does the software have quick turnaround times
6. Scalability - Will the software continue to be performant if the user base were to increase substantially
7. Usability - How intuitive is it to use the software

These business factors are usually achieved by the following technical factors:
1. Architecture (Assuming OO design)
a. Choice of classes and their responsibilities
b. Coupling between classes
c. Usage of appropriate design patterns
d. Avoiding known anti patterns

2. Code quality
a. Adherence to coding standards
b. Choice of loops and conditionals
c. Algorithms
d. Size of methods (how large are the methods?)
e. Clarity of comments

3. Test coverage
a. Coverage of unit tests
b. Coverage of functional tests
c. Stress tests (for multi-user software)

4. The overall development process
a. Is the development process ad hoc or is it well outlined?
b. If it is well outlined then is it effective?
c. Code reviews
d. Build frequency
e. Processes each developer must follow locally before check-ins

Now let's consider each business factor and its relation with the technical factors.
1. Architecture
Software adaptability is usually achieved by the right selection of classes and loose coupling between them. This assumes knowledge of what is likely to change. However if we do not know aspects of the system that are likely to change then we could make a matrix of things that we think might change and associate a probability with change case. We can then address the high probability changes in the architecture.
Use of appropriate design patterns will be very useful.
2. Code Quality
We often have to refactor existing code when dealing with changes in business requirements. Two things are involved here. Identifying the code to change and understanding the implications of the change. Choice of appropriate class and method names, keeping methods small and meaningful, and clear comments play an important role in helping us identify code that needs to be refactored. Clear interactions among methods (non-spaghetti code?) will help us identify the implications of the change.
3. Test Coverage
Having a solid test harness will give us immediate feedback of the implication of refactoring.
4. The Overall Process
Regular code reviews ensure code quality, and adequate test coverage.

1. Architecture
Architecture probably does not have an important role here.
2. Code Quality
Good coding practices like dealing with and recovering from Exceptions gracefully are very useful to ensure reliability.
3. Test Coverage
Adequate tests are very important to ensure reliability.
4. The overall design process
Again code reviews will help ensure adequate test coverage.

This is the tricky one. Let's say it is very important for a customer to deploy the software by a certain date and let us assume that the time is scarce. Before I write ahead, let me make it clear that making timeliness an important priority can be done only by sacrificing other factors. Whether the sacrifice is appropriate is discussed a few paragraphs ahead.
1. Architecture
Not overengineering the architecture will be useful. An overengineered architecture usually means more classes, and will result in a significantly greater effort on coding and writing test cases. In short do not plan for the future. Plan for the current scope, use best practices and go ahead.
2. Code Quality
We surely cannot achieve timeliness by skipping some methods. Assuming that we've got the write the code we've got to write, where can we save time? Perhaps in the thought process. Perhaps in commenting the code. I definiteky will not recommend saving time in the thought process. Commenting on the other hand is something where corners can be cut. Please do not wince at the thought of cutting corners. Atleast not here. We will discuss the concept very soon.
3. Test Coverage
We can produce software quickly if we write fewer test cases. But this has been known to cause more delays in the QA phase. However I sure there is a law of dimishing returns for test coverage - although I not sure where the curve starts flattening.
4. The Overall Process
Keeping the process light will defenitely help. Perhaps reducing the frequency of code reviews or even elliminating them might help.

1. Architecture
Is there any aspect in the architecture of a software that can help us achieve economy? Maybe this is slightly misplaced, but using open source frameworks or products may reduce costs. I say *may* reduce costs because we will first have to calculate the total cost of ownership of the open source software we intend to use before we can determine if it will really reduce costs. Some people may be thinking - but architecture should be generic - how did frameworks and open source products get here? Well from a practical perpective I am not sure if architecture can be truly generic. If we were making a web based application using Struts, then we will identify Action classes and ActionForm classes. The choice of these classes has been dictated by Struts. Were we using Turbine or Spring then we would have designed the application slightly differently. I strongly believe that the design of an application is infuenced by the choice of frameworks and other third party products.
Again keeping the architecture simple will help us reduce development costs.
2. Code Quality
Here economy translates into time spent on developing the software. The priciples we identified for timeliness apply here too.
3. Test Coverage
Here economy translates into time spent on developing the software. The priciples we identified for timeliness apply here too. Choice of open source testing frameworks might again help us. However it is important to evaluate their total cost of ownership first.
4. The Overall Process
Certain processes are heavy and also demand the use of expensive tools. I am not sure if there is any clear indication if using such processes and tools add value commensurate to the cost of the tools and other process elements. Again like in 'timeliness', using a light weight process with appropriate, but simple (and open source) tools can reduce the overall cost of developement.

1. Architecture
Here too I am not very sure if architecture plays a role. Perhaps it does. For example the choice of technology will determine performance. Using EJB's will be slower than using POJO's. But the speed can be enhanced by increasing the resources on the server. There are way too many factors that determine the performance of an application. Architecture cannot be linked with performance in any simplistic way.
2. Code Quality
Code quality is important for performance. We identified algorithms as part of code quality. Most applications have to iterate through object trees to produce an output. Apprpriate algorithms, and database queries play an important role in the overall performance of an application. Having said this I do agree with the widely held belief - "first make it work, then make it fast".
3. Test Coverage
Having appropriate stress tests will help us uncover areas which perform inadequaltely. Test suites will not elliminate performance problems, they will only help us identify them, which is better than the client identifying them.
4. The Overall Process
Again the overall process will contribute only in terms of ensuring proper test coverage. Code reviews might uncover obvious performance issues.


Popular posts from this blog

My HSQLDB schema inspection story

This is a simple story of my need to inspect the schema of an HSQLDB database for a participar FOREIGN KEY, and the interesting things I had to do to actually inspect it. I am using an HSQLDB 1.8 database in one of my web applications. The application has been developed using the Play framework , which by default uses JPA and Hibernate . A few days back, I wanted to inspect the schema which Hibernate had created for one of my model objects. I started the HSQLDB database on my local machine, and then started the database manager with the following command java -cp ./hsqldb- org.hsqldb.util.DatabaseManagerSwing When I tried the view the schema of my table, it showed me the columns and column types on that table, but it did not show me columns were FOREIGN KEYs. Image 1: Table schema as shown by HSQLDB's database manager I decided to search on StackOverflow and find out how I could view the full schema of the table in question. I got a few hints, and they all pointed to

Fuctional Programming Principles in Scala - Getting Started

Sometime back I registered for the Functional Programming Principles in Scala , on Coursera. I have been meaning to learn Scala from a while, but have been putting it on the back burner because of other commitments. But  when I saw this course being offered by Martin Odersky, on Coursera , I just had to enroll in it. This course is a 7 week course. I will blog my learning experience and notes here for the next seven weeks (well actually six, since the course started on Sept 18th). The first step was to install the required tools: JDK - Since this is my work machine, I already have a couple of JDK's installed SBT - SBT is the Scala Build Tool. Even though I have not looked into it in detail, it seems like a replacement for Maven. I am sure we will use it for several things, however upto now I only know about two uses for it - to submit assignments (which must be a feature added by the course team), and to start the Scala console. Installed sbt from here , and added the path

Inheritance vs. composition depending on how much is same and how much differs

I am reading the excellent Django book right now. In the 4th chapter on Django templates , there is an example of includes and inheritance in Django templates. Without going into details about Django templates, the include is very similar to composition where we can include the text of another template for evaluation. Inheritance in Django templates works in a way similar to object inheritance. Django templates can specify certain blocks which can be redefined in subtemplates. The subtemplates use the rest of the parent template as is. Now we have all learned that inheritance is used when we have a is-a relationship between classes, and composition is used when we have a contains-a relationship. This is absolutely right, but while reading about Django templates, I just realized another pattern in these relationships. This is really simple and perhaps many of you may have already have had this insight... We use inheritance when we want to allow reuse of the bulk of one object in other