数学建模社区-数学中国

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

作者: 杨利霞    时间: 2019-3-23 15:52
标题: 代码洁癖系列(五):外在的格式美
代码洁癖系列(五):外在的格式美
3 b3 s0 N! d/ }( n- {1 S1 c( Y  y! y' R( Z
我们在阅读一些优秀项目的源码时,一定会感叹他们代码的整洁和一致性。而作为第一印象,代码格式的整齐是让人能够继续阅读下去的动力。今天我们分别从垂直格式和横向格式两个方面来讨论代码的格式。修正格式的方法有:间隔、靠近和调整顺序。
  J* S9 e1 ~" Y, S% g# r: ~! z垂直格式6 f& D) x& T1 d! W3 w  r( x  C  x: |
. ]% \" o. C. k8 O2 a6 ?
在垂直格式方面,我们要向报纸的排版学习。
  B5 }6 x# A! ~, V" Q$ k  d9 P( `: K- Y+ u- M3 S2 O

' [  A$ h5 U0 F) `% G( N# a8 C  x1 w# \% A/ v$ C( `
首先有一个标题告诉你这栏新闻要讲什么,好让你知道是否要继续阅读下去。对应到代码中就是类的名字,我们要力求只通过名字就可以知道这个类要描述什么事情;然后,代码的第一段往往都交代了整个故事的概要,类似于代码中的接口,我们往往通过接口了解类中有哪些函数,每个函数都是干什么的。了解了这些之后,才会去读详细的内容。
' I5 Y( S5 ]' r& y
: m: {- L8 m$ ~' D- vnewspaper        code
- |$ S' I% I2 [/ N标题        类名
2 G8 ?% R9 m2 h5 p第一段        接口5 N1 Q( O+ _& ~5 Y4 [
内容        方法体' ?$ D& `, w! z" M# w9 y, y/ k
此外,还需要注意的就是报纸的排版、段落和段落之间用空行做间隔。写代码也可以用同样的方式,例如,我们习惯于在包声明、导入声明和每个函数之间用空白行来分隔。我们直接拿代码来解释。
) S$ ?4 u# S& R! a" ?7 h8 h" {8 E+ t2 M+ S) I" @
package com.thoughtworks.selenium;* s+ v& ?4 y. u- j
import org.testng.ITestContext;3 p, u7 H: F. t/ ]+ }/ R
import org.testng.ITestResult;; G! M- q% y! T9 I4 e
import org.testng.Reporter;- q. n& ~: \4 d
import org.testng.internal.IResultListener;
; }3 e; \9 p& n1 R
$ u* K: z, o  u6 b- Iimport java.io.File;' Q0 l) o$ l% A0 q; t8 O
# Z0 J5 u, _$ u; i. S. a
public class ScreenshotListener implements IResultListener {
9 N' @4 d7 @" e; ]
! W/ c: L! i8 |/ J0 ]2 g. Q  File outputDirectory;
. n7 i8 d4 C& }8 |$ T$ b4 |  Selenium selenium;
) L' F& H- p/ U! |/ A
  u$ |; R9 q' ]% ]6 U: ]  public ScreenshotListener(File outputDirectory, Selenium selenium) {& T. r  n: a- w4 U( C" ?' y
    this.outputDirectory = outputDirectory;
; `8 k* j4 A# z" m" t  d& D    this.selenium = selenium;. Y7 n% q/ R4 C- ]
  }' M4 l8 j) E- ]7 a/ ]' w  s
/ u4 g$ w, t6 }  U* |3 n
  public void onTestFailure(ITestResult result) {
0 q- A* u1 C' y    Reporter.setCurrentTestResult(result);
: S2 f9 _9 G/ `
3 z) J; N% q- Y) n8 b! C$ x    try {
. h8 x% W4 M/ r      outputDirectory.mkdirs();. D& g/ d3 Z: R% T' F
      File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
; ?+ {; E4 D+ @* H; c0 t      outFile.delete();) k& z4 |& h; G1 D2 C) ^) Q4 ^
      selenium.captureScreenshot(outFile.getAbsolutePath());5 ^) t+ j4 S: ]% o) a' p
      Reporter.log("<a href='" +
1 k% M' o& e+ e" N9 d          outFile.getName() +
. x6 @8 G" E5 }) Q: C' I3 ]          "'>screenshot</a>");
& P' _8 Q# a7 \& n    } catch (Exception e) {$ O" O3 {2 s9 U$ }! e& @; X
      e.printStackTrace();
1 n% d. }9 V7 x, C& v" U: i      Reporter.log("Couldn't create screenshot");. f  `. [7 _2 b5 x, D! G
      Reporter.log(e.getMessage());
. d; O  `, Q: _' S$ R2 E0 D7 B    }. d; R2 _  a- ~! z+ h

. [/ E& C; _3 i) N- P    Reporter.setCurrentTestResult(null);7 n7 h$ T' V! M4 j3 i# j
  }
  E6 i2 C& s0 f}0 ~. v( e, S& B' f0 v

9 |2 _3 R; @6 Fpackage com.thoughtworks.selenium;+ T. {! g* S  o" C  U
import org.testng.ITestContext;* Z/ T. q2 J( a1 T3 ?( `
import org.testng.ITestResult;2 K  C, A8 v  j- z; P
import org.testng.Reporter;" s% x$ |7 Q- J4 j* w2 V  k
import org.testng.internal.IResultListener;+ Z/ Q5 `0 }$ O" S
import java.io.File;: e. g1 }4 C/ l) K
public class ScreenshotListener implements IResultListener {
9 k8 k& C" K$ A; J. _) z  File outputDirectory;0 s& W/ @9 O1 g
  Selenium selenium;
* I* a8 P3 A0 o& i9 ]" x  public ScreenshotListener(File outputDirectory, Selenium selenium) {, E1 {: D2 L2 a3 }+ X4 q0 W
    this.outputDirectory = outputDirectory;
. e: N* r- M" q) Y2 T    this.selenium = selenium;
- P3 h, n9 _( _/ R! s' _. p  }; c/ d+ _% T# M& ]% o* s; l
  public void onTestFailure(ITestResult result) {
$ K- q6 s" _: ~- ^4 f* x7 H    Reporter.setCurrentTestResult(result);( X- Z6 a6 |% Q; e4 g$ j0 n
    try {
) G0 ?) Y5 @1 t1 [. z      outputDirectory.mkdirs();
) m8 B! p# d5 @2 M, K% e6 ~      File outFile = File.createTempFile("TEST-" + result.getName(), ".png", outputDirectory);
5 Q  _$ P& V6 ~& t& E      outFile.delete();
* d0 F2 A+ r3 @3 Z( x      selenium.captureScreenshot(outFile.getAbsolutePath());
- j, E) g* T6 A3 e      Reporter.log("<a href='" +
' m- a7 F! I6 Y, A3 K8 |          outFile.getName() +% ^* V! p# {# P! f% O0 v
          "'>screenshot</a>");% z6 C0 v' w4 a2 g5 W/ q, ]' E% {
    } catch (Exception e) {
" E2 b1 q- a! `# D5 p      e.printStackTrace();
7 `, y1 i. M- k& g+ Y2 x' j3 @      Reporter.log("Couldn't create screenshot");2 P7 `# [3 b; Q, s, v. Y
      Reporter.log(e.getMessage());9 ~' E4 Q& w$ C3 E3 X) }9 }
    }  e8 D8 y" F  W) I
    Reporter.setCurrentTestResult(null);6 v# p4 U8 |6 }+ v5 t. @
  }
+ Z% \( F7 R7 |! J* `}
5 D1 g+ D; H: ]1 g" ^' E' t是不是适当增加空白行就提高了代码的可读性呢,这里说的是适当增加空白行,并不代表随意增加。事实上,如果增加一些无意义的空白行反而会使代码的可读性变差。
) a. n8 L4 f2 |8 @0 K, _4 b  q" s  e# d2 v
我们习惯于使有关联的代码彼此靠近,无明显关联的代码相互分隔。因此我们不但需要使用空白行间隔代码,还要调整代码位置,把有关联的代码放在一起,通常我们把被调用的函数放在调用函数的下面。这样别人在读我们的代码的时候再也不用经历来回“跳跃”的痛苦了。4 S) |8 ~: D" l8 L( m" {" B" ?
, b) _6 z2 F; K2 Q: v
最后,我们通常把实体变量定义在类的顶部,这个只是我们Java程序员的习惯操作,如果突然在类的中间位置出现一个变量声明会让人觉得很奇怪。如果你想说,定义在中间是不想让定义位置和调用位置离太远,那么只能说明你的类定义出现了问题。建议你看一下旧文代码洁癖系列(三):整洁的类和函数。, s8 G4 ]& O' d5 D7 r

9 b; a! N% O8 A+ E, I2 m, ~3 m8 @横向格式) N! z3 |9 O% O. t8 ^

# x0 W& p9 a( q/ }介绍完垂直格式,紧接着自然要来介绍一下它的兄弟,横向格式。或许你会问为什么不叫水平格式,我的回答是:也可以叫水平格式,只要你喜欢。横向格式也是需要间隔和靠近的,这里的间隔主要是为了起到强调的效果。举个例子。
" h7 k* ?5 v" S
7 q& n. m  G& f1 s. Z1 zint lineSize = line.length();" x, z& @  a' w/ u
1
6 y% a' C$ V! i这里等号两边的空格分别是为了强调左右两边的元素。横向格式另一个比较重要的元素就是缩进,Java程序对缩进没有强制性要求,而Python程序对缩进的要求非常严格,稍有不慎,执行的结果就会不同。但是Java程序员也要注意缩进,因为我们的代码是层级关系,而缩进可以帮我们快速理清层级关系。- {2 u0 k! w2 e9 x% S
1 M/ [! H3 k* {6 n
最后,横向代码格式对每行代码长度是有要求的,如果代码过长,那么在阅读的时候就需要左右滑动,而这个操作其实是不受人喜欢的。虽然现在代码编辑器可显示的长度变大了,但我们还是习惯每行代码最多100个字符。% W+ Z4 S" h( e* X$ G( h
; Y- b9 q& x# J; A+ G
团队的规则
1 y" l, J/ H% t: Y- c
: t5 Z" |; @/ S, x, c. C每一个优秀的团队都已一套属于自己的代码格式要求,有些是特定的,有些是使用公共的。我们team所用的代码规范就是Google的代码规范,阿里的代码规范也是比较被大家认可的。这里给大家一个小福利,在我的公众号后台回复【代码规范】,就可以获得一份阿里的Java开发手册。* k" m. S# J3 q0 }% @7 Y
---------------------
1 a) }; V! {6 x8 q& k! U
# I2 W- H8 A+ J4 @, |$ b' ]! D/ Q% X* N& `' t# ^
3 j5 s. Q- O1 D& A1 Q

# t: W+ r0 j7 N' i+ g9 j, Q9 u' G8 G& Q1 }0 o
5 X4 @# S/ e/ B, ^* f

+ W# m( C6 m) z; Z5 I5 ]% S  G  d7 P. K" N4 R1 A3 g( ~: Y# V

2 |& m. ?0 [3 J9 U5 b. {! e; ~( F" H7 e

- p) }: w( |  t) [( Y0 J2 v; F/ H; K* l. g5 t% f" m

7 G$ i6 r0 J$ V8 o
% u/ B6 x- j7 j! ]0 B; U
/ X% M6 h+ ]/ y1 B1 a. Z' Z$ Q
$ x/ F# c8 r1 k" D& g
! R4 p  i8 }/ y  h: j' k) w& I. F
6 \; c  p& y% w6 o! r( I
6 F% l# v+ J/ c. z' T" u  A7 s) o$ S& `
$ F+ s/ T7 |4 S0 w) j3 T, R4 m$ Q  t
$ z" X  n3 |0 A3 s+ @! s
* l* ]: D/ {& T& S" a( j! e

( A/ d+ e/ s( x' L  S, ^
" p0 i, U- y: W( J; D5 ^4 ^& U! d! L+ \- Y- w- _
% n& u9 r* h" ~5 ~" t3 a

16种常用的数据分析方法汇总.docx

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






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