Bölüm 13 / 13
Kendi başına yapabilir misin?
Hat sonu yeterlilik kontrolü: gerçekçi görev + kontrol listesi.
10 dakikalık okuma
Hat 08'de çerçevesiz yazdığın, Hat 09'da strict TypeScript'e taşıdığın başvuru arayüzünün üçüncü ve en büyük dönüşümü: Angular'a taşıyacaksın. Elle kurduğun her mekanizmanın — DOM güncellemesi, durum makinesi, yarış çözümü, form doğrulaması — artık çerçevedeki bir karşılığı var; görev, o karşılıkları doğru yerlerde kullanmaktır. Davranış kullanıcı gözünde aynı kalmalı. Kural aynı: görevi derslere bakmadan tamamlayamıyorsan hat bitmemiştir.
01Bu hat sana ne kazandırmış olmalı
- SPA/MPA kararını gerekçeyle vermek; Angular projesinin anatomisini
(
angular.json,app.config.ts, strict tsconfig) okumak; üretim çıktısını ve SPA fallback kuralını açıklamak. - Arayüzü bileşen ağacına bölmek; veri aşağı, olay yukarı sözleşmesini
input()/output()ile kurmak; akıllı/sunumsal ayrımını uygulamak. - Şablon dilini kullanmak: dört binding,
@if/@for/@switch, track zorunluluğu, pipe'lar — ve "şablon aptal kalır" kuralı. - İş mantığını servise koymak;
inject()ve injection context'i bilmek; provider tariflerini ve hiyerarşik enjektörü ("singleton'ım çoğaldı" tuzağıyla) açıklamak. - RxJS'le düşünmek: soğuk akış, abonelik disiplini (
asyncpipe →takeUntilDestroyed→ elle), düzleştirme kararı (switch/concat/merge/exhaust),catchError'ın yeri. - HttpClient'la tipli istek atmak;
get<T>'nin beyan olduğunu bilip sınırda dönüştürücü kullanmak; yükleniyor/hata/veri üçlüsünü tek akışta modellemek; interceptor yazmak. - Rota tablosu kurmak; parametreyi akış/input olarak okumak ("bileşen yeniden kullanılır" tuzağıyla); lazy loading ve guard'ları — guard'ın güvenlik olmadığını bilerek — kullanmak.
- Reactive Forms'la tipli form kurmak: doğrulama katmanları,
toucheddisiplini,valueChanges,FormArray, sunucu hatasını forma yazma. - Değişiklik algılamayı anlatmak: zone.js, OnPush sözleşmesi, değişmezlik
zorunluluğu;
signal/computed/effectile durum kurmak; RxJS/signals işbölümünü ve zoneless yönü bilmek. - Kendi yapı taşını yazmak: attribute/structural direktif, özel pipe (saf/saf
olmayan bedeliyle),
viewChild/contentChildsorguları, çok yuvalı projeksiyon,hostDirectiveskompozisyonu. - Performansı süreç olarak yürütmek: tembellik katmanları (lazy rota /
@defer/ sanal kaydırma), profil ve paket analiziyle ölçmek; SSR + hydration mekanizmasını vewindowtuzağını açıklamak. - Durum mimarisi kararını vermek: signal servis → SignalStore → NgRx merdiveni; action/reducer/selector/effect döngüsünü ve saflık/değişmezlik şartını bilmek.
- Eski yazımları okuyabilmek: NgModule,
*ngIf/*ngFor,@Input/@Output, kurucu DI — sahadaki kodun çoğu hâlâ böyle.
02Görev — Arayüzü Angular'a taşı
Hat 08-09'daki başvuru arayüzünü Angular uygulaması olarak yeniden kur. Kullanıcı
gözünde davranış aynı kalmalı: liste, arama (iptalli), beş ekran durumu, kayıt ekleme,
klavye erişilebilirliği. İçeride ise her katman bu hattın araçlarına devredilecek.
Bu kez proje kurulumu gerçek: ng new (ya da StackBlitz'te tam Angular
şablonu) — strict varsayılanlarıyla.
| Bölüm | Yapılacak |
|---|---|
| 1. Kurulum | ng new — standalone, strict; app.config.ts'e
provideRouter (+ withComponentInputBinding) ve
provideHttpClient. API adresini InjectionToken ile
kökte ver. Sahte API olarak 8. hattaki sunucunu ya da genel bir sahte servis
kullan. |
| 2. Bileşen ağacı | En az: liste sayfası (akıllı), başvuru kartı (sunumsal —
input.required + output, OnPush), arama kutusu,
durum rozeti. Kart hiçbir servis enjekte etmez; silme olayı yukarı akar.
@for'da track kayıt kimliğidir. |
| 3. Durum servisi | Başvuru durumu providedIn: "root" serviste, signal
kalıbıyla: private signal + asReadonly() +
türevler (computed: görünen liste, sayaç). Güncellemeler
değişmez. Ekran durumu (yükleniyor/hata/veri/boş) ayırt edici birleşimle. |
| 4. HTTP katmanı | Veri erişimi ayrı serviste: DTO gelen hâliyle tiplenir, tek dönüştürücüden
geçer (9. hat sınır ilkesi). Yükleniyor/hata/veri üçlüsü
startWith/catchError ile tek akışta. Bir
interceptor: her isteğe sabit bir başlık ekle ve süreyi konsola yaz. |
| 5. Rotalar | "" → liste, basvurular/:id → detay (parametre
akış ya da input ile — snapshot yasak; "sonraki başvuru" bağlantısıyla
kanıtla), ** → 404. Detay ya da "yönetim" bölümü
loadComponent ile lazy. Basit bir CanActivateFn:
bayrak yoksa UrlTree ile girişe yönlendir. |
| 6. Form | Yeni başvuru formu Reactive: nonNullable, en az bir özel ve
bir grup düzeyi doğrulayıcı, hatalar touched disipliniyle ve
role="alert" ile. Gönderimde markAllAsTouched +
düğme kilidi; sahte sunucu hatasını setErrors ile alana yaz.
Form dirty iken çıkışı CanDeactivateFn ile sor. |
| 7. Arama | 8. hatta elle çözdüğün yarış artık üç operatör:
debounceTime + distinctUntilChanged +
switchMap; catchError iç akışta (arama
hatada susmamalı). Sonucu toSignal ile duruma indir
(initialValue bilinçli seçilmiş). |
| 8. İleri katman | Bir attribute direktif (appOdakla — panel açılınca ilk
alana odak) ve *appYetkiliyse structural direktifi ("Sil"
düğmesi yetkiye bağlı); kisalt pipe'ı kart açıklamasında.
Sayfa altındaki özet/grafik bölgesi @defer (on viewport) +
boyutlu @placeholder ile. İsteğe bağlı artı: durum servisini
signalStore'a taşı ve satır sayısını kıyasla. |
| 9. Doğrulama | Kabul turu: beş durum, arama iptali (Network'te canceled isteği
gör), F5 her rotada çalışıyor (dev sunucusunun fallback'i bunu
kendiliğinden yapar — neden gerektiğini bir paragrafla yaz), klavye
turu. ng build temiz; konsolda hata yok; hiçbir bileşende elle
subscribe edilmiş, bırakılmamış abonelik yok. |
Kabul ölçütü: davranış Hat 08'deki kabul turuyla birebir; listeye
push yerine değişmez güncelleme yapıldığını OnPush'lu kartın doğru
çalışmasıyla gösterebiliyorsun; hızlı arama değişiminde eski cevabın yeniyi ezmediğini
ve iptal edilen isteği Network sekmesinde gösterebiliyorsun; "F5 neden 404 vermiyor?"
ve "guard neden güvenlik değil?" sorularını iki cümleyle cevaplayabiliyorsun. Bu
uygulamayı silme: 11. hatta aynı görevi React'le yapıp iki çerçeveyi aynı iş
üstünde kıyaslayacaksın.
03Kontrol listesi
Her satırı kendine sorarak işaretle; "evet" diyemediğin satırın dersine dön.
| Yardımsız yapabiliyor musun? | Takılırsan dön |
|---|---|
SPA/MPA kararını vermek; proje anatomisini ve
bootstrapApplication zincirini okumak; AOT'yi, üretim bütçelerini
ve SPA fallback kuralını açıklamak; "pakete sır konmaz" demek |
1. ders |
Arayüzü bileşenlere bölmek; input.required/output
ile veri-aşağı-olay-yukarı kurmak; yaşam döngüsünü ve ViewEncapsulation'ı
bilmek; akıllı/sunumsal ayrımını uygulamak |
2. ders |
Dört binding'i ayırmak; @if/@for/@switch
yazmak; track kararını vermek ve $index'in zararını göstermek;
pipe'ları ve [innerHTML] ciddiyetini bilmek |
3. ders |
Servis yazmak; inject() ve injection context'i (NG0203)
bilmek; provider tariflerini ve InjectionToken'ı kullanmak;
hiyerarşik enjektörü ve çoğalma tuzağını anlatmak |
4. ders |
Observable/Promise farkını ve soğuk akışı anlatmak; abonelik disiplinini
tercih sırasıyla kurmak; düzleştirme kararını vermek; Subject/BehaviorSubject
kalıbını yazmak; catchError'ı doğru yere koymak |
5. ders |
Tipli istek atmak ve get<T>'nin sınırını bilmek;
üçlü durumu tek akışta modellemek; HttpErrorResponse'u okumak;
fonksiyonel interceptor yazmak (clone, sıra) |
6. ders |
Rota tablosu kurmak (pathMatch, joker); parametreyi akış/input
ile okumak; lazy loading ve rota providers kullanmak; guard yazmak ve
güvenlik sınırını doğru çizmek; fallback'i açıklamak |
7. ders |
Tipli Reactive form kurmak (nonNullable,
getRawValue); doğrulama katmanlarını ve touched
disiplinini uygulamak; valueChanges/FormArray
kullanmak; gönderim kalıbını uçtan uca yazmak |
8. ders |
zone.js/OnPush mekanizmasını ve değişmezlik zorunluluğunu anlatmak;
signal/computed/effect ile durum kurmak;
RxJS/signals işbölümünü ve toSignal köprüsünü kurmak; zoneless
yönü bilmek |
9. ders |
Attribute/structural direktif yazmak (* şekeri,
TemplateRef/ViewContainerRef); özel pipe yazmak ve
pipe vs computed kararını vermek; sorguları ve çok yuvalı
ng-content'i kullanmak |
10. ders |
Tembellik katmanlarını doğru sırayla uygulamak; @defer
bloğunu tetikleyici/placeholder/prefetch'iyle kurmak; SSR + hydration'ı,
window tuzağını ve TransferState'i anlatmak;
profil ve paket analiziyle ölçmek |
11. ders |
Durum mimarisi merdivenini gerekçeyle çıkmak; action/reducer/selector/
effect döngüsünü kurmak; effect'te operatör ve catchError yerini
doğru seçmek; SignalStore'u kullanmak |
12. ders |
04Sözlü provası
Angular nedir; hangi tür projede seçersiniz? Mimarisini genel hatlarıyla anlatın.
Angular, Google'ın geliştirdiği, TypeScript'le yazılan ve
tek sayfa uygulamaları (SPA) hedefleyen bir web çerçevesidir. "Çerçeve" vurgusu
önemli: React gibi bir kütüphanenin aksine router, HTTP istemcisi, form altyapısı,
DI ve test araçları kutudan çıkar — mimari kararların çoğu verilmiştir; bedeli
öğrenme eğrisi, kazancı büyük ekiplerde tutarlılıktır. Bu yüzden uzun ömürlü,
çok geliştiricili kurumsal uygulamalarda güçlü adaydır. Mimaride uygulama,
bootstrapApplication ile açılır; yapı taşı standalone bileşendir —
sınıf (durum ve davranış) + şablon (görünüm) + üst veri; bileşenler ağaç kurar,
veri aşağı input'larla iner, olay yukarı output'larla çıkar. İş mantığı ve
paylaşılan durum servislerde yaşar, DI ile ulaşır; sayfalar router'ın URL-bileşen
eşlemesiyle çizilir; sunucu iletişimi Observable döndüren HttpClient'tan,
reaktivite RxJS akışları ve giderek signals üzerinden akar. Derleme AOT'dir:
şablonlar üretimde koda çevrilir, hatalar derlemede yakalanır; çıktı hash'li
paketlerdir ve barındırma SPA fallback ister. Eski kod tabanlarında NgModule ve
*ngIf dünyasını da okuyabilirim — sahada ikisi bir arada yaşıyor.
Bileşen mimarisini ve DI'ı birlikte anlatın: durum nerede yaşar, sınırlar nasıl çizilir?
Kural katmanlıdır. Görünüm bileşenindir: sunumsal bileşen
yalnız input alır, olay yayar, servis enjekte etmez — test ve yeniden kullanım
bedavaya gelir; akıllı bileşen az sayıdadır, servisleri o bağlar. İş mantığı ve
bileşenden uzun yaşaması gereken durum servistedir: providedIn: "root"
ile tree-shakable singleton olarak kaydedilir, durum private tutulup
dışarıya salt okunur yüz verilir, güncellemeler değişmezdir. Servisi bileşene DI
ulaştırır: modern yol inject() — tip dönüşten gelir, kalıtımda kurucu
tekrarı gerektirmez, guard/interceptor gibi fonksiyonlarda da çalışır; tek kuralı
injection context'tir, bağımlılıklar sınıfın tepesinde alan olarak alınır. Enjektör
hiyerarşiktir: arama bileşenden köke çıkar, ilk tarif kazanır — bileşen
providers'ı bilinçli kapsam açar (sihirbaz durumu), dikkatsizce
kullanılırsa "singleton'ım çoğaldı" tuzağıdır. Sınıf olmayan değerler
InjectionToken ile verilir çünkü arayüz çalışma anında yoktur. DI'ın
meyvesi değiştirilebilirliktir: testte sahte provider, üretimde ortam factory'si —
tüketici kod değişmez. Bu, .NET tarafında bildiğim DI'ın aynısıdır; fark eksendedir:
kapsam HTTP isteği değil bileşen alt ağacıdır.
Angular ekranı ne zaman günceller? zone.js, OnPush ve signals'ı bir bütün olarak anlatın.
Üç kuşaklı bir hikâye. Klasik mekanizmada zone.js, tarayıcının
asenkron API'lerini sararak "bir iş bitti" haberini çerçeveye taşır; Angular da
"durum değişmiş olabilir" varsayımıyla bileşen ağacını tarayıp bağları yeniden
değerlendirir — şeffaf ama kaba: ne değiştiğini bilmez, alakasız bir zamanlayıcı
bile tüm ağacı taratır. İkinci kuşak OnPush'tur: bileşen yalnız input referansı
değişince, kendi olayı doğunca, async pipe'ına değer gelince ya da okuduğu signal
değişince kontrol edilir. Bedeli değişmezlik sözleşmesidir — diziye push eden kod
referansı değiştirmediği için ekranı güncelleyemez; "tıklayınca birden göründü"
belirtisini teşhis edebilirim. Üçüncü kuşak signals: değer artık değiştiğini kendisi
bildirir — okuma bağımlılık kaydeder, set/update tam olarak bayatlayan
görünümleri uyarır; computed tembel ve önbellekli türev, effect
dışa dönük yan etkidir. Bu bildirimli model zoneless Angular'ı mümkün kılar:
zone.js devreden çıkar, tahmin yerine bilgi vardır. İşbölümü de netleşir: zaman ve
olay (debounce, yarış, HTTP) RxJS'te kalır, durum ve türev signal'a geçer; sınırda
toSignal/toObservable köprüleri durur.
Bir özelliği uçtan uca anlatın: "başvuru detayı + düzenleme formu" ekranını nasıl kurarsınız?
Rotadan başlarım: basvurular/:id tanımı, özellik
büyükse loadComponent ile lazy; girişli kullanıcı şartı varsa
CanActivateFn — UrlTree ile yönlendirir, ama bunun UX
olduğunu, asıl yetkinin API'de denetlendiğini bilirim. Parametreyi akış ya da input
binding ile okurum — aynı bileşen 42'den 43'e yeniden kullanılır, snapshot eski
kayıtta bırakır; switchMap hızlı gezinmede önceki isteği iptal eder.
Veri katmanı serviste: DTO gelen hâliyle tiplenir (tarih string), tek dönüştürücüden
iç modele geçer — get<T> beyandır, kanıt değil; ekran
yükleniyor/hata/veri üçlüsünü ayırt edici birleşimle, startWith +
catchError ile tek akışta modeller, şablon @switch ile
çizer. Düzenleme formu Reactive'dir: nonNullable grup, kayıt
patchValue ile dökülür, alanlar arası kural grup doğrulayıcısında,
hatalar touched'dan sonra role="alert" ile. Gönderimde
markAllAsTouched → düğme kilidi → getRawValue tek
dönüştürücüden gövdeye → 422 dönerse setErrors ile alanlara geri;
form dirty iken çıkışı CanDeactivateFn sorar. Durum signal
kalıbındadır; kart bileşenleri OnPush + değişmez güncellemeyle çizilir. Kesişen
işler — kimlik başlığı, süre günlüğü — interceptor'dadır.
05Karar
Görevi yardımsız bitirdiysen
Bu düğümü "tamamladım" işaretle — Hat 10 kapanır. İlan A'nın "React / Angular / Vue'dan en az biri" ve İlan B'nin "React / Angular / Vue frontend kütüphaneleri" maddeleri için Angular kanadı tamam; iki madde de Hat 11'le birlikte tümden kapanacak. Artık 8. hatta elle kurduğun her mekanizmanın çerçevedeki karşılığını biliyorsun: DOM güncellemesi → şablon + değişiklik algılama, durum makinesi → signal + ayırt edici birleşim, yarış → switchMap, form doğrulaması → Reactive Forms. Sıradaki durak Hat 11 · React: aynı görevi bu kez React'le yapacak, iki çerçeveyi aynı iş üstünde kıyaslayacaksın — Angular'ın kutudan çıkardığı router/form/DI kararlarını React ekosisteminde tek tek kendin vereceksin; bu kıyas, mülakatların "neden X, neden Y değil" sorusunun en sağlam cevabıdır. Angular sürümünü silme — kıyasın referans ucu o.
Takıldıysan
Takıldığın maddeyi tablodan dersine eşle, o dersi ve mini alıştırmasını yeniden
çalış, 24 saat sonra görevi düzeltmeden, sıfırdan yap. Bu hatta en sık
takılan altı yer: istek atılmıyor ya da iki kez atılıyor
(5. ve 6. ders —
tembellik ve soğuk akış), listeye ekleyince ekranın güncellenmemesi
(9. ders — OnPush + mutasyon; değişmez
güncelleme), "singleton'ım çoğaldı"
(4. ders — bileşen providers'a ikinci
kayıt), detay sayfasının parametre değişiminde eski kayıtta kalması
(7. ders — snapshot yerine akış/input),
aramanın ilk hatadan sonra susması
(5. ders — catchError dış zincirde)
ve grup doğrulayıcısının tek alana konması
(8. ders — alanlar arası kural grup düzeyine).
Bu altısı, sahadaki Angular kod incelemelerinin de en sık işaretlenen
hatalarıdır; şimdi çözersen orada ayrıştırıcı olursun.
