Sometimes the number of kwargs of a method increase to a level where I think it should be refactored.
Example:
def foo(important=False, debug=False, dry_run=False, ...):
....
sub_foo(important=imporant, debug=debug, dry_run=dry_run, ...)
My current preferred solution:
class Args(object):
...
def foo(args):
sub_foo(args)
First question: How to call Args
? Is there a well known description or design pattern?
Second question: Does Python have something which I could use as base class for Args
?
Update
I use Python work daily since 13 years. I used methods with many kwargs and wrote methods with many kwargs. During the last weeks a read the book "clean code" and I liked it. Somehow it is like wearing an other pair of glasses now. My old code works, but it is not nice to look at. Splitting long methods into several smaller methods is easy. But I am not sure how to handle methods with kwargs-bloat.
I think what you've described is an example of the "Context" design pattern.
I usually call your "Args" a "Context" (or a "FooContext" if it's foo-specific enough).
I think the best explanation I saw was here: http://accu.org/index.php/journals/246 ("The Encapsulate Context Pattern", by Allen Kelly in Overload Journal #63 - Oct 2004, which I saw from another SO answer: https://stackoverflow.com/a/9458244/3427357).
There's also some decent papers that elaborate further if you want an in-depth exploration: http://www.two-sdg.demon.co.uk/curbralan/papers/europlop/ContextEncapsulation.pdf https://www.dre.vanderbilt.edu/~schmidt/PDF/Context-Object-Pattern.pdf
As pointed out by yet another SO answer (https://stackoverflow.com/a/1135454/3427357), the Context pattern is considered dangerous by some (c.f. http://misko.hevery.com/2008/07/18/breaking-the-law-of-demeter-is-like-looking-for-a-needle-in-the-haystack/).
But I think the "Law of Demeter" warnings are about not over-complicating your early design more than they're about cleaning up the cruft that accidentally grew while you were solving other problems. If you're passing an "important" boolean through multiple function call layers you're already going to testing hell, and in that situation the refactor you've described is generally a pure win in my experience.
I don't think there's a standard base class for this in python, unless maybe you're lazy enough to pass an argparse.Namespace as your context object just because you already had your parameter values there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With