当我第一次开始涉足软件开发世界时,我经常发现自己被周围飞来飞去的流行语和概念淹没。似乎特别令人畏惧的概念之一是“坚实的原则”。感觉就像只有“认真的”开发人员才需要担心的事情。但随着我对编码越来越熟悉,我意识到这些原则并不是花哨,而是编写不会让你在几个月后就想抓狂的代码。
所以,这是我对 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 接口,则仅粉刷房屋的 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中文网其他相关文章!