Skip to content

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 (async pipe → 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ı, touched disiplini, 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/effect ile 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/contentChild sorguları, çok yuvalı projeksiyon, hostDirectives kompozisyonu.
  • 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ı ve window tuzağı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ümYapı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.