Navigating Human Decision Trees

SWE Management Diary #2

Radosław Warisch
Brainly Technology Blog
4 min readNov 28, 2022

--

This series of articles provides software engineering management insights to improve engineering velocity and maturity.

After working for six years as a software engineer, I decided to switch to leadership. These are the findings and insights from my journey as a Software Engineering Manager!

PART 1: LINK

Photo by Markus Spiske on unsplash.com

Software engineers make a lot of decisions during a typical workday. Some of them are good, and some of them are not so good. Identifying and mitigating the impact of poor decisions early can increase velocity and overall work quality.

The big picture

At Brainly, we’ve worked hard to define best practices and codify them in a complete developer ecosystem. This allows our teams to move fast while keeping churn low. By integrating this ecosystem into our developer tools and change management system, we can keep developers happy while ensuring quality decision-making at every step of the development process.

Well-defined practices

Even something as simple as a presentation component can require several decisions from a developer. For example, consider the trivial component below:

This component performs analytics tracking and navigation for a link. But even this component requires decisions about memoization, component-app communication, and state management. Not enforcing best practices when making these decisions can lead to the following:

  • The creation of technical debt
  • The wrong abstraction
  • Poor performance
  • Redundant implementations

At Brainly, we believe that best practices can’t just be taught, it needs to be codified in automation. Therefore, we've invested in building robust documentation, linters, and code generators. This creates the context in which our developers make design decisions.

A choice architect has the responsibility for organizing the context in which people make decisions. — Richard H. Thaler, Author of “Nudge: Improving Decisions About Health, Wealth, and Happiness”

Documenting Design Decisions

At the organizational level, we delegate developer experience (including frameworks and automation) to our infrastructure teams. The creation of these tools often requires many decisions and their corresponding justifications. For example: why do we use Recoil instead of React Context, or what is the benefit of not using the undefined in the codebase? This allows the developer to understand the chosen approach and why such a choice was made. This fosters trust through transparency. A good example is how ESLint presents the reasoning behind each rule.

On top of understanding, we promote participation and involvement from our engineers using Request For Comments (RFC).

Request for comments flow

Once an RFC is accepted and the resulting implementation is complete, we document the new framework features. While many companies use no-code tools like Confluence, we opted to keep it as close to code as possible. Using markdown files in the repository might not be enough, so we decided to use Nextra and Github Pages, primarily due to our developers' simplicity and ease of use.

Extending linters

Linters are one step ahead of just well-written documentation, mainly because the feedback loop for the developer is quick and automatic. They are, however, not designed for detecting high-level architectural flaws but rather issues contained in the single file scope.

Linters solve mostly low-level code issues.

ESLint is considered the industry standard tool. While ESLint is highly flexible and widely adopted, there are cases where it falls short:

  • Complex code checks between several files
  • Displaying lint result in GitHub Pull Request with linked examples in the documentation

We use Abstract Syntax Tree tools, like jscodeshift, to check if the committed code meets our standards. AST interprets the code into a set of hierarchical entities and allows for detecting specific declarations, functions, or dependencies between them in the code.

Code generators

Creating a new, style-compliant component using a quick CLI command is another step towards a clear and immediate feedback loop for our software engineers.

We use NX to manage our mono-repo at Brainly. I highly recommend reading Przemek’s article on how we leverage the power of code generators to improve the developer experience and code quality.

NX is a monorepo management tool packed with code generators utilities

Thanks for reading this article and watching the video.

Feel free to ask me questions in the comment section if you have any concerns!

--

--