Skip to content

Library that will house implementations used by the engagement service.

License

Notifications You must be signed in to change notification settings

savannahghi/engagementcore

Repository files navigation

Engagement Library

Maintained

MIT license Linting and Tests Coverage Status

A helper library for the engagement-service and other services that will contain some common functionalities used by these services

Description

The project implements the Clean Architecture advocated by Robert Martin ('Uncle Bob').

Clean Architecture

A cleanly architected project should be:

  • Independent of Frameworks: The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints.

  • Testable: The business rules can be tested without the UI, Database, Web Server, or any other external element.

  • Independent of UI: The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.

  • Independent of Database: You can swap out Cloud Firestore or SQL Server, for Mongo, Postgres, MySQL, or something else. Your business rules are not bound to the database.

  • Independent of any external agency: In fact your business rules simply don’t know anything at all about the outside world.

How to use this library

This project uses semantic versioning and can be imported as a package in the (engagement-service)[https://github.com/savannahghi/engagementcore-service] or any other service.

after importing the package, you can create a new instance from the usecases, and use the functionality exposed

How to deploy changes for this projects

This is a library that uses semantic versioning hence every change made to the library, after approval and release, it must be tagged, then upgrade the (engagement-service)[https://github.com/savannahghi/engagementcore-service] with the latest tag version.

tagging

  git tag -m "v0.0.n" "v0.0.n"
  git push --tags

This project has 5 layers:

Domain Layer

Here we have business objects or entities and should represent and encapsulate the fundamental business rules.

Repository Layer

In the domain layer we should have no idea about any database nor any storage, so the repository is just an interface.

Infrastructure Layer

These are the ports that allow the system to talk to 'outside things' which could be a database for persistence or a web server for the UI. None of the inner use cases or domain entities should know about the implementation of these layers and they may change over time because ... well, we used to store data in SQL, then document database and changing the storage should not change the application or any of the business rules.

Usecase Layer

The code in this layer contains application specific business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their enterprise wide business rules to achieve the goals of the use case.

This represents the pure business logic of the application. The rules of the application also shouldn't rely on the UI or the persistence frameworks being used.

Presentation Layer

This represents logic that consume the business logic from the Usecase Layer and renders to the view. Here you can choose to render the view in e.g graphql or rest

Points to note

  • Interfaces let Go programmers describe what their package provides–not how it does it. This is all just another way of saying “decoupling”, which is indeed the goal, because software that is loosely coupled is software that is easier to change.
  • Design your public API/ports to keep secrets(Hide implementation details) abstract information that you present so that you can change your implementation behind your public API without changing the contract of exchanging information with other services.

For more information, see:

JSON Schema Files

This project uses JSON Schema to validate inputs and outputs.

Environment variables

For local development, you need to export the following env vars:

# Google Cloud Settings
export GOOGLE_APPLICATION_CREDENTIALS="<a path to a Google service account JSON file>"
export GOOGLE_CLOUD_PROJECT="<the name of the project that the service account above belongs to>"
export FIREBASE_WEB_API_KEY="<an API key from the Firebase console for the project mentioned above>"

The server deploys to Google Cloud Run. For Cloud Run, the necessary environment variables are:

  • GHOST_CMS_API_ENDPOINT
  • GHOST_CMS_API_KEY

Service architecture

The design of this service aspires to follow the principles of domain driven design and hexagonal architecture.

For the feed, the domain object is feed.Feed . The aggregate is feed.FeedAggregate. There's a feed.Repository interface that can be used to adapt to alternative databases. There's a feed.NotificationService interface that can be used to adapt to alternative message buses.

The communications to the outside world occur over both REST and GraphQL. At the time of writing, there's a plan to add gRPC and messaging ports.