[HN Gopher] Design patterns you should unlearn in Python
___________________________________________________________________
Design patterns you should unlearn in Python
Author : zeitlupe
Score : 76 points
Date : 2025-08-01 16:29 UTC (6 hours ago)
(HTM) web link (www.lihil.cc)
(TXT) w3m dump (www.lihil.cc)
| wodenokoto wrote:
| I like the concept of the article but I'm not sure I've seen
| these in the wild.
| BugsJustFindMe wrote:
| It's more like "if switching from Java to Python". I've also
| never seen anyone writing Python do this.
| citrin_ru wrote:
| I've seen a person using in Perl Singleton classes, Factory
| classes and other Java patterns. The app worked well but the
| code was probably 2x large than it could be.
| whilenot-dev wrote:
| An example of the Builder pattern in the wild:
| https://github.com/bikram990/PyScep/blob/8d80bc03368ea8dc6ea...
|
| ...especially annoying if it's only used in one continuous
| chain:
| https://github.com/bikram990/PyScep/blob/8d80bc03368ea8dc6ea...
| mrweasel wrote:
| The singleton one is one I've attempted, and no, it doesn't
| work well in Python. Early in my career I worked on a number of
| projects where the architects had used a singleton pattern for
| a number of things. The pattern sort of stuck in my head, but
| this was in C# and I've mostly worked in Python ever since. As
| the article points out it's designed for language like Java and
| C++ (and C#).
|
| In my opinion the singleton pattern does however not make
| Python code harder to test. In Python it's actually extremely
| handy, because its incredibly easy to mock out a singleton in
| your test cases.
| AtlasBarfed wrote:
| How does Python do mocking if it doesn't use singletons?
|
| Or do people just not do unit testing in Python using spock-
| like technology? And I do use the word technology because
| Spock is that much better than just a bunch of test scripts
| mrweasel wrote:
| You can overwrite pretty much anything in Python at
| runtime, and the mock tooling in the standard library can
| help you with that, if you can't straight up just override
| a method or object.
| AtlasBarfed wrote:
| Global vars?
|
| So with a Singleton what you can do at least in Java land
| is have your service invoke the method to get the
| Singleton semi-global object.
|
| So you can mock that method invocation to return a
| different object. So you basically have the local object
| to play with in your test and won't be affecting any
| actual real global state
|
| But basically the article was just saying just use global
| variables. Does python have a means for then intercepting
| the value request and data assignments for that global
| variable for the local scope of the testing code? Or is
| it hardwired like a global variable, presumably is?
| orwin wrote:
| I'm tired and I'm not sure I understood your question
| correctly, sorry if it doesn't address your point:
|
| In python test library, you have something called
| 'monkeypatch' that allows you to intercept calls to
| specific functions or classes and set the response
| yourself (I mostly use it to mock API responses tbh but
| it can do a lot more, an really complex operations).
| Monkeypatch only operate in the scope of the function or
| file it's written in (I think. I only remember using it
| in unit test functions).
| AtlasBarfed wrote:
| The answer if I understand correctly is if you want to
| use testing frameworks in Python, you should probably not
| be using global variables and you should probably
| actually be using the Singleton pattern.
| tptacek wrote:
| Peter Norvig has a well-known piece that goes into more depth on
| why the GoF-style patterns don't make much sense in high-level
| languages:
|
| https://www.norvig.com/design-patterns/
| shawn_w wrote:
| Those slides would be a lot more useful with a transcript of
| the talk that went along with them. Or a video of it. Wonder if
| anything like that still exists.
| aswerty wrote:
| The Zen of Python: there should be one obvious way to do things.
|
| Python in practice: there is more ways of doing it than in any
| other programming language.
|
| Oh Python, how I love and hate you.
| shlomo_z wrote:
| > than in any other programming language After reading the
| article, I couldn't believe anyone designs their systems like
| that. His "solutions" seemed to be the obvious way to do
| things.
| nhumrich wrote:
| People misunderstand the target audience and code base for the
| zen of python
| ddejohn wrote:
| Who's it for, then?
| dkarl wrote:
| I don't think any of the examples in the article contradict the
| Zen of Python. Even if there's one simplest and clearest way to
| do it in Python, there's nothing stopping people from using a
| more complicated solution that they got used to while working
| in a different language. They might not know to look for a
| simpler way, because they're used to working in a language
| where their way is the simplest.
| taylorallred wrote:
| 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.
| zelphirkalt wrote:
| Probably also a problem that exists because of how programmers
| are taught. Using Java and being presented with the patterns as
| solutions to what Java does.
| seadan83 wrote:
| > a lot of younger programmers treat these patterns like a
| religious dogma
|
| First you learn what the pattern is. Then you learn when to use
| it. Then you learn when not to use it.
|
| The gap between the first and third step can be many years.
| arcanemachiner wrote:
| > The gap between the first and third step can be many years.
|
| I admire your optimism!
| kccqzy wrote:
| I don't however appreciate that the author doesn't actually
| know about Java or C++ well enough such that they are spewing
| falsehoods about Java or C++. Saying things like "There's no
| clean way to say 'this is private to this file' (in C++)" is
| just bonkers. The author is well intentioned, but coming up
| with the wrong reason is worse than not offering any reason.
| dgfitz wrote:
| I had that thought too, and thought I must have misunderstood
| something. I generally assume I'm the dummy. :)
| motorest wrote:
| > 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.
| hinkley wrote:
| I see you've been downvoted.
|
| Design patterns aren't solutions to common design problems.
| They're after the fact descriptions of solutions for design
| problems. That's the issue. That's the beef. Everyone thought
| of that book as a cook book instead of a naturalists' musings
| on an ecosystem, which is what they are.
|
| Those of us who designed before people discovered that stupid
| book were constantly asked what the differences were between
| this pattern and that. And the book just isn't thick enough
| and Eric Gamma was just trying to complete a thesis not write
| a book, so despite having at least 8 years in industry before
| completing his masters he cocked it up. And ruined Java in
| the process.
|
| We had a contemporary of Vlissades teach a class at my last
| company and he crystallized all of my suspicions about the
| GoF book and added a whole lot more.
|
| My advice for at least fifteen years is, if you think you
| want to read GoF, read _Refactoring_ instead. If you've read
| _Refactoring_ and still want to read GoF, read _Refactoring_
| a second time because it didn't all sink in.
|
| _Refactoring_ is ten times the value of GoF for teaching you
| how to do this trade and how to break up architectural
| brambles.
| orwin wrote:
| I mean, people usually call those 'feature' when they're
| built-in. I would never call 'lazy evaluation' in Haskell a
| design pattern, because it's part of the language.
|
| If I have to implement something similar myself in C++
| however, I'll use a niche design pattern.
| hinkley wrote:
| 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.
| AceJohnny2 wrote:
| The explanations are great! The condescension, not so much.
|
| > Simple: we just use the language _like it was meant to be
| used._
|
| > Use Default Arguments _Like a Normal Human_
|
| etc
| layer8 wrote:
| The main motivation for the concept of design patterns is to
| give unique names to existing programming patterns, so that
| when someone says "Strategy pattern", everyone knows what
| pattern that refers to, and vice versa that the same pattern
| isn't called ten different things. It's to make communication
| about program design efficient, by defining a vocabulary of
| patterns that tend to reoccur, and a common structure for
| describing them. Not all patterns were successful in that way,
| but it's the main idea behind design patterns.
|
| The question of when a using a given pattern is appropriate is
| orthogonal to that. The fact that a named pattern has been
| defined doesn't imply a recommendation to use it across the
| board. It depends on the context and on design forces, and
| those change with time and circumstances. Anti-patterns are
| patterns as well.
|
| It's a pity that the idea of design patterns ended up (after
| the pattern language craze faded) being almost exclusively
| associated with the specific patterns named and described in
| the GoF book.
| dragonwriter wrote:
| > The main motivation for the concept of design patterns is
| to give unique names to existing programming patterns
|
| No, naming them is not the main purpose, preserving and
| transmitting knowledge of what they are and what they are
| useful for, so that people aren't fofced to rediscover
| solutions to the same problems over and over again. [0]
| Naming is obviously important for that purpose, but isn't the
| main goal, but a means of supporting it.
|
| [0] If this sounds like a subset of the purpose of a reusable
| code library, it is, which is why in languages with
| sufficient abstraction facilities to allow the generic
| implementation of a pattern to be reusable, well documented
| (for the "where and when to use this" piece) code libraries
| replace documents that have the explanation paired with
| implementation recipes that one can modify to one's
| particular use.
| dkarl wrote:
| > It's a pity that the idea of design patterns ended up
| (after the pattern language craze faded) being almost
| exclusively associated with the specific patterns named and
| described in the GoF book
|
| That book is the closest we came to establishing a common
| language. I remember brushing up on the names of design
| patterns whenever I had an interview. Ultimately, though, it
| didn't yield any benefit that the industry is missing now.
|
| Like you said, the fundamental idea behind the book was that
| consciously naming, cataloging, and studying design patterns
| would improve communication among programmers. There was also
| an idea that studying design patterns would give beginning
| programmers a richer repertoire of programming techniques
| faster than if they had to figure them out themselves.
|
| Looking back with decades of hindsight, my belief is that
| awareness and intentional use of design patterns made no
| difference whatsoever. Some names stuck, and would have
| anyway. Others didn't, and years of status as official
| "design patterns" in a book widely studied across the
| industry couldn't make them. The younger programmers I work
| with who had no exposure to the GoF book, and for whom
| "design patterns" is something that dusty old farts used to
| talk about, use patterns like Flyweight, Proxy, Command,
| Facade, Strategy, Chain of Responsibility, Decorator, etc.
| without knowing or needing a name for them, and they
| communicate amongst themselves just as efficiently as my
| generation did at the height of the design pattern craze.
|
| In the final analysis, I have never looked at the less
| experienced programmers around me and thought, "This
| situation would go faster and smoother if they had studied
| design patterns." The generation that learned to program
| after design patterns had faded as an idea learned just as
| quickly and communicates just as well as the generation that
| studied them assiduously as junior programmers like I did.
| tmh88j wrote:
| > Like you said, the fundamental idea behind the book was
| that consciously naming, cataloging, and studying design
| patterns would improve communication among programmers.
|
| > The younger programmers I work with who had no exposure
| to the GoF book.....and they communicate amongst themselves
| just as efficiently as my generation
|
| > The generation that learned to program after design
| patterns had faded as an idea learned just as quickly and
| communicates just as well as the generation that studied
| them assiduously as junior programmers like I did.
|
| I've never read GOF so I don't know if they emphasize
| communication, but I have read and studied many other
| programming pattern books and communication is low on the
| list of reasons to learn them in my opinion. Their only
| purpose for me is to organize code in a way that has been
| proven to "scale" along with a codebase so that you don't
| end up with a plate of spaghetti.
| NeutralForest wrote:
| I've never seen anybody do that... In Python you can use a module
| as a singleton (mentioned in the article). Or provide some data
| like: from functools import lru_cache
| class Whatever: pass @lru_cache(maxsize=1)
| def get_whatever(): return Whatever()
|
| And use `get_whatever` as your interface to get the resource.
| motorest wrote:
| > I've never seen anybody do that...
|
| I feel the blog post is a bunch of poorly thought through
| strawmen. I was browsing through the singleton example and I
| was wondering why would anyone use buggy code to implement
| something it clearly was not designed to implement.
|
| The whole article is quite subpar. I was expecting idiomatic
| stuff that eliminated the need to implement something, like for
| example implementing singletons with modules and even getter
| functions, but there was none of that: just strawmen.
|
| Really disappointing.
| e1gen-v wrote:
| I do this in fast api and then pass get_whatever as a
| dependency to an endpoint
| whilenot-dev wrote:
| Alternatively you could make use of the lifespan[0] and its
| state[1][2].
|
| [0]: https://fastapi.tiangolo.com/advanced/events/#lifespan-
| funct...
|
| [1]: https://asgi.readthedocs.io/en/latest/specs/lifespan.htm
| l#li...
|
| [2]: https://www.starlette.io/lifespan/#lifespan-state
| empiko wrote:
| You can implement a singleton class that works properly quite
| easily. The advantage is that most people are familiar with
| singleton as a pattern, and it is a self contained chunk of
| code. The cache solution you provided works, but its
| functionality is not obvious and it feels very hacky to me.
| Somebody's going to initialize Whatever in another way down the
| line without using the cached function...
| tayo42 wrote:
| 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.
| atoav wrote:
| I like method chaining (not the same as builder patterns) for
| code that needs to run chained operations on objects. It is not
| exacrly the same because each chained operation usually does
| more than just setting a variable.
|
| E.g. signal = Sine(freq=440.0, amp=1.0)
| .rectify() .gain(2.0)
| .center() .clip(0.5)
|
| Each of the methods may return a Signal object that can get
| processed by the next function, allowing you to chain them
| together to get complex results quickly. The ergonomics on this
| are stellar and because these methods can be implemented as
| generators, each step can yield values lazily instead of
| building full intermediate arrays.
|
| That way, you get the clean chaining style _and_ efficient,
| streaming computation.
| mystifyingpoi wrote:
| This also greatly increases API discoverability, because I
| can just type "." and see the IDE pop up me all the options
| right there, no need for docs.
| mrweasel wrote:
| 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.
| dragonwriter wrote:
| > 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.
| mystifyingpoi wrote:
| Good example for Python not needing this pattern sometimes is
| Pulumi. Check out the differences between example code in Java
| and Python.
|
| https://www.pulumi.com/docs/iac/get-started/kubernetes/revie...
|
| In Java (or even Go) this pattern is required to enforce type
| safety. In Python it seems that they ignore the typing part and
| just pass a bunch of dicts. Looks much cleaner, even if not
| entirely typesafe.
| the__alchemist wrote:
| All good ones. I'll add this because A: It's common in Python,
| and B: There are suitable alternatives in the standard library:
|
| Conflating key/value lookups (dicts) with structured data
| (classes). They are both useful tools, but are for different
| purposes. Many python programmers (Myself many years ago
| included!) misused dicts when they should have been using
| dataclasses.
| ddejohn wrote:
| Everything in the codebase I maintain at my job is an arbitrary
| dict and there is no type information anywhere. It wasn't even
| written that long ago (dataclasses were a thing long before
| this codebase was written).
|
| There's actually a place where the original authors subclassed
| dict, and dynamically generate attributes of a "data class"
| such that it can be used with dotted attribute access syntax or
| dict access syntax but the `__slots__` attribute of these
| classes is also generated dynamically so you don't have any
| auto-complete when trying the dotted attribute access. It's
| genuinely insane lol.
| z_open wrote:
| He didn't mention the worst pattern, the visitor pattern, which
| has extremely few use cases.
| zelphirkalt wrote:
| I have observed these "design pattern shoehorned into Python" so
| many times ... Great post. When you see these things done in a
| code base, you know that you got people, who would rather want to
| write Java working on it. Or maybe people who don't have the feel
| for Python as a language or something.
|
| First thing I looked up in the article was "singleton", as a
| sanity check, whether the article is any good. And yes, it shows
| module level binding as alternative, exactly what I expected,
| because I looked into this in the past, when someone implemented
| API client singleton, in a case of irrelevant early optimization
| of something that was never a bottleneck.
|
| Articles like this are helpful in spreading the awareness, that
| one should not hold a Python like one holds a Java.
| necovek wrote:
| Module-level initialization has one huge problem in Python,
| though.
|
| That means that as soon as you import a module, initialization
| happens. Ad infinitum, and you get 0.5s or more import times
| for libraries like sqlalchemy, requests...
| ddejohn wrote:
| yep, the legacy codebase I maintain does a lot of this kind
| of stuff and has made it difficult to write unit tests in
| some cases due to all the code that runs at import and all
| the state we end up with
| pbh101 wrote:
| The article addresses this.
| ddejohn wrote:
| I know, I'm just complaining about the mountain of code
| that does this at my company. And there is no fixing it
| using the article's approach or any other for that matter
| due to the sheer scale of the abuse.
| zelphirkalt wrote:
| Initialization only happens once, when you import the module
| for the first time, afaik. Unless you are running multiple
| Python processes, that is.
| AtlasBarfed wrote:
| 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 problem with overuse of patterns, but
| the patterns are legitimate tools even outside of Oop.
|
| I haven't done much research into testing frameworks in other
| languages, but the spock testing framework in groovy/javaland is
| a serious piece of good software engineering that needs
| singletons and other "non hard coded/not global" approaches to
| work well.
|
| Spring gets a ton of hate outside of jabs, and I get it, they
| tried to subsume every aspect of programming and apis especially
| web into their framework, but the core spring framework solved
| complex object graph construction in a very effective way
|
| Oh you hate "objects" but have thousand line struct graph
| construction code?
|
| It's kind of sad that groovy never took off. It offered all the
| good parts of java with a ton of good python, ruby, and other
| langs with the solid foundation of the jvm for high speed
| execution.
|
| But it's effectively dead. Kind of like Cassandra is effectively
| dead. The tech treadmill will eventually leave you behind.
| chuckadams wrote:
| 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.
| mystifyingpoi wrote:
| In my experience everyone will hate on Spring, showing how much
| easier other frameworks are using tiny unrealistic examples,
| until they hit a _really_ hard architectural challenge (imagine
| reimplementing @Transactional in pure Java) and that 's where
| Spring shines.
|
| Yeah, it's sad, I like Groovy a lot. It got relegated to a
| second-class citizen role on Jenkins, for the most part.
| Kuraj wrote:
| 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
| motorest wrote:
| > 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 problem vanishes and all your code suddenly is
| unit testable.
| Kuraj wrote:
| 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.
| motorest wrote:
| > We don't really have this problem in .NET 8, we mock
| stuff just fine using an in-memory database provider.
|
| No, you don't. At best in-memory databases represent a test
| double that you can use in integration tests.
|
| If you need to write unit tests, EF leaves you no better
| option than to add repositories to abstract out everything
| and anything involving DbContext.
| acedTrex wrote:
| What you dont like public class
| Repository<TEntity> : IRepository<TEntity> where TEntity :
| class { public async Task Add(TEntity entity)
| { _context.Add(entity); await
| _context.SaveChangesAsync(); } }
|
| everywhere?
| ashvardanian wrote:
| Singletons are considered an antipattern in pretty much all PLs.
| C++, mentioned in the article, is not an exception.
| eduardofcgo wrote:
| Singleton is the worst example of design pattern, not sure why
| these kinds of posts always like to mention it. Singleton is
| just a hack for avoiding OOP with OOP languages. Obviously
| python allows non OOP code, so not surprised singleton is
| useless there.
| bitpush wrote:
| Great post. I dont write much python these days, but I distinctly
| remember things being suspiciously easy .. to the point where I
| started to wonder why arent things so complicated.
| acedTrex wrote:
| 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 cases
| where an intermediate state could be invalid but a subsequent
| update will update it to a valid state. So you dont want to
| validate on every update.
| xigoi wrote:
| > 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.
| acedTrex wrote:
| The constructor can not do it because the constructor does
| not have all the data. This is lazy evaluation.
| ptx wrote:
| 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)
| chuckadams wrote:
| Builders have some neat properties like partial evaluation,
| which becomes especially neat when you use stateless builders
| that return new instances. They can also be subclassed,
| allowing not only behavior that can be overridden at
| individual method granularity, but able to build a different
| subclass.
|
| Obviously don't reach for a builder if you don't have these
| use cases though.
| zem wrote:
| I've used the builder pattern in python when I wanted to have
| the mutable and immutable version of a class be different
| types. you do a bunch of construction on the mutable version
| then call "freeze" which uses the final data to construct the
| "immutable" class.
| eduardofcgo wrote:
| Could you not just use dicts and some schema validation logic
| for this?
| kamma4434 wrote:
| I got a feeling the author has but a vague idea of what Java and
| C++ are.
| ayhanfuat wrote:
| Brandon Rhodes has a series of talks on this topic. Here's the
| most up to date one:
|
| Classic Design Patterns: Where Are They Now - Brandon Rhodes
| (https://www.youtube.com/watch?v=pGq7Cr2ekVM)
| zem wrote:
| I remember the fad for dependency injection frameworks in ruby,
| and the eventual similar pushback pointing out you could just use
| the language features for most of it
| mekoka wrote:
| If I had but one design pattern I would just LOVE to see
| disappear from Python, it's the need for super(). Don't get me
| wrong, super() is a clever piece of engineering, but if your code
| actually _needs_ what it 's useful for (C3 linearization, MRO,
| etc), then you've made things too complicated. I deplore the
| proliferation of libraries that have embraced the seductive, but
| ultimately deceptive ways of the mixin, because they saw all the
| big boys reaching for it. The devil gave multiple inheritance a
| cooler name, some new outfits, and sunglasses to confuse the
| Pythonistas and they embraced it with open arms.
|
| Refactor to favor composition over inheritance. But if you really
| must inherit, single over multiple, and shallow over deep.
| Eventually your code will less and less need super() and it'll
| become pointless to use it over the more explicit mechanism,
| which incidentally makes everything cognitively lighter.
| eduardofcgo wrote:
| The programmers that insist in using type hints in python usually
| are the ones that makes these mistakes. I think the main reason
| that these patterns do not make sense is because python is a
| dynamic language. If you turn off the part of your brain that
| thinks in types you realize that you can solve most of these in
| plain functions and dicts. Using default args as replacement to
| the builder pattern is just ridiculous. If you want to encode
| rules for creating data, that screams schema validation, not
| builder pattern.
| crgwbr wrote:
| Python type hints are hugely valuable both as a means of
| correctness checking, but also just as a means of
| documentation. It strikes me as incredibly shortsighted to say
| you can forget about types just because it's a dynamic
| language. The types are absolutely still there and need thought
| about. They just aren't defined or used in terms of allocation
| and management of memory.
| david422 wrote:
| > The types are absolutely still there and need thought about
|
| Yes, if they aren't in the code, it just means the programmer
| has figure out and carry that around mentally when reading or
| writing code.
| eduardofcgo wrote:
| Usually with OOP several builders are composed together to
| express the creation of some data. These builders have
| functions with types, which define the rules for the creation
| of the objects.
|
| My point is that the CarBuilder is not a real type that
| relates to the business, but something that we had to create
| to encode some behaviour/rules.
|
| Some function that validates that a dict is a valid car is
| much more explicit that lots of different builder classes in
| my opinion.
___________________________________________________________________
(page generated 2025-08-01 23:01 UTC)