通用与专用
通用模块(General-Purpose Modules)
设计新模块时,您将面临的最普遍的决定之一就是是以通用还是专用方式实现它。有人可能会争辩说,您应该采用通用方法,在这种方法中,您将实现一种可用于解决广泛问题的机制,而不仅是当今重要的问题。在这种情况下,新机制可能会在将来发现意外用途,从而节省时间。另一方面,我们知道很难预测软件系统的未来需求,因此通用解决方案可能包含从未真正需要的功能。此外,如果您实现的东西过于通用,那么可能无法很好地解决您今天遇到的特定问题。结果,有些人可能会争辩说,最好只关注当今的需求,构建您所知道的需求,并针对您今天打算使用的方式进行专门化处理。如果您采用特殊用途的方法并在以后发现更多用途,则始终可以对其进行重构以使其通用。专用方法似乎与软件开发的增量方法一致。
通用方法最重要的(也许是令人惊讶的)好处是,与专用方法相比,它导致更简单,更深入的界面。如果您将该类用于其他目的,则通用方法还可以节省将来的时间。但是,即使该模块仅用于其原始用途,由于其简单性,通用方法仍然更好。通用接口比专用接口具有许多优点。它们往往更简单,使用的方法更少。它们还提供了类之间的更清晰的分隔,而专用接口则倾向于在类之间泄漏信息。使模块具有某种通用性是降低整体系统复杂性的最佳方法之一。
示例:为编辑器存储文本
编辑器必须显示一个文件,并允许用户指向,单击并键入以编辑该文件。编辑者必须在不同的窗口中支持同一文件的多个同时视图。他们还必须支持多级撤消和重做以修改文件。文本类通常提供以下方法:将文件加载到内存,读取和修改文件的文本以及将修改后的文本写回到文件。
许多学生团队为文本课实现了专用的
void backspace(Cursor cursor);
void delete(Cursor cursor);
这些方法中的每一个都以光标位置作为参数。特殊类型的光标表示此位置。编辑器还必须支持可以复制或删除的选择。学生通过定义选择类并在删除过程中将该类的对象传递给文本类来解决此问题:
void deleteSelection(Selection selection);
学生们可能认为,如果文本类的方法与用户可见的功能相对应,则将更易于实现用户界面。但是,实际上,这种专业化对用户界面代码几乎没有好处,并且为使用用户界面或文本类的开发人员带来了很高的认知负担。文本类以大量浅层方法结束,每种浅层方法仅适用于一个用户界面操作。许多方法(例如
更好的方法是使文本类更通用。仅应根据基本文本功能定义其
void insert(Position position, String newText);
void delete(Position start, Position end);
第一种方法在文本内的任意位置插入任意字符串,第二种方法删除大于或等于开始但小于结束的位置处的所有字符。此
Position changePosition(Position position, int numChars);
此方法返回一个新位置,该位置与给定位置相距给定字符数。如果
text.delete(cursor, text.changePosition(cursor, 1));
同样,可以按以下方式实现退格键:
text.delete(text.changePosition(cursor, -1), cursor);
使用通用文本
使用通用接口实现的文本类除交互式编辑器外,还可以用于其他目的。作为一个示例,假设您正在构建一个应用程序,该应用程序通过将所有出现的特定字符串替换为另一个字符串来修改指定文件。专用文本类中的方法(例如,退格键和
Position findNext(Position start, String string);
通用方法在文本和用户界面类之间提供了更清晰的分隔,从而可以更好地隐藏信息。文本类不需要知道用户界面的详细信息,例如如何处理退格键。这些细节现在封装在用户界面类中。可以添加新的用户界面功能,而无需在文本类中创建新的支持功能。通用界面还减轻了认知负担:使用用户界面的开发人员只需要学习一些简单的方法,就可以将其重复用于各种目的。
文本类原始版本中的