diff --git a/chapters/10-tdd-with-autotest.md b/chapters/10-tdd-with-autotest.md index cf07f65..a3726be 100644 --- a/chapters/10-tdd-with-autotest.md +++ b/chapters/10-tdd-with-autotest.md @@ -1 +1,78 @@ -#测试 \ No newline at end of file +#测试 + +##一次测试驱动开发 + +虽然接触的TDD时间不算短,然而真正在实践TDD上的时候少之又少。除去怎么教人TDD,就是与人结对编程时的switch,或许是受限于当前的开发流程。 + +偶然间在开发一个物联网相关的开源项目——[Lan](https://github.com/phodal/lan)的时候,重拾了这个过程。不得不说提到的一点是,在我们的开发流程中**测试是由相关功能开发人员写的**,有时候测试是一种很具挑战性的工作。久而久之,为自己的开源项目写测试变成一种自然而然的事。有时没有测试,反而变得**没有安全感**。 + +###故事 + +之前正在重写一个[物联网](http://www.phodal.com/iot)的服务端,主要便是结合CoAP、MQTT、HTTP等协议构成一个物联网的云服务。现在,主要的任务是集中于协议与授权。由于,不同协议间的授权是不一样的,最开始的时候我先写了一个http put授权的功能,而在起先的时候是如何测试的呢? + + curl --user root:root -X PUT -d '{ "dream": 1 }' -H "Content-Type: application/json" http://localhost:8899/topics/test + +我只要顺利在request中看有无``req.headers.authorization``,我便可以继续往下,接着给个判断。毕竟,我们对HTTP协议还是蛮清楚的。 + +```javascript +if (!req.headers.authorization) { + res.statusCode = 401; + res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"'); + return res.end('Unauthorized'); +} +``` + +可是除了HTTP协议,还有MQTT和CoAP。对于MQTT协议来说,那还算好,毕竟自带授权,如: + +```bash +mosquitto_pub -u root -P root -h localhost -d -t lettuce -m "Hello, MQTT. This is my first message." +``` + +便可以让我们简单地完成这个功能,然而有的协议是没有这样的功能如CoAP协议中是用Option来进行授权的。现在的工具如libcoap只能有如下的简单功能 + +```bash +coap-client -m get coap://127.0.0.1:5683/topics/zero -T +``` + +于是,先写了个测试脚本来验证功能。 + +```javascript +var coap = require('coap'); +var request = coap.request; +var req = request({hostname: 'localhost',port:5683,pathname: '',method: 'POST'}); + +... + +req.setHeader("Accept", "application/json"); +req.setOption('Block2', [new Buffer('phodal'), new Buffer('phodal')]); + +... + +req.end(); +``` + +写完测试脚本后发现不对了,这个不应该是测试的代码吗? 于是将其放到了spec中,接着发现了上面的全部功能的实现过程为什么不用TDD实现呢? + +###说说测试驱动开发 + +测试驱动开发是一个很"古老"的程序开发方法,然而由于国内的开发流程的问题——即开发人员负责功能的测试,导致这么好的一项技术没有在国内推广。 + +测试驱动开发的主要过程是: + +1. 先写功能的测试 +2. 实现功能代码 +3. 提交代码(commit -> 保证功能正常) +4. 重构功能代码 + +而对于这样的一个物联网项目来说,我已经有了几个有利的前提: + +1. 已经有了原型 +2. 框架设计 + +###思考 + +通常在我的理解下,TDD是可有可无的。既然我知道了我要实现的大部分功能,而且我也知道如何实现。与此同时,对Code Smell也保持着警惕、要保证功能被测试覆盖。那么,总的来说TDD带来的价值并不大。 + +然而,在当前这种情况下,我知道我想要的功能,但是我并不理解其深层次的功能。我需要花费大量的时候来理解,它为什么是这样的,需要先有一些脚本来知道它是怎么工作的。TDD变显得很有价值,换句话来说,在现有的情况下,TDD对于我们不了解的一些事情,可以驱动出更多的开发。毕竟在我们完成测试脚本之后,我们也会发现这些测试脚本成为了代码的一部分。 + +在这种理想的情况下,我们为什么不TDD呢? \ No newline at end of file diff --git a/chapters/11-refactor-project.md b/chapters/11-refactor-project.md index 8d5bd4b..7f379a0 100644 --- a/chapters/11-refactor-project.md +++ b/chapters/11-refactor-project.md @@ -151,4 +151,263 @@ str = tableHandler(str, execStr, strict); ✓ should return correctly class name ``` -快来试试吧, [https://github.com/artisanstack/js-refactor](https://github.com/artisanstack/js-refactor) \ No newline at end of file +快来试试吧, [https://github.com/artisanstack/js-refactor](https://github.com/artisanstack/js-refactor) + +是时候讨论这个Refactor利器了,最初看到这个重构的过程是从ThoughtWorks郑大晔校开始的,只是之前对于Java的另外一个编辑器Eclipse的坏感。。这些在目前已经不是很重要了,试试这个公司里面应用广泛的编辑器。 + +##Interllij Idea重构 + +开发的流程大致就是这样子的,测试先行算是推荐的。 + + 编写测试->功能代码->修改测试->重构 + +上次在和buddy聊天的时候,才知道测试在功能简单的时候是后行的,在功能复杂不知道怎么手手的时候是先行的。 + + +开始之前请原谅我对于Java语言的一些无知,然后,看一下我写的Main函数: + +```java +package com.phodal.learing; + +public class Main { + + public static void main(String[] args) { + int c=new Cal().add(1,2); + int d=new Cal2().sub(2,1); + System.out.println("Hello,s"); + System.out.println(c); + System.out.println(d); + } +} +``` + +代码写得还好(自我感觉),先不管Cal和Cal2两个类。大部分都能看懂,除了c,d不知道他们表达的是什么意思,于是。 + +###Rename + +**快捷键:Shift+F6** + +**作用:重命名** + + - 把光标丢到int c中的c,按下shift+f6,输入result_add + - 把光标移到int d中的d,按下shift+f6,输入result_sub + +于是就有 + +```java +package com.phodal.learing; + +public class Main { + + public static void main(String[] args) { + int result_add=new Cal().add(1,2); + int result_sub=new Cal2().sub(2,1); + System.out.println("Hello,s"); + System.out.println(result_add); + System.out.println(result_sub); + } +} +``` + +###Extract Method + +**快捷键:alt+command+m** + +**作用:扩展方法** + +- 选中System.out.println(result_add); +- 按下alt+command+m +- 在弹出的窗口中输入mprint + +于是有了 + +```java +public static void main(String[] args) { + int result_add=new Cal().add(1,2); + int result_sub=new Cal2().sub(2,1); + System.out.println("Hello,s"); + mprint(result_add); + mprint(result_sub); +} + +private static void mprint(int result_sub) { + System.out.println(result_sub); +} +``` + +似乎我们不应该这样对待System.out.println,那么让我们内联回去 + +###Inline Method + +**快捷键:alt+command+n** + +**作用:内联方法** + +- 选中main中的mprint +- alt+command+n +- 选中Inline all invocations and remove the method(2 occurrences) 点确定 + +然后我们等于什么也没有做了~~: + +```java +public static void main(String[] args) { + int result_add=new Cal().add(1,2); + int result_sub=new Cal2().sub(2,1); + System.out.println("Hello,s"); + System.out.println(result_add); + System.out.println(result_sub); +} +``` + +似乎这个例子不是很好,但是够用来说明了。 + +###Pull Members Up + +开始之前让我们先看看Cal2类: + +```java +public class Cal2 extends Cal { + + public int sub(int a,int b){ + return a-b; + } +} +``` + +以及Cal2的父类Cal + +```java +public class Cal { + + public int add(int a,int b){ + return a+b; + } + +} +``` + +最后的结果,就是将Cal2类中的sub方法,提到父类: + +```java +public class Cal { + + public int add(int a,int b){ + return a+b; + } + + public int sub(int a,int b){ + return a-b; + } +} +``` + +而我们所要做的就是鼠标右键 + +###重构之以查询取代临时变量 + +快捷键 + +Mac: 木有 + +Windows/Linux: 木有 + +或者: ``Shift``+``alt``+``command``+``T`` 再选择 ``Replace Temp with Query`` + +鼠标: **Refactor** | ``Replace Temp with Query`` + +####重构之前 + +过多的临时变量会让我们写出更长的函数,函数不应该太多,以便使功能单一。这也是重构的另外的目的所在,只有函数专注于其功能,才会更容易读懂。 + +以书中的代码为例 + +```java +import java.lang.System; + +public class replaceTemp { + public void count() { + double basePrice = _quantity * _itemPrice; + if (basePrice > 1000) { + return basePrice * 0.95; + } else { + return basePrice * 0.98; + } + } +} +``` + +####重构 + +选中``basePrice``很愉快地拿鼠标点上面的重构 + + + +便会返回 + +```java +import java.lang.System; + +public class replaceTemp { + public void count() { + if (basePrice() > 1000) { + return basePrice() * 0.95; + } else { + return basePrice() * 0.98; + } + } + + private double basePrice() { + return _quantity * _itemPrice; + } +} +``` + +而实际上我们也可以 + +1. 选中 + + _quantity * _itemPrice + +2. 对其进行``Extrace Method`` + +3. 选择``basePrice``再``Inline Method`` + +####Intellij IDEA重构 + +在Intellij IDEA的文档中对此是这样的例子 + +```java +public class replaceTemp { + + public void method() { + String str = "str"; + String aString = returnString().concat(str); + System.out.println(aString); + } + +} +``` + +接着我们选中``aString``,再打开重构菜单,或者 + +``Command``+``Alt``+``Shift``+``T`` 再选中Replace Temp with Query + +便会有下面的结果: + + +```javas +import java.lang.String; + +public class replaceTemp { + + public void method() { + String str = "str"; + System.out.println(aString(str)); + } + + private String aString(String str) { + return returnString().concat(str); + } + +} +``` \ No newline at end of file diff --git a/github-roam.md b/github-roam.md index d5cdc14..1914773 100644 --- a/github-roam.md +++ b/github-roam.md @@ -1588,6 +1588,83 @@ SQLiteHelper.prototype.getData = function (url, callback) { #测试 +##一次测试驱动开发 + +虽然接触的TDD时间不算短,然而真正在实践TDD上的时候少之又少。除去怎么教人TDD,就是与人结对编程时的switch,或许是受限于当前的开发流程。 + +偶然间在开发一个物联网相关的开源项目——[Lan](https://github.com/phodal/lan)的时候,重拾了这个过程。不得不说提到的一点是,在我们的开发流程中**测试是由相关功能开发人员写的**,有时候测试是一种很具挑战性的工作。久而久之,为自己的开源项目写测试变成一种自然而然的事。有时没有测试,反而变得**没有安全感**。 + +###故事 + +之前正在重写一个[物联网](http://www.phodal.com/iot)的服务端,主要便是结合CoAP、MQTT、HTTP等协议构成一个物联网的云服务。现在,主要的任务是集中于协议与授权。由于,不同协议间的授权是不一样的,最开始的时候我先写了一个http put授权的功能,而在起先的时候是如何测试的呢? + + curl --user root:root -X PUT -d '{ "dream": 1 }' -H "Content-Type: application/json" http://localhost:8899/topics/test + +我只要顺利在request中看有无``req.headers.authorization``,我便可以继续往下,接着给个判断。毕竟,我们对HTTP协议还是蛮清楚的。 + +```javascript +if (!req.headers.authorization) { + res.statusCode = 401; + res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"'); + return res.end('Unauthorized'); +} +``` + +可是除了HTTP协议,还有MQTT和CoAP。对于MQTT协议来说,那还算好,毕竟自带授权,如: + +```bash +mosquitto_pub -u root -P root -h localhost -d -t lettuce -m "Hello, MQTT. This is my first message." +``` + +便可以让我们简单地完成这个功能,然而有的协议是没有这样的功能如CoAP协议中是用Option来进行授权的。现在的工具如libcoap只能有如下的简单功能 + +```bash +coap-client -m get coap://127.0.0.1:5683/topics/zero -T +``` + +于是,先写了个测试脚本来验证功能。 + +```javascript +var coap = require('coap'); +var request = coap.request; +var req = request({hostname: 'localhost',port:5683,pathname: '',method: 'POST'}); + +... + +req.setHeader("Accept", "application/json"); +req.setOption('Block2', [new Buffer('phodal'), new Buffer('phodal')]); + +... + +req.end(); +``` + +写完测试脚本后发现不对了,这个不应该是测试的代码吗? 于是将其放到了spec中,接着发现了上面的全部功能的实现过程为什么不用TDD实现呢? + +###说说测试驱动开发 + +测试驱动开发是一个很"古老"的程序开发方法,然而由于国内的开发流程的问题——即开发人员负责功能的测试,导致这么好的一项技术没有在国内推广。 + +测试驱动开发的主要过程是: + +1. 先写功能的测试 +2. 实现功能代码 +3. 提交代码(commit -> 保证功能正常) +4. 重构功能代码 + +而对于这样的一个物联网项目来说,我已经有了几个有利的前提: + +1. 已经有了原型 +2. 框架设计 + +###思考 + +通常在我的理解下,TDD是可有可无的。既然我知道了我要实现的大部分功能,而且我也知道如何实现。与此同时,对Code Smell也保持着警惕、要保证功能被测试覆盖。那么,总的来说TDD带来的价值并不大。 + +然而,在当前这种情况下,我知道我想要的功能,但是我并不理解其深层次的功能。我需要花费大量的时候来理解,它为什么是这样的,需要先有一些脚本来知道它是怎么工作的。TDD变显得很有价值,换句话来说,在现有的情况下,TDD对于我们不了解的一些事情,可以驱动出更多的开发。毕竟在我们完成测试脚本之后,我们也会发现这些测试脚本成为了代码的一部分。 + +在这种理想的情况下,我们为什么不TDD呢? + #重构 或许你应该知道了,重构是怎样的,你也知道重构能带来什么。在我刚开始学重构和设计模式的时候,我需要去找一些好的示例,以便于我更好的学习。有时候不得不创造一些更好的场景,来实现这些功能。 @@ -1743,6 +1820,265 @@ str = tableHandler(str, execStr, strict); 快来试试吧, [https://github.com/artisanstack/js-refactor](https://github.com/artisanstack/js-refactor) +是时候讨论这个Refactor利器了,最初看到这个重构的过程是从ThoughtWorks郑大晔校开始的,只是之前对于Java的另外一个编辑器Eclipse的坏感。。这些在目前已经不是很重要了,试试这个公司里面应用广泛的编辑器。 + +##Interllij Idea重构 + +开发的流程大致就是这样子的,测试先行算是推荐的。 + + 编写测试->功能代码->修改测试->重构 + +上次在和buddy聊天的时候,才知道测试在功能简单的时候是后行的,在功能复杂不知道怎么手手的时候是先行的。 + + +开始之前请原谅我对于Java语言的一些无知,然后,看一下我写的Main函数: + +```java +package com.phodal.learing; + +public class Main { + + public static void main(String[] args) { + int c=new Cal().add(1,2); + int d=new Cal2().sub(2,1); + System.out.println("Hello,s"); + System.out.println(c); + System.out.println(d); + } +} +``` + +代码写得还好(自我感觉),先不管Cal和Cal2两个类。大部分都能看懂,除了c,d不知道他们表达的是什么意思,于是。 + +###Rename + +**快捷键:Shift+F6** + +**作用:重命名** + + - 把光标丢到int c中的c,按下shift+f6,输入result_add + - 把光标移到int d中的d,按下shift+f6,输入result_sub + +于是就有 + +```java +package com.phodal.learing; + +public class Main { + + public static void main(String[] args) { + int result_add=new Cal().add(1,2); + int result_sub=new Cal2().sub(2,1); + System.out.println("Hello,s"); + System.out.println(result_add); + System.out.println(result_sub); + } +} +``` + +###Extract Method + +**快捷键:alt+command+m** + +**作用:扩展方法** + +- 选中System.out.println(result_add); +- 按下alt+command+m +- 在弹出的窗口中输入mprint + +于是有了 + +```java +public static void main(String[] args) { + int result_add=new Cal().add(1,2); + int result_sub=new Cal2().sub(2,1); + System.out.println("Hello,s"); + mprint(result_add); + mprint(result_sub); +} + +private static void mprint(int result_sub) { + System.out.println(result_sub); +} +``` + +似乎我们不应该这样对待System.out.println,那么让我们内联回去 + +###Inline Method + +**快捷键:alt+command+n** + +**作用:内联方法** + +- 选中main中的mprint +- alt+command+n +- 选中Inline all invocations and remove the method(2 occurrences) 点确定 + +然后我们等于什么也没有做了~~: + +```java +public static void main(String[] args) { + int result_add=new Cal().add(1,2); + int result_sub=new Cal2().sub(2,1); + System.out.println("Hello,s"); + System.out.println(result_add); + System.out.println(result_sub); +} +``` + +似乎这个例子不是很好,但是够用来说明了。 + +###Pull Members Up + +开始之前让我们先看看Cal2类: + +```java +public class Cal2 extends Cal { + + public int sub(int a,int b){ + return a-b; + } +} +``` + +以及Cal2的父类Cal + +```java +public class Cal { + + public int add(int a,int b){ + return a+b; + } + +} +``` + +最后的结果,就是将Cal2类中的sub方法,提到父类: + +```java +public class Cal { + + public int add(int a,int b){ + return a+b; + } + + public int sub(int a,int b){ + return a-b; + } +} +``` + +而我们所要做的就是鼠标右键 + +###重构之以查询取代临时变量 + +快捷键 + +Mac: 木有 + +Windows/Linux: 木有 + +或者: ``Shift``+``alt``+``command``+``T`` 再选择 ``Replace Temp with Query`` + +鼠标: **Refactor** | ``Replace Temp with Query`` + +####重构之前 + +过多的临时变量会让我们写出更长的函数,函数不应该太多,以便使功能单一。这也是重构的另外的目的所在,只有函数专注于其功能,才会更容易读懂。 + +以书中的代码为例 + +```java +import java.lang.System; + +public class replaceTemp { + public void count() { + double basePrice = _quantity * _itemPrice; + if (basePrice > 1000) { + return basePrice * 0.95; + } else { + return basePrice * 0.98; + } + } +} +``` + +####重构 + +选中``basePrice``很愉快地拿鼠标点上面的重构 + + + +便会返回 + +```java +import java.lang.System; + +public class replaceTemp { + public void count() { + if (basePrice() > 1000) { + return basePrice() * 0.95; + } else { + return basePrice() * 0.98; + } + } + + private double basePrice() { + return _quantity * _itemPrice; + } +} +``` + +而实际上我们也可以 + +1. 选中 + + _quantity * _itemPrice + +2. 对其进行``Extrace Method`` + +3. 选择``basePrice``再``Inline Method`` + +####Intellij IDEA重构 + +在Intellij IDEA的文档中对此是这样的例子 + +```java +public class replaceTemp { + + public void method() { + String str = "str"; + String aString = returnString().concat(str); + System.out.println(aString); + } + +} +``` + +接着我们选中``aString``,再打开重构菜单,或者 + +``Command``+``Alt``+``Shift``+``T`` 再选中Replace Temp with Query + +便会有下面的结果: + + +```javas +import java.lang.String; + +public class replaceTemp { + + public void method() { + String str = "str"; + System.out.println(aString(str)); + } + + private String aString(String str) { + return returnString().concat(str); + } + +} +``` + #Github连击 ##100天 diff --git a/img/replace.jpg b/img/replace.jpg new file mode 100644 index 0000000..08d55ef Binary files /dev/null and b/img/replace.jpg differ diff --git a/index.html b/index.html index e840010..f4db17f 100644 --- a/index.html +++ b/index.html @@ -137,7 +137,13 @@ code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Inf
重构完后的代码比原来还长,这似乎是个问题~~
虽然接触的TDD时间不算短,然而真正在实践TDD上的时候少之又少。除去怎么教人TDD,就是与人结对编程时的switch,或许是受限于当前的开发流程。
+偶然间在开发一个物联网相关的开源项目——Lan的时候,重拾了这个过程。不得不说提到的一点是,在我们的开发流程中测试是由相关功能开发人员写的,有时候测试是一种很具挑战性的工作。久而久之,为自己的开源项目写测试变成一种自然而然的事。有时没有测试,反而变得没有安全感。
+之前正在重写一个物联网的服务端,主要便是结合CoAP、MQTT、HTTP等协议构成一个物联网的云服务。现在,主要的任务是集中于协议与授权。由于,不同协议间的授权是不一样的,最开始的时候我先写了一个http put授权的功能,而在起先的时候是如何测试的呢?
+curl --user root:root -X PUT -d '{ "dream": 1 }' -H "Content-Type: application/json" http://localhost:8899/topics/test
+我只要顺利在request中看有无req.headers.authorization,我便可以继续往下,接着给个判断。毕竟,我们对HTTP协议还是蛮清楚的。
if (!req.headers.authorization) {
+ res.statusCode = 401;
+ res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"');
+ return res.end('Unauthorized');
+}可是除了HTTP协议,还有MQTT和CoAP。对于MQTT协议来说,那还算好,毕竟自带授权,如:
+mosquitto_pub -u root -P root -h localhost -d -t lettuce -m "Hello, MQTT. This is my first message."便可以让我们简单地完成这个功能,然而有的协议是没有这样的功能如CoAP协议中是用Option来进行授权的。现在的工具如libcoap只能有如下的简单功能
+coap-client -m get coap://127.0.0.1:5683/topics/zero -T于是,先写了个测试脚本来验证功能。
+var coap = require('coap');
+var request = coap.request;
+var req = request({hostname: 'localhost',port:5683,pathname: '',method: 'POST'});
+
+...
+
+req.setHeader("Accept", "application/json");
+req.setOption('Block2', [new Buffer('phodal'), new Buffer('phodal')]);
+
+...
+
+req.end();写完测试脚本后发现不对了,这个不应该是测试的代码吗? 于是将其放到了spec中,接着发现了上面的全部功能的实现过程为什么不用TDD实现呢?
+测试驱动开发是一个很“古老”的程序开发方法,然而由于国内的开发流程的问题——即开发人员负责功能的测试,导致这么好的一项技术没有在国内推广。
+测试驱动开发的主要过程是:
+而对于这样的一个物联网项目来说,我已经有了几个有利的前提:
+通常在我的理解下,TDD是可有可无的。既然我知道了我要实现的大部分功能,而且我也知道如何实现。与此同时,对Code Smell也保持着警惕、要保证功能被测试覆盖。那么,总的来说TDD带来的价值并不大。
+然而,在当前这种情况下,我知道我想要的功能,但是我并不理解其深层次的功能。我需要花费大量的时候来理解,它为什么是这样的,需要先有一些脚本来知道它是怎么工作的。TDD变显得很有价值,换句话来说,在现有的情况下,TDD对于我们不了解的一些事情,可以驱动出更多的开发。毕竟在我们完成测试脚本之后,我们也会发现这些测试脚本成为了代码的一部分。
+在这种理想的情况下,我们为什么不TDD呢?
或许你应该知道了,重构是怎样的,你也知道重构能带来什么。在我刚开始学重构和设计模式的时候,我需要去找一些好的示例,以便于我更好的学习。有时候不得不创造一些更好的场景,来实现这些功能。
有一天,我发现当我需要我一次又一次地重复讲述某些内容,于是我就计划着把这些应该掌握的技能放到Github上,也就有了Artisan Stack 计划。
@@ -1614,6 +1675,188 @@ str = tableHandler(strreturn correctly class name快来试试吧, https://github.com/artisanstack/js-refactor
+是时候讨论这个Refactor利器了,最初看到这个重构的过程是从ThoughtWorks郑大晔校开始的,只是之前对于Java的另外一个编辑器Eclipse的坏感。。这些在目前已经不是很重要了,试试这个公司里面应用广泛的编辑器。
+开发的流程大致就是这样子的,测试先行算是推荐的。
+编写测试->功能代码->修改测试->重构
+上次在和buddy聊天的时候,才知道测试在功能简单的时候是后行的,在功能复杂不知道怎么手手的时候是先行的。
+开始之前请原谅我对于Java语言的一些无知,然后,看一下我写的Main函数:
+package com.phodal.learing;
+
+public class Main {
+
+ public static void main(String[] args) {
+ int c=new Cal().add(1,2);
+ int d=new Cal2().sub(2,1);
+ System.out.println("Hello,s");
+ System.out.println(c);
+ System.out.println(d);
+ }
+}代码写得还好(自我感觉),先不管Cal和Cal2两个类。大部分都能看懂,除了c,d不知道他们表达的是什么意思,于是。
+快捷键:Shift+F6
+作用:重命名
+于是就有
+package com.phodal.learing;
+
+public class Main {
+
+ public static void main(String[] args) {
+ int result_add=new Cal().add(1,2);
+ int result_sub=new Cal2().sub(2,1);
+ System.out.println("Hello,s");
+ System.out.println(result_add);
+ System.out.println(result_sub);
+ }
+}快捷键:alt+command+m
+作用:扩展方法
+于是有了
+public static void main(String[] args) {
+ int result_add=new Cal().add(1,2);
+ int result_sub=new Cal2().sub(2,1);
+ System.out.println("Hello,s");
+ mprint(result_add);
+ mprint(result_sub);
+}
+
+private static void mprint(int result_sub) {
+ System.out.println(result_sub);
+}似乎我们不应该这样对待System.out.println,那么让我们内联回去
+快捷键:alt+command+n
+作用:内联方法
+然后我们等于什么也没有做了~~:
+public static void main(String[] args) {
+ int result_add=new Cal().add(1,2);
+ int result_sub=new Cal2().sub(2,1);
+ System.out.println("Hello,s");
+ System.out.println(result_add);
+ System.out.println(result_sub);
+}似乎这个例子不是很好,但是够用来说明了。
+开始之前让我们先看看Cal2类:
+public class Cal2 extends Cal {
+
+ public int sub(int a,int b){
+ return a-b;
+ }
+}以及Cal2的父类Cal
+public class Cal {
+
+ public int add(int a,int b){
+ return a+b;
+ }
+
+}最后的结果,就是将Cal2类中的sub方法,提到父类:
+public class Cal {
+
+ public int add(int a,int b){
+ return a+b;
+ }
+
+ public int sub(int a,int b){
+ return a-b;
+ }
+}而我们所要做的就是鼠标右键
+快捷键
+Mac: 木有
+Windows/Linux: 木有
+或者: Shift+alt+command+T 再选择 Replace Temp with Query
鼠标: Refactor | Replace Temp with Query
过多的临时变量会让我们写出更长的函数,函数不应该太多,以便使功能单一。这也是重构的另外的目的所在,只有函数专注于其功能,才会更容易读懂。
+以书中的代码为例
+import java.lang.System;
+
+public class replaceTemp {
+ public void count() {
+ double basePrice = _quantity * _itemPrice;
+ if (basePrice > 1000) {
+ return basePrice * 0.95;
+ } else {
+ return basePrice * 0.98;
+ }
+ }
+}选中basePrice很愉快地拿鼠标点上面的重构

便会返回
+import java.lang.System;
+
+public class replaceTemp {
+ public void count() {
+ if (basePrice() > 1000) {
+ return basePrice() * 0.95;
+ } else {
+ return basePrice() * 0.98;
+ }
+ }
+
+ private double basePrice() {
+ return _quantity * _itemPrice;
+ }
+}而实际上我们也可以
+选中
+_quantity * _itemPrice
对其进行Extrace Method
选择basePrice再Inline Method
在Intellij IDEA的文档中对此是这样的例子
+public class replaceTemp {
+
+ public void method() {
+ String str = "str";
+ String aString = returnString().concat(str);
+ System.out.println(aString);
+ }
+
+}接着我们选中aString,再打开重构菜单,或者
Command+Alt+Shift+T 再选中Replace Temp with Query
便会有下面的结果:
+import java.lang.String;
+
+public class replaceTemp {
+
+ public void method() {
+ String str = "str";
+ System.out.println(aString(str));
+ }
+
+ private String aString(String str) {
+ return returnString().concat(str);
+ }
+
+}
我也是蛮拼的,虽然我想的只是在Github上连击100~200天,然而到了今天也算不错。
@@ -1819,7 +2062,7 @@ str = tableHandler(str编程的基础能力虽说算法很重要,但是编码才是基础能力。算法与编程在某种程度上是不同的领域,算法编程是在编程上面的一级。算法写得再好,如果别人很难直接拿来复用,在别人眼里就是shit。想出能work的代码一件简单的事,学会对其重构,使之变得更易读就是一件有意义的事。
于是,在某一时刻在Github上创建了一个组织,叫Artisan Stack。当时想的是在Github寻找一些JavaScript项目,对其代码进行重构。但是到底是影响力不够哈,参与的人数比较少。
-如果你懂得如何写出高可读的代码,那么我想你是不需要这个的,但是这意味着你花了更多的时候在思考上了。当谈论重构的时候,让我想起了TDD(测试驱动开发)。即使不是TDD,那么如果你写着测试,那也是可以重构的。(之前写过一些利用Intellij IDEA重构的文章:提炼函数、以查询取代临时变量、重构与Intellij Idea初探、内联函数)
在各种各样的文章里,我们看到过一些相关的内容,最好的参考莫过于《重构》一书。最基础不过的原则便是函数名,取名字很难,取别人能读懂的名字更难。其他的便有诸如长函数、过大的类、重复代码等等。在我有限的面试别人的经历里,这些问题都是最常见的。