[무료] 자바스크립트로 알아보는 함수형 프로그래밍 (ES5) - 인프런 | 강의

마플(http://www.marpple.com)의 CTO 유인동님이 알려주는 함수형 프로그래밍에 대한 강좌 입니다. 함수형 프로그래밍으로 라이브러리를 직접 만들어가며 함수형 프로그래밍의 패러다임과 코딩의 즐거

www.inflearn.com

_.each([1,2,3,4], n=> console.log(n))
_.each(null, n=> console.log(n))

list 가 null이면 프로그램이 멈춘다. 

each는 다른 함수 반복문에 자주 쓰이는 중요한 함수다. null이 인자로 들어와도 그럴싸하게 동작할 방법이 필요하다.

함수형 프로그래밍은 불완전한 값이 들어와도 그럴싸한 값을 리턴해 전체 프로그램이 동작하게 하도록 프로그래밍하는 경향이 있다.

 

get

값을 안전하게 가져오는 함수

/* 요소 리스트 값을 하나씩 꺼내어 준다.*/
function each(list, iter){
    for(let i=0;i<get(list,"length");i++){
        iter(list[i]);
    } 
    return list;
}
/*안전하게 값 가져오기*/
function get (obj,key){
    return obj === null ? undefined : obj[key];
}

null을 만나면 undefined라는 그럴싸한 값을 반환해 프로그램이 멈추지 않게 한다.

get을 each에 적용했다.

_.each([1,2,3,4], n=> console.log(n))
_.each(null, n=> console.log(n))
console.log( _.filter(null, n=> true));
console.log( _.map(null, n=> n));

이제 프로그램이 안 멈춘다. 

더불어 each를 사용한 모든 함수들이 혜택을 받게 됐다.

 

추가개선, keys, is_object

each가 돌림직한 데이터도 순회를 했으면 좋겠다.

우선 보조함수가 필요

/* 객체의 keys를 안전하게 리턴하는 함수*/
function keys(obj){
    return is_object(obj) ? Object.keys(obj) : [];
}
/* 객체인지 안전하게 확인하는 함수 */
function is_object(obj){
    return typeof obj === "object" && !!obj;
}

!!obj 의미

_.each({a:1,b:2,c:3}, a=>console.log(a))
//기대하는 동작 => 1 , 2,  3 출력
/* 요소 리스트 값을 하나씩 꺼내어 준다.*/
function each(list, iter){
    const _keys = keys(list);
    for(let i=0;i<_keys.length;i++){
        iter(list[_keys[i]]);
    } 
    return list;
}
_.each({a:1,b:2,c:3}, a=>console.log(a));
_.each([1,2,3], a=>console.log(a));

이제 object도 순회할 수 있게 됐다. 

원리는 object의 key들을 배열로 만들어 key를 순회할 수 있도록 만든다.

자바스크립트는 친절하게도 object 속성 접근방식과 array 인덱스 접근 방식이 동일하다.

object[key]  ,  array[index]  

배열의 경우 추상화해서 생각하면 배열 요소의 key는 인덱스로 볼 수 있다. 

배열의 인덱스를 key로 하는 key 배열이 생성된다. 

 

이 유연한 동작이 가능한 것은 Object.keys() 동작방식과 배열과 오브젝트를 같은 방식으로 접근할 수 있는 자바스크립트 특징 덕분이다.

 

불필요한 관심사를 제거하고, 돌림직한 데이터를 마치 같은 자료구조처럼 다룰 수 있게 됐다.

 

좀 더 알아보기 Object.keys()

열거할만한 데이터를 keys()함수에 이자로 들어올 수 있다.

//Object.keys 동작방식
console.log(Object.keys(["a","b","c"]).join("-")  );
console.log(Object.keys("가나다라").join("-")   );
console.log(Object.keys({고:"바",구:"바",마:"나"}).join("-")   );
//Object.values 동일
console.log(Object.values(["a","b","c"]).join("-")  );
console.log(Object.values("가나다라").join("-")   );
console.log(Object.values({고:"바",구:"바",마:"나"}).join("-")   );

문자열을 결국 char 배열이므로 똑같이 돌림직한 데이터다.

for...in , for ... of

//Object.keys 는 for...in 과 유사
function forIn(list){
    const result = [];
    for(const arg in list) result.push(arg);
    return result.join("-");
}
//Object.values 는 for...of 과 유사
function forOf(list){
    const result = [];
    for(const arg of list) result.push(arg);
    return result.join("-");
}
console.log(forIn(["a","b","c"]) );
console.log(forIn("가나다라") );
console.log(forIn({고:"바",구:"바",마:"나"}));
console.log(forOf(["a","b","c"]) );
console.log(forOf("가나다라") );
console.log(forOf({고:"바",구:"바",마:"나"}));//불가능

 

단일 접근 원칙

동일한 접근 방식에 관련된 법칙,

데이터 접근에 불필요한 관심사를 제거하고 동일한 방식으로 다룬다.

 

bliki: UniformAccessPrinciple

a bliki entry for UniformAccessPrinciple

martinfowler.com

 

 
//단일 접근 원칙
class Data{
    constructor(name, age){
        this._name = name;
        this._age =age;
    }
    get name(){
        console.log("name 게터 호출");
        return this._name;
    }
    get age(){
        console.log("age 게터 호출");
        return this._age;
    }
    set name(arg){
        console.log("name 세터 호출");
        this._name = arg;
    }
    set age(arg){
        console.log("age 세터 호출");
        this._age = arg;
    }
}
const data1 = new Data("홍길동", 50);
console.log(data1.name); //변수처럼 다룬다
data1.name = "임꺽정"
console.log(data1.name); //변수처럼 다룬다

function.html
0.01MB

다형성(polymorphism)

조상 클래스 타입 참조 변수로 자손 타입 객체를 가리키는

실제 생성된 인스턴스가 무엇인지가 가장 중요하다.

 

public class Test {
	public static void main(String[] args) {
		Tv tv = new SmartTv();
		tv.down();
		tv.up();
//		tv.search(); 사용 못한다. Tv클래스를 보면 search()없기 때문
		//실제 생성된 객체는 SmartTv이기에 타입을 변경하면 호출할 수 있다.
		((SmartTv)tv).search();
	}
}

class Tv{
	void up() {}//채널 업
	void down() {}//채널 다운
}
class SmartTv extends Tv{
	void search() {}//인터넷 검색기능
}

원래 생성된 객체가 SmartTv니까 문제가 없다. 만약 Tv라면 어떻게 될까?

컴파일러는 오류를 못잡는다. 즉, 런타임 예외가 발생하게 된다. (실행 중 예외) 

형변완 예외 발생

이 때문에 형변환 시에 무조건 instanceof 연산자로 형변환가능한 경우만 형변환되도록 하는 것이 중요하다.

 

위까지가 다형성의 사전 지식

public class Test {
	public static void main(String[] args) {
		Tv tv = new SmartTv();
		tv.down();
		tv.up();
	}
}
class Tv{
	void up() {
		System.out.println("일반 TV 채널 업");
	}//채널 업
	void down() {
		System.out.println("일반 TV 채널 다운");
	}//채널 다운
}
class SmartTv extends Tv{
	void up() {
		System.out.println("스마트 TV 채널 업");
	}//채널 업
	void down() {
		System.out.println("스마트 TV 채널 다운");
	}//채널 다운
	void search() {}//인터넷 검색기능
}
///////////////////////////////////////
스마트 TV 채널 다운
스마트 TV 채널 업

실제 동작은 생성된 객체 구현부로 동작되는 것을 알 수 있다. 이를 통한 다형성 사례

public class Test {
	public static void main(String[] args) {
		SmartTv tv1 = new LGSmartTv();
		SmartTv tv2 = new SamsungSmartTv();
		tvTest(tv1);
		tvTest(tv2);
	}
	//앞으로 새로운 스마트 TV가 추가되어도 기존 아래 코드는 수정할 일이 없다.
	static void tvTest(SmartTv smartTv) {
		smartTv.down();
		smartTv.up();
		smartTv.search();
	}
}
class Tv{
	void up() {
		System.out.println("일반 TV 채널 업");
	}//채널 업
	void down() {
		System.out.println("일반 TV 채널 다운");
	}//채널 다운
}
//객체 생성을 막음
abstract class SmartTv extends Tv{
	void up() {
		System.out.println("스마트 TV 채널 업");
	}//채널 업
	void down() {
		System.out.println("스마트 TV 채널 다운");
	}//채널 다운
	void search() {
		System.out.println("스마트한 검색");
	}//인터넷 검색기능
}

class LGSmartTv extends SmartTv{
	void up() {
		System.out.print("LG");
		super.up();
	}
	void down() {
		System.out.print("LG");
		super.down();
	}
	void search() {
		System.out.print("LG의 ");
		super.search();
	}
}
class SamsungSmartTv extends SmartTv{
	void up() {
		System.out.print("삼성");
		super.up();
	}
	void down() {
		System.out.print("삼성");
		super.down();
	}
	void search() {
		System.out.print("삼성의 ");
		super.search();
	}
}
////////////////////////////////
LG스마트 TV 채널 다운
LG스마트 TV 채널 업
LG의 스마트한 검색
삼성스마트 TV 채널 다운
삼성스마트 TV 채널 업
삼성의 스마트한 검색

객체지향 원칙 캡슐화, 추상화, 상속, 다형성을 기반으로 다양한 디자인 패턴들이 존재한다.

 

인터페이스(interface)

일종의 추상클래스

추상클래스 처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높다

 

개발 코드가 객체에 종속되지 않게 하여 객체를 교체할 수 있도록 한다. (OCP, 변경엔 닫혀있고, 확장엔 열려있어야한다)

객체 간 느슨한 결합을 위한 핵심

객체지향 원칙에 구현보다는 인터페이스에 맞춰서 프로그래밍한다는 원칙도 있다.

 

인터페이스 모든 멤버변수는 public static final이다. 그렇기에 생략해도 컴파일러가 일괄적으로 붙여준다.

모든 메서드는 public abstract다.

 

인터페이스 간 상속도 당연히 된다. expands 키워드, 인터페이스를 클래스가 구현하면 implements

 

느슨한 결합 예시

public class Test {
	public static void main(String[] args) {
		LgTv lgTv = new LgTv();
		tvTest(lgTv);
	}
	//지금 구조에서 기존 코드(tvTest)를 절대 건드리지 말고 SamSungTv로 바꿔 동작하게 할 수 있나? 
	public static void tvTest(LgTv lgTv) {
		lgTv.volDown();
		lgTv.volUp();
	}
}
class LgTv{
	void volUp() {}
	void volDown() {}
}

class SamSungTv{
	void volUp() {}
	void volDown() {}
}

절대 불가능하다.

public class Test {
	public static void main(String[] args) {
		LgTv lgTv = new LgTv();
		SamSungTv samSungTv = new SamSungTv();
		//자동 형변환된다.
		tvTest(lgTv);
		tvTest(samSungTv);
	}
	//지금 구조에서 기존 코드(tvTest)를 절대 건드리지 말고 SamSungTv로 바꿔 동작하게 할 수 있나? 
	public static void tvTest(Tv tv) {
		tv.volDown();
		tv.volUp();
	}
}
interface Tv{
	void volUp();
	/*public abstract*/void volDown();
}
class LgTv implements Tv{
	public void volUp() {}
	public void volDown() {}
}

class SamSungTv implements Tv{
	public void volUp() {}
	public void volDown() {}
}

객체지향을 시작으로 다양한 디자인 원칙, 더 나아가 디자인 패턴에서 중요한 핵심은 기존코드를 수정하지 않고 새로운 기능을 손쉽게 추가하는 것이다.

익명 클래스(anonymous class)

이름 없는 클래스, 이유는 선언과 객체 생성을 동시에 하기 때문이다.

일회용으로 쓰거나, 오직 하나의 객체만을 생성한다.

 

public class Test {
	public static void main(String[] args) {
		new AnonymousTest();
	}
}
class AnonymousTest {
	public AnonymousTest() {
		System.out.println("객체 선언과 동시에 생성");
	}
}
////////////////////
객체 선언과 동시에 생성
public class Test {
	public static void main(String[] args) {
		Runnable runnable = ()->Test.call("1");
		Thread thread = new Thread(runnable);
		thread.start();
		call("0");
	}
	static void call(String msg) {
		for(int i = 0; i< 10000 ; i++) {
			System.out.print(msg);
		}
	}
}

람다식은 익명 구현 객체이다.

 

 

 

 

 

 

 

 

 

'개발 > 자바(JAVA)' 카테고리의 다른 글

컴포지트 패턴 연습 - 1  (0) 2023.04.13
기본형 배열 List로 변환하기  (0) 2023.03.10
객체 지향 - 5  (0) 2023.02.01
객체 지향 - 4  (0) 2023.01.31
객체 지향 - 3  (0) 2023.01.29
의도는 "메시징"이다. 훌륭하고 성장 가능한 시스템을 만들기 위한 핵심은 모듈 내부의 속성과 행동이 어떤가보다는 모듈이 어떻게 커뮤니케이션하는가에 달려있다. -앨런 케이

 

자율적인 책임

설계의 품질을 좌우하는 책임

자율적인 객체란 스스로 정한 원칙에 따라 판단하고 스스로의 의지를 기반으로 행동하는 객체

적절한 책임이 자율적인 객체를 낳고, 자율적인 객체들이 모여 유연하고 단순한 협력을 낳는다.

협력에 참여하는 객체가 얼마나 자율적인지에 따라 애플리케이션 품질이 결정된다.

 

 

너무 추상적인 책임

추상적인 것도 정도가 있다. 협력의 의도를 명확하게 표현하지 못할 정도로 추상적인 것은 문제다.

추상적인 책임은 재사용성과 유연성을 가진다. 다만 협력에 참여하는 의도는 명확하게 설명할 있는 수준이야 한다.

 

'어떻게' 아니라 '무엇'

책임을 어떻게는 질지가 중요한게 아니라. 책임이 무엇인지가 중요하다.

어떻게는 구체적인 방법이라 객체의 행동에 자율성을 제한한다.

다형성을 떠올려보자. 무엇을 제공해주는 지가 중요하지 그 방법 따위는 중요치 않다.

이는 결국 결합도와도 연결된다. 

 

책임을 자극하는 메시지

객체가 자신에게 할당된 책임을 수행하도록 만드는 것은 외부에서 전달되는 요청이다.

사실 객체 소통은 요청뿐이다.

요청=메시지

 

메시지와 메서드

메시지

메시지를 전송함으로써 다른 객체에 접근한다.

메시지는 이름과 인자 부분으로 구성(메서드나 함수)

메시지 전송은 수신자, 메시지 이름, 인자로 구성됨

 

메시지 수신을 통해서만 자신의 책임을 수행할 있다.

 

메시지는 객체들이 서로 협력하기 위해 사용할 있는 유일한 의사소통 수단이다. 객체가 메시지를 수신할 있다는 것은 객체가 메시지에 해당하는 책임을 수행할 있다는 것을 의미한다. 객체가 유일하게 이해할 있는 의사소통 수단은 메시지뿐이며 객체는 메시지를 처리하기 위한 방법을 자율적으로 선택할 있다. 외부 객체는 메시지에 관해서만 있고 객체 내부는 없기 때문에 자연스럽게 객체의 외부와 내부가 분리된다.

 

 

메서드

메시지 수신을 처리하기 위해 내부적으로 선택하는 방법을 메서드라 한다.

 

다형성

서로 다른 유형의 객체가 동일한 메시지에 대해 서로 다르게 반응하는

 

무엇이 실행될 지는 명시했지만 어떻게 실행할 것인지는 수신자가 결정한다.

 

다형성을 만족시킨다는 것은 객체들이 동일한 책임을 공유한다는

 

송신자의 관점에서 다형성은 수신자들을 구분할 필요없다. 마다 방법이 다를지라도 동일한 책임을 수행하기 때문이다.

나아가 수신자가 무엇인지 관심도 없다. 역할만 알면된다.(대체 가능성)

따라서 유연하고 재사용성이 높아진다.

 

송신자-수신자 사이 객체 타입에 대한 결합도를 메시지에 대한 결합도를 낮춤으로써 달성한다.

 

 

유연하고 확장 가능하고 재사용성이 높은 협력의 의미

메시지 송신자는 수신자가 메시지를 이해할 있다는 사실만 알고 있는 상태에서 협력에 참여한다.

매우 작은 정보만 알고 있더라도 상호 협력이 된다는 것은 설계의 품질에 영향을 미친다.

 

첫째, 협력이 유연해진다. 수신자가 대체 되더라도 상관이 없고, 송신자는 변경 사실을 조차 없다.

둘째, 협력이 수행되는 방식을 확장할 있다. 송신자에게 아무런 영향 없이 수신자를 교체할 있기 때문에 세부 수행 방식을 쉽게 수정할 있다.

셋째, 협력이 수행되는 방식을 재사용할 있다. 수신자가 교체가 가능하기 때문에 문맥에 맞게 재사용할 있다.

 

 

 

송신자와 수신자를 약하게 연결하는 메시지

메시지는 송신자와 수신자 사이의 결합도를 낮춤으로써 설계를 유연하고, 확장 가능하고, 재사용 가능하게 만든다.

 

송신자의 관점에서 송신자는 메시지만 바라본다. 수신자의 정확한 타입을 모르더라도 상관없다. 단지 처리해 것이라는 사실만 알면 그만이다.

수신자는 메시지를 처리할 방법을 자유롭게 선택하며, 구체적인 방법은 송신자에게 노출하지 안는다.

 

송신자와 수신자 사이 약하게 연결하는 메시지는 낮은 결합도를 보장한다.

이에 따라 유연하고, 대체가능하며, 재사용 가능하며, 확장까지 가능하다.

 

 

 

개념의 가지 관점

일반적으로 객체의 분류 장치로서 개념을 이야기할 때는 아래의 가지 관점을 함께 언급한다[Martin 1998, Larman 2004]

  • 심볼 : 개념을 가리키는 간략한 이름이나 명칭
  • 내연 : 개념의 완전한 정의를 나타내며 내연의 의미를 이용해 객체가 속하는지 여부를 확인할 수 있다.
  • 외연 : 개념에 속하는 모든 객체의 집합

심볼은 예시에서 '트럼트' '토끼'

내연 예시 몸이 납작하고 손과 발이 네모난 모서리에 달려 있다는 트럼프 설명이 예시다.

외연 예시 실제 개념에 일치해 개념에 속한 객체들

 

개념이 심볼, 내연, 외연으로 구성돼 있다는 사실보다는 개념을 이용해 객체를 분류할 있다는 사실이 중요하다.

객체지향 패러다임이 복잡성을 극복하는 사용하는 가장 기본적인 인지 수단이기 때문이다.

 

객체지향의 세계에서 Class 사용한다는 사실을 감안하면

분류(Classification)라는 개념이 얼마나 중요한지 실감할 있다.

 

 

 

객체를 분류하기 위한

분류란 객체에 특정한 개념을 적용하는 작업이다. 객체에 특정한 개념을 적용하기로 결심했을 우리는 객체를 특정한 집합의 멤버로 분류하고 있는 것이다.

 

분류는 객체지향의 가장 중요한 개념 하나다.

분류가 적절치 않다면 애플리케이션 유지보수가 어렵고 변화에 쉽게 대처하지 못한다.

 

 

 

분류는 추상화를 위한 도구다

추상화 가지 차원

번째, 구체적인 사물 간의 공통점을 취하고 차이점을 버리는 일반화를 통한 단순화

번째, 중요한 부분을 강조하기 위해 불필요한 세부 사항을 제거해 단순화

 

개념을 통한 객체 분류는 추상화의 가지 차원을 모두 사용한다.

 

개념은 객체들의 복잡성을 극복하기 위한 추상화 도구다.

추상화를 사용함으로써 우리는 극도로 복잡한 세상을 그나마 제어 가능한 수준으로 단순화할 있는 것이다.

 

 

 

타입

타입은 개념이다

개념을 대체할 있는 용어를 수학에서 차용, 그것은 바로 타입(Type)

 

타입은 개념과 동일하다. 따라서 타입이란 우리가 인식하고 있는 다양한 사물이나 객체에 적용할 있는 아이디어나 관념을 의미한다. 어떤 객체에 타입을 적용할 있을 객체를 타입의 인스턴스라고 한다. 타입의 인스턴스는 타입을 구성하는 외연인 객체 집합의 일원이 된다.

 

 

데이터 타입

실제로 컴퓨터는 01로만 이루어져 있다. 비트배열이 숫자인지 문자인지 구분이 안간다.

그래서 메모리 안에 데이터에 특정한 의미를 부여하기 시작했다. 그것이 타입 시스템(Type System)이다.

타입 시스템의 목적은 메모리 안의 모든 데이터가 비트열로 보임으로써 야기되는 혼란을 방지하는 것이다.

 

타입에 관련된 가지 중요한 사실

첫째, 타입은 데이터가 어떻게 사용되느냐에 관한 것이다.

숫자형 데이터는 연산을 있다.

둘째, 타입에 속한 데이터를 메모리에 어떻게 표현하는지는 외부로부터 철저하게 감춰진다.

데이터 타입의 표현은 연산 작업을 수행하기에 가장 효과적인 형태가 선택되며, 개발자는 해당 데이터 타입의 표현 방식을 몰라도 데이터를 사용하는 지장이 없다.

단지 데이터 타입을 사용하기 위해 연산자만 알고 있으면 된다.

숫자형 데이터에 산술 연산자를 알고 있다면 메모리 내부에 숫자가 어떤 방식으로 저장되는지를 모르더라도 숫자형 데이터를 사용할 있다.

 

책에서는 프로그래밍 언어 관점에서 데이터 타입을 다음과 같이 정의한다.

데이터 타입은 메모리 안에 저장된 데이터의 종류를 분류하는 사용하는 메모리 집합에 관한 메타데이터. 데이터에 대한 분류는 암시적으로 어떤 종류의 연산이 해당 데이터에 대해 수행될 있는지를 결정한다.

 

객체와 타입

객체지향 프로그램에서 객체를 일종의 데이터처럼 사용한다.

객체를 타입에 따라 분류하고 타입에 이름을 붙이는 것은 결국 프로그램에서 사용할 새로운 데이터 타입을 선언하는 것과 같다.

 

객체는 행위에 따라 변할 있는 상태를 가지고 있다는 사실을 기억하라

 

그렇다면 객체는 데이터인가? 그렇지 않다.

다시 한번 강조하지만 객체에서 중요한 것은 객체의 행동이다.

상태는 행동의 결과로 초래된 부수효과를 쉽게 표현하기 위해 도입한 추상적인 개념일 뿐이다.

객체가 협력을 위해 어떤 책임을 지녀야 하는지 결정하는 것이 객체지향 설계의 핵심이다.

협력은 객체간 행동으로만 이루어진다.

 

데이터 타입 가지 조언을 객체의 타입에 적용

첫째, 어떤 객체가 어떤 타입에 속하는지를 결정하는 것은 객체가 수행하는 행동이다.

어떤 객체들이 동일한 행동을 수행할 있다면 객체들은 동일한 타입으로 분류될 있다.

둘째, 객체의 내부적인 표현은 외부로부터 철저하게 감춰진다. 객체의 행동을 가장 효과적으로 수행할 수만 있다면 객체 내부의 상태를 어떤 방식으로 표현하더라도 무방하다.

 

 

행동이 우선이다

객체의 내부 표현 방식이 다르더라도 객체들이 동일하게 행동한다면 객체들은 동일한 타입에 속한다.

결과적으로 동일한 책임을 수행하는 일련의 객체는 동일한 타입에 속한다고 말할 있다.

객체가 어떤 데이터를 보유하고 있는지는 타입을 결정하는 아무런 영향도 미치지 않는다.(인터페이스, 다형성)

 

원칙을 다르게 해석해보자

동일한 타입에 속한 객체는 내부의 데이터 표현 방식이 다르더라도 동일한 메시지를 수신하고 이를 처리할 있다. 다만 내부의 표현 방식이 다르기 때문에 동일한 메시지를 처리하는 방식은 서로 다를 수밖에 없다.

이것은 다형성에 의미를 부여한다.

다형성은 동일한 요청에 대해 서로 다른 방식으로 응답할 있는 능력을 뜻한다.

 

데이터의 내부 표현 방식과 무관하게 행동만이 고려 대상이라는 사실은 외부에 데이터를 감춰야 한다는 것을 의미한다.

좋은 객체지향 설계는 외부에 행동만을 제공하고 데이터는 행동 뒤로 감춰야 한다.

원칙을 흔히 캡슐화라고 한다.

 

행동에 따라 객체를 분류하기 위해서는 객체가 내부적으로 관리해야 하는 데이터가 아니라 객체가 외부에 제공해야 하는 행동을 먼저 생각해야 한다. 이를 위해서는 객체가 외부에 제공해야 하는 책임을 먼저 결정하고 책임을 수행하는 적합한 데이터를 나중에 결정한 , 데이터를 책임을 수행하는 필요한 외부 인터페이스 뒤로 캡슐화해야 한다.

책임-주도 설계(Responsibility-Driven Design) 데이터-주도 설계(Data-Driven Design)방법의 단점을 개선하기 위해 고안됐다.

 

객체를 결정하는 것은 행동이다. 데이터는 단지 행동을 따를 뿐이다. 이것이 객체를 객체답게 만드는 가장 핵심적인 원칙이다.

+ Recent posts