[OOP] 객체 지향 개발 5대 원칙(SOLID)

블루·2022년 9월 14일
0

프론트엔드 개발자 단톡방에서 우연히 oop에 대해 이야기가 오갔습니다. 이를 보고 문득 내가 지금 짜고 있는 코드에 객체 지향 원칙을 적용한다면 어떤 부분을 바꿔야 할까 하는 생각이 들었습니다. 생각을 거듭할수록 내가 객체 지향에 대한 이해가 너무 모호하다는 생각이 들었습니다. 학부 2, 3학년에 자바, 코틀린, 스프링 등을 공부하며 객체 지향에 대해 어느 정도 알고 있다고 자신했지만, 지금 돌이켜 생각해 보니 많이 부족했던 것 같습니다. 그래서 이번 기회에 객체 지향 개발 5대 원칙(SOLID)에 대해 정리해 보려 합니다.

1. SRP(단일 책임 원칙)

소프트웨어의 설계 부품(클래스, 함수 등)은 단 하나의 책임만을 가져야 한다.

나쁜 코드

function emailClients(clients: Client[]){
	clients.forEach((client)=>{
      	const clientRecord = database.lookup(client);
      if(clientRecord.isActive()){
        	email(client);
      }
    })
}

좋은 코드

function emailClients(clients: Client[]){
  	clients.filter(isActiveClient).forEach(email)
}

function isActiveClient(){
  	const clientRecord = database.lookup(client);
  	return clientRecord.isActive()
}

너무나 당연하지만, 막상 코드를 짜거나 유지 보수를 할 때에 이게 잘 보이지가 않습니다. 함수를 들여다볼 때 이 원칙을 생각하며 로직 분리가 가능한지 항상 확인해 봐야겠습니다.

2. OCP(개방-폐쇄 원칙)

기존의 코드를 변경하지 않고 기능을 수정하거나 추가할 수 있도록 설계해야한다.

나쁜 코드

function getMultipledArray(array, option){
 	const result = []
    for(let i=0; i<array.length; i++){
      if(option === 'doubled'){
        result[i] = array[i] * 2
      }
      if(option === 'tripled'){
        result[i] = array[i] * 3
      }
      if(option === 'half'){
        result[i] = array[i] / 2
      }
    }
  	return result
}

좋은 코드

function map(array, fn){
  const result = []
  for(let i=0; i<array.length; i++){
    result[i] = fn(array[i])
  }
  return result
}

const getDoubledArray = (array) => map(array, x => x * 2)
const getTripledArray = (array) => map(array, x => x * 3)
const getHalfArray = (array) => map(array, x => x / 2)

기존 코드의 수정이나 변경은 못하도록 하고, 추가와 확장은 쉽게 가능하게 한다는 원칙입니다. 이 원칙을 보고 저번 프로젝트에서 유지 보수를 진행할 때 기존 코드 내용을 수정하느라 시간이 오래 걸렸던 것이 새록새록 기억납니다😂 이 원칙을 고려해 코드 리팩토링을 진행해야겠습니다.

3. LSP(리스코프 치환 법칙)

자식 클래스는 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다

4. ISP(인터페이스 분리 원칙)

한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다. 하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다

나쁜 코드

interface SmartPrinter {
  print()
  fax()
  scan()
}

class AllInOnePrinter implements SmartPrinter {
 	print(){
      
    }
  
  	fax(){
      
    }
  
  scan(){
    
  }
}

class EconomicPrinter implements SmartPrinter {
  	print(){
      
    }
  
  	fax(){
      throw new Error('Fax not supported.');
    }
  
  	scan(){
      throw new Error('Scan not supported.');
    }
}

좋은 코드

interface Printer {
  print();
}

interface Fax {
  fax();
}

interface Scanner {
  scan();
}

class AllInOnePrinter implements Printer, Fax, Scanner {
  print() {

  }  
  
  fax() {

  }

  scan() {

  }
}

class EconomicPrinter implements Printer {
  print() {

  }
}

5. DIP(의존관계 역전 원칙)

구체화 보다 추상화에 의존해야한다




참고자료
https://velog.io/@lsb156/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EB%8C%80-%EC%9B%90%EC%B9%99-SOLID
https://velog.io/@teo/Javascript%EC%97%90%EC%84%9C%EB%8F%84-SOLID-%EC%9B%90%EC%B9%99%EC%9D%B4-%ED%86%B5%ED%95%A0%EA%B9%8C
https://dev-momo.tistory.com/entry/SOLID-%EC%9B%90%EC%B9%99
https://github.com/labs42io/clean-code-typescript

profile
개발 일지를 작성합니다

0개의 댓글

관련 채용 정보