base-domain
Version:
simple module to help build Domain-Driven Design
240 lines (176 loc) • 7.41 kB
Markdown
[](https://circleci.com/gh/CureApp/base-domain)
[](https://waffle.io/CureApp/base-domain)
# base-domain
framework for Domain-Driven Design in JavaScript (or CoffeeScript, recommended.)
[latest API documentation Page](http://cureapp.github.io/base-domain/index.html)
## installation
```bash
$ npm install -g base-domain
```
## concept
base-domain helps easier practice of Domain-Driven Design.
1. list models in the domain of your concern (by your own way)
1. define models with base-domain
1. define their factories with base-domain
1. define their repositories with base-domain
1. define services with base-domain if needed
### essential classes and relations
- Base
- Facade
- BaseModel
- BaseFactory
- BaseRepository
- BaseService
- Entity
- AggregateRoot
- ValueObject
- BaseList
- BaseDict

#### Base
[API Doc](http://cureapp.github.io/base-domain/classes/Base.html)
- Base is an origin of all classes
- Base has Facade
- Base does not have any other properties or methods
#### Facade
[API Doc](http://cureapp.github.io/base-domain/classes/Facade.html)
- Facade is the gate of all classes
- Facade knows all classes
- Facade is module-exported in base-domain: require('base-domain') returns Facade class
#### BaseModel
[API Doc](http://cureapp.github.io/base-domain/classes/BaseModel.html)
- BaseModel is a base class of model
- essential methods for model are defined
- BaseModel is a child of Base
#### BaseFactory
[API Doc](http://cureapp.github.io/base-domain/classes/BaseFactory.html)
- BaseFactory is a base class of factory
- BaseFactory creates specific BaseModel instance
- BaseFactory is a child of Base
#### BaseRepository
[API Doc](http://cureapp.github.io/base-domain/classes/BaseRepository.html)
- BaseRepository is a base class of repository
- BaseRepository connects to database, filesystem or other external data resources (settings needed).
- BaseRepository saves specific BaseModel to data resources
- BaseRepository read BaseModels from data resources
- BaseRepository has BaseFactory (to generate BaseModel from data resources)
#### ValueObject
[API Doc](http://cureapp.github.io/base-domain/classes/ValueObject.html)
- ValueObject is child of BaseModel
- instance of ValueObject does not have id
- ValueObject.isEntity is false
- that's all of ValueObject
#### Entity
[API Doc](http://cureapp.github.io/base-domain/classes/Entity.html)
- Entity is child of BaseModel
- instance of Entity has id
- Entity.isEntity is true
#### AggregateRoot
[API Doc](http://cureapp.github.io/base-domain/classes/AggregateRoot.html)
- AggregateRoot is child of Entity
- AggregateRoot implements RootInterface, thus it can create other models, factories and repositories.
#### BaseList
[API Doc](http://cureapp.github.io/base-domain/classes/BaseList.html)
- BaseList is child of ValueObject
- BaseList has many BaseModels as items
- BaseList#items is array of specific BaseModel
#### BaseDict
[API Doc](http://cureapp.github.io/base-domain/classes/BaseDict.html)
- BaseDict is child of ValueObject
- BaseDict has many BaseModels as items
- BaseDict#items is dictionary of key => specific BaseModel
- BaseDict.key is function to get key from item
## usage
### model definition
model is classified into "Entity" and "ValueObject"
Entity is model with id, ValueObject is model without id.
```coffee
# {domain-dir}/hospital.coffee
class Hospital extends require('base-domain').Entity
# property types
@properties:
name : @TYPES.STRING
address : @TYPES.STRING
beds : @TYPES.NUMBER
registeredAt : @TYPES.DATE
isValidated : @TYPES.BOOLEAN
doctors : @TYPES.MODEL 'doctor-list'
flags : @TYPES.MODEL 'flag-dict'
state : @TYPES.ENUM ['PREPARED', 'RUNNING', 'CLOSED']
module.exports = Hospital
```
#### properties definition
@TYPES.XXX is an object and also a function.
```coffee
@properties:
aaa: @TYPES.STRING
bbb: @TYPES.NUMBER 3
ccc: @TYPES.MODEL 'foo-bar'
```
mark | property type | meaning | arg1 | arg2
-----|-------------------|------------------------------|-----------------|-----------------------------------
x | @TYPES.ANY | prop accepts any type | default value |
x | @TYPES.STRING | prop is string | default value |
x | @TYPES.NUMBER | prop is number | default value |
x | @TYPES.DATE | prop is date | default value |
x | @TYPES.BOOLEAN | prop is boolean | default value |
x | @TYPES.ARRAY | prop is array | default value |
x | @TYPES.OBJECT | prop is object | default value |
x | @TYPES.BUFFER | prop is buffer | default value |
x | @TYPES.GEOPOINT | prop is geopoint | default value |
o | @TYPES.CREATED_AT | date set when first saved | default value |
o | @TYPES.UPDATED_AT | date set each time saved | default value |
o | @TYPES.MODEL | prop is BaseModel | model name | id prop name (if model is Entity)
o | @TYPES.ENUM | prop is index of the alternatives | alternatives | default value
Types with marked "x" just provide the name of the type.
base-domain **does not validate** the prop's type.
### factory definition
```coffee
# {domain-dir}/hospital-factory.coffee
class HospitalFactory extends require('base-domain').BaseFactory
@modelName: 'hospital'
module.exports = HospitalFactory
```
### repository definition
```coffee
# {domain-dir}/hospital-repository.coffee
class HospitalRepository extends require('base-domain').BaseRepository
@modelName: 'hospital'
module.exports = HospitalRepository
```
### use them by facade
```coffee
domain = require('base-domain').createInstance
dirname: '/path/to/domain-dir'
Hospital = domain.getModel('hospital')
hospitalFactory = domain.createFactory('hospital')
hospitalRepository = domain.createRepository('hospital')
hosp = hospitalFactory.createFromObject(name: 'Suzuki Clinic')
hospitalRepository.query(where: name: 'CureApp Hp.').then (hospitals)->
console.log hospitals
```
### list definition
```coffee
# {domain-dir}/hospital-list.coffee
class HospitalList extends require('base-domain').BaseList
@itemModelName: 'hospital'
module.exports = HospitalList
```
### dict definition
```coffee
# {domain-dir}/hospital-dict.coffee
class HospitalDict extends require('base-domain').BaseDict
@itemModelName: 'hospital'
@key: (item) -> item.id
module.exports = HospitalDict
```
# use in browser with browserify
[browserify](http://browserify.org/) is a tool for packing a js project into one file for web browsers
To enable base-domain's requiring system in browsers, use 'base-domain/ify' transformer.
```bash
browserify -t [ base-domain/ify --dirname /path/to/domain/dir ] <entry-file>
```
## include modules
```bash
browserify -t [ base-domain/ify --dirname /path/to/domain/dir --modules foo:/path/to/foo,bar:/path/to/bar ] <entry-file>
```