Non strutturare i dati fino in fondo

7

Nel post del blog Non strutturare i dati fino in fondo , l'autore discute diversi modi per strutturare una cerchia datatype e come implementare i parametri in una funzione Radius.

area({circle, {point,0,0}, 17.4})

Tipo di disordine. Che ne pensi di una funzione per costruire un cerchio per noi? Quindi potremmo fare questo:

area(make_circle(0, 0, 17.4))

Potremmo anche avere una versione più breve di make_circle che accetta solo un raggio, impostando di default il punto centrale su 0,0. Ok, fermati, ci stiamo ingegnando fino alla morte. Tutto ciò di cui abbiamo bisogno è una semplice funzione per calcolare l'area di un cerchio:

area(R) -> math:pi() * R * R.

Sta parlando delle funzioni nel linguaggio di Erlang, che è funzionale e non orientato agli oggetti (OO). La mia domanda è: questo argomento vale per i linguaggi OO e vale per le lingue funzionali?

    
posta spirc 22.04.2012 - 08:54
fonte

6 risposte

5

Credo che il succo sia "non sovrastimare". L'equivalente OOP del suo argomento userebbe una classe Circle , un po 'come questa (si presuppone che il linguaggio OOP sia basato sulla classe canonico ma ipotetico):

public class Circle {
    private Point center;
    private double radius;
    public Circle(Point, radius) { ... }
    public Circle(radius) { ... }
    public double getArea() { return radius * radius * Math.PI; }
}

... quando in realtà, tutto ciò di cui hai bisogno è:

public double getCircleArea(double radius) { return radius * radius * Math.PI; }

Ovviamente, "l'over-engineering è male" è una dichiarazione facile da fare, e l'under-engineering è ugualmente male. Il trucco è trovare esattamente il giusto livello di astrazione e imparare questo richiede esperienza.

La programmazione orientata agli oggetti è particolarmente vulnerabile alla trappola dell'ingegneria, perché offre così tanti modi per aggiungere strati di astrazione; la maggior parte delle volte, aggiungere un'altra astrazione in cima allo stack è la cosa giusta da fare, anche se troppo spesso non lo è.

    
risposta data 22.04.2012 - 15:55
fonte
4

Il punto è "Non ne avrai bisogno" (aka YAGNI) e quindi non dovresti implementarlo. Questo non ha nulla a che fare con il paradigma di programmazione (OO o funzionale).

    
risposta data 22.04.2012 - 09:34
fonte
2

Penso che la risposta dipenda interamente dal contesto. È quasi sempre sensato costruire astrazioni per tutto ciò che potenzialmente ricorre ovunque in un'applicazione, anche se quell'astrazione è solo leggera è più probabile che fornisca un codice più pulito più avanti

Ad esempio, il tuo livello logico potrebbe aver bisogno di costruire un algoritmo più complicato che determina se due cerchi si toccano o si intersecano e determina i punti in cui toccano; questo tipo di codice gioverà a IMO con la capacità di condensare due serie di X, Y, Radius in un'unica struttura. - L'utente dell'algoritmo probabilmente si occupa in modo specifico di cerchi in questo caso e il cerchio stesso potrebbe finire con un'interfaccia più ampia di quella di Get / Set.

All'altro capo, a volte una struttura è semplicemente esagerata se l'astrazione finisce con l'essere "usa e getta" una tantum - se il cerchio non ha altro potenziale utilizzo se non per un singolo scenario localizzato che calcola l'area, allora un molto il semplice calcolo area andrebbe benissimo

    
risposta data 22.04.2012 - 09:34
fonte
1

Usando un linguaggio OO o uno stile OO, hai una gerarchia di elementi di struttura. Ad esempio (intenzionalmente molto semplificato):

  1. istruzioni, variabili
  2. funzioni / funzioni membro
  3. classi / oggetti
  4. librerie / componenti -

Quindi di solito generi classi più o meno complicate da blocchi elementari più semplici come funzioni e variabili. E mi sembra che sia tutto ciò che riguarda il post del blog: mantenere semplici i building block di livello inferiore (come una funzione per calcolare l'area del cerchio) e la struttura dei dati "one layer up", che potrebbe essere una "classe" in un linguaggio OO. Ciò potrebbe sembrare ovvio per chi è abituato a progettare strutture dati in modalità OO, ma potrebbe non essere così ovvio quando si utilizza uno stile funzionale puro.

In realtà, ciò non significa che dovresti mai implementare qualcosa come una funzione area al di fuori dell'ambito di una classe circle - non devi dargli i parametri che non avranno comunque bisogno (come le coordinate X / Y).

    
risposta data 22.04.2012 - 09:35
fonte
0

Penso che questo possa essere riassunto in quanto non creare un oggetto solo per chiamare un singolo metodo su di esso e quindi distruggerlo e questo è un buon consiglio nel mondo OOP. Ricordo di aver visto un video poderoso su infatti .

Nel mondo funzionale, specialmente in Haskell (come i suoi pigri), è spesso vero il contrario. Un modello comune è costruire un'enorme struttura di dati, solo per scomporla immediatamente. Essendo pigro e se fatto bene, Haskell non usa molta memoria facendo questo.

    
risposta data 22.04.2012 - 09:37
fonte
0

Il punto che vedo in quell'esempio di area del cerchio è che le tue funzioni non dovrebbero richiedere parametri che non usano.

Una funzione area del cerchio ha solo bisogno di conoscere il raggio, quindi dovrebbe solo prendere il raggio come parametro. Questo principio può essere esteso da semplici funzioni a blocchi di codice di qualsiasi dimensione. Le tue classi non dovrebbero dipendere da altro codice di cui non hanno bisogno. Allo stesso modo le tue DLL dovrebbero richiedere solo altre DLL che in realtà hanno bisogno .

Riducendo al minimo le dipendenze e i dati richiesti dal codice, è più semplice da utilizzare e più facile da riutilizzare. Rende anche molto più semplice il collaudo delle unità.

    
risposta data 22.04.2012 - 16:11
fonte

Leggi altre domande sui tag