2014-11-23 17 views
6

Durante lo sviluppo di una classe vettoriale bidimensionale come parte di una libreria matematica, sto considerando di avere coppie di metodi statici e di istanza per motivi stilistici e di usabilità. Cioè, due funzioni equivalenti, ma una è statica & non mutante e l'altra è istante & mutante. So che non sono il primo a considerare questo problema (vedi here, ad esempio) ma non ho trovato alcuna informazione che lo indirizzi direttamente.Avere coppie di metodi statici e istanziati che eseguono le stesse attività?

A favore di avere coppie statiche e metodo esempio:

  • Alcune persone preferiscono utilizzare uno o l'altro e in alcuni casi di essere in grado di scegliere rende il codice più facile da leggere.
  • È implicito che i metodi statici non stanno mutando quando sono forniti sia i metodi statici che quelli istanziati. Questo può rendere il codice chiamante molto più chiaro, es .:

    someVector = Vector2d.add(vec1, vec2); 
    someVector = (new Vector2d(vec1)).add(vec2); // does the same thing although more convoluted. 
    
    // similarly adding directly to a vector is simpler with a mutator method. 
    someVector.add(vec2); 
    someVector = Vector2d.add(someVector, vec2); 
    

    Questo è particolarmente importante quando si utilizzano lunghe catene di chiamate di funzione, che è comune con i vettori.

  • Le operazioni sul posto possono essere più rapidamente computazionalmente rispetto alla creazione di una nuova istanza per ogni operazione. L'utente decide quando le prestazioni sono importanti. Per gli utenti di una classe Vector, le prestazioni possono essere importanti in quanto i vettori vengono spesso utilizzati in un codice computazionalmente costoso.

A favore di avere solo metodi statici o di istanza, ma non entrambi:

  • No significativo la ridondanza del codice. Più semplice da mantenere.

  • Meno ingombro. I javadoc saranno quasi la metà delle dimensioni.

  • Non è necessario informare gli utenti che i metodi statici non si alterano mai e che i metodi non basati su getter vengono sempre modificati.

Quanto disapprovante sta avendo coppie di metodi statici/di istanza? È usato in tutte le principali biblioteche?

Il modello "i metodi statici non mutano, i metodi di istanza" sono ampiamente conosciuti?

+2

È vero che la progettazione di una classe apparentemente banale come un "2D Vector" pone * molte * sfide progettuali. In particolare, il compromesso tra convenienza e prestazioni (meno spazzatura) e il trade off tra l'uso "idiomatico" e cose come l'immutabilità rendono questo aspetto più difficile di quanto non sembri a prima vista. Nessuna risposta fino ad ora (se ne scrivessi una, doveva essere * lunga * ...), ma ... se hai fornito un po 'più di codice (vale a dire, l'intera classe) questo potrebbe essere adatto per http://codereview.stackexchange.com/ – Marco13

+2

Si potrebbe argomentare che avere due metodi con nomi equivalenti, ma semantica selvaggiamente diversa, potrebbe confondere l'utente, portando a bug sottili. –

risposta

3

Penso che il tuo concetto di fornire sia metodi statici/immutabili che istanza/mutevoli sia buono. Penso che la distinzione sia facile da spiegare e sarà facile per gli utenti dell'API comprendere e ricordare.

Penso che il codice di implementazione dell'API non abbia una logica aziendale ridondante. Troverete che ripetete un pattern in cui l'implementazione statica crea una nuova istanza e chiama il metodo di istanza su quella nuova istanza.

Dato che sono pigro, vorrei considerare la creazione di un po 'di infrastruttura che genererebbe automaticamente i metodi statici, i loro javadoc e i loro test unitari in fase di compilazione. Questo sarebbe eccessivo se hai 10 metodi, ma diventa una grande vincita se hai 1.000 metodi.

1

Nella prima parte, "i metodi statici non mutano", che è ampiamente utilizzato in OOP. Non ne ho sentito parlare esplicitamente. Ma è un buon senso: "Se cambi un oggetto, perché il metodo sarebbe statico se potesse essere un metodo di istanza?" Quindi sono completamente d'accordo con "i metodi statici non mutano".

Nella seconda parte, "i metodi di istanza si [mutano]", in realtà non è così diffuso. Dipende piuttosto dal fatto che si decida di applicare la proprietà immutabilità o . Esempi dal API Java: java.lang.String è immutabili, java.util.Date è mutevole (molto probabilmente per caso/cattiva progettazione), java.lang.StringBuilder è mutevole intenzionalmente (che è il suo scopo).La mutabilità può portare alla clonazione difensiva al fine di proteggere il codice da bug di mutazione. Se questo è davvero un problema dipende da alcune cose:

  • È un'API che altri useranno? Non sai mai come useranno il tuo codice ... IMO è più importante proteggere il codice API da bug di mutazione rispetto al codice normale.
  • Quanto è buona la copertura del test unitario? I tuoi test di unità troveranno tutti i bug di mutazione che potrebbero entrare di nascosto? Se segui correttamente TDD (le 3 leggi di TDD di Uncle Bob), ed è un codice non-API, è molto improbabile che i bug di mutazione vengano introdotti di nascosto senza essere scoperti immediatamente.
  • Se si dispone di un codice che deve proteggersi dai bug di mutazione che utilizzano la clonazione difensiva, con quale frequenza viene chiamato quel codice? Se i cloni difensivi vengono creati frequentemente, potrebbe essere preferibile utilizzare oggetti immutabili rispetto agli oggetti mutabili. Fondamentalmente questo è il richiamo del numero di chiamate di metodi di sola lettura (che alla fine cloneranno in modo difensivo) di associare classi al numero di chiamate di metodi mutator sulla classe stessa.

Personalmente, preferisco oggetti immutabili, io sono un fan di final (se potessi cambiare Java, vorrei fare final di default per tutti i campi e le variabili, e introdurre una parola chiave var per renderli non-finale), e cerco di eseguire la programmazione funzionale in Java, anche se non è un linguaggio di programmazione funzionale, per quanto possibile. Dalla mia esperienza so che trascorro molto meno tempo a eseguire il debug del mio codice rispetto ad altri (in realtà eseguo il debugger Java forse due volte all'anno o giù di lì). Non ho abbastanza dati empirici e analisi adeguate per creare alcun tipo di "relazione causale" tra esperienza, immutabilità, programmazione funzionale e correttezza, quindi dirò solo che credo che l'immutabilità e la programmazione funzionale aiutino alla correttezza, e tu dovrai vieni con il tuo giudizio su questo.

Concludendo sulla seconda parte, "i metodi di istanza fanno [mutare]" è l'assunto ampiamente utilizzato nel caso in cui l'oggetto sia comunque modificabile, altrimenti i metodi di istanza potrebbero clonare.