Gagasan Single Entry, Single Exit (SESE) ini berasal dari bahasa dengan manajemen sumber daya eksplisit , seperti C dan assembly. Dalam C, kode seperti ini akan membocorkan sumber daya:
void f()
{
resource res = acquire_resource(); // think malloc()
if( f1(res) )
return; // leaks res
f2(res);
release_resource(res); // think free()
}
Dalam bahasa tersebut, Anda pada dasarnya memiliki tiga opsi:
Replikasi kode pembersihan.
Ugh. Redundansi selalu buruk.
Gunakan a goto
untuk melompat ke kode pembersihan.
Ini membutuhkan kode pembersihan untuk menjadi hal terakhir dalam fungsi. (Dan inilah mengapa beberapa orang berargumentasi bahwa goto
ada tempatnya. Dan memang ada - dalam C.)
Memperkenalkan variabel lokal dan memanipulasi aliran kontrol melalui itu.
Kelemahannya adalah bahwa aliran kontrol dimanipulasi melalui sintaks (berpikir break
, return
, if
, while
) jauh lebih mudah untuk mengikuti dari aliran kontrol dimanipulasi melalui keadaan variabel (karena variabel tersebut tidak memiliki negara ketika Anda melihat algoritma).
Dalam perakitan itu bahkan lebih aneh, karena Anda dapat melompat ke alamat mana pun dalam suatu fungsi ketika Anda memanggil fungsi itu, yang secara efektif berarti Anda memiliki jumlah titik masuk yang hampir tidak terbatas untuk fungsi apa pun. (Kadang-kadang ini membantu. Pemukul seperti itu adalah teknik yang umum bagi kompiler untuk mengimplementasikan this
penyesuaian pointer yang diperlukan untuk memanggil virtual
fungsi dalam beberapa skenario warisan di C ++.)
Ketika Anda harus mengelola sumber daya secara manual, mengeksploitasi opsi memasukkan atau keluar dari fungsi di mana saja mengarah ke kode yang lebih kompleks, dan dengan demikian ke bug. Karena itu, muncul aliran pemikiran yang menyebarkan SESE, untuk mendapatkan kode yang lebih bersih dan lebih sedikit bug.
Namun, ketika suatu bahasa memiliki pengecualian, (hampir) fungsi apa pun mungkin keluar sebelum waktunya di (hampir) titik mana pun, jadi Anda harus tetap membuat ketentuan untuk pengembalian prematur. (Saya pikir finally
ini terutama digunakan untuk itu di Jawa dan using
(ketika menerapkan IDisposable
, finally
sebaliknya) di C #; C ++ sebagai gantinya mempekerjakan RAII .) Setelah Anda melakukan ini, Anda tidak dapat gagal untuk membersihkan setelah Anda sendiri karena return
pernyataan awal , jadi apa yang mungkin argumen terkuat yang mendukung SESE telah menghilang.
Itu membuat keterbacaan. Tentu saja, fungsi 200 LoC dengan setengah lusin return
pernyataan ditaburkan secara acak di atasnya bukan gaya pemrograman yang baik dan tidak membuat kode yang dapat dibaca. Tetapi fungsi seperti itu tidak akan mudah dipahami tanpa pengembalian prematur itu.
Dalam bahasa di mana sumber daya tidak atau tidak seharusnya dikelola secara manual, ada sedikit atau tidak ada nilai dalam mematuhi konvensi SESE lama. OTOH, seperti yang saya katakan di atas, SESE sering membuat kode lebih kompleks . Ini adalah dinosaurus yang (kecuali untuk C) tidak cocok dengan sebagian besar bahasa saat ini. Alih-alih membantu pemahaman kode, justru menghambatnya.
Mengapa programmer Java tetap pada ini? Saya tidak tahu, tetapi dari POV (luar) saya, Java mengambil banyak konvensi dari C (di mana mereka masuk akal) dan menerapkannya ke dunia OO (di mana mereka tidak berguna atau sangat buruk), di mana sekarang menempel mereka, tidak peduli berapa biayanya. (Suka konvensi untuk mendefinisikan semua variabel Anda di awal ruang lingkup.)
Programmer berpegang pada semua jenis notasi aneh karena alasan irasional. (Pernyataan struktural yang sangat bersarang - "panah" - dalam bahasa seperti Pascal, pernah dipandang sebagai kode yang indah.) Menerapkan penalaran logis murni untuk ini tampaknya gagal meyakinkan mayoritas dari mereka untuk menyimpang dari cara yang telah mereka tetapkan. Cara terbaik untuk mengubah kebiasaan seperti itu mungkin mengajar mereka sejak dini untuk melakukan yang terbaik, bukan apa yang konvensional. Anda, sebagai guru pemrograman, memilikinya di tangan Anda.:)