原则
- 代码单元的长度应该限制在15行代码以内。
- 你应该编写不超过15行代码的单元,或者将长的单元分解成多个更短的单元,知道每个单元都不超过15行代码。
- 该原则能提高可维护性的原因在于,短小的代码单元易于理解、测试及重用。
动机
- 短小的代码单元易于测试。
- 短小的代码单元易于分析。
- 短小的代码单元易于重用。
重构技巧
方法提取
假如有一段代码是长这个样子的:
public void Start()
{
if(inProgress())
{
return;
}
inProgress = true;
if(!IsAnyPlayerAlive())
{
foreach (LevelObserver o: observers)
{
o.LevelLost();
}
}
if (RemainingPellets() == 0)
{
foreach (LevelObserver o: observers)
{
o.LevelWon();
}
}
}
第一步是方法提取,然后就变成下面的样子:
public void Start()
{
if (inProgress())
{
return;
}
inProgress = true;
UpdateObservers();
}
private void UpdateObservers()
{
if (!IsAnyPlayerAlive())
{
foreach (LevelObserver o: observers)
{
o.LevelLost();
}
}
if (!RemainingPellets())
{
foreach (LevelObserver o: observers)
{
o.LevelWon();
}
}
}
第三步是方法的在提取:
...
public void UpdateObservers()
{
UpdateObserversPlayerDied();
UpdateObserversPelletsEaten();
}
private void UpdateObserversPlayerDied()
{
if (!IsAnyPlayerAlive())
{
foreach (LevelObserver o: observers)
{
o.LevelLost();
}
}
}
private void UpdateObserversPelletsEaten()
{
if (RemainingPellets() == 0)
{
foreach (LevelObserver o: observers)
{
o.LevelWon();
}
}
}
将方法替换为方法对象
假如有这么一段代码:
public Board CreateBoard(Square[,] grid)
{
Debug.Assert(grid != null);
Board board = new Board(grid);
int width = board.Width;
int height = board.Height;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Square square = grid[x, y];
foreach(Direction dir in Direction.Values)
{
int dirX = (width + x + dir.DeltaX) % width;
int dirY = (height + y + dir.DeltaY) % height;
Square neighbour = grid[dirX, dirY];
square.Link(neighbour, dir);
}
}
}
}
重构为方法对象之后:
internal class BoardCreator
{
private Square[,] grid;
private Board board;
private int width;
private int height;
internal BoardCreator(Square[,] grid)
{
Debug.Assert(grid != null);
this.grid = grid;
this.board = new Board(grid);
this.width = board.Width;
this.height = board.Height;
}
internal Board Create()
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Square square = grid[x, y];
foreach(Direction dir in Direction.Values)
{
SetLink(square, dir, x, y);
}
}
}
return this.board;
}
private void SetLink(Square square, Direction dir, int x, int y)
{
int dirX = (width + x + dir.DeltaX) % width;
int dirY = (height + y + dir.DeltaY) % height;
Square neighbour = grid[dirX, dirY];
square.Link(neighbour, dir);
}
}
public Board CreateBoard(Square[,] grid)
{
return new BoardCreator(grid).Create();
}
[荷] Joost Visser 著. 张若飞译. 【代码不朽:编写可维护软件的10大要则(C#版)】