Restarts as a strategic tool for better software

During the years when I started to learn agile development, especially TDD and good OO, I had the fortune to work as a consultant for a company that ran a massive number of small projects, each lasting for approximately 3 months. This was exactly the amount of time I needed to learn something new, apply it, and discover the limitations of it.

At the end of each project I realized there was a much better way of doing things, and the effort to rewrite the code probably would have eaten me alive. But hey, no problem, I’ll be on a new project next week, with a fresh code base to apply my new findings at.

At that time the recurring project restarts actually was a good strategy to improve the average code quality! If I would have had to keep on working with the same code base I would never have been able to incorporate that much new technology and knowledge in the code base, and I would never have learned that much about what makes code good.

Later on I also learned refactoring, but I doubt I would appreciate it as much if I hadn’t learned about good code first. I think this is one of the great limitations of refactorings, it requires a lot of experience to know in what direction to go.

By allowing people and projects to restart you can make people raise their sight to take a new direction, to get a new vision of what it will be like there, to learn and incorporate their experiences in the new. Granted, most agile processes have retrospectives, but sometimes they are not enough a kick-in-the-butt to start off something new.

If it is hard to introduce refactoring in order to improve the code base, or when retrospectives don’t seem to do it either; try a fresh start iteration where you can dream a little! If you realize it’s not leading anywhere, just keep on working with the old code base. In the long run you will probably gain more from the new perspectives than the lost iteration cost.

How much is a team-minute?

As opposed to the light-year, which is a very long distance, there is also the notion of the beard-second, which is a very short distance. As the name implies, it is how long a straw of beard grows in one second. When you calculate the length of the beard-second (5 nm) it is amazing that anybody has beard (or hair) at all! Still, you see it every day. How is that possible!?

The not so surprising answer is: It accumulates over time.

When in a software project (or any project for that matter) the team always spend time on doing the same tasks over and over again, every day. I have always felt that it is good to cut down on build times, having fast computers etc, but I never calculated the gain from it.

The other day I asked myself “how much would we gain if everyone on the team gained one minute per day?”

There are approximately 200 working days in a year, and on my team we are approximately 10 people. If we gain one minute each per day, that is

200*10*1/60=33h20min (for one person)

Wow! That means that I can spend 33h on making a one team-minute improvement, and it will pay back in about a year!

If we gain half an hour that is

200*10*1/2 = 1000h

Whew!

Then I started to measure in money. If the approximate hourly cost for one person is €100, every team-minute costs €3300. That is a lot of money. For a minute! Half a team-hour a day costs €100.000 per year.

If the machine park is aged, or the network is slow, add up all your team-minutes and present them with hard numbers to your boss. I’m not saying he or she will listen, but it will be much harder to reject such a proposition!

The plan could backfire and your coffee- and lunch breaks be revoked, but it might be worth the risk! 😉

Good luck!

Software development is all about dependency management

All substantial knowledge I’ve come across as a SW developer has been about dependencies, and particularly about managing dependencies to minimize their impact on design and its flexibility.

A thinking tool

By thinking of what I do as “dependency management” I have a tool that will guide me in any situation, including managing projects, servers, build automation, xml- and property files, database design, architecture and object design.
It may sound somewhat abstract, but it always manifests itself very clearly when getting down to work. I just keep the following quote in mind:

“What need this part NOT know about?”
-Joakim Ohlrogge

Good dependencies are the minimal set of vital dependencies on work organized to minimize the set of vital dependencies.

Circular proof?!?

Not really, but usually an iterative process.

The range of dependency management

Dependency management ranges from organisations and projects, down to the smallest piece of bit-coding:

“Hey, we cannot finish this piece of work because we need that
piece of work from that other project and they’re not ready”

or

“It would be so much easier to parse this stream protocol if the length information was in the beginning of the stream…”

There are ways around everything, but having the right dependencies will make all work flow.

Dependency smells and refactoring

Dependency management can also be used when refactoring, by trying to identify “dependency smells”. Here are some examples that will show you what I mean and how I think about dependency management in the software design space. The examples are basically design principles versus dependency smells:

Don’t repeat yourself (DRY) vs Degraded Dependency (DD)
DRY:
“Remove duplication” – One of the core principles of all software development.
DD:
The code modules that should be depending on one single module is actually depending on two identical modules that are not the same, hence degrading both dependencies. This does not increase the code management burden to the double, but rather one order of magnitude, since the knowledge of the duplication must be passed on to and remembered by everyone involved.

Single responsibility principle (SRP) vs Piggyback Dependency (PD)
SRP:
“Let each module have one responsibility”. This principle is also interpreted as “Let each module have only one reason to change”.
PD:
If a module A has a dependency on a two-responsibility module B(r1,r2), but it is only interested in one of the responsibilities (say r1), there is an implicit piggyback dependency A->r2. This piggyback dependency will actually tie the application down, and make it more and more difficult to change over time.

Liskow Substitution Principle (LSP) vs Obscured Dependency (OD)
LSP:
States that a if a base module A (class/interface) is accepted for execution, any module B that extends A should be accepted as well. This principle protects the dependency B has on A.
OD:
Often when extension is used only to make A’s functionality available in B, or when the chain of inheritage gets long, LSP is in danger as complexity makes it harder to manage the original B->A dependency and its meaning. The functionality of the code can be validated by tests, but the design has been obscured.

Abstraction (Abs) vs Hardwired Dependency (HD)
Abs:
An abstraction tells that a module only has a description of its access points, not of how those access points will execute.
With this design pattern there is an explicit anti-dependency on the implementation.
HD:
When not using abstractions in code, executing modules are depending directly on other executing modules. This hardwiring has a tendency to spaghettizie over time, making it virtually impossible to change a piece of code without breaking another.

Dependency management and TDD

Well used, and especially with a low threshold for akward tests, TDD tends to lead to good design regarding dependencies. However, good knowledge of dependency management will lead to even better tests. I personally started to understand the value of dependency management when I started to write tests for my code, but I write much better tests (and code) now that I think in terms of dependency management.

Conclusion

By abstracting your thinking to using dependencies it is often much easier to reach good, concrete design decisions that will stand the test of time.