DEV Community

Cover image for Feature flag teknik borca nasıl dönüşür?
Hüseyin Bozdemir
Hüseyin Bozdemir

Posted on Originally published at huseyinbozdemir.com on

Feature flag teknik borca nasıl dönüşür?

Bir tenant'ı mutlu etmek için açılmış bir flag'imiz vardı. Ürün o tenant'ta biraz farklı çalışsın diye veritabanındaki ayar tablosuna bir satır eklenmiş, kodda da o satıra bakan bir if yazılmıştı. Sonraki her geliştirmede o if'i bozmamak için kulağı tersten tuttuk. Yeni özellik o tenant'ta nasıl davranacak, eski yol hâlâ çalışıyor mu, testte o tenant'ın ayarını da açtık mı? Sonra bir gün öğrendik ki o tenant ürünü kullanmayı çoktan bırakmış.

Feature flag, kodu yeniden yayınlamadan bir davranışı açıp kapatan anahtardır. Bu yazının iddiası şu: tek bir müşteri için açılan flag'in bir sahibi ve bir bitiş tarihi olmaz; bu yüzden kapanmaz ve zamanla teknik borca dönüşür.

Feature flag nedir, neden kapanmaz?

En basit hali bir config değeri; bizde olduğu gibi veritabanında tenant bazlı bir ayar da olabilir: "bu tenant'ta yeni ekran açık, diğerlerinde kapalı."

Martin Fowler'ın feature toggle yazısı flag'leri ömürlerine göre ayırır. Bir özelliği yarım haliyle canlıya almak için açılan release toggle birkaç hafta yaşar ve özellik herkese açılınca silinir. Bir müşteriye ya da pakete özel davranışı açan permissioning toggle ise uzun ömürlüdür; aslında bir ürün kararıdır.

Sorun, tenant'a özel flag'in ikisinin arasında kalması. Geçici bir ihtiyaç için açılır ("şimdilik bu müşteride böyle olsun"), ama kalıcı bir ayar gibi saklanır. Kapatılacağı bir tarih yoktur, kapatma kararını verecek bir sahibi de yoktur. Ayar tablosunda bir satır olarak durur ve kimse onu silmeye cesaret edemez, çünkü kimin kullandığını bilen yoktur.

Bedeli kodda ödenir

Her flag kodda iki yol demek. İki flag dört kombinasyon, üç flag sekiz. Bunların hepsi test edilmez; genelde varsayılan yol test edilir, flag'li yol "eskiden çalışıyordu" diye kalır.

Asıl maliyet yeni geliştirmede ortaya çıkıyor. Bizdeki flag tek bir tenant içindi ama o tenant'ın yolu her yeni işin içine girdi. Tasarımı o yolu bozmayacak şekilde eğip büktük. Sonunda kodun bir kısmı, artık kimsenin kullanmadığı bir davranışı korumak için vardı.

Tenant'ın ürünü bıraktığını da sonradan öğrendik. O dalın en son ne zaman çalıştığını gösteren bir şey yoktu.

Temizlik

Bu olaydan sonra feature flag temizliği yaptık ve tenant'a özel davranışların hepsini ortak davranışa çektik: her tenant aynı yoldan geçiyor. Flag'li dallar koddan silinince, her yeni işte sorulan "o tenant'ta ne olur?" sorusu da ortadan kalktı.

Yeni bir flag açarken

Temizlik bir kez yapılınca bitmiyor; yeni flag'ler aynı yoldan gelir. Bir flag eklerken şu üç soruya cevap verilmiş olmalı:

  • Sahibi kim? Kapatma kararını verecek kişi ya da ekip. Sahibi olmayan flag sonsuza kadar yaşar.
  • Ne zaman silinecek? Geçici bir flag'in son kullanma tarihi olmalı. Fowler'ın yazısında anlatılan bir yöntem, tarihi geçen flag'de testi kırmak.
  • Kim kullanıyor? Flag'li yol çalıştığında bunu tenant bilgisiyle loglamak ya da saymak. Son 90 günde hiç çalışmamış bir dal, silinmek için en güçlü argümandır.

İkinci maddenin .NET'teki basit bir hali:

public sealed record FeatureFlag(string Ad, string Sahip, DateOnly SonKullanma);

public class FlagTarihleriTesti
{
    [Fact]
    public void Suresi_gecmis_flag_kalmasin()
    {
        var bugun = DateOnly.FromDateTime(DateTime.UtcNow);

        // FlagKatalogu: flag'lerin tutulduğu yer (ayar tablosu, config)
        var gecmis = FlagKatalogu.Tumu
            .Where(f => f.SonKullanma < bugun)
            .Select(f => $"{f.Ad} ({f.Sahip})");

        Assert.Empty(gecmis);
    }
}
Enter fullscreen mode Exit fullscreen mode

Test kırıldığında iki seçenek var: flag'i silmek ya da tarihi bilerek uzatmak. İkisi de bir karar; önemli olan, flag'in kendiliğinden yaşamaya devam etmemesi.

Bizim hikâyemizde bu üç sorudan yalnızca üçüncüsü sorulmuş olsaydı, o tenant'ın gittiğini çok daha önce öğrenirdik.


Bu yazı ilk olarak huseyinbozdemir.com'da yayımlandı.

Top comments (0)