CTO Insights #1 with Christian Longberg— “Processes stop people from being creative”
|
|
Today there is a large number of software startups, though only few of them become giants. We could name a lot of reasons why most startups that seemed promising experience slowdown in growth or even die. However, I would say that the most painful reason for the failure of many software startups is their inability to develop their software systems. They may start successfully, have ambitious and promising plans for further development, and nevertheless fail. Below, I want to describe this problem in detail and show how it can be solved. All my ideas and conclusions are based on the experience I have gained as CEO of a software development company.
Due to the well-known fact that software startups grow faster than those in other sectors, it may seem strange that many of them face such an issue. Nevertheless, I have met many problematic startups that were unable to keep up the pace of software development. And that was not because of an inefficient development team or inappropriate technologies; though these aspects do also matter, I would say that what matters most is the software itself—that is, its architecture.
To start with, I would like to touch on the evolution of software architecture. This was perfectly illustrated by Benoit Hediard:
First, a monolithic architecture (now often called spaghetti) was used. Therein, an application is built as a single unit; new features are added to the core software, so that all its functionality is tied together. With each feature added to the software, its codebase becomes more complex; therefore, any changes to the software require a great deal of testing. This complexity makes further development slow down.
Later, a multi-layer architecture was preferred for enterprise software systems. Usually, a three-layered architecture is implied: a client-side user interface, a database, and a server-side application. In this approach, each layer is a monolith; thus, adding new functionality requires deployment of a new version of a single layer, but not the entire system. However, as the system functionality expands, layers—especially the server-side application—become more complex. Developers feel frustration with this complexity because even minor changes require the huge codebase block to be rebuilt and redeployed.
This led to a new approach to software development—building layers as suites of services—which is called a service-oriented architecture (SOA). Each service has a defined interface that can be used to perform its tasks; this interface definition hides details of the service’s implementation. Thus, all services are interoperable and can be deployed independently. Moreover, they are independent of the application and programming language.
As SOA is evolving, services are divided into microservices with a range of sizes. Microservices should be as fractional as reasonably possible, considering all risks and spendings.
Though this view may change in the future, today I consider microservice architecture as the most appropriate for enterprise software development.
A lot of startups started developing their software years ago, when the vision of software architecture was quite different, and software scalability and maintenance were not matters of concern for developers. Today, having built a rather complex codebase, such companies have trouble expanding the software functionality. The following challenges appear:
Even if a startup intends to develop software using service architecture, when they conceive the software it is almost never possible to predict how successful the software will be, which functionality will be the most popular, and what extra functionality will be required as the software develops. This is why services are often extensive, and over time the software becomes complex and its further development slows down.
Let’s assume that a startup has a development team that created software according to the startup’s business goals. The software has a layered architecture, though it is rather monolithic. It is integrated with databases and a number of external systems.
As the business grows, new functionality is required. However, adding this functionality to the monolith is very challenging. Moreover, if several new functions are required, the team will not be able to deal with the tasks even being increased, because adding changes to the monolith leads to redeployment of the entire software system again and again.
In this situation, the following actions are possible:
Step by step, more and more pieces of the monolith codebase may be split out into microservices. Thus, the size of the monolith software is reduced. All new functionality is developed as microservices. Later, as the functionality grows, services may become large enough to then be divided into several microservices; each of them may be developed by a separate developer, if required.
In this case, a number of new developers may be hired. The work of microservices they develop does not influence the core block and other microservices. The new developers don’t have access to the core software, which is vital to understand when referencing security issues. The core development team does not need to be increased, though it remains responsible for the core block, which may not be assigned to new developers.
As a result, development of new functionality is parallelized and the pace of development accelerates.
Because the design that occurs first is almost never the best possible, the prevailing system concept may need to change. Therefore, flexibility of organization is important for effective design.
“Any organization that designs a system (defined more broadly here than just information systems) will inevitably produce a design whose structure is a copy of the organization’s communication structure.” This is the famous Conway’s Law, which has been confirmed by the experience of companies such as Netflix, Amazon, and many others. Due to the development team structure, which consists of multiple small teams, which are loosely coupled and often distributed, the outcome of the development is software consisting of a number of services that can change, evolve, and be created and removed separately from one another. The more autonomous each team, and the better the communication established between these teams, the more efficient software development becomes. As a result, the software system becomes flexible, and changes may be delivered to production faster.
As a rule, startups create new software by means of a small development team. If the business is successful, the software grows, the team increases, and at some stage the software architecture does not allow for rapid expansion of functionality. In this case, reengineering the software using microservices must be done in a timely manner. The software architecture should evolve together with the system and team growth.
Using microservices brings the following advantages:
The microservices approach brings even more benefits; it is crucial, nevertheless, to plan its implementation and consider all possible risks and effects.
Today, using microservices is on trend. Many specialists write about the benefits of using microservices; however, few of them write about risks and disadvantages. But these do exist, and this fact should be definitely considered.
First of all, when using microservices instead of a monolith or multi-layered architecture, the software infrastructure increases significantly and new challenges appear, such as:
When software reengineering is needed, two scenarios are possible:
In the past, we have used both scenarios. When reengineering an online marketing platform, we took the following steps:
So, the process was first thoroughly planned, possible risks were assessed, and we then executed actions to mitigate those risks.
Another scenario was used to reengineer an enterprise knowledge-management system. Rapid deployment of a new functionality into production was required; thus, the following actions were done:
To achieve a safer reengineering process and avoid the risk of failure in production, we created a local replication of the system and used it as the groundwork for all changes made.
When providing software reengineering under the second scenario, the main challenge is to replace the particular functionality with links to the new microservice. For example: a new microservice has been developed that sends mass emails to a selected group. In addition to the functionality that existed in the monolith application, some new features have been added. To use this microservice, developers need to find every place in the system where sending emails is executed, remove these blocks of coding from the codebase, and link these places to the microservice. After this work has been conducted, the whole system should be tested to check that removing this part of code hasn’t affected other parts of the software. If one of the blocks has been missed and the new microservice has not been linked there, the software will suffer from inadequate mailing functionality in that particular place.
There are a number of signs that make it obvious that system reengineering is urgently required. In the cases below, reengineering is needed if the problem cannot be solved quickly:
When talking about a legacy software that requires enhancements or expansions to functionality, the following signs show that it cannot be done without reengineering the entire system:
It is impossible to specify exact steps of reengineering—they definitely depend on a particular system. However, there are some mandatory actions that can promote success in reengineering your legacy software. They are as follows:
These are general steps. Obviously they don’t reflect the process in detail; however, it is impossible to write a one-size-fits-all plan because each case differs in terms of existing software, data, and requirements for the new system. Having expertise in reengineering legacy systems becomes a great advantage, especially when analyzing risks and selecting technologies. This is why I always suggest consulting with software vendors that have considerable expertise in reengineering.