Apologies upfront for a lengthy post, but I've been trying to come up
with a solution to this issue Gabriel started (thanks man!), and I'm
kind of stuck.
Here is a "short" definition of the problem and a few directions my
thoughts took me.
Any help appreciated :-)
#Persistence / Business rules separation
##Goals
* business objects should not know about persistence
* persistence should be plugged into the business rules
* allowing for different implementations
* this should be configurable
* persistence should be configurable
* e.g. configure cache-able data vs direct database access
##Proposed solutions
###Abstract persistence layer returns hashes
*business object*
class ConferenceRoom
include PersistenceConversion #implements new_from_hash and
to_hash
def self.find_by_room_number(number)
new_from_hash
ConferenceRoomPersistence.find_by_room_number(number)
end
def book_me(from, to)
@from, @to = from, to
ConferenceRoomPersistence.update(to_hash)
end
end
*abstract persistence*
class ConferenceRoomPersistence
def self.find_by_room_number(number)
#just a placeholder
end
def self.update(hash)
#just a placeholder
end
end
*concrete persistence implementation*
ConferenceRoomPersistence.clas_eval do
def self.find_by_room_number(number)
#the real implementation
end
def self.update(hash)
#the real implementation
end
end
**Pros:**
* business objects expose only persistence methods that are need for
the rest of the application (see `ConferenceRoom.find_by_room_number`)
* from business objects to persistence there is only one route
* persistence layer is only in one place, easily replaceable
**Cons:**
* business objects directly reference the persistence layer, no
dependency injection (see `ConferenceRoom.book_me`)
* persistence is not implemented but it is still used in business
objects (see `ConferenceRoom.book_me`)
###Persistence layer appended to business objects
*business object*
class ConferenceRoom
def book_me(from, to)
@from, @to = from, to
end
def self.book(room_number, from, to)
room = find_by_room_number(room_number)
room.book_me(from, to)
end
end
*concrete persistence implementation*
ConferenceRoom.clas_eval do
include PersistenceConversion #implements new_from_hash and
to_hash
def self.find_by_room_number(number)
new_from_hash ...
end
def update
...
end
def book_me(from, to)
super
update
end
end
**Pros:**
* persistence implementation is glued to the domain object
* business objects get all the persistence methods "for free"
* from business objects to persistence there is only one route
* persistence layer is only in one place, easily replaceable
**Cons:**
* persistence methods used in other parts of the application are
"somewhere else"
* business objects sometimes do have to use persistence methods (see
`ConferenceRoom.book`), seams like a code smell
On Feb 27, 8:28 pm, Avdi Grimm <
a...@avdi.org> wrote:
> Nice, I'd missed that one.
>
>
>
>
>
>
>
>
>
> On Mon, Feb 27, 2012 at 2:07 PM, Adam Guyot <
shaoline...@gmail.com> wrote:
> > If no one has posted this yet:
> >
https://github.com/raganwald/homoiconic/blob/master/2011/11/COMEFROM.md
> > Seems somewhat relevant to this conversation.
>
> > A
>
> > On Mon, Feb 27, 2012 at 9:02 AM, Alexandre de Oliveira
> > <
chavedomu...@gmail.com> wrote:
>
> >> I'm kinda annoyed with AR lately. As a matter of exercise, I created a gem
> >> where I monkey patched Object#method_added, so:
>
> >> class Person; end
> >> class PersonMapper < DataMapper::Mapper; attributes :name, :age; end
>
> >> whenever Person has a change in its variables (name, age), the
> >> PersonMapper will automatically know it (thought
> >> DataMapper::Mapper#unit_of_work and intelligently persist the domain object.
>
> >> The code so
> >> far:
https://github.com/kurko/datamapper2/blob/master/lib/dm2/unit_of_work...
>
> >> It's just food for thought, actually. I not sure that monkey patching
> >> Object#method_added would be a good thing in practice.
>
> >> --Alexandre
>
> --
> Avdi Grimmhttp://
avdi.org