数学建模社区-数学中国

标题: 代码洁癖系列(五):外在的格式美 [打印本页]

作者: 杨利霞    时间: 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( Bnewspaper        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$ yimport 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 upublic 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, gimport 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- Ximport 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 B4 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 p6 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 K4 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 ]; N5 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

20.53 KB, 下载次数: 1, 下载积分: 体力 -2 点






欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5