Status: Experimental
DDD base class library for JavaScript client-side application.
Notes:
This library does not depend on Almin. You can use it with other JavaScript framework.
Features
This library provide basic DDD base classes.
Entity
: Entity is domain concept that have a unique identityIdentifier
: Identifier is unique identifier for an EntityValueObject
: Value Object is an entity’s state, describing something about the entityRepository
: Repository is used to manage aggregate persistenceConverter
: Converter convert between Entity <-> Props(Entity's props) <-> JSON(Serialized data object)
Install
Install with npm:
npm install ddd-base
Usage
Entity
Entities are domain concepts that have a unique identity in the problem domain.
Entity's equability is Identifier.
Identifier
Identifier is a unique object for each entity.
Entity#equals
check that the Entity's identifier is equaled to other entity's identifier.
Entity Props
Entity Props have to id
props that is instance of Identifier
.
- Define
XProps
typeXProps
should includeid: Identifier<string|number>
property.
- Pass
XProps
toEntity<XProps>
You can get the props via entity.props
.
;console.logxEntity.props.id;
Example:
// Entity A// Entity B// A is not B;;assert.ok!a.equalsb, "A is not B";
Props can includes other property.
// Entity A ;
ValueObject
Value object is an entity’s state, describing something about the entity or the things it owns.
ValueObject's equability is values.
; // X ValueObject; // x1's value equal to x2's value;;console.logx1.props.value; // => 42console.logx2.props.value; // => 42console.logx1.equalsx2;// => true// x3's value not equal both;console.logx1.equalsx3;// => falseconsole.logx2.equalsx3;// => false
📝 ValueObject's props have not a limitation like Entity. Because, ValueObject's equability is not identifier.
Repository
A repository is used to manage aggregate persistence and retrieval while ensuring that there is a separation between the domain model and the data model.
Repository
collect entity.
Currently, Repository
implementation is in-memory database like Map.
This library provide following types of repository.
NonNullableBaseRepository
NullableBaseRepository
NonNullableBaseRepository
NonNullableRepository
has initial value.
In other words, NonNullableRepository#get always return a value.
/** * NonNullableRepository has initial value. * In other words, NonNullableRepository#get always return a value. */declare
NullableBaseRepository
NullableRepository
has not initial value.
In other word, NullableRepository#get may return undefined.
/** * NullableRepository has not initial value. * In other word, NullableRepository#get may return undefined. */declare
Converter
JSON <-> Props <-> Entity
Converter is that convert JSON <-> Props <-> Entity.
createConverter
create Converter
instance from Props
and JSON
types and converting definition.
// Pass Props type and JSON types as generics// 1st argument is that a Constructor of entity that is required for creating entity from JSON// 2nd argument is that a mapping object// mapping object has tuple array for each property.// tuple is [Props to JSON, JSON to Props] createConverterEntityConstructor, mappingObject: Converter<PropsType, JSONType>;
mappingObject
has tuple array for each property.
Example of createConveter
.
// Entity A // Create converter// Tuple has two convert function that Props -> JSON and JSON -> Props;;// Entity to JSON;assert.deepStrictEqualjson, ;// JSON to Entity;assert.deepStrictEqualentity, entity_conveterted;
📝 Limitation:
Convert can be possible one for one converting.
// Can not do convert following pattern
// JSON -> Entity
// a -> b, c properties
Nesting Converter
You can set Converter
instead of mapping functions.
This pattern called Nesting Converter.
// Parent has A and B ;
For more details, see test/Converter-test.ts.
[Deprecated] Serializer
JSON <-> Entity
DDD-base just define the interface of Serializer
that does following converting.
- Convert from JSON to Entity
- Convert from Entity to JSON
You can implement Serializer
interface and use it.
Implementation:
// Entity A // JSON // Serializer; it"toJSON: Entity -> JSON",; it"fromJSON: JSON -> Entity",;
📝 Design Note
props
?
Why entity and value object has It come from TypeScript limitation. TypeScript can not define type of class's properties.
// A limitation of generics interface ;// can not typeaEntity.key; // type is any?
We can resolve this issue by introducing props
property.
// `props` make realize typing ;// can not typeaEntity.props; // props is AEntityProps
This approach is similar with React.
Nesting props is ugly
If you want to access nested propery via props
, you have written a.props.b.props.c
.
It is ugly syntax.
Instead of this, you can assign props
values to entity's properties directly.
; console.logitem.props.price === item.price; // => true
props
is readonly by default
This is related with "Nesting props is ugly"
props
is readonly
and Object.freeze(props)
by default.
props:
It is clear that props
are a Entity's configureation.
They are received from above and immutable as far as the Entity receiving them is concerned.
state:
ddd-base does not define state
type.
But, state
is own properties of Entity.
It is mutable value and it can be modified by default.
For example, this.id
, this.name
, and this.price
are state of ShoppingCartItem
.
You can modify this state.
Changing props and state
props | state | |
---|---|---|
Can get initial value from parent Entity? | Yes | Yes |
Can be changed by parent Entity? | Yes | No |
Can set default values inside Entity? | Yes | Yes |
Can change inside Entity? | No | Yes |
Can set initial value for child Entity? | Yes | Yes |
Related concept:
Real UseCase
- azu/irodr: RSS reader client like LDR for Inoreader.
- azu/searchive: Search All My Documents{PDF}.
- proofdict/editor: Proofdict editor.
Changelog
See Releases page.
Running tests
Install devDependencies and Run npm test
:
npm i -d && npm test
Contributing
Pull requests and stars are always welcome.
For bugs and feature requests, please create an issue.
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request :D
Author
License
MIT © azu