1 回答

TA贡献1725条经验 获得超7个赞
恐怕没有通用的万能的神奇答案——这完全取决于“几乎”部分以及推动代码中这些部分发生变化的力量。IOW,只能用一个具体的例子来回答......
话虽如此,从经验中吸取了一些教训,这些教训主要在著名的(但不幸的是经常被误解的)GOF“设计模式”一书中进行了总结。如果您花时间先阅读本书的第一部分,您就会明白目录中的大多数(如果不是全部)模式都基于相同的原则:将变体与不变体分开。一旦你可以在你的代码中区分一个和另一个(警告:这里有一个陷阱,初学者几乎总是陷入其中),应用哪种模式通常是显而易见的(有时你才意识到你在你之后使用了这个和那个模式重构了你的代码)。
现在正如我所说,有一个陷阱:意外重复。仅仅因为两段代码看起来相似并不意味着它们是重复的——很多时候,它们现在只是“意外地”相似但会造成其中一种改变的力量大多是不相关的。如果您尝试立即重构此代码,您很快就会发现自己使“通用”案例变得越来越复杂,以支持实际上不相关的更改,最终导致过于复杂、难以理解的混乱,只会使您的代码无法维护。所以这里的诀窍是仔细检查整个上下文,问问自己什么会推动一个或其他“相似”部分发生变化,如果有疑问,等到你知道更多。如果它发生比每次更改 A 时都必须出于完全相同的原因在 B 中进行完全相同的更改,那么您确实有真正的重复。
对于基于我们可以从您过于抽象的示例(和经验)中猜测的更实用的短期建议,至少有两种模式最常涉及在类层次结构中排除重复:模板方法和策略。
注意:我说“不幸的是经常被误解”,因为大多数人似乎跳到模式目录并试图强制将它们全部放入他们的代码中(无论它是否对手头的问题有意义),并且通常通过复制粘贴规范教科书_实现_(通常基于Java或C++)而不是理解_概念_并以既惯用又适应具体用例的方式实现它(例如:当函数是第一类对象时,你不一定需要一个Strategie类抽象基类和具体子类 - 最常见的是普通的旧回调函数 JustWork(tm))。
编辑完全不相关,但这个:
def __init__(self):
# initialize logging
logging.config.fileConfig(os.path.join(os.getcwd(),
'../myconfig.ini'))
self.logger = logging.getLogger(__name__)
不是如何使用日志记录。库代码可以使用记录器,但不能配置任何东西 - 这是应用程序(您的主脚本/函数/其他)的责任,合理的原因是正确的日志记录配置取决于上下文 - 哪种类型的应用程序正在使用库(a CLI 应用程序、本地 GUI 应用程序和后端 Web 应用程序根本没有相同的需求)以及在哪种环境中(例如,本地开发环境需要比生产环境更多的日志)。
此外,使用__name__在您的基类模块中创建的记录器,所有子类都会将它们的日志发送到同一个记录器,这当然不是您想要的(您希望它们拥有自己的包/模块特定的记录器,以便您可以微调每个包/模块的配置)。
最后,这个:
os.path.join(os.getcwd(), '../myconfig.ini')
当然不会像您期望的那样工作-此时您的 cwd 可以是任何东西,而您无法提前知道。如果要引用相对于当前文件目录的路径,则需要os.path.dirname(os.path.realpath(__file__)). 当然,在os.path.join()调用中添加系统特定的路径内容(即“../”)完全破坏了使用os.path.
添加回答
举报