Jun 개발노트

코드스피치 강의 ES6+OOP 1회차 정리

September 06, 2020

Function & OOP

SUB ROUTINE FLOW

  1. FLOW

    • 메모리에 적재된 명령어가 순차적으로 ALU에 의해서 실행되는 과정
    • 한번 실행이 되면 중간에 멈출 수 없고, 명령어가 다 실행되기전까지 절대 멈출수 없다(Sync / 동기화명령)
  2. ROUTINE

    • Flow 그 자체를 의미한다
    • 메모리에 적재된 명령어를 한번만 실행하는게 아니라 여러번 실행시킬 수 있는것
  3. SUB ROUTINE

    • 현재 루틴안에서 일어나는게 아니라 밖에서 일어나면 다 서브 루틴(상대적인 관점)
    • 메인 플로우에서 서브루틴(하나의 또다른 루틴)를 호출시키면 flow가 이동하여 서브루틴안에 있는 명령어들을 다 실행하고 메인 플로우로 돌아오는게 특징
    • 서브루틴을 호출할때는 메인 플로우에서 다시 돌아올 지점을 같이 넣어서 호출한다(돌아올것)
  4. MAIN FLOW vs SUB FLOW

    • Main FLOW - Main routine이 실행되는 것
    • Sub FLOW - Main flow에서 Sub Routine이 실행 되는것
// Main FLOW
const routineA = b => {
	const result = b * 2;
	console.log(result);
	return result;
}

const routineB = d => {
	const result = d * 3;
	console.log(result);
	return result;
}

const b = 10, d = 30;
const a = routomeA(b); // Sub Flow
console.log(a);
const c = routineB(d); // Sub Flow
console.log(c);

Communicate with routine

  1. MAIN FLOW와 SUB FLOW사이에서의 통신

    • 위치 : MAIN FLOW에서 SUB Routine을 호출한 위치(되돌아올 장소)
    • 값 : 인자(메인 ⇒ 루틴)와 리턴 (루틴 ⇒ 메인)
const routineA = arg => {
	const result = arg * 2;
	return result;
}
const b = 10, c = 20, d = 30;
const b = routineA(a) + routineA(b) + routineA(c);
  1. 연산자로 인한 스택 메모리 생성

    • A만 실행시 문제가 없지만, A의 리턴값과 B의 리턴값을 가지고 연산을 하려고 하면 A 와 연산자를 저장
    • B가 실행되고 돌아올때까지 이전 결과값과 연산자를 메모리(스택)를 만들놔야지 연산 진행(아니면 성립불가)

Sub Routine in Sub Routine

  1. 서브루틴 안에 서브루틴

    • 서브루틴 상에서 또다른 서브루틴을 호출하려고 하면 지금 현재의 상태를 Snap Shot을 찍어서 가지고 있고 호출한 루틴이 끝나면 다시 돌아와 그 값을 이용하여 서브루틴을 끝낸다.
  2. Keep

    • 무리한 call stack은 stackover로 프로그램이 멈춘다.(크롬은 대략 100번 정도)
    • 이러한 Keep을 call stack이라고 부른다 ⇒ Stack Memory에 저장
    • Snap shot을 찍어서 저장하는 과정을 Keep이라고 부른다
const routineA = arg => routineB(arg * 2); // routineB를 호출하기전 routineB에 대한 상태값을 저장해놔야한다.
const routineB = arg => arg * 3;

const b = 10;
const a = routineA(b);

Value vs Reference

  1. Primitive Value

    • 메모리상에서 값이 복사되는 형태
    • 루틴으로 전달될때 값이 복사되서 넘어가기 때문에 의존성이 낮아진다(사이드 이펙트가 없다)
  2. Reference Value

    • 공유된 객체의 포인터를 전달(전달된 객체를 바꾸면 원래값을 바꾼다??? 값은 원래값 하나뿐)
    • 레퍼런스로 넘어온 경우, 포인터를 건드리지 않고 readonly로만 사용하고 만들어서 사용해라(사이드 이펙트)
const r = ({a,b, ...rest}) => rest;

const p = {a: 3, b : 4, c :5, d: 8};

const a = r(p)

p !== a

Structured Design

높은 응집도, 낮은 결합도

  1. 높은 응집도

    • 배열을 처리하기 위해서 다른 메소드를 부르는게 아니라 배열의 내장메소드를 이용한다
    • Math 내장객체는 높은 응징도(수학에 관련된 모든 함수)
    • 어떤 함수를 처리하기 위해 여러 함수를 호출하는게 아니라 하나의 함수만으로 처리한다
  2. 낮은 결합도

    • 어떤 함수를 사용하려면 앞에 40개의 함수를 가지고 있어야 해 높은 결합도
    • Math 함수 ⇒ floor round (필요할때 가져다가 쓴다 = 의존성이 제로)

COUPRING

  1. 정의

    • 의존성보다는 더 포괄적인 의미를 가지고 있다.
    • 의존성은 방향을 가지고 잇다. 커플링은 둘이 의존을 양쪽에서 하고 있다.
  2. CONTENT - 강결합

    • A클래스 속성 v가 변경되면 즉시 B클래스 깨짐
    • B클래스에서 A클래스의 속성을 다 볼수 있기 때문에
    • 이렇게 대부분이 코딩을 하고 있으며, 하면 안된다.
const A = class {
	 constructor(v){
		this.v = v;
	}
}

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

const b = new B(new A(3));
  1. COMMON - 강결합

    • COMMON이란 전역객체, 공유객체, 인메모리에 안에 있는 객체를 의미한다.
    • 1:1 구조를 COMMON으로 바꾼것일 뿐
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 B(new Common(3));
  1. External 강결합

    • 이 결합은 피할수 없다 정복해야 한다
    • member.json에 의존적이라서 어쩔수 없다
    • swagger 같은 것이 있어서 키랑 응답값에 대해서 정의
    • 키가 없거나 다를 경우를 대비해서 throw 처리를 해줘야 한다.
const A = class{
	constructor(member){
		this.v = member.name;
	}
};

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

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

    • A 클래스 내부의 변화는 B클래스의 오작동을 유발
    • flag를 기준으로 proces를 처리하기 때문에 문제가 많다.
    • 팩토리 패턴에서 자주 발생되는 문제이며, 전략 패턴으로 해결해야한다.
const A = class {
	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){
		this.a.process(2, data);		
	}
};

const b = new B(new A());
b.noop();
b.echo("test");
  1. STAMP - 강결합 or 유사약결합

    • A와 B는 ref로 통신함 ref에 의한 모든 문제가 발생할 수 있음
    • A클래스는 단순히 add라는 행위에 초점을 둬야 하는데 객체로 받아오면 객체의 key가 변경이되면 오류 발생
    • B클래스에서는 count 그 값자체만 주고 update는 본인이 해야함
const A = class{
	add(data){
		data.count++;
	}
};

const B = class{
	constuctor(counter){
		this.counter = counter;
		this.data = { a : 1, count : 0};
	}
	count(){
		this.counter.add(this.data);
	}
};

const b = new B(new A());
b.count();
b.count();
  1. DATA - 약결합

    • A와 B는 value로 통신함 모든 결합문제에서는 자유로워짐
    • 하지만 A클래스에서 당연히 값이 온다고 가정했기 떄문에 데이터에 대한 커플링 발생
    • 루틴간 통신하려고 할때는 값으로!!
const A = class{
	add(count){
		return count++;
	}
};

const B = class{
	constuctor(counter){
		this.counter = counter;
		this.data = { a : 1, count : 0};
	}
	count(){
		this.data.counter = this.counter.add(this.data.count);
	}
};

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

COHESION

  1. COINCIDENTAL(우연히)

    • Util 같이 메소들이 아무런 관계가 없음. 다양한 이유로 수정됨
    const Util = class {
    	static isConnect(){}
    	static log(){}
    	static isLogin(){}
    }
  2. LOGICAL

    • 사람이 인지할 수 있는 논리적 집합. 언제나 일부만 사용됨.
    • 동등한 지식을 가진 사람이 인식할 수 있는 수준의 응집된 함수의 모임
    • 도메인이 일반적이고 누구든지 알수있다면 진행(Math, URL)
    const Math = class{
    	static sin(r){}
    	static cos(r){}
    	static random(){}
    	static sqrt(v){}
    }
  3. TEMPOLAL

    • 시점을 기준으로 관계없는 로직을 묶음.
    • 관계가 아니라 코드의 순서가 실행을 결정
    • 역할에 맞는 함수에게 위임해야 함.
    const App = class{
    	init(){
    		this.db.init();
    		this.net.init();
    		this.asset.init();
    		this.ui.start();
    	}
    }
  4. PROCEDURAL

    • 외부에 반복되는 흐름을 대체하는 경우
    • 순서정책변화에 대응불가
    const Account = class{
    	login(){
    		p = this.ptocken();
    		s = this.stoken(p);
    		if(!s) this.newLogin();
    		else this.auth(s);
    	}	
    }
  5. COMMUNICATIONAL

    • 하나의 구조에 대해 다양한 작업이 모여있음.
    • 배열처럼 push/pop/slice 하나의 목적
    • 하나의 객체가 하나의 역할을 수행하는것이 좋다.
    const Array = class{
    	push(v){}
    	pop(){}
    	shift(){}
    	unshift(){}
    }
  6. SEQUENTIAL

    • 실행순서가 밀접하게 관계되며 같은 자료를 공유하거나 출력결과가 연계됨
    • 프로시져와 커뮤니케이션의 복합체, chainning 함수
    const Account = class{
    	ptocken(){
    		return this.pk || (this.pk = IO.cookie.get("ptocken"));
    	}
    	stoken(){
    		if(this.sk) return this.sk;
    		if(this.pk){
    			const sk = Net.getSessionFromProken(this.pk);
    			sk.then(v => this.sk);
    		}
    	}
    	auth(){
    		if(this.isLogin) return;
    		Net.auth(this.sk).then(v => this.isLogin)
    	}
    }
  7. FUNCTIONAL

    • 역할모델에 충실하게 단일한 기능이 의존성 없이 생성된 경우

결합도와 응집도는 서로가 다른 방향으로 향하게 되므로 둘 사이의 밸런스를 찾는 것이다.

추가

  1. 순수한 함수를 만들때 this가 필요해?

    • 함수는 에로우로 만들자
    • 메소드는 클래스 문법으로 만들자
  2. 자바스크립트는 리턴값을 정의하지 않으면 무조건 undefined가 된다
  3. undefined의 두가지

    • new Array(10) ⇒ 길이가 10인 undefiend
    • var a = undefined ⇒ 값이 undefiend
  4. es6부터는 객체의 키값이 선언한 순서대로 순서를 보장한다

Written by Junho You 배운것을 기록하자