6 ms·
Growing object-oriented software vs. what I would do
- Jtsummers 5y ago> I've quickly realized that the authors have a concrete idea of what an object means to them. I was confused why their code was always so... “callback-y” and after studying it a little more, I've discovered the reason. I might have missed it, but I don't think they ever explicitly state it. All calls between objects are unidirectional: no public method of an actual object (not a plain data class) returns any value. They are always void methods. Objects don't “call” each other. They send a message and don't wait for a response. (Well, actually since they actually “send” it via method call, they do wait, but they pretend they don't. https://en.wikipedia.org/wiki/Command–query_separation https://en.wikipedia.org/wiki/Command–query_separation https://martinfowler.com/bliki/CQRS.html https://martinfowler.com/bliki/CQRS.html That sounds very much like Command-query separation or Command Query Responsibility Segregation to me. I haven't read this particular book (and almost certainly won't be getting to it within the next decade based on my ever increasing pile of unread books), but I wonder if they call this out. It's a critical decision in the architecture/design of a piece of software and it's worth stating that it's how they intend to design the system. Coincidentally, to my mind, that model (CQS/CQRS) fits well with the blog author's idea of using an agent-based event system. Moving the objects into distinct threads of execution or processes, which also coincides with one of the intended ideas of OO by Alan Kay. OO-as-message-passing very much fits within the agent-based execution model.
- crabmusket 5y agoTo the author: if you haven't read POODR, I highly recommend that. It's the book that felt the most "real OOP" to me. No `class Dog extends Animal` in sight. It's written by one of those Smalltalkers, and I think it's got a lot of very valuable ideas about software design, not just OOP specifically. The "callback-y" approach in Growing Object-Oriented Software sounds fascinating. > Immediately I remind myself that the implementation from the book ignores the problem of persistence completely. If you close that application it loses all the state. I think this is not an accident. This is where things go wrong for OOP really fast. This is a really good point. EDIT: I see you really did not like 99 Bottles of OOP, which is by the author of POODR. In that case maybe her way of explaining things doesn't agree with you and you should skip it!
- Jtsummers 5y agoPOODR = Practical Object-Oriented Design in Ruby by Sandi Metz.
- crabmusket 5y agoThanks. I tend to leave it abbreviated because it's always the top Google result!
- deleted 5y ago[deleted]
- josephg 5y agoThis is a hot take but: I have a growing sense that one defining feature of some software engineers is that they’re embarrassed by dense logic. I think you see this in the Java world where people seem to hide the core logic of their program amidst a dizzying array of interfaces and deep function call chains. Maybe with enough DI and whatnot, the business logic itself can melt into the structure of the program. In comparison, C programs tend not to hide this stuff. C functions are often long and complex. If you were implementing quicksort in C, you would write (more or less) one function with all the logic packed in there you can just read top to bottom. In Java it would be a nest of SortComparator interfaces and SortAlgorithm implementors, which would act to hide the algorithm itself. There’s something more honest about the C style. It’s like, yeah, the algorithm is complicated. So we put it all together in one dense function. Here it is - go nuts! You don’t have to go hunting for the right implementing class. Or divine how FooFactory has configured your Foo object instance. All that Java style class abstraction seems to (intentionally or otherwise) make the actual logic of your program hard to find and hard to trace. It’s coy. When I’m trying to read someone’s code, that’s simply never what I want.
- dgb23 5y agoIn A Philosophy of Software Design the author talks at length about this and proposes that "deeper" modules (classes/methods/functions etc.) provide the most cost/benefit ratio, where the interface of a module is the cost and the functionality is the benefit. Code doesn't magically become less complex by hacking it into pieces.
- deltasixeight 5y agoNo hacking code to pieces makes it more complex. The trade off here is that the code becomes more modular. Whether you want your code to be more modular is an opinionated decision but most people don't realize the benefits of high modularity. Almost all major design mistakes that necessitate code rewrites come from lack of modularity.
- sam0x17 5y ago
- theteapot 5y ago> I've purchased three OOP books (in the order I've read them): ... If your gonna pick three books on OOP it should include Design Patterns at the top of the list. At least if you want to understand why OO is a thing people still use and talk about.
- Zababa 5y agoIsn't "Design Patterns" about how to solve problems through an OOP approach, rather than about the strict benefits of OOP?
- codr7 5y agoMore a bag of tricks to get around issues you tend to run into when doing OOP. Bridge comes to mind, I ran into that specific example myself trying to OO-design a GUI framework with different back ends. With a pinch of common sense stuff like Facade etc. Much of it only makes sense for static languages such as C++ and Java. I'd say it gets way more credit than it deserves. Stepanov on OOP is interesting (just search for object oriented): http://www.stlport.org/resources/StepanovUSA.html http://www.stlport.org/resources/StepanovUSA.html
- theteapot 5y agoArticle's stated motivation: > I'm looking to gain more confidence in my criticism and understanding of OOP. In the past, I have published multiple posts criticizing Object Oriented Programming ... I always feel this anxiety that... maybe there is such a thing as “good OOP”, maybe all the OOP code I wrote, and the OOP code I keep seeing here and there is just “incorrect OOP”. To that I'm saying read DP and critique that and if you still feel that way, your on to something. Cherry picking 3 crap OOP books to critique then concluding OOP is crap feels like a bit of a strawman argument.
- Zababa 5y agoAgain, I'm saying that I think DP isn't a good idea because DP is about how to solve problems using OOP and not why OOP is a good idea in the first place.
- jim-jim-jim 5y ago> does anyone really care? I liked this piece. Enough to log in and comment at least. It's the rare article where the author is open about his biases but gives an opposing approach an honest go. Reading three books about OOP is way more generous than I'd ever be. And when that approach still doesn't make sense, he offers a better one. Always enjoy reading the informed hater's perspective.
- ratww 5y ago> Immediately I remind myself that the implementation from the book ignores the problem of persistence completely. If you close that application it loses all the state. I think this is not an accident. This is where things go wrong for OOP really fast. This point hits hard. Managing "live" scattered state that is gonna go away when the program dies is hard in itself. But as soon as you have to persist it or do anything fancy with it, you pretty much have to change the whole approach of your app. This is why it's always a good idea to start with established frameworks that handle persistence if you're ever gonna need it. Bolting-on is just too hard. It also reminds me of my first job, in a Desktop app. State became so complex that to apply a "global change", like currency or language, it was required to close the app and open again. It was something very common, seeing how many apps required such things. In the middle of my career I also worked in a very large video game. The higher ups wanted to change how "game saving" worked and instead of having to serialise just the basic stuff (health, lives, level) we needed to change it to serialise the whole game state including enemy positions and actions. It was the biggest change we did and we ended up having to add lots of boilerplate because of the scattered state. IMO, ECS was a very interesting development purely because now state is not encapsulated anymore, making serialisation completely separate from everything else. Curiously, as much as modern frontend programming is maligned, such issues are easier to solve with central state management libraries like Redux.
- neutronicus 5y agoHa I do like how ECS and Redux have that common thread of rediscovering global state
- ratww 5y agoTrue. There's lots of parallels between those two things and relational databases, too. In the end it seems that the "web app with a database" is becoming the template for other types of apps.
- amw-zero 5y agoHere’s another review / critique of this book, but with a full implementation based on the author’s grievances: https://enterprisecraftsmanship.com/posts/growing-object-oriented-software-guided-by-tests-without-mocks/ https://enterprisecraftsmanship.com/posts/growing-object-ori.... The main point of it is to avoid testing via mocks and to also avoid interfaces that are only there for testing purposes. The end design is extremely simple, and because it has command / query separation, the actual logic is trivially testable. Give it a read. I love Growing Object oriented software guided by tests as well, these are all just different approaches with different mindsets.
- rytor718 5y agoI really enjoyed reading this one and loved the example. Unwittingly I found that my approach feels similar to what the author did as far as isolating the domain and writing unit tests. I learned some new things as well. Thanks for the link.
- Zababa 5y agoThe part about data is interesting. I remember than in Clean Code, Robert Martin made the distinction between "data structures" (objects that have lots of parameters, few functions) and "objects" (objects that don't have many parameters, lots of functions). The author seems to have rediscovered this distinction here. If people keep rediscovering it, maybe an object is a too abstract building block? Maybe languages should offer a struct/dataclass/record as a basic building block too?
- ratww 5y agoJava offers Records now, which are pretty much that. Pretty cool feature IMO: https://docs.oracle.com/en/java/javase/14/language/records.html https://docs.oracle.com/en/java/javase/14/language/records.h...
- Zababa 5y agoRecords seems very nice! What I wonder is if people are going to use them, considering Java is a bit old at this point and lots of code already exists. Refactoring to use object would be a heavy cost. Maybe some new framework and ecosystems will appear based on new features of Java?
- ratww 5y agoRefactoring to use them is not really hard, as they are easily interchangeable with regular classes. They are pretty much syntax sugar for this class pattern here: https://stackoverflow.com/a/63615514 https://stackoverflow.com/a/63615514
- kazinator 5y ago> That discovery blew my mind initially. I panicked. “OMG, is this the secret sauce? Is the joke on me? Not only is that not the secret sauce, an OOP program with almost nothing but methods that return nothing (i.e. have some effect without reporting a result), is a giant red idiot flag.
- deleted 5y ago[deleted]
- terrorOf 5y agoI found this post ridiculous indeed. Actor + event design can still be implemented with OO design as well as with any other designs. So the author is comparing apples to oranges. And the code put up on Github does not give a good example of OO design either. I agree on one point: it does not change anything.
- PaulDavisThe1st 5y agoThings I've learned from 25+ years of programming in C++ (and 5+ years of C before that): 1. not all software is about pushing and pulling to/from a database; if yours isn't, be sure you understand why that's the case. 2. "backends" (not "web backends", but the more general "where the mechanisms are") should know nothing about "frontends" (again, not web, but the more general "user interface of some kind"). This is really just MVC in its most basic sense. One good way I've found to think about this is to assume that there's always at least two UIs running simultaneously. Make sure this can work. 3. if your program has a user interface, everything the user can do without further interaction should be represented by a closure that can be invoked from anywhere (but always in the correct thread). 4. single-threaded GUI code seems like a limitation but in most projects, it's the right choice. By all means use helper threads when needed, but never allow them to use any API that's part of your GUI toolkit. Knowing that your GUI code is ALWAYS serialized is a huge conceptual assist when reasoning about behavior. 5. access to an excellent cross-thread message queueing system is likely to be a must if your software uses threads. This should include a way for one thread to cause arbitrary code execution in another thread. 6. direct memory access for the UI is nice from a programming perspective (that is: just directly call methods of backend objects), but can erode the wall of separation between the UIs and the backend. 7. lack of direct memory access for the UI(s) can significantly impede performance, but enforces a conceptual clarity that can be valuable. 8. when notifying the View(s) about changes in the Model(s), there's a tradeoff between fine-grained notifications ("frob.bar.baz.foo just changed") and high-level notifications ("something about frob just changed"). Finding the sweet spot between these two can be a challenge across the life of a long-lived piece of software. 9. lifetime management will never be trivial. Accept it, and move on to thinking about how it is going to work even if it is not trivial. 10. try to refer to as many things as possible indirectly. if something has a color, don't make it's state refer to the color, but the name or ID of the color. do not over-use this pattern when performance matters, but also do not over-estimate your ability to understand when performance matters.
- athrun 5y agoA lot of wisdom to unpack here. Thank you for sharing!
- 5y ago
- mistrial9 5y ago> does anyone care? I do care and I read this with interest just now. The idea that it took three hours to write a review of a month+ of work as part of "professional development" and that this person must bear that costs of that education, is a tip of the iceberg indicator to me as to the difficult work world we live in today. How is it that capital owners make money while sleeping, while craftsmen intellects spend a month+ without compensation to "get up to speed?" I am on the tail end of this after decades and it jumps out for me now, past the OOP part. Second - I learned OOP approaches long ago, have written a lot of software and have used OOP in my own ways, much like this author. I appreciate the effort here! It is an interesting, technically somewhat shallow (no code in this essay) yet as noted, good balance of critical and open mindedness. I do not understand OOP-hatred past "I hate the music my parents liked" and "Java is so tedious that it makes me hate all of the whole structure of it". I used OOP code myself to separate parts in loosely coupled systems of several flavors; to make a systematic ordering of commands, to enable scripted or menu-driven command sets; and to wrap an interface around data for the convenience of other code. I feel that a strong point of OOP is to REDUCE the cognitive load for the human. Yet many snipes in articles about OOP specifically complain about the lengthy, spread-out, tedious nature of OOP code. Your mileage may vary ! Use it badly or use it well .. its not my doing. The specific kind of software system described in the third book here, with messages passed without state between objects, is interesting, and reminds me to say now: I think there is vastly insufficient distinction made between software solutions, their design and implementation, in OOP criticism. What are you trying to solve? How much persisted data is there? or state, or interface to XYZ external system. This matters in design choices and I feel like OOP-critics often race to their favorite annoying thing rather than do the intellectual work of distinguishing for a reader, what the assumptions are and what the finished product requires.. Overall, this essay is worth reading, feels short to me despite obvious effort on the part of the author, and personally, I get a nagging feeling that people doing this kind of work should be less scammed by low-morals middlemen and more valued socially for the architects of software that they are.
- wangvnn 5y agohttps://twitter.com/martinfowler/status/1423700358233305096?s=19 https://twitter.com/martinfowler/status/1423700358233305096?... This made sense for me right before I gave up on good OOP.
- mbrodersen 5y agoWhat an excellent read. His approach is very similar to how I have developed successful software for years. It scales from the smallest throw away code to the largest Enterprise system and is flexible/adaptable without 27 levels of empty abstractions.