数学建模社区-数学中国
标题:
代码洁癖系列(五):外在的格式美
[打印本页]
作者:
杨利霞
时间:
2019-3-23 15:52
标题:
代码洁癖系列(五):外在的格式美
代码洁癖系列(五):外在的格式美
# N8 \6 E$ N2 \- e% q/ @0 J
+ L, ^) x1 x% W. `
我们在阅读一些优秀项目的源码时,一定会感叹他们代码的整洁和一致性。而作为第一印象,代码格式的整齐是让人能够继续阅读下去的动力。今天我们分别从垂直格式和横向格式两个方面来讨论代码的格式。修正格式的方法有:间隔、靠近和调整顺序。
! P# b2 a9 Y4 s3 h" E' K- ]6 M
垂直格式
3 t# R; C& G4 d0 V! C h/ G
' ]& L- W3 d6 N( l
在垂直格式方面,我们要向报纸的排版学习。
* x" y& m8 [" b/ k- z+ c7 }$ j
, } z b2 o z" F, b9 o
% E; {& X- L/ \7 j* W3 ]
) U$ ~8 C% j$ @
首先有一个标题告诉你这栏新闻要讲什么,好让你知道是否要继续阅读下去。对应到代码中就是类的名字,我们要力求只通过名字就可以知道这个类要描述什么事情;然后,代码的第一段往往都交代了整个故事的概要,类似于代码中的接口,我们往往通过接口了解类中有哪些函数,每个函数都是干什么的。了解了这些之后,才会去读详细的内容。
% d2 |. r# [* g3 `: ?9 p i
7 n- w/ M9 @& P+ u. Q
newspaper code
5 w. `8 S# r$ l( @; V0 [. X- S0 X
标题 类名
5 D/ v/ H( N6 Z7 s" e7 v- n
第一段 接口
+ h5 J( w- b9 Y" D0 S
内容 方法体
; W, }( P6 u8 R' u: } P
此外,还需要注意的就是报纸的排版、段落和段落之间用空行做间隔。写代码也可以用同样的方式,例如,我们习惯于在包声明、导入声明和每个函数之间用空白行来分隔。我们直接拿代码来解释。
2 D4 A* X* _- Q0 H
+ D" T/ h, k" m; {" w
package com.thoughtworks.selenium;
. u/ |1 o& X8 O* B/ @
import org.testng.ITestContext;
* ^' k+ t! p1 l8 o* R* ~. D
import org.testng.ITestResult;
$ P, C0 n Y& r0 B! O8 }
import org.testng.Reporter;
( d5 U4 J; w. k
import org.testng.internal.IResultListener;
$ E9 \+ Z8 L! u3 l& U& l; Q
# `3 E- |) t! y' R- L1 O3 q9 C4 G
import java.io.File;
) @, O/ Y5 x( I! ?/ W3 d
8 m* q$ ?4 W( `- i# V8 V
public class ScreenshotListener implements IResultListener {
, g) z# A0 g! v# O8 V
2 `% R' s2 n1 g" b: N' [( I* F8 M( y, Q
File outputDirectory;
. w, \' r( s; H
Selenium selenium;
9 b0 h1 C+ R& W# p
q0 K2 M7 x1 E7 p1 h( c* e% e
public ScreenshotListener(File outputDirectory, Selenium selenium) {
1 C+ F7 k+ I4 }: u$ i
this.outputDirectory = outputDirectory;
% q0 \1 X9 {. E9 [0 f- P
this.selenium = selenium;
" F7 w6 d" f% X
}
+ x* v; v4 S* E F- ^
! A( J7 C- R) I0 q- I" y
public void onTestFailure(ITestResult result) {
1 W9 o8 G3 v9 ^( N
Reporter.setCurrentTestResult(result);
8 b1 |' g6 B1 A
* S+ N. N- L: S; L4 b
try {
2 V* i& X/ _/ F& Q/ Y( q7 ~8 G& U
outputDirectory.mkdirs();
7 l. b* N) R$ Y
File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
9 {) X3 U( e% Q) O% v" p
outFile.delete();
, ]* Z; z* Q" a) j
selenium.captureScreenshot(outFile.getAbsolutePath());
+ B; m0 |( B W& k) B3 w
Reporter.log("<a href='" +
4 Q9 w6 H, N0 u8 b, Q$ d
outFile.getName() +
/ f4 T7 i7 T% [! I2 I
"'>screenshot</a>");
- G# @+ n0 j' `
} catch (Exception e) {
% b$ E0 l* o7 a. y, t& D
e.printStackTrace();
$ |- i7 P4 F% i9 S! o9 q b$ i
Reporter.log("Couldn't create screenshot");
7 S/ Q) O! H0 i6 g) s7 X
Reporter.log(e.getMessage());
) _& M: k G) X# `' R4 G+ X( {
}
: S9 G1 f. H- f; b
2 R7 Q- U1 c9 R( m. L9 D( e2 ~
Reporter.setCurrentTestResult(null);
# ?0 O' v& m- V; g
}
' v9 d- b" ?! f7 n
}
4 C8 p+ F( u0 ?* m. b! @8 R/ C
2 S* |/ [+ i2 o+ \4 y) B
package com.thoughtworks.selenium;
1 D) y5 T& b9 f8 f5 V8 T% C# `) m6 S* _
import org.testng.ITestContext;
/ \6 Q8 F9 ?1 a8 r& X
import org.testng.ITestResult;
+ Q# R( p- W N3 Y4 m- c: n2 o' c3 O
import org.testng.Reporter;
1 Y! F! J- v% \" t1 d4 ?7 Y
import org.testng.internal.IResultListener;
# r: ]; `" O$ W$ h! [6 o/ M0 ]
import java.io.File;
' c# j% g1 n! \6 z1 O F: V2 k
public class ScreenshotListener implements IResultListener {
+ T3 p& J# S2 e' K6 {
File outputDirectory;
6 `9 J4 y, C+ j' R' `
Selenium selenium;
" S9 H. Z3 _! b! q4 o! O( {
public ScreenshotListener(File outputDirectory, Selenium selenium) {
$ y& N$ n3 {: I4 S$ v
this.outputDirectory = outputDirectory;
6 k5 i- g0 ]% M$ Q* m7 O1 x
this.selenium = selenium;
8 K0 K" _( V6 V8 K# s0 A
}
* q9 V- C1 T7 E& H
public void onTestFailure(ITestResult result) {
$ e, M% a- R0 w/ q6 t* `0 p
Reporter.setCurrentTestResult(result);
2 r3 y% i/ c( D. x/ P& T
try {
- a' T% L4 ]0 T4 |2 p
outputDirectory.mkdirs();
: r2 _. u. z1 P* y
File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
E: w D! q6 n4 _; |/ x% \) ~* d& _
outFile.delete();
9 r7 R' g" u5 W2 ^! h
selenium.captureScreenshot(outFile.getAbsolutePath());
, O1 s, o: H o9 s9 Q; m
Reporter.log("<a href='" +
7 Y9 z6 d: N( N8 ]- W- W3 F3 ?
outFile.getName() +
3 H2 P5 a0 P6 H. W" Z/ Y
"'>screenshot</a>");
' k. E" s' q/ |0 w# I
} catch (Exception e) {
8 O# B+ {, c& a. B+ ?3 N
e.printStackTrace();
( w1 Y0 n- Z: [, O1 ~; e- ~, f
Reporter.log("Couldn't create screenshot");
1 Z/ _+ u9 c2 {( C9 D; T
Reporter.log(e.getMessage());
8 G3 l) g' G! p
}
: P) U- r- m% k% V. x V
Reporter.setCurrentTestResult(null);
+ o) a( l! N/ _9 k7 U
}
/ {9 k4 Q8 R& z1 y3 w
}
. U4 |3 }9 ]/ O1 m2 Q8 _: W
是不是适当增加空白行就提高了代码的可读性呢,这里说的是适当增加空白行,并不代表随意增加。事实上,如果增加一些无意义的空白行反而会使代码的可读性变差。
! o# K6 T1 \: X3 I7 T/ F/ ?
2 H% H5 x' d' u7 w5 {8 M2 w
我们习惯于使有关联的代码彼此靠近,无明显关联的代码相互分隔。因此我们不但需要使用空白行间隔代码,还要调整代码位置,把有关联的代码放在一起,通常我们把被调用的函数放在调用函数的下面。这样别人在读我们的代码的时候再也不用经历来回“跳跃”的痛苦了。
: d' \7 `$ N' J# O, I
9 I. J% ^3 }' Y' y. _7 b
最后,我们通常把实体变量定义在类的顶部,这个只是我们Java程序员的习惯操作,如果突然在类的中间位置出现一个变量声明会让人觉得很奇怪。如果你想说,定义在中间是不想让定义位置和调用位置离太远,那么只能说明你的类定义出现了问题。建议你看一下旧文代码洁癖系列(三):整洁的类和函数。
4 r2 r3 \! q3 ~( R* B. E4 v" X, e
; u4 ~: W9 P$ H- C* }7 i
横向格式
" V4 j5 V7 n F7 i
$ J# Q2 h7 [* S' V+ g
介绍完垂直格式,紧接着自然要来介绍一下它的兄弟,横向格式。或许你会问为什么不叫水平格式,我的回答是:也可以叫水平格式,只要你喜欢。横向格式也是需要间隔和靠近的,这里的间隔主要是为了起到强调的效果。举个例子。
( Z! Q9 V- ~5 W, |8 f% |
7 h9 A* f3 F3 f9 t& } ?
int lineSize = line.length();
p* t" e7 x% R# n( m) }" s
1
% G6 O( ^0 E+ Y! g8 ~9 g
这里等号两边的空格分别是为了强调左右两边的元素。横向格式另一个比较重要的元素就是缩进,Java程序对缩进没有强制性要求,而Python程序对缩进的要求非常严格,稍有不慎,执行的结果就会不同。但是Java程序员也要注意缩进,因为我们的代码是层级关系,而缩进可以帮我们快速理清层级关系。
. o! I7 Z; g' X5 g) d
+ j) q8 t+ n* n) f% u4 R
最后,横向代码格式对每行代码长度是有要求的,如果代码过长,那么在阅读的时候就需要左右滑动,而这个操作其实是不受人喜欢的。虽然现在代码编辑器可显示的长度变大了,但我们还是习惯每行代码最多100个字符。
. A! ?! y5 t' {# b8 x: a
: k2 ? L1 T3 f% ?2 Y0 W
团队的规则
2 [$ z# g3 ~& C0 v* q$ W
! i8 Q9 g8 B- G) T/ ] n- K
每一个优秀的团队都已一套属于自己的代码格式要求,有些是特定的,有些是使用公共的。我们team所用的代码规范就是Google的代码规范,阿里的代码规范也是比较被大家认可的。这里给大家一个小福利,在我的公众号后台回复【代码规范】,就可以获得一份阿里的Java开发手册。
( n- R9 [. S* Y R/ C; f
---------------------
* }7 p% g3 m- B( z$ j
' @* E! d9 \" D* _2 H
# ]1 W3 z ?) _) @
, e0 `# s; M" q: t1 I
$ b, p/ d2 H( ~3 d
: T( Z- S8 c" b8 @# b0 [" m
7 I0 v X. j3 m$ e8 o' z% q, g* [
: C" Z) h. ^. h* b& r% z1 W
7 o" J# Q% d9 p
3 F, |" G- E9 x, p! N) i, ~# y
( R- Z* i& w* q0 b
; ~: y1 n$ s/ z9 G" K3 J: E
( t% {1 V& k" |" p
: F, j; }# J; z0 Y, Q6 \8 R$ ~5 l
: A# {& Q4 _) H n6 A; P W
u, O$ _, r. M% J0 m2 f; o& }
' }* A% q" @4 K8 L3 r
; J0 u$ f; Z9 I# R0 A- d6 i4 M
) y6 m. u: u0 Y" H: y' H
. f# i7 A! j5 p. b, M5 l5 _
) q8 v, O6 p. c6 ?, u) {
( ?# s, Y1 x2 O: u% y. d
9 |( I! j+ R6 X7 y. i* O. O% ?
9 h5 w V! C# l& ^
! @4 w N: I+ R# x# I
+ ^% N% C/ h1 Z( b) H
% z; X; y4 Q/ Y/ C, K, b
+ ]0 E" U) w9 G0 ~
16种常用的数据分析方法汇总.docx
2019-3-25 17:29 上传
点击文件名下载附件
下载积分: 体力 -2 点
20.53 KB, 下载次数: 1, 下载积分: 体力 -2 点
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5