[squeak-dev] message style: few bigs or many littles?
marcel.taeumel at hpi.de
Mon Apr 4 08:22:40 UTC 2022
Hi Lauren --
Let me assume that you want to write source code that is extensible, re-usable, and maintainable. While Smalltalk supports various paradigms, let me further assume that you want to learn how to write using an object-oriented style where you objects remain extensible, re-usable, and maintainable.
To me, your thoughts indicate some bias toward performance optimization. So, let me further suggest that you put those concerns aside for now. Instead, focus on how to write object-oriented source code in a modular fashion. One wants to grow an app, library, framework. One does not design it on a whiteboard to then write it down and be done with it. On the contrary: programmers will constantly read and modify the fragments of their work over and over again. Embrace the mistakes and the chance to correct them. To learn something along the way. About your domain, the language, the libraries.
That is, you want to write code that *you* can understand. You can always tweak the performance later. Actually, modular code allows you to identify and treat the bottlenecks very easily.
For that matter, I suggest that you treat message sends "for free" and focus on how to name classes/protocols/methods, design relationships, and add extra commentary to further document your thoughts.
You mention some design patterns, namely "Builder" (w/ its director) and "Chain of Responsibility." You also mention variation points that are possible due to inheritance/subclassing. So, I assume that you are aware of the trade-offs between architectural design, performance considerations, and tool support. That is, for example, single inheritance may demand for other strategies to implement and document cross-cutting concerns (i.e., concerns whose implementation cross-cuts the primary decomposition).
Well, I don't know about your current projects and goals. What I can further share is my perspetive on how to write good object-oriented code for the Squeak/Smalltalk system, given its shared object space, programming tools, and language concepts.
Provided that I can somehow figure out a good way to decompose the problem into classes that match domain concepts, how to design a class' protocols?
Well, objects send messages to each other. There are no "private" messages per se. Thus, I try to make it possible to be able to send any message to an object at any time. Regardless of it's state. That makes it easier to inspect objects and debug their state. Sometimes, this may lead to larger methods, but often these can typically be regarded short. Yet, I don't care. My goal is to write robust protocols. Consequently, I will not split up a method into parts for the reason of length but rather for the reasons of re-usability and extensibility. It should still be possible to easily inspect instances and poke around with some message sends to better understand what's going on.
I hope this helps. You can read about my most recent work that tries to follow these suggestions via TTFontReader in Trunk. Even for that performance thing. :-)
P.S.: If you are looking for more fine-grained ways to optimize a specific algorithm of yours, ask Levente as he has many useful tricks in how to write methods that should produce efficient byte codes. ;-) Yet, at that microscopic level, it's not primarily about object-oriented design anymore.
Am 01.04.2022 09:45:58 schrieb Lauren P <drurowin at gmail.com>:
The Forth and Lisp upbringing in me is wanting to create more methods that do fewer things each. So I was curious what seasoned Smalltalkers have to say. Do you like more littles or fewer bigs?
For those not familiar, in Forth and Lisps function calls are free, so it makes not a lot of difference if you write 10 1-statement functions that call the next in line, or 1 10-statement function that does it all, broken up roughly by the amount you can comprehend without pretty-printing and commenting.
Here are my thoughts:
Obviously, a reason not to do so is the need to come up with all those names for "1 method for 1 action", but I use noweb outside of Squeak so I've gotten pretty good at that.
Another would be a performance penalty of having to do a method lookup more often.
For pros, the most apparent is making more points where the process can be inherited and uninherited. Give a name to "check index is a member of the contents" and a subclass can say "I do this one part faster than my superclass!" without copy-pasting the entire thing.
You could also use tail calls so you don't waste call stack. I see this already happens in a few places like PackagePaneBrowser, where implementation bounces between it and Browser.
For unknowns, there's the director method, which specifies the names of each step and the order they happen, and the chain method, where each method specifies what the next step is.
Director is the best method. It offers a clear specification of the steps that need to happen and offers room for extra steps in between. It also organizes your thoughts in one place for later reading.
Chain is the best method. It allows a subclass to override the default specification at an arbitrary point without needing to stub out steps in the process that aren't applicable. It also doesn't waste methods if you can short-circuit an operation.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Squeak-dev