Skip to content

pixel-point/development-guidelines

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

25 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Development Guidelines

Table of Content

Before you begin

  • Before starting to work on the project, please check out the project's SASS variables and mixins, dependencies, and shared components.

  • Before starting to work on a specific section, please try to find a similar section that has already been built and make sure that your code looks and works as similar as the code of this section.

  • Before picking a 3rd party, make sure you are familiar with the our list 3rd parties of choice which contains best picks for a certain use cases

  • Before requesting a review, please double-check that everything works fine, the code is in good quality and everything from this page is completed.

Working with Git and Github

Git basics

If you don't feel confident using Git yet, you should spend some time exploring Github's learning center. There you can find more that enough resources to expand your Git knowledge

Git commands cheat sheet

There are tons of Git cheat sheets out there in the web, but in case you still don't have a favourite one, you might want to try this, which covers just about all things you really need to know in order to start working effectively from the day one.

Git workflow

Git workflow is a kind of an instruction for how to use Git to accomplish work in a consistent and productive manner. It contains recommendations on introducing changes, solving conflicts, using branches, and more.

Though there is a number of workflows available, we mostly use Github Workflow:

  1. Make sure your master branch is up to date
  2. Create a separate feature branch with descriptive name, e.g. feature/user-authentication
  3. Make your changes
  4. Push the feature branch to remote repo
  5. Make a PR to master branch, request a peer code review from your colleague
  6. After you've passed it successfully, merge it!
πŸ“š Read more on Git Workflows

Mandatory:

Optional:

Commits

Use conventional commits

The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of.

We opted in for CC because they make it easier for team members to work on projects by allowing them to explore a more structured commit history. Also CC comes in handy when we want to automate routine tasks on certain projects, such as generating CHANGELOG, triggering build and publishing processes, determining a semantic version bump etc.

❗ Examples

image

πŸ“š Read more on atomic commits:

Mandatory

Optional:

Keep commits "atomic"

β€œAtomic commit” is basically a fancy way of saying a commit that commits one and only one thing. It’s a single complete unit of work.

There are three basic features a commit needs to have to be atomic:

  1. Single, irreducible unit

    Every commit pertains to one fix/feature/refactoring.

  2. Everything works

    Commit shouldn't break the build on any commit.

  3. Clear and concise

    Purpose is clear from commit message and description

πŸ“š Read more on atomic commits:

Optional:

Commit related changes

A commit should be a wrapper for related changes. For example, fixing two different bugs should produce two separate commits. Small commits make it easier for other developers to understand the changes and roll them back if something went wrong. Leverage the Git's staging area.

Commit often

Committing often keeps your commits small and, again, helps you commit only related changes. Moreover, it allows you to share your code more frequently with others. That way itβ€˜s easier for everyone to integrate changes regularly and avoid having merge conflicts. Having large commits and sharing them infrequently, in contrast, makes it hard to solve conflicts.

Often commits also make code review much more pleasant. You’ll be able to review commit by commit, which will give your brain less information overload and offer a clear context of what you’re reviewing.

Pull requests

Avoid β€œmonster” pull requests; keep them "atomic" too

We prefer making PRs conceptually similar to our commits, that is, clear, small and concise, unless other project-specific conventions come to the scene, because:

  • Each pull request is relatively small and independent, which makes the commit history more granular and easier to manage;
  • Code reviews can be conducted quickly;
  • You can get CI to run on each successive commit you add to your pull request, which helps you debug as you go; and
  • You can work on multiple tasks concurrently while previous pull requests are waiting to be reviewed.

This strategy decreases the human costs associated with developing software: it allows for other team members to comment early (avoid blind alleys) and gives them smaller units of code to review (faster iteration speed.)

Don't postpone a PR until the job is done

We believe, that the most effective way to use pull requests is to get code out in front of other developers on your team early and often, before you’ve invested too much development time into something new. If you’re going down the wrong path or if your work is in conflict with someone else’s it’s better for everyone to have that conversation early.

Put pull requests in front of the team as soon, as possible - this way you can get feedback quickly and leverage the knowledge and experience of your team right away, rather than when it’s too late.

Review your own pull requests

It may sound like a daunting task and unproductive due to author bias, but in reality self-review brings huge benefits:

  • You'll have a chance to fix typos, spot dead code or bad naming
  • You might come up with a more elegant solution to your problem
  • You might perform some insta-refactor before you reviewers spend time on pointing at the necessity of this

Remember, you, the pull request author, are the person in the room who knows the most about why you wrote your own code this way. Share that information with the rest of the team to help eliminate guesswork and speculation.

πŸ“š Read more on Pull Requests

Optional:

Issues

Usually we don't use issues if the Pixel Point team members are the only one who currently works on the project, but we during this period we do use Notion's kanban board for similar purposes, so the concept is roughly the same.

Three common uses for Github issues:

  1. Reporting a bug with the project
  2. Proposing a new feature or change
  3. Discussing tactical and strategic issues with other stakeholders, i.e. β€œshould we switch from moment.js to date-fns.js because moment.js is declared to be sealed recently?”

Here’s what all of these have in common: they give other developers and stakeholders on the team a chance to weigh in and share information before code gets done.

You’re a single developer - you’re only as effective up to the limits of your own knowledge, talent, and experience. When you create an issue on Github or Notion and get into communication with your team members you can leverage the collective knowledge of everyone else. You will routinely save yourself hours of wasted effort if you get into communication early.

Use issues templates

Every project contains issues templates. They may somewhat differ from project to project, but they share some strictly defined structure which is mandatory to follow filling it up.

You can explore examples of issues in this repo.

Use permalinks when discussing code

One of the most effective tools to come to Github is the permalink- the ability to quickly reference an entire section of code and drop it into a Github issue so it can be unambiguously shared with the team at large.

Github permalinks provide a high degree of easily accessible context and they do it inexpensively. They make your technical communication more precise and reduce the cost of fix bugs and address design questions. Use them liberally.

Use issue labels

Github issue labels are a great tool that makes it easy to organize and aggregate similar kinds of issues quickly.

However, the trick with labels is to use them tersely. For instance, if we have a β€œcritical” label that we apply on bugs that have created downtime for end-users - if we applied β€œcritical” to every single issue then the label becomes meaningless.

Useful labels, when used sparingly, make it really easy to slice and dice the set of open issues into independent categories.

πŸ“š Read more on issues:

Optional:

Code

General principles

Each developer in our team is expected to write code that is clean and maintainable. In order to achieve that we agreed upon following a number of well-known coding principles. These principles make yours and the life of other team members easier.

Keep It Simple, Stupid

We pursue a goal of keeping our code as clean, obvious and simple as possible. Don't get caught up in trying to be overly clever or showing off with a paragraph of advanced code. Make it easy to come back after six months and get right back to work.

❗ Examples

A simple example to illustrate the point

// pseudocode

(A ? B : C) // fine

A ? B ? C : D : E // what?

if A {
	B ? C : D
} else E // better
πŸ“š Read more on KISS:

Optional:

You Aren't Gonna Need It

We do not solve problems that do not exist and want you to do the same. Never code for functionality on the chance that you may need it in the future.

❗ Examples

Imagine you were assigned to implement a simpler counter, like this one:

Simplest counter possible

What would be violation for YAGNI principle here? Implementing option in component that allows user to count in real numbers besides the integers because you thought that could come in handy in a future. Don't do that.

πŸ“š Read more on YAGNI:

Optional:

Don't Repeat Yourself

We are constantly eliminating repeating code, starting from setting up projects variables in SCSS that contain all cross-project values like colors, shadows, font-sizes etc. all the way down to pieces of JS logic. If you see that something is repeating over and over or clearly will be repeated, make a layer of abstraction.

Be aware of early abstractions though as it has a potential to violate the YAGNI principle.

❗ Examples
/* bad */

// in one component
.box {
  background-color: white;
}

// in another component
.item {
  border-color: white;
}

// in third component
.title {
  color: white;
}

/* good */

// define a global variable
$color-primary: white;

// in one component
.box {
  background-color: $color-primary;
}

// in another component
.item {
  border-color: $color-primary;
}

// in third component
.title {
  color: $color-primary;
}
πŸ“š Read more on DRY:

Optional:

Don't reinvent the wheel

We are not solving the problems that were already solved. Our projects have in common a lot of similar UI elements, logic, configs etc, so before working on something, answer the following questions:

  • Was that particular thing implemented already in your current project? Can you reuse it? Can you make it reusable?
  • Was that particular thing implemented already (therefore passed code review) in some other project? Can you reuse it?
  • Does it make sense to add a 3rd party instead of writing it from the ground up?

Start the implementation only if you have 3 negative answers.

❗ Examples

Example 1 You have to create a reusable Heading component that will different behavior depending on passed props. Is it worth doing it? Nope, Heading exists in every single web project, so you better ask you team members in which project should you look into to take a decent one.

Example 2 You have to create a complex Select component with multi-selecting, option search etc. Is it worth doing it? Nope, you probably better pick react-select as a 3rd party since it has appropriate functionality and well-tested.

Example 3 You have to create a LollipopGallery component that will act as a modal window and display to user a random picture of lollipop, but on mobiles will be shown as an animated svg lollipop itself. No idea, why stakeholders would want to have that, but anyway, this is exact case where you can demonstrate your excellent dev skills.

P.S. Still better check for OS projects, no one knows for sure.

Lollipop

JavaScript

⚠️ On every single project there is a number of linters/formatter set up to ensure our code style is consistent. Always keep it enabled!

Choose meaningful names

Make sure your variables and functions are named meaningfully. This reduces the need for additional comments as your code speaks for itself.

Remember, variables should give an answer for What is, functions for What does it do

❗ Examples
// bad
cosnt d = new Date();
// good
const date = new Date();

// bad
const mail = () => {}
// good
const sendEmails = () => {}

Avoid "magic" values

Each variable has to have an origin that is easy to find, otherwise that would be confusing on the reader’s end.

❗ Examples
/* bad */
// Reader would have no clue on what 86400000 is
setTimeout(randomFunction, 86400000);
/* good */
// Declare them as capitalized named constants.
const MILLISECONDS_IN_A_DAY = 86_400_000;

setTimeout(blastOff, MILLISECONDS_IN_A_DAY);

Avoid mental mapping

Don't force people and your future self to memorize the variable context. Variables should be understood even when the reader has not managed to follow the whole history of how they came to be.

❗ Examples
// bad
const names = ["John", "Jane", "Joseph"];
names.forEach((n) => {
  doStuff();
  doSomethingExtra();
  // ...
  // ...
  // ...
  // What is this 'n' for?
  dispatch(n);
});
// good
const names = ["John", "Jane", "Joseph"];
names.forEach((name) => {
  doStuff();
  doSomethingExtra();
  // ...
  // ...
  // ...
  // 'name' makes sense now
  dispatch(name);
});

Single-purpose functions

Avoid multiplying side effect in your functions. Distribute the logic between two/three/four - this way they could be understood and tested better.

❗ Examples
// bad
const onFormSubmit = values => {
	// validate submitted values in place
	// send values to your backend
}
// good
const validate = values => {
	// validate submitted values
}
const onFormSubmit = values => {
	validate(values)
	// send values to your backend

Avoid long list of arguments

Ideally, you should avoid a long number of arguments. One or two arguments is the ideal case, and three or more should be consolidated in an object to ease the usage.

❗ Examples
/* bad */

// utils.js
export const buildCTAMessage = (name, lastName, city, action) => // stuff
// index.js
import { buildCTAMessage } from './utils.js'

const data = {
	name: 'John',
	lastName: 'Doe',
	city: 'Dallas'
}
const action = 'play golf'

const ctaMessage = buildCTAMessage(
	// which one should go first?
	data.lastName,
	data.name,
	data.city,
	action
)

/* good */

// utils.js
export const buildCTAMessage = ({name, lastName, city, action}) => // stuff

// index.js
const data = {
	name: 'John',
	lastName: 'Doe',
	city: 'Dallas'
}
const action = 'play golf'

const ctaMessage = buildCTAMessage({
	// doesn't matter
	...data,
	action
})

Styling

Keep naming consistent across the projects

We try to use the same naming everywhere it is possible to avoid any confusion. Here is a bunch of words we use for our classes: wrapper, inner, title, subtitle, description, text, button, illustration, image, logo, icon.

Avoid properties shortcuts

We try to avoid using shortcuts in our styles where it is possible. E.g. if we need to set the background color, we use background-color, if we need to set top and bottom paddings, we use padding-top and padding-bottom, if we need to set border radius for a specific corner, we use, for example, border-top-right-radius.

Prefer variables over inline values

We try to use SASS variables everywhere where it is possible. We always have font styles and common colors in SASS variables that should always be used. Before starting to work on the project, make sure that you check what SASS variables the project has. (DRY)

Pursue reasonable pixel-perfect

We try to use round numbers in our styles where it is possible and our designers try to do the same when creating the design of the website. Don't be that guy who puts 151px magic values "just as in the mockup", 150px will do just fine.

Frameworks

Backbone of our toolset for actually building projects consists of the following frameworks, each of them has a separate section or a separate repo due to its complexity:

  1. ReactJs
  2. GatsbyJs
  3. NextJs

3rd party of choice

We have a curated list of 3rd parties that we decided to use in certain cases, like react-hook-form for working with forms or date-fns for working with dates. It is always good to consult with this list before picking a 3rd party.

See list of chosen 3rd parties

Tooling

We have a curated list of miscellaneous tools that are of a great help for us in the development process, e.g. online image compressor or md editor. You might find it useful as well.

See list of tools

Tips and Tricks

We also have a somewhat random collection of tips, tricks and gists that we consider worth keep under the hand.

See collection

Development guidelines contribution

Typo

If you spotted a typo, indentation or hierarchy inaccuracy, please, submit a PR or raise an issue.

Content

If you think some piece of content is suboptimal, provides irrelevant info, redundant, obsolete or needs to be changed in some way, please, raise an issue.

Structure

If you think the structure of guidelines could be improved, please, raise an issue.

Other

If you have an idea how to make guidelines better, but for some reason can not use Github tools to let contributors know about it, don't hesitate to reach Kirill Bolotsky in Slack or Telegram

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published