Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: David Epler
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: David Epler

OOPhoto - Returning To The Domain Model (Round V)

By
Published in

The latest OOPhoto application can be experienced here.

The latest OOPhoto code can be seen here.

In the last week or so, I got a little off track about modeling the domain in OOPhoto, my latest attempt at learning object oriented programming in ColdFusion. The project tangents were good in that they did get me to think more about objects and services, and I will keep what I have done so far. But now, let's get back to the domain model for our primary objects.

There are some cool things we can do here with the object composition that allows us to have complex objects without the overhead of fully loading every object. For example, when we load a PhotoGallery object, we don't necessarily have to load all of its Photos until those photos are requested. But, of course, this is an implementation detail that we don't have to concern ourselves with yet. So for now, what I'm actually gonna do it just bring back the basic domain model that we explored in Round II. But rather than include the service objects, I am gonna pair it down to just the primary domain objects.

As I stated before, I am going to use generic getters and setters. I know that a lot of people will throw red flags at this concept, but there is something that I really like about it. Plus, I believe that it will save a good amount of typing, which, until I get involved in Code Generation, is quite welcome. I know that one of the biggest arguments against generic getters and setters is that it does not lend itself to good documentation; as such, I am going to mark up my domain model below to give some insight into how things will work for each of the objects from an external point of view.

In the object descriptions below, I am going to list the properties first and then the methods second. The list of properties does not necessarily line up perfectly with the internal storage of object data - remember, the beauty of objects is that they encapsulate the actual implementation; but, the list of properties does describe perfectly the values that can be passed to the Get() and Set() methods.

Furthermore, each property is followed by a list of flags: g and s. The "g" flag indicates that the property may be Get()'d from the object. The "s" flag indicates that the property may be Set()'d to the object. Notice that not all properties can be used for both getting and setting. Currently the get and set restrictions work on more of an "honor system" than anything else. These flags are meant to express the intent of the domain model, not necessarily the actual restrictions. For example, ideally, you never need to set the ID of an object, but, in reality, something (probably the Service object) needs to be able to set that property. So for now, just concentrate on the intent while I work out the details.

PhotoGallery

  • ID (g)
  • PhotoID (g)
  • Title (gs)
  • Description (gs)
  • JumpCode (g)
  • Photos[ 0..n ] (gs)
  • DateUpdated (g)
  • DateCreated (g)

  • Init() :: PhotoGallery
  • Get() :: Any
  • Set() :: PhotoGallery

Photo

  • ID (g)
  • FileName (g)
  • FileExt (g)
  • Size (g)
  • Sort (g)
  • ViewCount (g)
  • Comments[ 0..n ] (gs)
  • PhotoGallery (gs)
  • DateUpdated (g)
  • DateCreated (g)

  • Init() :: Photo
  • Get() :: Any
  • Set() :: Photo

Comment

  • ID (g)
  • Comment (gs)
  • Photo (gs)
  • DateCreated (g)

  • Init() :: Comment
  • Get() :: Any
  • Set() :: Comment

You might notice that I got rid of the PhotoAsset object since we last touched on the domain model. After some great feedback from Elliott Sprehn and Brian Kotek, I have decided to scrap the idea of storing the binary data in the object and just rely on the photo ID for linking to the binary source. A little bit of an old-school, procedural mentality, but I am comfortable with trade-offs.

Because the nesting on these objects can get pretty big (galleries contain N photos which contain N comments), I am not going to load the entire composition all at one time. Instead, I am going to use a sort of lazy loading to make the processing a bit less intense. For example, when I load a PhotoGallery object, I am not going to load the Photos array just yet. Rather, I will wait until the Photos are requested before I load them. What I am envisioning is that when this happens, the PhotoGallery will call the PhotoService object to retreive the Photo instances. In order to do this, the PhotoGallery will need to have a reference to the PhotoService singleton which brings us back to our good friend, "Dependency Injection." Just as before, with the service objects, this will be handled by our object factory.

Of course, the implementation details won't ever affect the consuming programmer since the details will be encapsulated behind the Get() and Set() methods of the object being invoked. I am listing the ideas here more for feedback than anything else.

Before I end, I wanted to drop a note on validation; I don't really know what I am gonna do about validation just yet. I have struggled with this concept before and I am simply too tired to figure it out right now. So, for the time being, I am just going to implement these objects and leave the validation in the Controller.

Nap time.

Reader Comments

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel