Hi Gilad
I've been thinking about a related issue: so-called "convenience methods". These turninto "nuisance methods" if they get into the base platform, because they create bloat and new users are confronted with a huge API that they must sort through. On the other hand, these methods are convenient.
One approach is to use class hierarchy inheritance. If you want twenty additional methods in the collection hierarchy, you create a module that is designed to act as a mixin that will be applied to the existing collections module, and use that.
I think part of my examples not simply related but exactly concern problem of "convenience methods". Incidentally I've came up with different conclusion. Maybe I just do not see some obvious solution.
I'll try to clarify my opinion.
I'll again use my "real life" scenario as example. So I'm adding some internalization to my application. It's boil down to Class I18n with method
translate: aValue <String>
On this point in full squeak programming mode I would like to add "convenience method" i18n to String. i.e.
i18n <String> = (
^I18n translate: self
)
That method is convenient in usage and very similar to such a "convenient methods" of squeak base as
asPoscript,
asAlien,
asURI and so on.
But adding such a "convenient method" is not only a badthing but just does not works for me in Newspeak programming mode. The freshly added to String "convenient method" will be absent in deployment image and raise DNU in deployed application.
(And BTW I would say I understand and agree that it is right and good from many points of view)
But how ability to create mixin - say InternalizationAwareString - with such a method would help me to sugar code in that situation?
I basically have 3 patterns of usage of message i18n
'someStringLiteral' i18n
someMethodInMyModuleReturningString i18n
someMethodFromBaseClassReturningString i18n
Literal and methods of external class will return ByteString, unaware of i18n.
and
someMethodInMyModuleReturningString would look like
someMethodInMyModuleReturningString = (
^InternalizationAwareString fromString: 'someStringLiteral'
)
and that doesn't loook more convenient then original I18n translate: self.
Actually while I may imagine some scenarios where class inheritance approach may help to emulate "convenient methods" usage pattern - as a rule, I think such scenario as in my case is prevailed. (BTW another my case - with tooltips - is very similar. In that case I would like to add convenience method to Fragment). And for such a scenario mixins IMO are not relevant.
I'm not quite sure, but I guess relevant would be some variation of macro system as in Lisp world.
I imagine macro section in top level class declaration which stated something like:
Anything i18n => (I18n translate: Anything) .
Anything tooltip: aStr => Anything addDecorator: (TooltipAgent new tooltip: aStr) .
And i result of such declaration inside my module Parser substitute left part of macro statement with right one.
so
button: 'someLabel' i18n action: [nothing]
would be substituted by
button: (I18n translate: 'someLabel') action: [nothing]
Nothing did clutter the base system. All works in deployed applpication. Convenience is at upmost level.
Readability hopefully did improved too.
What a dream
