假设我有两个几乎完全相同的函数,它们代表了系统的瓶颈,看起来像这样,(更复杂):
void f1( int s )
{
for( size_t i = 0, END = m_v.size(); i < END; ++i )
{
int bin_id = binId( m_v[ i ], s );
m_result[ bin_id ] += m_w[ i ]; //
}
}
void f2( int s )
{
for( size_t i = 0, END = m_v.size(); i < END; ++i )
{
int bin_id = binId( m_v[ i ], s );
m_result[ bin_id ] += 1.f; //
}
}
除了在代码的一行中使用变量或常量之外,一切都是相同的。如上所述,假设实际代码要复杂得多。如果没有与次要差异重复两次将是很好的,因为它需要一个确保每个相同的维护。我可以做这样的事情将它们合并为一个:
void f3( bool use_weight, int s )
{
if( use_weight )
{
for( size_t i = 0, END = v.size(); i < END; ++i )
{
int bin_id = binId( v[ i ], s );
result[ bin_id ] += m_w[ i ]; //
}
}
else
{
for( size_t i = 0, END = v.size(); i < END; ++i )
{
int bin_id = binId( v[ i ], s );
result[ bin_id ] += 1.f; //
}
}
}
但这仍然是在一个函数内复制代码。我们可以这样做,但会带来更糟糕的表现:
void f3( bool use_weight, int s )
{
for( size_t i = 0, END = v.size(); i < END; ++i )
{
int bin_id = binId( v[ i ], s );
if( use_weight )
{
result[ bin_id ] += m_w[ i ]; //
}
else
{
result[ bin_id += 1.f; //
}
}
}
调用代码如下所示:
bool use_weight = something.use_weight();
const int N = very_large_number;
for( int s = 0; s < N; ++s )
{
f3( use_weight, s );
}
同样,假设代码更加复杂,例如f3实际上是复制了很多逻辑。
答案 0 :(得分:1)
老实说,有时优化代码可重用性通常可以解决问题,但在您的示例中,利用多态性可能会更好。类和函数应该接受它们正在处理的参数而不是工作成员变量。制作一个“超级”功能或“完成所有”的课程通常是一个错误。随着时间的推移,这些类和函数变得越来越臃肿。
因此,代码理想情况下将使用接口,并且将注入所需的解析器。 :)
var parser1 = new HotSauceParser();
parser.parse(arrayData);
var parser2 = new WeightParser();
parser2.setWeights(m_w); // in many langages you can chain this.
parser.parse(arrayData);
这跟在Single responsibility principle之后,很容易测试。然后你可以编写一个类来决定何时使用一个类或另一个类。 HOW解析的逻辑封装在解析器本身中。
就效率而言,通常如果您正在解析数组,性能问题是关于该数组是如何BIG以及您是否必须遍历整个结构。
请注意“干掉”代码,很容易过度干掉代码,并陷入常见的陷阱,例如过度使用继承和/或使用“功能羡慕”创建类和函数。
您可能需要查看清洁代码一书和 S.O.L.I.D。。