Normally its the Subclasses where implementation-specific optimizations are done, not in the top abstractions. At the level of Collection, the code should be elegant, expressive, and defining of the responsibilities by the messages it sends. #size is something of Collection, period, there is nothing wrong with sending it, and checking size = 0 is more elegant than a block activation with non-local return.
As a community that respects its user base, we need to consider the *type* of damage that "Change it!" could cause to existing production applications. These applications were built on the expressive implementation, but now they'll be sending #do: to that SQLCollection instead of #size, which will cause the database to retrieve a full ResultSet, send it back to the client, just so it can answer #isEmpty.
Its this kind of "silent" damage that is the worst. Because its invisible, not a an error, not a blow up. Just an degradation in performance (ironic, given our motive here) which, believably, would not be caught in testing.
I agree with Monty. Collection is abstract, there will never be an instance of it. No self-respecting subclass needs this optimized, and trying to optimize it way up there forces too many assumptions about implementation. It makes the code less expressive while silently inflicting potentially performance-killing pain onto legacy applications until they're forced to sprinkle duplicate #isEmpty implementations all about..
On Mon, Oct 24, 2016 at 3:31 AM, Bert Freudenberg bert@freudenbergs.de wrote:
On Monday, 24 October 2016, monty monty2@programmer.net wrote:
Why not just make #size a subclassResponsibility or add abstract superclasses for lazy or infinite collections that implement #isEmpty using #do: and change #size to shouldNotImplement?
Because #do: is the only method required to be overridden by Collection subclasses. All other methods are implemented in terms of #do:.
So yes, if your Collection subclass has an optimized implementation for #isEmpty, then provide it. That is a small price to pay for making a class work optimally across different code bases.
- Bert -