The Specification pattern is a software design pattern that allows you to define business rules in a readable and reusable format. It is useful in applications that need to implement complex business rules involving multiple entities. In this article, we are going to see how to implement the Specification pattern in a Node.js with TypeScript application.
Defining the entity
To exemplify the Specification pattern use, let’s create a simple entity called Transaction. It has three properties: amount (transaction amount), date (transaction date), and description (transaction description).
Create a file called transaction.ts in the src/entities folder with the following content:
This class represents a financial transaction with the following attributes:
amount: the transaction amount
date: the transaction date
description: a transaction description
Creating the business rules
Now that we have the transaction entity, let’s create the business rules to check if a transaction is valid or not. Create a file named specification.ts in the src/specifications folder with the following content:
This file defines a Specification interface that represents a business rule and a CompositeSpecification class that implements the logic for combining business rules.
The classes AndSpecification, OrSpecification, and NotSpecification are subclasses of CompositeSpecification that implement logical operations AND, OR, and NOT, respectively.
Create a file named transaction.ts in the src/specifications folder with the following content:
The TransactionSpecification class is a CompositeSpecification subclass that defines specific Transaction entity business rules.
The static functions amountIsGreaterThan, amountIsLessThan, dateIsGreaterThan, dateIsLessThan, and descriptionContains return TransactionSpecification instances that represent each business rule. The isSatisfiedBy method contains the composition of the rule. the class is subclassed public so that when creating another rule it can just be tweaked and extended to compose.
Using business rules
Now that we have the business rules defined, we can use them to validate a transaction. Create a file called transaction.ts in the src/validators folder with the following content:
This file defines the TransactionValidator class, which receives an instance of Specification<Transaction> in the constructor and has a validate method that receives a transaction and returns a boolean value indicating whether the transaction is valid.
In the example above, we created a transaction with value 100, data new Date(), and description ‘Buy at the supermarket’. Next, we create a TransactionValidator instance, and the business rule checks if the transaction amount is greater than 50 if the transaction date is greater than 01/01/2022, and if the transaction description contains the word ‘supermarket’. Finally, we call the validate method passing the created transaction and display the result in the console.
Conclusion
In this article, we saw how to implement the Specification pattern in a Node.js application with TypeScript. We create a Transaction entity, define business rules to validate a transaction using the TransactionSpecification class, and create a transaction validator using the TransactionValidator class.
The Specification pattern can be applied in different contexts and is a good option when implementing complex business rules involving multiple entities. With it, we can make the code more modular, maintainable, and extensible.
Here’s an example on GitHub: https://github.com/jhonesgoncalves/example-specification-ts
*O conteúdo deste artigo é de responsabilidade do(a) autor(a) e não reflete necessariamente a opinião do iMasters.
Leave a comment