On Saturday, 5 May 2012 10:23:34 UTC-5, Tiago Almeida wrote:
>
> Hi,
> The issue about dal/orm, like Anthony said, there are tradeoffs to 
> consider. In my opinion you loose too much not having an orm to gain very 
> little with the dal. Let me continue my example.
> In the Deparment/Teacher hypothetical model, you also have assignment of 
> Teachers to Departments. This assignment is very simple (for the sake of 
> brevity) and has the start/end dates of the assignment and the function 
> (just a string) of the Teacher in that Department.
> You now want, Given the ID of a department list all the assignments of all 
> teachers along with their functions in a cool graphical timeline fashion.
> It's not about how you get the data. It's about the effort you have 
> implementing this req. and how you organize your code. Do you?
> a) write your .selects() in the view function
> b) write a historical_assignments(dep_id) function somewhere that hides 
> the DAL and call it from the view
> c) write a computed field on the department model
> d) write a method  historical_assignments() on the class Department
>
> To me, the d) option is by far the most elegant. I would have had the 
> Department class created anyway, so it's a matter of sticking a method in 
> there. If I am working with an ORM, by defining the classes, I 
> automagically get the tables defined. Without it, I have to repeat myself, 
> redefining the fields and the fields in the tables and their types, etc. 
> etc. in the persistance layer.
> What if I didn't define those classes? Then I couldn't contain these kinds 
> of business related operations into a single application layer and they 
> would leak everywhere, for instance in to the views, being much harder to 
> maintain.
>

this is somewhat a religious matter. We do not like to pollute the 
namespace with one class per table. We do not even usually do Department = 
db.define_table(...). We just expose db and access department via 
db.department. Given this preference:

db.departement.historical_assignments = Field.Lazy(lambda departement, 
date: db(db.teacher.departement)(db.teacher.asdate<date).select())

seems simpler and clear than to define a class and a method. It does not 
pollute the namespace. In fact web2py does allow to create a VirtualField 
class and map that into table, so that records have fields corresponding to 
methods. We consider it a legacy feature because users prefer the new 
syntax.
Yet this is kind of a religious issue.

Regarding the higher  vs different abstraction. A "perfect" persistence 
> layer (if there is such a thing) allows one to actually forget that you 
> have a DB system. I honestly don't care, from the biz point of view, if 
> things are stored in tables in a DB, xml files or sent via the wire to 
> China. I only care that I create my Departments, .save() them and get them 
> later as they were saved .get(id=dep_id).
>

We do not want to "forget" that we have a DB system. One can only forget 
when one builds simple queries. Ifone can only do simple queries than one 
starts to think a relational database is not good enough. We want to make 
sure .select() maps in an SQL SELECT, .insert() into SQL INSERT, etc. We do 
not want to hide database access which can cause performance issues. This 
is a significative difference. We do no need .save() and .get() because 
they are kind of like .insert() and .select() but the mapping is not always 
as clear. Moreover is not very Object Oriented either.
 

> Do you lose anything with this abstraction? Yes, of course. If you hide 
> that it's a DB you lose, for instance, DB triggers. It's the normal 
> tradeoff in any abstraction. If you use TCP, you get delivery guarantees 
> and peace of mind regarding all the dropped/corrupted packets nonsense 
> while loosing, say, realtime guarantees. Should we stop using TCP because 
> we loose this 'realtimeness'? Of course not.
> Are there things that you can do with an orm that you can not with adal? 
> No, it's quite the opposite. The dal exposes more details therefore allows 
> you to do more. However, by exposing all these details, you get a tool that 
> is harder to use (in the sense that you have to repeat yourself) for all 
> the other scenarios where you don't need such details. Python is used 
> because no one wants to deal with the nonsense of lower level languanges 
> that arise from exposing too many details (manual memory management, target 
> machine dependency, etc....).
> Lastly, If I am working with an orm and need to implement a really complex 
> query, nothing stops me from going deeper and use the dal or even writing 
> SQL. 
>

This is what we do not like. The goal of the DAL is to try avoid this as 
much as possible, although it does not prevent it.

 
>
>>  look at 
>> the Django ORM Tutorial example: 
>>
>> Poll.objects.filter(question__startswith='What') 
>>
>> In web2Py DAL it would use more standard python methods: 
>>
>> db( db.Poll.question.startswith("what") ).select() 
>>
> I've never said that Django's orm is perfect. That "__operator" thing 
> could be done in a different way. Anyway I accept that minor annoyance 
> because it saves me time overall.
>

I see this in a different light. Web2py supported left joins, aggregates, 
and nested selects 2 years before Django did. While they added those 
features over time, we added so many other features (list types, native GAE 
support, geospatial APIs for postgres, mongodb support, teradata support, 
imap-dal support, expressions, lazy virtual fields, full auditing in all 
database tables, multiple database support, semi-natural-language query 
parsing, etc.) that it is pointless to even compare them today, and we 
managed to remain backward compatible.

The DAL expressions are consistently shorter then the equivalent Django and 
SQLAlchemy ones (some example here 
http://www.web2py.com/AlterEgo/default/show/150 and I would love to see a 
counter example) and support more features than Django does (in the sense 
we can use the DAL to generate more SQL statements than the Django ORM can).

Web2py falls short of SQLAlchemy for support of legacy tables with 
arbitrary primary keys (but we have been getting better) and for lack of 
the concept of DB session (because we never needed that).

Just for fun two years ago, I implemented a Django-compatible ORM for 
web2py:
http://www.web2py.com/AlterEgo/default/show/189
Nobody used it so it died but it would be trivial to improve it to add a 
mapping between arbitrary methods and virtual fields.

Since you are building your own ORM, instead of starting from scratch, you 
may want to look into proving that and still take advantage of the DAL 
goodies underneath.

Anyway, please understand we value your comments as we can learn from them.

Massimo

Reply via email to