News for hackers. Stuff that matters.
Re:“Design Patterns” Aren't (2002) by captainmuon on Sunday March 07, 2021 @01:01PM (#26378049)
The best explanation I heard of design patterns is, that they are not a template to slavishly follow when producing code, but a common language to talk about code. So you should be able to go and identify, look, this is an iterator, this is a command pattern, this is a monad, and you have a clear and concise way to reason about your code and talk to other people.

The second best explanation is that patterns are often a sign of shortcomings in the language. OP gives the example of iterators. Another example is the visitor pattern. Or async/yield as a replacement for explicit state machines.

A thing I'd really like to see in a language would be language level support for the command pattern (being able to capture arbitrary blocks of code, lift the execution to an object, and undo/redo it). Or to be able to include the state of an object in the type system - not like Rust does it with typestates, but to be able to say `Child` is a `Person` where `age < 18`, and if the compiler can't prove that the condition always holds, then it will force you to write the precondition checks or check it at runtime.

Re:“Design Patterns” Aren't (2002) by hosh on Sunday March 07, 2021 @02:04PM (#26378685)
That’s great, but misses the point. Christopher Alexander’s big ideas involve the people who lives, works, and plays within the architecture. The pattern language was designed for them, so they can participate in the design process of their own living spaces.

The equivalent would be a pattern language that app users themselves can use for their apps. Instead of having the app developers drive design with A/B testing to gain user traction (with a societal risk of dark patterns), the users themselves put things together that would work with how they are doing things.

The implementation of the code would work from there. Something the end-users can change the code themselves.

Smalltalk was designed to allow that level of user participation ... but the legacy we ended up with is OOP and gang of four.

If anything, something like TCL/TK is closer to that vision than what we currently have. (What we currently have: mass lockin of consumers and end-users by a different Gang of Four — Facebook, Amazon, Apple, Google).

Alexander’s keynote to the ‘96 OOPSLA conference goes into detail about his ideas and how it can be applicable to software engineering. He was imploring software engineers not to make the same mistake that architects did with his pattern language ideas ... but we still made the same mistake anyways.

Re:“Design Patterns” Aren't (2002) by jluxenberg on Monday March 08, 2021 @04:44AM (#26383848)
The keynote is a great read! Here's a link for anyone else who is interested: https://www.patternlanguage.com/archive/ieee.html
Re:“Design Patterns” Aren't (2002) by matheusmoreira on Sunday March 07, 2021 @03:20PM (#26379404)
The best explanation I've ever seen for design patterns is that they are workarounds for weaknesses of the programming language. Usually Java and its contemporaries.

http://journal.stuffwithstuff.com/2010/09/18/futureproofing-...

Factories, for example. They're essentially just constructors. So why not use the new keyword? Turns out new has limitations:

  - Dependency on the constructed type at the ABI level
  - Cannot return subtypes of the constructed type
  - Special keyword, not orthogonal with the rest of the language
Singletons, for example. They're essentially classes with static methods and state. Why not use these language features instead of coming up with incredibly convoluted ways to ensure only a single instance of an object has been created? Turns out classes have limitations:

  - Classes aren't objects
  - Classes cannot be passed as parameters
  - Classes cannot implement interfaces
The need for all of these patterns simply disappears in a better designed language. In Ruby for example everyone uses factory methods without even realizing it and classes are fully featured objects that can be used in any context.
Re:“Design Patterns” Aren't (2002) by catlifeonmars on Sunday March 07, 2021 @06:04PM (#26380666)
Interestingly enough, the same phenomenon arises in languages with fewer features. In go, for example, there are no constructors, only functions that return structs. Singletons are just global variables referencing a struct, etc etc.
Re:“Design Patterns” Aren't (2002) by commandlinefan on Sunday March 07, 2021 @06:20PM (#26380754)
Every programming language has “singletons”: they’re just global variables.
Re:“Design Patterns” Aren't (2002) by wruza on Sunday March 07, 2021 @07:57PM (#26381307)
Singleton’s main feature is not that it is globally accessible, but in that it represents a state that cannot be naturally duplicated. The pattern itself lies in a controlled instantiation, where a method/constructor/factory returns a cached value on a second call. Globals are just that – globals.
Re:“Design Patterns” Aren't (2002) by bvrmn on Sunday March 07, 2021 @08:18PM (#26381420)
Global variable is naturally can't be duplicated. Or do you assume dark corners of initialization spec for c++?
Re:“Design Patterns” Aren't (2002) by AnimalMuppet on Sunday March 07, 2021 @09:02PM (#26381654)
At global level:

   ThingThereCanBeOnlyOneOf a;
   ThingThereCanBeOnlyOneOf b;
Oops. That's not a singleton. That depends on nobody, ever, anywhere in the code creating another one. In contrast, a true singleton can enforce that there is only one, no matter what the callers do.
Re:“Design Patterns” Aren't (2002) by wott on Sunday March 07, 2021 @09:21PM (#26381762)
Globals like a and b are fields of the singleton, not instance of singleton(s). The global space is the singleton (or a juxtaposition of singletons, if we let aside the lack of visibility protection), and global variables and functions are the fields (members) and the methods of the singleton.
Re:“Design Patterns” Aren't (2002) by AnimalMuppet on Sunday March 07, 2021 @09:26PM (#26381780)
You can look at it that way, I suppose, though I consider it to be a fairly odd perspective. But it doesn't help at all with the problem of enforcing that there be only one ThingThereCanBeOnlyOneOf. Therefore globals are not a true solution to the problem that singletons are trying to solve.
Re:“Design Patterns” Aren't (2002) by bcrosby95 on Sunday March 07, 2021 @10:33PM (#26382080)
Just use static methods.
Re:“Design Patterns” Aren't (2002) by candiodari on Tuesday March 09, 2021 @07:06AM (#26398032)
Singletons solve several problems with static methods, namely that you can't change their behavior (e.g. do error logging to both the global error log and a per-request log, then at other times do it to a log buffer for testing, and NOT to anywhere else).

At least with a singleton you can create a bunch of "standard configurations" by calling them with a different constructor at startup time. So you can have a test DB during tests, different log targets, read from different filesystem (not the real one, but the one in the testdata/ directory) ...

Better yet is to have a "context" abstraction that you pass down the chain. Issue with that is, every method needs to have a first parameter that is the context ... so it requires some discipline.

Some frameworks (java @#$@#%@# servlet spec for example) make this parameter implicit and then use something akin to exception resolution to get this parameter (so when you do GetContext(), it unwinds the stack to give you the correct context). That makes things very complicated, and is an invisible LOT of state that gets passed down the stack. Still better than singletons or static methods, but good luck figuring out why a context is set to X.

In all cases you need to be very careful to USE the context. DO NOT use database except the one in the context, no caches except the one in the context, no filesystem reading, logging, ... except by redirecting through the context.

Re:“Design Patterns” Aren't (2002) by bvrmn on Tuesday March 09, 2021 @01:34AM (#26396055)
I can also get second instance with singleton. In reality singleton doesn't enforce anything. It's a only a convenient way to make global scope in inconvenient languages.
Re:“Design Patterns” Aren't (2002) by AtomicPlayboy on Sunday March 07, 2021 @09:30PM (#26381802)
I would partially agree, although I don't know many implementations.

It's a state that cannot be naturally duplicated, alright, a "single source of truth". But lazy instantiation is nothing more than a very important and very common second. The pattern itself lies in preventing public-level instantiation (i.e. in Java it could translate to a class with a private constructor, private instantiation and access to the instance through a class-level/static getter, and also making it a final class).

Re:“Design Patterns” Aren't (2002) by virtue3 on Sunday March 07, 2021 @10:07PM (#26381961)
my (very tongue in cheek) favorite description of singletons - an object oriented way to break object orientedness.
Re:“Design Patterns” Aren't (2002) by dwaite on Sunday March 07, 2021 @10:26PM (#26382043)
Not quite - variables are references to objects, there's nothing that restricts global variables themselves to only reference a single _instance_ of an object.

That said, a global singleton (and global state in general) is usually an anti-pattern; having pretty much any code be able to depend on the state makes it very difficult to evaluate the impact of a change.

Re:“Design Patterns” Aren't (2002) by galaxyLogic on Monday March 08, 2021 @12:22AM (#26382523)
> - Classes aren't objects

Right. Except in Smalltalk they are

Re:“Design Patterns” Aren't (2002) by grzm on Monday March 08, 2021 @12:33AM (#26382579)
Ruby, too, IIRC. And likely others.
Re:“Design Patterns” Aren't (2002) by kitkat_new on Sunday March 07, 2021 @06:28PM (#26380808)
is the Abstract Factory showing a weakness of all languages in which it is useful? What is the underlying weakness?
Re:“Design Patterns” Aren't (2002) by anonymoushn on Sunday March 07, 2021 @10:01PM (#26381934)
The question is, "I have some code that wants to make some different kinds of a thing in the same way, then use the different kinds in the same way, being unaware that they are different and not depending on any particular kind. How?" The answer is typically that you can pass a function to that code which accepts some stuff and returns the thing it is concerned with. You may say "Thats an Abstract Factory" but when we write like 4 LoC instead of 3 classes in different files we often don't feel a need to give it a name.

Edit: Also, depending on the circumstances, you can probably just pass the class or its constructor instead of passing a newly written function. That would get you down to ~0 LOC involved in replicating the functionality of this pattern.

Re:“Design Patterns” Aren't (2002) by anonymoushn on Monday March 08, 2021 @02:02AM (#26382958)
I guess if we want to get really abstract, we can say that the Abstract Factory pattern is a shim from a kind of late binding that is implemented in the language ("object orientation" a.k.a. dynamic dispatch on the first argument to a function) to one that is not (late binding of classes, constructors returning null, etc.). This isn't the whole picture though, because sometimes late binding isn't even an important part of what we're getting from the Abstract Factory pattern! For many use cases, we could imagine implementing the function that consumes the Abstract Factory using C++ templates or Zig comptime, and our compiler would generate separate subroutines for each factory type and statically determine which one to use at each call site and we would still be doing the Abstract Factory thing.

Another pattern called the Visitor Pattern is similarly a shim from dynamic dispatch on one argument to dynamic dispatch on two arguments. You just really hope you don't need dynamic dispatch on five arguments one day.

Re:“Design Patterns” Aren't (2002) by capableweb on Sunday March 07, 2021 @03:07PM (#26379288)
> The second best explanation is that patterns are often a sign of shortcomings in the language

Agree. Came across a blogpost that describes this very well by using Clojure as an example: http://mishadoff.com/blog/clojure-design-patterns/

Re:“Design Patterns” Aren't (2002) by dwaite on Sunday March 07, 2021 @10:27PM (#26382048)
> The second best explanation is that patterns are often a sign of shortcomings in the language

Or the inverse, the patterns are common enough that a limited form of them is baked directly into the language itself.

Re:“Design Patterns” Aren't (2002) by riffraff on Sunday March 07, 2021 @02:56PM (#26379166)
for the second thing, there's a famous presentation by Norvig[0] showing how many GoF patterns are "invisible" in powerful enough languages.

It's 25 years old, but still interesting.

[0] http://www.norvig.com/design-patterns/

Re:“Design Patterns” Aren't (2002) by AnimalMuppet on Sunday March 07, 2021 @09:12PM (#26381720)
I don't think the issue is "powerful enough". I think it's that something is hard to do cleanly in the language. For instance, you could view monads for sequence and IO as "design patterns" in Haskell, because it's hard to do those things in Haskell in a straightforward manner. This is just the nature of the language. It's not that Haskell isn't "powerful enough".
Re:“Design Patterns” Aren't (2002) by BoiledCabbage on Sunday March 07, 2021 @01:28PM (#26378287)
That last thing you're looking for I believe is called dependent types.
Re:“Design Patterns” Aren't (2002) by Smaug123 on Sunday March 07, 2021 @01:55PM (#26378573)
Dependent types are one way to achieve that effect, but I think what you're actually referring to is "refinement types".
Re:“Design Patterns” Aren't (2002) by centimeter on Sunday March 07, 2021 @02:37PM (#26379003)
See LiquidHaskell for probably the most mature SMT-based refinement types implementation.
Re:“Design Patterns” Aren't (2002) by kazinator on Tuesday March 09, 2021 @01:58PM (#26402353)
You can't give people the language to recognize and identify a pattern, and then forbid them from using that as a tool to reproduce it.

Can you imagine?

"You can talk about patterns as a means of description, but don't consciously wield them as a means of production. Also, do not make statements such as 'the architect used this pattern'. Rather say, 'the pattern spontaneously emerged in the work, facilitated by the architect's intuition'."

Haha, right.