The Rimeto Development Environment

Optimizing developer efficiency and happiness

Photo credit: coyot

Introduction

At Rimeto, we spend a lot of time thinking about how to optimize engineering efficiency and happiness. We believe that a well-designed development environment — specifically the languages, frameworks, tools, and processes used to develop software — can enable an engineering team to be significantly more productive. In this post we survey several of the languages, frameworks, tools, and processes we have found to be valuable in Rimeto’s development environment.

Languages + Frameworks

Typescript

One of our earliest environment decisions was to standardize the majority of our codebase on TypeScript, a cross-platform, typed superset of the JavaScript language that compiles to pure JavaScript. TypeScript extends the JavaScript language to support features like static typing, classes with access modifiers, interfaces, and more. TypeScript makes large-scale JavaScript application development significantly more scalable by elevating development invariance checking to compile-time and integrating deeply with tools like Visual Studio Code.

The choice of TypeScript originated from our desire to leverage the React and ReactNative frameworks for web and mobile client development. Since many of us had worked extensively with these framework during our time at Facebook, we were confident that the React and ReactNative ecosystems could enable us to execute quickly across multiple platforms as an early stage company. But at the same time, we were reluctant to introduce a dependency on JavaScript for a major component of our stack. While there are many powerful aspects of JavaScript, the language has many challenges (limited support for contracts, lack of compile-time invariance checking, ease of introducing typos, etc.) that can manifest during application development at scale. We identified TypeScript as a possible solution to our dilemma: this superset of JavaScript could mitigate the more significant challenges of JavaScript while still allowing us to take advantage of frameworks like React and ReactNative.

Fast-forward 18 months and our bet on TypeScript is paying off. It has led us to write cleaner, self-documenting code, effectively eliminated all occurrences of fatal errors due to typos, and integrated seamlessly with our development tool chain. TypeScript has been especially beneficial whenever we refactor code: the compiler’s support in guaranteeing all affected call sites are updated saves us much engineering headache and debugging. Not only has TypeScript been helpful in scaling development of our growing set of service and applications, but it has allowed us to standardize our language and environment across our stack, from our NodeJS service infrastructure up through our React and ReactNative client applications. Our standardized environment has created efficiencies for our engineering team by minimizing context switching between our several code repositories.

(Side note: a reasonable alternative to TypeScript is Flow. The two frameworks are very similar, and you can’t go wrong with either approach. At the time of the decision, our impression was that TypeScript had a stronger community backing and deeper integrations with tools like VS Code.)

React Native

ReactNative as a mobile application development framework deserves a special callout in this post. While ReactNative does have its challenges (notably: it’s pace of change at a framework level can make upgrades challenging), on balance the framework has been hugely beneficial to the efficiency of mobile development at Rimeto. The biggest wins for the team have been:

Over-the-air Code Deployments

  • We are able to patch application code with over-the-air (“OTA”) updates. This gives us extraordinary flexibility to deploy bug fixes, make configuration updates, and ship new features without the need to re-do the various app store review processes. OTA updates ultimately benefit our customers as they receive important code updates on their mobile devices faster.

Cross-platform Support

  • ReactNative supports iOS and Android out of the box. While we have built some native customizations for the two platforms respectively, we’ve architected our application such that the majority of our application logic is defined in the TypeScript layer with minimal branching between platforms.

Ability to Share Code Across Platforms

  • Since our web app is also built as a React application, we are able to share code across not only our iOS and Android environments, but also our web environment! This arrangement empowers us to update certain application logic across all client platforms without redundancy!

Tools

Visual Studio Code

One of our favorite development tools is Visual Studio Code. VS Code is a free, open source, cross-platform code editor that integrates particularly well with our TypeScript + git environment. It is extremely fast, highly configurable, and endlessly extensible by way of a rich ecosystem of extensions. Some of our favorite extensions include:

TSLint

  • An extension that integrates the tslint linter for TypeScript into VS Code. It can be configured to highlight and automatically fix identified issues inline.

GitLens

  • Helps you visualize code authorship and change history of any file with embedded git blame annotations, code change heat maps, and more.

Code Spell Checker

  • Simple extension that helps catch common spelling errors in variable/method/class naming as well as comments.

Sort

  • Simple but incredibly handy extension in a variety of different circumstances!

Testing

We expect every engineer at Rimeto to take full responsibility for the quality of their code, and we firmly believe in the long term value of unit testing. A small amount of time invested up front writing tests almost always yields many saved hours down the road. We utilize jest across all of our repos and encourage our engineers to make full use of the framework. Moreover, unit testing is wired into all of our CI/CD pipelines such that all tests must pass before any branch can be merged to master. This helps us mitigate regressions and build breaks across all of our repos.

Code Tidiness

We subscribe to the philosophy that there are certain development tasks best left to robots. We work hard to eliminate the mindless, pedantic tasks of development and code review so that our team can stay focused on the more important matters of design and architecture. Catching and correcting common coding mistakes and code formatting inconsistencies are two such tasks. We utilize TSLint and Prettier to automate dealing with these two more mechanical components of the software development cycle, respectively. TSLint is an extensible lint framework designed specifically for TypeScript, and prettier makes code style and formatting consistent and objective. We configure both of these tools to run automatically as pre-commit hooks using lint-staged and husky. By programmatically enforcing and automatically correcting numerous coding and formatting guidelines, we eliminate unnecessary discussion about these topics during code review cycles.

Processes

Code Review

While we generally strive to stay lean process-wise at Rimeto, we do believe in the value that a rigorous peer code review process can create. Before any code is merged, it must be reviewed and approved by at least one other peer developer. The goals of our code review process are to:

Increase Accountability

  • We naturally produce higher quality work when there is expectation that others will be looking closely at that work.

Exchange Knowledge

  • Code reviews are great moments for sharing ideas and best practices. Not only can code review feedback help the code-writer more quickly converge on an optimal solution, code-reviewers can also benefit through exposure to alternative approaches to completing certain technical tasks.

Improve Code Readability

  • After working on a particular piece of code for a while, we become blind to aspects of our code that may not be as clear, concise, or well structured as they could be. A second set of eyes on our code often very quickly reveals opportunities to improve code readability and maintainability. Note that this is not about style nitpicks. In fact, by the time code reaches code review in our environment, our tools have already standardized style and formatting via pre-commit hooks.

Sanity Check Completeness

  • While code reviews are not meant to be a substitute for testing, often a second set of eyes can catch code that is incomplete or otherwise incongruous with the stated purpose of the change. Code reviews are also great opportunities to spot check test plans to make sure we haven’t missed anything obvious in verifying our work.

To make sure the code review process doesn’t unnecessarily slow down development pace, we set expectations with the team about completing code reviews in a timely manner, and encourage the team to proactively seek reviews in situations where engineers are blocked. On balance, we believe that slowing down for peer code reviews improves efficiency over the long term: we write higher quality and longer lasting code, all the while become stronger software engineers through the process.

Summary

We have selected every framework, tool, and process we use today at Rimeto with the goal of improving developer efficiency and happiness. We constantly reevaluate our setup as our tech evolves and our team grows. A tool or process that works beautifully today may not scale for tomorrow. As such, the last component we see in a well-designed development environment is a feedback loop to ensure that we are meeting our developer happiness and efficiency goals in a sustainable manner. At Rimeto, we stay on top of this by regularly poll the team about “what is slowing you down?” and prioritizing improvements accordingly.


Passionate about cutting edge development environments? Come work with us!