HELPFUL TIPS FROM AN EXPERIENCED SOFTWARE ENGINEER

Ifeanyi Ibekie
9 min readAug 11, 2022

--

The software engineering field is a fast-paced environment and I know that keeping up with trends in itself is a task but some engineers forget to build up good habits to live by in such an environment and this article is to help with that. I am definitely not the best software engineer in the world but in my years of writing code and building production apps, there are some general tips that I feel are really a good step in the right direction in being not just a senior software engineer but a good one at that especially if you are a starting your career. These are some of the skills I have learned (still learning) and I feel you should learn too.

Adopt a clean architecture (Fe/Be)

Every senior engineer mentions clean architecture and some engineers like to download clean architecture starter templates to adopt it but in as much as these templates exist and are easy to follow there is more to clean architecture than just following the templates. I see clean architecture as a lifestyle and an approach to software engineering that once you develop the mindset you can write or build software in a really clean way even when not following the exact patterns clean architecture demands. Here are my tips on a clean lifestyle:

  1. Wrap your data source as repositories: Every mode of entry of data from an external point should be grouped together preferably called repositories. This puts the control to one point, prevents repeated changes all over the code, facilitates testing and mocking, and finally debugging.
  2. Wrap your core business logic code related by domain or purpose into files (preferably called use-cases/services): This not only helps with readability and debugging but it also helps in implementing new business logic as in development most requirements may require a combination of two or more business logic code written earlier and It is then that you will appreciate taking this approach the most as new features will take fewer lines and kill repetition completely.
  3. Keep to a structured communication pattern across your code: One thing that confuses readers of code is when there is no clear flow to how data comes in, is processed, and output. Most libraries and frameworks already enforce this but if you are doing things the vanilla way or working out of the scope of libraries and frameworks it can be a huge problem. You should have a clear up to down flow from input to output and processing in-between and it should be a repeated pattern so that it is something that is easily understandable. This would prevent cyclic dependencies and would help in debugging unexpected side-effects in your code. This is a must especially if you are using the MVC pattern.
  4. Isolate constants into a file or group of files: I had to add this because it is deficient in some software codebases that I have encountered no matter how unbelievable it is. Every constant used in your application should be defined in a particular file/files this is because as trivial as constants seem when it comes to changing them, it would prevent a lot of bugs if there were in one place instead of having to do a find and search or something worse.
  5. Isolate your repeated utility methods into a file: Just as above any method that is cross-domain should be grouped into a utility folder, this is to help with debugging and changes, especially on a global scale.
  6. Separate your state from side effects: In any stateful implementation, you are coding to ensure that your state is different from side effects. That means your side-effects (methods that alter the state or respond to/from changes in state) get a copy of the state and perform their actions with that copy before persisting to the state. This pattern is used in so many front-end libraries e.g Redux and Vuex and it may seem trivial but it is a very useful pattern to adopt especially where there is one state and multiple side-effects.

The tips mentioned in the section are just patterns that will help keep your code clean but it is still highly advised you understand the proper clean architecture.

Protect your application process (Fe/Be)

As an engineer, your number one goal and security measure you can implement is to guard your application (process). This is simply protecting your application process to ensure that at all costs your application process will not break no matter what is thrown at it. I know this is really a tough one and may be absolutely impossible to guarantee 100% protection. Still, it is a good mindset to have in building applications as denial of service can be very costly to your application and organization at large. Here are my tips on protecting your application process:

  1. Wrap your side-effects with pure responses: Every application has side-effects and they are the most likely cause of errors that can affect your application process because of their dependency on a lot of IO that can fail. So when implementing side-effects handle error cases and ensure that they return responses that are pure to the callers (i.e Business Logic). This way, if a provider, database, or endpoint is down, your application is not hung and vulnerable to attacks.
  2. Code to cater for unavailability (Paranoid Code): Most developers code assuming all is well but even the planet we live in is imperfect so why should your code assume perfection? This is why I appreciate languages that enforce null safety because null safety is a guard that checks for the unavailability of data. So even if the code is as trivial as handling JSON or reading from an object or endpoint always add that check for unavailability of that data or the parent to that data (undefined or null checks) so that your application process will not panic (pun intended) on encountering those gaps.
  3. Always clear up console errors: I know this may sound like nitpicking but even production apps of big companies leave errors to be logged on their console and it is bad because not only may it leak sensitive info on the technologies used, it may slow down your application as writing to console is an IO operation and if you chain a million of them, they will drag your application. In some rare cases it is errors that do not necessarily affect your code and even if that is the case please try your best to fix them. You know what they say little drops make an ocean, always clear up console errors because not only do they improve your error handling they also improve your skills by helping you fix bugs and broaden your knowledge of your stack.

Atoms, Molecules, Elements (Fe)

For my front-end lads, if you are just hearing this for the first time then what have you really been building? The concept of atoms, molecules, and elements is just like that of chemistry. There should be a proper composition of your front-end code. You should have a component structure like buttons, input fields (atoms) that will be joined together in forms (molecules) in pages (elements) each with their specific codes separate from them, and communication is done from the smallest to the largest or vice-versa depending on the use-case. Even though HTML or JSX lets you juxtapose everything together it is a bad idea to do that.

Remember the underlying technology (Fe/Be)

This is mostly targeted at frameworks and the developers who code using frameworks. Do not forget that those frameworks are powered by an underlying language and there are some features and edge-cases that coding in vanilla language can just help you fix. This problem is so bad that I encounter some developers who code Flutter searching the Flutter Pub for a package for certain things that they can just write in Dart. Laravel developers are also guilty of these things as well because they depend on “Spatie-this” and “Laravel-that” for any feature forgetting that they are actually writing PHP. Frameworks introduce opinions, patterns, ease of use and structure so do not hesitate to implement any edge-case in the native language, not only will this boost your skills in understanding the interoperability of the language but you could implement helper libraries this way.

There will always be work to do

Some developers always try to give more than is expected in the early stages of an app/employment or some just love to over-engineer any task they are given. For instance, you are asked to implement email, and password authentication for a startup and because the requirements are not so specific you are rushing to implement 2FA (two-factor authentication). That is a clear case of over-engineering as you should only focus on the requirement you are asked to do this is highly advised because when you code you introduce bugs and trust me the hardest bugs to debug are bugs that are a result of your own over-engineering. Another example is coding to show off by trying to use recursions in places where a loop might just do. There will be always work to do so do what is required of that time and when the time comes to supplement any code you’ve written it will be assigned to you. Remember this is not an excuse for poorly written code.

Divide and Conquer Problem Solving

No programming article would be complete without mentioning this. Do not gloom over the requirement or problem in its wholistic scale, break it into chunks as easy as possible and attack it little by little, it may seem hard or impossible but with every small issue tackled you are a step closer to the bigger one. This easy-looking skill is what can make you the head of a team or even C.T.O in your organization because that is what those roles are about.

Dive into other people’s Code

No one is perfect, such is the code or package you are using so do not be afraid of tinkering into libraries, packages, and codes. The benefits to this are countless

  1. They will teach you new design patterns
  2. They will prove to you that even the most complex-looking frameworks are composed of simple bits and help you face your imposter syndrome
  3. Tinkering with them helps you learn from the best
  4. You can extract your use-case from them instead of having to install everything just to use only 5% of the library

In my personal experience, I usually had this feeling that my implementation of solving a problem was inferior and I would always resort to installing a library because I felt that if it were out there in the public it would be way better than my approach but looking into them has made me know that sometimes the way you think to solve a problem is actually not so bad of a solution and libraries may actually code it the same way you would or a tad bit better. So try to read packages you use on a daily, your curiosity will be highly rewarded as you would learn more and even tweak them to your perfect taste while not clogging your codebase with bloatware code just because of your heavy library dependency.

Comments

Do you know that one way to know a good developer is just by writing good and self-explanatory comments? In addition to proper function naming please write proper comments and keep proper code documentation. This would not only benefit the other developers but in a fast-paced environment, it would help you with context switching when you come back to a code that you have abandoned in a long time. Please write comments and clear and succinct ones at that.

Finally, coding software should be treated with all seriousness as civil engineering or medicine because the fact that your work is intangible and is reliant on computers doesn’t mean you should be sloppy because if the civil engineers or doctors were to be a bit unprofessional it could have dire changes and you should not wait till your application can hurt lives before you train yourself on best practices. Always code for accountability and give your best in everything you do. I am able to come up with all of these tips because I have developed such a mindset, try it and it would not let you down. Thanks and Happy Coding

--

--