Software engineering is hard and easy.

Creating software has become easier over time. Yet software engineering is evolving with its own challenges. The first step to solving a problem is understanding it. Understanding the hard parts is the first step to making it easy.

Ranganathan Balashanmugam
EverestEngineering
8 min readSep 21, 2019

--

There is programming and there is software engineering. Software engineering is not just programming.

First, the easy parts: We have more software engineers than ever before. Access to global teams has expanded. Tools, computing power, infrastructure, technology, and learning materials have never been this readily available and accessible. There are considerable improvements in the software development process. We have access to many programming languages, techniques, designs, algorithms, patterns, and use cases. Technology is advancing very fast, and so is the adoption. Building a software product is getting easier and cheaper, and so is owning software. For one dollar, you can afford an app with unlimited upgrades. It is easier to use software than ever before. A four-year-old can choose and play his or her favorite videos.

Now to the hard parts. We have more software engineers than ever before, yet we struggle to hire and strive to retain. We still struggle working late nights to manage an underestimated project and spend sleepless nights debugging someone else’s code. We take hours or days to fix a broken service. Companies struggle to manage software budgets. We still build software that hangs, loses data, becomes inaccessible at peak times, and kills companies. We find it is hard to scale — software, teams, and customers. We still know a lot of security compromises taken, performance tradeoffs, known bugs, and yet ship it to production. There are millions of lines of code in production, transforming industries, which is a nightmare to maintain. And we know it is going to stay there for a few more decades.

Software engineering is hard and easy.

Parts of software engineering

If we decompose software engineering, there are four main parts — problem, software, people, and process. And there is a bonus; all these parts are bounded by business context.

When we have
- a problem (what to and what not to build)
- solved by people (the hardest part)
- building software (solution)
- by collaborating (process)

- bounded by business context (dynamic rules of the game), we call it software engineering.

When there is only one problem, one person, there is no process required — software engineering becomes easier. Then why should we add people? Mostly because of time. We need to catch up with the market needs on time.

Scaling these parts pose a separate challenge. When the problem scales, we struggle to make choices and prioritize; when people scale, it becomes hard to decide and collaborate; when software scales, it becomes hard to maintain. It is not impossible, but it is hard.

1. Problem:

“Software is eating the world.” — Marc Andreessen. There are so many interesting problems. From product to features, ideas are abundant.

“Success is not delivering a feature; success is learning how to solve a customer’s problem.” — Scott Cook.

Understanding the problem is not straightforward. It involves guesswork. It requires understanding and agreeing on what to do and what not to do. Hard parts include identifying the problem, estimating, articulating and narrowing down the choices, experimenting, accepting the changes while building, being flexible with the plan, and delivering on time.

2. Software:

Software is the solution to the problem. The hardest part of the software is that it does not have a physical shape. It limits the ability to understand as complexity increases.

Two people can see a car and can agree on how it is. But the same two people cannot take a code base and view it the same way. Two people cannot write the same code for the same problem.

There are a few constants and lots of variables. And generally, the software is not built from scratch.

3. People:

src:holocracy.org

“Software engineering is what happens to programming when you add time, and other programmers.” — Russ Cox. People are the hardest part of anything, let alone software. Most of the people in software come from a mathematical background. And they assume that people are rational and work in the way math works. If one person does a piece of work in twelve days, the same task can be done by three people in four days. That is what math teaches us. Well, it does not work that way. First, we find it hard to accept it because it questions our mathematical skills. Then, there is the experience. And different people have different experiences.

People come with different strengths and weaknesses. It is hard to assume that they only play on their strengths. Someone who is a superstar in one team or company may be a mediocre performer in another. And two superstars may not work well together.

4. Process:

1950: Just 67 Seconds after he stops. 2013: 2 seconds. Src: https://www.youtube.com/watch?v=RRy_73ivcms

Process is the agreed way to collaborate. It is supposed to remove ambiguity and increase velocity. Bees collaborate, ants collaborate. They do it in the same way forever. It is hardcoded. If we take two groups of ants (of the same type) and give the same challenge, they may not show considerable difference in finishing the task. If we do that with people, there are chances of a significant difference in the time taken to complete the job. It is where the process comes in. This is where diversity helps. Bees and ants don’t argue about the process. People do. They need to decide, and decisions take time. Process is supposed to make things easier, but many times, it adds overhead.

5. Business:

Business is the dynamic rulebook for these parts. This is the most irrational part. All other parts are bounded within this. A sudden market condition can block you from offering after a painful hiring process. A new compliance law can halt your feature development and make you focus on restructuring the data. A competing product can make your product or even the company obsolete. With a lot of startups in the last decade, there is hyper-growth. And sudden hyper-growth attracts chaos, and many times, an addition to the team is more of a hindrance than growth.

Sometimes, you cannot deliver the business demands with the team you have because either your team is too small or too large.

Hard parts

When people, process, and software come together, with dynamic rules created by business, software engineering becomes hard.

Code does not lie, but it does not tell the truth
We cannot know everything by seeing the code. Every decision is a tradeoff.

We can analyze the code and understand what is there, but we don’t know why something is not there.

And knowledge of some of those tradeoffs is critical — why something which appears as an obvious choice now was not taken then. A lot of the decisions are in mails, Slack, chats, phone calls, Jira cards, heads, and conversations in the cafeteria.

Complexity
The complexity of software accumulates over time. As complexity increases, it is risky and time-consuming to redesign. This results in patching, which makes it still worse.

Complexity also increases with the growth of teams. Decisions take time, and it becomes hard to orchestrate the team’s efforts.

Dependencies
Software is not a single repository anymore. It is a cocktail of dependencies. Tasks are not independent.

“Each element in the system is ignorant of the behavior of the system as a whole […] If each element ‘knew’ what was happening to the system as a whole, all of the complexity would have to be present in that element.” — K.A. Richardson.

Autonomy is constrained. Autonomy is at the service the team builds and restricted by the dependencies. Dependencies, if not handled well, can cascade into failure. Dependencies also limit our in-depth understanding of the products we are building. We may build something that is highly secure, but a dependency can expose the whole system. Similarly, an unreliable service can make our system unpredictable. Backward compatibility restricts the freedom of better choices.

Early decisions
Early decisions are the foundations of the future. The interesting part is that we have the least information when these are made. They are mostly irreversible. When we become part of the project at a later point in time, we inherit the responsibilities of these decisions. In hindsight, many of these appear stupid — hindsight bias. These decisions constrain us.

Wealth of tooling
The wealth of tooling is quite high, and it is growing exponentially. When options are abundant, it becomes hard to choose. Although we know a particular tool is right, we are compelled to stick with the choice based on the team’s skills.

Hiring and retention
There are so many software engineers. We feel we have access to them when in reality, we do not. Every team has its own expectations on capability and skills, which drastically narrows the pool size. We struggle to hire. After so much effort in finding a successful hire, there is attrition. The hiring process, along with efforts exerted for retention takes time.

Competing interests
At the organizational level, there are competing goals. Sales want a particular feature so that they can close a big deal. Marketing requires a specific quality since it is fancy, and no one else has it. The product team demands a characteristic that can satisfy a few existing customers. Developers hope for an attribute as the work builds new services with cool technology stack. UX needs a trait that gives a complete design uplift. Service desk yearns for people to work on stabilizing the existing features to reduce support calls. Generally, in startups, the founders can orchestrate this. As the size of the organization becomes larger, the more influential person drives the agenda. Politics.

Technology drug
We find it very hard to convince people to work on maintenance projects. People expect to work on the latest technology. Technology is addictive. It is like a steroid; engineers keep expecting more of the latest technology. Many times we choose technology as it appears cool on the resume or someone wanted to learn it.

Debugging
When we are part of a team, we are supposed to work on other people’s codes. Working is not just writing code, but also deploying and maintaining it. It is unusual for two people to write the same code for the same problem. When something goes wrong in production, someone’s code will give us sleepless nights.

Tech debts
Tech debts arise either because of our rush to market, or laziness, or evolution of the product, or wrong decisions. We accrue the leftovers over releases. We have limited time to deliver features and do things the right way. Businesses cannot run with a lot of feature debts. Feature debts are the features committed by business to customers. Teams get demoralized when the tech debts are not prioritized.

Conclusion

People have been writing programs for more than 80 years. Programming evolved into software engineering. Software engineering is not just programming. It has made a lot of things both easy and hard. Understanding the hard parts is the first step to make them easy.

--

--