我有几个星期前编写的代码(代码的目的并不像它的结构那么重要):
if (_image.Empty)
{
//Use the true image size if they haven't specified a custom size
if (_glyphSize.Width > 0)
imageSize.Width = _glyphSize.Width //override
else
imageSize.Width = _image.GetWidth;
if (_glyphSize.Height > 0) then
imageSize.Height = _glyphSize.Height
else
imageSize.Height = _image.GetHeight
}
else
{
//No image, but they can still override it with a custom size
if (_glyphSize.Width > 0) then
imageSize.Width = _glyphSize.Width
else
imageSize.Width = 0;
if (_glyphSize.Height > 0)
imageSize.Height = _glyphSize.Height
else
imageSize.Height := 0;
}
今晚我正在检查它,当我清理它时,我意识到清洁版本必须更加简洁:
//Figure out the final image width
if (_glyphSize.Width > 0)
imageSize.Width = _glyphSize.Width
else if (not _glyph.Empty)
imageSize.Width = _glyph.GetWidth
else
imageSize.Width = 0;
//Figure out the final image height
if (_glyphSize.Height > 0)
imageSize.Height = _glyphSize.Height
else if (not _glyph.Empty)
imageSize.Height = _glyph.GetHeight
else
imageSize.Height = 0;
注意:我已经将代码修改为裸逻辑流,并且使用了源代码语言。
最后,我采用了嵌套的if
,然后将它们倒转。这样做可以缩短时间。我的问题是:我将来如何认识到这一点?
有什么迹象表明我刚刚编写了一些可以重构为更短的代码?
几个星期前的另一个例子是类似于权限检查:用户可以执行操作:
我最初编码为:
if ((HasPermission || (!HasPermission and OverrideEnabled))
{
...do stuff
}
if
条款的逻辑条件似乎有点罗嗦。我试图回到我的布尔代数课程,找出如何简化它。最后我可以做到,所以我最终绘制了一个真值表:
Permission Override Result
0 0 0
0 1 1
1 0 1
1 1 1
当我看到它是 OR 操作时。所以我的if
声明成了:
if (HasPermission or OverrideEnabled)
{
...
}
这是显而易见的。所以现在我想知道我怎么也看不到这一点。
这让我回到了我的问题:为了识别某些代码块需要一些TLC,我可以/应该寻找什么样的迹象?
答案 0 :(得分:2)
以下是Code Complete的一些指导原则。对于这类事情来说,这是一本好书。
我发现离散数学会影响我现在写if语句的方式。通常,我看到我在两个区块中写了两个相同的IF语句,然后我会做一些心理上的'因子'。
答案 1 :(得分:1)
与布尔评估特别相关,值得注意的是大多数(?)现代语言都实现了懒惰的评估。
也就是说,如果“a”为真,那么if(a)
和if(a or b)
在逻辑上和功能上都是等价的;解释器在真正的变量之后看到or
时会停止评估。当a
和b
是变量时,这不是很重要,但如果它们是可调用的[例如}当if(a() or b())
为真时,b()
},a
将无法评估。
通过以下方法学习,您可以节省大量的击键次数(和处理器时间):
if(!userExists()):
if(!createUser()):
errorHandling()
else:
doStuff()
else: doStuff()
变为
if(userExists() or createUser()): doStuff()
else: errorHandling()
答案 2 :(得分:1)
做得好。现在,当我看到这个:
//Figure out the final image width
if (_glyphSize.Width > 0)
...
//Figure out the final image height
if (_glyphSize.Height > 0)
...
我认为还有更多的重构要做。将代码提取到方法中不仅是消除冗余代码的好方法。这也是使代码自我记录的好方法:
我倾向于将代码缩减为:
set_final_image_size
使用set_final_image_size及其minions定义如下:
def set_final_image_size:
imageSize.Width = final_image_width;
imageSize.Height = final_image_height;
def final_image_width:
if (_glyphSize.Width > 0)
return _glyphSize.Width;
else if (not _glyph.Empty)
return _glyph.GetWidth;
else
return 0;
def final_image_height:
if (_glyphSize.Height > 0)
return _glyphSize.Height;
else if (not _glyph.Empty)
return _glyph.GetHeight;
else
return 0;
答案 3 :(得分:0)
现在您已经分离了宽度和高度逻辑,并注意到它是相同的 - 如果您要在课程中添加getDimension(Direction direction)
和setDimension(Direction direction, int length)
,该怎么办?现在你已经
if (_glyphSize.getDimension(direction) > 0)
imageSize.setDimension(direction, _glyphSize.getDimension(direction))
else if (not _glyph.Empty)
imageSize.setDimension(direction, _glyph.getDimension(direction))
else
imageSize.setDimension(direction, 0);
提取当地人带来了我们:
length = _glyphSize.getDimension(direction);
if (length > 0)
imageSize.setDimension(direction, length)
else if (not _glyph.Empty)
imageSize.setDimension(direction, _glyph.getDimension(direction))
else
imageSize.setDimension(direction, 0);
进一步说明:
length = _glyphSize.getDimension(direction);
if (length == 0 && !_glyph.Empty)
length = _glyph.getDimension(direction);
imageSize.setDimension(direction, length);
至少在我的眼里,开始看起来很漂亮。