Object Persistence With Nested Value Type - Anything Wrong With This Approach?

87 views
Skip to first unread message

Landon Martin

unread,
Mar 12, 2014, 3:54:45 PM3/12/14
to growing-object-o...@googlegroups.com
So I have a class (I'll call it Chunk, the details of its use aren't important) with an identity crisis. It can't decide (and I can't decide) if it wants to be an object or value. At first I thought it would just be a value:

(Code is C# btw)

struct Chunk
{
    public String Name;
    public MetaDataItem[] MetaData;
    public String[] Tags;
}

Chunk needs to be persisted so I have an interface IChunkBase. I could do this:

void Foo() 
{
    IChunkBase chunkBase = // Get concrete class from somewhere
    Chunk newChunk;

    // Do stuff to update newChunk

    chunkBase.Save(newChunk);
}

That was all well and good except I realized that I had a few issues
1. The fact that I'm persisting chunk means it has an identity (in fact it has an actual ID), which was a red flag it shouldn't be a value.
2. If I want to do further updates to newChunk I want the persisted version to stay in sync as much as possible and I don't like passing chunkBase around everywhere.

So fine, I think. I'll make chunk an object.

class Chunk
{
    private IChunkBase chunkBase;
    public String ID;
    public String Name;
    public MetaDataItem[] MetaData;
    public String[] Tags;

    public Chunk(IChunkBase chunkBase) { this.chunkBase = chunkBase; }
    
    public void Save()
    {
        chunkBase.Save(this);
    }
}

This works well enough except I found situations where I wanted to move a chunk between locations. Moving it required creating a new copy of it with a new ID, but in my tests I wanted to compare equality as I would a value:

Chunk copiedChunk = chunkBase.Move(originalChunk, newLocation);
Assert.AreEqual(copiedChunk, originalChunk);

Except they *aren't* equal. They have differing ID's even if their other values are identical. I played with writing a "AreChunksSimilar" method but that kind of smells to me. I've finally settled on creating a nested struct for the values.

class Chunk
{
    public struct Data
    {
        public String Name;
        public MetaDataItem[] MetaData;
        public String[] Tags;
    }

    private IChunkBase chunkBase;
    public String ID;
    public Data chunkData;
 
    public void Save()
    {
        chunkBase.Save(this);
    }
}

Am I approaching this in the right way? Is there something obvious that I'm missing? Thanks all.

Steve Freeman

unread,
Mar 12, 2014, 5:10:05 PM3/12/14
to growing-object-o...@googlegroups.com
A couple of thoughts. In some OR mappings, the ID is internal to the database and not used as the "business key". I recently saw a talk that suggested never updating, but always adding to a database--in which case, an ID represents an immutable set of values. That might make some of your problems go away. Otherwise, hasSameValuesAs() is a reasonable method, either in a matcher or the object itself.

I strongly recommend against the "objects save themselves" pattern. It looks neat but always seems to end up messy. I'd keep the base out of the chunk.

S
> --
>
> ---
> You received this message because you are subscribed to the Google Groups "Growing Object-Oriented Software" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriente...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Steve Freeman

Winner of the Agile Alliance Gordon Pask award 2006
Book: http://www.growing-object-oriented-software.com

+44 797 179 4105
Twitter: @sf105
Higher Order Logic Limited
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 7522677



Landon Martin

unread,
Mar 13, 2014, 1:16:15 PM3/13/14
to growing-object-o...@googlegroups.com
I'm not working with an actual database (this is actually a OneNote AddIn), so I'm pretty much saddled with having to have a key and updating my items. However I've gone ahead without having the objects updating themselves. Instead I'm having the ChunkContainers do the updating:

Container tinCan = new Container(IChunkBase, ContainerType.Foo);
Chunk thing = tinCan.CreateChunk(chunkName);
// Update thing here
tinCan.UpdateChunk(thing);
tinCan.DeleteChunk(thing);
// etc.

I'm still treating the Chunks as values despite the ID and have implemented a "IsCopyOf" method. I feel this works well and is as "clean" as I can make it under the restrictions I have. Thanks for your feedback!
> To unsubscribe from this group and stop receiving emails from it, send an email to growing-object-oriented-software+unsubscribe@googlegroups.com.

Steve Freeman

unread,
Mar 14, 2014, 12:38:50 PM3/14/14
to growing-object-o...@googlegroups.com
One more option might be to pass the tinCan into the chunk:

thing.updateIn(tinCan)
thing.deleteFrom(tinCan)

where tinCan is some kind of common interface.

whether this is a good idea or not depends on how the code and dependencies fall out.

S
Reply all
Reply to author
Forward
0 new messages