This post contains advice I wish I had been given when I started my career as a professional software developer – an attempt at sharing some of the things that I’ve learned in the last few years. If you’re a beginner developer I hope you’ll find this post helpful.
Write Unit Tests
If you want to be considered a professional, you must write unit-tests for your code – shipping untested code to production is unprofessional. Writing unit-tests shows that you care about the quality of your code and of the system as a whole. It also shows that you care about your team and your company. Code that has unit-tests is easier to write, understand, maintain and modify.
For someone who’s never done it before, writing unit-tests can seem very challenging at first but once you start writing your first tests, you’ll see that it’s actually very easy. You’ll probably wonder why you’ve never done it before. The key, and this is critical, is not to try to write unit-tests for existing code that has not been designed to be testable. You can only write tests for code that has been designed and written to be testable. What does testable code look like? As a rule of thumb, if your code satisfies the Solid Principles of Object Oriented, it should be very easy to test. I would suggest starting by writing unit-tests only for new code. Once you get the hang of it, you can move on to your older code. This will first need to be refactored and made testable before you can unit-test it.
A mistake many developers make is considering unit-tests as something extra and optional, that can be added once they finished working on a new feature. However, a new feature should not be considered finished until its corresponding unit-tests have been written. They are as important as the production code and should be taken into account when giving your time estimates.
Another mistake related to unit testing is thinking that they make the development process slower, that things will take longer if you have to write tests as well as your production code. That’s probably true when you first start writing tests. Once you get the hang of it, you’ll see that they actually make writing code easier and faster. Having to write testable code forces you to write code that is cleaner and modular, with proper interfaces. They also allow you to run parts of your code instantly, giving you immediate feedback as to whether things work as expected.
Code Quality Matters
It’s not enough to simply write code that works. Your code also needs to be maintainable, which means that it should be easy to understand and modify by other people. The names of the variables and classes you choose, how long your methods and classes are, the number of dependencies that your classes have – they all matter.
Before you sign off your code, make sure that it’s as good as it can be, that it’s consistent and that it conforms to your company’s standards. You should assume that other people will have to read it, understand it and modify it when you’re not there. Having to tidy up your code after you’ve finished will probably mean that things will take you a bit longer to finish. That’s fine, this extra effort will soon pay for itself tenfold or more. The reason for this is that developers don’t spend most of their time writing new functionality. Most of their time is actually spent going though existing code, trying to understand it and figuring out how to add new functionality. Code is written once but read hundreds of times.
This also relates to the The Boy Scout Rule: Always check-in a module in a cleaner state than when you checked it out. If you’re working on existing code, you should try to leave it better than you found it, even if it was originally written by someone else.
Perfect is the enemy of good
A mistake I constantly used to make was trying to implement design features in the most generic way, trying to support potential future features that may or may not have been requested. The reason I did this was that I used to see code as something static: once the code has been written, you’re not supposed to change it.
But if you see your code as something that you need to get right the first time, then it’s very hard to get started – it’s almost paralyzing. Not only that, but very often you also end up with overly complicated code, that is hard to maintain, with features that will never be used.
The key when working with software is to treat it as something that should be constantly changing and evolving. Existing code is supposed to be reviewed on an ongoing basis and improved or refactored if needed. This approach to software development makes the design process for new features much easier. You actually don’t need to anticipate what features might be requested in the future. Things don’t need to be 100% generic. You can create a simple design that supports the requested features. If new requirements come up in the future that force you to change your existing design and make it more flexible or generic, that’s fine. The idea is to stop trying to avoid changing existing code and see it as something that is part of the development process.
For this approach to work, existing code needs to be easy to understand and modify. You also need to have a good test suite to make sure that changes to existing code won’t introduce new bugs. If you have proper tests, you can improve your code as much as you need without fearing that you’ll create new bugs or make the system unusable. As long as all the tests pass, you’ll know that everything is ok. On the other hand, if you don’t have tests, then making changes to existing code becomes a risk, no one in the team will want to do it and you’ll end up with stale code.
Don’t Stop Learning
If you want to stay relevant, then you have to keep learning and stay up-to date with the latest technologies. This might seem obvious and you’ve probably heard it before, but it’s not a trivial thing to do. Learning new things, especially when you might be working full time and also juggling family commitments, requires effort and discipline. It’s important to make time to keep learning on an ongoing basis. There is also the issue of what to learn. There are new frameworks, languages, databases and tools popping up all the time. My advice would be to start by learning the basics of software engineering, so that you can write good code, and worry less about learning the latest framework or database. Not much point in using the latest framework if you’re going to write complicated code that it’s hard to understand and maintain. I would recommend the following books to someone who wants to improve the way they design and write code:
- Head First Design Patterns
- Clean Code: A Handbook of Agile Software Craftsmanship
- The Pragmatic Programmer: From Journeyman to Master
- Refactoring: Improving the Design of Existing Code
- Code Complete
Once you have a good foundation, then you can move on to learning new frameworks or languages. Just keep in mind that frameworks come and go, so don’t get too attached.
So, that’s it. What do you think? Are these things that you’re already doing?