Simple pattern for pluggable implementations

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Simple pattern for pluggable implementations

mkobetic
I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:

        ^(OSHandle currentOS = #win32)
                ifTrue: [ BCryptCipher basicNew initialize ]
                ifFalse: [ LibCryptoCipher basicNew initialize ]

I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.

I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.

Thanks,

Martin


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

Steven Kelly
[vwnc] Simple pattern for pluggable implementations
This sounds like a case for splitting behaviour into classes rather than into switch-case or if statements. Maybe you could implement #newCipher in the class hierarchy that mirrors supported platforms (IIRC something like OSSystemSupport, Win32SystemSupport - I don't have VW here!). E.g. :
 
OSSystemSupport>>newCipher
^self newCipherClass basicNew initialize.
 
OSSystemSupport>>newCipherClass
^BCryptCipher
 
Win32SystemSupport>>newCipherClass
^LibCryptoCipher
 
If the user wanted to make it so all platforms got his new cipher implementation, he could override OSSystemSupport>>newCipher.
 
Steve
PS you might want those methods on the class side, I forget the details!


From: [hidden email] on behalf of [hidden email]
Sent: Wed 16/02/2011 21:02
To: [hidden email]
Subject: [vwnc] Simple pattern for pluggable implementations

I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:

        ^(OSHandle currentOS = #win32)
                ifTrue: [ BCryptCipher basicNew initialize ]
                ifFalse: [ LibCryptoCipher basicNew initialize ]

I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.

I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.

Thanks,

Martin


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

mkobetic
In reply to this post by mkobetic
Thanks Steven,

This would work for my current setup, but I'm not sure it's sufficient. I do want to be pragmatic, but I don't want to shut the door on valid deployment cases. I'm thinking of scenarios like:

a) I want Bcrypt on any Windows and LibCrypto everywhere else unless it's one of our old Solaris boxes that doesn't have openssl in which case I want to fall back on a Smalltalk implementation.

b) I want BCrypt on all Windows unless I'm on one of the big servers with accelerated hw crypto modules for which I need to use different library.

I guess my point is that I'm not sure that the OS will be sufficient discriminator, even if we ignore the fact that the OSSupportHierarchy doesn't really model our platform coverage (it's basically just Windows or Not). So tying it to that hierarchy seems quite limited and it doesn't really provide the pluggable aspect. Many people wouldn't consider having to patch an existing method as pluggable, even though in this particular case it might be quite safe.

"Steven Kelly"<[hidden email]> wrote:

> This sounds like a case for splitting behaviour into classes rather than into switch-case or if statements. Maybe you could implement #newCipher in the class hierarchy that mirrors supported platforms (IIRC something like OSSystemSupport, Win32SystemSupport - I don't have VW here!). E.g. :
>  
> OSSystemSupport>>newCipher
> ^self newCipherClass basicNew initialize.
>  
> OSSystemSupport>>newCipherClass
> ^BCryptCipher
>  
> Win32SystemSupport>>newCipherClass
> ^LibCryptoCipher
>  
> If the user wanted to make it so all platforms got his new cipher implementation, he could override OSSystemSupport>>newCipher.
>  
> Steve
> PS you might want those methods on the class side, I forget the details!
>
> ________________________________
>
> From: [hidden email] on behalf of [hidden email]
> Sent: Wed 16/02/2011 21:02
> To: [hidden email]
> Subject: [vwnc] Simple pattern for pluggable implementations
>
>
>
> I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:
>
>         ^(OSHandle currentOS = #win32)
>                 ifTrue: [ BCryptCipher basicNew initialize ]
>                 ifFalse: [ LibCryptoCipher basicNew initialize ]
>
> I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.
>
> I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.
>
> Thanks,
>
> Martin
>
>
> _______________________________________________
> vwnc mailing list
> [hidden email]
> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
>
>


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

Holger Guhl
In reply to this post by mkobetic
Here is a pattern which I am very happy with, best explained by example.
The objective is associating a nice icon for each kind of file type (extension). For every file type I create a subclass of FileItem which represents the file type and provides the icon. I changed the implementation of
Tools.FileTools.FileItem class on:
	| finalClass |
	(finalClass := self) == FileItem
		ifTrue: [finalClass := self bestClassForFilename: aPlatformFilename].
	^finalClass new initialize: aPlatformFilename
The implementation of #bestClassForFilename: asks each subclass whether it matches the problem. If no subclass matches, then the superclass stands in with the default implementation.
bestClassForFilename: stringOrFilename
	...
	self allSubclassesDo:
		[:each | (each isBestForFilename: aFilename extension: ext) ifTrue: [^each]].
	^self
Each subclass must implement #isBestForFilename:extension:. This is the point where each class can integrate by plain existence and get its share in contributing to the application.
One shortcoming of this approach is the Boolean logic. What if two subclasses say "yes, I am best"? To handle this, I extended the approach slightly. The selection criterion is no longer defined by a Boolean method #isGoodForProblem:. Instead, I designed a method - e.g. #applicabilityScoreForProblem: - that returns a score how good each class can support the problem. The score value is an Integer. Using score values with large gaps between predefined classes (10, 20, 30, ...) gives a good chance for new classes to squeeze in and supersede other candidates that claim to be good for the problem. Competing approaches can easily be tested by redefining the score that gives one alternative priority over the other.

Cheers,
Holger

[hidden email] schrieb:
I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:

	^(OSHandle currentOS = #win32)
		ifTrue: [ BCryptCipher basicNew initialize ]
		ifFalse: [ LibCryptoCipher basicNew initialize ]

I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.

I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.

Thanks,

Martin


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

mkobetic
In reply to this post by mkobetic
Hm, I'd rather not create a hierarchy of mostly empty classes for this, but given that I kinda expect the implementations to subclass the Cipher class, I could traverse the Cipher hierarchy and let the subclasses score themselves. That sounds pretty reasonable.

Another alternative I was thinking of was annotated methods with the body expressing the criteria and the pragma pointing at the implementation class.

"Holger Guhl"<[hidden email]> wrote:

> Here is a pattern which I am very happy with, best explained by example.
> The objective is associating a nice icon for each kind of file type
> (extension). For every file type I create a subclass of FileItem which
> represents the file type and provides the icon. I changed the
> implementation of
>
> Tools.FileTools.FileItem class on:
> | finalClass |
> (finalClass := self) == FileItem
> ifTrue: [finalClass := self *bestClassForFilename:* aPlatformFilename].
> ^finalClass new initialize: aPlatformFilename
>
> The implementation of #bestClassForFilename: asks each subclass whether
> it matches the problem. If no subclass matches, then the superclass
> stands in with the default implementation.
>
> bestClassForFilename: stringOrFilename
> ...
> self allSubclassesDo:
> [:each | (each isBestForFilename: aFilename extension: ext) ifTrue: [^each]].
> ^self
>
> Each subclass must implement #isBestForFilename:extension:. This is the
> point where each class can integrate by plain existence and get its
> share in contributing to the application.
> One shortcoming of this approach is the Boolean logic. What if two
> subclasses say "yes, I am best"? To handle this, I extended the approach
> slightly. The selection criterion is no longer defined by a Boolean
> method #isGoodForProblem:. Instead, I designed a method - e.g.
> #applicabilityScoreForProblem: - that returns a score how good each
> class can support the problem. The score value is an Integer. Using
> score values with large gaps between predefined classes (10, 20, 30,
> ...) gives a good chance for new classes to squeeze in and supersede
> other candidates that claim to be good for the problem. Competing
> approaches can easily be tested by redefining the score that gives one
> alternative priority over the other.
>
> Cheers,
> Holger
>
> [hidden email] schrieb:
> > I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:
> >
> > ^(OSHandle currentOS = #win32)
> > ifTrue: [ BCryptCipher basicNew initialize ]
> > ifFalse: [ LibCryptoCipher basicNew initialize ]
> >
> > I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.
> >
> > I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.
> >
> > Thanks,
> >
> > Martin
> >
> >
> > _______________________________________________
> > vwnc mailing list
> > [hidden email]
> > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

Boris Popov, DeepCove Labs (SNN)
You could probably avoid pragmas by treating nil returns as a false condition.

Sent from my iPhone

On 2011-02-16, at 18:53, "[hidden email]" <[hidden email]> wrote:

> Hm, I'd rather not create a hierarchy of mostly empty classes for this, but given that I kinda expect the implementations to subclass the Cipher class, I could traverse the Cipher hierarchy and let the subclasses score themselves. That sounds pretty reasonable.
>
> Another alternative I was thinking of was annotated methods with the body expressing the criteria and the pragma pointing at the implementation class.
>
> "Holger Guhl"<[hidden email]> wrote:
>> Here is a pattern which I am very happy with, best explained by example.
>> The objective is associating a nice icon for each kind of file type
>> (extension). For every file type I create a subclass of FileItem which
>> represents the file type and provides the icon. I changed the
>> implementation of
>>
>> Tools.FileTools.FileItem class on:
>>    | finalClass |
>>    (finalClass := self) == FileItem
>>        ifTrue: [finalClass := self *bestClassForFilename:* aPlatformFilename].
>>    ^finalClass new initialize: aPlatformFilename
>>
>> The implementation of #bestClassForFilename: asks each subclass whether
>> it matches the problem. If no subclass matches, then the superclass
>> stands in with the default implementation.
>>
>> bestClassForFilename: stringOrFilename
>>    ...
>>    self allSubclassesDo:
>>        [:each | (each isBestForFilename: aFilename extension: ext) ifTrue: [^each]].
>>    ^self
>>
>> Each subclass must implement #isBestForFilename:extension:. This is the
>> point where each class can integrate by plain existence and get its
>> share in contributing to the application.
>> One shortcoming of this approach is the Boolean logic. What if two
>> subclasses say "yes, I am best"? To handle this, I extended the approach
>> slightly. The selection criterion is no longer defined by a Boolean
>> method #isGoodForProblem:. Instead, I designed a method - e.g.
>> #applicabilityScoreForProblem: - that returns a score how good each
>> class can support the problem. The score value is an Integer. Using
>> score values with large gaps between predefined classes (10, 20, 30,
>> ...) gives a good chance for new classes to squeeze in and supersede
>> other candidates that claim to be good for the problem. Competing
>> approaches can easily be tested by redefining the score that gives one
>> alternative priority over the other.
>>
>> Cheers,
>> Holger
>>
>> [hidden email] schrieb:
>>> I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:
>>>
>>>    ^(OSHandle currentOS = #win32)
>>>        ifTrue: [ BCryptCipher basicNew initialize ]
>>>        ifFalse: [ LibCryptoCipher basicNew initialize ]
>>>
>>> I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.
>>>
>>> I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.
>>>
>>> Thanks,
>>>
>>> Martin
>>>
>>>
>>> _______________________________________________
>>> vwnc mailing list
>>> [hidden email]
>>> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
>
>
> _______________________________________________
> vwnc mailing list
> [hidden email]
> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

mkobetic
In reply to this post by mkobetic
Right, that's if we want just Boolean results, but I kinda like the idea of scoring. If you allow negative scores and multiple methods for one implementation, you could change the outcome of previously defined scores without having to override code. As a use-case I'm thinking, what if in particular deployment I decide to install openssl on Windows as well and not use the native bcrypt, I could negate the default scores to favor libcrypto even on Windows. Overkill ?

"Boris Popov, DeepCove Labs"<[hidden email]> wrote:
> You could probably avoid pragmas by treating nil returns as a false condition.

> On 2011-02-16, at 18:53, "[hidden email]" <[hidden email]> wrote:
> > Hm, I'd rather not create a hierarchy of mostly empty classes for this, but given that I kinda expect the implementations to subclass the Cipher class, I could traverse the Cipher hierarchy and let the subclasses score themselves. That sounds pretty reasonable.
> >
> > Another alternative I was thinking of was annotated methods with the body expressing the criteria and the pragma pointing at the implementation class.


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

Holger Guhl
In reply to this post by mkobetic
  Maybe I was not clear enough. There is no need for more class hierarchies other than the classes
that implement the solution. My FileItem example is like that. The subclasses that provide the
helpful stuff just have one more method to return the applicability score.
Ok, if the classes that implement some of the solution variants are not in a common class hierarchy,
this approach must be implemented slightly different. In this case I would rewrite the iteration
method that lists all candidate classes. But the rest remains the same.
The big advantage is that you define a behavior "let's negotiate who can handle the task best" and
you have the classical object oriented answer at the candidate class itself.
Cheers,
Holger

Am 17.02.2011 00:51, schrieb [hidden email]:

> Hm, I'd rather not create a hierarchy of mostly empty classes for this, but given that I kinda expect the implementations to subclass the Cipher class, I could traverse the Cipher hierarchy and let the subclasses score themselves. That sounds pretty reasonable.
>
> Another alternative I was thinking of was annotated methods with the body expressing the criteria and the pragma pointing at the implementation class.
>
> "Holger Guhl"<[hidden email]>  wrote:
>> Here is a pattern which I am very happy with, best explained by example.
>> The objective is associating a nice icon for each kind of file type
>> (extension). For every file type I create a subclass of FileItem which
>> represents the file type and provides the icon. I changed the
>> implementation of
>>
>> Tools.FileTools.FileItem class on:
>> | finalClass |
>> (finalClass := self) == FileItem
>> ifTrue: [finalClass := self *bestClassForFilename:* aPlatformFilename].
>> ^finalClass new initialize: aPlatformFilename
>>
>> The implementation of #bestClassForFilename: asks each subclass whether
>> it matches the problem. If no subclass matches, then the superclass
>> stands in with the default implementation.
>>
>> bestClassForFilename: stringOrFilename
>> ...
>> self allSubclassesDo:
>> [:each | (each isBestForFilename: aFilename extension: ext) ifTrue: [^each]].
>> ^self
>>
>> Each subclass must implement #isBestForFilename:extension:. This is the
>> point where each class can integrate by plain existence and get its
>> share in contributing to the application.
>> One shortcoming of this approach is the Boolean logic. What if two
>> subclasses say "yes, I am best"? To handle this, I extended the approach
>> slightly. The selection criterion is no longer defined by a Boolean
>> method #isGoodForProblem:. Instead, I designed a method - e.g.
>> #applicabilityScoreForProblem: - that returns a score how good each
>> class can support the problem. The score value is an Integer. Using
>> score values with large gaps between predefined classes (10, 20, 30,
>> ...) gives a good chance for new classes to squeeze in and supersede
>> other candidates that claim to be good for the problem. Competing
>> approaches can easily be tested by redefining the score that gives one
>> alternative priority over the other.
>>
>> Cheers,
>> Holger
>>
>> [hidden email] schrieb:
>>> I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:
>>>
>>> ^(OSHandle currentOS = #win32)
>>> ifTrue: [ BCryptCipher basicNew initialize ]
>>> ifFalse: [ LibCryptoCipher basicNew initialize ]
>>>
>>> I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.
>>>
>>> I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.
>>>
>>> Thanks,
>>>
>>> Martin
>>>
>>>
>>> _______________________________________________
>>> vwnc mailing list
>>> [hidden email]
>>> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

Steven Kelly
In reply to this post by mkobetic
I've used that pattern too, and of course it is well known from thinks
like #generality in the ArithmeticValue hierarchy. One possible problem
in your scenario is if two 3rd parties add their own extensions, or even
just with one 3rd party and a change in scoring in the base. It's pretty
likely that the wrong implementation will be picked in that kind of
situation.

A similar situation is found with Process priorities. As new processes
have been added by VW, ourselves, and 3rd party components we use,
they've tended to choose the named priorities (factors of 10), or then a
common priority +/-1. This leads to problems when two processes share a
priority (and the birthday paradox ensures that happens really quickly).

A slightly better scheme is seen in the pragma argument for menu item
positions. I'm not quite sure what exactly makes it better: obviously
using floats extends the number of values, helping avoid collisions;
there's probably also something to do with the fact that a value is more
often clearly a reference to an existing value, plus a bit.

Steve
 
> -----Original Message-----
> From: [hidden email] [mailto:[hidden email]] On
> Behalf Of [hidden email]
> Sent: 17. helmikuuta 2011 1:51
> To: Holger Guhl
> Cc: [hidden email]
> Subject: Re: [vwnc] Simple pattern for pluggable implementations
>
> Hm, I'd rather not create a hierarchy of mostly empty classes for
this,

> but given that I kinda expect the implementations to subclass the
> Cipher class, I could traverse the Cipher hierarchy and let the
> subclasses score themselves. That sounds pretty reasonable.
>
> Another alternative I was thinking of was annotated methods with the
> body expressing the criteria and the pragma pointing at the
> implementation class.
>
> "Holger Guhl"<[hidden email]> wrote:
> > Here is a pattern which I am very happy with, best explained by
> example.
> > The objective is associating a nice icon for each kind of file type
> > (extension). For every file type I create a subclass of FileItem
> which
> > represents the file type and provides the icon. I changed the
> > implementation of
> >
> > Tools.FileTools.FileItem class on:
> > | finalClass |
> > (finalClass := self) == FileItem
> > ifTrue: [finalClass := self *bestClassForFilename:*
> aPlatformFilename].
> > ^finalClass new initialize: aPlatformFilename
> >
> > The implementation of #bestClassForFilename: asks each subclass
> whether
> > it matches the problem. If no subclass matches, then the superclass
> > stands in with the default implementation.
> >
> > bestClassForFilename: stringOrFilename
> > ...
> > self allSubclassesDo:
> > [:each | (each isBestForFilename: aFilename extension:
ext)

> ifTrue: [^each]].
> > ^self
> >
> > Each subclass must implement #isBestForFilename:extension:. This is
> the
> > point where each class can integrate by plain existence and get its
> > share in contributing to the application.
> > One shortcoming of this approach is the Boolean logic. What if two
> > subclasses say "yes, I am best"? To handle this, I extended the
> approach
> > slightly. The selection criterion is no longer defined by a Boolean
> > method #isGoodForProblem:. Instead, I designed a method - e.g.
> > #applicabilityScoreForProblem: - that returns a score how good each
> > class can support the problem. The score value is an Integer. Using
> > score values with large gaps between predefined classes (10, 20, 30,
> > ...) gives a good chance for new classes to squeeze in and supersede
> > other candidates that claim to be good for the problem. Competing
> > approaches can easily be tested by redefining the score that gives
> one
> > alternative priority over the other.
> >
> > Cheers,
> > Holger
> >
> > [hidden email] schrieb:
> > > I'm searching for a simple and elegant pattern for pluggable
> implementations. In my specific case I have different implementations
> of cryptographic primitives for different platforms, so for example
> Cipher class>>new looks like this:
> > >
> > > ^(OSHandle currentOS = #win32)
> > > ifTrue: [ BCryptCipher basicNew initialize ]
> > > ifFalse: [ LibCryptoCipher basicNew initialize ]
> > >
> > > I'd like to preserve the dynamic nature, so that different
> implementations kick in on different platforms, but at the same time I
> want to let people plug in their own, so that everywhere 'Cipher new'
> is used their implementation could be picked up as well.
> > >
> > > I'd like something simple, without throwing around too much
obscure
> terminology and infrastructure. The crypto libraries like to use
> pluggable 'engine'/'provider' mechanisms, but they don't really help
> with the more dynamic aspect that I'm after. I guess I'd like some
sort

> of extensible mapping from some sort of criteria to implementation
> class, but a Dictionary with selection blocks mapping to classes seems
> a bit of an overkill. I guess a simple "factory" block that can be
> completely replaced would do as well, but that seems a bit too
> unstructured. On the other hand the mapping is unlikely to get too
> complex in practice so maybe it's fine. I'd welcome any suggestions.
> > >
> > > Thanks,
> > >
> > > Martin
> > >
> > >
> > > _______________________________________________
> > > vwnc mailing list
> > > [hidden email]
> > > http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
>
>
> _______________________________________________
> vwnc mailing list
> [hidden email]
> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

Paul Baumann
In reply to this post by mkobetic
If performance is an issue then use a global or class variable that is configured for the platform with behavior that you need to be portable. The platform test logic only needs to be run once for the image. Any code that is not portable to all dialects/platforms is routed through the variable. This is the technique I use to make State Replication Protocol portable on most dialects.

AppPortableBehavior>>newCipher
        ^LibCryptoCipher basicNew initialize

AppPortableBehaviorWin32>>newCipher
        ^BCryptCipher basicNew initialize

AppPortableBehavior class>>configurePortalForPlatform
        AppPortal := nil.
        (OSHandle currentOS = #win32)
                ifTrue: [ AppPortal := AppPortableBehaviorWin32 new ].
        AppPortal isNil ifTrue: [ AppPortal := AppPortableBehavior new ].

AppPortableBehavior class>>initialize
        AppPortableBehavior configurePortalForPlatform.

AppPortableBehavior class>>portal
        AppPortal isNil ifTrue: [AppPortableBehavior configurePortalForPlatform].
        ^AppPortal


^AppPortal newCipher

or

^AppPortableBehavior portal newCipher

Paul Baumann


-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of [hidden email]
Sent: Wednesday, February 16, 2011 14:02
To: [hidden email]
Subject: [vwnc] Simple pattern for pluggable implementations

I'm searching for a simple and elegant pattern for pluggable implementations. In my specific case I have different implementations of cryptographic primitives for different platforms, so for example Cipher class>>new looks like this:

        ^(OSHandle currentOS = #win32)
                ifTrue: [ BCryptCipher basicNew initialize ]
                ifFalse: [ LibCryptoCipher basicNew initialize ]

I'd like to preserve the dynamic nature, so that different implementations kick in on different platforms, but at the same time I want to let people plug in their own, so that everywhere 'Cipher new' is used their implementation could be picked up as well.

I'd like something simple, without throwing around too much obscure terminology and infrastructure. The crypto libraries like to use pluggable 'engine'/'provider' mechanisms, but they don't really help with the more dynamic aspect that I'm after. I guess I'd like some sort of extensible mapping from some sort of criteria to implementation class, but a Dictionary with selection blocks mapping to classes seems a bit of an overkill. I guess a simple "factory" block that can be completely replaced would do as well, but that seems a bit too unstructured. On the other hand the mapping is unlikely to get too complex in practice so maybe it's fine. I'd welcome any suggestions.

Thanks,

Martin


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc


This message may contain confidential information and is intended for specific recipients unless explicitly noted otherwise. If you have reason to believe you are not an intended recipient of this message, please delete it and notify the sender. This message may not represent the opinion of IntercontinentalExchange, Inc. (ICE), its subsidiaries or affiliates, and does not constitute a contract or guarantee. Unencrypted electronic mail is not secure and the recipient of this message is expected to provide safeguards from viruses and pursue alternate means of communication where privacy or a binding message is desired.


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: Simple pattern for pluggable implementations

mkobetic
In reply to this post by mkobetic
Right, some sort of 'defaultClass' configured on startup was my first thought, but it gets more complicated when you want to let people override the default with their choice. If you flush the global on startUp it's difficult to establish if it was set explicitly or if it just caches the previous default. So it gets more complicated if you want a bit more flexibility. If you decide nil means "compute default" then the defaults are hardwired in code. And it doesn't give you the option to override in platform specific way (or based on some other criteria).

Ultimately I don't expect performance to be critical here. These things represent complicated, time-consuming algorithms so I expect performance to be dominated by them doing their actual job rather than by still rather minor expense of figuring out which implementation to pick. So my first inclination would be to suppress performance concerns at least initially. I can always look at some sort of caching mechanism later if this turns out to be wrong call.

"Paul Baumann"<[hidden email]> wrote:
> If performance is an issue then use a global or class variable that is configured for the platform with behavior that you need to be portable. The platform test logic only needs to be run once for the image. Any code that is not portable to all dialects/platforms is routed through the variable. This is the technique I use to make State Replication Protocol portable on most dialects.


_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

[7.7.1] Widget Multi-select in Canvas Problem

Hildebrant, Richard
Gang-selecting multiple widgets in the canvas with the mouse appears not
to work in vw7.7.1 - was fine in 7.6.  Selecting multiple widgets, using
shift-select, however does work.  Has anyone else seen this and know of
a fix, if there is one?

Thanks,
Rick

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc
Reply | Threaded
Open this post in threaded view
|

Re: [7.7.1] Widget Multi-select in Canvas Problem

Steven Kelly
Just tried this in the latest 7.8 vw-dev build, and it fails there too.
It seems to select and then deselect them.

Steve

> -----Original Message-----
> From: [hidden email] [mailto:[hidden email]] On
> Behalf Of Hildebrant, Richard
> Sent: 17. helmikuuta 2011 21:23
> To: [hidden email]
> Subject: [vwnc] [7.7.1] Widget Multi-select in Canvas Problem
>
> Gang-selecting multiple widgets in the canvas with the mouse appears
> not
> to work in vw7.7.1 - was fine in 7.6.  Selecting multiple widgets,
> using
> shift-select, however does work.  Has anyone else seen this and know
of
> a fix, if there is one?
>
> Thanks,
> Rick
>
> _______________________________________________
> vwnc mailing list
> [hidden email]
> http://lists.cs.uiuc.edu/mailman/listinfo/vwnc

_______________________________________________
vwnc mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/vwnc