tag:blogger.com,1999:blog-22587889.post5686679738755071013..comments2024-02-11T13:21:47.930+05:30Comments on Ruminations of a Programmer: Why OOP Alone in Java is Not EnoughAnonymoushttp://www.blogger.com/profile/01613713587074301135noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-22587889.post-88647895343001113922008-08-19T21:53:00.000+05:302008-08-19T21:53:00.000+05:30package bird;import java.util.ArrayList;import jav...package bird;<BR/>import java.util.ArrayList;<BR/>import java.util.Iterator;<BR/>public abstract class Bird {<BR/><BR/>public String name;<BR/>public void strikewinds() {<BR/>System.out.println("Yes, relax, I'm bird and striking winds");<BR/>}<BR/><BR/>} <BR/>public abstract class Flyingbird extends Bird {<BR/>public abstract void fly(); <BR/>}<BR/>public abstract class Swimmingbird extends Bird {<BR/>public abstract void swim(); <BR/>} <BR/>public abstract class Flyswimbird extends Bird {<BR/><BR/>public abstract void flyswim();<BR/>}<BR/><BR/>public class Eagle extends Flyingbird {<BR/>public void fly(){<BR/>System.out.println("Yes, relax, I'm bird and fly"); <BR/>} <BR/><BR/>}<BR/>public class Dove extends Flyingbird {<BR/>public void fly(){<BR/>System.out.println("Yes, relax, I'm bird and fly"); <BR/>} <BR/><BR/>} <BR/><BR/>public class Penguin extends Swimmingbird {<BR/>public void swim(){<BR/>System.out.println("Yes, relax, I'm bird and swim"); <BR/>} <BR/>}<BR/>public class Swan extends Flyswimbird {<BR/>public void flyswim(){<BR/>System.out.println("Yes, relax, I'm bird and fly and swim"); <BR/>} <BR/><BR/>}<BR/>public class Ostrich extends Bird {<BR/><BR/>}<BR/>public class Chiken extends Bird {<BR/><BR/>}<BR/>public class Duck extends Flyswimbird {<BR/>public void flyswim(){<BR/>System.out.println("Yes, relax, I'm bird and fly and swim"); <BR/>} <BR/>}<BR/><BR/>public class Arrays extends Flyingbird {<BR/>public static void main(String[] args) {<BR/>Flyingbird[] flyer = { new Eagle(), new Dove()};<BR/>for (int i = 0; i < flyer.length; i++)<BR/>flyer[i].fly();<BR/><BR/>}<BR/>}<BR/>class FlyingFlock {<BR/>private List Flyingbird birds = new ArrayList Flyingbird();<BR/><BR/>public void addBird(Flyingbird bird) {<BR/>birds.add(bird);<BR/>}<BR/><BR/>public void fly() {<BR/>}<BR/>} <BR/>class SwimmingFlock {<BR/>private List Swimmingbird birds = new ArrayList Swimmingbird();<BR/><BR/>public void addBird(Swimmingbird bird) {<BR/>birds.add(bird);<BR/>}<BR/><BR/>public void swim() {<BR/>}<BR/>} <BR/>class FlyswimFlock {<BR/>private List Flyswimbird birds = new ArrayList Flyswimbird();<BR/><BR/>public void addBird(Flyswimbird bird) {<BR/>birds.add(bird);<BR/>}<BR/><BR/>public void flyswim() {<BR/>}<BR/>} <BR/>class AnyFlock {<BR/>private List Bird birds = new ArrayList Bird();<BR/><BR/>public void addBird(Bird bird) {<BR/>birds.add(bird);<BR/>}<BR/><BR/>public void strikewinds() {<BR/>}<BR/>} <BR/><BR/>public class Test {<BR/>public static void main(String[] args) {<BR/>ArrayList Bird flock = new ArrayList Bird(); <BR/>flock.add(new Eagle());<BR/>flock.add(new Penguin());<BR/>flock.add(new Swan());<BR/>Iterator i = flock.iterator();<BR/>while (i.hasNext()) {<BR/>try {<BR/>((Flyingbird)i.next()).fly(); <BR/>((Swimmingbird)i.next()).swim();<BR/>((Flyswimbird)i.next()).flyswim(); <BR/><BR/>}<BR/>catch (InterruptedException e) {<BR/><BR/>}<BR/>}<BR/>}<BR/>}Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-14990242902877455782008-08-19T21:46:00.000+05:302008-08-19T21:46:00.000+05:30hello, I have to do 1 programm, can you check my p...hello, <BR/>I have to do 1 programm, can you check my programm<BR/><BR/>Create the abstract class Bird, there is no abstact method flapwings and String name.<BR/>Create derived abstract classes Flyingbird, Swimmingbird, Flyingandswimmingbird with corresponding abstact methods swim and/or fly.<BR/>Create no abstact subclasses from class Bird, for example Dove, Eagle, Ostrich, Swan.<BR/>Create 4 classes, which model next bird flocks:<BR/>1. flock of any birds<BR/>2. flock of flying birds<BR/>3. flock of swimming birds<BR/>4. flock of flying and swimming birds<BR/>Flocks create with the objects type Collection. There is espessial method for adding birds to the flock, it being known that adding alien objects must be impossible.<BR/>Classes structure must be so, that swan can adding to every flock. In every flock must be method, which make all birds, included in this flock, do, that all birds of flock ought do: flapwings and/or fly and/or swim.<BR/>About all actions print corresponding messages.<BR/>In test programm creat 4 different flocks, include in these flocks a few birds. <BR/>Class hierarchy must be such, that it would possible to make objects array, who can, for example to swim.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-26952022644619501852007-11-26T08:57:00.000+05:302007-11-26T08:57:00.000+05:30C# is the answer to everything, array to collectio...C# is the answer to everything, array to collection is fixed with List.AddRange(new string[] {"","",""});<BR/><BR/>However, I'm sad that by default Collections don't overload += and -= operators, that would be a very natural syntax.<BR/><BR/>Iterating over collections is fixed with easy to use anonymous delegates.<BR/><BR/>List.ForEach(delegate(object){ /*yay my action*/ });<BR/><BR/>And most user code runs faster than the equivalent java implimentationAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-11426362728125456182007-06-19T18:26:00.000+05:302007-06-19T18:26:00.000+05:30@Anonymous:Good thoughts, well taken .. though at ...<I>@Anonymous:</I><BR/>Good thoughts, well taken .. though at the end of the day, don't you think Java is a bit more verbose than what is needed to strike the right balance between conciseness and elegance ?Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-15438727080883852472007-06-05T13:17:00.000+05:302007-06-05T13:17:00.000+05:30I am new here, so just a few comments on collectio...I am new here, so just a few comments on collection initialization:<BR/><BR/>You called the Arrays.asList() approach unintuitive - which it is, because you must first learn the extra helper method. Likewise the Ruby-way is 'unintuitive' since it employs some extra syntax (invented just for this purpose!) that you must learn before use.<BR/><BR/>The 'anonymous inner class trick' uses normal initialization syntax in a smart way to reduce typing work and text clutter. This is elegant and orthogonal (if it were easier to come up with this solution I would even call it intuitive, but... read on. ;-)<BR/><BR/>You criticize the overhead of the extra class but: where do we use such hard coded ad-hoc initialization? Mostly 'in writing unit tests' - like you said - or similar? Yes! And there the overhead would not matter much.<BR/><BR/>There's another reason, though, to mostly avoid this idiom: An anonymous or local class is always non-static, so the initialized list will keep a reference to the enclosing outer instance (and prevent it from being garbage collected as long as the list lives!) plus you cannot use it in static contexts without providing a dummy instance for the outer object (maybe stored as a static final, just to support that idiom: crazy, but at least then we wouldn't be too surprised that the dummy does not get garbage collected ;)<BR/><BR/>So this was not a good discussion example either. My opinion is that too much advocacy for concise syntax can be as bad as verboseness. And often verboseness can be as helpful as conciseness. Don't go overboard with "what if my language had that feature"-stories; mostly use it as is and be modest in your wishes - lest it gets overcrowded with obscure features that lengthen the learning curve - and the time required to understand your colleague's code of 'different style' that you must maintain since he 'suddenly left' last month (my 2c: the 'suddenly left'-syndrome is often due to a sudden disgust of a person towards their own coding style; and it probably happens with verbose as well as concise orthogonal languages ;-)Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-76823491375652906042006-11-17T01:11:00.000+05:302006-11-17T01:11:00.000+05:30Interesting. I could write this same article chang...Interesting. I could write this same article changing the word "Ruby" to "Groovy" replace one or two symbols (changing the pipe "I" arg delimiter to an arrow "->") and acheive the same results. I could also compile my examples, package them as native Java APIs and sit them next to any existing Java code that needed them.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-47405696921993636522006-11-13T23:44:00.000+05:302006-11-13T23:44:00.000+05:30I find it strange how many people seem to think th...I find it strange how many people seem to think that succintness is synonymous with readability. I'd always find a 3-line for loop and call more readable than a 1-line perl map statement for example. Verbosity can be a problem, but I don't think it's one of the most important considerations in the readability of code.<br /><br />I'm also less than convinced of the benefits of a fluent interface outside the realms of basic data construction. I've been using JMock practically every day for some time now and still find myself having to think carefully about the syntax I need. Perhaps it's just a bad example, but I find it consistently frustrating.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-70912184547756568772006-11-01T08:04:00.000+05:302006-11-01T08:04:00.000+05:30Having used Perl and messed around with Python and...Having used Perl and messed around with Python and Ruby I do agree that Java can be really verbose. This is one of the arguments I have with a colleague who is quick to point out that "IDEA will write it for you". My point is that code tends to be read for much more time than it is written and there is definitely a lot of value in being succint and expressive.Nanhttps://www.blogger.com/profile/05085327443849810726noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-19743120141050115622006-10-30T12:47:00.000+05:302006-10-30T12:47:00.000+05:30[for Anomymous: if getters and setters are evil, h...<i>[for Anomymous: if getters and setters are evil, how am I supposed to express the fact that I need to get the name (a String) out of a Person object?] </i><br /><br />Getters and setters are evil in the sense that in many cases careless exposure of getters and setters cause implementation to escape out of your model. So the focus should be *not* to expose implementation artifacts, but to publish *public* behavior of the abstraction.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-2550668652066095482006-10-30T11:32:00.000+05:302006-10-30T11:32:00.000+05:30[for Anonymous on Collection initialization:]
Tha...<i>[for Anonymous on Collection initialization:]</i><br /><br />Thanks for pointing to one of those *lesser used* features of instance initialization. Yes, this is definitely more terse than the standard idiom for initialization. But, the main point of the blog post is to highlight the natural way of doing things and that Java adds more verbosity to it. I have never told that it is the "biggest failure in Java" - only that it may be less elegant than some of the practices in other programming languages.<br /><br />The instance initialization syntax that u have pointed to *should never* be used in production code, since it has the overhead of an extra anonymous inner class. Hence it is not surprising that we do not come across such syntax frequently. Yes, we can use this in writing unit tests - and that is probably an area where hard coded initializations make more sense. But try using the same syntax to define more complex nested structures in Java .. possibly a Map of Lists .. I simply do not think this scales.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-30613676180913074662006-10-29T10:54:00.000+05:302006-10-29T10:54:00.000+05:30Map m = new HashMap() {{
put("k1", "val1");
pu...Map m = new HashMap() {{<br /> put("k1", "val1");<br /> put("k2", "val2");<br /> put("k3","val3");<br />}};<br /><br />You're welcome to find this more verbose than Ruby, but a lot of people will disagree.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-34702003524433036032006-10-29T10:53:00.000+05:302006-10-29T10:53:00.000+05:30Anonymous: if getters and setters are evil, how am...Anonymous: if getters and setters are evil, how am I supposed to express the fact that I need to get the name (a String) out of a Person object?Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-36228081269359245562006-10-29T10:46:00.000+05:302006-10-29T10:46:00.000+05:30On top of asList(), you can also initialize collec...On top of asList(), you can also initialize collections as easily in Java as you can in Ruby:<br /><br />List a = new ArrayList() {{<br /> add("a");<br /> add("b");<br />}};<br /><br />If you're going to call something the "biggest failure of Java", at least make sure you know what you're talking about.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-43860246984257309292006-10-28T07:12:00.000+05:302006-10-28T07:12:00.000+05:30The productivity issue with Java is overhyped, IMH...The productivity issue with Java is overhyped, IMHO. Java is quite expressive for a wide range of problems, but is also, when well written, expressive in the human readable sense, in which verbosity can be a good thing.<br /><br />One of the problems I've seen in a lot of Java code is the same problem in many other languages, when a programmer is not abstracting the problem domain, but rather trying to abstract the implementation.<br /><br />Of course, to some extent that is unavoidable, and I've been guilty too, but code which expresses too much about patterns, factories, etc should be reworked to mostly hide those implementation artifacts, and rather express a view of the domain/problem space.<br /><br />This is doable with or without OO,<br />but it is work.<br /><br /><br />One more thing, re: the comment about too much code for an object, because of all the getters & setters (and yes, this is a rant):<br />Getters and setters are evil. They miss the point about encapsulation and objects. Expose behavior, not data! If you are exposing mostly data, then rethink things. Sometimes that really is the nature of what you're doing, but mostly I've seen people blindly exposing data with getters and setters, and the unfortunate histroy of the old java bean spec doesn't help.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-22587889.post-23248217880786276102006-10-24T17:26:00.000+05:302006-10-24T17:26:00.000+05:30[for ricky] :
some observations on your observati...<i>[for ricky] :</i><br /><br />some observations on your observations ..<br /><br /><i>[on getters and setters] :</i><br /><br />Making all variables public is, of course, no solution. It exposes implementation details. In fact exposign implementation through getters is also never recommended. My main point was terseness and brevity, which has never been Java's forte. I think Ruby and Scala do this better.<br /><br /><i>[Jakarta Commons Collections] :</i><br /><br />Yes, it predates generics, but unfortunately there is a huge codebase out there that use these unsafe api s. We have been using them in one of the projects which started before generics was there in Java. And lots of users still use them as time-tested api s.<br /><br /><i>[find(songs,compose(equals(title),getName()));] :</i><br /><br />As I mentioned in my blog, Java is a turing complete language. Hence you can do everything which u can in other Turing complete languages. The question is elegance, intuitiveness and naturalness of syntax. Initializing a List with Arrays.asList() is never intuitive. Similarly the find/compose stuff that u have written needs lots of other plumbing to present to the user as a nice api. No wonder we have lots of frameworks in Java that try to hide the verbosity of the language. I have the same issue with arrays in Java as well. One other thing which I missed in my post is the complete disharmony in treating the primitives. The primitives in Java are a diff creature altogether and u need to write lots of specialised treatment codes to deal with primitives. But that's another story and deserves a separate post of its own.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-76847635481112156622006-10-24T16:35:00.000+05:302006-10-24T16:35:00.000+05:30"Building UIs in Swing is this huge, festering gob..."Building UIs in Swing is this huge, festering gob of object instantiations and method calls. It's OOP at its absolute worst."<br /><br />Agreed, to some extent. When you've been working with Swing for a while you get to know which objects and method calls you really need, and how to organise things, and then you find that it's not really that bad. One approach is to wrap up the stuff that you find ugly, so that you keep the ugliness localised. It's a tradeoff.<br /><br />"in Java, we often find people generating reams of boilerplates (aka getters and setters) that look like pureplay copy-paste stuff."<br /><br />I don't know why people seem to hide variables, then just make them visible again through getters/setters. You may as well just make public variables. Sure, if this is in public APIs this makes it harder to refactor later, so only do it for internal code, or aim to annoy your clients.<br /><br />"Object orientation ... never prevents the language from providing elegant constructs to handle boilerplates."<br /><br />I don't think object orientation itself even requires the boilerplates, nevermind constructs to hide them. Encapsulation isn't about making fields appear as methods, it's more about making the class that contains the method not even appear to the API user (e.g., a private implementation class or even an anonymous class). Encapsulation can exist without access restrictions, even access restrictions enforced by code conventions only.<br /><br />About Jakarta Commons Collections - your complaint is about an API that predates generics - nowadays you would be able to use static imports and you wouldn't sacrifice type safety.<br /><br />"in Ruby we can do this with much more elegance and lesser code<br /><br />@songs.find {|song| title == song.name }"<br /><br />Fine, but this can be approached in Java:<br /><br />find(songs,compose(equals(title),getName()));<br /><br />This is the kind of Java code I like to write. Of course, it takes more setting up than Ruby's does, but that's ok.<br /><br />"[arrays] cannot be subclassed and are not extensible" - True, but you can use them rather than extend them - anything you can do by subclassing you can emulate with composition - why would you want to subclass an array? To put extra methods on it, probably, in which case you may as well put those extras in a utility class, or in an object that holds an array. All you lose is direct assignment compatibility - an extra method call isn't too painful.<br /><br />If Java had operator overloading, you could then overload the cast operator and make the assignment compatible.<br /><br />About the Java code samples - try to write realistic code samples that demonstrate some working knowledge of Java (e.g., a commenter mentioned asList to shorten your collection initialisation code), and try not to use pre-1.5 type-unsafe libraries as examples, it only serves to lengthen your posts and make your points seem weaker, though some are good points.<br /><br />Personally, I like the static typing, but feel that Java would benefit more from type inference. I don't know Scala, maybe it's similar, but use Haskell for a little while - at least follow Yet Another Haskell Tutorial.<br /><br />You get a real functional language, with brief syntax, but compile errors that may as well be garbage (so far - I'm in the early stages of learning it).<br /><br />I'm using some of the things I've learned from Haskell (and from bits of other languages such as Ruby) in Java, and it's fun.Ricky Clarksonhttps://www.blogger.com/profile/13845104548520132930noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-40096330173274435262006-10-24T15:26:00.000+05:302006-10-24T15:26:00.000+05:30[for jesse] :
Regarding Collection initialization ...<i>[for jesse] :</i><br />Regarding Collection initialization example it is true that Java provides an alternative syntax based on Arrays.asList(). But I don't like the syntax loaded with statics and ultimately backed with an array in the implementation - it is not intuitive. I need to learn Arrays class to get an initialization syntax for a List. My point is that the elegance is not there in literal based initialization of Collections in Java. Take this example in Ruby :<br /><br />sample_hashmap = {<br /> "k1" : "val1",<br /> "k2" : "val2",<br /> "k3" : "val3",<br /> ...<br />}<br /><br />Neat huh ! Java's syntax is much more verbose which becomes much worse in case of nested data structures.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-35614786784558790302006-10-24T12:40:00.000+05:302006-10-24T12:40:00.000+05:30[for dietrich kappe] :
I agree that operator ove...<i>[for dietrich kappe] : </i><br /><br />I agree that operator overloading may lead to unsupportable codebase, I personally have faced this music while maintaining C++ codebase for my client. I just wanted to mention that it offers some level of extension of operators - and given proper disciplined usage can lead to orthogonal syntaxes in a language. I remember in one of the Java One sessions long back, Gilad Bracha had talked about implementing operator overloading in Java, but only over his dead body .. :-)Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-56787052701807485412006-10-24T12:35:00.000+05:302006-10-24T12:35:00.000+05:30[for nameless_1] :
In Java refactoring does not he...<i>[for nameless_1] :</i><br />In Java refactoring does not help always to get rid of repetitions. A classic example is the ream of getters and setters - I agree they can be generated by IDEs. But at the end of the day they add up to the size of the jars, more code to maintain and this is definitely not DRY. And certainly brevity has not been a strong point of Java - Ruby and Scala do a much better job of it.Anonymoushttps://www.blogger.com/profile/01613713587074301135noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-20575550013161822902006-10-24T09:01:00.000+05:302006-10-24T09:01:00.000+05:30Whomever you got your Java Tree class from did a f...Whomever you got your Java Tree class from did a fairly bad job at designing the API. Java can certainly do tight APIs:<br />Tree tree = tree("a",<br /> tree("b", tree("d"), tree("e")),<br /> tree("c", tree("f"), tree("g"), tree("h"))<br /> );<br /><br />... you just need to provide the helper method:<br />public Tree tree(String name, Tree... children) {<br /> Tree tree = new Tree(name);<br /> for(Tree child : children) tree.addChild(child);<br /> return tree;<br />}<br /><br />Similarly for your Collections example, you can use the concise Arrays.asList() method:<br />List animals = Arrays.asList("elephant", "tiger", "cat", "dog");swankjessehttps://www.blogger.com/profile/04905794974441087900noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-6912631719194941972006-10-23T23:13:00.000+05:302006-10-23T23:13:00.000+05:30Nice article. There's a lot of things I love about...Nice article. There's a lot of things I love about Java, but expressivity is not one of them. <br /><br />And it's not about the static typing. Lack of static typing is the one thing that annoys me in dynamic languages. <br /><br />So what's nice about (for me) the dynamic languages is not the dynamism of types, but of code - the meta-programming, functional programming stuff. That's the stuff we need in java. <br /><br />So no, it's not the static typing that's a problem. That's a good thing. I want to write less boilerplate iterating code, pass functions around with writing some interface so that I can create an anonymous inner class that implements it, have my getters and setters written automagically, etc. etc. etc.flagellumhttps://www.blogger.com/profile/00751262071430018877noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-73822566199877046872006-10-23T22:51:00.000+05:302006-10-23T22:51:00.000+05:30i disagree with some of your points. one example, ...i disagree with some of your points. one example, when was the last time you needed to hard code something like the tree example apart from unit tests? My take is this, "most of the time" Java can modularize many things nicely, if you think you are repeating yourself, re-factor, write a new method or a helper. it is many times better then introducing new language key words or meta-programming. and it is much more tool friendly (IDE's).afsinahttps://www.blogger.com/profile/07225476124525448066noreply@blogger.comtag:blogger.com,1999:blog-22587889.post-78363627864499071172006-10-23T20:14:00.000+05:302006-10-23T20:14:00.000+05:30Interesting article. I hasten to point out that la...Interesting article. I hasten to point out that language extensibility also has its dark side. C++ operator overload, which you mention, was infamous for making code unsupportable. I certainly saw plenty of code as a contract programmer in the 90's where you had to study the operator overloading for a week just to be able to read the code.<br /><br />My favorite example of this nonsense was the example of using operator overloading to make C++ look like Pascal. Great fun.Anonymousnoreply@blogger.com