Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Angular 16 Signals – State Management

Merhaba,

Bu içeriğimizde, Angular 16 ile gelmiş olan Signals yapılanmasını kullanarak state management’ın nasıl uygulanabileceğini inceliyor olacağız.

Angular mimarisi, yapısal olarak fazlasıyla kurallı bir anatomiye sahip olsa da, esasında temel mantığı anlaşıldığı taktirde oldukça kolay ve geliştirici dostu bir yapıya sahiptir. Haliyle bu tarz zahiren komplike gözüken bir mimaride mevzu bahis state management olduğunda da ister istemez bir karmaşıklık söz konusu olabilmektedir.

Doğrusu büyük projelerde state management’ı sağlayabilmek için basitlik ilkesi gereği mümkün mertebe sade bir yaklaşım sergilenmesine ve oldukça sadece ihtiyaç olan state’lerin yönetilmesine odaklanılması gerektiği kanaatindeyim.

Bunun için tercihen NgRx başta olmak üzere Akita ve MobX gibi hazır kütüphanelerden istifade edilebileceği gibi esasında bu kütüphanelerin getirdiği karmaşıklık ve basmakalıp(boilerplate) yapılanmalardan kaçınmak için herhangi bir framework’e ihtiyaç duyulmaksızın Angular mimarisinin injectable servislerinden istifade edilmesi gerektiğine dair son zamanlarda kanaat getiriyor gibiyim… Çünkü injectable service’ler; reaktiftirler, başlangıç değerleri mevcuttur ve yazılmaları, geliştirilmeleri ve bakımları oldukça kolay ve maliyetsizdirler.

Zamanla anladım ki, projenin hacmi ne olursa olsun, state management için actions, action types, reducers, selectos, effects vs. gibi terminolojik terimlerin öğrenilmesine ve ayrıca bunların kullanılıp, yönetilme zahmetinin verilmesine sanırım hiçte gerek yokmuş. Ayrıca NgRx’den yola çıkarsak eğer arka planda kullandığı BehaviorSubject aşağıdaki kimi dezavantajları da barındırdığı için ister istemez bu kanaatim hakkında haklılık payımı da görmedim değil;

  • RxJS’i son derece iyi bilmeyi gerektirmektedir.
  • Uzun süreli veya büyük veri akışlarında çalışırken fazlasıyla bellek tüketimi ve hatta bellek sızıntıları(memory leaks) söz konusu olabilir.
  • Birden fazla iş parçacığı veya asenkron işlem söz konusu olduğu durumlarda, senkronizasyon veya güvenilirlik sorunları söz konusu olabilir.

Haliyle tüm bu kaygılara karşın, injectable service’lere nazaran değişiklik algılama ve senkronizasyon açısından oldukça optimize edilmiş olan ve anlık olarak değerini her daim okuyabilme(snapshot) imkanımız olan signal yapılanmasını da state management süreçlerinde tercih edebiliriz.

Bunun için signal tabanlı bir store tasarlamamız yeterli olacaktır. Bunu da aşağıdaki gibi bir component’te girilen person bilgilerinin, başka bir component’te listelendiği basit bir senaryo çalışması üzerinden inceleyebiliriz.

Şimdi CreatePersonComponent ve ListPersonComponent adında iki component’e ve PersonStateManagementService adında da bir service’a sahip bir uygulama tasarlayalım.

ng g c components/createPerson --standalone
ng g c components/listPerson --standalone
ng g s services/personStateManagement

İlk olarak PersonStateManagementService‘ini aşağıdaki gibi geliştirelim;

import { Injectable, WritableSignal, signal } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class PersonStateManagementService {

  constructor() { }

  persons: WritableSignal<{ name: string, surname: string }[]> = signal([]);
  createPerson(name: string, surname: string) {
    this.persons.mutate(datas => datas.push({
      name: name, surname: surname
    }))
  }

  getPersons() {
    return this.persons();
  }
}

Yukarıdaki çalışmaya göz atarsanız eğer 10. satırda oluşturulmuş olan ‘persons’ isimli signal içerisindeki koleksiyona, ‘createPerson’ metodunda name ve surname bilgileri gelen person nesnesi eklenmekte, ‘getPersons’ metodunda ise bu signal’ın değeri olan koleksiyon geriye döndürülmektedir.

Şimdi oluşturduğumuz component’lerin içeriklerini sırasıyla aşağıdaki gibi geliştirelim;

import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PersonStateManagementService } from 'src/app/services/person-state-management.service';

@Component({
  selector: 'app-create-person',
  standalone: true,
  imports: [CommonModule],
  template: `
    <input type="text" #txtName placeholder="Name"> <br>
    <input type="text" #txtSurname placeholder="Surname"> <br>
    <button (click)="createPerson(txtName.value, txtSurname.value)">Create Person</button>
  `,
})
export class CreatePersonComponent {
  personStateManagementService: PersonStateManagementService = inject(PersonStateManagementService);
  createPerson(name: string, surname: string) {
    this.personStateManagementService.createPerson(name, surname);
  }
}
import { Component, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PersonStateManagementService } from 'src/app/services/person-state-management.service';

@Component({
  selector: 'app-list-person',
  standalone: true,
  imports: [CommonModule],
  template: `
    <ul>
      <li *ngFor="let person of persons">{{person.name}} {{person.surname}}</li>
    </ul>
  `,
})
export class ListPersonComponent implements OnInit {
  personStateManagementService: PersonStateManagementService = inject(PersonStateManagementService);


  persons: { name: string, surname: string }[];
  ngOnInit() {
    this.persons = this.personStateManagementService.getPersons()
  }
}

Görüldüğü üzere CreatePersonComponent‘te eklenen person bilgileri, signal tabanlı servis sayesinde ListPersonComponent‘e dinamik bir şekilde aktarılmaktadır. Ya da bir başka deyişle person ekleme durumu neticesinde oluşan değişiklik anlık olarak listelemeden sorumlu olan component’e yansıtılmaktadır.

Evet, anlayacağınız herhangi bir third party library kullanmaksızın Angular uygulamalarında state management’ın signal’lar ile nasıl yönetilebileceğini görmüş ve özellikle büyük projelerde basit ve sade bir yaklaşımla bu işlemin yapılabileceğini vurgulamış olduk. Bu yaklaşım ile karmaşıklık azaltılırken, projelerin daha etkili ve verimli bir şekilde geliştirilmesine olanak tanındığına sizlerin de kanaat getirdiğini düşünüyorum.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not: Örnek çalışmaya aşağıdaki github adresinden erişebilirsiniz.
https://github.com/gncyyldz/StateManagementExampleInAngular

Bunlar da hoşunuza gidebilir...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir