在我的代码上运行FxCop,我收到此警告:
Microsoft.Maintainability:'FooBar.ctor与来自9个不同命名空间的99种不同类型相结合.重写或重构方法以减少其类耦合,或考虑将方法移动到与其紧密耦合的其他类型之一.高于40的类耦合表明可维护性差,40到30之间的类耦合表明适度的可维护性,并且低于30的类耦合表明良好的可维护性.
我的类是来自服务器的所有消息的登陆区域.服务器可以向我们发送不同EventArgs类型的消息:
public FooBar()
{
var messageHandlers = new Dictionary<Type, Action<EventArgs>>();
messageHandlers.Add(typeof(YouHaveBeenLoggedOutEventArgs), HandleSignOut);
messageHandlers.Add(typeof(TestConnectionEventArgs), HandleConnectionTest);
// ... etc for 90 other types
}
Run Code Online (Sandbox Code Playgroud)
"HandleSignOut"和"HandleConnectionTest"方法中的代码很少; 他们通常将工作交给另一个班级的职能部门.
如何通过较低的耦合使这个类更好?
虽然我已经编程了很长一段时间,但是当涉及耦合对象时,我似乎总是把头撞到墙上,所以我想知道是否有人有任何资源或我可以遵循的黄金规则.
让我举一个小例子,没有特别的语言......
class Person {
private int personnel_id
private String first_name;
private String last_name;
private int personnel_level;
//Lab labs[4]; <- Lab(s) the Person works in
}
class Lab {
private int lab_id;
private String lab_name;
//Person[99] personnel; <- Person(s) working in the Lab
}
Run Code Online (Sandbox Code Playgroud)
让我们暂时忽略ctors/setters/getters/dtors并只是实例化一些东西......
Person people = new Person[1500];
Lab labs = new Lab[10];
Run Code Online (Sandbox Code Playgroud)
我的问题是......这里最好的做法是什么......
people["Gordon Freeman"].blewUp((Lab)"Black Mesa");
-> returns T/F
Run Code Online (Sandbox Code Playgroud)
要么...
labs["BlackMesa"].blownUpBy((Person)"Gordon Freeman");
-> returns T/F
Run Code Online (Sandbox Code Playgroud)
或者它甚至不重要:S
我正在研究的现实生活中的例子要复杂得多.每当Person做某事时,每个人都Lab需要得到通知等等,而我只想弄清楚我是否有任何原则可以在这里申请.
是否有任何实用程序可以检查一组托管程序集,并告诉您一个名称空间中的任何类型是否依赖于另一个名称空间中的任何类型?例如,假设我有一个MyApp.BusinessRules命名空间,并且不希望它直接访问任何内容MyApp.GUI,但两个命名空间都在同一个程序集中.我的目标是能够编写一个自定义MSBuild任务,以验证各种耦合规则是否已被破坏.
到目前为止,我遇到的唯一一个看起来可能会这样做的工具是NDepend,但我想知道是否有更简单的解决方案.
他们是否矛盾?
解耦是很棒的,很难实现.然而,在大多数应用程序中,我们并不真正需要它,因此我可以设计高度耦合的应用程序,除了明显的副作用之外,它几乎不会改变任何东西,例如"你不能分离组件","单元测试是痛苦的屁股"等
你怎么看?你总是试图解耦和处理开销吗?
刚刚大学毕业,我遇到了一些需要减少耦合的代码.但我并不完全理解所有概念,并想要一个简单的例子来帮助我.为了让你开始,我有一个人类,一个字段,名称.我在该类中有一个方法来连接一些文本.
我知道这是一个愚蠢的例子,大多数人都不会考虑在这种简单的情况下减少耦合,但我只想要一个简单的例子来帮助我完全理解代码和概念.
在主窗口后面的代码中,我放了一个文本框和一个按钮.窗口加载时,它显示person x name字段的当前值.单击该按钮时,将调用x.PersonAddText方法.目前,此示例的耦合计算为8.按钮单击事件为3,窗口加载事件为3.
有没有办法,使用这个例子,我们可以将它们降低到低于它们中的一个或两个.
以下是我的所有代码:
我的人员类:
public class Person
{
//Fields
private string name;
//Properties
public string Name
{
get { return name; }
set { name = value; }
}
//Constructors
public Person()
{
name = "joe";
}
//Methods
public string PersonAddText(string text)
{
return name += " - " + text;
}
//Interfaces (or additional code below here please to aid understanding)
}
Run Code Online (Sandbox Code Playgroud)
我的守则背后:
Person x = new Person();
public MainWindow()
{
InitializeComponent();
}
private void …Run Code Online (Sandbox Code Playgroud) 正如您在下面看到的,在构造函数中我实例化了一个验证对象,因此我可以在set方法中验证用户的电子邮件.这种架构是最佳实践还是有缺陷的?我可以避免让我的User类直接依赖于我的Validation类吗?
Class User {
Private Email
//constructor
User() {
Validation = new Validation
}
SetEmail(NewValue) {
if (Validation.isEmail(NewValue)) {
Email = NewValue
}
}
Run Code Online (Sandbox Code Playgroud)
还有一个相关的问题:当set方法收到无效值时,什么是正确的响应?我看到2个选项
我怀疑#1是最佳实践,因为您可以确保任何对象属性的值始终有效.正确?
我正在编写一个简单的游戏来学习获得更多的C++经验,我有一个想法,我觉得多态几乎可以工作,但没有.在这个游戏中,Party移动相当线性地通过一个Map,但偶尔可以Fork在路上遇到一个.fork(基本上)是一个std::vector<location*>.Originally我打算在Party成员函数中编写如下代码:
if(!CurrLocation->fork_.empty())
// Loop through forks and show options to the player, go where s/he wants
else
(CurrLocation++)
Run Code Online (Sandbox Code Playgroud)
但我想知道以下某些变体是否会更好:
CurrLocation = CurrLocation->getNext();
Run Code Online (Sandbox Code Playgroud)
使用Fork实际上是从Location派生的,并且重载了一些新功能getNext().但在后一种情况下,在location(低层次结构)将不得不提出的信息给用户,而不是"通过这个备份",我不觉得是优雅的,因为它夫妻一个location来UserInterface::*.
你的意见?
我有一个类(让我们称它MyService)在它的构造函数中接受两个依赖项.第一个与问题无关.第二个是PaymentDetails.PaymentDetails的寿命比MyService长,后者由工厂创建以处理此特定请求.
在MyService.process(),它:
new TransactionDetails()对象并在其上设置各种东西,myPaymentDetails.setTransactionDetails( td );PaymentDetails必要时有很多方法.它是一个实体样式对象,当用户逐步浏览大约5页时,信息就会建立在该对象中.
困扰我的是,写作我的服务类取决于整个PaymentDetails但只调用一个方法.
这困扰我,因为:
我的问题是:
解决此问题的最佳方法是什么,以便我的服务类具有最小的依赖性?
我的游戏基础包括一系列模块,按类组织,在需要时创建,更新和交互.
有几个例子可以是:CWindowManager,CGraphicsManager,CPhysicsManager,等等.
我不得不说我目前使用全局指针(extern CWindowManager* g_WindowManager;),我知道这可能是一件坏事.
无论如何,事情是这些模块需要动态创建和删除,当然也需要正确的顺序.还有像模块一样CPhysicsManager依赖于场景的问题,因此在切换场景然后再次创建场景时会删除它们.
现在,我想转而使用全局变量来处理游戏中的模块.
我并不害怕重构,但我真的不能想到什么是全局变量的最佳选择.
我考虑过创建一个CModuleManager类并将模块的实例存储在那里作为成员,然后从CModule基类派生.虽然我无法真正想到这将如何发挥作用.
这似乎是软件开发,特别是游戏开发中的常见问题,因此:
- 与仅使用全局指针相比,管理模块的最佳选择是什么?
coupling ×10
oop ×3
c++ ×2
decoupling ×2
.net ×1
c# ×1
code-metrics ×1
dependencies ×1
java ×1
modularity ×1
polymorphism ×1
sonarqube ×1
yagni ×1