asb_cloud_front/CODE_STANDART.md

192 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 1. Общие положения
1. Все несамостоятельные компоненты должны быть написаны на TypeScript. Для самостоятельных компонентов (использующихся как страницы) (далее страницы) допускается использование JavaScript для ускорения написания;
### 1.1. Файловая структура проекта
1. Компоненты должны распределяться по директориям в соответствии со своим назначением:
* `src/context` - Для контекстов приложения;
* `src/components` - Для несамостоятельных компонентов, применяющихся многократно;
* `src/pages` - Для страниц и компонентов, использующихся исключительно в единственном экземпляре;
* `src/images` - Для компонентов-изображений.
2. Если страница описывается 1 файлом она должна именоваться в соответствии с содержимым, в ином случае должна быть создана директория с соответствующим названием, внутри которой будут находиться файлы страницы. Основной файл в таком случае должен быть переименован в `index.jsx`;
3. Файлы именуются в соответствии с таблицей:
| Тип содержимого файла | Расширение | Стиль именования |
|--------------------------------------|------------|--------------------------|
| Компонент или страница | jsx/tsx | **PascalCase** |
| Файл стилей | css/less | **snake_case** |
| Вспомогательные методы или константы | js/ts | **snake_case** |
| Описательные документы | md | **SCREAMING_SNAKE_CASE** |
### 1.2. Стилизация кода
1. Все строки должны по возможности описываться одинарными кавычками или при необходимости обратными:
```js
const name = 'world'
const msg = 'Hello, \'' + name + '\'!'
const toPrint = `Message: ${msg}`
```
2. Все переменные по возможности должны инициализироваться как `const`, применение `var` не допускается;
3. Переменные именуются в соответствии с таблицей:
| Тип переменной | Стиль именования |
|-------------------|--------------------------|
| Метод, переменная | **camelCase** |
| Константы | **SCREAMING_SNAKE_CASE** |
| Компонент | **PascalCase** |
### 1.3. Импортирование / Экспортирование
1. Импортированные файлы (в том числе lazy import) необходимо указывать в самом верху документа в следующем порядке с разделением пустой строкой:
1. Внешние зависимости (`react`, `antd`, `webpack` и т.д.);
2. Локальные компоненты по порядку:
1. Контексты (`@asb/context`);
2. Компоненты (`@components/Table`);
3. Вспомогательные методы (`@utils`);
4. Сервисы API (`@api`).
3. Изображения и компоненты-изображения (`@images`);
4. Стили (`@styles`);
5. Lazy import (`const page = React.lazy(() => import('./page'))`).
2. При импорте локальных файлов стоит пользоваться alias'ами:
| Путь | Alias |
|------------------|--------------|
| src/components | @components |
| src/context | @asb/context |
| src/images | @images |
| src/pages | @pages |
| src/services/api | @api |
| src/styles | @styles |
| src/utils | @utils |
3. По возможности импортировать из пакетов и файлов только использующиеся сущности:
```tsx
// вместо
import React from 'react'
const page: React.ReactNode = React.lazy(() => import (...))
// стоит использовать
import { lazy, ReactNode } from 'react'
const page: ReactNode = lazy(() => import (...))
```
### 1.4. Работа с репозиторием
#### 1.4.1. Подготовка к публикации работы по заданию
При получений задания необходимо создать для неё ветку, наследуемую от **dev**.
Ветка должна именоваться в **kebab-case** и иметь префикс соответствующий типу задачи:
* "**feature/**" - для нового функционала или визуала;
* "**fix/**" - для багов и любых исправлений.
Название ветки должно кратко описывать проблему или новые возможности.
Далее необходимо создать *pull request* на ветку dev от новосозданной и сразу отметить его как WIP.
При завершении задания метку WIP необходимо снять.
#### 1.4.2 Оформление коммита
Изменения файлов необходимо разделять на коммиты по общим изменениям и соответствующе его именовать.
Если в коммит попадает более одного логического изменения стоит указывать их в виде маркированного списка, например:
```
* На странице "Мониторинг" и "Архив" сокращено колличество запросов;
* Страница "Сообщения" удалена.
```
## 2. JS
1. Методы, константы и переменные документируются в соответствии с `JSDoc`;
2. При документации страниц необходимо указать её название, краткое описание и описание получаемых параметров:
```jsx
import { memo } from 'react'
import LoaderPortal from '@components/LoaderPortal'
/**
* Тестовая страница
*
* @description Данная страница не имеет смысла и просто выводит переданное название и контент
* @param title - Название страницы
* @param content - Контент страницы
* @param loading - Отображать ли оверлей загрузки над блоком страницы
*/
export const TestPage = memo(({ title, content, loading }) => (
<LoaderPortal show={loading}>
<div className={'dd-test-page'}>
<div className={'dd-test-page-title'}>{title}</div>
<div className={'dd-test-page-content'}>{content}</div>
</div>
</LoaderPortal>
))
export default TestPage
```
## 3. TS
1. Методы, константы и переменные документируются в соответствии с `TSDoc`;
2. При документации компонентов необходимо указать их название, краткое описание, а также описать параметры в типе:
```tsx
import { memo } from 'react'
import LoaderPortal from '@components/LoaderPortal'
export type TestPageProps = {
/** Название страницы */
title: ReactNode
/** Контент страницы */
content: ReactNode
/** Отображать ли оверлей загрузки над блоком страницы */
loading: boolean
}
/**
* Тестовая страница
*
* @description Данная страница не имеет смысла и просто выводит переданное название и контент
*/
export const TestPage = memo<TestPageProps>(({ title, content, loading }) => (
<LoaderPortal show={loading}>
<div className={'dd-test-page'}>
<div className={'dd-test-page-title'}>{title}</div>
<div className={'dd-test-page-content'}>{content}</div>
</div>
</LoaderPortal>
))
export default TestPage
```
3. Использование `any` в типах допустимо только, если значение используется только в параметрах компонентов, обозначенных типом `any`. Если метод предполагает работу с разными типами значений стоит описать его как обобщённый.
## 4. JSX/TSX
### 4.1. Стилизация кода
1. Все указываемые к компоненту параметры должны быть обёрнуты в фигурные скобки, кроме параметров флагов со значением `true`:
```jsx
<Button disabled title={'Hello, world!'} type={'ghost'}>Click me!</Button>
```
2. Если описание параметров компонента не укладывается в ширину в 120 строк стоит перенести их в соответствии с шаблоном:
```jsx
<Button
disabled
title={'Hello, world!'}
type={'ghost'}
>
Click me!
</Button>
```
3. Если JSX код передаётся как значение стоит обернуть его в круглые скобки:
```jsx
const a = (
<Button disabled title={'Hello, world!'} type={'ghost'}>Click me!</Button>
)
```
### 4.2. Логика поведения
1. Не допускается создание значений ссылочных типов в области рендера. Они должны быть вынесены в переменные или константы;
2. Не допускается создание переменных в функциональных компонентов без использования хуков `useMemo`/`useCallback`/`useState`;
3. Если переменные или методы не имеют зависимостей и не вызывают методы, доступные исключительно внутри компонента, они должны быть вынесены выше кода компонента.
## 5. LESS
1. Использование id должно быть сведено к минимуму;
2. Все классы именуются с префиксом компании "`dd-`";
3. Слова в классах разделяются тире ("`-`");
4. Файлы именуются в соответствии с компонентом, к которому относятся;
5. В одном файле описываются стили либо к конкретному компоненту, либо к странице;
6. Файл со стилями должен подключаться не более чем к одному компоненту (странице);
7. Файлы поделены на директории виду компонента, к которому применяются стили:
* `styles/components` - для компонентов, не использующихся самостоятельно;
* `styles/pages` - для компонентов, использующихся как страница;
* `styles/widgets` - для компонентов, применяющихся как виджеты в дашбордах.