Fullstack NestJS

Domain Driven Design


The Goal

We are going to discuss how the our code should be a reflection of the business domain that we are operating in.

We also want to highlight the importance of having clear boundaries between distinct contexts within our conceptual understanding as well as in our code.

These boundaries allow us to start to develop and converge on a set of unambiguous semantics that developers and non-technical stakeholders can use to describe the core domain and sub-domains.

Another super important concept is the need to establish a data contract so that the frontend and the backend are decoupled as they can both program to the same interfaces.

Our goal is to define the domain model and data contract for our application.

The Domains

Users

The user domain is responsible for registering users and setting user roles.

The users domain will also be responsible for authenticating users. This may need to be broken out into a separate domain.

Challenges

The challenges domain is where challenges can be created and grouped in a series for users to complete.

Flashcards

The flashcards domain is where flashcards can be created and iterated through much like Anki.

Notes

The notes domain allows for users to create and save snippets much like GitHub Gist.

The Apps

Portal The portal is a registery for microfrontends (MFEs) which is used to expose MFEs, control access, andd perform health checks.

We may consider allowing the register API endpoints as well.

Dashboard

The dashboard is the client facing application which queries the portal after authenticating and loads available MFEs.

Mobile

The mobile application is a read-only mobile variation which will illustrate the power of creating reusuable libraries.

The Stack

Portal Dashboard Mobile Users Challenges Flashcards Notes
APP
API
DOCKER
DB

The Data Contract

Users

export interface BaseEntity {
  id?: string | null;
}

export interface User extends BaseEntity {
  firstName: string;
  lastName: string;
  email: string;
  password: string;
  role: UserRoleEnum;
  company_id: string;
}

export enum UserRoleEnum {
  ADMIN = 'admin',
  MENTOR = 'mentor',
  APPRENTICE = 'apprentice',
}

export interface Company extends BaseEntity {
  name: string;
  description: string;
}

Challenges

export interface Challenge extends BaseEntity {
  slug: string;
  title: string;
  description: string;
  completed: boolean;
  repo_url: string;
  comment: string;
  user_id: string;
}

This TypeScript code defines an interface named Challenge. An interface in TypeScript is a way to define a contract for a certain structure of an object. It describes what the shape of an object should be.

The Challenge interface extends BaseEntity, which means it inherits all properties and methods defined in the BaseEntity interface. The specifics of BaseEntity are not provided here, but it's common for a BaseEntity to include properties like id, createdAt, and updatedAt.

The Challenge interface then defines additional properties:

  • slug: a string that represents a URL-friendly version of the challenge title.
  • title: a string that represents the title of the challenge.
  • description: a string that provides a description of the challenge.
  • completed: a boolean indicating whether the challenge has been completed.
  • repo_url: a string that holds the URL of the repository associated with the challenge.
  • comment: a string for any comments or notes related to the challenge.
  • user_id: a string that represents the ID of the user who is associated with the challenge.

This interface could be used to type-check objects that represent challenges in a coding challenge application, ensuring they have the correct structure.

Notes


export interface Note extends BaseEntity {
  title: string;
  content: string;
  type: NoteTypeEnum;
  user_id: string;
}

export enum NoteTypeEnum {
  TEXT = 'text',
  IMAGE = 'image',
  VIDEO = 'video',
  LINK = 'link',
}

Flashcards

export interface Flashcard extends BaseEntity {
  title: string;
  description: string;
  question: string;
  answer: string;
  user_id: string;
}

The Portal

export interface Feature extends BaseEntity {
  title: string;
  description: string;
  slug: string;
  remote_uri: string;
  api_uri: string;
  healthy: boolean;
}

Challenges

Pending.

< Nest Home