SOLID 원칙

공부의 기록·2022년 10월 21일
0

OOP

목록 보기
1/1

SOLID 원칙은 소프트웨어 작업에서 프로그래머가 소스 코드 가 읽기 쉽고 확장하기 쉽게 될 때까지 소프트웨어 소스 코드를 리팩토링하여 코드 냄새를 제거하기 위해 적용할 수 있는 지침입니다.

SRP

SRP, Single Responsibility Priciple, 은 "모듈, 클래스, 함수는 하나의 책임을 가져야 한다." 라는 뜻입니다.

  • Bad in SRP
function addTwoNumber(num1: number, num2: number): number {
 	const num = num1 + num2;
  
  	console.log(num);
  	return num;
}

const result = addTwoNumber(1, 2);
  • Good in SRP
function addTwoNumber(num1: number, num2: number): number {
	const num = num1 + num2;
  	return num;
}
function printNumber(num: number):void {
    console.log(num);
}

const result = addTwoNumber(1, 2);
printNumber(result);

SRP in class

  • Bad in SRP
class Cat {

	age: number;
    name: string;
  
  	constructor(age: number, name: string) {
        this.age = age;
        this.name = nmae;
	}
  
	eat() { /* eat */ }
  	walk() { /* walk */ }
  	speak() { /* speak */ }
  
  	print() { // Bad
      	console.log({
          	age: this.age,
          	name: this.name
        });
    }
  	
  	log() { // Bad
      	someLogger.log(datetime.now());
    }
  
}
  • Good in SRP
class Cat {

	age: number;
    name: string;
  
  	constructor(age: number, name: string) {
        this.age = age;
        this.name = nmae;
	}
  
	eat(): void { /* eat */ }
  	walk(): void { /* walk */ }
  	speak(): void { /* speak */ }
  
	representation(): { age: number, name: string } {
      	return {
          	age: this.age,
          	name: this.name
        }
    }
  
}

kitty = new Cat();
console.log(kitty.representation());
someLogger.log(kitty.representation());

OCP

OPP, Open Closed Principle, "확장에 대해서는 개방, 수정에 대해서는 폐쇄하라"라는 뜻입니다.

이는 코드에 대한 제한이 아니라, 코드 행동에 대한 원칙입니다.

  • Bad in OCP
class Animal {
  
  	type: string;
  
  	constructor(type: string) {
      	this.type = type;
    }
}

function hey(animal: Animal): void {
  
	if (animal.type === 'cat')
		console.log('meow');
  	else if (animal.type === 'dog')
      	console.log('bark');
  	else
      	throw new Error('Wrong Animal.prototype.type');
}

const kity = Animal('kitty');
const bingo = Animal('Dog');

hey(kitty);
hey(bingo);

/* 새로운 Animal 이 나타나면, hey 를 수정해야 하므로...
 *  새로운 extension(확장) 에 대한 새로운 Modification (수정)
 *  이 필요하므로, OCP 를 위반하고 있다.
 */
  • Good in OCP
class Animal() {
    speak() {
      	throw new Error('Animal.prototype.speak must be override');
    }
}

class Cat() {
  	speak() {
      	console.log('meow');
    }
}

class Dog() {
  	speak() {
      	console.log('bark');
    }
}

function hey(animal: Animal) {
  	animal.speak();
}

const cat = new Cat();
const dog = new Dog();

hey(cat);
hey(dog);

LSP

LSP, Liskov Subsititution Pricinple, 은 "Type S 가 T 의 Sub Type 일 때, object T 는 object S 로 치환 가능하다"라는 뜻입니다.

쉽게 설명하면, 부모와 자식을 변경해도 기능 상에 문제가 없어야 한다는 뜻입니다.

이를 위해서, 일관성 있는 클래스 상속관계를 유지하는 것이 중요합니다.

ISP

ISP, Interface Segregation Principle, 은 다음과 같은 뜻입니다.

1. Client 들은 사용하지도 않는 메서드들에 의존하게 만들면 안된다.
2. Big Interface 들은 Small Interfaces 로 분리하는 것이 좋다.

  • Bad in ISP
interface ICarBoat {

  	drive(): void;
	turnLeft(): void;
  	turnRight(): void;
  
  	steer(): void;
	steerLeft(): void;
	steerRight(): void;
}

class Genesis implements ICarBoat {
  	drive() { /* logic */ }
    turnLeft() { /* logic */ }
    turnRight() { /* logic */ }
  
  	/* 나머지는 불피요함 */
}
  • Good in ISP
interface ICar {
  	drive(): void;
  	turnLeft(): void;
  	turnRight(): void;
}

interface IBoat {
  	steer(): void;
  	steerLeft(): void;
  	steerRight(): void;
}

class SampleCarA implements ICar {}
class SampleBoatA implements IBoat {}
class SampleCarBoatA implements ICar, IBoat {}

DIP

DIP, Dependency Inversion Principle, 은 "loosely coupling software module 의 구체적인 형태" 라고 알려져 있습니다.

  • Basic
class Cat {
  	speak(): void {
      	console.log('meow');
    }
}

class Dog {
   	speak(): void {
      	console.log('bark');
    }
}

class Zoo {
  
  cat: Cat;
  dog: Dog;
  
  constructor() {
    	cat = Cat();
    	dog = Dog();
  }
  
}
  • Dependency Inversion
interface Animal {
  	speak(): void;
}

class Cat implements Animal {
  	speak() {
      	console.log('meow');
    }
}
class Dog implements Animal {
  	speak() {
      	console.log('bark');
    }
}

class Zoo {
  	
  	animals: Array<Animal>;
  
  	constructor(animals: Array<Animal>) {
      	this.animals = animals;
    }
  
  	apendAnimal(animal: Animal): void {
      	this.animals.append(animal);
    }
  
  	speakAll(): void {
      	for (const animal of this.animals) {
          	animal.speak();
        }
    }
  
}

zoo = Zoo();
zoo.addAnimal(Cat());
zoo.addAnimal(Dog());
zoo.speakAll();

References

profile
2022년 12월 9일 부터 노션 페이지에서 작성을 이어가고 있습니다.

0개의 댓글