过去我以为这句话只是一种好的编程习惯,以为即便是不遵守照样编出正确的程序。而实际上并非如此,不遵循这条规则几乎无法编出正确的程序。这个法则的重要性不仅仅是可读性、可维护性,更是深深影响了程序的正确性。
下面一个具体的实例展示“一个函数做多件事”的后果,这个实例是一个下五子棋的大概框架
whoseTurn=黑棋
def init():
初始化棋盘
whoseTurn=黑棋
def move(着法):
按照着法移动棋子
if 检查是否结束:
gameOver()
def gameOver():
是否还玩?
if 还玩:
init()
else:exit()
def 黑棋用户():
move(黑棋最佳着法)
whoseTurn=白棋
def 白棋用户():
move(白棋最佳着法)
whoseTurn=黑棋
如上代码,如果黑棋用户走完一招后,在move()函数中判断结束条件,发现黑棋赢了,游戏结束,用户还想接着玩,所以调用init函数进行初始化,先手依然是执黑棋者。init()返回到gameOver()函数,gameOver()函数返回到move()函数,move()函数返回到黑棋用户()
函数,这时whoseTurn突然被置成了白棋!显然这不是我们想要的结果。
改良的方式就是一个函数只做一件事,既然move()函数作用是移动棋子,那就让它专心干一件事,不要让它进行游戏结束的检测,要把游戏结束检测放到黑棋用户()
和白棋用户()
中,虽然这样会多写一些代码,但是这样能够增强可维护性。
有些情况下,冗余的代码能增强可维护性。
如果黑棋用户赢了加100分,白棋用户赢了加10分,那么很显然,这时候游戏结束条件中就需要分别处理一下。如果两个人共同使用同一件东西,当两个人的需求发生改变时,这两个人想对这一件东西做不同的处理,这时必须要分家!不分家二人无法再继续共用一件东西。这时必须进行分化。
原来二人共用一件东西,这就是一种耦合性强的表现。耦合性强就会导致代码更改时需要综合考虑两家人的需要,需要协调。协调好了,继续雅观优美;协调不好,必须分家。即便是协调好了,如果需要在这段共同的代码中加入大量的判断语句来判断到底是谁在调用这段共同的代码,效率必然降低,因为分家之后是谁在调用是明确的。
然而,“何时分家”是一个艰难的决定,没有准确的答案。这就是程序员永恒不变的追求着的“平衡”。