우리는 객체로 이루어진 객체로 살아가며 수 많은 객체들과 상호작용한다. 이러한 상호작용은 단방향으로 일어나기보단 양방향으로 일어나는 경우가 많다.
코드 상에서는 DI라는 개념으로 객체가 단방향으로 주입(영향)받는 구조를 설계하지만 우리의 삶처럼 양방향으로 일어나는 것을 문득 구현해보고 싶었다.
type KnowledgeLevel = '초급' | '중급' | '고급';
type KnowledgeArea = '프로그래밍' | '디자인' | '마케팅';
interface Knowledge {
subject: string;
level: KnowledgeLevel;
area: KnowledgeArea;
}
class Person {
name: string;
knowledge: Map<string, Knowledge>;
interactions: Map<string, number>;
constructor(name: string) {
this.name = name;
this.knowledge = new Map();
this.interactions = new Map();
}
learn(newKnowledge: Knowledge) {
this.knowledge.set(newKnowledge.subject, newKnowledge);
}
teach(otherPerson: Person, subject: string) {
const myKnowledge = this.knowledge.get(subject);
if (myKnowledge) {
otherPerson.learn({ ...myKnowledge, level: '초급' });
// 지식을 전달할 때는 항상 '초급' 수준으로 시작
this.recordInteraction(otherPerson.name);
}
}
recordInteraction(otherPersonName: string) {
this.interactions.set(otherPersonName, (this.interactions.get(otherPersonName) || 0) + 1);
}
displayKnowledge() {
console.log(`${this.name}'s knowledge: `, Array.from(this.knowledge.values()));
}
displayInteractions() {
console.log(`${this.name}'s interactions: `, Array.from(this.interactions.entries()));
}
}
// 예시 사용
const pengoose = new Person('Pengoose');
const bob = new Person('Bob');
pengoose.learn({ subject: 'React', level: '중급', area: '프로그래밍' });
bob.learn({ subject: 'Graphic Design', level: '고급', area: '디자인' });
pengoose.teach(bob, 'React');
bob.teach(pengoose, 'Graphic Design');
pengoose.displayKnowledge();
bob.displayKnowledge();
pengoose.displayInteractions();
bob.displayInteractions();
Pengoose의 지식:
React (중급, 프로그래밍)
Graphic Design (초급, 디자인)
Bob의 지식:
Graphic Design (고급, 디자인)
React (초급, 프로그래밍)
Pengoose의 상호작용:
Bob: 1회
Bob의 상호작용:
Pengoose: 1회
조금 편견을 깨는 코드를 작성하며 객체간 상호작용하는 방식을 추상화하여 Person 객체에 상속하는 방식도 고려해봄직하다. extend가 유용하다는 것은 알지만 문득 위 코드를 생각하며 해당 부분의 필요성을 실제로 체감하여 만족스러운 것 같다.
우리는 살면서 정말 많은 정보들을 얻고, 망각한다.
망각이라는 것은 뇌의 효율성을 위해 불필요한 정보를 배제하고 중요한 정보를 남기는 과정으로 볼 수 있다.
interface Knowledge {
subject: string;
level: KnowledgeLevel;
area: KnowledgeArea;
importance: number; // 지식의 중요도
lastReviewed: Date; // 지식을 마지막으로 복습한 시간
}
class Person {
// ...codes
learn(newKnowledge: Knowledge) {
newKnowledge.lastReviewed = new Date(); // 지식을 배울 때 현재 시간으로 초기화
this.knowledge.set(newKnowledge.subject, newKnowledge);
}
review(subject: string) {
const knowledge = this.knowledge.get(subject);
if (knowledge) {
knowledge.lastReviewed = new Date(); // 지식을 복습할 때마다 시간 갱신
knowledge.importance++; // 복습할 때마다 중요도(가중치) 증가
}
}
forget() {
const now = new Date();
this.knowledge.forEach((value, key) => {
// 일정 기간 동안 복습하지 않은 지식은 망각
if ((now.getTime() - value.lastReviewed.getTime()) > /* 일정 기간 */) {
this.knowledge.delete(key);
}
});
}
displaySortedKnowledge() {
const sortedKnowledge = Array.from(this.knowledge.values())
.sort((a, b) => b.importance - a.importance); // 중요도에 따라 내림차순 정렬
console.log(`${this.name}'s sorted knowledge: `, sortedKnowledge);
}
// ...codes
}
Knowledge에 대한 복잡도가 늘어난다면 따로 Class로 분리하는 것도 좋아보인다. 다만, 지식의 생명주기는 사람(Person)의 뇌에서 일어나는 과정이므로 interface로 작성하였다.
const pengoose = new Person('Pengoose');
// Pengoose가 지식을 배우고 복습하는 과정
pengoose.learn({ subject: 'React', level: '중급', area: '프로그래밍', importance: 1 });
pengoose.review('React');
pengoose.learn({ subject: 'Graphic Design', level: '고급', area: '디자인', importance: 1 });
// 일정 시간 후 Pengoose 지식을 확인
setTimeout(() => {
pengoose.forget(); // 망각 과정
pengoose.displaySortedKnowledge(); // 정렬된 지식 출력
}, 1); // 망각 단위시간 원하는대로 설정
길을 걸어가거나, 버스 창 밖을 멍하니 바라다보면 문득 이런저런 상상에 빠지곤 한다. 그 중 하나는 현실 세계의 것들을 최대한 코드로 옮겨보는 것
. 예를 들어 인간을 코드로 최대한 추상화하는 프로젝트
를 오픈소스로 진행해보면 재밌지 않을까? 문득 생각이 들었다.
빨리 어떠한 사건이나 현상을 보면, 그것을 코드로 구현하고 설명할 수 있는 고수가 되고싶다.