처음 소프트웨어 개발의 세계에 뛰어들기 시작했을 때, 나는 종종 떠도는 온갖 유행어와 개념에 압도당했습니다. 특히 어려워 보이는 개념 중 하나는 SOLID 원칙이었습니다. 이는 "진지한" 개발자들만이 걱정해야 할 문제처럼 느껴졌습니다. 하지만 코딩에 점점 익숙해지면서 이러한 원칙은 화려하기보다는 몇 달이 지나도 머리를 뽑고 싶지 않은 코드를 작성하는 것에 더 가깝다는 것을 깨달았습니다.
자바스크립트의 SOLID 원칙에 대한 제 견해는 다음과 같습니다. 처음 시작할 때 갖고 싶었던 실용적이고 실용적인 가이드입니다.
단일 책임 원칙은 클래스가 변경해야 할 이유가 하나만 있어야 한다고 명시합니다. 즉, 클래스에는 하나의 작업이나 책임만 있어야 한다는 의미입니다.
당신이 가장 좋아하는 커피숍의 바리스타를 생각해 보세요. 그들의 직업은 커피를 만드는 것입니다. 갑자기 에스프레소 머신을 수리하고, 페이스트리를 제공하고, 쓰레기를 버리기 시작하면 상황이 혼란스러워질 것입니다. 바리스타가 커피를 만드는 데 집중해야 하는 것처럼, 수업도 한 가지 일을 잘하는 데 집중해야 합니다.
사용자 인증, 데이터 검증, 데이터베이스 저장을 처리하는 User 클래스가 있다고 상상해 보세요. 너무 많은 일을 하고 있어요! 이러한 책임을 별도의 클래스로 나누면 코드를 더 쉽게 관리하고 유지할 수 있습니다.
class UserAuthenticator { login(user) { // handle login } } class UserDataValidator { validate(user) { // validate user data } } class UserDatabase { save(user) { // save user to the database } }
개방/폐쇄 원칙은 소프트웨어 엔터티가 확장을 위해 개방되어야 하고 수정을 위해 폐쇄되어야 한다고 명시합니다. 즉, 기존 코드를 변경하지 않고도 새로운 기능을 추가할 수 있어야 합니다.
당신이 가장 좋아하는 게임 콘솔을 상상해보세요. 새로운 게임, 컨트롤러, 액세서리를 추가할 수 있지만 이를 위해 열어서 다시 연결할 필요는 없습니다. 마찬가지로 핵심 구조를 변경하지 않고도 코드에 새로운 기능을 추가할 수 있어야 합니다.
면적을 계산하는 메서드가 포함된 Shape 클래스가 있다고 가정해 보겠습니다. 삼각형과 같은 새로운 모양을 추가해야 하는 경우 기존 클래스를 수정할 필요가 없습니다. 대신 확장하세요.
class Shape { area() { throw "Area method not implemented"; } } class Rectangle extends Shape { constructor(width, height) { super(); this.width = width; this.height = height; } area() { return this.width * this.height; } } class Circle extends Shape { constructor(radius) { super(); this.radius = radius; } area() { return Math.PI * this.radius * this.radius; } }
리스코프 대체 원칙은 프로그램의 정확성에 영향을 주지 않고 슈퍼클래스의 객체를 서브클래스의 객체로 대체할 수 있어야 한다고 명시합니다.
자동차를 렌트한다고 상상해 보세요. 세단이든 SUV이든 자동차의 기본 기능, 즉 운전, 조향, 정지 기능을 갖기를 기대합니다. 렌트카에 완전히 다른 제어 장치가 필요한 경우 문제가 발생할 수 있습니다! 마찬가지로, 하위 클래스는 상위 클래스가 설정한 기대치를 깨뜨리지 않는 방식으로 작동해야 합니다.
Bird 클래스와 이를 확장하는 Penguin 클래스가 있는 경우 Penguin은 날 수 없더라도 여전히 Bird처럼 동작해야 합니다. 여전히 걷고, 먹고, 수영할 수도 있습니다.
class Bird { move() { console.log("Flies in the sky"); } } class Penguin extends Bird { move() { console.log("Swims in the water"); } } const myBird = new Bird(); const myPenguin = new Penguin(); myBird.move(); // Flies in the sky myPenguin.move(); // Swims in the water
인터페이스 분리 원칙은 클라이언트가 사용하지 않는 인터페이스를 구현하도록 강요해서는 안 된다고 제안합니다. 하나의 큰 인터페이스를 사용하는 대신 더 작고 구체적인 인터페이스를 만들어야 합니다.
셰프가 웨이터, 바텐더, 식기 세척기도 겸직해야 하는 레스토랑을 상상해 보세요. 너무 부담스럽고 비효율적이에요! 대신 각 역할에는 특정 작업이 있어야 합니다. 마찬가지로 인터페이스도 전문화되고 집중되어야 합니다.
buildHouse, PaintHouse, designHouse와 같은 메서드를 포함하는 Worker 인터페이스가 있는 경우 집만 칠하는 작업자는 다른 모든 메서드를 구현할 필요가 없습니다. 더 작은 인터페이스로 나누세요.
class Builder { build() { console.log("Building house..."); } } class Painter { paint() { console.log("Painting house..."); } } class Designer { design() { console.log("Designing house..."); } }
종속성 역전 원칙은 상위 수준 모듈이 하위 수준 모듈에 의존해서는 안 된다는 것을 명시합니다. 둘 다 추상화에 의존해야 합니다.
휴대폰 충전기를 벽면 콘센트에 연결하는 방법을 생각해 보세요. 벽 내부의 전기 배선에 대한 세부 사항을 알 필요는 없습니다. 장치에 전원을 공급하기 위한 인터페이스(소켓)만 있으면 됩니다. 마찬가지로, 코드는 구체적인 구현이 아닌 추상화(인터페이스)에 의존해야 합니다.
Switch 클래스를 직접 제어하는 LightBulb 클래스가 있는 경우 긴밀한 결합을 생성하게 됩니다. 대신 둘 다 PowerSource와 같은 인터페이스에 의존해야 합니다.
class LightBulb { turnOn(powerSource) { powerSource.provideElectricity(); console.log("Light is on"); } } class Switch { constructor(powerSource) { this.powerSource = powerSource; } operate() { this.powerSource.togglePower(); } } class PowerSource { provideElectricity() { console.log("Providing electricity"); } togglePower() { console.log("Toggling power"); } }
SOLID 원리를 익히는 것은 검증된 레시피 세트로 요리하는 법을 배우는 것과 같습니다. 일단 이해하고 나면 기능적일 뿐만 아니라 우아하고 유지 관리하기 쉬운 코드를 만들 수 있습니다. 그러니 다음에 코딩 문제에 직면하게 된다면, 여기에는 원칙이 있다는 점을 기억하세요!
즐거운 코딩 되세요! ?
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3