-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1816dc7
Showing
13 changed files
with
7,774 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
## SPECIFICATION PATTERN | ||
|
||
> Reaproveitamento de código | ||
> Regra de negócio multável ou dinâmica | ||
> Muitas condicionais | ||
O que vamos fazer? | ||
Criar uma regra specification que vai identificar | ||
se o usuário que vamos informar pode estar com | ||
COVID-19, se precisa de UTI ou se precisa de atendimento médico. | ||
Com base nos sintomas: | ||
|
||
Mais comuns: (More Common) | ||
|
||
- Febre | ||
- Tosse seca | ||
- cansaço | ||
|
||
Menos comuns: (Less Common) | ||
|
||
- Dores e desconfortos | ||
- Dor de garganta | ||
- Diarreia | ||
- Conjuntivite | ||
- Dor de cabeça | ||
- Perda de paladar ou olfato | ||
- Erupção cutânea na pele | ||
|
||
Sintomas mais graves: (Serious) | ||
|
||
- Dificuldade de respirar | ||
- Dor no peito | ||
- Perda de fala | ||
|
||
User | ||
|
||
> Sintomas (symptoms) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"transform": { | ||
"^.+\\.ts$": "ts-jest" | ||
}, | ||
"testRegex": "\\.spec\\.ts$", | ||
"moduleFileExtensions": [ | ||
"js", | ||
"json", | ||
"ts" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "specification-covid", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"license": "MIT", | ||
"scripts": { | ||
"test": "jest" | ||
}, | ||
"dependencies": { | ||
"@types/jest": "^26.0.21", | ||
"@types/node": "^14.14.35", | ||
"jest": "^26.6.3", | ||
"ts-jest": "^26.5.4", | ||
"typescript": "^4.2.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export abstract class Entity<T> { | ||
constructor(protected readonly props: T) {} | ||
} |
5 changes: 5 additions & 0 deletions
5
src/specification/common/interfaces/specification.interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export interface ISpecification<T> { | ||
isSatisfiedBy: (target: T) => boolean; | ||
and: (other: ISpecification<T>) => ISpecification<T>; | ||
or: (other: ISpecification<T>) => ISpecification<T>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { ISpecification } from './interfaces/specification.interface'; | ||
|
||
export abstract class Specification<T> implements ISpecification<T> { | ||
abstract isSatisfiedBy(target: T): boolean; | ||
and(other: ISpecification<T>): ISpecification<T> { | ||
return new AndSpecification<T>(this, other); | ||
} | ||
or(other: ISpecification<T>): ISpecification<T> { | ||
return new OrSpecification<T>(this, other); | ||
} | ||
} | ||
|
||
export class AndSpecification<T> extends Specification<T> { | ||
constructor( | ||
private readonly one: ISpecification<T>, | ||
private readonly other: ISpecification<T>, | ||
) { | ||
super(); | ||
} | ||
|
||
isSatisfiedBy(target: T): boolean { | ||
return ( | ||
this.one.isSatisfiedBy(target) && | ||
this.other.isSatisfiedBy(target) | ||
); | ||
} | ||
} | ||
|
||
export class OrSpecification<T> extends Specification<T> { | ||
constructor( | ||
private readonly one: ISpecification<T>, | ||
private readonly other: ISpecification<T>, | ||
) { | ||
super(); | ||
} | ||
|
||
isSatisfiedBy(target: T): boolean { | ||
return ( | ||
this.one.isSatisfiedBy(target) || | ||
this.other.isSatisfiedBy(target) | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Entity } from '../interfaces/entity.interface'; | ||
|
||
export enum typeSymptoms { | ||
'FEBRE', | ||
'TOSSE_SECA', | ||
'CANSACO', | ||
'DORES', | ||
'DOR_DE_GARGANTA', | ||
'DIARREIRA', | ||
'CONJUNTIVITE', | ||
'DOR_DE_CABECA', | ||
'PERDA_DO_PALADAR', | ||
'ERUPCAO_CULTANE', | ||
'DIFICULDADE_DE_RESPIRAR', | ||
'DOR_NO_PEITO', | ||
'PERDA_DE_FALA', | ||
} | ||
|
||
export type symptom = keyof typeof typeSymptoms; | ||
|
||
export interface UserProps { | ||
name: string; | ||
symptoms?: symptom[]; | ||
} | ||
|
||
export class User extends Entity<UserProps> { | ||
private constructor(props: UserProps) { | ||
super(props); | ||
} | ||
|
||
get name(): string { | ||
return this.props.name; | ||
} | ||
|
||
get symptoms(): symptom[] { | ||
return this.props.symptoms; | ||
} | ||
|
||
public static create(props: UserProps): User { | ||
return new User(props); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import { User } from './user.entity'; | ||
import { | ||
UserHasAllCommonSymptomsSpecification as CommonSymptom, | ||
UserNeedMedical, | ||
UserNeedsUTI, | ||
} from './user.specification'; | ||
import { UserHasLessCommonSymptomsSpecification as LessCommonSymptom } from './user.specification'; | ||
import { UserHasSomeSeriousSymptomsSpecification as SeriousSymptom } from './user.specification'; | ||
|
||
describe('user.specification', () => { | ||
it('user should has fever', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['FEBRE', 'CANSACO', 'TOSSE_SECA'], | ||
}); | ||
|
||
const result = new CommonSymptom().isSatisfiedBy(Peter); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it('user should has not fever', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['DOR_NO_PEITO'], | ||
}); | ||
|
||
const result = new CommonSymptom().isSatisfiedBy(Peter); | ||
expect(result).toBe(false); | ||
}); | ||
|
||
it('user should has some less common symptom', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['DIARREIRA'], | ||
}); | ||
|
||
const result = new LessCommonSymptom().isSatisfiedBy(Peter); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it('user should has not less common symptom', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['FEBRE'], | ||
}); | ||
|
||
const result = new LessCommonSymptom().isSatisfiedBy(Peter); | ||
expect(result).toBe(false); | ||
}); | ||
|
||
it('user should has some serious symptom', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['DIFICULDADE_DE_RESPIRAR'], | ||
}); | ||
|
||
const result = new SeriousSymptom().isSatisfiedBy(Peter); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it('user should has not serious symptom', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['DIARREIRA'], | ||
}); | ||
|
||
const result = new SeriousSymptom().isSatisfiedBy(Peter); | ||
expect(result).toBe(false); | ||
}); | ||
|
||
it('user should needs UTI', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: [ | ||
'FEBRE', | ||
'TOSSE_SECA', | ||
'CANSACO', | ||
'DIFICULDADE_DE_RESPIRAR', | ||
], | ||
}); | ||
|
||
const result = new UserNeedsUTI().isSatisfiedBy(Peter); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it('user should not needs UTI', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['FEBRE', 'TOSSE_SECA', 'CANSACO'], | ||
}); | ||
|
||
const result = new UserNeedsUTI().isSatisfiedBy(Peter); | ||
expect(result).toBe(false); | ||
}); | ||
|
||
it('user should not needs UTI', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['TOSSE_SECA', 'CANSACO', 'DIFICULDADE_DE_RESPIRAR'], | ||
}); | ||
|
||
const result = new UserNeedsUTI().isSatisfiedBy(Peter); | ||
expect(result).toBe(false); | ||
}); | ||
|
||
it('user should needs medical ', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['FEBRE', 'TOSSE_SECA', 'CANSACO'], | ||
}); | ||
|
||
const result = new UserNeedMedical().isSatisfiedBy(Peter); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it('user should needs medical ', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['FEBRE', 'TOSSE_SECA', 'CANSACO', 'PERDA_DE_FALA'], | ||
}); | ||
|
||
const result = new UserNeedMedical().isSatisfiedBy(Peter); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it('user should needs medical ', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: ['PERDA_DE_FALA'], | ||
}); | ||
|
||
const result = new UserNeedMedical().isSatisfiedBy(Peter); | ||
expect(result).toBe(true); | ||
}); | ||
|
||
it('user should not needs medical ', () => { | ||
const Peter = User.create({ | ||
name: 'Peter', | ||
symptoms: [], | ||
}); | ||
|
||
const result = new UserNeedMedical().isSatisfiedBy(Peter); | ||
expect(result).toBe(false); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { Specification } from '../specification/common/specification'; | ||
import { symptom, User } from './user.entity'; | ||
|
||
export class UserHasAllCommonSymptomsSpecification extends Specification<User> { | ||
private readonly SYMPTOM_CRITERIAL_FEVER: symptom = 'FEBRE'; | ||
private readonly SYMPTOM_CRITERIAL_TOSSE_SECA: symptom = 'TOSSE_SECA'; | ||
private readonly SYMPTOM_CRITERIAL_CANSACO: symptom = 'CANSACO'; | ||
|
||
isSatisfiedBy(user: User): boolean { | ||
const symptoms = user.symptoms; | ||
return ( | ||
symptoms.includes(this.SYMPTOM_CRITERIAL_FEVER) && | ||
symptoms.includes(this.SYMPTOM_CRITERIAL_TOSSE_SECA) && | ||
symptoms.includes(this.SYMPTOM_CRITERIAL_CANSACO) | ||
); | ||
} | ||
} | ||
|
||
export class UserHasLessCommonSymptomsSpecification extends Specification<User> { | ||
private readonly SYMPTOM_CRITERIAL: symptom[] = [ | ||
'DORES', | ||
'DOR_DE_GARGANTA', | ||
'DIARREIRA', | ||
'CONJUNTIVITE', | ||
'DOR_DE_CABECA', | ||
'PERDA_DO_PALADAR', | ||
'ERUPCAO_CULTANE', | ||
]; | ||
|
||
isSatisfiedBy(user: User): boolean { | ||
const symptoms = user.symptoms; | ||
return symptoms | ||
.map((symptom) => this.SYMPTOM_CRITERIAL.includes(symptom)) | ||
.includes(true); | ||
} | ||
} | ||
|
||
export class UserHasSomeSeriousSymptomsSpecification extends Specification<User> { | ||
private readonly SYMPTOM_CRITERIAL: symptom[] = [ | ||
'DIFICULDADE_DE_RESPIRAR', | ||
'DOR_NO_PEITO', | ||
'PERDA_DE_FALA', | ||
]; | ||
|
||
isSatisfiedBy(user: User): boolean { | ||
const symptoms = user.symptoms; | ||
return symptoms | ||
.map((symptom) => this.SYMPTOM_CRITERIAL.includes(symptom)) | ||
.includes(true); | ||
} | ||
} | ||
|
||
export class UserNeedsUTI extends Specification<User> { | ||
isSatisfiedBy(user: User): boolean { | ||
return new UserHasAllCommonSymptomsSpecification() | ||
.and(new UserHasSomeSeriousSymptomsSpecification()) | ||
.isSatisfiedBy(user); | ||
} | ||
} | ||
|
||
export class UserNeedMedical extends Specification<User> { | ||
isSatisfiedBy(user: User): boolean { | ||
return new UserHasAllCommonSymptomsSpecification() | ||
.or(new UserHasSomeSeriousSymptomsSpecification()) | ||
.or(new UserHasLessCommonSymptomsSpecification()) | ||
.isSatisfiedBy(user); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
Passos | ||
|
||
✔ Iniciar projeto com yarn @done(21-03-20 11:30) | ||
✔ Instalar dependências @done(21-03-20 11:33) | ||
- Typescript | ||
- Jest | ||
- ts-jest | ||
- @types/jest | ||
- @tyeps/node | ||
✔ Criar nossa classe abstrata entity @done(21-03-20 14:00) | ||
✔ Criar interface de usuário @done(21-03-20 14:00) | ||
✔ Criar classe usuário @done(21-03-20 14:00) | ||
✔ Criar classe specification @done(21-03-20 15:32) | ||
✔ Criar classe de sintomar specification @done(21-03-20 15:32) | ||
✔ Criar testes @done(21-03-20 15:32) |
Oops, something went wrong.