The software development scenario changed over the last years with the increasing participation of web based solutions as a replacement of the tradicional desktop applications.
In this scenario you usually don’t install the app, simply access it using a modern browser. That solved some problems (and created others) such as the need to rely on the users to install the updates. Now you simply update your app on the web server and in the next access your users will use it.
This led to a trend were the “release soon, release often” is adopted in an increasing rate. The major players have millions of users and manage to push, in a daily basis, new versions with corrected or new features.
To cope with this short release cycle some changes in the traditional development process occurred. The usage of agile methodologies such as Scrum helped but the pressure to have a bug-free are still there.
As anyone involved in the development of software can tell you, manually testing all features quickly becomes impossible as your software grows and the release cycle shortens. The same applies to the other relevant aspects, such as guaranteeing adherence to coding standards, detecting copy and paste and generating documentation.
In order to help us automate some os those tasks, tools and techniques like TDD/BDD were developed and have been increasingly adopted.
One particular tool that I’ll start discussing in this article is the CI (Continuous Integration) server as one important part of our development strategy. If you search for the definition of CI you will find that it “is the practice, in software engineering, of merging all developer workspaces with a shared mainline several times a day”.
For our purposes the CI will be responsible for verifying if the software being developed works and meets the quality standards defined as part of the development process. In its simplest form (and initial definition) the CI will periodically run the unit/system tests and report the result of current “build” of the software.
That alone is of great help because it allows the Q&A process to be part of the development as it occurs, and not after it has been finished. And since it is an automated tool we can configure it, for example, to be run after every commit is made to our source code repository.
Before we start configuring our CI server let’s take a brief look on quality control of software development. Unless stated otherwise all examples/tools will be based on PHP but the principle can be applied to other tools and languages as well.
Now that we know, albeit briefly, what is the job of a CI, let’s dig a little deeper and specify some of the tasks you may want to make it do it for you.
Every developer should develop code that is bug free and that performs exactly what we expect from it. Unfortunately in reality a lot of factors prevent this from being something we can count on 100%.
So besides code review, the recommended approach is to either use TDD or at least develop unit and system tests to verify that the code being developed not only satisfies the specifications/user stories, but it also did not break anything else in the process.
Even tough each developer should run the entire test suite, sometimes it may not be feasible due to the time that the tests may take to run.
So in one situation or another the CI can help you by ensuring that the code that has been committed to, for example, the release branch, has all the tests run and a report generated.
You can add triggers so emails can be sent if the tests break, or even check the builds to see which commit caused the undesired behaviour.
Code coverage is a metric that can be applied to your project that allows to mesure how much of your code has been executed by your tests.
In addition of having such percentage you can understand which tests are executing your code and which lines have or haven’t been called.
The code coverage generation can be also automated by your CI server as it executes the unit tests.
As a good practice, specially if you have more than one developer in the team, is to choose a coding standard. That allows you some level of predictability of the created code. Pear, Zend, PSR are some of the standards found in the PHP world that defines aspects as how to write the function names, usage of tabs, maximum line length and so on.
You can add a code sniffing tool, such as PHPCS, to be executed by the CI server as new commits are added so you notify the necessary parts when a violation occurs and where.
One of the principles you should always try to follow is DRY (Dont Repeat Yourself), which means prevent or at least hunt down the duplicated code you have.
While some aspects still benefits from manual inspection, this is one that can be better executed by a tool like PHPcpd (Copy and paste detector), which scans the source code and points out which parts are copies.
As time goes by and your project grows, one usual side effect is that adding new features start to take more and more time and/or are followed by breaking of existing functionality (aka regression).
While the usage of test driven development technique mitigates this or at least makes it apparent by failures in the test suite, you can almost point the code complexity as the culprit.
Spotting unnecessary complexity requires analysis of the source code and a certain degree of expertise since it is not always easy to detect where you have possible problems. Tools like PHPDepend (inspired the the Java counterpart JDepend) can help you to perform static analysis and gather a toon of metrics.
It will be still up to you to decide what should be changed (and how) but at least you will have good starting points and a more precise way of measuring the result.
Among the several available metrics one that can indicate problems is the cyclomatic complexity. With this metric you assign scores (and adds) as different execution paths appear in the code (if, switch, try/catch etc).
The higher the cyclomatic complexity, more difficult is your code to read and, by default, to change it or extend it. As a matter of fact complex code usually triggers the copy and paste programming.
Conclusion (not quite)
As we’ve seen you can do a lot in terms of quality control of your project. The tools and metrics briefly shown in this post can be used standalone but beg to be automated so we can update them as the software is developed, and not only at the end (hence the continuous name).
In the next post I’ll start configuring one CI server (Jenkins) to make it gather all the artifacts shown and a few more for a sample project.