What Software Engineering Is All About

I felt the urge to write a summary like this on my flight. Nothing new is said here.

Di Fan
5 min readDec 28, 2018

Software

Software is meant to be soft. Software do things; they provide the features that make up the business, but they also adapt to changes so any feature changes can be supported. Being innovative and responsive is what keeps a business competitive.

Good software is adaptive to changes. Codes can be added or deleted at linearal cost. Bad software, on the other hand, is hard to change, they take exponential efforts to change, if they can be changed at all.

Cost

The difficulty of changing something can be measured by cost, e.g. how much developer efforts (e.g. in hours, days, weeks, etc) is required to make the change happening.

This entails the software engineering side of the job: how the software can be built in a way that enables developer productivity, both long-term and short-term. This is the hardest part.

The computer science side of the job ensures the solution built is efficient, consuming no more machine resources than necessary.

Either way, the bare minimum requirement is that the software should work. Without features business does not make money.

Codes

Features are provided by codes. Codes are blocks that do things. Different programming paradigms organize codes differently. There is no real restriction on how to organize codes, and crazy messy codes could still work.

Codes are run as program by computers, but only incidentally. They are more often read by people: the code reviewer, another developer, the original developer six months from now. As a result, codes should be written to be read by human, not written to be run by computers.

In other word, codes should be easy-to-read, which usually mean it should be clean, concise, and self-explanatory. Comment as much as necessary but no more. Best documentation is no documentation, if that still achieves the goal; the best code is no code.

Code, very carefully. Keep it simple and show your intentions.

Testing

Tests demand corresponding codes of a certain behavior, and often a certain size. Writing codes that barely pass tests and no more is a way to organize codes, which usually makes overall development faster.

At development time, if there is no test, there is no organization. If there is no organization, there is no direction, and it will take long to get to where the end goal is from nothing. Or at least it can get confusing if all the plans are only in your head.

Once development is done, tests provide a minimum guard against regression. They provide some comfort that the behavior of the codes is predictable, and more importantly, that the behavior of changes to the codes is predictable. Tests should make software adaptive to changes.

Tests are also codes, and they should (and often do) make its companion codes easier to understand by providing examples.

Write tests. Always.

Refactoring

No one writes prefect codes. No one understands problem fully at the begining. Everyone gets sloppy at times and leave ‘holes’ in the codes.

Changes, a.k.a. refactoring, are always need to be made at a later time to get things back in line.

However, it is a dangerous thought to relax the standard of quality just because things will always be imperfect. The ‘get things done now and fix later’ mentality will never work, as there are always more features to develop.

If this happens over time, the codes will reach the pivot point where they become impossible to be refactored. There is too much risk involved in making changes. The software becomes rigid and horrifying.

Instead, refactoring should be a natural process that is incorporated into the development cycle, e.g. refactor-as-you-go.

Refactor, as soon as it feels necessary, i.e. when the codes start to smell, but not earlier , or later.

Writing Design Docs

No one understands the problem fully at first, but we should strive to understand as as much as possible before committing the software to take a certain shape.

Design Doc is a tool to help developers ask questions necessary to carry out a given project, and find good answers to the questions.

The PM should address mostly what features are being built, though Engineers can go more into details on that.

Engineers’ Design Doc mostly focus on how to implement those features well, by describing the design / architecture of the system in question.

We want to ask all the questions that will impact the design decision of the project, so these question can be answered thoughtfully, i.e. thoughtful design decisions can be made.

These questions can go from very high level to possibly very detailed. They should go as detailed as necessary to support the high level design, but no more. Sound high level design can quickly fall apart without solid executions to support it.

Ideally all the questions relevant should be asked and answered before implementation. Again, this is a worthwhile effort, but it’s not always possible. Sometimes we only find out about a question once we starting work info. The design is an ongoing process.

Write Design Doc, if it is necessary, i.e. if there are questions regarding the design that need to be answered.

Learning

Good deaign is hard to come by. It requires following the principles and processes, as well as experiences. Analyzing a bad design can be a good learning experience, because we have to know what can go wrong before we could know what to think about early in the design process. In that sense, working on legacy systems or carrying a pager, though often painful, can provide valuable insights if the experience is structured well to promote learning.

Seek good learning experience and be reflective. Merely getting the work done doesn’t teach you much.

Levels

Junior software engineer should learn as much as possible about how to make and execute good design.

Senior software enigneer is reliable enough to create software that is easy to change.

Even more senior engineer, often but not necessarily a team lead, is experienced enough to be responsible for the architecture, a.k.a. design, of multiple components across the team.

Good managers know how to develop the requisite skills for their reports, by providing the right projects and guide the learning experiences.

Good managers are rare. Sometimes it’s a two-way street. You have to ask for what you want and grow together.

Conclusion

There is no perfect or bug-free code. That is not the goal. The goal is to produce results, to feel good about the progress made, and to be happy. This goal cannot be achieved if engineers spend all days debugging the ‘holes’ in the code or painfully figuring out where is the right place to insert this one line change.

Humans are incredible creatures that can learn from not only their own, but others’, experiences. The way to good software engineering has more to do with avoiding the known pitfalls than being creative and going freestyle.

In the end, coding and software engineering are about applying discipline and limitation, so as to keep things (changes, cost, frastruation) under control.

The path to good software engineering is there. Regardless of the changes in languages, program paradigms, computing powers, technologies, or platform / devices, the principles of software architecture do not change. And this is the path no aspiring software engineer should ignore.

--

--

Di Fan

Traveler, Reader, Dreamer. Writing highly deletable codes.