2010-11-02 15 views
7

Quando ho letto di più sulla metaprogrammazione di Ruby, la maggior parte delle volte abbiamo trovato almeno due soluzioni per risolvere un problema. Si prega di guardare due esempi di seguito:Class vs Module nella progettazione dell'API Ruby?

class Base 
    def self.has_many(*args) 
    # ... 
    end 
end 

class Student < Base 
    has_many :books 
end 

Un altro stile:

module Base 
    def self.included(klass) 
    klass.extend ClassMethods 
    end 

    module ClassMethods 
    def has_many(*args) 
     # ... 
    end 
    end 
end 

class Student 
    include Base 

    has_many :books 
end 

Ma quando progettiamo api, dobbiamo decidere quale usare, ma vorrei chiedere le vostre idee e alcune delle le migliori pratiche che molte persone hanno già implementato nelle loro librerie.

risposta

5

Se l'API fornisce la funzionalità di base, che sarà esteso dal cliente, allora si dovrebbe preferire eredità.

Se la tua API estenderà vari client con le loro funzionalità di base, allora dovresti cercare la composizione .

2

Hai una serie di teorie attorno a questa domanda.

Preferisco la composizione perché rende il comportamento molto più riutilizzabile in questo modo ma se si guarda Rails, sarà necessario sottoclasse classe ActiveRecord :: Base ogni volta che si desidera un oggetto nel database. Se si guarda DataMapper, è l'opposto in quanto hanno solo richiesto di includere DataMapper :: Resource.

Ereditarietà rispetto alla composizione (tramite moduli) è un grande argomento e la domanda che dovrai porsi verrà: come posso ottenere il maggiore disaccoppiamento tra i componenti che fornisco e un altro codice utente esistente?

1

Ruby supporta solo ereditarietà singola. Pertanto, se il client API deve ereditare la classe base, perde la possibilità di ereditare altre classi. Utilizzando l'inclusione del modulo si rende possibile un codice come:

class Student < Person 
    include Base 
    has_many :books 
end 

E così si può "ereditare" sia la Persona che la Base.

Tuttavia, la sintassi eredità classica sembra più naturale e meno "magico"