Discussions

News: Dr Heinz Kabutz on the Strategy Pattern with Generics

  1. In his most recent Java Specialists newsletter, Dr Heinz Kabutz collaborates with Generics specialists Angelika Langer, Philip Wadler and Maurice Naftalin to demonstrate how one can combine Generics with the Strategy Pattern.

    The newsletter starts with a single class that can easily benefit from the strategy pattern. It contains a number of code smells that include a large switch statement. It is this code smell that motivates Heinz to refactor the class into several so that he may isolate process from policy.
    A better approach is to avoid using a switch or multi-conditional if-then-else and instead use the Strategy pattern. This allows us to have a separate class for each tax calculation. We can then add new tax categories more easily.
    After refactoring the code we are still left with one remaining task, to add generics to the code so that we can avoid the need to downcast. The remarkable thing about the way in which the class is generified is that the compiler will enforce proper typing of any new policy classes that maybe added to the system later on.

    The newsletter is published at the Java Specialist website. You will be able to see Heinz demonstrate more Java 5isums at TSSJS in Las Vegas and Barcelona.

    Threaded Messages (75)

  2. To understant recursion you must first understand recursion..
    :).
  3. To understant recursion you must first understand recursion..:).

    :) indeed.

    I struggled for ages to decide whether to write class TaxPayer<P extends TaxPayer<P>> or just TaxPayer<P extends TaxPayer>.

    Eventually my generics gurus Angelika, Philip and Maurice convinced me that if you have a generic type, you should always use a parameter for it. In JDK 1.5 and 1.6, there is no compile time difference that I could pick up.

    Basically, TaxPayer<P extends TaxPayer<P>> is more correct than TaxPayer<P extends TaxPayer<?>>, so we use that instead.

    Heinz
  4. recursion[ Go to top ]

    To understant recursion you must first understand recursion..:).

    Not understanding it, I looked it up in the dictionary. The definition for recursion said: "See recursion."

    Peace,

    Cameron Purdy
    Tangosol Coherence: Clustered Shared Memory for Java
  5. recursion[ Go to top ]

    A pretty poor dictionary which doesn't define the base case! How about "see recursion until you understand." :-)
  6. recursion[ Go to top ]

    A pretty poor dictionary which doesn't define the base case! How about "see recursion until you understand." :-)

    :-) yes, the stop condition is important, otherwise you'll end up with a stack overflow error reading your dictionary...

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  7. that was bizarre[ Go to top ]

    I found it odd how making the Strategy interface use of generics meant the TaxPayer class had to refer to the same generic in its class definition.
  8. that was bizarre[ Go to top ]

    I found it odd how making the Strategy interface use of generics meant the TaxPayer class had to refer to the same generic in its class definition.

    Yes, I agree. It's as weird as the Enum class definition. Maybe in 5 years time we'll look back at these classes and laugh that we found them difficult to read ;-)

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  9. Recursive generics -"bizarre?"[ Go to top ]

    The recursive types in the generics are becoming standard with Java, but seem to me to be erronious.

    If we say <T extends P<T> > this is in concept wrong. It defines an infinite type definition with no solution.
    The type <T extends P> is ok, or the
      <T extends P<?> > also is OK, with the usual caveats of Java issues for it.

    Perhaps I'm missing something..! :-)

    The logic of a TaxPayer being a subtype of TaxPayer seems wrong in this same sense. And then what is the proper usage for a list of taxpayers, and a loop over them?
      List<TaxPayer<?>> group = new ArrayList<TaxPayer<?>>();
      ...
      for( TaxPayer<? extends TaxPayer> t : group ) ...

    Pretty cumbersome.

    I also don't like the resultant usage:
        TaxPayer<Employee> heinz =
             new TaxPayer<Employee>(TaxPayer.EMPLOYEE, 50000);

    Three required syntactic repetitions of the same type on one line.
  10. Recursive generics -"bizarre?"[ Go to top ]

    Which leads me to another question. Why does the following code not cause a warning now (I am using a raw type)?

        Collection<TaxPayer> payers = new ArrayList<TaxPayer>();
        payers.add(new Employee(TaxPayer.EMPLOYEE, 50000,
              true, Employee.Gender.MALE));
        payers.add(new Company(TaxPayer.COMPANY, 100000));
        payers.add(new Trust(TaxPayer.TRUST, 30000, false));
        for (TaxPayer payer : payers) {
          System.out.println(payer.extortCash());
        }

    Oh, that is probably the same reason why the class definition class TaxPayer<P extends TaxPayer> does not currently produce warnings!

    So would it be more correct then to write the following?

        Collection<TaxPayer<?>> payers = new ArrayList<TaxPayer<?>>();

    and then

        for (TaxPayer<?> payer : payers) {
          System.out.println(payer.extortCash());
        }

    The problem here is that I am trying to be theoretically correct regarding raw types, but the compiler does not tell me when I am getting it right / wrong.

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    <
  11. Which leads me to another question. Why does the following code not cause a warning now (I am using a raw type)
    The compiler doesn't warn about the use of raw types. Maybe it should, but it doesn't: it saves the warnings for uses of raw types that could lead to exceptions at run time.

    Regards
    Maurice
    ---
    Coming soon: "Generics and Collections in Java 5", Naftalin & Wadler, O'Reilly Media
  12. It would be nice to have a self generic. Where one could be more precise and say:

    TaxPayer<T is this.class>

    Or actually remove the type completely from the class definition and implicitly into the class by allowing this.class to be a type. (would fix Clonable/Object.clone too)

    On the area of overly verbose syntax it would be nice if sun had made typing of constructors optional when the type can be derived. As a factory method can actually get the result I don't see the point of not providing it in constructors.

    Perhaps auto types would be a nice syntactic sugar too when types could be derived without confusion.
  13. I found it odd how making the Strategy interface use of generics meant the TaxPayer class had to refer to the same generic in its class definition.
    Yes, I agree. It's as weird as the Enum class definition. Maybe in 5 years time we'll look back at these classes and laugh that we found them difficult to read ;-)

    It is actually less mysterious, once ou shift your perspective from <em>recursive</em> to that of a FixPoint. We all learnt to solve <em>x=tan(x)</em>.

    In <em>T<P extends T<P>></em> we solve a similar problem though now we are generating a class rather than a numeric value.

    For a specific class, say A, just start with <em>T<A extends T<Object>></em>, you get some generated code for A. Insert that back and you will soon see that the generated code is identical to its previous iteration, i.e., it has converged and we have the solution. Voila. (BTW, that's not how the code is generated, but it is a useful method of proof.)
  14. Simpler Syntax[ Go to top ]

    I liked Werner Schulz's explination of how to read recursive generics - the algebraic example is very good. Even with a good explanation like Werner's the syntax is a little cumbersome, e.g. class T< P extends T< P > > { ... } and class TD extends T< TD > { ... }.

    I don't think this is possible in Java because of backward compatibility, but I would like normal inheritance, i.e. class T { ... } and class TD extends T { ... }, mean class T< P extends T< P > > { ... } and class TD extends T< TD > { ... }.

    There is a crutial difference between the recursive and non-recursive forms at the moment in class T. In the recursive form P does not have the same type as this, P is a T or something that extends T whereas this is exactly a T (exluding things that extend T).

    Similarly in a class with the recursive delaration you can return a P (meaning a T or something derived from T), wheras without this declaration the best you can do is return T (which means exactly of type T).

    This would mean many examples simpler, e.g.:

    interface TaxStrategy {
      double extortCash( TaxStrategy taxStrategy );
    }

    class CompanyTaxStrategy implements TaxStrategy {
      public double extortCash( Company company ) { ... }
      ...
    }

    etc.

    This would have the disadvantage of catching less errors at compile time; e.g. if the base class is used as in TaxStrategy cts = new CompanyTaxStrategy(); cts.extortCash( person ) then no compiler error, but the error is still caught at runtime. But it could still catch errors if the base class wasn't used, e.g. CompanyTaxStrategy cts = new CompanyTaxStrategy(); cts.extortCash( person ).

    PS very similar discussions to this have been on the Artima site under Bruce Eckels blogs - he was trying to understand generics and in particular recursive generics.
  15. Raw Types[ Go to top ]

    Heinz,

    You wrote about raw types perhaps being phased out. Scott Seligman comments that this is a goal of Sun at http://java.sun.com/developer/community/chat/JavaLive/2004/jl1012.html [search for the word 'raw' about 2/3rds down the page].
     
    How realistic is it that Sun will ever phase out raw types?
  16. Raw Types[ Go to top ]

    How realistic is it that Sun will ever phase out raw types?

    Good question, John! One of the problems with Java in general is Sun's inability to change anything, once released.

    The only thing that might happen is that the warnings become more severe.

    One of the comments from my readers was that the whole abstract method getDetailedType() was strictly speaking not necessary. We could just do a downcast inside extortCash():

      public double extortCash() {
        return strategy.extortCash((P)this);
      }

    In addition, he suggested that I add a @SuppressWarnings to the code.

    One of my initial goals was to make this work without the @SuppressWarnings. Personally I don't like the idea of using the @SuppressWarnings annotation. Code should never need it. But it does.

    So even if Sun does make the warnings more strict, I think that most programmers will find it too much effort to make them go away and just sprinkle @SuppressWarnings everywhere.

    I do not think that they will ever make the use of raw a compile time error.

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  17. SuppressWarnung[ Go to top ]

    Personally I don't like the idea of using the @SuppressWarnings annotation. Code should never need it. But it does.So even if Sun does make the warnings more strict, I think that most programmers will find it too much effort to make them go away and just sprinkle @SuppressWarnings everywhere.

    Heinz, you're being romantic about this warning issue. I would never write the same 100 methods in 100 strategies implementing the same abstract class. For my understanding those warning remain warnings, not errors.
    Now, concerning your newsletter, we meet a problem that the whole generic concept answers with a warning even though the solution is logical to us. This is a case where I WILL ignore warnings if I can. In most other cases I would never, there I completely agree with you.

    I think we cannot afford to satisfy all the little hiccups of inconsistent concepts, to satisfy every warning of a compiler. Sometimes a solution simply is so easy that it is the right. And for my company, for our customers of course the best. ;-)

    Kind regards,
    Stefan Schubert

    *************************************************
    W3 Solutions GmbH, Berlin
    http://www.w3statistics.com/index_en.htm
    -------------------------------------------------
  18. SuppressWarning[ Go to top ]

    Heinz, you're being romantic about this warning issue. I would never write the same 100 methods in 100 strategies implementing the same abstract class. For my understanding those warning remain warnings, not errors.Now, concerning your newsletter, we meet a problem that the whole generic concept answers with a warning even though the solution is logical to us. This is a case where I WILL ignore warnings if I can. In most other cases I would never, there I completely agree with you.I think we cannot afford to satisfy all the little hiccups of inconsistent concepts, to satisfy every warning of a compiler. Sometimes a solution simply is so easy that it is the right. And for my company, for our customers of course the best.

    Stefan - ideally I would like to see a middle road. Generics should be clever enough to NOT give me a warning there in the first place. We could not figure out a way to do that, except to put the abstract method in.

    And yes, if you repeat this 100 times, you are going to write a lot of boring, stupid methods :)

    So my question here is - can anyone get this right without causing extra code in the subclasses (such as the abstract method) and without @SuppressWarning?

    I do not like that @SuppressWarning annotation because it can easily hide real problems. I also do not like the way that Eclipse offers it as a default option when the compiler is warning you about something.

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  19. SuppressWarning[ Go to top ]

    I do not like that @SuppressWarning annotation because it can easily hide real problems. I also do not like the way that Eclipse offers it as a default option when the compiler is warning you about something.

    +1 (er, maybe +1000000000).

    I really think that @SuppressWarning is uglier than the compiler warnings themselves.
  20. SuppressWarning[ Go to top ]

    So my question here is - can anyone get this right without causing extra code in the subclasses (such as the abstract method) and without @SuppressWarning?I do not like that @SuppressWarning annotation because it can easily hide real problems. I also do not like the way that Eclipse offers it as a default option when the compiler is warning you about something.

    You're completely right. It is no good style to annotate warnings away. Not at all.

    There will be no solution. I'll try to explain why. For this, please look at:



    1 public TaxPayer(TaxStrategy<P> strategy) {
    2 this.strategy = TaxStrategy.class.cast(strategy);
    3 }
    4
    5 TaxStrategy strategy;
    6
    7 void extortCash() {
    8 strategy.extortCash(this);
    9 }


    The java compiler encourages you through warnings not to use raw types. So the code aboves produces a warning in line 8. In line 8 it would be a possible, fitting solution not to use the parametrized type of TestStategy because the abstract type Test simply cannot know how its concrete parameters are at runtime as generics are interpreted at compile-time.

    The second solution is to ask the parametrized Test type. But this is a model class and I would not want my model class to know what workarounds are needed to correctly execute a strategy. This even somehow breaks with the strategy concept. If someone should know "how to handle it" it should be the strategy.

    So the third solution would be to give the strategy a Class<E> getHandledType() method and strategy.getHandledType().cast(this). I would have less headache with this solution though it may produce even more redundant code than the other solution. At least it keeps the model simple, what is what we want to achieve with strategies.

    The fourth is our simple solution to call the strategy with strategy.doSomething((E) this). But again we try to access compile-time information at runtime (casting) and thus receive a warning.

    The answer lies hidden within in your class diagram (newsletter): All the concrete types of TaxPayer<P extends TaxPayer<P>> and TaxStrategy<P extends TaxPayer> know at compile-time what parameters they have. At runtime they don't. Now you call the strategys (knowing it has the parameter P at compile time) method from the abstract model (were we don't know at compile time that TaxPayer<P> is in fact P).

    In fact the compiler does not know (Sun's failure?) That TaxPayer<P extends TaxPayer<P> can only mean that P has to a class inheriting TaxPayer. At this point the concept of (forced) generics at compile-time breaks.
  21. Its great to see the article on TSS. But, just a small follow up question:

    The generics are great but one drawback is that they are compile time only. The example given is great and serves its purpose more than enough. But I can't help to notice that most of the parameters would be configured outside the code and that processing of taxes would be done one TaxPayer at a time. It is also mentioned that we want to eliminate the need for switch statements and deep complex if statements by utilizing Strategy Pattern. But lets say we want to do taxes for bunch of people in our database (seems logical) and then we have to create TaxPayer object on the fly for each person.

    Maybe I'm missing something, but hmmm.... we do need to have bunch of if statements or utilize a Factory Pattern. The reason I'm asking is that I'm never sure of the best way to do something like this. In the end, all my creator classes end up with complex switches and ifs just for creation of appropriate objects.

    Thought I'd ask :)
  22. The generics are great but one drawback is that they are compile time only.

    Well, the checking is obviously done at runtime as well.
    It is also mentioned that we want to eliminate the need for switch statements and deep complex if statements by utilizing Strategy Pattern. But lets say we want to do taxes for bunch of people in our database (seems logical) and then we have to create TaxPayer object on the fly for each person. Maybe I'm missing something, but hmmm.... we do need to have bunch of if statements or utilize a Factory Pattern.

    That is an excellent question, Daniil! It took me a while to see the difference as well. When you use the Strategy pattern, you would often need to have some mapper that takes a some value and maps it to a Strategy instance. This could be done with switch / if-else-if statements, or could be done using enums with a reverse lookup (look at my newsletter on enum inversion http://www.javaspecialists.co.za/archive/newsletter.do?issue=113 ). Enums work nicely for strategies, except that you are then limited to a finite set of strategy possibilities, which is something you might want with tax calculations.

    So, if you do have a switch statement that maps an int to a Strategy instance, then you only need to have one such switch statement, and not one whereever it is used. I once wrote a CASE tool that had different operations stuck into switch statements, where polymorphism or strategy would have been a much better approach. There was a different switch for each operation: print, import, export, draw, erase, move, etc. Yes, the code was terrible, but it was a long time ago. When I had to add new graphical objects to the CASE tool, I had to update every switch statement. If I forgot one, I would only pick that up at runtime, e.g. printing did not work for certain components.
    The reason I'm asking is that I'm never sure of the best way to do something like this. In the end, all my creator classes end up with complex switches and ifs just for creation of appropriate objects.Thought I'd ask :)

    Yes, but at least you only have one horrible switch statement, and not five. In addition, it only ever gets called once, whereas the other switch statements would be called every time an operation is executed.

    Kind regards

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  23. choosing your strategies.[ Go to top ]

    The generics are great but one drawback is that they are compile time only.
    Well, the checking is obviously done at runtime as well.
    It is also mentioned that we want to eliminate the need for switch statements and deep complex if statements by utilizing Strategy Pattern. But lets say we want to do taxes for bunch of people in our database (seems logical) and then we have to create TaxPayer object on the fly for each person. Maybe I'm missing something, but hmmm.... we do need to have bunch of if statements or utilize a Factory Pattern.
    That is an excellent question, Daniil! It took me a while to see the difference as well. When you use the Strategy pattern, you would often need to have some mapper that takes a some value and maps it to a Strategy instance. This could be done with switch / if-else-if statements, or could be done using enums with a reverse lookup (look at my newsletter on enum inversion http://www.javaspecialists.co.za/archive/newsletter.do?issue=113 ). Enums work nicely for strategies, except that you are then limited to a finite set of strategy possibilities, which is something you might want with tax calculations.So, if you do have a switch statement that maps an int to a Strategy instance, then you only need to have one such switch statement, and not one whereever it is used. I once wrote a CASE tool that had different operations stuck into switch statements, where polymorphism or strategy would have been a much better approach. There was a different switch for each operation: print, import, export, draw, erase, move, etc. Yes, the code was terrible, but it was a long time ago. When I had to add new graphical objects to the CASE tool, I had to update every switch statement. If I forgot one, I would only pick that up at runtime, e.g. printing did not work for certain components.
    The reason I'm asking is that I'm never sure of the best way to do something like this. In the end, all my creator classes end up with complex switches and ifs just for creation of appropriate objects.Thought I'd ask :)
    Yes, but at least you only have one horrible switch statement, and not five. In addition, it only ever gets called once, whereas the other switch statements would be called every time an operation is executed.Kind regardsHeinz--Dr. Heinz M. Kabutz (Maximum Solutions)Sun Java ChampionAuthor of "The Java(tm) Specialists' Newsletter"http://www.javaspecialists.co.za

    Forgive me if I'm misapprehending something in this discussion, but there's another solution that seems obvious to me - use configuration. I did this a few years ago with the strategy I implemented for importing differing XLS worksheet formats.

    Define in your configuration a list of strategy identifiers with the full class name, load the configuration and instantiate the classes into a hash (er, dictionary. Been on C# for a while, sorry). Use the identifier to "name" your particular scenario and simply call the strategy with this information. No switches, or ifs, and changing your rules is as simple as updating the configuration and adding the new class. In my case the ID represented the type of worksheet format, and the user chose that from a dropdown, also populated from the same configuration entry.

    --
    David Bicking
  24. choosing your strategies.[ Go to top ]

    Forgive me if I'm misapprehending something in this discussion, but there's another solution that seems obvious to me - use configuration. I did this a few years ago with the strategy I implemented for importing differing XLS worksheet formats.Define in your configuration a list of strategy identifiers with the full class name, load the configuration and instantiate the classes into a hash (er, dictionary. Been on C# for a while, sorry). Use the identifier to "name" your particular scenario and simply call the strategy with this information. No switches, or ifs, and changing your rules is as simple as updating the configuration and adding the new class. In my case the ID represented the type of worksheet format, and the user chose that from a dropdown, also populated from the same configuration entry.

    Absolutely, in which case, instead of having one initial switch statement, we end up with a Factory class that does some initialization based on the configuration parameters. I think that's what Daniil may have meant here:
    Maybe I'm missing something, but hmmm.... we do need to have bunch of if statements or utilize a Factory Pattern.

    This begs another question: how complex can we allow configuration to become?

    Kind regards

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  25. choosing your strategies.[ Go to top ]

    Forgive me if I'm misapprehending something in this discussion, but there's another solution that seems obvious to me - use configuration. I did this a few years ago with the strategy I implemented for importing differing XLS worksheet formats.Define in your configuration a list of strategy identifiers with the full class name, load the configuration and instantiate the classes into a hash (er, dictionary. Been on C# for a while, sorry). Use the identifier to "name" your particular scenario and simply call the strategy with this information. No switches, or ifs, and changing your rules is as simple as updating the configuration and adding the new class. In my case the ID represented the type of worksheet format, and the user chose that from a dropdown, also populated from the same configuration entry.
    Absolutely, in which case, instead of having one initial switch statement, we end up with a Factory class that does some initialization based on the configuration parameters. I think that's what Daniil may have meant here:
    Maybe I'm missing something, but hmmm.... we do need to have bunch of if statements or utilize a Factory Pattern.
    This begs another question: how complex can we allow configuration to become? Kind regardsHeinz--Dr. Heinz M. Kabutz (Maximum Solutions)Sun Java ChampionAuthor of "The Java(tm) Specialists' Newsletter"http://www.javaspecialists.co.za

    Exactly what I'm talking about. We either end up with one switch vs. many (when using Strategy) or creating some kind of Factory. And as far as factories go these days people seem to prefer having huge & complex configurations to complex code. I'm guessing this is place for Spring. But theory aside, I'm just always on lookout for avoiding hard coding (but its so fast to gain results!!!) with something more generic and more exciting :)

    Thanks for replies guys!
  26. Do what creates certainty.[ Go to top ]

    Maybe I'm missing something, but hmmm.... we do need to have bunch of if statements or utilize a Factory Pattern. The reason I'm asking is that I'm never sure of the best way to do something like this. In the end, all my creator classes end up with complex switches and ifs just for creation of appropriate objects.Thought I'd ask :)

    What is most important is that your code is robust. This means do whatever makes sure that adding or changing classes will either work correctly or fail by the compiler.

    About the if statements when instanciating classes. Look at whether the logic is local to the instanciator, or is generic for a larger part of the system. In the latter case use a factory. In the first case you can use an if statement.
  27. First I have no problems with the strategy pattern as is shows strong use of polymorphisum. However consider this. It took 4 experts in generics to finally sort out what the syntax for this piece of code should look like. I have four questions and one comment.

    If it took 4 Generic gods to write this code then how the heck are us mere mortals suppose to be able to follow?

    Can anyone (and I do mean *anyone*) out side of the Sun compiler group provide me with a step by step breakdown of these declarations mean so that I might have a fighting chance of understanding them?

    Was all of that worth it to avoid a downcast? Certianly if you don't get the inheritance right the compiler is going to complain anyways. Certianly a 1.4 compiler would.

    Why do I feel that we have reduced the community from interesting discussions about designs and frameworks down to boring questions of syntax?

    IM (not so) HO, this is a classic case as to why we should work to eliminate generics from the Java langauge and it should be expunged ASAP. This is a lot of un-needed complexity for almost 0 gain. I'll even go so far to be rude and say that is your response includes type safety then don't bother wasting your time with it. It is a strawman arguement totally without merit. If you seriously have problems with ClasscastException then we need to be talking about design and coding patterns and not be reduced to talking about draconian syntax.

    Kind regards,
    Kirk
  28. To bore you even more with syntax and generics.

    It is much more easy to program a thousand times of:
    for (Concrete c : list) {
      c.doSomething();
      c.doSomeOtherThing();
    }

    Than:
    for (Object o : list) {
      Concrete c = (Concrete) o;
      s.doSomething();
      s.doSomeOtherThing();
    }

    Or rather (as with J2SE 1.4):
    for (Iterator itr = list.iterator; itr.hasNext()) {
      Concrete c = (Concrete) iterator.next();
      s.doSomething();
      s.doSomeOtherThing();
    }

    Things to know: Where has this list been defined?
    Or rather: What framework provided me with this list and what's in there?
    Am I a developer to write the same _solely_administrative_ code that can cause runtime exceptions at more than one point again and again?

    This grows really anoying code. I am indeed wondering how I would be protected from a ClassCastException out of the Collection Framework now and then with design and coding patterns, I'm really curious.
    A ClassCastException is one of the most common exceptions at runtime. To avoid such issues moving the specification of an interface from the documentation into the programming language actually isa high gain from the developers point of view .

    Not of course, if you simply don't like it, can't get used to it, find it too complex etc. But this is a problem with every change in programming languages.
    Easy additional features where they _might_ be of use for developers I would always encourage. Others don't.
  29. To bore you even more with syntax and generics.It is much more easy to program a thousand times of:for (Concrete c : list) {&nbsp;&nbsp;c.doSomething();&nbsp;&nbsp;c.doSomeOtherThing();}Than:for (Object o : list) {&nbsp;&nbsp;Concrete c = (Concrete) o;&nbsp;&nbsp;s.doSomething();&nbsp;&nbsp;s.doSomeOtherThing();}Or
    Oh the follies of the code fragments. Lets talk about what you have to do to setup for this wonderful for loop. ;)
    I am indeed wondering how I would be protected from a ClassCastException out of the Collection Framework now and then with design and coding patterns
    I've covered this subject in my blog and that is all I feel like saying about it.
    ClassCastException is one of the most common exceptions at runtime.
    Can you quote statistics on this? IME null pointer exceptions are far more common. Should we work to ban null pointers from the language?

    Kind regards,
    Kirk
  30. Kirk's Agreggates[ Go to top ]

    Kirk in another blog (http://kirk.blog-city.com/generics_reloaded.htm) has suggested that instead of List< String > we do:

    class Strings {
        private List l = new ArrayList();
        String get( int index ) { return (String)l.get( index ); }
        void add( String s ) { l.add( s ); }
        ...
    }

    IE he is suggesting composition instead of inheritance and generics. This has the advantage of avoiding generics at the expense of a little extra typing.

    Another option is:

    class Strings extends ArrayList< String > { }

    This nicely combines the benifits of both forms.
  31. Kirk's Agreggates[ Go to top ]

    Another option is:class Strings extends ArrayList< String > { }This nicely combines the benifits of both forms.

    AFAIU it's not! What if you want to turn it into a Map or a Set? This is the _main_ point of Kirk with composites not type-safety.
  32. Kirk's Agreggates[ Go to top ]

    To be more precise: Inheriting from a concrete Java OEM class just because for type safety is presenting you a couple of more problems.

    I personally have difficulties imagining to introduce the whole wrapped collections concept into my projects. Though I realize that a lot of my problems (a lot of errors if an API you change the implementation) come from using collections directly.

    I know that a lot of people a) do have the same problems and b) never heard of wrapping every implementation thing up. Are there any open source projects, books etc. explaining those concepts on a more than tiny-because-it-is-easy scale?
    Is such an extensive-to-the-detail use of aggregation actually in use?

    Kind regards,

    Stefan
  33. Kirk's Agreggates[ Go to top ]

    Another option is:class Strings extends ArrayList< String > { }This nicely combines the benifits of both forms.
    AFAIU it's not! What if you want to turn it into a Map or a Set? This is the _main_ point of Kirk with composites not type-safety.

    Using Kirk's technique you have to program to the specific class not the base, i.e. you write Strings strings = new Strings(); not List< String > ... since in Kirk's original a Strings wasn't a List. Therefore you can change Strings to be a map if you want. Similarly if you start of using inheritance and latter change your mind and want composition (say a reduced interface) you can refactor. Why not start with something simple and see how you go.
  34. Kirk's Agreggates[ Go to top ]

    Another option is:class Strings extends ArrayList< String > { }This nicely combines the benifits of both forms.
    AFAIU it's not! What if you want to turn it into a Map or a Set? This is the _main_ point of Kirk with composites not type-safety.

    Strings is not my example and I'm not so sure that it is the best example for what I was trying to say. What I am saying is that by wrapping the collection I get a number of benefits. Type safety is an accidential benefit so I don't have to be concerned with it. I also prescribe to the notion of using short methods. When I use short methods generics actually increases the amount of typing that I have to do. But again this is yet another point that is not so important because ctrl-space and my IDE looks after it.

    The big benefit is that it seems to be a better way for me to organize my code. Smaller methods are more useful in that they make better building blocks for supporting more complex functionality in other (short) methods. As I've already said in this thread, the woes of code fragments is that you don't really get to see these benefits because the code is too small to demonstrate them. You see these benefits when you start looking at entire applications and you start using software metrics to measure importand aspects of design and structure. Thing such as cohession, couplings, volumes, complexity, how many if-then-else statements do you use. Do you use any switch statements?

    The best thing to come out of Heinz's newsletter is the advantages of using polymorphisum. The Strategy pattern promotes good use of polymorphisum. But don't take my word for it, go do the metrics yourself. Every if-then-else is potentially a lost opportunity for polymorphium. Switch is OO's goto. The starting code contains a switch (cascading if-then-else block == switch statement). That switch statement is eliminated from the design. In terms of metrics we went from 1->0 in switch and 0->0 in if-then-else. Later on the if-then-else count creeps up to 2 as complexity is introduced into the problem. The question is; is it worth it to do the work that is necessay to eliminate the if-then-else. Certianly your code is going to have these because they are quite useful. So there is no hard and fast rule here. The question is, would the change be useful to your model to increase polymorpisum and eliminate the need for the if-then-else? We could morph the question to, are you violating SRP and if so.. how flagerent is the violation. This question translates into, is your class cohessive and that is a question we can answer with metrics. These metrics look at the relationship between methods and instance variables. You see where we expect classes to be loosely coupled and not share implementation or state, we do expect that the inner workings of a class to be tightly coupled as thing work together to get things done.

    I believe that if you measure and follow practices that improve your measurements, you will end up with better code. I've also said that these measurements are not so perfect and they certianly break down when you reach the edge of your system. However, they are a heck of a lot better then handwaving.

    Kind regards,
    Kirk
  35. Kirk's Agreggates[ Go to top ]

    Every if-then-else is potentially a lost opportunity for polymorphium. Switch is OO's goto. The starting code contains a switch (cascading if-then-else block == switch statement). That switch statement is eliminated from the design. In terms of metrics we went from 1->0 in switch and 0->0 in if-then-else. Later on the if-then-else count creeps up to 2 as complexity is introduced into the problem.
    This is where theoretical and practical complexity differ.

    Humans will certainly find an if/else or switch statement easier to read than if the branches are abstracted in polymorphic methods.

    Bertrand Meier used to agree with you and he purposefully omitted switch from Eiffel. And he resisted the pressure for years, but even he eventually caved.

    --
    Cedric
    http://testng.org
  36. Facade to the rescue[ Go to top ]

    When I was deciding which patterns to put into my Design Patterns Course, I noticed how different Facade was to the other patterns. Have a look at the structure. Facade does not have a typical class structure - all the other patterns do.

    Something else that few people realist - Facade explicitly allows users access to the innards of the subsystem. So it differs from the Session Facade in more than one way.

    The point is this - Facade should never have been in the catalog of Design Patterns, because it is only there thanks to the additional classes / methods that we see made when we start using design patterns.

    It might be easier to write one large switch / if-else statement. It might also be easier to read and comprehend. It is also much more tempting to copy &amp; paste this switch statement to another place in your system.

    The Facade helps us here by giving the users of the system a more condensed interface that they can use to speak to the subsystem. i.e. They do not have to construct a strategy, composite, template method visitor listener in order to use the subsystem, they can simply use the Facade.

    I would rather have a well factored system where the metrics give me a green light, because it then gives me hope that I will be able to maintain it without dangers of a stroke.

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  37. Kirk's Agreggates[ Go to top ]

    Every if-then-else is potentially a lost opportunity for polymorphium. Switch is OO's goto.
    This is where theoretical and practical complexity differ. Humans will certainly find an if/else or switch statement easier to read than if the branches are abstracted in polymorphic methods.

    yes indeed that would appear to be the case. Is this because people are getting off to the wrong start in their (programming) life?
    Bertrand Meier used to agree with you and he purposefully omitted switch from Eiffel. And he resisted the pressure for years, but even he eventually caved.

    Maybe he still does agree but put the switch in anyways ;)

    Switch plays an important role in Java as it is afterall) a mixed language. Primitives don't exactly support polymorphisum all that well do they. This is why software metrics are not absolute. They need to be backed by an investigation of the code. For example in this case, Heinz was clearly using switch in favor of polymorphisum and the application of the pattern may not clarify the code (the curse of code fragements) but it does enhance it's mantainability and certianly moves it to compliance with the open/closed principle.

    Kind regards,
    Kirk
  38. Switch and Goto[ Go to top ]

    There are programs that are better expressed with a goto. (Gasp!) (Actually you can think of a method as an organized way to "goto" the start of a bit of code and "goto" the same place you came from at the end of that code. Its a very useful convention.)

    At the end of this is an example that convinces me. You may see it differently.

    There are programs that are better expressed with a switch. Its the same principle. If you have only one way to do things, you can't choose the best way. We have traded the "goto" option away so we can remove some of the confusion that it can be used for. (I'm not really against this decision made back in the 70's.)

    One problem with thinking about this is that the switch in Java is so limited. You can execute one of several blocks of code based on a numeric value. A more generic switch is just a list of tests with some code that you run if the test is true. The Java switch has just one sort of test. You can use a series of "if .. else if .. else if" to do the same thing as a more generic switch but it can be hard to read.

    The problem is that when the tests are all the same, as someone said, you would be better off using some sort of polymorphism. Polymorphism of this sort means we do the same thing in different ways for different but related classes. But when the tests are very different its hard to arrange the classes so as to make the distinctions clear.

    Think of redoing this sort of code with polymorphism. (This code is in a class that holds some kind of number. Oh .. and ignore the epsilon-its-close-enought issue.)

    ---------------------------------------------

    public boolean equals(Object that) {
       if (that == null) return false;
       if (that instanceof MyClass) return this.val() == ((MyClass)that).val();
       if (that instanceof Number) return this.val() == that.doubleValue();
       String val = that.toString();
       if (areAnyNonDigits(val)) return false;
       return (new Double(val)).doubleValue() == this.val();
    }

    ---------------------------------

    The problem with doing this with polymorphism is that the returns on the effort are so small with the tests so different.

    An example for goto? You might disagree. Here is one I like.

    Consider a state machine used to respond intelligently to incoming signals. One way to analyze this problem is to create a drawing with little circles showing the "states" and arrows showing how to get from one state to another based on the incoming stimulus.

    The diagram is inheirently two dimensional. Programs are inherently linear but broken into groups by classes and methods and such.

    You could write some sort of tool that allows you to draw circles and lines and add bits of code to define the process.

    A simple way to do this is to put bits of code like this. I'm not using any real language. The "line" labels represent the lines in the state diagram. "line01" goes from state 0 to state 1. The "state" labels represent the circles. Using these con

    -----------------------------
    state0:
    while (true) {
      if (condition1) goto line01;
      if (condition2) goto line02;
    }
    // we never get here

    line01:
    doAction01();
    goto state1:

    state1:
    while (true) {
      if (condition2) goto line12;
      if (condition3) exit;
    }

    // More lines and states would follow to represent the whole diagram.

    --------------------------------------

    What are the alternatives? I've seen (and used) a couple.

    One other way to do it is to use a loop and switch on the state. This has no "goto"s. It looks like this. The circles are represented by the "case"s and the lines are represented by the code after each "if". I find it acceptable to work with but harder to read. The looping around all the cases seems to hide the truth of the code. The code for the lines is hidden in among the if's.

    ---------------------------------------

    int state = 0; // starting state
    while (true) {
      switch (state) {
        case 0:
          if (condition1) {
            doAction01();
            state = 1;
          }
          else if (condition2) {
            doAction02();
            state = 2;
          }
          break;
        case 1:
          if (condition2) {
            doAction12();
            state = 2;
          }
          else if (condition3) ...
          break;
      }

    -------------------------------------------

    I'm getting too long to show but the last way I have done this is a classic use of the "State" pattern. You have a class to represent each state and they all extend some base class. A controller class loops and calls the current state object repeatedly. That state object does its tests, executes its code to represent each of the lines and then tells the controller somehow which state is the next one.

    This is really hard to read. The "class" structure hides the simplicity of it all. The line code is hidden inside the class for the state that is the source of the line (in the diagram).
  39. Switch and Goto[ Go to top ]

    You have a class to represent each state and they all extend some base class. A controller class loops and calls the current state object repeatedly. That state object does its tests, executes its code to represent each of the lines and then tells the controller somehow which state is the next one.This is really hard to read. The "class" structure hides the simplicity of it all. The line code is hidden inside the class for the state that is the source of the line (in the diagram).

    Hi Lee,

    interesting pattern you picked on there :) I also find that the State Pattern code can be hard to follow. However, the same holds true for the classical goto approach for state machines, the moment that it grows too large.

    I maintain that state machine code should be autogenerated from a formal specification language like SDL or Estelle. Even Petri nets if that excites you (some of the extensions of these such as Queuing Petri Nets and Colored Petri Nets are more powerful for modelling systems than the ordinary old Petri net).

    Ideally if you are working with a state machine, you should be looking at the graphical representation. How it is implemented should not matter. Maintenance should only happen on the formal specification and not inside your code.

    Unfortunately, I have still not found a good and free tool for translating SDL to Java. I wrote a free SDL editor in C++ many many years ago, but I don't think that is in circulation anymore (I certainly hope not).

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  40. Switch and Goto[ Go to top ]

    There are programs that are better expressed with a goto. (Gasp!)

    Certianly error handling is one case where this is true. However in Java we've settled on exceptions.
    ---------------------------------------------public boolean equals(Object that) {&nbsp;&nbsp;&nbsp;if (that == null) return false;&nbsp;&nbsp;&nbsp;if (that instanceof MyClass) return this.val() == ((MyClass)that).val();&nbsp;&nbsp;&nbsp;if (that instanceof Number) return this.val() == that.doubleValue();&nbsp;&nbsp;&nbsp;String val = that.toString();&nbsp;&nbsp;&nbsp;if (areAnyNonDigits(val)) return false;&nbsp;&nbsp;&nbsp;return (new Double(val)).doubleValue() == this.val();}---------------------------------

    The problem with doing this with polymorphism is that the returns on the effort are so small with the tests so different.

    The problem with handling this polymorphicly is that equals is very specific to the thing that you are testing. It also must deal with things that are not objects as Java is a mixed language. You can't apply polymorphium to primitives or null. Also you want to be dealing with things that are the same taxonimy. So we are not in the case where we would like to send a message to an arbritrary object and have it respond accordingly.

    I've never felt the need to use goto in state machines with the exception of handling exceptions. That said all of my recent work with state machines has been with parsers and for that I have generated them using javacc.

    Kind regards,
    Kirk
  41. Switch and Goto[ Go to top ]

    Exactly my point!

    1) When the conditions for the "switch" are similar in important ways, it is easy to use polymorphism to replace the "switch" statement.

    2) Java's switch statement only allows conditions that are pure integers.

    3) Java's switch statement is an excellent candidate to replace with polymorphism.

    That's my point and why I agee when you say "switch is this decade's goto" and explain how to replace its use with polymorphism.

    Of course, the other side of my point is that if you think of "switch" more generally than the way Java does it (and the way C and C++ did it in the days of our fathers), you can only replace the switch with polymorphism when the conditions (and maybe the actions resulting) are substantially similar.

    Thanks.
  42. Taxonomies[ Go to top ]

    Harking back to the original article, it is really common to have multiple taxonomies of classes that have the same structure.

    Example: You have base classes for houses, cars and people. You have blue cars owned by blue people who drive blue cars and you have have red cars owned by red people who drive red cars. Under the blue category you have both navy and azure. And so forth.

    All three base classes have subclasses that have the same structure and you always use the corresponding ones together.

    Professor Kabutz does the same thing with taxpayers and tax calculation strategies. The same taxonomies exist for both sets of classes (with their subclasses) and they have to work with their corresponding class from the other group.

    The article used generics to tie them together. I'm not sure that is a very satisfying answer though.

    One rule says an object should do things for itself. That would translate to "the taxpayer object should calculate its own tax"

    We break this rule when the "calculate" phase is complex so we use brokers or managers to handle the work. This is exactly like the way we have customer objects and customer DAO's to handle persistence of customers. The process of persisting a customer should be done by the customer itself but it is complex and, in some ways, akin to persisting an invoice. So we have a bunch of domain classes and a bunch of DAO classes corresponding to them.

    Two ways pop to mind to solve this:

    1) You have a persistence manager that knows somehow that a customer is needs a customer dao to persist him. This would be analogous to a taxing authority class that knows that a particular type of taxpayer needs a particular type of calculator.

    2) You can have the particular class know which DAO will be doing his persistence. Either a method to return to an interested party the correct DAO or delegate methods to call the DAO methods. In the customer example, the customer class would have a 'getDao()' method OR the customer class would hold a DAO and have methods such as "create", "read", "update" and "delete" that would delegate to that DAO. In the taxpayer example, the taxpayer subclass would either supply the taxing strategy instance OR it would hold the right taxing strategy instance and delegate requests for the taxable amount to it.

    So ... my post isn't really relevant in the sense that the article was about using generics for implementing the strategy pattern. However, is the example that different from other situations where we would use strategies? And if not, does the comparison I gave above to the use of brokers apply better?
  43. Taxonomies[ Go to top ]

    Hi Lee,

    the DAO does use the Strategy pattern.

    Let's say that you had a hierarchy of Data Objects, and you wanted the DAO system to be in place from the root object.

    You could then define a DAO interface at the top level with create / update / etc. methods that take the generic type as a parameter.

    However, where the comparison falls apart is that you ideally would only call the Strategy's methods from one place.

    Heinz
    --
    http://www.javaspecialists.co.za
  44. Kirk's Agreggates[ Go to top ]

    Another option is:class Strings extends ArrayList< String > { }This nicely combines the benifits of both forms.
    AFAIU it's not! What if you want to turn it into a Map or a Set? This is the _main_ point of Kirk with composites not type-safety.

    Kirk, this fits in with the idea of "favour composition over inheritance". i.e. you are building a Decorator / Filter for your classes, rather than adding functionality through inheritance.

    Interesting.

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  45. A ClassCastException is one of the most common exceptions at runtime.

    I don't know about that, Stefan. I can count on my hand the number times that I have seen a ClassCastException caused by my code since I started programming Java in 1997.

    Now NullPointerExceptions I have caused far more frequently, even though the Null Object Pattern provides such a nice solution. Imagine if Java had a new "feature" that objects could not be set to "null", but had to be assigned to Null Objects? They would solve a more common problem, but at the cost of lots of code lying around.

    Kirk does have a point, IMO.

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    <
  46. Hi Kirk, Heinz,

    you're both right. Of course I do count CCEs not that often as many other RuntimeExceptions. And if I do count one than mostly not because of collections.

    I however see, Kirk, that you have a completely different view on collections. After I found your blog (searching for about half an our) ... http://kirk.blog-city.com/generics_reloaded.htm ... I understand now that you see many java.* implementations as helpers doing the "how" that should not be exposed to other application tiers.

    Am I understanding you when I think that you encourage the use of custom classes for every utility-supported aspect in my business domain?

    Taking for example hibernate dealing with my relations between business objects should I not expose the various lists, sets etc. through the tiers of my server? But rather write a new class wrapping every relation thus hiding the implementation of it?

    I consider aggregation very useful. But even for quite medium-sized OO database models the code explodes if I'd introduce wrapper classes for every single relation. For only 10 model classes I might easily come to 50 wrappers just dealing with the same: Managing sets or lists. Doesn't this break with DRY as well?
    And how do you deal with topics were you need to expose your Collection to the view (like iterating lists in a JSF) or to the database framework.

    Do you have any proposal where to read on making this a really useful approach for applications?

    Kind Regards,

    Stefan
  47. Hi Kirk, Heinz,you're both right. Of course I do count CCEs not that often as many other RuntimeExceptions. And if I do count one than mostly not because of collections.I however see, Kirk, that you have a completely different view on collections.

    Indeed.. and one that I've found has saved me a lot of trouble ;)
    ... I understand now that you see many java.* implementations as helpers doing the "how" that should not be exposed to other application tiers.Am I understanding you when I think that you encourage the use of custom classes for every utility-supported aspect in my business domain?

    My arguement is that HashMap, ArrayList etc have no symantic meaning in the vast majority of applictions that I've written and as such have no place in the DOM. However classes sometimes need collection like behavior and in that case they would most likey contain some type of collection from java.*. People have always argued with me that this would result in code bloat. However I find that I write much less code then others do for the same unit of work. I think it comes down to a style issue. I find that others that write with a similar style also write much less code.
    Taking for example hibernate dealing with my relations between business objects
    snip
    Doesn't this break with DRY as well? And how do you deal with topics were you need to expose your Collection to the view (like iterating lists in a JSF) or to the database framework.

    All good points and I'm not sure if I covered them off in that blog or in another. Another pet topic of mine is software metrics. Now I'm not talking about the kind that counts the number of times you put the open bracket on the same line or on the next time. I'm talking about a deeper analysis of software such as halstead, demeter, cyclic complexity, fan-out etc.

    If you use these metrics enough what you will notice is that the measurements break down once you hit the edge of your system. The edge of an OO system is unfortunately not so far away. The edge of a system ends just before the outter edge of the JVM. This is where you hook in GUI to wetware, O/R mappings to databases, RMI to other JVMs... etc... The reason for this is that when you need to sneak over the edge into another world you need to violate encapsulation. You need to expose and couple yourself in ways that would/should be unacceptable if you were to just remain within a single JVM. So does reaching out beyond the edge violate good design principles? The metrics would certianly say yes. Common sense say so also. However it can be done nicely. If you look at IBM-DW Eye on Performance (http://www-128.ibm.com/developerworks/java/library/j-perf07304/index.html)you can see that I wrote an article demonstrating why serialization is not so bad from a design point of view. If you look at the stability metrics serialization measures very high.

    This suggest that we can do better on the edges of our systems then we currently do. In fact I prescribe to the teachings of Peter Coad and his pre Java view on MVC. If you look at that work it also measures very high on stability. High stability means that you are not interfering with him and he is not interfering with you. IOWs.. you are losely couple or at least coupled in a single direction (proper layering). Peter Coad maybe old work but it is worth looking at IMHO.

    Kind regards,
    Kirk
  48. Rubbish[ Go to top ]

    [quote]This is a lot of un-needed complexity for almost 0 gain[/quote]

    I'd disagree about the complexity bit, and the lack of gain.

    One example of where generics reduce complexity, and provide gain is in the creation of a typesafe data access layer in Hibernate.

    Being able to create a parameterized base data access class is just one example of a big time saver.

    The complexity argument is not black or white. Certainly, using a single parameterized type in a class is usually pretty easy to understand.

    The benefit of generics providing a sort of forced documentation should not be understated either, e.g. you can now look at a Map or Collection, etc, and see what the hell is in it, without spending time going through the code to find out what populated it.
  49. Rubbish[ Go to top ]

    you can now look at a Map or Collection, etc, and see what the hell is in it, without spending time going through the code to find out what populated it.

    Rubbish.. I think not and with aggregation you avoid the need to even know that there is a collection involved. Even better!

    Kind regards,
    Kirk
  50. Rubbish[ Go to top ]

    The benefit of generics providing a sort of forced documentation should not be understated either, e.g. you can now look at a Map or Collection, etc, and see what the hell is in it, without spending time going through the code to find out what populated it.

    I only agree partially.

    If I see a declaration:

        Collection<String>

    I still have no clue what is in that Collection. Yes they are Strings, but what do they represent.

    I've noticed that when I use generics in my coding, I am now in the grey (rather than the dark) as to what the collections actually contain. I still have to read the JavaDocs (if they are actually there) or scan through the code to see what is really being put in there.

    Perhaps it should be considered bad practice to put primitives (including standard JDK classes) into collections? What do you think?

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
  51. Rubbish[ Go to top ]

    I only agree partially.If I see a declaration:&nbsp;&nbsp;&nbsp;&nbsp;Collection<String>I still have no clue what is in that Collection.
    True, but Generics still improved the readability of your code.

    I posted a blog entry on that very subject a few days ago, you can find it here.

    I find that Generics + JavaDoc comments have certainly raised the readability of Java quite a bit, although as I said in my blog, JavaDocs are increasingly becoming more useful in IDE's than in Web browsers...

    --
    Cedric
    http://testng.org
  52. Rubbish[ Go to top ]

    True, but Generics still improved the readability of your code.

    In my opinion, you should start that sentence with.. "I find that", or "for me"... because your statement is a matter of opinion and it's one that I don't share. In fact I'd say that it reduces readability in all but the most trivial cases and then it's just an eye sore.


    Kind regards,
    Kirk
  53. Guessing types of Generics[ Go to top ]

    I only agree partially.If I see a declaration:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Collection<String>I still have no clue what is in that Collection.
    I find that Generics + JavaDoc comments have certainly raised the readability of Java quite a bit

    JavaDoc certainly helps, when people actually use it! Goodness me, to date I have not had the priviledge of seeing a single commercial application which had a complete set of JavaDocs. I even wrote a Doclet to find missing comments, and you can check private members by simply invoking it with "-private". However, I still find that there is far too much code where even the public members are not properly documented.

    A place where the JavaDoc argument fails, however, is when someone defines a Map<String, MapEntry<String, Integer>> as a local variable, especially if the method is hundreds of lines long.

    So let's hope that IDEs will encourage developers to be more diligent in writing documentation.

    Cedric, see you next week in Las Vegas - where hopefully we can discuss this some more :))

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  54. Guessing types of Generics[ Go to top ]

    JavaDoc certainly helps, when people actually use it! Goodness me, to date I have not had the priviledge of seeing a single commercial application which had a complete set of JavaDocs. I even wrote a Doclet to find missing comments ...

    ... and didn't bother to comment it. I'll use whatever excuse you have on my next project :-)
  55. Guessing types of Generics[ Go to top ]

    JavaDoc certainly helps, when people actually use it! Goodness me, to date I have not had the priviledge of seeing a single commercial application which had a complete set of JavaDocs. I even wrote a Doclet to find missing comments ...
    ... and didn't bother to comment it. I'll use whatever excuse you have on my next project :-)

    Amazing. You are the first person to "comment" on the absence of comments in the CommentChecker, if you will excuse the pun, since I released that newsletter almost 4 years ago.

    They should be there of course.

    Heinz

    P.S. I had a discussion with a friend this afternoon about comments. He has decided to stop using them altogether, a point I did not agree with.
  56. javadocs[ Go to top ]

    Goodness me, to date I have not had the priviledge of seeing a single commercial application which had a complete set of JavaDocs.

    JavaDoc is a great investment. We have always JavaDoc'd everything .. even all fields, private methods, and test code. Once you get into the habit, it becomes as natural as making sure you use proper indentation ;-)

    Peace,

    Cameron Purdy
    Tangosol Coherence: Clustered Shared Memory for Java
  57. javadocs[ Go to top ]

    Goodness me, to date I have not had the priviledge of seeing a single commercial application which had a complete set of JavaDocs.
    JavaDoc is a great investment. We have always JavaDoc'd everything .. even all fields, private methods, and test code. Once you get into the habit, it becomes as natural as making sure you use proper indentation ;-) Peace,Cameron Purdy

    Good stuff - I would love to look at a class or two to see what type of comments you have in there.

    My colleagues used to laugh at me for documenting private members, but I think it is essential for production code to be properly commented.

    Do you also comment your test cases, Cameron? That is where I draw the line.

    Heinz
    --
    http://www.javaspecialists.co.za
  58. javadocs[ Go to top ]

    Do you also comment your test cases, Cameron? That is where I draw the line.
    You mean you don't?

    That's odd.

    I certainly feel the need to comment my tests *less* than regular code, but comments certainly come in handy when a test class fails. Before I start investigating the failure, I need to understand and/or remember what this class does, and a comment is certainly.

    Here is an example randomly picked from the TestNG code base:

    /**
     * beforeGroups test: make sure that if before methods are scattered on
     * more than one class, they are still taken into account
     */

    These two lines of comments certainly save a lot of time compared to puzzling out the code (not that it's hard to read, it just does complex stuff :-)).

    --
    Cedric
    TestNG
  59. javadocs[ Go to top ]

    JavaDoc is a great investment. We have always JavaDoc'd everything .. even all fields, private methods, and test code.
    Couldn't agree more.
     Once you get into the habit, it becomes as natural as making sure you use proper indentation ;-)
    So... when are you going to start?

    --
    Cedric
    TestNG
  60. Rubbish[ Go to top ]

    I only agree partially.If I see a declaration:&nbsp;&nbsp;&nbsp;&nbsp;Collection<String>I still have no clue what is in that Collection. Yes they are Strings, but what do they represent.

    I guess you can do a few things.

    1. Use a meaningful variable name, e.g. Collection<String> invoiceNumbers

    2. If the data being managed is important, create a class for it, e.g. Collection<InvoiceNo> invoiceNumbers. This is a trivial example.

    You already knew this of course...

    The fact that at least you know they're String is still an improvement (as noted by Cedric).

    I'd also mention the improved readability through the carry over effect of not having to do typecasting in loops, e.g.

    for(InvoiceNo invoiceNo : invoiceNos) {
      doSomething(...);
    }

    It'd be back to the good ol' days without generics here.

    BTW, Thanks for your newsletter. Good read.
  61. Cat in a box[ Go to top ]

     e.g. you can now look at a Map or Collection, etc, and see what the hell is in it, without spending time going through the code to find out what populated it.

    That is flatly not true. List<? super Cat> is a List which you can put Cats into. You have no idea what is in there already.
  62. Cat in a box[ Go to top ]

    &nbsp;e.g. you can now look at a Map or Collection, etc, and see what the hell is in it, without spending time going through the code to find out what populated it.
    List<? super Cat> is a List which you can put Cats into. You have no idea what is in there already.

    I think the ? super construct only makes sense in conjunction with other generics. For example java.util.Collections.sort():

      public static <T extends Comparable<? super T>> void sort(List<T> list) ...

    You can only pass in Lists containing objects that implement Comparable, and where the parameter to Comparable is either a T, or a superclass of T.

    At least this generics construct makes sense when you think about it long enough. The Enum one not.

    Heinz
  63. Cat in a box[ Go to top ]

    You can cast assign a parameter List<? super Cat> to an object of type List<Animal> without any compiler warnings. You can then pass this into a method as an argument perfectly validly.

    Whether you think it makes sense only in the Comparable case is by-the-by; it is legitimate code and hence may be want I want to do (or do by accident, not fully understanding generics).
  64. Cat in a box[ Go to top ]

    You can cast assign a parameter List<? super Cat> to an object of type List<Animal> without any compiler warnings.

    Hmm...how do you do that. I get:

    "cannot convert from List<capture-of ? super Cat> to List<Animal>", which makes sense.
  65. Cat in a box[ Go to top ]

    That is flatly not true. List<? super Cat> is a List which you can put Cats into. You have no idea what is in there already.

    In this case, wouldn't you likely only be interested in the Cat methods/properties of objects in the list?

    You're right in that you probably don't know if the List contains a BigCat subclass, but you probably also don't care -- but at least everything in the list will be a Cat.

    Not sure if i'm missing something here.
  66. It took 4 experts in generics to finally sort out what the syntax for this piece of code should look like. I have four questions and one comment.If it took 4 Generic gods to write this code then how the heck are us mere mortals suppose to be able to follow?
    IM (not so) HO, this is a classic case as to why we should work to eliminate generics from the Java langauge and it should be expunged ASAP. This is a lot of un-needed complexity for almost 0 gain.

    Look at C++ templates. They have been hyped for 10 years and have filled numerous newsgroup discussions. But they are hardly used in real world code because of the introduced complexity. It's unfortunate that Java hasn't learned anything from the C++ failures but repeats them.
  67. I agree Generics is hard for the Generics Gods. Just look at the Generics FAQ, it is really really big! Getting used to ClassCastException was easy. Getting my head around all the problems with Generics is a nightmare.

    From looking at Generics, it seems most problems are rooted in Type Erasure. Forgetting the type info at runtime is giving Java a bad case of Alzheimer's. (I hate to admit it, but .Net generics seems to be a better solution.)

    I agree that Java should remove or redo generics.
  68. I agree Generics is hard for the Generics Gods. Just look at the Generics FAQ, it is really really big! Getting used to ClassCastException was easy. Getting my head around all the problems with Generics is a nightmare.

    I think that in 95% of cases, Generics are easy to read and understand. It is in the 5% of cases that things become tricky. What makes it doubly hard is that I do not have compiler support to tell me when my code is theoretically correct.

    All in all, I think that Generics do improve the quality of your code a little bit, especially when you combine them with the new cool foreach statement. Have a look at
    Making Enumerations Iterable and
    New for/in loop gymnastics.

    I am actually glad that Sun did not make generics more powerful than they did, otherwise we would have even further maintenance nightmares.

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  69. Look at C++ templates. They have been hyped for 10 years and have filled numerous newsgroup discussions. But they are hardly used in real world code because of the introduced complexity. It's unfortunate that Java hasn't learned anything from the C++ failures but repeats them.

    That's just wrong altogether. There's plenty of real world code using templates. Just think of all the code that uses the standard c++ library. Not to mention boost or atl. Or take a look at the code release by google - modern code, and in use by billions since it's at the foundation of google's infrastructure. Obviously I'm not going to compile a list here.
    But, whatever, everybody wants the world to be as one sees it so my saying this will most likely lead to no effect.

    In my opinion, templates (not generics) are the single most powerful programming paradigm and technique for imperative languages. I think there's your functional languages with all their brain-twisting magick right up there at the top followed closely by C++ with templates. The rest is just bland.
    If you don't like it, may I suggest switching programming languages. Java was not made especially for you, was it? I for one am very dissatisfied with the rate it evolves at and the "uuuh let's not implement this and that cause the programmers might hurt their little brains trying to figure it out" attitude. When I get into that mood I just **** off and write some real code in C++ and get my self-esteem back.
  70. Composite may be better[ Go to top ]

    For the Tax Office example given the Composite pattern may be better, see below.

    Note:

    1. In the example below the tax logic is in with the main classes, if you want to seperate the tax logic from the main logic you can pass the tax calculation to a referenced object or package private class with a static method.

    2. I have used my own pet Pattern Enforcing Compiler (http://pec.dev.java.net) because it: enforces the Composite pattern, documents the roles of classes (Component, Leaf, or Composite), and as a blatent plug of my work :)

    3. To use a conventional Java Compiler delete the import, references to Component, Leaf, and Composite, and write the body of TaxableComposite.extortCash.

    class Tax {
        double total; // A wrapper for a double so that you can pass a double by reference
    }

    import pec.compile.composite.*; // Import Composit pattern into PEC

    interface Taxable extends Component {
        void extortCash( Tax tax );
    }

    class TaxablePerson implements Taxable, Leaf {
        public void extortCash( Tax tax ) {
            tax.total += 2.718;
        }
    }

    class TaxableCompany implements Taxable, Leaf {
        public void extortCash( Tax tax ) {
            tax.total += 3.142;
        }
    }

    class TaxableComposite implements Taxable, Composite {
        private final Taxable[] taxables;

        TaxableComposite( final Taxable[] taxables ) {
            this.taxables = taxables;
        }

        public void extortCash( Tax tax ) {
            throw new AssertionError(); // Body written by PEC! - it steps over array calling extortCash
        }
    }

    // Test useage:

    public class TaxOffice {
        public static void main( final String[] notUsed ) {
            final TaxablePerson person = new TaxablePerson();
            final Tax personTax = new Tax();
            person.extortCash( personTax );
            System.out.println( "Person's Tax = " + personTax.total );

            final TaxableCompany company = new TaxableCompany();
            final Tax companyTax = new Tax();
            company.extortCash( companyTax );
            System.out.println( "Company's Tax = " + companyTax.total );

            final TaxableComposite all = new TaxableComposite(
                                                 new Taxable[] { person, company } );
            final Tax totalTax = new Tax();
            all.extortCash( totalTax );
            System.out.println( "Total Tax = " + totalTax.total );
        }
    }

    Which is arguably simpler than using a strategy. Note Composite and Strategy are similar in that they both rely on a base class.
  71. Composite may be better[ Go to top ]

    Hi Howard,

    I'm definitely going to look at your Pattern Enforcing Compiler (http://pec.dev.java.net) - that looks very interesting. Thanks for the link :)

    The Composite is a structural pattern, whereas the Strategy is a behavioural pattern. This solves two different sets of problems.

    The intent of the Composite is to provide a part-whole hierarchy where clients can disregard the difference between individual components and groups of components. For a counter example of where this should have been used is in the structure of Thread and ThreadGroup. However, this is only used for structuring your code, not for representing behaviour.

    The intent of the Strategy is to encapsulate the behaviour of a class, thereby making it interchangeable.

    In the behavioural context, I think that what you are suggesting may be more similar to the Template Method pattern, where we have an abstract method that is overridden in subclasses.

    In my approach, I would be able to have different TaxStrategy objects for the same TaxPayer subclass. i.e. if I wanted to eliminate some more if-else statements, I could have a MarriedWomanEmployeeTaxStrategy class that I configure the Employee with, and then this could simply return the different rate, without doing any more if-else code. As Kirk so rightly stated: switch (or multi-conditional if-else) is the GOTO in object orientation.

    Now, I do not disagree with mixing the Composite and Strategy pattern, the way you did. The Composite goes well with behavioural patterns, look for example at the MacroCommand idea in the Command pattern.

    However, in this case, I wanted to specifically separate the tax calculation algorithm from the tax payer class, and that is what I am doing with this example.

    Kind regards from

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  72. What are the reasons for Generics?
    Java is a type-safe language. This means you define types during development and the compiler will verify those types. Types improve the communication of the design and allow more of the correctness of a system to be verified before runtime.
    Generics allow for the strengthening of the type system when multiple classes interact.
    What are the reasons for Patterns?
    Patterns allow us to improve to communication around design decisions which leads to improvement in verification of the correctness of a system
    Bringing Patterns and Generics together provides a further improvement in the communication of design and the verifiability of a system before runtime.
    If correctness and verifiability is not part of your goals in building software you are probably going to find a reason to dismiss Generics or Patterns.
  73. What are the reasons for Generics?Java is a type-safe language. This means you define types during development and the compiler will verify those types. Types improve the communication of the design and allow more of the correctness of a system to be verified before runtime.Generics allow for the strengthening of the type system when multiple classes interact.

    This is indeed a good way to look at it. Of course taking this to the extreme one could argue that casts should not be allowed at all. While the java language has not enough features to make this feasible that would be a good development. Generics are a step in that direction eliminating explicit casts where they could break havoc. And the casts that are avoided by generics further are those that normally go unprotected by a type check in advance.
  74. Interfaces/Plugins[ Go to top ]

    I'm not a doctor.

    Nor a "Generics specialist" --> Oxymoron?

    Nor do I think about extrinsicizing my code.

    But isn't all we need here is an interface to abstract the taxpayer implementations? If the required data varies, provide a hashmap or variable length arg list in the signature.

    I don't trust the esteemed professor's coding talent if he even wrote code that had that many switch statements in it in the first place. Any programmer worth his salt would have done an abstraction layer way before then.
  75. Interfaces/Plugins[ Go to top ]

    I don't trust the esteemed professor's coding talent if he even wrote code that had that many switch statements in it in the first place. Any programmer worth his salt would have done an abstraction layer way before then.

    Dunno if I am meant by "professor" -- if so - thanks for the promotion ;-)

    If you want to make classes extendable, you can either make an abstract method that you override in the subclasses (Template Method Pattern) or you can encapsulate the behaviour that may change and put that in a seperate class (Strategy Pattern).

    The Strategy Pattern is more flexible in general.

    I must admit that I have written code like the initial TaxPayer class before, with complicated if-else / switch statements. I have even, against my better judgement, copy and pasted classes.

    However, the Strategy and State patterns are great at converting terrible code like mine into code that is easier to extend.

    Look for example at AWT layout managers. Imagine that every time you wanted to change a layout manager, you had to use a different subclass of Panel. Your code would be really hard to maintain. In addition, the algorithm for doing a layout would be duplicated between Panel and Frame and ... As it is now, you can take a Panel class and apply a LayoutManager strategy to it, thereby changing the behaviour. With my design, I can apply different tax strategies to each tax payer, which you can't do so easily with the Template Method approach (i.e. abstract method that you are overriding)

    Kind regards

    Heinz
    --
    Dr. Heinz M. Kabutz (Maximum Solutions)
    Sun Java Champion
    Author of "The Java(tm) Specialists' Newsletter"
    http://www.javaspecialists.co.za
  76. Interfaces/Plugins[ Go to top ]

    Nor a "Generics specialist" --> Oxymoron?
    Obviously not. I do hope that was a joke!
    I don't trust the esteemed professor's coding talent if he even wrote code that had that many switch statements in it in the first place. Any programmer worth his salt would have done an abstraction layer way before then.
    That's true, however you do know that patterns emerge when people try to solve exactly from these sorts of problems. A programmer that makes mistakes is understandable; after all we all do or at least did do! A programmer that doesn't recognise them, on the other hand, is a problem.