Di mana kode ini tinggal?
Layer & alur request di ASP.NET Core Web API, dilihat dari kacamata Express
Kuis di lesson ini adalah feedback cepat, bukan bukti penguasaan. Soal yang sama akan muncul lagi secara acak di review campuran 0007 besok pagi, dan hanya hasil di sana yang dicatat.
1. Anda sudah tahu 80%-nya
Di Express Anda mungkin sudah memisahkan routes/, controllers/,
services/, dan models/. ASP.NET Core memakai ide yang sama.
Bedanya, pemisahan ini diharapkan oleh pewawancara, dan semuanya disambungkan oleh
dependency injection bawaan, bukan oleh require/import manual.
| Express / Node | ASP.NET Core | Tanggung jawab (satu kalimat) |
|---|---|---|
routes/ + controllers/ | Controllers/ | Menerjemahkan HTTP ↔ panggilan method. Tidak berisi aturan bisnis. |
| schema Zod / Joi | DTOs/ | Bentuk data yang masuk/keluar API. |
services/ | Services/ | Aturan bisnis: "harga harus > 0", "nama Product tidak boleh duplikat". |
| data-access di atas Prisma | Repositories/ | Query & simpan data untuk satu Entity. |
| model Prisma + Prisma client | Models/ + Data/AppDbContext | Entity yang dipetakan ke tabel, dan DbContext sebagai sesi ke database. |
config/ + .env | appsettings.json + Config/ | Konfigurasi bertipe lewat Options Pattern. |
app.js / server.js | Program.cs | Composition root: mendaftarkan service ke DI container dan menyusun Middleware. |
Project ASP.NET Core baru memang dimulai sebagai satu project. Microsoft menyebutnya all-in-one: "In a single project scenario, separation of concerns is achieved through the use of folders." [1]
2. Alur satu request
Hasilnya kembali ke arah sebaliknya: Entity diubah menjadi DTO di Service, lalu Controller membungkusnya
menjadi Ok(...), NotFound(), atau CreatedAtAction(...).
Urutan Middleware sendiri dibahas di lesson 0005.
Controller sengaja dibuat tipis. Dokumentasi resmi menulis bahwa Controller adalah abstraksi tingkat UI, dan "In well-factored apps, it doesn't directly include data access or business logic. Instead, the controller delegates to services handling these responsibilities." [2]
Aturan arahnya juga jelas: setiap layer hanya bicara dengan layer di bawahnya.
"The UI layer shouldn't make any requests to the DAL directly"
[1].
Artinya Controller tidak memakai DbContext secara langsung.
3. DTO: kontrak API, bukan tabel
Padanannya di Node adalah schema Zod/Joi untuk body dan response. Microsoft menyebut DTO sebagai
"subset of a model" dan mendaftar kegunaannya: mencegah over-posting, menyembunyikan property yang tidak boleh dilihat client,
mengurangi ukuran payload, dan meratakan object graph yang bersarang
[4].
Over-posting artinya client mengisi field yang seharusnya tidak boleh ia isi, misalnya Id atau IsAdmin.
4. Interface dan composition root
Di N-layer klasik, Service bergantung langsung pada kelas data access. Akibatnya, menurut Microsoft,
"Testing business logic in such an architecture is often difficult, requiring a test database."
[1]
Dokumentasi DI menjelaskan solusinya: memakai interface untuk mengabstraksi implementasi, mendaftarkannya di service container
(biasanya di file Program), lalu menyuntikkannya ke kelas yang memakainya
[3].
// Services/ProductService.cs — hanya tahu kontraknya, tanpa new
public class ProductService(IProductRepository repo) : IProductService { ... }
// Program.cs — satu-satunya tempat yang tahu implementasi konkret
builder.Services.AddScoped<IProductRepository, ProductRepository>();
builder.Services.AddScoped<IProductService, ProductService>();
Tempat penyambungan ini disebut composition root:
"The place where this logic is performed is known as the app's composition root"
[1].
Di Unit Test, Anda tinggal memberikan Mock IProductRepository tanpa database.
Ini huruf D di SOLID (lesson 0008). Arti AddScoped dibahas di lesson 0004.
Padanan Node: di NestJS ini sama dengan providers di module plus constructor injection.
Di Express polos, bayangkan app.js yang membuat semua instance sekali lalu menyerahkannya ke constructor.
Bedanya, di .NET framework yang membuat dan membuang instance-nya untuk Anda.
5. Options Pattern, sekilas
Konfigurasi dari appsettings.json tidak dibaca dengan string di mana-mana, tapi di-bind ke kelas bertipe:
"The options pattern uses classes to provide strongly typed access to groups of related settings."
[5]
Registrasinya juga di composition root, misalnya builder.Services.Configure<JwtSettings>(builder.Configuration.GetSection("Jwt")).
Padanan Node: process.env yang dibaca sekali oleh modul config/ yang divalidasi. Detailnya di lesson 0005.
Latihan 1: Kode ini milik layer mana?
Pewawancara sering menunjukkan potongan kode lalu bertanya, "Ini seharusnya ada di mana?" Jawab tanpa scroll ke atas.
Latihan 2: Alasannya
Pewawancara mid-level jarang berhenti di "di mana". Mereka biasanya lanjut bertanya "kenapa".
Latihan 3: Ucapkan dengan suara keras
Pasang timer 60 detik. Jawab pertanyaan ini dengan suara keras, seolah sedang interview. Jangan buka jawaban contoh sebelum selesai. Mengingat tanpa melihat inilah yang membuat materi menempel.
"Bagaimana Anda menstruktur project ASP.NET Core Web API, dan kenapa?"
Bandingkan dengan jawaban contoh dan checklist-nya
"Untuk API kecil sampai menengah saya pakai layered architecture dalam satu project.
Controller hanya mengurus HTTP: binding request, memanggil Service, dan memilih status code.
Service berisi aturan bisnis. Repository membungkus akses data lewat EF Core DbContext.
Data keluar-masuk API lewat DTO, jadi skema database tidak bocor dan over-posting tercegah.
Setiap layer bergantung pada interface, dan semuanya didaftarkan di Program.cs sebagai composition root,
sehingga Service bisa di-unit-test dengan Mock repository. Konfigurasi dibaca dari appsettings.json lewat Options Pattern.
Kalau domainnya makin kompleks, saya pecah menjadi Clean Architecture dengan beberapa project."
Checklist (6 poin): apakah Anda menyebut…
- tanggung jawab Controller, Service, dan Repository masing-masing?
- DTO beserta alasannya (skema DB tidak bocor / over-posting)?
- interface + DI + composition root (
Program.cs)? - manfaatnya untuk testing (Service di-unit-test dengan Mock)?
- konfigurasi lewat Options Pattern?
- trade-off: kapan memilih struktur lain (mis. Clean Architecture, lesson 0011)?
Kurang dari 4 poin? Ulangi besok pagi sebelum review 0007. Jeda waktu itu memang sengaja (spacing).
Sumber: [1] Common web application architectures · [2] Handle requests with controllers in ASP.NET Core MVC · [3] Dependency injection in ASP.NET Core · [4] Tutorial: Create a controller-based web API (Prevent over-posting) · [5] Options pattern in ASP.NET Core
Ringkasan untuk dicetak: Reference: Layered architecture ASP.NET Core · Istilah: GLOSSARY.md
Ada yang belum jelas? Tanyakan ke saya (agent) di terminal, misalnya: "kalau Service sudah memakai EF Core, Repository masih perlu?" atau "apa bedanya layer dan tier?"