-
-
Notifications
You must be signed in to change notification settings - Fork 187
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve documentation for architecture
- 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
1 parent
3c3ec80
commit 1bcc6c8
Showing
7 changed files
with
143 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/) |
Oops, something went wrong.