tarihinde yayınlandı Yorum yapın

Data Transfer Objects Nedir? Güzellikleri Nelerdir? Gerçek Bir Uygulama Örneği Üzerinden

Bir önceki yazımın üzerinden 24 saat geçmeden ikinci yazıyı paylaşıyorum, normalde çok nadirdir bu durum.

Öncelikle Data Transfer Objects veya nam-ı diğer DTO nedir? Hemen Claude’a yazdıralım:

Data Transfer Objects (DTO), farklı yazılım katmanları veya sistemler arasında veri taşımak için kullanılan, genellikle sadece veri içeren ve iş mantığından arındırılmış basit nesnelerdir. DTO’lar, özellikle istemci-sunucu mimarisinde veya mikroservis yapılarında, veritabanı varlıklarının (entity) doğrudan dış dünyaya açılmasını önleyerek güvenliği artırır ve gereksiz veri transferini azaltır. Örneğin, bir kullanıcı nesnesi veritabanında şifre, e-posta doğrulama token’ı gibi birçok alan içerebilirken, DTO sadece isim, soyisim ve profil fotoğrafı gibi API üzerinden paylaşılması gereken alanları taşır. Bu sayede hem performans iyileşir (gereksiz veri taşınmaz), hem güvenlik artar (hassas veriler gizlenir), hem de farklı katmanlar arasında gevşek bağlılık (loose coupling) sağlanarak kod daha sürdürülebilir hale gelir.

CLAUDE AI

Bu Claude’un yaptığı tanım fakat biz Laravel geliştiricileri için Model’de tanımlanan $hidden ve Resource bu açıklamadaki bir çok hizmeti bize sağlıyor. Gelelim benim ihtiyacımın nerede oluştuğuna, örnek kodlarımı biraz sadeleştiriyorum elbette.

Senaryom çok basit, kullanıcı e-posta adresini değiştirdiğinde yeni e-posta adresi ve rastgele bir string ifadeyi array’de saklayıp Cache’e kaydetmek istiyorum.

PHP
$email_change_data = [
    'hash' => Str::random(64),
    'new_email' => $email,
    'created_at' => now(),
];

Cache::set('email_change', $email_change_data, 60 * 60 * 3);

Buradaki problem dizi anahtarlarımı asla unutmamam gerekiyor. Diğer türlü farklı bir yerde email_change önbelleğini sorgularsam elde edeceğim dizide kullandığım anahtarları hatırlamak için tekrar gerisin geri buraya dönmem gerekiyor. İşte tam bu noktada imdadımıza DTO’lar yetişiyor.

Laravel’de aslında istediğimiz varlıklarla bir gün Collection oluşturabilirsek bu DTO mitio falan hiç gerekmeyecek muhtemelen. php artisan make:collection EmailChangeCollection komutu ile bir nevi DTO yapabilir oluyoruz. Sanırım.

Şimdi app dizini içerisinde DTOs diye bir klasör oluşturalım. Ben böyle yapmayı seviyorum en azından. Yukarıdaki problemi çözen DTOmuzu hazırlayalım:

PHP
<?php

namespace App\DTOs;

use Illuminate\Support\Carbon;
use Illuminate\Support\Str;

readonly class EmailVerificationData
{
    public function __construct(
        public string $hash,
        public ?string $new_email,
        public Carbon $created_at,
    ) {}

    public static function create(?string $email = null): self
    {
        return new self(
            hash: Str::random(64),
            new_email: $email,
            created_at: now(),
        );
    }

    public function toArray(): array
    {
        return [
            'hash' => $this->hash,
            'new_email' => $this->new_email,
            'created_at' => $this->created_at,
        ];
    }

    public static function fromArray(array $data): self
    {
        return new self(
            hash: $data['hash'],
            new_email: $data['new_email'],
            created_at: $data['created_at'],
        );
    }
}

Yukarıdaki örnekte de görebileceğiniz üzere dizide tanımladığımız öğelerin veri tiplerini de tanımlamış olduk. Bu sayede hem bu verinin içeriğini hatırlamamıza gerek kalmayacak, IDE’miz bize hatırlatacak aynı zamanda created_at ile Carbon nesnesini rahatlıkla kullanabilir olacağız. create() metodu ile aşağıdaki örnektede görebileceğiniz gibi kaydedilecek verimizi hazırlıyorum. toArray() ve fromArray() metodlarını kullanmayı tercih ediyorum. Bu dönüşümlerle beraber verimin hangi DTO olduğunu IDE ile paylaşıyorum kabaca.

Şimdi ilk hazırladığımız kodu güncelleyelim:

PHP
$email_verification_data = EmailVerificationData::create($email);
Cache::set('email_change', $email_verification_data->toArray(), 60 * 60 * 3);

Çok harika değil mi? Artık verimi DTO ile oluşturdum, diziye çevirip cache’e attık. Şimdi cache’den veriyi alıp kontrol işlemlerine geçelim:

PHP
$email_verification_data = EmailVerificationData::fromArray(Cache::get('email_change'));

İşte cachedeki veri ile DTOmuzu oluşturduk yeniden. Bu örnekte cacheten verinin direkt geleceği varsayılışmıştır, cache’in varlığını öncesinde kontrol etmeniz gerekir veyahut Cache::get('email_change', ['hash' => null, 'new_email' => null, 'created_at' => now()]) gibi bir fallback ekleyebilirsiniz ki cache varlığını önceden kontrol etmenizi tavsiye ederim.

Artık email_verification_data değişkenini isteğimiz doğrultusunda değerlendirebiliriz.

PHP
if($email_verification_data->hash === $incoming_hash) {
  echo $email_verification_data->created_at->toDateTimeString();
}

Bu sayede hem projeniz daha sürdürülebilir bir hale geliyor, hem daha okunabilir hale geliyor hem de type safe olduğundan bir kat daha güvenli hale geliyor.

Böyle veli nimetlerden faydalanmak gerekiyor, lazım olduğunda. Bir başka yazıda görüşünceye dek, selametle.

Bir yanıt yazın

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