我表示同情,编写并重构了python“上帝对象”。我所做的就是根据方法将原始对象分解为几个子部分。例如,原始代码看起来像下面的伪代码:
method A():
self.bla += 1
method B():
self.bla += 1
do stuff():
self.bla = 1
method A()
method B()
print self.bla
填充方法是工作的独立“单元”。我将其迁移到原始实例化的新类。这也拉出了必要的属性。有些仅由子类使用,可以直接移动。其他人被共享,并进入共享类。
“上帝对象”在启动时会创建共享类的新副本,并且每个新的子类都将指针作为其init方法的一部分。例如,这是邮件的剥离版本:
#!/usr/bin/env python
# -*- coding: ascii -*-
'''Functions for emailing with dirMon.'''
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os
import smtplib
import datetime
import logging
class mailer:
def __init__(self,SERVER="mail.server.com",FROM="support@server.com"):
self.server = SERVER
self.send_from = FROM
self.logger = logging.getLogger('dirMon.mailer')
def send_mail(self, send_to, subject, text, files=[]):
assert type(send_to)==list
assert type(files)==list
if self.logger.isEnabledFor(logging.DEBUG):
self.logger.debug(' '.join(("Sending email to:",' '.join(send_to))))
self.logger.debug(' '.join(("Subject:",subject)))
self.logger.debug(' '.join(("Text:",text)))
self.logger.debug(' '.join(("Files:",' '.join(files))))
msg = MIMEMultipart()
msg['From'] = self.send_from
msg['To'] = COMMASPACE.join(send_to)
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
msg.attach( MIMEText(text) )
for f in files:
part = MIMEBase('application', "octet-stream")
part.set_payload( open(f,"rb").read() )
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
smtp = smtplib.SMTP(self.server)
mydict = smtp.sendmail(self.send_from, send_to, msg.as_string())
if self.logger.isEnabledFor(logging.DEBUG):
self.logger.debug("Email Successfully Sent!")
smtp.close()
return mydict
它一次创建,并在需要邮件功能的不同类之间共享。
因此,为您创建larry
具有所需属性和方法的类。客户说到处larry = blah
都用larryObj.larry = blah
。这样可以在不中断当前界面的情况下将内容迁移到子项目。
唯一要做的另一件事是寻找“工作单元”。如果您打算将“上帝对象”的一部分变成它自己的方法,请这样做。但是,将方法放在它外面。这迫使您在组件之间创建接口。
奠定基础使其他所有事情都可以遵循。例如,帮助对象的一部分演示了它如何与邮件程序交互:
#!/usr/bin/env python
'''This module holds a class to spawn various subprocesses'''
import logging, os, subprocess, time, dateAdditionLib, datetime, re
class spawner:
def __init__(self, mailer):
self.logger = logging.getLogger('dirMon.spawner')
self.myMailer = mailer
专注于最小的单个工作单元,然后将其移出。这更容易实现,并且可以让您快速进行设置。不要看待移动的属性,在大多数情况下,它们是使用它们完成的任务的辅助工具。处理完方法后剩下的所有内容都应该保留在原始对象中,因为它是共享状态的一部分。
但是,现在,新对象应该将它们需要的属性作为初始变量接受,而不涉及调用方对象的属性。然后,它们返回任何必要的值,调用者可以根据需要使用这些值来更新共享属性。这有助于将对象分离,从而使系统更坚固。