我是一名学生,最近作为实习生加入了一家软件开发公司。在大学里,我的一位教授曾经说过,我们必须努力实现“低耦合、高凝聚力”。
我理解低耦合的含义。它意味着单独保存独立组件的代码,这样一个地方的更改就不会破坏另一个地方的代码。
但是什么是高凝聚力。如果这意味着将同一组件的各个部分很好地集成在一起,我不明白这是如何变得有利的。
什么是高凝聚力?能否解释一个例子来理解它的好处?
发布于 2012-08-31 08:19:16
从面向对象的角度来看内聚力的一种方法是,类中的方法是否使用任何私有属性。使用诸如LCOM4 (缺乏内聚方法)之类的度量标准(如这个答案在这里中的gnat指出的那样),您可以识别可以重构的类。您希望重构方法或类以增强凝聚力的原因是,它使代码设计更容易被其他人使用。相信我,当你解决这些问题时,大多数技术主管和维护程序员都会喜欢你的。
您可以在构建过程中使用工具(如声纳 )来识别代码库中的低内聚力。有几个非常常见的例子,我可以想到方法的“内聚力”很低:
中都与类无关
请考虑以下示例:
public class Food {
private int _foodValue = 10;
public void Eat() {
_foodValue -= 1;
}
public void Replenish() {
_foodValue += 1;
}
public void Discharge() {
Console.WriteLine("Nnngghhh!");
}
}其中一种方法,Discharge(),缺乏凝聚力,因为它没有触及任何类的私有成员。在这种情况下,只有一个私有成员:_foodValue。如果它没有对类内嵌做任何事情,那么它真的属于那里吗?该方法可以移动到另一个可以命名的类,例如FoodDischarger。
// Non-cohesive function extracted to another class, which can
// be potentially reused in other contexts
public FoodDischarger {
public void Discharge() {
Console.WriteLine("Nnngghhh!");
}
}在Javascript中这样做,因为函数是一流的对象,因此释放可以是一个自由的函数:
function Food() {
this._foodValue = 10;
}
Food.prototype.eat = function() {
this._foodValue -= 1;
};
Food.prototype.replenish = function() {
this._foodValue += 1;
};
// This
Food.prototype.discharge = function() {
console.log('Nnngghhh!');
};
// can easily be refactored to:
var discharge = function() {
console.log('Nnngghhh!');
};
// making it easily reusable without creating a class这实际上是破坏凝聚力的常见情况。每个人都喜欢实用程序类,但这些类通常表明了设计缺陷,而且大多数情况下,代码库的维护变得更加棘手(因为与实用程序类相关的高度依赖)。考虑以下几类:
public class Food {
public int FoodValue { get; set; }
}
public static class FoodHelper {
public static void EatFood(Food food) {
food.FoodValue -= 1;
}
public static void ReplenishFood(Food food) {
food.FoodValue += 1;
}
}在这里,我们可以看到实用工具类需要访问类Food中的属性。在这种情况下,实用程序类中的方法根本没有凝聚力,因为它需要外部资源来完成它的工作。在这种情况下,在它们自己处理的类中使用方法不是更好吗(与第一种情况非常类似)?
中的隐藏对象
还有另一种实用工具类,其中有未实现的域对象。程序员在编程字符串操作时的第一个反应是为它编写一个实用类。就像这里验证几个常见字符串表示的那样:
public static class StringUtils {
public static bool ValidateZipCode(string zipcode) {
// validation logic
}
public static bool ValidatePhoneNumber(string phoneNumber) {
// validation logic
}
}这里大多数人没有意识到的是,邮政编码、电话号码或任何其他字符串修复本身都可以是一个对象:
public class ZipCode {
private string _zipCode;
public bool Validates() {
// validation logic for _zipCode
}
}
public class PhoneNumber {
private string _phoneNumber;
public bool Validates() {
// validation logic for _phoneNumber
}
}这篇博文是@codemonkeyism中详细介绍了不应该直接“处理字符串”的概念,但这与凝聚力密切相关,因为程序员通过在实用程序类中放置逻辑来使用字符串。
发布于 2012-08-31 03:26:23
高内聚力是指将相似和相关的事物保持在一起,将内容、功能、原因或目标共享的部分进行耦合或融合。换句话说,低内聚力可能意味着一个功能/类/代码实体,它服务于多个目的,而不是“指向”。其中一个承载的想法是做一件事并把它做好。其他可能包括这样一个明显的事实,即在许多地方,您不会复制类似的功能。这也提高了代码库的局部性,在某个地方可以找到某些类型的东西(文件、类、函数集、.)而不是散落在各处。
例如,考虑一个类提供两个或三个用途:加载/存储资源(例如文件),然后分析和显示内容。这样一个类的内聚性很低,因为它管理至少两个完全无关的任务(文件I/O、分析和显示)。高内聚力设计可以使用不同的类来加载和存储资源,分析资源,然后显示资源。
另一方面,低耦合的目的是保持不同的事物分离,这样它们之间的交互就越少越好,从而降低了复杂性并简化了设计。
发布于 2012-08-31 02:58:02
这意味着对象的各个部分与对象的功能密切相关。这意味着,在功能或责任方面,物体内部很少或根本没有浪费。这反过来可以提高对所讨论的对象应该用于什么目的的理解。
https://softwareengineering.stackexchange.com/questions/163090
复制相似问题