Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
1
わかるコードを書くために
For writing clean code
2
$ whoami
青木太郎
Eyes, JAPAN / ヅ大2年目
Groove Coaster
STEINS;GATE
色々...
3
わからないコード
s = a(p.h);
function a(b) {
return b * 900 + 4000;
}
4
5
目次
1. 目的
2. 表面の改善
3. 内面の改善
4. まとめ
6
1. 目的
7
主な対象者
一人でコードを数千行書いたことのない人
8
プログラミング
コードを読む
コードを書く
9
コードを読む時間のほうが書く時間より圧倒的に多い
プロジェクトのコードの処理の把握
バグの発生場所の検証
ライブラリなどのドキュメント
10
コードが汚いと…
誰も読めなくなる
保守性が下がる
バグが混入しやすくなる
楽しくない
11
きれいなコードを書けると…
自然と誰が見ても分かりやすいコードになる
嬉しくなってテンションが上がり、ゾーンに突入できる
12
一人で作業するならきれいなコードを書く必要はない?
13
一人で作業するならきれいなコードを書く必要はない?
数週間後の自分は他人
14
数週間後の自分は他人
15
2. 表面の改善
16
コーディング規約
殆どの言語でコーディング規約が存在する
17
18
代表的な表記法
名前 例
アッパーキャメルケース(UCC) ExampleString
ローワーキャメルケース(LCC) exampleString
スネークケース example_string
ハンガリアン記法 mExampleS...
19
わりと一般的な命名規則の例
名前 表記 例
クラス UCC class ImageUtil {...}
変数、メンバ変数 LCC or スネークケース let imageTitle;
関数、メソッド LCC function fetchI...
20
なぜコーディング規約を守る必要があるか?
21
細かな違い
if (example.isTrue) {
...
} else {
...
}
if(example.isTrue)
{
...
}
else
{
...
}
if (example.isTrue) {
...
}
else...
22
タブvs スペース
23
Emacs vs Vim
24
なぜコーディング規約を守る必要があるか?
複数人で開発する際に起きる好みの違いを吸収するため
↓
コードの私物化を防ぐ
25
EditorConfig
プロジェクトでのエディタの設定を共有できる
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
indent_style = s...
let s = a(p.h);
function a(b) {
return b * 900 + 4000;
}
let salary = getSalary(person.hours);
function getSalary(hours) {...
26
27
明確な名前をつける
28
関数やメソッドの命名パターンの一例
パターン プレフィックス 例
getter / setter get / set getText(), setText()
boolean is, can, has isEmpty()
外部から取得する...
29
明確な名前をつける
let salary = getSalary(person.hours);
function getSalary(hours) {
return hours * 900 + 4000;
}
let salary = c...
30
ロジックを確認しなくても把握しやすい
let salary = computeSalary(person.workedHours);
31
スコープと命名
スコープと変数の持つ意味を考える
void swap(int *a, int *b) {
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
32
ゆとりを持つ
33
ゆとりを持つ
<?php
/*認証 必要 読 込 */
require_once( 'twitter/' .'config.php');
require_once( 'twitter/' .'twitteroauth.php');
ses...
34
適切な改行とスペース
<?php
// 認証 必要 読 込
require_once('twitter/' . 'config.php');
require_once('twitter/' . 'twitteroauth.php');
s...
35
マジックナンバー
36
マジックナンバーは敵
let salary = computeSalary(person.workedHours);
function computeSalary(workedHours) {
return workedHours * 9...
37
なぜマジックナンバーがダメなのか?
一目で何を表しているのか分からない
変更があった際、すべての箇所を変更する必要がある
バグの原因に
↓
定数に置き換え、一つにまとめる
38
マジックナンバーの置き換え
let salary = computeSalary(person.workedHours);
function computeSalary(workedHours) {
return workedHours ...
39
適切なコメントを書く
40
不要なコメント
// 引数 定数倍 返
function multiple(number) {
const MULTIPLIER = 5;
return number * MULTIPLIER;
}
41
不要なコメント(補助的なコメント)
// 楽曲 名前 取得
function getMusicList() {
...
return musicList;
}
function fetchAllMusicName() {
...
retu...
42
適切なコメント(新たな情報を伝えている)
// 10秒未満 制限 掛
const SLEEP_TIME = 10
43
3. 内面の改善
44
ユニットテストとリファクタリング
45
ユニットテスト(単体テスト)
1つのモジュールのロジックに対して、
入力を与え、期待した結果が得られるかをテストするための手法
46
リファクタリング
外部から見た時の振る舞いを保ちつつ、理解や修正が簡単
になるように、ソフトウェアの内部構造を変化させること
(新装版リファクタリングより)
↓
ユニットテストを活用することで振る舞いを保証する事ができる
47
ガード節の利用
{
"status": 0,
"player_data": {
"player_name": "Name",
"total_score": "394262836",
"rank": 3083,
"average_score": "851539"...
48
49
ガード節の利用
異常な場合は即return する
if-else はどちらも正常な処理の場合に使う
// GET 取得 JSON 列挙
request.get(URL, function(error, response, body) {
if (error) {
return;
}
let json = JSON.parse(body);
i...
50
51
分かりづらい条件分岐の改善
52
例えば…
if (serverA.status !== 0 && serverB.status !== 0) {
// A B 異常 時 処理
} else if (serverA.status !== 0 && serverB.stat...
if (serverA.status !== 0) {
if (serverB.status !== 0) {
// A B 異常 時 処理
} else {
// A 異常 時 処理
}
} else {
if (serverB.status...
53
54
55
分かりづらい条件分岐
if (serverA.status !== 0 && serverB.status !== 0) {
// A B 異常
} else if (serverA.status !== 0) {
// A 異常
...
56
分かりづらい条件分岐の特徴
&& や|| を多用している
否定の条件が多い
マジックナンバーとの比較
↓
メソッドや関数に抽出する
57
分かりづらい条件分岐をメソッドで置き換える
//
public boolean isStatusError() {
if (status !== 0) {
return false;
}
return true;
}
if (server...
58
神のクラス(God class)
59
神のクラス(God class)
すべてを創造することのできるクラス
神のメソッド、神の関数、etc.
60
神の* を錬成しやすいポイント
一つのメソッド当たりの行数が多い
不適当なクラスにメンバ変数やメソッドを割り当てている
ユニットテストを書きにくい
単一責任原則を守っていない
一時変数が多い
etc.
61
単一責任原則
変更する理由が同じものは集める。変更する理由が違うも
のは分ける。(プログラマが知るべき97のことより引用)
62
神の* を錬成しやすいポイント
一つのメソッド当たりの行数が多い
不適当なクラスにメンバ変数やメソッドを割り当てている
ユニットテストを書きにくい
単一責任原則を守っていない
一時変数が多い
etc.
63
一時変数が多い場合
ローカル変数である
↓
そのメソッドでしか利用できない
↓
神のメソッド化
↓
64
一時変数をメソッドや関数で置き換える
let exists = false;
for (let i = 0; i < BLACK_LIST.length; i++) {
if (person.name === BLACK_LIST[i])...
65
メソッドに抽出する
function isExists(person.name) {
let exists = false;
for (let i = 0; i < BLACK_LIST.length; i++) {
if (person...
66
呼び出し側
if (isMarkedPerson(person.name)) {
// BAN
} else {
// 一般人 時 処理
}
67
オブジェクトを利用したリファクタリング
( JavaScript → Java )
68
オブジェクト指向プログラミング
(OOP: Object-Oriented Programming)
69
手続き型プログラミング
関数を元に一連のステップを実行していく
70
オブジェクト指向プログラミング
オブジェクト間でメッセージをやりとりしながらプログラムを構成する手法
オブジェクトは状態(メンバ変数)と振る舞い(メソッド)を持つ
71
車
名前 例
クラス 設計図
メソッド 機能
メンバ 状態(速度)
インスタンス 実際の車
72
OOP の3大要素
継承
カプセル化
ポリモーフィズム
73
継承
抽象的なクラスの要素をより具体的なクラスへそのまま引き継ぐ
例: 車→ 軽自動車、パトカー、救急車、トラック、etc.
74
カプセル化
不必要なメンバ変数やメソッドを隠蔽する
例: エンジンの動作の隠蔽
75
ポリモーフィズム
子孫関係にあるクラスはその親クラスを元にして抽象的に扱うことができる
例: すべての車はアクセルとブレーキがある
76
メンバ変数を一つにまとめる
String firstName, lastName, email, nickname;
int gender;
firstName = json.getString("firstName");
lastNam...
77
データクラス
class Profile {
private String firstName, lastName, email, nickname;
private Gender gender;
Profile(String first...
78
呼び出し側
Profile profile = new Profile(
json.getString("firstName"),
json.getString("lastName"),
json.getString("email"),
...
79
null オブジェクトの利用
80
null オブジェクトの利用
public class PartTimeStudent {
private String firstName, ..., email, hireDate;
// 下 ParensHome 利用
// 住民票...
81
if やswitch を多用せざるを得ない
if (exampleStudent.getParentsHome() === null) {
System.out.println("実家 電話番号: -");
}
String phoneN...
82
1. nullオブジェクトの追加
class NullParentsHome extends ParentsHome {
...
}
83
2. isNull() の追加
class ParentsHome {
private String phoneNumber;
private String address;
private String representative;
...
84
3. PartTimeStudent クラスの呼び出し元の修正
public class PartTimeStudent {
...
ParentsHome getParentsHome() {
return parentsHome;
}...
85
4. null 判定箇所をisNull() で置き換え、テストする
if (exampleStudent.getParentsHome() === null) {
return;
}
if (exampleStudent.getParen...
86
5. ParentsHome がnull の時のgetter の値を設ける
class NullParentsHome extends ParentsHome {
@Override
public boolean isNull() {
r...
87
6. if を削除できる
if (exampleStudent.getParentsHome() === null) {
return;
}
String phoneNumber = exampleStudent.getParentsHo...
88
4. まとめ
89
意識をしてコードを書く
常にシンプルを心がける
コードを知らない人への配慮
より良い書き方
違和感を感じ取る
90
より良いコードを書くための近道
91
スパゲッティを作ってみる
92
スパゲッティを作ってみる
どこが原因なのか?
どうすれば改善できるのか?
一つずつ対処していく
↓
楽しくなってくる!
93
楽しくコードを書こう!!
94
スライド(Reveal.js版)
http://lycoris0731.github.io/slides
95
参考書籍
リーダブルコード―より良いコードを書くためのシンプルで実践的なテクニック
JUnit実践入門~体系的に学ぶユニットテストの技法
新装版リファクタリング―既存のコードを安全に改善する―
96
参考サイト
プログラマが知るべき97のこと
97
出典(スライド内で使用した画像)
ヴォイニッチ手稿:
青峰: アニメ黒子のバスケ2期OP
TABS vs SPACES:
Emacs vs Vim:
どうしてこうなった: 2ちゃんねるAA
FXで有り金全部溶かした人の顔: あいまいみー第...
わかるコードを書くために For writing clean code
わかるコードを書くために For writing clean code
Upcoming SlideShare
Loading in …5
×

わかるコードを書くために For writing clean code

926 views

Published on

Eyes, JAPAN社内勉強会での弊社青木による発表です

Published in: Engineering
  • I can advise you this service - ⇒ www.HelpWriting.net ⇐ Bought essay here. No problem.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • There is a useful site for you that will help you to write a perfect and valuable essay and so on. Check out, please ⇒ www.HelpWriting.net ⇐
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

わかるコードを書くために For writing clean code

  1. 1. 1 わかるコードを書くために For writing clean code
  2. 2. 2 $ whoami 青木太郎 Eyes, JAPAN / ヅ大2年目 Groove Coaster STEINS;GATE 色々...
  3. 3. 3 わからないコード s = a(p.h); function a(b) { return b * 900 + 4000; }
  4. 4. 4 5 目次 1. 目的 2. 表面の改善 3. 内面の改善 4. まとめ
  5. 5. 6 1. 目的
  6. 6. 7 主な対象者 一人でコードを数千行書いたことのない人
  7. 7. 8 プログラミング コードを読む コードを書く
  8. 8. 9 コードを読む時間のほうが書く時間より圧倒的に多い プロジェクトのコードの処理の把握 バグの発生場所の検証 ライブラリなどのドキュメント
  9. 9. 10 コードが汚いと… 誰も読めなくなる 保守性が下がる バグが混入しやすくなる 楽しくない
  10. 10. 11 きれいなコードを書けると… 自然と誰が見ても分かりやすいコードになる 嬉しくなってテンションが上がり、ゾーンに突入できる
  11. 11. 12 一人で作業するならきれいなコードを書く必要はない?
  12. 12. 13 一人で作業するならきれいなコードを書く必要はない? 数週間後の自分は他人
  13. 13. 14 数週間後の自分は他人
  14. 14. 15 2. 表面の改善
  15. 15. 16 コーディング規約 殆どの言語でコーディング規約が存在する
  16. 16. 17 18 代表的な表記法 名前 例 アッパーキャメルケース(UCC) ExampleString ローワーキャメルケース(LCC) exampleString スネークケース example_string ハンガリアン記法 mExampleString
  17. 17. 19 わりと一般的な命名規則の例 名前 表記 例 クラス UCC class ImageUtil {...} 変数、メンバ変数 LCC or スネークケース let imageTitle; 関数、メソッド LCC function fetchImageTitle() {...} 定数 大文字+ スネークケース const MAX_STRING;
  18. 18. 20 なぜコーディング規約を守る必要があるか?
  19. 19. 21 細かな違い if (example.isTrue) { ... } else { ... } if(example.isTrue) { ... } else { ... } if (example.isTrue) { ... } else { ... }
  20. 20. 22 タブvs スペース
  21. 21. 23 Emacs vs Vim
  22. 22. 24 なぜコーディング規約を守る必要があるか? 複数人で開発する際に起きる好みの違いを吸収するため ↓ コードの私物化を防ぐ
  23. 23. 25 EditorConfig プロジェクトでのエディタの設定を共有できる [*] charset = utf-8 end_of_line = lf trim_trailing_whitespace = true indent_style = space indent_size = 2 [*.js] indent_style = space indent_size = 2 [Makefile] indent_style = tab indent_size = 4
  24. 24. let s = a(p.h); function a(b) { return b * 900 + 4000; } let salary = getSalary(person.hours); function getSalary(hours) { return hours * 900 + 4000; }
  25. 25. 26 27 明確な名前をつける
  26. 26. 28 関数やメソッドの命名パターンの一例 パターン プレフィックス 例 getter / setter get / set getText(), setText() boolean is, can, has isEmpty() 外部から取得する fetch fetchImageTitle() イベント発生時 on onItemClick()
  27. 27. 29 明確な名前をつける let salary = getSalary(person.hours); function getSalary(hours) { return hours * 900 + 4000; } let salary = computeSalary(person.workedHours); function computeSalary(workedHours) { return workedHours * 900 + 4000; }
  28. 28. 30 ロジックを確認しなくても把握しやすい let salary = computeSalary(person.workedHours);
  29. 29. 31 スコープと命名 スコープと変数の持つ意味を考える void swap(int *a, int *b) { int tmp; tmp = *a; *a = *b; *b = tmp; }
  30. 30. 32 ゆとりを持つ
  31. 31. 33 ゆとりを持つ <?php /*認証 必要 読 込 */ require_once( 'twitter/' .'config.php'); require_once( 'twitter/' .'twitteroauth.php'); session_start(); // getToken.php oauth_token 一致 if ($_SESSION['oauth_token'] !== $_REQUEST['oauth_token']) { unset($_SESSION); echo '<a href="getToken.php">token不一致</a>'; exit; } // access token 取得 $tw = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']); $access_token = $tw->getAccessToken($_REQUEST['oauth_verifier']); // Twitter user_id + screen_name(表示名) $_SESSION['user_id'] = $access_token['user_id']; $_SESSION['screen_name'] = $access_token['screen_name']; include('db_connection.php'); $sql = 'SELECT * FROM user_data WHERE user_id = ' . $_SESSION['user_id' $query = mysql_query($sql, $link);
  32. 32. 34 適切な改行とスペース <?php // 認証 必要 読 込 require_once('twitter/' . 'config.php'); require_once('twitter/' . 'twitteroauth.php'); session_start(); // getToken.php oauth_token 一致 if ($_SESSION['oauth_token'] !== $_REQUEST['oauth_token']) { unset($_SESSION); echo '<a href="getToken.php">token不一致</a>'; exit; } // access token 取得 $tw = new TwitterOAuth( CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], $_SESSION['oauth_token_secret'] ); $access_token = $tw -> getAccessToken($_REQUEST['oauth_verifier']);
  33. 33. 35 マジックナンバー
  34. 34. 36 マジックナンバーは敵 let salary = computeSalary(person.workedHours); function computeSalary(workedHours) { return workedHours * 900 + 4000; }
  35. 35. 37 なぜマジックナンバーがダメなのか? 一目で何を表しているのか分からない 変更があった際、すべての箇所を変更する必要がある バグの原因に ↓ 定数に置き換え、一つにまとめる
  36. 36. 38 マジックナンバーの置き換え let salary = computeSalary(person.workedHours); function computeSalary(workedHours) { return workedHours * 900 + 4000; } let salary = computeSalary(person.workedHours); function computeSalary(workedHours) { const BASE_SALARY = 4000; const HOURLY_PAYMENT = 900; return workedHours * HOURLY_PAYMENT + BASE_SALARY; }
  37. 37. 39 適切なコメントを書く
  38. 38. 40 不要なコメント // 引数 定数倍 返 function multiple(number) { const MULTIPLIER = 5; return number * MULTIPLIER; }
  39. 39. 41 不要なコメント(補助的なコメント) // 楽曲 名前 取得 function getMusicList() { ... return musicList; } function fetchAllMusicName() { ... return musicNameList; }
  40. 40. 42 適切なコメント(新たな情報を伝えている) // 10秒未満 制限 掛 const SLEEP_TIME = 10
  41. 41. 43 3. 内面の改善
  42. 42. 44 ユニットテストとリファクタリング
  43. 43. 45 ユニットテスト(単体テスト) 1つのモジュールのロジックに対して、 入力を与え、期待した結果が得られるかをテストするための手法
  44. 44. 46 リファクタリング 外部から見た時の振る舞いを保ちつつ、理解や修正が簡単 になるように、ソフトウェアの内部構造を変化させること (新装版リファクタリングより) ↓ ユニットテストを活用することで振る舞いを保証する事ができる
  45. 45. 47 ガード節の利用
  46. 46. { "status": 0, "player_data": { "player_name": "Name", "total_score": "394262836", "rank": 3083, "average_score": "851539", } } // GET 取得 JSON 列挙 request.get(URL, function(error, response, body) { if (!error) { let json = JSON.parse(body); if (json.status === 0) { let playerData = json["player_data"]; for (let p in playerData) { if (playerData[p] !== null) { console.log(p + " is " + playerData[p]); } } } } });
  47. 47. 48 49 ガード節の利用 異常な場合は即return する if-else はどちらも正常な処理の場合に使う
  48. 48. // GET 取得 JSON 列挙 request.get(URL, function(error, response, body) { if (error) { return; } let json = JSON.parse(body); if (json.status !== 0) { return; } let playerData = json["player_data"]; for (let p in playerData) { if (playerData[p] === null) { continue; } console.log(p + " is " + playerData[p]); } });
  49. 49. 50 51 分かりづらい条件分岐の改善
  50. 50. 52 例えば… if (serverA.status !== 0 && serverB.status !== 0) { // A B 異常 時 処理 } else if (serverA.status !== 0 && serverB.status === 0) { // A 異常 時 処理 } else if (serverA.status === 0 && serverB.status !== 0) { // B 異常 時 処理 }
  51. 51. if (serverA.status !== 0) { if (serverB.status !== 0) { // A B 異常 時 処理 } else { // A 異常 時 処理 } } else { if (serverB.status !== 0) { // B 異常 時 処理 } }
  52. 52. 53
  53. 53. 54 55 分かりづらい条件分岐 if (serverA.status !== 0 && serverB.status !== 0) { // A B 異常 } else if (serverA.status !== 0) { // A 異常 } else if (serverB.status !== 0) { // B 異常 }
  54. 54. 56 分かりづらい条件分岐の特徴 && や|| を多用している 否定の条件が多い マジックナンバーとの比較 ↓ メソッドや関数に抽出する
  55. 55. 57 分かりづらい条件分岐をメソッドで置き換える // public boolean isStatusError() { if (status !== 0) { return false; } return true; } if (serverA.isStatusError() && serverB.isStatusError()) { // A B 異常 } else if (serverA.isStatusError()) { // A 異常 } else if (serverB.isStatusError()) { // B 異常 }
  56. 56. 58 神のクラス(God class)
  57. 57. 59 神のクラス(God class) すべてを創造することのできるクラス 神のメソッド、神の関数、etc.
  58. 58. 60 神の* を錬成しやすいポイント 一つのメソッド当たりの行数が多い 不適当なクラスにメンバ変数やメソッドを割り当てている ユニットテストを書きにくい 単一責任原則を守っていない 一時変数が多い etc.
  59. 59. 61 単一責任原則 変更する理由が同じものは集める。変更する理由が違うも のは分ける。(プログラマが知るべき97のことより引用)
  60. 60. 62 神の* を錬成しやすいポイント 一つのメソッド当たりの行数が多い 不適当なクラスにメンバ変数やメソッドを割り当てている ユニットテストを書きにくい 単一責任原則を守っていない 一時変数が多い etc.
  61. 61. 63 一時変数が多い場合 ローカル変数である ↓ そのメソッドでしか利用できない ↓ 神のメソッド化 ↓
  62. 62. 64 一時変数をメソッドや関数で置き換える let exists = false; for (let i = 0; i < BLACK_LIST.length; i++) { if (person.name === BLACK_LIST[i]) { exists = true; break; } } if (exists) { // BAN } else { // 一般人 時 処理 }
  63. 63. 65 メソッドに抽出する function isExists(person.name) { let exists = false; for (let i = 0; i < BLACK_LIST.length; i++) { if (person.name === BLACK_LIST[i]) { exists = true; break; } } return exists; } ↓ function isMarkedPerson(name) { for (let i = 0; i < BLACK_LIST.length; i++) { if (name === BLACK_LIST[i]) { return true; } } return false; }
  64. 64. 66 呼び出し側 if (isMarkedPerson(person.name)) { // BAN } else { // 一般人 時 処理 }
  65. 65. 67 オブジェクトを利用したリファクタリング ( JavaScript → Java )
  66. 66. 68 オブジェクト指向プログラミング (OOP: Object-Oriented Programming)
  67. 67. 69 手続き型プログラミング 関数を元に一連のステップを実行していく
  68. 68. 70 オブジェクト指向プログラミング オブジェクト間でメッセージをやりとりしながらプログラムを構成する手法 オブジェクトは状態(メンバ変数)と振る舞い(メソッド)を持つ
  69. 69. 71 車 名前 例 クラス 設計図 メソッド 機能 メンバ 状態(速度) インスタンス 実際の車
  70. 70. 72 OOP の3大要素 継承 カプセル化 ポリモーフィズム
  71. 71. 73 継承 抽象的なクラスの要素をより具体的なクラスへそのまま引き継ぐ 例: 車→ 軽自動車、パトカー、救急車、トラック、etc.
  72. 72. 74 カプセル化 不必要なメンバ変数やメソッドを隠蔽する 例: エンジンの動作の隠蔽
  73. 73. 75 ポリモーフィズム 子孫関係にあるクラスはその親クラスを元にして抽象的に扱うことができる 例: すべての車はアクセルとブレーキがある
  74. 74. 76 メンバ変数を一つにまとめる String firstName, lastName, email, nickname; int gender; firstName = json.getString("firstName"); lastName = json.getString("lastName"); email = json.getString("email"); nickname = json.getString("nickname"); gender = Integer.parseInt(json.getString("gender"));
  75. 75. 77 データクラス class Profile { private String firstName, lastName, email, nickname; private Gender gender; Profile(String firstName, String lastName, String email, String nicknam this.firstName = firstName; this.lastName = lastName; this.email = email; this.nickname = nickname; this.gender = gender; } // getter & setter }
  76. 76. 78 呼び出し側 Profile profile = new Profile( json.getString("firstName"), json.getString("lastName"), json.getString("email"), json.getString("nickname"), Integer.parseInt(json.getString("gender")) ); profile.getFirstName();
  77. 77. 79 null オブジェクトの利用
  78. 78. 80 null オブジェクトの利用 public class PartTimeStudent { private String firstName, ..., email, hireDate; // 下 ParensHome 利用 // 住民票 実家 場合 private ParentsHome parentsHome; // getter & setter } class ParentsHome { private String phoneNumber; private String address; private String representative; public String getPhoneNumber() { return phoneNumber; } // getter & setter }
  79. 79. 81 if やswitch を多用せざるを得ない if (exampleStudent.getParentsHome() === null) { System.out.println("実家 電話番号: -"); } String phoneNumber = exampleStudent.getParentsHome().getPhoneNumber(); System.out.println("実家 電話番号: " + phoneNumber);
  80. 80. 82 1. nullオブジェクトの追加 class NullParentsHome extends ParentsHome { ... }
  81. 81. 83 2. isNull() の追加 class ParentsHome { private String phoneNumber; private String address; private String representative; public boolean isNull() { return false; } public String getPhoneNumber() { return this.phoneNumber; } ... } class NullParentsHome extends ParentsHome { @Override public boolean isNull() { return true; } ... }
  82. 82. 84 3. PartTimeStudent クラスの呼び出し元の修正 public class PartTimeStudent { ... ParentsHome getParentsHome() { return parentsHome; } ... } ↓ public class PartTimeStudent { ... ParentsHome getParentsHome() { if (parentsHome === null) { return new NullParentsHome(); } return parentsHome; } ... }
  83. 83. 85 4. null 判定箇所をisNull() で置き換え、テストする if (exampleStudent.getParentsHome() === null) { return; } if (exampleStudent.getParentsHome().isNull()) { return; }
  84. 84. 86 5. ParentsHome がnull の時のgetter の値を設ける class NullParentsHome extends ParentsHome { @Override public boolean isNull() { return true; } @Override public String getPhoneNumber() { return "-"; } ... }
  85. 85. 87 6. if を削除できる if (exampleStudent.getParentsHome() === null) { return; } String phoneNumber = exampleStudent.getParentsHome().getPhoneNumber(); System.out.println("実家 電話番号: " + phoneNumber); ↓ String phoneNumber = exampleStudent.getParentsHome().getPhoneNumber(); System.out.println("実家 電話番号: " + phoneNumber); 出力 実家 電話番号: 0000-11-2222 実家 電話番号: -
  86. 86. 88 4. まとめ
  87. 87. 89 意識をしてコードを書く 常にシンプルを心がける コードを知らない人への配慮 より良い書き方 違和感を感じ取る
  88. 88. 90 より良いコードを書くための近道
  89. 89. 91 スパゲッティを作ってみる
  90. 90. 92 スパゲッティを作ってみる どこが原因なのか? どうすれば改善できるのか? 一つずつ対処していく ↓ 楽しくなってくる!
  91. 91. 93 楽しくコードを書こう!!
  92. 92. 94 スライド(Reveal.js版) http://lycoris0731.github.io/slides
  93. 93. 95 参考書籍 リーダブルコード―より良いコードを書くためのシンプルで実践的なテクニック JUnit実践入門~体系的に学ぶユニットテストの技法 新装版リファクタリング―既存のコードを安全に改善する―
  94. 94. 96 参考サイト プログラマが知るべき97のこと
  95. 95. 97 出典(スライド内で使用した画像) ヴォイニッチ手稿: 青峰: アニメ黒子のバスケ2期OP TABS vs SPACES: Emacs vs Vim: どうしてこうなった: 2ちゃんねるAA FXで有り金全部溶かした人の顔: あいまいみー第9話 やらなければ、一生わからん!!: 燃えよペン Voynich Manuscript Truly Code 4.bp.blogspot.com

×