IWETHEY v. 0.3.0 | TODO
1,095 registered users | 0 active users | 0 LpH | Statistics
Login | Create New User
IWETHEY Banner

Welcome to IWETHEY!

New I see bloated people
This is better? Instead of:
\nselect * from bidView\nwhere description like "hibernate%"\n  and amount > 100\n

One writes
  \nList auctionItems = \n  session.createCriteria(AuctionItem.class)\n     .setFetchMode("bids", FetchMode.EAGER)\n     .add(Expression.like("description", desc))\n     .createCriteria("successfulBid")\n       .add(Expression.gt("amount", minAmount))\n     .list();\n

And I am skeptical it can handle the more complex stuff between vendors.
It reminds me of the "bloat joke" on my main anti-OOP page:
\nNORMAL\n\n  print(a + b)\n\nBLOATED\n\n  am = new math.ArithmeticManager()\n  opA = new math.Operand((float) a)\n  opB = new math.Operand((float) b)\n  am.addOperand(opA)\n  am.addOperand(opB)\n  am.operator = new math.operators.Addition()\n  am.executeMathOperation()\n  system.io.output.print(am.mathOperationResult())\n

________________
oop.ismad.com
New Er...
List l = template.find("from User user where user.nickname = ?", nickname); *

Or maybe:
user = template.get(User.class, id);

Hmmm. let's see, after I make some changes to the user, what do I do to save it:
template.saveOrUpdate(user);

And if it's a new user, it will automatically create it for me.

Or let's say I'd like to get all of the accounts associated with that user:
List accounts = user.getAccounts();

What did you do, sort through that site until you found the most convoluted example you could?

One nifty feature of Spring, btw, is that I can use a User object tied to the database as the backing object for a form. Auto-filled HTML forms, auto-parsed form parameters.

Here's some code for a Create New User form:

\n\tpublic ModelAndView onSubmit(HttpServletRequest request, \n\t\t\t\tHttpServletResponse response,\n\t\t\t\tObject command, BindException errors)\n\t\t{\n\t\t\tUser user = (User) command;\n\n\t\t\tint id = mUserManager.createNewUser(user);\n\n\t\t\t// This bit logs the user in as well\n\t\t\tHttpSession sess = request.getSession();\n\t\t\tsess.setAttribute(USER_ID_ATTRIBUTE, new Integer(id));\n\n\t\t\treturn new ModelAndView(new RedirectView(getSuccessView()));\n\t\t}\n\n    protected Object formBackingObject(HttpServletRequest request)\n\t\tthrows ServletException\n\t\t{\n\t\t\tUser user = new User();\n\t\t\tuser.setNickname(request.getParameter("nickname"));\n\t\t\tuser.setUnencryptedPassword(request.getParameter("password"));\n\n\t\t\treturn user;\n\t\t}\n

That plus a little configuration XML that ties that code with the form URI is all I need.

* Note that I am using Hibernate in conjunction with Spring, but that there's not much difference in the basic code either way. This is actual code that I'm using now, incidentally.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New re: Er...
List l = template.find("from User user where user.nickname = ?", nickname);


That is basically just embedding some or all of the query strings into query API's. One can make functions that do similar things if need be.

user = template.get(User.class, id);


One can make a "record = getUser(id)" function if need be. Generally I will only factor SQL to a function if I see it repeated about 3 times. But, most SQL is specific to a task, so little is gained by wrapping it.

What did you do, sort through that site until you found the most convoluted example you could?


Queries can get far more involved than that. That was nothing.

One nifty feature of Spring, btw, is that I can use a User object tied to the database as the backing object for a form.


That is just yet another CRUD-screen (create,read,update,delete) framework it appears.
________________
oop.ismad.com
New Nice attempt
The POINT that you missed is that THERE IS NO BLOAT. You found an example of the programmatic query language that they suggest people NOT use, in order to show how bloated it was. You failed. Accept it and move on. Difficult queries are no more convoluted using Hibernate than they are using SQL. A good many queries are more straight-forward, such as the getAccounts() example. Are you willing to admit this yet?

That is just yet another CRUD-screen (create,read,update,delete) framework it appears.
No, it's quite a bit more flexible than just CRUD. But it makes CRUD dead stupid simple to do.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New re: Nice attempt
We would probably have to do a code-for-code shootout to settle this. A lot of the "simple" examples require a fair amount of set-up work to define stuff (a lot of it essentially duplicating the RDB schemas with an OO twist.)

Even if by chance the code-size was the same (not convinced yet), you still have not justified the extra OR-mapper layer, per other message.
________________
oop.ismad.com
New re: Nice attempt
Hibernate definitions. Note that this can be used to generate the database schema in any of the supported databases automatically.
\n<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE hibernate-mapping PUBLIC\n        "-//Hibernate/Hibernate Mapping DTD//EN"\n        "[link|http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd|http://hibernate.sou...e-mapping-2.0.dtd]">\n\n<!-- $Id: iwethey.hbm.xml 17 2004-04-28 22:13:29Z anderson $ -->\n<hibernate-mapping auto-import="true">\n\n\t<class name="org.iwethey.domain.User" table="iwethey_user" lazy="true">\n\t\t<cache usage="read-write"/>\n\n\t\t<id name="id" column="user_id" unsaved-value="0">\n\t\t\t<generator class="sequence">\n\t\t\t\t<param name="sequence">seq_user</param>\n\t\t\t</generator>\n\t\t</id>\n\t\n\t\t<property name="nickname"/>\n\t\t<property name="encryptedPassword" column="password"/>\n\t\t<property name="created" type="timestamp" insert="false"/> <!-- update="false"/> -->\n\t\t<property name="lastPresent" column="last_present" type="timestamp" insert="false"/>\n\n\t\t<map name="properties" table="user_property" cascade="all" lazy="true">\n\t\t\t<cache usage="read-write"/>\n\t\t\t<key column="user_id"/>\n\t\t\t<index column="name" type="string"/>\n\t\t\t<element column="value" type="string"/>\n\t\t</map>\n\t</class>\n</hibernate-mapping>\n


Data interface class. Exists for the purpose of allowing swappable data sources (note the "implements UserManager"). Not strictly necessary as a separate object/interface if you are using only a single data source.
\npublic class HibUserManager extends HibernateSupportExtensions implements UserManager\n{\n\tpublic List getUserList()\n\t{\n\t\treturn getHibernateTemplate().loadAll(User.class);\n\t}\n\n\tpublic User getUserByNickname(String nickname)\n\t{\n\t\tList l = getHibernateTemplate().find("from User user where user.nickname = ?", nickname);\n\t\tif (l.size() == 1)\n\t\t\treturn (User) l.get(0);\n\t\treturn null;\n\t}\n\n\tpublic User getUserById(int id)\n\t{\n\t\ttry\n\t\t\t{\n\t\t\t\treturn (User) getHibernateTemplate().get(User.class, new Integer(id));\n\t\t\t}\n\t\tcatch (HibernateObjectRetrievalFailureException e)\n\t\t\t{\n\t\t\t\treturn null;\n\t\t\t}\n\t}\n\n\tpublic boolean checkLogin(User user)\n\t{\n\t\tList l = getHibernateTemplate().find(\n\t\t\t"from User user where user.nickname = ? and user.encryptedPassword = ?",\n\t\t\tnew Object[] { user.getNickname(), user.getEncryptedPassword() }\n\t\t\t);\n\t\treturn l.size() == 1;\n\t}\n\n\tpublic void saveUser(User user)\n\t{\n\t\tgetHibernateTemplate().saveOrUpdate(user);\n\t}\n\n\tpublic void saveUserAttributes(User user)\n\t\t{\n\t\t\tif (!user.isAnonymous())\n\t\t\t\tgetHibernateTemplate().saveOrUpdate(user);\n\t\t}\n\n\tpublic void removeUser(User user)\n\t\t{\n\t\t\tif (!user.isAnonymous())\n\t\t\t\tgetHibernateTemplate().delete(user);\n\t\t}\n\n\tpublic int getUserCount()\n\t\t{\n\t\t\treturn single("select count(*) from User user").intValue();\n\t\t}\n\n\tpublic int getActiveUserCount()\n\t\t{\n\t\t\treturn single("select count(*) from User user where (CURRENT_TIMESTAMP - last_present) < interval '10 minutes'").intValue();\n\t\t}\n\n\tpublic boolean getExists(String nickname)\n\t\t{\n\t\t\treturn single("select count(*) from User user where nickname = ?", nickname).intValue() > 0;\n\t\t}\n\n\tpublic boolean getExists(User user)\n\t\t{\n\t\t\treturn getExists(user.getNickname());\n\t\t}\n}\n


User object. Serves as a form backing object as well as a data object. Supports an arbitrary number of properties, any type that can be represented as a string. I've omitted some convenience methods (getPropertyAsBoolean, etc.) that aren't necessary for the purpose of proving the point. This class can also be used in anonymous mode before the user has logged in, allowing preference settings that persist for the session only. Note that other OO languages do not require nearly as much boiler-plate set/get cruft as Java.
\npublic class User implements Serializable\n{\n\tprivate int mId = 0;\n\tprivate String mNickname = null;\n\tprivate String mUnencryptedPassword = null;\n\tprivate String mEncryptedPassword = null;\n\tprivate String mPasswordCheck = null;\n\tprivate Date mCreated = null;\n\tprivate Date mLastPresent = null;\n\tprivate Map mProperties = null;\n\n\tpublic User() { }\n\n\tpublic User(User user)\n\t\t{\n\t\t\tsetFromUser(user);\n\t\t}\n\n\tpublic User(String nickname)\n\t\t{\n\t\t\tsetNickname(nickname);\n\t\t}\n\n\tpublic User(String nickname, String password)\n\t\t{\n\t\t\tthis(nickname);\n\t\t\tsetUnencryptedPassword(password);\n\t\t}\n\n\tpublic void setId(int id) { mId = id; }\n\tpublic int getId() { return mId; }\n\n\tpublic void setNickname(String nickname) { mNickname = nickname; }\n\tpublic String getNickname() { return mNickname; }\n\n\tpublic void setUnencryptedPassword(String password)\n\t\t{\n\t\t\tmUnencryptedPassword = password;\n\t\t\tif (password != null && !password.equals(""))\n\t\t\t\tmEncryptedPassword = encrypt(password);\n\t\t}\n\tpublic String getUnencryptedPassword() { return mUnencryptedPassword; }\n\n\tpublic void setEncryptedPassword(String password) { mEncryptedPassword = password; }\n\tpublic String getEncryptedPassword() { return mEncryptedPassword; }\n\n\tpublic void setPasswordCheck(String passwordCheck) { mPasswordCheck = passwordCheck; }\n\tpublic String getPasswordCheck() { return mPasswordCheck; }\n\n\tpublic void setCreated(Date created) { mCreated = created; }\n\tpublic Date getCreated() { return mCreated; }\n\n\tpublic void setLastPresent(Date lastPresent) { mLastPresent = lastPresent; }\n\tpublic Date getLastPresent() { return mLastPresent; }\n\n\tpublic void setProperty(String name, String value)\n\t\t{\n\t\t\tgetProperties().put(name, value);\n\t\t}\n\n\tpublic Map getProperties()\n\t\t{\n\t\t\tif (mProperties == null)\n\t\t\t\tmProperties = new HashMap();\n\n\t\t\treturn mProperties;\n\t\t}\n\n\tpublic void setProperties(Map props)\n\t\t{\n\t\t\tmProperties = props;\n\t\t}\n\n\tpublic String getProperty(String name, String defaultValue)\n\t\t{\n\t\t\tString val = (String) getProperties().get(name);\n\n\t\t\tif (val == null)\n\t\t\t\treturn defaultValue;\n\n\t\t\treturn val;\n\t\t}\n\n\tpublic void setFromUser(User user)\n\t\t{\n\t\t\tassert user != null;\n\n\t\t\tsetId(user.getId());\n\t\t\tsetNickname(user.getNickname());\n\t\t\tsetUnencryptedPassword(user.getUnencryptedPassword());\n\t\t\tsetEncryptedPassword(user.getEncryptedPassword());\n\t\t\tsetPasswordCheck(user.getPasswordCheck());\n\t\t\tsetCreated(user.getCreated());\n\t\t\tsetLastPresent(user.getLastPresent());\n\t\t\tsetProperties(user.getProperties());\n\t\t}\n\n\tpublic Object clone()\n\t\t{\n\t\t\treturn new User(this);\n\t\t}\n\n\tprivate static final char mHexChars[] =\n\t{\n\t\t'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'\n\t};\n\n\tpublic String encrypt(String buffer)\n\t\t{\n\t\t\tMessageDigest crypt = null;\n\n\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tcrypt = MessageDigest.getInstance("MD5");\n\t\t\t\t}\n\t\t\tcatch (NoSuchAlgorithmException e1)\n\t\t\t\t{\n\t\t\t\t\tLogFactory.getLog(getClass()).error("No MD5 implementation!");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\tcrypt.update(buffer.getBytes());\n\n\t\t\tbyte[] bytes = crypt.digest();\n\n\t\t\tStringBuffer hex = new StringBuffer(2 * bytes.length);\n \n\t\t\tfor (int i = 0; i < bytes.length; i++)\n\t\t\t\t{\n\t\t\t\t\tbyte bch = bytes[i];\n\n\t\t\t\t\thex.append(mHexChars[(bch & 0xF0) >> 4]);\n\t\t\t\t\thex.append(mHexChars[bch & 0x0F]);\n\t\t\t\t}\n\t\t\n\t\t\treturn hex.toString();\n\t\t}\n\n\tpublic boolean isAnonymous()\n\t\t{\n\t\t\treturn mId == 0;\n\t\t}\n}\n



Omitted: Spring bean factory XML, as this is application dependent and not actually necessary to use the code. It adds things like declarative transaction boundaries, cache controls, and the like.

This is working code. If you don't believe me, go [link|http://lord.gregfolkert.net:8180/iwethey/main.iwt|here]. Note that there are few interface bugs in that version, since fixed.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Forgot to add:
The user properties are lazily loaded when called. This is one of the main reasons I went with Hibernate. The excess code I was able to jettison was just an added benefit.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Aieee! Actual code! HOW DARE YOU!!!


Peter
[link|http://www.debian.org|Shill For Hire]
[link|http://www.kuro5hin.org|There is no K5 Cabal]
[link|http://guildenstern.dyndns.org|Blog]
New Making it interesting
How about a nice useful assignment that all in these parts could actually benefit from. Let's say that Admin goes about building a useful app with OOP techniques. Let's say that Bryce gets to write the same app using only procedural constructs.

The application is the zIWETHEY board. Bryce will have the advantage that Admin will have provided a working set of software that will be open sourced. He can use that to construct a working prototype in any procedural language he so desires (assuming, of course, that the language runs under Apache).

Bryce claims that the procedural version will be much cleaner. Let's see some actual proof.

Let the games begin. :-)
New Heh. I think Bryce would rather have someone else write it
...then he can tear it apart and say, "it's not how *I* would have done it. Case dismissed." ;)
New Don't you know?
Message board is not a "business application"
--

Buy high, sell sober.
New Putting words in my mouth
Bryce claims that the procedural version will be much cleaner. Let's see some actual proof.

I didn't claim that. I only claim that it will not be objectively worse.

The real benefit would probably be that a p/r version would be more consistent from developer to developer because OO is too open-ended. Every professed OO guru does a very different design. OO is all over the fricken map because it the Goto of structuring. Relational rules and the "group by task" of procedural will tend to produce a more consistent and predictable result than OO.
________________
oop.ismad.com
New Actually, what you said was:
"You spend all your code translating back and forth between two discordant paradigms."

So, where's the bloat? Are you ready to admit that it isn't there yet?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Re: Putting words in my mouth
Relational rules and the "group by task" of procedural will tend to produce a more consistent and predictable result than OO.
Having seen several large procedural database programs, I question the validity of this statement. "Tend" is a weasel word. Where's your proof?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Code Talks. Bryce Walks.
So let's set our goals a bit more realistic. Let's see if you can produce a version of zIWETHEY software that is not "objectively worse".
New I shall consider it
________________
oop.ismad.com
New Thanks.
Looking at this is an opportunity to learn more about the app, and make the discussions a bit more than rhetoric. Even if you don't want to piece together the whole app, perhaps you can at least show how some of the pieces of it could be written from a P/R perspective.
New If you don't...
... then you forfeit all right henceforth to whine, "show me the code".
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New RE: Are you willing to admit this yet?
Let's see. Wasn't it 1997 or so when this discussion began. And haven't we been through 4 boards (IWETHEY, EZBoard IWETHEY and Jay's OO, and zIWETHEY).

And you really think he's going to admit something after all this time? :-)
New Even OO fans are mixed about OR-mappers
I did NOT write this:

[link|http://www.c2.com/cgi/wiki?ObjectRelationalMappingCostsTimeAndMoney|http://www.c2.com/cg...CostsTimeAndMoney]

Go argue with those guys.
________________
oop.ismad.com
Expand Edited by tablizer May 20, 2004, 11:57:54 PM EDT
New Looks pretty specific.
Took me about two hours to get Hibernate going the first time. Took me another two to port all my old JDBC code to the new mapping stuff. It adds about 5-10% to the runtime costs (which are pretty small to begin with). The cost was nil. Stuff that requires a lot of database interaction back and forth is done in a trigger or stored procedure.

Use a hammer for nails, a screwdriver for screws. This is the basic lesson you have yet to learn.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New In Dejavu, one would write:
f = lambda x: x.description.startswith("hibernate") and x.amount > 100\nfor unit in recall(Thing, logic.Expression(f)):\n    do_something_with(unit)


instead of:

sql = 'select * from bidView where description like "hibernate%" and amount > 100'\nfor row in db.execute(sql, connection):\n   do_something_with(row)


...I don't see any bloat. On the contrary, the first one is written in the same programming language throughout. The second one introduces a declarative language (SQL) inside the original application language. And it only applies to databases where Like is a valid operator, and where the percent-sign is a wildcard character, and where double-quotes are valid delimiters, and where keywords (like 'select') can be lowercase, and where bidView isn't forced into a namespace (with a prefix), and where 'amount' and 'description' are not reserved words.

In addition, user input is made far more safe--you can't simply insert "; DELETE * FROM important_table" into Dejavu code. ;)
New Re: In Dejavu, one would write:
> f = lambda x: x.description.startswith("hibernate") and x.amount > 100\n> for unit in recall(Thing, logic.Expression(f)):\n>     do_something_with(unit)
This looks a lot like the criteria library ([link|http://onestepback.org/index.cgi/Tech/Ruby/Criteria.rdoc|http://onestepback.o...uby/Criteria.rdoc]). Is the implementation based on similar principles?
--
-- Jim Weirich jim@weirichhouse.org [link|http://onestepback.org|http://onestepback.org]
---------------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)
New An earlier version was like that.
I had a class which would absorb criteria via Python expressions, so:

e = logic.Expression()\ne.attribute == 3


would trigger:

class Expression(object):\n    def __eq__(self, other):\n        stack.append(operator.eq, other)


Etcetera. Then I would pass around the stack and evaluate it as necessary. But I also (like Criteria) had the issue of not being able to override shortcut And and Or (I used binary & and | instead), and it got a bit ugly. In addition, I was abusing normal syntax--as above, line 2, most manipulations took a comparison and didn't return or assign anything; it wasn't very natural.

So, after seeing a brilliant post by Raymond Hettinger on c.l.p., I wrote two things: an EarlyBinder and a LambdaDecompiler class. Passing a lambda (a Python anonymous function) into an Expression constructor now does early binding via a bytecode Visitor, grabbing globals and cell objects from the closure and dereferencing them (making them constants), then making a new function object. At that point, I'm free to pass it around, even make a string out of it and store it in a DB, because all variables are either arguments to the function, or constants. Flexibility of function is provided through a single mechanism; you can write:

lambda x, **kw: x.Size > kw['Size']


..where kw is keyword arguments--a dictionary (mapping; hash to you Perlers).

The LambdaDecompiler also is a bytecode Visitor, and produces the Python source code from bytecode--that's how I get a string to store. But, having that decompiler core, I subclass it and write SQLDecompilers as well. So the above decompiles into SQL Server (ADO) as:

"WHERE [Size] > %(Size)s" % kwargs


...which, when evaluated with kwargs = {'Size': 3}, yields WHERE [Size] > 3. This gets me the speed boost you mentioned (avoiding 'SQL fragments').

But it was also important for me to have an expression which I could then pass a fully-formed class and test it, because:

1) I have an in-memory object cache, and I need to filter it by the same logic, and
2) The match between Python logic and SQL is imperfect. For example, == is case-sensitive in Python but -insensitive in ADO SQL. It's fastest just to create the class object and run it through the lambda than try to wrangle SQL Server into making the search case-sensitive, which is set database-wide, per column, *and* per query IIRC.

The only ugly bit now is that it's CPython-specific, it won't work on Jython (Python which runs on the JVM), because the bytecode is different. Meh. One thing I really like is that the application code (what a developer using my framework would write) doesn't mention SQL at all. So you can use exactly the same code for huge DB tables, or 10-item in-memory lists, and leave those decisions about the best storage mechanism up to the deployers. They can decide that a list of 10 small items should stay in memory, and the huge table shouldn't. Or vice-versa.
New Forgot: code links
The logic module contains the Expression class, which wraps up the lambdas and adds some sugar, like simpler filters, and allowing you to add (logical-and) Expressions together:

>>> f = logic.Expression(lambda x: x.Size > 3)\n>>> g = logic.filter(Color='Blue')\n>>> f += g\n>>> f\nlogic.Expression(lambda x: (x.Size > 3) and (x.Color == 'Blue'))


The codewalk module does the bytecode inspection, etc.

Both at [link|http://www.aminus.org/rbre/python/index.html|http://www.aminus.or...python/index.html]
New ICLRPD
It only applies to databases where Like is a valid operator, and where the percent-sign is a wildcard character, and where double-quotes are valid delimiters, and where keywords (like 'select') can be lowercase, and where bidView isn't forced into a namespace (with a prefix), and where 'amount' and 'description' are not reserved words.
===

Implicitly condoning stupidity since 2001.
New Why learn and/or create another query language?
SQL is fairly well known. Why introduce yet another query language for developers to learn? Why not come up with a generic SQL dialect and then translate it into different dialects instead of a very different query language into SQL dialects?

Personally I see that most places don't swap DB vendors that often so it is not worth worrying about.

I would like to toss SQL also for something easier to standardize, but your approach is not it. BTW

description.startswith("hibernate")

is much more cluttery than

like "hibernate%"

One could make string processing functions to do something similar if need be, I would note. At least get rid of that damned demeter-violating dot bloat and make it just "startsWith()".
________________
oop.ismad.com
New In case you missed it:
as I said, I am not introducing another query language. The language which you are viewing as "another query language" is nothing more nor less than pure Python, and it applies perfectly to the fully-formed Python objects with which I wish to work. For example, with the expression:

f = lambda x: x.description.startswith("hibernate")

I have just defined an anonymous function in Python. I can then use it directly, without any further translation, on a Thing object:

class Thing(object):\n    def __init__(self, description):\n        self.description = description\n\nbear = Thing("hibernates in winter")


And f(bear) returns True without any intermediate magic. I hope you're not saying that calling a function is more than a programmer can handle. I will concede the fact that lambdas seem to mystify some people.

Given that simplicity, since functions are first-class objects in Python, I can pass that function down to a server like so:

hibernators = namespace.recall(Thing, f)

...and get back a list of all Thing objects for which the function f returns True.

Second point you might have missed: not every storage mechanism is going to be SQL-based. Some might be better off without persistence altogether. Some might be better off with a bsddb. So my solution is even more generic than a "generic SQL dialect".

Third, don't cheat. You wrote:
description.startswith("hibernate")

is much more cluttery than

like "hibernate%"


...conveniently leaving out the field name in your example to make it shorter. At the least, you should have written:

description.startswith("hibernate")

is much more cluttery than

description like "hibernate%"


I won't digress again into how UN-generic and cluttery "like" and "%" are. But I will note that new developers are far more likely to grok my Python syntax at first glance than your SQL.
New only for the trivial
conveniently leaving out the field name in your example to make it shorter.


I assure you it was not intentional. I apologize for the error.

But I will note that new developers are far more likely to grok my Python syntax at first glance than your SQL.


More developers know SQL than know Python. And I am still skeptical it can handle non-trivial queries.

BTW, How would your framework handle this:
\n  SELECT AVG(GPA) FROM (\n\tSELECT AVG(grade) AS GPA FROM Grades GROUP BY studentID\n  )\n

It calculates total GPA with an equal weight per student rather than per class.
________________
oop.ismad.com
New There are multiple ways of doing that...
...depends to a large extent on how the designer puts things together. If we had, for example, a Grade Unit and a Student Unit:

class Grade(dejavu.Unit):\n    pass\nGrade.set_properties({'Value': float,\n                      'StudentID': unicode})\n\nclass Student(dejavu.Unit):\n    def GPA(self):\n        grades = [x.Value for x in self.Grade()]\n        if grades:\n            return sum(grades) / len(grades)\n        else:\n            return 0.0  # This may not be what you want\n\nnamespace.associate(Student, 'ID', Grade, 'StudentID')


That .associate function binds a new .Grade() method to the Student class*; said method looks up all Grade objects which have a StudentID equal to our Student.ID; storage managers are free to optimize that call with a JOIN if they manage both classes**. Our Student.GPA() function uses this (as "self.Grade()") to recall associated units.

So developer code to calc the GPA for multiple students would then look like this (assuming you want all students, all years, etc.):

gpas = [x.GPA() for x in namespace.recall(Student)]\nif gpas:\n    avg_gpa = sum(gpas) / len(gpas)\nelse:\n    avg_gpas = 0.0 # Again, this may not satisfy requirements...


Is it as fast as straight SQL? Guaranteed not. But is it fast enough? Probably. If it isn't, there's nothing stopping the developer from hand-crafting an SQL statement and bypassing some of the layers, if he wants to completely sacrifice maintainability and portability. But I've built three apps on top of this framework now, and haven't run into a speed conflict yet.


Fu xiansheng


* And, incidentally, makes a reciprocal Student() method for the Grade class.

** However, one of the design points of Dejavu is that the framework does not assume all data is managed by the same storage manager unless explicitly told so by the deployer. At my company, for example, I have expense Transactions in one store and income in another, and have to mix them to show, say, amount paid on an invoice. This is done transparently from the point of view of application code--it's handled by a mixing Unit Server in the middle layer. When the day comes that we decide to stop using the second store (which is 3rd party code), all I have to do is change a line in a .conf file, and roll on. I could even build a tool very quickly to migrate the data for me; it's on my list of things to write for version 4.1.
     Have I mentioned lately that Python is BITCHIN??? - (FuManChu) - (167)
         The solution is to toss OO to begin with, not Python - (tablizer) - (166)
             Re: The solution is to toss OO to begin with, not Python - (admin) - (11)
                 not today -NT - (tablizer) - (2)
                     *BLAM BLAM* *VROOOOOooooommm.....* -NT - (pwhysall) - (1)
                         and when you do the same? -NT - (tablizer)
                 Bloat explanation - (tablizer) - (7)
                     Not what I meant. - (admin)
                     That's a very table-centric point of view - (FuManChu) - (5)
                         Of course. Tables rock. Code is ugly. - (tablizer) - (4)
                             Snort. - (FuManChu) - (1)
                                 Re: Snort - (tablizer)
                             So now you're down on "skinny" tables? - (ben_tilly) - (1)
                                 Re: So now you're down on "skinny" tables? - (tablizer)
             Not sure what you're pushing for. - (FuManChu) - (153)
                 Software engineering is gambling - (tablizer) - (152)
                     The only thing this app does is business modeling. -NT - (FuManChu) - (151)
                         I meant showing me code, not anecdotes -NT - (tablizer) - (150)
                             Ironic, considering how much code *you* have shown... -NT - (ben_tilly) - (9)
                                 Wonder how the L Compiler is getting on? -NT - (pwhysall) - (6)
                                     It's Late. - (admin) - (5)
                                         I was wondering where the L it was. -NT - (pwhysall)
                                         The P game - (tablizer) - (3)
                                             Re: The P game - (admin) - (2)
                                                 you still have no evidence of betterment - (tablizer) - (1)
                                                     No, you compare it. - (admin)
                                 The burden of evidence is on you - (tablizer) - (1)
                                     And what claim did I ever make? - (ben_tilly)
                             Well, here's the thing - (FuManChu) - (139)
                                 Unicorns - (tablizer) - (138)
                                     OT: Have you been reading Groklaw tonight too? - (Another Scott)
                                     General description - (FuManChu) - (136)
                                         SQL wrapper? - (tablizer) - (135)
                                             Generic SQL wrapper API - (admin) - (30)
                                                 I see bloated people - (tablizer) - (29)
                                                     Er... - (admin) - (19)
                                                         re: Er... - (tablizer) - (18)
                                                             Nice attempt - (admin) - (17)
                                                                 re: Nice attempt - (tablizer) - (13)
                                                                     re: Nice attempt - (admin) - (12)
                                                                         Forgot to add: - (admin)
                                                                         Aieee! Actual code! HOW DARE YOU!!! -NT - (pwhysall) - (10)
                                                                             Making it interesting - (ChrisR) - (9)
                                                                                 Heh. I think Bryce would rather have someone else write it - (FuManChu)
                                                                                 Don't you know? - (Arkadiy)
                                                                                 Putting words in my mouth - (tablizer) - (6)
                                                                                     Actually, what you said was: - (admin)
                                                                                     Re: Putting words in my mouth - (admin)
                                                                                     Code Talks. Bryce Walks. - (ChrisR) - (3)
                                                                                         I shall consider it -NT - (tablizer) - (2)
                                                                                             Thanks. - (ChrisR)
                                                                                             If you don't... - (admin)
                                                                 RE: Are you willing to admit this yet? - (ChrisR) - (2)
                                                                     Even OO fans are mixed about OR-mappers - (tablizer) - (1)
                                                                         Looks pretty specific. - (admin)
                                                     In Dejavu, one would write: - (FuManChu) - (8)
                                                         Re: In Dejavu, one would write: - (JimWeirich) - (2)
                                                             An earlier version was like that. - (FuManChu) - (1)
                                                                 Forgot: code links - (FuManChu)
                                                         ICLRPD - (drewk)
                                                         Why learn and/or create another query language? - (tablizer) - (3)
                                                             In case you missed it: - (FuManChu) - (2)
                                                                 only for the trivial - (tablizer) - (1)
                                                                     There are multiple ways of doing that... - (FuManChu)
                                             LCD *for my framework* - (FuManChu) - (103)
                                                 RDBMS > "data store" - (tablizer) - (102)
                                                     Re: RDBMS > "data store" - (admin) - (92)
                                                         still have not justified yet another tool/layers - (tablizer) - (91)
                                                             Re: still have not justified yet another tool/layers - (admin) - (90)
                                                                 before and after - (tablizer) - (89)
                                                                     Re: before and after - (admin) - (88)
                                                                         Then why have an OR-mapper middleman? -NT - (tablizer) - (87)
                                                                             Because: - (admin) - (86)
                                                                                 I forgot about query caching--a big part of my other app. -NT - (FuManChu)
                                                                                 Those are problems that OO introduces - (tablizer) - (84)
                                                                                     Re: Those are problems that OO introduces - (admin) - (83)
                                                                                         response - (tablizer) - (82)
                                                                                             Re: response 1 - (admin) - (3)
                                                                                                 Looks like a lot of beurOOcracy to me - (tablizer) - (2)
                                                                                                     Not claiming "victory" - (admin)
                                                                                                     Let's see your version, then. -NT - (pwhysall)
                                                                                             Re: response 2 - (admin) - (16)
                                                                                                 Re Re: response 2 - (tablizer) - (15)
                                                                                                     HQL is a superset of SQL - (admin) - (13)
                                                                                                         re: HQL is a superset of SQL - (tablizer) - (12)
                                                                                                             re: HQL is a superset of SQL - (admin) - (11)
                                                                                                                 Forced to use A to get B? Tsk tsk tsk. How MS of them. -NT - (tablizer) - (10)
                                                                                                                     You miss the point, anyway. - (admin) - (9)
                                                                                                                         I am not necessarily disagreeing with that here - (tablizer) - (8)
                                                                                                                             Re: I am not necessarily disagreeing with that here - (admin) - (7)
                                                                                                                                 not my burden of evidence - (tablizer) - (6)
                                                                                                                                     Wrong. - (admin) - (3)
                                                                                                                                         exist != good - (tablizer) - (2)
                                                                                                                                             Existence beats Non-Existence -NT - (ChrisR)
                                                                                                                                             I've already shown you. - (admin)
                                                                                                                                     Hm. So I can make any claim and force you to prove me wrong? - (FuManChu) - (1)
                                                                                                                                         Actually, what he said was: - (admin)
                                                                                                     Persistence vs. reporting - (admin)
                                                                                             Re: response 3 - (admin) - (55)
                                                                                                 Re Re: response 3 - (tablizer) - (54)
                                                                                                     Caching - (admin) - (2)
                                                                                                         Re: caching - (tablizer) - (1)
                                                                                                             Er, no it isn't. - (admin)
                                                                                                     Serial changes - (admin) - (50)
                                                                                                         "Bound" fields - (tablizer) - (49)
                                                                                                             No, no integration. - (admin) - (48)
                                                                                                                 re: No integration - (tablizer) - (47)
                                                                                                                     re: No integration - (admin) - (46)
                                                                                                                         So you want to see an Iwethey clone? - (tablizer) - (45)
                                                                                                                             I'd prefer you answer the points first. - (admin) - (44)
                                                                                                                                 We need code, not brochure-talk, to settle this - (tablizer) - (43)
                                                                                                                                     Re: We need code, not brochure-talk, to settle this - (admin) - (42)
                                                                                                                                         Is that part of iwethey? -NT - (tablizer) - (1)
                                                                                                                                             Yes. -NT - (admin)
                                                                                                                                         questions and comments - (tablizer) - (39)
                                                                                                                                             Reading comprehension? - (ben_tilly) - (2)
                                                                                                                                                 What is your complaint? - (tablizer) - (1)
                                                                                                                                                     Why not eliminate everything that is only a bonus? - (ben_tilly)
                                                                                                                                             Then don't bother. - (admin) - (16)
                                                                                                                                                 Fine. It is not "bloated". Just unknown. - (tablizer) - (15)
                                                                                                                                                     That's all I needed. - (admin) - (8)
                                                                                                                                                         Probably not telling you anything you don't already know... - (ChrisR) - (5)
                                                                                                                                                             I take it you mean... - (admin) - (1)
                                                                                                                                                                 Yep = That's what I meant - (ChrisR)
                                                                                                                                                             Re: Probably not telling you anything you don't already know - (JimWeirich) - (2)
                                                                                                                                                                 My memory is too taxed - (ChrisR)
                                                                                                                                                                 Memory Lane - (tablizer)
                                                                                                                                                         re: That's all I needed. - (tablizer) - (1)
                                                                                                                                                             re: That's all I needed. - (admin)
                                                                                                                                                     Caching - (admin)
                                                                                                                                                     Login checks and declarative processing - (admin) - (4)
                                                                                                                                                         re: Login checks and declarative processing - (tablizer) - (3)
                                                                                                                                                             re: Login checks and declarative processing - (admin) - (2)
                                                                                                                                                                 re re: Login checks and declarative processing - (tablizer) - (1)
                                                                                                                                                                     Re: Login checks and declarative processing (new thread) - (admin)
                                                                                                                                             I18N - (admin) - (18)
                                                                                                                                                 You are WRONG! - (tablizer) - (17)
                                                                                                                                                     My my, I touched a raw nerve, apparently. - (admin) - (16)
                                                                                                                                                         Grep is no substitute for clean, normalized data - (tablizer) - (15)
                                                                                                                                                             Re: Grep is no substitute for clean, normalized data - (admin) - (14)
                                                                                                                                                                 Depends on the scale - (tablizer) - (13)
                                                                                                                                                                     You've never used CVS either, have you? -NT - (FuManChu) - (3)
                                                                                                                                                                         No, only MS sourcesafe -NT - (tablizer) - (2)
                                                                                                                                                                             *shudder* - (admin) - (1)
                                                                                                                                                                                 Not my pickings -NT - (tablizer)
                                                                                                                                                                     Re: Depends on the scale - (admin) - (8)
                                                                                                                                                                         no no no - (tablizer) - (7)
                                                                                                                                                                             Re: no no no - (admin) - (6)
                                                                                                                                                                                 Doing my part to promote right shifting - (ChrisR) - (3)
                                                                                                                                                                                     "Oh goody, a new framework for xmas!" - (tablizer) - (1)
                                                                                                                                                                                         Re: "Oh goody, a new framework for xmas!" - (admin)
                                                                                                                                                                                     Internationalization (new thread) - (admin)
                                                                                                                                                                                 admin - (tablizer) - (1)
                                                                                                                                                                                     Resource files (new thread) - (admin)
                                                                                             Re: response 4 - (admin) - (3)
                                                                                                 Lock-in is lock-in - (tablizer) - (2)
                                                                                                     Query caching is a feature of JDBC - (admin) - (1)
                                                                                                         Yes - (tablizer)
                                                                                             Re: response 5 - (admin)
                                                     Most of those are problems, not solutions. - (FuManChu) - (8)
                                                         intense DBA and RDBMS bashing - (tablizer) - (7)
                                                             ..heh. Only because they deserve it. ;) - (FuManChu) - (6)
                                                                 re: Only because they deserve it. - (tablizer) - (5)
                                                                     I assume you already expect my response: - (FuManChu) - (4)
                                                                         I will agree that... - (tablizer) - (3)
                                                                             I've never claimed that _every_ O-R mapper is chicken soup - (FuManChu) - (2)
                                                                                 Most people can at least read Python within 5 minutes. -NT - (admin) - (1)
                                                                                     Whatever -NT - (tablizer)

What does this have to do with the movie?
403 ms