Kedengarannya cukup mendasar, saya tahu, tetapi saya baru-baru ini memiliki seorang kolega memberi tahu saya bahwa metode yang disebut startHttpServer
terlalu rumit untuk dipahami karena hanya menjalankan server jika belum berjalan. Saya menemukan saya mendapat masalah ketika saya menanggapi dengan, "Serius? Saya sudah melakukan ini selama beberapa dekade - ini adalah pola umum dalam pemrograman." Lebih sering daripada saya mau mengakui bahwa dia kembali dengan beberapa bukti terdokumentasi yang menunjukkan bahwa seluruh komunitas pemrograman berada di belakang sudut pandangnya dan akhirnya saya merasa malu.
Pertanyaan : Apakah ada pola desain yang terdokumentasi di balik konsep metode yang tidak boleh jika tindakan yang diperlukan sudah berlaku? Atau, jika bukan sebuah pola, apakah ia memiliki nama juga? Dan jika tidak, apakah ada alasan untuk berpikir terlalu rumit untuk mempertimbangkan menulis metode dengan cara ini?
sumber
startHttpServer
), dan ya, istilah "idempoten" berlaku di sini baik.Jawaban:
Seperti yang sudah dikatakan NickWilliams : konsep yang dijelaskan OP disebut idempoten (kata benda Idempotensi ). Ini memang praktik umum, terutama di API tingkat tinggi.
TAPI: Ganti nama fungsinya.
Alih-alih
startHttpServer
menyebutnyamakeSureHttpServerIsRunning
atauensureHttpServerIsRunning
.Ketika suatu fungsi dipanggil
startHttpServer
, pembaca mengharapkannya untuk memulai server HTTP; ketika dipanggil sepuluh kali berturut-turut, saya akan menjalankan sepuluh server. Fungsi Anda sebagian besar tidak melakukannya. Selain itu, nama dengan "mulai" menunjukkan bahwa jika saya ingin hanya satu server yang berjalan saya harus melacak apakah fungsi tersebut sudah dipanggil atau belum.Ketika suatu fungsi dipanggil
makeSureHttpServerIsRunning
, saya menganggap itu akan melakukan hal-hal yang diperlukan untuk memastikan bahwa server HTTP sedang berjalan, kemungkinan besar dengan memeriksa apakah sudah berjalan, dan memulainya jika tidak. Saya juga berasumsi bahwa fungsi memastikan server benar-benar berjalan (memulai server mungkin melibatkan beberapa waktu di mana ia belum cukup berjalan).sumber
Ubah nama menjadi
EnsureServerRunning
.Sama sekali tidak ambigu dan jelas bahwa itu memastikan itu berjalan (jika tidak) tanpa menyiratkan restart jika itu.
(Alternatif:?
StartServerIfNotRunning
)sumber
Tidak benar-benar pola desain tetapi saya akan menyebut metode Anda idempoten . Ada istilah yang biasanya digunakan untuk merujuk ke panggilan jarak jauh tetapi deskripsi tampaknya cocok dengan apa yang Anda lakukan.
Efek samping server di sini adalah bahwa server http dimulai setelah metode dipanggil. Saya tidak melihat ada yang salah dengan metode melakukan ini.
Jika Anda memerlukan pola desain, saya kira Anda bisa mengekspos httpServer Anda sebagai singleton yang dimulai ketika diinisialisasi.
sumber
Sebagai orang yang menerapkan ini alat ,
startHttpServer
, Anda harus mencoba untuk membuatnya yang paling sederhana, halus dan mulus untuk digunakan ...Logika fungsi
Secara teknis, dengan memisahkan
startHttpServer
's logika menjadi 2 fungsi dan memanggil mereka secara terpisah , semua apa yang Anda lakukan adalah bergerakstartHttpServer
' s idempotency ke dalam kode memanggil kedua fungsi bukan ... Selanjutnya, kecuali jika Anda membungkus kedua logika dalam fungsi ketiga (yang adalah apa yang dilakukannyastartHttpServer
di tempat pertama), ini memaksa Anda untuk menulis kode unDRYed, menduplikasinya secara eksponensial di mana pun Anda harus meneleponstartHttpServer
. Singkatnya,startHttpServer
harus menyebut dirinyaisHttpServerRunning
fungsi.Jadi maksud saya adalah:
isHttpServerRunning
fungsi karena ini mungkin diperlukan secara mandiri ...startHttpServer
membuatnya digunakanisHttpServerRunning
untuk menentukan tindakan selanjutnya sesuai ...Namun, Anda dapat
startHttpServer
mengembalikan nilai apa pun yang mungkin diperlukan oleh pengguna fungsi ini, misalnya:0
=> kegagalan memulai server1
=> keberhasilan memulai server2
=> server sudah dimulaiPenamaan fungsi
Pertama-tama, apa tujuan utama pengguna? Untuk memulai server HTTP , bukan?
Pada dasarnya, tidak ada masalah dengan berniat untuk memulai sesuatu yang sudah dimulai, AKA
1*1=1
. Jadi, setidaknya bagi saya, menyebutnya "ensureHttpServerIsRunning
" tampaknya tidak dibutuhkan secara kritis, saya akan lebih peduli tentang berapa lama, alami dan mudah diingat nama fungsi itu.Sekarang jika Anda ingin tahu cara kerja secara detail fungsi di bawah tenda, ada dokumentasi atau sumber kode untuk itu, maksud saya seperti untuk fungsi lain dari library / framework / API / etc ...
Anda mempelajari fungsinya satu kali saat Anda menulisnya beberapa kali ...
Jadi, saya tetap dengan
startHttpServer
yang lebih pendek, lebih sederhana dan lebih eksplisit daripadaensureHttpServerIsRunning
.sumber
Saya kira kolega Anda berarti
startHttpServer
melakukan terlalu banyak:Itu adalah dua bagian kode yang tidak terkait. Misalnya, situasi serupa terjadi ketika aplikasi desktop harus memastikan bahwa itu belum berjalan ketika diluncurkan; akan ada bagian dari kode yang menangani instance aplikasi (misalnya menggunakan mutex), dan kode yang akan memulai loop pesan aplikasi.
Ini berarti Anda tidak harus memiliki satu, tetapi setidaknya - dua metode :
isHttpServerRunning: boolean
startHttpServer
Titik masuk aplikasi akan memanggil metode pertama, dan yang kedua jika nilai baliknya
false
. Sekarang, setiap metode melakukan satu dan satu hal, dan mudah dimengerti.¹ Jika logika yang diperlukan untuk mengetahui apakah server sudah berjalan terlalu kompleks, mungkin memerlukan pemisahan lebih lanjut menjadi beberapa metode.
sumber
startHttpServer
disebut lebih dari satu tempat dalam kode? Haruskah beberapa baris serupa disalin-tempel di mana-mana? Haruskah ini dilakukan dengan semua fungsi? Segera program Anda akan menjadi ukuran yang tak terbatas.startHttpServer
metode ini akan terlihat seperti kira-kiraif (isHttpServerRunning()){ return; }
. Anda menegaskan aturan bisnis bahwa "tidak sah untuk memulai server http jika sudah berjalan", tetapi kemudian membuatnya menjadi tanggung jawab orang lain untuk menegakkan aturan itu. Ad-hoc dan berulang kali di setiap lokasi tempat mereka meneleponstartHttpServer
.Karena Anda tidak menentukan bahasa, dalam JavaScript banyak perpustakaan memiliki fungsi "satu kali" misalnya Garis Bawah . Jadi, jika itu sudah tidak asing lagi bagi Anda, sebut saja itu pola "sekali" dan mungkin ganti nama metode Anda.
Saya sendiri, datang lebih banyak dari Jawa, istilah "caching" atau "evaluasi malas" datang ke pikiran. "Idempoten" secara teknis benar dan merupakan pilihan yang baik, esp. jika Anda memiliki latar belakang yang lebih fungsional.
sumber
restartHttpServer()
. Tapi hanya berhenti - apa gunanya di sana? Anda suka kegagalan koneksi sporadis? :-)ensureRunning()
? :-) Adapun admin menghentikannya, memiliki kode lain ini terus-menerus restart sementara admin mencoba untuk memodifikasi atau memperbaiki sesuatu akan sangat menjengkelkan dan salah. Biarkan admin memulai kembali, bukan kodenya.Saya lebih suka
startHttpServerIfNotIsRunning
.Dengan cara ini, kondisinya disebutkan dengan jelas dalam nama metode.
Ensure
ataumakeSure
sepertinya agak kabur bagi saya, karena itu bukan ekspresi teknis. Sepertinya kita tidak tahu persis apa yang akan terjadi.sumber
Ensure
artinya. Saya masih tidak suka kata ini untuk ungkapan teknis.Ensure
adalah sesuatu yang manusiawi. Suatu sistem tidak dapat memastikan apa pun, hanya akan melakukan apa yang seharusnya dilakukan.Apa yang seharusnya dikatakan oleh kolega Anda adalah bahwa Anda tidak memiliki bisnis yang menulis metode itu. Sudah ditulis berkali-kali, dan ditulis lebih baik daripada kemungkinan Anda menulisnya. Misalnya: http://docs.ansible.com/ansible/latest/systemd_module.html https://docs.saltstack.com/en/latest/ref/states/all/salt.states.service.html
Dari perspektif arsitektur, memiliki sedikit kode sewenang-wenang mengelola server web adalah hal-hal buruk. Kecuali jika mengelola layanan secara eksklusif apa yang dilakukan kode Anda. Tapi saya kira Anda tidak menulis monit (atau kubernetes atau ...).
sumber
startServer
fungsi atau sejenisnya sama sekali tidak umum . Itu tidak berarti Anda akan menulis detail tingkat rendah seluk beluk.