Lesson 0001 · Hari 1 · Backend · ±13 menit

Di mana kode ini tinggal?

Layer & alur request di ASP.NET Core Web API, dilihat dari kacamata Express

Target lesson ini: Anda bisa menjawab pertanyaan interview "Bagaimana Anda menstruktur project ASP.NET Core Web API, dan kenapa?" dalam 60 detik, dan bisa menentukan layer yang tepat (Controller, Service, Repository, atau composition root) untuk potongan kode yang ditunjukkan pewawancara.

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 / NodeASP.NET CoreTanggung jawab (satu kalimat)
routes/ + controllers/Controllers/Menerjemahkan HTTP ↔ panggilan method. Tidak berisi aturan bisnis.
schema Zod / JoiDTOs/Bentuk data yang masuk/keluar API.
services/Services/Aturan bisnis: "harga harus > 0", "nama Product tidak boleh duplikat".
data-access di atas PrismaRepositories/Query & simpan data untuk satu Entity.
model Prisma + Prisma clientModels/ + Data/AppDbContextEntity yang dipetakan ke tabel, dan DbContext sebagai sesi ke database.
config/ + .envappsettings.json + Config/Konfigurasi bertipe lewat Options Pattern.
app.js / server.jsProgram.csComposition 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

HTTP request→ Middleware→ Controller→ Service→ Repository→ DbContext→ SQL Server

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…

  1. tanggung jawab Controller, Service, dan Repository masing-masing?
  2. DTO beserta alasannya (skema DB tidak bocor / over-posting)?
  3. interface + DI + composition root (Program.cs)?
  4. manfaatnya untuk testing (Service di-unit-test dengan Mock)?
  5. konfigurasi lewat Options Pattern?
  6. 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).

Bacaan utama (±15 menit) Microsoft Learn: Common web application architectures, bagian dari eBook resmi Architect Modern Web Applications with ASP.NET Core and Azure. Baca bagian "All-in-one applications", "What are layers?", "Traditional N-Layer", dan "Clean architecture". Bagian Azure/Docker bisa dilewati.

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?"