Saya tahu ini adalah pertanyaan yang sangat luas, ambigu, dan mungkin filosofis. Sampai batas tertentu, kata kunci yang paling penting dalam pertanyaan - sistem tipe "kuat" - itu sendiri, tidak terdefinisi dengan baik . Jadi, izinkan saya mencoba menjelaskan apa yang saya maksud.
Konteks keseluruhan untuk pertanyaan
Kami telah membangun aplikasi web berskala sangat besar di Ruby on Rails dan kami umumnya senang dengan tumpukan kami. Ketika kami mau, kami dapat mengirimkan barang dengan sangat cepat - sesuatu yang bekerja untuk 90% kasus "bisnis", tanpa terlalu mengkhawatirkan sekitar 10% kasus tepi. Di sisi lain, dengan bantuan tinjauan kode & cakupan uji, kami bisa lambat & disengaja dan memastikan kami mencakup semua pangkalan - lagi, hanya dalam situasi yang layak mendapatkan pengawasan & keamanan yang lebih dekat.
Namun, seiring pertumbuhan tim, saya mulai merasa tidak nyaman dengan kurangnya "jaring pengaman" yang dimasukkan ke tumpukan kami.
Kami baru-baru ini mulai melakukan beberapa pengembangan Android asli di Jawa. Dan saya (dengan senang hati) diingatkan akan keamanan yang diberikan oleh bahasa yang dikompilasi / statis / diketik dengan sangat kuat.
- Variabel salah ejaan, tipe data yang salah, pemanggilan fungsi yang salah, dan sejumlah kesalahan sepele ditangkap oleh IDE Anda sendiri. Semua karena IDE dapat menghubungkan ke kompiler dan memverifikasi aspek-aspek tertentu dari program "kebenaran".
- Perlu mengubah tanda tangan fungsi? Mudah. Compiler + IDE dapat membantu Anda melihat SEMUA situs panggilan.
- Perlu memastikan bahwa pengecualian tertentu selalu ditangani? Pengecualian yang diperiksa untuk penyelamatan Anda.
Sekarang, sementara fitur keamanan ini memiliki kelebihan, saya juga menyadari kelemahan mereka. Terlebih lagi, di dunia "boilerplate heavy" Java. Oleh karena itu, alih-alih Jawa, saya sudah mulai melihat banyak bahasa modern, "sangat diketik" yang sudah mulai digunakan orang pada hari ini. Sebagai contoh: Scala, Rust, Haskell, dll. Yang paling menarik minat saya adalah kekuatan sistem tipenya dan pemeriksaan statis / kompilasi waktu.
Sekarang, pertanyaannya
Bagaimana cara menggunakan sistem tipe kuat ini dan fitur statis / waktu kompilasi dalam aplikasi yang lebih besar?
Sebagai contoh, bagaimana saya bisa melangkah keluar dari jenis pengantar standar "hello world" untuk fitur-fitur canggih ini? Yang menggunakan sistem tipe kaya untuk memodelkan masalah bisnis-domain? Apakah sistem tipe membantu, atau menghalangi, ketika Anda berada di zona 30.000 LOC +? Apa yang terjadi pada jaring pengaman yang disediakan oleh sistem tipe ini (dan pemeriksaan waktu kompilasi) ketika sistem Anda berinteraksi dengan dunia luar yang diketik dengan lemah, misalnya. melalui JSON atau XML API, berbagai penyimpanan data, input pengguna, dll.
Jawaban:
Saya akan memberikan jawaban singkat karena kurangnya waktu saya saat ini, tetapi saya sedang mengerjakan dua proyek besar (> 100.000 LOC di Haskell) - flowbox.io dan luna-lang.org. Kami menggunakan Haskell untuk semua bagian, termasuk backend, kompiler dari bahasa pemrograman kami dan bahkan GUI berbasis webGL. Saya harus mengakui bahwa sistem tipe yang kuat dan mesin seperti "tipe dependen" dapat memandu Anda dan menyelamatkan Anda dari beban dan kerumitan yang diketahui dari bahasa lain. Kami menggunakan tipe yang sangat luas dan segala sesuatu yang dapat diperiksa dalam waktu kompilasi, dilakukan demikian. Faktanya, selama 3 tahun terakhir pengembangan, kami tidak pernah menemukan kesalahan runtime atau stack overflow (dan ini adalah sesuatu yang sangat luar biasa). Satu-satunya kesalahan adalah kesalahan logika jelas yang dibuat oleh programmer. Banyak orang mengatakan, bahwa jika sesuatu dikompilasi di Haskell, itu hanya berfungsi dan Anda harus cukup yakin itu tidak akan meledak di wajah Anda suatu hari nanti.
Menjawab bagian pertama dari pertanyaan: Anda dapat mempelajari tentang fitur-fitur sistem tipe kuat ini membaca beberapa blog yang hebat, seperti:
Faktanya, ada banyak blog bagus lainnya di luar sana (seperti planet Haskell ). Bagaimanapun, metode terbaik untuk benar-benar memahami sistem tipe canggih adalah mengembangkan perpustakaan open source yang bermanfaat. Kami (di Flowbox & Pesanan Byte Baru) merilis banyak perpustakaan (Anda dapat menemukannya di Hackage), jadi jika Anda tidak tahu apa yang harus dikembangkan, Anda selalu dapat terlibat dalam proyek-proyek kami - cukup kirim email kepada saya setiap kali Anda inginkan (email tersedia di luna-lang.org ).
sumber
Yah, mengetik lemah vs kuat cukup jelas. Lebih jauh, karena yang paling dekat dengan penggunaan umum 'pengetikan kuat' adalah untuk merujuk hal-hal yang membuatnya sulit untuk mengetik, yang tidak meninggalkan apa pun untuk menggambarkan sistem tipe yang lebih kuat. Ini seperti mengatakan jika Anda dapat membawa kurang dari 30 pon Anda lemah, dan semua orang yang dapat mengangkat lebih banyak berada dalam kategori 'kuat' yang sama - perbedaan yang menyesatkan.
Jadi saya lebih suka definisi:
Apa yang saya maksudkan dengan melakukan sesuatu untuk Anda? Nah, mari kita periksa menulis API konversi gambar dalam kerangka Servant (di Haskell, tetapi Anda tidak benar-benar perlu mengetahuinya untuk mengikuti, Anda akan melihat ...)
Ini mengatakan bahwa kami ingin beberapa modul termasuk paket Servant dan plugin JuicyPixels untuk Servant, dan bahwa titik masuk utama program adalah menjalankan fungsi 'konversi' pada port 8001 sebagai server menggunakan backend Warp. Abaikan sedikit bahasa.
Ini mengatakan bahwa fungsi konversi adalah server di mana API harus cocok dengan tipe 'ConversionApi' dan permintaan ditangani oleh fungsi
handler
Ini menentukan
ConvesionApi
jenisnya. Dikatakan bahwa kita harus menerima jenis konten yang masuk yang ditentukan oleh daftar '[BMP, GIF, JPEG 50, PNG, TIFF, RADIANCE], dan menanganinya sebagai DynamicImage, dan kita harus mengembalikan DynamicImage yang dikonversi ke dalam rentang konten yang sama. jenis. Jangan khawatir tentang apa:> artinya, anggap saja itu sebagai sihir bahagia untuk saat ini.Jadi, mengingat definisi yang saya sukai, sistem yang diketik dengan lemah sekarang dapat memastikan hal-hal seperti:
Semua tujuan yang tinggi, tetapi sebenarnya tidak cukup untuk memenuhi syarat sebagai sistem yang diketik dengan kuat, mengingat definisi di atas. Dan sekarang kita harus sampai pada bagian yang sulit dari penulisan kode yang mengikuti spesifikasi ini. Dalam sistem tipe yang sangat kuat , kami menulis:
Dan kemudian kita selesai. Itu dia, tidak ada lagi kode untuk ditulis . Ini adalah server web yang sepenuhnya operasional (modulo semua kesalahan ketik yang saya lewatkan). Tipe telah memberitahu kompiler segala yang diperlukan untuk membuat server web kami dari tipe dan paket (modul secara teknis) yang kami definisikan dan impor.
Jadi, bagaimana Anda belajar melakukan ini pada skala aplikasi utama? Yah, itu benar-benar tidak jauh berbeda dari menggunakannya dalam aplikasi skala kecil. Jenis yang absolut tidak peduli berapa banyak kode yang ditulis terkait dengan mereka.
Inspeksi tipe run time adalah sesuatu yang Anda mungkin ingin hindari, karena itu mengukir sejumlah besar manfaat dan memungkinkan tipe untuk membuat proyek Anda lebih rumit untuk dikerjakan, daripada memiliki tipe yang menyederhanakan hal-hal.
Karena itu, sebagian besar hanya soal praktik memodelkan hal-hal dengan tipe. Dua cara utama untuk memodelkan sesuatu (atau membangun sesuatu secara umum) adalah dari atas ke bawah dan dari atas ke bawah. Top down dimulai dengan tingkat operasi tertinggi, dan ketika Anda membangun model Anda memiliki bagian-bagian di mana Anda menunda pemodelan sampai nanti. Pemodelan bottom-up berarti Anda memulai dengan operasi dasar, sama seperti Anda memulai dengan fungsi-fungsi dasar, kemudian membangun model yang lebih besar dan lebih besar sampai Anda sepenuhnya menangkap operasi proyek. Bottom up lebih konkret dan kemungkinan lebih cepat untuk dibangun, tetapi top-down mungkin lebih baik menginformasikan model tingkat bawah Anda tentang bagaimana mereka harus benar-benar berperilaku.
Jenis adalah bagaimana program berhubungan dengan matematika, secara harfiah, jadi tidak ada batas atas seberapa rumitnya mereka bisa, atau titik di mana Anda bisa 'selesai' belajar tentang matematika. Hampir semua sumber daya di luar program universitas tingkat tinggi semuanya didedikasikan untuk bagaimana jenis bekerja dalam beberapa bahasa tertentu, jadi Anda perlu memutuskan itu juga.
Yang terbaik yang bisa saya tawarkan, tipe dapat dikelompokkan seperti:
Secara umum, semakin jauh dalam daftar ini Anda pergi, semakin banyak jenis yang bisa lakukan untuk Anda, tetapi pada bagian paling bawah, Anda naik ke stratosfer dan udaranya semakin tipis - ekosistem paket jauh lebih kecil dan Anda ' Saya harus menulis lebih banyak hal sendiri vs telah menemukan perpustakaan yang relevan. Hambatan untuk masuk juga semakin tinggi saat Anda turun, karena Anda harus benar-benar memahami jenis sistem yang cukup untuk menulis program skala besar.
sumber
Proxy :: Proxy True
berfungsi, tetapi lebih baik untuk menuliskannya sebagaiProxy :: Proxy 'True
.'[xs]
sintaks? Ini jelas bukanChar
, tapi saya tidak melihat bagaimanaTypeOperators
atauDataKinds
mengaktifkan sintaks alternatif. Apakah ini semacam quasiquoting?Saya baru saja mulai bekerja pada tim inti dari platform besar yang ditulis dalam Scala. Anda dapat melihat aplikasi open source yang sukses, seperti Scalatra, Play, atau Slick untuk melihat bagaimana mereka menangani beberapa pertanyaan Anda yang lebih terperinci tentang interaksi dengan format data dinamis.
Salah satu keuntungan besar yang kami temukan dari pengetikan kuat Scala adalah dalam pendidikan pengguna. Tim inti dapat membuat keputusan dan menegakkan keputusan-keputusan itu dalam sistem tipe, jadi ketika tim lain yang jauh kurang akrab dengan prinsip-prinsip desain harus berinteraksi dengan sistem, kompiler mengoreksi mereka, dan tim inti tidak terus-menerus memperbaiki hal-hal di tarik permintaan. Ini adalah keuntungan besar dalam sistem besar.
Tentu saja, tidak semua prinsip desain dapat diterapkan dalam sistem tipe, tetapi semakin kuat sistem tipe Anda, semakin banyak prinsip desain yang dapat Anda terapkan dalam kompiler.
Kami juga dapat membuat segalanya lebih mudah bagi pengguna. Seringkali bagi mereka, mereka hanya bekerja dengan koleksi reguler atau kelas kasus, dan kami mengonversinya ke JSON atau apa pun secara otomatis yang diperlukan untuk transportasi jaringan.
Pengetikan yang kuat juga membantu membedakan antara hal-hal seperti input yang tidak bersih dan sanitasi, yang dapat membantu keamanan.
Mengetik dengan kuat juga membantu tes Anda menjadi lebih fokus pada perilaku Anda yang sebenarnya , alih-alih membutuhkan banyak tes yang hanya menguji tipe Anda. Itu membuat pengujian jauh lebih menyenangkan, lebih fokus, dan karenanya lebih efektif.
Kerugian utama adalah tidak terbiasa dengan bahasa dan paradigma bahasa, dan itu dapat diperbaiki dengan waktu. Selain itu, kami telah menemukan upaya yang sepadan.
sumber
Meskipun bukan jawaban langsung (karena saya belum bekerja di +30.000 basis kode LOC di haskell :( ..), saya mohon Anda untuk memeriksa https://www.fpcomplete.com/business/resources/case-studies / yang menampilkan banyak studi kasus haskell dalam pengaturan industri aktual.
Artikel bagus lainnya adalah IMVU, yang menggambarkan pengalaman mereka berubah menjadi haskell - http://engineering.imvu.com/2014/03/24/what-its-like-to-use-haskell/ .
Dari pengalaman pribadi dalam aplikasi yang lebih besar, sistem tipe sangat membantu Anda, terutama jika Anda mencoba untuk menyandikan sebanyak mungkin dalam jenis. Kekuatan sebenarnya benar-benar jelas ketika datang ke hal-hal refactoring - yang berarti pemeliharaan dan semacamnya menjadi tugas yang jauh lebih mengkhawatirkan.
Saya akan membuang beberapa tautan ke sumber daya yang saya rekomendasikan, karena Anda mengajukan cukup banyak pertanyaan sekaligus:
Sebagai komentar penutup, tentang berurusan dengan dunia luar dilakukan dalam beberapa cara. Ada perpustakaan untuk memastikan hal-hal di ujung Anda adalah tipe aman, seperti Aeson untuk JSON, Esqueleto untuk SQL dan banyak lagi.
sumber
Apa yang saya lihat:
Saya telah mengerjakan beberapa aplikasi web Ruby besar (Rails), satu aplikasi web Haskell besar, dan beberapa yang lebih kecil. Dengan pengalaman itu saya harus mengatakan bahwa kehidupan yang bekerja pada aplikasi Haskell jauh lebih mudah daripada di Rails dalam hal seperti pemeliharaan dan kurva belajar yang lebih rendah. Saya berpendapat bahwa manfaat ini karena sistem tipe Haskell dan gaya pemrograman fungsional. Namun, tidak seperti banyak, saya percaya bahwa bagian "statis" dari sistem tipe hanya kenyamanan besar karena masih ada manfaat yang bisa didapat ketika menggunakan kontrak dinamis.
Apa yang saya yakini
Ada paket bagus yang disebut Kontrak Ruby yang berjalan bersama dalam menyediakan beberapa fitur utama yang saya rasa membantu proyek Haskell mencapai karakteristik perawatan yang lebih baik. Kontrak Ruby melakukan pemeriksaannya pada saat run-time sehingga yang terbaik adalah ketika dipasangkan dengan konvergen tes tinggi tetapi masih memberikan dokumentasi in-line dan ekspresi maksud dan makna yang sama seperti menggunakan anotasi jenis dalam bahasa seperti Haskell.
Anwser to Question
Untuk menjawab pertanyaan-pertanyaan yang diajukan di atas, ada banyak tempat di mana orang dapat terbiasa dengan Haskell dan bahasa lain dengan sistem tipe canggih. Namun, dan harus benar-benar jujur, sementara sumber-sumber dokumentasi ini sangat baik dalam hak mereka sendiri, mereka semua tampak agak underwhelming bila dibandingkan dengan kebanyakan dokumentasi dan saran praktis yang ditemukan dalam bahasa Ruby, Python, Jawa dan bahasa-bahasa lain semacam itu. Bagaimanapun, Real World Haskell semakin tua tetapi masih merupakan sumber yang bagus.
Kategori Teori
Jika Anda memilih Haskell, Anda akan menemukan banyak literatur yang membahas teori Kategori. Teori kategori IMHO berguna tetapi tidak perlu. Mengingat prevalensi dalam komunitas Haskell, mudah untuk mengacaukan pro dan kontra dari jenis dengan perasaan tentang kepraktisan teori Kategori. Sangat membantu untuk mengingat mereka adalah dua hal yang berbeda, yaitu untuk mengatakan bahwa implementasi dipandu oleh teori Kategori dapat dilakukan dalam bahasa yang diketik secara dinamis sama seperti statis (modulo manfaat yang disediakan oleh sistem tipe). Sistem tipe lanjutan pada umumnya tidak terikat pada teori Kategori dan teori Kategori tidak terikat pada sistem tipe.
Lebih lanjut tentang Jenis
Ketika Anda belajar lebih banyak tentang pemrograman dengan tipe dan teknik di dalamnya (yang terjadi cukup cepat karena menyenangkan), Anda akan ingin mengekspresikan lebih banyak dengan sistem tipe. Dalam hal ini saya akan melihat ke beberapa sumber daya berikut dan bergabung dengan saya dalam membuat vendor alat sadar bahwa kami ingin alat berkualitas industri dengan fitur-fitur ini hanya dikemas menjadi sesuatu yang memperlihatkan antarmuka yang mudah digunakan (seperti Kontrak Ruby):
Pengantar Pemrograman dalam ATS
Jenis Perbaikan LiquidHaskell melalui TPS dan Abstraksi Predikat
Pengembangan Berbasis Tipe dengan Idris
sumber
Pertama, saya merasa seperti ada kebingungan dalam jawaban antara yang diketik dengan lemah versus diketik dengan kuat, dan statis versus diketik secara dinamis. Tautan OP yang disediakan jelas membuat perbedaan:
Sebagai contoh, C, C ++ dan Java diketik secara statis karena variabel diketik pada waktu kompilasi. Namun, C dan C ++ dapat dianggap diketik dengan lemah karena bahasa memungkinkan untuk memotong pembatasan menggunakan
void *
pointer dan gips. Lebih banyak tentang topik ini.Pada perbedaan ini, pengetikan yang kuat hanya bisa lebih baik. Semakin awal gagal, semakin baik.
Namun, pada penulisan program besar, saya tidak berpikir sistem tipe memainkan peran penting. Kernel Linux adalah sepuluh juta LOC yang ditulis dalam C dan assembly dan dianggap sebagai program yang sangat stabil, itu jauh dari 200 baris Java saya yang mungkin penuh dengan lubang keamanan. Demikian pula, meskipun "bahasa skrip" yang diketik secara dinamis menderita reputasi buruk ketika menulis program besar, kadang-kadang ada bukti bahwa itu tidak layak (seperti Python Django, lebih dari 70k LOC)
Menurut pendapat saya, ini semua tentang standar kualitas. Tanggung jawab untuk skalabilitas aplikasi besar seharusnya hanya dipegang oleh programmer dan arsitek dan keinginan mereka untuk membuat aplikasi bersih, diuji, didokumentasikan dengan baik dll.
sumber
dari jawaban sebelumnya https://www.fpcomplete.com/business/resources/case-studies/
itu benar-benar seperti bahasa lain untuk membangun kekuatan
Dengan menggunakan Jenis Data Abstrak, atau lebih umum polimorfisme
Itu membantu sepanjang jalan. sistem tipe membantu Anda menulis kode karena memberi tahu Anda bentuk hasil yang ingin Anda miliki. Sebenarnya Agda menulis kode untuk kamu.
PS: jangan membuat kesalahan dengan memiliki sistem jenis dan harus menulis sendiri jenisnya, yang bodoh: komputer dapat melakukannya untuk Anda.
Ini bagus, karena mengetahui struktur nilai melalui tipe berarti komputer dapat menyimpulkan cara untuk menulis (de) serializer untuk Anda.
Jika Anda benar-benar ingin tahu tentang jenis dan abstraksi, pengantar terbaik adalah Pada Jenis Pemahaman, Abstraksi Data, dan Polimorfisme
Ini kertas, bukan studi kasus dengan gambar-gambar cantik, tapi mencerahkan
sumber
Sebagai seorang programmer. Net yang bekerja pada aplikasi web banyak saya melihat kedua sisi C # diketik dan Javascript yang belum diketik.
Saya tidak yakin saya telah melihat literatur tentang pertanyaan yang Anda ajukan. Dengan bahasa yang diketik Anda menerima semua hal ini begitu saja. Dengan yang belum diketik Anda melihat mendefinisikan jenis sebagai overhead yang tidak perlu.
Secara pribadi, saya tidak berpikir Anda dapat menyangkal bahwa bahasa yang diketik sangat menawarkan manfaat yang Anda gambarkan dengan biaya yang sangat rendah (dibandingkan dengan menulis tes unit yang setara). Berinteraksi dengan sistem yang diketik dengan lemah biasanya melibatkan tipe generik, seperti Array atau Kamus Objek, seperti DataReader, atau penggunaan kreatif string atau kelas dinamis baru. Intinya semuanya berfungsi, Anda hanya mendapatkan kesalahan runtime alih-alih waktu kompilasi.
Jika Anda ingin menulis program yang sangat singkat, mungkin mendefinisikan fungsi dalam beberapa baris untuk bekerja dengan aplikasi yang lebih besar, maka Anda tidak punya ruang untuk mendeklarasikan kelas. Tentunya ini adalah bahasa yang tidak diketik seperti JS yang ditempati?
sumber