不要痴迷于原始类型

| 2021-03-03

不要痴迷于原始类型

编程语言提供基本类型,如 int ,string 和 map ,这些类型在许多场景下都被用到,例如,利用 string 保存人名,或者网页URL等等。 然而,过度使用基本类型而非自定义的抽象类型,代码可能变得难以理解和维护

原始类型的痴迷是指:过度使用基本(“原始”)类型,来表示程序中更高层次的领域概念。例如,下面的代码使用基本类型来表示形状:

vector<pair<int, int>> polygon = ...
pair<pair<int, int>, pair<int, int>> bounding_box = GetBoundingBox(polygon);
int area = (bounding_box.second.first  - bounding_box.first.first) *
           (bounding_box.second.second - bounding_box.first.second);

pair 在这里并不是一个正确的抽象层次,因为它的一般命名 firstsecond 两个参数被用于表示 XY,其中一处被用做标识 lower-left (或者, upper-left?) 而另外一处用作 upper-right (或, lower-right?) 。更糟糕的是,基本类型并没有对领域专属的代码进行封装,例如边框(bounding box)和面积(area)。

自定义并使用更高级别的抽象类型,写的代码可能更清晰,而且封装性更好:

Polygon polygon = ...
int area = polygon.GetBoundingBox().GetArea();

下面是一些原始类型痴迷的例子:

  • maps, lists, vectors 等类型可以很方便地成为一个容器集,将值合并到自定义的更高级抽象中。

    map<UserId, string> id_to_name; map<UserId, int> id_to_age;map<UserId, Person> id_to_person;
  • 包含魔术键值的vector或 map ,例如 用0,1和2分别代表name, address, and phone #,应该将其放入到更高一级的抽象中。

    person_data[kName] = "Foo";person.SetName("Foo");
  • 用一个字符串表示复杂或结构化的文本(例如一个日期)。更好的做法是使用更高层的抽象(如 Date 类型) ,它还提供自我说明的访问函数(例如 GetMonth ) ,并且还保证正确性。

    string date = "01-02-03";Date date(Month::Feb, Day(1), Year(2003));
  • 用一个整型或浮点数表过一个时间值,例如多少秒。更好的做法是使用结构化的时间戳( timestamp )或时间段类型( duration )。

    int timeout_secs = 5;Duration timeout = Seconds(5);

对于某个任务来说,任何类型都可能显得过于原始,从最原始的 int ,到复杂的红黑树。

如果你看到代码使用了很多的基础类型,那么,使用更高级别的抽象更能够表达清楚,封装性也会更好。你应该把它重构了,或者礼貌地提醒作者要 保持优雅


发表时间:November 13, 2017

原文作者:Marc Eaddy

原文链接Code Health: Obsessed With Primitives?