Quale interfaccia pubblica dovrei offrire per creare oggetti che conoscono l'un l'altro?

3

Sto creando una libreria in C # che verrà utilizzata per interrogare i database.

Per utilizzare questa libreria, un utente deve prima dire alla biblioteca cosa contiene lo schema del database, creando Schema , Table e Column oggetti.

Un oggetto Schema è composto da:

  • Un nome, che è un string .
  • Una raccolta di Table oggetti di sua proprietà.

Un oggetto Table è composto da:

  • Un riferimento all'oggetto Schema che lo possiede.
  • Un nome, che è un string .
  • Una raccolta di Column oggetti di sua proprietà.

Infine, un oggetto Column è composto da:

  • Un riferimento all'oggetto Table che lo possiede.
  • Un nome, che è un string .
  • Un tipo, che è uno dei valori String , DateTime e Reference .
  • Se il tipo è Reference , quindi un target, che è un riferimento a un Table oggetto all'interno dello stesso Schema .

Posso pensare a un sacco di modi per progettare un'interfaccia pubblica per la creazione di questi oggetti, ma tutti hanno dei difetti. Quale approccio dovrei usare?

Ecco le idee che ho pensato:

Fornisci solo classi mutevoli

L'utente può creare Schema , Table e Column oggetti e quindi modificare tutte le proprietà di questi oggetti dopo il fatto.

Svantaggi:

  • Garantire che gli stati di questi oggetti rimangano coerenti tra loro potrebbe essere difficile.
  • Poiché tutti questi oggetti sono mutabili, l'utente dovrà tenere presente che potrebbe cambiare in qualsiasi momento. (E anche io, l'autore della biblioteca!)

Fornire solo classi immutabili: edizione naive

Le classi Schema , Table e Column sono tutte immutabili. Tutte le proprietà di questi oggetti devono essere specificate al momento della creazione. Non puoi creare un Schema senza specificare tutto il Table s che contiene e non puoi creare un Table senza specificare a quale Schema appartiene.

Fatal downside:

  • La creazione di oggetti non sarebbe effettivamente possibile: non è possibile creare uno schema senza prima creare le sue tabelle e non è possibile creare tabelle senza prima creare lo schema.

Fornisce solo classi immutabili: costruzione dal basso verso l'alto

Per prima cosa, crei oggetti Column . Successivamente, crei Table oggetti passando in Column oggetti. Infine, crei un oggetto Schema passando in Table oggetti. Tutte queste classi sono immutabili.

Svantaggi:

  • L'oggetto Column non può avere una proprietà che indica a quale Table appartiene la colonna, poiché l'oggetto Column viene creato prima che l'oggetto Table sia, e l'oggetto Column sia immutabile. Allo stesso modo, l'oggetto Table non può avere una proprietà che indica a quale Schema appartiene.
  • La proprietà "tabella di destinazione" di un oggetto Column dovrà essere solo una stringa, non un riferimento a un oggetto Table .
  • L'utente API è costretto a creare oggetti in un ordine specifico. Cosa fare se si desidera creare prima le tabelle e aggiungere colonne in un secondo momento?

Fornisci due tipi di classi immutabili

Fornire due famiglie di classi. Innanzitutto, ci sono le classi SchemaDefinition , TableDefinition e ColumnDefinition , che funzionano esattamente come nell'approccio "bottom-up construction".

Esistono anche Schema , Table e Column classi, anch'esse immutabili. Queste classi hanno tutte le proprietà che potresti sperare: un Schema ha una proprietà che ti dice di tutto il suo Table s, e un Table ha una proprietà che ti dice a quale Schema appartiene.

Le classi Schema , Table e Column non hanno costruttori pubblici. Invece, c'è una classe SchemaFactory che prende un SchemaDefinition e la usa per creare un gruppo di Schema , Table e Column oggetti, e poi ti dà Schema .

Svantaggi:

  • Ci sono due classi per ogni tipo di oggetto di business, invece di uno solo.
  • L'utente API è ancora obbligato a creare oggetti in un ordine specifico.

Fornire classi mutevoli e immutabili

Fornire due famiglie di classi. Innanzitutto, ci sono le classi SchemaMutable , TableMutable e ColumnMutable , che funzionano esattamente come nell'approccio "fornire solo classi mutabili".

Esistono anche Schema , Table e Column classi, che funzionano proprio come nell'approccio "due tipi di classi immutabili". Esiste una classe factory che prende un SchemaMutable e ti dà Schema .

Svantaggi:

  • Ancora una volta, ci sono due classi per ogni tipo di oggetto di business.
  • E ancora, garantire che gli stati di questi oggetti rimangano coerenti tra loro potrebbe essere difficile.
posta Tanner Swett 20.09.2016 - 22:37
fonte

2 risposte

3

C'è un altro approccio per risolvere questo problema. Potresti utilizzare le classi che sono immutabili per il consumatore dell'API. Potresti quindi includere una classe extra, che si occupa della creazione di oggetti e del loro collegamento. Questa classe potrebbe avere accesso interno per mutare gli oggetti. Poiché ora hai il pieno controllo degli scenari che desideri supportare per la creazione e la modifica degli oggetti, puoi ragionare sulle cose che devi controllare e aggiornare per ciascuno di questi scenari.

I costruttori per questi oggetti sarebbero privati.

L'utente dell'API dovrebbe solo conoscere la classe Context, ma da quel momento l'API è auto-scoperta.

    
risposta data 21.09.2016 - 11:13
fonte
1

Non perfetto ma potrebbe andare con una scrittura una volta

private string prop = string.Empty;
public string Prop 
{
    get { return prop; }
    set 
    {
        if (string.IsNullOrEmpty(prop))
           prop = value;
    }
}

op modifica la domanda

così per costruttore Schema

public Schema ( List<columun> columns, string name ) 
{
     foreach (column col in columns)
     {
        if (col != null)
           throw proper exception
        col.Schema = this;
     }
     _columns = columns; 
     _name = name;
}
    
risposta data 22.09.2016 - 15:00
fonte

Leggi altre domande sui tag