4

I'm currently in the process of modelling a generic form of RNA and RNA transcription and I'm having difficulty finding a proper OO modeling of this area.

Human RNA has 4 types of Nucleotides (A, G, U, and C). An RNA strand is just a string of these 4 types. eg, AAGACAUUCUA...

What I'm trying to model is more generic in the sense that I want to be able to decide the number of Nucleotide types at runtime. So, my object model needs to be able to represent an arbitrary number Nucleotide types.

Initially, I thought I'd just have a Nucleotide class which had a int TypeId member. This way, I could have a sequence of Nucleotide instances of arbitrary types... but this doesn't feel right.

I'm not a huge fan of storing type in a variable. I'm also not comfortable with what is essentially definition information being set on every instance (instead of being defined in the a class).

So, how do I get around this? Here's what I've come up with so far:

  • On a previous project, we would have Singleton objects which represented another object's type. The other object would simply reference the singleton and that was it. It prevented us from having multiple instantiations of the "definition" of our types. Not too great IMO.
  • I remember Entity Framework generating Dynamic Proxies at runtime. I could so something similar. I could have a NucleotideBase base class and, at runtime, define derived classes. I believe this is possible through reflection. I'm not sure what the performance impact is with this approach, but I would assume it's all just one-time overhead when defining the classes.

Are there better, more OO, approaches?

7
  • 5
    What difference in behavior is there between two nucleotides of different types? Commented Aug 26, 2013 at 14:50
  • Nothing, yet. A grouping of nucleotides will eventually represent a codon (a genetic instruction), but the nucleotides themselves don't do much. Nucleotides in a strand will get read/parsed and transcribed, but the nucleotide is just data and doesn't do anything itself. But, to be honest, my knowledge of this is still incomplete, so it is quite possible that the nucleotides types will each eventually have distinct behaviours.
    – MetaFight
    Commented Aug 26, 2013 at 14:57
  • 1
    Your "Not too great IMO" solution is my favorite. What caused you to dislike it? Commented Aug 26, 2013 at 15:21
  • I don't like the idea of "definition" information being stored in an object instance. Using singletons minimizes the ick-factor. I imagine this must be a fairly common problem, so I assume brighter people than me have found better solutions :)
    – MetaFight
    Commented Aug 26, 2013 at 15:23
  • 2
    It occurs to me that a nucleotide might not deserve its own class at all: If it has no significant behavior, then represent it with, e.g., a character. Commented Aug 26, 2013 at 15:36

4 Answers 4

11

If a nucleotide has no significant behavior, and if its type information can be represented compactly (for example, a single character), then it doesn't deserve a separate class at all. Simply represent each nucleotide as a character (or whatever).

If, however, a nucleotide has behavior, then I would model this with singletons, one instance per nucleotide type.

Since there is no difference in behavior in nucleotides, they are simple value objects. A nucleotide instance should be immutable, so that all nucleotides of a given type can be represented by a single instance.

I would like to use the nucleotide's symbol as its type; this would be the sole instance variable of a Nucleotide.

A nucleotide factory can keep track of the singleton instances of nucleotide, creating a new instance when a new nucleotide type is asked for, or returning an existing instance otherwise. Depending upon the language, it may be convenient for this factory to be implemented in static methods of the nucleotide class.

8
  • wow, this is exactly what I've currently done as a place-holder solution. We'll see if it becomes my final solution ;)
    – MetaFight
    Commented Aug 26, 2013 at 15:21
  • I agree. @MetaFight Also, look at it from practical side. RNA is huge. Representing each Nucleotide as separate class would cause huge overhead. So from practical point, representing RNA as simple array of bytes is best solution.
    – Euphoric
    Commented Aug 26, 2013 at 17:37
  • 1
    @MetaFight Even then, references can take 32/64 bits each, depending on OS. Considering you will probably never need more than 256 Nucleodite types, you can get 4 to 8 times smaller memory footprint when you use simple array of bytes.
    – Euphoric
    Commented Aug 26, 2013 at 21:38
  • 2
    To be pedantic, what you describe isn't a Singleton at all but a flyweight.
    – Telastyn
    Commented Aug 28, 2013 at 13:17
  • 1
    @WayneConrad: well, the gist of the flyweight is not to store object references (singleton or not) in each object, but to pass extrinsic context on each method of the flyweight which needs that context from outside, instead of storing the context within the object. See my answer how to implement a flyweight in C# using just 1 byte per TypeId instead of 4. I admit, the Wikipedia article is not very good, better have a look into the original GOF book.
    – Doc Brown
    Commented Aug 28, 2013 at 15:45
3
  • I would use byte TypeId instead of int TypeId, because when you make RNA strands with long lists of Nucleotides, you don't want to waste 4 times of the memory you really need. The TypeId should be the only member attribut of that struct. If you need additional information for some operations, try to use the Flyweight pattern. So a List<Nucleotide> with 1000 elements will need almost exactly 1000 bytes in memory, with neglectable overhead (in C#).

  • if you don't expect different behaviours for different Nucleotide types, it feels complety wrong for me to use different derived classes for representing the types. Don't overcomplicate things - only because different derived classes can technically be used for distinguishing types, it is not always the best solution.

2
  • I'm not sure I understand. For the case of 4 nucleotide types and a strand of 1000 nucleotides, wouldn't that be 4 instances of the Nucleotide struct (4 * 1 byte) and then 1000 references (1000 * 4 bytes) which adds up to 4004 bytes?
    – MetaFight
    Commented Aug 26, 2013 at 21:12
  • 1
    @MetaFight: you may miss the point that structs are quite different from classes in C#. Say you have your example from above, AAGACAUUCUA, a list of eleven Nucleotides. Gives you eleven instances of the "Nucleotide" class, each one needs just one byte. Structs are value types in C#, not reference types, and the memory layout in a generic List is AFAIK compact.
    – Doc Brown
    Commented Aug 27, 2013 at 7:08
1

How about an enum for the Type?

[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
}
  • Easily extensible as shown. The notation keeps me from having to actually write out the value of 2^25 for Z

  • I can see manipulating List<byte> or List<Nucleotide> or Stream as needed and casting if/when necessary.

  • Handy for passing to a Factory to build Nucleotide-specific behavior objects
  • A Nucleotide Property in some other class effectively makes sub-classing unnecessary.
  • The Flags attribute will allow us to define simple Nucleotide combinations, or even separate enums of those. You can go kinda crazy abstracting bit manipulation via enum I suppose. Direct bitwise manipulation could mitigate execution time issues and make the code expressive in Nucleotide terms.
  • enums are essentially constants and compile to constants in IL, i.e. good performance. Casting is quick.

.

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

EDIT

@MichaelT comment got me thinking about structure vis-a-vis classification; that, and I'm with DocBrown's comment "..don't over complicate things." It seems to me that structure is classification.

Tuple class may be useful. It is intended as a generic data structure.

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

"there is no practical limit to the number of components a tuple may have ... you can create tuples of eight or more elements by nesting tuple objects in the Rest property "

Tuple is immutable so it can be treated kinda like a singleton.

Implement IStructuralEquatable for those codons. The 3-Tuple class explicitly implements IStructuralEquatable.

It is Typed of course so this seems to fit the need to create types at runtime. Perhaps use a Factory to encapsulate a specific Tuple object with its IStructrualEquatable implementation.

4
  • What use does a pair have? A codon is a standard unit in genetics and is made up of three neucleotides, which may be repeated (TTT is Phenylalanine).
    – user40980
    Commented Aug 27, 2013 at 19:21
  • The Tuple<T1,T2,T3> might prove a nice data structure to represent codons. It's typed of course, and immutable.
    – radarbob
    Commented Aug 28, 2013 at 2:25
  • [Flags] is wrong here as 1. Nucleotide sequences are ordered (AGU != UGA) and (more seriously) 2. Nucleotide sequences can have duplicates!
    – AakashM
    Commented Aug 28, 2013 at 13:08
  • @AakashM, yeah it occurred to me that this might be the case. Just thinkin' out loud.
    – radarbob
    Commented Aug 28, 2013 at 13:11
0

I would try the following for starters.

A, G, U, and C should all derive from a base class nucleotide - they are specific instances of the abstract class that nucleotide represents. In OO modeling parlance "A is a nucleotide"

This gives you the ability to extend all 4 classes of nucleotides at once, or just the individual nucleotide.

You'll need another class to model the Strand as a strand is composed of a series of nucleotides. "Strand has a (list of) nucleotides". You can likewise extend the Strand class to perform operations that a strand would be responsible for but that a nucleotide would not be responsible for.

I also added an interface for "just in case" purposes. For the immediate uses, the base nucleotide class should be sufficient, but if not, then an interface is there to help guarantee behavior.

Likewise I used a List collection in the Strand so I don't have to worry about particulars such as the strand length when first modeling. Most OO languages should have an equivalent generic collection to use.

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);
    }
}

The above sample is in C#.

Singletons really aren't appropriate for this modeling exercise - there isn't anything "single" about what you're modeling. You'll have potentially many instantiations of A, G, U, and C as well as the Strands.

8
  • But the only thing relevant about the nucleotide is "what kind is it"? It's nothing more than a value object as the asker uses it, and should be a good candidate for a flyweight proxy...
    – user44798
    Commented Aug 27, 2013 at 17:28
  • @tuespetre - we don't know the OP's particular usage. From the limited biology work I've done with RNA and DNA, there are a number of properties that may need to be modeled or considered. So that's why I presented a full OO model for the question. If we took YAGNI to the extreme here, all that's necessary is some strings to capture the nucleotide sequence. The OP's inference in asking for an OO model is that they are doing more than that.
    – user53019
    Commented Aug 27, 2013 at 17:35
  • (Speaking C#) If each strand is nothing more than a List<T> of nucleotides, and he used singleton nucleotides, he could do something like this: var numberofgNucleotides = strand.Where(n => n == GNucleotide.Instance).Count() which would meet the need described in the question ("I want to be able to decide the number of Nucleotide types at runtime.")
    – user44798
    Commented Aug 27, 2013 at 18:39
  • Of course, in a very light pattern, a strand could just be a queryable string, too.
    – user44798
    Commented Aug 27, 2013 at 18:40
  • Sorry, I think I was a bit unclear. When I mentioned AGCU I was just showing an example with 4 types. I'd like to be able to, at runtime, decide to have an arbitrary number of types. For example, have 26 types (ABCDEF... etc).
    – MetaFight
    Commented Aug 27, 2013 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.