About three years ago, the Hootsuite Engineering team began a transition from a monolithic application to a services oriented architecture. While the journey is ongoing, we have come a long way from learning how to build services at all to efficiently delivering new customer value on top of a constellation of services.
This post shares what our journey has looked like, what we’ve learned along the way, and how key metrics have been impacted.
To gauge our progress we have tracked a number of relevant metrics:
Production lines of code in monolith vs SOA
Services in production
As the data shows, there have been three distinct phases in our transition to SOA. This post goes into detail on each phase.
If you’ve ever posted to a social network from Hootsuite’s iOS or Android application, then you’ve used the composer. The composer is where you write the message body of your post, maybe attach a video or GIF, and select the social networks to send it off to.
The code behind message composition, however, has grown unwieldy. The main activity on Android is somewhere in the order of 3,500 lines long. When it comes to implementing new features, it is difficult to add to and easy to break. As Publisher’s mobile team looked to revamp the design, refine some features and add others, developing a new architecture for message composition was the clear first step.
At the centre of most galaxies lies a supermassive black hole. Similarly, at the heart of many existing codebases lies a supermassive tangle of legacy code. One of these phenomena is hard to understand: it seems to defy the laws of physics, and sucks the life and energy out of anyone who approaches. The other is a black hole. In this post, I will compare these two mysterious concepts and suggest some strategies for dealing with legacy code that are inspired by some of the postulated solutions to the black hole information paradox.
A module is a way of dividing or grouping your code into files or sections. Modules are ideally self contained and decoupled, so that changes can be made in a single module without having to rewrite other modules.
Why Use Modules?
Modules have a number of benefits including namespacing, better maintainability, and reusability.
Without modules, it’s very easy to get namespace pollution because all variables outside of top level functions are global and accessible everywhere in the code, even if it’s unrelated. Modules allow namespacing, which creates private variables to reduce or eliminate this pollution.
Modules also allow for decoupling of unrelated code. This means that changes in one file should not require changes to be made in other files, resulting in more maintainable code.
Modules allow you to import and export a single module, so that it can be reused as many times as you would like without duplicating the code. This is great because it means that any required changes will only be needed in one spot, instead of all the potential duplicated places.
Kotlin, a new JVM language created by Jetbrains, is quickly becoming the go-to programming language used for Android development at Hootsuite. Its many features and Java interoperability make writing code much faster, cleaner, and less verbose. However, without being aware of language idioms it can be easy to fall back to old Java patterns. In order to maximize the utility of this new language, it is important to familiarize yourself with writing idiomatic Kotlin code. Kotlin’s features, such as the nullable types, lambdas, and delegates, differentiate the language from Java and are useful for writing effective code.
As part of the engagement team at Hootsuite, we use React as part of our front-end framework for everything from the streams that users see when they log on to dashboard to the new Assignment Manager. Testing is crucial to ensure that our code will work correctly when it has the right inputs, or will fail gracefully when it doesn’t. One of the many challenges of front-end testing is that with increasingly complex frameworks like React, thorough tests are needed to ensure that components render correctly, receive the right props, and update properly. Such tests are often difficult to implement, maintain, and understand. While React offers a ReactTestUtils library, the library is very basic in terms of ease of testing and manipulating the React component’s output. We went as far as writing our own test utils but it simply did not provide the extensive coverage needed.
While working at Hootsuite, I’ve had the pleasure of working in-depth with React to build our newest features for the dashboard. For example, I was tasked with building a component to show a horizontal list of items that adapted to the changing window size. Based on the window width, my component would show a dynamic amount of items and tell the user how many of those items were hidden if any. It’d be a fairly simple task if the amount of items was static, but but since the number of items is dynamic, I had to calculate how many to display each time the window size changed.
More specifically, the amount of items in the list should change depending on the size of the container. The last item in the list should show how many hidden items there are in the list if all the items didn’t fit (i.e +3).
At Hootsuite, we are moving from in-place deployments with statically provisioned hosts to running Docker containers on an orchestration platform. This platform manages the running containers and handles scaling and failure recovery. Transitioning to Docker will allow us to build microservices more quickly and with reduced operational overhead. We’ve chosen Marathon and Mesos as our orchestration platform (other options were Docker Swarm, Kubernetes, ECS, and Nomad).
You aren’t truly ready for a career in Big Data until you have everyone in the room cringing from the endless jargon you are throwing at them. Everyone in tech is always trying to out-impress one another with their impressive grasp of technical jargon.