On Saturday, 5 May 2012 11:51:22 UTC-5, Tiago Almeida wrote:
>
> Thanks for the comment. This is an interesting debate.
>
> Sábado, 5 de Maio de 2012 17:13:07 UTC+1, Massimo Di Pierro escreveu:
>>
>> 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.
>>
>  
> It may be a religious issue. I was assuming I already had the class 
> defined because it made sense if this hypothetical app had a very complex 
> domain layer. Like a very complex MMO game. I really believe that not all 
> operations could be patched as virtual fields. What about operations that 
> have a side effect, instead of returning something?
>

Perhaps the name virtual fields is not the most descriptive. A virtual 
fields is very much like a method in an ORM. You can pass values to it. 
They can do everything method can including "side effects" such as writing 
to the db.

db.teacher.give_raise=lambda row,raise: 
row.update_record(salary=row.salary+raise)
and you can do:
for teacher in db(db.teacher).select(): teacher.give_raise(5000)

Virtual fields can also store a state in the row very much like a method 
stores member variables, access and change existing ones.
By doing this outside of a class the DAL make it easier to have virtual 
fields which are context dependent. For example methods defined only for 
users who have permissions, such as:

if auth.has_permission('give_raise','teacher'):
    db.teacher.give_raise=lambda row,raise: 
row.update_record(salary=row.salary+raise)

 

> 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.
>>
> Ok. This is the old issue of performance vs elegance and the correct 
> answer really depends on the type of project. When you use Python, you 
> "forget" that below you there is probably a cpu with lots of unused vector 
> specialized instructions. They could be exposed, but they were not.
>  
>  
>
>> 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.
>>
> Again, it's a matter of project target.
>  
>
>>
>>  
>>>
>>>>  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.
>>
>
> This post is more of a debate about the usefulness of an orm in general 
> than the state of django's orm vs web2py's dal. I've presented my arguments 
> for prefering an orm in general, while supporting that for some specialized 
> projects you should not use an orm. Regarding the feature set of django, I 
> can say that Django suffers from a problem of too much inertia when it 
> comes to change. It may be a consequence of having 3 or 4BFDL's instead of 
> 1 and a much larger community. There are huge, years long discussions about 
> how this or that should be done, without conclusions. Also, I won't compare 
> those features one by one because I'm not *that* informed about what django 
> supports or not.
>

True. Elephants are slower then mice. :-)
 

> 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.
>>
>  
> I'm not building an orm :) It would be a fun exercise though.
>  
>
>> Anyway, please understand we value your comments as we can learn from 
>> them.
>>
>> Massimo
>>
>
> As I value this community comments'.
>  
>

Reply via email to