SOLID 时代,我最幸运
程序的目标是不是很坚固?我不担心,但我想说明一下我们的例子,但我们并没有对此进行深入研究。
什么是 SOLID?
作为面向对象的程序,从 设计的角度来看, SOLID 一词是 为了 帮助理解、开发和制造软件。
我们结合原则,不减少错误的产生,提高编码的质量,组织编码的生产,减少附件,改善编码并重新评估编码。
S - Princípio da responsabilidade única
SRP——单一职责原则
阶级发展的本质、意义、动机
这是所有的功能和责任的变数。 Provavelmente você já fez ou se deparou com alguma classe que faz de tudo um pouco, a tal da God Class .这是一个非常重要的时刻,需要解决逻辑问题并解决问题。
God Class - Classe Deus: 一个面向对象的程序,是一个可以使用的类或常用的类。
class Task {
createTask(){/*...*/}
updateTask(){/*...*/}
deleteTask(){/*...*/}
showAllTasks(){/*...*/}
existsTask(){/*...*/}
TaskCompleter(){/*...*/}
}
该类任务是SRP的基本任务,是四个不同的任务。该任务可用于执行、显示、验证和验证任务。
问题是这样的:
Falta de nexo
- uma classe não deve Assumir responsabilidades que não são suas;Muita informação junta
- sua classe vai ficar com muitas dependentências e uma grande diificuldade para alterações;Dificuldades na implementação de testes automatizados
- “mockar”的困难是 经典的;
Agora 应用SRP类任务,其原理如下:
class TaskHandler{
createTask() {/*...*/}
updateTask() {/*...*/}
deleteTask() {/*...*/}
}
class TaskViewer{
showAllTasks() {/*...*/}
}
class TaskChecker {
existsTask() {/*...*/}
}
class TaskCompleter {
completeTask() {/*...*/}
}
Daria 可以创建、更新和删除各个类,它们依赖于上下文和项目以及所需的复杂性。
如果您不这样做,请按照以下方法和功能进行相反的操作só vou conseguir aplicar isso em classes?
。
//❌
function emailClients(clients: IClient[]) {
clients.forEach((client)=>{
const clientRecord = db.find(client);
if(clientRecord){
sendEmail(client);
}
})
}
//✅
function isClientActive(client: IClient):boolean {
const clientRecord = db.find(client);
return !!clientRecord;
}
function getActiveClients(clients: IClient[]):<IClient | undefined> {
return clients.filter(isClientActive);
}
function emailClients(clients: IClient[]):void {
const activeClients = getActiveClients(clients);
activeClients?.forEach(sandEmail);
}
Código mais bonito,优雅和组织。基本原理是作为结尾的基础,因此您可以轻松地使用它来获得资格,轻松地休闲和轻松地进行操作。
O - 开放日期原则
OCP-开放封闭原则
对象或实体的原则是扩展、修改、必要的附加功能和功能,并且不能更改字体。
想象一下,在学校秘书处的小系统中,存在两个班级,代表着学生的一个等级,基本的和中等的。 Além de uma classe que é para definir as aulas do aluno。
class EnsinoFundamental {
gradeCurricularFundamental(){}
}
class EnsinoMedio {
gradeCurricularMedio(){}
}
class SecretariaEscola {
aulasDoAluno: string;
cadastrarAula(aulasAluno){
if(aulasAluno instanceof EnsinoFundamental){
this.aulasDoAluno = aulasAluno.gradeCurricularFundamental();
} else if(aulasAluno.ensino instanceof EnsinoMedio){
this.aulasDoAluno = aulasAluno.gradeCurricularMedio();
}
}
}
一个类SecretariaEscola
的响应验证是否有足够的能力以将其应用到地籍中。 Agora 想象一下,如果你对技术和技术有很高的要求,那么在没有系统的情况下,你需要对课程进行修改,然后就可以了,所以你会遇到一些问题,或者是小提琴或坚固Princípio Aberto-Fechado
的东西。
有什么解决办法吗? Provavelmente adicionar um else if
na classe e pronto,问题已解决。 Não pequeno Padawan 😐,这是问题!
在新的辅助工具中,我们将介绍一些新的错误,并介绍一些新的功能。
Lembre-se: OCP 可以提供更改和扩展的权限。
Veja a beleza que fica ao refatorar o código:
interface gradeCurricular {
gradeDeAulas();
}
class EnsinoFundamental implements gradeCurricular {
gradeDeAulas(){}
}
class EnsinoMedio implements gradeCurricular {
gradeDeAulas(){}
}
class EnsinoTecnico implements gradeCurricular {
gradeDeAulas(){}
}
class SecretariaEscola {
aulasDoAluno: string;
cadastrarAula(aulasAluno: gradeCurricular) {
this.aulasDoAluno = aulasAluno.gradeDeAulas();
}
}
必须遵循地籍和光环的查SecretariaEscola
马尔方法。如果您想了解地籍的等级,请注意以下事项: 观察所需的辅助工具或所需的材料或材料EnsinoTecnico
。
这是为了实现一个接口
gradeCurricular
。将接口的扩展性与依赖项的相反性分开。
鲍勃叔叔
Aberto para extensão
: 可以使用额外的阿尔古玛新功能或与经典的标准字体相匹配。Fechado para modificação
:该类功能或组合不存在问题算法,不改变新算法的源代码。
L - 里氏替换原理
LSP - 里氏替换原则
里氏替换原理——由类基派生 出 的替换原理。
里斯科夫在 1987 年的一次会议上介绍了他的基本原理,该会议的内容非常复杂,但我们并不担心,因此您将无法详细了解该内容,并且可以作为一个示例。
Se para cada object o1 do tito Sha um object o2 do tito T de forma que, para todos osprogramas P definidos em termos de T, o comportamento de Pé inalterado quando o1 é substituído por o2 então S éum subtipo de T
恩滕德乌? Não né, eu também não entendi na primeira vez que li isso (nem nas outras dez vezes), mas calma aí, Existe outra explicação:
如果是 T 的替代项,则 T 的对象是程序的一部分,因此可以将 T 的对象替换为程序的属性。 —— 维基百科。
视觉上的平静示例如下:
class Fulano {
falarNome() {
return "sou fulano!";
}
}
class Sicrano extends Fulano {
falarNome() {
return "sou sicrano!";
}
}
const a = new Fulano();
const b = new Sicrano();
function imprimirNome(msg: string) {
console.log(msg);
}
imprimirNome(a.falarNome()); // sou fulano!
imprimirNome(b.falarNome()); // sou sicrano!
一个类 ea 类 derivada estão passando como paraâmetro eo código continua funcionando da forma esperada, magica?这就是 Liskov 的原则。
暴力行为的例子:
- Sobrescrever/implementar um método que não faz nada;
- Lançar uma exceção inesperada;
- Retornar valores de tipos differente da classe base;
I - 接口隔离原理
ISP——接口隔离原则
接口隔离原理 — 开发类的目的 是为了实现接口和不使用的方法。
接口的基本原则是通用接口的具体特征。
没有例子可以说明 criado uma 接口Animal
与抽象的动画组合以及作为类实现 essa 接口的接口,veja:
interface Animal {
comer();
dormir();
voar();
}
class Pato implements Animal{
comer(){/*faz algo*/};
dormir(){/*faz algo*/};
voar(){/*faz algo*/};
}
class Peixe implements Animal{
comer(){/*faz algo*/};
dormir(){/*faz algo*/};
voar(){/*faz algo*/};
// Esta implementação não faz sentido para um peixe
// ela viola o Princípio da Segregação da Interface
}
Animal
这是一个通用接口,可与 ISP和LSPPeixe
原理相结合。
使用ISP解决以下问题:
interface Animal {
comer();
dormir();
}
interface AnimalQueVoa extends Animal {
voar();
}
class Peixe implements Animal{
comer(){/*faz algo*/};
dormir(){/*faz algo*/};
}
class Pato implements AnimalQueVoa {
comer(){/*faz algo*/};
dormir(){/*faz algo*/};
voar(){/*faz algo*/};
}
Agora ficou melhor、foi retirado 或 método voar()
da 界面Animal
和 adicionamos em uma 界面 derivada AnimalQueVoa
。 Com isso o comportamento 隔离管理相关的上下文和接口隔离原则。
D - 依赖关系倒置原理
DIP — 依赖倒置原则
依赖关系反转原理 — 抽象与实现的依赖关系。
中音模块不依赖于下层模块的开发。 Ambos devem依赖于抽象。
摘要不依赖于详细信息。详细信息取决于抽象。
- 鲍勃叔叔
没有任何例子可以说明DIP 的简单情况。例如,我们可以使用不同的通知系统,例如电子邮件和短信。主要通知内容如下:
class EmailNotification {
send(message) {
console.log(`Enviando e-mail: ${message}`);
}
}
class SMSNotification {
send(message) {
console.log(`Enviando SMS: ${message}`);
}
}
Agora,vamos criar uma classe de serviço que dependente dessas 实施具体:
class NotificationService {
constructor() {
this.emailNotification = new EmailNotification();
this.smsNotification = new SMSNotification();
}
sendNotifications(message) {
this.emailNotification.send(message);
this.smsNotification.send(message);
}
}
没有任何例子,NotificationService
依赖于具体实施的EmailNotification
方向SMSNotification
。 Isso viola o DIP, pois a classe de alto nível NotificationService
está ditamente dependente de baixo nível.
Vamos corrigir esse código usando DIP。它们依赖于具体的实现,NotificationService
是一个抽象的类。 Vamos criar uma 界面Notification
摘要:
// Abstração para o envio de notificações
interface Notification {
send(message: string): void
}
Agora,作为具体实现EmailNotification
和SMSNotification
开发实现 essa 接口:
class EmailNotification implements Notification {
send(message: string) {
console.log(`Enviando e-mail: ${message}`);
}
}
class SMSNotification implements Notification {
send(message: string) {
console.log(`Enviando SMS: ${message}`);
}
}
最后,通知服务类别依赖于抽象Notification
:
class NotificationService {
private notificationMethod: Notification;
constructor(notificationMethod: Notification) {
this.notificationMethod = notificationMethod;
}
sendNotification(message: string) {
this.notificationMethod.send(message);
}
}
这种形式NotificationService
是一种抽象的依赖服务Notification
类别,它不是具体的实施,而是依赖于逆向原则的实现。
结论
遵循这些原则,我们的系统可以提供弹性的运动、便利的操作和良好的品质以及长时间的节奏。
所有内容均以以下方式进行:原则。能力是推动研究进展的力量。
文章来源:https://dev.to/clintonrocha98/era-solid-o-que-me-faltava-bhp