Come modellare un numero arbitrario di tipi

3

Attualmente sono in fase di modellazione di una forma generica di trascrizione di RNA e RNA e sto riscontrando difficoltà nel trovare una modellazione OO corretta di questa area.

L'RNA umano ha 4 tipi di Nucleotidi (A, G, U e C). Un filamento di RNA è solo una stringa di questi 4 tipi. ad esempio, AAGACAUUCUA ...

Quello che sto cercando di modellare è più generico nel senso che voglio essere in grado di decidere il numero di tipi Nucleotide in fase di runtime. Quindi, il mio modello di oggetti deve essere in grado di rappresentare un numero arbitrario di tipi di nucleotidi .

Inizialmente, pensavo di avere solo una classe Nucleotide con un membro int TypeId . In questo modo, potrei avere una sequenza di istanze Nucleotide di tipi arbitrari ... ma questo non sembra giusto.

Non sono un grande fan del tipo di archiviazione in una variabile. Inoltre, non mi sento a mio agio con ciò che è essenzialmente definizione informazioni impostate su ogni istanza (invece di essere definite nella classe a).

Quindi, come faccio a evitare questo? Ecco cosa ho scoperto finora:

  • In un progetto precedente, avremmo degli oggetti Singleton che rappresentavano il tipo di un altro oggetto. L'altro oggetto farebbe semplicemente riferimento al singleton e così è stato. Ci ha impedito di avere più istanze della "definizione" dei nostri tipi. IMO non troppo grande.
  • Ricordo Entity Framework che genera proxy dinamici in fase di runtime. Potrei quindi qualcosa di simile. Potrei avere una classe base NucleotideBase e, in fase di runtime, definire le classi derivate. Credo che questo sia possibile attraverso la riflessione. Non sono sicuro di quale sia l'impatto sulle prestazioni con questo approccio, ma suppongo che si tratti di un unico overhead durante la definizione delle classi.

Ci sono migliori, più OO, approcci?

    
posta MetaFight 26.08.2013 - 16:45
fonte

4 risposte

11

Se un nucleotide non ha un comportamento significativo e se le sue informazioni sul tipo possono essere rappresentate in modo compatto (ad esempio, un singolo carattere), allora non merita affatto una classe separata. Rappresenta semplicemente ogni nucleotide come un personaggio (o qualsiasi altra cosa).

Se, tuttavia, un nucleotide ha un comportamento, modellerei questo con i singleton, un caso per ogni tipo di nucleotide.

Poiché non vi è alcuna differenza nel comportamento nei nucleotidi, sono oggetti di valore semplice. Un'istanza nucleotidica dovrebbe essere immutabile, in modo che tutti i nucleotidi di un determinato tipo possano essere rappresentati da una singola istanza.

Vorrei usare il simbolo del nucleotide come suo tipo; questa sarebbe l'unica variabile di istanza di un Nucleotide.

Una fabbrica di nucleotidi può tenere traccia delle istanze singleton del nucleotide, creando una nuova istanza quando viene richiesto un nuovo tipo di nucleotide o restituendo un'altra istanza esistente. A seconda del linguaggio, può essere conveniente che questa fabbrica sia implementata in metodi statici della classe nucleotidica.

    
risposta data 26.08.2013 - 17:18
fonte
3
  • Vorrei usare byte TypeId invece di int TypeId , perché quando si creano filamenti di RNA con lunghe liste di nucleotidi, non si vuole sprecare 4 volte la memoria di cui si ha realmente bisogno. Il TypeId dovrebbe essere l'unico membro attributo di quella struct . Se hai bisogno di informazioni aggiuntive per alcune operazioni, prova a utilizzare il modello di peso vivo . Quindi un List<Nucleotide> con 1000 elementi avrà bisogno di quasi esattamente 1000 byte in memoria, con overhead trascurabile (in C #).

  • se non ci si aspetta comportamenti diversi per i diversi tipi di nucleotidi, è del tutto sbagliato per me utilizzare diverse classi derivate per rappresentare i tipi. Non complicare eccessivamente le cose: solo perché diverse classi derivate possono essere utilizzate tecnicamente per distinguere i tipi, non è sempre la soluzione migliore.

risposta data 26.08.2013 - 22:17
fonte
1

Che ne dici di un enum per il tipo?

[Flags]
public enum Nucleotide : byte {
    undefined =0,
    A = 1,
    G = 1 << 1,
    U = 1 << 2,
    C = 1 << 3
    . . . 
    Z = 1 << 25   // of course a byte can't handle this
}
  • Estensibile facilmente come mostrato. La notazione mi impedisce di dover scrivere effettivamente il valore di 2^25 per Z

  • Riesco a vedere la manipolazione di List<byte> o List<Nucleotide> o Stream come necessario e di casting se / quando necessario.

  • Utile per passare a Factory per creare oggetti comportamentali specifici di Nucleotide
  • A Nucleotide La proprietà in qualche altra classe rende in modo efficace la sottoclassificazione.
  • L'attributo Flags ci permetterà di definire semplici combinazioni Nucleotide , o anche di separare enum s di quelle. Puoi andare pazzo manipolando il bit astratto con enum suppongo. La manipolazione diretta bit a bit potrebbe mitigare i problemi del tempo di esecuzione e rendere il codice espressivo in termini Nucleotide .
  • enums sono essenzialmente costanti e compila a costanti in IL , cioè buone prestazioni. La trasmissione è veloce .

.

[Flags]
public enum Pairs : byte {
    AC = Nucleotide.A | Nucleotide.C,
    GC = Nucleotide.G | Nucleotide.C, 
    . . .
}

Modifica

@MichaelT commento mi ha fatto pensare alla struttura rispetto alla classificazione; quello, e io sono con il commento di DocBrown "..non complicare le cose". Mi sembra che la struttura sia classificazione.

La classe

Tuple potrebbe essere utile. È inteso come una struttura di dati generica.

var Phenylalanine = 
   Tuple.Create(Nucleotide.T,Nucleotide.T,Nucleotide.T);

"non esiste un limite pratico al numero di componenti che può avere una tupla ... puoi creare tuple di otto o più elementi annidando gli oggetti tupla nella proprietà Rest"

Tuple è immutabile, quindi può essere trattato come un singleton.

Implementa IStructuralEquatable per quei codoni. La classe 3-Tuple implementa esplicitamente IStructuralEquatable .

Naturalmente è tipizzato, quindi questo sembra adattarsi alla necessità di creare tipi in fase di esecuzione. Forse usa un Factory per incapsulare un oggetto Tuple specifico con la sua implementazione IStructrualEquatable.

    
risposta data 27.08.2013 - 20:18
fonte
0

Vorrei provare quanto segue per i principianti.

A , G , U e C dovrebbero tutti derivare da una classe base nucleotide - sono istanze specifiche della classe astratta rappresentata da nucleotide. Nel linguaggio di modellazione OO " A è un nucleotide "

Questo ti dà la possibilità di estendere tutte e 4 le classi di nucleotidi contemporaneamente o solo il singolo nucleotide.

Avrai bisogno di un'altra classe per modellare il Strand in quanto un filamento è composto da una serie di nucleotidi. " Strand ha una (lista di) nucleotides ". Puoi anche estendere la classe Strand per eseguire operazioni di cui un filamento sarebbe responsabile ma che un nucleotide non sarebbe responsabile.

Ho anche aggiunto un'interfaccia per gli scopi "just in case". Per gli usi immediati, la classe nucleotidica di base dovrebbe essere sufficiente, ma in caso contrario, un'interfaccia è lì per aiutare a garantire il comportamento.

Allo stesso modo, ho usato una raccolta List nel Strand , quindi non devo preoccuparmi di particolari come la lunghezza del filo durante la prima modellazione. La maggior parte delle lingue OO dovrebbe avere una raccolta generica equivalente da usare.

class Program
{
    static void Main(string[] args)
    {
        Strand myStrand = new Strand();

        myStrand.Add(new A());
        myStrand.Add(new G());
        myStrand.Add(new U());
        myStrand.Add(new C());
    }
}

public interface INucleotide 
{
}

public class Nucleotide : INucleotide
{
    public byte TypeID;
}

public class A : Nucleotide {}
public class G : Nucleotide {}
public class U : Nucleotide {}
public class C : Nucleotide {}

public class Strand
{
    private List<INucleotide> Nucleotides = new List<INucleotide>();
    public void Add(INucleotide nuc)
    {
        Nucleotides.Add(nuc);
    }
}

L'esempio sopra è in C #.

I single non sono davvero appropriati per questo esercizio di modellazione - non c'è nulla di "single" su ciò che stai modellando. Avrai potenzialmente molte istanze di A , G , U e C e Strand s.

    
risposta data 27.08.2013 - 19:26
fonte

Leggi altre domande sui tag