Hello, buddies! During the past two weeks, I have been reading a fantastic book that introduces key concepts and techniques that professional and experienced software engineers regularly use to produce reliable and maintainable code. But this is not just for Software engineers; it's for everyone in the Software Development field.
Good Code, Bad Code book aims to explain the core reasoning behind
each concept and technique, as well as any trade-offs. This should help readers develop a fundamental understanding of how to think and code like a experienced software engineer
Here you can read some key points of the book, but this won't cover the whole gold mine. I highly recommend you to read the whole book by Manning Publications by using this link. If you want to try your luck and get a free book of "Good Code, Bad Code", scroll down to the end of the article and fill in the small form.
And one of the best things that are gonna happen is, you can get any book from Manning Publications with a 35% discount, using this code: blunbuddy21
. Don't forget to say Thanks to Manning Publications!
Code Quality
We've heard this word thousands of times but who cares? This chapter is one of my favorites, let me elaborate more on this topic.
In everyday life, we interact with software a lot. There are many pieces of software that we depend on. Think about a banking app that doesn't have a well-behaved backend system, is going to unexpectedly transfer the contents of our bank account to someone else, or suddenly decide that we’re in millions of dollars of debt! A small bug can ruin lives.
Higher-quality code tends to produce software that is more reliable, easier to maintain, and less buggy which makes it is one of the most important things in Software development.
The goals of code quality 🎯
Defining code as being high quality or low quality is an inherently subjective and somewhat judgmental thing. To try to be a bit more objective about it, you should look back at the code and figure out what exactly you're trying to achieve by this piece of code. Tom Longs suggests the Code which helps anyone to achieve these 4 things is a high-quality code.
- It should work: Your piece of code must work
- It should keep working: It should keep working all the time, without breaking in anywhere.
- It should be adaptable to changing requirements: It’s quite rare that a piece of code is written once and then never modified again.
- It should not reinvent the wheel: You don't have to code a file importing system from scratch when there's a library for it.
Pillars of Code Quality
The 4 goals we just looked at help us focus on what we’re trying to achieve, but they don’t provide specific advice about what to do in our everyday coding. I think it'll be useful to see some strategies that will help us to achieve these goals easily.
Make code readable: If our code has poor readability, other engineers will have to spend a lot of time trying to decipher it. There is also a high chance that they might misinterpret what it does or miss important details. If this happens, then it’s less likely that bugs will be spotted during code review, and it’s more likely that new bugs will be introduced when someone else has to modify our code to add new functionality. Commenting on code can be a solution sometimes, but it's easier and safe to make your code readable itself.
Avoid surprises: Surprises are very nice on your Birthday but when we’re trying to get a specific task done, surprises are usually a bad thing. In software systems when some code does something surprising: because the caller of the code doesn’t know to expect it, they carry on unaware. It will often look like things are fine for a bit, but then later things will go horribly wrong when the program finds itself in an invalid state or a weird value is returned to a user.
Make code hard to misuse: Code we write is often called by other code. We expect that other code to insert certain things in, like input arguments or placing the system in a certain state before calling. If the wrong things get inserted into our code,
then things might blow up; the system crashes, a database gets permanently corrupted, or some important data gets lost. Even if things don’t blow up there’s a good chance that the code is not going to work.Make code modular: Modularity means that an object or system is composed of smaller components that can be independently exchanged or replaced. Simply, this means that you have to make your code just like a LEGO toy. Others should be able to remove and add things without breaking the code.
Make code reusable and generalizable: Reusability means that something can be used to solve the same problem but in multiple scenarios. And Generalizability means something can be used to solve multiple conceptually similar problems that are subtly different. If we get a hand drill, it is also Generalizable because it can be used to drill holes, it can also be used to drive screws.
Make code testable and test it properly: It’s hard to explain how testing is important is in software development. There are different levels of testing such as Unit testing, which is well described in the book.
Writing high-quality code slows us down? 🤔
When thinking about how to do all these things, you may have often questioned that doesn't this slow us down? The book has a beautiful example, let's take a look at it.
You are putting a shelf up at home. You get two ways of doing this,
The proper way: We attach brackets to the wall by drilling and screwing into something solid like the wall studs or masonry. We then mount the shelf on these brackets. Time took: 40 minutes
Hacky way: We buy some glue and glue the shelf to the wall. Time took: 10 minutes
How nice! The hacky way saves us 30 minutes. We glued the shelf to whatever the wall is surfaced with; this is most likely a layer of plaster. Plaster is not strong and can easily crack and come off in large chunks. When we put some weight on the shelf, it will fall down and now you don't have a shelf and your wall is also awful so you're gonna redecorate it which will take you hours; sometimes days!
You get the idea. It might seem like doing it in the proper way is a waste of 20 minutes but when compared to the time and hassle by the "bugs" made by the hacky way, the proper way saves us a lot of time.
Therefore, writing high-quality code never slows you down. It just makes great software.
Working with Other engineers
Creating software is usually Teamwork. A company making software may have hundreds of developers creating hundreds of projects and you may often have to work with other people's code as well as they will work with yours.
Therefore, when writing code; even though you're single, you have to care about these things.
1. Things that are obvious to you are not obvious to others
When you get down to writing some code, you have probably already spent hours or days thinking about the problem you are solving. You may have been through several stages of design, user experience testing, product feedback, or bug reports. You might be so familiar with your logic that things seem obvious, and you barely need to think about why something is the way it is or why you are solving the problem the way you are.
But what bout your teammates? They will need to interact with your code, make changes to it, or make changes to something it depends on. They will not have had the benefit of all your time to understand the problem and think about how to solve it. The things that are obvious to you aren't obvious to them
Therefore, It’s useful to always consider this and make sure your code explains how it should be used, what it does, and why it is doing it.
2. Other engineers will inadvertently try to break your code
Sounds cynical. Your code probably depends on multiple other pieces of code, and these, in turn, depend on even more pieces of code. And there are probably yet more pieces of code that depend on your code.
If another engineer makes a change that breaks or misuses your code, then you want to ensure that their change does not get submitted into the main codebase until they’ve fixed the issue they’ve caused. The only two reliable ways to do this are to ensure that, when something is broken, either the code stops compiling or some tests start failing. A lot of the considerations around writing high-quality code are ultimately about ensuring that one of these two things happen when something is broken
3. In time, you will forget about your own code.
The piece of code you just wrote is in your mind and you will never think that you will forget it. But we're not machines, we forget things. By that time, you will forget the code that you wrote and ask someone else about it. This won't matter until a new feature comes along, or a bug gets assigned to you in a year’s time from now, you might have to modify that code you wrote and may no longer remember all the ins and outs of it.
Looking at code that you wrote a year or two ago is not much different from looking at code written by someone else. Make sure your code is understandable even to someone with little or no context, and make it hard to break. You’ll not only be doing everyone else a favor, but you’ll be doing your future self one too.
Unit Testing
Unit testing involves the testing of each unit or an individual component of the software application. It is the first level of functional testing. The aim behind unit testing is to validate unit components with their performance. In the book, it has beautifully explained what exactly is Unit Testing, highly encourage you to get the book yourself!
What makes a Good Unit Test?
While you may think it is not much important, it is the most important part of making good software. When it is not going well, it may lead to many problems such as unnoticed bugs, unable to maintain, etc. So knowing what makes good unit testing is important.
- Accurately detects breakages—If the code is broken, a test should fail. And a test should only fail if the code is indeed broken (we don’t want false alarms).
- Agnostic to implementation details—Changes in implementation details should ideally not result in changes to tests.
- Well-explained failures—If the code is broken, the test failure should provide a clear explanation of the problem.
- Understandable test code—Other engineers need to be able to understand what exactly a test is testing and how it is doing it.
- Easy and quick to run—Engineers usually need to run unit tests quite often during their everyday work. A slow or difficult-to-run unit test will waste a lot of engineering time.
That's only a bit of the book!
Yes, 1000 words can't cover this gold mine. The book has a lot of things— I mean really a lot of things in those 300 pages. I highly recommend you to get it and read it yourself. Once you've read it, you will find some coding techniques that will take years to learn by experience.
Get the book here
Now I guess it's the time for,
Giveaway!
Yes, to be thanks to the Manning publications, you can try your luck to get a free eBook of "Good Code, Bad Code". Just fill this 2-question form here. Or, you can buy it yourself with a 35% discount using this code: blunbuddy21
And that's all for today. Don't forget to read the book and happy coding! See you soon ✌