crabmusketa 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.
lastofus2 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!
crabmusket2 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.
inopinatusa day ago
Avdi Grimm preaches a similar gospel.
giraffe_lady2 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.
jonathaneunice18 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.
robomc2 days 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?
jonathaneunice17 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.
SiempreViernesa 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".
inanepenguin16 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.
kubav12 days ago
Is the book DRM free? Sorry to be this paranoid, but you cannot be sure today.
bityard2 days 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.
kubav12 days ago
I checked it but found only the same pages as you. This is the reason I asked.
faizmokha day ago
Yes, I have one. It's DRM free.
tomstuart2 days ago
Yes, it is.
dangsuxa day ago
[dead]
elashri2 days ago
Previous Discussion
Bottles of OOP - https://news.ycombinator.com/item?id=12129821 - July 2016 (71 comments)
chiraua day ago
that was not for the Python version
janislawa day 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.
gigatexala 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
yxhuvuda 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.
crabmusketa day ago
Mainstream OOP languages (looking at you Java) have failed to make composition as convenient as inheritance.
flakesa 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.
crabmusketa 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?
flakesa 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.
yxhuvuda day ago
How is composition inconvenient?
mdaniel15 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
watwuta day ago
How is composition in Java inconvenient?
vram22a 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+...
Toutouxca 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.
bccdee19 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.
Toutouxc18 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.
bccdee11 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).
gigatexala 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.
gigatexala 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.
inopinatusa 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.
dennisy17 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?
teraflop2 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".
Stratoscope2 days ago
Note to anyone who submits an article: If the title gets mangled like this, edit it.
codetrottera 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.
amelius21 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.
layer817 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.
jdminhbg19 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.'
zombota day ago
> edit it.
How???
Jtsummersa day 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.
[deleted]20 hours agocollapsed
hansvm21 hours ago
Here I was assuming bottles might fit nicely into the Flask ecosystem.
randlet19 hours ago
There's already a bottle web framework [1]. It came out around the same time as Flask I think. It might have even started as a spoof of Flask even? Or vice versa?
darrenf19 hours ago
IIRC, it's vice versa. Bottle predates Flask by a few years I think.
Edit to add: Bottle's own FAQ says so: https://bottlepy.org/docs/dev/faq.html#what-about-flask
km14420 hours ago
Why does HN automatically edit titles??
corytheboyd20 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.
[deleted]2 days agocollapsed
zombota day ago
> HN's automatic title editing strikes again.
Demonstrating for the umpteenth time that automated clairvoyance is an idiotic idea.
cutlera 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).
chipdarta 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.
galangalalgola 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.
layer816 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.
ryao15 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.
carmackfan14 hours ago
Your problem was a misuse of inheritance, not encapsulation or interfaces.
Sohcahtoa8212 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.
nailera day ago
A. OOP as practically implemented for the last 25 years is glueing functions to state
B. Functions and structs.
corytheboyd19 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.
lioeters19 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.
chipdart19 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.
nineplay18 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.
chipdart19 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_vD19 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?"
nineplay18 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'.
InDubioProRubioa 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.
lelanthrana 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.
bnchrch19 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.
lelanthran8 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.
ejflicka 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.
kolja005a 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.
[deleted]a day agocollapsed
henning2 days ago
[flagged]
PaulRobinson2 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.
[deleted]2 days agocollapsed
henning2 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.
InitialBPa 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.
otteromkrama day ago
Thank you for using snake_case.
That's all I got. Best of luck!