18 Running with Microservices
In this chapter, we discuss how Smith’s development team made use of Microservices in their development. Developing software with microservices is an evolution of designing software with components, which facilitates a modular approach to building the software system.
A component can be described as an element containing code and data. Only the code “inside” the component (object) can modify the data inside the object and it does that when another component sends a message with a request to do that. This idea is known as “data hiding” (data is hidden to other components) and is an accepted best practice in developing maintainable software.
Components were created to help solve the problems many developers face with large complex software systems that require long change cycles. Like components microservices are interconnected via interfaces over which messages are sent to allow communication. Components as well as microservices manage their own databases only accessible from other components via the interfaces. Such a “decentralized” approach allows each component and microservice to be developed and managed independently. Thus, like components, each microservice can evolve separately from other microservices, thus making it easy to introduce new functionality.
In a software system built from microservice, each microservice runs a unique executing process. A process is an execution of a computer program. There may be several such executions or instances of the same program running in parallel. What microservices bring to software beyond what components already did is the ability to also deploy the microservices independently without stopping the execution of the entire software system. This is very attractive to businesses because, they can now update their software more quickly and hence adapt to market changes quickly.
18.1 Microservices Explained
To understand the value of Microservices , one needs to understand how most software systems were developed traditionally before components were the standard way of developing software. Traditional approaches resulted in monolithic software, everything was one big chunk of code and data with no modularity of real value. In Figure 129 the icons represent users, user interfaces, processing code, and data stores (places where information is stored and retrieved).
Figure 129 Microservices Big Picture
Before we continue our discussion, we would like to introduce some terms and concepts used in Figure 129, that a new student to software engineering may not be familiar with. Basically, these are typical parts of a Software System, namely:
- User Interface – A user interface is the part of a software system that users interact with. It is the screens, and buttons, and so on.
- Application Logic – The code behind the user interface that performs computation, move data around, etc.
- Data Store – The data retrievable by the application logic lives in a data store.
- Containers – Containers are components of a software system that can be managed separately (i.e. started, stopped, upgraded, and so on).
The left-hand-side side of Figure 129 depicts a monolithic software system. Even though it serves many users with different user interfaces, there is no clear separation of application logic or the data store. These appear as a single complex blob, whereby changes in one part affects other parts in an uncontrolled manner. Such systems are not easy to maintain and extend.
The right-hand-side of Figure 129 shows a microservice-based software system. Each microservice runs as a separate process, possibly in its own container or virtual machine. It has its own programming language, user interface, application logic and data store. This allows developers to upgrade a particular microservice from say Java 8 to Java 9 to take advantage of new language features in Java 9, or to upgrade the data store without impacting other microservices. If however, code for different logical software element were to run in the same process or virtual machine, an upgrade of one element may inadvertently impact another element. Thus, enhancing the functionality of an existing microservice is easier than that of a monolithic software system. As an analogy, you can treat each column on the left side of Figure 129 as a village of people eating out of a pot, i.e. the datastore. With the monolithic approach, every time the pot is being cleaned, everyone is affected. With the Microservice approach, each family has their own pot. While one family is preparing their pot, other families are not affected. Each family can prepare and use their pots independent of other families. This is similar to microservices.
However, designing microservices are not without its challenges. If microservices are not designed properly, there might be too much coupling between microservices leading to performance degradation, for example too much inter-microservice communication. You can resolve this in two ways:
- There must be appropriate identification of microservices. In addition to considering modularity, one needs to consider performance, specifically the interactions between microservices. There are a number of trade-offs, which requires design practices and patterns, which are mostly out of scope of this book.
- The state-of-the-art today is that we are in the era whereby computing resources is inexpensive through the use of cloud computing from cloud providers, etc. This is because with cloud computing when you need more computational computer time you don’t need to upgrade your own hardware, rather you just request it from the cloud and the additional resources are provided via hardware that is owned and operated by the cloud service providers. For example, when Smith’s recommendation engine was first introduced to a small group of users, a single instance of the recommendation engine was sufficient. When it was introduced to more users more instances were needed each requiring computing resources. With cloud services, adapting to changing requirements can be done more easily and usually with less infrastructure costs because you can just purchase the amount of resources you need from the cloud service provider. You don’t need to worry about the impact to modifying your own hardware set up inside your organization. As an analogy, not so long ago, we needed to buy external hard-drives to backup our data, but today we can put our data in the cloud for a yearly subscription fee. The cloud provider through economies of scale can optimize the allocation of cloud storage to subscribers.
The second point above is the view taken today. Adaptability is key with the advent of inexpensive computing power. Upgrading finer grained microservices is less disruptive to end users as compared to upgrading monolithic systems, because you can upgrade module by module. You probably have encountered service providers saying, “we will not be providing any services during the maintenance period”. This will be a thing of the past with microservices.
18.2 Making the Microservice Practice Explicit Using Essence
Microservices has become a very popular practice for design of software. In the 1990s it became standard to develop software using components with well-defined interfaces. Though this approach had been used for more than 20 years (information hiding, object-oriented programming) it became popular through new platforms such as .com and new languages such as Java. What Microservices has added to this evolution is support for components all the way down from design, code to deployment. Though microservices is popular it is not a new idea, similar support has been provided with components since their introduction in the 1970’s.
Moving from a monolithic approach to a Microservice based approach is not easy. It requires a new way of thinking. In particular, there are two important challenges, namely:
- An effective way to decompose a monolithic software system into cooperating microservices.
- An effective way to make changes to microservices and upgrade them once they are deployed.
A simple practice that takes advantage of microservices and address these challenges is depicted in Figure 130. This is a Lite practice because we have selected what we deem as a minimal core of the practice; minimal for demonstration but in the real world would require much more technical detail. For instance, we do not go into the depths of object oriented analysis and design, or the technology needed to implement microservices, which are each a set of books by themselves. The Microservice Lite practice highlights what we deem as important differences from traditional component thinking.
Figure 130 Microservice Lite Practice Expressed in the Essence Language
In this chapter, we will use the example of the recommendation engine that Smith and his team were building to demonstrate the use of the Microservice Lite practice. In particular, the recommendation engine is implemented as a set of microservices outside of the existing legacy hotel reservation system. This allowed Smith to take advantage of new data processing technologies to perform the recommendation computation. This practice extends the kernel with guidance regarding:
- Microservice: This is an alpha, which the team will progress from its identification to its deployment (i.e. made available for use by users). As you recall, an alpha is an element with states that can be used to measure progress and health. Since a software system is comprised of microservice subalphas, the progress and health of the software system is dependent on each and every microservice. The recommendation engine is implemented as a set of microservices – one for general recommendations (based on user preferences and history), and one for location based recommendations (based on where the traveler’s current location is).
- Design Model: This is a work product that describes the software system at a higher abstraction level than code – usually in some graphical notation such as UML. A good design model must simplify the understanding of the code, which normally means that elements in the design model are traceable to elements in the code. Here, we are looking at the software system as a whole to identify appropriate ways of decomposing it into microservices. Finding an appropriate decomposition is a delicate activity called Identify Microservices, which relies on both experience by the developers and well-known criteria such as keeping low coupling between different microservices and high cohesion within a microservice. The work on the design model also focuses on creating well-defined interfaces between microservices. Through the Design Model, we can also understand how individual microservices collaborate with one another. For example, the Design Model describes how the recommendation microservices interact with the legacy hotel reservation system.
- Microservice Design: This is a work product describing the design of a microservice, from its interfaces to its behavior and internal design. In our Microservice Lite version we do not go into further details beyond saying that a good microservice design exhibits the characteristics of clear interfaces, internal cohesion and low coupling to other microservices.
- Microservice Test Case: This is a work product capturing the test cases for a microservice.
An example of how the TravelEssence team applied the Microservice practice is provided later in this chapter.
There are a number of activities providing explicit guidance as to how to progress the above alphas and work products.
- Identify Microservices: This first activity identifies and clarifies the purpose and scope of a microservice. As already said, microservices are identified by focusing on high cohesion within each microservice and low coupling between microservices. As you recall in our story, Smith and his team had been working on a recommendation engine. From earlier requirements background studies, Angela had found that recommendations fall into two categories, namely based on customer traits, and based on geographical localities. These two categories of recommendations are subject to independent requirement changes and enhancements. Thus, Smith identified them as two candidates for microservices.
- Make Evolvable: This second activity looks at all the ways the development can support the evolution of a microservice. This includes making the design extensible, similar to adding/upgrading an app on your phone without upgrading or buying a new phone. It also includes automation to test and deploy the microservice quickly without impacting other microservices. This is usually done by developing scripts that allow each microservice to be produced and deployed (made ready for use) independent of other microservices. By keeping each microservice small and reducing its impact on others, rapid deployment is supported.
- Evolve Microservice: This is an ongoing activity to add new functionality to the microservice. Evolving a microservice includes modifying and testing the code to ensure each part meets its intent. Because microservices can be changed, tested and deployed independently, evolving a microservice can be accomplished rapidly. This includes making the microservice available to users.
Smith’s team found the idea of microservices very attractive. Tom, the ever so eager-to-try-new technology geek in the team, was elated when the suggestion was proposed. Tom was tasked to investigate the technologies to support microservice development. But Grace was not as convinced as Tom in the value microservices would provide to the team. She said, “I don’t see how microservices will help us anymore than using use cases and components.” Tom replied, “Grace, let me show you by using the Essence kernel.” Tom then pulled out the Requirements and Software System alpha cards (see Figure 131) and said, “use cases helps us progress the Requirements alpha, and components helps us with the Software System alpha. Microservices also helps us to progress the Software System alpha, but it helps more on the deployment side.”
Figure 131 Requirements and Software System alpha cards
18.3 Microservices Lite
Micrsoservices Lite is a practice that begins first by having the team identify the requirements, which can be done by applying use cases or user stories or using any other requirement practice. Next finding a proper set of microservices to implement the requirements; this basically is the same activity as finding appropriate components for a software system. Then is to make each microservice evolvable by developing the needed support environment, such as deployment scripts that support the rapid deployment of each microservice independently of other microservices. Lastly, each microservice is evolved independently, which involves rapid coding and testing of each microservice as well as rapid deployment of the microservice into the production environment. The production environment is the “live” environment in which real users use the software system.
The elements of the Microservice Lite practice are shown summarized in Table 13.
Table 13 Elements of Micro-Services Lite
A separately replaceable piece of software that exhibits the properties of high internal cohesion, low coupling to external microservices, and that has well-defined interfaces.
A description of the responsibilities of the microservice and how it fulfils these responsibilities.
A description of the overall software system and how the microservices relate to and interact with one another
Build and Deploy Script
An automated script that supports rapid production and deployment of each microservice independent of other microservices.
Microservice Test Case
The set of tests to verify the behavior of the microservice.
Find an appropriate set of microservices needed in the software system to implement the requirements and outline their responsibilities.
Make Microservice Evolvable
Microservices are made evolvable by developing deployment scripts that allow each microservice to be produced and deployed (made ready for use) independently of other microservices.
Incrementally evolve the microservice functionality. This activity includes rapid coding and testing of each microservice as well as rapid deployment of the microservice into the production environment.
18.4 Microservices Lite alphas
The primary alpha in the Microservice Lite practice is of course the Microservice alpha. All work products and activities in this practice revolve around this alpha. The Microservice alpha relates to the Software System alpha as a sub-alpha (see Figure 132). As mentioned, the Microservice alpha represents a resilient and elastic piece of the software (i.e. part of the Software System) that delivers a well-defined capability. By resilient, we mean that it will be robust to changes done in other microservices. By elastic, we mean that the microservice can adapt to changes in workload (e.g. from a thousand users to one million users).
Figure 132 Microservice alpha
Building and delivering microservices resolve around the following states:
- Identified – Firstly, the scope of the microservice must be clear. Team members must understand what functionality the microservice is responsible for.
- Rapidly Deployable – The major point about using microservices is the ability to quickly change it and re-deploy it to the production environment. In this way, team members can quickly evolve the functionality of a microservice in the production environment. This rapid deployment capability is what gives microservices its advantage over traditional approaches. This is very much unlike monolithic systems, which due to their complexity and tight coupling are difficult to test and upgrade. Achieving rapidly deployable microservices requires an architecture with low coupling between microservices and high cohesion within a microservice. It also requires setting up build and deployment scripts to automate the test and deployment steps.
- Minimal – Once the microservice can be updated and deployed rapidly, the team can then work iteratively to realize the required functionality of the microservice. This starts with fulfilling a minimal set of requirements so that it can be integrated and tested in collaboration with other microservices.
- Complete – The team will then evolve the microservice to fulfill all the required interfaces of the microservice. At the same time, the team would likely refine the structure of the microservice so that it is extensible, (i.e. new functionality to the software system can be added without big changes to the microservice).
The checklists for the Microservice alpha states are depicted in Figure 133.
Figure 133 Microservice alpha state cards
18.5 Microservices Lite work products
The Microservice Lite practice introduces several work products, namely: the Design Model, Microservice Design, the Build and Deployment Script, and the Microservice Test Case.
The Design Model work product describes how a microservice fit within the overall Software System, and the Microservice Design describes the scope, interfaces and the design of a particular microservice. The Build and Deployment Script is the work product that makes the microservice rapidly deployable. The Microservice Test Case is a work product to evaluate the quality of the microservice, that the implementation of the Microservice indeed meets the requirements.
Working with microservices is not easy. It is not just about understanding engineering concepts, but also the implementation technology. This book cannot be a bible when it comes to microservices, and we do not attempt to do so. What we are doing is to provide a glimpse of how to work with microservices in a healthy manner, as accorded by the Microservice Lite practice.
There are several pre-requisites when working with microservices, such as being able to clearly articulate its design, implementation, and deployment. Having a good understanding of a visual notation helps. In the next section, we give an overview of one standard such notation, (i.e. the Unified Modeling Language (UML)). Thereafter, we will describe how to use each Microservice Lite work product in detail.
18.5.1 A Brief UML Primer
Before we go into greater detail into the Microservice Lite work products, in this section, we will provide a very brief and concise introduction to the Unified Modelling Language (UML). The UML is a visual language to describe software intensive systems. Whereas Essence provides a language to describe software development practices and methods through constructs such as alphas, work products, etc., UML provides a language to describe software intensive systems. By software intensive systems, we mean systems that may involve hardware, but are driven largely by the software. The main focus of UML is describing the software part. The reason why we need to provide a brief introduction to UML, is simply because we will use UML to describe how Smith’s team makes use of Microservices.
Table 14 UML for Microservices Design
A microservice is a special kind of subsystem that has its own data store. A legacy system is an existing system that is normally built using some traditional approach that results in it being monolithic. Both microservices and legacy systems are denoted by the same subsystem notation.
Note that UML is a lot more than what we discuss above. It has guidance for describe the structure and behavior of software elements. We only focus on a small portion of the structure description using interfaces, and subsystems in Table 14. We do however recommend that you learn more about UML.
18.5.2 Design Model
The Design Model (see Figure 134) is a description of the Software System. It depicts the elements in the Software System and how they interact with one another. We will use Smith’s recommendation engine as an example. We will just provide a brief overview of the design model, bearing in mind comprehensive design is outside the scope of this book.
Figure 134 Design Model work product
The Design Model work product has the following levels of detail:
- Structure and Approach Described – At this level of detail, the Design Model describes clearly the elements the Software System. It will describe how the different parts are organized and the purpose of each part.
- Collaborations and Interfaces Defined – At this level of detail, the roles and responsibilities of each part are more detailed. The example in this section goes to this level of detail.
- Design Patterns identified – At this level of detail, common design patterns that can be shared across elements are identified and described. A design pattern is a common design solution to a common design problem.
Re-engineering the legacy hotel system from a monolith to one based on microservices would be too big an effort. However, the new recommendation functionality was quite separate and distinct. The decision was to leave the legacy hotel system alone with minimal changes, and to develop the required new recommendation functionality using a separate Microservices approach as shown in Figure 135.
Figure 135 Design model for recommendation functionality
The left-hand-side of Figure 135 shows the legacy hotel system. It is modified slightly to provide an interface, referred to an eTravelerEvent used to push out traveler events, While the software in the Legacy Hotel System executes and gets to a point when something of interest happens, such as when a traveler books a hotel, that fact is communicated to the iTravelEventHandler by an event. Such information is used by the Recommendation subsystem to analyze the popularity of hotels, travelers’ preference, etc.
The right-hand-side of Figure 135 shows the Recommendation subsystem designed using two microservices, the Traveler Recommendation microservice dealing with specific travelers or groups of travelers, and the Geographical Recommendation microservice dealing with specific recommendations related to the traveler’s current or near term planned geographical locations.
- As the name implies, each collects traveler events through the iTravelEventHandler interface to analyze them either geographically or according to specific travelers or traveler groups.
- These microservices each provide an iRecommendation interface to provide recommendations to travelers. The Traveler Recommendation microservice provides some basic recommendations, and will delegate the determination of recommendation based on geographical details to the Geographical Recommendation microservice.
Once the system is deployed there would be multiple microservice processes running (one for each traveler group and for each geographical area), each with its own datastore for Traveler Recommendations. This is in line with TravelEssence goal to gradually rollout the recommendation functionality to increasing number of travelers, and geographical regions.
18.5.3 Microservice Design
The Microservice Design (see Figure 136) is a work product describing the design of a microservice, from its interfaces to its behavior and internal design. It provides more detail than the Design Model for that specific microservice.
Figure 136 Microservice Design work product
The level of details for this work product are:
- Required Behavior Defined – At this level of detail, the scope of a microservice is described in words.
- Interfaces Specified – At this level of detail, the scope of the microservice is described using interfaces.
- Internal Structure Defined – Once the external behavior is agreed, this level of detail describes the elements within the microservice. Developers can then start to write code with a good understanding of this structure.
- Internal Elements Designed – For complex microservices and elements, therein, more details are needed.
We will continue to use the recommendation engine as an example, and in particular the Geographic Recommendation microservice.
In addition to the interfaces highlighted in the design model, a microservice also needs interfaces to manage its execution, such as setting configuration parameters, and controlling its execution (starting, pausing, resuming, stopping, reset.) that appear in the figure below. Figure 137 shows all the interfaces to the Geographic Recommendation microservice including manage its execution (iService), manage its recommendations (iRecommendations), and handle traveler events (iTravelerEventHandler).
Figure 137 Microservice design of geographical recommendation
18.5.4 Build and Deployment Script
The Build and Deployment Script (see Figure 138) is an automated script that supports rapid production and deployment of each microservice independent of other microservices. The primary purpose of this work product is to make the build and deployment process as repeatable as possible, which is critical when working with microservices. Without any rapid deployment and upgrade capability, there is no real advantage of using microservices when compared to using more traditional component approaches.
Figure 138 Microservice Build and Deployment Script work product
Working with Build and Deployment Scripts involve the following levels of detail:
- Outlined – At this level of detail there is an agreement as to what rapidly evolvable entails and steps to achieve it are agreed and described. There is not an actual runnable script available yet.
- Automated – This is where the real work has been done. The team has written the actual build and deployment script and it has made sure that it works within the development and deployment environment.
- Continuous –This is a higher level of detail that ensures that the script runs in continuous support of microservice upgrades without disruption to other microservices.
18.5.5 Microservice Test Case
The testing of a microservice follows a similar approach to testing user stories, and use-case slices. You start by first identifying scenarios, just like we have showed you earlier regarding testing use-cases.
The execution of a microservice will likely depend on other microservices. So, you might have to mock out the surrounding dependencies, (i.e. substituting real parts of the software system which developers have little control on with parts that developers have control on during testing). For example, the recommendation engine has a dependency on the legacy hotel system. So, instead of testing the recommendation engine microservices with the real legacy hotel system, Smith’s team choose to create a mock (substitute) hotel system whose behavior they can change quickly. This might sound like a big task, but in reality, only the interfaces needed by the recommendation engine need to be mocked.
Figure 139 Microservice Test Case work product
Testing microservices is not much different from testing use cases in terms of how you think about test cases for use cases and user stories. Of course, the tools you use to test microservices (which normally does not have user interfaces) and use cases (which quite possibly have user interfaces) will be different. The levels of detail of Microservice Test Cases (see Figure 139) are:
- Test Scenarios Chosen – At this level of detail, different scenarios in which the microservice is used are enumerated systematically and prioritized.
- Test Dependencies Managed – At this level of detail, the scope for each test case is agreed, including dependencies, which will be mocked or stubbed. Mocked means to create extra test code that simulates the other side of the interface. Stubbed means rather than simulate the interface to just ensure the test code will execute without the program crashing.
- Test Automated – At this level of detail, the test cases are scripted and automated. They usually run as part of the build and deployment process.
18.6 Microservices Lite Activities
Applying the Microservice Lite practice involves the activities:
- Identify Microservices
- Make Evolvable
- Evolve Microservice
Each of these activities is discussed below.
18.6.1 Identify Microservices
Microservice development begins with the identification of microservices within a software system. Identifying microservices requires both the Development and Analysis competencies. These competencies are needed to identify microservices that exhibit high cohesion, low coupling and well-defined interfaces. Identifying microservices with these characteristics helps teams achieve the Software System alpha, Architecture Selected state (see Figure 140).
Figure 140 Identify Microservices activity
Depending on the specific endeavor, teams may make different decisions on the level of detail needed for work products during the identification of microservices. For example, some teams may decide that their design model work product only needs to describe the structure and approach (lowest level of detail, see Figure 134). Other teams may decide that the collaborations and interfaces among microservices need to be documented explicitly (second level of detail in design model). Still other teams may decide that the design patterns employed need to be explicitly captured in the model (highest level of detail in design model).
Similarly, different teams may reach different conclusions on the level of detail needed in their microservice design work product with respect to the level of detail needed for defining required behavior, specifying interfaces, defining the internal structure, and internal element design (see Figure 136).
The design model work product (see Figure 134) gave Smith’s team an overall perspective of how to design and implement the recommendation functionality. Working with microservices involves making microservices evolvable and then evolving each microservice and adding levels of detail to a microservice’s design, build and deployment scripts and microservice test cases. Progressing the microservice alpha through its states will be discussed later in this chapter.
18.6.2 Make Evolvable
The key and compelling characteristic about microservice development is the ability to make rapid changes to a software system in the production environment. The key goal is to be able to replace a single microservice quickly without affecting other parts of the software system (i.e. other microservices). This does not come free, and it is what the Make Microservice Evolvable activity is about. It requires at least two areas of investment, namely:
- Ensuring the modularity and extensibility of each microservice so that requirements changes are localized to individual microservices, and that changes to a microservice does not severely impact other microservices. This is about great design, which we unfortunately cannot cover in this book. But suffice to say, a team will capture its design approach in the Design Model, Microservice Design and Microservice Test Case work products (see Section 18.5.2, Section 18.5.3 and Section 18.5.5 respectively).
- Improving the development and production environment so that changes to microservices are repeatable, reliable and fast. This requires the streamlining of the deployment pipeline with plenty of automation. The idea is to reduce as much mundane and manual work as possible. This is embodied in the Build and Deployment Script work product (see Section 18.5.4)
The first point above is covered largely by the activity Identify Microservice (see Section 18.6.1) , whereas the activity Make Evolvable focus more on the second point, It requires the scope and boundaries of microservices to be stable.
Figure 141 Make Microservice Evolvable
In our story, Smith had earlier identified several microservices, and they are in the Identified state. The next state is to make each microservice Rapidly Deployable, which means that it should be possible to deploy the microservice to a target environment quickly, be it the test environment or the deployment environment. This deployment has to be automated, which necessitates the use of build and deployment scripts. By “rapid”, we mean that changes that used to take months, are now reduced to hours, and even to minutes.
18.6.3 Evolve Microservices
Once a microservice has been made rapidly deployable and its interfaces identified, it becomes straightforward to evolve each microservice, and thereby introduce new functionality to the entire software system.
Figure 142 Evolve Microservice
Smith’s team can now safely develop and test the code required for each microservice. Smith’s team achieved this by first agreeing on the test cases before adding/changing microservice code required to successfully pass the test cases. In effect, Smith is applying another practice known as Test Driven Development (TDD), (i.e. first agree on the test cases and use the test cases to drive development). The test cases will initially fail because there is no implementation. Smith’s team may identify more test cases along the way. But as Smith’s team complete the implementation, more test cases will pass. Thus, the number of test cases that pass will act as a progress indicator.
18.7 Visualizing the Impact of Microservice Practice to the Team
Recall that both User Story Lite and Use Case Lite did not provide any guidance on how to implement the software system. These two practices focused on requirements and tests of the software system. The Microservice Lite practice addresses implementation guidance as shown in Figure 143. The Microservice Lite activities provide guidance to Smith’s team how to design and implement the solution.
Figure 143 Microservice Lite coverage of the kernel solution activity spaces
Note that the Microservice Lite does not deal with the requirements and test of the solution itself. The Microsevice Lite practice provides guidance only for the testing of individual microservices, not the entire software system’s functionality. That is covered by the Use Case Lite practice discussed in the previous chapter.
At the time of writing, microservices are gaining widespread attention. Although the idea of having components as a separate and independent deployable unit of modularity has been in existence for a long while, the implementation of this idea more often than not had not been ideal. Monolithic designs often inevitably resulted in components either tightly coupled with language, infrastructure or data store. The idea of microservices each being independently deployable seems to be an attractive answer.
Of course, having many microservices each running separately raises other problems such as:
- how to manage and coordinate their execution
- how to propagate the change of data from one microservice to other microservices
- how to manage the security of each microservice
- and so on.
Fortunately, there are a number of approaches to deal with the above problems, and cloud providers such as Amazon Web Services provide standard mechanisms to solve them. This allows developers to focus on the application rather than the low-level infrastructure plumbing which now happens behind the scenes. As a result, developers can focus on realizing user requirements, push out functionality to the users quickly, get user feedback, and innovate. Such rapid cycles are ultimately the value of microservices.
18.8 Progress and Health of Microservice Development
What we have demonstrated in the above sections is a single pass on how a microservice is developed from its identification to its evolution. The progress of the development of a microservice is captured through its alpha state cards as shown in Figure 133. Smith’s team found that not all work was directly related to implementing requirements as we have discussed in chapter 17. There was additional work including identifying microservices, building deployment scripts, coding, and testing. All of this work required time. What the team realized was that the Microservice alpha state provided a way to help them think about and plan all the tasks they would have to do to get the Software System to a state where the customer would be happy with the result.
Thus, by the time they explicitly applied the Scrum Lite, Use-Case Lite, and the Microservice Lite practices, they had quite a number of alphas additional to the kernel alphas. To recap, they had:
- Product Backlog-Item
- Use-Case Slice
- Use Cases
Someone outside Smith’s team was looking at how they were running development with Essence and the practice. He asked, “for a small endeavor like ours, isn’t this too many things to check? It seems that you have many cards!”
The usually quiet Grace was quick to reply, “When we were doing the actual work, each of us would only focus on achieving a few alpha states, for example Use-Case Slice Verified, and Microservice Rapidly Deployable. The states are like micro-checklists for the small chunks of work we do that could be completed each day. They help us split the work into small chunks, and gave us a sense of progress during the day.”
That is indeed true; each practice deals with a specific set of challenges, and would normally be useful for persons playing specific roles. Smith as the leader of the team focuses much on the Essence kernel alphas and the Sprint and Use Case alphas. The developers were mostly focusing on the Use-Case Slice and Microservice alphas. Joel, the techie guy, was especially delighted with the Microservice alpha states. He always said, “The essence of Microservices is getting to Rapidly Deployable first, before adding functionality! This is a 180 degree change from old ways that implement first before even considering how to deploy to the production environment.”
 “Coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; i.e. the strength of the relationships between modules. Coupling is usually contrasted with cohesion.” From https://en.wikipedia.org/wiki/Coupling_(computer_programming)