The Seam Model
Programming languages are not inherently easy to test. In most popular languages, the IDE and libraries will allow a programmer to write code without having much forethought. With the increase in software developer positions attracting people from all backgrounds, software design principles become increasingly important.
This means that we need to design for testability. With the large number of test harnesses available (see my last post), Test Driven Development is a great way to tackle designing code for testing.
Test Driven Development (TDD) – The development principle where programmers will write a simple (failing) test case for application requirements before application code. Once the test is built, the code is written to allow the test to pass, and the next test case is written. This process is repeated, creating short development cycles with tested code.
When working in legacy code, you aren’t usually starting with a fresh class. You are likely chipping away at a monolith of untested, difficult to read, challenging code. Most developers are writing for modularity, so where does this come from, and how do we tackle it?
Modular code should be small pieces, easy to reuse and combine elsewhere. When I was working on my B.S. for Computer Science, the idea of modular code was simple – but most of my projects had less than a few thousand lines of code. When we move into these large legacy systems, we realize that most ‘Independent’ and ‘Reusable’ code has some sort dependency on other code.
This happens for a variety of reasons. Most systems start off with a clear, well defined vision for what the code should be. As time passes – teams, deadlines, standards, technologies, etc. all impact the same project. So how do we start separating and testing this code? We do it by using seams.
Side Note – Speaking with Director – In one of my legacy systems, I had the opportunity to speak with a director who used to be a senior developer, and was one of the lead contributors of my system! I asked about the eventual disregard of the architecture, specifically business logic going in the presentation layer.
He explained that as waterfall project management started to fail the teams, correct architecture was disregarded to meet deadlines. I think this is a common occurrence, but to hear it from such a highly regarded figure cemented this possibility.
Seams – A seam is a place where you can alter behavior in your program without editing the code in that place.
Approaching your next project looking for seams is incredibly valuable. As a developer, you want to see opportunities that exist in your code base, and create seams as you work. When future developers are working in your code, this will help protect that code from decaying design!
If we can replace behavior at seams, we can selectively exclude dependencies in our tests. As we discussed, we want to be designing with Test Driven Development, and if we make our code easier to test, we are protecting the system down the road.
Side Note – Real World Seams – As a car enthusiast, I have encountered a lack of seams in the real world. Volkswagen/Audi Group developed a whole platform of turbocharged cars where they cast all of the turbocharged components into the exhaust manifold. This was probably a cost savings decision.
The idea of a turbocharger is simple; exhaust gas spins a turbine, which compresses air as it enters the engine. The turbocharger itself is mechanical, so it needs a way to release the compressed air once the correct amount of pressure exists. The mechanical release for the air is called a wastegate.
A wastegate is a small and inexpensive part, but it was cast into the same piece as the turbocharger. In the case of a failing wastegate in this Volkswagen/Audi platform, you will have to spend the money to replace the exhaust manifold, turbocharger, and wastegate.
If Volkswagen had thought to create a seam between the expensive turbocharger and inexpensive wastegate, the resale value of their vehicles in this generation would be significantly higher.
Summary
When working in legacy systems, always keep an eye out for areas where you can create seams. When developing new code, it is important to approach the code with testability design in mind. Test Driven Development is the best way to do this, and seams will enable you to get your code into a test harness. I will discuss different seam types in the next post.