我有一个QueueProcessor
类来处理工作队列。我想发送一封电子邮件,其中包含所有使用大量统计信息完成的工作的摘要。我已经在使用邮件类(Zend_Mail
),因此大部分电子邮件工作都是抽象出来的,但我仍然需要弄清楚将代码放在哪里以生成摘要信息。我基本上是在处理过程中收集数据,然后我必须将数据转换为适合电子邮件的格式。
我的问题是,我应该创建一个名为QueueProcessorSummaryEmail
的单独类,还是被认为是糟糕的设计,因为它与原始类紧密耦合?如果我做了使它成为自己的类,我必须传递大量数据才能生成电子邮件,但是这种分离会很好。如果我不使它成为一个类,那么所有数据都可以从QueueProcessor
类中获得,但只是将处理逻辑和报告生成逻辑混合在一个类中感觉很奇怪。
为了记录,当我说“报告生成逻辑”时,我并不是说我正在生成HTML内联;我正在使用一个视图。通过格式化我的意思是获取数据并将其聚合成电子邮件报告可用的内容。
答案 0 :(得分:4)
被认为是糟糕的设计,因为它与原始类非常紧密地耦合在一起?
不,这不是问题。子类 - 超类设计也紧密耦合。
将处理逻辑和报告生成逻辑混合在一个类中感觉很奇怪。
报告/摘要的授权通常是有意义的。与处理相比,报告更改和扩展的速度更快。
答案 1 :(得分:4)
Ryeguy,
我的建议是创建一个装饰器类(比如说SummarizedQueryProcessor)来扩展QueueProcessor的功能。这将允许更高程度的关注点分离,并将简化单元测试。
泰德
答案 2 :(得分:1)
帮助解除设计失败的一种方法是使用接口。例如,您可以创建一个名为ISummaryDataProvider
的接口,并使QueueProcessor
实现该接口,其中包含为处理摘要数据的另一个类提供数据所需的属性和方法。
然后,您可以让QueueProcessorSummaryEmail
的构造函数接受ISummaryDataProvider
作为参数。这样,如果您决定从QueueProcessor
之外的其他内容获取摘要数据,则只需确保新数据源实现ISummaryDataProvider
,以便{{1}可以正确使用它}}
我在问题How should I model my code to maximize code re-use in this specific situation?中探讨了类似的面向对象设计问题。使用依赖注入建议的答案之一,我之前并不理解。您可以在我的问题的底部看到我是如何以松散耦合的方式实现此解决方案的。您可能会发现有助于您处理的信息。
答案 3 :(得分:0)
ryeguy,
我很想让QueueProcessor
类成为基本抽象类,然后扩展它以创建QueueProcessorSummaryMail
类。
class QueueProcessor
{
// all your methods and properties
}
class QueueProcessorSummaryMail extends QueueProcessor
{
// add your custom properties and methods here
}
希望这能为您提供主要想法。
吉姆
[编辑]当然是为了php。对于c#,你仍然使用抽象类或接口。
答案 4 :(得分:0)
结构很重要。如果有一组逻辑并不真正属于一个类,那么在其他地方重构它可以真正帮助将来保持主要可用性。
在支持内部类的语言中,您可以将其作为内部类。可能稍后你将它分开并重新使用它,然后需要将数据传递给它,此时你可以定义一个Mail类接受的接口,以及哪个队列处理器实现。
答案 5 :(得分:0)
这样的事情怎么样?
public interface WorkProcessorI {
public void process( WorkQueue queue ); // could also be something like "process( Task[] queue )"
}
public interface SummaryGeneratorI () {
public String[][] generateSummary(); // returns subscripted string array of name/values or whatever
}
public class QueueProcessor implements WorkProcessorI, SummaryGeneratorI {
public void process( WorkQueue queue ) {
// process queue populating member values that will be used to generate the summary.
}
public String[][] generateSummary() {
// read values that were populated by the process( WorkQueue ) method.
}
}
public class SummaryMail {
private String[][] summary = null;
public void setSummary( String[][] argSummary ) {
this.summary = argSummary;
}
// to, from, server, cc, bcc, subject, Additional body text, ...
public void send() {
// sends email via whatever api you want.
}
}