Over the 15+ years of my development career, I have learned several things that significantly increase my effectiveness. In this post, I share those learnings with you.
Over the 15+ years of my development career, I have learned several things that significantly increase my effectiveness. In this post, I share those learnings with you.
Structure:
This blog post mentions and links valuable concepts that you can explore further as you see fit.
As developers, we like writing code. Most of us want to be given a nice unambiguous task. A fun technical puzzle to solve without paying attention to the rest of the world.
Put reasonable effort into making sure that you are solving the right problem. To quote Peter Drucker: There is nothing so useless as doing efficiently that which should not be done at all . Gather feedback early and often, typically by continuous delivery to real users. Be Agile .
Software development is expensive, with the vast majority of the effort of real-world projects typically going into maintenance. Combine this with the goal being user/business outcomes, the best code is often no code . To quote Bill Gates: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight."
See also: YAGNI , KISS , The Last Responsible Moment .
During the first 5 years of my development career, I thought that software design is for software architects or other people with special roles. I was focused on "getting things done", and saw software design and practices such as writing tests, as a distraction at best. My code worked, and I was getting a lot of things done. Or so I thought.
Then I read Clean Code , by Robert C. Martin . This book motivates caring about software design and contains examples and many technical heuristics. The central takeaway of the book is: "The only way to go fast is to go well". In other words, if you make a mess, it will slow you down . See also: TradableQualityHypothesis , DesignStaminaHypothesis
Learning how to write well-designed clean code of course takes time and effort. And when you start, you will be slower and make mistakes. Simple is not Easy .
Writing tests tends to be beneficial. There are exceptions, but most of the time, it makes a lot of sense to write automated tests. Writing tests is an example of a best practice.
If you are new to writing tests, just follow the best practice and write tests for everything.When starting, blindly following the best practice will be better than following your own underdeveloped judgment. Over time you will learn how to write tests effectively, and be able to tell the difference between you have messed up, and situations where writing a test is not worth it. You will also start to understand the value tests bring on a more visceral level, by having experienced the decrease in debugging sessions and the worry-free refactoring enabled by your tests.After developing your judgment, you will be able to transcend the best practice.
This advice applies to best practices in any area that you are a junior in. Automated tests are just an example.
One big gotcha is that it is not easy to tell the difference between a sensible best practice and something nonsensical or even counterproductive. This is made more complicated by most existing code being a mess, and by most developers, including "experienced" and "senior" ones, not knowing software design basics. This makes having a good mentor extremely valuable. Barring that, one piece of advice based on my own experiences is to be wary of best practices specific to the community of your language or framework. Look for evergreen advice that has been around for decades.
Our focus will be on technical topics. Many other areas are important, such as health, happiness, career, and soft skills. Knowing how to avoid a technical pitfall won't help you if you are sleep deprived and working on the wrong problem for a toxic boss that underpays you.
Write automated tests. Perhaps write tests before the code, such as via Test Driven Development (TDD). This makes it easy to verify your code is correct in a repeatable manner, thus saving you from much manual retresting and from debugging sessions.
You think test-first is difficult? Try debug-after.
Perhaps even more importantly, tests give you the safety net to refactor your code. And continuous refactoring is needed to keep your code clean. Without a reliable test suite, it is all the more likely that your code will rot.
Writing tests is difficult if the design of your code is poor, such as when using inheritance for code reuse, or when using static functions. If on the other hand, you have SOLID classes, with no global dependencies, then writing nice tests is not so difficult.
Test design matters because poorly written tests will slow you down. Avoid binding your tests to implementation details of the code under test or to the structure of the system. Avoid overusing Mocks and write better Test Doubles .
This is one of those best practices that bring to mind the "Use the Best Practices" section. My advice: do not use inheritance for code reuse at all when you are starting out. It is rarely the right call and can do a lot of harm. Favor composition over inheritance .
Write SOLID code that is not STUPID . There is so much value in understanding these principles and anti-patterns.
Actually create objects. Classes with only static methods are not OO. Try to avoid using static code altogether.
See also: my defense of SOLID .
( Functional programming is not to be confused with imperative structural programming .)
This point is not about fully switching to a functional language. You can benefit from using a functional style in your OO language. Minimize state , especially mutable state, and do one thing in your functions . See also: functional core, imperative shell .
Copy-pasting big chunks of code to multiple places is almost always unwise. Any self-respecting developer soon learns this and starts to follow some form of Don't Repeat Yourself (DRY). Unfortunately, the well-intended pursuit of DRY often leads to overengineering and accidental complexity. This is where the counterpart of DRY comes in: Write Everything Twice (WET). The idea behind WET is to only deduplicate on the third occurrence of duplication.
For a more in-depth look at the costs and benefits of deduplication, see The Fallacy of DRY .
Try to write self-documenting code and avoid comments.
Every time you write a comment, you should grimace and feel the failure of your ability of expression. -- Robert C. Martin
Comments are dangerous because they can lie. The code can change without the comment being updated. New code can be added right under the comment. The comment might have been wrong or inaccurate in the first place. When this happens, the comment not only becomes useless, it becomes misleading.
To write self-documenting code:
Clean Code by Robert C. Martin has some good rules of thumb about naming and comments.
See also: Recommended Reading for Developers by Jeff Atwood
Jeroen De Dauw is CEO of Professional Wiki , which provides wiki hosting services. He occasionally writes on his software design blog . You can follow Jeroen on Twitter .