Episode ini membahas arsitektur dan pola pengembangan: feature modules dan modular architecture, shared dan core modules, domain-driven design dengan struktur folder yang scalable, serta clean architecture dan separation of concerns.

Aplikasi kecil mudah dirawat. Masalah muncul saat aplikasi tumbuh: file berpindah, dependency melilit, dan tim bingung harus menaruh kode di mana. Di sinilah arsitektur yang disengaja berperan.
Episode 18 membahas feature modules dan modular architecture, shared dan core modules, domain-driven design dengan struktur folder yang scalable, serta clean architecture dan separation of concerns. Arsitektur yang baik membuat aplikasi tetap bisa dikelola di skala tim besar.
Prinsip pertama modular architecture: kelompokkan kode berdasarkan fitur, bukan berdasarkan jenis file. Setiap fitur memiliki folder sendiri yang berisi komponen, service, model, dan route-nya.
src/app/
fitur/
auth/
produk/
keranjang/
checkout/
shared/
core/Folder auth, produk, dan checkout masing-masing adalah fitur yang bisa dikembangkan dan diuji secara independen. Fitur besar di-lazy-load melalui rute, sehingga hanya dimuat saat dibutuhkan.
Setiap fitur hanya boleh berbicara dengan fitur lain lewat antarmuka yang disepakati — bukan mengimpor komponen internal satu sama lain. Jika dua fitur saling membutuhkan banyak hal, kemungkinan keduanya seharusnya satu fitur atau bagian yang dipakai bersama dipindah ke shared.
core folder) berisi service dan konfigurasi sekali pakai: HTTP interceptor, guard, error handler, dan state global.Pisahkan keduanya agar dependensi ringan. Shared tidak boleh mengimpor fitur; core tidak boleh berisi komponen UI yang spesifik fitur.
Fitur yang besar atau jarang diakses di-lazy-load. Dengan standalone components, lazy loading terjadi di level route:
{
path: 'checkout',
loadComponent: () =>
import('./fitur/checkout/checkout.component')
.then((m) => m.CheckoutComponent),
}CheckoutComponent dan dependency-nya diunduh hanya saat pengguna menuju halaman checkout. Lazy loading menjaga initial bundle tetap kecil sekaligus menjaga batas antar fitur secara teknis.
Domain-driven design (DDD) menyarankan: kode harus berbicara dalam bahasa domain bisnis, bukan bahasa teknis. Model Order, Invoice, dan Customer lebih jelas daripada DataTable, ItemList, dan Record.
export interface Order {
id: string;
customerId: string;
items: OrderItem[];
total: number;
status: 'draft' | 'paid' | 'shipped' | 'cancelled';
}status dengan nilai domain seperti paid dan shipped membuat aturan bisnis bisa diekspresikan langsung di tipe. Tempatkan logika bisnis yang kompleks di domain layer — bukan di dalam komponen.
Struktur berbasis fitur dengan DDD membentuk pola yang bisa tumbuh tanpa perombakan besar: tambah fitur baru dengan membuat folder fitur/<nama>, dan setiap fitur membawa model, service, state, dan komponennya sendiri. Konsistensi struktur lebih penting daripada kesempurnaan awal.
Clean architecture memisahkan kode menjadi lapisan: presentasi (komponen), application (use case dan state), dan domain (model serta aturan bisnis). Tiap lapisan bergantung ke arah dalam — presentasi tahu tentang application, application tahu tentang domain, dan domain tidak tahu apa pun di luarnya.
Penerapan penuh clean architecture bisa terasa berat untuk aplikasi kecil. Mulai dengan prinsip paling penting — separation of concerns:
@Component({
selector: 'app-checkout',
standalone: true,
template: `<button (click)="checkout()" [disabled]="memproses()">
Bayar Sekarang
</button>`,
})
export class CheckoutComponent {
private readonly checkoutService = inject(CheckoutService);
readonly memproses = signal(false);
checkout(): void {
this.checkoutService.proses().subscribe({
next: () => console.log('Pesanan dibuat'),
error: (err) => console.error(err),
});
}
}Komponen CheckoutComponent hanya menampilkan tombol dan memicu service — tidak ada logika bisnis di dalamnya. CheckoutService yang menangani pembuatan order. Komponen tipis ini jauh lebih mudah dites dan dirawat.
Arsitektur terbaik adalah yang dipahami seluruh tim dan dipakai konsisten. Dokumentasikan struktur folder di README atau AGENTS.md, sepakati aturan di code review, dan evaluasi arsitektur secara berkala. Yang paling mahal bukan keputusan arsitektur yang salah — melainkan arsitektur yang tidak konsisten.
Inti yang harus dibawa pulang:
loadComponent.Di episode 19 selanjutnya kita akan membahas tooling modern dan build automation — memakai Angular CLI, builders, dan custom schematics, menyusun build pipeline dengan linting dan formatting, continuous integration untuk aplikasi Angular, serta reproducible builds dan release management.