Software engineering challenges I've found difficult

02 December 2022

prosoftware-engineering

The most difficult

The most difficult engineering problem I've had to solve is finding common ground with incompatible views from people with different priorities and skill levels.


A good human being and a terrible engineer

Another is working with a person who is a good person but a terrible engineer. Not an engineer at all, to be honest. A code cowboy. With zero self-awareness about where they stand as a programmer and desire to improve. Imagine you have a business person as a cowerker who learned enough coding to be able to show working UI to the manager, and do it quickly.

The problem was that this person had already done a lot before I even came into the picture. They were established in the eyes of our manager for pushing out new features fast. I couldn't just go in and start fixing all the terrible "infrastructure"(think random code that was put together by a business person who had to quickly code something. Code that had been thought in isolation, without any thoughts of how it would have to work together). Thoughts of how anyone new would have to work with that code in the future weren't even an afterthought. They were non-existent. A ton of guesswork of what the code author meant and relying on hope that new things don't break the old.

The attempted solutions were too many to go into detail here. Maybe in some future posts. Long story short, there was a ton of team effort to try to adapt the team's workflow to the rogue developer's workflow, to not have to let them go. There were discussions about how the approach of the rogue dev was incompatible with our current team. And often the obvious solution was to either let this dev work on some rogue(isolated) project where they can once again do as their heart desires or to let them go. They were eventually fired but that was unfortunately after my perseverance tank ran out.


Architectural problems

I've had some architectural problems. But not of the type where you find it difficult how to structure the project. Yes, this is difficult but there is something more difficult.

In a lot of teams, architectural problems come from people not sticking to the most basic rules. Examples:

  • put common components in the "common" folder
  • Just because you put a file in "common" folder, does not make it reusble. don't fill "common" folder with non-common (e.g. page specific) components
  • Creating a "common" component and making it depend on non-common (page specific) features, and then putting it into the "common" folder
  • forgetting to add .style.ts(or whatever other convention) on styled component files.
  • putting business logic in style files/components and style logic in business logic files/components
  • A function that says it's doing one thing shouldn't do 5 other things
  • Try to make function and variable names meaningful
  • Basically, laziness. I know linters and CI pipeliness and code reviews can be helpful to catch many but there is always limited resources(time, money). And if a lot of the attention of the competent devs is focused on "guarding" for people being lazy, then there isn't much attention left for building.

People sticking to the rules is especially crucial at the beginning of a new project. Yes, sometimes there are rules to be broken. What I'm referring to is when the rules are both obvious and not to be broken, and people still not making the effort to follow the rules.

Failing to follow the rules can be acceptable when the person is more junior, or if they are not junior but are learning the ropes. Or if they are suggesting an obvious improvement that passes a basic cost-benefit analysis. In other cases, not following the rules isn't acceptable.

I am not saying that actual technical architecture is easier to solve than people's issues. What I am saying is that this type of issue is reserved only for the top-percentile professional teams who are disciplined/organized enough to stick to the rules long term. Few are the lucky ones who get to work on such teams, though.


Cost-benefit analysis and explaining technical concepts

Technical issues I've found difficult are doing a cost-benefit analysis or trying to explain something technical. E.g. a change we need to make in our workflow to team members who aren't onboard. Examples:


Type safety

Type safety. It is very important for the health of any long-term team projects, larger than say 5-10k lines of code. For instance, we've had a lot of 'undefined' behavior in the past, and Typescript solves a lot of that. But we have a team of people who aren't accustomed to using TS(properly). So, how many features of TS are we going to use? Is it worth the hassle if we don't use it properly(e.g. any)?

We know that TS can be adopted incrementally. But is our team going to do that properly if we don't enforce strict rules? Developers often take the laziest way out possible. For many teams, non-strict TS rules will mean that they keep writing Javascript in .ts files. Let's say that we conclude that TS is worth it only if it's used strictly. Depending on the team, this can mean a month or maybe two where we push features at a slower rate. E.g. javascript devs getting used to the basics of TS, or simply being frustrated with the new things(not seeing the point, when they were previously faster) and working in a less motivated manner? Can we afford it?

Luckily, as of late 2022, Typescript is a standard choice for all teams and is expected from devs, solving this conundrum automatically.


Explaining unit testing to get a team onboard. No unnecessary details wanted.

Unit tests. Similar in purpose to type-safety - catching bugs in advance. They are very important for the health of any long-term team projects, larger than say 5-10k lines of code. If, say, writing tests increases developing time twofold, they save at least as much time in fixing bugs, and not introducing new bugs to begin with, and usually save way more time in fixing bugs as the project grows. Stability is a key feature, at the cost of initial development speed and flexibility. They can also serve as a form of documentation.

Unlike Typescript, which can catch structural issues e.g. trying to add a number variable with another variable that can be either a number or a string, unit testing can catch logic errors. E.g. a function is expected to take a number, process it, and then return the number + 10. Typescript is not meant to ensure that. This is where unit testing is useful. Regression testing. Did adding/changing this feature break something that used to work? Simply re-run the tests. Having to remember/memorize fewer things is one of the main features of tests. Tests free up mental bandwidth so that you can remember more important things, that can't be easily automated.

Cool, it still looks like a lot of work but the purpose is clear. Then why do so many teams not do testing? IMHO, it's not because it takes more time. I think the real reason is that testing seems like something separate, that is very different from the development of features. It feels like something very foreign. The key of testing is never the testing framework or its implementation details, it's running the functions. Just like you run/call normal functions. Can you write a function and then run it to see if it behaves correctly? Yes. This should be in the head of developers when they think about testing. Not all the details around testing frameworks.

Just like you don't care about all the details of React when you write your components. In my humble experience, most developers are introduced to the "magic" of testing frameworks, with unnecessary differences to remember, too early, which makes them forget the core aspect of the tests. Running the functions and seeing if they return the expected result. The technical challenge is not writing the tests but explaining to your team what is the gist of testing. And to not bog them down with less important details too early. That has been my technical challenge, more than how and what to test, or what testing framework to use.