Skip to content

02. Code Guidelines Conventions

kevin-hashimoto edited this page Mar 4, 2024 · 1 revision

General

Try to follow DRY ( Dont Repeat Yourself ) and KISS ( Keep it Super Simple) principals as well as separation of concerns

Frontend

Directory structure

Generally all working files are in the ./frontend/src directory. e2e tests and config files are in the ./frontend directory. The src directory is separated into categories and should be adhered to to provide easy access to the necessary files.

.
├── backend
└── frontend
    ├── .husky #...git hooks
    ├── .storybook #...storybook settings
    ├── cypress #...cypress e2e test files
    ├── public #...static assets (assets here are copied to the root of dist 'as is' durnig build)
    ├── src
    │   ├── assets
    │   │   ├── fonts
    │   │   ├── icons
    │   │   └── images
    │   ├── components #...ui components that are reused in more than one file
    │   ├── constants #...variables that do not typically change
    │   ├── hooks #...custom react hooks
    │   ├── layouts #...wrappers with common ui elements for page layouts
    │   ├── services #...for interacting with external services ( apis etc )
    │   ├── stores #...zustand stores
    │   ├── themes #...theme files ( mui etc )
    │   ├── utils #...utility functions
    │   ├── pages/views #...ui page components
    │   ├── global.scss
    │   ├── App.jsx
    │   └── main.jsx
    ├── .eslnit.cjs #...linting configurations
    ├── .gitignore
    ├── .prettierignore
    ├── .prettierrc #...code format configurations
    ├── cypress.config.js #...cypress configuration
    ├── cypress.env.json #...cypress environment varianbles
    ├── Dockerfile.dev
    ├── index.html
    ├── jsconfig.json
    ├── package-lock.json
    ├── package.json
    ├── README.md
    ├── vite.config.js #...vite configurations
    └── vitestSetup.js #...vitest setup file

Files that do not have dependency files can live in its respective directory as is.

.
└── frontend/
    └── src/
        ├── components/
        │   └── exampleComponent.jsx
        ├── views/
        │   └── examplePage.jsx

If a dependancy file is exclusive to its consumer those files should be within its own directory.

.
└── frontend/
    └── src/
        ├── components/
        │   └── exampleComponent/
        │       ├── ExampleComponent.jsx #...houses main component
        │       ├── ExampleComponent.test.jsx #...houses main component unit tests
        │       ├── ExampleComponent.stories.jsx #...storybook component
        │       ├── index.js #...redirects to main component
        │       ├── styles.scss #...shouldnt need to extract styles often but if you do it would go in here. most of the time it is taken care of with mui components
        │       └── ComponentSpecificComponent.jsx #...is not reused elsewhere so stays in this folder
        └── pages/views/
            └── examplePage/
                ├── ExamplePage.jsx #...houses main component
                ├── ExamplePage.test.jsx #...houses main component unit tests
                ├── ExampleComponent.stories.jsx #...storybook component
                ├── index.js #...redirects to main component
                ├── styles.scss #...shouldnt need to extract styles often but if you do it would go in here. most of the time it is taken care of with mui components
                └── PageSpecificComponent.jsx #...is not reused elsewhere so stays in this folder

note that index.js is used as an entry point. This avoids writing imports like so: @/components/exampleComponent/exampleComponent and can be shortened to @/components/exampleComponent.

// index.js
export {ExampleComponent} from './exampleComponent`

import alias

To avoid import path drilling, we can use import aliases instead.

Our main alias is @ that maps to src/ for example: instead of ../../../components/ExampleComponent we can do @/components/ExampleComponent

You can add more aliases in jsconfig.js and vite.config.js

default export vs named export

We use named exports instead of default exports.

Named exports are more explicit and help to keep naming concise throughout the application.

export const ExampleComponent () => {}
// instead of
const ExampleComponent () => {}
export default ExampleComponent

and

import { ExampleComponent } from '@/components/ExampleComponent'
// instead of
import ExampleComponent from '@/components/ExampleComponent'

Backend

Directory structure

.
├── backend
    └── lcfs
        ├── db  # module contains db configurations
        │   ├── migrations  # Alembic migrations used to seed the database.
        │   ├── models  # Package contains different models for ORMs.
        │   └── seeders  # Alembic migrations used to seed the database.
        ├── services  # Package for different external services such as rabbit or redis etc.
        ├── tests  # Tests for project.
        ├── utils  # 
        └── web  # Package contains web server. Handlers, startup config.
            ├── api  # Package with all handlers.
            │   └── router.py  # Main router.
            ├── core  #
            ├── exception  # 
            ├── application.py  # FastAPI application configuration.
            └── lifetime.py  # Contains actions to perform on startup and shutdown.
        ├── __main__.py  # Startup script. Starts uvicorn.
        ├── conftest.py  # Fixtures for all tests.
        ├── prestart.sh  # 
        ├── settings.py  # Main configuration settings for project.
        └── start.sh  #
    ├── .dockerignore
    ├── .editorconfig
    ├── .flake8
    ├── .gitignore
    ├── .pre-commit-config.yaml
    ├── .python-version
    ├── alembic.ini
    ├── .pre-commit-config.yaml
    ├── Dockerfile
    ├── Dockerfile.openshift
    ├── migrate.sh
    ├── poetry.lock
    ├── pyproject.toml
    ├── README.md
    └── wait-for-it.sh

└── frontend