Berikut adalah contoh bagaimana Anda dapat mendekati ini dari perspektif fungsional, dan bagaimana hal itu membantu menghindari potensi jebakan. Saya bekerja di Haskell, yang saya anggap Anda tidak tahu, jadi saya akan menjelaskannya secara rinci saat saya melanjutkan.
data Application = Applied ApplicationDetails |
InReview ApplicationDetails |
Approved ApplicationDetails |
Declined ApplicationDetails
Ini mendefinisikan tipe data yang bisa di salah satu dari empat negara yang sesuai dengan negara aplikasi Anda. ApplicationDetails
diasumsikan sebagai tipe yang ada yang berisi informasi terperinci.
newtype UpdatableApplication = UpdatableApplication Application
Jenis alias yang perlu konversi eksplisit ke dan dari Application
. Ini berarti bahwa jika kita mendefinisikan fungsi berikut yang menerima dan membuka UpdatableApplication
dan melakukan sesuatu yang berguna dengannya,
updateApplication :: UpdatableApplication -> ApplicationDetails -> Application
updateApplication (UpdatableApplication app) details = ...
maka kita harus secara eksplisit mengonversi Aplikasi ke Aplikasi yang Dapat Diperbarui sebelum kita dapat menggunakannya. Ini dilakukan dengan menggunakan fungsi ini:
findUpdatableApplication :: Application -> Maybe UpdatableApplication
findUpdatableApplication app@(Applied _) = Just (UpdatableApplication app)
findUpdatableApplication _ = Nothing
Di sini kami melakukan tiga hal menarik:
- Kami memeriksa status aplikasi (menggunakan pencocokan pola, yang sangat berguna untuk kode semacam ini), dan
- jika dapat diperbarui, kami membungkusnya dalam
UpdatableApplication
(yang hanya melibatkan catatan jenis kompilasi dari perubahan jenis yang ditambahkan, karena Haskell memiliki fitur khusus untuk melakukan tipuan tingkat-jenis seperti ini, tidak memerlukan biaya saat runtime) , dan
- kami mengembalikan hasilnya dalam "Mungkin" (mirip dengan
Option
di C # atau Optional
di Jawa - itu adalah objek yang membungkus hasil yang bisa hilang).
Sekarang, untuk benar-benar menyatukan ini, kita perlu memanggil fungsi ini dan, jika hasilnya berhasil, meneruskannya ke fungsi pembaruan ...
case findUpdatableApplication application of
Just updatableApplication -> do
storeApplicationInDatabase (updateApplication updatableApplication)
showConfirmationPage
Nothing -> do
showErrorPage
Karena updateApplication
fungsi membutuhkan objek yang dibungkus, kita tidak bisa lupa untuk memeriksa prasyarat. Dan karena fungsi pemeriksaan prakondisi mengembalikan objek yang dibungkus di dalam Maybe
objek, kita tidak bisa lupa untuk memeriksa hasilnya dan merespons jika gagal.
Sekarang ... Anda bisa melakukan ini dalam bahasa berorientasi objek. Tapi itu kurang nyaman:
- Tak satu pun dari bahasa OO yang saya coba memiliki sintaks sederhana untuk membuat tipe pembungkus yang aman, jadi itu boilerplate.
- Ini juga akan menjadi kurang efisien, karena setidaknya untuk sebagian besar bahasa mereka tidak akan dapat menghilangkan jenis pembungkus, karena akan diperlukan untuk ada dan dapat dideteksi pada saat runtime (Haskell tidak memiliki pengecekan jenis runtime, semua jenis cek adalah dilakukan pada waktu kompilasi).
- Sementara beberapa bahasa OO memiliki tipe yang setara dengan
Maybe
mereka biasanya tidak memiliki cara yang nyaman untuk mengekstraksi data dan memilih jalur yang akan diambil pada saat yang sama. Pencocokan pola juga sangat berguna di sini.