Hacker News new | comments | ask | show | jobs | submit login

Let's try this advice. Say, we're solving Hanoi Towers [1]. So, we're going to have rods, and disks, and rods are going to have the number of disks on them, and disks are going to have size, and probably a reference to the disk underneath, and a reference to the disk on top, and maybe also weight and color... and by the end of the day instead of a 10-line snippet [2] we're going to have Enterprise Java Beans.

No, it doesn't mean that OOP is awful - it just means that this particular way of modeling a problem is a recipe for over-engineering.

Start with the simplest thing that works. That thing will probably be just a function. Grow it from there. If it gets too big, split it. If you find that you pass the same 12 parameters to a bunch of functions - factor out a class. If you do the same thing in a bunch of classes - abstract it out. Keep it DRY [3]. Keep it SOLID [4]. Rinse and repeat. This way you end up with a useful class hierarchy - and OOP won't be awful.

[1] http://en.wikipedia.org/wiki/Tower_of_Hanoi

[2] http://rosettacode.org/wiki/Towers_of_Hanoi

[3] http://en.wikipedia.org/wiki/Don't_repeat_yourself

[4] http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

I like your philosophy, but I think this counterexample is misleading. The Hanoi puzzle is an old favorite, largely because it lends itself to a surprisingly short, recursive solution. If your goal is merely to churn out the steps, then an OO implementation is easily mocked as overkill, but that's because you went into the implementation with the solution already worked out. If your intention was instead to build a program with a UI for playing around with the pieces, moving discs around willy-nilly and perhaps adding more rods, then Rod and Disc classes present themselves quite naturally. In this more real-world setting I think an OO design would be quite elegant and flexible.

Yes, this. Most of these, OOP is bad articles follow the same pattern of showing how an idiomatic object based decomposition doesn't do well on algorithmic problems that developers rarely deal with. They then leverage red herring and slippery slope to show that OOP is bad in general. FP similarly falls down on stateful interactive systems in the same grain, where an object-like system emerges in the end in any case.

Who doesn't go into the implementation with the solution worked out?

I think that's not the problem. I think it's just that different things have different levels of complexity, and your representation should match what you want to do.

There is a lot of "real world" computation where it makes more sense to do things the "mathy way" rather than representing them with objects.

>>Who doesn't go into the implementation with the solution worked out?

OOP, as Allan Kay envisioned it, is about making developing software a process of learning about what you are modeling. You are expected to naturally find the solution to your problem as you model it, not to have a worked up a solution you have to put into the code. With real-world sized problem, this approach gives good results. But, obviously, it can fail to find some great solutions. As is the case for the Hanoi problem: you can model it very well without finding the optimal solution to it. But the model still has some added usefulness.

This is exactly right. Alan Kay said something to the effect that the reason he invented OOP is because he hated algorithms (and data structures). Indeed, one of his criticisms of Java-style OOP is that, by using setters, it "turns objects back into data structures".

I think the point being made is that we use OOP to provide a natural abstraction of the real world to the end user. In this Towers problem: it would be like building the Towers game for an end user to play with - not solve it for the user.

I think that's a little too black and white back the other way.

Don't get me wrong, I live in python, I create classes on the odd occasion I need them and not before it's definitely required.

That said, there's nothing wrong with sitting down and modelling the problem you're trying to solve on paper to try to understand what's involved. You don't need to implement it that way. Whatever you do, stop and take a moment to think it through.

It's not philosophically wrong to model the problem upfront, it's just very hard to get it right in practice.

You don't literally have to start with one function. If you've solved a similar problem before you may have a good idea of what the code structure is going to be (this is what design patterns are all about). Frameworks may force a structure on you. There are shortcuts. But even then, I've been bitten more then once by the problems that looked awfully similar to what I've done before only to turn out to be very different at the end.

The thing that I keep finding myself wanting in Python is a more structured way to refer to data; fortunately, that's what namedtuple[1] is for.

    >>> DataType = namedtuple("DataType", ["field1", "field2"])
    >>> datum = DataType(1, "a")
    >>> datum
    DataType(field1=1, field2='a')
    >>> datum.field1
    >>> datum.field2
Keeps my code a bit more sensible than constantly indexing into tuples, imo.

[1]: http://docs.python.org/2/library/collections.html#collection...

It was personally strange to start programming in earnest with Python, and think namedtuples (or classes with __slots__) were so cool and efficient, and then learn C and just think "oh yeah. Structs."

What's really missing though is unions with destructuring `case`. Once you start coding in a language with proper unions, it's hard to go back. In python it might look something like this:

    DataType = union({ 'type1': ['field1', 'field2'], 'type2': ['field3'] })

    DataType.type1(val1, val2)

    # pretend syntax
    case datum:
      DataType.type1(a, b):
        doSomethingWith(a, b)

I think this is the right way to start learning OO. The difficulty with OO modelling though is that many of your classes are abstract ideas that don't have a real-world counterpart. How to group information into classes can be decidedly unintuitive. For this type of modelling it's better to group information into classes according to their lifecycle. Normally the only way you can really know this is to build the system and refactor as the lifecycles become more obvious.

On another note, the problem with the way OO, and really programming in general at the uni level, is taught is that it's always in the context of toy apps that aren't going to grow. This encourages an up front planning process and you can get away with it because all you have to do is make it work. You're only learning how to tell the computer what to do, not how to build a system that can adapt to a changing user base for instance. Perhaps it's necessary that you learn to just talk to a computer first and with experience learn to build growable systems. The problem though is that the upfront planning process is taught as _the_ way to build a system.

Your link to Rosetta Code reminded me how much I love Inform. http://rosettacode.org/wiki/Towers_of_Hanoi#Inform_7

I agree that the functional paradigm works very well for a problem like Hanoi. In fact, it's certainly very good for any type of operational/algorithmic challenge.

However, the question isn't just alluding to functional questions or algorithms. It's talking about designing a solution that can be used to manage multiple types of operations in a well organized manner.

Think: I want to change the colors of the tower pieces. I want to analyze them based on their properties. I want to attach meta information to them as I sort them. Perhaps I want to keep track of where they go over the course of their journey to the tower. Maybe I'm a particularly indecisive architect that wants to build 5 types of towers.

As you may imagine, it's possible to do this well in FP and in OOP. But the most likely best solution is a healthy mixture of both, to handle the true nature of problems that have verbs AND nouns.

I like your idea of what matter is what the program must do, and thus we must think firstly what will be the functions. I may be wrong, but once we have a 12 parameters function, it may be interesting to factor out to more than one class. If I do this factorisation as a no-brain, I will create a "FooParameter" class with 12 getter and setter. It will be better to stop and think of what will be the easier to read. Ie do some abstraction work:

    double getDistanceTravelled(Point[] relevedPositions)
instead of

    double getDistanceTravelled(double[] x, double[] y)

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact