架构师书房-《代码不朽》-代码快速变短小的重构技巧-提取方法

架构师书房-《代码不朽》-代码快速变短小的重构技巧-提取方法

首页角色扮演代号重构更新时间:2024-07-01

大家好,我是码农老吴,欢迎收看,我们极客架构师,最新推出的,架构师书房栏目,今天,我继续给大家解读《代码不朽》这本书,上期我们聊了第一原则,要编写短小的代码单元(Write Short Units of Code ),最好15行以内。今天,我们聊聊如何才能编写出短小的代码。

写代码犹如写文章

好的代码是设计出来的吗?

好的代码是一蹴而就的吗?

非也,非也,我的观点是(非本书作者的观点),写代码犹如写文章,好的代码往往是修改出来的,是重构出来的

写代码之前,先大致构思一下,然后开始写第一版代码(也就是初稿),先确保业务功能基本实现(deadline给你带来的焦虑感会随之消失大半),然后是一点点的修改,优化,或者叫重构(每优化完成一点点,成就感,兴奋感就会增加一点点,大脑的多巴胺就会多分泌一点点,这大概就是码农的快乐吧),直至改无可改,或者deadline已到,形成终版,代码提交。当然,随着编码水平的提高,第一版(初稿)的质量也会越来越高,优化,重构的速度也会越来越快,直至封神,成为技术大牛。

本章介绍了两个,使用率很高的,很实用的代码重构技巧。在介绍这些技巧之前,我们先简要介绍一下,本书采用的案例代码。

案例介绍-代尔夫特理工大学教授的授课案例Jpacman 吃豆人

本书使用的案例有些特别,不是临时编写的实验性质的代码,而是采用了一款类似吃豆人的游戏源代码,项目的名称是JPacman(吃豆人),它是由荷兰代尔夫特理工大学(Delft University of Technology, The Netherlands)的 Arie van Decursen 教授及其团队开发创建,用于讲授测试代码的编写技巧。这个项目我已经fork到我的github上了,大家有兴趣可以看看。

案例1:start方法重构

重构前-start方法

16行代码,超过15行,需要重构

重构方案1:将19行-30行代码,提取到一个新的方法中,最终2个方法(满足要求,每个方法不超过15行)

重构方案2:将19行-30行代码,两个if语句,分别提取为一个独立方法,最终3个方法(满足需求,但是后面每个方法,5行代码,有点过了)

操作提示

重构后

// tag::start[] public void start() { if (inProgress) { return; } inProgress = true; updateObservers(); } // end::start[] @SuppressWarnings("unused") // tag::updateObservers[] private void updateObservers() { // Update observers if player died: if (!isAnyPlayerAlive()) { for (LevelObserver o : observers) { o.levelLost(); } } // Update observers if all pellets eaten: if (remainingPellets() == 0) { for (LevelObserver o : observers) { o.levelWon(); } } }

点评

上面提取出来的方法updateObservers(),比较简单,没有任何参数,也没有返回值。下面看一个复杂一点的,提取的方法,会包含很多参数。

案例2:createBoard方法重构

重构前-createBoard()

该方法明显超过15行

重构方案1:将红色标注部分,15-20行,最里面的for语句,提取为一个方法。

重构后

package eu.sig.training.ch02.v1; public class BoardFactory { // tag::createBoard[] public Board createBoard(Square[][] grid) { assert grid != null; Board board = new Board(grid); int width = board.getWidth(); int height = board.getHeight(); for (int x = 0; x < width; x ) { for (int y = 0; y < height; y ) { Square square = grid[x][y]; for (Direction dir : Direction.values()) { setLink(square, dir, x, y, width, height, grid); } } } return board; } // end::createBoard[] // tag::setLink[] private void setLink(Square square, Direction dir, int x, int y, int width, int height, Square[][] grid) { int dirX = (width x dir.getDeltaX()) % width; int dirY = (height y dir.getDeltaY()) % height; Square neighbour = grid[dirX][dirY]; square.link(neighbour, dir); } // end::setLink[] } class Board { @SuppressWarnings("unused") public Board(Square[][] grid) {} public int getWidth() { return 0; } public int getHeight() { return 0; } } class Square { @SuppressWarnings("unused") public void link(Square neighbour, Direction dir) {} } class Direction { public static Direction[] values() { return null; } public int getDeltaY() { return 0; } public int getDeltaX() { return 0; } }

点评

上面重构出来的代码中,setLink方法包含了7个参数,当一个方法,参数过多时,一般不超过3到4个,说明存在优化的可能。

private void setLink(Square square, Direction dir, int x, int y, int width, int height, Square[][] grid) { int dirX = (width x dir.getDeltaX()) % width; int dirY = (height y dir.getDeltaY()) % height; Square neighbour = grid[dirX][dirY]; square.link(neighbour, dir); }

那么如何优化呢?欲知后事如何,且听下回分解,下期我们聊聊,另外一个重构技巧,方法对象的提取。我们下期见。

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved