crabmusket a day ago

I'd like to mention that despite OOP being in the title, I thought this book had a lot to teach that isn't specific to OOP architecture or OOP languages. Really, I think the star of the show is TDD and refactoring.

For a short intro to Sandi's style and approach, I always recommend this 35min talk: https://youtu.be/OMPfEXIlTVE?si=Ird6t8uDN86T06Y7

Aside from any specifically educational content, as a talk it is fantastic - funny, smart, well put together.

lastofus 2 days ago

This is one of my favorite software development books of all time. It's the book that finally offered straight forward guidance and wisdom on how to properly utilize OOP language features.

I'm very happy to see it out for Python!

  • crabmusket 2 days ago

    Sandi's earlier book, POODR, was also great. While it is focused on Ruby, most of the advice applies more broadly.

    Reading these two really helped me understand just how impoverished the concept of OOP has become by C++ and Java, from its Smalltalk roots.

    • inopinatus a day ago

      Avdi Grimm preaches a similar gospel.

    • giraffe_lady 2 days ago

      I was so lucky to have run into poodr when I did. Early enough in my career to still feel like I didn't know anything, but with just enough experience to have encountered the problems she was addressing "in the wild." Absolutely formative for me I have no idea where I'd be without it. The only other book to even approach its impact for me is working effectively with legacy code.

  • jonathaneunice 17 hours ago

    Concur. I took Sandi's workshop based on the 99 Bottles book, in Ruby with a Ruby crowd, but was immediately able to apply it to Python programming.

    Very helpful and clear thinking about refactoring out complexity—and not just refactoring for its own sake, but under the constraint that you want to move your program forward, add new functionality, etc. Refactoring with a direction, purpose, and direct payoff.

robomc a day ago

Maybe this is misguided, but it feels a bit to me (comparing the ruby and js versions for example) that this is using the same code examples in both, and neither are really typical of the sorts of code people in either language community would actually write?

  • jonathaneunice 16 hours ago

    The problem: How do you have examples that are simple enough for those learning the refactoring tricks and techniques to quickly grok and be able to work on, and not overly complicated by the kinds of "real-world complexities" that do regularly appear in "real-world code."

    I had the same "this isn't realistic!" complaint when studying the book, but the examples nonetheless helped me see, practice, and adopt the techniques so that I could immediately apply them to the complex production examples I needed to improve. YMMV... but as a former skeptic, "trust the process." Walk that path an work those examples for 5 days, then see how you feel. I was already pretty skilled, including in complex refactorings, and it still leveled me up.

SiempreViernes a day ago

> The 2nd Edition contains 3 new chapters and is about 50% longer than the 1st.

I've never really had the problem that I've read an OOP text and felt "this was too short".

inanepenguin 15 hours ago

While I understand the complaints against OOP, I highly recommend this book to anyone working in an environment where they're working with OOP languages/frameworks. There are plenty of Ruby/Rails shops out there still. At the very least I love the mentality that this book teaches and often recommend Tidy First by Kent Beck at the same time.

kubav1 2 days ago

Is the book DRM free? Sorry to be this paranoid, but you cannot be sure today.

  • bityard a day ago

    You could check?

    The site says, "Available in digital form only (epub, kepub, mobi, pdf). Includes separate books for JavaScript, PHP, Python, and Ruby languages, and beer and milk beverages."

    There is no mention of needing special software to read them, so I think it's safe to guess that there is no DRM. And it's sold directly by the author. Publishers are generally the ones who insist on DRM. It would not surprise me if there was watermarking, but that is not DRM.

    • kubav1 a day ago

      I checked it but found only the same pages as you. This is the reason I asked.

  • faizmokh a day ago

    Yes, I have one. It's DRM free.

elashri 2 days ago

Previous Discussion

Bottles of OOP - https://news.ycombinator.com/item?id=12129821 - July 2016 (71 comments)

  • chirau a day ago

    that was not for the Python version

    • janislaw 21 hours ago

      I have the book and don't speak Ruby at all. Nevertheless, is so we'll written, that you can take the lessons and apply them in any language with virtual polymorphism. A Python version of the book means bigger audience, to the benefit of the trade.

gigatexal a day ago

I’m gonna buy the book but I prefer composition over OOP. I prefer to have an init that takes some params where those params are fully baked clients of whatever services I need and then the class just uses them as needed. I don’t see a lot of value in having a Python class that might have a few or more classes that it extends where all the functions from all the classes crowd up the classes namespace.

Class Foo.__init__(self, db, blob_storage, secrets_manager, …)

Instead of class Foo(DB, BlobStorer, SecretsMgr)

Etc

  • yxhuvud a day ago

    Why on earth do you put composition and OOP as opposing techniques? Composition is just one more technique in the OOP toolbox and there is nothing in OOP that mandates an inheritance based architecture.

    • crabmusket a day ago

      Mainstream OOP languages (looking at you Java) have failed to make composition as convenient as inheritance.

      • flakes a day ago

        The common toolkits today (spring boot, google guice, etc) are much more focused on composition over inheritance, by injecting arguments and implementing pure interfaces rather than extending base classes. Older legacy Java frameworks and bad teachers are more at fault than the Java language itself IMO.

        • crabmusket a day ago

          I take your point, though having `extends` as a first-class language feature surely encouraged that culture and approach in older frameworks right?

          • flakes a day ago

            There are some valid cases where extends really can help, and IMO the language would feel limited without it. Maybe if the language designers had their time back they could have taken an approach like Golang with nested structs and syntactic sugar for calling their attributes/methods.

            The main reason I see new devs opt for extends, is because that was 99% of the content in their Java 101 programming course, not because it exists in the language. Imagine how many more `friend`s we would have in cpp if that was crammed down everyone's throats? :)

      • _old_dude_ a day ago

        Very true, in Java, at least in the last 20 years, inheritance is de-facto deprecated, all new bits and bolts like enums, annotations, lambdas or records do not support inheritance.

        So you have to use composition.

      • yxhuvud a day ago

        How is composition inconvenient?

        • mdaniel 14 hours ago

          Contrast the Java way

              class Delegated implements Base {
                  final Base b;
                  public Delegated(Base b) { this.b = b; }
                  @Override
                  public void printMessage() { b.printMessage(x); }
                  @Override
                  public void printMessageLine() { b.printMessageLine(x); }
          
          with the Kotlin way https://kotlinlang.org/docs/delegation.html#overriding-a-mem...

          OT1H, yes, sane people using IJ would just alt-Insert, choose delegate to, and move on with life. But those misguided folks using VS Code, vim, or a magnetized needle and a steady hand would for sure find delegating to a broader interface to be a huge PITA

      • watwut a day ago

        How is composition in Java inconvenient?

  • vram22 a day ago

    >I’m gonna buy the book but I prefer composition over OOP.

    The GoF book (the design patterns book) says in a page right near the start, "Prefer composition over inheritance", in the middle of an otherwise blank page, presumably to emphasize the importance of that advice.

    As others have replied, composition is one technique you can use in OOP, not something that is the opposite of OOP.

    You can also use composition in non-OOP procedural languages like C, by having a struct within a struct.

    https://www.google.com/search?q=can+you+have+nested+structs+...

  • Toutouxc a day ago

    Then you're going to be pleasantly surprised, because composition is actually a genuine OOP technique and Sandi Metz advocates for exactly this kind of sane OOP focused on encapsulation and objects making sense, instead of masturbating with class hierarchies.

    • bccdee 18 hours ago

      But I've read the book, and her solution to the "bottles of beer" problem involves encoding all the logic into an elaborate class hierarchy!

      I'm not rabidly anti-OOP, but the point at which I turn against it is when the pursuit of "properly" modelling your domain with objects obscures the underlying logic. I feel like this book reaches that point. This is her stance on polymorphism:

      > As an OO practitioner, when you see a conditional, the hairs on your neck should stand up. Its very presence ought to offend your sensibilities. You should feel entitled to send messages to objects, and look for a way to write code that allows you to do so. The above pattern means that objects are missing, and suggests that subsequent refactorings are needed to reveal them.

      Absolutely not! You should not, as a rule, be replacing conditional statements with polymorphic dispatch. Polymorphism can be a useful tool for separating behaviour into modules, but that trade-off is only worthwhile when the original behaviour is too bloated to be legible as a unit. I don't see an awareness of that trade-off here. That's my problem.

      • Toutouxc 17 hours ago

        Well, the entire book is focused on solving a laughably trivial problem, any solution is going to feel excessive. The elaborate object hierarchy that she uses would obviously feel different in real world, complicated domain.

        I found the excerpt in the book and I don't see her mentioning traditional class-level polymorphism (of the Java kind) anywhere around it. What SM generally advocates for is using OBJECT hierarchies to implement behaviors and encapsulate logic, the objects usually being instances of simple (and final!) free-standing classes. All thanks to the ability of any Ruby object to send messages to (call methods of) a different object, without knowing or caring about its type or origin, and the other object supplying the behavior without having to check its own type (because the correct behavior is the only one that the object, being a specialized object, even knows). This is done at runtime and is called "composition" (as in "composition over inheritance") and is different from using pre-built CLASS hierarchies to implement behaviors, aka "inheritance" (as in "composition over inheritance"). In Ruby, composition is Dog.new(Woofing.new), whereas using inheritance (class hierarchies) is Dog.new after you've done "include Woofing" inside the class.

        I don't know Python well, but it seems like the person in the top-level comment expressed their dislike for the second kind.

        • bccdee 10 hours ago

          I should clarify that the elaborate class hierarchy in the book is inheritance-based. When there's one bottle of beer on the wall, she instantiates `new BottleNumber1()`, which inherits from `BottleNumber` and overrides the method `container()` to return the singular "bottle" rather than the plural "bottles" which the base class's `BottleNumber::bottle()` would return (in the javascript edition, at least).

    • gigatexal a day ago

      What’s funny is I did composition for a take home project when interviewing at a place and they said the approach was too complicated and failed me for it. They wanted multiple inheritance instead. Fair enough. Their codebase probably had a lot of it and my not showing it probably told them I didn’t understand it.

    • gigatexal a day ago

      I used to work at a flask shop that did views with 3-5 or more inherited classes. Nobody could really follow how everything worked. It was insane.

      Anyways yeah give me composition and flat classes all day long.

  • inopinatus a day ago

    These are complementary not contradictory ideas. One of the principal takeaways from the Ruby edition (and many of Sandi Metz’s conference talks) is undoubtedly a mindset of, and techniques for, writing compositional OO code.

dennisy 16 hours ago

I have seen quite a few digital books at this price point now. Personally I feel it is quite high, but I assume I am in the minority?

teraflop 2 days ago

HN's automatic title editing strikes again. The title of this submission should presumably be: "99 Bottles of OOP now available in Python".

  • Stratoscope 2 days ago

    Note to anyone who submits an article: If the title gets mangled like this, edit it.

    • codetrotter a day ago

      It definitely took me quite a bit of time from I joined HN until I learned that if you edit your submission title then you can override the automatic edits that HN makes to the title you originally submitted.

      And I would guess that likewise there are still a lot of people that don’t know this.

      Also, sometimes one might not realize that the title got changed until it’s too late to edit the title of the post.

      • amelius 20 hours ago

        I wish HN could just take the url and then fetch the title of the page.

        That would save quite a hassle, especially on mobile.

        • layer8 16 hours ago

          That would be prone to title injection by malicious pages. ;)

          More seriously, HN should instead display an instruction after submitting, informing that the title was changed and that the submitter should check the change and edit if necessary. The issue is that most submitters either don’t seem to notice that the title changed or don’t hit on the idea that they can edit it after the fact.

        • jdminhbg 18 hours ago

          In this case, the missing '99' isn't a typo, it's deliberate by HN to eliminate clickbaity headlines like '7 Ways To Be A Better Programmer.'

    • zombot 21 hours ago

      > edit it.

      How???

      • Jtsummers 21 hours ago

        Same as with comments, submissions have an edit link that works for an hour or so after submission.

        You can only edit the submission title. If you want to edit the link, email the mods.

  • hansvm 20 hours ago

    Here I was assuming bottles might fit nicely into the Flask ecosystem.

  • km144 19 hours ago

    Why does HN automatically edit titles??

    • corytheboyd 19 hours ago

      It’s supposed to kill clickbait titles. In practice it just randomly mangles titles. I don’t get why they don’t remove the feature and instead rely on flagging.

  • zombot 21 hours ago

    > HN's automatic title editing strikes again.

    Demonstrating for the umpteenth time that automated clairvoyance is an idiotic idea.

cutler a day ago

OOP is an industry of its own which generates a ton of incidental complexity. See "Object-Oriented Programming is Bad" by Brian Wills (https://www.youtube.com/watch?v=QM1iUe6IofM) and most of Rich Hickey's excellent videos, especially his keynote at Rails Conf 2012 where he basically told the Ruby crowd they're doing it wrong (https://www.youtube.com/watch?v=rI8tNMsozo0).

  • chipdart a day ago

    > OOP is an industry of its own which generates a ton of incidental complexity.

    I think you're confusing "OOP is used in projects and I've seen accidental complexity in projects" with "OOP generates accidental complexity".

    The truth of the matter is that developers create complexity. It just so happens that the vast majority use OOP.

    I challenge you to a) start by stating what you think OOP is, b) present any approach that does not use OOP and does not end up with the same problems, if not worse.

    • galangalalgol a day ago

      a) I'm not sure what OOP is, and it doesn't seem like the people who tout it are either. I'm sure someone would look at code I think is good and call it OOP, and someone who wouldn't. It is so many buzzwords old at this point that using it is more a label of a viewpoint than a coding style. Combined with the book's apparent focus on TDD and carefully selecting names, it zeros me precisely in on a set of people I have worked with over the years. I don't, as a rule, like the code those people generate.

      b) The best style is no style, or at least pick a more recently popular dogma like FP, at least it gets you easy/safe parallelism in exchange for throwing some of the tools out of your toolbox.

      • layer8 15 hours ago

        The core of OOP is encapsulation (into objects) and polymorphic interfaces. You program against interfaces with well-defined contracts. Implementation details are encapsulated behind those interfaces. The same interface can have different implementations. The same interface-typed variable can point to different implementations at different times within the same program execution. The caller who invokes operations on an interface is supposed to not care about the implementation details behind it, and thus be decoupled from them. Interfaces can have an inheritance/subtyping relationship. (Implementations may as well, but that’s optional.) This enables abstracting over the commonalities of several related interfaces without having to introduce an adapter/proxy object. That’s basically it.

        • ryao 14 hours ago

          After making those interfaces, the moment you need to do something that breaks those interfaces, you suddenly have a headache. I wrote a program in college that daemonizes by being an instance of a daemon class. Years later, people wanted the option to not daemonize. With C, this would be easy. With the way that I did things according to OOP principles in C++, I need to delete all of the code related to starting the program and write it from scratch.

          You could say that I just did not do it right, but that is the problem. You need to know precisely what the future will want to do it right and that is never possible to know in advance. OOP encapsulation is heavily overrated. There are a ton of headaches in C++ that do not exist in C because C does not try to do these things. Ever hear of the diamond problem? It does not exist in C. Nonsensical types that span multiple lines when trying to figure out why there is a type error? Not an issue in C either.

          C++ was advertised as reducing complexity, but in reality, it that encourages developers to drown themselves in complexity. If it were not for C never gaining a widespread STL equivalent, C++ would be far less popular. Sun Microsystems did make libuutil to provide such facilities, but sadly, it never caught on outside of Sun Microsystems technologies. The BSD sys/queue.h is the closest we have to it, but it is only for lists, and we need trees too to get a good equivalent to the C++ STL. That said, libuutil is available through ZFS, so it is not that people cannot adopt its awesome AVL tree implementation on other platforms. It is just that people do not know about it.

          • carmackfan 13 hours ago

            Your problem was a misuse of inheritance, not encapsulation or interfaces.

            • Sohcahtoa82 11 hours ago

              Misuse of inheritance is often the biggest generator of criticism of inheritance, sadly.

              People use the wrong tool for the job, or use it incorrectly, and then blame the tool. It's like using a hammer to play drums, obliterating the drum set, then ranting against hammers.

    • nailer 21 hours ago

      A. OOP as practically implemented for the last 25 years is glueing functions to state

      B. Functions and structs.

      • corytheboyd 18 hours ago

        In the real world, where many people of varying backgrounds and skill levels are editing the same code, if the OOP method becomes a mess, why wouldn’t the functional approach also become a mess? I think that is more the point OP was making. In a vacuum with a single perfect Adonian programmer, seems like the OOP and functional approaches would becomes the same level of maintainable, because we’re in a vacuum of perfection anyway.

        • lioeters 18 hours ago

          In my experience, the mess created using OOP is harder to untangle than the mess created using a functional approach. With the latter, it's simpler to replace a different function for any part of the logic, and the data is always just data; whereas with OOP the method is usually tied up with shared state and other functions.

          • chipdart 18 hours ago

            > In my experience, the mess created using OOP is harder to untangle than the mess created using a functional approach.

            OP complained about accidental complexity, not subjective takes on how hard it is to refactor code.

            Even so, anyone who has any cursory experience with TypeScript projects that follow a functional style can tell you without any doubt whatsoever that functional style is incomparably harder to refactor than any "enterprise-grade" OOP.

            • nineplay 17 hours ago

              > OP complained about accidental complexity, not subjective takes on how hard it is to refactor code.

              The biggest problem with accidental complexity _is_ how hard it is to refactor code. Refactoring code is a huge part of software development.

      • chipdart 18 hours ago

        > A. OOP as practically implemented for the last 25 years is glueing functions to state

        I see you opt to go with a huge amount of handwaving over the question.

        > Functions and structs.

        That's what a class is, and thus OOP, except it supports information hiding and interfaces. So your alternative to OOP is... OOP?

        • Joker_vD 18 hours ago

          I suspect "functions and structs" here meant "functions and structs, separately, instead of gluing functions together with structs into unholy amalgams". Basically, Wirth's "Algorithms + Data Structures = Programs" idea.

          Compare e.g. to "What should a language have instead of Lua-like tables? Maps and vectors" — "But that's what a table is, so your alternative to tables is... tables?"

        • nineplay 17 hours ago

          >>> a) start by stating what you think OOP is

          >> A. OOP as practically implemented for the last 25 years is glueing functions to state

          > I see you opt to go with a huge amount of handwaving over the question.

          I think the question was answered pretty clearly. You can't ask for an opinion ( "what do you think" ) and then criticize the response as 'hand-waving'.

    • InDubioProRubio a day ago

      OOP is a mental crutch that breaks complex problems down into a easy mentally discoverable world/domain model with objects that have a life of their own, that is capable to derive correct results to complex problems via the relations of the objects.

      Meanwhile its creators can not hold the whole complexity in mind (often barely in spec) and still can produce a artifact that produces correct results.

  • lelanthran a day ago

    > OOP is an industry of its own which generates a ton of incidental complexity.

    And that "ton" is still miniscule compared to front-end development which almost completely eschews OOP and has 10x more incidental complexity.

    I guess my point is that, while OOP's incidental complexity is large, it's still insignificant compared to other technology stacks which developers are showing a great appetite for anyway. Things like "incidental complexity" is irrelevant to developers anyway, today, at the tail end of 2024.

    IOW, OOP introduces significantly less $BAD_THING, when the clear majority of developers don't even care about the quantity of $BAD_THING in the first place, making the whole "should we use OOP" argument moot.

    Doesn't matter if you use it or not, the extra introduced incidental complexity is still going to be insignificant due to the complexity load of the entire project, more so in front-end.

    Hence, there's no point in having the argument in the first place.

    • bnchrch 18 hours ago

      Is your argument that

      1. its ok to add incidental and unnecessary complexity

      2. so long as it's less complex than your most complex component?

      Because that's a formula we can all agree leads no where good nor productive.

      • lelanthran 7 hours ago

        > Is your argument that

        > 1. its ok to add incidental and unnecessary complexity

        > 2. so long as it's less complex than your most complex component?

        That is not my argument.

  • kolja005 a day ago

    As it pertains to Python in particular I think OOP is great for libraries but of limited usefulness at the application layer. Things like pytorch's nn.module IMO is a great abstraction, but every time I've tried to map some concrete business concept to an OOP construct I've regretted it.

  • ejflick a day ago

    > OOP is an industry of its own which generates a ton of incidental complexity.

    Code in any form can generate a ton of incidental complexity. The issue isn't the tool rather than the education to properly wield those tools. Especially when you introduce the team dynamic where everyone has varying understandings of what is being built and how it should be built.

henning 2 days ago

[flagged]

  • PaulRobinson 2 days ago

    Can you actually give an example?

    I believe in mechanical empathy. I think developers should - win performance is a concern - think about how their code ends up on the CPU, what ends up on the heap, how caches are used, and so on.

    But for most Python developers, and Ruby developers, it's more important, in more use cases, to have clear and readable code that is easily maintainable.

    I've met Sandi, I've gone through her Ruby books, I recommend her teaching and her books to others. I don't see the problem.

    If you need ASM, use ASM. If you're on a team doing OOP, maybe learn about OOP.

    • henning 2 days ago

      Look at the fastest linting/build tools/runtimes for JavaScript. They are mostly not written in JavaScript, because JavaScript is slow and no amount of hotspot profiling/optimization will fix that. This is also why Python's core data types for dictionaries and so on are not implemented in Python.

      You can also look at any microbenchmark between pure Python and a native language of your choice, even one that uses GC like OCaml or Go, and unless the Python code has been written so that it spends all its time calling C code the way you sometimes can with regex-heavy code, Python will generally lose by a varying margin. These micro inefficiencies multiply at every level hundreds of times over to create needlessly slow, inefficient applications.

      The truth is I can link benchmarks, case studies of app rewrites from Ruby to Go or something comparable, measurements about the results of using NIFs in Erlang/Elixir, etc. all day long but you'll ignore all of them.

      • InitialBP a day ago

        A lot of time (most?) writing software isn't about writing software for the pleasure of doing so, but for building something that helps generate revenue.

        For businesses, having a highly optimized web application that takes a long time to develop and doesn't allow for quick additions of new features is not worth the cost. Instead, they can have a poorly optimized web application with way more features and a faster feature production because Python/Ruby/Javascript are more approachable than other native languages.

otteromkram a day ago

Thank you for using snake_case.

That's all I got. Best of luck!