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'. > >