Revision 11 not available (showing current revision instead)

proj-oot-ootOopNotes2

" Go is “OO-ish” with its use of interfaces — interfaces are basically duck typing for your structs (as well as other types, because, well, just because). I had some trouble at first understanding how to get going with interfaces and pointers. You can write methods that act on WhateverYouWant? — and an interface is just an assertion that WhateverYouWant? has methods for X, Y, and Z. It wasn’t really clear to me whether methods should be acting on values or pointers. Go sort of leaves you to your own devices here.

At first I wrote my methods on the values, which seemed like the normal, American thing to do. The problem of course is that when passed to methods, values are copies of the original data, so you can’t do any OO-style mutations on the data. So instead methods should operate on the pointers, right?

This is where things get a little bit tricky if you’re accustomed to subclassing. If your operate on pointers, then your interface applies to the pointer, not to the struct (value). So if in Java you had a Car with RaceCar? and GetawayCar? as subclasses, in Go you’ll have an interface Car — which is implemented not by RaceCar? and GetawayCar?, but instead by their pointers RaceCar?* and GetawayCar?*.

This creates some friction when you’re trying to manage your car collection. For example, if you want an array with values of type Car, you need an array of pointers, which means you have to need separate storage for the actual RaceCar? and GetawayCar? values, either on the stack with a temporary variable or on the heap with calls to new. The design of interfaces is consistent, and I generally like it, but it had me scratching my head for a while as I got up to speed with all the pointers to my expensive and dangerous automobiles. "

---

" The Common Lisp Object System (CLOS) has multiple-inheritance, multi-methods, method combinations, introspection and extensibility via the MOP, generic functions that work on builtin classes, support for dynamic instance class change (change-class, update-instance-for-changed-class) and class redefinition (defclass, update-instance-for-redefined-class), a semi-decent story for combining parametric polymorphism and ad hoc polymorphism (my own lisp-interface-library), etc. Racket seems to still be playing catch-up with respect to ad hoc polymorphism, and is lacking a set of good data structure libraries that take advantage of both functional and object-oriented programming (a good target is Scala's scalaz or its rival cats). "

---

keithnz 3 days ago [-]

I think a lot of bad things happened when the advice around how to determine classes started by looking at the nouns in the problem domain.

OO is fundamentally about messaging not abstract data types. So if you start your design from trying to determine ADTs instead of trying to work out the kinds of message conversations that need to go on you end up with mess of types.

In the wizards and warriors [1] we see a large amount of modelling of a domain with rules. But we, even at the end, still have little idea of what messaging is going to be going on, there is a hint about attacking werewolves. But we've already made a lot of assumptions about what our first class entites are. Often what can happen is we find, while we thought we modelled it ok and even sorted out a rule based system, it still seems difficult for our objects to have conversations.

maybe what would be better is some thing that can attack other things and wizards, weapons, and warriors are all simply modelled by some composable set of stat modifiers.

reply

aryehof 2 days ago [-]

The original advice was to use nouns to "identify candidate classes", rather than "determine classes".

Sadly when confronted with a problem, the majority of programmers can get no further than writing down lots of nouns, perhaps dozens of them, with no idea how to combine the few actually required into an object-oriented design.

OO isn't fundamentally about messaging. That is incorrectly assuming that object-orientation began with Smalltalk, Alan Kay and Dan Ingalls. Smalltalk's "messaging with objects, all the way down" approach largely ended with its popular use and the widespread adoption of Java. Java's object model is entirely based on Simula (James Gosling Sept 2017).

reply

---

"information: it is simple. The only thing you can possibly do with information is ruin it. :) ... Don't ruin it By hiding it behind a micro-language ie a class with information-specific methods thwarts generic data composition ties logic to representation du jour Represent data as data " ... Objects were made to encapsulate IO devices, so there's a screen, but I can't touch the screen, so I have the object...That's all they're good for. They were never supposed to be applied to information...it ruins your ability to build generic data manipulation things." -- Rich Hickey, Simple Made Easy talk

So, in oot, we want to make it so that we can have classes and yet still manipulate the values of the attributes in those classes just as easily as if it were a map in clojure

---

BruceIV? 49 days ago [-]

[on the Cforall team] FWIW, the Go docs are somewhat ambivalent on the OO nature of Go[1]. Along similar lines, our main objections to object-orientation are that, in "traditional" implementations like C++ or Java, it tightly couples a number of features that we believe would be better served by a more orthogonal design.

More specifically, C++-style OO couples (1) in-memory layout of types, (2) behaviour of objects, (3) encapsulation boundaries, and (4) the hierarchical "is-a" relationship. In Cforall, (1) and (3) are handled by the usual C mechanisms of struct types and translation-unit boundaries [we go to great effort to maintain C-style separate compilation, though we will likely build a better namespace/module system at some point], (2) by traits, and (4) by a yet-to-be-implemented system of RTTI for specific "inherited" types [likely when the undergrad RA who started our exceptions implementation comes back as a Master's student this fall].

As you mention, many use-cases (including widgets in GUIs, but also abstract syntax trees in compilers) require some sort of heterogeneous collection type to work properly, and for this OO is the right model. We just don't want to force the entirety of that model on every use case, so we can just take traits when we want to write a polymorphic function over related types or an ADT like "Set" which requires its keys be sortable, or just take RTTI for exception handling, when the set of exception types we're handling is known statically, but we need to determine if the thrown exception inherits from one of the caught types.

[1] https://golang.org/doc/faq#Is_Go_an_obje

---

gbrown 2 days ago [-]

...You can still do (several types) of object oriented programming in R,...

mr_toad 2 days ago [-]

A sane language shouldn’t need three different object systems.

reply

gbrown 1 day ago [-]

Meh, S3 is nice and lightweight for a very particular kind of analysis interoperability. S4 isn't super useful IMHO. RC is very well thought out, and I've heard good things about R6. It might not be sane language design, but it works well for designing very different kinds of analytical procedures.

reply

---

losteric 7 minutes ago [-]

Is it unreasonable to think of the method as a semantic "port" to which messages (arguments) are passed?

---

revvx 2 hours ago [-]

> Isn't a method call a message, and the return value a message back?

It is!

...

Alan Kay uses the term "late binding". In Kay's opinion, "extreme late binding" is one of the most important aspects of his OOP [1], even more important than polymorphism. Extreme late binding basically means letting the object decide what it's gonna do with a message.

This is what languages like Objective-C and Ruby do: deciding what to do after a method is dispatched always happen during runtime. You can send a message that does not exist and have the class answer to it (method_missing in Ruby); you can send a message to an invalid object and it will respond with nil (Objective-C, IIRC); you can delegate everything but some messages to a third object; you can even send a message to a class running in other computer (CORBA, DCOM).

---

" Why OO Sucks by Joe Armstrong ((the Erlang guy))

Objection 1. Data structure and functions should not be bound together. Since functions and data structures are completely different types of animal it is fundamentally incorrect to lock them up in the same cage.... In most languages...To understand functions you have to understand the order in which things get done...Data structures...are intrinsically declarative

...

Objection 2. Everything has to be an object. Consider “time”. In an OO language a “time” has to be an object...But in a non OO language a “time” is a instance of a data type. For example, in Erlang there are lots of different varieties of time, which can be clearly and unambiguously specified using type declarations... -deftype day() = 1..31. -deftype month() = 1..12.

...

Objection 3. In an OOPL data type definitions are spread out all over the place. In an OOPL data type definitions belong to objects. So I can't find all the data type definition in one place. In Erlang or C I can define all my data types in a single include file or data dictionary.

...

Lisp programmers have know for a long time it is better to have a smallish number of ubiquitous data types and a large number of small functions that work on them, than to have a large number of data types and a small number of functions that work on them.

Objection 4. Objects have private state. State is the root of all evil. In particular functions with side effects should be avoided.

The “hide the state from the programmer” option chosen by OOPLs is the worst possible choice. Instead of revealing the state and trying to find ways to minimise the nuisance of state, they hide it away. " -- [www.cs.otago.ac.nz/staffpriv/ok/Joe-Hates-OO.htm]

---

..."I wrote a an article, a blog thing, years ago - Why object oriented programming is silly. I mainly wanted to provoke people with it. They had a quite interesting response to that and I managed to annoy a lot of people, which was part of the intention actually. I started wondering about what object oriented programming was and I thought Erlang wasn't object oriented, it was a functional programming language.

Then, my thesis supervisor said "But you're wrong, Erlang is extremely object oriented". He said object oriented languages aren't object oriented. I might think, though I'm not quite sure if I believe this or not, but Erlang might be the only object oriented language because the 3 tenets of object oriented programming are that it's based on message passing, that you have isolation between objects and have polymorphism. " -- https://news.ycombinator.com/item?id=19716258

---

tux1968 3 hours ago [-]

Isn't a method call a message, and the return value a message back? Or is it that "true OO" must be asynchronous?

reply

randomdata 28 minutes ago [-]

I think the spirit of OO, an object has agency over how the message is interpreted in order for it to be considered a message. If the caller has already determined for the object that it is going to call a method then the object has lost that agency. In a 'true OO' language an object may choose to invoke a method that corresponds to the details within the message, but that is not for the caller to decide.

Consider the following Ruby code:

    class MyClass
      def foo
        'bar'
      end
    end
    class MyClass
      def method_missing(name, *args, &block)
        if name == :foo
          return 'bar'
        end
        super
      end
    end

---

losteric 7 minutes ago [-]

Is it unreasonable to think of the method as a semantic "port" to which messages (arguments) are passed?

And languages that allow programmers to bypass OO with jmp instructions seem multiparadigm rather than not-OO...

reply

---

What is the difference between Alan Kay's definition of OOP and Carl Hewitt's Actor Model?

Alan Kay Alan Kay, Had something to do with "Object-Oriented Programming" Answered Feb 13, 2018 · Author has 289 answers and 2.3m answer views

Not a lot of difference.... -- https://www.quora.com/What-is-the-difference-between-Alan-Kays-definition-of-OOP-and-Carl-Hewitts-Actor-Model

---

"

> Objection 1. Data structure and functions should not be bound together ... > Objection 2. Everything has to be an object. ...

Also, most OO langs make a big ceremony out of each new type: create the class file, create the test file, blah blah blah. I want types to be cheap so I can make them easily and capture more meaning with less work. "

"

-- https://news.ycombinator.com/item?id=19715778

---

" Why inheritance never made any sense Graham / March 16, 2018 / OOP

There are three different types of inheritance going on.

    Ontological inheritance is about specialisation: this thing is a specific variety of that thing (a football is a sphere and it has this radius)
    Abstract data type inheritance is about substitution: this thing behaves in all the ways that thing does and has this behaviour (this is the Liskov substitution principle)
    Implementation inheritance is about code sharing: this thing takes some of the properties of that thing and overrides or augments them in this way. The inheritance in my post On Inheritance is this type and only this type of inheritance.

These are three different, and frequently irreconcilable, relationships. Requiring any, or even all, of them, presents no difficulty. However, requiring one mechanism support any two or more of them is asking for trouble.

A common counterexample to OO inheritance is the relationship between a square and a rectangle. Geometrically, a square is a specialisation of a rectangle: every square is a rectangle, not every rectangle is a square. For all s in Squares, s is a Rectangle and width of s is equal to height of s. As a type, this relationship is reversed: you can use a rectangle everywhere you can use a square (by having a rectangle with the same width and height), but you cannot use a square everywhere you can use a rectangle (for example, you can’t give it a different width and height).

Notice that this is incompatibility between the inheritance directions of the geometric properties and the abstract data type properties of squares and rectangles; two dimensions which are completely unrelated to each other and indeed to any form of software implementation. We have so far said nothing about implementation inheritance, so haven’t even considered writing software.

Smalltalk and many later languages use single inheritance for implementation inheritance, because multiple inheritance is incompatible with the goal of implementation inheritance due to the diamond problem (traits provide a reliable way for the incompatibility to manifest, and leave resolution as an exercise to the reader). On the other hand, single inheritance is incompatible with ontological inheritance, as a square is both a rectangle and an equilateral polygon. " -- [2]

---

"are es6 classes just syntactic sugar for the prototypal pattern in javascript?

Yes, perhaps, but some of the syntactic sugar has teeth...Less sugary is that class declarations and methods are always executed in strict mode, and a feature that gets little attention: the .prototype property of class constructor functions is read only: you can't set it to some other object you've created for some special purpose...

---

" Dynamic dispatch mechanism of OOP

Existential types in conjunction with type classes can be used to emulate the dynamic dispatch mechanism of object oriented programming languages. To illustrate this concept I show how a classic example from object oriented programming can be encoded in Haskell.

 class Shape_ a where
   perimeter :: a -> Double
   area      :: a -> Double
 
 data Shape = forall a. Shape_ a => Shape a
 
 type Radius = Double
 type Side   = Double
  
 data Circle    = Circle    Radius
 data Rectangle = Rectangle Side Side
 data Square    = Square    Side
 
 
 instance Shape_ Circle where
   perimeter (Circle r) = 2 * pi * r
   area      (Circle r) = pi * r * r
 
 instance Shape_ Rectangle where
   perimeter (Rectangle x y) = 2*(x + y)
   area      (Rectangle x y) = x * y
 
 instance Shape_ Square where
   perimeter (Square s) = 4*s
   area      (Square s) = s*s
 
 instance Shape_ Shape where
   perimeter (Shape shape) = perimeter shape
   area      (Shape shape) = area      shape
 
 
 --
 -- Smart constructor
 --
 
 circle :: Radius -> Shape
 circle r = Shape (Circle r)
 
 rectangle :: Side -> Side -> Shape
 rectangle x y = Shape (Rectangle x y)
 
 square :: Side -> Shape
 square s = Shape (Square s)
 
 shapes :: [Shape]
 shapes = [circle 2.4, rectangle 3.1 4.4, square 2.1]

(You may see other Smart constructors for other purposes). " -- [3]

---

"An object is a variable of an abstract data type consisting of private data (its state) and procedures that operate on this data." -- https://cseweb.ucsd.edu/~wgg/CSE131B/oberon2.htm

---

HN discussion on OOP:

https://news.ycombinator.com/item?id=23192264

i just skimmed the first few comments. The only thing i got out of it so far is Implementation Inheritance Considered Harmful. ( https://news.ycombinator.com/item?id=23197753 , and a lot of +1 replies to that; many dislikes inheritance hierarchies; one or two recommend interface but not implementation inheritence)

some say that information hiding is good. One guy likes polymorphism.

one guy mentions the wording "data-with-associated-functions, encapsulation"

“OOP consisted of three major ideas: classes that defined protocol and implementation, objects as instances of classes, and messages as the means of communication.”

an example of why ppl dislike hierarchies:

" A (non-satirical) illustration is in the infamous “TDD Sudoku” series of blog posts (follow the links from http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-s... or https://news.ycombinator.com/item?id=3033446) where (in contrast to Norvig's program which just solves the problem) the TDD/OOP proponent ends up with a “class Game”, “class Grid”, “class Cell”, “class CellGroup”?