Python设计指导:
我是一名非常有经验的开发者,已经用Delphi、C#和C++做了很多复杂的工作好多年了。我一直非常遵循结构化编程、面向对象编程(OOP)、松耦合模块设计等原则。因为我用的这些语言都有内置的方式来强制执行这些概念,比如访问控制、静态类型、接口和抽象类支持等等,所以我依赖这些来组织我的代码。
最近,我开始玩Python几个月了。它有很多很棒的功能让我印象深刻,但我非常怀念那些内置的约束,这些约束能让我更容易保持代码的模块化和有序。不幸的是,我发现很多用Python写的“意大利面条代码”——也就是混乱不堪的代码,甚至来自一些很有声望的来源。我不想点名,但我有几本大牌Python专家写的书,里面的例子充满了让我感到不安的设计(更准确地说,是“反设计”)。在我看来,Python虽然很容易使用,但也很容易被滥用。
我在用Python编码时尽量自律,但我发现要实现这些设计原则需要额外的努力,很多时候我只能依靠自己的记忆来设置和遵循约束,而语言本身并没有提供任何帮助。而且,由于没有“编译时”检查,这让事情变得更加困难——通常你要等到真正运行那段代码时才会发现设计上的缺陷。
所以,我在寻找非常具体的信息:一些例子,或者更好的是一本关于良好结构化Python设计和设计技巧的书——如何最好地实现封装、间接性、非常松耦合的设计等等。
在我看来,一位知名Python书籍作者的糟糕设计——(带有混淆)
def populateList(self, selecteddisk=None):
selected = None ***#Bundling - coupling:***
self.listWidget.clear()
for disk in self.disks.inOrder():
item = QListWidgetItem(QString("%1 of %2/%3 (%L4)") \
.arg(disk.name).arg(disk.owner).arg(disk.country) \
.arg(disk.teu))
self.listWidget.addItem(item)
***#Bundling - coupling:***
if selecteddisk is not None and selecteddisk == id(disk):
selected = item
if selected is not None:
selected.setSelected(True)
self.listWidget.setCurrentItem(selected)
2 个回答
关于设计模式支持:
有一种观点认为,设计模式可以作为衡量编程语言不足之处的一个粗略标准。这将是一个有趣的阅读材料,也可以作为你提到的设计模式是语言支持的限制的反面观点。
我发现,要实现和编译符合设计要求的代码,光靠我自己的记忆而不借助语言的帮助,真的需要额外花费很多功夫。在写代码之前,语言本身并没有给我任何帮助。虽然一些集成开发环境(IDE)提供了一些帮助,但语言本身却没有。
而且,由于“编译时”检查似乎并不能帮我找到普通的逻辑错误,这让事情变得更加困难——通常你要等到真正运行那段代码时,才会发现设计上的缺陷。
Python的设计和设计技巧…… 如何最好地实现封装,
通过封装。在像Java和C++这样的语言中,“封装”意味着到处使用私有的东西。但在Python中,这种做法并不被支持。
我们都是成年人。
你仍然可以像在其他语言中那样进行封装,只是没有private
这个词。
Python提供了属性、装饰器和重写__getattribute__
的方法来实现各种封装技巧。
间接引用,
通过引用其他对象。我不太清楚你具体遇到了什么问题,但也许是你给某个函数传了错误类型的参数。避免这种情况的方法就是阅读你自己写的文档字符串。
非常松散耦合的设计等等。
通过依赖注入来实现。同样,Python在松散耦合方面的工作方式和其他语言是一样的。
你应该深入研究并大量使用文档字符串。
你可能还想使用https://www.sphinx-doc.org来从你的文档字符串生成漂亮的文档。
你也可以使用Python内置的help()
函数来查看你在写代码时写的文档字符串。