What This Is and What This Isn’t
These values are not unbendable rules. They’re an attempt to share knowledge about how the application came to be and how we currently think it should be developed. It’s a non-exhaustive, living document of intentions and beliefs.We’ve chosen to focus exclusively on the engineering (i.e. how we write code) part in this document. There are other values surrounding visual design, product and project management, community etc that we’re not going to consider here.
Our Core Values
1. Types Are Good
We believe in strongly typed programming languages that help us avoid mistakes that are all too easy to make. When the compiler can’t help us we believe in augmenting with other kinds of static analysis. Type systems and static analysis helps us not only in the moment we’re writing code but also extends further out. By codifying our intentions we help prevent the next person from making a mistake.Examples
assertNever HelperOur
assertNever helper lets us leverage the type system to verify exhaustiveness and get compile-time errors when that assertion fails.Static Analysis RulesOur react-readonly-props-and-state static analysis ensures that we don’t accidentally mutate state which React prohibits being mutated but isn’t able to enforce due to the dynamic runtime.Custom Type DefinitionsWe write our own type definitions when none exist.2. Immutability Is Good
By choosing to keep as much of our state as possible in immutable data structures we can be explicit about when and where we update it and have confidence that it’s not going to change from underneath us. The last part is especially important in an application such as GitHub Desktop which has lots of state. The best way we’ve found so far to maintain our sanity is to be explicit about how that state flows through the app and when it’s updated, and immutability is one tool to help us stay on the right track.Examples
Read-only Arrays and ObjectsWe use read-only versions of arrays in interfaces and objects as well as in function parameters.Prefer const Over letWe prefer:Over:We prefer the first example because it states to ourselves and future readers that you can trust
a to not change. Not only does it make that intention clear, it enforces it. In the case of let, we’d have to scan the method to verify that it doesn’t get mutated, and even then we can’t be sure that some developer in the future adds logic which changes it.If the checks required to determine the result are too complicated, it might be time to create another function which does the heavy lifting and returns a value that you can assign to a
const.3. Passing Values to Functions Is Good
We believe that small, consistent, and composable methods are easier to understand and less prone to errors than larger methods operating on data from sources other than those passed to it via arguments. You might recognize this sentiment from the concept of pure functions in functional programming. While we aren’t using a language which lets us express such conditions, we believe in striving towards writing methods which act on values that is provided to it via arguments and returns a consistent result based solely on those values.If a method has to acquire data from multiple sources to then do some processing on it, we prefer that the gathering of data and the processing of it is separated into two methods such that the computational part doesn’t get entangled with acquisition of state.
Example
Extracting Pure FunctionsIn app-menu-bar we’ve extracted a method called
createState from the component to live outside of the class.This ensures that the only thing that matters to the outcome of that function is the props object that’s passed to it. By doing this we can avoid a very common example of using this.props inside of the method when, in fact, we might want to create a state object from nextProps or even prevProps that was given to us from one of the React lifecycle methods.Recommended Resources
These talks and articles have influenced our engineering values:- Lifting state up - React documentation on state management
- The Value of Values - Rich Hickey’s talk on immutability
- Simple Made Easy - Rich Hickey on simplicity vs easiness
- Boundaries aka Functional Core, Imperative Shell - Gary Bernhardt’s talk on architecture