Bayrakları kontrol etme ihtiyacını ortadan kaldırmak için bir tasarım deseni var mı?


28

Veritabanında bazı string loadload'ları biriktireceğim. İki global konfigürasyonum var:

  • şifreleme
  • sıkıştırma

Bunlar konfigürasyon kullanılarak, her ikisinin de etkinleştirildiği veya her ikisinin de devre dışı bırakıldığı şekilde etkinleştirilebilir veya devre dışı bırakılabilir.

Mevcut uygulamam şudur:

if (encryptionEnable && !compressEnable) {
    encrypt(data);
} else if (!encryptionEnable && compressEnable) {
    compress(data);
} else if (encryptionEnable && compressEnable) {
    encrypt(compress(data));
} else {
  data;
}

Dekoratör kalıbı hakkında düşünüyorum. Doğru seçim mi, yoksa daha iyi bir alternatif var mı?


5
Şu an sahip olduğun şeyin nesi yanlış? Bu işlevsellik için gereksinimlerin değişmesi olası mı? IE, yeni ififadeler olma ihtimali var mı?
Darren Young

Hayır, kodu geliştirmek için başka bir çözüme bakıyorum.
Damith Ganegoda

46
Bu konuda geriye doğru gidiyorsun. Bir model bulamazsanız, desene uyması için kod yazın. Kodu gereksinimlerinize uyacak şekilde yazıp isteğe bağlı olarak kodunuzu tanımlamak için bir kalıp kullanın .
Monica

1
Not Sorunuzun gerçekten birinin kopyası olduğuna inanıyorsanız bu bir , daha sonra bir asker olarak "geçersiz kılma" için bir seçenek yol açan son singlehandedly yakın bu gibi yeniden ve. Bunu kendi sorularımın bazılarına yaptım ve cazibeye benziyor. İşte böyle yaptım, 3 kolay adım - "talimatlarım" ile olan tek fark, 3K temsilcisinden daha az sahip olduğunuzdan , "yinelenen" seçeneğine ulaşmak için bayrak iletişim kutusundan geçmek zorunda kalacağınız
gnat

8
@LightnessRacesinOrbit: Söylediklerinizde bazı gerçekler var, ancak birinin kodunu yapılandırmanın daha iyi bir yolu olup olmadığını sormak kesinlikle makul ve önerilen daha iyi bir yapı tanımlamak için bir tasarım modelini çağırmak tamamen makul. (Yine de, istediğiniz bir tasarım olduğunda bir tasarım deseni sormanın biraz iyi bir XY problemi olduğuna katılıyorum, herhangi bir iyi bilinen kalıba uyması veya tam olarak takip etmemesi gerekiyor.) Ayrıca, "kalıplar" için de meşru. Kodunuzu biraz etkile, ki eğer iyi bilinen bir desen kullanıyorsanız, bileşenlerinizi buna göre adlandırmak çoğu zaman mantıklı olur.
Ocak'ta 16:16

Yanıtlar:


15

Kod tasarımı yaparken, iki seçeneğiniz var.

  1. sadece halledin, bu durumda hemen hemen her çözüm sizin için işe yarayacak
  2. Pedantik olmak ve dilin tuhaflıklarından ve ideolojisinden faydalanan bir çözüm tasarlamak (bu durumda OO dilleri - polimorfizmin karar vermek için bir araç olarak kullanılması)

Ben ikisinin ilkine odaklanmayacağım, çünkü söylenecek hiçbir şey yok. Çalışmasını sağlamak istiyorsanız, kodu olduğu gibi bırakabilirsiniz.

Peki, onu sinsi bir şekilde yapmayı seçtiyseniz ve gerçekte istediğiniz gibi tasarım desenleriyle sorunu çözdüyseniz ne olurdu?

Aşağıdaki sürece bakıyor olabilirsiniz:

OO kodunu tasarlarken, koddaki çoğu ifs kodunun orada olması gerekmez. Doğal olarak, ints veya floats gibi iki skaler tipini karşılaştırmak istiyorsanız, sahip olma ihtimaliniz yüksektir if, ancak konfigürasyona dayalı prosedürleri değiştirmek istiyorsanız, istediğiniz şeyi elde etmek için polimorfizmi kullanabilirsiniz , kararları hareket ettirin ( ifs) iş mantığınızdan nesnelerin somutlaştırıldığı bir yere - fabrikalara .

Şu andan itibaren, işleminiz 4 ayrı yoldan geçebilir:

  1. dataşifreli veya sıkıştırılmamış (hiçbir şey arama, geri dönme data)
  2. datasıkıştırılmış (arayın compress(data)ve geri gönderin)
  3. dataşifreli (arayın encrypt(data)ve iade edin)
  4. datasıkıştırılmış ve şifrelenmiş (arayın encrypt(compress(data))ve iade edin)

Sadece 4 patikaya bakarak bir sorun bulursun.

3'ü çağıran bir işleminiz var (teorik olarak 4, eğer hiç birşeyi çağırmazsanız) verileri işleyen ve sonra döndüren farklı yöntemler. Yöntemlerin ortak adları (yöntemlerin davranışlarını iletme şekilleri) ortak API adı verilen farklı adları vardır .

Bağdaştırıcı şablonunu kullanarak, ortaya çıkan ad çarpışmasını çözebiliriz (ortak API'yi birleştirebiliriz). Basitçe söylemek gerekirse, adaptör iki uyumsuz ara yüzün birlikte çalışmasına yardımcı olur. Ayrıca, bağdaştırıcı, API uygulamalarını birleştirmeye çalışan sınıfların oluşturduğu yeni bir bağdaştırıcı arabirimi tanımlayarak çalışır.

Bu somut bir dil değil. Bu genel bir yaklaşımdır, herhangi bir anahtar kelime herhangi bir türde olabilir, C # gibi bir dilde generics ( <T>) ile değiştirebilirsiniz .

Varsayıyorum, şu anda sıkıştırma ve şifrelemeden sorumlu iki sınıfınız olabilir.

class Compression
{
    Compress(data : any) : any { ... }
}

class Encryption
{
    Encrypt(data : any) : any { ... }
}

Bir işletme dünyasında, bu belirli sınıfların bile, classanahtar kelimeyle değiştirilecek interface(örneğin, C #, Java ve / veya PHP gibi dillerle ilgileniyorsanız) veya classanahtar kelime kalacak gibi arayüzlerle değiştirilme olasılığı çok yüksektir . C ++ 'da kodlamanız gerekir Compressve Encryptyöntemler saf bir sanal olarak tanımlanır .

Bir adaptör yapmak için ortak bir arayüz tanımlarız.

interface DataProcessing
{
    Process(data : any) : any;
}

O zaman onu kullanışlı kılmak için arayüzün uygulamalarını sağlamalıyız.

// when neither encryption nor compression is enabled
class DoNothingAdapter : DataProcessing
{
    public Process(data : any) : any
    {
        return data;
    }
}

// when only compression is enabled
class CompressionAdapter : DataProcessing
{
    private compression : Compression;

    public Process(data : any) : any
    {
        return this.compression.Compress(data);
    }
}

// when only encryption is enabled
class EncryptionAdapter : DataProcessing
{
    private encryption : Encryption;

    public Process(data : any) : any
    {
        return this.encryption.Encrypt(data);
    }
}

// when both, compression and encryption are enabled
class CompressionEncryptionAdapter : DataProcessing
{
    private compression : Compression;
    private encryption : Encryption;

    public Process(data : any) : any
    {
        return this.encryption.Encrypt(
            this.compression.Compress(data)
        );
    }
}

Bunu yaparak, her biri tamamen farklı bir şey yapan ancak her biri aynı ortak API'yi sağlayan 4 sınıfla karşılaşırsınız. ProcessYöntemi.

Hiçbiri / şifreleme / sıkıştırma / her iki kararla ilgilendiğiniz iş mantığınızda, nesneyi daha DataProcessingönce tasarladığımız arayüze bağlı olacak şekilde tasarlayacaksınız .

class DataService
{
    private dataProcessing : DataProcessing;

    public DataService(dataProcessing : DataProcessing)
    {
        this.dataProcessing = dataProcessing;
    }
}

Sürecin kendisi bu kadar basit olabilir:

public ComplicatedProcess(data : any) : any
{
    data = this.dataProcessing.Process(data);

    // ... perhaps work with the data

    return data;
}

Başka şart yok. Sınıf DataService, dataProcessingüyeye iletildiğinde verilerle gerçekten ne yapılacağına dair hiçbir fikri yoktur ve bu onunla gerçekten ilgilenmez, bu onun sorumluluğu değildir.

İdeal olarak, çalıştıklarından emin olmak için oluşturduğunuz 4 adaptör sınıfını test eden ünite testlerine sahip olursunuz, test geçişinizi yaparsınız. Ve geçerlerse, kodunuzda nerede çağırırlarsanız çalınacaklarından emin olabilirsiniz.

Yani bu şekilde yapmak, ifartık benim kodumda olmayacak?

Hayır. İş mantığınızda şartlı olma olasılığınız daha düşüktür, ancak yine de bir yerlerde olmaları gerekir. Burası senin fabrikaların.

Ve bu iyi. Yaratma ile ilgili endişeleri birbirinden ayırıyorsunuz ve kodu gerçekten kullanıyorsunuz. Fabrikalarınızı güvenilir hale getirirseniz (Java’da Google’dan Guice framework gibi bir şey kullanmaya bile gidebilirsiniz ), işletme mantığınızda enjekte edilecek doğru sınıfı seçmekten endişe duymazsınız. Çünkü fabrikalarınızın çalıştığını ve sorulanı teslim edeceğini biliyorsunuz.

Bütün bu sınıflara, arayüzlere vb. Sahip olmak gerekli midir?

Bu bizi tekrar başlangıç ​​noktasına getiriyor.

OOP'de, polimorfizmi kullanma yolunu seçerseniz, gerçekten tasarım kalıplarını kullanmak istiyorsanız, dilin özelliklerinden yararlanmak ve / veya her şeyi takip etmek istiyorsanız, bir nesne ideolojisi, öyleyse öyledir. Ve o zaman bile, bu örnek bile ihtiyacı olacak tüm fabrikalar göstermez ve eğer refactor Compressionve Encryptionsınıfları ve siz de onların uygulamalarını içerecek şekilde var onları yerine arabirimleri olun.

Sonunda, çok özel şeylere odaklanan yüzlerce küçük sınıf ve arayüzle karşılaşıyorsunuz. Bu mutlaka kötü bir şey değildir, ancak tek isteğiniz iki sayı eklemek kadar basit bir şey yapmaksa, sizin için en iyi çözüm olmayabilir.

Bunu hemen ve çabucak halletmek istiyorsanız, bence en azından bir düzlükten bile daha kötü olan blokları else ifve en azından ortadan kaldırabilen Ixrec'in çözümünü kapabilirsiniz .elseif

Bu benim için iyi OO tasarımı yapmanın bir yoludur. Uygulamalardan ziyade arayüzlere kodlama yapmak, bunu son birkaç yıldır böyle yaptım ve en rahat olduğum yaklaşım bu.

Şahsen if-if programlamayı daha çok seviyorum ve 5 kod satırı üzerindeki daha uzun çözümü çok takdir ediyorum. Kod tasarlamaya alışkınım ve onu okumak çok rahat.


Güncelleme 2: Çözümümün ilk sürümü hakkında çılgınca bir tartışma oldu. Tartışma, çoğunlukla özür dilediğim benden kaynaklanıyor.

Cevabı, çözüme bakmanın yollarından biri olacak şekilde düzenlemeye karar verdim, sadece bir değil. Aynı zamanda dekoratör kısmını da çıkarttım, bunun yerine cepheyi kastetmiştim, sonunda tamamen bırakmaya karar verdim, çünkü bir adaptör bir cephe değişimidir.


28
Oy vermedim ama gerekçe, orijinal kodun 8 satırda yaptığı bir şeyi yapmak için saçma miktarda yeni sınıf / arayüz olabilir (ve diğer cevap 5'te yapıldı). Bence başardığı tek şey kodun öğrenme eğrisini artırmak.
Maurycy

6
@Bayanlık OP'nin sorduğu şey, eğer böyle bir çözüm varsa ortak tasarım desenlerini kullanarak sorununa bir çözüm bulmaya çalışmaktı. Çözümüm onun veya Ixrec'in kodundan daha mı uzun? Bu. Bunu itiraf ediyorum. Benim çözümüm problemini tasarım kalıplarını kullanarak çözüyor ve bu nedenle sorusunu yanıtlıyor ve tüm gerekli işlemleri süreçten etkin bir şekilde çıkarıyor mu? Öyle. Ixrec's yapmaz.
Andy

26
Açık, güvenilir, özlü, performanslı ve bakımı kolay bir kod yazmanın yolunun olduğuna inanıyorum . Ne zaman birisi SOLID’e atıfta bulunduysa veya amaçlarını ve gerekçelerini açıkça ifade etmeden bir yazılım modelini alıntı yaptıysa, zengin bir adam olurdum.
Robert Harvey,

12
Sanırım burada gördüğüm iki sorun var. Birincisi Compressionve Encryptionarayüzlerin tamamen gereksiz göründüğü. Dekorasyon işleminde bir şekilde gerekli olduklarını mı yoksa sadece çıkarılan kavramları temsil ettiklerini mi ima ettiğinizden emin değilim. İkinci sorun ise, böyle bir sınıf yapmanın CompressionEncryptionDecoratorOP'nin şartlarıyla aynı türde birleşimsel patlamaya yol açmasıdır. Ayrıca dekoratör modelini önerilen kodda yeterince net göremiyorum.
cbojar

5
Basit ve SOLID konusundaki tartışma biraz eksiktir: bu kod da değildir ve aynı zamanda dekoratör modelini kullanmaz. Kod sadece bir sürü arayüz kullandığı için otomatik olarak SOLID değildir. Bir DataProcessing arayüzünün bağımlılık enjeksiyonu çok hoş; her şey gereksizdir. SOLID, değişimi iyi idare etmeyi amaçlayan mimari düzeyde bir kaygıdır. OP, mimarisi hakkında ne de kodunun değişmesini beklediğiyle ilgili hiçbir bilgi vermedi, bu yüzden bir yanıt olarak SOLID'i gerçekten tartışamıyoruz.
Carl Leth

120

Şu anki kodunuzda gördüğüm tek sorun, daha fazla ayar eklerken birleşimsel patlama riskidir; bu, kodu daha fazla yapılandırarak kolayca azaltılabilir:

if(compressEnable){
  data = compress(data);
}
if(encryptionEnable) {
  data = encrypt(data);
}
return data;

Bunun bir örnek olarak kabul edilebileceği herhangi bir "tasarım deseni" veya "deyim" farkında değilim.


18
@DamithGanegoda Hayır, kodumu dikkatlice okursanız, bu durumda tam olarak aynı şeyi görürsünüz. Bu yüzden elseiki ifadem arasında hiçbir ifade yok ve neden dataher seferinde atayım . Her iki bayrak da doğruysa, sıkıştırmak () yerine konur, sonra da istediğiniz gibi sıkıştırmak () ile sonuçlanır.
Ixrec,

14
@DavidPacker Teknik olarak, her programlama dilinde her if ifadesi de öyle. Sadelik için gittim, çünkü bu çok basit bir cevabın uygun olduğu bir soruna benziyordu. Çözümünüz de geçerlidir, ancak kişisel olarak endişelenecek ikiden fazla boole bayrağı bulunduğunda saklarım.
Ixrec,

15
@DavidPacker: Doğru, bazı yazarlar tarafından bazı programlama ideolojileri hakkında bazı kılavuzlara kodun ne kadar iyi uyduğu ile tanımlanmamıştır. Doğru "kod yapması gerekeni yapar mı ve makul bir sürede uygulandı" dır. Bunu "yanlış yoldan" yapmak mantıklıysa, o zaman yanlış yol doğru yoldur çünkü zaman paradır.
whatsisname

9
@DavidPacker: Eğer OP'nin pozisyonundaysam ve bu soruyu sorarsam, Orbit'in yorumunda Hafiflik Yarışı gerçekten ihtiyacım olan şeydi. “Tasarım kalıplarını kullanarak bir çözüm bulmak” zaten yanlış ayaktan başlıyor.
whatsisname,

6
@DavidPacker Aslında soruyu daha yakından okursanız, bir kalıp üzerinde ısrar etmez. “Dekoratör modeli hakkında düşünüyorum. Doğru seçim mi, yoksa belki daha iyi bir alternatif var mı?” Diye belirtiyor . . İlk cümleye teklifimi verdiniz, ikinciyi değil. Diğer insanlar bu yaklaşımı benimsemiştir, doğru seçim değildir. Öyleyse soruyu yalnızca sizin cevapladığını iddia edemezsiniz.
Jon Bentley,

12

Sanırım sorunuz pratiklik için değil, lxrec'in cevabı doğru, ama tasarım kalıplarını öğrenmek.

Açıkçası, komut düzeni , önerdiğiniz gibi önemsiz bir sorun için bir eksikliktir, ancak buradaki illüstrasyon uğruna:

public interface Command {
    public String transform(String s);
}

public class CompressCommand implements Command {
    @Override
    public String transform(String s) {
        String compressedString=null;
        //Compression code here
        return compressedString;
    }
}

public class EncryptCommand implements Command {
    @Override
    public String transform(String s) {
        String EncrytedString=null;
        // Encryption code goes here
        return null;
    }

}

public class Test {
    public static void main(String[] args) {
        List<Command> commands = new ArrayList<Command>();
        commands.add(new CompressCommand());
        commands.add(new EncryptCommand()); 
        String myString="Test String";
        for (Command c: commands){
            myString = c.transform(myString);
        }
        // now myString can be stored in the database
    }
}

Gördüğünüz gibi komutları / dönüşümü bir listeye koymak, sıralı olarak çalıştırılmasına izin verir. Açıkçası, her ikisini de yürütecek, ya da yalnızca biri, şartlar olmadan listeye yazdıklarınıza bağlı.

Açıkçası şartlı şartlar, komut listesini bir araya getiren bir tür fabrikada bitecek.

@ Texacre adlı kullanıcının yorumu için EDIT:

Çözümün yaratıcı kısmındaki if koşullarından kaçınmanın birçok yolu vardır, örneğin bir masaüstü GUI uygulamasını ele alalım . Sıkıştır ve şifreleme seçenekleri için onay kutularına sahip olabilirsiniz. Bu on cliconay kutuları durumunda, ilgili komutu başlatır ve listeye eklersiniz veya seçeneğin seçimini kaldırıyorsanız listeden çıkarırsınız.


Temelde Ixrec'in cevabına benzeyen bir kod olmadan "komut listesini bir araya getiren bir fabrika türüne" bir örnek veremezseniz, IMO bu soruyu cevaplamaz. Bu, sıkıştırma ve şifreleme işlevlerini uygulamak için daha iyi bir yol sağlar, ancak bayraklardan nasıl kaçınılacağını değil.
thexacre

@ thexacre Bir örnek ekledim.
Tulains Córdova,

Yani, onay kutusu olay dinleyicinizde "if checkbox.ticked, sonra komut ekleyin" var. Sen sadece ... eğer ifadeleri etrafında bayrağı karıştırma konum gibi Bana öyle geliyor
thexacre

@ thexacre Hayır, her onay kutusu için bir dinleyici. Sadece commands.add(new EncryptCommand()); veya commands.add(new CompressCommand());sırasıyla click olayında .
Tulains Córdova,

Kutunun işaretini kaldırmaya ne dersiniz? Neredeyse karşılaştığım her dilde / UI araç setinde, olay dinleyicisindeki onay kutusunun durumunu kontrol etmeniz gerekir. Bunun daha iyi bir model olduğuna katılıyorum, ancak bayrak bir yerde bir şey yaparsa temelde ihtiyaçtan kaçınmaz.
thexacre

7

Bence "tasarım desenleri" gereksiz yere "oo desenlerine" yöneliktir ve daha basit fikirlerden tamamen kaçınırlar. Burada bahsettiğimiz şey (basit) bir veri hattıdır.

Bunu clojure ile yapmaya çalışırdım. İşlevlerin birinci sınıf olduğu diğer diller de muhtemelen tamamdır. Belki daha sonra bir C # örneği yapabilirim, ama o kadar iyi değil. Bunu çözme yöntemim, clojuryalı olmayanlar için bazı açıklamalarla birlikte aşağıdaki adımları izleyecektir:

1. Bir dizi dönüşüm temsil eder.

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )})

Bu bir harita, yani arama tablosu / sözlük / her neyse, anahtar kelimelerden fonksiyonlara. Başka bir örnek (dizelere anahtar kelimeler):

(def employees { :A1 "Alice" 
                 :X9 "Bob"})

(employees :A1) ; => "Alice"
(:A1 employees) ; => "Alice"

Yani, yazma (transformations :encrypt)veya (:encrypt transformations)şifreleme işlevini döndürürdü. ( (fn [data] ... )sadece bir lambda işlevidir.)

2. Seçenekleri bir anahtar kelime dizisi olarak alın:

(defn do-processing [options data] ;function definition
  ...)

(do-processing [:encrypt :compress] data) ;call to function

3. Verilen seçenekleri kullanarak tüm dönüşümleri filtreleyin.

(let [ transformations-to-run (map transformations options)] ... )

Örnek:

(map employees [:A1]) ; => ["Alice"]
(map employees [:A1 :X9]) ; => ["Alice", "Bob"]

4. İşlevleri bire bir birleştirin:

(apply comp transformations-to-run)

Örnek:

(comp f g h) ;=> f(g(h()))
(apply comp [f g h]) ;=> f(g(h()))

5. Sonra birlikte:

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )})

(defn do-processing [options data]
  (let [transformations-to-run (map transformations options)
        selected-transformations (apply comp transformations-to-run)] 
    (selected-transformations data)))

(do-processing [:encrypt :compress])

SADECE yeni bir fonksiyon eklemek istiyorsak değiştirelim, "debug-print" diyoruz:

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )
                       :debug-print (fn [data] ...) }) ;<--- here to add as option

(defn do-processing [options data]
  (let [transformations-to-run (map transformations options)
        selected-transformations (apply comp transformations-to-run)] 
    (selected-transformations data)))

(do-processing [:encrypt :compress :debug-print]) ;<-- here to use it
(do-processing [:compress :debug-print]) ;or like this
(do-processing [:encrypt]) ;or like this

İşlevler sadece temelde bir if ifadesi bir şekilde veya başka bir şekilde kullanılmadan uygulanması gereken işlevleri içerecek şekilde nasıl yerleştirilir?
thexacre

Satır funcs-to-run-here (map options funcs)filtreleme yapıyor, böylece uygulanacak bir dizi işlev seçiliyor. Belki de cevabı güncellemeliyim ve biraz daha ayrıntıya girmeliyim.
NiklasJ

5

[Esasen, cevabım yukarıdaki @Ixrec tarafından verilen cevabın bir takipçisi . ]

Önemli bir soru: Ele almanız gereken farklı kombinasyonların sayısı artacak mı? Konu alanınızın daha iyi farkındasınız. Bu sizin karar vermenizdir.
Değişkenlerin sayısı muhtemelen artabilir mi? Bu düşünülemez değil. Örneğin, daha farklı şifreleme algoritmaları kullanmanız gerekebilir.

Farklı kombinasyonların sayısının artacağını tahmin ediyorsanız, Strateji kalıbı size yardımcı olabilir. Algoritmaları kapsüllemek ve çağıran koda değiştirilebilir bir arayüz sağlamak için tasarlanmıştır. Her bir dize için uygun stratejiyi oluşturduğunuzda (başlattığınızda), hala az miktarda bir mantık olacaktır.

Gereksinimlerin değişmesini beklemeyeceğiniz konusunda yukarıda yorum yaptınız. Değişken sayısının artacağını düşünmüyorsanız (veya bu yeniden düzenleme işlemini erteleyebilirseniz), mantığı olduğu gibi tutun. Şu anda, küçük ve yönetilebilir bir mantık miktarınız var. (Belki bir Strateji modeline olası bir yeniden düzenleme ile ilgili yorumlarda kendi kendine bir not koyun.)


1

Bunu scala'da yapmanın bir yolu:

val handleCompression: AnyRef => AnyRef = data => if (compressEnable) compress(data) else data
val handleEncryption: AnyRef => AnyRef = data => if (encryptionEnable) encrypt(data) else data
val handleData = handleCompression andThen handleEncryption
handleData(data)

Yukarıdaki hedeflere ulaşmak için dekoratör paterninin kullanılması (bireysel işlem mantığının ayrılması ve nasıl bir araya getirildiği) çok ayrıntılı olacaktır.

Bir OO programlama paradigmasında bu tasarım hedeflerine ulaşmak için bir tasarım modeline ihtiyaç duyduğunuzda, fonksiyonel dil, birinci sınıf vatandaşlar (koddaki 1. ve 2. satırlar) ve işlevsel kompozisyon (3. satır) olarak işlevleri kullanarak yerel destek sunar.


Bu neden OP'nin yaklaşımından daha iyi (veya daha kötü)? Ve / veya OP'nin dekoratör modelini kullanma fikri hakkında ne düşünüyorsunuz?
Kasper van den Berg,

bu kod pasajı daha iyidir ve sipariş verme konusunda açıktır (şifreleme öncesi sıkıştırma); istenmeyen arayüzleri önler
Rag
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.