Live data from Hacker News

Design patterns you should unlearn in Python

lihil.cc

41–50 of 110 posts

Re: Design patterns you should unlearn in Python

#42
post #21

Great post. Now let's do C# because if I see a repository pattern doing nothing but calling Entity Framework under the hood again I'm going to rip the planet in half

What you dont like

  public class Repository : IRepository where TEntity : class
  {
      public async Task Add(TEntity entity)
      {
          _context.Add(entity);
          await _context.SaveChangesAsync();
      }
  }
everywhere?

Re: Design patterns you should unlearn in Python

#43
post #21

Great post. Now let's do C# because if I see a repository pattern doing nothing but calling Entity Framework under the hood again I'm going to rip the planet in half

> Great post. Now let's do C# because if I see a repository pattern doing nothing but calling Entity Framework under the hood again I'm going to rip the planet in half Your comment shows a hefty amount of ignorance. Repositories wrap Entity Framework because Entity Framework's DbContext & Co are notoriously complicated to mock and stub. Once you wrap EF stuff with a repository that implements an interface, that probl…

We don't really have this problem in .NET 8, we mock stuff just fine using an in-memory database provider.

But I admit my tone missed the mark. It may have been much harder to do in the past, or maybe I'm missing some nuance.

But also at this point why not just have your DbContext directly implement an interface that you can mock? Surely that must be more straightforward than adding an entire abstraction layer, that you have to extend with each new usage scenario, and without sacrificing implicit transactionality.

Re: Design patterns you should unlearn in Python

#44

I don't agree with the builder pattern. For basic objects yes its a bit silly. But the ACTUAL value of the builder pattern is when you want to variadically construct an object. Create the base object, then loop or otherwise control flow over other state to optionally add stuff to the base object. Then, additionally, the final "build" call can run validations over the set of the complete object. This is useful in case…

> Create the base object, then loop or otherwise control flow over other state to optionally add stuff to the base object.

That’s what list comprehensions are for.

> Then, additionally, the final "build" call can run validations over the set of the complete object.

The constructor function can do that too.

Re: Design patterns you should unlearn in Python

#45

I don't agree with the builder pattern. For basic objects yes its a bit silly. But the ACTUAL value of the builder pattern is when you want to variadically construct an object. Create the base object, then loop or otherwise control flow over other state to optionally add stuff to the base object. Then, additionally, the final "build" call can run validations over the set of the complete object. This is useful in case…

Couldn't you build up a dictionary of keyword arguments instead and do all the validation in the __init__ method? E.g.

  kwargs = {}
  if is_full_moon() and wind_direction == EAST:
    kwargs["baz"] = 42
  
  thing = Thing(foo=3.14, bar=1, **kwargs)

Re: Design patterns you should unlearn in Python

#46

I really appreciate how this article explains why certain design patterns became a thing. Usually, it was to address some very practical problem or limitation. And yet, a lot of younger programmers treat these patterns like a religious dogma that they must follow and don't question if they really make sense for the specific situation they are in.

> I really appreciate how this article explains why certain design patterns became a thing. Usually, it was to address some very practical problem or limitation.

I don't agree at all. I feel that those who criticise design patterns as solution to practical problems are completely missing the point of design patterns, and the whole reason they have the name the have: design patterns. I'll explain.

Design patterns are solutions to common design problems, but "problems" isn't the kind of problems you think it is. It's "problems" in the sense that there are requirements to be met. A state pattern is a way to implement a state machine, but you still have a state machine and a state pattern if your state classes don't handle state transitions.

More to the point, look at singletons. It's irrelevant if they are implemented with a class or a closure or a module. What makes a singleton a singleton is the fact that there is an assurance that there will be a single instance of an object. Does an implementation that allow multiple instances or doesn't return the same instance qualifies as a singleton? Obviously not.

Design patterns are recurring solutions to recurring problems. They are so recurring that they get their name and represent a high level concept. A message queue is a design pattern. An exception is a design pattern. Lazy loading is a design pattern. Retries and exponential backoffs are design patterns. Etc. Is anyone arguing that Python has none of it?

So many people trying to criticise the GoF but they don't even bother to be informed or form an educated opinion.

Re: Design patterns you should unlearn in Python

#47

I don't agree with the builder pattern. For basic objects yes its a bit silly. But the ACTUAL value of the builder pattern is when you want to variadically construct an object. Create the base object, then loop or otherwise control flow over other state to optionally add stuff to the base object. Then, additionally, the final "build" call can run validations over the set of the complete object. This is useful in case…

[deleted]

Re: Design patterns you should unlearn in Python

#48

I really appreciate how this article explains why certain design patterns became a thing. Usually, it was to address some very practical problem or limitation. And yet, a lot of younger programmers treat these patterns like a religious dogma that they must follow and don't question if they really make sense for the specific situation they are in.

I am an ex Java developer. Enterprise Fizz Buzz is highly entertaining. That stupid masters thesis pretending to be a design book landed right an inflection point and ruined half a generation of developers.

What isn’t entertaining is using OpenTelemetry, which takes me right back to Java for over-engineering. Moving to OTEL from StatsD cost us about 3% CPU per core, which on 32 core machines is an entire CPU lost to telemetry. Or more accurately, an entire second CPU lost to telemetry. That is not right.

Prometheus doesn’t have these problems. And isn’t trying to fix quite as many problems I’ve never had.

Re: Design patterns you should unlearn in Python

#49
post #14

I was writing a python thing where the class was going to have like at least 20 paramaters to configure it. Builder pattern was kind of feeling like a good idea to keep it cleaner for the user. But it is surprising to see in the python world. It felt like a mess of default values though for the user to handle.

Rarely have I seen a class that truly needs 20 parameters, that's most often a design flaw. There might be cases where this isn't true, but those are edge cases, so it's probably also fine to apply a special patterns, such as the builder pattern.

> Rarely have I seen a class that truly needs 20 parameters

If a class seems like it needs that many parameters, it is very common that one or both of these is true:

1. It is doing too much, or

2. There are things-that-should-be-their-own-classes hiding in groups of the parameters.

#2 is kind of a subset of #1, but the "doing too much" tends to be concentrated in validating relations between parameters rather than what happens after the object is constructed.

Re: Design patterns you should unlearn in Python

#50

Builder patterns are seriously useful for high complexity state construction with the ability to encore rules to prevent degenerate state. A good example from my experience might be connecting to a Cassandra cluster it other type of database that can have extremely complex distributed settings and behaviors: timeouts, consistency levels, failure modes, retry behavior, seed connector sets. Javaland definitely had a pr…

I'd say Kotlin took most good parts of Groovy syntax and put it into a decent type system, then Clojure peeled off the folks who still preferred a more dynamic language. Languages can't all live forever, otherwise there'd be no room for new growth.
Post reply on HN