Senior
Ядродо перифериялык компоненттердин көзкарандарынын колдонулушу маселесин кантип чечсе болот?
sobes.tech AI
AIден жооп
Маселени чечүү үчүн, перифериялык компоненттердин (адаптерлердин, интерфейстердин) көз карандылыгын ядродо (домен логикасында) колдонуу, мисалы, Чистая Архитектура же DDD сыяктуу архитектураларда, Тескери көз карандылык принцибин (Dependency Inversion Principle - DIP) колдонуу аркылуу чечүүгө болот.
DIPтин мааниси:
- Жогорку деңгээлдеги модулдар төмөнкү деңгээлдеги модулдарга көз карандуу болбошу керек. Экиси да абстракциялардан көз каранды болушу керек.
- Абстракциялар деталдарга көз карандуу болбошу керек. Деталдар абстракциялардан көз каранды болушу керек.
Практикалык колдонуу:
- Ядро интерфейстерди жарыялайт: Ядро, перифериялык компоненттерден керектүү функцияларды сүрөттөгөн абстракциялар (интерфейстер же абстракттуу класстар) аныктайт.
- Перифериялык компоненттер интерфейстерди ишке ашырат: Четке чыккан модулдар (маалымат базалары үчүн адаптерлер, HTTP-клиенттер, файл системдери жана башка) бул интерфейстерди ишке ашырат.
- Көз карандылыктарды киргизүү (Dependency Injection - DI): Перифериялык компоненттер сырттан ядрого киргизилет, көбүнчө колдонмонун жогорку деңгээлинде (мисалы, композициялык тамырда же DI-контейнер колдонуу менен). Ядро гана абстракциялар менен иштейт.
Node.jsте DIP колдонуу мисалы:
Бизде ядро бар деп элестетели, ал маалыматка жетүү керек.
// src/domain/interfaces/UserRepository.ts
// Ядро интерфейсди жарыялайт
export interface UserRepository {
getUserById(id: string): Promise<User | null>;
}
// src/domain/entities/User.ts
// Ядро объектиси
export class User {
constructor(public id: string, public name: string) {}
}
// src/domain/usecases/GetUserUseCase.ts
// Ядро use case UserRepository абстракциясына көз каранды
import { UserRepository } from '../interfaces/UserRepository';
import { User } from '../entities/User';
export class GetUserUseCase {
constructor(private userRepository: UserRepository) {}
async execute(id: string): Promise<User | null> {
return this.userRepository.getUserById(id);
}
}
// src/infrastructure/database/MongoDbUserRepository.ts
// Ядро интерфейсин ишке ашырууучу перифериялык компонент
import { UserRepository } from '../../domain/interfaces/UserRepository';
import { User } from '../../domain/entities/User';
export class MongoDbUserRepository implements UserRepository {
// Бул жерде MongoDB менен байланыш логикасы болот
async getUserById(id: string): Promise<User | null> {
console.log(`MongoDBден user алуу: ${id}`);
// Моделдин симуляциясы
if (id === '123') {
return new User('123', 'John Doe');
}
return null;
}
}
// src/app/CompositionRoot.ts
// Композициялык тамыр көз карандылықтарды чогултат
import { GetUserUseCase } from '../domain/usecases/GetUserUseCase';
import { MongoDbUserRepository } from '../infrastructure/database/MongoDbUserRepository';
// Көз карандылыкты киргизүү: Ядро MongoDbUserRepository реализациясын интерфейс аркылуу алат
const userRepository = new MongoDbUserRepository();
const getUserUseCase = new GetUserUseCase(userRepository);
// Эми use case колдонсо болот
async function run() {
const user = await getUserUseCase.execute('123');
if (user) {
console.log(`Табылган колдонуучу: ${user.name}`);
} else {
console.log('Колдонуучу табылган жок');
}
}
run();
Бул ыкманын артыкчылыктары:
- Ядро көз карандылыктан көз каранды эмес: Ядро конкреттүү перифериялык компоненттердин реализацияларын билбейт.
- Тестирлөө оңой: Ядро мок-реализацияларды колдонуу менен оңой тестирленет.
- Ийкемдүүлүк: Бир реализацияны (мисалы, маалымат базасын) башкасына оңой алмаштыруу мүмкүн, ядро кодун өзгөртпөстөн.
- Колдоо: Кодду тейлөө жана өзгөртүү жеңилдейт.