数学建模社区-数学中国
标题:
代码洁癖系列(五):外在的格式美
[打印本页]
作者:
杨利霞
时间:
2019-3-23 15:52
标题:
代码洁癖系列(五):外在的格式美
代码洁癖系列(五):外在的格式美
9 v+ V9 e I1 G4 m
0 b( E8 Y# H) O; a0 k1 C
我们在阅读一些优秀项目的源码时,一定会感叹他们代码的整洁和一致性。而作为第一印象,代码格式的整齐是让人能够继续阅读下去的动力。今天我们分别从垂直格式和横向格式两个方面来讨论代码的格式。修正格式的方法有:间隔、靠近和调整顺序。
4 L- I7 b+ d* l! W ]; a p8 X
垂直格式
* K; `; ^4 D5 w9 B% s) A
M! H5 D" y4 y
在垂直格式方面,我们要向报纸的排版学习。
# N$ U+ q. }% D8 E3 l7 X4 F
- m: @) H& e; u% ^
# |3 O' o( G" U( t) f* f
R- D' k" B. Y' Y7 I
首先有一个标题告诉你这栏新闻要讲什么,好让你知道是否要继续阅读下去。对应到代码中就是类的名字,我们要力求只通过名字就可以知道这个类要描述什么事情;然后,代码的第一段往往都交代了整个故事的概要,类似于代码中的接口,我们往往通过接口了解类中有哪些函数,每个函数都是干什么的。了解了这些之后,才会去读详细的内容。
- Y% _5 H* N9 g' N
! ?6 \* |; {6 Q( B
newspaper code
, h0 ]7 ]& H$ A! G+ M
标题 类名
3 k7 V J& E# c
第一段 接口
. H5 E# }( J# u1 ~0 h
内容 方法体
$ h" |5 A) Z) A0 k, E
此外,还需要注意的就是报纸的排版、段落和段落之间用空行做间隔。写代码也可以用同样的方式,例如,我们习惯于在包声明、导入声明和每个函数之间用空白行来分隔。我们直接拿代码来解释。
; D1 C% Y6 L* \0 X( H& z0 `! m; |1 R
5 _1 p- W8 n0 ?9 `
package com.thoughtworks.selenium;
1 A! I& r! s9 i
import org.testng.ITestContext;
% A# W" N. p& x0 E8 I5 |
import org.testng.ITestResult;
6 z/ ]4 w$ Z/ @+ I A# r0 s$ y
import org.testng.Reporter;
$ i) p! C1 i- {3 F) W) |
import org.testng.internal.IResultListener;
/ w2 D+ \7 Q, n0 D/ k' q5 w- a
, C, M$ {0 n3 T* A: }5 N
import java.io.File;
* m/ U3 n; r. t) d
- U5 y: Q+ K" B2 L3 V5 u
public class ScreenshotListener implements IResultListener {
+ b, r/ O% e3 x+ A5 T
4 D7 r( |7 i* }& R' v$ ^" M/ i. i
File outputDirectory;
9 r9 r" O0 R( J
Selenium selenium;
, T) N X8 b! I5 u/ b) w& q# h. g
( D, d8 V1 H2 M
public ScreenshotListener(File outputDirectory, Selenium selenium) {
/ Y7 f5 V% t9 G* q
this.outputDirectory = outputDirectory;
" G$ u# W0 l+ p- x
this.selenium = selenium;
: y; w" L" q% L. L( @8 m
}
7 L) o+ G$ i& x* R: q' D
9 X% \: s# {9 [# L
public void onTestFailure(ITestResult result) {
& P' X3 H# A' \% s2 ^! i
Reporter.setCurrentTestResult(result);
/ V' y* s& z' b0 t; m0 V
' S& }6 ~: [9 l! o1 T2 s
try {
* Z: ^/ W+ f% h; k& c( Z
outputDirectory.mkdirs();
: m: @3 J8 f2 q4 Q9 `) }
File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
" o- |* l( o7 t/ i8 v' x
outFile.delete();
& [' ]& J) u! a" G1 a; `
selenium.captureScreenshot(outFile.getAbsolutePath());
5 k) S0 ~ _ g ?/ ^, y1 Z: d+ E
Reporter.log("<a href='" +
# S" g1 n' I. v0 B( q
outFile.getName() +
7 @6 y0 ?. e0 P) N: Q. T4 u
"'>screenshot</a>");
7 H1 g3 I [/ W" J# u, y
} catch (Exception e) {
5 X9 H: o( b: t8 x, y. ?
e.printStackTrace();
, l# B% w3 i$ Z& n N% W$ J' {
Reporter.log("Couldn't create screenshot");
/ E5 P0 W2 P- ~( Q; y# ]. K
Reporter.log(e.getMessage());
c; K% q, t3 ^; C# S6 m% U) M% t& Q
}
* V1 U S/ k {
$ q3 F8 i( h- z: n6 U2 {$ L) g) N
Reporter.setCurrentTestResult(null);
( H/ {% N) t5 [- z s' q: j
}
0 i3 N* {1 M O! |0 c- D6 @( ^
}
+ u+ i; n3 e3 B' U2 C
8 L' b) p! g8 Y1 w, C
package com.thoughtworks.selenium;
' A( M" b% A! R2 l/ O5 \
import org.testng.ITestContext;
9 t# i. J9 l, I, g
import org.testng.ITestResult;
- H, w6 y% m# B5 I1 I+ Q
import org.testng.Reporter;
5 O4 F) E6 B; P- H7 f) v& J- X
import org.testng.internal.IResultListener;
1 m2 d* v& A: M
import java.io.File;
' X3 _! b8 a& W* ^! I [
public class ScreenshotListener implements IResultListener {
$ e9 M: M' | B+ h ]5 ^. f0 g7 ?
File outputDirectory;
* D2 }4 r1 R* Y. c
Selenium selenium;
/ m6 i8 ]" N* Q1 a
public ScreenshotListener(File outputDirectory, Selenium selenium) {
7 c3 G/ b& ^3 o0 k. v# t- B
this.outputDirectory = outputDirectory;
: c1 o6 P3 V* N/ l% e. g
this.selenium = selenium;
$ h" X- w. T6 t3 N$ P6 Z
}
) P% g& X7 O0 ~8 T
public void onTestFailure(ITestResult result) {
1 k7 { Z2 y5 Z) C3 \" u
Reporter.setCurrentTestResult(result);
- x m% f3 d9 d7 r3 C* i3 y/ p
try {
; `$ O8 _: @. X; p" D; }
outputDirectory.mkdirs();
/ ]1 P/ s Q3 j# Q% Y7 d+ E+ J0 m. O
File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
* y, w1 a, E# V$ j
outFile.delete();
$ n* f% L# N" @6 ]/ L4 \" ?% W
selenium.captureScreenshot(outFile.getAbsolutePath());
; V4 O" s1 Z; A) A( Q. [4 K
Reporter.log("<a href='" +
- R5 W* m. c4 _3 I/ s4 c ~" |
outFile.getName() +
- @' a# A4 v0 x* y+ E6 d9 ~
"'>screenshot</a>");
4 R0 k8 F- V8 a/ c g# H; M
} catch (Exception e) {
2 G9 u# n) w, N9 C5 F! b
e.printStackTrace();
+ c7 o- D3 l; q2 ^
Reporter.log("Couldn't create screenshot");
; \0 x+ T/ |8 v
Reporter.log(e.getMessage());
" j; o5 |( `& H- [
}
8 M) B- f$ w6 ^
Reporter.setCurrentTestResult(null);
: O9 b& U% B5 U
}
1 b" ^& L( q+ `/ s& d/ D
}
/ m. e; u" T( }3 l. q$ |
是不是适当增加空白行就提高了代码的可读性呢,这里说的是适当增加空白行,并不代表随意增加。事实上,如果增加一些无意义的空白行反而会使代码的可读性变差。
7 B' k- V! F! b4 @' W2 u/ f# ~* v
1 `, }. E5 Y" \% J& N2 x: F0 S' @
我们习惯于使有关联的代码彼此靠近,无明显关联的代码相互分隔。因此我们不但需要使用空白行间隔代码,还要调整代码位置,把有关联的代码放在一起,通常我们把被调用的函数放在调用函数的下面。这样别人在读我们的代码的时候再也不用经历来回“跳跃”的痛苦了。
4 l5 c! d) x# r( ]. y9 Z. C7 B
4 F8 h/ N3 o7 @0 b+ G
最后,我们通常把实体变量定义在类的顶部,这个只是我们Java程序员的习惯操作,如果突然在类的中间位置出现一个变量声明会让人觉得很奇怪。如果你想说,定义在中间是不想让定义位置和调用位置离太远,那么只能说明你的类定义出现了问题。建议你看一下旧文代码洁癖系列(三):整洁的类和函数。
- t1 M4 E$ i2 Q# @
1 P+ X$ w3 N- T9 Z; l. [
横向格式
' V( o. \0 c' q& X2 g3 Q1 V. s& q
t5 d' U7 R1 g! ?
介绍完垂直格式,紧接着自然要来介绍一下它的兄弟,横向格式。或许你会问为什么不叫水平格式,我的回答是:也可以叫水平格式,只要你喜欢。横向格式也是需要间隔和靠近的,这里的间隔主要是为了起到强调的效果。举个例子。
; m# g. a+ q0 ?+ z, s, D
( B; _! }3 J) J( C; |7 M( g, `
int lineSize = line.length();
9 R W! j- X- s6 X3 ]
1
: y9 B; V T& C6 c+ O# w' N
这里等号两边的空格分别是为了强调左右两边的元素。横向格式另一个比较重要的元素就是缩进,Java程序对缩进没有强制性要求,而Python程序对缩进的要求非常严格,稍有不慎,执行的结果就会不同。但是Java程序员也要注意缩进,因为我们的代码是层级关系,而缩进可以帮我们快速理清层级关系。
* h A, L( x0 P
* O6 X4 N! [) w$ a" h+ Q
最后,横向代码格式对每行代码长度是有要求的,如果代码过长,那么在阅读的时候就需要左右滑动,而这个操作其实是不受人喜欢的。虽然现在代码编辑器可显示的长度变大了,但我们还是习惯每行代码最多100个字符。
# i1 f" R& G* T! I2 U8 p
6 w) h5 c1 V1 o8 D6 _/ Q* l7 |# _
团队的规则
; h# X0 S7 z* i% f+ K# L7 C: n
* t( ~( O9 k. \
每一个优秀的团队都已一套属于自己的代码格式要求,有些是特定的,有些是使用公共的。我们team所用的代码规范就是Google的代码规范,阿里的代码规范也是比较被大家认可的。这里给大家一个小福利,在我的公众号后台回复【代码规范】,就可以获得一份阿里的Java开发手册。
5 o" ]0 D" }' V h
---------------------
) D) B- v( C; K6 I8 f2 n9 N
1 V% @7 K4 W/ r) ~# y" }+ Y1 T+ t
+ a$ T9 a1 y- \9 V; D- o
1 M' f7 U, ]0 E" p
- s' X" S2 G, w3 U0 H @: [
0 L) G- `' p# y4 X( J
- n6 K; \2 O( z# ], K! m
! S2 P4 J: N4 a F8 R: V
. Y( Q! Y4 I6 S& s% O: A
( B- K7 [* ?9 U8 S
y6 F( H5 T: h- Q3 L; w$ H9 m
/ I, e0 Z% u* Q( V0 k
, }: N6 _$ G/ A/ A- r) P0 ?7 K
4 Q! F W9 Q# ]1 z+ ^# z
h4 ? g1 T5 \0 ~' I8 C- V
0 x4 f$ S5 M/ a2 v
2 R8 e! i& v" B( S4 ]- i* W& W. i
; L5 f+ ~, G9 t2 E4 ]; N
5 s/ Y& L8 g- E/ h
6 [4 V% i/ ]7 l1 o
# b5 i' O1 J; O$ Y$ K) z
3 M2 c$ A) X/ u, }
( u- E, z7 I# |6 G- z* Z
( R3 s$ h1 D7 l5 H0 |# _1 ]
4 C2 e$ Q3 k$ n9 B' d% b2 F
& b) U8 H# T: i X% E
/ r7 T: i* \# y% ~3 E: {5 i/ y
" z& k- [: n( k& ^8 f6 J
16种常用的数据分析方法汇总.docx
2019-3-25 17:29 上传
点击文件名下载附件
下载积分: 体力 -2 点
20.53 KB, 下载次数: 1, 下载积分: 体力 -2 点
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5