Design: Idiom for classes and methods that are customizable by the user?
Marko Rauhamaa
marko at pacujo.net
Thu May 12 18:01:53 EDT 2016
Dirk Bächle <tshortik at gmx.de>:
> I'm one of the SCons (http://www.scons.org) developers
I take the opportunity to thank you and your colleagues for the
wonderful building tool that I have used professionally to great success
since 2003.
> We're a build system and all the code is written in Python. Even more
> so, our build scripts (build description files) are Python
> scripts...allowing the user to have the full power of this beautiful
> language at his/her fingertips whenever it's needed.
It is indeed great to have Python available when needed. However, I have
striven not to need it. SConscript files should be understood by casual
maintainers who aren't necessarily fluent with Python.
> To put it shortly, the user should be able to slip a new Taskmaster
> under the covers of SCons...and it should behave as if it would've
> been built-in.
I have tried to resist the temptation, successfully so far.
> # The built-in Taskmasters
> types = {'default' : DefaultTaskmaster,
> 'noclean' : NocleanTaskmaster}
>
> def create(key, targets, top, node):
> """ Simple factory for creating an actual Taskmaster,
> based on the given key.
> """
> if key in types:
> return types[key](targets, top, node)
>
> return DefaultTaskmaster(targets, top, node)
>
> def add(key, taskm_class):
> """ Register the given Taskmaster class, if its key doesn't
> exist yet.
> """
> if not key in types:
> types[key] = taskm_class
>
> [...]
>
> - Is this a good approach
As an approach, that looks ok. The code looks a bit too lenient, though,
which can easily surprise and baffle the user. I think it would be
better to fail:
========================================================================
class AlreadyExistsError(Exception):
pass
types = {}
def create(key, targets, top, node):
""" Simple factory for creating an actual Taskmaster,
based on the given key.
"""
return types[key](targets, top, node)
def add(key, taskm_class):
""" Register the given Taskmaster class, if its key doesn't
exist yet.
"""
if key in types:
raise AlreadyExistsError("Task manager '%s' already exists" % key)
types[key] = taskm_class
# The built-in Taskmasters
add('default', DefaultTaskmaster)
add('noclean', NocleanTaskmaster)
========================================================================
> - Are there other options that have stood the test of time under
> operational conditions? If yes, I'd be interested to get links and
> pointers to the corresponding projects (I'm prepared to read stuff and
> do further investigations on my own).
Based on the given information, I can't give recommendations. However,
in general, I'm suspicious of the factory pattern. Whenever possible, I
prefer explicit construction.
For example, why do you need a key? Couldn't you simply pass the task
master class as an argument?
Marko
More information about the Python-list
mailing list