Skip to main content
36 events
when toggle format what by license comment
Apr 26 at 6:39 history edited JacquesB CC BY-SA 4.0
deleted 9 characters in body
Apr 26 at 6:32 history edited JacquesB CC BY-SA 4.0
deleted 1 character in body
Apr 26 at 6:25 history edited JacquesB CC BY-SA 4.0
added 1076 characters in body
Jun 16, 2020 at 10:01 history edited CommunityBot
Commonmark migration
May 2, 2017 at 12:52 history edited JacquesB CC BY-SA 3.0
deleted 37 characters in body
S May 2, 2017 at 9:29 history suggested Søren D. Ptæus CC BY-SA 3.0
corrected grammar and typos;
May 2, 2017 at 9:26 review Suggested edits
S May 2, 2017 at 9:29
May 1, 2017 at 20:52 comment added candied_orange @Giorgio correct on all counts. What this design needs is an Entertainment abstraction that can accept either stereo or bicycle. Of course next they'll want tunes while biking but lets wait till they ask for that.
May 1, 2017 at 20:46 comment added Giorgio @JacquesB: Well, I do not think that anyone wants to turn a stereo into a bicycle. If you bought a stereo and it turns out you needed a bicycle, you put the stereo aside and go buy a bicycle. This would again speak in favour of OCP: do not try to change a component into something completely different. Rather, remove the old component and write a new one.
May 1, 2017 at 18:29 comment added JacquesB @CandiedOrange: Good call, I have rewritten to make that part a bit clearer. My point is just that in reality you cannot modify any kind of behavior through extension, so you sometimes might end up having to rewrite whole components to get desired behavior. E.g. a stereo is designed to have replaceable speakers, but you cannot easily turn it into a bicycle.
May 1, 2017 at 18:20 history edited JacquesB CC BY-SA 3.0
added 218 characters in body
May 1, 2017 at 17:56 comment added candied_orange Where this answer lost me was here: "can't modify the behavior of a component". No. When you extend a class you most certainly modify it's behavior. What you don't modify is it's code. Finding a way to modify behavior without modifying code is the POINT of OCP. It lets you accommodate change by simply writing new code and plugging it into old code. I like being able to buy stereo equipment without being forced to buy new speakers. Don't you?
S May 1, 2017 at 14:01 history suggested Peter Mortensen CC BY-SA 3.0
Copy edited (ref. <https://en.wikipedia.org/wiki/Open/closed_principle> and <http://en.wikipedia.org/wiki/.NET_Framework>). Expanded.
May 1, 2017 at 13:53 review Suggested edits
S May 1, 2017 at 14:01
May 1, 2017 at 9:40 comment added Jörg W Mittag @Giorgio: Exactly. The thing that makes Common Lisp multimethods solve the EP is actually not multiple dispatch. It is the fact that the methods are open. In typical FP (or procedural programming), the type discrimination is tied to the functions. In typical OO, the methods are tied to the types. Common Lisp methods are open, they can be added to classes after the fact and in a different module. That's the feature that makes them usable for solving the EP. For example, Clojure's protocols are single dispatch, but also solve the EP (as long as you don't insist on static safety).
May 1, 2017 at 9:22 comment added Giorgio Adding a new type means implementing all operations for it. Both extensions can be done in a separate module. On the other hand, with the visitor pattern, the types are tied in the interface of the visitor, and the operations for the new types MUST be added to the existing implementations of the visitor. Good point!
May 1, 2017 at 9:20 comment added Giorgio @JörgWMittag: I knew the background about the expression problem (OOP versus FP) but I hadn't looked any deeper into the visitor pattern, thanks for the explanation. I superficially assumed that the visitor pattern does solve the expression problem because (1) multimethods (multiple dispatch) do and (2) the visitor pattern is a way to emulate multiple dispatch. If I understand correctly, there is more to it: with multimethods neither types nor operations are tied to a specific module / class: adding an operation means adding a defgeneric and then implementing the operation for all types.
May 1, 2017 at 6:57 history edited JacquesB CC BY-SA 3.0
added 1150 characters in body
May 1, 2017 at 6:47 history edited JacquesB CC BY-SA 3.0
added 1150 characters in body
May 1, 2017 at 1:18 comment added Jörg W Mittag … and types into methods (i.e. operations). Which means that you now can add operations easily but no longer types. You haven't solved the expression problem, you have only turned it 90°.
May 1, 2017 at 1:16 comment added Jörg W Mittag @Giorgio: The Expression Problem says that it's hard to design kinds of data and operations on those kinds in such a way that you can add both new kinds and new operations. In "traditional" OO it is easy to add new kinds by subclassing, but adding new operations requires either duplicating them across classes or modifying the base class. In "traditional" FP, kinds of data are handled by case discrimination in the functions, which makes it easy to add new operations, but requires adding new cases to add new kinds of data. The Visitor Pattern turns operations into classes (i.e. types), …
Apr 30, 2017 at 20:54 comment added Giorgio @Jules: Indeed, in my project we use a default empty implementation in a superclass of the visitor(s). This is OK in our case but I see that it might not be OK in general.
Apr 30, 2017 at 18:53 comment added Jules @Giorgio ... Using the visitor pattern on the expression problem results in you needing to update all your visitor classes when you need to add a new type of node to your syntax tree. There are ways around this (you could have default implementations in a superclass of your visitors, for example) but this ends up losing the static guarantee that you've handled all cases that are necessary. AIUI, the team working on the most recent iteration of the C# compiler sidestepped this by having the visitor implementations automatically generated ... Essentially using metaprogramming to make it go away.
Apr 30, 2017 at 18:09 comment added Giorgio Regarding Java and C++: isn't the visitor pattern a possible solution. A bit verbose, but I have used it and it seems to work pretty well, in particular, you do not need to touch old code when you want to have a new implementation.
Apr 30, 2017 at 18:03 comment added Jörg W Mittag … future someone else will come up with another restriction that Scala fails but some as-yet-to-be-invented mechanism can provide (maybe dependent types are the answer)?
Apr 30, 2017 at 18:03 comment added Jörg W Mittag … language can even solve this "harder" version. For example, Wadler originally phrased the expression problem to not only be about modular extension, but statically safe modular extension. Common Lisp multimethods however are not statically safe, they are only dynamically safe. Odersky then strengthened this even more by saying it should be modular statically safe, i.e. the safety should be statically checkable without looking at the whole program, only by looking at the extension module. This can actually not be done with Haskell type classes, but it can be done with Scala. And in the …
Apr 30, 2017 at 18:00 comment added Jörg W Mittag @Giorgio: In Haskell, the solution are type classes. In Scala, the solution is implicits and objects. Sorry, I don't have the links at hand, currently. Yes, multimethods (actually, they don't even need to be "multi", it's rather the "open" nature of Lisp's methods that is required) are also a possible solution. Note that there are multiple phrasings of the expression problem, because typically papers are written in such a way that the author adds a restriction to the expression problem which results in the fact that all currently existing solutions become invalid, then shows how his own …
Apr 30, 2017 at 17:49 comment added Giorgio @JörgWMittag: Can you point at some Haskell and Scala literature about solving the expression problem? Also, what about multimethods in Lisp? They also provide a solution to the expression problem, don't they?
Apr 30, 2017 at 17:40 comment added Jörg W Mittag … that, for example. Neither Java nor C♯ have a solution for the Expression. Haskell and Scala do, but their userbase is much smaller.
Apr 30, 2017 at 17:39 comment added Jörg W Mittag "The principle basically says you can't modify the behavior of a component. Instead you have to provide a new variant of the component with the desired behavior, and keep the old version around unchanged for backwards compatibility." – I disagree with this. The principle says that you should design components in such a way that it shouldn't be necessary to change its behavior because you can extend it to do what you want. The problem is that we haven't figured out how to do that yet, especially with the languages that are currently in wide-spread use. The Expression Problem is one part of …
Apr 30, 2017 at 17:20 comment added TheCatWhisperer Good answer, I think Open/Closed is the least useful SOLID principal. Interface segregation is the most important, but least used.
Apr 30, 2017 at 15:22 history edited Robert Harvey CC BY-SA 3.0
deleted 1 character in body
Apr 30, 2017 at 15:20 history edited JacquesB CC BY-SA 3.0
edited body
Apr 30, 2017 at 15:19 history edited Robert Harvey CC BY-SA 3.0
added 1 character in body
Apr 30, 2017 at 15:18 history edited JacquesB CC BY-SA 3.0
added 381 characters in body
Apr 30, 2017 at 15:12 history answered JacquesB CC BY-SA 3.0