본문 바로가기

TDD, CleanCode

클린코더스 강의 리뷰 1. OOP

https://www.youtube.com/watch?v=60lLSe1phks&list=PL7pUrjEGbG8ZMPQ-XukPJsFyMeyvtGcnV&index=1

해당 유튜브 강의를 바탕으로 작성된 글입니다.

 

이제서야 Clean Code가 얼마나 중요한 지 깨달았지만, 막상 내가 제대로 작성하고 있는지, 규칙을 잘 지키고 있는지 알 수 없었다. 예시를 찾다가 git에서 많은 개발자분들이 위 강의를 듣고 연습을 하고 계시더라.

 

1. Why OOP(절차지향과 객체지향 사고)

 

< 절차지향적 사고 >

절차 지향적 사고는 하나의 커다란 데이터를 여러 기능들이 꺼내서 사용하는 방식을 의미한다. (이제까지 클래스를 사용하기만 한다면 객체지향이라고 생각했다.) 이러한 방식은 기능 하나를 추가하기는 쉽다. 하지만, 데이터를 하나 수정하기 위해서 많은 기능들을 일일이 수정해야할 가능성이 있다.

< 객체지향적 사고 >

반대로 객체지향적이라는 것은 객체가 그 기능(역할)을 스스로 수행한다. 객체는 데이터를 가지는 역할이 아니라 스스로 자신의 데이터를 가공하고 관리하여 사용자에게 직접 출력한다. 뿐만 아니라 객체는 다른 객체의 영향을 미치지 않는다. 그렇기 때문에, 각각의 객체들은 다른 데이터에 영향을 받지 않아, 쉽게 데이터를 추가할 수 있다.

 

2. Object의 책임과 역할

다음은 객체를 어떠한 관점으로 설계하는가이다. 상태나 행위의 관점이 아닌 객체들의 책임과 역할의 관점으로 설계를 하는 것이 옳다고 한다. 역할은 사용하는 기능으로 브리핑 되는 유저의 그룹(로그인 사용자, 비로그인 사용자, 운영자)으로 불릴수 있는 것을 뜻하고 그 역할이 필요한 기술들을 기능이라고 한다고 한다.

 

3. 절차지향과 객체지향 비교 (캡슐화)

< 밀리세컨드로 지원하는 스톱워치 >

해당 스톱워치는 startTime과 stopTime을 공개한 후에 셋팅을 해주고 있다.(setter를 사용하는 것과 똑같음) 그리고 getElapsedTime을 이용하여 시간차를 계산한다. 이때 nano지원을 추가한다고 가정하자.

< nano추가 >

다음처럼 nano초에 대한 변수와 함수를 추가해 주어야 한다.

< 실행 코드 >

그 이후에 나노초로 바꾸기 위해서 다음 드래그가 된 모든 부분을 고쳐야 한다.

< 객체지향적으로 코딩한 밀리세컨드 스톱워치 >

다음 코드는 객체지향적으로 설계된 코드이다. start와 stop메소드를 이용하여 값을 셋팅한다.(이때 밖에서는 start가 도대체 뭘 하고 있는지 모르는게 핵심) 이는 setter접근과는 다르게 값에 직접적으로 접근하는 것이 없다. 이후에 getElapseTime은 stopTime과 startTime을 뺀 값으로 Time 객체를 생성한다. 그리고 Time 객체의 메소드를 통해서 MilliTime으로 반환된 값을 결과로 얻는다.

이와 같은 코드는 단지 Time객체의 메소드만 추가해주면 된다. 메인 함수 역시 Time객체의 메소드를 호출 해주기만 하면 된다.

< 객체 지향 작성 요령 >

다음과 같이 코드를 작성하려면 다음 처럼 작성하라고 한다. 특히 데이터를 요청해서 변경하고 저장하라고 하지말고 무슨 기능을 실행하라라는 말이 가장 와닿는다.

 

4. 다형화

다형화라는건 다음과 같이 하나의 클래스가 다른 클래스로 정의 될수 있는 것을 의미한다. 이 때, 수퍼 타입을 통해 부모클래스의 기능을 자식클래스에서 사용할 수 있는 것이 다형성이라고 착각하는 경우가 있는데 아니라고 한다.

 

5. 추상화

< concrete class를 직접 사용 >

collector는 FtpLogCollector의 객체이다. 그런데 만약 그 방식이 달라진다면 다음과 같은 코드는 FileLogCollector의 객체를 다른 방식으로 바꾸어야 한다.

< 인터페이스를 이용한 추상화 > 

인터페이스로 LogCollector의 종류를 모두 처리하는 LogCollector클래스를 만들어 놓으면 인스턴스만 수정하면 처리가 된다.

이를 만약 LogFactory와 같은 메소드로 구현한다면 더욱 유지보수하기 용이해 진다고 한다.

왼쪽은 process 메소드 안에서 변수들에 객체와 값을 할당 해주었다.

오른쪽은 생성자로 파라미터를 외부에서 받아 초기화한다.

왼쪽이 파라미터를 적게 받기 때문에 깔끔해보이지만, 오른쪽은 외부에서 값을 넘겨주기 때문에 수정이 있을 경우 로직을 수정할 일이 없어진다.

 

LuggageCompartment는 ArrayList<Luggage>를 상속받는다.

그리고 Luggage의 빈공간을 하나 만드는 extract 메소드가 있다.

하지만 ArrayList를 상속받아 remove함수를 실수로 잘못 사용한 경우이다.

이 결과 restSpace는 적용되지 않는다.

오른쪽은 List<Luggage>를 private 변수로 받았다. 이로써 extract 대신 remove로 실수로 사용할 일이 없다.