Un grande inizializzatore statico è un odore di codice?

8

Sto estendendo SimpleExpandableListAdapter in Android. Non penso che l'adattatore di Android sia implementato molto bene, in quanto i suoi costruttori hanno un gran numero di argomenti piuttosto complicati e non ha setter o builder. Nella mia classe, la maggior parte di questi argomenti non dipende dalla classe chiamante, quindi voglio costruirli internamente. Tuttavia, gli argomenti sono nidificati List s e matrici di interi e stringhe che devono essere creati a livello di programmazione.

Poiché non è possibile chiamare nulla prima del costruttore super e non è possibile chiamare i metodi di istanza prima che la chiamata di super torni, al momento ho diversi metodi statici che chiamo dalla chiamata super :

super(getContext(), initGroupData(), groupLayout, initGroupFrom(), initGroupTo(),
        initChildData(), childLayout, initChildFrom(), initChildTo());

Vedo tre modi per gestirlo: chiamare metodi statici come sono ora, con un inizializzatore statico di grandi dimensioni che probabilmente chiama questi stessi metodi per inizializzare le variabili statiche che vengono poi utilizzate nella chiamata super , o incapsulare tutte queste metodi in un costruttore.

Penso che ora mi sto appoggiando al costruttore, ma mi chiedo se c'è un modo migliore per gestirlo.

    
posta TBridges42 27.09.2015 - 17:55
fonte

1 risposta

9

Avere funzioni di supporto statiche per creare l'argomento del costruttore è una soluzione perfettamente sana, ma queste funzioni sono limitate nelle operazioni che possono eseguire poiché devono produrre esattamente un argomento ciascuna e non possono comunicare tra loro.

Nel caso più generale in cui si desidera adattare un'interfaccia Constructor(A, B, C) a un'interfaccia più utilizzabile Constructor(X, Y) , è possibile definire un costruttore di helper privato che accetta%%% e catene per il costruttore esistente. Il costruttore più utilizzabile quindi esegue una catena al costruttore di helper tramite una funzione di supporto statico per creare l'oggetto argomento:

class Constructor {
  // constructor you want to wrap
  public Constructor(A a, B b, C c) { ... }
  // better constructor you are defining
  public Constructor(X x, Y y) { this(createArgumentObject(x, y)); }
  // helper constructor using an ArgumentObject
  private Constructor(ArgumentObject ao) { this(ao.a, ao.b, ao.c); }
  // helper to create the argument object
  private static ArgumentObject createArgumentObject(X x, Y y) { ... }
  private static class ArgumentObject { ... }
}

Nelle lingue che non hanno il concatenamento del costruttore all'interno della stessa classe (come C ++ 03), dovresti definire una sottoclasse intermedia per il costruttore helper.

Tuttavia, questa tecnica è semplicemente una generalizzazione dell'uso delle funzioni statiche negli argomenti del costruttore. Le altre soluzioni che hai proposto hanno vari inconvenienti, motivo per cui vorrei evitarli a meno che non ci sia un buon motivo per preferirle:

  • l'implementazione di buoni costruttori richiede un grande sforzo per pochissimo valore. Se il nuovo costruttore è abbastanza semplice, puoi fare a meno di un costruttore. Supponendo che la classe che si sta eseguendo esegua una validazione solida, si potrebbe rendere pubblico l'argomento object in modo che gli argomenti possano essere passati usando l'idioma ArgumentObject .

  • l'uso di variabili statiche calcolate in un blocco di inizializzazione statico ha senso per dati veramente statici, ma occorre prestare attenzione per evitare lo stato globale. A meno che l'inizializzazione non sia molto semplice, è necessario utilizzare le funzioni statiche per inizializzare queste variabili affinché l'inizializzazione sia verificabile. Ora, l'unico vantaggio rispetto all'utilizzo diretto dei metodi statici è che i valori vengono calcolati una sola volta e riutilizzati per tutte le inizializzazioni.

    Dato che la tua domanda indica che queste inizializzazioni potrebbero essere più complesse, l'uso di blocchi di inizializzazione statici è un grosso problema se la testabilità è importante per te. (Se non lo è, hai più problemi urgenti.)

risposta data 27.09.2015 - 19:06
fonte

Leggi altre domande sui tag