Bu yazıda özellikle programlamaya yeni başlayanlar için seçtiğiniz programlama dilinden bağımsız olarak karşınıza çıkabilecek mutable ve immutable kavramlarından bahsedeceğim. İlgili dilleri öğrenirken kaynakarda şunlar şunlar mutable’dır, şunlar şunlar immutable’dır gibi bir not görürseniz bu kavramları ve ne anlama geldiğini bilmeniz önemli olacaktır.

Normalde mutable ve immutable nedir konulu bir yazı yazmak aklıma bile gelmezdi. Golang kurcalamaya başladığım bu günlerde dokümanlarda karşıma çıkınca hemen yazı konusu olarak not aldım.

Mutable değiştirilebilir bir değişken/değer anlamı taşır. Değişken ama değiştirilemez bu nasıl oluyor?

Örneğin Javascript’de nesneler (object) ve diziler (array) mutable iken string, number, bigint, boolean, undefined, symbol ve null (primitive types) immutable yani değiştirilemezdir. Diğer örneği de Go’dan verelim. Go’da string ve int değerler, interface, booleans, numerik değerler, pointer’lar vs. vs. immutable iken, array, slice, map, channel gibi değerler mutable’dır.

Ama biz bunların hepsini değiştirebiliyor, yeni değerler atayabiliyoruz, o zaman değiştirilemez ne demek? Javascript’de bir stringi atadıktan sonra değiştiremiyor muyuz? Aslına bakarsanız değiştirmiyoruz. O stringin değiştirilmiş kopyası yeni bir değer olarak hafızada bir yere yazılıyor, eski kopya ise garbage collection sürecine (çöp toplama desem anlaşılır mıydı?) giriyor.

Kodu yüzeysel yazan biri için değiştirilebilir/değiştirilemez diye bir kavram yok, ama biraz daha derinde işlerin nasıl yürüdüğünü önemiyorsanız kodunuzu yazarken bu bilgiyi dikkate almanızda fayda var. Örneğin bir for döngüsü içerisinde 10000 defa bir string değiştiriyorsanız, aslında garbage collector tarafından temizlenmesi gereken 9999 kopya hafızada yer kaplamış oluyor.

Bir stringin sadece bir defa değiştirilmesinde arkada dönen mantık nedir Mozilla sitesinde bu konu şöyle bir örnekle açıklanmış.

var immutableString = "Hello";

// In the above code, a new object with string value is created.

immutableString = immutableString + "World";

// We are now appending "World" to the existing value.

immutableString değişkenine yeni bir metin eklerken şunlar gerçekleşiyor

  1. immutableString değişkeninin mevcut değeri alınıyor.
  2. mevcut değere “World” kelimesi ekleniyor.
  3. Sonuç hafızada yeni bir bloğa yazılıyor.
  4. immutableString değişkeni artık hafızadaki bu yeni bloğa işaret ediyor
  5. önceki hafıza alanı garbage collection tarafından temizlenmek için hazır

Nesnelere referansla ulaşımKopya ve Referans/Pointer farkı

Java, C#, Go, Python vb. dillerde nesnelere referans vererek ulaşmak mümkün. Kimi zaman bunu özellikle böyle yapmamız gerekirken, kimi zaman bizi buna mecbur kılan bir durum olmuyor. Fakat bu gibi durumlarda bile nesnenin kopyası yerine referansını vermemiz daha faydalı olacaktır. Örneğin Go’da bir metoda gönderdiğimiz parametre nesnenin/değişkenin pointer’ı yerine kendisi ise hafızada yeni bir nesne oluşturulmuş oluyor.

Bu metodu bir döngü içerisinde – örneğin o an socket üzerinden bağlı tüm istemcilere bir mesaj göndermek için- kullandığımızı düşünürsek gereksiz bir hafıza kullanımı ve garbage collection süreci (her ne kadar go bu konuda oldukça başarılı olsa da) başlamış olacak.

Sözün özü çalışan değil, verimli çalışan kodlar yazmak için mutable, immutable ve pointer kavramlarının çok iyi anlaşılması gerekiyor, bu yazıyı yazarka bu konuda bir not düşmek istedim. 😉

Kapak Fotoğrafı: KOBU Agency on Unsplash