47.避免产出write-only code

问题实例

 
假设现有一个vector,我们需要删除vector中值小于x且出现在至少和y一样大的最后一个元素之后的所有元素,现有实现如下:

1
2
3
vector<int> v;
int x, y;
v.erase(remove_if(find_if(v.rbegin(), v.rend(),[](int i){return i>=y;}).base(),v.end(),[](int i){return i<x;}),v.end());

虽然该实现用一条语句就解决了问题,但看起来…emm…似乎不是很好维护。
那接着考虑如下实现:
1
2
3
ypedef vector<int>::iterator VecIntIter;
VecIntIter rangeBegin = find_if(v.rbegin(),v.rend(),[](int i){return i>=y;}).base();
v.erase(remove_if(rangeBegin, v.end(), [](int i){return i<x;}), v.end());

这一段代码的可读性无疑强了很多。


问题剖析

 
让我们回到问题本身:去除值小于x且出现在至少和y一样大的最后一个元素之后的所有元素。
那我们很自然的会想到下面的方案:

  1. 找到一个元素的最后一次出现需要用反向迭代器,并且需要使用find或者find_if
  2. 去除元素需要使用erase-remove惯用法

那么写出如下伪代码也顺理成章:

1
v.erase(remove_if(find_if(v.rbegin(), v.rend(), something).base(),v.end(),something)),v.end());

读者不难发现这种形式的程序写出来很容易,但如果逆向从代码去推导最初的需求则很难,这种风格被称为write-only,可读性极差。

代码的可读性十分重要,从某种意义上来说,它直接影响了软件开发的高效性。码农何苦为难码农,write-only类型的代码虽然写起来很舒服,但在工作中应当尽力避免。