Thursday, October 25, 2018

Separation of Concerns in Microservices World

When developing microservices, we need to make design decisions like

How is the service getting exposed?. Example: HTTP, Queues

How inter-service communication going to happen?. Example: HTTP, Thrift, gRPC, Socket, Queues

How does service A know what is the service to call next, its transport mode, version, url .etc?

How to deploy service?. Example: Serverless, Containerize service, deploy services in a single instance and autoscale, each service in the separate instance

Decision making should be based on factors like ease of coding, performance improvement, ease of deployment, maintainability.etc. A better approach is to have a clearer separation in your code (separation of concerns) explained below.





(You can substitute with whatever name you think relevant for - Handler, Executor, Service Caller )

Handler

Handler is the piece of code which receives the request in microservice. It can be either through HTTP, Queue etc. It will call the Service Logic / Executor for the business logic to be executed.

Executor

Treat your microservice as a set of functions which does some work. Don't tie up transport layers, inter-service dependency in the executor

It should be a set of functions like this.

doSomething1() { return response;)

doSomething2()...

Service Caller

Executor calls the Service caller for all inter-service communication dependencies. Service caller will decide what is service to call, resolve its URL, version.etc. We may not need a service registry for all use cases.

Let's take a scenario to explain a typical microservice communication.

A, B, C, D, E are microservices.

A->B ->C-->D ( Data flows from A to D)

B->E ( B internally has a dependency on E)

A, B, C should not hard-code its calling/dependent services. It just has to call the Service Caller.

Service Caller can have a function like callNextService( context, data) {}

Context object contains details related to calling service, its version, business specific data
Data contains the payload and other relevant data like tokens essential for the service call
Depending on the context and data, Service Caller resolve the next service and handles the inter service communication.

Write a generic function for Controller and Service Caller (wherever possible) and have a shared library exposed to all microservices.

By having this separation of concerns, changes are easy to accommodate. For ease of understanding, I'm sharing some examples for changes we may come across during development


  • Introduce queue between services
  • Deploy services in AWS Lambda, containerize services .etc
  • Introduce Thrift instead of HTTP for inter-service communication
  • Change microservice communication flow from A->B->C->D to A->B->D


I hope with this examples it is clearer why the separation of concerns is important.

I just want to end this post with some basic design principles which I think more important for microservices development

  • Ability to independently develop, test and deploy
  • Avoid sharing the data model between services
  • Make your Service boundary right by having high cohesion and single responsibility principle
  • Loosely coupled

Sunday, May 21, 2017

Get your basics right with these smart software principles

A software is always written and rewritten to make it relevant for business and technology. It makes more sense not to violate some basic and important software principles. Languages and tools you use may provide some best practices and principles. But in general independent of what technology you use, some design principles are fundamental and adhering to it helps to ship quality and maintainable software.

I'm highlighting some important software principles below and few suggestions on how to enforce in your work and project.

Single Purpose: Each unit of code should serve one purpose and do it well. Unit of code can be a function, class etc. depending on the language you use.

High Cohesion: Keep related logic together in one place to have high cohesion. Depending on your project, it can be in your module/class/library

Loose Coupling: All components in the system should be loosely coupled for maintainability and easy modification

Side effects: Avoid side effects. This is a wide topic of discussion in functional programming, but in simple terms, it can be explained as side-effect is when an operation has an effect on a variable/object outside its intended usage.

Immutability: Don't mutate variables and objects wherever applicable.

Write Simple and Readable Code:  Coding is a collaborative work. Write code which is simple and easy to understand. Don't complicate things even if the language and tools you use support complication.

Wrong Abstractions:  Too much of abstraction is bad practice. There is no definite answer on what is the correct level of abstractions. But one best approach is don't prematurely abstract things and do when the need arises.

DRY /Avoid duplicates: Avoid duplication of code and logic wherever possible. It is fine to have some level of duplicate code when you are in initial phase of the product but it has to be resolved at right time. ( Refer technical debt below)


How to enforce it?


Below things, you can do in your project to enforce the best principles

Refactoring and Iterative development: Develop a culture in your team where refactoring and iterative development is encouraged as good practice. Especially it is far more important when you are in the initial phase of your product development.

Technical Debt: Maintain a list of all the technical debt in your project and iteratively reduce it.

API-Centric Model: API-centric model has many advantages. For instance, by reviewing API spec/contract, if you see if an API expects additional inputs than its intended purpose, you can easily figure out and avoid even before implementing the code.

Code Reviews: Do peer code reviews before you push the code . Especially review the unit tests/ test cases to catch any potential violation of principles.

Tools / Linters: You can use code linters /tools which enforce best practices in your code


Let me give you some casual examples to understand some of the principles.

Example 1: Suppose you are the developing a module in your application where it sends the notification to users through various channels like email,. API should get the details related to its intended purpose, say a recipient list, content, email subject, attachment. etc and send the notification. But if you also add more business logic not related to this module,  then it is a sign of bad practice.

Example 2: If you find a super function/class which does many things in your project, then it may be a sign of prematurely you are abstracting things

Project Management Musings - Polygot

Generally, the term polygot refers to programming and technologies where the ability of person work on multiple languages and technologies.  In the context of product and project management, it is someone possessing skills to contribute in other roles of the project apart from his/her primary responsibility and ownership

For instance,  below are the responsibilities and roles in a typical software development project.

Responsibilities

Business Analysis, Product Management, Product Ideation, Product Development, Technical Architecture, QA

Roles

Tech Lead / Lead Developer,  QA Lead,  Business Analyst, Product Manager

The Core responsibility of a QA Lead is to plan the testing and ensure product quality is met. But if a QA Lead can contribute to Business Analysis, he/she can do the process of QA better and give a new perspective to product and business.

Similarly, a technical person can contribute to Product Management, Business Analysis and can make the technology and project deliverables close fit to business.

Depending on your product, you can combine the roles and responsibilities to get a new perspective on the product and also enable the team to do their primary role more efficiently.

Project Management Musings - Context Matters

Implement your processes and decision-making aligned with the context.  Context can be the current scenario and  factors surrounding the project

Some of the questions you need to ask yourself to understand the context.

Which phase of product lifecycle are you in?.
Are you working on a product already used by many customers?
Are you a startup trying to figure out the right market fit?
How is your team comprised of and what are their Strengths and weakness?
How far does your current funding go?
What is the current market trend related to your domain and product? .etc.

Suppose you are a startup and have a potential customer.

Do you resolve major issues in the product, unblock and release your initial version and get feedback?.  (or)  Would you adhere to all processes you planned before making release?.

You need to move fast, you may need to change your processes based on the context.

Always take your decision aligning with the context!

Tuesday, August 11, 2015

Ask - Why? How? What?


Do you ask these questions  when developing a consumer internet application?

Why a User  has to use my application?

How a  User identify my application ?

What  actions Users do in my application?








By finding the answer,

You can understand the user's motivation in using the product.

You can understand the user behavior.

You can measure the performance of a campaign and see which suits.

You can visualize the user data with different dimensions like demographics, device .etc

& many more.

All these findings leads to a better Customer Analytics.

Customer Analytics aids the product strategy,  product road map and overall product management.

Sunday, August 9, 2015

Product Management Checklist

How you execute the project, best practices you follow is crucial for overall success of the project.  I'm sharing here some pointers for a better product management. I write this more on a consumer web/mobile application perspective but it can be applied to other kind of projects as well.



Lean Startup  - Understand the Lean Startup & Lean UX principles. 
Specifically understand these things - MVP, Continuous Deployment, A/B Test, Build Measure Learn.

Take Decisions & Release Early  - Take decision fast.  Have a shorter iteration and release early.

Metrics & Forecasting  -  Maintain a simple project metrics which conveys the overall progress of the project. What I mean simple here is have a document which have only the crucial metrics which track project deliverable, user adoption .etc. You can have a metric on various levels depending on the business but have this as a separate document where everyone in the company can easily relate to  and understand. Similarly have a project forecast document. Things can change quickly but keeping this in place can avoid unnecessary deviation from the product priorities.

Single Team - Its time for the designers, front end developers,  back end developers, business analyst, marketing folks to work together in a single team.
Lines between the functions are getting blurred due to change in business models and technology.

Place for new ideas and innovation - Create a culture in your team to share new ideas, new business models and talk innovation.   

Edge Cases - Make developers think about the edge cases in a project. Imposing test cases and code review helps to achieve this.

User Journey & Workflow  -  Make your team to think in terms of  a workflow and user's journey  with your product.

Code Review -  Code Review is a must to have which can increase the overall quality of product and improve developer productivity.

Analytics as stack -  Have analytics as part of your project stack as you have front end, back end, database .etc. 

Benchmarks -  Maintain a benchmark for Performance, Security, Usability .etc from start and improve iteratively.

Refactoring & Iteration - Refactor when necessary. Particularly this is very crucial in initial phases of the project.

Quality Expectation  -  Have a quality expectation in your team. Most likely everyone adhere to it.

Automate -  Look for automating the processes wherever you can. Use CI.  Automate - builds, testing.etc

Move Fast  -  Team / Companies that move fast succeed . Take decisions, measure & move fast.

This is all I have now.  I'll add to this list if I there is anything I missed out..

What to choose?. Java, Javscript, Python, Scala ... - Feeling confused?

When you start a new project, the important question  pops in your mind is choosing the technology stack.

This blog post is not about comparing  different languages and databases rather I'm going to highlight some general principles and understanding which helps to take a better decision in choosing the technology stack.





Think as modules /components


Different portion of application can use different language and database. Visualize your application as a group of components, modules and services. Now choose the best technology which suits your need.


I'm just listing down some possibilities for using different technologies  in same application

You can have a web-service written on Java, Some can run on Python
You can use Node JS/Javascipt on server side.
You can use Javascript framework like Angular JS for front-end
You can use Python for the scripting needs.
User data can be stored in MongoDB,
Cache data can be stored in Redis,
Analytics Data can come from Redshift.
You can implement your search layer using ElasticSearch.
You can use Big Data technologies like Spark, Kafka .etc for your data processing requirements.

How to approach?

Approach like this to take better decision in choosing the technology.

What experience I'm going to give to the end user?. What problem I'm going to solve?

List down the workflows, use cases, performance requirement, access patterns. (Access pattern may be the types of queries, query frequency, is it dynamic? .etc)

Now see which language, database, tools, framework suits your need.

Your team's current tech expertise is also an important factor to consider but create a atmosphere where they are open to new technology and willing to try it out.

Product Architecture  is important

How you architecture your app is very important.  Generally  it is the architecture which scales not the language. Also how you architecture makes your application maintainable in a longer run. For instance choosing between Java (or) Scala  may not relate to project's overall success.

Comparison with successful products

You may come across people saying, "Even Facebook uses PHP as back-end". "Netflix uses Microservices" etc and try to apply to your project . But the level of optimization they do, expertise they have for it and the maturity of their business model  is important factor to consider. You can consume these kind of information but apply whichever suits your project.

For example, you can take a middle path between monolothic and microservice. As you project matures  you will be in a a better position to convert it completely to microservices.

Refactoring is not harm 

If you able to get traction for your  project, you can always refactor your code . Even big companies do it often. Refactoring  is not harm.