views:

220

answers:

3

For background, i have a Data layer and Service layer loosely based on Rob Conery's Storefront model and like Rob's, many of my domain objects and chained with LazyList<>'s and LazyItem<>'s to make use of the deferred execution that Linq2Sql provides given that my Lazy* types utilise IQueryable<T> rather than this awesome delegate approach.

So i have an object graph like this (basically, each Activity should have a photo gallery of many images- thumbnails and full size photos):

latest3Activities[0].Gallery.Images.Inner[1].FullImage

The Gallery type has an Images property of LazyList<PhotoGalleryImage> and so the IList<PhotoGalleryImage> from that LazyList is the Inner you see. Each PhotoGalleryImage item has a FullImage property and a Thumbnail property, both of type Image.

The idea is that the full rez uploaded photo is stored in the PhotoGalleryImage.FullImage property and initially, the Thumbnail property is Null. What i'm after is this: when the Thumbnail property is accessed for the 1st time, if it is Null i want my Service layer to generate the Thumb, persist it to the DB, then return the Image instance which is the smaller photo. I have all the code to create the thumbnail from the full size image, so that's not the question here.

What i cant figure out is how to catch the first access of the Thumbnail property (in my IQueryable<> architecture context) and then have the Service layer do the resizing and not the Repositories (DAL). I strongly feel that the Service (business) layer should be responsible for this functionality decision but i don't see how to make it work.

Currently i'm thinking the mapping from my domain classes in the repositories to the Linq2Sql classes would be a good place to identify this 'first access' i refer to, but i dont then see how a lower tier can then call up into the Service layer and perform the shrink (or even if it can, that it should).

Maybe my design constrains me to have the Repos do the conversion. Maybe i shouldn't want the Service layer to perform this logic at all. Maybe my design is just so horrid that i really shouldn't be facing this mess at all.

Pls help. All feedback is appreciated.

A: 

I assume that in order to display an image you need image URI, which can be handed to you by a IThumbnailingService, which will generate thumbnail if required and return a valid URI which points to the generated image.

Anton Gogolev
More detail please. I dont understand how a URI will do me any good. I'll need the Image instance returned from the Thumbnail property. I'd expect the only difference to calling the Thumbnail property and getting the Image from the DB to calling the Thumbnail property and having the 'lazy-gen' kick in, would be a few hundred milliseconds of blocking while it's being genned and persisted for the 1st time.
cottsak
+2  A: 

I had a very similar issue a couple of months ago with uploaded images, thumbnail generation and the question of where the code to generate the thumbnail images should go. I too really felt that this code belonged in the service layer (not least because the storage for the image files and thumbnails was abstracted out into an interface and injected via an IOC container and I didn't want to have any dependency injection into my domain layer).

In the end I created all the thumbnails at the point the image is uploaded via calls to the service layer from the UI controller. I did try generating the images in the domain layer before this though. To do this I used a pattern whereby when the domain layer needed to generate an image it raised an event which was hooked up to the service layer. The service layer then passed an instance of the storage interface back via event args to the domain layer so the domain layer could persist the image. This was very loosely based on some ideas on Udi Dahan's blog that I came across about using events in a domain model as a way of leveraging logic in the service layer. I can't find the reference on Udi's site now unfortunately but it's there somewhere. In any case it never really felt right - it seemed like tight coupling via another route, which is why I reverted to having the thumbnails created at the time the image is first uploaded via the service layer. However, perhaps in your case you could use the idea of events from the domain layer to invoke logic in the service layer. I'm sure there's a lot of value in the idea itself it just didn't quite fit what I was doing.

Steve Willcock
Funny. I did consider events to hook up the two layers as a 'plan B'.. but i feel you with the 'it never really felt right'. It also seems like a lot of mess too. I guess the 1st time these images will be accessed will be when the uploader gets the post back from a successful upload - so it matters not whether i gen the thumbs on create, or lazy - the result is the same.
cottsak
+2  A: 

The point of lazy init is to defer allocating resources since you don't know when or if you need them.

In your case, this doesn't really make sense: As soon as the image is uploaded, the server will need the thumbnail -- the user wants to see the new image immediately, right? Therefore deferring the creation of the thumbnail has no positive ROI.

Aaron Digulla
Agreed. This is the type of conceptual answer i was after.
cottsak
Indeed - For all it's faults, this is one of the things I think the Personal Site Starter kit gets right - if you're storing the image and various thumbnails in the database, then generate the thumbnail as you upload it/save it initially.
Zhaph - Ben Duguid