Re: The wisdom of the object mentors (Was: Searching OO Associations with RDBMS Persistence Models)
Date: Sat, 3 Jun 2006 10:48:58 +0000 (UTC)
Message-ID: <e5rpeq$r9m$1_at_news.lth.se>
In article <1149286189.785856.107950_at_i40g2000cwc.googlegroups.com>,
<frebe73_at_gmail.com> wrote:
>> >Yes, in some cases it would be an excellent idea, but why don't we
>> >normally separate math libraries?
>>
>> Um, we still do, or certainly did until recently, if using C on most Unix
>> platforms - you had to explicitly link in a math library, 'libm', if you
>> wanted to use anything other than simple addition, multiplication or
>> similar.
>
>Ever tried to replace java.lang.Math?
No; but looking at it, because of certain design decisions in Java, it appears to be difficult. However, with the judicious use of classloaders it might be possible.
>It wouldn't have been very
>difficult for Gosling&Co to make a decoupled Math class. But still
>they didn't.
True.
>It was simply not worth the effort.
*That*, however, is your _interpretation_ (unless you can show a citation where this is actually stated), and ascribes to them a conscious decision, weighing the cost vs utility of writing a decoupled Math facility. Another, simpler and in my opinion more likely explanation, is that the thought didn't cross their mind, so there was no specific decision on the issue, and we are left with the current solution more by accident than by specific design (on this particular issue).
>> >Because the cost is higher than the benefits in most cases.
>> As things like disk and memory space get less expensive and processors get
>> faster, some such costs decrease - in the case of a math library, the
>> extra space is hardly even noticable these days, but there may still be
>> reasons for why you might want to use a _specific_ math library
>> implementation (if you need to have completely repeatable results down to
>> the least significant bit, which is somehthing where some CPUs can
>> actually differ - or if you can sacrifice some specific accuracy in the
>> quest for extra speed, or if you replace code that uses the floating-point
>> processor with code that uses the vector unit, or similar).
>
>Of course I am not talking about CPU time here. I am talking about
>development time. Compare
>
>rs = sql("select companyid, name from company where name like 'E%'");
>
>to
>
>rs = findCompaniesByNameStartingWith("E");
>
>List findCompaniesByNameStartingWith(name)
>{
> rs = sql("select * from employee where name like '" + name + "%'");
> result = new ArrayList();
> while (rs.next()) {
> c = new Comapny(rs.getString("companyid"),
> rs.getString("name"),
> .....);
> result.add(c);
> }
> return result;
>}
>
>Which one do you think take less time to write?
For a once-off situation, the first, of course. You probably meant to write 'select * from company where' in the 'findCompanies...' method, right?
But the initial writing is not the only time it is used. Also consider if you start using the same thing over and over, and in different parts of your code - possibly in different applications, including perhaps ones that are not in fact under your direct control. Now, consider a change to the company table. If you've written the sql everywhere, you need to change the sql everywhere. yes, a search-and-replace will help, but what if there is code that you don't control? you have to make sure the change is made there, as well. If instead you have a function/method/procedure that does the job for you, you just update that _once_, and then you only need to make sure that everybody uses your updated library - and nobody other than you actually needs to change any code at all.
public class SQLUtil {
List runSqlAndInstantiateObjects(String query, Class c) {
return instantiateObjectsFromResultSet(sql(query));
}
public class Company {
public static List companiesWithNameLike(String name) {
List instantiateObjectsFromResultSet(ResultSet rs, Class c) {
List list = new LinkedList();
Constructor con = c.getConstructor(new Class[] {ResultSet.class});
while (rs.next()) {
list.add(con.newInstance(rs));
}
return list;
}
}
public Company(ResultSet rs) {
this.id = rs.getString("id");
this.name = rs.getString("name");
// ...
}
return runSqlAndInstantiateObjects(
"select * from company where name like '" + name + "',
Company.class);
}
}
One thing with this is that the 'instantiateObjectsFromResultSet' and 'runSqllAndinstantiateObjects' are of course eminently reusable for use with other tables and classes, and indeed they shield me from the underlying ResultSets and so on (which are just an implementation detail for talking to the dbms, after all). Also, the SQL code for working companies is kept together with the Java code for the Company class, which is another thing that makes sense (keeping similar things close together).
With support like this in place, the code to write for the operation 'fetch all employees with a salary greater than x' becomes
- for your Employee class, write a constructor thhat takes a ResultSet and constructs the Employee instance from the ResultSet's current row b) write a static method on the Employee class that calls 'runSqlAndInstantiateObjects', passing in the SQL to run and the class of object to instantiate (the Emplpyee class)
>> In my experience, it's usually well worth separating out SQL into a, well,
>> separate part of the application, for ease of maintenance if nothing else
>> (because it keeps all the SQL code, which may be a comparatively small
>> proportion of the total code, close together rather than spread out,
>> which makes it easier to find, if/when it needs maintenance).
>
>My experience is exactly the opposite. In an average enterprise
>application, the SQL code is not a comparatively small proportion of
>the total code.
It appears we work on different types of applications. This is hardly surprising :)
>If you have problem finding SQL code, i suggest that you use the search
>function in your IDE.
But finding sql code is even easier if it is in fact not spread out through many different parts of the project or projects involved, but instead focused in a few well-known locations. Yes, powerful search functions are very useful, but if I can avoid having to use them by designing things appropriately, that, to me, is a win.
>By the way, what kind of maintenance are you
>thinking about? If I said that I want to separate all use of the
>mathematical operators (+, -, *, /) into a separate part of the
>application, because it makes it easier to find when it needs
>maintenance, probably nobody would accept it.
Consider if you are performing a certain calculation, using a certain formula consisting of + - * /, and you use that formula in several different places in your project.
Suddenly, you are told that the formula needs to be adjusted. Now, if you've used the formmula itself in various places in your code, you will have to search through the code and replace every instance thereof with the new one. If, instead, you have written a function (or method, or procedure, or macro) that performs the calculation using that formula, you only need to update that one place and make sure that everyone starts using the updated function/method/..., and the new formula will be used throughout the application.
Best wishes,
>Fredrik Bertilsson
// Christian Brunschen Received on Sat Jun 03 2006 - 12:48:58 CEST