IslomDevIslomDev
Booster
Imtihon
Booster
Imtihon
  • Angular Intervyu Tayyorgarlik
  • JavaScript / TypeScript

    • JavaScript / TypeScript
    • Asoslar (JavaScript)
    • Asinxronlik
    • Prototip va OOP
    • TypeScript
    • Performance
  • Algoritmlash

    • Algoritmlash
    • Murakkablik tahlili
    • Ma'lumot tuzilmalari
    • Qidiruv va Saralash
    • Algoritmik paradigmalar
    • Amaliy masalalar
  • Angular — Boshlang'ich

    • Angular — Boshlang'ich
    • Component
    • Template
    • Change Detection
    • Advanced Component
  • Angular — Service va DI

    • Angular — Service va DI
    • Service asoslari
    • HTTP
    • Hierarchical DI
    • Advanced DI
    • State management (service)
  • Angular — Versiyalar

    • Angular — Versiyalar
    • Angular 12–13
    • Angular 14
    • Angular 15
    • Angular 16
    • Angular 17
    • Angular 18+
  • Angular — Directive

    • Angular — Directive
    • Built-in Directives
    • Custom Attribute Directive
    • Custom Structural Directive
    • Advanced
  • Angular — RxJS

    • Angular — RxJS
    • Observable asoslari
    • Asosiy operatorlar
    • Higher-order operatorlar
    • Combination operatorlar
    • Subject turlari
    • Xato va xotira
    • Advanced
  • Angular — Pipe

    • Angular — Pipe
    • Built-in Pipes
    • Custom Pipe
    • Performance
  • Angular — Forms

    • Angular — Forms
    • Template-driven Forms
    • Reactive Forms
    • Validators
    • Advanced
  • Angular — NgModule

    • Angular — NgModule
    • NgModule asoslari
    • Module arxitekturasi
    • Lazy Loading
    • Standalone vs NgModule
  • Angular — Sintaksis va Clean Code

    • Angular — Sintaksis va Clean Code
    • Template sintaksisi
    • Angular 17+ yangi sintaksis
    • Komponent arxitekturasi
    • Performance pattern'lar
    • SOLID va Clean Code
    • Testing

SOLID va Clean Code

Daraja:

SOLID tamoyillari va Angular Style Guide — katta jamoada kod sifati, kengaytirish va test qilish uchun asos. Bu guruh intervyuda arxitektura va clean code savollarini qamrab oladi.

Single Responsibility — har class bitta mas'uliyat

Middle

Nima bu?

Single Responsibility Principle (SRP) — har bir class/modul faqat bitta o'zgarish sababi bo'lishi kerak. Angular'da: komponent faqat UI, service — biznes logika, guard — route himoya, interceptor — HTTP middleware. "God component" — ham HTTP, ham validatsiya, ham formatlash bir joyda — SRP buziladi.

Kod misoli

// ❌ SRP buzilgan — hamma narsa bir komponentda
@Component({ /* ... */ })
export class BadUserPageComponent {
  users: User[] = [];

  ngOnInit() {
    this.http.get<User[]>('/api/users').subscribe((data) => {
      this.users = data.map((u) => ({
        ...u,
        displayName: `${u.firstName} ${u.lastName}`.trim(),
        isActive: u.lastLogin > Date.now() - 30 * 86400000,
      }));
    });
  }
}
// ✅ Mas'uliyatlar ajratilgan
import { Injectable, Component, inject } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class UserService {
  private http = inject(HttpClient);

  getUsers(): Observable<User[]> {
    return this.http.get<User[]>('/api/users');
  }
}

@Injectable({ providedIn: 'root' })
export class UserMapper {
  toViewModel(user: User): UserViewModel {
    return {
      ...user,
      displayName: `${user.firstName} ${user.lastName}`.trim(),
      isActive: user.lastLogin > Date.now() - 30 * 86400000,
    };
  }
}

@Component({
  selector: 'app-user-page',
  standalone: true,
  template: `
    @for (u of users$ | async; track u.id) {
      <p>{{ u.displayName }} — {{ u.isActive ? 'Faol' : 'Nofaol' }}</p>
    }
  `,
  imports: [AsyncPipe],
})
export class UserPageComponent {
  private userService = inject(UserService);
  private mapper = inject(UserMapper);

  users$ = this.userService.getUsers().pipe(
    map((users) => users.map((u) => this.mapper.toViewModel(u)))
  );
}

Imtihonda

  • SRP buzilgan komponentni qanday refactor qilasiz?
  • Service va util/helper class farqi?
  • "Bitta mas'uliyat" deganda Angular kontekstida nima tushuniladi?

Yodlash uchun

Bitta class = bitta sabab o'zgarishi; UI ≠ biznes logika.

Open/Closed — kengaytirish uchun ochiq

Senior

Nima bu?

Open/Closed Principle (OCP) — class kengaytirish uchun ochiq, o'zgartirish uchun yopiq. Yangi funksiya qo'shish uchun mavjud kodni o'zgartirmasdan yangi implementatsiya qo'shiladi. Angular'da: abstract class/interface, Strategy pattern, custom validator/pipe/directive ro'yxatga qo'shish, InjectionToken bilan plugin arxitektura.

Kod misoli

// Abstract strategy — yangi to'lov turi qo'shish oson
export abstract class PaymentStrategy {
  abstract pay(amount: number): Observable<PaymentResult>;
}

@Injectable()
export class CardPaymentStrategy extends PaymentStrategy {
  private http = inject(HttpClient);

  pay(amount: number): Observable<PaymentResult> {
    return this.http.post<PaymentResult>('/api/pay/card', { amount });
  }
}

@Injectable()
export class PaymePaymentStrategy extends PaymentStrategy {
  private http = inject(HttpClient);

  pay(amount: number): Observable<PaymentResult> {
    return this.http.post<PaymentResult>('/api/pay/payme', { amount });
  }
}

export const PAYMENT_STRATEGY = new InjectionToken<PaymentStrategy>('PaymentStrategy');

@Component({
  selector: 'app-checkout',
  standalone: true,
  providers: [
    { provide: PAYMENT_STRATEGY, useClass: CardPaymentStrategy },
  ],
  template: `<button type="button" (click)="checkout()">To'lash</button>`,
})
export class CheckoutComponent {
  private payment = inject(PAYMENT_STRATEGY);

  checkout(): void {
    this.payment.pay(99_000).subscribe(/* ... */);
  }
}
// Route config kengaytirish — mavjud guard o'zgartirilmaydi
export const authGuard: CanActivateFn = () => inject(AuthService).isLoggedIn();
export const adminGuard: CanActivateFn = () => inject(AuthService).isAdmin();

// Yangi route — faqat config qo'shiladi
{ path: 'admin', canActivate: [authGuard, adminGuard], loadComponent: () => import('./admin') }

Imtihonda

  • OCP va Dependency Injection bog'liqligi?
  • if/else zanjiri o'rniga qanday pattern ishlatiladi?
  • Angular'da OCP buzilgan misol?

Yodlash uchun

Yangi funksiya = yangi class; eski kodni tegmang.

Dependency Inversion — abstrakt'ga bog'liq bo'l

Senior

Nima bu?

Dependency Inversion Principle (DIP) — yuqori darajadagi modullar past darajadagi modullarga bog'liq bo'lmasligi kerak; ikkalasi ham abstraksiyaga bog'lanadi. Angular DI buni tabiiy qo'llab-quvvatlaydi: interface + InjectionToken, @Injectable implementatsiya almashtirish, test'da mock inject qilish.

Kod misoli

// Abstraksiya — konkrét API'dan mustaqil
export interface Logger {
  log(message: string, context?: string): void;
  error(message: string, error?: unknown): void;
}

export const LOGGER = new InjectionToken<Logger>('Logger');

@Injectable()
export class ConsoleLogger implements Logger {
  log(message: string, context?: string): void {
    console.log(`[${context ?? 'App'}]`, message);
  }
  error(message: string, error?: unknown): void {
    console.error(message, error);
  }
}

@Injectable()
export class RemoteLogger implements Logger {
  private http = inject(HttpClient);

  log(message: string, context?: string): void {
    this.http.post('/api/logs', { level: 'info', message, context }).subscribe();
  }
  error(message: string, error?: unknown): void {
    this.http.post('/api/logs', { level: 'error', message, error: String(error) }).subscribe();
  }
}

// Yuqori daraja — faqat Logger interface'ga bog'liq
@Injectable({ providedIn: 'root' })
export class OrderService {
  private logger = inject(LOGGER);

  submit(order: Order): Observable<void> {
    this.logger.log(`Buyurtma #${order.id} yuborildi`, 'OrderService');
    return this.http.post<void>('/api/orders', order);
  }
}

// app.config.ts — implementatsiya almashtirish
providers: [
  { provide: LOGGER, useClass: environment.production ? RemoteLogger : ConsoleLogger },
]

Imtihonda

  • DIP va Angular DI farqi/nisbati?
  • InjectionToken qachon kerak (interface runtime'da yo'q)?
  • Test'da DIP qanday yordam beradi?

Yodlash uchun

Interface/Token → inject; concrete class'ga to'g'ridan-to'g'ri bog'lanmang.

Naming convention — Angular style guide

Middle

Nima bu?

Angular Style Guide nomlash qoidalarini belgilaydi: fayl nomi kebab-case + suffix (user-profile.component.ts); class PascalCase + suffix (UserProfileComponent); selector kebab-case, prefiks bilan (app-user-profile); service — @Injectable, -service suffix; constant — UPPER_SNAKE. Bir feature = bir papka (component + html + scss + spec).

Kod misoli

src/app/features/users/
├── user-list/
│   ├── user-list.component.ts      → UserListComponent
│   ├── user-list.component.html
│   ├── user-list.component.scss
│   └── user-list.component.spec.ts
├── user-detail/
│   └── ...
├── services/
│   └── user.service.ts             → UserService
├── models/
│   └── user.model.ts               → interface User
└── users.routes.ts                 → usersRoutes
// Selector prefiks — loyiha prefiksi (app, lib, admin)
@Component({
  selector: 'app-user-list',           // element
  // selector: 'app-user-list',        // attribute: <div app-user-list>
  templateUrl: './user-list.component.html',
})
export class UserListComponent {}

// Output naming — verb + Change (two-way uchun)
@Output() selectedUserChange = new EventEmitter<User>();

// Observable suffix $
users$ = this.userService.getUsers();

// Boolean — is/has/can prefiks
isLoading = false;
hasPermission = true;

Imtihonda

  • Nima uchun Component suffix majburiy deyiladi?
  • Selector prefiks nima uchun kerak?
  • $ suffix Observable uchun convention qayerdan?

Yodlash uchun

kebab-case file; PascalCase class + suffix; selector prefiks.

Barrel exports — index.ts pattern

MiddleSenior

Nima bu?

Barrel file (index.ts) — papkadagi public API'ni bitta joydan export qiladi. Import qisqaradi: from './users' o'rniga from './users/user-list.component'. Ehtiyot: circular dependency va tree shaking muammolari — faqat public surface export qiling, ichki helper'larni export qilmang.

Kod misoli

// features/users/index.ts — public API
export { UserListComponent } from './user-list/user-list.component';
export { UserDetailComponent } from './user-detail/user-detail.component';
export { UserService } from './services/user.service';
export type { User, UserViewModel } from './models/user.model';
// Ichki helper export QILINMAYDI — _user.mapper.ts
// Boshqa modul — qisqa import
import { UserListComponent, UserService, User } from '@app/features/users';

@Component({
  standalone: true,
  imports: [UserListComponent],
})
export class DashboardComponent {
  private users = inject(UserService);
}
// tsconfig paths — alias bilan
// "paths": { "@app/features/users": ["src/app/features/users/index.ts"] }

// ❌ Circular dependency xavfi
// index.ts → component → index.ts (orqaga import)

// ✅ To'g'ri — component ichki fayllardan to'g'ridan-to'g'ri import
import { UserMapper } from '../services/user.mapper';

Imtihonda

  • Barrel export afzallik va kamchiliklari?
  • Circular dependency qanday aniqlanadi va hal qilinadi?
  • Library (ng build) uchun public-api.ts farqi?

Yodlash uchun

index.ts = public API; ichki modul export qilmang; circular'dan saqlaning.

Angular CLI library loyihalarida `public-api.ts` barrel vazifasini bajaradi — faqat shu fayl orqali export qilingan narsalar tashqi consumer'ga ochiq.
Prev
Performance pattern'lar
Next
Testing