Otomatik programlama: [kapalı] kodunu yazan kod yazın


105

Kitabı okuduktan sonra , en ilginç bulduğum argümanlardan biri olan Pragmatik Programcı “kod yazan kod yaz” dı.

Net hakkında daha fazla açıklama veya makale araştırmaya çalıştım ve konuyla ilgili bazı iyi makaleler bulurken, henüz belirli bir kod uygulaması veya iyi örnek bulamadım.

Hala çok yaygın bir argüman olmadığını, belgelerin bulunmadığını veya pek çok insan tarafından benimsenmediğini düşünüyorum ve bu konuda daha fazla bilgi edinmek istiyorum.

Konu hakkında ne düşünüyorsunuz? Verimliliğinizi gerçekten artıracak bir şey mi? Konuyla ilgili, kitaplar, bloglar, slayt gösterileri vb. Gibi iyi kaynaklar nelerdir?


Bazı kod örnekleri, uygulanmasını daha iyi anlayabilmem için çok takdir edilecektir.


İşte wiki sayfası Meta Programlama, Üretken Programlama ve Kod Üretimi gibi çeşitli alakalı programlama teknikleri ile konuyla ilgili.


32
Bir keresinde kod yazan kod yazan bir kod yazdım ... :)
Benjol

9
@ Benjol: Lisp'te yazıyor muydunuz?
compman

11
Ek olarak, sunucu tarafı diller bunu her zaman HTML, CSS ve JavaScript oluşturarak yapar. Daha fazla html oluşturan javascript ile html oluşturan bir sunucu tarafı komut dosyası oluşturan bir sunucu tarafı komut dosyasına sahip olabilirsiniz ve hiç kimse ne kadar yaygın olduğu için bu konuya göz atamaz .
zzzzBov

8
Henüz yapmadıysanız, şu IBM developerWorks makale serisini inceleyin: " Metaprogramlama sanatı " Bölüm 1 , Bölüm 2 ve Bölüm 3 .
John Tobler

3
AtomWeaver ( atomweaver.com ) otomatik programlamaya iyi bir örnektir: İlk olarak, Lua'da yeniden kullanılabilir mini programlar yaratırsınız. Ardından, sisteminizi bu varlıkları yeniden kullanarak modelleyin. Daha sonra AtomWeaver, sistemin nihai kaynak kodunu oluşturmak için "mini-jeneratörlerinizi" içeren bir Lua programını örüyor. Daha sonra modelinizi değiştirebilir ve yeniden oluşturabilirsiniz.
Rui Curado

Yanıtlar:


49

Lisp dünyasında, kod yazan kodu yazan kodun görülmesi oldukça yaygındır (vb.). Bu nedenle, terbiyeli boyutta herhangi bir Lisp veya Scheme projesi iyi bir kod örneği olacaktır. Racket derleyicisine ve çalışma zamanı kaynaklarına ve ayrıca Bigloo'ya kitaplıklarına göz atmanızı tavsiye ederim .

Verimlilik gelince: Metaprogramming'i neredeyse tüm geliştirme çalışmalarımda baskın bir teknik olarak kullanıyorum ve hem kod boyutunu azaltmak hem de okunabilirliğini artırmak için çok yardımcı oluyor. Anahtar Etki Alanına Özel Dilleri kullanmakta ve metaprogramlama bunları uygulamanın en etkili yollarından biridir.


67

Biraz daha ileri gitmeyi ve kod yazan kod yerine nesneler, yöntemler, işlevler üreten kod yazmayı tercih ederim . Bu, örneğin Lisp makroları veya Ruby dinamik program değiştirme yetenekleriyle sağlanabilir.

Küçük fark, otomatik olarak oluşturulan kaynak dosyalarla bitmemenizdir. Genellikle bu dosyalar insan tarafından okunamaz ve değiştirilemez, bu nedenle neden bunlarla uğraşmıyorsunuz? Kod tabanımı kontrol edemediğim bir şeyle geliştirme fikrini sevmiyorum.

Konuyla ilgili okumaktan zevk aldığım bir kitap Metaprogramming Ruby idi (Ruby dilini biliyorsanız)


Yorumda şu sorudan sonra düzenleme yapın:

Neden üreten kodu kodlamam gerektiğine yardımcı olmalı Tekrar tekrar kullanabilmem için kullanıcı girişine bağlı olarak farklı şeyler üretebilecek bir kod yazmalı mıyım?

İlk olarak, metaprogramlama bir amaç değil bir araçtır. Metaprogramming kullanmayın çünkü "cool" veya "X her geliştiricinin kullanması gerektiğini söyledi".

Metaprogramlamayı kullanmak için iyi bir neden, kodunuzda bulduğunuz ve başka hiçbir genel programlama tekniğinin (kalıtım, tasarım desenleri, vb.) Elde edemediği bazı genel kalıpları (tekrar eden bir şey olarak desen) genelleştirmek olduğunu düşünüyorum.

Ürdün'ün dediği gibi , tipik bir kullanım örneği veritabanı kullanımı ve ORM'dir (Nesne İlişkisi Haritalaması). Bir kez daha Ruby'de ORM'ye uygulanan metaprogramlamanın harika bir örneği olan ActiveRecord'a bakmalısınız .

Son not olarak:

"Metaprogramming uygulamak istiyorum, kodumda nerede uygulayabilirim?" Diye düşünmeyin .

Düşün "Ben bütün kodun üzerine tekrarlıyor bu modeli bakın ben. Küçük ve daha yeniden kullanılabilir bir hale kodunu refactor için bir yol bulamıyorum Belki metaprogramming bana yardımcı olabilir?"


3
@Jose: En sık şablonlar aracılığıyla kod oluşturursunuz. Örneğin apache (N-) hızı veya görsel T4 şablonları. Sonra meta verilerini şablonlarınıza besleyen ve bundan sonra yeni dosyalar oluşturan bir programınız olur. Oldukça kolay ve her zaman UI-iskeletleri, Varlıklar vs. oluşturmak için yapıyorum
Falcon

2
@Jose Faeti, Lisp makrolarına (ya da platform tercihlerinize bağlı olarak Clojure ya da Nemerle'ye) yakından bakın.
SK-mantığı

1
Metaprogramming’in, politika ya da durum gibi bazı kalıpların yerine geçebileceğini, ancak çalışma zamanının hiçbir maliyeti olmadığını söyleyebilirim. Bu sadece genel yeniden yapılanma ile elde edilemeyen problemler için değil, bazen daha iyi bir alternatif için de geçerlidir.
deadalnix

1
@Jose Faeti: Bir Python tanıdığını biliyorum. Aynı zamanda metaprogramlama yeteneklerine de sahip, ancak bunları gerçekten kullanmadım. Bir göz atın Tehlikeli Gelişmiş Python PDF
Kit

3
@Falcon: IMO, kod oluşturmanın en kötü yoludur; Yerleşik meta programlama özelliği olmayan diller için oldukça zahmetli bir iş. Java veya C # oluşturmak yerine, bu kodu daha yüksek bir JVM veya .NET dilinde yazmak daha iyi olur.
kevin cline

19

Daha da iyisi, kodunuzu sizin için yazan başka birinin yazdığı kodu kullanın.

Kod otomasyonu genellikle ORM'ler ve diğer veritabanı etkileşim kodları için ve tabii ki tekrarlayan fakat benzer kod oluşturma için iyidir.

Tabii ki, çok sayıda benzer görünümlü sınıf oluşturuyorsanız, belki de aynı şeyi dinamik bir dilde daha önce başardınız, ama ben dalıyorum.

Bu, birçok kişi tarafından benimsenir, ancak çoğu zaman kod üreteci olarak etiketlenmiş yazılımı bulacaksınız.

CodeSmith ve MyGeneration gibi şirketleri ve ürünleri görün veya bu Wikipedia makalesine göz atın: http://en.wikipedia.org/wiki/Comparison_of_code_generation_tools


6
Daha iyi değil. Değerli küçük çok çok kendi kodunuz, başka bir kodun kod üretme aracı tarafından doğru şekilde yönetilemez, çünkü diğer kod, sizin özellikleriniz hakkında hiçbir şey bilmez. Meta programlamanın en verimli kullanımı, alana özgü dilleri uygulamaktır - ve adından da anlaşılacağı gibi, sizin sorun alanınıza özgüdürler, sizden başkası tarafından uygulanamazlar.
SK-mantık

@ SK-mantık: ORM tarafından üretilen kod ne olacak? Başka bir araç / kütüphane tarafından üretilir ve hala birçok proje ihtiyacını karşılar.
David

@David, dürüst olmak gerekirse, genel ORM'lerle tam olarak ikna olmadım. Geçmişte onlarla çok fazla sorun yaşadım, sık sık kendi küçük ORM'lerimi uygulamaya koyuldum.
SK-mantığı

1
@Jordan, tüm bu araçlar çok spesifik (ve daha da kötüsü - metin tabanlı, yani tasarımdan daha düşük). Bunun yerine uygun metaprogramlamadan bahsediyorum.
SK-mantık

1
@AtillaOzgur, onlar "çok iyi" olabilir, doğru. Ama onlar eDSL'lerden daha iyi değiller. Bağımsız kod üretimi açıkça makro meta programlamaya göre çok daha sınırlıdır ve çok daha az esnektir.
SK-mantığı

16

Klasik örneklerden biri lex ve yacc. Öncelikli amacı, herhangi bir ayrıştırıcı yazmanın zorluğundan kaçınmaktır. Yol boyunca, birçok kural ve devlete sahip karmaşık parserler oluşturmayı çok daha hızlı hale getiriyorlar ve aynı zamanda insanların kendi yuvarladıkları sürpriz hatalardan kaçınıyorlar.

Bu ayrıca c'nin ardındaki fikirdür, ki bu durumda assembler yazmak için bir araçtır. Aynı şey, isimlendirmek istediğin herhangi bir üst seviye dil için de geçerli. Sizin için kod yazan araçlar için, birkaç basit paradigma vardır.

Doğru bir IDE parmaklarınızın ucunda belgeler, akıllı otomatik tamamlama ve kod parçacıkları sağlayarak yardımcı olur. IDE'ler ayrıca çeşitli şablonlar da içerdiğinden, bir programı sıfırdan başlatmanız gerekmez. Bir uml diyagramı ve kabadayı sınıfları yüksek seviyede bir dilde almak için programlar var.

Son olarak, problem setinize kod oluşturma için kendi araçlarınızı yazabilirsiniz. Lex ve yacc ilk olarak böyle başladı. Herhangi bir etki alanına özgü dil dili tam da bu nedenle var. Çözümünüzü kodu daha kolay anlaşılması, ortak etkinlikleri tamamlaması veya basit komutları içeren karmaşık bölümleri anlamasıyla açıklayan bazı yapı taşları oluşturursunuz. Her soruna bir çözüm aramıyorsunuz , uğraştığınız belirli bir tanımın sadece kolay bir tanımı.

Bir anlamda, ikili katman üzerinde yaptığınız her şey kod otomasyonu.


Bu gerçekten çok hoş bir manzara. Sonuçta, programcılar işlemlerini kolaylaştırmak için kullanmaya çalıştıkları ve sözdizimi kodu ayrıntıları yerine daha yüksek bir kodlama seviyesine odaklanan birçok yöntemden sadece bir tanesidir.
Jose Faeti

1
@Jose Faeti wikipedia makalesi en.wikipedia.org/wiki/Automatic_programming , daha fazla ayrıntıya ilgi duyarsa , çeşitli farklı araçlara bağlantılar sunar. Ayrıca biraz daha fazla dokümantasyon ve açıklama olduğu için lex ve yacc hakkında okuma yapmanızı öneririm.
Spencer Rathbun

Yeterince güçlü dillerde (örneğin C yerine C ++), lex ve yacc gibi harici araçlar gerekli değildir.
kevin cline

YACC "her türlü ayrıştırıcı" yazmıyor. Otomatik yardım almadan doğru elde etmek çok zor olan belirli bir tür ayrıştırıcı (LALR) yazıyor. Yazması ve düzeltilmesi daha kolay olan ve buna bağlı olarak neler olup bittiğini okumak ve anlamak daha kolay olan başka bir ayrıştırıcı türü (özyinelemeli iniş) vardır.
Mason Wheeler,

@MasonWheeler Ayrıştırıcı türü, problemlerin çözümü için geniş ve kesin olmayan bir şekilde oluşturulabilecek gramerlere atıfta bulunuyordu. Bir yıl sonra okudum, istediğim kadar net değildi. LL (*) ayrıştırıcıları üzerinde sizinle aynı fikirde olduğumdan emin değilim, ancak yazmak ve kullanmak daha kolay.
Spencer Rathbun

13

metaprogramming

Metaprogramming birçok mağazada tartışmalı bir tekniktir. Bunun nedeni, güçlü bir araç gibi, yardımın veya incinmenin büyüklüğüdür.

Artıları

  • Daha Etkileyici, yazmak ve sürdürmek için daha az kod
  • Tutarlılık, kodla çözdüğünüz sorun sınıfı üzerinde daha tutarlı davranış
  • Verimlilik, daha büyük sorunlu alanların çözümü için daha az kod

Eksileri

  • Karmaşıklık, daha az kod olsa bile çok karmaşık olabilir
  • Güvenlik, genel olarak bazen emniyet tipi ve statik analizler feda edilecek
  • Hatalar Daha Çok Etkiler, Küçük hataların daha büyük etkisi olur

Çok büyük bir metaprogramming hayranıyım ama bunu uzun zamandır yapıyorum. Bana göre, azaltılmış kod büyüklüğü ve tutarlı davranışın değişmesi riskleri telafi etmekten daha fazla. Daha az kod, daha az hata, daha az kod korumak anlamına gelir ve genellikle çok hızlı bir şekilde büyük işlevsellik parçaları ekleyebilirim.

Ancak bu, tüm programcıların buna katılması gerektiğini düşündüğüm anlamına gelmiyor. Metaprogramming tarafından yaratılan büyük sorunları gördüm ve çözdüm. Genellikle kavramı anlamayan ve işlevselliği genişletmeye çalışan veya sadece bir hatayı gideren kişilerden. En az ayrıntıya odaklanmış belirli bir zihin kümesi gerektirir. Metaprogramlama tekniklerini kullanma sorusu bir takım kararı olmalıdır . Eğer anlamayan takım üyeleriniz varsa, bunun için mizacınız yok veya tam olarak buna karşıysanız, hiçbir takım metaprogramlama kullanmamalı.


Yararlı düşünceleriniz için teşekkürler! Bana biraz basit bir örnek olarak normal kodlamada zaman kazandıracak metaprogramming kullanarak uygulayabileceğim gerçekten basit ve basit bir görev önerebilir misiniz?
Jose Faeti

haha, birkaç yıl önce GCC’de yaşadığım bir hatayı hatırlattı. Ekrana hata mesajı koymak için 162 satır. Özyinelemeli metaprogramming FTW!
deadalnix

6
Metaprogramlamanın karmaşıklığı oldukça abartılmıştır. Doğru araçları kullandığınız sürece kesinlikle hiçbir şey karmaşık değildir. DSL'lerin hata ayıklaması ve bakımı, tipik boyler kodundan daha kolaydır. Ayrıca, neden bir tür güvenliği feda etmek gerektiğini anlamıyorum - bu tam tersidir, DSL'ler etki alanına özgü, yüksek verimli tipte sistemlere de sahip olabilir.
SK-mantığı

2
@ SK-mantık: Bütün diller metaprogramlamayı iyi desteklememektedir. Bu yüzden bazen tür güvenliği gibi şeyler feda edilir (yani C) . Ayrıca metaprogramlama sadece DSL'ler değildir. Gönderme stilinde programlama, jenerikler, kurutma, nesne incelemesi, dinamik uygulama vb. Gibi şeyleri içerir. Karmaşıklık konusunda, karmaşık olmadığını söylemek bizim için (metaprogramlama deneyimine sahip kişiler) kolay olduğunu düşünüyorum. Kodun altında yürütülecek bütün davaları anlamak için başka bir mücadele gördüm. Çoğunlukla deneyimlerine ve ilgili tekniğe bağlıdır.
dietbuddha

@dietbuddha, lütfen biraz daha detaylandırabilir misiniz, nasıl uygulanırsa yapılsın neden biri kendi DSL'lerinin tip güvenliğini feda etsin? Özel bir yorumlayıcıyı güçlü bir C tipi sistem ile saf bir C'ye yazabilirsiniz (örneğin, Hugs'a bakınız). Hedef dil tipi sistemine dayanarak, tüm daktilo kontrolünü yapan C hedefli bir kod oluşturucu yazabilirsiniz. Karmaşıklık için: çoğu insan gereksiz yere karmaşık bir şekilde yapıyor, oysa tüm tasarım metodolojileri "normal" programlamada olduğu gibi kod üretmeye uygulanabilir. Neredeyse yeni bilgi gerekmez.
SK-mantık

9

Çoğu kod kod yazar. Örneğin php kodu html yazmanıza yardımcı olur. Php pdo kütüphanesi, SQL çağrıları yazmaya yardımcı olur. G / Ç dosyası, işletim sistemi ile iletişim kurmak için kod yazar. Düzenli bir işlev çağrısı bile, yürütülen başka bir kod bloğuna referanstır. Yani fonksiyon çağrılarınız kod yazıyor.

Geniş anlamda, hesaplamayı, donanımın içine bağlanan kodların fiziksel gerçekliğine karşı bittiğinde durdurulan bir istif oluşturan kodları tekrarlayan yazacak kodlar olarak düşünebiliriz.


3
Html'ye bir programlama dili demem. Bu belgeler için bir sözdizimidir
Simon Bergot

3
@Simon ilginç bir nokta. Kullandığımız farklı kodlar için çok çeşitli ifade gücü vardır. Kod daha zayıf bir dile, daha güçlü bir dile veya kendi diline yazabilir.
Ben Haley

5

Bunu nasıl yaptığınız, gereksinimlerinize bağlı olarak değişir. Statik kod oluşturma kullanıyorsanız, tüm altyapıyı kendiniz yazabilir veya CodeSmith veya MyGeneration gibi mevcut bir jeneratör kullanabilirsiniz. Bunları kullanarak sadece gerekli şablonları yazmanız gerekir.

Bunu içeren son projem, bazı temel ASP.NET CRUD ekranlarıydı (kod üretimi bunun için iyidir). İşlem, varlıkları xml dosyalarında meta veriler olarak tanımladı. Gerekli olan çeşitli eserleri (şablon sınıfları, depoları, servis sınıfları, asp.net kontrolleri, asp.net sayfaları vb.) Kapsayacak şekilde şablonlar yazın. Üretim işlemini çalıştırın ve çıktıyı stillendirin.

Şablonları yazmakta bazı ek yükler vardır, ancak sonraki benzer projeler için tekrar kullanılabilirler. Benzer şekilde, temel verilerdeki değişiklikler, meta verileri değiştirerek ve üretim değişikliklerini daha kolay ve daha hızlı şekilde uygulayarak yeniden yaparak yeniden işlenir.

Test gelince. Bu şablonlu bir sistem olduğundan, başlangıçta işlemin çıkışını doğrulamak için biraz zaman harcamanız gerekecektir, eğer şablonunuz yanlışsa bu şablondan gelen tüm çıktılar aynı şekilde yanlış olacaktır. Bundan memnun olduğunuzda, daha sonra özel durumları kapsayacak şekilde genişletebileceğiniz xml meta verilerinden temel testler oluşturmak için kod jeneratörlerini de kullanabilirsiniz. Bununla birlikte, belirli şeyleri karşılamak için hala kod testlerini vermeniz gerekebileceğini unutmayın, kod oluşturma işinizi azaltır, tamamen ortadan kaldırmaz.


5

Şirketimizde internetten indirilen verilerle C ++ veya C # sınıfları üreten bazı araçlar kullanıyoruz. Bu sınıflar veri kaplarıdır ve listelerde çok sayıda nesne içerir.


Örneğin, Visual Studio gibi bir IDE'de bulunan kod parçacıkları gibi bir şey?
Jose Faeti

@Jose Bizim araç sadece HTML çıktısını bir sınıfa dönüştürmek için bir uygulamadır. Bu yüzden, uygulama her başlatıldığında verileri indirmek yerine, bir kere indiririz ve bir sınıf oluştururuz.
Holli

5

Metaprogramming, uzun süredir programlamanın bir parçası olmuştur. Yalnızca SWIG veya WYSIWYG tasarımcıları gibi kod oluşturan araçları değil, aynı zamanda C'nin önişlemcisi, hatta C ++ 'ın şablonları ve C # / Java's generics gibi dil araçlarını da düşünün.

Aslında, her derleyicinin başka bir metaprogram olduğunu iddia edebilirsiniz - program metni ve çıktı makinesinde veya VM kodunda aldılar. Ve derleyiciler olmadan hayat? Owch.


Bu doğru, ancak verimliliğinizi artırmak için onu aslında kendi programlama dilinizde nasıl uygulayabilirsiniz? İşte eksik olan bu.
Jose Faeti

5

İşte geçmişimden somut bir örnek.

Veri erişimi için BDE kullanan yaklaşık 50 MB Delphi kaynak koduna sahip bir sitede çalışıyordum. BDE'nin desteklediği en yüksek sürümü geçerek Oracle yükseltmesini sağlamak için Direct Oracle Access kullanmaya geçmek istediler (doğru hatırlıyorsam 8i).

Bu yüzden, her form ve veri modülünü kullanarak her kodlayıcıyı elle değiştirmek için bir kodlayıcı ekibinin yerine çalışmak yerine bir PERL betiği yazdım:

  1. DFM'yi (form dosyası) ayrıştırdı ve tüm TQuery, TTable, TStoredProcedure & TDatabase nesnelerini tanımladı - öğeleri bir listede sakladı.

  2. PAS (kod) ayrıştırıldı ve nesnelerin kullanımı belirlendi - TQueries güncelleme mi yapıyor yoksa seçti mi? Ayrıca, IDE'deki bir forma bırakılmak yerine kodda oluşturulan nesneleri tanımladı.

  3. Nesne türlerini uygun şekilde değiştirerek DFM & PAS'nin yeniden yazıldığını (örn. TTable -> TOracleDataSet, SQL özelliği "select * from" vb. İle ayarlanmış) ve yöntem çağırır. Ayrıca, parametreleri açmak, kapatmak ve ayarlamak için uygunsa ilave yöntem çağrıları eklendi.

Kısacası, 3 hafta süren çalışma, 6 ay boyunca çalışan 5+ geliştiricinin orijinal tahmini yerine farklı kodlama stillerine sahip farklı ekipler tarafından yazılmış farklı uygulamalar üzerinde çalışmak üzere senaryoyu değiştiriyor.

Ve bu yaklaşımı kullanmayı bile düşündüğüm sebep Pragmatik Programcı'yı okumaktı .


Harika, birkaç günden beri Perl'deyim ve web geliştirme için temel çalışma alanları oluşturmak için bazı dizinler, dosyalar vb. Sadece "create workpace" yazarak bazı üretkenlik araçları yaptım! :)
Jose Faeti

1
@Jose Bu fikir. Tekrarlayan şeyleri otomatikleştirmek için komut dosyası dillerini kullanın. 8x verimlilik artışı elde ettiğiniz bir defalık olabilir veya durumunuzdaki gibi, tekrar tekrar yapacağınız zaman alıcı bir şey olabilir.
mcottle

4

Sizden örnekler isteyin ...

SQL ile çalışırken, veritabanını doğrudan değiştirmemeniz gerekir; bunun yerine, veritabanında yapısal değişiklikler (tablolar, sütunlar, birincil anahtarlar, kısıtlamalar vb. Dahil) dahil olmak üzere, istediğiniz değişiklikleri yapan komut dosyaları çalıştırmanız gerekir. . Oldukça sık, aynı anda birçok masaya veya sütuna karşı aynı işlemi yapmanız gerekecek ve bunları tek tek yapmak sıkıcı olacaktır, istediğiniz şeyi yapan daha büyük bir komut dosyası çıktısı veren kısa bir komut dosyası zaman kazandıran.

Örneğin, DATE veri türü MS SQl Server'a tanıtılmadan önce, bir tarih sütunu için tek seçenek bir zaman bölümü olan DATETIME idi - veri ile başa çıkmayı biraz zorlaştıran bir zaman bölümü. Tarih veri türüne sahip bir sürüme yükseltme yapıldığında, saatin her zaman 00:00 olduğu sütunları güncellemek isteyebilirsiniz. Düzinelerce, hatta yüzlerce DateTime sütunu içeren bir veritabanında bu oldukça zaman alıcı olurdu. Ancak, tüm tabloları sorgulayan, her sütunu DATETIME veri türüyle kontrol eden, saat 00: 00'dan başka bir zaman olup olmadığını görmek ve tablonun / sütunun değişmesi için bir ALTER deyimi oluşturup oluşturmadığını görmek için bir komut dosyası yazmak kolaydır. DATE veri türü. Presto, kod yazan kod.


3

CL (Common Lips) Macros'a bir göz atın. Bence tam olarak istediğin bu. Dudaklar metaprogramlamada mükemmeldir.

Ayrıca , mükemmel Metaprogramming desteğiyle (makrolar dahil) .NET yetkileri almak istiyorsanız Nemerle’yi öneriyorum

Fakat gerçek bir kod oluşturma motoru istiyorsanız, Apache tasarrufuna bir göz atın


3

Sadece böyle bir araç üzerinde çalışıyorum. Özel durumumuzda, veri tabanındaki fonksiyonların imzalarında Veri Katmanına dayanan VB.NET kodunu üretiyoruz.

Kod oluşturma ve kod oluşturma ile çalışmaya başlamak ilk başta zordur, çünkü kodun nasıl üretileceğine dair hiçbir fikriniz yoktur, ancak bir kez belirlenmiş bir kurallar diziniz varsa ve oluşturulması gereken kod her zaman bu kurallara göre oluşturulabilir. , bu kodla çalışmak o kadar da zor değil. Tabii ki, kod oluşturma karmaşıklığına ve kural sayısına bağlı olarak, görev daha zor olabilir. Fakat özünde, otomatik kod oluşturma, tekrarlayan kodlama görevleri için kullanılır, çok değişken olan gelişmiş kodlar için kullanılmaz.

Çıktının test edilmesi iki yönlüdür. İlk önce kodun derlendiğinden emin olmalısınız ve bu kolaydır. Ardından çıktının, üzerinde oluşturduğu parametrelere dayanarak ne demek istediğini yaptığından emin olmalısınız .. ve bunun zorluğu, oluşturduğunuz kodun karmaşıklığına bağlı olarak değişir.

Benim içten tavsiyem, tekrarlayan bir şekilde kod yazıyormuş gibi hissettiğinizde ve zamanınızı karşılayabiliyorsanız .. Yaptığınız şeyin oluşturulan kodla yapılamayacağını düşünmeye çalışın. Ve eğer öyleyse (eğer her zamanki durumun tekrarlayan koduysa) kaç kez genişletmek zorunda kalacağınızı düşünün, bu kodu biraz değiştirin ve aynı zamanda bu tür bir kodu ne kadar yazmak zorundasınız? Bunlardan herhangi birinin cevabı "çok" ise, o zaman bu kod için bir jeneratör yapmayı ciddiye almalısınız .

Yardımcı olur umarım,
IPP


Cevap için teşekkürler! Örneğinizdeki kurallar gerçekte nasıl uygulanır?
Jose Faeti

1
Sana bütün kuralları söyleyemem ama sana bazı örnekler verebilirim. Oracle veritabanının açığa çıkardığı arayüzü ayrıştırırız ve Oracle arayüzü içindeki fonksiyonların imzasını dikkate alırız. İmzaya dayanarak, veri katmanı işlevinin adını oluştururuz. Verilerimizi saklamak için kullandığımız özel nesne türü dizisine kaydettiğimiz ve kaydettiğimiz sonuç olarak her zaman db'den bir kehanet veri tablosu elde ettiğimizi biliyoruz. Ayrıca, biz böyle devam üretmek ve fonksiyonlara giriş ve çıkış parametreleri karşılık gelen ekleyin db işlevi imza giriş / çıkış parametrelerine dayalı ..
Ioan Paul Pirau

3

HTML üreten JavaScript kodu içeren bir web sayfası çıkaran bir PHP modülüm var. İşte üç kat var. Çocuk okumak zordu!

Bir programlama sınıfında, kullanıcıdan bir formül dizgisini alan ve ayrıştırıp değeri gösteren bir program yazmamız gerekti. En etkileyici çözücü basitçe kullanıcı girdisini aldı, main () {printf ("% d", ...);} dizisine sardı ve derlemek, bağlamak ve çalıştırmak için bir komut dosyası çalıştırdı. Ayrıştırıcı yazmadı! Bugün bunu bir SQL SELECT deyiminde yapabilirsiniz.

Bu, oynamanız gereken bir araçtır, daha sonra kullanışlı olacağı bir sonraki gün için saklayın.


Bu aslında uygulamaya çalıştığım şeydi! :) Ama sonra Perl ile çevrimdışı olarak kodlamaya karar verdim ve harika çalışıyor. Eklemeyi düşündüğüm bir sürü özelliğim var!
Jose Faeti

Hiç bir sorun yaşamadan dil katmanına 20'ye kadar dil katmanıyla kod yazıyorum. Bir çağrı yığını derinliği 20 kattan daha karmaşık değildir. Bu yüzden " kullanışlı olacak zaman gelecek gün için saklamak için bir araç" olduğunu kesinlikle kabul etmiyorum - kod oluşturma her zaman kullanışlıdır.
SK-mantık

3

Prolog ile temiz meta-programlama çözümleri geliştirdim . Ana uygulamanın (C ++ 'a yazdığı gibi) problemin soyut tanımını çalışma zamanında Prolog uygulamasına çevirdiği ve ardından yetkilendirildiği yere. Genellikle C ++ ile eşdeğer işlevsellik yazmak sonsuza kadar sürer.

Bence bu senaryo, kod yazma kodu argümanı lehine mükemmel bir durum .


3

Konu hakkında ne düşünüyorsunuz?

Metaprogramlama en yaygın olarak dinamik olmayan dillerle ilişkilidir, çünkü üretken olmayan ve akıllı olmayan kod satırları olmadan belirli davranışlara (ORM uygulamak gibi) ulaşmada daha fazla zaman yoktur.

Ancak PHP gibi daha dinamik dillerde bile, kod oluşturma gerçekten hayat kurtarıcı olabilir ve büyük miktarda üretkenliği artırabilir. Modern çerçevelerde, ilan ettiğiniz belirli bir iş nesnesi için ortak model, form, test ve eylemlerin çoğunu üreten iskeleye sahip olmak çok yaygındır. Symfony veya RoR gibi çerçevelerin bu kadar başarılı olmasının nedenlerinden biri de bu kod oluşturma araçlarının çok hızlı bir şekilde tutarlı kod oluşturması ve programcıların verimliliğini arttırması.

Web sitelerinde, etkileşimin çoğu dört ana eylem etrafında döner:

  • Öğe oluştur
  • Bir öğe kümesini alın (olası filtreleme ile)
  • Bir öğeyi yeni özelliklerle güncelleme
  • Bir öğe kümesini silin

En azından bu 4 temel eylem etrafında dönen her şey mümkün olabilir ve IMHO, maksimum üretkenliğe ulaşmak için kod oluşturma araçları kullanılarak gerçekleştirilmelidir.

Şirketimde, sembolik bir yazılım kullanıyoruz ve yönetici-oluşturucu, çalışma zamanında kod üreten (ve önbelleğe alan) bile istisnai bir araçtır; yeni kod üretmek, sadece önbelleğimizi temizlememiz gerekir. CRUD işlemleri için bu tür bir aracı kullanmanızı şiddetle tavsiye ederim.

Ancak, symfony harika katkıda bulunanların yaptığı şeyi yapmak kolay bir iş değildir. Bazı kod oluşturma görevlerini kendim uyguladım ve gerçekten tutarlı olan bir şey yapmak ve çoğu köşe durumunu kapsayan geniş bir uygulama ile kolay değil.

Verimliliğinizi gerçekten artıracak bir şey mi?

Metaprogramlamanın alt düzeydeki işlerde (çerçeveler, önbellekleme, derleyiciler vb.) Çok önemli olduğuna inanıyorum, ancak iş katmanında bir şeyler yapıyorsak çok dikkatli yaklaşmamız gereken bir şey.

Kod üretmeyi kullanmak hiç kuşkusuz büyük bir verimlilik arttırıcıdır. Kendi kod oluşturma araçlarınızı uygulamak, kendiniz bir çerçeve oluşturmadığınız sürece çok değil.

Konuyla ilgili, kitaplar, bloglar, slayt gösterileri vb. Gibi iyi kaynaklar nelerdir?

Programlamayı anlamak için en iyi kaynak her zaman iyi ve iyi yorumlanmış bir kaynak kodudur. RubyOnRails ve Symfony admin jeneratörlerine bakmanın iyi bir fikir olduğunu söyleyebilirim .


3

Buradaki birçok cevap genellikle meta programlama olarak bilinen şeye atıfta bulunurken, aslında otomatik programlama olarak bilinen AI ile ilgili programları anlama veya sentezleme programları ile ilgili bir alan vardı [1].

Herhangi bir derleyici (veya meta-program, kod üreteci, tercüman, makro sistemi, ...) dönüşümlerle çalışır, sabit dönüşüm algoritmasını uygulayarak bir girdiden çıktı üretir. Ancak geleneksel bir derleyici veya meta-program, bir listenin ne şekilde sıralandığının bir tanımı, açıklaması veya örneği verilmediğinde (örneğin, [5, 3, 9] => [3,5,9]) bir sıralama algoritması oluşturmaz. Bu "otomatik programlama" alanının ilgisini çeken sorunlar.

[1] - Program anlama sistemlerinde ilerleme raporu ftp://db.stanford.edu/pub/cstr/reports/cs/.../CS-TR-74-444.pdfShare


2

Meta programlama bakımı çok zor olabilir. İlk başta zarif görünüyor, ancak köşe davalarına girmeye başladığınızda, hatalar geç kaldı (üretilen kodda) ve her şey kullanmak / hata ayıklamak için bir kabusa dönüşüyor.

Temelde python kodu yazdım ve deneyimlerime göre meta programlama bu dilde her zaman kötü bir seçimdir. Her zaman sıkıcı normal dil özellikleri ile yapmak için şeyler refactor. Sonuç daha az korkak, ancak birlikte yaşamak daha kolay.


herhangi bir kod türünün korunması çok zor olabilir . Doğru şekilde yapılırsa çok kolay olabilir. Metaprogramming, aslında büyüklük derecelerinde sürdürülebilirliği artırabilir. Python deneyiminiz büyük olasılıkla, gerçek metaprogramlama ile alakasızdır, çünkü Python, çok derin AST ile bu düşünce tarzı için pek uygun değildir. Ancak Python ile bile, Tempita kütüphanesini yüksek verimlilikle kullandım ve daha önce Python deneyimi olmayan bir ekiple bile, hiçbir bakım problemi yaşamadım.
SK-mantığı

Python AST hakkındaki noktanızla ilgileniyorum. Meta programlama amacıyla tempita kullandınız mı?
Simon Bergot

bu ( docs.python.org/library/ast.html ) oldukça geçici bir AST'dir ve ayrıştırıcı, analizi problemli kılan (özellikle Python'da uygun örüntü eşleşmesinin olmaması durumunda), aşılmamış, aşırı katlı bir ağaç verir. Böyle bir AST üretmek de pek uygun değildir. Hem Python hem de C kodu üretmek için tempita kullandım (örneğin, saf metin tabanlı metaprogramlama), bu belirli görev için (kazan plakası kodu oluşturma) iyi çalıştı. Ayrıca, bazı XML yüksek seviye açıklamalarından C kodu oluşturmak için Python'u sık sık kullandım.
SK-mantık,

2

OP kaynaklar için sorar.

DMS Software Reengineering Toolkit ürünümüzü ilginç bulabilirsiniz. Özel bir program analizi ve dönüştürme araçları oluşturmak için tasarlanmış saf bir metaprogramlama aracıdır.

[OP'nin sorusuna bir yorum yapmak için, belirli bir dönüşüm aracı oluşturmak için kullanıldığında, DMS kod yazan, kod yazan bir ürün satırıdır:]

DMS bunu, hedef programlama sınırlarının agnostik (ancak bağımsız değil) olmasıyla başarır. DMS, çok çeşitli metaprogramlama görevlerinin ihtiyaç duyduğu standart hizmetleri sağlar, bir işletim sistemi ise standart programlama görevleri için çok çeşitli hizmetler sunar. Bu hizmetler arasında güçlü ayrıştırma, otomatik olmayan sözdizimi ağaçları yapısı, ağaçlar üzerinde desen eşleştirme ve yeniden yazma, çoklu kalıtım, kontrol akışı, veri akışı, noktalara ve çağrı gibi kötü kapsam belirleme kuralları olan dilleri kolayca yöneten sembol tablo kütüphaneleri yer alıyor. grafik analizi. Bunların hiçbiri, işlenecek belirli dillerin yokluğunda anlamsızdır, bu nedenle DMS, bu genel makine parçalarına bağlı dil tanımlarını kabul eder, dile özgü ayrıştırma, AST yapımı, hedef dili özel kalıp eşleme / yeniden yazma hedefini kullanarak verir. dil sözdizimi,

Ve bir işletim sistemi gibi, DMS de yazmak istediğiniz ne (meta) programlarla ilgili çok az görüşe veya kısıtlamaya sahip olacak şekilde tasarlanmıştır; bu, çok çeşitli amaçlar için kullanılabileceği anlamına gelir: metrikleri çıkarmak, ölü kodu bulmak, görünüş dokumacılarını uygulamak, çevirmek diller, DSL'lerden kod üretme, büyük uygulamaları yeniden arama. (DMS, bu görevlerin tümü için zaten kullanılıyor).

Zamanınızı dil referans referans kılavuzundaki her şeyi kodlamak için harcamak istemiyorsanız, sağlam dil tanımları gerekir (bunun Java ve C ++ için ne anlama geldiğini düşünün). DMS, mevcut bir tam dil tanımları kütüphanesinin bulunmasıyla bu sorunu çözer. Buradaki analog, işletim sisteminiz için bir veri tabanına sahip olmak gibidir; veritabanı merkezli uygulamanızı yazmak için bunlardan birini uygulamanız gerekmez.


2

Philip Greenspun'un MIT kursu 6.916'daki 4. setindeki problemine bakınız: Yenilikçi Web Servisleri Yazılım Mühendisliği ( http://philip.greenspun.com/teaching/psets/ps4/ps4.adp ).

Amacı, "Öğrencilere meta verinin erdemlerini öğretin. Daha spesifik olarak, bir Web servisinin gereksinimlerini resmi olarak nasıl göstereceklerini ve daha sonra bu servisi uygulayan bilgisayar programlarını oluşturmak için bir bilgisayar programı oluşturmayı öğreniyorlar" diyor.

Potansiyel ArsDigita ( http://en.wikipedia.org/wiki/ArsDigita ) askerlerinin ilk balon sırasında çözmeleri gereken sorunlardan biri budur .

"Kümeler için SQL" kitabı pset'teki Philip referansları taşındı ( http://philip.greenspun.com/sql/ ).


2

2001 yılında veya çevresinde, iş nesnelerini ve veri nesnelerini yoğun şekilde kullanan bir proje üzerinde çalışmaya başladım. Ön uç web sitesini kuracaktım, ancak iş katmanı ve veri erişim katmanı tam olarak gelişmemiş olduğundan baş parmaklarımı sıkarak kapattım. Bundan birkaç hafta sonra, bu katmanların ne yaptıklarına sert bir göz atmaya başladım. Temel olarak, depolanan prosedürlerden döndürülen verileri, verilerdeki alanlara karşılık gelen özelliklere sahip nesnelerin koleksiyonları olarak ifşa ediyorlardı ya da girdi parametrelerini alıyorlar ve bunları veritabanı tablolarına kaydedilmek üzere saklı prosedürlere gönderiyorlardı. İki katman arasında birçok seri hale getirme / seri hale getirme vardı, Microsoft Transaction Server vardı, IDL / ODL tipi bir kütüphane vardı ... ama hepsi bir kalıba uyuyordu.

2 hafta sonra, IDL / ODL'yi terk edecek bir kod üretecim çalıştı ve ayrıca iş ve veri nesnelerini de çıkaracaktım. İş ve veri katmanı nesnelerini inşa eden adamı bu hata ayıklama ve test etme noktalarına ulaşmak için 2 yıl almış. 2 hafta içinde, kod oluşturma ile aynı çıktı elde ettik, ancak hepsi üretildiğinden dolayı oldukça hatasızdı.

Bu kod üreteci (düşük seviye CASE aracı), yaklaşık 8 ila 10 yıl boyunca birçok farklı yinelemede beni takip etti, çünkü prensip çok basitti: veritabanlarıyla konuşurken yapılması gereken bir şey yapıyorsunuz çok tekrarlayan kodlama ve bir kez doğru yaptıktan sonra, artık endişelenmenize gerek kalmaz.

Öyleyse, evet: özellikle kodlama tekrarlandığında ve iyi tanımlanmış bir desene uyduğunda bir kod üreticisi kullanın.

İnsanları benzer şeyler yapmak için RegX makrolarını kullanmalarını ya da benzer şeyler yapmak için Excel formüllerini kullanmalarını biliyorum (Bunu da yapıyorum).


2

Bir metaprogramlama örneği

Authority adında bir Ruby yetki kitaplığım var . Bu geliştiriciler gibi yöntemlerle, uygulamasına soru sormak sağlar current_user.can_read?(@post)ve @post.readable_by?(current_user). Bu sorular merkezi yazar sınıfları tarafından cevaplanmaktadır.

Bu çok önemli bir bölüm: Kurum, kullanıcının konfigürasyonunu görene kadar hangi yöntemleri tanımlayacağını bilmiyor . Kullanıcı yapılandırması şunları içerebilir:

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

Bu durumda, gibi bir yöntem olması gerekir current_user.can_microwave?(@post).

Metaprogramming bunu mümkün kılar: konfigürasyonu okuduktan sonra, hangi yöntemleri tanımlayacağımı biliyorum :

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.