in reply to I dislike object-oriented programming in general

Well, you make several good points, but as with anything good in life (sex, drugs, rock-n-roll, you name it), it is best when it is in moderation. OOP is just one of the paradigms you should be using in your code. Anyone who tells you different is usually a first year CS student who just finished thier first "Intro to Java" class and can be safely ignored. Also, first class functions != functional programming, there is a very long history of first class functions/blocks in OOP (see Smalltalk). FP is a much deeper mindset which goes beyond just "functions as data".

You should really look into some of the newer thinking around OO, and even some of the older, but less mainstream, thinking as well.

For instance, roles (and the original concept of Traits) goes a long way towards helping modular decompositon in OO not be so "entity" centric. You might be interested in this talk I just gave on Moose::Role at the Pittsburg Perl Workshop this weekend. Towards the end of the slides it gives a number of examples of how roles can provide features that that a class "does" where an "isa" relationship just wouldn't make any sense.

You should also look into some of the more multi-paradigm languages like Scala and OCaml, both of which provide an excellent hybrid of OO and functional paradigms.

And lastly, OOP != Java/C#/C++ there are some really nice OO systems out there in which modeling is not so "entity" centered. Take CLOS for instance, it uses generic functions and classes, so that behavior is very clearly seperated from state. There are many Scheme OO systems which expand on the CLOS concepts too. There is also prototype basesd OO, which also leads to very different modeling approaches.

However, I'm slightly worried about the approach taken in Perl 6 ...

Fear not, it might be OO under the hood, but this wont stop you from ignoring it's OO-ness as much as you want. And as for efficiency, let the compiler writers worry about that :)

-stvn
  • Comment on Re: I dislike object-oriented programming in general

Replies are listed 'Best First'.
Re^2: I dislike object-oriented programming in general
by dragonchild (Archbishop) on Oct 17, 2007 at 20:39 UTC
    You forgot to mention Self and its more popular cousin Javascript. JS is more OO than Ruby, but it doesn't have the concept of a class.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      I'm curious. In your view, on what basis is JS more OO than Ruby? If anything I'd say that it was the other way around. (Note that both are far more OO than Perl.)

      For example in Ruby if you sort an array of numbers, it defaults to sorting them as numbers. In JavaScript it defaults to sorting them alphabetically, no matter what their types are.

      For another example, in Ruby I can trivially add a new method to Integer, and then call my new method on the integer 5. In JS it works, but much less consistently. This works:

      Number.prototype.foo = function () {alert("Hi!")}; x = 5; x.foo();
      But this doesn't (at least not in Firefox):
      Number.prototype.foo = function () {alert("Hi!")}; 5.foo();
      That isn't what I expect from a completely object-oriented language!

      Furthermore the OO hooks in Ruby are much more pervasive than in JavaScript. For instance I once tried to write a fairly efficient factorial function in Ruby. I found that it was more efficient than the routine to convert big integers to strings! So I replaced the routine to convert big integers to strings.

      I wouldn't even dream of messing around in the internals like that in JavaScript.

        The reason why that doesn't work is a legacy error in the ECMAScript standard. By following a numeral with a dot, the parser expects that you're defining a floating-point value, rather than an integer. You can still call methods on it, however, if you disambiguate by wrapping it in parentheses first.
        (5).foo();
          A reply falls below the community's threshold of quality. You may see it by logging in.
        ++tilly for proving a surprising (to me, at least) example of where JS's object modeling goes wrong.

        Personally, I think javascript's object model is cleaner than ruby's, but its prototype model seems quite alien when you're coming from a language that distinguishes classes and objects and for some reason javascript tries so very hard to hide that fact by stuffing so much niceness behind so many ugly constructs (for instance, when you've understood the JS model of inheritance, the new constructor() special operator and all it entails no longer makes any sense at all)

        You're absolutely correct in your examples. The implementations of Javascript do not provide proper autoboxing. This isn't that surprising, given Javascript's history and the browser wars.

        What I was referring to was Javascript's prototype-based (vs. class-based) OO. I find that you can easily build classes on top of prototype, but you can't build prototype on top of classes as easily. I can't imagine how I'd build a prototype OO system in Ruby. There's a dozen really decent implementations in Javascript of a class system.


        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        (5).foo(); works, at least here using firebug It is reasonable that parenthesis are required, as 5. makes the tokenizer think about floats and it is legal syntax. I have not checked the standard, though.
Re^2: I dislike object-oriented programming in general
by vrk (Chaplain) on Oct 18, 2007 at 15:38 UTC

    And lastly, OOP != Java/C#/C++

    I deliberately tried to steer away from any particular programming language, but if you received the expression that I'm talking about those three, my apologies. The concerns I have about OOP goes beyond single versus multiple inheritance, static versus "dynamic" typing, calling methods versus sending messages, etc. The point was not to compare programming languages, but to explain why the means of abstraction and combination in pure object-oriented thinking do not appeal to me in general.

    FP is a much deeper mindset which goes beyond just "functions as data".

    I should know, having been a FP fanatic... My "functions are modules" argument doesn't mean first class functions or doesn't even presuppose functional programming. What I mean by "passing modules as arguments" is trying to be a generalization of what you can do in different programming languages. It might be implemented as being able to pass function pointers (C); or function names (ALGOL); or function references (Pascal). It might be implemented as passing closures (e.g. Scheme, Haskell, Perl, and too many languages to list); or passing objects; or doing something exotic.

    The point is that you can parameterize what code does as well as which state it starts the computation from ("non-module" parameters such as numbers and strings).

    And as for efficiency, let the compiler writers worry about that

    But it's not even a concern for me... To me, a programming language is foremost a notation with which and in which to express ideas, usually algorithms. That we have machines that can use text written in the notation to do something is just a bonus. (Rather nice bonus, I must say.) This stand is partially hypochritical, but I can live with it.

    If I am worried about pervasive OO thinking in Perl 6, it's because frequently I don't want to think in terms of objects. There are no "efficiency" worries -- I already know there are efficient implementations for message-passing, delegation, virtual function tables, and what-have-you that goes with implementing these things. Just take a look at C++ or OCaml.

    The concept of roles resembles Objective-C protocols, though with being able to define not only which functions the implementing class needs to provide but also some common functions that all classes implementing the role "inherit". However, this would again be a much more useful technique to think about if there was no mandatory link to objects and classes! (That's just me.)

    I'll install Moose::Role some rainy day, I promise.

    --
    print "Just Another Perl Adept\n";

      I deliberately tried to steer away from any particular programming language, but if you received the expression that I'm talking about those three, my apologies.

      Well, it just seemed to me (and I may have read in between the lines too heavily and I apologize in advance if that is so), that much of what you were talking about were problems with particular OO implementations and the more idiomatic usage of said OO implementations. For instance, in CLOS programming it is not uncommon to have many plain vanilla functions (and macros) along with the classes and generic functions. The same can be said of much Javascript and C++ programming as well. It is only languages like Java which do not allow vanilla functions/subroutines to exist that the "pure OO" approach tends to win out (mostly because there is no other choice).

      The point was not to compare programming languages, but to explain why the means of abstraction and combination in pure object-oriented thinking do not appeal to me in general.

      Well, I think it is very hard to discuss abstract OO thought without at some point coming back down to the language level. Every OO system has it's own set of rules and therefore has its own set of limitations, and some systems contradict or are in direct conflict with one another. A "pure OO" system which is not tied to any language would need to be defined before it can be discussed. As for discussing the merits of the parts of OO like abstraction, polymorphism, encapsulation, modularization, etc etc etc, that discussion too will eventually need to come back down to a particular implementation for all the same reasons.

      My point is basically that there is not such things as "pure object oriented thinking" which is 100% language agnostic.

      My "functions are modules" argument doesn't mean first class functions or doesn't even presuppose functional programming.

      I am a little confused by what you mean when you say "functions as modules", this makes me think of the Standard ML module system and functors in particular. A function being a function which takes a module as an argument and returns a new module. Is this what you are refering too? If not then I am totally confused by your use of the word "module". Please expand.

      If I am worried about pervasive OO thinking in Perl 6, it's because frequently I don't want to think in terms of objects.

      This is exactly my point, you wont have to think it objects if you dont want too. This is a stated design goal of Perl 6.

      The concept of roles resembles Objective-C protocols, though with being able to define not only which functions the implementing class needs to provide but also some common functions that all classes implementing the role "inherit".

      No, that is totally wrong actually. Obj-C protocols are pretty much the same as Java interfaces, and therefore are about as use{ful,less}. Roles (optionally) provide an implementation as well as just abstract interfaces. This makes them more akin to mix-ins or multiple inheritance. However, unlike mixins or MI, roles are actually composed into the class (in perl we do this with symbol table operations to copy from the role package into the class the role is being composed into) which means there is no inheritance relationship between the role and the class. There is also a strict set of rules by which roles are composed into classes, which makes for highly predictable behavior, whereas MI and mixins are much more difficult to predict behavior-wise.

      However, this would again be a much more useful technique to think about if there was no mandatory link to objects and classes!

      Well actually, they don't have to be linked to objects and classes at all. Roles are very similar the OCaml/SML module systems in that they can be used to compose a non-OO module just as easily as they can be used to compose classes. In fact, I have one specific usage of roles which uses pure roles as "function groups" which can be composed together (following the rules of role compositition) and are then used as "function groups" and never actually composed into classes/objects.

      I'll install Moose::Role some rainy day, I promise.

      You won't like it because it comes with the entire Moose object system. And that is deep down OO to the core, complete with metaclasses and all that fun OO-over-abstraction you seem to really dislike. In fact it is a meta-circular object system so it is actually OO that is implemented in OO. Which I am sure just makes you cringe :)

      So, in conclusion, I think you have many good points, but your anti-OO stance seems to me to be somewhat reactionary to the pro-OO zealots. All good programmers know that silver bullets don't exist and in the end you just need good tools to get the job done. Those tools may be OO-based, they may be full of FP madness, or they may be a crusty CPAN module from the mid-90s like FindBin that sucks horribly but (for the most part) works when you need it to so you just use it and move on with your life. The moment you exclude any of those tools on some philisophical, moral or religious basis, you are really just adding more work for yourself.

      -stvn

        I am a little confused by what you mean when you say "functions as modules", this makes me think of the Standard ML module system and functors in particular. A function being a function which takes a module as an argument and returns a new module. Is this what you are refering too? If not then I am totally confused by your use of the word "module". Please expand.

        This is one part where I think it is essential to take a step back and forget everything you know about any programming languages you have learned.

        The problem here is that both module and function are highly overloaded concepts. Sometimes modules are building blocks as in other engineering disciplines, sometimes they are an abstraction mechanism, sometimes they are a particular way in your programming language to encapsulate functionality, ... Similarly functions could be procedures, methods, subroutines, lambda expressions, or mathematical functions (which could be mappings or relations), or what have you. Let's forget all about that, too.

        Actually, let's give a new name for the concept.

        Let gob have the following meaning: Any particular functionally sensible piece of program text that has a well-defined interface through which it can be used and with which it can be connected to other gobs.

        Given this meaning, a computer program is a gob: it accepts some input and produces some output. (If you want, the input and output can be partially or completely the global state of the machine.) A computer program can be connected to other gobs through its input and output.

        A class in object-oriented programming is a gob: the well-defined interface is the public methods, and these are used when connecting the class to other classes (gobs).

        A module in, say, Perl, is a gob: whether it is object-oriented, functional, or a collection of procedures, it has some interface through which it can be used. The interface can again be used to connect it to other gobs.

        A function/routine/subroutine/procedure is a gob: the interface to a function is the parameters it accepts (the input) and the return values (the output). (If you want, it may also partially affect the (global) state of the machine, i.e. work through side-effects.) The interface can, again, be used to connect this gob to other gobs.

        This is what I mean. At a very high level, all current programming paradigms let you create gobs and pass gobs as parameters to other gobs. How gobs are implemented in your particular programming language is not relevant; the concept is! Gob is the quintessential Lego block of programming, if you want.

        Suppose you have that small statistical analysis framework. One gob abstracts the control: it takes in data in some form, processes the data chunk by chunk by giving it to another gob (supplied by user), which returns a value, and the value is given to a third gob (supplied by user) along with the ID number of the data chunk. The user provides such a pair of gobs that they work well together (the latter understands the output format of the former), and the framework is completely agnostic to what kind of data these two gobs pass around; it just connects the gobs together and provides them with small pieces of data.

        How you might implement this could be with three classes: one for control, another for data analysis, and a third for data collection or plotting.

        Or you could implement the control as a function that takes two closures as parameters.

        Or you could implement the control as a function that takes two objects as parameters.

        Or...

        In a word, this is what I mean with gob.

        (As an aside, gob is an actual word.)

        --
        print "Just Another Perl Adept\n";

      Regarding Perl 6, giving you access to everything via objects/classes does not mean requiring you to write everything as objects/classes. I like OO because it provides a simple and effective way to encapsulate data, even provides for encapsulating code, and provides convenient namespaces to avoid name collisions (encapsulating names).1

      Sure, many (perhaps most) authors trying to teach OO certainly make too big of a deal of inheritance (and don't teach the pitfalls of overuse of it). And I can see your concern about people trying to make too many or the wrong classes trying to identify the "objects" they are dealing with.

      But I don't think "the Larrys" are newbie OO fanboys so I don't expect them to make stupid OO design mistakes. And I don't see the downside to having a unifying "framework" for providing convenient access to methods and attributes of internal components. And the Larrys certainly don't appear to have drunk the "OO koolaid" of the Java designers, trying to deny coders the ability to design in paradigms other than OO. Quite the opposite.

      1 Yes, I know about the problems with name collisions in the face of inheritance. I don't use that type of inheritance much and you shouldn't have to either.

      - tye        

        But I don't think "the Larrys" are newbie OO fanboys so I don't expect them to make stupid OO design mistakes.

        Not the stupid newbie OO design mistakes. Maybe some subtle ones, but hopefully not.