How can I avoid switch or chained ifs, if I don't want to subclass for design reasons?
Specifically, in my model I have already a type hierarchy consisting of a few classes that implement an interface. The interface represents a relation between two nodes and the classes represent different types of relations.
Another class that does SQL generation has a list of relations and wants to do different things based on the type of relation. I could, of course, put the code inside the relation classes. That is undesirable for two reasons though:
1) Separation of concerns dictates that my model classes should not care that at some point SQL is generated for them. (Admitedly a puristic stand.)
2) More practical: I have different strategies to generate SQL for the same relation. So there's a 1-n mapping from model class to SQL generation. I also want to be able to dynamically change the strategy for testing purposes.
I think, the decorator pattern is the solution here. What I can't figure out, though, is how to dymanically add the right SQL generation decorator to a relation class, without writing a whole bunch of code.
PS: The code is Java and I use Spring for dependency injection.
just wanted to mention that the post has no title and the link to the slides points to the previous talk (same goes for the Slides link on your blog btw)
...and look at Haskell and ML. Everything you talk about can and should be done... WITHOUT subtyping. Subtyping is fundamentally broken... because of the fragile base class problem. http://en.wikipedia.org/wiki/Fragile_base_class
Haskell and ML style programming does not have NULL (unless you explicitly want NULL.. and then the type checker forces you to handle the NULL case). Haskell has the ability to get rid of ifs through ad-hoc polymorphism through typeclasses.
Also, the "case" statement is very powerful in Haskell and ML... much more so than in OOP languages. It makes sure that all cases are covered... and that you cannot use data that is not to be used (as you talk about with your Leaf and Node case).
How can I avoid switch or chained ifs, if I don't want to subclass for design reasons?
ReplyDeleteSpecifically, in my model I have already a type hierarchy consisting of a few classes that implement an interface. The interface represents a relation between two nodes and the classes represent different types of relations.
Another class that does SQL generation has a list of relations and wants to do different things based on the type of relation. I could, of course, put the code inside the relation classes. That is undesirable for two reasons though:
1) Separation of concerns dictates that my model classes should not care that at some point SQL is generated for them. (Admitedly a puristic stand.)
2) More practical: I have different strategies to generate SQL for the same relation. So there's a 1-n mapping from model class to SQL generation. I also want to be able to dynamically change the strategy for testing purposes.
I think, the decorator pattern is the solution here. What I can't figure out, though, is how to dymanically add the right SQL generation decorator to a relation class, without writing a whole bunch of code.
PS: The code is Java and I use Spring for dependency injection.
hi,
ReplyDeletejust wanted to mention that the post has no title and the link to the slides points to the previous talk (same goes for the Slides link on your blog btw)
Great talk. Could you provide the code how to implement toString with parentheses only when needed? I am lost...
ReplyDeletePlease please please... consider functional programming.
ReplyDeletePlease please please... look at:
http://en.wikipedia.org/wiki/Tagged_union
http://en.wikipedia.org/wiki/Type_class
...and look at Haskell and ML. Everything you talk about can and should be done... WITHOUT subtyping. Subtyping is fundamentally broken... because of the fragile base class problem.
http://en.wikipedia.org/wiki/Fragile_base_class
Haskell and ML style programming does not have NULL (unless you explicitly want NULL.. and then the type checker forces you to handle the NULL case). Haskell has the ability to get rid of ifs through ad-hoc polymorphism through typeclasses.
Also, the "case" statement is very powerful in Haskell and ML... much more so than in OOP languages. It makes sure that all cases are covered... and that you cannot use data that is not to be used (as you talk about with your Leaf and Node case).