Apakah ada pola desain untuk menghilangkan kebutuhan untuk memeriksa bendera?

28

Saya akan menghemat beberapa payload string dalam database. Saya memiliki dua konfigurasi global:

  • enkripsi
  • kompresi

Ini dapat diaktifkan atau dinonaktifkan menggunakan konfigurasi sedemikian rupa sehingga hanya salah satu dari mereka yang diaktifkan, keduanya diaktifkan atau keduanya dinonaktifkan.

Implementasi saya saat ini adalah ini:

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

Saya sedang berpikir tentang pola Dekorator. Apakah ini pilihan yang tepat, atau mungkin ada alternatif yang lebih baik?

Damith Ganegoda
sumber
5
Apa yang salah dengan apa yang Anda miliki saat ini? Apakah persyaratan cenderung berubah untuk fungsi ini? IE, apakah mungkin ada ifpernyataan baru ?
Darren Young
Tidak, saya sedang mencari solusi lain untuk meningkatkan kode.
Damith Ganegoda
46
Anda akan mundur tentang hal ini. Anda tidak menemukan pola lalu menulis kode yang sesuai dengan pola. Anda menulis kode agar sesuai dengan kebutuhan Anda, lalu secara opsional menggunakan pola untuk menggambarkan kode Anda.
Lightness Races dengan Monica
1
perhatikan jika Anda yakin bahwa pertanyaan Anda memang merupakan duplikat dari pertanyaan ini , maka sebagai penanya Anda memiliki opsi untuk "menimpa" yang dibuka kembali baru-baru ini dan menutupnya sendiri-sendiri. Saya melakukan itu untuk beberapa pertanyaan saya sendiri dan itu berfungsi seperti pesona. Inilah cara saya melakukannya, 3 langkah mudah - satu-satunya perbedaan dengan "instruksi" saya adalah karena Anda memiliki kurang dari 3K perwakilan, Anda harus melalui dialog bendera untuk mendapatkan opsi "duplikat"
gnat
8
@LightnessRacesinOrbit: Ada beberapa kebenaran dalam apa yang Anda katakan, tetapi sangat masuk akal untuk bertanya apakah ada cara yang lebih baik untuk menyusun kode seseorang, dan sangat masuk akal untuk menggunakan pola desain untuk menggambarkan struktur yang diusulkan lebih baik. (Namun, saya setuju bahwa ini sedikit masalah XY untuk meminta pola desain ketika apa yang Anda inginkan adalah desain , yang mungkin atau mungkin tidak secara ketat mengikuti pola yang terkenal.) Juga, itu sah untuk "pola" untuk sedikit mempengaruhi kode Anda, karena jika Anda menggunakan pola yang terkenal, sering kali masuk akal untuk memberi nama komponen Anda sesuai.
ruakh

Jawaban:

15

Saat mendesain kode, Anda selalu memiliki dua opsi.

  1. selesaikan saja, dalam hal ini hampir semua solusi akan bekerja untuk Anda
  2. menjadi bertele-tele dan merancang solusi yang mengeksploitasi kebiasaan bahasa dan ideologinya (bahasa OO dalam hal ini - penggunaan polimorfisme sebagai sarana untuk memberikan keputusan)

Saya tidak akan fokus pada yang pertama dari keduanya, karena benar-benar tidak ada yang bisa dikatakan. Jika Anda hanya ingin membuatnya berfungsi, Anda bisa membiarkan kode apa adanya.

Tetapi apa yang akan terjadi, jika Anda memilih untuk melakukannya dengan cara yang sangat bagus dan benar-benar menyelesaikan masalah dengan pola desain, seperti yang Anda inginkan?

Anda bisa melihat proses berikut:

Saat merancang kode OO, sebagian besar ifyang ada dalam kode tidak harus ada di sana. Secara alami, jika Anda ingin membandingkan dua tipe skalar, seperti ints atau floats, Anda cenderung memiliki if, tetapi jika Anda ingin mengubah prosedur berdasarkan konfigurasi, Anda dapat menggunakan polimorfisme untuk mencapai apa yang Anda inginkan, pindahkan keputusan ( ifs) dari logika bisnis Anda ke suatu tempat, di mana objek dipakai - ke pabrik .

Sampai sekarang, proses Anda dapat melewati 4 jalur terpisah:

  1. datatidak dienkripsi atau dikompresi (tidak memanggil apa pun, kembali data)
  2. datadikompresi (panggil compress(data)dan kembalikan)
  3. datadienkripsi (panggil encrypt(data)dan kembalikan)
  4. datadikompresi dan dienkripsi (panggilan encrypt(compress(data))dan kembalikan)

Hanya dengan melihat 4 jalur, Anda menemukan masalah.

Anda memiliki satu proses yang memanggil 3 (secara teoritis 4, jika Anda menghitung tidak memanggil apa pun sebagai satu) metode berbeda yang memanipulasi data dan kemudian mengembalikannya. Metode memiliki nama yang berbeda , berbeda disebut API publik (cara di mana metode mengkomunikasikan perilaku mereka).

Dengan menggunakan pola adaptor , kita dapat memecahkan masalah colision nama (kita dapat menyatukan API publik) yang telah terjadi. Sederhananya, adaptor membantu dua antarmuka yang tidak kompatibel bekerja bersama. Juga, adaptor bekerja dengan mendefinisikan antarmuka adaptor baru, yang mana kelas mencoba menyatukan implementasi API mereka.

Ini bukan bahasa konkret. Ini adalah pendekatan generik, kata kunci apa pun yang ada untuk mewakili mungkin dari jenis apa pun, dalam bahasa seperti C # Anda dapat menggantinya dengan generik ( <T>).

Saya akan berasumsi, bahwa saat ini Anda dapat memiliki dua kelas yang bertanggung jawab untuk kompresi dan enkripsi.

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

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

Dalam dunia perusahaan, bahkan kelas-kelas khusus ini sangat mungkin akan diganti oleh antarmuka, seperti classkata kunci yang akan diganti interface(jika Anda berurusan dengan bahasa seperti C #, Java dan / atau PHP) atau classkata kunci akan tetap ada, tetapi Compressdan Encryptmetode akan didefinisikan sebagai virtual murni , jika Anda kode dalam C ++.

Untuk membuat adaptor, kami mendefinisikan antarmuka umum.

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

Kemudian kita harus menyediakan implementasi antarmuka agar bermanfaat.

// 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)
        );
    }
}

Dengan melakukan ini, Anda berakhir dengan 4 kelas, masing-masing melakukan sesuatu yang sama sekali berbeda, tetapi masing-masing dari mereka menyediakan API publik yang sama. The ProcessMetode.

Dalam logika bisnis Anda, di mana Anda berurusan dengan keputusan tidak ada / enkripsi / kompresi / keduanya, Anda akan merancang objek Anda untuk membuatnya tergantung pada DataProcessingantarmuka yang kami desain sebelumnya.

class DataService
{
    private dataProcessing : DataProcessing;

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

Prosesnya sendiri bisa sesederhana ini:

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

    // ... perhaps work with the data

    return data;
}

Tidak ada lagi persyaratan. Kelas DataServicetidak tahu apa yang akan dilakukan dengan data ketika diberikan kepada dataProcessinganggota, dan tidak terlalu peduli tentang itu, itu bukan tanggung jawabnya.

Idealnya, Anda akan memiliki unit test yang menguji 4 kelas adaptor yang Anda buat untuk memastikan mereka bekerja, Anda membuat test pass Anda. Dan jika mereka lulus, Anda bisa yakin mereka akan bekerja di mana pun Anda memanggilnya dalam kode Anda.

Jadi melakukannya dengan cara ini saya tidak akan pernah memiliki ifkode lagi?

Tidak. Anda cenderung memiliki persyaratan dalam logika bisnis Anda, tetapi mereka masih harus berada di suatu tempat. Tempat itu adalah pabrikmu.

Dan ini bagus. Anda memisahkan masalah penciptaan dan benar-benar menggunakan kode. Jika Anda membuat pabrik Anda dapat diandalkan (di Jawa Anda bahkan bisa menggunakan sesuatu seperti kerangka kerja Guice oleh Google), dalam logika bisnis Anda, Anda tidak khawatir memilih kelas yang tepat untuk disuntikkan. Karena Anda tahu pabrik Anda berfungsi dan akan memberikan apa yang diminta.

Apakah perlu untuk memiliki semua kelas, antarmuka, dll?

Ini membawa kita kembali ke awal.

Dalam OOP, jika Anda memilih jalur untuk menggunakan polimorfisme, benar-benar ingin menggunakan pola desain, ingin mengeksploitasi fitur-fitur bahasa dan / atau ingin mengikuti semuanya adalah ideologi objek, maka itu. Dan bahkan kemudian, contoh ini bahkan tidak menunjukkan semua pabrik yang akan Anda butuhkan dan jika Anda ingin refactor Compressiondan Encryptionkelas dan membuat mereka antarmuka, Anda harus memasukkan implementasinya juga.

Pada akhirnya Anda berakhir dengan ratusan kelas kecil dan antarmuka, fokus pada hal-hal yang sangat spesifik. Yang tidak selalu buruk, tetapi mungkin bukan solusi terbaik untuk Anda jika semua yang Anda inginkan adalah melakukan sesuatu yang sederhana seperti menambahkan dua angka.

Jika Anda ingin menyelesaikannya dengan cepat, Anda dapat mengambil solusi Ixrec , yang setidaknya berhasil menghilangkan else ifdan elsememblokir, yang, menurut pendapat saya, bahkan sedikit lebih buruk daripada dataran if.

Mempertimbangkan ini adalah cara saya membuat desain OO yang bagus. Pengodean ke antarmuka daripada implementasi, ini adalah bagaimana saya telah melakukannya selama beberapa tahun terakhir dan ini adalah pendekatan yang paling nyaman bagi saya.

Saya pribadi lebih suka pemrograman jika-kurang dan akan lebih menghargai solusi yang lebih lama dari 5 baris kode. Ini adalah cara saya terbiasa mendesain kode dan saya sangat nyaman membacanya.


Pembaruan 2: Telah ada diskusi liar tentang versi pertama dari solusi saya. Diskusi sebagian besar disebabkan oleh saya, yang saya minta maaf.

Saya memutuskan untuk mengedit jawaban dengan cara yang merupakan salah satu cara untuk melihat solusi tetapi bukan satu-satunya. Saya juga menghapus bagian dekorator, di mana yang saya maksud adalah fasad, yang akhirnya saya putuskan untuk ditinggalkan sepenuhnya, karena adaptor adalah variasi fasad.

Andy
sumber
28
Saya tidak downvote tetapi alasannya mungkin jumlah konyol kelas baru / antarmuka untuk melakukan sesuatu kode asli lakukan dalam 8 baris (dan jawaban lainnya lakukan dalam 5). Menurut pendapat saya satu-satunya hal yang dicapai adalah meningkatkan kurva belajar untuk kode.
Maurycy
6
@ Maurycy Apa yang diminta OP adalah mencoba menemukan solusi untuk masalahnya menggunakan pola desain umum, jika solusi tersebut ada. Apakah solusi saya lebih lama dari kode nya atau Ixrec? Ini. Saya akui itu. Apakah solusi saya memecahkan masalahnya menggunakan pola desain dan dengan demikian menjawab pertanyaannya dan juga secara efektif menghapus semua jika diperlukan dari proses? Itu benar. Ixrec tidak.
Andy
26
Saya percaya bahwa menulis kode yang jelas, andal, ringkas, performan , dan dapat dipelihara adalah cara yang harus ditempuh. Jika saya memiliki satu dolar untuk setiap kali seseorang mengutip SOLID atau mengutip pola perangkat lunak tanpa dengan jelas mengartikulasikan tujuan dan alasan mereka, saya akan menjadi orang kaya.
Robert Harvey
12
Saya pikir saya punya dua masalah yang saya lihat di sini. Pertama adalah bahwa Compressiondan Encryptionantarmuka tampak sangat berlebihan. Saya tidak yakin apakah Anda menyarankan bahwa mereka entah bagaimana diperlukan untuk proses dekorasi, atau hanya menyiratkan bahwa mereka mewakili konsep yang diekstraksi. Masalah kedua adalah bahwa membuat kelas seperti CompressionEncryptionDecoratormengarah ke jenis ledakan kombinatorial yang sama dengan persyaratan OP. Saya juga tidak melihat pola dekorator cukup jelas dalam kode yang disarankan.
cbojar
5
Perdebatan tentang SOLID vs sederhana agak tidak penting: kode ini tidak ada, dan juga tidak menggunakan pola dekorator. Kode tidak secara otomatis SOLID hanya karena menggunakan banyak antarmuka. Ketergantungan injeksi antarmuka DataProcessing agak bagus; segala sesuatu yang tidak perlu. SOLID adalah masalah tingkat arsitektur yang bertujuan menangani perubahan dengan baik. OP tidak memberikan informasi tentang arsitekturnya atau bagaimana dia mengharapkan kodenya berubah, jadi kita bahkan tidak bisa mendiskusikan SOLID dalam sebuah jawaban.
Carl Leth
120

Satu-satunya masalah yang saya lihat dengan kode Anda saat ini adalah risiko ledakan kombinatorial saat Anda menambahkan lebih banyak pengaturan, yang dapat dengan mudah dikurangi dengan menyusun kode lebih seperti ini:

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

Saya tidak mengetahui adanya "pola desain" atau "idiom" yang dapat dianggap sebagai contoh.

Ixrec
sumber
18
@DamithGanegoda Tidak, jika Anda membaca kode saya dengan hati-hati, Anda akan melihatnya melakukan hal yang persis sama dalam kasus itu. Itu sebabnya tidak ada di elseantara dua pernyataan if saya, dan mengapa saya menugaskan datasetiap kali. Jika kedua flag benar, maka kompres () dijalankan, kemudian enkripsi () dieksekusi pada hasil kompres (), seperti yang Anda inginkan.
Ixrec
14
@ Davidvider Secara teknis, demikian juga setiap pernyataan if dalam setiap bahasa pemrograman. Saya mencari kesederhanaan, karena ini tampak seperti masalah di mana jawaban yang sangat sederhana sesuai. Solusi Anda juga valid, tetapi secara pribadi saya akan menyimpannya ketika saya memiliki lebih dari dua bendera boolean yang perlu dikhawatirkan.
Ixrec
15
@ Davidvider: benar tidak didefinisikan oleh seberapa baik kode mematuhi beberapa pedoman oleh beberapa penulis tentang beberapa ideologi pemrograman. Yang benar adalah "apakah kode melakukan apa yang seharusnya dilakukan dan apakah itu dilaksanakan dalam jumlah waktu yang wajar". Jika masuk akal untuk melakukannya dengan "jalan yang salah", maka jalan yang salah adalah jalan yang benar karena waktu adalah uang.
whatsisname
9
@ Davidvider: Jika saya berada di posisi OP, dan mengajukan pertanyaan itu, Lightness Race dalam komentar Orbit adalah apa yang saya butuhkan. "Menemukan solusi menggunakan pola desain" sudah dimulai dari kaki yang salah.
whatsisname
6
@ Davidvider Sebenarnya jika Anda membaca pertanyaan lebih dekat, itu tidak bersikeras pada pola. Disebutkan, "Saya sedang memikirkan pola Dekorator. Apakah ini pilihan yang tepat, atau mungkin ada alternatif yang lebih baik?" . Anda menjawab kalimat pertama dalam kutipan saya, tetapi bukan yang kedua. Orang lain mengambil pendekatan bahwa tidak, itu bukan pilihan yang tepat. Anda tidak dapat mengklaim bahwa hanya Anda yang menjawab pertanyaan itu.
Jon Bentley
12

Saya kira pertanyaan Anda mencari bukan untuk kepraktisan, dalam hal ini jawaban lxrec adalah yang benar, tetapi untuk belajar tentang pola desain.

Jelas bahwa pola perintah adalah kerja keras untuk masalah sepele seperti yang Anda usulkan tetapi demi ilustrasi, begini:

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
    }
}

Seperti yang Anda lihat menempatkan perintah / transformasi dalam daftar memungkinkan untuk dijalankan secara berurutan. Jelas itu akan mengeksekusi keduanya, atau hanya satu dari mereka tergantung pada apa yang Anda masukkan dalam daftar tanpa syarat.

Jelas kondisi akan berakhir di semacam pabrik yang mengumpulkan daftar perintah.

EDIT untuk komentar @ texacre:

Ada banyak cara untuk menghindari kondisi if di bagian kreatif dari solusi, mari kita ambil contoh aplikasi GUI desktop . Anda dapat memiliki kotak centang untuk opsi kompres dan enkripsi. Dalam on clicacara mereka kotak centang Anda instantiate perintah yang sesuai dan menambahkannya ke dalam daftar, atau menghapus dari daftar jika Anda tidak memilih opsi tersebut.

Tulains Córdova
sumber
Kecuali Anda dapat memberikan contoh "semacam pabrik yang menyatukan daftar perintah" tanpa kode yang pada dasarnya tampak seperti jawaban Ixrec maka IMO ini tidak menjawab pertanyaan. Ini memberikan cara yang lebih baik untuk mengimplementasikan fungsi kompres dan enkripsi, tetapi tidak bagaimana menghindari flag.
thexacre
@ thexacre saya menambahkan contoh.
Tulains Córdova
Jadi di pendengar acara kotak centang Anda, Anda memiliki "jika checkbox.ticked maka tambahkan perintah"? Sepertinya saya seperti Anda hanya mengibarkan bendera jika pernyataan di sekitar ...
thexacre
@ thexacre Tidak, satu pendengar untuk setiap kotak centang. Dalam acara klik hanya commands.add(new EncryptCommand()); atau commands.add(new CompressCommand());masing - masing.
Tulains Córdova
Bagaimana dengan penanganan tidak mencentang kotak? Di hampir semua bahasa / toolkit UI yang saya temui Anda masih perlu memeriksa keadaan kotak centang di pendengar acara. Saya setuju ini adalah pola yang lebih baik, tetapi pada dasarnya tidak perlu jika flag melakukan sesuatu di suatu tempat.
thexacre
7

Saya pikir "pola desain" tidak sesuai diarahkan ke "pola oo" dan sepenuhnya menghindari ide-ide yang jauh lebih sederhana. Yang kita bicarakan di sini adalah pipa data (sederhana).

Saya akan mencoba melakukannya di clojure. Bahasa lain di mana fungsi adalah kelas mungkin juga ok. Mungkin saya bisa contoh C # nanti, tapi tidak sebagus ini. Cara saya memecahkan ini adalah langkah-langkah berikut dengan beberapa penjelasan untuk non-clojurian:

1. Mewakili serangkaian transformasi.

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

Ini adalah peta, yaitu tabel pencarian / kamus / apa pun, dari kata kunci hingga fungsi. Contoh lain (kata kunci ke string):

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

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

Jadi, menulis (transformations :encrypt)atau (:encrypt transformations)akan mengembalikan fungsi terenkripsi. ( (fn [data] ... )hanya fungsi lambda.)

2. Dapatkan opsi sebagai urutan kata kunci:

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

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

3. Saring semua transformasi menggunakan opsi yang disediakan.

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

Contoh:

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

4. Menggabungkan fungsi menjadi satu:

(apply comp transformations-to-run)

Contoh:

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

5. Dan kemudian bersama-sama:

(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])

HANYA berubah jika kita ingin menambahkan fungsi baru, katakanlah "debug-print", adalah sebagai berikut:

(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
NiklasJ
sumber
Bagaimana fungsi diisi hanya mencakup fungsi yang perlu diterapkan tanpa dasarnya menggunakan serangkaian pernyataan if dalam satu atau lain cara?
thexacre
Baris funcs-to-run-here (map options funcs)melakukan penyaringan, sehingga memilih serangkaian fungsi untuk diterapkan. Mungkin saya harus memperbarui jawabannya dan masuk ke sedikit lebih detail.
NiklasJ
5

[Pada dasarnya, jawaban saya adalah lanjutan dari jawaban oleh @Ixrec di atas . ]

Sebuah pertanyaan penting: apakah jumlah kombinasi berbeda yang perlu Anda bahas akan bertambah? Anda lebih menyadari domain subjek Anda. Ini adalah penilaian Anda untuk dibuat.
Bisakah jumlah varian mungkin bertambah? Yah, itu tidak terbayangkan. Misalnya, Anda mungkin perlu mengakomodasi lebih banyak algoritma enkripsi yang berbeda.

Jika Anda mengantisipasi bahwa jumlah kombinasi berbeda akan bertambah, maka pola Strategi dapat membantu Anda. Itu dirancang untuk merangkum algoritma dan menyediakan antarmuka dipertukarkan ke kode panggilan. Anda masih memiliki sedikit logika ketika Anda membuat (instantiate) strategi yang tepat untuk setiap string tertentu.

Anda telah berkomentar di atas bahwa Anda tidak mengharapkan persyaratan untuk berubah. Jika Anda tidak berharap bahwa jumlah varian akan bertambah (atau jika Anda dapat menunda refactoring ini), maka pertahankan logika tetap seperti semula. Saat ini, Anda memiliki jumlah logika yang kecil dan dapat dikelola. (Mungkin menaruh catatan di komentar tentang kemungkinan refactoring ke pola Strategi.)

Nick Alexeev
sumber
1

Salah satu cara untuk melakukan ini dalam scala adalah:

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)

Menggunakan pola dekorator untuk mencapai tujuan di atas (pemisahan logika pemrosesan individu dan bagaimana mereka saling terhubung) akan terlalu bertele-tele.

Di mana Anda akan memerlukan pola desain untuk mencapai tujuan desain ini dalam paradigma pemrograman OO, bahasa fungsional menawarkan dukungan asli dengan menggunakan fungsi sebagai warga negara kelas pertama (baris 1 dan 2 dalam kode) dan komposisi fungsional (baris 3)

Sachin K
sumber
Mengapa ini lebih baik (atau lebih buruk) daripada pendekatan OP? Dan / atau apa pendapat Anda tentang ide OP untuk menggunakan pola dekorator?
Kasper van den Berg
cuplikan kode ini lebih baik dan eksplisit tentang pemesanan (kompresi sebelum enkripsi); menghindari antarmuka yang tidak diinginkan
Rag