数学建模社区-数学中国
标题:
代码洁癖系列(五):外在的格式美
[打印本页]
作者:
杨利霞
时间:
2019-3-23 15:52
标题:
代码洁癖系列(五):外在的格式美
代码洁癖系列(五):外在的格式美
4 I/ T7 t! _. u* b) R
. T7 ^7 D& Y: g8 j7 z
我们在阅读一些优秀项目的源码时,一定会感叹他们代码的整洁和一致性。而作为第一印象,代码格式的整齐是让人能够继续阅读下去的动力。今天我们分别从垂直格式和横向格式两个方面来讨论代码的格式。修正格式的方法有:间隔、靠近和调整顺序。
* b6 e- }# D5 w e. z& B
垂直格式
) y( R3 \3 [4 ^( m5 x' N! x
8 F3 {* G1 K: a
在垂直格式方面,我们要向报纸的排版学习。
( q3 J% u1 L. n3 e3 b
8 H" h( o' w! }" v$ [+ T
1 z- @# {5 x# ]* E
/ Y/ r& [( o4 q! w- L
首先有一个标题告诉你这栏新闻要讲什么,好让你知道是否要继续阅读下去。对应到代码中就是类的名字,我们要力求只通过名字就可以知道这个类要描述什么事情;然后,代码的第一段往往都交代了整个故事的概要,类似于代码中的接口,我们往往通过接口了解类中有哪些函数,每个函数都是干什么的。了解了这些之后,才会去读详细的内容。
, y! y% T8 u$ x& q, R
! u' H9 `9 t8 }4 i
newspaper code
& b9 H" Q7 C# [& f. j: t$ M
标题 类名
! O7 \! J4 ?0 J; j; x. Y+ [( a
第一段 接口
/ T1 j* U6 `$ T6 ~4 G6 G
内容 方法体
0 `$ Y0 G& N- q% F
此外,还需要注意的就是报纸的排版、段落和段落之间用空行做间隔。写代码也可以用同样的方式,例如,我们习惯于在包声明、导入声明和每个函数之间用空白行来分隔。我们直接拿代码来解释。
: f) n/ {4 `4 l( H1 A5 b2 `
) o' D' R l0 }4 l
package com.thoughtworks.selenium;
/ p' X+ ^. a$ E( Y. E
import org.testng.ITestContext;
6 G- H* \: @' X6 t* X
import org.testng.ITestResult;
2 } Z4 `1 s5 b0 e
import org.testng.Reporter;
1 G$ ^" T' Q# x, }2 t% S5 S
import org.testng.internal.IResultListener;
/ p$ R, D( k0 d" y( U8 r& N9 a, s
( K: B$ Q5 J( k( H% |9 |# n' N
import java.io.File;
$ `1 F. n, V4 A3 B. l
: O4 o, w% X2 J
public class ScreenshotListener implements IResultListener {
- \) M- D7 ]. l$ V( P7 i& U5 W7 m
4 `+ x- { ]7 y+ O; j2 B& s1 y
File outputDirectory;
7 @- s+ v& x7 D' h& l9 v8 G
Selenium selenium;
4 }; @$ A5 L$ ]2 N" X$ r
8 X. m# k [6 U+ F& |2 I4 Z N$ ]
public ScreenshotListener(File outputDirectory, Selenium selenium) {
% J: y8 y) [" u, ?+ s2 O
this.outputDirectory = outputDirectory;
! D" f6 b' H" r! Q$ [( u$ a) k* E) I2 F
this.selenium = selenium;
% X# D+ V$ H; r0 N
}
) J( k5 `- o0 i( {9 b
; ~ j- B* }7 ?6 u
public void onTestFailure(ITestResult result) {
6 H! k: l! D0 E' I" l
Reporter.setCurrentTestResult(result);
/ S0 y. d; n! k5 W2 ^% o) v" q
5 Q) O0 A) ]& Y2 w+ D. I
try {
# U) G: w# m# C
outputDirectory.mkdirs();
K4 | [ p7 l8 n$ ]0 _7 `3 @- Q, \
File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
, B2 o8 z1 j7 Z6 A2 b
outFile.delete();
- `- b3 d5 m# _2 E% y3 z. o
selenium.captureScreenshot(outFile.getAbsolutePath());
& O9 I x" m' x! r6 h
Reporter.log("<a href='" +
( a' @: r& y) z4 @4 {! E" }
outFile.getName() +
7 Y5 b/ G- ~/ ?$ k4 ?2 C! }& \
"'>screenshot</a>");
" I1 p, N9 R* u2 A8 H2 s8 n9 ~
} catch (Exception e) {
! B; a: r: s5 f6 J; o7 R3 n
e.printStackTrace();
* r- {" _ K; L; |1 ]
Reporter.log("Couldn't create screenshot");
" R2 ]) u0 T: l7 O k! U4 s+ O, T% D
Reporter.log(e.getMessage());
& ]& D# n2 R' G
}
J V# Q( q6 v
: w* B; l' y0 u+ K7 R
Reporter.setCurrentTestResult(null);
$ U) v: m/ u, Q, J5 I4 F& N5 k
}
0 U7 s Y' H; ?9 a- r
}
* ^3 |6 s4 M: P) `( Z
4 w# O4 b5 ?6 {: {5 v" @
package com.thoughtworks.selenium;
) `; I, P8 R8 E d) r8 Z- i* u
import org.testng.ITestContext;
% B( U6 v% p3 h/ E# {9 T: {
import org.testng.ITestResult;
6 n& q8 [- ]$ M( p6 P) P) g4 r0 J
import org.testng.Reporter;
3 z, w0 L" [! y& W- B
import org.testng.internal.IResultListener;
/ J) Q% q. v j0 O: G# M7 }) [" d5 I: P
import java.io.File;
9 f. }+ \1 b( t K1 b
public class ScreenshotListener implements IResultListener {
6 K* o9 A9 U. ~+ s9 h; [* `+ r+ b2 f
File outputDirectory;
* I/ j; S" L! B& V
Selenium selenium;
- ^( \3 R$ d# p, F* U
public ScreenshotListener(File outputDirectory, Selenium selenium) {
3 x6 ]/ Z. M0 f2 \9 e, }
this.outputDirectory = outputDirectory;
9 q' D) U) o$ L4 k. L) e& I
this.selenium = selenium;
0 T7 ~* k) j; `6 m" J0 o
}
+ | _& L% R/ t' d; g
public void onTestFailure(ITestResult result) {
% N/ n. ?7 ^" H( v D
Reporter.setCurrentTestResult(result);
$ @8 {* c9 h D' W2 Z
try {
- `" K/ M X" p. T
outputDirectory.mkdirs();
4 k( o4 d7 G ?. W% ^% I' _
File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
* p, i3 V; ]7 m4 S
outFile.delete();
2 y& b+ Z, \1 P
selenium.captureScreenshot(outFile.getAbsolutePath());
7 X6 ~9 F3 g4 ^0 u6 X
Reporter.log("<a href='" +
" n- U* i9 U. b
outFile.getName() +
# d7 V$ G; n3 D
"'>screenshot</a>");
; W/ O9 ^$ a; v: W! p4 V7 B1 m
} catch (Exception e) {
- @8 t6 G+ U; a- w
e.printStackTrace();
$ {2 W1 z7 N5 n
Reporter.log("Couldn't create screenshot");
! Y5 ]- q; X T# l; e: F
Reporter.log(e.getMessage());
5 G- q2 f- T4 z( F& A) G1 }1 {# e2 m) T
}
% Y& O: Z3 h5 ]) i& T
Reporter.setCurrentTestResult(null);
! T' U. L" Z9 }- J/ a2 O4 U) r
}
" \# j+ Z% c6 a6 d. I" K: J
}
. t. a; `( N5 L4 w9 ~- `4 O$ b+ z
是不是适当增加空白行就提高了代码的可读性呢,这里说的是适当增加空白行,并不代表随意增加。事实上,如果增加一些无意义的空白行反而会使代码的可读性变差。
3 T$ d* M: o* A* y
' X. X' B. X4 T
我们习惯于使有关联的代码彼此靠近,无明显关联的代码相互分隔。因此我们不但需要使用空白行间隔代码,还要调整代码位置,把有关联的代码放在一起,通常我们把被调用的函数放在调用函数的下面。这样别人在读我们的代码的时候再也不用经历来回“跳跃”的痛苦了。
9 c2 B- F! e4 `; t* t
: K9 i9 h& v9 d; g6 p" N2 I: U
最后,我们通常把实体变量定义在类的顶部,这个只是我们Java程序员的习惯操作,如果突然在类的中间位置出现一个变量声明会让人觉得很奇怪。如果你想说,定义在中间是不想让定义位置和调用位置离太远,那么只能说明你的类定义出现了问题。建议你看一下旧文代码洁癖系列(三):整洁的类和函数。
& }3 ] V& V. ?! O# p) N
( v, g# M- R: t% a$ \
横向格式
4 P9 r: i/ A+ G$ P7 x" g- L
4 Q1 l. q+ Y2 N# h- r3 t6 T
介绍完垂直格式,紧接着自然要来介绍一下它的兄弟,横向格式。或许你会问为什么不叫水平格式,我的回答是:也可以叫水平格式,只要你喜欢。横向格式也是需要间隔和靠近的,这里的间隔主要是为了起到强调的效果。举个例子。
8 `. c( ]& Z$ v, V, `2 a
; q. w7 b# C/ Q# n7 |/ H
int lineSize = line.length();
! }6 e' Z( H; a
1
# o2 }9 l) f( g _
这里等号两边的空格分别是为了强调左右两边的元素。横向格式另一个比较重要的元素就是缩进,Java程序对缩进没有强制性要求,而Python程序对缩进的要求非常严格,稍有不慎,执行的结果就会不同。但是Java程序员也要注意缩进,因为我们的代码是层级关系,而缩进可以帮我们快速理清层级关系。
* y9 o$ C8 h* L
/ N9 p! z H4 L5 k
最后,横向代码格式对每行代码长度是有要求的,如果代码过长,那么在阅读的时候就需要左右滑动,而这个操作其实是不受人喜欢的。虽然现在代码编辑器可显示的长度变大了,但我们还是习惯每行代码最多100个字符。
- a+ G X2 E% [( f8 s
0 x/ n5 n1 }0 O% H4 \. |9 N& w
团队的规则
+ |2 [6 H% `/ \2 I: I1 @& }
1 S" B- F7 a7 S
每一个优秀的团队都已一套属于自己的代码格式要求,有些是特定的,有些是使用公共的。我们team所用的代码规范就是Google的代码规范,阿里的代码规范也是比较被大家认可的。这里给大家一个小福利,在我的公众号后台回复【代码规范】,就可以获得一份阿里的Java开发手册。
( \' Q4 Y5 M- }( c2 c% l# n! c: O
---------------------
' o9 i' P! M% {* q8 s
$ s4 r1 K# Z! L8 N M2 h2 B N
5 S! l9 h/ i) B1 y8 D' Y( P; T
/ @ E$ H$ J) D ~& X- c5 d& k
2 f& e1 h3 G$ `5 @7 F
3 f- e3 Q2 y7 W- d5 A& ^% @5 G; J# K
+ F/ x% |1 n- v
' l- I. Y6 O! \) {
# N: Y% f$ v$ }8 Y6 a
& Q2 P+ B# ]- h. Q' G* l
7 W8 m9 R- j8 W8 r* G( w# L
$ x) e! F# N0 V! O
" `: ^& F* z* J1 H7 p/ l T2 |
6 t0 d G$ T( n3 D
$ b( n' k( b% b) K" y
$ V: E* d6 G, y# w' B9 l1 c
7 Y1 m" \3 {9 K9 O4 Y& O& u; G
! u' T) [' H/ Z" J
8 f7 M( s9 ~- E$ s6 f$ @
$ v( w# K+ B2 `8 b; O
! \" j* R* }2 s8 @: y4 p' |# C
) f. R% Q% S4 S E$ d2 J5 D
4 i; ?' F6 ~; }
0 z8 o8 l% U$ r: H
$ Q; @* v0 G: Q1 A0 ?
5 |0 K2 v0 m2 b; Y7 H
2 j0 _- _ ?7 U- J% S. F
9 C/ r* f; B6 {% E
16种常用的数据分析方法汇总.docx
2019-3-25 17:29 上传
点击文件名下载附件
下载积分: 体力 -2 点
20.53 KB, 下载次数: 1, 下载积分: 体力 -2 点
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5