LHJ

I'm a FE developer.

ES6+ 함수와 OOP 1회차

24 Jun 2020 » codespitz

ES6+ 함수와 OOP 1회차

  1. 본 강의는 ES6 이후의 문법을 기준으로 하고 있습니다.
  2. 취지에 따라 기초 문법이나 사용법을 포함하지 않고 있습니다.
  3. 기본 문법이나 기초 개념이 없으신 분들이 듣기에 무리힌 수업입니다.

즉 초심자나 입문자보다는 보다 높은 수준의 개발 개념과 원리 이해를 원하는 개발자를 위해 설계된 과정입니다.


SUB ROUTINE FLOW

메인루틴이 아닌 서브루틴을 배운다.
서브루틴이란 메인쪽 루틴이 아니라 다른쪽 루틴을 사용해서 프로그램을 짜는 것을 뜻한다.
b라는 루틴을 a라는 루틴이 불러와 실행한다면 a는 b에게 있어선 메인루틴, b는 a에게 있어서 서브루틴이된다.(상대적)

  • FLOW : 메모리에 적재된 명령이 순서대로 실행되는 것을 뜻한다. (=SYNC 동기화 명령들이 이렇게 실행된다.)
  • ROUTINE : FLOW(명령어 세트) 그 자체를 의미한다. 명령어 세트를 한 번만 실행할 수 있으면 루틴이라고 안 부른다. 여러번 실행할 수 있을 때 루틴이라고 부른다.
  • SUB ROUNTINE : MAIN ROUTINE과 상대적인 개념이다.

루틴과 펑션

  • 펑션 : 수학적인 개념, x값이 들어가면 y값으로 반드시 나와야하는 공역, 치역의 개념
  • 루틴 : 메모리의 흐름(FLOW) 관점에서 바라보는 개념

ES6에선 에로우 펑션을 사용해라.
이유를 생각해보자.
this라는 개념을 순수 function에서 필요할까? 아니다.
this는 언제 나오는 걸까? 메소드에서 나온다.
하지만 메소드는 ES6에서 어떻게 정의되게 되어있지?
클래스문에서 메서드로 정의되게 되어있다.
ES6 이후부터는 function 보다 에로우 펑션 또는 클래스 메서드를 사용해라.

그렇다면 function 키워드는 왜 아직 사용되고 있지?
하위 호환성을 위해서 유지되고 있는 것일 뿐이다.

명시적으론 function을 안 쓰게 하는 것이 맞다.
thisfunction 안에서 쓰이게 하는 것은 옳지 않다.
에로우 펑션클래스 안의 메서드로 쓰는 것이 옳다.

메인루틴과 서브루틴 사이 값을 통신하는 방법

  • 인자 (메인루틴 -> 서브루틴)
  • 리턴 (서브루틴 -> 메인루틴)

자바스크립트는 return 없는 루틴이 없다.

// 자동반환
// 그것도 undefined가 있는 값으로 반환
return undefined

자바스크립트 undefined 종류 2가지

  1. 진짜 undefined 가 있고 (= new Array(10) : length가 10인 배열이지만 forEach, map 등 다 안됨, length만 10인거지 진짜 아무것도 없기 때문에)
  2. undefined 값이 정의된 undefined가 있다. : a = undefined, a는 존재하고 그 값이 undefined

현재 자바스크립트 스팩에서는 empty 값을 논의중이다.
진짜 없는 undefined와 혼돈되기 때문이다.


자바스크립트는 lr parse(left -> right parse)를 사용한다.
왼쪽에서 오른쪽, 위에서 아래로 parse. (당연한 개념이 아니다.)

lr parse 예외

  1. 할당 (x = 3) 오른쪽에서 왼쪽. - 수학자들이 디자인 했기 때문.

위의 덧셈 연산식 - 메모리가 기억하고 있다. ROUTINEA(B)를 기억한 상태에서 ROUTINEA(C)를 실행하고 덧셈을 실행한다.
더하기 즉, 연산자를 제거하는 것이 꼬리물기 최적화의 핵심이 된다. ROUTINEA(B)를 기억한 상태에서 ROUTINEA(C)를 실행시켜야 연산자가 성립이 된다는 것을 캐치해내는 것이 전문 프로그래머의 역량이다.

  1. 인자 (메인루틴 -> 서브루틴)
  2. 루틴 (서브루틴 -> 메인루틴)

위의 두개, 당연한 거 아니야?
당연하지 않다. 코루틴에선 yield라는 값으로 메인 플로우에게 값을 주기도 한다.
그리고 yield가 아니라 next의 인자라는 방식으로 코루틴에게 값을 주기도 한다.

서브루틴 안에 서브루틴이 있는 경우

KEEP : 인자, 로컬변수 등등 메모리에 기억하는 기능이 작동한다.

이런식이라면 메모리 블록을 계속해서 만들어야 한다.

자바스크립트에선 콜스텍을 (브라우저마다 다르지만) 일반적으로 100번만 해라. 라고 권고하고 있다.
꼬리물기 최적화를 잘하면 사파리 브라우저 한정 무한번 반복할 수 있다.
사파리는 꼬리물기 최적화를 지원하기 때문에, 소스를 잘만 짜면 콜스텍을 해제하고 쌓고, 해제하고 쌓고, 이런 식으로 작동하게 할 수 있다.

스택이 너무 많이 쌓여서 플로우가 죽어버리는 현상을 stack overflow라고 한다.

참조와 값(Reference와 value)

‘값’은 언어마다 다르다.
문자열은 자바스크립트에선 ‘값’으로 정의하고 있지만, 자바에서는 ‘참조’로 정의하고 있다.
자바스크립트의 값 : primitive data type (Number, String, Boolean, undefined, NaN, null, Symbol)
위의 값들을 제외한 나머지 데이터 유형은 자바스크립트에선 싹 다 ‘참조’이다.

자바스크립트에서 function은 ‘복사되지 않기 때문에’ 참조이다.
Object, date, Regex - 모두 참조이다.

하나의 루틴이 여러개의 플로우와 교류하면서 작동해도 아무런 문제가 생기지 않는다.
왜? 다 ‘값’을 주고 받기 때문이다.(복사본)
‘참조’가 아닌 ‘값’을 주고 받으면 서로에 대한 의존성이 낮아진다.

이른 안전한 상태(State Safe)라고 부른다.

‘값’을 기반으로한 함수형 프로그래밍. - 해당 함수를 어디에서 몇번이든 사용해도 신경쓸 필요가 없다.
다른 말로 완전 수학적 함수라고도 한다.

첫번째 배울점
메인루틴과 서브루틴이 서로 ‘값’을 주고받는다면, 우리가 크게 신경쓸 필요가 없는 안전한 함수다.
가장 안정적인 형태가 바로 이거기 때문에, 여러분들이 함수를 짠다면, 가장 먼저 고려해야될 대상은 바로 값과 값으로만 되어있는 녀석 - 이것을 고려해보는 것이 가장 좋다.
이러면 크게 신경쓰지 않아도 프로그램이 안정적으로 변한다.
하지만 이렇게 쉬울리가 없다.

참조를 넘길 경우

SOMETHING은 레퍼런스 객체이다. 이 경우를 생각해보자.

레퍼런스를 루틴 안에서 체인지하면 어떤일이 벌어지는지를 보여주고 있다.
이런 함수는 나쁜 함수냐? 아니다.
여러분이 머리로 이 모든 과정을 이해하고 쓰고 통제할 수 있다면 나쁜 함수가 아니다.
그러기 어려울 뿐이다.
함수형 프로그래밍을 쓰는 이유는 쉽게.. 정말 쉽게 하려고 사용하는 것도 있다.

그러니 되도록 쓰지말자.
하지만 레퍼런스가 넘어가는 것은 어쩔 수 없다.

그러니 참조를 체인지하지말고 READONLY로만 사용하자.
참조가 넘어오는 것은 어쩔 수 없지만, 해당 참조를 변형할 생각말고 읽기 전용으로 생각해.

똑같은 코드를 위와 같이 바꿀 수 있다.

  • ES6 : 함수의 해체 구문을 지원한다.
  • ES8 : 객체 rest 라는 개념을 지원한다. (정해져있는 키를 해체하고 나머지를 묶어 객체로 만드는 기능)

위는 참조를 수정했으니, READONLY가 아니다.

그래서 이때는 새로운 OBJECT를 만들어 return하자.

같은 코드를 개선하면 이렇다.

ES5에서는 객체리터럴의 내부 키의 순서를 보장하지 않는다.
그런데 ES6부턴 여러분이 선언한 객체 키 순서대로 순서가 정해진다.
ES5까지는 해시맵이었는데, ES6부턴 링크드 해시맵이 되었다고 생각하면 된다.
그래서 객체 안의 키의 순서가 보장이 된다.
ES6부턴 객체 리터럴의 순서를 중요하게 생각할 필요가 있다.

  1. 인자(arguments)로 들어오는 ‘참조’는 Readonly로 사용해라.
  2. 지역변수나 리턴값엔 ‘새 객체’로 리턴해라.
  3. 제일 베스트는 ‘값’을 리턴하는 것이다.

‘성능’ 걱정은 하지마라.
여러분들의 실력에서 ‘성능’을 걱정하기엔 아직 이르다.
‘성능’에 문제를 일으킬만큼 기저층의 레이어를 짤 실력이 아니기 때문에 어차피 한번 실행하는 거 조금 더 걸리나 덜 걸리나 의미 없다.
무조건 ‘새 객체’ 만들어서 사용해라.

요약

  1. 인자에 참조를 넘기면 Read only로 사용하고
  2. 로컬변수나 리턴 값에는 새 객체를 반환하도록 노력하자.

  • 핵심 개념 : 높은 응집도, 낮은 결합도
  • 높은 응집도 : 이 부분 저 부분에서 가져다 쓰는 것이 아닌 한 곳에서 가져다 써도 되는 것. (배열 객체를 가져오면 배열 관련 함수를 사용할 수 있다. 응집도가 높다.)
  • 낮은 결합도 : 이 함수를 쓰려면 적어도 다른 47개 함수가 필요해. 이는 결합도가 굉장히 높은 것.
  • 바람직한 방향 : 응집도가 높고 결합도는 낮추자.

예)
sin 함수는 SIN 객체에서. cos 함수는 COS 객체에서 가져온다. - 낮은 응집도.
sin, cos 등등 수학관련 함수는 모두 Math 객체에서 가져온다. - 높은 응집도(O).
sin 함수를 사용하려면 다른 tri 함수 등 6개 함수를 import 시켜야해 - 높은 결합도. sin 함수? 그냥 사용하면되 - 낮은 결합도(O).

좋은 코드란, 좋은 서브루틴이란 높은 응집도, 낮은 결합도를 갖춰야 된다.

결합도(Coupling) - 커플링

결합도와 의존성은 다르다.
의존성 - dependency
결합도는 의존성보다는 좀 더 넓은 범위를 포괄하고 있다.
의존성은 방향을 가지고 있다.
커플링은 양쪽 서로가 서로에게 의존하고 있다.

컨텐츠 커플링

빨강 박스는 사용하면 안되는 방법이다.
클래스 A의 v를 data로 바꾸던가 그러면 클래스 B의 인스턴스는 바로 망가지게 된다.
이런 경우를 우리는 클래스 A와 B가 컨텐츠 강결합을 하고 있다라고 부른다.

Common(전역객체 / 공용객체) Coupling

const Common = class{
    constructor(v) {
        this.v = v;
    }
}

const A = class {
    constructor(c) {
        this.v = c.v;
    }
}

const B = class {
    constructor(c) {
        this.v = c.v;
    }
}

const a = new A(new Common(3));
const b = new A(new Common(4));

컨텐츠 커플링보단 낫다.
Common 객체 하나만 잘 관리하면 되기 때문이다.
하지만 이 경우도 1대1 컨텐츠 커플링이 커먼 커플리으로 바뀌었을 뿐 좋은 점이 없다.

External Coupling

나쁘지만 회피할 방법이 없을 때도 있다.
이게 앞의 두 가지 커플링과는 다른 점이다.
그렇기에 이 External Coupling은 ‘정복’할 수 밖에 없다. (앞의 두 가지 커플링은 사용하면 안되는 거고 이 경우는 정복을 해야되는 거고.)

앞의 Common 커플링은 우리가 만든 ‘전역 객체’에 의해 발생하는 문제였다.
하지만 External 커플링은 외부에서 주어지는 객체에 의해 발생되는 문제다.

위 코드를 보면 멤버 json 객체를 받아 각 클래스 A, B의 인스턴스를 만들고 있다.
그렇게 생성된 a, b는 맴버 json 객체에 의존하고 있다.
맴버 json 객체의 name이 userName으로 변경된다면 위 코드는 깨지게 된다.
맴버 json 객체의 age가 삭제된다면 클래스 B는 깨지게 된다.

하지만 json 을 안 받을 수는 없다.
그래서 이런 json은 사내 공지 게시판에 해당 json api는 이렇게 관리할거야 라는 내용을 공지하게 되고, 이런걸 관리해주는 많은 사이트들이 존재한다.(스웨거 등등)

이런 익스터널 커플링만 서비스가 존재하는 이유가 있다.
필수 불가결한 것이기 때문이다.

위 코드에서 더 좋은 방법

const A = class {
    constructor(member) {
        // member. name이 없으면 throw를 던져서 죽여버리는 것이다.
        // 이렇게 하면 누가 잘못했는지 바로 알 수 있게 된다.(FE가 잘못했는지 서버쪽이 잘못했는지)
        // 강결합은 되도록 빨리 에러처리를 할 수 있게 해야된다.
        // 안 그러면 제품 출시 다 한 후에 에러가 발견된다.
        this.v = member.name;
    }
}

const B = class {
    constructor(member) {
        this.v = member.age;
    }
}

fetch('/member').then(res => res.json()).then(member => {
    const a = new A(member);
    const b = new B(member);
})

Control Coupling

현대 디자인패턴으로 회피할 수 있는 기술이 생겼다.
그래서 해당 커플링은 여러분들이 수정해야되는 커플링이다.
이 커플링은 루틴에게 직접적인 대상 객체를 주지 않고, 대상 객체에 대한 힌트를 주었을 때 발생한다.

예시) 햄버거 가게
손님 A : 메뉴 3번 주세요.
메뉴판이라는 External 객체 존재. - 여기서 메뉴 3번이라는 flag를 점원에게 넘김
이러한 일이 프로그래밍에서도 생긴다.

// 메뉴판 객체인 A는 겁나서 수정할 수도 없다.
// 메뉴판 객체인 A를 물고있는 것들이 얼마나 많을줄 알고...
const A = class {
    // flag 형 변수는 true, false만 있는 것이 아니다.
    // order를 내리기 위한 기호적인 변수는 전부 flag 변수이다.
    process(flag, v) {
        switch (flag) {
            case 1: return this.run1(v);
            case 2: return this.run2(v);
            case 3: return this.run3(v);
        }
    }
}

const B = class {
    constructor(a) {
        this.a = a;
    }
    noop() {
        this.a.process(1);
    }
    echo(data) {
        // 신상품을 개발해 메뉴 2번이 더 이상 콜라가 아니게 되었을 경우,
        // 이런 식의 소스는 다 깨지게 되어있다.
        this.a.process(2, data);
    }
};

const b = new B(new A());

flag 변수가 흐름제어(Flow Control)에 관여한다.
그래서 Control Coupling이라고 부르는 것이다.
디자인 패턴 중에 팩토리 패턴에서 가장 많이 일어나는 오류이다.
팩토리 패턴을 제대로 쓰려면 추상 팩토리를 쓰던지 추상 팩토리 메소드를 쓰던지 해야된다.

이러한 문제를 해결하려면 전략 패턴(strategy pattern)을 사용하면 된다.
전략 객체를 사용하게되면 컨트롤 플로우를 위 A 객체가 처리하지 않기 때문에 받아온 전략객체에 위임해서 처리할 수 있다.

강결합은 일반적인 제어문으로는 파훼하기가 굉장히 어렵다.
하지만 객체지향을 통해서 전략패턴을 도입하면 굉장히 쉽게 해결할 수 있다.
컨트롤 커플링 : 무조건 고쳐야되는 코드다.

STAMP Coupling

부분집합과 전체집합의 문제라고 생각하면 된다.(범위의 문제)

// A 때문에 B를 수정할 수 없다.
const A = class {
    add(data) {
        data.count++;
    }
}

const B = class {
    constructor(counter) {
        this.counter = counter;
        // 아래 count 키를 cnt로 바꾸는 순간 다 깨지게 된다.
        this.data = {a:1, count:0};
    }
    count() {
        // this.data 전체를 넘길 필요가 없다.
        // this.data.count를 넘기면 될일이다.
        // 좁은 범위를 주어야 하는데 되게 넓은 범위를 주었다. 그렇기에 어떤일이 발생한다?
        this.counter.add(this.data);
    }
};

const b = new B(new A());
b.count();
b.count();

되도록이면 필요한 범위의 data만 넘겨줘야 한다.

DATA 약결합

아까 위의 범위의 문제를 해결했다.
위 코드를 보면 data를 안 넘기고 count를 넘긴다.
결합도를 줄인 것을 알 수 있다.

const A = class {
    add(count) {
        return count + 1;
    }
}

const B = class {
    constructor(counter) {
        this.counter = counter;
        // 아래의 count를 cnt로 바꿔도 괜찮다.
        // 결합도가 줄었다.
        this.data = {a:1, count:0};
    }
    count() {
        this.data.count = this.counter.add(this.data.count);
    }
}

const b = new B(new A());
b.count();
b.count();

하지만 아직 한 가지 문제가 남았다.
A 클래스가 반환하는 데이터 유형에 아직은 의존적이라는 것이다.
A 클래스가 반환하는 데이터 유형은 Number라는 믿음이 있어야 된다.
이를 data 커플링이라고 한다.
하지만 이 정도면 괜찮다고 판단하는 것이다.
데이터 커플링 정도는 유지보수할 수 있다.

위 소스를 보면, data에서 count 즉, 레퍼런스에서 value(값)으로 바꾼거 자체가 커플링을 줄이는 효과가 있다.
즉 처음에 말한 레퍼런스가 아닌 값을 사용하라는 내용이 우연이 아닌 것이다.
레퍼런스로 통신을 하게되면 커플링이 높아지게 된다.

Data 커플링만 초록색이고 나머진 다 빨강색?
ㅇㅇ맞다. 최소 Data 커플링정도로 코드를 수정해야된다.


Cohesion (응집도)

우연한 응집도

제일 나쁜 응집도는 우연히 모여있는 애들이다.
Coincidental (우연의) 라는 뜻이다.
우연히 모여있는 애들, 우연한 응집도가 제일 나쁜 응집도이다.

const Util = class {
    static isConnect(){}
    static log(){}
    static isLogin(){}
}

프로젝트하다보면 항상 있는 js파일들 : main, common, util
util 안에는 위와 같은 소스가 항상 들어있다.
왜 들어있을까?
‘우연히’ 쓰레기들을 모으다 보니까 우연히 들어가있게 된 것이다.
가장 응집성이 나쁜 예라고 볼 수 있다.

왜 나쁠까?
Util 만든 작업자 빼곤 해당 메소드, 함수가 존재하는지 안하는지 아무도 몰라.
결국 그 프로젝트엔 똑같은 함수가 여러개 겹치게 된다.

로지컬 응집도

로지컬? 좋은거 아니야?
좋기도하고 나쁘기도 하기 때문에 노랑색이다.

const Math = class {
    static sin(r){}
    static cos(r){}
    static random(){}
    static sqrt(v){}
}

위 소스를 보고 로직컬하다고 생각이 드나요?
로직컬하다고 대부분 생각할 것이다.
그 이유는 여러분이 ‘고등수학 교육’을 받았기 때문이다.
위의 소스는 여러분들이 비슷한 교육을 받고 비슷한 지적 수준을 가지고 있기에 이해가 가능한 것이다.
의 Math 자리에 ‘보험 2상품’이라고 쓰여있다면 여러분이 위 소스를 로직컬하다고 이해할 수 있을까?
만약 Math 자리에 ‘네이버 FE개발 2팀’이라고 쓰여있다면 저 안에 소스들이 이해가 갈까?
그 팀 안에서도 고인물들만 이해가 갈 것이다.

이러한 로지컬 응집성 때문에 똑같은 함수를 계속 만들기도 한다.

그럼 로지컬은 언제 써야되는걸까?
도메인(Math 같은 거)이 괜찮으면 써도 된다.
도메인이 일반적이면 일반적일수록 써도 되는 것이다.
도메인이 특수하면 특수할수록 로지컬 응집성은 헬이다.

Temporal cohesion

템포럴이라는 단어는 시간의 순서라는 뜻이다.
위 소스의 init 이라는 함수 자체가 초기화를 의미하는 것이다.
어떤 것들을 초기화 한 후에 소스들을 진행시킬 거야.라는 뜻을 내포하고 있는 것이다.

const App = class {
    init() {
        // 1. 만약에 순서가 바뀌면 어떻게 할꺼야? 
        // 2. 아래 식들은 병렬로 실행되도 상관없는건지, 아니면 순서가 바뀌면 안되는건지 어떻게 파악할꺼야?
        this.db.init();
        this.net.init();
        this.asset.init();
        this.ui.start();
    }
}

시간에 의한 흐름은 사람의 뇌가 생각하는 사고 방식이 시간의 흐름에 따라 사고하기 때문에 이런 템포럴 응집성을 사용하는 것이다.
하지만 템포럴은 정말 위험하다.
왜냐면 소스의 흐름은 사람이 짜는 것이기 때문에 언제든지 바뀔 가능성이 있어서이다.
그렇게 된다면 나중에 소스를 수정할 때 굉장한 어려움을 겪게 될지도 모른다.

하지만 결국 가장 많이 보는 응집성 중에 하나이다.
하지만 안쓸수는 없으니 노랑색을 부여했다.

procedural cohesion

프로시져는 템포럴 보단 낫다.
템포럴은 시간의 흐름, 프로시져는 절차적 순서에 의한 흐름이다.
즉, 절차적 순서란 작업자가 의도한 흐름이라는 것이다.

모던 사이트의 로그인 기능은 어렵다.
왜? 상시 로그인을 할 것인가? 라는 항목이 있기 때문이다.
페이스북, 인스타그램 등등 항상 로그인되어있다.

P토큰 -> 서버로 전달 -> 서버에서 확인 후 맞으면 세션 토큰으로 답 -> 여러가지 권한 확인 후 로그인상태로 바꿔줌

이러한 절차는 우리가 정하는 것이다.
그래서 시간의 흐름에 따른 것보다는 응집도가 높아진다.
그렇기에 초보일 땐 ‘순서도’를 항상 그리면서 코드를 짜는 것이 좋다.

Communicational cohesion

하나의 대상에 대해서 상호보완적으로 그 주제를 처리한다는 개념이다.
이때부터 우린 역할을 인식할 수 있다.
역할은 책임이기도하고 권한이기도 하다.

나는 사장이면서 강사이기도 하고 아빠이기도 하고 남편이기도 하다.
역할은 보통 책임과 권한으로 설명하는 경우가 많다.
나는 사장이기에 이런 권한이 있으면서도 이런 책임이 있다.

보통 프로그래밍에서 권장하는 것은 하나의 객체가 하나의 역할만을 수행하는 것이다.
단일 역할 원칙

사회적 문제는 왜 발생할까?
자기가 관리자면 관리자의 역할만 수행하면 되는데, 여직원에게 아빠의 역할까지 수행하려다보니 문제가 생기는 것이다.
사회에서도 이런 단일 역할 원칙을 어겨서 발생하는 문제가 많다.

위의 객체 안의 메서드들은 한 마디로 표현하면 ‘배열 관련된 메서드입니다.’라고 할 수 있는 것이다.
위와 같은 체계가 당연한 것이 아니라고 했다.
PHP 언어만 봐도 Array를 다루는 객체가 여러가지 있다.
언어는 시간에 의해 발전하는 것이기 때문이다.
이건 언어마다 다 그렇다. 응집도를 깨는 그러한 부분들이 언어마다 다 있기 마련이다.

여튼 위의 응집도는 매우 바람직하다.

Sequential cohesion

시퀀셜은 보다 더 한단계 더 나아간다.

P토큰 -> 서버로 전달 -> 서버에서 확인 후 맞으면 세션 토큰으로 답 -> 여러가지 권한 확인 후 로그인상태로 바꿔줌

Account 관련을 수정하려면 위 Account 객체만 바라보고 수정하면 된다.
응집성이 굉장히 높은 것이다.
시퀀셜은 프로시져와 커뮤니케이션을 합쳐놓은 개념이라고 볼 수 있다.

함수체이닝 같은 빌드업패턴이 다 이런 시퀀셜 응집성을 따르고 있는 것이다.
시퀀셜 : 절차적인 메서드를 말하기도 하지만 체이닝되는 함수들을 말하기도 한다.

체이닝은 응집성 관점에서 보면 굉장히 좋은 코드이다.

Functional cohesion

펑셔널 응집성은 최고로 좋은 응집성이다. 그린라이트
그런데 무슨 코드인지 예시는 없다.
앞으로 우리 스터디에서 배우게될 주제이기 때문이다.
달성하기도 어렵다. 경우의 수가 많기 때문에.

하지만 앞으로 계속해서 꾸준히 추구해야될 코드이다.


높은 응집성 VS 낮은 결합성(커플링)
이 두개는 서로 모순되는 개념이다.
높은 응집성을 추구하면 높은 결합성이 되게 된다.
반대로 낮은 결합성을 추구하면 응집성 또한 낮아지게 된다.
이러한 모순점이 생긴다는 것이다.

아래로 갈수록 좋은 코드인데 저 둘은 같이 달성할 수 없다라는 것이 핵심 내용이다.
그렇기에 프로그래밍이 어려운 것이다.
프로그래밍을 하기위해선 이러한 관계(커플링과 응집도)에서 합의를 봐야된다.
좋은 프로그래머의 자질이다.