모든 프로그램은 변한다
- 프로그래밍 역사상 변하지 않는 유일한 원칙
- 변화할때 어떻게 해결 해야 할까?
격리
- 답 : 격리 (isolation)
- how : 격리 전략 (이미 알려진 격리 전략을 취한다)
격리 전략
- 코드를 변화율에 따라 작성하기
- 변화율
- 그 부분의 코드가 바뀌는 빈도, 이유 등
- 시간적인 대칭성 (시간에 따라 변화율이 변한다)
- 변화의 원인과 주기별로 정리
- 실전 수칙 :
- 강한 응집성 & 약한 의존성
- 응집성 <-> 의존성 (상반)
- 응집성, 의존성을 절충 하는 의사결정
Domain 모델 vs Native 모델
- Domain 모델
- 순수 언어의 변수 와 메모리만 사용
- 순수 data 구조체
- Native 모델
- native 객체를 하나라도 사용 하는 모델
- platform, OS에 관여 하나는 코드가 조금이라도 삽인된 모델
- Domain, Native 모델을 완벽하게 격리!!
Example
const err = msg => { throw msg };
const Info = class{
constructor(json){
const {title, header, items} = json ;
if(typeof title !== 'string' || !title) return err('invalid title');
if(!Array.isArray(header) || !header.length) return err('invalid header');
if(!Array.isArray(items) || !items.length) return err('invalid items');
this._private = {title, header, items};
}
get title(){return this._private.title}
get header(){return this._private.header}
get items(){return this._private.items}
};
const Data = class{
async getData(){
const json = await this._getData();
return new Info(json)
}
async _getData(){
return err('_getData must be overrided');
}
};
const JsonData = class extends Data{
constructor(data){
super();
this._data = data
}
async _getData(){
if(typeof this._data === 'string'){
const response = await fetch(this._data);
return await response.json();
}else return this._data
}
};
const Renderer = class{
async render(data){
if(!data instanceof Data) return err('invalid data type')
this._info = await data.getData();
this._render();
}
_render(){
err('Must be overrided')
}
}
const TableRenderer = class extends Renderer{
constructor(parent){
if(typeof parent !== 'string' || !parent) return err('invalid param');
super();
this._parent = parent;
}
_render(){
const parent = document.querySelector(this._parent);
if(!parent) return err("invalid parent");
parent.innerHTML = '';
const {title, header, items} = this._info;
const [table, caption, thead] = "table,caption,thead".split(',')
.map(v=> document.createElement(v))
console.log(title, header, items, table, caption, thead)
caption.innerHTML = title ;
const headers = header.reduce((_,v)=> (thead.appendChild(document.createElement('th')).innerHTML=v, thead))
const items2 = items.map(item => item.reduce(
(tr,v) => (tr.appendChild(document.createElement('td')).innerHTML = v, tr),
document.createElement('tr')
))
table.appendChild(caption)
table.appendChild(headers)
items2.map(item => table.appendChild(item))
parent.appendChild(table)
}
}
const tableRender = new TableRenderer('#root')
tableRender.render(new JsonData('http://localhost:3030/api'))
코드스피츠-디자인패턴과 뷰패턴