개발하는 리프터 꽃게맨입니다.
[C++/디자인패턴] 디자인 패턴 및 소프트웨어 개발 원칙 본문
디자인 패턴이란?
처음에 프로그래밍에 입문했을 때 이런 말을 들었습니다.
'좋은 코딩 습관을 들여라'
여기서 좋은 코딩 습관이란 사람마다 생각이 다 다르겠지만,
저는 가독성이 좋은 코드를 작성하는 것이 좋은 코딩 습관이라고 생각합니다.
버그나 오류가 많은 것도 나쁜 코드겠지만, 성능이 좋다고 하더라도 나만 알아보거나 나조차도 못 알아보는 코드는 아무래도 좋은 코드가 아니겠죠. 그러나 작은 규모의 프로그램을 작성해도 설계를 할 때 있어서 실수나 문제를 피하기는 어렵습니다.
프로그램 설계에 있어 자주 발생하는 문제를 피하고, 좋은 코드를 지향하기 위해서 만들어진 설계 패턴이 디자인 패턴입니다.
컴퓨터 과학은 수십년간 발전을 이뤄왔기 때문에 내가 겪은 문제를 다른 사람이 겪지 않았을 확률은 매우 낮습니다.
그래서 전문가들이 경험을 토대로 많은 일종의 좋은 설계 패턴, 베스트 프랙티스가 디자인 패턴이라는 것이죠.
물론 디자인 패턴은 하나의 방법론일 뿐이기에 상황에 따라 필요한 곳에만 적용하는 것이 중요합니다.
오히려 무분별한 패턴의 과사용이 코드의 간결성과 가독성을 역으로 해칠 수 있기 때문이죠.
다음 포스팅부터 유명하고 실용적인 디자인 패턴을 하나하나 소개해보도록 하겠습니다.
나머지 포스팅은 소프트웨어 개발 원칙에 대해서 몇 가지 다루고 포스팅을 끝내도록 하겠습니다.
KISS 원칙
Keep It Simple, Stupid
의역) 간결하게 해, 멍청이야
소프트웨어를 설계할 때, 되도록이면 간단하고 단순하게 만드는 것이 좋다는 원리입니다.
소스 코드나 설계의 내용이 불필요하게 복잡해지는 것은 지양해야 한다는 의미죠.
만약 간단하게 구현할 수 있는 기능이라면, 단순하게 코드 몇 줄로 해결하면 됩니다.
굳이 불필요하게 디자인 패턴을 사용할 필요도 없고, 새롭거나 흥미롭다는 이유만으로 패턴을 사용하거나 모든 설계를 디자인 패턴으로 때우는 행위 또한 지양해야 합니다.
좋은 디자인 패턴을 몇 개 알아서 꼭 필요한 곳에만 사용하시길 바랍니다.
디자인 패턴은 엄격하게 지켜야 할 규칙이라기 보단 새로운 코드 정리 방식에 대한 지침으로 보는 것이 올바릅니다.
YAGNI 원칙
You Ain't Gonna Need It
의역) 그거 안필요할걸?
프로그램을 작성하다 보면 현재는 사용하지 않지만 확장성을 고려해서 미리 작업해 놓는 경우가 있는데, 그런 작업들을 하지 말라는 원칙입니다.
현재는 사용하지 않지만 미래 어느 시점에 사용될지도 모를 코드를 작성해 놓으면 코드가 불필요하게 장황해집니다.
당장 필요한 적업에 집중하고 쓸데없는 작업은 하지 않는 것이 중요하다는 원칙입니다.
DRY 원칙
Do not Repeat Yourself
의역) 반복하지 마라
소스코드에서 동일한 코드가 반복이 된다는 것은 유지 보수에 있어서 위험한 상황입니다.
만약 반복되는 코드 내용이 변결될 경우, 반복되는 모든 코드에 접근해서 코드를 수정해야 하고 이 과정에서 실수가 발생할 수도 있죠.
때문에 2~3번 이상 코드가 반복된다 싶으면 함수로 처리하는 것이 좋습니다.
역으로 재활용성이 없는 코드를 굳이 함수로 처리하는 것도 지양해야 할 코딩습관이죠.
SOLID 원칙
SOLID 원칙은 소프트웨어 설계에서 지켜야 할 다섯 가지 핵심 원칙을 뜻합니다.
유연하고 관리하기 쉬운 객체 지향 설계를 추구하기 위해 명심해야 하는 다섯 가지 원칙이라 생각하면 됩니다.
1) 단일 책임 원칙 (Single Responsibility Principle)
하나의 객체는 반드시 하나의 동작만의 책임을 갖는다.
모듈화가 강해질수록 다른 객체에 대한 의존/연관성이 줄어듭니다.
그렇기에 하나의 객체에 모든 기능을 때려 박기보다는
하나의 객체가 하나의 동작만을 정확히 수행하도록 하는 게 중요합니다.
이러면 하나의 객체에 책임 과중을 피할 수 있습니다.
2) 개방 폐쇄 원칙 (Open-Closed Principle)
객체의 확장은 개방적으로,
객체의 수정은 폐쇄적으로.
기능이 변하거나 확장은 가능하지만, 해당 기능의 코드는 수정하면 안 된다는 것을 뜻합니다.
우리가 라이브러리를 사용할 때, 라이브러리의 내부 코드를 직접 건드리지는 않죠.
그냥 떼서 사용하고 필요 없으면 기능을 사용하지 않는 식으로 코딩합니다.
우리가 만드는 프로그램에서도 동일한 방식으로 설계할 수 있도록 노력해야 합니다.
3) 리스코프 치환 원칙 (Liskov Substitution Principle)
부모 객체와 이를 상속한 자식 객체가 있을 때,
부모 객체를 호출하는 동작에서 자식 객체가 부모 객체를 완전히 대체할 수 있다는 원칙
리스코프 치환 원칙은 올바른 상속관계를 위한 원칙으로
자식 객체의 확장이 부모 객체의 방향을 온전히 따르도록 권고하는 원칙입니다.
4) 인터페이스 분리 원칙 (Interface Segregation Principle)
객체의 자신이 호출하지 않는 메서드에 의존하지 않아야 한다는 원칙입니다.
구현할 객체에서 무의미한 메서드의 구현을 방지하기 위해 반드시 필요한 메서드만을 상속/구현하는 것을 지향합니다.
부모에서 너무 많은 메서드를 미리 구현해놓고, 자식이 그것을 상속한다면
불필요한 메소드 또한 자식이 상속받기 때문이죠.
5) 의존성 역전 원칙 (Dependency Inversion Principle)
객체는 저수준 모듈보다 고수준 모듈에 의존해야 한다는 원칙입니다.
고수준 모듈이란 '인터페이스'와 같은 객체의 형태나 추상적인 개념을 뜻하고
저수준 모듈이란 '구현된 객체'를 뜻합니다.
즉, 가급적 객체~객체의 상속보다는
객체~인터페이스 간의 상속을 지향해야 한다는 의미로 해석할 수 있습니다.
인터페이스에 대해서는 해당 링크의 하단에 정리해 놨습니다.
https://powerclabman.tistory.com/33
의존성 역전 원칙은 경직된 객체보다 구현되지 않아 유연한 인터페이스가 더욱 확장 가능성이 높다는 것을 의미합니다.
마치며
해당 내용을 공부하면서 '객체 지향'에 있어서 허술한 코딩을 하고 있었음을 깨달을 수 있었습니다.
저를 포함하여 많은 프로그래머들이 OO을 구현하는데 더 많은 노력을 기울입니다.
그러나 결과물을 만든다 해도 내부 코드가 엉망진창이면 유지 보수 및 협업할 때 힘들겠죠?
다음 포스팅부터는 효과적인 디자인 패턴 및 베스트 프랙티스에 대해서 추가적으로 포스팅해 보겠습니다.
'기타 개발 지식 > 디자인패턴' 카테고리의 다른 글
[C++/디자인패턴] 커맨드 패턴 (Command Pattern) (1) | 2024.01.29 |
---|---|
[C++/디자인패턴] 옵저버 패턴 (Observer) (1) | 2024.01.29 |
[C++/디자인패턴] 상태 패턴 (State Pattern) (0) | 2024.01.28 |
[C++/디자인패턴] 싱글톤 (Singletone) (1) | 2024.01.27 |
[C++/디자인패턴] 팩토리 메소드 패턴 (2) | 2024.01.27 |