Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: split guidelines #850

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# .devcontainer

Incorporating dev containers further enhances the efficiency and security of our
development process. Dev containers encapsulate the development environment,
including dependencies and tools, within a containerized environment, ensuring
consistency across different machines and operating systems. This
standardization **MUST** simplify the onboarding process for new developers and
reduce the risk of configuration drift or compatibility issues.

The following Getting Started instructions explain how to develop locally using
a devcontainer.

Expand Down
196 changes: 189 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,200 @@ Github Codespaces.
Alternatively, git clone the repo and build, test, and deploy apps locally using
the [devcontainer](.devcontainer/README.md).

## Infrastructure
### Architecture Guidelines

### Architecture
This document adheres to the guidelines outlined in
[RFC 2119](https://www.ietf.org/rfc/rfc2119.txt), which defines the standard
interpretations of key words used in IETF documents. These key words include
"MUST", "MUST NOT", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",
"MAY", and "OPTIONAL". The usage of these words in this document follows the
specifications set forth in RFC 2119, ensuring clarity and consistency in the
requirements and recommendations presented herein.

This repository houses a collection of event-driven microservices, built on a
powerful Platform as a Service (PaaS) foundation. The integration of
Infrastructure as Code (IaC) ensures a streamlined DevOps pipeline for
continuous integration and continuous deployment (CI/CD) leveraging the power of
AWS.
#### What is Architecture?

Outlining the stuff that is hard to change. In the realm of architecture, it's
not merely about constructing individual buildings; it's about designing the
city. Similarly, our architecture guidelines go beyond the confines of a single
project; they lay the groundwork for the entire landscape.

The guide below outlines principles and standards applicable to this repository,
ensuring that each piece contributes harmoniously to the overall cityscape we're
constructing.

![Flow Chart](docs/flow-chart.drawio.svg)

#### Twelve Factor App

Applications **MUST** be designed to run as a service. To avoid common systemic
problems in modern application development, layers **MUST** be constructed
around twelve factor app principles. Code **MUST** be agnostic of environment.

[https://12factor.net/](https://12factor.net/)

#### MACH Architecture

Overall this repository adheres to a Microservices-based, API-first,
Cloud-native, and Headless architecture.

#### Code Structure

A monorepo is believed to help streamline changes. The project **MUST** be
designed as a monorepo instead of polyrepo. Apps **MUST** be mostly serverless
microservices. Not every bit of code the organization maintains should go into
the monorepo, but those that change together stay together.

Microsoft backed Rush was selected over Nx, Lerna, Turbo, etc. for monorepo
management. Nx would probably also be suitable, but rush has worked fine so far.
A package base approach is preferred as to create a clear separation in layers.

The structure of the parent project folder **MUST** follow the pattern
established by Microsoft Rushstack. When it comes to individual package files,
those that typically change in tandem **SHOULD** be kept together. The
organization of code **SHOULD** be based on features. The code is divided into
several categories: libraries, platform, services, middleware, and clients.

#### Universal language

Javascript is the chosen base language for microservices in this project, due to
its performance, ubiquity, beginner-friendly nature, extensive adoption, and
omnipresence. Typescript, backed by Microsoft, is utilized for compiling
Javascript. Typescript brings the advantage of type hinting, which aids in
maintenance and improves the readability of code. As a guideline, Typescript
**SHOULD** be the default language for the majority of application code, unless
there's a substantial reason to opt for a different language.

#### Persistent Storage

##### S3

For persistent file storage S3 **SHOULD** be used. Buckets are a simple
abstraction layer for persistent file storage.

AWS S3 buckets **SHOULD** be provisioned following the principle of least
privilege. This principle implies that each user or service should have the
minimal permissions necessary to perform their specific tasks, and no more. This
approach minimizes the potential damage that can result from error, malicious
activity, or compromise of a specific user or service.

##### Database

Every service employing a database **MUST** maintain its dedicated database
instance within our architecture.

Specifically, code **SHOULD** rely on MongoDB, leveraging the Mongoose library
for interaction for persistent storage. In the context of microservices, we
consciously avoid the use of an Object-Relational Mapping (ORM) layer,
considering it an unnecessary abstraction.

Instead of utilizing ObjectId for identification, services **SHOULD** opt for
UUID type 4 IDs. This choice not only enhances security but also mitigates the
exposure of details such as when the ID was generated and processor-related
information.

##### Data Lake

Messages sent between services **SHOULD** adhere to a contract and persist in a
data lake. Because services communicate via queues and queues publish messages
this **SHOULD** occur automatically.

#### Infrastructure

AWS **MUST** be selected a single Infrastructure as a Service (IaaS) provider.
This project assumes it will fail before AWS does. Vendor lock-in/buy-in allows
leveraging numerous undifferentiated services. For this project that outweighs
being cloud agnostic. The cost it would take to move off AWS was considered.

##### Cloudformation

The entire infrastructure is defined as code, allowing for version control, easy
replication, and consistent environments across different stages of the
development lifecycle. All Infrastructure as Code (IaC) **MUST** be defined as
or compile to CloudFormation templates.

###### AWS CDK

AWS CDK **MUST** be selected for generating Cloudformation templates. The only
exception is for platform which **MAY** use AWS Org Formation or other
Cloudformation abstraction layers.

CDK was selected instead of
[Serverless Framework](https://github.com/serverless-stack/serverless-stack).
When it comes down to it, SST is an unnecessary and incomplete abstraction
layer. SST live lambda development works using serverless website. There does
not appear to be a need to add a reliance on SST. SST future plans, incentives,
and kickback are questionable.

#### Documentation

A README.md file **SHOULD** be added to explain each project and important
folder structures. Any code that isn't self-documenting **MUST** be accompanied
by documentation.

Documentation as code is desired. Documentation **SHOULD** be maintained where
it will be looked for.

Tsdoc **MAY** be selected as a standard for writing Typescript documentation.
Typedoc **MAY** be selected to compile documentation as code.

#### Deployments

Each app **MUST** be capable of deployment themselves using CDK via
`rushx cdk:deploy`. `rushx cdk:deploy` **MAY** be used in local development to
deploy services.

During CI, an artifact from each project **MUST** be uploaded to S3. This
artifact **SHOULD** be processed by AWS CodePipeline for CD.

#### Empowering Teams

If a team needs to rely on another team to make a change that slows down the
application development life cycle, this is unacceptable.

This separation of concerns between dev and ops teams is commonly seen in
enterprises. This introduces numerous problems. Instead Ops in ment to provide a
platform to enable Dev to focus on writting code that matters.

Dev should not be limited by Ops infulstructure, and be forced to add logic to
the same ball of mud. The should be empowered to release software. It's better
for platform to provide a L3 construct than to ship code it doesn't understand.

#### Ephemeral Environments

Furthermore, ephemeral environments **MUST** facilitate parallel development and
testing, enabling multiple teams to work on different features simultaneously
without interfering with each other. This parallelization **MUST** accelerate
development cycles and enhance collaboration, ultimately leading to faster
time-to-market and improved software quality.

Data necessary for setting up a service should move uphill from one environment
to the next through migrations. Software engineers should not require access to
production to do their job.

#### Domain-Driven Design and Ubiquitous Language

Domain-Driven Design (DDD) principles are integral to our architecture
guidelines. We emphasize the importance of establishing a Ubiquitous Language
throughout our development process. This language ensures that domain concepts
are consistently represented and understood across all stakeholders, from domain
experts to developers. By aligning our codebase with the language used in the
domain, we enhance communication, reduce ambiguity, and foster a deeper
understanding of the problem space. Therefore, all code artifacts **MUST**
reflect the Ubiquitous Language established for the respective domain,
facilitating collaboration and maintaining clarity throughout the software
development lifecycle.

### Conway's Law

In this repository, we embrace Conway's Law as a guiding principle in our
software development practices. Conway's Law states that the structure of an
organization will reflect in the design of its systems. By organizing our
codebase into modules and components that correspond to the various teams and
departments within our organization, we foster a natural alignment between our
software architecture and our organizational structure. This approach not only
enhances communication and collaboration but also promotes autonomy and
ownership.

<details>
<summary>Provisioning</summary>

Expand Down
4 changes: 4 additions & 0 deletions clients/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
This directory contains frontend client applications. Each client connects to
backend services, often through a dedicated Backend for Frontend (BFF).

## React

React **SHOULD** be selected as a framework for clients.

## Guidelines

- **Dependency on Backend Services**: Clients rely on backend services for data
Expand Down
7 changes: 7 additions & 0 deletions common/git-hooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Hooks Automation

Git hooks can help reduce the need to perform redundant tasks, allowing
developers to focus on building code that matters. Code **MUST** be
automatically pushed on commit, packages **MUST** be automatically installed on
pull. Automation is in place that is aimed at allowing developers to focus on
what matters.
Loading
Loading