Asal "sebuah metode harus mengembalikan nilai atau memiliki efek samping, tetapi tidak keduanya"

12

Saya pernah membaca bahwa suatu metode harus memiliki nilai balik (dan transparan secara referensial), atau memiliki efek samping, tetapi tidak keduanya. Saya tidak dapat menemukan referensi untuk aturan ini, tetapi ingin belajar lebih banyak tentangnya.

Apa asal usul nasihat ini? Dari orang atau komunitas apa itu muncul?

Kredit ekstra: Apa manfaat yang diklaim dari mengikuti saran ini?

Wayne Conrad
sumber
1
@gnat Ya, ini terutama tentang sejarah. Saya takut bahwa bagian kredit ekstra terlalu subjektif untuk berdiri sendiri, dan bahwa sejarah memiliki peluang lebih baik untuk keluar dari penutupan. Saya akan menambahkan tag.
Wayne Conrad
beberapa jawaban yang membuat saya bertanya-tanya apakah Anda bertanya tentang manfaat yang diklaim oleh penulis saran ini atau untuk daftar semua manfaat yang mungkin diklaim sama sekali?
nyamuk
@gnat Saya bertanya tentang manfaat yang diklaim oleh penulis (sekali lagi, penutupan takut), tapi saya yakin tidak keberatan dengan alasan tumpukan - mereka menjawab pertanyaan yang sebenarnya ingin saya tanyakan. Jika saya menghapus "diklaim" dari pertanyaan saya, membuat tumpukan-on jawaban pada topik, apakah itu mendorong pertanyaan terlalu jauh ke subyektif?
Wayne Conrad
"alasan tiang pancang" cenderung mendorong pertanyaan itu ditutup terlalu luas . Jika Anda lebih suka "tetap di sisi terbuka", saya pikir akan lebih aman untuk mempersempitnya demi keuntungan yang diklaim oleh penulis
nyamuk
Satu manfaat adalah bahwa jika Anda dibayar berdasarkan volume kode, ini menghasilkan tambahan. "Melakukan sesuatu; GetResultOfSesuatu; HandleErrorsFromSomething;"
Ⴖ uі

Jawaban:

13

Menurut Greg Young, ide ini berasal dari Bertrand Meyer : pemisahan Command-Query .

Ini menyatakan bahwa setiap metode harus berupa perintah yang melakukan tindakan, atau permintaan yang mengembalikan data ke pemanggil, tetapi tidak keduanya. Dengan kata lain, Mengajukan pertanyaan seharusnya tidak mengubah jawabannya . 1 Secara lebih formal, metode harus mengembalikan nilai hanya jika mereka secara transparan transparan dan karenanya tidak memiliki efek samping.

1: Eiffel: bahasa untuk slide rekayasa perangkat lunak 43-48

Dalam Domain Driven Design, ini mirip dengan Command-Query-Read Separation / Segregation (CQRS), sebagaimana dinamai oleh Greg Young.

Greg Young mengambil ide CQS dari Bertrand untuk memberi nama CQRS sebagaimana disebutkan oleh Martin Fowler dalam artikel CQRS ini

Manfaat

  • Bagian Read (Query) dapat diskalakan / tweak secara berbeda dari bagian Write (command). Memisahkan keduanya akan mencegah salah satu dari menghalangi satu sama lain ketika optimasi / kinerja adalah kunci.

Baca artikel di tautan Martin Fowler untuk informasi lebih lanjut.

tunmise fasipe
sumber
1
Secara alami, dalam banyak situasi menghasilkan hasil yang bermanfaat dan melakukan beberapa modifikasi pada saat yang sama tidak lebih mahal daripada melakukan yang lebih sulit dari keduanya secara terpisah.
Deduplicator
1
@Deduplicator Contoh klise adalah InterlockedCompareExchange?
і uі
1
Saran ini jelas tidak berlaku ketika pengembalian adalah beberapa informasi tentang apa yang dilakukan dalam perintah, namun - metode untuk menghapus baris dari dataset dapat mengubah keadaan dataset, menghapus baris yang ditunjukkan sesuai dengan kriteria yang diberikan, dan lalu kembalikan jumlah baris yang dihapus atau bahkan daftar dengan baris tersebut.
T. Sar
4

Saya tidak tahu dari mana asalnya, tetapi itu adalah saran yang bagus dan cukup mudah dipahami.

Setiap program yang dirancang dengan baik akan dipecah menjadi berbagai bagian, digabungkan dan disusun dengan berbagai cara. Semakin sulit untuk berpikir tentang apa yang dilakukan bagian tertentu, semakin sulit untuk memastikan bahwa program Anda akan bereaksi dengan cara yang dapat diprediksi.

Mengisolasi bagian-bagian yang menghasilkan efek samping membuat sisanya lebih mudah untuk dipikirkan, diuji, dan di-debug. Mengurangi jumlah efek samping di setiap bagian yang menghasilkan efek samping akan membuat bagian itu lebih mudah untuk dikerjakan dengan cara yang sama.

Jika Anda menguraikannya lebih jauh, nilai kembali adalah efek. Efek samping adalah efek. Suatu fungsi seharusnya hanya menghasilkan 1 efek (jika mungkin) karena semakin banyak input dan efek yang dimiliki fungsi, semakin besar kesulitan dalam berpikir tentang apa yang sebenarnya dilakukannya.

Morgen
sumber
ini bahkan tidak berusaha menjawab pertanyaan yang diajukan, lihat Bagaimana Menjawab
nyamuk
@gnat Pertanyaan saya datang dalam dua bagian: Pertanyaan utama ("siapa"), dan kredit ekstra ("mengapa). Bukankah ini membahas bagian kredit ekstra?
Wayne Conrad
per bacaan saya (" manfaat diklaim "), mengapa bagian diharapkan menjadi salah satu yang diusulkan oleh penulis kutipan. Pertanyaan sepertinya tidak menanyakan daftar semua kemungkinan manfaat
agas
2
@gnat Saya memahami pertanyaan ini sebagai upaya untuk memahami saran ini, baik alasan di baliknya maupun konteksnya. Saya tidak percaya bahwa tidak pantas hanya membahas sebagian dari pertanyaan.
Morgen
1

Kredit ekstra: Apa manfaat yang semula diklaim dari mengikuti saran ini?

Salah satu manfaat memisahkan nilai kembali dari efek samping adalah menghilangkan nilai masalah potensial yang mungkin disebabkan oleh evaluasi hubung singkat .

bool FooWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

bool BarWithSideEffect() {
    // do query
    // do side effect
    return resultOfQuery;
}

void BadShortCircuitEvaluation()
{
    // the programmer's intent is to have side effects of both functions
    if (FooWithSideEffect() && BarWithSideEffect() ) {
        // do something
    }

    // in case FooWithSideEffect() returns true, 
    // then BarWithSideEffect() is not called at all
    // because of short-circuit evaluation
}
Nick Alexeev
sumber
apakah ini manfaat yang diklaim oleh penulis saran ?
nyamuk
@gnat Saya memiliki perpaduan antara sejarah dan praktis, saya khawatir.
Nick Alexeev
1
komentar dan kode tidak cocok, BarWithSideEffects tidak dipanggil jika FooWithSideEffects mengembalikan false
jk.