

Awful Programming Advice - lackbeard
http://bramcohen.livejournal.com/69753.html

======
tptacek
I think it's a bit skeevy to start an article with "a square is not a subclass
of a rectangle is not a subclass of a polygon" and end with "and maybe that's
why Tornado couldn't use Twisted Python".

~~~
statictype
I think his point was that having a simple and clean design would make the
software easily adoptable.

What's wrong with that?

~~~
tptacek
Because things should be as simple as they can be, and no simpler. He made a
case for simplifying square -> rect -> poly. He made no such case for Twisted,
but still tarred them with the same brush.

------
strlen
That's a very interesting thought and I have a gut feel he's onto something.

Last two times I used subclasses were in case of a C++ library that was
designed very much like twisted (except it used threading a great deal more):
there were events coming from epoll() and going to a pool of worker threads.

I subclassed this framework to create my own asynchronous network server.
However, that got me thinking: wouldn't this have been better implemented
using callbacks?

The other time I've used subclassing was in Java with the "decorator" pattern:
I needed to extend the functionality of object foo, while still allowing any
subclasses of foo to behave as they normally would. However, the Scala
approach to this (mixing in traits) seems a great deal more elegant.

------
xsmasher
Classes (and OOP) are there to help you, and they apply to a specific set of
problems - use them where they help, and don't when they don't.

I just finished a game with monsters, soldiers, snipers, movable barricades,
etc. Someone who's class-crazy would probably make a soldier class that
inherits from a generic "entity" class, ditto for each monster type, etc - I
don't think that's efficient, I wind up with too many files and too much
repetition. Instead I built a single "character" class with a constructor that
takes a "type" - monster, soldier, etc - and drive behavior of each method
with "if" statements where required.

I'm sure some purist is having heart strictures right now, but I'm not writing
an API - I'm working in a living structure where the map format and drawing
format may change from day to day, and I don't want to make updates in half a
dozen files if the rules for aiming change. I want a single "aim" method that
behaves differently based on type.

I subclass system objects all the time of course, but like the author I rarely
subclass my own objects. Am I being pragmatic or foolish?

~~~
Nwallins
> _but I'm not writing an API - I'm working in a living structure where the
> map format and drawing format may change from day to day, and I don't want
> to make updates in half a dozen files if the rules for aiming change._

I find that I am always writing APIs, and it's not always clear which is going
to be 'public' or 'private'. That is, I generally work bottom-up, and my
lower-level classes present a sensible API that I can work with directly, e.g.
in irb. This makes the design of higher-level classes easier, if I've done the
low-level API correctly.

> _I want a single "aim" method that behaves differently based on type._

Hm, you mean like _char.aim_? Where char may be a Monster, Soldier, or ?

~~~
xsmasher
>I find that I am always writing APIs, and it's not always clear which is
going to be 'public' or 'private'.

I understand the sentiment, and I believe in SOLID principles. I just mean
that I'm not building a library that other people will use. No one is ever
going to subclass my "player" class, not even me. Unlike my sound or graphics
or AI code it's unlikely to be reused even in another game.

>Hm, you mean like _char.aim_? Where char may be a Monster, Soldier, or ?

Yes. My "aim" method is 90% identical for all types, about 10% specific to the
type - if(type==monster){do this}; if(type==soldier){do that}

I've heard "if you're using if statements like this you're probably not using
OOP correctly", but in my case I don't want six nearly identical methods
spread out in six class files. That's repeating myself, which is the real sin
I'd rather avoid; it comes back to haunt me if the map format or some other
data structure changes.

------
huhtenberg
> _if Twisted followed this example straightforwardly .. then Tornado would
> never have been written._

The only reason Tornado came about is that it is far more interesting to
_write_ your own code than to _learn_ someone else's. It has very little to do
with whether Twisted was designed well or not.

------
davidmathers
The referenced blog post: <http://news.ycombinator.com/item?id=822354>

------
ilyak
I think he's right.

If you end up thinking about non-trivial tree of classes, like shape-circle-
oval, square-rect-polygon, triangle - you're doing it wrong! I don't know why,
but it just does never seem to work. You can generalize it to a polygon, tho,
and it would work.

What you really want from subclassing is interfaces (Set and List come to mind
immediately) and civilized monkey-patching (you have a class, you want some of
its behavior changed, so you override a method or two).

~~~
joe_the_user
Excellent point,

It's worth having Objects represent a particular hierarchy of characteristics
that you would like to concentrate on and to allow other characteristics be
represent by containment and list objects. I've programming in c++ w/ QT
lately and it seems like it actually has most of what I've gotten used to in
Ruby if I represent a significant amount of the data structures with hash and
list templates rather than trying to represent everything with the class
construct.

