Summary: ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.
ITNEXT
ITNEXT is a platform for IT developers & software engineers to share knowledge, connect, collaborate, learn and experience next-gen technologies.
In this post, we will go over 10 principles that will make you a better developer. Those will make you a more complete professional, improving:
- How you write code for maintainability
- What to focus on while writing code
- Improving application Security
- Observability so that you can monitor your production applications
Let’s go through the 10 principles.
1 — THERE IS NO DEV COMPLETE
It’s complete when production users are using it and meeting the conditions of acceptance, not when the code is committed.
)
Image of a person in the middle of a city and the universe
We are software engineers; we develop software. What value does software that is not in production add? It’s likely Zero. When used by live customers, our applications generate revenue, efficiency, and customer satisfaction.
The DevOps movement started 13 years ago, bringing developers closer to operational responsibilities. Trust me, this will change your life. For every line of code you write, you will think:
- What will the user see in this scenario?
- If this fails, will I get called at 2 AM?
- How many requests/sec do I need to handle here?
2 — KEEP YOUR COMMENTS TO YOURSELF
If you have to explain a joke, it’s probably bad. The same goes for your code.
)
90% of comments I’ve seen in codebases are not worth it. There are multiple drawbacks to comments:
- They are separate from the implementation, so there is a likely chance of the coding changing and the comment forgetting to be updated
- Redundant comments add no value, make the code larger and get hit by the update issue:
- TODO: Those are typical of staying left behind. Is it important enough to be done now? Do it now; otherwise, don’t bother.
When should I use a comment?
Sometimes, you have to explain some weird behaviour that method and class names can’t convey, for example, a production incident that the code protects against or a workaround we had to add because of this. It’s a rare, rare case.
3 — BOY SCOUT RULE
Always make sure that what you commit is better than it was before. Even the slightest improvement raises the overall quality of the codebase.
)
The boy Scout rule. Leave the campground cleaner than you found it. Source: https://www.jovanbienvenu.com/blogs/boy-scout-rule
If the commits never make the codebase worse, theoretically, it will never be worse. It may be larger and more complex, but never worse per se.
This is a perfect hook for refactoring. Refactoring for engineering is like washing the hands of a surgeon. You don’t ask the patient if he wants us not to refactor. We do it as part of our job. When working on a new feature in an existing codebase, would it be easier to add the feature if the code was refactored? Or try to hack your way in and make the mess even more complicated to understand?
And, of course, do not refactor just because you want to. Be a pragmatic professional with an intention in mind and balance with the product priorities.
4 — THIRD TIME’S A CHARM
If you have to do it more than twice, automate it. If you have to write it more than twice, refactor it.
)
Keep calm. Third time’s the charm. And may the odds be ever in your favor
That applies not only to code but also to manual processes.
Imagine you have a manual task on your deployment pipeline that only takes 5 minutes, so you won’t spend 1 hour automating it.
Those 5 minutes, compound, 5 minutes today, another 15 min tomorrow with 3x deployment.
Very quickly, your 5 minutes sum up to hours, and it would have been better to automate it. Therefore, the Third time’s a charm.
5 — DO NOT PIMP YOUR RIDE
Write clean, simple, elegant code that adheres to good engineering principles, including SOLID, KISS, DRY, YAGNI, and Tell-Don’t-Ask. If it’s not in the acceptance criteria, don’t add it. If you find yourself wanting to create an IRepository
, go and take a cold shower.
)
A product that looks good but is not functional
I’ve seen this multiple times, trying to over-generalise code, obsessing to reduce DRY, but missing the point: “ Duplication is cheaper than the wrong abstraction.” The code would end up with unrelated abstractions. Let me give you a typical example.
Imagine you are writing a web API, and you have a design system that the controller will handle the HTTP layer and then delegate the processing to a service. So, all controllers need to execute a service.
What you might see is an interface like this:
So now all controllers can call IService.DoStuff(), and we reuse this interface. That’s what a MediatR pattern adds: fancy syntax to provide you with the IDoStuff interface.
The downsides:
- Code navigation becomes horrendous; you can’t go to the definition and must know how to find the handler via name patterns. (Pray you don’t get confused or find an old version. Been there, done that)
- You lose valuable naming power. When you name each service, you can convey what the service is doing rather than I Execute().
- Cohesion issue. Things that change together should stay together. The handler's registration is in a separate file and is most likely only used once.
I advise keeping it simple: Interface segregation per service, and no need to write generics. In fact, you are rarely going to be using generics
Simplicity is the ultimate sophistication.
6 — YOU ARE NOT ALONE
You are almost certainly not the first person to solve this problem. Go and find out before you try.
Most of the time, you will be in uncharted territory, doing something in a business or technology you have not mastered. As a software engineer, your most important skill is knowing how to Google things.
If you get an error, you can Google the error code or just the key part of the error message. Eighty percent of the time, you will find a StackOverflow with the answer. The other twenty percent of the time, you might have to resort to looking into GitHub issues for the repository of the package you are working with.
While googling, each word you give has importance on the results, so I don’t add things that do not narrow the search. For example:
Bloated: How to interpolate string c#
Lean: Interpolate string c#
7 - NO RACING STRIPES
Performance is a key part of working at scale, but optimisation is driven by business needs and based on profiling and performance test results. If you find yourself burning time trying to shave milliseconds off of a method on your local machine, go and take a cold shower.
)
Pareto principle, 20% effort results in 80% resutls
What is faster, an If-else or a ternary operator? It doesn’t matter.
The users won’t feel optimisations in nanoseconds, even a couple of milliseconds.
Optimise performance based on data from production and following the Pareto principle.
I only preemptively care about performance when algorithms are at O(n²), avoiding the Big O squared at source by spotting it early. A common way for this to happen is for syntactic sugars that hide for loops in C# Linq or JS collection methods.
A more in-depth explanation.
8 — You are not Daredevil.
If you can’t see a problem, you can’t fix it. Always write in logging and instrumentation from the outset and ensure it goes somewhere you and anyone else who needs it can see it. Deciphering cryptic messages in the middle of the night should be left to MI5, Dan Brown characters and people in tin-foil hats.
My added value for this principle is how you log it.
Please don’t add a line every place in the codebase telling what action is happening.
It makes doubles or triples the size of the codebase and will provide you with cryptic data. In the past, we had tools like log4net, where you could have a single text file looking like this:
03/22 08:51:06 INFO User has added product123 to cart
03/22 08:51:06 INFO User has clicked “go to checkout”
03/22 08:51:06 INFO User has purchased
But what happens when you have ten concurrent requests? All log lines will interlap, and you will feel like Alan Turing.
Could you use an APM (Application performance monitoring) tool? Something that gives you a log context per request, request count, failure rate, latency, and so much more.
)
Application insights screen, displaying a log context for a specific event
Until now, AppInsights from Azure has been the best for me. It can be implemented within 5 minutes and has low running costs.
9 - IF YOU CAN’T GIVE IT A GOOD NAME, IT’S DOING TOO MUCH
If you can name a method or class really well, it probably does one thing and one thing only, which means you’ve figured out a decent way to separate your concerns. If you find yourself wanting to call something ‘Manager’, go and take a cold shower.
)
Lord of the rings meme, One does not simply call things “helper”, “utils”
The biggest code smell I often see is poor naming if we see things named “utils”, “helper”, or “manager”. The easiest way to find out if something is following the Single Responsibility Principle is to write a phrase about the responsibility of this class.
As soon as the keywords “AND”, “OR” appear in this phrase, its the smell it’s doing more than one thing. Another way to see the single responsibility principle is that this class should change for only one reason.
10 — THEY TOOK ‘GULLIBLE’ OUT OF THE DICTIONARY
RANDOM STRANGER: “Close your eyes and open your mouth”
YOU: “No way! You could put anything in there!”
)
Trojan horse picture
The same goes for validating your input — if you don’t check what someone’s putting into your system, don’t be surprised when it turns out
to be something nasty.
When developing web APIs, I want you to think you are a sitting duck. Attackers might pounce on your application at any point. So, sitting there and allowing any input into your application will result in tears.
This goes for business rules, ensuring validations rules are applied, but also for security purposes. In multiple attacks, the attacker has to add crazy inputs into the system to inject JS/HTML or SQL where they shouldn’t.
Wrapping it up
If you got this far, congratulations. You are putting in the effort to become a better developer. Those principles are not everything, but they give you a good direction, so I recommend revisiting them every couple of months.
How will you apply them?
Founder at Koritsu AI. FinOps and Cloud expert with a background of 15 years in Software Development
Responses (14)
Noah Yejia Tong
What are your thoughts?
Really nice article and I agree with most of what you say except this statement.Comments are part of the code and should always be treated as such - they are not an overhead, a "nice to have", they are an essential aspect of future maintainability…
30
I advise keeping it simple: Interface segregation per service, and no need to write generics. In fact, you are rarely going to be using generics
I thought the article was pretty good. Lots of good points. I'm not exactly with you on the comments about generics. I use them quite a bit and I think when used and understood properly they are very powerful and helpful.
59
Nice article! Written in a funny way :-)What I missed is the part with documentation. I am expecting from one very good developer to be able to write technical documentation. But this is maybe a separate topic :-)
45
