Enum e principio di responsabilità singola (SRP)

4

Sono stato sperimentare ultimamente con enumerazioni, e Ho scoperto che in Java possono fare molto di più che semplicemente rappresentare un insieme fisso di costanti.

Ora, sto pensando di creare una nuova enumerazione per la mia classe Logger, per tenere i diversi livelli di gravità del registro (informazioni, avvertenze, errori, ecc.), ma mi chiedo perché non dovrei fare un passo avanti e fare in modo che il mio enum esegua la stessa registrazione ed evitare del tutto la classe di registrazione? (grazie al framework che sto usando, il codice che fa il log è più semplice).

  1. D'altra parte, e in generale, non si tratta di una violazione di l'SRP? In generale, un enum non dovrebbe servire al suo scopo principale (enumera i valori) invece di fornire alcuni ulteriori funzionalità (come nei miei due esempi)?
  2. Dovrei semplicemente limitarmi alle enumerazioni, proprio come suggerisce il loro nome e evitare la tentazione di utilizzare le funzionalità che Java porta a questo tipo di dati? Quali sarebbero i tuoi criteri per valutare quanto funzionalità da mettere su enumerazioni?
posta carlossierra 12.05.2016 - 19:19
fonte

3 risposte

6

Forse è perché ho usato C / C ++ in una vita precedente, ma direi strongmente per mantenere semplice l'enumerazione. In quelle lingue un enum era solo un glorificato intero. In Java, come dici tu, sono davvero un vero oggetto. Ma io sento che lo stimolo di un enum non è di avere un sacco di codice in là - un'enumerazione è un elenco completo, ordinato di tutti gli articoli in una raccolta . Mi piace questa definizione perché non implica alcun comportamento - solo un contenitore.

    
risposta data 12.05.2016 - 19:44
fonte
2

In Java, le enumerazioni sono progettate per essere più che semplici costanti. I valori Enum sono oggetti (come quello che potresti instanciare da qualsiasi classe standard) ma con alcune restrizioni:

  • Le istanze di un enum sono limitate da te: quando scrivi enum Number {ONE, TWO, THREE;} dici esplicitamente che le tre istanze sono le uniche a cui è permesso vivere
  • Java si prende cura di instanciare le istanze dell'enum (quindi il costruttore deve essere private )
  • Java genera anche una serie di metodi di supporto per aiutarti a utilizzare queste istanze di enum ( values() , valueOf() , ...)

Poiché sono oggetti e dal momento che gli oggetti hanno un comportamento, è perfettamente soddisfacente avere metodi in enumerazione.

Tuttavia, ho raramente affrontato un caso in cui ho finito per implementare qualcosa del genere. L'unica volta che lo faccio è quando ho un class che conosco dai requisiti o dal dominio può avere solo un insieme noto di istanze . Esempio:

Norm A describe how a device counting energy should be identified.

Company X is working in energy domain and produces 3 devices that are separately identified according to norm A. Let's say that these 3 devices are identified as such:

  • Device1 is from generation 1 and of type 1
  • Device2 is from generation 2 and of type 2
  • Device3 is from generation 2 and of type 1

I am mandated by Company X to create a software that manage data extracted from these 3 devices.

Quindi questa potrebbe essere una potenziale classe che modella un dispositivo da Azienda X :

public final class CompanyXDevice {
    private final int generation;
    private final int deviceType;

    public CompanyXDevice(int generation, int deviceType) {
        this.generation = generation;
        this.deviceType = deviceType;
    }

    public int[] generateHistoricalData() {
        ...
    }

    ...
}

Tutto potrebbe funzionare perfettamente qui ... tranne che è possibile fare qualcosa del genere: new CompanyXDevice(3, 3); che non dovrebbe essere consentito poiché CompanyX non ha tale dispositivo. Il prossimo passo è trovare un modo per limitare le possibilità di instanciazione. Questo può essere ottenuto (non solo) rifattorizzando un enum:

public enum CompanyXDevice {
    DEVICE_1(1, 1),
    DEVICE_2(2, 2),
    DEVICE_3(2, 1);

    private final int generation;
    private final int deviceType;

    private CompanyXDevice(int generation, int deviceType) {
        this.generation = generation;
        this.deviceType = deviceType;
    }

    public int[] generateHistoricalData() {
        ...
    }

    ...
}

Ora è possibile giocare solo con dispositivi che riflettono realmente un dispositivo reale di Azienda X .

    
risposta data 12.05.2016 - 21:16
fonte
1

Sembra che stai pensando a "valori" in modo limitato (magari applicando un concetto da altre lingue).

Che cosa succede se hai ampliato la tua idea dei tipi di valori che possono essere enumerati? Ciò apre una vasta gamma di possibili usi. La tua saggezza progettuale ti impedirà di fare cose orribili con quel potere terrificante.

Prova questo:

  • Pensa a enum come nient'altro che a un tipo con un set fisso di valori.
  • Espandi il tuo concetto di valori di enum per adattarli a qualsiasi cosa consenta Java.
  • Applica tutta la tua saggezza progettuale, dato il concetto espanso di enum .
risposta data 12.05.2016 - 21:08
fonte

Leggi altre domande sui tag