10 commandments On Microservice Decomposition.


 While we are talking about Microservices, we talked a lot about Domain-Driven design, Event-Driven Architecture, Core domain, Subdomain, Bounded context, Anti-corruption Layer, etc,

Whether you are working in a Brownfield project or a Green Field project, If your organization wants to adopt Microservices, (assuming your organization has a compelling reason for adopting Microservices as it is not a free lunch.) then you need to understand the above terms in detail to properly decomposing your Business domain logic(Business Space) and mapped it with Microservices architecture(Code Space) , so you can gain the benefits of Microservice traits.


In this article, I will try to cover the purposes of the above-mentioned terms while decomposing Microservices and try to fit them under one umbrella concept.


To understand each term from the root, it must be one or more than one article. Having said that, I will concise them in this article and give you the pointers while you are applying the Microservice decomposition strategy in your Organization.


Let’s begin with the 10 Commandments of Microservice Decomposition.


1. View Your Business Domain In terms of Bounded Context and Ubiquitous Language::


Before taking any step on decomposition, the first thing first is to reduce the gap between Product owners and developers, Product owners do not understand Technical term, and the Technical team not understand the importance of a term in terms of Business and how business interpret it, It is like one Portugees talking with one American with their native language no one understood the conversation, so to bridge the gap we need to take below steps,


  1.  gather in front of a Drawing board start a discussion with Product owners what is the objective of the business, what are the actors in a particular feature, what are the terms they used while defining the feature, on every step ask more questions until you figure out what are the conflicting terms, like in Order Context Customer is different than Infrastructure Support context Customer. 

  2. Once you understand the conflicting terms and clubbed the related feature, draw a context so that in each context every domain entity name is clear. 

  3. Define a Ubiquitous language for each context. So the Business team and tech team in sync and using a common language when they communicate.

  4. Start with a Coarse-grained Bounded context, later If has a compelling reason to divide then divide the bounded context, I would recommend not do that if there is a Business reason.



2. Identify the Core Domain and apply Innovative Idea:: 


The core domain is such domain, which brings the revenue to your Business, Say for Online shopping Shopping cart module is the core domain which gives the platform to Buy and Sell (B2C) opportunity to Business and consumers, understand your core module is and think about how you can improve that module which your competitor does not have, any automation, innovations will add advantage and boost your revenue, so pay attention, do R&D invest money on core domain to stay ahead of the competition.


3. Do Cost Optimization on Generic Domains:: 


Generic Domains are such domain which is common in every business in that niche, and already different Third-party already provides the solution and commercialize in the market, Like you Notification module, or Ad Campaign module for your business, it is the best strategy, not to spend money on In house project to create this module and reinvent the wheel unless you have some compelling reason, preferably adopt the Third-party solution for the cheap price. 


4. Think on Support Domains:: 


Core domain needs the Support domains help, to enrich itself and in some cases, Support domain can lead the revenue and can be possible core domains in future. So it is important to think and take decisions to invest in the support domain so that it can generate revenue. Like in a shopping cart domain Inventory Management is Support domain but it is important to invest money to expand inventory locations to cut down the shipping cost, and also invest in algorithms, which can identify the nearest Inventory location for a Customer order to reduce shipping cost.


5. Introduce Anti Corruption Layer:: 


Anticorruption Layer is an integral part of Microservice design it protects Microservices from outerworld malformation, In a real-time Legacy project always you will encounter with such old system which builds on Mainframe or any other language, while you are doing decommission they are the important source of Microservice input data and live side by side with Microservices architecture you can not decompose that system for various reasons.


So it is a good idea to create a facade between Legacy and microservice communication, rather than directly consume data from legacy and create coupling on Microservice and Legacy architecture.


Also think on the Generic domain as they are adopting third party library so rather than directly consume/publish the data according to their contract introduce an anti-corruption layer which insulated the Microservices from outer world contract API, The Port and Hub pattern, so rather than driven by their contract we create our contract and ACL(Anti-corruption layer act as a translator between Microservice and third party contact. It helps you to adopt any third-party library in the future.


6. Identify the Data Communication patterns:: 


Once you decompose the microservices based on the features, and your core services encapsulated their own database/persistence layer,(database per service), the next important things to understand, to complete a feature, how your UI views/components will communicate with each other, is it a sequential flow? At a one-shot your user needs to complete the whole feature, or it can be asynchronous where the user can do a partial functionality and create an intermediate state, another system takes action on the intermediate state and calls back or notify the user to resume the action.


7. Introducing Event-Driven Architecture (EDA):


In a real-time application, your business cases having complex workflows and many branches on the workflows based on the state of the data, based on the state change, workflow took a different strategy, so if you think to expose all by Rest API, you will see that it creates a chatty network not only that each microservices coupled with others and create a spaghetti code and distributed ball of muds.


So somehow we need a clean architecture where each microservices can operate independently without creating coupling, here Event-driven architectures play a vital role, each event is wrapping a change of a state, and the Microservices are followed pub/sub model so one microservice produces it state change and wrap the necessary data in a form of event other Microservices listens to that events and can take the strategy based on the data wrapped in the event. As Events are immutable it also holds the history of an entity or aggregator so if you are adopting an event store and event storming you can generate any statistics and report from the events.


8. Make API contract Clean and concise :


In Microservices you need to publish API so it will act as a contract, so while you are publishing API make sure your api does not publish internal state, think about the encapsulation, and think about the network call, so publish API is such a way that other services can get enough information to carry on their flow, they should not come back multiple times for getting derivative information, also think about the events which events, which you should publish and which must remain inside, maybe you can publish one coarse-grained event rather than publish small internal events.


Example: say internally you have Address Change Event, Personal info change event rather than publish both in API contract, publish a Coarse-grained event called CustomerUpdateEvent.


9. Merge Related Microservices to a Bigger Service:: 


After decomposing if you can experience, few microservices always changing together when a feature needs to be added or updated, then you know, you decomposed it in the wrong way, they must not be segregated to a small service they are part of the same logical unit so it is wise to merge them a single service, it will reduce unnecessary coupling and network call. 


10.  Introduce Supporting tool for Seamless development:: 


Microservices is not free lunch, If you adopt Microservices first thing first be ready to expense on the supporting software as Microservice is distributed we adopt it for scaling resiliency and high availability and reduce Time to Market, it is distributed and works over the network so failure is inevitable and you need to catch the failure at the earliest without spending on infrastructure it is not possible.


If you spend well, then only Microservice allows you to buy out different options and help your organization to grow further.


So spend on CI/CD pipeline, adopt cloud infrastructure, use Tracing tool, use Log aggregator to search logs, use chaos tools for checking how you are prepared for failure, etc.






Conclusion ::

 The above points are necessary while you are decomposing Microservices, I will write an article on each topic on how they play a pivotal role in adopting Microservices architecture.


Also, like to hear from you more on the challenges you faced while decomposing to Microservices.


Microservices and Scaling Strategy.

 

I have heard many times below question 

" How do I scale Microservices? 

 or

What type of Scaling Microservices unlocks?

So I thought to write a crisp article on the Scaling.


A distributed system can always be scaled in a 3D space, i.e X axis, Y axis, and Z axis, and we need to scale distributed system to manage the load and having a high availability of the website and of course managing the cost in an efficient manner by maintaining servers/other resources optimum way.


X-Axis offers to spawn the environment based on the load, the old way of scaling distributed system that is behind a load balancer increase instances. It offers infinite scaling.


Y-axis offers, scaling by isolated the business functionality, aka functional decomposition so if a function has more load/usage/priority than the other functionality, we only scale that function and managing the cost of resources optimized manner. it offers infinite scaling of a particular function but total decomposition is finite but can be increased as function increases.


Z-axis offers Scaling through partitioning via business parameters, it's unlocked servicing premium customers or special request or geodiversity, etc. It also can be infinite based on the business parameters. But total parameter rules is finite but can be increased as you add more rule to it.


Keep one thing in mid Monoliths also distributed and it is also logically functionally decomposed through multi-module projects or package structure etc, but while deploying it packages as a single artifact ear or jar, so it does not unlock the Y-axis, as it does not offer a physical functional decomposition, each function does not have it's own program space or environment(Per function per container/server), Microservice is by nature unlocks that so, Microservice adopted 3D space scaling.


 



Microservices uses 3 types of scaling, actually, It follows the Art of scaling principles.


Y-Axis Scaling:: Microservices' main focus is to do the functional decomposition and it does it very well, each function wrapped by a few microservices, so If one feature in your system dealing with high loads you can only scale up that functions only not touch the others.


Z-axis Scaling: It helps you to partition your data, zone wise if your business distributed geologically you can put data centers based on Zones and that datacenter will serve the request for that zone, it helps serve your request quickly, and if loads of zones increases you can scale only that zones, not only that you can apply logic based on request param and send it to separate servers, say you have premium customers you want to serve them quickly you can do that.


X-axis Sclalling: : you can spawn multiple instances of Microservices based on the loads, you can use Cloud or can spawn by containers, it will give you the whole environment, not only artifacts that save your boot uptime.

So, if you think Microservices Scaling in a Hirechy order it starts with Y-axis Scaling then each Microservices can be scaled Via X and Z axis, you can adopt all type of scaling through Microservices architecture.

What is a Microservice?


Although the question is Simple, it is tough to answer as Microservice does not have any de facto standard, many people have many perspectives on Microservices so many definitions.




The compelling definition is.

Microservices is a Suite of services where each service is, bounded by a bounded context and can run, deployed, and scale independently without impacting other services.

So, to make the above statement correct in reality, organizations that are adopted Microservices follow few common characteristics, so

Javaonfly recommends, rather than going by definition go for Characteristics.

Characteristics to be followed for creating a successful Microservices architecture.

Componentization of services:: Service can be upgraded, evolved, deployed, scalable, tested independently.

Database per core services:: Take out the coupling from the database and make it private to core services, create an API contract by which other services get data.

Test cases are the first-class citizen:: as MS is a collaboration of multiple services so Unit test and Integration test is needed often to identify issues, Fail fast strategy is key to success, So need full Unite test case and integration test coverage with automation.

CI/CD Pipeline and Automation:: To become a success, we need CI/CD pipeline and provision to deploy in UAT, SIT, and may be automated deployment to PROD as well. Also If using PAAS, or containerization to treats resources like cattle, not Pet, we can spin servers on the fly for X-axis scaling

You build it you run It Strategy:: Make sure Team are mixed bag Agile teams UI, Backend, dba, QA, and Team is responsible for implementing a Business capability, like Registration Team or Login Team, Order Team, Payment Team, etc, may One Scrum handle Aggregator and core services for that functionality based on organization Team strength but one feature is built that team is the Sole owner of that feature, all bugs, support, deployment, delivery, database tuning, testing will be done by that team.

Strategy for Failure is must:: Microservice architecture dealing with a chain of services call over the network which is not in Teams control, so it bounds to fail but we create MS for high availability so Failure strategy is must, not a good to have kind of things, so always design Plan A, B, C D for failure and lastly fallback.

No Single Point of Failure:: Never ever design a component that can't be scalable through X-axis, so replication is a must for MS, use CAP theorem for your business needs, whether it is the service or database or Cache, config, Load balancer any component.

Reduce Chattiness by Aggregator:: As microservices over network call and a capability spans multiple services design an Aggregator which collects information from core services and returns UI specific response. Use Aggregrtaor carefully it might cause a God Service antipattern

Tracing and Logging:: s microservices over network call and a capability spans multiple services, think about developers how they debug if something goes wrong so use Tracing mechanism, also as MS using X-axis scaling it is not possible to check every server rather need a log aggregator like ELK or Splunk so using correlated id developer trace the call.

Smart endpoint dumb pipe:: Pipe means carrier of instructions i.e network only carry the payload all logic in the MS itself, unlike Service Bus where middleware did all stuff for you!!

Externalization of configuration:: Configuration must be extracted out from MS so we can change them without restarting the services, it helps to achieve high up time for the service.

If the above characteristics are present we can safely say it is Microservice, missing of one or many then that is not a Microservice but we can say they tend to achieve Microservices.


Tips::Favor Composition Over Inheritance is not a Universal Mantra!!

 


"Composition and Inheritance are the atoms of Pure OOO design.

One can't be replaced by others. Two have their own purpose,  Most of the time developers use Inheritance in the wrong way and it looks  Composition is the better option. 

One of the signs of using Inheritance the wrong way if you suppress a parent method by throwing "not implemented exception" or by silent/empty implementation.

To restrict that silly mistakes, Seniors often giving the above mantras without thinking about the context, but it does not fit always."

To know in detail please follow#javaOnFly , we will publish an article soon!!!


javaOnFly started a new segment called Tips corner, every Saturday we will post Tips only for you to make you a better programmer.


If you Like the Tips want more about the topic , you can read a whole bunch of detailed Java Articles on javaOnFly, if you like the content, you can subscribe to javaonfly.


Still not Satisfied!!! I love to discuss with enthusiastic people like you, on Java, Patterns, Microservice, clean code latest Trends, I am just one click away from you to connect


Follow me on

javaonfly :: https://javaonfly.blogspot.com

Twitter :: https://twitter.com/Shami83

Linked In :: https://www.linkedin.com/in/shamik-mitra-05b66227/

Instagram :: https://www.instagram.com/shamik.mitra/

Dzone :: https://dzone.com/users/1211805/mitrashamik.html

Facebook Group :: https://www.facebook.com/groups/javachamp

FaceBook Page :: https://www.facebook.com/artofjavaprog


#java #javaOnFly #code #programming #cleancode #javaonfly

#ask2shamik #tips #composition #inheritence #oops

Tips:: Don't Play with Developers emotion.

Clean code Tips
 

Tips:: "To Me, CLean code is the Developer's Emotion, a code maintaining a classical design or badly written, both are two extremities and must be avoided, as per statistics we have a large number of developers who wants to see code as simple methods and classes combination with   readable variable names neither a grand design nor an unreadble code."



javaOnFly started a new segment called Tips corner, every Saturday we will post Tips only for you to make you a better programmer.

If you Like the Tips want more about the topic , you can read a whole bunch of detailed Java Articles on javaOnFly, if you like the content, you can subscribe to javaonfly.

Still not Satisfied!!! I love to discuss with enthusiastic people like you, on Java, Patterns, Microservice, clean code latest Trends, I am just one click away from you to connect

Follow me on

javaonfly :: https://javaonfly.blogspot.com

Twitter :: https://twitter.com/Shami83

Linked In :: https://www.linkedin.com/in/shamik-mitra-05b66227/

Instagram :: https://www.instagram.com/shamik.mitra/

Dzone :: https://dzone.com/users/1211805/mitrashamik.html

Facebook Group :: https://www.facebook.com/groups/javachamp

FaceBook Page :: https://www.facebook.com/artofjavaprog


#java #javaOnFly #code #programming #cleancode #covid javaonfly

#ask2shamik #tips

Getter method - cheating the spirit of "Law of Demeter"

 

Every time I look at the Getter methods, I wonder, a simple getter method but its impact is very high on the code. 

Is it a friend for developers or enemies who are acting as friends? 

We can discuss various topics on Getter but here I would focus on one topic, which impacts codebase severely and forcibly implementing coupling and breaching the encapsulation. 

The most interesting part is that in some cases Getters can cheat the “Law of Demeter” rules, welcome coupling, and breach encapsulation. 

So it creates confusion for developers and as an outcome, we ended up with bad quality code. Today I am going to discuss how getter method cheats the “Law of Demeter's” rules

 

Note:: I will not discuss “ Law of Demeter “ principles, I assume you have a fair bit of idea of that, I will just give a pointer on Law of Demeter so I can show you the cheating. 

What is Law of Demeter say:: 

In layman's terms, it is saying never talk to strangers as strangers are a danger, only talk to your friends. 

So, in technical terms, a method can only interact with its arguments, it’s holding class instance variables, Objects which are created inside the method context, and static variables in java.  

More precisely, For any class C, a method M belonging to C may only invoke the following:

  1. The object class C itself
  2. Members of class C
  3. An argument of the method M
  4. An object created within the method M
  5. Global objects 

Rules are very clear and specific, it tries to minimize the communication /

If you restrict your communication with passed arguments and the class instance variable then you are reducing the coupling, more communication means more coupling, if your degree of coupling is higher the obvious you are breaching encapsulation.

Although, Law of Demeter tries to secure encapsulation by enforcing the law “Talk to immediate friends not to any strangers” -- but our good(really?) The getter method can trick it, getter will maintain all the laws but humiliate the Law of Demeter by cheating. 

Let’s take a regular example which we can see often in the codebase.


Department.java

public class Department { private Long deptId; private Employee deptHead; private String deptName; public Long getDeptId() { return deptId; } public void setDeptId(Long deptId) { this.deptId = deptId; } public Employee getDeptHead() { return deptHead; } public void setDeptHead(Employee deptHead) { this.deptHead = deptHead; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } } DepartmentReport.java package blog.javaonfly.article.getter; public class DepertmentReport { public void buildReport(Department dept) { /* * As per LOD Ok , but what is the use of doing that--??????? * Why are you cheating LOD spririt. */ Employee deptHead = dept.getDeptHead(); String deptHeadName = deptHead.getName();//LOD Breaks here !!!!! System.out.println("In Report" + dept); } }

Now , inspect these two lines


Employee deptHead = dept.getDeptHead();

String deptHeadName = deptHead.getName();//LOD Breaks here !!!!!


We have passed the Department object in build report method, so as per Law of Demeter we can talk to Department object, so we can call it’s getter method, getDepartmentHead() , which return an Employee Object which is stranger to buildReport method, so at this point, although we have not broken the Law of Demeter rule but Employee Object sneak in Report class and create a coupling!!!

Think logically, is it the Report object’s responsibility to deal with the Employee Object? 

The answer is obviously no, but then what do we do with only Employee Object in Report class? Employee Object is not useful if we do not dig into it as in report we may need the name of the Department head, the moment we call getName method it breaks the Law of Demeter as it says method needs to only interact with arguments, Rule 3.

So, dept.getDeptHead().getName(); is not permissible according to the law, and it is good as you do not know Employee is null or not in buildreport method if it is null, it will break Reports code!!!

So, By getter actually, we did the cheating to get a third level Object Employee(Report -> Department->Employee), but we can not do any useful thing with it without breaking Law of Demeter, But no one gives attention to Law of Demeter and we break the Law of Demeter, by happily calling a chain of getter methods.

This is one reason I do not like Getter's, it breaks encapsulation silently.

Now, let's make it more interesting.

Adding below code snippet in Department.java


public String getDeptHeadName() {

return deptHead != null? deptHead.getName():null;

}


Then , call this method in Department Report class buildReport method


String deptHeadName = dept.getDeptHeadName();


Now, Again according to the Law of Demeter it is perfect. The Department only talks to an instance variable department Head(Rule 2), and Report class told to method arguments(Rule3).

But again, we are breaking the spirit of Law of Demeter, Departments should not do any operation on Employe objects field, it is Employee Object responsibility to do the formatting and all other operation on it’s filed and get presentable data to the caller so, the caller should not do any operation on it.

Basically, Caller will not ask for data it will command the associate class for readymade data.

Tell don’t ask principle.

In this example you are asking, getter methods are asking for data that means asking for more responsibility to properly handle them, which is not your duty at all.

Now, what about this case,


public void buildReport(Department dept) {

Employee deptHead = dept.getDeptHead();

String deptHeadName = getDepartmentHeadName(deptHead);

System.out.println("In Report" + dept);

}

private String getDepartmentHeadName(Employee emp) {

return emp.getName();

}


Again, we did some trickery, we maintained the Law of Demeter but cheating its essence!!!

Now, we create a private method and pass the Employee object as an argument and call geName in that method, now as per Rule 3 we are good, but think on class perspective, as per Law of Demeter we should talk to immediate friends which is Department Object but here again We are talking to Employee Object.

What do we learn from this?


  • We learn that the Law of Demeter is giving us suggestions on how to reduce coupling and be safe by not talking to strangers but there are many loose ends from where we can break the naive clause of Law of Demeter, Getter is one of those.
  • Use Getter carefully, it may look simple but often breaks encapsulation by exposing a Has-A relationship to the Outerworld.
  • Do not write getter for HAS-A relationship, it means you are delegating the responsibility to the caller or Higher level methods.
  • Calling getter Chain is bad if each getter returns different Objects, because if any of the values is null then you are in deep trouble, adding multiple nulls check will not help you, it increases your complexity of codes.


Conclusion:: Law of Demeter is good when you take it as a suggestion, but if you technically try to prove you are maintaining the laws and tricks it, then there will be debate and may you win the debate but losing the code quality, on other hand, if you think logically put programming reasoning then only you can thank “Law of Demeter”.