问题描述
我有那个代码示例:
from time import sleep
import asyncio
class bird:
def __init__(self,sleeptime=1):
self.var = sleeptime
def wait_meep(self):
sleep(self.var)
print("Meep")
def do_sth(self):
print("Dop Dop Do do ...")
class bird_async:
def __init__(self,sleeptime=1):
self.var = sleeptime
async def wait_meep(self):
await asyncio.sleep(self.var)
print("Meep")
def do_sth(self):
print("Dop Dop Do do ...")
如您所见,两个客户端几乎都是相同的,并且应包含相同的名称(这样每个人都知道期望什么)。现在,我想成为DRY并写bird_async(bird)
。因为bird
中的每个扩展名也应在bird_async
中使用。这是可能的,但是我的同事说这不是SOLID,因为我已经覆盖了wait_meep
。现在,我正在寻找不同的灵魂,并找到了抽象类。
我不知道的是,如果创建抽象类birdBase(ABC)
也是SOLID。我也会覆盖那里,因为首先是一个函数,然后是一个协程,还是我在这里错了?
在不重命名方法的情况下将这两个类放在一起的SOLID和DRY解决方案是什么?
解决方法
DRY解决方案就像您已经做的那样是子类化。
我认为在您的情况下很难实现“固体”解决方案。实际上,您有两个函数wait_meep
,它们实际上具有不同的签名和语义。即,第一个阻塞睡眠间隔,该间隔可以任意长。第二个OTOH是异步的,即需要特殊的调用语义并同时运行。
一个类似的情况是标准库中的Queue
类。那里有get
和get_nowait
方法,它们以不同的方式执行相同的操作。第二个示例可以是__iter__
和__aiter__
方法。
因此,我认为唯一的“正确”解决方案是重命名其中一种方法。这样做的副作用是您可以将所有内容都写成一个类,即减少活动部件的数量。
,问题
您有两个具有重复代码的类,这些类可以利用继承,但不想覆盖wait_meep。此外,wait_meep
和do_sth
中存在无法自定义的硬编码文本。
解决方案
请考虑以下内容,以使您的代码更加扎实和干爽:
from time import sleep
import asyncio
class Bird:
DEFAULT_WAIT_MEEP_TEXT = "Meep"
DEFAULT_DO_STH_TEXT = "Dop Dop Do do ..."
def __init__(self,sleeptime=1):
self.sleeptime = sleeptime
def wait_meep(self,text=DEFAULT_WAIT_MEEP_TEXT):
sleep(self.sleeptime)
print(text)
def do_sth(self,text=DEFAULT_DO_STH_TEXT):
print(text)
class BirdAsync(Bird):
async def wait_meep_async(self,text=DEFAULT_WAIT_MEEP_TEXT):
await asyncio.sleep(self.var)
print(text)
注释
这里的想法是创建一个执行异步(DRY)的特定方法,并确保将硬编码的默认值改为在args中传递(开放式-封闭式原理)。当然,所有这些都可以在原始的Bird类中完成,而无需BirdAsync类