Model layer should not be (IMHO) monolithic - data persistence should not be
tightly coupled to your domain model, while Active Record does exactly that.
So your model should have a low-level layer that does the persistence, and
high-level domain logic layer that deals with your application logic.
Also, your controllers should probably not use session object at all - you
could wrap all the high-level processes (eg. user creation, posting an
article etc.) in functions (maybe classmethods) or classes in the model
layer.
Just out of curiosity... which University of Technology? The Kraków one (AGH)?
--
Paweł Stradomski
Why do you have to implement them into the User object? Why can't you
do this....
r = UserRepository()
u = User("Me")
r.add(u)
I just saved a user to a database, all of my domain code is in the
User class, all of my persistence code is in the UserRepository class,
which itself deals with meta.Session. If later I want to switch from
storing in a database to storing in a data file, I only need to make a
new class and have the controllers use this new one instead.
You can also have UserRepository inherit from a BaseRepository class
with the typical Add, Update, Delete, etc. methods so that you don't
have to rewrite them over and over again. More importantly, you can
have custom functions, like r.GetUsersWithExpiredPasswords(). Because
the SQLAlchemy query code is encapsulated into the repository's
GetUsersWithExpiredPasswords method, your controller still works fine
when you want to change to a datafile repository, so long as you have
reimplemented these custom queries using your new persistence
mechanism (which you would've done anyway, just in your User class).
Actually yes, there are things that can work better, eg. SQLAlchemy or
Hibernate. I don't know much about Django ORM, but pretty much about RoR
ActiveRecord.
Such a simple ORMs have many limitations, eg they assume one table - one
class. What about join-table inheritance? What about a db structure when one
object maps to three tables? Or one table to many objects (the last one is
supported in RoR actually). What about vertical and horizontal partitioning?
Similarily, they usually lack an identity map. When doing really complex
operations it is very probable you'll end with two object instances that
represent the same row - and it'll be a pain to solve.
Original poster mentioned situation, when he wants to switch from RDBMS to
another storage mechanism. Now, if that mechanism (eg files) requires some
objects to be kept together in one file... let's say a blog post and all the
comments in single file (stupid example, but will do for now). What about all
the calls to comment.save()? Should they just do post.save() or not? Will
that mean you save a single post many times in a single transaction?
Another thing, not strictly related to AR... code written with such a ORM
tends to put too much logic in persistence operation hooks, like
before/afterInserts, before/afterDelete etc. In the end, it's usually a bad
idea - those methods should just deal with persistence aspect, like data
denormalization - not even logging (I'm planning to write a post on that
later).
ActiveRecord works pretty well for simple schemas, but as the schema and
application logic grows, it becomes more and more difficult to use properly -
I mean applications where transactions span multiple classes, eg receiving CC
payment triggers checking customer account balance which fires multiple
no-longer-debtor hooks which re-activate customer's internet account which
allocates IP in the network which determines the pool is 90% full and sends
an e-mail to network operators etc... Fun starts at 100 tables in the system.
Cluttering domain logic code with persistence aspects is not nice.
--
Paweł Stradomski
> def __new__(cls, *args, **kwargs):
> if 'username' in kwargs.keys():
> uid = getpwnam(kwargs.get('username')).pw_uid
> if 'uid' in kwargs.keys():
> uid = kwargs.get('uid')
> # @todo - poprawic czytelnosc
> if uid:
> if meta.Session.query(Informations).get(uid) == None:
> return object.__new__(cls, *args, **kwargs)
> else:
> return meta.Session.query(Informations).get(uid)
> else:
> return object.__new__(cls, *args, **kwargs)
>
What exactly are you trying to achieve?
--
Paweł Stradomski
Right, didn't think of it.
--
Paweł Stradomski
I think others have pretty much drove the point home, but the reason
you think it's "more work" is because SA does X well, and you want it
to do Y. We can argue the point of X vs. Y, but ultimately it's your
decision. Perhaps you should check out elixir...
Don't wrap meta.Session. That's a silly thing to do. The semantics
of the session and the sematics of your object are *completely*
seperate things. In SQLAlchemy, your model objects don't save
themselves - the session commits their data.
It seems like you're putting a square peg in a round hole.
--
Ross Vandegrift
ro...@kallisti.us
"If the fight gets hot, the songs get hotter. If the going gets tough,
the songs get tougher."
--Woody Guthrie