A real discussion!  woo hoo!

Mike, you make some very valid points.

I think I should preface this with a disclaimer to everyone else
reading this.  All points presented by both sides of the discussion are
correct.  Most of the work of designing a system is in choosing one of
many ways to do something, and making tradeoffs between various goals
of programming.

So here we go.

I don't like empty class extensions.  It doesn't give you anything but
confusion, unless you provide the base name within the sub-class name. 
Just name your variables.

HashMap customerDataHashmap = ...

rather than

CustomerData extends HashMap{}
...
CustomerData myCustomerData = ...

Otherwise, when someone else is trying to read you code later, they
come across a CustomerData type and have to keep track of the fact
(once they figure it out) that it's just a HashMap.

On to the dynamic typing issue.

Yes, the interface to the RDBMS is dynamically typed, but the data in
it generally is not.  This is a case of dynamic typing being
*unavoidable*.  To implement an interface to a system that stores
arbitrary data, you need your interface to handle arbitrary data types.
 Therefore, they (correctly) made the tradeoff to dynamic typing.  If
you do not *need* to handle arbitrary data, you shouldn't.  This is the
same for the container classes; they need to handle arbitrary data, so
they are dynamically typed.

Data validation.

Yes, you could make a Tuple class that validated it's data, but it
would have to break the principle of abstraction to do so.  You would
have to check what was going in (the key probably) to see if you wanted
to validate the field or not.  This breaks abstraction because the key
is no longer a generic and arbitrary key object, but something to be
checked on input, and you would have to document in the interface every
'special case' key, and what it's requirements are.  If you have more
than one validated field, this will get really ugly very quickly.

I agree that you don't want to put in data constraints that are not
necessary.  If all you are doing is shuttling data from a RDBMS to a
screen and back, you can probably get away with storing a bunch of
strings and displaying generic objects.  

Next month, however, when marketing decides they want to integrate with
the mailing list and print address labels for some reason, you have
data integrity issues.  

Then, next year when a law gets passed that you have to check all
mailings against a centralized government DB server, you could run into
real problems.

I'm not saying that you should enforce all of the data integrity you
can possibly think of (that way lies madness), but you should have the
ability to put it in later with minimal impact.

Design Patterns.

I suppose I should say that they are over used in *some* places.

Heh; this is probably my most unpopular opinion.  With the exception,
perhapse of my opinion on EJBs.  Design Patterns (ala gang-of-four
book) are all the rage right now.  They are useful solutions to know,
and solve some sticky problems if you happen to have those problems.

Every single one of them, however breaks the KISS principle.  If you
read the book, it actually states this right in the beginning, and
warns against using them if you don't need them.

Notice that I didn't say don't use them, just be careful.  If you
overuse them you end up with a system that is too complex to use and
maintain.

You can use a producer-consumer pattern, but you could also use
something simple like:

// note that I'm leaving out the synchronization and error handling,
// they're almost, but not quite, trivial
...
for( i = 0; i < NUMBER_OF_PROCESSING_THREADS; i++ ){
    Thread t = new Thread( new Runnable(){
        public void run(){
            while( true ){
                if( jobQueue.hasNext() ){
                    ((Job)jobQueue.next()).runJob();
                }else{
                    sleep( SLEEP_TIME );
                }
            }
        }
    } );
    t.setDaemon( true );  // VERY IMPORTANT!!
    t.start();
}

A couple things.  Note that you could use Runnable instead of Job, and
then combine processing of different tasks, but this could confuse
people, because they tend to associate Runnable with separate Thread
objects.

Also, you could use a wait()/notify() process rather than check and
sleep.  It would be cleaner, but at that point you probably should
break the inner class out into it's own file, need to pair it with the
queue, and then it's harder to show everything in an e-mail.  :-)  This
is just the KISS principle in action, so I kept it small.

}:->

Bill

 
--- Mike Bresnahan <mike at fruitioninc.com> wrote:
> If you feel there is value in attaching names to your tuples, then
> you can
> always do this:
> 
> class MyTupleName extends Tuple { }
> 
> Or more simply in C, C++, or CORBA IDL:
> 
> typedef Tuple MyTupleName;
> 
> I agree that there is a cost when to use dynamic typing.  I illuded
> to it
> and you elaborated on it.  However, Java makes this trade-off all
> over the
> place and it always will until they add the equivalent of C++
> templates
> (e.g. the container classes).  Additionally, in the type of
> applications I
> have written over the past 7 years, the source and destination of the
> data
> is dynamically typed.  For example, the source and/or destination is
> often a
> RDBMS and the interface to the RDBMS (JDBC) is dynamically typed. 
> Thus
> using static typing does not save you as much as you might want.
> 
> Concerning the data validation logic you mentioned.  I agree, the
> simple
> Tuple class I described does not support this.  However, you could
> conceieve
> of one that did.  Additionally, in my experience, 90% of the data
> elements
> in a given tuple do not have any business logic associated with them.
>  To
> the application they are just plain old data going from one location
> to
> another - perhaps to the display monitor or to a RDBMS.  As time
> passes and
> requirments change, elements get added, change type, or get removed,
> but the
> application really doesn't give a hoot.  A dynamically typed
> architecture
> makes it much easier to maintain this sort of thing.  For example,
> Bob, is
> there business logic in your application  that depends on the zip
> code
> existing and having particular datatype - i.e. a dependency? 
> Assuming there
> is none, then why force your application to have such a dependency?
> Unnecessary dependencies are the bane of software quality.  This is
> same
> agrument used to advocate data abstraction and the same mistake that
> caused
> the Y2K problem.
> 
> Note that I do believe in static typing for elements that do have a
> lot of
> application logic attached to them.
> 
> Why do you think patterns are over used, Bill?  My opinion is that
> they are
> way _under_ used.  In any case, the Producer-Consumer pattern is the
> perfect
> fit for the problem and the one I've seen used in many similar
> servers.  The
> idea is there you have a single request handler thread that does
> nothing but
> recieve requests and put them on a queue and a pool of worker threads
> taking
> requests of the queue and processing them.  You may also want a
> response
> handler thread to deliver the responses asynchronisly.
> 
> Mike
> ----- Original Message -----
> From: "Bill Gladen" <nobody170 at yahoo.com>
> To: "Mike Bresnahan" <mike at fruitioninc.com>;
> <tclug-devel at mn-linux.org>
> Sent: Friday, July 13, 2001 9:29 AM
> Subject: Re: [TCLUG-DEVEL] Java Interfaces and multi-extends?
> 
<snip/>

__________________________________________________
Do You Yahoo!?
Get personalized email addresses from Yahoo! Mail
http://personal.mail.yahoo.com/