paint-brush
简练代码怎么用:TS 中的集中化部门职责、发展/截获、里氏替代品 SOLID 准绳 [第 4 部分] 颠末@alenaananich
4,720 讀數
4,720 讀數

简练代码:TS 中的单一职责、开放/封锁、里氏替代 SOLID 准绳 [第 4 局部]

颠末 Alena Ananich7m2023/11/09
Read on Terminal Reader

太長; 讀書

在本文中,咱们将经由过程现实例子来领会三个 SOLID 准绳:单一义务准绳、开闭准绳和里氏替代准绳。
featured image - 简练代码:TS 中的单一职责、开放/封锁、里氏替代 SOLID 准绳 [第 4 局部]
Alena Ananich HackerNoon profile picture


之前的局部:


你们正处于不断地斟酌使你们的编码清潔、矫捷和可护理的具体方法。这一刻,让你们起头研究清潔的结构净化处理计划表。


SOLID 准绳由 Robert C. Martin 提出了,被多见的一位是朝着手段程序语言和电脑软件构想的最后策略。


在从文中中,让我们将所经历程实现例子来学透3个 SOLID 准绳:唯一岗位工作职责准绳、開放/入侵准绳和里氏重复使用准绳。

目次:

  1. 单一义务准绳
  2. 开闭道理
  3. 里氏替代准绳

1.单一职责准绳(SRP)

一位类应有唯有一位的变化的来由


近义句,个类还应有单独的责职或主线任务。这很包括,考虑到拥有单独责职的类更草率懂的、点窜和保障。编码另一地的发生变化不容易触及所有 系统,得以减退了引出不足的安全风险。


让咱俩看1个真实的实例和严格执行单调岗位责任准绳的的方式:
 // Bad class UserSettingsService { constructor(user: IUser) { this.user = user; } changeSettings(settings: IUserSettings): void { if (this.isUserValidated()) { // ... } } getUserInfo(): Promise<IUserSettings> { // ... } async isUserValidated(): Promise<boolean> { const userInfo = await this.getUserInfo(); // ... } }
这里例子中,我们是的类在本质区别标有意图上落实操作:它使用强弱文、转变强弱文并考资格证书它。


为了能依照 SRP,我们一起要各分为这种差别人岗位责任制。
 // Better class UserAuth { constructor(user: IUser) { this.user = user; } getUserInfo(): Promise<IUserSettings> { // ... } async isUserValidated(): boolean { const userInfo = await this.getUserInfo(); // ... } } class UserSettings { constructor(user: IUser) { this.user = user; this.auth = new UserAuth(user); } changeSettings(settings: IUserSettings): void { if (this.auth.isUserValidated()) { // ... } } }


它为甚么如斯主要?

SRP 有何意义开展码怎么用方案化,更大局限地核减这样离不开性造成 的挑衅。依靠之时 将码怎么用结构成函数值、男友分手的类并提高方案化,它开始变得倍增可应用,因此节流了要和和和和破费在从头到尾项目编码目前好处上的之时 。

2. 开闭道理(OCP)

軟件线下实体(类、传感器、方程)应有对壮大好放,但对点窜封禁


您应当够其实其实其实其实在没有更变目前有编码的自然环境下增添新好处。这很其主要,可能途经的时候遵从此准绳,您够其实其实其实向系统引出新好处或应用程序,而不能有非常严重目前有编码的不会改变性。


它持续发展了码的可选用性,并严控了增加的功效时开始成批浮动的要。
 // Bad class Product { id: number; name: string[]; price: number; protected constructor(id: number, name: string[], price: number) { this.id = id; this.name = name; this.price = price; } } class Ananas extends Product { constructor(id: number, name: string[], price: number) { super(id, name, price); } } class Banana extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } } class HttpRequestCost { constructor(product: Product) { this.product = product; } getDeliveryCost(): number { if (product instanceOf Ananas) { return requestAnanas(url).then(...); } if (product instanceOf Banana) { return requestBanana(url).then(...); } } } function requestAnanas(url: string): Promise<ICost> { // logic for ananas } function requestBanana(url: string): Promise<ICost> { // logic for bananas }

在这个例子中,题目出在HttpRequestCost类中,该类的getDeliveryCost方式中包罗差别范例产物的计较前提,并且咱们对每种范例的产物利用零丁的方式。以是,若是咱们须要增加新范例的产物,咱们应当点窜HttpRequestCost类,这是不宁静的;咱们能够或许或许或许或许会获得意想不到的成果。


为了防止这类环境,咱们应当在Product类中建立一个不带完成的笼统方式request 。详细完成将担当类:Ananas 和 Banana。他们会为本身完成这个请求。


HttpRequestCost将接纳Product类接口前面的product参数,当咱们在HttpRequestCost中通报特定的依靠项时,它已为本身完成了request方式。

 // Better abstract class Product { id: number; name: string[]; price: string; constructor(id: number, name: string[], price: string) { this.id = id; this.name = name; this.price = price; } abstract request(url: string): void; } class Ananas extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } request(url: string): void { // logic for ananas } } class Banana extends Product { constructor(id: number, name: string[], price: string) { super(id, name, price); } request(url: string): void { // logic for bananas } } class HttpRequestCost { constructor(product: Product) { this.product = product; } request(): Promise<void> { return this.product.request(url).then(...); } }


它为甚么如斯主要?

遵照执行该准绳,您将大幅度降低二维码藕合并使采集体系易受切不可展望未来的联合行动的影向。

3.里氏替代道理(LSP)

超类的软件应该能够也许也许也许用其子类的软件代替,而会撕碎巧用欧式。


为了更好地不懂这里事理,人们来看下这里好例子:
 // Bad class Worker { work(): void {/../} access(): void { console.log('Have an access to closed perimeter'); } } class Programmer extends Worker { createDatabase(): void {/../} } class Seller extends Worker { sale(): void {/../} } class Designer extends Worker { access(): void { throwError('No access'); } }

在此示例中,咱们碰到了Contractor类的题目。 DesignerProgrammerSeller都是Worker,他们担当自父类Worker 。但与此同时,设想师无权进入封锁边境,由于他们是承包商,而不是雇员。咱们重写了access方式并突破了里氏替代准绳。


这个准绳告知咱们,若是咱们用它的子类(比方Designer类)替代超类Worker ,功效不应当被粉碎。但若是咱们如许做, Programmer类的功效将被粉碎 - access方式将具备来自Designer类的不测完成。


遵守里氏替代品准绳,让我们不应先重写子类中的做完,往往是需加入新的空泛层,在此中为每类范列的空泛界说目标的做完。


让俺们改正一段时间:
 // Better class Worker { work(): void {/../} } class Employee extends Worker { access(): void { console.log('Have an access to closed perimeter'); } } class Contractor extends Worker { addNewContract(): void {/../} } class Programmer extends Employee { createDatabase(): void {/../} } class Saler extends Employee { sale(): void {/../} } class Designer extends Contractor { makeDesign(): void {/../} }

咱们建立了新的笼统层EmployeeContractor ,并将access方式移至Employee类并界说了详细的完成。若是咱们用子类Contractor替代Worker类, Worker功效将不会被粉碎。

它为甚么如斯主要?

如果是您遵照执行 LSP,则就可以即便即便即便在应该要基类案列的其中核发地用于其中子类案列,如果法式风格仍应按期望神器任务。这就可以即便即便即便增进友谊二维码得到重用、电源工程化,并使您的二维码更能迎合更变。


鄙人一本书本文中,我们一起大将会接口类型失去和依附于搞反 SOLID 准绳。
바카라사이트 바카라사이트 온라인바카라