Posts from November 2016

For our continuous delivery practice, an important part of shipping code to production is running automated tests against those production candidates to ensure the version of those applications work as we expect. Sometimes those automated tests take so long to run that it feels like it kills the flow of continually shipping. So, one of our goals this summer was to reduce testing time, even when the number of tests is high, so we can keep pushing code to production. By introducing Bazel to our Insights product we were able to reduce the testing time by 50% from 7 minutes to 3.5 minutes, and reduced our time-to-deploy by 70% from 9 minutes to 2.7 minutes.

Bazel

Bazel is the open-sourced cousin of Google’s internal tool – Blaze. Bazel allows the automation of building and testing, developed by Google too. What makes Blaze unique is that it has been designed to solve build problems specific to Google’s development environment. According to Jeff Cox from Google’s Bazel team, it is suitable for projects that involve massive, shared code repositories, extensive testing and release processes and language and platform diversity.

It has proven to be both scalable and reliable after extensive usage by tens of thousands of engineers and tested over years on Google’s environment. It has proven to be build software quickly and correctly too. It’s speed is achieved by caching and parallel execution, as Bazel rebuilds only the files that are needed, instead of the entire project and runs tests only for the code that has been changed.

To understand Bazel and see if we could benefit from it, we first had to understand how it worked. Bazel works with WORKSPACES and each workspace is defined by a file named WORKSPACE (which can be empty). Inside every workspace you can define BUILD files with rules and each defined rule is a target. Each target will be a node in the dependency graph, and the target’s dependencies are edges.

bazel-workspace-and-targets
WORKSPACE – defines the project workspace (folders hierarchy). BUILD files – define targets using rules

Read More …

Tagging has become a ubiquitous part of modern web applications ever since it was popularized by Flickr and Delicious in the early 2000s. The ability to add a tag to arbitrary content allows a user to organize, filter, manage, and measure however they see fit. This flexibility of application makes tagging a very valuable feature to invest in.

tag: rawr
tag: rawr

Tagging has been a function of the Hootsuite dashboard for some time. In its current incarnation, users have the ability to add tags to messages in their streams, and to add tags to their outbound messages. This allows them to generate analytics reports on things such as the number of retweets of their messages with a given tag, or how often they receive messages with the tag ‘Pokemon Go’. In addition, organizations have the ability to tag arbitrary uploaded content, such as files or images, so that a team member can more easily find resources for composing messages.

Read More …

The Dark Side of Modularization

Working on our iOS application has been an incredibly eye-opening experience. I was anticipating being overwhelmed by jumping into a colossal monolithic application with a complicated set of interdependencies. Luckily for me, our mobile team was on the same track as our web teams and had taken steps to avoid a monolithic architecture for both their iOS and Android applications. The decision was made to fragment the application into highly cohesive modules that abstract away implementation details from the main application. On iOS, externalizing code is best done with frameworks; which are libraries that can also contain resources like xib files, storyboards and images. At the beginning of my work term, our app was consuming over a dozen internal frameworks and several external frameworks. As a result of managing so many dependencies, the time it took to build our app had skyrocketed and became a serious block in our daily workflow. Just imagine having to wait 25 minutes every time you wanted to get the latest changes from the repository!

A New Hope

Over the last few months we have made several key revisions to our workflow that has allowed our framework approach to be far more effective, and ultimately, made our lives easier.

Our transformation into frameworks began with extracting the small, reusable, components and has now extended to features as large as the entire searching tab of the application. What makes this framework approach so valuable stems from the roots of modularization as a software technique: maintainability, reusability, and abstraction. With each major feature of our application in it’s own framework, different iOS teams at Hootsuite are able to maintain different frameworks independently, each with their own separate commit history. Many of our internal frameworks depend upon each other, they were designed to be as reusable as possible. Each framework has a well defined public interface, the implementation details of a framework are inherently abstract. As a co-op starting out in a new position, this level of abstraction and modularity has made my life easier and far more productive!

We have categorized our frameworks as either a Component, a Feature, or a Core utility. This graph doesn’t include all of our frameworks, but it illustrates the hierarchy:

iOS Features Components Core

When is it suitable to make a framework?

Read More …