-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
executable file
·1659 lines (1088 loc) · 31.1 KB
/
index.html
File metadata and controls
executable file
·1659 lines (1088 loc) · 31.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>30分で『リーダブルコード』を読んだ気になれる資料</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/night.css">
<!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="lib/css/monokai.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match(/print-pdf/gi) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName('head')[0].appendChild(link);
</script>
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h3>
30分で『リーダブルコード』を<br />
読んだ気になれる資料
</h3>
</section>
<section data-markdown data-separator="^\n---$" data-separator-vertical="^\n>>>$">
<script type="text/template">
### まず『リーダブルコード』とは🤔
>>>
これ
https://amzn.to/2EWVSfE

>>>
読んだことある?
>>>
* 読む時間がねぇ
* めっちゃいろんな人から推される
* なんか使えることが書いてあるらしい
>>>
じゃあ、折角だし?
この資料で読んだ気持ちになりましょう
---
## 0章. まえがき
>>>
### 『リーダブルコード』の目的
* 読みやすいコードを書けるマンにする

>>>
### 『リーダブルコード』の読み方
* 気軽に読んでね
* できれば1~2週間ぐらいで読んでね
* いい感じに区切られてるからいつでもどこからでも読めるよ
>>>
### 本編
---
## 1章. 理解しやすいコード
>>>
コードは理解しやすくなければいけません
>>>
そも「理解しやすいコード」とは🤔
>>>
読みやすいのはどっち
```
return a ? a.split(':').length : b ? b.split(':').length : 0
```
```
if (a) {
return a.split(':').length
} else if (b) {
return b.split(':').length
}
return 0
```
>>>
一行にまとめるとすっきりするから読みやすい
明示的にifで分けて書いたほうが分かりやすい
基準が人それぞれ
>>>
でも、重要なことはただ1つ
>>>
### 他人が最短時間で理解できること
これが大事
---
## 2章. 名前に情報を詰込む
>>>
名前をつけるときには、
変数/関数/クラス関係なく
同じ原則で当てはめることができる
>>>
名前は短いコメントと考えれば良い
短くても良い名前をつければ無問題
>>>
### 明確な単語を選ぶ
```
// 何のサイズ?
public Integer size;
// PDFを取得して何する?
public Object getPdf() {};
```
↓
```
// 高さ
public Integer height;
// PDFをダウンロード
public Object downloadPdf() {};
```
モノや動作をはっきりさせよう
>>>
### 抽象的な名前よりも具体的な名前を使う
```
let record; // 何のレコード?
let count; // 何のカウント?
```
↓
```
let employeeRecord; // 従業員情報
let allEmployeeCount; // 全従業員数
```
>>>
### 名前に情報を追加する
```
// 単位が分からない…
private Integer getFileSize() {}
```
↓
```
// ファイルサイズ(MB)
private Integer getFileSizeMb {}
```
>>>
### 2章のまとめ
* 名前は短いコメントと考えよう
* モノや動作を名前に含めよう
* より具体的な名前を使おう
* 単位などの情報を名前に含めよう
---
## 3章. 誤解されない名前
>>>
```
// textを先頭から切り出す
truncate(text: string, length: number): string => {
...
}
```
lengthがバイト数なのか文字数なのか
はたまた単語数なのか分からない
↓
```
// textを先頭から切り出す
truncate(text: string, charLength: number): string => {
...
}
```
charLengthにすることで文字数であることを明示
>>>
よくあるやつ
```
public static Integer DOWNLOAD_REPORT_LIMIT = 100
```
LIMITってあるけど
これは100以下?それとも未満?
>>>
限界値を設定するときは min/max を使う
```
public static Integer DOWNLOAD_REPORT_MAX = 100
```
>>>
他にも…
* 範囲を指定する時 → first/last
* 包含や排他的範囲を指定する時 → begin/end
適切な単語を調べてみましょう
>>>
### 3章のまとめ
* 誤解されないよう明示的な名前にしよう
* 限界値や範囲などの変数には適切な単語を使おう
---
## 4章. 美しさ

>>>
### 見た目がキレイなコードを書こう
* 読み手がなれているパターンと一貫性のあるレイアウトを使う
* 似ているコードは似ているように見せる
* 関連するコードをまとめてブロックにする
これを心掛けるだけで結構キレイに見える
>>>
### 見たら分かる汚いやつ
```
let result1 = validation(text1);
let result2 = validation(
text2
);
let result3 =
validation(text3);
validation(text: string): boolean => {
if (null == inputText)
{
return false;
}
// 入力された文字列の文字数を検証
if (inputText.length < 8) /* 8文字に満たない場合はfalse
*/ { return false }
return true;
}
```
>>>
### 見やすい状態にしましょう
```
let result1 = validation(text1);
let result2 = validation(text2);
let result3 = validation(text3);
validation(text: string): boolean => {
if (null == inputText) {
return false
}
// 入力された文字列の文字数を検証
if (inputText.length < 8) {
// 8文字に満たない場合はfalse
return false
}
return true
}
```
>>>
### 項目の並びを合わせよう
画面から取得してきた値は項目の並びを合わせよう
```
name = request.POST.get('name');
nameKana = request.POST.get('nameKana');
address = request.POST.get('address');
tel = request.POST.get('tel');
email = request.POST.get('email');
```
合わせておくと迷子になりづらくなるぞ
>>>
### 処理ごとにまとめよう
```
List<Car> carlist = getCarList();
Car latestCarData = null;
if (carList.length() > 0) {
latestCarData = carList.get(0)
}
ScreenDto screen = new ScreenDto();
screen.setCarList(carlist);
screen.setLatestCarData(latestCarData)
return screen;
```
やってることは分かる。分かるけど見づらい。
>>>
### 処理ごとにまとめよう
```
List<Car> carlist = getCarList();
Car latestCarData = null;
if (carList.length() > 0) {
latestCarData = carList.get(0)
}
ScreenDto screen = new ScreenDto();
screen.setCarList(carlist);
screen.setLatestCarData(latestCarData)
return screen;
```
改行させるだけでも全然違う
>>>
### 処理ごとにまとめよう
```
// リストを取得
List<Car> carlist = getCarList();
// 1件以上ある場合は最新情報として先頭の情報を取得
Car latestCarData = null;
if (carList.length() > 0) {
latestCarData = carList.get(0)
}
// 画面へ表示するためにDTOへ設定
ScreenDto screen = new ScreenDto();
screen.setCarList(carlist);
screen.setLatestCarData(latestCarData)
return screen;
```
コメントを書くとなお良し
>>>
### 4章のまとめ
* 一貫性のあるレイアウトにしよう
* 画面などと関連する場合は順序を合わせよう
* 関連する箇所はまとめて改行で区切ろう
---
## 5章. コメントすべきことを知る
>>>
コメントの目的は
書き手の意図を読み手に知らせること
>>>
### 意味の無いコメントはやめよう
```
User user = null;
// ユーザーIDを取得
String userId = dto.getUserId();
// 有効なユーザーであるか確認
if (isValid(userId)) {
// ユーザー情報を取得する
user = getUser(userId);
}
// ユーザー情報を返却する
return user;
```
見れば分かるやつ
逆にノイズ
>>>
### でも、全く無いと 読む側も大変だから…
要約したコメントをつけましょう
```
// 有効なユーザー情報を返却する
String userId = dto.getUserId();
if (isValid(userId)) {
return getUser(userId);
}
return null;
```
処理を箇条書きで書くレベルでOK
>>>
### 処理/変数にまつわる背景は書こう
```
// 検索結果の取得件数上限
// 1万件を上限として設定すると著しくパフォーマンスが低下し、
// システムに影響がでるため5000件を上限に設定している
public static int SEARCH_RESULT_COUNT_MAX = 5000;
```
書いておけば新しく入ってきた人が
安易に変更しない…はず…きっと…
>>>
### 欠陥を見つけたらコメントしよう
```
// TODO:(uyawer) タイムゾーンのリストは外部のライブラリから取得する
List<String> timezoneList = Lists.arrayList("Etc/UTC", "Asia/Tokyo")
```
自分のメモ書き程度でも良し
(汚くならない程度に)
欠陥を恥ずがしがってはいけないぞ!
>>>
### TODO以外にも…
* TODO : 後で手をつける
* FIXME: 既知の不具合がある箇所
* HACK : あまりきれいじゃない解決策
* XXX : 重大な不具合がある箇所
もっとも、XXXなんてあったら
「すぐ直して」とか言われそうだけど
>>>
あと、私は名前も書くようにしてます
誰がコメント書いたのか分かるように
```
// TODO:(uyawer) タイムゾーンのリストは外部のライブラリから取得する
List<String> timezoneList = Lists.arrayList("Etc/UTC", "Asia/Tokyo")
```
>>>
### 全体像のコメントを残そう
クラスとかファイルの先頭に
概要を入れましょう
```
/**
* タイムゾーン情報を扱うクラス
* 値は外部ライブラリから取得している
*/
public class Timezone {
private String timezone;
private Integer gmt;
}
```
仕様書が無くても、他の人に聞かなくても
このコメントがあるだけで大分違う
>>>
「ソースコードが仕様書です」と言うぐらいなら
これぐらいのコメント書いてね
>>>
### 5章のまとめ
* 書かなくていいこと
* コードからすぐに抽出できること
* 書くべきこと
* 定数の値にまつわる背景
* TODOなどを使った欠陥の指摘
* 処理やクラスの要約/概要
---
## 6章. コメントは正確で簡潔に
>>>
### あいまいな代名詞は避ける
```
// データをキャッシュに入れる。ただし、先にそのサイズをチェックする。
```
この場合の「その」は
データ?それともキャッシュ?
>>>
### あいまいな代名詞は避ける
「その」とか「この」とか使わない
```
// データをキャッシュに入れる。ただし、先にデータのサイズをチェックする。
```
>>>
### 歯切れの悪い文章を磨く
```
# A. これまでにクロールしたURLかどうかによって優先度を変える
# B. これまでにクロールしていないURLの優先度を上げる
```
Aは問題なさそうに見えるけど
Bの方が単純だし短いし直接的
Aにはない優先度についても言及してる
>>>
### 関数の動作を正確に記述する
ファイルの行数を数える関数があるとする
```
// 指定されたファイルに含まれる行数を返す
int CountLines(string fileName) {}
```
言いたいことは分かるが正確性に欠ける
>>>
### 関数の動作を正確に記述する
* 空ファイルは0行なのか1行なのか
* "hello\n" は1行なのか2行なのか
* "hello\n world" は1行なのか2行なのか
* "hello\n\r cruel\n world\r" は一体…
ソースコード読めば分かるとは思うけど…
>>>
```
// 指定されたファイルに含まれる改行文字('\n')を返す
int CountLines(string fileName) {}
```
上記のようなコメントにすれば
"\n" が含まれていない場合は0となるし
"\r" を無視することも分かる
>>>
### コードの意図を書く
```
// listの順序を逆順にする
```
↓
```
// listの順序を値段の降順にする
```
「値段の降順」という説明がある
"処理の詳細"ではなく"内容"を書こう
>>>
### 6章のまとめ
* 「それ」や「これ」などの代名詞を避ける
* 関数の動作はできるだけ正確に説明する
* コードの意図は「詳細」ではなく「内容」を書く
---
## 7章. 制御フローを読みやすくする
>>>
### 三項演算子
これはまだ読めるのであり
```
return (hour >= 12) ? "午後" : "午前";
```
>>>
では、これは……
```
return (e >= 0) ? m * e : m / e;
```
やってることは分かるけど……
パッと見分かりづらい……
>>>
無理に1行に収めずにif/elseを使おう
```
// ゼロ除算を避ける
if (e >= 0) {
return m * e;
} else {
return m / e;
}
```
三項演算子は簡潔となるときに使おう
>>>
### do-whileは避けましょう
「最低1回は実行する」として使われるが
下記の場合だとnodeがnullの可能性がある
```
// 名前が含まれているか確認
do {
if (node.name().equals(name)) {
return true;
}
node = node.next();
} while(node != null);
return false;
```
>>>
### do-whileは避けましょう
大抵の場合はwhileに書き直せるので
do-whileはなるべく避けましょう
```
// 名前が含まれているか確認
while (node != null) {
if (node.name().equals(name)) {
return true;
}
node = node.next();
}
return false;
```
>>>
### 関数から早く抜けましょう
関数で複数のreturn文を
使ってはいけないと思っている人がいる。
アホくさ。関数から早く返すのはいいことだ。
(原文ママ)
```
// 項目の入力確認
public boolean validation(ScreenDto screen) {
if (screen == null) {
return false;
} else if (isEmpty(screen.getName())) {
return false;
} else if (isEmpty(screen.getNameKana())) {
return false;
}
return true;
}
```
>>>
### ネストは浅くしましょう
```
if (company != null) {
List employeeList = company.getEmployeeList();
if (employeeList != null) {
if(employeeList.size() > 0) {
for (Employee employee : employeeList) {
if (employee == null) {
continue;
} else {
employeeIds.add(employee.getId());
}
}
}
}
}
```
ネストが深くなると
読み手が精神的に辛くなるのでやめましょう
>>>
かといって論理演算子で繋げまくるのも
良くないのでやめましょう
```
if (company != null && company.getEmployeeList() != null && company.getEmployeeList().size() > 0) {
for (Employee employee : company.getEmployeeList()) {
if (employee != null) {
employeeIds.add(employee.getId());
}
}
}
```
>>>
ネストは浅く…if文に詰め込みすぎず……
読み手に伝わるように心がけましょう
```
// company情報がない場合は中断
if (company == null) {
return;
}
// 従業員リストが空の場合は中断
List employeeList = company.getEmployeeList();
if (employeeList == null || employeeList.size() == 0) {
return;
}
// 従業員IDをリストに詰め込む
for (Employee employee : employeeList) {
Integer employeeId = getEmployeeId(employee);
employeeIds.add(employeeId);
}
```
>>>
### 7章のまとめ
* 三項演算子は簡潔となるときに使おう
* do-whileは避けてwhileを使おう
* ネストが深くならないようにしよう
* かといって論理演算子で繋げるのはダメ
* returnやcontinueで処理から早く抜けさせる
---
## 8章. 巨大な式を分割する
>>>
### ブレイクタイム
ダイオウイカって驚くほど知的な生き物らしい
でも、ダイオウイカの脳って
食道の周りを取り囲んでいるんだって
>>>
一度に大量の食料を食べると
脳にダメージを与えてしまうらしい
悲しい
>>>
人間も同じ…
情報の食べすぎは混乱を招きます
>>>
### 閑話休題
巨大な式は飲み込みやすい大きさに
分割しましょう
>>>
### 説明変数
式を簡単に分割するには
式を表す変数に置き換えてしまえば良い
```
if line.split(':')[0].strip() == "root":
...
```
↓
```
username = line.split(':')[0].strip()
if username == "root":
...
```
>>>
### 要約変数
式を変数に代入しておくと便利
```
if (request.user.id == document.ownerId) {
// ユーザーはこのドキュメントを編集できる
}
...
if (request.user.id != document.ownerId) {
// ユーザーにこのドキュメントの編集をさせない(読み取り専用)
}
```
↓
```
final boolean userOwnsDoc = (request.user.id == document.ownerId);
if (userOwnsDoc) {
// ユーザーはこのドキュメントを編集できる
}
...
if (!userOwnsDoc) {
// ユーザーにこのドキュメントの編集をさせない(読み取り専用)
}
```
>>>
### ド・モルガンの法則
電気回路か論理学を学んだことがあれば
一度は聞いたことがあるかも
>>>
### ド・モルガンの法則
```
!(a || b || c) ⇔ !a && !b && !c
!(a && b && c) ⇔ !a || !b || !c
```
覚えにくかったら
* notを分配してand/orを反転
* 逆の場合はnotをくくりだす
と覚える
>>>
### ド・モルガンの法則
複雑そうになっている条件文を書き直せる
```
// ファイルが存在している かつ 保護されていない の反対
if (!(fileExists && !isProtected)) Error("このファイルは読み込み専用です")
```
↓
```
// ファイルが存在していない または 保護されている
if (!fileExists || isProtected) Error("このファイルは読み込み専用です")
```
>>>
### 短絡評価の悪用
boolは短絡評価を行うものが多い
```
// aがtrueならbは評価されない
if (a || b) {
...
}
```
便利なんだけど
悪用すると複雑なロジックになってしまう
>>>
悪用した例
```
// キーに一致するバケツを取得し、nullでなかったら中身を確認する
assert((!(bucket = FindBucket(key))) || !bucket->IsOccupied());
```
1行書けてで頭良さそうだけど
読み手としては一旦立ち止まらなきゃいけない
>>>
```