더 나은 방법이나 틀린 내용이 있을 시에 댓글 남겨주시면 감사하겠습니다.
2022-05-09 작성되었습니다.
SOLID 원칙이란 무엇일까요?
소프트웨어에서의 변화는 쉴 틈 없이 일어나고 있으며,
개발자의 입장에서 요구를 맞춘다던가 새로운 기능을 추가해야 할 일이 너무나도 많습니다.
이러한 끊임없는 변화에서 코드의 가독성, 확장성, 유지보수성 등을 향상시켜 일관성을 갖도록 하는 원칙들이 있습니다.
그중 가장 대표적인 게 객체지향 프로그래밍의 SOLID 원칙입니다.
단순히 어떻게 구현해라!라고 보여주는 것이 아닌 설계하는 방법을 보여주는 원칙이라고 생각합니다.
따라서 어떤 프로그래밍 언어에도 귀속되지 않으나, 코틀린을 사용하는 안드로이드 개발자의 입장에서 풀어보려고 합니다.
Single Responsibility : 단일 책임
Open / Closed : 개방 폐쇄
Liskov Substitution : 리스코프 치환
Interface Segregation : 인터페이스 분리
Dependency Inversion : 의존 역전
1. Single Responsibility Principle
Gather together those things that change for the same reason,
and separate those things that change for different reasons.
Robert C. Martin
단순히 원칙의 이름만 생각했을때, "클래스는 하나의 책임을 가져야 한다"라고 풀이됩니다.
Car.kt라는 클래스를 예시로 들어보겠습니다.
Car 클래스는 자동차에 대한 책임만을 가져야 합니다.
다시 말해서, 자동차의 무게, 색상 등 관련된 속성만을 정의해야 합니다.
자동차의 데이터 모델과 관련 없는 saveCarToPreference라는 함수는 데이터 저장 기능을 정의하고 있습니다.
하나의 책임을 가져야 하는 SRP 원칙에 위배됩니다.
따라서 다음과 같이 수정될 수 있습니다.
2. Open-Closed Principle
확장에 열려 있어야 하고, 변경에 닫혀 있어야 한다.
위 코드는 새로운 자동차를 추가하기 위해서는 더 많은 if-else 문이 필요하게 되며, 변경에 닫혀있다고 볼 수 없습니다.
새로운 자동차가 추가되어 문의 갯수가 변경된다면,
그 유형의 자동차 클래스를 만들고 Car 클래스를 상속받아 doorCount를 재정의하게 만들어줍니다.
3. Liskov Substitution Principle
상호 대체 가능한 구성요소를 이용해 소프트웨어를 만들 수 있으려면 이들 구성 요소는 반드시 서로 치환 가능해야 한다.
printEngineCapacity라는 함수는 엔진의 용량을 출력해줍니다.
그 파라미터가 되는 car에 Bmw, Mini 등 다양한 클래스로 치환되어도 프로그램의 동작은 변하지 않습니다.
4. Interface Segregation Principle
사용하지 않는 것에 의존하지 말아야 한다.
클래스에 의해 구현되는 더 구체적인 인터페이스를 작성해야 한다라고 명시됩니다.
위의 예시에서 Sport 인터페이스는 필요보다 훨씬 더 많은 내용을 가지고 있습니다.
stop()은 모든 스포츠에서 공유될 수 있지만, Swimming 클래스에서 run(), jump() 함수는 사용되지 않습니다.
따라서 더 구체적인 내용으로 인터페이스를 분리해야할 필요가 있습니다.
인터페이스가 분리되어 더 이상 사용하지 않는 기능에 의존하지 않게 되었습니다.
5. Dependency Inversion Principle
고수준 정책을 구현하는 코드는 저수준 세부사항을 구현하는 코드에 절대 의존해서는 안 된다.
추상화가 세부 사항에 의존되는 것이 아닌, 세부 사항이 추상화에 의존되어야 하는 것을 의미합니다.
즉, 의존성은 concretions가 아닌 abstractions에 있어야 합니다.
상단의 코드는 추상화가 아닌 구체적인 객체를 이용하여 처리하고 있습니다.
이를 DIP 원칙에 맞게 수정하여 보겠습니다.
이 코드에서 고수준 및 저수준 모듈은 모두 추상화에 의존하는 것으로 볼 수 있습니다.
물론 이와 같은 코드 작성에는 추가적인 비용이 필요할 수 있겠지만,
코드의 장기적 유지 보수성을 고려해 볼 때, DIP의 이점이 더 크다고 생각됩니다.
'모든 클래스에 반드시 적용하라'라는 것이 아닙니다.
작성된 클래스의 변경의 예측 빈도 수 등을 고려하여 적용하는 것이 좋습니다.
다시 한 번 강조하지만, 이렇게 해야 된다! 는 절대 아닙니다.
그러나 SOLID 원칙은 수많은 개발자들에 의해 검증된 원칙이며, 더욱 더 깔끔하고 명확한 코드를 작성할 수 있음을 보여주고 있습니다.
단순히 글을 몇번 읽는 것만으로 당장 프로젝트에 도입할 수는 없겠지만, 적어도 개발을 하며 객체지향 프로그래밍의 관점에 맞추어 생각할 수 있는 계기가 되었으면 좋겠습니다.
'Object-Oriented Programming' 카테고리의 다른 글
MVVM (Model-View-ViewModel) (0) | 2022.04.08 |
---|