From: "Bill Gladen" <nobody170 at yahoo.com> To: <tclug-devel at mn-linux.org> Sent: Monday, July 16, 2001 7:14 AM Subject: Re: [TCLUG-DEVEL] Java Interfaces and multi-extends? > 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. Both opinions may be correct, but mine is the most correct. ;) > 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. My point is that by considering the data to be dynamically typed, you can write code that is more general. For example, you can write one toString() function instead of one for every data holder class. To illustrate this further, see the following code: // Multiple statically typed data holder classes design class DataHolder1 { private String a; private int b; public String getA() { return a; } public int getB() { return b; } public String toString() { return "{a=" + a + ",b=" + b + "}"; } } class DataHolder2 { private String a; private double b; private java.util.Date c; public String getA() { return a; } public int getB() { return b; } public java.util.Date getC() { return c; } public String toString() { return "{a=" + a + ",b=" + b + ",c=" + c + "}"; } } class DataHolder3 { // ... } class DataHolder4 { // ... } // ... on and on and on... until DataHolderBizillion // Single dynamically typed holder class design class Tuple { private java.util.Hashtable map; public Object get( String key) { return map.get( key); } public void put( String key, Object value) { map.put( key,value); } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("{"); java.util.Enumeration enum = map.keys(); while( enum.hasMoreElements()) { String key = (String)enum.nextElement(); Object value = map.get( key); buffer.append( key); buffer.append("="); buffer.append( value); buffer.append(","); } buffer.append("}"); return buffer.toString(); } As a excercise for the reader, make changes to each implementation to make toString() use '[' intead of '{'. When you're done, tell me which design you spent the most time making the changes to. This is just a simple example. A more complex example is a function that inserts the data into a given table in a given database. > 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. Allow me to change my mind. I don't think I would put validations in a tuple class. Tuple is simply a data holder, not a data processor. I would put the data validation in the data processing classes. > 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. What is the KISS principle - Keep It Super Simple? I don't follow you here. Why do you think patterns produce overly complex solutions? The idea is that they are the best of breed of solutions, no? If there is a better way to do something then perhaps that way should be a pattern! What is your opinion of EJB? My opinion is that the entity bean model is misguided for the same reasons we have been discussing here. I think it breeds bizillions of boring data holder classes along with bizillions of lines of redundant code. I'm not strong with this opinion yet, because I have not actually done any EJB development. > 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(); > } I'm confused. This IS the producer consumer pattern. Well ok, its part of it. You haven't shown the rest of the code, e.g. the implemenation of jobQueue.hasNext() and you haven't used a good performing sychronization mechanism. > 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. Cleaner yes and also a better performer and better neighbor. The sleep() design will use up CPU when the application is idle. A design should be simple, but not TOO simple. I think I may be missing your logic with respest to the KISS principle and design patterns. Mike