projentry

Conventions

Code, structure, architecture

Pages

WIP: На данный момент ведутся активные обсуждения касаемо этого слоя:

  • является ли страница тем же слайсом
  • может ли быть иерархия страниц фрактальной, чтобы повторять структуру роутов
  • и т.д.

Поэтому здесь приведены общие сведения по этому слою

Страницы приложения

└── pages/{slice}
          ├── index.ts
          ├── lib.ts
          ├── model.ts
          └── ui.tsx
  1. Здесь располагаются страницы приложения

    • соответствующие конкретному роуту
    • при необходимости - сгруппированные общей папкой / родительской страницей
  2. Каждая страница должна иметь максимально простую логику

    • вся логика отображения, бизнес правил и прочего - должна реализовываться путем композиции нижележащих слоев (shared, entitites, features)
    • при этом взаимодействие между нижележащими слоями - также должно осуществляться чаще всего на странице
      • Т.е. если featureA влияет на featureB на определенной странице - эта логика должна быть прописана в модели самой странице и только на ней!
      • Без кода в самих фичах и тем более, кросс-импортов!

Примеры

Страница оформления заказа

Реализация БЛ заказа очень зависит от вашего проекта, где-то порой это может регулироваться и процессами. Поэтому здесь приведена лишь одна из имплементаций

import { Order } from "features/order";
import { ProductCard } from "entities/product";
import { orderModel } from "entities/order";
import { Layout } from "shared/ui/layout"

export const CartPage = () => {
    const order = orderModel.useOrder();
    
    // Очень условная разметка
    return (
        {/** Используем shared (Layout) */}
        <Layout>
            <Layout.Main>
                ...
                {/** Используем entities (order.items, ProductCard) */}
                {order.items.map((item) => (
                    <ProductCard key={item.id} data={item} />
                ))}
            </Layout.Main>
            <Layout.Sidebar>
                ...
                {/** Используем features (Order.TotalInfo) */}
                <Order.TotalInfo />
            </Layout.Sidebar>
        </Layout>
    )
}

Features

Части функциональности приложения

└── features/{slice}
          ├── lib/
          ├── model/
          ├── ui/
          └── index.ts

Каждая фича - часть бизнес-логики, при этом обязательно имеющая смысл и ценность для конечного пользователя

  • ProductList, OfficeMap - вряд ли можно назвать фичами
  • WalletAddFunds, AddToCart - уже больше смысла для конечного пользователя

При этом:

  • для построения логики используются нижележащие слои
    • shared, entities
  • одна фича не может импортировать другую
    • Если [возникла такая необходимость][refs-low-coupling] - зависимость нужно переносить на слой выше / ниже, либо решать через композицию через children-props
  • фичи не могут быть вложенными, но при этом могут объединяться общей папкой, т.е. структурно
    • При этом нельзя создавать промежуточные файлы, нужные именно для конкретной группы фич
    • Можно использовать только файлы реэкспорты

Примеры

Авторизация по телефону

import { viewerModel } from "entities/viewer";

export const AuthByPhone = () => {
    return (
        // для redux - дополнительно нужен dispatch
        <Form onSuccess={(user) => viewerModel.setUser(user)}>
            <Form.Input 
                type="phone"
                ...
            />
            <Form.Button
                ...
            />
        </Form>
    )
}

CodeStyle

Please, don't ignore theese recommendations

Commits

Code

  • Don't be blinded by DRY principle

    TODO: add comments

  • Add comments - only if it's required
  • Describe props/types
type TreeItem = {
    /** Unique identifier */
    id: TreeNodeId;
    /** Name */
    name: string;
    /** Amount of related items */
    count: number;
    /** Parent identifier */
    parentId?: TreeNodeId;
}
  • Use tsdoc-like style
/**
 * Tooltip
 * @remark If you should not specify `title` props - tooltip'll be invisible
 */
const Tooltip = (props: Props) => {

Styles

  • Use css vars
    • specially - with work with colors
    • not only on app level, also at component's level
.app {
    --clr-base: #4d97fd;
    --clr-base-hover: #4d97fd1f;
    ...
}
Select article for continue