Metaprogramming dalam tugas dunia nyata

Halo! Pada artikel ini saya ingin berbicara tentang metaprogramming menggunakan contoh masalah umum yang nyata.





Ketika seseorang berbicara tentang metaprogramming, pembuat kode jadul akan marah.





Dan ada alasan untuk ini, dan pada proyek besar mungkin terlihat gila untuk menggunakan metaprogramming, karena kodenya menjadi sangat sulit untuk dibaca. Dan jika seorang spesialis dari luar bergabung dengan proyek tersebut, maka dia bahkan tidak akan mengerti apa pun dalam meta-code ini.





Tapi tidak sesederhana yang mereka katakan - tidak ada alat yang buruk. Pada artikel ini saya akan mencoba menunjukkan dengan contoh kerja nyata bagaimana metaprogramming dapat membantu membuat kode Anda lebih bersih dan menghilangkan pengulangan rutin. Dan akan membuatmu bersukacita dalam meta-magic.





Bantuan dari wikipedia

Metaprogramming adalah jenis pemrograman yang terkait dengan pembuatan program yang menghasilkan program lain sebagai hasil dari pekerjaannya (khususnya, pada tahap kompilasi kode sumbernya), atau program yang berubah sendiri selama eksekusi (kode modifikasi sendiri) . Yang pertama memungkinkan Anda mendapatkan program dengan waktu dan upaya yang lebih sedikit pada pengkodean daripada jika programmer menulis seluruhnya dengan tangan, yang kedua memungkinkan Anda untuk meningkatkan properti kode (ukuran dan kinerja).





Ini menyimpulkan pendahuluan. Sekarang saya ingin beralih ke bagian praktis dan memberi tahu Anda tentang esensi masalahnya

Selanjutnya kita akan berbicara tentang bahasa ruby ​​dan khususnya kerangka Rails. Ruby memiliki refleksi dan peluang besar untuk metaprogramming. Kebanyakan permata, modul, dan kerangka kerja dibangun dengan alat refleksi yang kuat.





Foto oleh Joshua Fuller di Unsplash





Siapa pun yang menulis sesuatu di Rails kemungkinan besar menemukan permata seperti Admin Rails, jika Anda belum mencoba menggunakannya dalam proyek Anda di rel, atau jika Anda memiliki analog, saya sangat menyarankan melakukan ini, karena hampir di luar kotak Anda akan melakukannya. dapatkan CMS lengkap untuk sistem Anda.





Jadi ada fitur yang tidak menyenangkan , masalah dengan asosiasi has_one.





has_one . 1. , .





gambar 1
1

. has_one (draft) CMS.





class TechProcess < ApplicationRecord
  include MdcSchema
  has_many :executor_programs, inverse_of: :tech_process, foreign_key: :barcode_tech_process, primary_key: :barcode

  validates :barcode, presence: true
  validates :barcode, uniqueness: true

  has_one :draft2tech_process, dependent: :destroy
  has_one :draft, through: :draft2tech_process

  has_many :tech_process2tech_operations
  has_many :tech_operations, through: :tech_process2tech_operations
end

      
      







. has_one , . .









def draft_id
  self.draft.try :id
end

def draft_id=(id)
  self.draft = Draft.find_by_id(id)
end
      
      



, , , CMS.









, 15 has_one ? , DRY. . .





Meta





self.reflect_on_all_associations(:has_one).each do |has_one_association|
  define_method("#{has_one_association.name}_id") do
    self.send(has_one_association.name).try :id
  end

  define_method("#{has_one_association.name}_id=") do |id|
    self.send("#{has_one_association.name}=",has_one_association.klass.find_by_id(id))
  end
end
      
      



, has_one Rails Admin





. .





, . reflect_on_all_associations , "macro" :hasone has_one , , .





, has_one . , , define_method .





has_one rails admin.





"" , . - concern





require 'active_support/concern'
module HasOneHandler
  extend ActiveSupport::Concern
  included do
    self.reflect_on_all_associations(:has_one).each do |has_one_association|
      define_method("#{has_one_association.name}_id") do
        self.send(has_one_association.name).try :id
      end

      define_method("#{has_one_association.name}_id=") do |id|
        self.send("#{has_one_association.name}=",has_one_association.klass.find_by_id(id))
      end
    end
  end
end
      
      



, . CMS has_one . , .





class TechProcess < ApplicationRecord
  include MdcSchema
  include HasOneHandler

  has_many :executor_programs, inverse_of: :tech_process, foreign_key: :barcode_tech_process, primary_key: :barcode

  validates :barcode, presence: true
  validates :barcode, uniqueness: true

  has_one :draft2tech_process, dependent: :destroy
  has_one :draft, through: :draft2tech_process

  has_many :tech_process2tech_operations
  has_many :tech_operations, through: :tech_process2tech_operations

end

      
      







Saya berharap saya bisa menunjukkan nilai praktis dari penggunaan teknik metaprogramming. Tentu saja, Anda memutuskan apakah akan menggunakannya atau tidak. Jika Anda menggunakannya terlalu sering dan tidak pada tempatnya, maka proyek akan menjadi benar-benar tidak dapat dibaca dan sulit untuk di-debug, tetapi jika digunakan dengan benar, sebaliknya, mengurangi jumlah kode, meningkatkan keterbacaan dan menghilangkan pekerjaan rutin. Terima kasih untuk semua yang membacanya!








All Articles