Giriş

Her yazılım projesinde tekrar eden işlemler, ortak fonksiyonlar ve yardımcı ihtiyaçlar vardır. Çoğu projede “Helper” veya “Util” olarak adlandırılan yardımcı sınıflar, tekrar eden kodu merkezileştirmek ve tekrar kullanımı artırmak için kullanılır.

helper-util

1. Helper/Util Sınıfları Nedir?

  • Helper/Util sınıfları, kodun farklı yerlerinde tekrar eden küçük işlevleri toplar.
  • Genellikle “StringHelper”, “DateUtil”, “FileHelper” gibi isimler alır.
  • Kodun okunabilirliğini ve tekrar kullanılabilirliğini artırır.

Temel Örnekler

  • Tarih formatlama
  • String işlemleri
  • Dosya okuma/yazma
  • E-posta gönderme
  • Validation işlemleri

2. Static Helper Kullanımı

Tanım

En klasik yöntem, yardımcı fonksiyonları static bir sınıfa koymaktır.

Avantajları

  • Kullanımı çok kolay ve hızlıdır.
  • Kodun herhangi bir yerinden erişilebilir.

Dezavantajları

  • Test edilemezlik: Mock veya dependency injection ile kolayca taklit edilemez.
  • State yönetimi yoktur, yan etkiler çıkabilir.
  • “God class” riskine yol açar (her şey bir sınıfa eklenirse).

C# Static Helper Örneği

public static class StringHelper
{
    public static bool IsNullOrEmpty(string s)
    {
        return string.IsNullOrEmpty(s);
    }

    public static string ToTitleCase(string s)
    {
        return System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
    }
}

// Kullanım:
bool isEmpty = StringHelper.IsNullOrEmpty("Tanju");
string title = StringHelper.ToTitleCase("merhaba dünya");

3. Dependency Injection ile Helper Kullanımı

Tanım

Helper sınıfı bir interface ile tanımlanır, uygulamaya dışarıdan “enjekte” edilir.
Bu, test edilebilirlik ve esneklik için modern ve önerilen bir yöntemdir.

Avantajları

  • Mock ve test kolaylığı
  • State yönetimi ve yapılandırma imkanı
  • Modülerlik ve gevşek bağlılık

Dezavantajları

  • Kullanım karmaşıklığı artabilir.
  • DI container yapılandırması gerekir.

C# DI ile Helper Örneği

public interface IEmailHelper
{
    void SendEmail(string to, string subject, string body);
}

public class EmailHelper : IEmailHelper
{
    public void SendEmail(string to, string subject, string body)
    {
        // Gerçek e-posta gönderim kodu
        Console.WriteLine($"Mail gönderildi: {to}, {subject}");
    }
}

// DI ile kullanımı:
public class NotificationService
{
    private readonly IEmailHelper _emailHelper;
    public NotificationService(IEmailHelper emailHelper)
    {
        _emailHelper = emailHelper;
    }
    public void Notify(string email)
    {
        _emailHelper.SendEmail(email, "Hoşgeldin!", "Sisteme giriş yaptınız.");
    }
}

.NET Core DI Kayıt

services.AddTransient<IEmailHelper, EmailHelper>();
services.AddTransient<NotificationService>();

4. Avantajlar ve Dezavantajlar

Avantajlar

  • Tekrar Kullanılabilirlik: Aynı fonksiyon farklı yerlerde yeniden kullanılabilir.
  • Bakım Kolaylığı: Kodda değişiklik gerektiğinde sadece helper sınıfında güncelleme yeterli olur.
  • Test Edilebilirlik: DI ile kullanıldığında kolayca mock yapılabilir.
  • Modülerlik: Kodun bağımlılıkları netleşir, bağımlı kodlar sadeleşir.

Dezavantajlar

  • Static helper’larda test, mock ve konfigürasyon imkansız veya çok zordur.
  • Helper/Util sınıflarının aşırı şişmesi: Tek bir sınıfa çok fazla iş yüklemek.
  • Yanlış kullanımlarda “God class” veya anti-pattern riski.

5. C# Kod Örnekleri

Static Helper

public static class MathHelper
{
    public static int Factorial(int n)
    {
        if (n <= 1) return 1;
        return n * Factorial(n - 1);
    }
}

// Kullanım:
int result = MathHelper.Factorial(5);

DI ile Helper

public interface IGuidHelper
{
    string NewGuid();
}

public class GuidHelper : IGuidHelper
{
    public string NewGuid() => Guid.NewGuid().ToString();
}

// Kullanım:
public class UserService
{
    private readonly IGuidHelper _guidHelper;
    public UserService(IGuidHelper guidHelper)
    {
        _guidHelper = guidHelper;
    }
    public void RegisterUser(string name)
    {
        var id = _guidHelper.NewGuid();
        Console.WriteLine($"{name} kaydedildi, ID: {id}");
    }
}

Test Edilebilirlik

// Mock ile test
public class FakeGuidHelper : IGuidHelper
{
    public string NewGuid() => "FAKE-GUID";
}

// Testte:
var userService = new UserService(new FakeGuidHelper());
userService.RegisterUser("Tanju"); // Her zaman "FAKE-GUID" kullanılır

6. Görseller & Diyagramlar

helper-util-resim

7. Özellikle dikkat edilmesi gerekenler

1. Her işlevi tek Helper/Util sınıfına eklemek.

Bu, helper sınıfının “God class” olmasına ve Single Responsibility Principle (SRP) ihlaline yol açar. Her farklı iş (örn. tarih işlemleri, string işlemleri, dosya işlemleri) için ayrı helper sınıfı önerilir.

2. Static helper’larda state saklamak

Çok önemli:

  • Static helper’larda kesinlikle değişken (field) olarak veri tutmak veya global state kullanmak tehlikelidir.
  • Static fonksiyonlar saf (stateless, pure) olmalı.
  • Yoksa thread-safe olmaz, beklenmedik yan etkiler olur.

3. Yardımcı sınıfı doğrudan iş kuralları katmanında çağırmak

Bu madde net:

  • Helper, service/repository ayrımını ihlal edecek şekilde kullanılmamalı.
  • Helper’lar “iş mantığı” içermez, sadece tekrarlayan basit işlemler için kullanılmalı.

4. Static helper’larda bağımlılık zinciri oluşturmak

Eğer bir static helper başka bir static helper’ı çağırıyorsa ve/veya zincirleme hale geliyorsa kod karmaşıklaşır, yönetimi zorlaşır.

  • Helper’lar sade ve bağımsız olmalı, zincir büyümemeli.

5. Test edilemeyen, büyüyen helper class’lar.

Helper’ların test edilebilir olması önemli; static helper kullanıldığında mocking/test zorlaşır. DI ile kullanılan helper/mock ile kolayca test edilir.

8. En İyi Uygulamalar

  • Her helper için ayrı interface ve implementasyon yaz (SRP’ye dikkat!).
  • Helper/Util’leri sadece ihtiyaç olan katmana enjekte et.
  • Dependency Injection ile test ve mock imkanı oluştur.
  • Helper’larda state tutma, sadece saf fonksiyonlar kullan.
  • Kullanımı zorunlu olmayan genel fonksiyonları extension method ile yazabilirsin.
  • Gereksiz helper oluşturmaktan kaçın; gerçekten ortak, tekrar eden işlemler için helper yaz.

9. Sıkça Sorulan Sorular

Static helper ile DI helper arasında ne zaman seçim yapmalıyım?
Test ve yapılandırma gerekiyorsa DI kullan.
Sadece saf, yan etkisiz fonksiyonlar için static tercih edebilirsin.

Helper class yerine extension method yazmak daha mı iyi?
Sadece bir tipe yeni, yan etkisiz fonksiyon ekliyorsan extension method uygundur.

Bir helper’a başka helper enjekte etmek iyi mi?
Genellikle hayır. Helper’lar sade ve bağımsız olmalı.
Bağımlılık karmaşası oluşmaması için helper’a helper enjekte etmekten kaçın.

Yardımcı sınıflar ne zaman anti-pattern olur?
Her işi tek bir helper’a yüklediğinde, static içinde state tuttuğunda, veya kodun yarısı sadece helper’a bağımlı olduğunda.

10. Sonuç ve Pratik İpuçları

  • Helper/Util sınıflarını küçük, basit ve amaca uygun tasarla.
  • Test edilebilirlik ve modülerlik için DI kullan.
  • Static helper’ı sadece saf, basit fonksiyonlar için kullan.
  • Helper/Util’lerin iş kuralları katmanına karışmasına izin verme.
  • Kodda helper yerine extension method veya service katmanı tercih edilebilir.
  • Proje büyüdükçe helper’ları modüllere ayır ve şişirmemeye dikkat et.

11. Kaynaklar

By tanju.bozok

Software Architect, Developer, and Entrepreneur

Bir yanıt yazın

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