Skip to content

Instantly share code, notes, and snippets.

@uyu423
Last active April 21, 2018 16:28
Show Gist options
  • Save uyu423/c69156ea3bc28e0c2848a1b716570157 to your computer and use it in GitHub Desktop.
Save uyu423/c69156ea3bc28e0c2848a1b716570157 to your computer and use it in GitHub Desktop.
Node.js 에서 사용할 수 있는 효율적인 Repository Pattern 에 대해 생각해보자
import config from 'getconfig';
import knex from 'knex';
import mongoose from 'mongoose';
import { User, Log } from './domainObjects';
import { Log as LogSchema } from './mongodbSchemas';
class MySQL {
constructor() {
this.driver = knex(config.DATABASE.MYSQL);
}
__findByIdx(table, idx) {
return this.driver.select().table(table).where({ idx });
}
__findByValue(table, params) {
return this.driver.select().table(table).where(params);
}
}
class MongoDB {
constructor() {
mongoose.connect(config.DATABASE.MONGODB);
this.driver = mongoose.connection;
}
__findByIdx(model, idx) {
return model.find({ idx });
}
}
class Repository {
constructor(engine) {
this.engine = engine;
this.connector = this.setEngine(engine);
}
setEngine(engine) {
switch (engine) {
case 'mysql': {
return new MySQL();
break;
}
case 'mongodb': {
return new MongoDB();
break;
}
default: {
throw new Error('Unsupported Database Engine Type');
}
}
return this;
}
__findByIdx(target, idx) {
return this.connector.__findByIdx(target, idx)
}
}
class UserRepository extends Repository {
constructor() {
super('mysql');
this.TABLE_NAME = 'user';
}
async find(idx) {
const result = await this.__findByIdx(this.TABLE_NAME, idx)
.catch(error => Promise.reject(new Error(String(error)))); // using Super Class Method
return new User(result[0]);
}
async findByEmail(email) {
const result = await this.connector.__findByValue(this.TABLE_NAME, { email })
.catch(error => Promise.reject(new Error(String(error)))); // using Super Class's connector object
return new User(result[0]);
}
}
class LogRepository extends Repository {
constructor() {
super('mongodb');
this.MODEL = mongoose.model('logs', LogSchema);
}
async find(idx) {
const log = await this.__findByIdx(this.MODEL, idx);
return new Log(log);
}
}
const repository = {
user: new UserRepository(),
log: new LogRepository(),
};
const findedUser = repository.user.find(49850).then(result => result);
const findedLog = repository.log.find(19910423).then(result => result);
const finedUser2 = repository.user.findByEmail('[email protected]').then(result => result);
@uyu423
Copy link
Author

uyu423 commented May 1, 2017

A. 고차원의 모듈은 저차원의 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화된 것에 의존 해야 한다.
B. 추상화 된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다.

더 쉽게 말할 수도 있다. 자주 변경되는 컨크리트 클래스에 의존하지 마라. 만약 어떤 클래스의 참조를 가져야 한다면, 참조 대상이 되는 클래스를 추상 클래스로 만들어라. 만약 어떤 함수를 호출해야 한다면, 호출 되는 함수를 추상 함수로 만들어라.

일반적으로, 추상 클래스와 인터페이스는 자신에게서 유도된 구체적인 클래스 보다 훨씬 덜 변한다.

Java 프로그래머를 위한 UML 실전에서는 이것만 쓴다!. 로버트 C.마틴 지음 / 이용원, 정지호 옮김, 인사이트 출판사, p140, 141

출처: http://vandbt.tistory.com/42 [소프트웨어 디자인- Design Software by vandbt]

  • 위 링크의 예제를 보면 abstract class ButtonClient 를 사용해서 Lamp Class를 정의할 때 TurnOn()과 TurnOff()를 재정의해준다.
  • class ButtonImplementation 는 Button을 상속받고, abstract method로 정의된 Button.GetState를 ButtonImplementation에서 재정의한다.
  • 자 이제 이것을 나의 코드에는 어떻게 적용을 시켜야할 것인가? 이건 숙제다...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment