6 Software Product Engineering Practices Every CTO Must Implement

software product engineering practices

Ideal software product engineering practices includes developing and maintaining software systems that behave reliably and efficiently. They are affordable to develop and maintain and satisfy all the requirements that customers have defined for them. It consists of a collection of concepts, tools, principles, and methods that a software engineer uses regularly. It equips the CTO to efficiently manage software projects, providing them with an MVP approach to transform ideas into realities.

A Chief Technology Officer otherwise known as the Chief Technical Officer (CTO) is responsible for investigating the various technology trends and implementing them within the minimum viable product according to the MVP’s vision, roadmap, and strategy.

Here come our 6 essential software product engineering best practices that every CTO must implement. These software engineering practices will help your team deliver a high-quality product. However, these practices are not limited to building an MVP alone. They also cover the whole process until the actual delivery of working software to the end-user.

1. Measure What Matters

Whether you’re an avid subscriber of a “You Are What You Measure philosophy” or not, this is very important. We all tend to shape our decisions and behavior to optimize what we’re measured against, either purposefully or subconsciously.

For example, a team measuring several bugs may intend for that metric to lead to a higher quality minimum viable product (MVP). However, since the metric is focused mainly on bug count and has nothing to do with quality, the team may specifically optimize the bug count. Similar bugs will tend to get grouped. The new bugs may get rolled into specifications for upcoming work. They may even start making claims of “that’s a feature, not a bug” rhetoric. These resulting actions aim to minimize bug counts while none of them seems to optimize quality and the metric’s intent.

This philosophy’s opposite effect is that which is not measured is not optimized and often ignored until it reaches critical levels. Quality assurance, operating costs, time spent context switching, system-wide complexity, sustainable work hours. When important metrics aren’t appropriately measured, their remedies will naturally be superseded by actions that will optimize metrics expressly measured.

You are what you measure. Ask yourself whether your metrics’ optimization will reliably lead to the desired outcome or whether it can be gamified and accidentally lead to an unexpected result? Carefully designed metrics are incredibly beneficial when those metrics’ natural gamification reliably leads to that metric’s intent.

Subscribe to our newsletter

2. Unit Testing is Important

The aim of unit testing is not necessarily to find errors. This is a specification of the expected behaviors of the tested code. The tested code is the implementation of these expected behaviors. Thus, the unit test and the code under test are used to verify each other’s accuracy and protect each other. Later, when someone has changed the tested code and changed the original author’s behavior, the test will fail. If a reasonable amount of unit testing covers your code, you can keep it without disrupting existing functionality. That’s why Michael Feathers defines legacy code in his book as code without unit testing. In the absence of unit testing, your refactoring efforts will be at significant risk every time you try to do so.

Every programmer knows what it is like to launch into a hacker attack, launching lines of code like a machine gun. When you have a big architecture vision in mind, you can never convert it to code fast enough.

Over the past decade, testing has improved more than ever as development teams built robust protocols and created automation capabilities to apply them. Software product engineering teams use new continuous integration mechanisms that take our code and start punching and stitching as soon as we save it. If we create useful unit tests, which is their kind of challenge, the test automation bots will make sure our code moves forward. If we make mistakes, it will catch up with them until they are corrected. And when our code goes through all the unit tests, we can be sure that it won’t fail, not as we expected when writing the tests. There is no guarantee that the code is genuinely bug-free, but rigorous testing ensures that we got the obvious ones.

Behavior-based Development (BDD) lets you learn functionality and requirements directly from the customer, and this alignment results in code that is closer to user needs. Full integration testing ensures that all components work together as expected and increase code coverage.

3. Coherence of The Code

Keep your code consistent throughout. When working with a software product engineering team, having a consistent style guide for your codebase is essential. If you have a codebase where you CAN find out who wrote a particular file, it simply means that there is no consistency between authors. There are many tools for applying a consistent style; here are three we love:

  • JSCS (Javascript Style Checker) is a JavaScript linter which is also in an excellent format.
  • ESLint is an extremely configurable linter and has gained tremendous popularity in the community.
  • Editorconfig is a tool that provides consistency across the many editors and IDEs that its developers use.

This is the lesson of good software product engineering. It doesn’t have to be perfect or deep. It doesn’t have to be great but has been carefully constructed with a diligent and systematic approach to remediation. The process might never fix all the bugs all the time, but that doesn’t mean we can’t be happy to find some of them. If this process is repeated, we can get close enough to it.

Good code maintenance begins with excellent MVP engineering. When teams write well-documented code with modular interfaces, their jobs can continue to function. Software engineering allows a part of us to continue living. It is not the same as unloading our soul in the womb, but it has a similarity.

4. Chaos Engineering

Even when all individual services in a distributed system function correctly, interactions between these services can lead to unpredictable results. Unpredictable results, compounded by rare but disruptive real-world events that impact production environments, make these distributed systems inherently chaotic.

This is the lesson of good software product engineering. It doesn’t have to be perfect or deep. It doesn’t have to be great but has been carefully constructed with a diligent and systematic approach to remediation. The process might never fix all the bugs all the time, but that doesn’t mean we can’t be happy to find some of them. If this process is repeated, we can get close enough to it.

You must identify weaknesses before they manifest into aberrant behavior throughout the system. Systemic weaknesses can take the following forms:

  • Outages when a downstream unit receives too much traffic
  • Incorrect fallback settings when a service is unavailable
  • Cascading failures when a single point of failure malfunction
  • Retry storms from improperly tuned timeouts; etc.

It would be best to address the most significant weaknesses proactively before they affect our customers in production. It would help if you had a way to manage the chaos inherent in these systems. This can be achieved by taking advantage of the increased velocity and flexibility and confidence in your production deployments despite the various complexity they represent.

An empirical systems-based approach addresses chaos in large-scale distributed systems. It also builds confidence in those systems’ ability to withstand realistic conditions. We understand the behavior of a distributed system by observing it during a controlled experiment. This is called Chaos Engineering, and an excellent example is the Chaos Monkey of Netflix.

5. Encapsulate Desired Behavior

This best practice can be broken down into two categories. The first relates to bettering technical implementation of a project by using a consistent first approach. The second aspect, more closely tied to software product engineering involves using a Design System.

A Design System describes the type of tooling which encapsulates and enforces aspects of an MVP. A team that effectively uses a Design System will start with the product’s atomic components: the typography, palette layout, and other fundamental concepts. These atoms compose together to make higher-level components such as menus, headings, and forms. We’re talking about the rigidly constructed legos that snap into place with other features and give the product a sense of holism and unity. We’re also referring to never creating ad hoc styles and components. Everything found on the website is a Design System lego, and none of it is duct-taped together.

Design Systems can be taken even further. This Design QA should include a powerful yet straightforward plugin which allows one to manipulate the Design System component in real-time to understand how it deals with edge cases. You should also be able to answer these questions:

  • Is it responsive?
  • Does it handle long names?
  • Is there a fixed header when scrolling?
  • Does it allow us to test many paths, users are likely to encounter?

Using a Design System to its fullest capacity will help deliver quality and holistic user experience.

6. Building and Iteration - Cut Scope Until It Hurts

You know you’ve found your minimum viable product when you’ve cut a project scope until it’s too painful to cut anymore. That’s when you know that you’re exercising lowercase “a” agility.

Remember, the scope will grow, and unexpected situations will come up. The real world will confront overly optimistic estimates. Either way, reality will take the plan that looked great on paper, flip it to another part, and you’ll find yourself pressed for time.

Specifically, this good practice is broken down as follows:

  • Start with a seemingly too small project (don’t worry; it will grow back). Break it down into small, value-driven versions, with a bias towards riskier items and critical path items first.
  • Put something of value into production quickly and repeatedly.
  • Observe. What have you learned? What technical obstacles did you not foresee? How are users using what has been released so far?
  • Repeat. Continually take what you’ve learned to remodel what you’ve already built or prioritized what you want to build next, build it, and put it into production. Do this repeatedly until the next most valuable thing the team can work on is something else.
  • Consider technical maintenance. Take the time to breathe and fine-tune the clockwork that keeps these functions going.

Conclusion

Most of these best practices are universal. They apply to the development of an MVP in any company’s type and size. Some of these best practices are only applicable to certain types of business environments or products (for example, serviceability/maintainability practices don’t apply to consumable products). In addition, design for manufacturability isn’t as crucial with a one-off product (e.g., a satellite). Hence, an importance weighting is used to tailor the importance of the best practice for each company’s business environment and products.

Unfortunately, many software engineers have had minimal exposure to these practices and their supporting tools. Apart from hindering agility, it frustrates the teams because it is almost impossible to deliver working software in high quality within one Sprint without applying these practices. If you want your agile initiatives to deliver agility, your organization will need to invest heavily in these software product engineering practices by training, tools, infrastructure, coaching and continuous improvement.

CTO’s in many organizations who have implemented these best practices in the past (or currently do so) have experienced considerable improvement in their MVP. However, as some companies’ size and complexity increased, the industry lost many of these practices. In this competitive business world, companies must aggressively improve the way that they develop products.

While software product engineering concepts are simple, the implementation of these practices and process is quite challenging. True success can be achieved with a well-planned and managed effort. A CTO must understand the concepts of software product engineering and manage change within the organization. As the CTO, you cannot delegate the responsibility of making these significant changes in culture, business process, technology and organization. Proactive management, leadership, and attention to detail will prove beneficial in the long run.

Looking to build a digital product?
Lets build it together.

Contact us now

  • This field is for validation purposes and should be left unchanged.