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.