Problems I face as a Software Developer

Below are some problems I have experienced at work (mostly working on large enterprise systems). I have attempted to describe and share some of the ways my team tried to overcome these issues.
1. Making technical decisions and forgetting why we made them.
“Why the hell did we do this, this way??”
Example: Have you seen some portion of code in your code-base where there is an obvious easy and simple way to implement something but you see that it’s implemented in a somewhat complicated manner. It’s probably because at some point that was the only viable option for the developer. Once you start refactoring this you will realize why it was implemented in the concocted manner it was.
Solutions tried by our team:
(Not in any order)
- Tech logs: Have a markdown file in your code base where we explained the decisions and some description. Helps to add date as well.
- Depends on how it’s organized, might get messy though. Other developers are not quite aware of this Tech log and might not use it after a while.
2. Comments: Leave a comment explaining the decision very close to the code you feel other developers will find strange.
- Comments might become obsolete if not careful.
3. README: Add a section to describe technical decisions to your README.md
- Might clutter it beside all those setting up instructions.
4. Keeping it in your brain: Or one can just not do anything about it. The next person in your team will figure things out just as you did.
- :smirk:
2. Having different ways of implementing the same thing.
Should I use Tom’s way of generating a JSON result manually using JsonMapper or Harry’s way using Jackson?
Example: When given a task to expose a REST endpoint, and there are two different existing implementations. They both work fine. Which one do you follow for consistency? Or do you change one of the implementations?
My Explanation: For other developers, it is confusing to understand the code. Are the implementations different because of a conscious business decision? Or is it just a developer preference thing? This creates inconsistency in the code base
Solutions tried by our team:
(Not in any order)
Learning sessions on the correct usages of certain concepts/frameworks.
Discussion to learn and understand other developers’ styles/intentions
3. Inconsistency in naming of business terms.
userId, userNo, userName, name, id, personName, clientNo, clientName??
Example: Imagine working on a booking system and dealing with “price”, “cost”, “fees” and “ticketPrice” (in the code base) to refer to the same thing or maybe slightly varying concepts of the business.
My Explanation: It leads to confusion among developers and just confusion understanding the code base. Things get worse when there are external systems also using these terms. Imagine having a discussion where developers are referring to different entities but each think they are the same.
Solutions tried by our team:
(Not in any order)
Domain modeling sessions for the team.
Learning session to understand the origin of these terms. To make a more informed decision on the naming.
Maybe even a deeper business understanding.
4. High coupling between our code base models and other systems’ models
Models here refer to the objects that model the problem domain object.
Example: Imagine consuming from an external API and also importing its models, and then using it all throughout your code base. That’s actually fine, if this external models are not going to change often and if all the attributes are used as is in our code base. However, if this is not the case, we are calling for high coupling between 2 systems.
My Explanation: There have been times we are using a weird named model in our code base because the team that crafted this external model just did a bad job. Instead of polluting our code base with the bad naming, we can convert the model to our internal model and even use appropriate data structures to represent the attributes, that’s more suited to our needs.
Solutions tried by our team:
- Making the other system’s models as Data Transfer Object (DTO) and creating our own data classes to be used within our code base.
5. Missing out on certain use cases
And repeatedly missing them out…
Example: Imagine implementing new features and closing stories only to realise that some edge use cases were missed out. Just every time…
Solutions tried by our team:
(Not in any order)
Paste stickies of those scenarios on your sprint board or developers’ screens. (Not the best idea!)
Acceptance Test Driven Development sessions.
Proper functional tests covering these edge cases.
Acceptance criteria written for the every story being picked up.
- Maybe even a Given-When-Then
6. Functional tests are always flaky
And therefore, no one bothers fixing them when they do fail
For us to write proper Functional tests, we need to either containerize all the downstream systems we are consuming or mock them, which gets a little complicated when dealing with a variety of different types of systems (especially really old technology). If not we will have multiple write issues. Or worse, if we are connected to the actual systems, there are chances that those systems aren’t up when the tests are run.
Note: In normal scenarios, we can containerize systems and run a reproducible setup for each test.
Solutions tried by our team:
(Not in any order)
Whenever someone is free, we created mocks (like fake implementations hidden behind feature toggles)
Before introducing a new dependency, we create an interface with an actual implementation and a fake implementer class.
7. Too much dependency on external systems.
When component X is down our development application is down.
If it was just one external system, we would have run it locally. However, when there are multiple such dependencies, we need really high CPU power to run all of them locally.
Worse of all, when this external system is still in beta and we are already consuming it. We need to be able to adapt to their changes smoothly.
Solutions tried by our team:
(Not in any order)
Try containerizing these dependencies. Then connect to the docker instances.
Mock all external API calls. We used feature toggles and Jsons for mocking of these services.
Encapsulate the models/clients used to interact with the external system, such that the impact remain to a few classes and not throughout the codebase.
Please share which problems you guys can relate to and some of the ways your team is solving them! I would love to learn more!


