Pemrograman otomatis: menulis kode yang menulis kode [tertutup]


105

Setelah membaca buku The Pragmatic Programmer , salah satu argumen yang saya temukan paling menarik adalah "tulis kode yang menulis kode".

Saya mencoba mencari di internet untuk penjelasan lebih lanjut atau artikel tentang itu, dan sementara saya menemukan beberapa artikel bagus tentang masalah ini, saya masih belum menemukan implementasi kode spesifik atau contoh yang baik.

Saya merasa itu masih bukan argumen yang begitu umum, sesuatu yang tidak memiliki dokumentasi atau tidak dianut oleh begitu banyak orang, dan saya ingin tahu lebih banyak tentang itu.

Apa pendapat Anda tentang subjek ini? Apakah ini sesuatu yang benar-benar akan meningkatkan produktivitas Anda? Apa sajakah sumber yang bagus tentang masalah ini, di antara buku, blog, tayangan slide, dll?


Beberapa contoh kode akan sangat dihargai untuk memungkinkan saya lebih memahami implementasinya.


Inilah halaman wiki tentang masalah ini dengan berbagai teknik pemrograman yang relevan, seperti Pemrograman Meta, Pemrograman Generatif, dan Pembuatan Kode.


32
Saya pernah menulis kode yang menulis kode yang menulis kode ... :)
Benjol

9
@ Benjol: Apakah Anda menulis dalam bahasa Lisp?
compman

11
Selain itu, bahasa sisi server melakukan ini sepanjang waktu dengan menghasilkan HTML, CSS, dan JavaScript. Anda bisa memiliki skrip sisi-server yang membuat skrip sisi-server yang membuat html dengan javascript yang membuat lebih banyak html, dan tidak ada yang akan mengetahuinya karena seberapa umum itu.
zzzzBov

8
Jika Anda belum melakukannya, lihat seri artikel IBM developerWorks ini: " Seni pemrograman " Bagian 1 , Bagian 2 , dan Bagian 3 .
John Tobler

3
AtomWeaver ( atomweaver.com ) adalah contoh pemrograman otomatis yang bagus: Pertama, Anda membuat program mini yang dapat digunakan kembali di Lua. Kemudian, Anda membuat model sistem Anda dengan menggunakan kembali aset ini. AtomWeaver kemudian membuat program Lua yang berisi "generator mini" Anda untuk menghasilkan kode sumber akhir sistem. Anda kemudian dapat mengubah model Anda dan menghasilkan kembali.
Rui Curado

Jawaban:


49

Di dunia Lisp, sangat umum untuk melihat kode yang menulis kode yang menulis kode (dan seterusnya). Jadi, setiap proyek Lisp atau Skema berukuran layak akan menjadi contoh kode yang baik. Saya akan merekomendasikan melihat sumber Racket compiler dan runtime, serta Bigloo , perpustakaan mereka hanya brilian.

Adapun produktivitas: Saya menggunakan metaprogramming sebagai teknik dominan di hampir semua pekerjaan pengembangan saya, dan itu jelas banyak membantu, baik mengurangi ukuran kode dan meningkatkan keterbacaannya. Kuncinya adalah dalam menggunakan Bahasa Khusus Domain , dan pemrograman program adalah salah satu cara paling efisien untuk mengimplementasikannya.


67

Saya lebih suka melangkah lebih jauh, dan, alih-alih menulis kode yang menulis kode, menulis kode yang menghasilkan objek, metode, fungsi. Ini dapat dicapai dengan Lisp macro atau kemampuan modifikasi program dinamis Ruby misalnya.

Perbedaan kecilnya adalah Anda tidak berakhir dengan file sumber yang dibuat secara otomatis. Biasanya file-file ini tidak dapat dibaca manusia dan tidak dapat dimodifikasi, jadi mengapa repot-repot dengan mereka. Saya tidak suka gagasan meningkatkan basis kode saya dengan sesuatu yang tidak dapat saya kendalikan.

Satu buku yang saya suka baca tentang topik itu adalah Metaprogramming Ruby (jika Anda tahu bahasa Ruby)


Edit setelah pertanyaan berikut dalam komentar:

Mengapa harus bermanfaat kalau saya masih harus kode kode menghasilkan? Haruskah saya menulis kode yang dapat menghasilkan hal-hal yang berbeda tergantung pada input pengguna, sehingga saya dapat menggunakannya kembali berulang kali?

Pertama, metaprogramming bukan tujuan, tetapi alat. Jangan gunakan metaprogramming karena "itu keren" atau "X mengatakan setiap pengembang harus menggunakannya".

Saya pikir salah satu alasan bagus untuk menggunakan metaprogramming adalah untuk menggeneralisasi beberapa pola umum (pola sebagai sesuatu yang berulang) yang telah Anda temukan dalam kode Anda dan bahwa tidak ada teknik pemrograman biasa lainnya (pewarisan, pola desain, dll.) Yang dapat dicapai.

Seperti yang dikatakan oleh Jordan , satu kasus penggunaan yang umum adalah penanganan basis data dan ORM (Object Relation Mapping). Sekali lagi, di Ruby, Anda harus melihat ActiveRecord yang merupakan contoh bagus dari program metaprogram yang diterapkan pada ORM.

Sebagai catatan akhir:

Jangan berpikir "Saya ingin menerapkan metaprogramming, di mana saya bisa menerapkannya dalam kode saya?".

Pikirkan "Saya melihat pola ini yang berulang di seluruh kode saya, saya tidak dapat menemukan cara untuk memperbaiki kode menjadi sesuatu yang lebih kecil dan lebih dapat digunakan kembali. Mungkin metaprogramming dapat membantu saya?"


3
@Jose: Paling umum Anda menghasilkan kode melalui template. Ada kecepatan apache (N-) misalnya atau template T4 studio visual. Kemudian Anda hanya memiliki program yang mengumpankan metadata ke template Anda dan membuat file baru dari itu. Ini cukup mudah dan saya melakukannya setiap saat untuk menghasilkan kerangka UI, Entitas, dll.
Falcon

2
@ Jose Faeti, perhatikan lebih dekat Lisp macro (atau Clojure, atau Nemerle, tergantung pada preferensi platform Anda).
SK-logic

1
Saya ingin menambahkan metaprogramming dapat menggantikan beberapa pola seperti kebijakan atau negara, tetapi tanpa biaya runtime. Ini tidak hanya untuk masalah yang tidak dapat dicapai dengan refactoring umum, tetapi juga kadang-kadang alternatif yang lebih baik.
deadalnix

1
@ Jose Faeti: Saya melihat Anda tahu beberapa Python. Ini juga memiliki kemampuan metaprogramming, meskipun saya belum benar-benar menggunakannya. Lihatlah Dangerously Advanced Python PDF
Kit

3
@ Falcon: IMO itu adalah cara terburuk untuk menghasilkan kode; ini sangat buruk untuk bahasa yang tidak memiliki fasilitas pemrograman meta bawaan. Alih-alih menghasilkan Java atau C #, akan lebih baik untuk menulis kode itu dalam bahasa JVM atau .NET tingkat yang lebih tinggi.
kevin cline

19

Lebih baik lagi, gunakan kode yang ditulis orang lain yang menulis kode Anda untuk Anda.

Otomatisasi kode umumnya baik untuk ORM dan kode interaksi basis data lainnya, dan tentu saja untuk pembuatan kode yang berulang tetapi serupa.

Tentu saja, jika Anda membangun banyak kelas yang mirip, mungkin Anda bisa menyelesaikan hal yang sama dalam bahasa yang dinamis lebih cepat, tapi saya ngelantur.

Ini dianut oleh banyak orang, meskipun Anda akan sering menemukan perangkat lunak yang berlabel pembuat kode.

Lihat perusahaan dan produk seperti CodeSmith dan MyGeneration, atau telusuri di artikel Wikipedia ini: http://en.wikipedia.org/wiki/Comparison_of_code_generation_tools


6
Itu tidak lebih baik. Kode kecil Anda yang sangat berharga itu tidak dapat dikelola dengan baik oleh alat pembuat kode cowok lain, karena cowok lain itu tidak tahu apa-apa tentang spesifikasi Anda. Penggunaan metaprogramming yang paling produktif adalah menerapkan bahasa khusus domain - dan, seperti namanya, mereka khusus untuk domain Anda yang sangat bermasalah, mereka tidak dapat diimplementasikan oleh orang lain selain Anda.
SK-logic

@ SK-logic: bagaimana dengan kode yang dihasilkan ORM? Itu dihasilkan oleh alat / perpustakaan lain dan masih memenuhi banyak kebutuhan proyek.
David

@ David, jujur ​​saja, saya tidak cukup yakin dengan ORM generik. Saya memiliki begitu banyak masalah dengan mereka di masa lalu, sering menggunakan untuk menerapkan ORM spesifik saya sendiri.
SK-logic

1
@ Jonord, semua alat itu terlalu spesifik (dan lebih buruk - berbasis teks , yaitu, lebih rendah dari desain). Saya berbicara tentang pemrograman yang tepat sebagai gantinya.
SK-logic

1
@AtillaOzgur, mereka bisa "sangat bagus", benar. Tapi mereka tidak lebih baik dari eDSL. Pembuatan kode mandiri jelas jauh lebih terbatas dan jauh lebih tidak fleksibel daripada pemrograman makro.
SK-logic

16

Salah satu contoh klasik adalah lex dan yacc. Tujuan utama mereka adalah menghindari pekerjaan menulis parser yang membosankan. Sepanjang jalan, mereka membuatnya jauh lebih cepat untuk membangun parser kompleks dengan banyak aturan dan negara, dan mereka juga menghindari semua kesalahan kejutan yang dilakukan oleh orang-orang yang menggulirkannya sendiri.

Ini juga ide di balik c, yang merupakan alat untuk menulis assembler. Hal yang sama berlaku untuk setiap bahasa tingkat tinggi yang ingin Anda beri nama. Untuk alat yang menulis kode untuk Anda, ada beberapa paradigma sederhana.

IDE yang tepat membantu dengan menyediakan dokumentasi di ujung jari Anda, penyelesaian otomatis pintar, dan cuplikan kode. IDE juga menyertakan berbagai templat, jadi Anda tidak harus memulai program dari awal. Ada beberapa program untuk mengambil diagram uml dan kelas kasar dalam bahasa tingkat tinggi.

Akhirnya, Anda bisa menulis alat sendiri untuk menghasilkan kode dalam set masalah Anda. Ini adalah bagaimana lex dan yacc pertama kali dimulai. Jenis bahasa tertentu domain ada untuk alasan ini. Anda membuat beberapa blok bangunan yang menggambarkan solusi Anda dalam kode yang lebih mudah dipahami, menyelesaikan kegiatan umum, atau bagian yang rumit dengan perintah sederhana. Anda tidak mencari solusi untuk setiap masalah, hanya definisi yang lebih mudah dari yang spesifik yang Anda hadapi.

Dalam arti tertentu, semua yang Anda lakukan di atas lapisan biner adalah otomatisasi kode.


Itu pemandangan yang sangat bagus. Semua dalam semua hanyalah salah satu dari banyak metode yang coba digunakan oleh pemrogram untuk memfasilitasi operasi mereka dan fokus pada tingkat pengkodean yang lebih tinggi, alih-alih rincian kode sintaks.
Jose Faeti

1
@ Jose Faeti Artikel wikipedia en.wikipedia.org/wiki/Automatic_programming memiliki tautan ke berbagai alat berbeda, jika Anda tertarik pada beberapa perincian lebih lanjut. Saya juga menyarankan membaca lex dan yacc, karena ada sedikit lebih banyak dokumentasi dan deskripsi untuk itu.
Spencer Rathbun

Dalam bahasa yang cukup kuat (misalnya C ++ sebagai lawan C), alat eksternal seperti lex dan yacc tidak diperlukan.
kevin cline

YACC tidak menulis "segala jenis parser". Ini menulis satu jenis pengurai spesifik (LALR) yang sangat sulit untuk mendapatkan yang benar tanpa bantuan otomatis. Ada jenis parser lain (keturunan rekursif) yang jauh lebih mudah untuk ditulis dan diperbaiki, dan karenanya lebih mudah untuk membaca dan memahami apa yang sedang terjadi.
Mason Wheeler

@MasonWheeler Jenis parser mengacu pada tata bahasa yang dapat dibuat untuk memecahkan masalah, dalam arti luas, tidak tepat. Membacanya setahun kemudian, tidak sejelas yang saya inginkan. Saya tidak yakin saya setuju dengan Anda tentang parser LL (*) yang lebih mudah untuk ditulis dan digunakan.
Spencer Rathbun

13

Metaprogramming

Metaprogramming adalah teknik kontroversial di banyak toko. Alasannya, seperti alat yang ampuh, besarnya bantuan atau luka sangat besar.

Pro

  • Lebih ekspresif, lebih sedikit kode untuk ditulis dan dipelihara (sering dengan urutan besarnya atau lebih)
  • Konsistensi, perilaku yang lebih konsisten di atas masalah yang Anda selesaikan dengan kode
  • Produktivitas, lebih sedikit kode untuk solusi ke ruang masalah yang lebih besar

Cons

  • Kompleksitas, ini bisa sangat rumit walaupun kodenya lebih sedikit
  • Keselamatan, kadang-kadang keselamatan jenis dan analisis statis pada umumnya akan dikorbankan
  • Bug Lebih Banyak Mempengaruhi, Kesalahan kecil akan berdampak lebih besar

Saya besar penggemar metaprogramming, tapi aku sudah melakukannya untuk waktu yang lama. Bagi saya tradeoff pengurangan ukuran kode dan perilaku yang konsisten lebih dari menebus risiko. Lebih sedikit kode berarti lebih sedikit bug, lebih sedikit kode untuk dipelihara, dan saya biasanya dapat menambahkan fungsionalitas besar dengan sangat cepat.

Namun, ini tidak berarti saya pikir semua programmer harus terlibat di dalamnya. Saya telah melihat dan harus memperbaiki masalah besar yang diciptakan oleh metaprogramming. Biasanya sejak saat orang yang tidak memahami konsep dan telah berusaha untuk memperluas fungsionalitas, atau hanya memperbaiki bug. Dibutuhkan pola pikir tertentu yang berorientasi paling detail. Pertanyaan untuk menggunakan teknik metaprogramming harus menjadi keputusan tim . Jika Anda memiliki anggota tim yang tidak mengerti, tidak memiliki temperamen untuk itu, atau hanya menentangnya tidak ada tim yang harus menggunakan metaprogramming.


Terima kasih atas pertimbangan yang bermanfaat! Bisakah Anda menyarankan saya tugas yang benar-benar sederhana dan dasar yang dapat saya terapkan dengan menggunakan metaprogramming, yang akan menghemat waktu saya dibandingkan pengkodean normal, contoh kode kecil?
Jose Faeti

haha membuat saya ingat kesalahan saya beberapa tahun yang lalu dengan GCC. 162 baris untuk meletakkan pesan kesalahan di layar saya. Pemrograman ulang rekursif FTW!
deadalnix

6
Kompleksitas metaprogramming sangat berlebihan. Sama sekali tidak ada yang rumit di dalamnya, selama Anda menggunakan alat yang tepat. Dan DSL jauh lebih mudah untuk di-debug dan dipelihara daripada kode boilerplate yang khas. Juga, saya tidak dapat mengerti mengapa seseorang harus mengorbankan keselamatan jenis - itu justru sebaliknya, DSL mungkin memiliki sistem tipe khusus domain, juga sangat efisien.
SK-logic

2
@ SK-logic: Tidak semua bahasa mendukung metaprogramming dengan baik. Jadi kadang-kadang hal-hal seperti keamanan jenis dikorbankan (mis. C) . Juga metaprogramming bukan hanya DSL. Ini termasuk hal-hal seperti pemrograman gaya pengiriman, generik, currying, inspeksi objek, aplikasi dinamis, dll. Adapun kompleksitas, saya pikir itu mudah bagi kita (orang-orang dengan pengalaman metaprogramming) untuk mengatakan itu tidak rumit. Saya telah melihat perjuangan lain dengan memahami semua kasus kode akan dieksekusi di bawah. Sebagian besar tergantung pada pengalaman mereka dan teknik yang terlibat.
dietbuddha

@ Dietbuddha, bisakah Anda menjelaskan, mengapa kita harus mengorbankan jenis keamanan DSL mereka sendiri, tidak peduli bagaimana itu diterapkan? Anda dapat menulis juru bahasa ad hoc dalam huruf C murni dengan sistem tipe yang kuat (lihat Pelukan misalnya). Anda dapat menulis kode yang menargetkan penargetan C yang melakukan semua pemeriksaan ketik itu sendiri, tidak bergantung pada sistem jenis bahasa target. Untuk kompleksitas: kebanyakan orang melakukannya dengan cara yang rumit dan tidak perlu, sedangkan semua metodologi desain yang sama dapat diterapkan pada pembuatan kode seperti pada pemrograman "normal". Hampir tidak diperlukan pengetahuan baru.
SK-logic

9

Sebagian besar kode menulis kode. Misalnya kode php membantu menulis html. Perpustakaan php pdo membantu menulis panggilan SQL. File I / O berfungsi menulis kode untuk berkomunikasi dengan OS. Bahkan panggilan fungsi biasa adalah referensi ke blok kode lain yang dijalankan. Jadi panggilan fungsi Anda menulis kode.

Dalam istilah yang luas, kita dapat menganggap komputasi sebagai kode penulisan yang menulis kode secara rekursif membentuk tumpukan yang berakhir ketika ia berhadapan dengan realitas fisik dari kode yang disambungkan ke perangkat keras.


3
Saya tidak akan menyebut html bahasa pemrograman. Ini adalah sintaksis untuk dokumen
Simon Bergot

3
@Simon itu poin yang menarik. Ada semua variasi kekuatan ekspresif untuk berbagai kode yang kami gunakan. Kode dapat menulis ke bahasa yang lebih lemah, bahasa yang lebih kuat, atau bahasanya sendiri.
Ben Haley

5

Bagaimana Anda melakukan ini bervariasi tergantung pada persyaratan Anda. Dengan asumsi Anda menggunakan pembuatan kode statis, Anda dapat menulis sendiri semua infrastruktur, atau Anda dapat menggunakan generator yang ada seperti CodeSmith atau MyGeneration. Dengan menggunakan ini, Anda hanya perlu menulis templat yang diperlukan.

Proyek terakhir saya yang melibatkan ini adalah beberapa layar dasar ASP.NET CRUD (pembuatan kode bagus untuk ini). Proses selanjutnya mendefinisikan entitas sebagai metadata dalam file xml. Tulis templat untuk mencakup berbagai artefak yang diperlukan (kelas entitas, repositori, kelas layanan, kontrol asp.net, halaman asp.net dll.). Jalankan proses generasi dan gaya output.

Ada beberapa overhead dalam menulis template tetapi mereka dapat digunakan kembali untuk proyek serupa berikutnya. Demikian pula perubahan pada data yang mendasarinya ditangani dengan mengubah metadata dan menjalankan kembali pembuatan yang membuat perubahan lebih sederhana dan lebih cepat untuk diterapkan.

Adapun pengujian. Karena ini adalah sistem templated, Anda perlu meluangkan waktu pada awalnya memvalidasi output dari proses, jika template Anda salah semua output dari template itu akan sama salah. Setelah Anda puas dengan ini, Anda juga dapat menggunakan generator kode untuk membuat tes dasar dari metadata xml yang kemudian dapat diperluas untuk mencakup kasus-kasus khusus. Namun ingat Anda mungkin masih perlu melakukan tes kode untuk memenuhi hal-hal tertentu, pembuatan kode mengurangi pekerjaan Anda, tidak menghilangkannya sama sekali.


5

Di perusahaan kami, kami menggunakan beberapa alat yang benar-benar menghasilkan kelas C ++ atau C # dengan data yang diunduh dari internet. Kelas-kelas ini adalah wadah data dan berisi sejumlah besar objek dalam daftar.


Sesuatu seperti cuplikan kode yang ditemukan di beberapa IDE seperti Visual Studio misalnya?
Jose Faeti

@Jose Alat kami hanyalah sebuah aplikasi untuk mengkonversi output HTML ke kelas. Jadi, alih-alih mengunduh data setiap kali aplikasi dimulai, kita unduh sekali dan buat kelas darinya.
Holli

5

Metaprogramming telah menjadi bagian dari pemrograman untuk waktu yang lama. Pertimbangkan tidak hanya alat seperti SWIG, atau desainer WYSIWYG, yang membuat kode, tetapi juga alat dalam bahasa seperti preprocessor C, atau bahkan templat C ++ dan generik C # / Java - belum lagi Refleksi.

Bahkan, Anda bisa berpendapat bahwa setiap kompiler hanyalah metaprogram lain - mereka mengambil teks program dan mesin output atau kode VM. Dan, hidup tanpa penyusun? Owch.


Itu benar, tetapi bagaimana Anda bisa benar-benar mengimplementasikannya dalam bahasa pemrograman Anda sendiri untuk benar-benar meningkatkan produktivitas Anda? Itu yang saya lewatkan.
Jose Faeti

5

Ini contoh nyata dari masa lalu saya.

Saya sedang bekerja di sebuah situs yang memiliki sekitar 50MB kode sumber Delphi menggunakan BDE untuk akses data. Mereka ingin beralih menggunakan Direct Oracle Access untuk memungkinkan pembaruan Oracle melewati versi tertinggi yang didukung oleh BDE (8i jika saya ingat dengan benar).

Jadi, alih-alih membuat tim coders untuk bekerja melalui setiap formulir dan modul data mengubah setiap komponen secara manual, saya menulis skrip PERL yang: -

  1. Parsing DFM (file formulir) dan identifikasi semua objek TQuery, TTable, TStoredProcedure & TDatabase - menyimpan item dalam daftar.

  2. Parsing PAS (kode) dan identifikasi penggunaan objek - apakah TQueries melakukan pembaruan atau memilih? Juga, itu mengidentifikasi objek yang dibuat dalam kode daripada jatuh ke formulir di IDE.

  3. Tulis ulang DFM & PAS yang mengubah tipe objek dengan tepat (mis. TTable -> TOracleDataSet dengan properti SQL diatur ke "select * from" dll) dan pemanggilan metode. Selain itu, panggilan metode tambahan ditambahkan jika sesuai untuk menutup, membuka & mengatur parameter.

Singkatnya, 3 minggu bekerja tweaker skrip untuk bekerja pada aplikasi yang berbeda yang ditulis oleh tim yang berbeda dengan gaya pengkodean yang berbeda, bukan perkiraan asli 5+ pengembang yang bekerja selama 6 bulan.

Dan alasan saya bahkan berpikir untuk menggunakan pendekatan itu adalah melalui membaca The Pragmatic Programmer


Itu hebat, saya sekarang menjadi Perl sejak beberapa hari dan saya sudah membuat beberapa alat produktivitas untuk menghasilkan ruang kerja dasar untuk pengembangan web, dengan semua direktori, file, dll dengan hanya mengetik "buat ruang kerja"! :)
Jose Faeti

1
@ Jose Itulah idenya. Gunakan bahasa scripting untuk mengotomatiskan hal-hal yang berulang. Ini bisa untuk sekali saja di mana Anda mendapatkan peningkatan produktivitas 8x atau seperti dalam kasus Anda sesuatu yang memakan waktu yang akan Anda lakukan lagi & lagi.
mcottle

4

Anda meminta contoh ....

Ketika bekerja dengan SQL, Anda seharusnya tidak mengubah database secara langsung, tetapi sebaliknya seharusnya mengeksekusi skrip yang membuat perubahan apa pun yang Anda inginkan, termasuk perubahan struktural ke database (menambahkan tabel, kolom, kunci utama, batasan, dan sebagainya) . Cukup sering Anda perlu melakukan tindakan yang sama terhadap banyak tabel atau kolom pada saat yang sama, dan melakukannya satu per satu akan membosankan, skrip pendek yang menghasilkan skrip yang lebih besar yang melakukan apa yang Anda inginkan dapat menjadi nyata penghemat waktu.

Misalnya, sebelum tipe data DATE diperkenalkan ke MS SQl Server, satu-satunya pilihan untuk kolom tanggal adalah DATETIME yang memiliki bagian waktu - bagian waktu yang membuat berurusan dengan data sedikit lebih sulit. Setelah memutakhirkan ke versi dengan tipe data tanggal, Anda mungkin ingin memperbarui kolom di mana waktu selalu 00:00. Dalam database dengan lusinan atau bahkan ratusan kolom DateTime ini akan cukup memakan waktu. Tetapi mudah untuk menulis skrip yang menanyakan semua tabel, memeriksa setiap kolom dengan tipe data DATETIME untuk melihat apakah waktunya sama dengan pukul 00:00 dan jika tidak membuat pernyataan ALTER untuk tabel / kolom untuk diubah tipe data ke DATE. Presto, kode yang menulis kode.


3

Lihatlah makro CL (Common Lips). Menurut saya itulah yang Anda inginkan. Bibir sempurna dalam metaprogramming.

Saya juga menyarankan Nemerle jika Anda ingin memiliki kekuatan .NET dengan dukungan Metaprogramming yang sempurna (termasuk makro)

Tetapi jika Anda ingin mesin pembuat kode yang benar lihatlah penghematan Apache


3

Saya hanya mengerjakan alat seperti itu. Dalam kasus khusus kami, kami menghasilkan kode VB.NET berdasarkan untuk Layer Data pada tanda tangan fungsi dalam database.

Mulai bekerja dan dengan pembuatan kode sulit pada awalnya karena Anda tidak tahu bagaimana kode harus dihasilkan, tetapi begitu Anda memiliki seperangkat aturan yang ditetapkan, dan kode yang harus dihasilkan selalu dapat dihasilkan berdasarkan aturan-aturan itu , bekerja dengan kode itu tidak terlalu sulit. Tentu saja, tergantung pada kerumitan pembuatan kode dan pada jumlah aturan, tugas bisa menjadi lebih sulit. Tetapi pada dasarnya, pembuatan kode otomatis digunakan untuk tugas pengkodean berulang dan bukan untuk kode lanjutan yang sangat bervariasi.

Menguji output ada dua. Pertama, Anda harus memastikan bahwa kode dikompilasi, dan itu mudah. Maka Anda harus memastikan bahwa output melakukan apa yang Anda maksudkan berdasarkan parameter yang dihasilkan .. dan kesulitannya bervariasi pada kompleksitas kode yang Anda hasilkan.

Rekomendasi tulus saya adalah bahwa jika Anda merasa seperti Anda menulis kode secara berulang , dan Anda dapat membayar waktu .. Cobalah untuk berpikir jika apa yang Anda lakukan tidak dapat dilakukan dengan kode yang dihasilkan. Dan jika demikian (jika itu kode berulang dari hampir selalu terjadi) pikirkan berapa kali Anda harus memperpanjang, sedikit modifikasi kode itu dan juga berapa kali Anda harus menulis kode yang tepat. Jika jawaban untuk semua ini adalah "banyak" maka Anda harus serius mempertimbangkan membuat generator untuk kode itu .

Semoga itu bisa membantu,
IPP


Terima kasih atas jawabannya! Bagaimana aturan dalam contoh Anda diterapkan sebenarnya?
Jose Faeti

1
Saya tidak bisa memberi tahu Anda semua peraturan tetapi saya bisa memberi Anda beberapa contoh. Kami mem-parsing antarmuka yang diekspos oleh database oracle dan kami mempertimbangkan tanda tangan fungsi-fungsi di antarmuka oracle. Berdasarkan tanda tangan kami menghasilkan nama fungsi lapisan data. kita tahu bahwa kita selalu mendapatkan dari tabel data orb sebagai hasil yang kita parse dan simpan ke dalam array tipe objek khusus yang kita gunakan untuk menyimpan data kita. juga, berdasarkan pada parameter input / output dari tanda tangan fungsi db, kami menambahkan parameter input dan output yang sesuai ke fungsi yang kami hasilkan dan seterusnya ..
Ioan Paul Pirau

3

Saya memiliki modul PHP yang menampilkan halaman web yang berisi kode JavaScript yang menghasilkan HTML. Itu tiga lapisan di sana. Bocah itu susah dibaca!

Di kelas pemrograman, kami harus menulis sebuah program yang akan mengambil string rumus dari pengguna dan menguraikannya dan menampilkan nilai. Pemecah yang paling mengesankan hanya mengambil input pengguna, membungkusnya dengan main () {printf ("% d", ...);} dan menjalankan skrip untuk mengkompilasi, menautkan, dan menjalankannya. Dia tidak menulis parser! Hari ini Anda bisa melakukannya dalam pernyataan SQL SELECT.

Ini adalah alat yang harus Anda mainkan, kemudian simpan untuk beberapa hari di masa depan ketika itu akan berguna.


Itu sebenarnya hal yang sama yang saya coba terapkan! :) Tapi kemudian saya memutuskan untuk membuat kode dengan Perl offline dan ini berfungsi dengan baik. Saya memiliki banyak fitur yang saya pikir akan ditambahkan!
Jose Faeti

Saya menulis kode dengan hingga 20 lapisan transformasi bahasa ke bahasa, tanpa masalah sama sekali. Ini tidak lebih rumit daripada memiliki kedalaman tumpukan panggilan 20 lapisan. Jadi saya sangat tidak setuju bahwa ini adalah alat untuk " menyimpannya untuk beberapa hari di masa depan ketika akan berguna " - pembuatan kode selalu berguna.
SK-logic

3

Saya telah mengembangkan solusi meta-programming yang rapi dengan Prolog . Di mana aplikasi utama (dalam C ++ say) menerjemahkan definisi abstrak dari masalah ke dalam aplikasi Prolog saat runtime, yang kemudian didelegasikan ke. Seringkali menulis fungsionalitas yang setara dalam C ++ akan berlangsung selamanya.

Saya pikir skenario ini adalah kasus yang sangat baik dalam mendukung argumen penulisan kode-kode .


3

Apa pendapat Anda tentang subjek ini?

Metaprogramming umumnya dikaitkan dengan bahasa non-dinamis, karena ada waktu yang sulit dalam mencapai perilaku tertentu (seperti menerapkan ORM) tanpa banyak baris kode yang tidak produktif dan tidak cerdas.

Tetapi bahkan dalam bahasa yang lebih dinamis seperti PHP, pembuatan kode dapat benar-benar menyelamatkan hidup dan meningkatkan produktivitas dalam jumlah besar. Dalam kerangka kerja modern, sangat umum untuk memiliki perancah yang menghasilkan sebagian besar model, bentuk, pengujian, dan tindakan umum untuk objek bisnis tertentu yang Anda nyatakan. Ini adalah salah satu alasan mengapa kerangka kerja seperti symfony atau RoR begitu sukses, alat-alat penghasil kode membuat kode yang konsisten dengan sangat cepat dan meningkatkan produktivitas pemrogram.

Di situs web, sebagian besar interaksi berkisar pada empat tindakan utama:

  • Buat elemen
  • Ambil satu set elemen (dengan kemungkinan pemfilteran)
  • Perbarui elemen dengan atribut baru
  • Hapus satu set elemen

Setidaknya semua yang berputar di sekitar ini 4 tindakan utama bisa dan IMHO HARUS dicapai menggunakan alat generasi kode untuk mencapai produktivitas maksimum.

Di perusahaan saya, kami menggunakan symfony, dan generator-adminnya adalah alat yang luar biasa, yang bahkan menghasilkan kode dalam run-time (dan menyimpannya), yang berarti kami bahkan tidak perlu menggunakan jenis tugas atau alat eksternal untuk menghasilkan kode baru, kita hanya perlu membersihkan cache kita. Saya SANGAT menyarankan untuk menggunakan alat semacam ini untuk operasi CRUD.

Tapi, melakukan apa yang kontributor hebat symfony lakukan, bukanlah tugas yang mudah. Saya sendiri telah mengimplementasikan beberapa tugas pembuatan kode dan melakukan sesuatu yang benar-benar konsisten dan dengan implementasi luas untuk mencakup sebagian besar kasus sudut tidak mudah.

Apakah ini sesuatu yang benar-benar akan meningkatkan produktivitas Anda?

Saya percaya bahwa metaprogramming sangat sangat penting dalam pekerjaan tingkat rendah (kerangka kerja, caching, kompiler, dll.) Tetapi sesuatu yang harus kita dekati dengan sangat hati-hati jika kita melakukan sesuatu pada lapisan bisnis.

Menggunakan generasi kode tanpa pertanyaan merupakan pendorong produktivitas utama. Menerapkan alat penghasil kode Anda sendiri, tidak terlalu banyak kecuali Anda membuat kerangka kerja sendiri.

Apa sajakah sumber yang bagus tentang masalah ini, di antara buku, blog, tayangan slide, dll?

Sumber daya terbaik untuk memahami pemrograman selalu baik dan kode sumber berkomentar dengan baik. Saya akan mengatakan bahwa melihat generator admin RubyOnRails dan Symfony adalah ide yang bagus.


3

Sementara banyak jawaban di sini merujuk pada apa yang umumnya dikenal sebagai pemrograman meta, sebenarnya ada bidang yang terkait dengan AI yang dikenal sebagai pemrograman otomatis yang membahas tentang pemahaman program atau program sintesis [1].

Setiap kompiler (atau program-meta, pembuat kode, penerjemah, sistem makro, ...) bekerja dengan transformasi, menghasilkan output dari input dengan melakukan algoritma transformasi tetap. Tetapi compiler atau meta-program tradisional tidak, dengan memberikan definisi, deskripsi atau contoh dari pengurutan suatu daftar (mis. [5, 3, 9] => [3,5,9]), membuat algoritma pengurutan. Masalah seperti itu di mana kepentingan bidang "pemrograman otomatis" ini.

[1] - Laporan kemajuan sistem pemahaman program ftp://db.stanford.edu/pub/cstr/reports/cs/.../CS-TR-74-444.pdfShare


2

Pemrograman meta bisa sangat sulit untuk dipertahankan. Pada awalnya terlihat elegan, tetapi ketika Anda mulai berlari ke dalam kasus sudut, kesalahan ditemukan terlambat (pada kode yang telah dihasilkan), dan semuanya menjadi mimpi buruk untuk digunakan / debug.

Saya terutama menulis kode python, dan dalam pengalaman saya pemrograman meta selalu merupakan pilihan yang buruk dengan bahasa ini. Anda selalu dapat memperbaiki hal-hal untuk melakukannya dengan fitur bahasa normal yang membosankan. Hasilnya tidak terlalu funky, tetapi lebih mudah dijalani.


segala jenis kode bisa sangat sulit dipertahankan. Dan bisa sangat mudah jika dilakukan dengan cara yang benar. Metaprogramming dapat meningkatkan rawatan dalam urutan besarnya sebenarnya. Pengalaman python Anda, sepertinya, tidak relevan dengan pemrograman yang sebenarnya, karena Python tidak terlalu cocok untuk cara berpikir seperti ini, dengan AST yang kikuk terlalu dalam. Tetapi bahkan dengan Python, saya menggunakan perpustakaan Tempita dengan efisiensi tinggi, dan tidak pernah memiliki masalah perawatan, bahkan dengan tim yang hampir tidak memiliki pengalaman Python sebelumnya.
SK-logic

Saya tertarik pada poin Anda tentang python AST. Sudahkah Anda menggunakan tempita untuk tujuan pemrograman meta?
Simon Bergot

ini ( docs.python.org/library/ast.html ) cukup AST ad hoc, dan parser memberikan pohon overbloated yang tidak dioptimalkan, yang membuat analisis bermasalah (terutama dengan kurangnya pencocokan pola yang tepat dengan Python). Menghasilkan AST seperti itu juga tidak nyaman. Saya menggunakan tempita untuk menghasilkan kode Python dan C (yaitu, pemrograman berbasis teks murni), itu berfungsi dengan baik untuk tugas tertentu (pembuatan kode boilerplate). Saya juga sering menggunakan Python untuk menghasilkan kode C dari beberapa deskripsi tingkat tinggi XML.
SK-logic

2

OP meminta sumber daya.

Anda mungkin menemukan Perangkat Rekayasa Perangkat Lunak DMS kami menarik. Ini adalah alat metaprogramming murni, yang dimaksudkan untuk membiarkan orang membangun analisis program kustom dan alat transformasi.

[Untuk mengikuti komentar pada pertanyaan OP, ketika digunakan untuk membangun alat transformasi tertentu, DMS adalah lini produk yang menulis kode, yang menulis kode:]

DMS mencapai ini dengan menjadi agnostik (tetapi tidak independen) dari bahasa pemrograman target. DMS menyediakan layanan standar yang dibutuhkan oleh beragam tugas metaprogramming, seperti halnya OS menyediakan beragam layanan untuk tugas pemrograman standar. Layanan ini termasuk penguraian yang kuat, konstruksi otomatis pohon sintaksis abstact, pencocokan pola dan penulisan ulang pada pohon, perpustakaan tabel simbol yang dengan mudah mengelola langauges dengan aturan pelingkupan yang buruk seperti beberapa pewarisan, aliran kontrol, aliran data, aliran data, poin-to dan panggilan analisis grafik. Tidak satu pun dari hal ini yang berarti karena tidak ada bahasa khusus untuk diproses, sehingga DMS menerima definisi bahasa yang terkait dengan bagian-bagian mesin yang umum ini, menghasilkan penguraian khusus bahasa, konstruksi AST, pencocokan / penulisan ulang pola bahasa spesifik menggunakan target- sintaks bahasa,

Dan seperti OS, DMS dirancang untuk memiliki sangat sedikit pendapat atau kendala pada program (meta) apa yang ingin Anda tulis, yang berarti dapat digunakan untuk berbagai tujuan: mengekstraksi metrik, menemukan kode mati, menerapkan aspek penenun, menerjemahkan bahasa, menghasilkan kode dari DSL, menyusun ulang aplikasi besar. (DMS sudah digunakan untuk semua tugas ini).

Seseorang membutuhkan definisi bahasa yang kuat jika Anda tidak ingin menghabiskan waktu untuk mengkodekan semua yang ada di manual referensi langauge (pikirkan apa artinya ini untuk Java dan C ++). DMS memecahkan masalah ini dengan memiliki perpustakaan definisi bahasa lengkap yang tersedia. Analog di sini agak seperti memiliki avaialbe database untuk OS Anda; Anda tidak harus mengimplementasikan salah satu dari mereka untuk melanjutkan dengan menulis aplikasi berbasis database Anda.


2

Lihat kumpulan masalah 4 dari Philip Greenspun dari MIT course 6.916: Rekayasa Perangkat Lunak dari Layanan Web Inovatif ( http://philip.greenspun.com/teaching/psets/ps4/ps4.adp ).

Tujuannya mengatakan, "Ajari siswa kebajikan metadata. Lebih khusus lagi, mereka belajar bagaimana secara formal mewakili persyaratan layanan Web dan kemudian membangun program komputer untuk menghasilkan program komputer yang mengimplementasikan layanan itu."

Ini adalah salah satu masalah yang ditetapkan calon ArsDigita ( http://en.wikipedia.org/wiki/ArsDigita ) yang harus diselesaikan oleh karyawan selama gelembung pertama.

"SQL untuk Web Nerds" buku referensi Philip di pset telah dipindahkan ke ( http://philip.greenspun.com/sql/ ).


2

Pada atau sekitar tahun 2001 saya mulai mengerjakan proyek yang banyak menggunakan objek bisnis dan objek data. Saya akan membangun situs web front-end, tetapi digantung memutar-mutar ibu jari saya karena lapisan bisnis dan lapisan akses data tidak sepenuhnya dikembangkan. Setelah beberapa minggu, saya mulai melihat dengan cermat apa yang dilakukan lapisan-lapisan itu. Pada dasarnya, mereka mengekspos data yang dikembalikan dari prosedur tersimpan sebagai koleksi objek dengan properti yang sesuai dengan bidang dalam data, atau mengambil parameter input dan mengirimkannya ke prosedur tersimpan untuk disimpan ke tabel database. Ada banyak serialisasi / deserialisasi yang terjadi di antara dua lapisan, ada Microsoft Transaction Server yang terlibat, perpustakaan tipe IDL / ODL ... tetapi semuanya sesuai dengan pola.

2 minggu kemudian, saya berhasil membuat generator kode yang akan membuang IDL / ODL, dan juga akan membuang objek bisnis dan data. Butuh orang membangun bisnis dan lapisan data objek 2 tahun untuk sampai pada titik debugging dan menguji benda-benda ini. Dalam 2 minggu, dengan pembuatan kode, kami memiliki output yang sama, tetapi karena semuanya dihasilkan, bug-nya cukup bagus.

Pembuat kode itu (alat KASUS tingkat rendah) mengikuti saya berkeliling melalui banyak iterasi yang berbeda, selama sekitar 8 hingga 10 tahun, karena prinsipnya sangat sederhana: Anda melakukan sesuatu yang perlu dilakukan ketika berbicara dengan basis data, cukup banyak kode berulang, dan sekali Anda melakukannya dengan benar, Anda tidak perlu khawatir lagi.

Jadi, ya: gunakan generator kode, terutama ketika pengkodeannya berulang dan cocok dengan pola yang jelas.

Saya tahu orang-orang menggunakan makro RegX untuk melakukan hal serupa, atau menggunakan rumus Excel untuk melakukan hal serupa (saya juga melakukan ini).


2

Contoh pemrograman metap

Saya memiliki perpustakaan otorisasi Ruby yang disebut Otoritas . Ini memungkinkan pengembang mengajukan pertanyaan di aplikasi mereka dengan metode seperti current_user.can_read?(@post)dan @post.readable_by?(current_user). Pertanyaan-pertanyaan ini dijawab oleh kelas otorisasi terpusat.

Ini adalah bagian penting: Otoritas tidak tahu metode mana yang harus didefinisikan sampai ia melihat konfigurasi pengguna . Konfigurasi pengguna mungkin berisi:

config.abilities =  {
  ...
  :read      => 'readable',
  :microwave => 'microwavable',  # user-defined
  ...
}

Dalam hal ini, perlu ada metode seperti current_user.can_microwave?(@post).

Metaprogramming memungkinkan ini: setelah membaca konfigurasi, saya tahu metode mana yang harus didefinisikan :

Authority.verbs.each do |verb|
  class_eval <<-RUBY, __FILE__, __LINE__ + 1 # allows for a nice bracktrace
    def can_#{verb}?(resource)
      resource.#{Authority.abilities[verb]}_by?(self)
    end
  RUBY
end
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.