Implementazione del codice funzionale / riutilizzabile [chiuso]

-3

Scrivere codice, a mio parere, di solito comporta 2 tipi di codice: codice logico e funzionale.

Sebbene la parte logica del codice differisca sempre tra ogni app e i suoi obiettivi, spesso la parte funzionale non cambia molto (specialmente il codice funzionale semplice di basso livello) ed è spesso riutilizzata nello stesso progetto.

Ad esempio, nella mia app uso molto codice relativo al file. Così ho creato una classe util dedicata in questo modo:

public final class FileUtils {

/* Constants */
private static int DEFAULT_BUFFER_SIZE = 1024;
public static final String PACKAGE_FILES_DIR = MyApplication.getContext().getFilesDir().getAbsolutePath(); // Usually: /data/data/package name/files
public static final String MAIN_LOCAL_STORAGE = Environment.getExternalStorageDirectory().getAbsolutePath(); // Usually:


/*
 * ================
 * Constructor
 * ================
 */

private FileUtils() {}


/*
 * ================
 * Helper methods
 * ================
 */

/**
 * Write text to file.
 * <a>{@see javadoc at the beginning of this class}</a>
 *
 * @param path     the path
 * @param fileName the file name
 * @param text     the text
 */
public static void writeTextToFile(String path, String fileName, String text) {

    File file = new File(path, fileName.toString());

    try {
        file.createNewFile();
        FileOutputStream fos = new FileOutputStream(file);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fos, "UTF-8");
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
        out.write(text.toString());
        out.close();
        fos.close();
        outputStreamWriter.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * Check and create sub dierctory.
 * <a>{@see javadoc at the beginning of this class}</a>
 *
 * @param path       the path
 * @param folderName the folder name
 */
public static void checkAndCreateSubDierctory(String path, String folderName) {
    // Check and if needed, create logs subdirectory
    File subDir = new File(path, folderName);
    if (!subDir.exists()) {
        subDir.mkdir();
    }
}

public static void createZip(){
// create a zip including several files
}
}

Il fatto è che non ho visto molto codice scritto in questo modo. I pro ei contro che vedo in questo approccio sono:

Pro:

  • Rende la parte logica del codice molto più chiara

  • Il codice funzionale non viene riscritto ed è accessibile ovunque

  • Per quanto ne so, il punto di static è un codice che non ha bisogno di essere istanziato ed è comune a tutti.

Aspetti negativi:

  • Può causare una quantità enorme di codice statico.

Un altro approccio possibile sarebbe:

public class FileUtils {

/* Constants */
private static int DEFAULT_BUFFER_SIZE = 1024;
public static final String PACKAGE_FILES_DIR = MyApplication.getContext().getFilesDir().getAbsolutePath(); // Usually: /data/data/package name/files
public static final String MAIN_LOCAL_STORAGE = Environment.getExternalStorageDirectory().getAbsolutePath(); // Usually:


/*
 * ================
 * Helper methods
 * ================
 */

/**
 * Write text to file.
 * <a>{@see javadoc at the beginning of this class}</a>
 *
 * @param path     the path
 * @param fileName the file name
 * @param text     the text
 */
public void writeTextToFile(String path, String fileName, String text) {

    File file = new File(path, fileName.toString());

    try {
        file.createNewFile();
        FileOutputStream fos = new FileOutputStream(file);
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fos, "UTF-8");
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
        out.write(text.toString());
        out.close();
        fos.close();
        outputStreamWriter.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * Check and create sub dierctory.
 * <a>{@see javadoc at the beginning of this class}</a>
 *
 * @param path       the path
 * @param folderName the folder name
 */
public void checkAndCreateSubDierctory(String path, String folderName) {
    // Check and if needed, create logs subdirectory
    File subDir = new File(path, folderName);
    if (!subDir.exists()) {
        subDir.mkdir();
    }
}

public void createZip(){}

}

Pro:

  • Non usa il codice statico

Aspetti negativi:

  • Ogni volta che vorrei usare il codice, avrei bisogno di istanziare la classe, qualcosa che potrebbe portare alla creazione di molti oggetti

Naturalmente, c'è sempre l'opzione di scrivere il codice localmente in ogni classe, ma che a mia conoscenza viola anche i principi OOP e porta a una maggiore quantità di codice che potrebbe essere salvato ...

Ho cercato molto su questo argomento e non sono riuscito a trovare risposte o approcci concreti.
È un approccio accettabile alla programmazione orientata agli oggetti?
Qualcuno può spiegare perché e quali sono le alternative a questo approccio?

    
posta henengel 02.08.2017 - 22:23
fonte

2 risposte

1

Queste due cose qui non sono affatto "pro":

  • Functional code is not rewritten and is accessible from anywhere

  • To my knowledge, the point of static is code that doesn't need to be instantiated and is common to all.

"Accessibile da qualsiasi luogo" e "comune a tutti" significa che non gestisci affatto le tue dipendenze. Cambia qualcosa in un posto e non si sa quante parti del tuo codice saranno interessate. Questo è l'opposto del buon design. È pessimo come usare le variabili globali ovunque.

I simboli, comprese le variabili e i nomi delle funzioni, dovrebbero essere esaminati il più strettamente possibile e resi disponibili solo a quelle parti del sistema che ne hanno bisogno. Inoltre, quando si forma una dipendenza, dovrebbe essere su un'interfaccia, non un'implementazione concreta (si veda Principio di sostituzione di Liskov ). I metodi statici non possono partecipare a un'interfaccia.

    
risposta data 02.08.2017 - 23:52
fonte
1

I professionisti orientati agli oggetti di solito si oppongono al metodo statico per diversi motivi:

  1. Non ottieni l'incapsulamento OO.
  2. Non puoi usare oggetti mock con una classe statica.
  3. I metodi statici possono contenere lo stato statico, che è difficile da testare.
  4. Il tuo metodo statico può dipendere da altri metodi statici non funzionanti.

Generalmente queste obiezioni derivano da persone che sono abituate a programmare usando oggetti. Prima c'erano oggetti, c'erano linguaggi procedurali come Fortran, Pascal e C. Gli oggetti sono diventati comuni nel panorama della programmazione perché forniscono un contenitore familiare e facile da usare per incapsulare dati e comportamenti correlati.

Ma Linus Torvalds è la prova vivente che è possibile programmare sistemi piuttosto grandi senza mai toccare un oggetto (egli programma in C, che non è un linguaggio orientato agli oggetti), usando ciò che sono essenzialmente strutture e metodi.

Quindi esaminiamo le obiezioni a turno:

Non ottieni l'incapsulamento OO

È vero. Ma ci sono modi per aggirare questo problema. In C, puoi farlo seguendo semplici regole ragionevoli per nominare le cose e organizzare le tue librerie e i file di intestazione. È molto lavoro? Può essere. Può certamente essere più lavoro che usare semplicemente spazi dei nomi e classi, ma ho anche visto la convenienza di spazi dei nomi e classi abusati per creare architetture sconfinate.

Non puoi usare oggetti fittizi con una classe statica

Ma neanche tu hai bisogno di loro. Un metodo statico appropriato non richiede mock, stub, interfacce o altri macchinari tipicamente riservati per il test dell'unità OO. Devi semplicemente passare al metodo alcuni valori di parametro e asserire il risultato di ritorno. Questo è tutto.

I metodi statici possono contenere lo stato statico, che è difficile da testare

Quindi non mantenere lo stato statico. Non ti servirà comunque, a meno che tu non stia scrivendo un registratore o creando il singleton di un povero.

Il tuo metodo statico può dipendere da altri metodi statici non funzionanti

Presumibilmente, hai metodi di test che esercitano quell'altro, presumibilmente metodo rotto, eh?

Gli sviluppatori OO hanno esaminato questo problema rispetto ai metodi privati e hanno raggiunto la conclusione opposta: non dovresti testare i tuoi metodi privati perché sono già stati testati indirettamente attraverso il tuo pubblico metodi!

    
risposta data 02.08.2017 - 22:54
fonte

Leggi altre domande sui tag