diff --git a/guides/development/coding-guidelines.md b/guides/development/coding-guidelines.md index 362310f..e20b761 100644 --- a/guides/development/coding-guidelines.md +++ b/guides/development/coding-guidelines.md @@ -4,54 +4,54 @@ Writing code can be as personal as hand-writing but we like to keep everyone wit Focus on code readability. Code should tell a story. Code should be easy to understand and reason about by anyone. -* **1.** [Do's and Don'ts](#DosandDonts) - * **1.1** [Do's](#Dos) - * **1.1.1** [Keep code simple](#KeepCodeSimple) - * **1.1.2** [Naming is key](#Naming) - * **1.1.3** [Remove unused code](#UnusedCode) - * **1.1.4** [Write meaningful code comments](#CodeComments) - * **1.1.5** [Keep it small](#KeepItSmall) - * **1.2** [Don'ts](#Donts) - * **1.2.1** [Refactor ahead of time](#RefactorAheadOfTime) - * **1.2.2** [Premature optimization](#PrematureOptimization) - * **1.2.3** [Unnecessary dependencies](#UnnecessaryDependencies) - * **1.2.4** [Don't comment code to remove it, just delete it](#CommentCodeToRemove) - * **1.2.5** [Refactor and add features](#RefactorAndAddFeatures) - * **1.2.6** [Don't make typos](#DontMakeTypos) - * **1.2.7** [Avoid comments with TODOs](#AvoidTODOs) - -## 1. Do's and Don'ts - -### 1.1 Do's - -#### 1.1.1 Keep Code Simple +* **1.** [Do's and Don'ts](#1-dos-and-donts) + * **1.1** [Do's](#11-dos) + * **1.1.1** [Keep code simple](#111-keep-code-simple) + * **1.1.2** [Naming is key](#112-naming-is-key) + * **1.1.3** [Remove unused code](#113-remove-unused-code) + * **1.1.4** [Write meaningful code comments](#114-write-meaningful-code-comments) + * **1.1.5** [Keep it small](#115-keep-it-small) + * **1.2** [Don'ts](#12-donts) + * **1.2.1** [Refactor ahead of time](#121-dont-refactor-ahead-of-time) + * **1.2.2** [Premature optimization](#122-premature-optimization) + * **1.2.3** [Unnecessary dependencies](#123-unnecessary-dependencies) + * **1.2.4** [Don't comment code to remove it, just delete it](#124-dont-comment-code-to-remove-it-just-delete-it) + * **1.2.5** [Refactor and add features](#125-refactor-and-add-features) + * **1.2.6** [Don't make typos](#126-dont-make-typos) + * **1.2.7** [Avoid comments with TODOs](#127-avoid-comments-with-todos) + +## 1. Do's and Don'ts + +### 1.1 Do's + +#### 1.1.1 Keep Code Simple Code should be simple! Easy to understand. Variables and methods with good naming. Methods short, classes small. Code should be properly organized for this purpose. Sometimes we can think of some design patterns that could be applied or some (complex) abstractions but these can lead to over-engineering. Your code as a purpose, focus on that. Let the patterns, the abstractions, the complexity come to you instead of driving you. [Keep it simple, stupid](https://en.wikipedia.org/wiki/KISS_principle). -#### 1.1.2 Naming is key +#### 1.1.2 Naming is key Spend some time looking for good classes, methods and variables names. Make use of long and descriptive names for both functions/methods and variables. Never use 1 char variables! Remember you are writing code for others and for you, make it the best. Push to give the readers a good time. Naming is key! -#### 1.1.3 Remove unused code +#### 1.1.3 Remove unused code When we stop using a feature or part of it we should remove that code and any other unused code as a consequence. Remember, we don't want "dead" code around. It will give you a hard time later when you need to comprehend it again. -#### 1.1.4 Write meaningful code comments +#### 1.1.4 Write meaningful code comments Don't comment the WHAT about a piece of code, only the WHY, and if necessary. Comments should exist if you believe that the solution you've chosen might need extra context to be understood. Always focus on the WHY instead of the WHAT as this last one is already there, is our code. -#### 1.1.5 Keep it small +#### 1.1.5 Keep it small Less code the better, less code changes the better. As we like to build one thing at a time we should also built it as simple and focused as possible. Less code makes it better to understand, less code changes make it much more accessible for you and our colleagues as reviewers. -### 1.2 Don'ts +### 1.2 Don'ts -#### 1.2.1 Don't refactor ahead of time +#### 1.2.1 Don't refactor ahead of time Wait until something is painful to change or understand. Remember that we should keep it small and simple. Refactor without a purpose can lead to complexity, unnecessary abstractions and miscommunication about what you are trying to achieve. -#### 1.2.2 Premature optimization +#### 1.2.2 Premature optimization In general don't do premature optimization, but always keep in mind that there are some basic techniques that can have big impact. Avoid N+1 queries (take advantage of the logs during development for this). Filter using SQL as long as possible (but keep a balance to avoid over-complicating the code). There are problems that can be avoided at first but don't go to deep blindly if there isn't any reason to. -#### 1.2.3 Unnecessary dependencies +#### 1.2.3 Unnecessary dependencies Before adding a 3rd party library or a dependency think carefully if it's really necessary and the compromises you are making. We don't want to re-invent the wheel but sometimes it could be better to build what we need instead of depend on some library that do that and much more. When adding a new library to an application, make sure: @@ -59,16 +59,16 @@ When adding a new library to an application, make sure: * It's not unnecessarily big and does not introduce a lot of extra dependencies under the hood. * The license fits within the policy used in the application. Some projects only allow to have libraries using the MIT license, for example. Before adding a library with a more restrictive license, check with the team. -#### 1.2.4 Don't comment code to remove it, just delete it +#### 1.2.4 Don't comment code to remove it, just delete it We have git for god's sake. We can always check a previous commit to find the deleted code. -#### 1.2.5 Refactor and add features +#### 1.2.5 Refactor and add features Don't build new features and refactor at the same time unless that feature demands it. Focus on your current code and use code refactoring as a tool to achieve our goal. Refactor an unrelated part of the code that has nothing to do with that feature will not bring any value to you, to the reviewer and your codebase. -#### 1.2.6 Don't Make Typos +#### 1.2.6 Don't Make Typos Be careful with your typing. Writing classes/methods/variable names, code comments, literal string/page copies and documentation should be free of typos. Let your editor help you by installing a spell checker. Check [this plugin](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) if you are using Visual Studio Code. Remember, checking typos is part of code reviews. -#### 1.2.7 Avoid comments with TODOs +#### 1.2.7 Avoid comments with TODOs If there is something that you think it should be done create an issue for it. Maybe it will be done right after, or maybe some weeks after. Let that decision be where it belongs, in your project management tool. Your code is not the place to leave tasks descriptions or memos. diff --git a/guides/development/git-guidelines.md b/guides/development/git-guidelines.md index 0baa8ea..422a9c8 100644 --- a/guides/development/git-guidelines.md +++ b/guides/development/git-guidelines.md @@ -2,25 +2,25 @@ This is a guide covering how we expect to work with Git at MarsBased. Most of this guide is GitHub oriented but might be adapted to other Git tools like GitLab or Bitbucket. -- **1.** [Commit Message Guidelines](#commitmessageguidelines) -- **1.1** [Message Format](#messageformat) -- **1.1.1** [Message Header Type](#headertype) -- **1.1.2** [Message Header Scope](#headerscope) -- **1.1.3** [Message Samples](#commitmessagesamples) -- **2.** [Git Branches Naming](#gitbranchesnaming) -- **3.** [Git Workflow](#gitworkflow) -- **4.** [Dangerous behaviours](#dangerousbehaviours) +- **1.** [Commit Message Guidelines](#commit-message-guidelines) +- **1.1** [Message Format](#commit-message-format) +- **1.1.1** [Message Header Type](#type) +- **1.1.2** [Message Header Scope](#scope) +- **1.1.3** [Message Samples](#commit-message-samples) +- **2.** [Git Branches Naming](#git-branches-naming) +- **3.** [Git Workflow](#git-workflow) +- **4.** [Dangerous behaviours](#dangerous-behaviours) - **5.** [Credits](#credits) At MarsBased we work with a large variety of clients. Some clients may follow their own guidelines. You can always suggest improvements over their guidelines but there will be cases where it will not be possible to use ours. -## Commit Message Guidelines +## Commit Message Guidelines We have very precise rules on how git commit messages should be formatted. This leads to more readable messages that are easy to follow when reviewing the project history. We use **Linear** as our tracking tool. Whenever possible, commit messages should reference the related Linear issue. -### Commit Message Format +### Commit Message Format Each commit message consists of a header and an optional description. @@ -45,7 +45,7 @@ The maximum length of the header must be 72 characters. Any other line of the co The language used in commit messages is English. If the client needs access to the commit history for documentation purposes and does not understand English, other languages may be used instead. -### Type +### Type Choose the type that best fits the task: @@ -56,7 +56,7 @@ Choose the type that best fits the task: - **docs**: Documentation-only changes. - **test**: Adding or fixing tests. -### Scope +### Scope The scope describes the specific module or part of the application affected by the change. It is optional. @@ -66,7 +66,7 @@ Examples: - **users**: User management. - **payment**: Payment gateway. -### Commit Message Samples +### Commit Message Samples With a Linear issue: @@ -88,7 +88,7 @@ Without a Linear issue (`feat` is not allowed): fix: update Docker base image to v2.6 ``` -## Git Branches Naming +## Git Branches Naming Any branch created for a project must follow these rules. @@ -116,7 +116,7 @@ Examples: For client projects, adapt the naming to their requirements if needed. -## Git Workflow +## Git Workflow We use a simplified version of Gitflow. @@ -147,11 +147,11 @@ For small projects or small teams, we usually keep things simpler by working wit Even in this simplified setup, we still work with short-lived branches per feature or fix, open Pull Requests, and perform code reviews before merging into `main`. -## Dangerous behaviours +## Dangerous behaviours - Avoid using `git push -f` when working on a shared branch. Use `git push --force-with-lease` instead. -## Credits +## Credits This guide is heavily influenced by: diff --git a/guides/development/react-guidelines.md b/guides/development/react-guidelines.md index 10b05d7..653aa6c 100644 --- a/guides/development/react-guidelines.md +++ b/guides/development/react-guidelines.md @@ -3,37 +3,37 @@ Until now, we've used [create-react-app](https://reactjs.org/) to bootstrap React applications and we follow its conventions. -* 1. [Do's and Don'ts](#DosandDonts) - * 1.1. [Use typescript if possible](#Usetypescriptifpossible) - * 1.2. [Use a generator to bootstrap the project](#Useageneratortobootstraptheproject) - * 1.3. [Write functional components](#Writefunctionalcomponents) - * 1.4. [Use hooks for state management](#Usehooksforstatemanagement) - * 1.5. [Use a declarative API library](#UseadeclarativeAPIlibrary) - * 1.6. [Do use function declarations](#Dousefunctiondeclarations) - * 1.7. [Do name exports](#Donameexports) - * 1.8. [Do inline type props](#Doinlinetypeprops) -* 2. [General project organization and architecture](#Generalprojectorganizationandarchitecture) - * 2.1. [Project structure example](#Projectstructureexample) - * 2.2. [References (project structure)](#Referencesprojectstructure) -* 3. [Description of the most common patterns used to solve common problems](#Describemostcommonpatternsusedtosolvecommonproblems) - * 3.1. [State management](#Statemanagement) - * 3.1.1. [Local state management](#Localstatemanagement) - * 3.1.2. [Global state management](#Globalstatemanagement) - * 3.2. [External services](#Externalservices) - * 3.3. [GraphQL](#GraphQL) - * 3.4. [REST](#REST) - * 3.5. [Routing (only create-react-app)](#Routingonlycreate-react-app) - * 3.5.1. [Page vs component](#Pagevscomponent) - * 3.5.2. [Route definitions](#Routedefinitions) - * 3.5.3. [Router.tsx](#Router.tsx) - * 3.5.4. [Access route parameters using hooks](#Accessrouteparametersusinghooks) - * 3.6. [Testing](#Testing) -* 4. [Libraries](#Libraries) - * 4.1. [Recommended libraries](#Recommendedlibraries) - * 4.2. [Other libraries we have used](#Otherlibrarieswehaveused) - * 4.3. [Libraries worth taking a look into](#Librarieswhichmayworthtakealookinto) - * 4.4. [References (libraries)](#Referenceslibraries) -* 5. [ Learning resources](#Learningresources) +* 1. [Do's and Don'ts](#1-dos-and-donts) + * 1.1. [Use typescript if possible](#11-use-typescript-if-possible) + * 1.2. [Use a generator to bootstrap the project](#12-use-a-generator-to-bootstrap-the-project) + * 1.3. [Write functional components](#13-write-functional-components) + * 1.4. [Use hooks for state management](#14-use-hooks-for-state-management) + * 1.5. [Use a declarative API library](#15-use-a-declarative-api-library) + * 1.6. [Do use function declarations](#16-do-use-function-declarations) + * 1.7. [Do name exports](#17-do-name-exports) + * 1.8. [Do inline type props](#18-do-inline-type-props) +* 2. [General project organization and architecture](#2-general-project-organization-and-architecture) + * 2.1. [Project structure example](#21-project-structure-example) + * 2.2. [References (project structure)](#22-references-project-structure) +* 3. [Description of the most common patterns used to solve common problems](#3-description-of-the-most-common-patterns-used-to-solve-common-problems) + * 3.1. [State management](#31-state-management) + * 3.1.1. [Local state management](#311-local-state-management) + * 3.1.2. [Global state management](#312-global-state-management) + * 3.2. [External services](#32-external-services) + * 3.3. [GraphQL](#33-graphql) + * 3.4. [REST](#34-rest) + * 3.5. [Routing (only create-react-app)](#35-routing-only-create-react-app) + * 3.5.1. [Page vs component](#351-page-vs-component) + * 3.5.2. [Route definitions](#352-route-definitions) + * 3.5.3. [Router.tsx](#353-routertsx) + * 3.5.4. [Access route parameters using hooks](#354-access-route-parameters-using-hooks) + * 3.6. [Testing](#36-testing) +* 4. [Libraries](#4-libraries) + * 4.1. [Recommended libraries](#41-recommended-libraries) + * 4.2. [Other libraries we have used](#42-other-libraries-we-have-used) + * 4.3. [Libraries worth taking a look into](#43-libraries-worth-taking-a-look-into) + * 4.4. [References (libraries)](#44-references-libraries) +* 5. [Learning resources](#5-learning-resources) -## 1. Do's and Don'ts +## 1. Do's and Don'ts -### 1.1. Use typescript if possible +### 1.1. Use typescript if possible -### 1.2. Use a generator to bootstrap the project +### 1.2. Use a generator to bootstrap the project A project generator saves a lot of boilerplate work and provides common conventions. @@ -53,11 +53,11 @@ We've used [create react app](https://create-react-app.dev/) for all our project We will consider using another system (mostly [next.js](https://nextjs.org/)) for newer projects, especially if they have important SEO requirements. -### 1.3. Write functional components +### 1.3. Write functional components Class components will be deprecated. For new components always use functions. -### 1.4. Use hooks for state management +### 1.4. Use hooks for state management - In general, prefer React's hooks for local stage management - Use a library (with hooks) for global state management @@ -65,7 +65,7 @@ Class components will be deprecated. For new components always use functions. See patterns (below) for examples and usages. -### 1.5. Use a declarative API library +### 1.5. Use a declarative API library It reduces boilerplate code a lot. @@ -74,7 +74,7 @@ We currently use: - REST: [react-query](https://github.com/tannerlinsley/react-query) - GraphQL: [apollo-client](https://github.com/apollographql/apollo-client) -### 1.6. Do use function declarations +### 1.6. Do use function declarations For a better readability. @@ -96,7 +96,7 @@ function App() { } ``` -### 1.7. Do name exports +### 1.7. Do name exports It allows to export multiple values and it encourages the use of the same naming. @@ -106,7 +106,7 @@ export function LoginPage() { } ``` -### 1.8. Do inline type props +### 1.8. Do inline type props It reduces the external dependencies of the function and therefore is more easy to move or change it without errors. @@ -117,7 +117,7 @@ export function LoginForm({user = ''}: {user: string}) { } ``` -## 2. General project organization and architecture +## 2. General project organization and architecture We follow https://create-react-app.dev/docs/folder-structure/ @@ -134,7 +134,7 @@ For small to medium projects this is recommended: - One folder for locales: `locales/` - The rest: utility functions, helpers, etc... under `lib/` (keep it clean, please) -### 2.1. Project structure example +### 2.1. Project structure example ``` src/ @@ -180,34 +180,34 @@ src/ If using a repo for both api and client, put the above inside `client/` folder -### 2.2. References (project structure) +### 2.2. References (project structure) - Route definitions idea taken from [Redwood](https://github.com/redwoodjs/redwood) framework -## 3. Description of the most common patterns used to solve common problems +## 3. Description of the most common patterns used to solve common problems -### 3.1. State management +### 3.1. State management - In general, prefer hooks over any other solution - You-don-t-need-redux. But if so, use hooks interface -#### 3.1.1. Local state management +#### 3.1.1. Local state management React hooks are enough most of the time. -#### 3.1.2. Global state management +#### 3.1.2. Global state management Prefer [zustand](https://github.com/pmndrs/zustand) over React contexts or redux. See zustand documentation. -### 3.2. External services +### 3.2. External services - Create a clean interface for each service. For example: `src/api/index.ts` (functions to send http requests to a REST API) or `src/graphql/index.ts` (queries and mutations of a GraphQL endpoint) - Create a file with the types (models): `/types.ts` - Use declarative data fetching: prefer `useQuery` over `fetch` (available both in Apollo client and react-query) -### 3.3. GraphQL +### 3.3. GraphQL We currently use [apollo-client](https://www.apollographql.com/docs/react/) @@ -215,14 +215,14 @@ Try to generate types and code as much as possible. In general, keep all graphql related code inside `graphql/` folder. -### 3.4. REST +### 3.4. REST - A single `src/api/index.ts` exports all possible API interactions - Use `src/api/types.ts` to declare API entity type definitions - Client specific functionality inside `src/api/client.ts` (like, for example) - If Auth and API are different services, is common to have two folders (`src/auth` and `src/api`) and the API depends on authorization (JWT tokens, for example). If auth and API are in the same service, the `src/auth` folder can be omitted. -### 3.5. Routing (only create-react-app) +### 3.5. Routing (only create-react-app) Custom routing is only required with create react app (next.js has its own routing standards and patterns). @@ -230,7 +230,7 @@ Custom routing is only required with create react app (next.js has its own routi - Create a route definitions file `src/routes.ts` with all route paths - It helps to mimic the actual routes in the `/pages` folder -#### 3.5.1. Page vs component +#### 3.5.1. Page vs component A Page is a component that: @@ -238,7 +238,7 @@ A Page is a component that: - Can access route parameters (like in: `/post/:id`) - Lives inside `src/pages/` folder (can be nested to reflect actual url structure) -#### 3.5.2. Route definitions +#### 3.5.2. Route definitions It's a file to generate route paths. Advantages: @@ -264,7 +264,7 @@ import routes from "./routes"; Users; ``` -#### 3.5.3. Router.tsx +#### 3.5.3. Router.tsx Use the `routes` definitions to create the routes placeholders: @@ -284,7 +284,7 @@ Use the `routes` definitions to create the routes placeholders: ``` -#### 3.5.4. Access route parameters using hooks +#### 3.5.4. Access route parameters using hooks For a route like `/posts/:postId/comments/:commentId` we use the following code to access route params: @@ -293,7 +293,7 @@ For a route like `/posts/:postId/comments/:commentId` we use the following code const { pageId, commentId } = useParams>(); ``` -### 3.6. Testing +### 3.6. Testing Follow React guidelines: https://reactjs.org/docs/testing.html @@ -303,9 +303,9 @@ Follow React guidelines: https://reactjs.org/docs/testing.html When we write tests, we use [Cypress](https://cypress.io) -## 4. Libraries +## 4. Libraries -### 4.1. Recommended libraries +### 4.1. Recommended libraries - Internationalization: [react-intl](https://www.npmjs.com/package/react-intl) - Forms: [react-hook-form](https://react-hook-form.com/) @@ -315,7 +315,7 @@ When we write tests, we use [Cypress](https://cypress.io) - GraphQL API: [apollo-client](https://www.apollographql.com/docs/react/) - Routing: [react-router-dom](https://reacttraining.com/react-router/web/guides/quick-start) -### 4.2. Other libraries we have used +### 4.2. Other libraries we have used - Styling - [tailwindcss](https://tailwindcss.com/) @@ -328,7 +328,7 @@ When we write tests, we use [Cypress](https://cypress.io) - Hooks: - [react-use](https://github.com/streamich/react-use) -### 4.3. Libraries worth taking a look into +### 4.3. Libraries worth taking a look into - State management @@ -338,11 +338,11 @@ When we write tests, we use [Cypress](https://cypress.io) - Component library - [Chakra UI](https://chakra-ui.com/) -### 4.4. References (libraries) +### 4.4. References (libraries) - Blog: [Internationalize React apps done right](https://medium.com/ableneo/internationalize-react-apps-done-right-using-react-intl-library-82978dbe175e) -## 5. Learning resources +## 5. Learning resources - React docs are quite good. Recommended reading: https://reactjs.org/docs/hello-world.html - egghead.io is one of our favourite places to learn and Kent C. Dodds is a master, so this can't fail: https://egghezad.io/courses/the-beginner-s-guide-to-reactjs diff --git a/guides/development/ruby-guidelines.md b/guides/development/ruby-guidelines.md index 7d7e876..e153d12 100644 --- a/guides/development/ruby-guidelines.md +++ b/guides/development/ruby-guidelines.md @@ -2,39 +2,39 @@ We follow the `Rubocop` official [Rubocop Ruby coding style guide](https://github.com/rubocop/ruby-style-guide) as the primary source of best practices and conventions. -- 1. [Do's and Don'ts](#DosandDonts) - - 1.1. [Environment Variables](#Environmentvars) - - 1.2. [Loading in batches](#Batchloading) - - 1.3. [Avoid Active Record callbacks with side effects](#Modelcallbacks) - - 1.4. [Avoid raw SQL queries](#Manualqueries) - - 1.5. [Size instead of count](#SizeCount) - - 1.6. [Avoid N+1 Queries with includes](#UseIncludes) - - 1.7. [Avoid Default Scope](#AvoidDefaultScope) - - 1.8. [Use find_by for instead where().first](#FindByInsteadWhere) - - 1.9. [Check constraints](#CheckConstraints) - - 1.10. [Filter sensitive parameters in logs](#FilterSensitiveParameters) -- 2. [General project organization and architecture](#Generalprojectorganizationandarchitecture) - - 2.1. [Project structure example](#Projectstructureexample) -- 3. [Common Patterns](#CommonPatterns) - - 3.1. [Devise (Authentication)](#DeviseIntegration) - - 3.2. [Testing](#Testing) - - 3.2.1 [Testing best practices](#TestingBestPractices) - - 3.2.1.1 [Use Let](#UseLet) - - 3.2.1.2 [Use Factories](#UseFactories) - - 3.2.1.3 [Describe Methods](#DescribeMethods) -- 4. [Gems](#Gems) - -## 1. Do's and Don'ts +- 1. [Do's and Don'ts](#1-dos-and-donts) + - 1.1. [Environment Variables](#11-use-dotenv-for-environment-variables) + - 1.2. [Loading in batches](#12-loading-in-batches) + - 1.3. [Avoid Active Record callbacks with side effects](#13-avoid-active-record-callbacks-with-side-effects) + - 1.4. [Avoid raw SQL queries](#14-avoid-raw-sql-queries) + - 1.5. [Size instead of count](#15-size-instead-of-count) + - 1.6. [Avoid N+1 Queries with includes](#16-avoid-n1-queries-with-includes) + - 1.7. [Avoid Default Scope](#17-avoid-default-scope) + - 1.8. [Use find_by for instead where().first](#18-use-findby-for-instead-wherefirst) + - 1.9. [Check constraints](#19-check-database-constraints) + - 1.10. [Filter sensitive parameters in logs](#110-filter-sensitive-parameters-in-logs) +- 2. [General project organization and architecture](#2-general-project-organization-and-architecture) + - 2.1. [Project structure example](#21-project-structure-example) +- 3. [Common Patterns](#3-common-patterns) + - 3.1. [Devise (Authentication)](#31-devise-authentication) + - 3.2. [Testing](#32-testing) + - 3.2.1 [Testing best practices](#321-testing-best-practices) + - 3.2.1.1 [Use Let](#3211-use-let) + - 3.2.1.2 [Use Factories](#3212-use-factories) + - 3.2.1.3 [Describe Methods](#3213-describe-methods) +- 4. [Gems](#4-gems) + +## 1. Do's and Don'ts Add and follow the official [MarsBased Rubocop configuration](https://github.com/MarsBased/marstyle/blob/master/ruby/.rubocop.yml), where most of rules are already defined, highlighting these two: - Use single quotes when possible. - Max length of 90 characters -### 1.1. Use Dotenv for environment variables +### 1.1. Use Dotenv for environment variables We use the [Dotenv](https://github.com/bkeepers/dotenv) gem for managing the environment variables. -### 1.2. Loading in batches +### 1.2. Loading in batches Don't iterate unlimited / big queries directly. Use find in batches for loading big queries: @@ -50,7 +50,7 @@ Car.find_each do |car| end ``` -### 1.3. Avoid Active Record callbacks with side effects +### 1.3. Avoid Active Record callbacks with side effects Avoid using Active Record callbacks unless it's related to data persistence specially avoiding side effects like sending and e-email. @@ -65,7 +65,7 @@ def notify_user end ``` -### 1.4. Avoid raw SQL queries +### 1.4. Avoid raw SQL queries Avoid writing raw SQL queries unless strictly necessary. @@ -95,7 +95,7 @@ User.where('dtCreationDate < ?', DateTime.current) # Needs to use column name in User.where(User.arel_table[:created_at].lt(DateTime.current)) # Can use aliased name ``` -### 1.5. Size instead of count +### 1.5. Size instead of count Use `size` instead of `count` unless you are doing a direct count on a table. Using `count` always triggers a query while using `size` is able to use the cached values of a previous query. @@ -110,7 +110,7 @@ Post.published.size Post.count # Counting directly on the model class ``` -### 1.6. Avoid N+1 Queries with includes +### 1.6. Avoid N+1 Queries with includes When you have to access an association, avoid N+1 query problems, you can use `includes` to eager load the associated records: ```ruby @@ -131,7 +131,7 @@ end You can find some more examples in the [Active Record guide](/guides/development/activerecord-guide.md). -### 1.7. Avoid Default Scope +### 1.7. Avoid Default Scope In order to avoid unexpected and hidden behaviour, avoid using default_scope and use named scopes and explicit uses of those scopes: ```ruby @@ -146,7 +146,7 @@ class User < ActiveRecord::Base end ``` -### 1.8. Use find_by for instead where().first +### 1.8. Use find_by for instead where().first When retrieving a single record from the database, don’t use `where(...).first`, use `find_by` instead. And similarly when selecting a single item from a collection use `find { ... }` instead of `select { ... }.first`. ```ruby @@ -157,17 +157,17 @@ User.where(active: true).first User.find_by(active: true) ``` -### 1.9. Check database constraints +### 1.9. Check database constraints Check that constraints are correct and that they match the validations. A typical example is adding a default without a not-null constraint. -### 1.10. Filter sensitive parameters in logs +### 1.10. Filter sensitive parameters in logs When receiving parameters in a controller that contain sensitive information like a password or secret key, add the name of the parameter to the list of filtered parameters. Note that `:password` is already filtered by default. ```ruby Rails.application.config.filter_parameters += [:api_key, :secret] ``` -## 2. General project organization and architecture +## 2. General project organization and architecture Follow the standard generated directory structure at project initialization with `rails new project_name` as described in [Ruby On Rails Guide](https://guides.rubyonrails.org/getting_started.html). @@ -178,7 +178,7 @@ Additionally: - Query objects under the `/app/queries` directory. - Form objects under the `/app/form_objects` directory. -### 2.1. Project structure example +### 2.1. Project structure example ``` app/ |- assets/ @@ -218,14 +218,14 @@ tmp/ vendor/ ``` -## 3. Common Patterns +## 3. Common Patterns - [Presenter](https://github.com/MarsBased/handbook/guides/patterns/rails/presenter.md) - [Command](https://github.com/MarsBased/handbook/guides/patterns/rails/command.md) - [Form Composition](https://github.com/MarsBased/handbook/guides/patterns/rails/form-composition.md) - [Query Object](https://github.com/MarsBased/handbook/guides/patterns/rails/query-object.md) -### 3.1. Devise (Authentication) +### 3.1. Devise (Authentication) Skip all the default routes generated by devise on `routes.rb` and create custom controllers and views according to the requirements. #### `routes.rb` @@ -285,7 +285,7 @@ end ``` -### 3.2. Testing +### 3.2. Testing We use the [Rspec](https://github.com/rspec/rspec) testing framework and usually we write these kind of tests: * Unit tests for models, commands, jobs. @@ -293,8 +293,8 @@ We use the [Rspec](https://github.com/rspec/rspec) testing framework and usually * Request specs for APIs. * Avoid controller tests: controllers functionality is already covered by integration specs. -### 3.2.1. Testing Best Practices -#### 3.2.1.1 Use let +### 3.2.1. Testing Best Practices +#### 3.2.1.1 Use let When you have to assign a variable to test, instead of using a before each block, use let. It is memoized when used multiple times in one example, but not across examples. @@ -308,7 +308,7 @@ describe User do end ``` -#### 3.2.1.2 Use factories +#### 3.2.1.2 Use factories Use [factory_bot](https://github.com/thoughtbot/factory_bot) to reduce the verbosity when working with models. ##### `spec/factories/user.rb` @@ -326,7 +326,7 @@ end user = FactoryBot.create(:user, name: 'John Rambo') # The rest of attributes are already set ``` -#### 3.2.1.3 Describe Methods +#### 3.2.1.3 Describe Methods When testing a method, create a describe block with the name of the method and place the specs inside. Use "." as prefix for class methods and "#" as prefix for instance methods. ```ruby @@ -341,7 +341,7 @@ describe "#generate_export" do end ``` -## 4. Gems +## 4. Gems * General * [Keynote](https://github.com/rf-/keynote) for presenters. * [Simple form](https://github.com/heartcombo/simple_form) for form generation. diff --git a/sections/development/cycles.md b/sections/development/cycles.md index 514e81a..06ddaa1 100644 --- a/sections/development/cycles.md +++ b/sections/development/cycles.md @@ -6,15 +6,15 @@ Linear is an incredible task management tool for development teams, but we use i In this section of the Handbook, we describe a few Linear concepts that every Martian ought to know. -1. [Triage](#triage) -2. [Backlog](#backlog) -3. [Cycles](#cycles) -4. [Projects](#projects) -5. [Statuses](#statuses) -6. [Fields](#fields) -7. [Other tips](#tips) +1. [Triage](#1-triage) +2. [Backlog](#2-backlog) +3. [Cycles](#3-cycles) +4. [Projects](#4-projects) +5. [Statuses](#5-statuses-columns-of-the-board) +6. [Fields](#6-fields) +7. [Other tips](#7-other-tips-and-best-practices) -## 1. Triage +## 1. Triage New tasks are typically created in the Triage section. It's like a list of things that we still haven't decided that we want to develop. Some tasks will be approved and moved to the backlog while others won't. @@ -35,17 +35,17 @@ If it's a bug, make sure to include the following information: - Screenshots or a video showing the problem, if it's meaningful. - URLs (staging / production / Sentry / other monitoring platforms), if present. -## 2. Backlog +## 2. Backlog The Backlog is our list of pending work, sorted by priority (urgent, high, medium, low). Tasks approved in the Triage section go here. -## 3. Cycles +## 3. Cycles Cycles are like development sprints but with a different name. We work in three-week sprints (or cycles πŸ˜…). The active cycle is where the development takes place. We typically plan the next development cycle right before finishing the previous one. Project managers and tech leads decide what's included according to the client's needs and the project priorities (we always try to mix technical improvements and maintenance tasks with new features). When it comes to cycle planning, we always leave room for new urgent tasks or unforeseen situations by leaving 15-20% of our capacity unplanned. -## 4. Projects +## 4. Projects We use Linear projects in a slightly different way than it might seem. @@ -55,7 +55,7 @@ In a few projects that are already in production, we use Linear projects to grou In other ones, where we can effectively apply a continuous delivery approach, we don't use Linear projects at all. So, as you can see, it depends a lot on each project πŸ€·πŸ»β€β™‚οΈ -## 5. Statuses (columns of the board) +## 5. Statuses (columns of the board) - **To Do:** Tasks assigned to the active cycle go here. We sort them by priority. - **Blocked:** If something is blocked, it goes into this column. @@ -67,7 +67,7 @@ In other ones, where we can effectively apply a continuous delivery approach, we - **Done:** When a task gets the final OK, it is moved to Done. - **Canceled:** Tasks that have been canceled because they are duplicated or no longer needed. -## 6. Fields +## 6. Fields Here's a short description of the fields that we use when we create a new issue: @@ -80,7 +80,7 @@ Here's a short description of the fields that we use when we create a new issue: - **Child issues:** You can create child issues inside other issues. Use it when a task is too big or has multiple steps. - **Comments:** Use comments as much as you like to update the rest of the team about a task, ask questions or answer your teammates. Linear is our source of truth so keeping it up to date with comments is very important. -## 7. Other tips and best practices +## 7. Other tips and best practices - We prefer working asynchronously. Please use the task comments to communicate if it's not urgent. - Keeping Linear organised is everyone's job, not just the tech lead's or the project manager's. diff --git a/sections/development/working-principles.md b/sections/development/working-principles.md index 91f497b..43313ea 100644 --- a/sections/development/working-principles.md +++ b/sections/development/working-principles.md @@ -1,14 +1,14 @@ # Working principles -1. [Speak like a Martian](#SpeaklikeaMartian) -2. [No Martian left behind](#NoMartianleftbehind) -3. [Let your code history speak for itself](#Letyourcodehistoryspeakforitself) -4. [Measure twice, cut once!](#Measuretwicecutonce) -5. [Who watches the watchmen?](#Whowatchesthewatchmen) +1. [Speak like a Martian](#1-speak-like-a-martian) +2. [No Martian left behind](#2-no-martian-left-behind) +3. [Let your code history speak for itself](#3-let-your-code-history-speak-for-itself) +4. [Measure twice, cut once!](#4-measure-twice-cut-once) +5. [Who watches the watchmen?](#5-who-watches-the-watchmen) Those are our principles, and if you don't like them... well, you know how that goes. -## 1. Speak like a Martian +## 1. Speak like a Martian Be communicative with your team. We're far from each other, so any information you can provide about you and your work is welcome. @@ -18,7 +18,7 @@ Use the #status Slack channel and / or Slack built-in status messages to inform Update the status of the task you are working on frequently on Linear. Use comments in the project management tool to keep everybody in the loop. Use Slack instead if you need a more direct status report. -## 2. No Martian left behind +## 2. No Martian left behind Software development is hard and no matter how expert you are. You may have doubts. Your team is here to support you. @@ -30,7 +30,7 @@ As a general rule, it's better to sort things early on before is too late, so th MarsBased encourages async communication and we all understand that someone might not be able to reply immediately; but by raising the flag it will be easier for everybody to organise the work and help you (sync or async). -## 3. Let your code history speak for itself +## 3. Let your code history speak for itself Git is a great tool to document the coding process. Take care of it. @@ -42,7 +42,7 @@ Git is a great tool to document the coding process. Take care of it. - Explain how to test if it requires some setup. - If you made additional changes, like a refactor or some other change needed, please explain it. -## 4. Measure twice, cut once! +## 4. Measure twice, cut once! Take some time to read all the documentation available (ticket description and comments) before starting any task. @@ -52,7 +52,7 @@ While you are working on the ticket, re-read its description to make sure no det Also, take a final look at the description when you are done with the implementation to double-check that the code is doing exactly what is expected. -## 5. Who watches the watchmen? +## 5. Who watches the watchmen? Any change can lead to new bugs. Do not think a change won't break everything or anything.