Navigating Microservices Code Repos

This happened when I was working for one of my previous employers.
I had just joined the company and was working on a microservice that was consuming a REST api exposed by another microservice.
There was this JIRA ticket I was working on and I was not sure about the data model exposed by this REST api call. At this point in time the adoption to OpenAPI / Swagger / RAML was just beginning. I was new and was wondering whom I should reach out to.
Just then my colleague, who had joined a month before me, sent me a link to the codebase of this repository that implemented this REST api.
He also went ahead and showed me the Crucible tool that showed me code reviews to this repo.
That was an “Aha !!” moment for me. It opened up new avenues to learn and to make new connections across teams.
Until then I had never explored a code repository that I did not work on.
But now, since I was seeking an answer to my question, it was motivation enough to explore this code repository.
It was like solving a puzzle and kept me hooked until I found an answer to the question.

Options to explore a new code repo

  1. ReadMe / Wiki Documentation
  2. Read the code
  3. Unit Tests
  4. Running the app

ReadMe / Wiki Documentation

The general expectation is that any good code repository has a good readme that talks about

  1. What does the project / codebase do ?
  2. How to set it up to run on a local machine ?
  3. How to contribute to it ?
    The above are generally true for well maintained open source repositories.
    If there is a readme with accurate information then look no further, literally !!

Many organizations use other products to maintain internal documentation. A popular product adopted being Confluence. Confluence has a good search capability. A quick search about the repo name or the project name should list Confluence pages that list or mention this repo. This also might give insight into the context of the project and how it fits in the organization.

Read the code

This should be the most obvious choice. But the irony is, there is nothing obvious about reading source code. Source code is the ultimate source of truth.
It takes a lot of experience to try and figure out the flow of control in an app just by reading the code.
I am no expert but I do try poking around the code to understand what certain parts of the code do.

A quick way to think of an app is:

  1. Bootstrapping / App initialization / Startup
  2. Dependencies
  3. Points of integration into the app

Bootstrapping / App initialization / Startup

  1. Spring Boot Application: Look for Application.java file or a file with @SpringBootApplication annotation
  2. Node.js: Look for index.js or look at package.json to see what starts the app.
  3. Go: Look for main.go

Dependencies

  1. Spring Boot Application: Look at the application properties or application yaml file.
  2. Node.js / Go Lang: Look for the environment files or look at the starter / bootstrap file to see which files it refers to load the configurations.
  3. Look for the infrastructure code to see where and what environment variables are set

Points of integration

An app can have multiple types of integration.
The most common ones being

  1. REST API
  2. Event driven interactions
  3. Database (DB) interactions
REST API
  1. Spring controllers in a Java Spring Boot based application
  2. Routes / Middleware in a express node.js based application
  3. Search the code for REST API path and figure out what is the handler for the code
  4. Search the code for controllers
Event driven interactions
  1. Search the code for “Listeners” or “Publishers”
  2. Search for code references for the queue / topic name
  3. Based on the code references for the queue or topic name, search for event handlers publish messages or subscribe messages.
Database (DB) interactions
  1. Search the code / application configuration for the connection string to the database.
  2. See if there are any .sql files in the code base that define the DDL
  3. See if the code uses any sql migration tool and what scripts it might use.
    If thee DB connection string is obtained, one can easily connect to the dev instance of the DB using a client and try to understand the table and get a hang of the model that this app interacts with.

Again all of this is just a shot in the dark. But over a period of time and with experience one can narrow down areas to look at and inspect.

Unit Tests / Integration Tests

So what do we do when the instructions in the readme are not accurate or in the worst case there is no readme at all ?
Many times I have come across libraries that do not have great documentation for their api.
In such situations I read through the unit tests to see how the library / api is being used.
The hope is that the developer cares for the code developed and has tested all the functionality that the api / library has to offer.
This is like a backdoor to documentation.

Running the app

The last resort is to run the app.
This is where the fun and exciting part begins.
One must be careful not to get into a rabbit hole trying to get the app running. This effort must be time-boxed.

I have worked across technologies like Java, Go and Node.js.
So as a developer I am familiar with how to run a Java app or a Go app or a Node.js app.
I just attempt to get the app running, fingers crossed.
More often than not there are errors running the app and now is where the exciting part comes.
I start to resolve the errors one by one.
More often than not the errors are related to the application configurations.
It is a matter of figuring out which configuration is missing or what needs to be tweaked to overcome that error.
It is like being a detective solving the clues one by one.

First step is to clone the repository on your local machine.
The next step is to download the dependencies for your application and download them.

  1. Spring Boot Application using Maven
    mvn clean install
  2. Node.js Application
    npm install
  3. Golang Code
    go mod download

Java Spring Boot Applications

I have been lucky that my organizations have always been able to provide me a license to use IntelliJ IDEA.
With IntelliJ, I just click on run on the Application.java file to try and start the app.
This creates a run configuration for me. More often than not the app would not run for me.
The errors would be singing a tune like
Could not instantiate a bean
A spring boot application is all about following the beans.
Looking at the bean one can see what properties it depends upon and try to correct the configurations.
If the app depends on a DB or an instance of a message broker, start up a local version of the DB or message broker and point your app to the local instance.
Eventually the app gets up and running.

Node.js Applications

Look for the startup file specified in package.json
The convention is that it should be index.js.
So I would run node index.js.
Again I follow the same process.
There would be errors starting up the app and it is a matter of reading / deciphering the errors to find out what configurations / environment variables need to be tweaked to get the app running.

Golang Applications

Look for main.go
If you have a GoLand license, just click on the Run next to the main function.
On command line run go main.go
Follow the process of deciphering the error messages and tweaking the configurations / environment variables to get the app running.

Docker

Look out for the Dockerfile if one exists.
If there is a Dockerfile, attempt to build the image and run it.
The Dockerfile also provides clues on what environment variables need to be set.

What’s in it for me

  1. You are not waiting on someone to walk through the code.
  2. There is a sense of achievement and satisfaction to get an app running.
  3. It validates my credentials as a Software Engineer
  4. It helps validate assumptions I had about the app or it helps understand things I did not know about the app.

Real life experience

In my job as a tech lead, I joined a team that managed 20 or so microservices. It had a mix of Java and Node.js. It had a mix of REST API and Event Driven architectures. I had a choice, to wait on someone to walk me through them or do it by myself. I chose the latter and I understood the challenges the team was facing much better. It helped me in my ability to lead the team and make good architectural decisions.