덩어리 진 것을 분리하는 과정
변화에 기민하면서도 효율적으로 대응하는 다양한 개발 방법론
개발해 나가면서 필요한 것들을 피드백을 바탕으로 주도적으로 개발
일정기간 협력과 피드백의 반복
권한이 있으면 책임이 있고 책임이 있으면 권한이 있어야한다.
viewModel이 heavy한 상태이므로 이를 권한과 책임에따라 분리해야한다.
const ViewModel = class extends ViewModelListener {
static get = data => new ViewModel(data)
static #subjects = new Set
static #inited = false
static notify (vm) {
this.#subjects.add(vm)
if (this.#inited) return
this.#inited = true
const f = () => {
this.#subjects.forEach(vm => {
if (vm.#isUpdated.size) {
vm.notify()
vm.#isUpdated.clear()
}
})
requestAnimationFrame(f)
}
requestAnimationFrame(f)
}
static descriptor = (vm, category, k, v) => ({
enumerable: true,
get: () => v,
set (newV) {
v = newV
vm.#isUpdated.add(new ViewModelValue(vm.subKey, category, k, v))
}
})
static define = (vm, category, obj) => (
Object.defineProperties(
obj,
Object.entries(obj)
.reduce((r, [k, v]) => (r[k] = ViewModel.descriptor(vm, category, k, v), r), {})
)
)
subKey = ''; parent = null
styles = {}; attributes = {}; properties = {}; events = {}
#isUpdated = new Set; #listeners = new Set
constructor(data, _ = type(data, 'object')) {
super();
Object.entries(data).forEach(([k, v]) => {
if('styles,attributes,properties'.includes(k)) {
if(!v || typeof v != 'object') throw `invalid object k: ${k}, v:${v}`
this[k] = ViewModel.define(this, k, v)
} else {
Object.defineProperty(this, k, ViewModel.descriptor(this, '', k, v))
if (v instanceof ViewModel) {
v.parent = this
v.subKey = k
v.addListener(this)
}
}
})
ViewModel.notify(this)
Object.seal(this)
}
viewmodelUpdated (updated) { updated.forEach(v => this.#isUpdated.add(v)) }
addListener (v, _ = type(v, ViewModelListener)) { this.#listeners.add(v) }
removeListener (v, _ = type(v, ViewModelListener)) { this.#listeners.delete(v) }
notify () { this.#listeners.forEach(v => v.viewmodelUpdated(this.#isUpdated)) }
}
javascript는 기본적으로 public이다 => 코드조작이 쉬워져 문제발생이 높다.
일정코드가 한번(transaction)에 일어나기 위해 함수를 사용한다.