Skip to content

Commit

Permalink
Improve documentation for architecture
Browse files Browse the repository at this point in the history
- Simplify `README.md` by creating and moving some documentation to
`architecture.md`.
- Add more documentation for state handling between layers.
- Improve some documentation to use clearer language.
  • Loading branch information
undergroundwires committed Jan 29, 2022
1 parent 3c3ec80 commit 1bcc6c8
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 87 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ By contributing, you agree that your contributions will be licensed under its [G

- See [tests](./docs/tests.md) for testing
- See [extend script](./README.md#extend-scripts) for quick steps to extend scripts
- See [architecture overview](./README.md#architecture-overview) to deep dive into privacy.sexy codebase
- See [architecture overview](./docs/architecture.md) to deep dive into privacy.sexy codebase
30 changes: 3 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,32 +128,8 @@

## Development

See [docs/development.md](./docs/development.md) for Docker usage, running/building application, development best-practices along with other information related to development.
See [development.md](./docs/development.md) for Docker usage, running/building application, development best-practices along with other information related to development of this project.

## Architecture overview
## Architecture

### Application

- Powered by **TypeScript**, **Vue.js** and **Electron** 💪
- and driven by **Domain-driven design**, **Event-driven architecture**, **Data-driven programming** concepts.
- Application uses highly decoupled models & services in different DDD layers.
- 📖 Read more on • [Presentation](./docs/presentation.md)[Application](./docs/application.md)

![DDD + vue.js](img/architecture/app-ddd.png)

### AWS Infrastructure

[![AWS solution](img/architecture/aws-solution.png)](https://github.com/undergroundwires/aws-static-site-with-cd)

- It uses infrastructure from the following repository: [aws-static-site-with-cd](https://github.com/undergroundwires/aws-static-site-with-cd)
- Runs on AWS 100% serverless and automatically provisioned using [GitHub Actions](.github/workflows/).
- Maximum security & automation and minimum AWS costs are the highest priorities of the design.

#### GitOps: CI/CD to AWS

- CI/CD is fully automated for this repo using different GIT events & GitHub actions.
- Versioning, tagging, creation of `CHANGELOG.md` and releasing is automated using [bump-everywhere](https://github.com/undergroundwires/bump-everywhere) action
- Everything that's merged in the master goes directly to production.
- 📖 Read more on [CI/CD pipelines](./docs/ci-cd.md)

[![CI/CD to AWS with GitHub Actions](img/architecture/gitops.png)](.github/workflows/)
Check [architecture.md](./docs/architecture.md) for an overview of design and how different parts and layers work together. You can refer to [application.md](./docs/application.md) for a closer look at application layer codebase and [presentation.md](./docs/presentation.md) for code related to GUI layer. [collection-files.md](./docs/collection-files.md) explains the YAML files that are the core of the application and [templating.md](./docs/templating.md) documents how to use templating language in those files. In [ci-cd.md](./docs/ci-cd.md), you can read more about the pipelines that automates maintenance tasks and ensures you get what see.
59 changes: 30 additions & 29 deletions docs/application.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,45 @@
# Application

- It's mainly responsible for
- creating and event based [application state](#application-state)
- [parsing](#parsing) and [compiling](#compiling) [application data](#application-data)
- Consumed by [presentation layer](./presentation.md)
Application layer is mainly responsible for:

- creating an event-based and mutable [application state](#application-state),
- [parsing and compiling](#parsing-and-compiling) the [application data](#application-data).

📖 Refer to [architecture.md | Layered Application](./architecture.md#layered-application) to read more about the layered architecture.

## Structure

- [`/src/` **`application/`**](./../src/application/): Contains all application related code.
- [**`collections/`**](./../src/application/collections/): Holds [collection files](./collection-files.md)
- [**`Common/`**](./../src/application/Common/): Contains common functionality that is shared in application layer.
- `..`: other classes are categorized using folders-by-feature structure
Application layer code exists in [`/src/application`](./../src/application/) and includes following structure:

- [**`collections/`**](./../src/application/collections/): Holds [collection files](./collection-files.md).
- [**`Common/`**](./../src/application/Common/): Contains common functionality in application layer.
- `...`: rest of the application layer source code organized using folders-by-feature structure.

## Application state

- [ApplicationContext.ts](./../src/application/Context/ApplicationContext.ts) holds the [CategoryCollectionState](./../src/application/Context/State/CategoryCollectionState.ts) for each OS
- Uses [state pattern](https://en.wikipedia.org/wiki/State_pattern)
- Same instance is shared throughout the application to ensure consistent state
- 📖 See [Application State | Presentation layer](./presentation.md#application-state) to read more about how the state should be managed by the presentation layer.
- 📖 See [ApplicationContext.ts](./../src/application/Context/ApplicationContext.ts) to start diving into the state code.
It uses [state pattern](https://en.wikipedia.org/wiki/State_pattern) with context and state objects. [`ApplicationContext.ts`](./../src/application/Context/ApplicationContext.ts) the "Context" of state pattern provides an instance of [`CategoryCollectionState.ts`](./../src/application/Context/State/CategoryCollectionState.ts) (the "State" of the state pattern) for every supported collection.

Presentation layer uses a singleton (same instance of) [`ApplicationContext.ts`](./../src/application/Context/ApplicationContext.ts) throughout the application to ensure consistent state.

📖 Refer to [architecture.md | Application State](./architecture.md#application-state) to get an overview of event handling and [presentation.md | Application State](./presentation.md#application-state) for deeper look into how the presentation layer manages state.

## Application data

- Compiled to [`Application`](./../src/domain/Application.ts) domain object.
- The scripts are defined and controlled in different data files per OS
- Enables [data-driven programming](https://en.wikipedia.org/wiki/Data-driven_programming) and easier contributions
- Application data is defined in collection files and
- 📖 See [Application data | Presentation layer](./presentation.md#application-data) to read how the application data is read by the presentation layer.
- 📖 See [collection files documentation](./collection-files.md) to read more about how the data files are structured/defined and see [collection yaml files](./../src/application/collections/) to directly check the code.
Application data is collection files using YAML. You can refer to [collection-files.md](./collection-files.md) to read more about the scheme and structure of application data files. You can also check the source code [collection yaml files](./../src/application/collections/) to directly see the application data using that scheme.

Application layer [parses and compiles](#parsing-and-compiling) application data into [`Application`](./../src/domain/Application.ts)). Once parsed, application layer provides the necessary functionality to presentation layer based on the application data. You can read more about how presentation layer consumes the application data in [presentation.md | Application Data](./presentation.md#application-data).

Application layer enables [data-driven programming](https://en.wikipedia.org/wiki/Data-driven_programming) by leveraging the data to the rest of the source code. It makes it easy for community to contribute on the project by using a declarative language used in collection files.

### Parsing and compiling

Application layer parses the application data to compile the domain object [`Application.ts`](./../src/domain/Application.ts).

## Parsing
A webpack loader loads (or injects) application data ([collection yaml files](./../src/application/collections/)) into the application layer in compile time. Application layer ([`ApplicationFactory.ts`](./../src/application/ApplicationFactory.ts)) parses and compiles this data in runtime.

- Application data is parsed to domain object [`Application.ts`](./../src/domain/Application.ts)
- Steps
1. (Compile time) Load application data from [collection yaml files](./../src/application/collections/) using webpack loader
2. (Runtime) Parse and compile application and make it available to presentation layer by [`ApplicationFactory.ts`](./../src/application/ApplicationFactory.ts)
Application layer compiles templating syntax during parsing to create the end scripts. You can read more about templating syntax in [templating.md](./templating.md) and how application data uses them through functions in [collection-files.md | Function](./collection-files.md#function).

### Compiling
The steps to extend the templating syntax:

- Parsing the application files includes compiling scripts using [collection file defined functions](./collection-files.md#function)
- To extend the syntax:
1. Add a new parser under [SyntaxParsers](./../src/application/Parser/Script/Compiler/Expressions/SyntaxParsers) where you can look at other parsers to understand more.
2. Register your in [CompositeExpressionParser](./../src/application/Parser/Script/Compiler/Expressions/Parser/CompositeExpressionParser.ts)
1. Add a new parser under [SyntaxParsers](./../src/application/Parser/Script/Compiler/Expressions/SyntaxParsers) where you can look at other parsers to understand more.
2. Register your in [CompositeExpressionParser](./../src/application/Parser/Script/Compiler/Expressions/Parser/CompositeExpressionParser.ts).
68 changes: 68 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Architecture overview

This repository consists of:

- A [layered application](#layered-application).
- [AWS infrastructure](#aws-infrastructure) as code and instructions to host the website.
- [GitOps](#gitops) practices for development, maintenance and deployment.

## Layered application

Application is

- powered by **TypeScript**, **Vue.js** and **Electron** 💪,
- and driven by **Domain-driven design**, **Event-driven architecture**, **Data-driven programming** concepts.

Application uses highly decoupled models & services in different DDD layers:

- presentation layer (see [presentation.md](./presentation.md)),
- application layer (see [application.md](./application.md)),
- and domain layer.

Application layer depends on and consumes domain layer. [Presentation layer](./presentation.md) consumes and depends on application layer along with domain layer. Application and presentation layers can communicate through domain model.

![DDD + vue.js](./../img/architecture/app-ddd.png)

### Application state

State handling uses an event-driven subscription model to signal state changes and special functions to register changes. It does not depend on third party packages.

Each layer treat application layer differently.

![State](./../img/architecture/app-state.png)

*[Presentation layer](./presentation.md)*:

- Each component holds their own state about presentation-related data.
- Components register shared state changes into application state using functions.
- Components listen to shared state changes using event subscriptions.
- 📖 Read more: [presentation.md | Application state](./presentation.md#application-state).

*[Application layer](./application.md)*:

- Stores the application-specific state.
- The state it exposed for read with getter functions and set using setter functions, setter functions also fire application events that allows other parts of application and the view in presentation layer to react.
- So state is mutable, and fires related events when mutated.
- 📖 Read more: [application.md | Application state](./application.md#application-state).

It's comparable with flux ([`redux`](https://redux.js.org/)) or flux-like ([`vuex`](https://vuex.vuejs.org/)) patterns. Flux component "view" is [presentation layer](./presentation.md) in Vue. Flux functions "dispatcher", "store" and "action creation" functions lie in the [application layer](./application.md). A difference is that application state in privacy.sexy is mutable and lies in single flux "store" that holds app state and logic. The "actions" mutate the state directly which in turns act as dispatcher to notify its own event subscriptions (callbacks).

## AWS infrastructure

The web-site runs on serverless AWS infrastructure. Infrastructure is open-source and deployed as code. [aws-static-site-with-cd](https://github.com/undergroundwires/aws-static-site-with-cd) project includes the source code.

[![AWS solution](../img/architecture/aws-solution.png)](https://github.com/undergroundwires/aws-static-site-with-cd)

The design priorities highest security then minimizing cloud infrastructure costs.

This project includes [GitHub Actions](../.github/workflows/) to automatically provision the infrastructure with zero-touch and without any "hidden" steps, ensuring everything is open-source and transparent. Git repositories includes all necessary instructions and automation with [GitOps](#gitops) practices.

## GitOps

CI/CD is fully automated using different Git events and GitHub actions. This repository uses [bump-everywhere](https://github.com/undergroundwires/bump-everywhere) to automate versioning, tagging, creation of [`CHANGELOG.md`](./../CHANGELOG.md) and GitHub releases. A dedicated [workflow](./../.github/workflows/release.desktop.yaml) creates desktop installers and executables and attaches them into GitHub releases.

Everything that's merged in the master goes directly to production.

📖 Refer to [ci-cd.md](./ci-cd.md) to read more on CI/CD pipelines.

[![CI/CD to AWS with GitHub Actions](../img/architecture/gitops.png)](../.github/workflows/)
Loading

0 comments on commit 1bcc6c8

Please sign in to comment.