Sobes.tech
Senior

Çekirdekdə periferik komponentlərin asılılıqlarının istifadəsi problemini necə həll etmək olar?

sobes.tech Süni İntellekt

AI-dan cavab

Yadroda (domen logikasında) periferik komponentlərin (adapterlərin, interfeyslərin) asılılıq problemlərini həll etmək üçün asılılıq inversiyası prinsipi (Dependency Inversion Principle - DIP) istifadə edilə bilər.

DIP-in mahiyyəti:

  1. Yuxarı səviyyəli modullar aşağı səviyyəli modullara asılı olmamalıdır. Hər ikisi abstraksiyalara əsaslanmalıdır.
  2. Abstraksiyalar detallara asılı olmamalıdır. Detallar abstraksiyalara əsaslanmalıdır.

Tətbiq nümunəsi:

  • Yadro interfeysləri elan edir: Yadro, periferik komponentlərdən lazım olan funksiyaları təsvir edən abstraksiyaları (interfeyslər və ya abstrakt siniflər) müəyyən edir.
  • Periferik komponentlər interfeysləri həyata keçirir: Xarici modullar (məlumat bazaları üçün adapterlər, HTTP müştəriləri, fayl sistemləri və s.) bu interfeysləri həyata keçirir.
  • Asılılıqların daxil edilməsi (Dependency Injection - DI): Periferik komponentlər xaricdən yadroya daxil edilir, adətən tətbiqin daha yuxarı səviyyəsində (məsələn, kompozisiya kökü və ya DI konteynerindən istifadə etməklə). Yadro yalnız abstraksiyalarla işləyir.

Node.js-də DIP-in istifadəsinə nümunə:

Tutaq ki, yadroda məlumatlara çıxış lazımdır.

// src/domain/interfaces/UserRepository.ts
// Yadro interfeys elan edir
export interface UserRepository {
  getUserById(id: string): Promise<User | null>;
}
// src/domain/entities/User.ts
// Yadro entitasiyası
export class User {
  constructor(public id: string, public name: string) {}
}
// src/domain/usecases/GetUserUseCase.ts
// Yadro istifadəçi halına gəlir, UserRepository abstraksiyasına bağlıdır
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
// Yadro interfeysini həyata keçirən periferik komponent
import { UserRepository } from '../../domain/interfaces/UserRepository';
import { User } from '../../domain/entities/User';

export class MongoDbUserRepository implements UserRepository {
  // Burada MongoDB ilə əlaqə loqikası olacaq

  async getUserById(id: string): Promise<User | null> {
    console.log(`MongoDB-dən istifadəçi alınır: ${id}`);
    // Məlumatların alınmasının simulasyonu
    if (id === '123') {
      return new User('123', 'John Doe');
    }
    return null;
  }
}
// src/app/CompositionRoot.ts
// Kompozisiya kökü asılılıqları toplayır
import { GetUserUseCase } from '../domain/usecases/GetUserUseCase';
import { MongoDbUserRepository } from '../infrastructure/database/MongoDbUserRepository';

// Asılılığı daxil etmək: Yadro, MongoDbUserRepository həyata keçirən interfeys vasitəsilə alır
const userRepository = new MongoDbUserRepository();
const getUserUseCase = new GetUserUseCase(userRepository);

// İndi istifadə edə bilərik
async function run() {
  const user = await getUserUseCase.execute('123');
  if (user) {
    console.log(`Tapılan istifadəçi: ${user.name}`);
  } else {
    console.log('İstifadəçi tapılmadı');
  }
}

run();

Bu yanaşmanın üstünlükləri:

  • Yadronun müstəqilliyi: Yadro konkret periferik komponentlərin həyata keçirilməsindən xəbərsizdir.
  • Test ediləbilərlik: Yadro interfeyslərin mock-implementasiyalarını istifadə etməklə asanlıqla test edilə bilər.
  • Esneklik: Bir həyata keçirilməni (məsələn, məlumat bazası) digərinə dəyişmək asandır, yadro kodunu dəyişmədən.
  • Dəstək: Kodun saxlanması və dəyişdirilməsi asanlaşır.