처음 소프트웨어 개발의 세계에 뛰어들기 시작했을 때 온갖 유행어와 개념에 압도되는 경우가 많았습니다. 특히 어려워 보이는 개념 중 하나는 SOLID 원칙이었습니다. 이는 "진지한" 개발자들만이 걱정해야 할 문제처럼 느껴졌습니다. 하지만 코딩에 점점 익숙해지면서 이러한 원칙은 화려하기보다는 몇 달이 지나도 머리를 뽑고 싶지 않은 코드를 작성하는 것에 더 가깝다는 것을 깨달았습니다.
여기 JavaScript의 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..."); } }
종속성 역전 원칙은 상위 모듈이 하위 모듈에 종속되어서는 안 된다는 것을 명시합니다. 둘 다 추상화에 의존해야 합니다.
Think about how you plug your phone charger into a wall socket. You don’t need to know the details of the electrical wiring inside the walls—all you need is the interface (the socket) to power your device. Similarly, your code should depend on abstractions (interfaces), not concrete implementations.
If you have a LightBulb class that directly controls a Switch class, you’re creating a tight coupling. Instead, both should depend on an interface like 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"); } }
Mastering the SOLID principles is like learning to cook with a set of proven recipes. Once you understand them, you can whip up code that’s not just functional but elegant and easy to maintain. So next time you find yourself in a coding conundrum, remember: there’s a principle for that!
Happy coding! ?
위 내용은 SOLID를 단순하게 만들기: 깔끔한 코드 원칙을 위한 JavaScript 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!