SOLID 소개 - Princípios L e I
20040 단어 ooptypescriptbeginnersbraziliandevs
타벨라 데 콘테우도스
Liskov 대체 원리
추천
O Princípio de Substituição de Liskov diz que devemos poder utilizar uma sub-classe, no lugar de uma super-classe. Na prática isso ocorre da implementação de Interfaces, ou através da herança de class, dessa forma toda a sub-classe que implementa determinada interface, ou herda de determinada super-classe, deve poder ser usada como substituto.
예시
A forma mais fácil de se entender o Princípio de Substituição de Liskov é através de classes que fazem a conexão com o banco de dados, dessa forma podemos ter diversas classes, responsáveis por diversos bancos, podendo se substituírem sem a geração de efeitos colaterais (버그 ).
MySQL과 MongoDB가 다른 DB와는 다른 상황에서 일반적으로 사용되는 주요 문제의 예가 아닙니다. Para isso iremos criar duas classes que implementam uma mesma Interface e utilizá-las da mesma forma.
interface IUserRepository {
create(name: string, age: number): Promise<void>;
}
import mysql from 'mysql2/promise'; // Esse pacote foi utilizado apenas como exemplo
class UserRepositoryMySQL implements IUserRepository {
constructor() {
this.mysql = mysql.createPool({
/* configuração da conexão */
});
}
async create(name: string, age: number): Promise<void> {
await this.mysql.execute(
'INSERT INTO users (name, age) VALUES (?, ?);',
[name, age]
)
}
}
import { User } from 'mongooseModels'; // pasta "fictícia"que armazena as Models do Mongoose
class UserRepositoryMongo implements IUserRepository {
constructor() {
this.userModel = new User();
}
async create(name: string, age: number): Promise<void> {
await this.userMode.create({ name, age });
}
}
import { IUserRepository } from 'IUserRepository';
class CreateUSerService {
constructor(private userRepository: IUserRepository) {}
async execute(name: string, age: number) {
this.userRepository.create(name, age);
}
}
import { Request, Response, NextFunction } from 'express';
import { UserRepositoryMySQL } from 'UserRepositoryMySQL';
import { UserRepositoryMongo } from 'UserRepositoryMongo';
import { CreateUserService } from 'CreateUserService';
const userRepositoryMySQL = new UserRepositoryMySQL();
const userRepositoryMongo = new UserRepositoryMongo();
/* ---------- Criando usuário no MySQL ---------- */
const createUserService = new CreateUserService(userRepositoryMySQL);
/* ---------- ----------------------- ---------- */
/* ---------- Criando usuário no MongoDB ---------- */
const createUserService = new CreateUserService(userRepositoryMongo);
/* ---------- ------------------------- ---------- */
const createUserRoute = async (req: Request, res: Response, next: NextFunction) => {
const { name, age } = req.body;
try {
await createUserService.execute(name, age);
res.status(200).end();
} catch {
res.status(500).json({ message: 'Internal server error' });
}
}
No example acima criamos duas classes que lidam com DB diferentes, porém podemos utilizar qualquer uma das duas em nosso serviço de criação de usuário
CreateUSerService
, isso porque o serviço espera a Interface IUserRepository
e como nossas classes implementam essa Interface podem ser usadas 코모 대체.Voltar ao top
인터페이스 분리 원리
추천
O Princípio de Segregação de Interfaces recomenda que separemos nossas interface em "blocos mínimos", em outras palavras, as criemos altamente especializadas e caso surja a necessidade, podemos criar uma Interface mais completa estendendo as mais específicas.
예시
O Princípio de Segregação de Interfaces é, na minha opinião, o mais simples de se entender o conceito teórico, porém o mais difícil de se aplicar em um caso real.
Nosso example será uma classe de serviço de uma API, ele deverá obrigatoriamente possuir o método
execute
para executar sua tarefa e opcionalmente poderá possuir métodos de validação, como por example: validar se um email já está em uso.// Iremos utilizar generics para "tipar" o input <T> e o output <O> posteriormente
interface IServiceExecute<T, O> {
execute(T): Promise<O>;
}
interface IServiceValidUnique<T> {
isUnique(T): Promise<boolean>;
}
interface IRequest {
username: string;
email: string;
password: string;
}
interface ICreatedUser extends IRequest {
id: string;
}
type UniqueUser = Pick<IRequest, 'email'>
class RegisterUserService implements IServiceExecute<IRequest | null, ICreateUser>, IServiceValidUnique<UniqueUser> {
constructor(private repository: IRepository) {}
async isUnique({ email }: UniqueUSer): Promise<boolean> {
const emailAlreadyInUse = await this.repository.find(email);
if (emailAlreadyInUse) {
return false;
}
return true;
}
async execute({ username, email, password }: IRequest): Promise<ICreatedUser> {
const isUnique = await this.isUnique({ email });
if (!isUnique) {
return null;
}
const newUSer = await this.repository.create({ username, email, password });
return newUser;
}
}
예를 들어 ACIMA ESTAMOS ALICANDO DUAS 인터페이스가 없습니다. 인터페이스는 UM UM úNICA CLASSE, ISSO PORQUE CADA 인터페이스 É RESPONSáVEL APENAS POR UM FUNCIONIDADE, DESA FORMA SE precisarmos construir UM serviço que não precision de validação, podemos apenas implementar a
IServiceExecute
.Obs: As Interfaces criadas junto da classe são um "complemento"as outras, isso porque optei por utilizar Generics na criação das Interfaces de serviço, logo é necessário inferir seu tipo posteriormente através de tipos primitivos,
types
ou interfaces
.Voltar ao top
링크 Úteis
Princípios SOLID com TypeScript 의해 Matheus Bessa
Os Princípios do SOLID — ISP Princípio de segregação da interface 의해 Jones Roberto
Os Princípios do SOLID — LSP -Princípio da substituição de Liskov 의해 Jones Roberto
Voltar ao top
Reference
이 문제에 관하여(SOLID 소개 - Princípios L e I), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gabrielhsilvestre/introducao-ao-solid-principios-l-e-i-4cm0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)