Company Standards
Hey there! You're probably reading this because you've been invited to take one of our code challenges or are working at Duro. Welcome!
To potential candidates: Please follow this criteria closely as adherence to
these rules will be used in determining role eligibility.
Code quality is very important to us, and we hope it is to you too. In this guide we'll share our engineering process that we use to ensure that we can build quickly while keeping our projects stable and maintainable.
Please use the links below to view all of Duro's Engineering and Communication Standards:
Some developers feel the need to debate code style. Other engineers will use the project's style and get stuff done. We prefer engineers who get stuff done. Consistency is important, please follow these guidelines.
We use the Airbnb Style in our code. This is the style used by React, Honey, ZocDoc, Zillow, Shutterfly, REI, Airbnb, and many others. Be sure to use an automatic formatter like eslint-config-airbnb for the IDE of your choice.
Line length should be limited to 80 characters.
Code Principles
- Code should be as simple, explicit, and as easy to understand as possible.
- Functional style is preferred to OOP. When possible functions should be pure and not rely on shared state or side effects.
Modules
- Always use modules (
import/export) over a non-standard module system. You can always transpile to your preferred module system. - Do not use wildcard imports.
Do not export directly from an import.
Put all imports above non-import statements. eslint: import/first
- Multiline imports should be indented just like multiline array and object literals. eslint: object-curly-newline
Ordering
Modules must use this order so that they can be understood quickly when skimmed:
- External dependencies: anything listed in
package.json, e.g.require('http') - Internal dependencies: any files created in the project
itself, e.g.
require('./api') - Constants and other setup: this includes anything absolutely
necessary to be defined before
module.exports - Exports:
module.exportsshould be as close to the beginning of the file as possible. The module should export either a single function or a "catalog object", e.g.module.exports = { method1, method2, ... } - Functions: these go after the above sections. Use function hoisting to control the placement of your functions so that important, high-level functions are above smaller more-general utility functions.
- External dependencies: anything listed in
Naming Conventions
- Use
camelCasewhen naming objects, functions, and instances. eslint: camelcase - Use descriptive variable names. Function names should be a verb
like
route()or verb combined with a noun likerouteRequest().- Avoid single letter names. Be descriptive with your naming. eslint: id-length
- Use
PascalCaseonly when naming constructors or classes. eslint: new-cap
Functions
- Use named function expressions instead of function declarations. eslint: func-style
- Wrap immediately invoked function expressions in parentheses. eslint: wrap-iife
- Keep your functions short. If your function is over 40 lines, you should have a good reason.
- Functions should not accept more than 3 arguments. Use a single options object if you need more arguments.
- Keep nesting to a minimum. Use early returns, single-line conditionals, and function calls.
Code Review
All PRs must be reviewed by a teammate before they are eligable to
be merged into the master branch. Large PRs are difficult to
review. Be sure to break large PRs into smaller ones so that they
can be reviewed quickly and deployed to production.
- Never commit passwords, access tokens, or other credentials into version control. If you think you absolutely have to, ask first. If you do this by accident, tell your manager immediately.
- Each commit should be as small and as simple as possible.
- The project must be operational and have all tests passing after every commit.
- Use Conventional Commits
- Valid types are
chore:,docs:,style:,refactor:,perf:, andtest:
- Valid types are
- Do not mix feature changes (added functionality) with fixes (restored functionality), refactors (no change in functionality), or style changes (only whitespace or other cosmetic changes).
- Before a PR is ready for review, make sure that it is a single commit. If the combined commit is too large or disparate, consider multiple PRs.
- The exception to the above single commit rule is when a PR introduces new packages. Create one extra commit in the same PR for each new package your PR needs.
- Do not modify a project's
.gitignoreto add files related to your editor or environment. Use your own global .gitignore for that instead. - Be sure that your PRs have descriptive titles that explain what has been changed. Typically the commit message is sufficient. "Fixes #66" is not.
- When submitting a PR with UI or visual changes, please add before and after screenshots to the PR. This makes it easy for the reviewer to quickly see what has been done.
Workflow
Company Workflow: Documentation GitHub Workflow: Documentation JIRA/Git Workflow: Documentation
Slack Communication
Since we work in an environment that produces primarily text communication, it is essential to understand how to properly utilize communication through text.
No Private Messages on Slack
When an engineer is nose down on a ticket, they can often times neglect important things like answering a teammate's request for help. This results in engineers privately messaging each other to get the help they need. As this activity increases, the public conversations start to disappear.
The behavior of messaging each other privately is a symptom of a team that is not working together efficiently. Lack of team work affects the overall success of the team, therefore the practice of private messaging is forbidden. Since we do not have the ability to turn this feature off in Slack, we have to constantly remind the team the effect that privately messaging each other has on the overall effectiveness of the team. Any mention of a private message needs to be reprimanded with a reminder as to why we do not appreciate private messages. When an engineer remarks about talking with a teammate, asking them where that conversation took place so that you can review it is another way to probe for this undesirable behavior.
The benefit of public conversation is that anyone can contribute to the conversation. If two engineers are discussing a topic and are unable to come to a solution, a public conversation allows them to quickly include someone else. That engineer can read the previous conversation and get up to speed quickly. Public conversations can also serve as documentation. Someone searching for a term related to that conversation may find that it helps them to understand the problem they are currently facing.
Filler Communication
We are social creatures, so it makes sense that we want to make sure that there is someone to talk to before we send a post out into the oid of a channel.
ex. "Hey, has anyone encountered problem X?"
This may seem like a rather miscellaneous question, and you'd be right. What exactly is wrong with miscellaneous questions? Answer: They waste time and space.
With miscellaneous questions, you can expect the conversation to flow like this:
[12:01] Dev 1: "Hey, has anyone encountered problem X?"
[12:03] Dev 2: "Oh yeah, that's a doozy."
[12:03] Dev 1: "How did you figure it out?"
[12:06] Dev 2: "I did fix=XYZ."
[12:08] Dev 1: "I've already tried that, didn't work."
[12:12] Dev 2: "Link me your PR"
[12:17] Dev 1: "Done"
[12:24] Dev 2: "Oh wait, your PR is for repo ABC! That's why my solution didn't work. Try fix = ABC"
[12:30] Dev 1: "You're right! That did the trick, thanks!"
That's 9 posts in a channel if they don't use threads, and over 30 minutes to solve an issue that had a quick fix.
Let's see what the conversation might look like if we cut out miscellaneous questions and instead used concise, well-thought out communication:
[12:01] Dev 1: "Hey @dev2, @dev3: I'm working on LinkToPR in Repo ABC, I've tried fix=XYZ, FIX=X. Am I approaching this the wrong way?
[12:02] Dev 3: "Did that last night, use fix=ABC"
[12:03] Dev 2: "Agree with @Dev 3. Fix=ABC is the solution."
[12:05] Dev 1: "Fix=ABC worked! Thanks!"
That took up 4 lines of code and lasted 5 minutes. Effective communication builds the team and helps the engineer learn how to communicate better.
Articles
- Hidden Documentation
- Optimism
- Law of Triviality
- Why do most top performers have the highest count of commits and pull requests?
- Choose Boring Technology
- Answer Questions Well
- Rob Pike's 5 Rules of Programming
- It's time to start writing
- The Wrong Abstraction
- The Two Pillars of JavaScript
- Why does writing matter in remote work?
- 3 steps to add tests on existing code when you have short deadlines
- Goodbye, Clean Code
- Idempotence Now Prevents Pain Later
- Why This Opportunity Solution Tree is Changing the Way Product Teams Work
- Hold Off On Proposing Solutions
Stand-ups
We utilize a service called Standuply.
Standuply is a program that runs text-formatted stand-up meetings in Slack. It helps our distributed teams organize and run stand-ups no matter the distance, and posts the results to the specified Slack channel.
There are two Standuply Reports. The first takes form as a weekly stand-up where your group gathers your weekly goals and inputs them into the report.
The second is a daily standup that is filled out individually by you every day.
Examples of both are available to view.
Filling out Stand-ups
These reports provide critical information and updates from engineers that helps better improve engineering's context for overall work and progress throughout the organization. Therefore, it is of utmost importance the answers received from both both standups are as clear and precise as possible.
Daily Standup Questions 1 & 2:
How many PRs have you approved since the last standup?
How many PRs have you rejected since the last standup?
PR Aprovals & Rejections
Engineers should actively approve and reject PRs throughout the week. If they have not approved or rejected PRs, they should note as to why on their daily Standuply Report. This explanation should be added to the daily standup's 5th question by selecting "No" and adding their reason there.
Daily Standup Questions 4 & 5:
Keeping the above in mind, what do you plan to accomplish before the next standup? Do not include reviewing PRs as part of your answer.
Look at your plan from the previous standup. Did you successfully complete it?
Specific and Measurable Responses
When responding to the questions from Standuply it is imperative to be descriptive and avoid vague statements. The response needs to be a measurable, durable change to the repository. Thinking and planning is acceptable as long as there is actual verifiable output.
For example:
What do you plan to accomplish before the next Standup?
“I wrote up a doc researching and comparing the different ways to fix
<issue>and it is available in a PR/issue/slack post”"By EOD, the
<component>will change to teal when :hover is triggered."
are the correct responses, not:
What do you plan to accomplish before the next Standup?
“I thought a lot about how to fix
<issue>”"Will work on
<component>."
Weekly Check-Ins
We use the Check-in meetings to see how engaged our engineers are.
If an engineer comes to a Check-in every week without much to discuss, we become concerned that they are not as engaged as we would like. The Check-in’s function as your opportunity to speak with your manager about anything that is important to you. This can be about your work or questions pertaining to personal development.
Your manager will also use Check-in’s as an opportunity to provide you with feedback. They are here to help guide you with your work at Duro, and they are also interested in your overall progress as an engineer.
Every day when you sit down and do work here at Duro, think about the challenges you face. Think about what you would like to see change, or what you could be doing to make things change.
In the end, the Weekly Check-in’s are only going to be as good as you can make it. You have to bring your own contributions because ultimately they are all about you.