I’m using python to do some research tasks. I have a class hierarchy for “tools”, where each object is an instance of a particular tool. They all share some functionality and have many similarities in their states.
Some of these tools can use one of several methods based on the tool object’s current state. The specific tool I’m going to ask about actually calls functions from external modules instead of methods written in the class directly. The underlying reason for this is to break up the code into multiple files, i.e. not have any huge monster file that has all the various methods and helper functions those methods use, when all it needs at any given time is a particular very-targeted subset. I.e. when the mode of the tool is “clean_house”, I would only functions like “wash_windows”, “vacuum_carpet”, and “ask_girlfriend_for_help”, while when the mode is “do_work”, I use functions like “write_code”, “debug_code”, and “ask_SO_question”. The subsets don’t intersect in any way, i.e. “write_code” would never call “ask_girlfriend_for_help”, etc.
Instead of calling these functions from module scope within the class methods, it seems to me that it’s a better idea to monkeypatch them to the tool’s class, since there are instance methods they need to call that go further up the class hierarchy and modify some (protected) part object’s state that is used later in the destructor.
I know monkeypatching is often considered poor design or last-resort practice when hot-fixes are in order (Programmer’s SE post here), but is it justified in this case? Any alternative code design suggestions?
2
You are not really monkey patching. Monkey patching is the act of using Python’s dynamic nature to change third-party code. What you are doing is using that same dynamic nature to build your class. That is not the same thing, per se.
It sounds like you are delegating functionality to other modules. That sounds like a perfectly fine practice. But I don’t quite see why you’d need to alter your tool to do so; your tool can pass on method calls to an underlying object that is responsible for the actual implementation, based on the current state.
Those responsible objects can still modify the state of the tool, as nothing in Python is private, really.
9