Jason Gorman of CodeManShip gave an interesting talk on code craft this week. The talk began with the business case for Code Craft, based on the cost of changing a line of code. If you compare the number of changes in source code repository to the expense of their development teams, the cost generally increases massively over time – 40X more expensive per line of code change after 8 years for one company. The same hockey-stick chart appears in Kent Beck’s book “Extreme Programming Explained”. Code Craft skills tend to flatten the cost-of-change curve, which is good for the business, and make the code easier to change, which is good for the developers.
Code Craft Skills
Write good unit tests, use version control, do continuous integration, apply design principles, refactor code safely.
Cost – if the cost of a change in design is 1, then the cost in implementation is 6.5, in testing is 15 and in maintenance is 100. Bringing testing forward in the development process gives a massive return on investment. Legacy code can be defined as any code that doesn’t have fast running, automated unit tests that can discover a bug quickly – enabling a cheap fix. You must automate testing and enable the feedback loop to iterate quickly – ideally in minutes or seconds.
Readability – 50%-80% of time spent on a codebase is reading code, not writing it. Making code easier to read and understand has a great pay-off. Code that’s hard to understand is easy to break.
Complexity – attack complexity, try to replace it with the simplest thing, which is less likely to be wrong.
Duplication – never copy/paste code, especially off the internet! You have no idea if it works or even compiles. Making changes to common logic is multiplied if there’s duplicate code. Duplication is the opposite of reuse – generate an abstraction to help improve the design. Duplication can be hard to spot (e.g. customer playing several roles which could have been parameterised).
Ripple Effect – a change to one area of code breaks a much wider circle of code. Cost of change greatly increased – need to have a local effect from a small change to code.
Principles of Clean Code
The speaker also coaches teams in the following principles:
1. Shorter feedback loops – automated unit testing. Not possible with manual testing iterations or a manual testing phase. Automated system testing can give good coverage, but is often too slow, can take hours to run. Need to run in minutes or seconds. Ideal chain is Unit Testing -> Integration testing -> System testing. Want most of the testing in first layer, minimal number of smoke tests in the top System layer.
2. Simple Design – the code works, clearly reveals intent, free of duplication, made out of simple parts. Need another pair of eyes to check the code is easy to read. Code review your own code every few minutes.
3. Single responsibility – traditionally, this is taught as classes should only have one reason to change. Or better, look at the number of combinations of the sections of code implemented in a function – it’s more powerful to break functions into smaller parts then use composition to implement the larger function. Smaller components/functions => many more ways to re-use. So give each piece of software a single responsibility.
4. Tell, don’t ask – lots of low-level coupling between objects. Better to have objects sharing smallest possible interface to each other. Don’t pass the whole object – pass the data needed to do the operation. Put the work where the knowledge lives – do the work in the right place so that data and behaviour belong together.
5. Dependency Inversion – you should be able to swap your dependencies. Talk to dependencies as abstractions through interfaces. Eg1 all commands inherit from ICommand and high-level components work on generic interface, not concrete classes. Eg2 VideoRental example, rather than coupling to Imdb, replace with an interface. Better for mocking/testing as well.