Monolithic Architecture Overview
Patterns and techniques
Patterns/techniques that are used:
- Domain Driven Design
- Command and Query Responsibility Separation (CQRS)
- Event Sourcing
We are developing an enterprise application. It will support a variety of different clients including desktop browsers, mobile browsers and native mobile applications. This clients will enable employees to manage blog posts, projects information, teams, customers and other data, and it will enable customers to browse the news and submit requests for new interesting projects. The application will also expose an API for 3rd parties (partners) to consume and support B2B. It will also integrate with other systems (Github, LinkedIn, Twitter) via web services to enrich and to share relevant data with them.
- UI Application - Frontend - Angular
- Web Application - Backend - REST API
- Database to store events, materialized views and to act as event-bus.
UI Application - Frontend - Angular Components
We used Angular to implement UI for our solution.
Additionally, you can use StackBlitz as an online IDE to live edit and preview the project in-browser: https://stackblitz.com/github/ivans-innovation-lab/my-company-angular-fe
Feature Components vs Presentational Components
Feature and Presentational Component Design pattern has been called many things such as:
- Container Components vs Presentational Components
- Smart/Dumb Components
- Stateful/Stateless Components
A Feature component is a top level component that contains all other components in our feature. This commonly is a routed component in Angular. Our feature components are responsible for gathering data from various services for our feature to use. If our user saves data the feature component is responsible to pass that data to our Angular Services to save the data to our server API. Feature components are very slim with the amount of application logic. We try to defer this logic to Services if possible. For this example the
blog.component is our Feature Component and it is composed of many Presentational components.
Presentational Components behave like pure functions taking in the data via @Input and emitting data via @Output. This allows the majority of our UI to not know the underlying implementation detail of where the data came from. For example a
side-item.component takes in a @Input of an item to display. This allows the
side-item.component component to have the only responsibility of rendering the item when the data is passed to it.
Many if not most Presentational Components can be abstracted into a style guide or UI library for the project. Using a shared style guide for an organization or project improves reusability, increases the consistency between the different views that form a web application and encourages the communication between the different teams. It can also ensure that a unified brand is used across different products. To get ideas of component design and style guide maintainability I recommend Brad Frost’s book Atomic Design.
There are downsides to this though. As the feature grows in complexity we may have a deeply nested component structure. Since presentation component events only bubble up one level at a time we will have to manually pass up to each parent component. Introducing other sub feature components (
blog-new.component) can help elevate this. The communication between feature components is event driven, and enables loose coupling. For example a
blog-new.component will trigger an event on successfull creation of a blog post, and
blog-list.component is subscribed to it so it can re-fetch and refresh a list of blog posts.
Presentational components are packaged in a [lib/module].(https://www.npmjs.com/package/@my-company-frontend/presentational-components)
Web Application - Backend - REST API Components
The domain is literally split into a command-side component and a query-side component (this is CQRS in its most literal form). Communication between the two components is event-driven and the demo uses simple event store (Database in this case - JPA - HSQLDB) as a means of passing the events between components.
The command-side processes commands. Commands are actions which change state in some way. The execution of these commands results in Events being generated which are persisted by Axon (using SQL DB - HSQLDB) and propagated out to components. In event-sourcing, events are the sole records in the system. They are used by the system to describe and re-build aggregates on demand, one event at a time.
The query-side is an event-listener and processor. It listens for the Events and processes them in whatever way makes the most sense. In this application, the query-side just builds and maintains a materialized view which tracks the state of the individual aggregates (Product, Blog, ...).
Every component is a separate maven project/library:
Project Command side component
Blog Posts Command side component
Project Query side component
Blog Posts Query side component
The command-side and the query-side do not have REST API's. This is why we need another component - web component, which will expose capabilities of all other components via REST API, and package application in one '.war' archive by including other components as depended libraries.