Perché le funzioni pure non dovrebbero essere sempre statiche e pubbliche? [duplicare]

5

Quali sono le ragioni, tecniche o meno, che le funzioni pure (funzioni che non si basano sullo stato esterno e non hanno effetti collaterali) dovrebbero non essere sempre pubbliche e statico?

Quando una funzione statica e pura è molto generica, come Math.floor() o qualcosa del genere, ha perfettamente senso essere pubblica e statica. Perché non dovremmo avere accesso globale alle funzioni matematiche di base? Ma quando si fa lo stesso con le funzioni specifiche del dominio dell'applicazione, specifiche anche solo per la classe in cui sono implementate, allora comincio a sentire che sto facendo qualcosa di sbagliato.

Ad esempio, supponiamo di avere una classe User , e ha un attributo super specifico chiamato happiness , che può essere modificato mangiando cibo. In generale avrei una funzione pubblica che agisce come un'interfaccia, ottenendo le informazioni esterne, quindi chiamo una funzione di helper protetta che è implementata puramente, trasmettendo dati di stato come argomenti. L'implementazione potrebbe essere simile a questa:

class User {
    private FoodPreference foodPreference; 
    private float age; 
    // ... 
    // constructors initializing the users food preferences and
    // changing the Users preferences as they get older
    // ...

    // Impure interface relying on users state to get their preferences
    public void EatFood(Food food) {
        this.happiness = this.ComputeHappiness(this.foodPreference, food); 
    }

    // Pure, does not rely on Users state to compute this info, it's passed in as an argument.  
    protected Happiness ComputeHappiness(FoodPreference preference, Food food) {
      Happiness newHappiness = /* some user-specific logic computing their happiness due to eating food */
      return newHappiness; 
    }

}

Se ComputeHappiness() era pubblico e statico , sarebbe male? La mia reazione istintiva è "Sì, sarebbe", penso perché sembra che l'uso della parola chiave statica in OOP sia qualcosa generalmente evitato poiché è così facile sparare ai piedi.

Riesco a vedere molti vantaggi nell'avere funzioni pure statiche e pubbliche, anche se non sono molto generali:

  • Le funzioni pure sono più facili da testare. Le funzioni statiche sono di facile accesso. I test unitari dovranno eseguire meno impostazioni per produrre i mezzi per testare la funzione. Ora hai solo bisogno dei dati, che di solito non sono la parte difficile delle funzioni di test.
  • Le funzioni pubbliche possono essere interfacce che accedono ai dati stateful (dall'oggetto, dal database o da qualsiasi altra fonte) e lasciano la logica di business alle loro funzioni di supporto puramente implementate.
  • Le funzioni pure possono essere riutilizzate molto più facilmente. Forse altre parti dell'applicazione vorrebbero ComputeHappiness ()!

Quali sono i motivi per cui questa è una pessima idea? Sicuramente sembra violare il principio del minimo stupore.

    
posta PandemoniumSyndicate 19.09.2015 - 08:27
fonte

4 risposte

5

È una questione di occultamento delle informazioni e astrazione dei dati. Se rendi le tue operazioni (anche se puramente e referenzialmente trasparenti) separate dall'oggetto, allora l'oggetto deve rendere pubblica la sua rappresentazione alle operazioni. Poiché nascondere la rappresentazione è una caratteristica importante (o, secondo alcune definizioni, anche di solo ) di OOP, il tuo oggetto smette quindi di essere un oggetto e diventa fondamentalmente una struct.

Mentre con i metodi che appartengono all'oggetto, il metodo ha accesso privilegiato alla rappresentazione dell'oggetto e può quindi utilizzare la rappresentazione nel suo calcolo, senza che l'oggetto trapelasse internamente ad altre parti del sistema.

Vedi Informazioni sull'astrazione dei dati, rivisitato di < a href="http://WCook.BlogSpot.Com/"> William R. Cook per la distinzione tra l'astrazione dei dati con i tipi di dati astratti e l'astrazione dei dati orientata agli oggetti. Il documento contiene anche un esempio di astrazione dati orientata agli oggetti in Java che utilizza solo metodi puramente referenziali trasparenti. In effetti, un punto importante che l'autore fa in quel documento è che OO e la mutabilità sono ortogonali.

    
risposta data 19.09.2015 - 10:08
fonte
2

Ogni funzione pubblica è parte dell'interfaccia del componente. Le interfacce sono limitate nei loro cambiamenti, hanno bisogno di essere retrocompatibili il più delle volte, e quando non lo sono, i loro client dovrebbero adattarsi ai cambiamenti. Pertanto, le interfacce tendono ad essere il più ristrette, il più efficace possibile. La mancanza di dettagli di implementazione nell'interfaccia distrugge la modularità e introduce costi di manutenzione aggiuntivi.

    
risposta data 19.09.2015 - 13:34
fonte
1

What are the reasons, technical or otherwise, that pure functions (functions which do not rely on external state and have no side effects) should not always be public and static?

Le funzioni pure possono essere pubbliche e statiche, quindi se si adatta alle tue esigenze, puoi rendere pubbliche e statiche tutte le tue pure funzioni. Nessuno ha detto che non dovrebbero essere pubblici e statici. Ma quando dici " sempre essere pubblico e statico" sembra che ti stia chiedendo perché non c'è una regola che costringa tutti a rendere pubbliche e statiche tutte le loro pure funzioni. Bene, ci sono molte molte ragioni per questo, ma dubito che questo è ciò che volevi chiedere. Quindi, potresti voler riformulare la tua domanda un po ', perché così com'è, non ha molto senso.

Why shouldn't we have global access to basic math functions?

Diverse lingue ti danno la possibilità di avere accesso globale alle funzioni statiche pubbliche. Ad esempio, in java, puoi

import static Math.floor;

e quindi puoi utilizzare floor( x ) anziché Math.floor( x ) . Se stai cercando un modo per utilizzare floor( x ) senza nemmeno dover importarlo staticamente in modo esplicito, sarebbe un'idea estremamente negativa perché significherebbe che un modulo potrebbe riservare il nome della funzione globale floor( double x ) e quindi nessun altro modulo potrebbe dichiara la stessa funzione globale.

What are the reasons this is a terrible idea?

Temo che tu non abbia spiegato, in modo chiaro e conciso, esattamente quale terribile idea tu stia parlando. Forse se riformuli la tua risposta, potremmo essere in grado di fornirti informazioni migliori.

    
risposta data 19.09.2015 - 11:08
fonte
0

Sembra che tu stia soffrendo di una certa confusione su come funzionano pure le funzioni OOP.

Una funzione pura è quella che non fa affidamento su nulla per produrre il suo risultato eccetto i valori passati ad esso. Un metodo (normale, non statico) in OOP prende l'oggetto a cui è associato come argomento implicito. Pertanto, è completamente possibile avere un metodo di oggetto come pura funzione. Usali quando hanno senso, e usa metodi statici quando loro hanno senso, e dovresti stare bene.

    
risposta data 19.09.2015 - 10:46
fonte

Leggi altre domande sui tag