3 ms·
What annoys me (only slightly) in the Ruby community, is it's loose and often "wrong" usage of design patterns. IMHO, the whole idea of "design patterns" is th
by berkes 1y ago
What annoys me (only slightly) in the Ruby community, is it's loose and often "wrong" usage of design patterns.
IMHO, the whole idea of "design patterns" is that they are a standardized way of doing stuff. So that when someone, regardless of language, says "use an abstract factory" we know what it does, how it can be used, what it doesn't do, it's pitfalls etc.
What ruby calls "decorators" aren't "decorators". That's for this DIY implementation, but even more so for "Draper".
It's not only that an actual Decorator should not introduce new methods, but also how it's set-up and used. And therefore, what it's pitfalls and downsides are.
In the case of Draper or this DIY: the views now rely on a concrete and specific subclass - losing both LSP and DIP. Worse: the layer using it -views- aren't the one setting it up or controlling it - the controllers. So it introduces very hard dependencies between different domains - the views/partials/serializers now depend on whether or not you've remembered to actually decorate the model. Something that in my experience will go wrong and will crash in production - or if you're lucky and have lots of E2E tests, in CI.
The same "imprecise use of design patterns" happen with MVC, Models, ActiveRecord, "interfaces" and so forth. Often because of limitations of Ruby, but rather often because the Ruby community just uses the term "wrong".
- baobun 1y ago> Often because of limitations of Ruby wat. If anything I think Rubys lack of limitations could be the issue. There's a thousand different ways to do anything, and people do.
- deleted 1y ago[deleted]
- berkes 1y agoRuby doesn't have "interfaces" - obviously, because it doesn't have types or a type-enforcement. So any design pattern, architecture or concept that relies on types, or interfaces, are "limited" in that sense. Ports, Adapters, Strategy, for example " require" interfaces in their definition. Their benefits rely on interfaces, so if a language lacks this, you really only get the downsides. Factory, Observer, Decorators, etc mention them, and use them, but can be implemented without them. Maybe "limitations" isn't the best word, because e.g. "an interface" is a deliberate limitation, imposed and designed by the developer.
- nsonha 1y agoyeah I'm not familiar with rails and when I read this I was like what do they think a decorator is? Something that literally decorates with colors?
- berkes 1y agoYes, that's very much how the Rails community thinks about "decorators": something that "decorates" the UI elements.
- arthurlewis 1y ago> It's not only that an actual Decorator should not introduce new methods Maybe I'm misreading you, but I've never seen a definition of the Decorator pattern that doesn't involve new methods on the Decorator. If that's what you mean, can you say more? If not, what do you mean?
- arthurlewis 1y agoOH WAIT I SEE IT I'M THINKING OF THE FACADE PATTERN. Yes, the Ruby community does tend to conflate Decorator, Facade, and Presenter in very confusing ways.
- Fire-Dragon-DoL 1y agoI mean, the ruby community thinks of draper when they talk about Ruby's decorators, so they have a unified definition, even if it conflicts with the definition outside of ruby world
- berkes 1y agoFWIW: I was referring to this: > Note that decorators and the original class object share a common set of features. In the previous diagram, the operation() method was available in both the decorated and undecorated versions. and > GoF Book, "Design Patterns: Elements of Reusable Object-Oriented Software", p.166: > "A decorator object conforms to the interface of the component it decorates so that its presence is transparent to clients."
- RangerScience 1y ago> IMHO, the whole idea of "design patterns" is that they are a standardized way of doing stuff To disagree - Design patterns are a communication language. You use them to talk about code; if you use them as strict recipes they become dogma, with all the problems that entails. Beyond that - most of the canonical design patterns are coping mechanisms for the limitations of pre-modern Java / strict OOP. You just plain don’t need them in a language like Ruby - IMO, mostly because of ‘yeild’. The “imprecise use” is a consequence of either trying to use an unnecessary design pattern, or trying too dogmatically to adhere to one.
- berkes 1y ago> communication language I very much agree. But that means when we both say "decorator pattern", we must mean the same. The thing that in the Ruby community is a "Decorator" isn't a "decorator pattern". It's not following the details, but also not even meant for the use-cases or to solve limitations of ruby or strict OOP. It's simply not a "decorator" that we both think of (or would google, or read in e.g. GoF). It's something entirely different. In ruby/Rails (draper gem, most notably), they happen to use the word "Decorator" for a system that makes "view helpers" OOP rather than the normal rails way of a large bucket of random global helper-functions. I've had this conversation that shows the problem: - Me: If we'd use the decorator pattern, we could easily tame that large clumsy tree of subclasses in our authorization logic and make it much easier testable and understandable. - Wat? Decorators? But our authn has nothing to do with views! Why would we want to pull views-logic into our authn layer? So, by using the term wrong, at least N=1 shows how the "communication language" of Design PAtterns fails.
- arthurlewis 1y agoCouldn’t get this idea out of my mind so I went back to the GoF text: > Decorator subclasses are free to add operations for specific functionality. For example, ScrollDecorator’s ScrollTo operation lets other objects scroll the interface if they know there happens to be a ScrollDecorator object in the interface.
- berkes 1y agobut also the next sentence: > ...The important aspect of this pattern is that it lets decorators appear anywhere a VisualComponent can. That way clients generally can't tell the difference between a decorated component and an undecorated one, and so they don't depend at all on the decoration. and further on: > The decorator conforms to the interface of the component it decorates so that its presence is transparent to the component's clients.