Sadece genellikle değişmezlik etrafında dönmeyen dillerde oluşturulan değişmez türler, istenen değişiklikleri ifade etmek için bazı "oluşturucu" nesne türüne ihtiyaç duymaları durumunda potansiyel olarak kullanımın yanı sıra, daha fazla geliştirici zamana mal olma eğiliminde olacaktır (bu, genel olarak iş daha fazla olacak, ancak bu durumlarda önceden bir maliyet var). Ayrıca, dilin değişmez türler oluşturmayı gerçekten kolay hale getirip getirmediğine bakılmaksızın, önemsiz olmayan veri türleri için her zaman biraz işlem ve bellek ek yükü gerektirme eğiliminde olacaktır.
Yan Etkilerden Yararlanma İşlevleri Yapma
Değişmezlik etrafında dönmeyen dillerde çalışıyorsanız, pragmatik yaklaşımın her bir veri türünü değişmez kılmak istemediğini düşünüyorum. Aynı avantajların çoğunu sağlayan potansiyel olarak çok daha üretken bir zihniyet, sisteminizde sıfır yan etkiye neden olan işlevlerin sayısını en üst düzeye çıkarmaya odaklanmaktır .
Basit bir örnek olarak, böyle bir yan etkiye neden olan bir fonksiyonunuz varsa:
// Make 'x' the absolute value of itself.
void make_abs(int& x);
O zaman bu işlevi yan etkilerden kaçınmak için başlatma sonrası atama gibi operatörleri yasaklayan değişmez bir tamsayı veri türüne ihtiyacımız yoktur. Bunu basitçe yapabiliriz:
// Returns the absolute value of 'x'.
int abs(int x);
Şimdi fonksiyon karmaşa x
dışında veya kapsamı dışında bir şey değil ve bu önemsiz durumda dolaylı / örtüşme ile ilişkili herhangi bir ek yükten kaçınarak bazı döngüleri traş etmiş olabiliriz. En azından ikinci versiyon, birincisinden daha pahalı bir şekilde pahalı olmamalıdır.
Tam Olarak Kopyalamak Pahalı Olan Şeyler
Tabii ki, yan etkilere neden olan bir işlev yapmaktan kaçınmak istiyorsak, çoğu vaka bu kadar önemsiz değildir. Karmaşık bir gerçek dünya kullanım durumu daha çok şöyle olabilir:
// Transforms the vertices of the specified mesh by
// the specified transformation matrix.
void transform(Mesh& mesh, Matrix4f matrix);
Bu noktada ağ, yüz binden fazla çokgen, daha fazla köşe ve kenar, çoklu doku haritaları, morph hedefleri vb. İle birkaç yüz megabayt bellek gerektirebilir. Bunu yapmak için tüm ağın kopyalanması gerçekten pahalı olurdu. transform
aşağıdaki gibi yan etkilerden arınmış:
// Returns a new version of the mesh whose vertices been
// transformed by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);
Ve bu durumda, bir şeyin tamamını kopyalamanın normalde destansı bir yük olacağı yerlerde Mesh
, değiştirilmiş versiyonları oluşturmak için kalıcı bir veri yapısına ve analog "oluşturucu" ile değişmez bir türe dönüşmenin yararlı olduğunu gördüm . basit olmayan sığ kopya ve referans olmayan benzersiz parçalar saymak olabilir. Tüm bunlar, yan etkilerden arındırılmış mesh işlevlerini yazabilme odağıdır.
Kalıcı Veri Yapıları
Ve her şeyin kopyalanmasının inanılmaz derecede pahalı olduğu bu durumlarda, Mesh
açık bir şekilde biraz dik bir maliyeti olmasına rağmen gerçekten ödeyecek bir değişmez tasarlama çabasını buldum , çünkü sadece iplik güvenliğini basitleştirmedi. Ayrıca, tahribatsız düzenlemeyi basitleştirdi (kullanıcının orijinal kopyasını değiştirmeden mesh işlemlerini katmanlamasına izin verdi), geri al sistemleri (şimdi geri alma sistemi, bir işlem tarafından yapılan bellek değişikliklerinden önce yapılan değişikliklerden önce meshin değişmez bir kopyasını saklayabilir kullanım) ve istisna güvenliği (şimdi yukarıdaki işlevde bir istisna oluşursa, işlevin tüm yan etkilerini geri alması ve geri alması gerekmez, çünkü herhangi biriyle başlamasına neden olmaz).
Bu durumlarda, bu iri veri yapılarını değişmez hale getirmek için gereken zamanın maliyetinden daha fazla zaman kazandığını söyleyebilirim, çünkü bu yeni tasarımların bakım maliyetlerini, değişebilirlik ve yan etkilere neden olan işlevler etrafında dönen eski tasarımlarla karşılaştırdım, ve eski değişebilir tasarımlar çok daha fazla zamana mal oldu ve özellikle geliştiricilerin istisna güvenliği gibi krizi zamanında ihmal etmeleri için gerçekten cazip olan alanlarda insan hatasına çok daha eğilimliydi.
Bu yüzden değişmez veri türlerinin bu durumlarda gerçekten işe yaradığını düşünüyorum, ancak sisteminizdeki işlevlerin çoğunu yan etkilerden arındırmak için her şeyin değişmez olması gerekmez. Birçok şey tam kopyalamak için yeterince ucuz. Ayrıca birçok gerçek dünya uygulamasının burada ve orada bazı yan etkilere neden olması gerekecektir (en azından bir dosyayı kaydetmek gibi), ancak tipik olarak yan etkilerden yoksun olabilecek çok daha fazla işlev vardır.
Bana bazı değişmez veri türlerine sahip olmanın amacı, sadece küçük bölümlerde tam olarak sola ve sağa büyük kopyalama yapılarak epik ek yüke maruz kalmadan, yan etkilerden arınmış maksimum işlev sayısını yazabildiğimizden emin olmaktır. bunların değiştirilmesi gerekir. Bu durumlarda kalıcı veri yapılarına sahip olmak, işlevlerimizi epik bir maliyet ödemeden yan etkilerden arınmış olarak yazmamızı sağlayan bir optimizasyon detayı haline gelir.
Değişmez Tepegöz
Şimdi kavramsal olarak değiştirilebilir versiyonlar her zaman verimlilikte bir avantaj sağlayacaktır. Değişmez veri yapıları ile ilişkili her zaman hesaplama yükü vardır. Ama yukarıda tarif ettiğim durumlarda değerli bir değişim buldum ve yükü doğada yeterince asgariye indirmeye odaklanabilirsiniz. Doğruluğun kolaylaştığı ve optimizasyonun kolaylaşmasından ziyade optimizasyonun zorlaştığı ancak doğruluğun zorlaştığı bu yaklaşımı tercih ederim. Yanlış sonuçlara ne kadar çabuk ulaşırsa başlasın, doğru şekilde çalışmayan kod üzerinde biraz daha fazla ayarlamaya ihtiyaç duyan mükemmel bir şekilde doğru şekilde çalışan bir koda sahip olmak neredeyse demoralize değil.