Live data from Hacker News

Design Patterns Are Temporary, Language Features Are Forever

ptrtojoel.dev

41–50 of 67 posts

Re: Design Patterns Are Temporary, Language Features Are Forever

#41

This reminds me of when I was still in university. During our compilers course we used the "Modern Compiler Implementation in Java" book. Because I was really into FP at the time, I instead used the "Modern Compiler Implementation in ML" version of this book (which was the original, the Java and C versions were made to make it more accessible). We noticed during the course that my version was missing a whole chapter…

> that software design patterns are sometimes failures of the language when they have no concise way of expressing these kinds of concepts.

This is _the_ most common comment you hear in any language design discussion, and it's so boring. Java doesn't have visitors because it's the best the language could come up with. It has visitors because of a particular dogmatic adherence to OOP principles. A fundamentalist reading that says you're never supposed to have any control flow, only virtual method calls. Visitors come from the same place as Spring and the infamous AbstractSingletonProxyFactoryBean.

Java is perfectly capable of expressing an enum, and you can easily switch on that enum. The limitation that you have to express that enum as a type hierarchy, and therefore encounter the double dispatch problem is entirely OOP brainrot.

Re: Design Patterns Are Temporary, Language Features Are Forever

#42

This reminds me of when I was still in university. During our compilers course we used the "Modern Compiler Implementation in Java" book. Because I was really into FP at the time, I instead used the "Modern Compiler Implementation in ML" version of this book (which was the original, the Java and C versions were made to make it more accessible). We noticed during the course that my version was missing a whole chapter…

[deleted]

Re: Design Patterns Are Temporary, Language Features Are Forever

#43
> Now knowing about pattern matching, this is how I came to realise that the visitor pattern was pattern matching in an OO way.

The programming language needs to be very expressive to replace the visitor pattern with pattern matching. For example, you need GADTs. The cool thing about static languages with OOP is that OOP can hide a lot of type-level complexity. Also, in languages with runtimes optimized for virtual calls (e.g., the JVM, V8), pattern matching can have less performance than the visitor pattern, despite pattern matching now being a reality on the JVM at least (e.g., Java, Scala have pattern matching).

The difference between pattern matching and the visitor pattern is the difference between tagless-initial and tagless-final encodings, or data versus Church-encodings. And as a software engineer, it's good to be aware of their strengths and weaknesses.

People making this claim (that design patterns are just missing language features) always mention Visitor, but stop short of mentioning other design patterns, such as Observable/Listener, but also, the even less obvious: Monad or the Free Monad (i.e., still a design pattern, despite being able to comfortably express it in your language).

Re: Design Patterns Are Temporary, Language Features Are Forever

#44
post #40

I always tell people who obsess over design patterns as clean code and good coding practices to remember that design patterns often indicate a lack of language features. For example, are you using a Builder? Would you use the Builder pattern if the language had named variables in arguments? My favorite reference on the topic is Peter Norvig's "Design Patterns in Dynamic Languages" (1996!) https://www.norvig.com/desig…

> Would you use the Builder pattern if the language had named variables in arguments?

Yes, absolutely. I see it all the time in the Ruby ecosystem and have used it myself in Ruby. Many times it gets called by a different name. I've seen it in Python and Elixir too.

Re: Design Patterns Are Temporary, Language Features Are Forever

#45
post #9

You don’t come across visitors every day, and they aren’t something to reach for instead of a simple switch, but if you are writing a Webpack or ESLint plugin or something like that, you might encounter them for traversing an AST. It’s not just an OO thing, either. I learned the visitor pattern in pretty ideal circumstances: from a classmate, back in college, when we were writing a compiler together for a class proje…

I wrote some Typescript AST walking code recently, and could not for the life of me figure out what the advantage of the visitor pattern was here. It seemed to only overcomplicate the implementation, made it much more difficult to track where you were in the tree and target specific nodes and seemed much easier to just call getChildren and iterate.

Re: Design Patterns Are Temporary, Language Features Are Forever

#46

This reminds me of when I was still in university. During our compilers course we used the "Modern Compiler Implementation in Java" book. Because I was really into FP at the time, I instead used the "Modern Compiler Implementation in ML" version of this book (which was the original, the Java and C versions were made to make it more accessible). We noticed during the course that my version was missing a whole chapter…

«Design patterns are bug reports against your programming language» (Peter Norvig)

This is pithy, but only applies to some rote design patterns which you have to code every time because the language lacks a good way to factor them out.

Wider-scale patterns often express key approaches enabled by the language, and they can't go onto a one-size-fits-all library or language feature, because you tailor their implementation to your specific needs. They are less like repetitive patterns of a brick wall, and more like themes or motifs that keeps reappering because they are fruitful.

Re: Design Patterns Are Temporary, Language Features Are Forever

#47

This reminds me of when I was still in university. During our compilers course we used the "Modern Compiler Implementation in Java" book. Because I was really into FP at the time, I instead used the "Modern Compiler Implementation in ML" version of this book (which was the original, the Java and C versions were made to make it more accessible). We noticed during the course that my version was missing a whole chapter…

> that software design patterns are sometimes failures of the language when they have no concise way of expressing these kinds of concepts. This is _the_ most common comment you hear in any language design discussion, and it's so boring. Java doesn't have visitors because it's the best the language could come up with. It has visitors because of a particular dogmatic adherence to OOP principles. A fundamentalist readi…

Indeed there should be no control flow, only computing values of function application :)

Indeed, this is also absolutism, just of a different kind, that proved to be somehow more fruitful in the application programming domain. And, to my mind, it's mostly because functions can be pure and normally return a value, while methods are usually procedures mutating some hidden state.

OTOH in a different domain, system programming, control flow is a good abstraction over the close-by hardware, mutable state is all over the place in the form of hardware registers, and it's more fruitful to think in terms of state machines, not function application.

If a tool forced you to do repetitive irrelevant motions, it's just a wrong tool, you need to find or create a better one.

Re: Design Patterns Are Temporary, Language Features Are Forever

#48
post #40

I always tell people who obsess over design patterns as clean code and good coding practices to remember that design patterns often indicate a lack of language features. For example, are you using a Builder? Would you use the Builder pattern if the language had named variables in arguments? My favorite reference on the topic is Peter Norvig's "Design Patterns in Dynamic Languages" (1996!) https://www.norvig.com/desig…

A builder can allow you create different kinds of objects from a common stem. They don't have to be bags of properties.

Say, SQLAlchemy is all built on chaining builder-like methods, which make one of the finest DSLs that translates to SQL. In the end, you build a representation of a SQL statement, but in no way could that work with named arguments alone.

Instead, consider named arguments as nice shortcuts over curried functions.

Re: Design Patterns Are Temporary, Language Features Are Forever

#49
post #9

You don’t come across visitors every day, and they aren’t something to reach for instead of a simple switch, but if you are writing a Webpack or ESLint plugin or something like that, you might encounter them for traversing an AST. It’s not just an OO thing, either. I learned the visitor pattern in pretty ideal circumstances: from a classmate, back in college, when we were writing a compiler together for a class proje…

Someone else beat me to it. Will answer anyway. Had a very similar experience to yours with one important exception. The visitor pattern is relevant for traversing ASTs in single dispatch languages. Most notably, this includes Java and C++. The alternative concept is multiple dispatch and it is way more anti-fragile. This is where the next step in college literally was to learn the concept of cargo-culting. The conce…

What do you mean by "multiple dispatch"? What's an example of a multiple dispatch program?

Re: Design Patterns Are Temporary, Language Features Are Forever

#50

Earlier quoted context omitted.

Someone else beat me to it. Will answer anyway. Had a very similar experience to yours with one important exception. The visitor pattern is relevant for traversing ASTs in single dispatch languages. Most notably, this includes Java and C++. The alternative concept is multiple dispatch and it is way more anti-fragile. This is where the next step in college literally was to learn the concept of cargo-culting. The conce…

What do you mean by "multiple dispatch"? What's an example of a multiple dispatch program?

https://en.wikipedia.org/wiki/Multiple_dispatch

It means dynamic dispatching based on the types of multiple arguments not a single argument.

Post reply on HN