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 Re: Those are problems that OO introduces
SQL is pretty compact. It is hard to beat in code size. And one can make little functions for patterns that are used often.
SQL is compact. The procedural code needed to manipulate the SQL and the results is not so compact.

What exactly is "manual result set handling"?
while (rs.hasNext()) { extract row information }

I am still skeptical that it can handle more complex SQL conversions. And, one does not need OO to make lowest-common-denominator SQL wrappers/helpers.
So show one that it can't handle. One doesn't "need" OO to do anything. I stated that that was a reason to prefer O-R mapping over JDBC.

What is transparent persistence? Sounds like something that only matters to OO heads because you have two databases: your application object RAM web and the database. If you talk directly to the database, you don't have this problem. An SQL UPDATE statement simply says "change this". OO creates a problem because you have two "state things" that must be coordinated. You have one "noun model" in app RAM and another in the database (which may be RAM or disk). They have to do the Tango.
If you talk directly to the database, you lose opportunities for caching the data closer to where it is used. You also lose opportunities for creating screens that collect changes serially, then post them to the database all at once.

Oxymoron. Perhaps you mean it builds those monotonous set/gets. "Natural" my ass.
Natural within an existing OO system, as opposed to combining OO with SQL.

Query string caching or query results caching?
Neither. Compiled query caching, to remove the need to parse "select * from foo" every time it's used.

I note that you omitted:

Dual layer caching
Lazy instantiation
Database/data source independence

Am I to take this to mean that you agree that these are benefits?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New response
I would like to see some psuedo-code or details for how you avoid "manual result set handling".

So show [SQL query] that it can't handle.


I posted one I would like to see in a nearby message. The "GPA" one.

If you talk directly to the database, you lose opportunities for caching the data closer to where it is used. You also lose opportunities for creating screens that collect changes serially, then post them to the database all at once.


I would like a more specific example.

Compiled query caching, to remove the need to parse "select * from foo" every time it's used.


That is called a "stored procedure". But, if it is DB-neutral, what are you sending to the DB itself? Not SQL?

I note that you omitted: Dual layer caching, Lazy instantiation, Database/data source independence


I suspect the first 2 are something specific to an OO-centric design. The last one was already discussed. I doubt one can nicely put nearly all SQL behind an API. And if possible, I doubt only OO can do it well.
________________
oop.ismad.com
New Re: response 1
I would like to see some psuedo-code or details for how you avoid "manual result set handling".
No pseudo-code, bunky. This here's th' real stuff.

This is the JDBC equivalent of HibUserManager, albeit an older version of the interface. Note that even so, this is much better than "straight" JDBC in that it has been Springified. Raw JDBC has a lot more try/catch logic.

"mapRow()" is an example of manual result set handling. There will be one line per column in the table, at least.
\npublic class JdbcUserManager implements UserManager\n{\n    private DataSource mDatasource;\n\n\tprivate HashMap mUserCache = new HashMap();\n\n\tprivate UserQuery mUserNicknameRetriever = null;\n\n\tprivate UserQuery mUserIdRetriever = null;\n\n\tprivate UserQuery mAllUsersRetriever = null;\n\n\tprivate SqlFunction mUserLogin = null;\n\n\tprivate SqlUpdate mUserCreater = null;\n\n\tprivate SqlUpdate mUserRemover = null;\n\n\tprivate SqlUpdate mUserUpdatePassword = null;\n\n\tprivate SqlFunction mUserCounter = null;\n\n\tprivate SqlFunction mUserExists = null;\n\n\tprivate SqlFunction mActiveUserCounter = null;\n\n\tprivate SqlUpdate mUserPresent = null;\n\n\tprivate UserPropertyQuery mUserPropertyRetriever = null;\n\n\tprivate UserPropertiesQuery mAllUserPropertiesRetriever = null;\n\n\tprivate SqlFunction mUserPropertySetter = null;\n\n    public List getUserList()\n\t\t{\n\t\t\treturn mAllUsersRetriever.execute();\n\t\t}\n\n    public User getUserByNickname(String nickname)\n\t\t{\n\t\t\tUser user = (User) mUserCache.get(nickname);\n\n\t\t\tif (user == null)\n\t\t\t\t{\n\t\t\t\t\tuser = (User) mUserNicknameRetriever.findObject(nickname);\n\t\t\t\t\tif (user != null)\n\t\t\t\t\t\tmUserCache.put(nickname, user);\n\t\t\t\t}\n\n\t\t\treturn user;\n\t\t}\n\n    public User getUserById(int id)\n\t\t{\n\t\t\treturn (User) mUserIdRetriever.findObject(id);\n\t\t}\n\n    public boolean checkLogin(User user)\n\t\t{\n\t\t\tif (mUserLogin.runGeneric(new Object[] { user.getNickname(), user.getEncryptedPassword() }) == null)\n\t\t\t\treturn false;\n\t\t\telse\n\t\t\t\treturn true;\n\t\t}\n\n    public void createNewUser(User user)\n\t\t{\n\t\t\tString password = user.getEncryptedPassword();\n\t\t\tint count = mUserCreater.update(new Object[] { user.getNickname(), password });\n\t\t}\n\n\tpublic void saveUser(User user)\n\t\t{\n\t\t\tif (userExists(user))\n\t\t\t\t{\n\t\t\t\t\tif (user.getEncryptedPassword() != null && user.getEncryptedPassword().length() > 0)\n\t\t\t\t\t\tmUserUpdatePassword.update(user.getEncryptedPassword(), user.getNickname());\n\t\t\t\t}\n\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcreateNewUser(user);\n\t\t\t\t}\n\n\t\t\tMap props = user.getProperties();\n\t\t\tif (props != null)\n\t\t\t\t{\n\t\t\t\t\tSet keys = props.keySet();\n\t\t\t\t\tIterator iter = keys.iterator();\n\t\t\t\t\twhile (iter.hasNext())\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tString key = (String) iter.next();\n\t\t\t\t\t\t\tsetUserProperty(user.getId(), key, (String) props.get(key));\n\t\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\tmUserCache.remove(user.getNickname());\n\t\t}\n\n    public void removeUser(User user)\n\t\t{\n\t\t\tlogger.info("deleting user: " + user.getNickname());\n\n\t\t\tint count = mUserRemover.update(user.getNickname());\n\t\t\tmUserCache.remove(user.getNickname());\n\t\t}\n\n    public void userPresent(User user)\n\t\t{\n\t\t\tint count = mUserPresent.update(new Object[] { new Timestamp(user.getLastPresent().getTime()),\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   user.getNickname() } );\n\t\t}\n\n\tpublic int getUserCount()\n\t\t{\n\t\t\treturn mUserCounter.run();\n\t\t}\n\n\tpublic int getActiveUserCount()\n\t\t{\n\t\t\treturn mActiveUserCounter.run(new Object[] {"10 minutes"});\n\n\t\t}\n\n\tpublic boolean userExists(String nickname)\n\t\t{\n\t\t\treturn mUserExists.run(new Object[] {nickname} ) == 1;\n\t\t}\n\n\tpublic boolean userExists(User user)\n\t\t{\n\t\t\treturn userExists(user.getNickname());\n\t\t}\n\n\tpublic Map getUserProperties(User user)\n\t\t{\n\t\t\treturn mAllUserPropertiesRetriever.execute(user.getId());\n\t\t}\n\n\tpublic String getUserProperty(int id , String name)\n\t\t{\n\t\t\treturn (String) mUserPropertyRetriever.findObject(\n\t\t\t\tnew Object[] { new Integer(id), name }\n\t\t\t\t);\n\t\t}\n\n\tpublic void setUserProperty(int id, String name, String value)\n\t\t{\n\t\t\tint count = mUserPropertySetter.run(\n\t\t\t\tnew Object[] { new Integer(id), name, value }\n\t\t\t\t);\n\t\t}\n\n\tpublic void clearUserCache()\n\t\t{\n\t\t\tmUserCache = new HashMap();\n\t\t}\n\n    protected class UserQuery extends MappingSqlQuery\n\t{\n        protected UserQuery(DataSource ds, String sql)\n\t\t\t{\n\t\t\t\tsuper(ds, sql);\n\t\t\t}\n \n        protected Object mapRow(ResultSet rs, int rowNum) throws SQLException\n\t\t\t{\n\t\t\t\tString nickname = rs.getString("nickname");\n\t\t\t\tUser user = (User) mUserCache.get(nickname);\n\t\t\t\t\n\t\t\t\tif (user == null)\n\t\t\t\t\t{\n\t\t\t\t\t\tuser = new JdbcUser(JdbcUserManager.this, rs);\n\n\t\t\t\t\t\tuser.setProperties(JdbcUserManager.this.getUserProperties(user));\n\n\t\t\t\t\t\tmUserCache.put(nickname, user);\n\t\t\t\t\t}\n\n\t\t\t\treturn user;\n\t\t\t}\n\n    }\n\n    protected class UserPropertyQuery extends MappingSqlQuery\n\t{\n        protected UserPropertyQuery(DataSource ds, String sql)\n\t\t\t{\n\t\t\t\tsuper(ds, sql);\n\t\t\t}\n \n        protected Object mapRow(ResultSet rs, int rowNum) throws SQLException\n\t\t\t{\n\t\t\t\treturn rs.getString("value");\n\t\t\t}\n\n    }\n\n\tpublic class UserPropertiesQuery extends SqlOperation\n\t{\n\t\tpublic UserPropertiesQuery(DataSource ds, String sql)\n\t\t\t{\n\t\t\t\tsetDataSource(ds);\n\t\t\t\tsetSql(sql);\n\t\t\t}\n\n\t\tpublic Map execute(int id)\n\t\t\tthrows DataAccessException\n\t\t\t{\n\t\t\t\tPropertyHandler handler = new PropertyHandler();\n\t\t\t\tgetJdbcTemplate().query(newPreparedStatementCreator(new Object[] { new Integer(id) } ), handler);\n\t\t\t\treturn handler.getResults();\n\t\t\t}\n\n\t\tprivate class PropertyHandler implements RowCallbackHandler\n\t\t{\n\t\t\tprivate Map mResults = new HashMap();\n\n\t\t\tpublic void processRow(java.sql.ResultSet rs)\n\t\t\t\tthrows SQLException\n\t\t\t\t{\n\t\t\t\t\tmResults.put(rs.getString("name"), rs.getString("value"));\n\t\t\t\t}\n\n\t\t\tMap getResults() { return mResults; }\n\t\t}\n\t}\n\n\tprivate static final String GET_ALL_USERS_SQL = \n\t"select user_id, nickname, created, last_present from iwethey_user order by nickname";\n\n\tprivate static final String GET_USER_SQL = \n\n\t"select user_id, nickname, created, last_present from iwethey_user where nickname = ?";\n\n\tprivate static final String GET_USER_ID_SQL = \n\t"select user_id, nickname, created, last_present from iwethey_user where user_id = ?";\n\n\tprivate static final String USER_LOGIN_SQL = \n\t"select 1 from iwethey_user where nickname = ? and password = ?";\n\n\tprivate static final String CREATE_USER_SQL = \n\t"insert into iwethey_user ( nickname, password ) values (?, ?)";\n\n\tprivate static final String REMOVE_USER_SQL = \n\t"delete from iwethey_user where nickname = ?";\n\n\tprivate static final String COUNT_USERS_SQL = \n\t"select count(1) from iwethey_user";\n\n\tprivate static final String USER_EXISTS_SQL = \n\t"select count(1) from iwethey_user where nickname = ?";\n\n\tprivate static final String COUNT_ACTIVE_USERS_SQL = \n\t"select count(nickname) as usercount from iwethey_user where ('now' - last_present) < interval ?";\n\n\tprivate static final String USER_PRESENT_SQL = \n\t"update iwethey_user set last_present = ? where nickname = ?";\n\n\tprivate static final String USER_UPDATE_PASSWORD_SQL = \n\t"update iwethey_user set password = ? where nickname = ?";\n\n\tprivate static final String GET_USER_PROPERTY_SQL = \n\t"select value from user_property where user_id = ? and name = ?";\n\n\tprivate static final String GET_ALL_USER_PROPERTIES_SQL = \n\t"select user_id, name, value from user_property where user_id = ?";\n\n\tprivate static final String SET_USER_PROPERTY_SQL = \n\t"select setUserProperty(?, ?, ?)";\n\n    public void setDataSource(DataSource ds)\n\t\t{\n\t\t\tmDatasource = ds;\n\n\t\t\tmAllUsersRetriever = new UserQuery(ds, GET_ALL_USERS_SQL);\n\t\t\tmAllUsersRetriever.compile();\n\n\t\t\tmUserNicknameRetriever = new UserQuery(ds, GET_USER_SQL);\n\t\t\tmUserNicknameRetriever.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserNicknameRetriever.compile();\n\n\t\t\tmUserIdRetriever = new UserQuery(ds, GET_USER_ID_SQL);\n\t\t\tmUserIdRetriever.declareParameter(new SqlParameter(java.sql.Types.INTEGER));\n\t\t\tmUserIdRetriever.compile();\n\n\t\t\tmUserLogin = new SqlFunction(ds, USER_LOGIN_SQL);\n\t\t\tmUserLogin.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserLogin.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserLogin.compile();\n\n\t\t\tmUserCreater = new SqlUpdate(ds, CREATE_USER_SQL);\n\t\t\tmUserCreater.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserCreater.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserCreater.compile();\n\n\t\t\tmUserRemover = new SqlUpdate(ds, REMOVE_USER_SQL);\n\t\t\tmUserRemover.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserRemover.compile();\n\n\t\t\tmUserPresent = new SqlUpdate(ds, USER_PRESENT_SQL);\n\t\t\tmUserPresent.declareParameter(new SqlParameter(java.sql.Types.TIMESTAMP));\n\t\t\tmUserPresent.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserPresent.compile();\n\n\t\t\tmUserUpdatePassword = new SqlUpdate(ds, USER_UPDATE_PASSWORD_SQL);\n\t\t\tmUserUpdatePassword.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserUpdatePassword.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserUpdatePassword.compile();\n\n\t\t\tmUserPropertyRetriever = new UserPropertyQuery(ds, GET_USER_PROPERTY_SQL);\n\t\t\tmUserPropertyRetriever.declareParameter(new SqlParameter(java.sql.Types.INTEGER));\n\t\t\tmUserPropertyRetriever.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserPropertyRetriever.compile();\n\n\t\t\tmAllUserPropertiesRetriever = new UserPropertiesQuery(ds, GET_ALL_USER_PROPERTIES_SQL);\n\t\t\tmAllUserPropertiesRetriever.declareParameter(new SqlParameter(java.sql.Types.INTEGER));\n\t\t\tmAllUserPropertiesRetriever.compile();\n\n\t\t\tmUserPropertySetter = new SqlFunction(ds, SET_USER_PROPERTY_SQL);\n\t\t\tmUserPropertySetter.declareParameter(new SqlParameter(java.sql.Types.INTEGER));\n\t\t\tmUserPropertySetter.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserPropertySetter.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserPropertySetter.compile();\n\n\t\t\tmUserCounter = new SqlFunction(ds, COUNT_USERS_SQL);\n\t\t\tmUserCounter.compile();\n\n\t\t\tmUserExists = new SqlFunction(ds, USER_EXISTS_SQL);\n\t\t\tmUserExists.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmUserExists.compile();\n\n\t\t\tmActiveUserCounter = new SqlFunction(ds, COUNT_ACTIVE_USERS_SQL);\n\t\t\tmActiveUserCounter.declareParameter(new SqlParameter(java.sql.Types.VARCHAR));\n\t\t\tmActiveUserCounter.compile();\n\t\t}\n}\n


In order to have lazy instantiation and caching, you need the JdbcUser object as well:
\npublic class JdbcUser extends User\n{\n\tprivate UserManager mManager = null;\n\n\tpublic JdbcUser() { }\n\n\tpublic JdbcUser(User user)\n\t\t{\n\t\t\tsuper(user);\n\t\t}\n\n\tpublic JdbcUser(UserManager manager)\n\t\t{\n\t\t\tsuper(manager);\n\t\t}\n\n\tpublic JdbcUser(UserManager manager, ResultSet rs)\n\t\tthrows SQLException\n\t\t{\n\t\t\tsuper(manager);\n\n\t\t\tsetId(rs.getInt("user_id"));\n\t\t\tsetNickname(rs.getString("nickname"));\n\t\t\tsetCreated(rs.getTimestamp("created"));\n\t\t\tsetLastPresent(rs.getTimestamp("last_present"));\n\t\t}\n\n\tpublic JdbcUser(UserManager manager, String nickname, String password)\n\t\t{\n\t\t\tsuper(manager, nickname, password);\n\t\t}\n\n\tpublic Map getProperties()\n\t\t{\n\t\t\tMap props = super.getProperties();\n\n\t\t\tif (props == null || props.size() == 0)\n\t\t\t\t{\n\t\t\t\t\tif (mManager != null)\n\t\t\t\t\t\tprops = ((JdbcUserManager) mManager).getUserProperties(this);\n\n\t\t\t\t\tif (props == null)\n\t\t\t\t\t\tprops = new HashMap();\n\t\t\t\t}\n\n\t\t\tsetProperties(props);\n\t\t\treturn props;\n\t\t}\n}\n


Note that the JdbcUser is actually NOT serializable, which prevents it being used in sessions and the like.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Looks like a lot of beurOOcracy to me
The question comes up: why did you need all that crap in the first place. It appears you replaced really bad crap with slightly less bad crap and claim victory.
________________
oop.ismad.com
New Not claiming "victory"
You asked why I would use O-R mapping. I stated that I would use it over JDBC for particular reasons, and over straight SQL for others.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Let's see your version, then.


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 Re: response 2
I posted one I would like to see in a nearby message. The "GPA" one.
I'm talking about persistence, not reporting. Hammers for nails, screwdrivers for screws. I'd probably use a stored procedure to obtain a single number like that. But since you asked, Hibernate supports aggregates as well.

Float avg = single("select avg(grade) from (select avg(student.grades) as grade from Student student)");

Note the absence of a group by. Very similar, otherwise.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Re Re: response 2
Float avg = single("select avg(grade) from (select avg(student.grades) as grade from Student student)");


You are passing a string of an SQL-like query language, but it is not SQL. Is this correct? Why invent another query language that is sort of like SQL? People already know SQL. (I agree that SQL is not the ideal relational language, but until a better standard is established, it is good enough.)

I'm talking about persistence, not reporting.


I am not sure what you are getting at then. Note that data dictionaries make a nice place to put info about converting fields into data columns, such as DB column type, length limits, etc. Ideally that perhaps should be stored in the RDBMS schemas, but vendors don't support extending that stuff for some reason.
________________
oop.ismad.com
New HQL is a superset of SQL
HQL understands inheritance and polymorphism. Joins are made automatically based on foreign key references. You'll note the lack of a group by in the previous example; that is significant. It also allows selection of grouped bodies of data without specification:

select parent from Post; - selects all of the data as a Parent object, without needing to specifiy what that entails.

It allows formation of objects on the fly through the query language as well:

select new Foo(a, b, c) from Bar; - creates a new Foo object as a subset of a Bar object.

Queries without joins:

from Post as post where post.parent.subject like '%response%';

from Post as post where post.forum.board.owner = ?;

Note that, with caching, some of the above can be resolved entirely in memory without a trip to the database.

Test sizes of collections:

from Forum as forum where forum.posts[0].responses.size > 42; - find all forums where the first post in the forums has more than 42 responses.

Here's a good one from the Hibernate docs:
select cust\nfrom Product prod,\n    Store store\n    inner join store.customers cust\nwhere prod.name = 'widget'\n    and store.location.name in ( 'Melbourne', 'Sydney' )\n    and prod = all elements(cust.currentOrder.lineItems)\n\nvs.\n\nSELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order\nFROM customers cust,\n    stores store,\n    locations loc,\n    store_customers sc,\n    product prod\nWHERE prod.name = 'widget'\n    AND store.loc_id = loc.id\n    AND loc.name IN ( 'Melbourne', 'Sydney' )\n    AND sc.store_id = store.id\n    AND sc.cust_id = cust.id\n    AND prod.id = ALL(\n        SELECT item.prod_id\n        FROM line_items item, orders o\n        WHERE item.order_id = o.id\n            AND cust.current_order = o.id\n    )\n






Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New re: HQL is a superset of SQL
Joins are made automatically based on foreign key references.


Some RDBMS SQL dialects provide this ability also I hear, but I have yet to try it.

Here's a good one from the Hibernate docs: ....


Hmmm. Interesting. It uses "dot paths", such as "store.location.name".

Anyhow, suppose this HQL is the greatest query language since sliced bread and really does isolate one from specific RDBMS vendors.

Couldn't one just use HQL in place of SQL in procedural code without the rest of the OR-mapper stuff? (Assuming ER info is given via meta data.)

You are doing a better job at selling a query language than you are at selling OR-mappers, and so far they generally seem like orthogonal things.
________________
oop.ismad.com
New re: HQL is a superset of SQL
The query language is integral to the O-R mapper, and vice versa, in that it returns objects.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Forced to use A to get B? Tsk tsk tsk. How MS of them.
________________
oop.ismad.com
New You miss the point, anyway.
HQL can be used against any database engine.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New I am not necessarily disagreeing with that here
I am only saying that a better and/or vender-neutral query language/system is or can be orthogonal to O-R mappers.
________________
oop.ismad.com
New Re: I am not necessarily disagreeing with that here
At this point, it is not orthogonal. It exists for Hibernate, and it was easy to write because of OO. If you disagree, prove me wrong. Otherwise concede the point.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New not my burden of evidence
It exists for Hibernate, and it was easy to write because of OO. If you disagree, prove me wrong. Otherwise concede the point.


By "easy to write", do you mean using the framework or making the framework?

You have the burden of showing something being "easy". Remember: "Equal, subjective, or unknown until proven otherwise". I can accept that my preferences may be purely a subjective mindfit. If you believe OO is some universal truth and/or a slum-dunk improvement, then it is your burden to show it.
________________
oop.ismad.com
Expand Edited by tablizer May 23, 2004, 12:10:06 AM EDT
New Wrong.
Hibernate exists. Your mythical über SQL doesn't. If your version is even as good, let alone better, then you need to show it. Otherwise it's vaporware.

Now go answer or concede the other points.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New exist != good
Hibernate exists. Your mythical \ufffdber SQL doesn't. If your version is even as good, let alone better, then you need to show it. Otherwise it's vaporware.


Mere existence does not necessarily lead to goodness. You need to explain why it is so good using code. Show me something that procedural or raw SQL MUST result in a mess with. Nor am I going to compete with an army of programmers to build a clone of Hibernate all by myself. That is not a realistic request. I can perhaps show specific aspects though.

And being DB-neutral is moot because you are tied to Hibernate in a similar way. You are applying a double-standard.
________________
oop.ismad.com
New Existence beats Non-Existence
New I've already shown you.
Go answer or concede the other points.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Hm. So I can make any claim and force you to prove me wrong?
You started this debate with some wild claims. Are you saying now "that was just subjective?"

Remember: "Equal, subjective, or unknown until proven otherwise".


Nice ideal. But they're in reverse order. If you want your claims to move from unknown/subjective to equal, the burden is on *you*. That's life. Suck it up.
New Actually, what he said was:
"You spend all your code translating back and forth between two discordant paradigms."

So he made a very specific claim in this instance. ;-)
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
Expand Edited by admin May 23, 2004, 10:53:33 AM EDT
New Persistence vs. reporting
Saving and retrieving students is persistence.

Performing aggregate queries on properties of students is reporting.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Re: response 3
If you talk directly to the database, you lose opportunities for caching the data closer to where it is used. You also lose opportunities for creating screens that collect changes serially, then post them to the database all at once.
I would like a more specific example.


Caching example: doing a direct select on the database every time you need user information prevents you from caching the user information in memory. This isn't so big a deal for something like FoxPro, but it is when the query is more expensive; ie. against a remote database. If you're constantly querying the users, just load them locally and don't go against the database. An O-R layer handles this transparently.

Serial changes with batch update example: a set of user preference screens with different properties on each page. The user can change the preferences individually, then when satisfied do a Save that saves all of the properties at once. If you're going directly to the database, you have no intermediary data representation to store the possibly temporary values.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
Expand Edited by admin May 22, 2004, 05:14:00 PM EDT
New Re Re: response 3
Caching example: doing a direct select on the database every time you need user information prevents you from caching the user information in memory.


If it is used often, then simply write it to a memory variable:
\n  // create user-info map array\n  userInfo = queryRow("select * from users where userId = %1", userID)\n

Things like this are used fairly often in web scripts where user authentication is in a standard include-file, for example. I don't see what the big deal is. Here is a more thorow example to clarify the context:
\n  // standard header include file\n  ...\n  userID = session('userID');\n  if (empty(userID)) {\n    loginScreen();\n    endScript();\n  } else {\n    // create user-info map array\n    userInfo = queryRow("select * from users where userId = %1", userID)\n  }\n  ...\n

The userInfo array is now available to the entire script. I suppose you could argue that the login screen and the array query may be redundant references to the User table, but the DBMS might already perform caching of such. In other words, the second time you reference a given record in a short period of time, the second request should be quicker because the DB caches it for a while. Further, if you have a middle-layer between the app and the DB, then things might get out of sync with the database, such as a user record being deleted because an employee is fired (for bashing OO). More things to go wrong and more time-out scenarios to test.

Serial changes with batch update example: a set of user preference screens with different properties on each page. The user can change the preferences individually, then when satisfied do a Save that saves all of the properties at once. If you're going directly to the database, you have no intermediary data representation to store the possibly temporary values.


Assuming a "real" GUI, that info stays on the screens until it is saved. The screen serves as the intermediary data hold in this case. When they press "Save" or "Ok", then it writes those fields to the tables. If they press "Cancel", then it doesn't. (A good screen system allows hidden fields also that can come in handy at times.)
________________
oop.ismad.com
New Caching
// create user-info map array
userInfo = queryRow("select * from users where userId = %1", userID)

That's not caching. Now show the code that checks to see if it's already cached, and if not, to retrieve it from the database. Because if you're just relying on the database to cache, and the database is on another machine, you have to wait for the information to come over the wire. With an in-memory cache, it's already there. The performance increase is substantial.

For most applications, out of sync data isn't a worry. Only if more than one application is modifying the data in question is that an issue. And if you have more than one application doing this, you can use distributed cache updates.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Re: caching
That's not caching.


Yes it is. If I need something often in a given task, then I save it in a memory variable. What is the big deal? You are creating a solution for a minor or non-existing problem it seems.
________________
oop.ismad.com
New Er, no it isn't.
Where's the code to update it when you change it? Where's the code that decides when to load it? All you're doing is loading the one set of values and then using them for a single render transaction. That isn't caching.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Serial changes
Assuming a "real" GUI, that info stays on the screens until it is saved. The screen serves as the intermediary data hold in this case. When they press "Save" or "Ok", then it writes those fields to the tables. If they press "Cancel", then it doesn't. (A good screen system allows hidden fields also that can come in handy at times.)
And then you have to copy that intermediary data to the update queries. With an O-R mapping layer, there is no reverse mapping step. As such, you are just poorly duplicating the O-R system with one-off field mappings and storage areas.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New "Bound" fields
And then you have to copy that intermediary data to the update queries. With an O-R mapping layer, there is no reverse mapping step. As such, you are just poorly duplicating the O-R system with one-off field mappings and storage areas.


That probably assumes some integration with the GUI system. It is sometimes called "bound" fields, or a variation of. Generally such a framework stores the database column name, and perhaps also entity or query name, in the screen widget definition. Then a standard set of operations can automatically create the SQL to populate and save the info.
________________
oop.ismad.com
New No, no integration.
Java Beans, mapped to fields. Automatic, and it doesn't care where the data comes from, or where it's going, like bound fields do. And that doesn't cover web applications.

So with a web application, you will have a reverse mapping step given your example. Yes or no?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
Expand Edited by admin May 22, 2004, 07:52:15 PM EDT
New re: No integration
Java Beans, mapped to fields. Automatic, and it doesn't care where the data comes from, or where it's going, like bound fields do. And that doesn't cover web applications.


Somehow database columns have to be associated with screen widgets. Applications and frameworks cannot read minds. For one, it is often not a one-to-one correspondence so that we cannot just take a schema as-is and splash it on a screen. Perhaps such can serve as the starting point, but not the final.

So with a web application, you will have a reverse mapping step given your example. Yes or no?


Ideally there is a data-dictionary-like UI item table that has optional column names. When the screen is drawn, it uses those column names to populate the widget. And when it is time to save, the same column names are used to build the saving SQL (unless designated read-only).
________________
oop.ismad.com
New re: No integration
Somehow database columns have to be associated with screen widgets. Applications and frameworks cannot read minds. For one, it is often not a one-to-one correspondence so that we cannot just take a schema as-is and splash it on a screen. Perhaps such can serve as the starting point, but not the final.
Correct.

Ideally there is a data-dictionary-like UI item table that has optional column names. When the screen is drawn, it uses those column names to populate the widget. And when it is time to save, the same column names are used to build the saving SQL (unless designated read-only).
So this includes data caching, query caching, and so on like Hibernate does? You'll have to write it and show it to convince me that it isn't more bloated than the example I've already given.

Where's the bloat with O-R mapping? You haven't shown that, and therefore your claim is still bogus.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New So you want to see an Iwethey clone?

________________
oop.ismad.com
New I'd prefer you answer the points first.
But suits me. The new version, of course, not this one.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New We need code, not brochure-talk, to settle this
I will not match iwethey feature-for-feature because nobody is ever going to use it, since there is already one. But, I could create the basic functionality and then add specific features that you want to explore.
________________
oop.ismad.com
Expand Edited by tablizer May 23, 2004, 05:24:01 PM EDT
New Re: We need code, not brochure-talk, to settle this
The user create/login/edit functionality of the new site I linked should be sufficient. I'll refresh the version that's on the site.

Features it has:

User caching and on-demand loading of user preferences
Session variables linked by a cookie session ID
Anonymous users
Login required can be turned on declaratively by screen
Remote database (ie. no filesystem databases - this isn't a desktop app)
Internationalized message stores for field labels and errors
Full unit and regression testing

Since this is a practical example, use whatever toolkits you wish, and no whining thereof. I'm not interested in pie-in-the-sky "well, it COULD be like this" crap.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
Expand Edited by admin May 23, 2004, 06:37:27 PM EDT
New Is that part of iwethey?
________________
oop.ismad.com
New Yes.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New questions and comments
Off the top of my head, here is how I might approach some of these, in case anyone is interested. I also have some questions.

User caching and on-demand loading of user preferences


I am not quite sure what you mean by this. I would possibly use the dictionary-array approach I described a day or so ago.

Session variables linked by a cookie session ID


PHP has built-in session handling (although they keep changing it).

Login required can be turned on declaratively by screen


Not sure what you mean by this. Do you mean the administrator has a switch?

Internationalized message stores for field labels and errors


I would probably create some tables something like this:

Table: Messages
---------------
msgID // could be number or pneumonic
EnglishMsg

Table: Languages
----------------
langID
langDescript // example: Spanish, French, etc.


Table: LanguageMessages
-----------------------
msgRef
langRef
msg

I probably would not include internationalization in my actual example because implementing the above is pretty obvious. More info on speed issues and others at:

[link|http://www.c2.com/cgi/wiki?InternationalUiExample|http://www.c2.com/cg...nationalUiExample]

Note pseudo-code example at the very bottom.

Full unit and regression testing


Fluck that. This is a toy example.

Since this is a practical example, use whatever toolkits you wish


May put me at a disadvantage since there are not a lot of existing TOP toolkits out there. Self-fulfilling prophecy trick again, eh? You sneaky devil.
________________
oop.ismad.com
Expand Edited by tablizer May 24, 2004, 02:01:55 AM EDT
Expand Edited by tablizer May 24, 2004, 12:41:13 PM EDT
New Reading comprehension?
From [link|http://z.iwethey.org/forums/render/content/show?contentid=156520|http://z.iwethey.org...?contentid=156520] (what you are replying to):

Since this is a practical example, use whatever toolkits you wish, and no whining thereof. I'm not interested in pie-in-the-sky "well, it COULD be like this" crap

What Scott said that he didn't want is a pretty good description of what you actually provided.

Don't say, "Well you could do this." Either do it or shut up.

Regards,
Ben
To deny the indirect purchaser, who in this case is the ultimate purchaser, the right to seek relief from unlawful conduct, would essentially remove the word consumer from the Consumer Protection Act
- [link|http://www.techworld.com/opsys/news/index.cfm?NewsID=1246&Page=1&pagePos=20|Nebraska Supreme Court]
New What is your complaint?
I provided descriptions as a *bonus*. If you don't want to read them, then simply ignore them. If Scott does not want to hear "it could be like this....", then he can just plain simply bypass it. The Web is big. Ignore what you don't want.
________________
oop.ismad.com
New Why not eliminate everything that is only a bonus?
Oops, not much is left, huh?

While Scott's attempts to enlighten you sometimes are informative for the rest of us, the conversation long ago reached the point where you really need to put up or shut up. Considering that nobody has demonstrable work experience with the way that you think should work better, while many of us have experience with existing alternatives, the burden of proof is on you to show that it is possible. Not us.

In case you didn't notice, our experience tells us that the approach that you're suggesting will not scale development-wise. Perhaps we just misunderstand what you're suggesting. Perhaps we really do understand what you're suggesting, and our intuition is wrong.

So why not build your own version of part of IWETHEY? I think that it really would be informative to see how you would tackle it. But until you do that, watching your hands flap in the breeze is rather pointless on all sides.

Cheers,
Ben
To deny the indirect purchaser, who in this case is the ultimate purchaser, the right to seek relief from unlawful conduct, would essentially remove the word consumer from the Consumer Protection Act
- [link|http://www.techworld.com/opsys/news/index.cfm?NewsID=1246&Page=1&pagePos=20|Nebraska Supreme Court]
New Then don't bother.
User caching: the user information is cached locally, in RAM, for performance reasons. User properties (preferences) aren't loaded unless they're needed.

Declarative login checking: if I want to require a user to be logged in to reach a particular screen, I put: <ref bean="loginInterceptor"/> in that section of the config file, and the login is checked and redirected if necessary.

Unit testing: Toy examples don't prove anything. If you aren't going to write unit tests then you're not showing anything, because one of the hallmarks of ease of maintenance is testability. It would be real easy to glop together a bunch of crap in a single messy, unmaintainable file and declare "victory".

Toolkits: Again, if it's not something you can do today, what's the point? I work with today's tools. I get things done. You're telling me that my code is bloated compared to what you can do. Well, prove it or concede that it isn't. PHP is used by an awful lot of people and there is a large body of work out there providing libraries of useful things. And if what you need is so all-fired useful, write it yourself so you have it to use in the future, for crying out loud. Should be easy, right, since it's "TOP"?

Unsurprising, Bryce. When it comes down to it all you have is excuses. Do you go to your employers and say, "well, I could code it like this if I had the ÜberMegaTOP Toolkit, but we don't, so I'll have to do a crappy job"...?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
Expand Edited by admin May 24, 2004, 08:27:08 AM EDT
New Fine. It is not "bloated". Just unknown.
User caching: the user information is cached locally, in RAM, for performance reasons. User properties (preferences) aren't loaded unless they're needed.


You are micro-managing how to design such an app. Putting the user preferences into a map array may take up far less space and time than your caching manager because cached info takes up space whether you use it later or not.

Declarative login checking: if I want to require a user to be logged in to reach a particular screen, I put: <ref bean="loginInterceptor"/> in that section of the config file, and the login is checked and redirected if necessary.


So, one could put a "loginOnly()" function at the start of any checked section/page. By not putting it in XML I also have smaller granularity options on where it is used. For example, maybe certain buttons don't show or have a different description if not logged in.

Toolkits: Again, if it's not something you can do today, what's the point? I work with today's tools. I get things done.


So do I. I have written an e-bay clone (more or less) in less than 7 weeks during the dot-com mayham.

When it comes down to it all you have is excuses.


You were the one who has been claiming OO is objectively better and then expect me to rewrite a whole Iwethey from scratch? I withdrawl the "bloated" claim for now. Feel better? However, that still does not make OO less bloated than p/r, only unknown.

BTW, you guys never countered my running-code toy example at:

[link|http://www.geocities.com/tablizer/chal06.htm|http://www.geocities...blizer/chal06.htm]

I was first with the coded challenge, and now you are trying to trump it with your own. If OO cannot do that better, I would like to know why. If it's because it is a toy example instead of a real one, then describe how it differs from a real one that prevents OO's benefits from showing up.

"well, I could code it like this if I had the \ufffdberMegaTOP Toolkit, but we don't, so I'll have to do a crappy job"...?


Sure, if they pay me, I will work with lame tools. It may slow me down compared to a good TOP system, but that is life. Same reason we live with Microsoft. I tend to think that favorite paradigms and tools are subjective. Studies by Ed Yourdon seem to suggest that using tools that one is comfortable with is more important for productivity and quality than selecting tools based on what is popular.

Show me slam-dunk evidence that OO is better, and I will look into it more. Most reasons given for OO are fuzzy-zenny, and make tradeoffs that the claimers are not aware of or conveniently ignore. For example grouping by noun helps noun-oriented changes, but un-helps task-oriented changes. Plus, the reasons everybody gives why OO is better differ. Some say polymorphism off of "subtypes" or variations is the main power of OO. Others who use more delegation disagree. Nobody has been able to clearly "encapsulate" the benefits of OO. All I get is, "it is j..j..j..just b..b..b..better, and if you were smart like me, you would see it."
________________
oop.ismad.com
New That's all I needed.
You were the one who has been claiming OO is objectively better and then expect me to rewrite a whole Iwethey from scratch? I withdrawl the "bloated" claim for now. Feel better? However, that still does not make OO less bloated than p/r, only unknown.
It seems to me the claim under discussion in this thread was "O-R mappers bloat your code". Now that you've admitted that they don't, we can put it to rest.

Although I'll note that old habits apparently die hard. You're still weaseling. Either the code is bloated compared to how you would do it, or it isn't. If you're not willing to provide an example, the conclusion to be drawn is "Bryce can't provide an example", not "the status is unknown." You say it's bloated, prove it. Otherwise it isn't.

So do I. I have written an e-bay clone (more or less) in less than 7 weeks during the dot-com mayham.
Then stop whining about toolkits. You must have used something to do that.

BTW, you guys never countered my running-code toy example at:

[...]

I was first with the coded challenge, and now you are trying to trump it with your own. If OO cannot do that better, I would like to know why. If it's because it is a toy example instead of a real one, then describe how it differs from a real one that prevents OO's benefits from showing up.
1) I'm not in the habit of reading your website in the off-chance that you've provided something for me to do and 2) I'm not interested in toys, which you admit it is. Here's an example that does a real-life thing. If you think you can do better, then have at it. Otherwise shaddap.

[edit: removed the broken "challenge" link]
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
Expand Edited by admin May 24, 2004, 03:12:45 PM EDT
New Probably not telling you anything you don't already know...
...but that example was originally started by Jim Weirich on Freep's OOP board. JohnU also got involved. Of course, since EZBoard decided to shut down the inactive boards, we don't have any extant to refer to.

The reason I like the EZBoard example is (a) it's working (or soon to be working) code - the code can be objectively tested for performance and features; (b) it's something that we share in common and can immediately reap the benefits of any new ideas.

So, yes, let's dispense with code fragments and toy code.
New I take it you mean...
... "IWETHEY example", and not "EZBoard example"?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Yep = That's what I meant
The reporting example was fine, it's just that there was no measurable way to run the code and verify for correctness and performance.
New Re: Probably not telling you anything you don't already know
...but that example was originally started by Jim Weirich on Freep's OOP board

Actually, the problem was introduced by someone else (JohnU perhaps?). Bryce actually wrote some (non-working) psuedo-code for it. All I did was translate Bryce's non-working psuedo-code into working Ruby code. Then I refactored to a better written procedural version and finally made it more flexible by introducing some polymorphism.

I always thought the problem description was a little screwy (I never really understood the need for some the the requirements), but at least we had some form of code from Bryce to compare to. And the OO code compared very favorably with the procedural version (e.g. comparable code sizes (no bloat), polymorphism without taxinomy).

At least, that's how I remember it.
--
-- 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 My memory is too taxed
Not sure why I thought you initiated the sample. But your recollection does sound about right.

Sure wish we hadn't lost the EZBoard archives. For that matter, I wish Freep would come visit every once in a while.
New Memory Lane
I always thought the problem description was a little screwy (I never really understood the need for some the the requirements)


We kind of never agreed on the scope.

And the OO code compared very favorably with the procedural version (e.g. comparable code sizes (no bloat), polymorphism without taxinomy).


If I remember correctly, you implemented a different set of features than mine, so that we really couldn't compare code-to-code for many parts, but rather focused on the architecture issues.
________________
oop.ismad.com
New re: That's all I needed.
It seems to me the claim under discussion in this thread was "O-R mappers bloat your code". Now that you've admitted that they don't, we can put it to rest.


I didn't say that they don't. I just don't have any comparative evidence to offer youses right now.

I am curious though about what percent of self-declared OO proponents prefer O-R mappers. Many have lots of complaints.

"Bryce can't provide an example", not "the status is unknown." You say it's bloated, prove it. Otherwise it isn't.


False dichotomy. The answer to "is A > B" is Null at this point.

Otherwise shaddap.


Okay. After addressing some ongoing subissues, I will shut up about O-R mappers until new evidence arises.
________________
oop.ismad.com
New re: That's all I needed.
Given that the evidence so far has either been conceded or unanswered by you, I'd say "isn't" is a lot closer to the current state of affairs than "null". Of course, you will never admit that, so I'll take a "shaddap". I have no doubt that you'll sit on this for a while and then trot out, "youses never proved it wasn't bloated!" at some point in the future, so I'm calling pre-foul now so it doesn't happen.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Caching
You are micro-managing how to design such an app. Putting the user preferences into a map array may take up far less space and time than your caching manager because cached info takes up space whether you use it later or not.
The caching manager is generic. I don't need special one-off caching code all over the place. And it seems to me that you've always been the "machines are fast, programmers aren't, optimize for the programmer" champion. Why the sudden reversal?

Regardless, I listed it as a feature. If you believe you have a better way of doing it, then do it that way. I'll warn you, though, that the caching speeds the app up considerably over loading it from the database for every request.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Login checks and declarative processing
So, one could put a "loginOnly()" function at the start of any checked section/page. By not putting it in XML I also have smaller granularity options on where it is used. For example, maybe certain buttons don't show or have a different description if not logged in.
Which is what my code does in addition to the generic declarative checks. So your method is not as functional. If I want to have the entire application protected, that's one change in the config file. Or perhaps every page that has the word "secure" in the URI. Less work on average.

But I don't care how you do it, I'm just telling you what needs to be done. Some pages are protected, others aren't.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New re: Login checks and declarative processing
If I want to have the entire application protected, that's one change in the config file.


In most web apps I have a standard "include" file. If I want the check applied to all pages, I simply put it there.

Or perhaps every page that has the word "secure" in the URI.

\n  // standard header file\n  ....\n  if (contains(selfURI, 'secure')) {\n    performCheckFoo(...)\n  }\n

________________
oop.ismad.com
New re: Login checks and declarative processing
And if you decide to move that include file? Or rename it? Don't say it doesn't happen, because it does. What if a developer forgets to include the check file in his page? What if two different clients share the same code, but run it locally and want to configure it differently?

Your solutions always "work" for suitably limited scopes. I'll take the solution that's more globally applicable, thank you.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New re re: Login checks and declarative processing
And if you decide to move that include file? Or rename it? Don't say it doesn't happen, because it does. What if a developer forgets to include the check file in his page?


Then most pages will probably not work because a lot of stuff tends to depend on it for things like database handles.

What if two different clients share the same code, but run it locally and want to configure it differently?


A "split or share" decision is part of any such endevour. Computers can't read minds. If the criteria for triggering a given check changes, we simply change the criteria. Boolean expressions are usually more powerful than subclassing because we don't have to try to cram it into a tree shape and can more easily have orthogonal factors involved. Subclassing tends to puke and squirm when dealing with orthogonal factors.
________________
oop.ismad.com
New Re: Login checks and declarative processing (new thread)
Created as new thread #156712 titled [link|/forums/render/content/show?contentid=156712|Re: Login checks and declarative processing]
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New I18N
All that link to the Internation UI Example showed was your inability to grasp the issues. "Bottom" is right... using a database over text files gives you no benefits, and results in a loss of efficiency.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New You are WRONG!
All that link to the Internation UI Example showed was your inability to grasp the issues.


Name calling? I don't appreciate that in the slight. I take big offense to that. Fuck you! If you have slam-dunk evidence then show it shove it!

"Bottom" is right... using a database over text files gives you no benefits, and results in a loss of efficiency.


If one has the option of using tables to generate "resource files" or whatever you want to call them, then the compiler does NOT CARE where they came from. It is not going to say, "Oh, these resource files were auto-generated from DB tables; therefore, I will run them slower". That is outright silly! That is a PHB-style mental error.

I personally don't want to manage boatloads of messages as programming language files. Databases were created to help people track and manage boatloads of attributes, and that is just what international message info is. You are not going to tell me how to best manage information that I have to work with. Sure, a boss can dictate to me how to organize such info, and can even dictate to me how to organize my desk and pencils and paperclips. But, that does not necessarily make me more productive. Having them in tables allows one to sort by language, sort by message (ID), search for similar messages, print reports that non-programmers understand, etc. The presentation becomes untied to a programming language grouping or file organization. Sure, if it is a small application and there are only a few target languages, then editing within code files directly is fine. The bottom line is that code makes a shitty database.
________________
oop.ismad.com
Expand Edited by tablizer May 24, 2004, 02:15:41 PM EDT
New My my, I touched a raw nerve, apparently.
Where's the name I called you?

From the link:
Top: I am trying to think fairly large-scale here. What if "last" is used to mean both "previous" and "final" in different circumstances in the application?

Bottom: The word "last" can be used in many different circumstances in the application.

Top: A simple content look-up will not work.

Bottom: It will and it does. The word "last" isn't looked up by itself. The phrases "Enter last name:" and "Your glory shall last" each have their own separate translation. It doesn't matter that the same word appears in each English version.
It's pretty plain to me that you don't understand the issues here. Hence your confusion in the conversation you linked. How is this name calling?

I personally don't want to manage boatloads of messages as programming language files.
Neither do I. That's why I use resource files.

You are not going to tell me how to best manage information that I have to work with.
And you have done how many internationalized sites? I thought so. Yet you still feel qualified to tell everyone that your approach is so much better, even though it just solves problems that don't exist. "Bottom" is right. People don't need the sorts of "reports" you're talking about.

Having them in tables allows one to sort by language,
Er, and this can't be done with resource files for what reason?

sort by message (ID),
Why would anyone want to do this? You don't understand the problem set.

search for similar messages,
grep is your friend.

print reports that non-programmers understand, etc.
What kind of reports? This stuff simply isn't needed, and your over-engineered "solution" is more work for no gain.

code makes a shitty database
And databases make shitty code.

Now change your tone or this conversation is over. I've been perfectly civil to you and I don't appreciate your response. You're acting like a sore loser.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Grep is no substitute for clean, normalized data
It's pretty plain to me that you don't understand the issues here.


The context of that has appearently been deleted. Some were proposing translations using phrase look-ups. Even the links given did not use direct phrase lookups.

How is this name calling?


You accused me of "inabability to grasp the issues" without giving specifics. Even if true, the diplomatic way to say it is, "I beleive you are incorrect with regard to point X" rather than some sweeping generalization. Your people skills are even worse than mine, and that is saying something.

I've been perfectly civil


Bull. See above. Even if you think somebody is a total retard, it is improper to inform them of such judgement. One should point out specific things to complain about, not sweeping or vague generalizations.

If you know of a specific use-case that busts my proposed solution, you are by all means welcomed to produce it.

grep is your friend.


That is a hacky approach. Tables are safer.

Neither do I. That's why I use resource files.


Hardly better than source code files.

Why would anyone want to do this? You don't understand the problem set.


That is nature of the biz world: you cannot predict ahead of time how somebody is going to want to see/query something.

And databases make shitty code.


Translation lookup tables are not "code". Even the VB resource file example calls them "tables".
________________
oop.ismad.com
New Re: Grep is no substitute for clean, normalized data
That is a hacky approach. Tables are safer.
That is a general statement. Provide specifics.

Hardly better than source code files.
In what way? They're a specific solution for a limited problem.

some.string=The specific string for a message.

How is the above "hardly better than source code"?

I'll go you one better, in fact: how do you maintain database information over revisions? Keeping this in the database isn't sufficient when you have several database environments (Dev, Test, QA, Prod for example). Text resource files are amenable to revision control via common source code control tools.

Translation lookup tables are not "code".
And neither are resource files.

That is nature of the biz world: you cannot predict ahead of time how somebody is going to want to see/query something.
Especially if you've never done an internationalized application, which I'm guessing (by your non-response) that you haven't. Those who have understand that this simply isn't a requirement. You're inventing problems in order to provide your "solution". And since your solution adds extra complexity in the form of database access (or code generation) for no material gain, it is inferior.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Depends on the scale
{That is a hacky approach. Tables are safer.} That is a general statement. Provide specifics.


You generally don't have to parse to isolate the "atoms". Unless you always provide a perfect parsing specification, there is a chance of getting it wrong. The "walls" are predefined for us so that we don't have to find them over and over.

I'll go you one better, in fact: how do you maintain database information over revisions? Keeping this in the database isn't sufficient when you have several database environments (Dev, Test, QA, Prod for example). Text resource files are amenable to revision control via common source code control tools.


I will agree that the existing crop of revision control tools are designed for files and not databases (although I have not done a survey yet). However, tables make it easier to roll-your-own. Plus, one can have more control over individual messages. See below.

I am just too damned far ahead of my time :-)

Especially if you've never done an internationalized application, which I'm guessing (by your non-response) that you haven't. Those who have understand that this simply isn't a requirement. You're inventing problems in order to provide your "solution". And since your solution adds extra complexity in the form of database access (or code generation) for no material gain, it is inferior.


No, I have not done formal internationalization. But, how large was the project(s) you did? A tablized solution probably would not be practical unless you have say 20+ languages and 1000+ messages (per lang). Files are fine for smaller stuff. I never disputed that here.

I am pretty sure there is a size-point in which you agree that files won't cut it anymore. For example, suppose most of the translators work offshore (which is expected for language translation). One may want a web-site where they log into and review and change messages. Doing that at a file granularity is a bit messy. Through such a portal we can fairly easily track which messages were changed by who and when. That can be done with files, but it takes a lot of Diff commands.

You also make it sound as if tables are hard to use and bulky for internal stuff. Somebody used to XBase stuff will generally disagree.
________________
oop.ismad.com
New You've never used CVS either, have you?
New No, only MS sourcesafe
________________
oop.ismad.com
New *shudder*
I used Source"Safe" once. Just once. It ate the repository. What a piece of cack that program is.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Not my pickings
________________
oop.ismad.com
New Re: Depends on the scale
You generally don't have to parse to isolate the "atoms". Unless you always provide a perfect parsing specification, there is a chance of getting it wrong. The "walls" are predefined for us so that we don't have to find them over and over.
foo.bar=Foo the bar\nmoo.gar=Moo the gar
grep "foo.bar" finds all instances of the "foo.bar" message. You're inventing problems where none exist.

I will agree that the existing crop of revision control tools are designed for files and not databases (although I have not done a survey yet). However, tables make it easier to roll-your-own. Plus, one can have more control over individual messages.
I'm not interested in "rolling my own". I'm interested in getting work done. If your approach provides no tangible benefits, and in fact has some disadvantages as I have named, why in the name of seven Hades would I "roll my own" just to get to the same level of functionality I already had?

I am pretty sure there is a size-point in which you agree that files won't cut it anymore.
I don't see why. One file per message set per language. No overhead. If it's farmed out, give them the English version and say, "translate this". Once the bulk job is done, changes will be minor and are best handled through existing revision control tools. And I certainly wouldn't give a bunch of people located off-shore access to a database used by the production system.

The management becomes harder the larger the system becomes, mainly due to the multiple environments I mentioned.

You also make it sound as if tables are hard to use and bulky for internal stuff. Somebody used to XBase stuff will generally disagree.
Something that large isn't using XBase, I can guarantee you. And they are bulkier and harder to use than resource files.

Here's an example:
\n<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">\n\t<property name="basename"><value>Messages</value></property>\n</bean>
That's what I do in the config file to load my resource files. When I want to use a message, I do this:
<fmt:message key="some.key"/>
That inserts it into the JSP file. Whoopdee doo, that's so incredibly hard. I must be high if I think that's better than a bunch of SQL select statements.

And calling into a remote database for thousands of strings isn't practical. And if you cache them, that's more coding and database maintenance overhead just to match the same functionality provided by resource files.

Pre-compiling involves the database in the compilation step, which is also useless overhead and harder to manage.

Have you actually worked on a large-scale system? Say something with a few hundred tables, a million lines of stored procedures, and millions of rows of dynamic data? The kind of thing you're proposing introduces unneeded, unwanted complexity into an already complex system.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New no no no
grep "foo.bar" finds all instances of the "foo.bar" message.


Yes, but if you have "x = 'my foo bar is here'", it may also pick up that message.

and in fact has some disadvantages as I have named


Very minor.

And the message tables can be used with other languages and systems.

Once the bulk job is done, changes will be minor and are best handled through existing revision control tools.


In my experience, vast change requests may come out of left field so that there is a lot of rework to be done.

And I certainly wouldn't give a bunch of people located off-shore access to a database used by the production system.


You don't give them database access, only access to a web application. And, it does not have to be a production system. Besides, why is file access safer than database access? A file system *is* a database, just not a relational one.

Something that large isn't using XBase, I can guarantee you. And they are bulkier and harder to use than resource files.


I am not necessarily talking about the production application language. One can build tools in a different language than final applications.

I must be high if I think that's better than a bunch of SQL select statements. And calling into a remote database for thousands of strings isn't practical.


You got it all wrong. Each message does not necessarily issue a Select statement.

Have you actually worked on a large-scale system? Say something with a few hundred tables, a million lines of stored procedures, and millions of rows of dynamic data? The kind of thing you're proposing introduces unneeded, unwanted complexity into an already complex system.


So we should chuck databases and go back to flat files to manage everything? How 1960's of you. The bigger the project, the more a database HELPS! Keeping tons of attributes in a bunch of hard-to-query and hard-to-find flat files is really annoyining.

How about this. We start out with a file-based approach. If message management becomes a headache, then we DB-tize the config file generation. Deal?
________________
oop.ismad.com
New Re: no no no
Yes, but if you have "x = 'my foo bar is here'", it may also pick up that message.
grep "foo.bar="

And the message tables can be used with other languages and systems.
And a text resource file can't? You're stretching.

In my experience, vast change requests may come out of left field so that there is a lot of rework to be done.
Ah, your vast experience doing internationalized systems. I see.

You don't give them database access, only access to a web application. And, it does not have to be a production system.
Ah, so now you're maintaining TWO databases for the sake of this labor-saving scheme of yours. Got it.

Besides, why is file access safer than database access? A file system *is* a database, just not a relational one.
Because the changes are being checked in and managed by me, not the guy on the other end of the wire whose only talent is converting English into Swahili.

You got it all wrong.
No, it's called "covering all bases" since you're being so vague about "might" and "doesn't necessarily" and so forth. You oh-so-conveniently didn't quote "And if you cache them, that's more coding and database maintenance overhead just to match the same functionality provided by resource files." So just exactly how does this system of yours work? Or haven't you thought it through properly? Does it issue a single select? "Not necessarily." Does it cache them on the first hit? Who knows. Does it cache them for each page? Can't tell you.

So we should chuck databases and go back to flat files to manage everything? How 1960's of you. The bigger the project, the more a database HELPS! Keeping tons of attributes in a bunch of hard-to-query and hard-to-find flat files is really annoyining.
No, but they're damn nifty for internationalized messages. How very binary of you.

"hard to query" Er, no. Got grep or find? Got an editor? Everyone does. Better that than "oh, to work on the messages you need to set up ODBC like so, and install Access, and search for them here like this. Oh, wait, you wanted to see the messages in QA, not DEV? Well, you need a different ODBC source then..." Seems to me the database version is a lot more of a pain in the ass for someone who just wants to edit a bit of text.

"hard to find" Care to back this up? They're right there in the same place as the JSP files that use them, as opposed to way off in database land, completely unrelated to the code that references the messages. Seems to me the database version is a lot more of a pain in the ass for someone who just wants to edit a bit of text.

How about this. We start out with a file-based approach. If message management becomes a headache, then we DB-tize the config file generation. Deal?
What's this "we", Kemosabe? Message management hasn't become a headache yet. You've not demonstrated that it will be, and given that you have no experience in the matter... and since I'm working on a system right now that has nearly 2000 similar text resource files, I'll keep my own counsel on that one, capicé?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Doing my part to promote right shifting
Perhaps you've already explained in this thread and I missed it, but.....

Was wondering why your putting internationalization in the board. I've been putting off internationalization in my current app, mostly due to Sarbanes-Oxley being U.S. centric. Sooner or later I'm going to have to tackle it, as some of our customers have to get sign offs from far away lands (europe, china, etc). So I fully understand that it is a requirement for a lot (if not most) business apps these days.

Just wondering what you are trying to leverage on zIWETHEY?

(For example, does it make Nadsat or Guido easier to implement?)
New "Oh goody, a new framework for xmas!"
Was wondering why your putting internationalization in the board.....Just wondering what you are trying to leverage on zIWETHEY?


Isn't it obvious?: To make competing with his features harder for me. His whole life revolves around kicking p/r's ass :-)
________________
oop.ismad.com
New Re: "Oh goody, a new framework for xmas!"
His whole life revolves around kicking p/r's ass
Not really. I do that before breakfast and then go on to get real work done the rest of the day... ;-)
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Internationalization (new thread)
Created as new thread #156729 titled [link|/forums/render/content/show?contentid=156729|Internationalization]
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New admin
grep "foo.bar="


That's the point: you have to keep sticking conditions in there as you encounter problems. And, what if there are spaces around the equal sign? A bigger and bigger regex for each new variation encountered.

And a text resource file can't? You're stretching.


I know that most languages can reference the common RDBMS. I don't have to keep reinventing the same parsing in different languages.

Ah, your vast experience doing internationalized systems. I see.


Just because you've done one or two does not mean you have encountered all possible request permutations.

Ah, so now you're maintaining TWO databases for the sake of this labor-saving scheme of yours. Got it.


Coupling to your favorite everchanging frameworks is not always labor-free either.

Because the changes are being checked in and managed by me, not the guy on the other end of the wire whose only talent is converting English into Swahili.


Well, then it is not a "large project".

So just exactly how does this system of yours work? Or haven't you thought it through properly? Does it issue a single select? "Not necessarily." Does it cache them on the first hit? Who knows. Does it cache them for each page? Can't tell you.


The optimum solution depends on a lot of things, for example whether we are using a dynamic or static language, whether performance is more important than developer labor, whether it is web-based, etc.

"hard to find" Care to back this up? They're right there in the same place as the JSP files that use them, as opposed to way off in database land, completely unrelated to the code that references the messages.


So lets put everything in code and forget databases. New employee? Don't put them into a database, but rather code up an XML file. Replace Oracle with XML. Yeah, that's progress.

________________
oop.ismad.com
New Resource files (new thread)
Created as new thread #156741 titled [link|/forums/render/content/show?contentid=156741|Resource files]
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Re: response 4
That is called a "stored procedure". But, if it is DB-neutral, what are you sending to the DB itself? Not SQL?
You still have the call to the stored procedure to parse. What many caching query libraries do is create a transient stored procedure transparently, then use it with supplied parameters whenever that query is called again. This portion depends on the facilities of the underlying database, which, I would point out, I don't have to worry about because I'm using a mapping layer. I get as much caching as can be supported without any changes, no matter what back end is doing the work.
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Lock-in is lock-in
This framework you use does not sound like a trivial peice of software. Again, you seem to be trading DB vendor lock-in for OR-mapping framework vendor lock-in. The same evil, but with yet more layers.
________________
oop.ismad.com
New Query caching is a feature of JDBC
The point being, which you are trying to avoid, is that this is something you get that straight SQL does not provide. Don't try to change the subject to "lock-in" now. So do you agree or not, query caching is a good thing to have?
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
New Yes
So do you agree or not, query caching is a good thing to have?

All else being equal, sure.
________________
oop.ismad.com
New Re: response 5
I note that you omitted: Dual layer caching, Lazy instantiation, Database/data source independence
I suspect the first 2 are something specific to an OO-centric design.
Dual layer caching refers to in-memory caching of database results. Lazy instantiation refers to only retrieving results as they are actually required.

The last one was already discussed. I doubt one can nicely put nearly all SQL behind an API.
Your doubts arise from ignorance.

And if possible, I doubt only OO can do it well.
Weaseling again. Your statement, once more: "You spend all your code translating back and forth between two discordant paradigms."

Where's the bloat?

Still waiting...
Regards,

-scott anderson

"Welcome to Rivendell, Mr. Anderson..."
Expand Edited by admin May 22, 2004, 07:49:36 PM EDT
     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)

LYNX-tested and approved!
367 ms