我正在尝试重构一个紧密耦合的大型应用程序,并试图使其更易于维护和灵活.
我有很多单元测试,所以我希望一步一步地进行重构.
我应该考虑实施/应用哪些设计和重构模式来完成这项任务?
我能想到一些:
也可以随意分享您自己的经验和这种重构工作的最佳实践.
UPDATE
由于这个问题中解释的原因,我正在进行这种重构.基本上我不能在不提取几个接口的情况下实现插件系统,并且这些接口是高度耦合的,这需要将40多个DLL中的应用程序分开,以便在没有循环引用问题的情况下进行编译.
我在处理服务层上完成的"业务验证"时遇到了一个问题.下面的代码显示了一个典型的账户资金转账示例,该示例验证了足够的资金,转账金额小于定义的限额.
在此示例中,调用者必须处理并捕获Action类中定义的异常,并使用相应的ActionError来显示错误消息.
所有业务验证都使用例外是"必须的"吗?
如果我决定不为此使用异常,我将必须在某种意义上在业务层(违反耦合/内聚)规则中定义相应的ActionError.
如何处理由服务层传播回Action类的消息?
public void transfer(String fromAccount, String toAccount, double amount) throws InsufficientFundsException, TransferLimitException, FactoryException {
try {
Account from = getAccountHome().findByPrimaryKey(
new AccountKey(fromAccount));
Account to = getAccountHome().findByPrimaryKey(
new AccountKey(toAccount));
if (from.getBalance() < amount)
throw new InsufficientFundsException(); // Add action errors
if (from.getTransferLimit() > amount)
throw new TransferLimitException(); // Add action errors
to.deposit(amount);
from.withdraw(amount);
} catch (Exception e) {
throw new FactoryException(
"cannot perform transfer. Nested exception is " + e);
}
}
Run Code Online (Sandbox Code Playgroud) 我现在正在进一步介绍 java 类,这就是该类的简要定义:
内聚:以高内聚为目标,在本例中,内聚意味着单个模块紧密关注其任务。
耦合:以低耦合为目标,在这种情况下,耦合意味着两个或多个模块交织的程度。
如何确定内聚性和耦合性的水平?
例如,我的一些方法调用同一类中的其他方法。这意味着调用其他方法的方法依赖于其他方法,以便“调用”方法完成其代码块。这是否意味着我对同一个类的方法具有低内聚和高耦合?或者这些概念更多的是指不同的类和不同的包?
我相信你必须熟悉这个成语,这是java的闭包借口
//In the "Resource Manager" class
public void process(Command cmd){
//Initialize
ExpensiveResource resource = new ExpensiveResource();
//Use
cmd.execute(resource);
//Release / Close
resource.close();
}
//In the Client class...
manager.process(new Command(){
public void execute(ExpensiveResource res){
//Do things with the resource
}
});
Run Code Online (Sandbox Code Playgroud)
我经常使用这个成语/模式,但最近我试着测试它,这让我头疼...
如何隔离测试ResourceManager和Client类?我发现这种情况非常严重,以至于你无法轻易做到这一点.
赞赏的想法.
问候
我有两个对象.会议对象和Action对象(在会议中引发的操作).行动也可以独立于会议而存在.我有两种方法将提出的行动与会议联系起来:
对于良好的OO设计,应该使用哪种方法?还是有第三种方式......
当然这取决于具体情况.但是当较低级别的对象或系统与更高级别的系统进行通信时,是否应优先使用回调或事件来保持指向更高级别对象的指针?
例如,如果我们正在开发游戏,我们就有world class一个成员变量vector<monster> monsters.如果monster class要与之通信world class,我应该更喜欢使用回调函数,还是应该指向怪物类中的世界类?
据我所知,Bundles是分离功能.假设我有一个UserBundle&a BlogBundle.然后我BlogBundle:Post会有一个author引用的字段UserBundle:User.这不是打败Bundles的目的吗?我不能换另一个UserBundle?我怎么能以正确的方式做到这一点?或者这是最好的吗?
我正在为dicom图像和光谱学编写工具,我想在我正在制作的函数之间使用很多共享数据.我有我制作的GUI,不同的滑块和按钮使用了dicom文件中的大量这些共享数据.
我一直在使用全局变量来存储所有这些函数共享的信息.我目前有很多全局变量.如果可能的话,我被教导要避免全局变量,因为耦合增加了.在每个函数中读取dicom文件中的数据会更好吗?这似乎是多余的.将MATLAB用作面向对象的帮助吗?
例如,如果我有一个64位变量并在其中存储两个32位数据项,也许是为了SIMD处理的目的,是否有一个名称来描述这两个数据项的逻辑耦合?
我的一位同事建议"混合耦合",这是一个广泛使用的术语?
澄清一下:我们追求的是一个比特定实现更高层次的概念.比方说,例如,在类似C语言中,我们有这两种结构:
struct CoupledData
{
uint64 x_and_y; // x is stored in the top 4 bytes, y in the bottom 4
}
struct UncoupledData
{
uint32 x;
uint32 y;
}
Run Code Online (Sandbox Code Playgroud)
无论这样做的原因如何,在CoupledData中的x和y数据成员之间存在隐式耦合,而UncoupledData中不存在这种耦合.是否有一个术语描述了x和y之间的这种耦合?
在使用MVC的Swift中,使用一种常见的向前发送数据的方法prepare(for:sender:).在该方法中,您将获得对目标VC的引用并访问其属性以发送数据.但这不是考虑耦合视图控制器吗?我希望答案不是一个意见问题,因为我真的很想了解seggu如何适应MVC.
我有一个很小的Python程序,包含很少的模块(约4个左右).主模块创建一个元组列表,从而表示许多记录.这些元组可以通过一个返回它们的简单函数(例如get_records())用于其他模块.
我不确定这是不是很好的设计.问题是其他模块需要知道元组中每个元素的索引.这增加了模块之间的耦合,并且对于想要使用主模块的人来说不是非常透明.
我可以想到几个选择:
使可作为模块常量(例如,元组元素的索引值IDX_RECORD_TITLE,IDX_RECORD_STARTDATE等).这避免了像魔术数字的需要title = record[3].
不要使用元组,而是创建一个记录类,并返回这些类对象的列表.优点是类方法将具有自解释名称record.get_title().
不要使用元组,而是使用字典.所以在这种情况下,该函数将返回一个字典列表.优点是字典键也是不言自明的(尽管使用该模块的人需要知道它们).但这似乎是一个巨大的开销.
我发现元组是Python的强大功能之一(很容易在没有类/对象的编码开销的情况下传递复合数据),所以我目前使用(1),但仍然想知道什么是最好的方法.
我知道我们几乎一直都希望在应用程序中的组件之间实现松散耦合以及为什么。
但是在下面的例子中,如果有人可以澄清为什么当我们将服务作为参数传递给构造函数时它没有紧密耦合,那么我就可以理解幕后发生的逻辑。
export class Test(){
dataResults;
constructor(service: testService){
this.dataResults = service.getData()
}
}
Run Code Online (Sandbox Code Playgroud) 假设 TaxCalculator 类中有以下方法:
public double calculateTax(double income) {
return income * 0.3;
}
Run Code Online (Sandbox Code Playgroud)
我们在 Main 类中使用这个方法,如下所示:
var calculator = new TaxCalculator();
double tax = calculator.calculateTax(100_000);
System.out.println(tax);
Run Code Online (Sandbox Code Playgroud)
如果我将该方法的实现更改calculateTax为:
public double calculateTax(double income) {
return income * 0.4;
}
Run Code Online (Sandbox Code Playgroud)
我是否需要重新编译 TaxCalculator 类和 Main 类?
我知道这个问题听起来很愚蠢,但我在一次讲座中听说,如果我们不使用接口,我们在紧耦合代码中所做的每一个更改(就像我上面展示的那样)都会迫使我们重新编译所有依赖的类在课堂上我们做出了改变。
这对我来说听起来很奇怪,因为 Main 类不知道我们所做的更改的方法的实现。
预先感谢您的任何帮助!