【孤独な読書会 1-5, 1-6】 リファクタリング 5章 6章
第5章 リファクタリング・カタログに向けて
説明
6章から先のリファクタリング手法説明文の書き方の説明のみのであるため割愛。
第6章 メソッドの構成
本章からついに、リファクタリングの各手法について言及された。
以下、各手法の典型的な例を提示する。
リファクタリング手法 | 説明 |
---|---|
メソッドの抽出 | ひとまとめにできるコードの断片をメソッドにして、それに目的を表すような名前をつける。 |
メソッドのインライン化 | メソッドの本体が名前を付けて呼ぶまでもなく明らかである場合に、メソッド本体を呼び出し元にインライン化してメソッドを除去する。 |
一時変数のインライン化 | 簡単な式によって一度だけ代入される一時変数があり、それが他のリファクタリングの障害となっている。 |
問い合わせによる一時変数の置き換え | 式をメソッドに抽出する。一時変数へのすべての参照を新たなメソッドに置き換える。 |
説明用変数の導入 | その式の結果または部分的な結果をその目的を説明する名前を付けた一時変数に格納する。 |
一時変数の分離 | 何回も代入される一時変数があるが、ループ変数でも一時変数を集める変数でもない場合に、代入ごとに別の一時変数に分ける |
パラメータへの代入の除去 | パラメータへの代入が行われている場合は一時変数を使う |
アルゴリズムの取り換え | アルゴリズムをわかりやすいものに置き換えたい場合、メソッドの本体を新たなアルゴリズムに置き換える |
メソッドの抽出
ひとまとめにできるコードの断片をメソッドにして、それに目的を表すような名前をつける。
void printOwing(double amount) { print Banner(); System.out.println("name:" + _name); System.out.println("amount:" + amount); }
↓
void printOwing(double amount) { printBanner(); printDetails(amount); } void printDetails(double amount); System.out.println("name:" + _name); System.out.println("amount:" + amount); }
ローカル変数が使われている場合は、上記のように"パラメータで渡す", "抽出先のメソッドの一時変数とする"など工夫が必要である。
メソッドのインライン化
メソッドの本体が名前を付けて呼ぶまでもなく明らかである場合に、メソッド本体を呼び出し元にインライン化してメソッドを除去する。
int getRating() { return (moreThanFiveLateDeliveries()) ? 2 : 1; } boolean moreThanFiveLateDeliveries() { return (_numberOfLateDeliveries > 5) ? 2 : 1; }
↓
int getRating() { return (_numberOfLateDeliveries > 5) ? 2: 1; }
一時変数のインライン化
簡単な式によって一度だけ代入される一時変数があり、それが他のリファクタリングの障害となっている。
double basePrice = anOrder.basePrice(); return (basePrice > 1000);
↓
return (anOrder.basePrice() > 1000);
問い合わせによる一時変数の置き換え
式をメソッドに抽出する。一時変数へのすべての参照を新たなメソッドに置き換える。
double basePrice = _quantity * _itemPrice; if(basePrice > 1000) return basePrice * 0.95; else return basePrice * 0.98;
↓
if(basePrice > 1000) return basePrice() * 0.95; else return basePrice() * 0.98; ・・・ double basesPrice() { return _quantity * _itemPrice; }
説明用変数の導入
その式の結果または部分的な結果をその目的を説明する名前を付けた一時変数に格納する。
if((platform.toUpperCase().indexOf("MAC") > -1) && browser.toUpperCase().indexOf("IE") > -1) && wasInitialized() && resize > 0 ) { // 略 }
↓
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1; final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1; final boolean wasResized = resize > 0; if(isMacOs && isIEBrowser && wasInitialized() && wasResized ) { // 略 }
一時変数の分離
何回も代入される一時変数があるが、ループ変数でも一時変数を集める変数でもない場合に、代入ごとに別の一時変数に分ける
double temp = 2 * (_height * _width); System.out.plintln(temp); temp = _height * _width; System.out.plintln(temp);
↓
final double perimeter = 2 * (_height * _width); System.out.plintln(perimeter); final double area = _height * _width; System.out.plintln(area);
パラメータへの代入の除去
パラメータへの代入が行われている場合は一時変数を使う
int discount(int inputVal, int quantity, int yearToDate) { if(inputVal > 50) inputVal -= 2; }
↓
int discount(int inputVal, int quantity, int yearToDate) { int result = inputVal; if(inputVal > 50) result -= 2; }
メソッドオブジェクトによるメソッドの置き換え
長いメソッドで「メソッドの抽出」を適用できないようなローカル変数の使い方をしている。
class Order...{ double price() { double primaryBasePrice; double secondaryBasePrice; double tertiaryBasePrice; // 長い処理; ... } }
アルゴリズムの取り換え
アルゴリズムをわかりやすいものに置き換えたい場合、メソッドの本体を新たなアルゴリズムに置き換える
String foundPerson(String[] people) { for (int i = 0; i < people.length; i++){ if (people[i].equals("Don")){ return "Don"; } if (people[i].equals("John")){ return "John"; } if (people[i].equals("Kent")){ return "Kent"; } } return ""; }
↓
String foundPerson(String[] people) { List candidates = Arrays.asList(new String[] {"Don", "John", "Kent"}); for (int i = 0; i < people.length; i++){ if(condidates.contains(people[i])) return people[i]; } return ""; }
【孤独な読書会 1-4】 リファクタリング 4章
第4章 テストの構築
テストがなぜ必要かを書いている章。 同時にどのようにテストを追加すべきかについて言及している。 JUnit自体の話もあるため、個人的には少し蛇足な部分もあった。テストの意義などを理解しているのであれば、最悪読み飛ばしてもよさそう。
JUnitの使い方
- テストを頻繁に実行せよ。1日に最低一度はすべてのテストを実行せよ
- バグレポートを受け取ったらまずそのバグを明らかにするための単体テストを書け
テストの追加
実行されない安全なてすとよりも、実行される不完全なテストのほうがましである。
プログラマによっては公開メソッドすべてをテストせよという人もいるが、著者は例えばフィールドを読み書きするだけのアクセサはテストしないらしい。テストをたくさん書こうとして必要なテストを書き洩らす恐れがあると言っている。
カバレッジを問われないのであればそうしたいのだが・・・日本では難しいよな、と正直思ってしまったのですが、以下の分で少し腑に落ちました。
過剰なテストを書こうとすると、やる気が失せて、何も書けずに終わってしまう危険性がある
適切な時間で大部分のバグを補足する方が良い
確かにただただカバレッジを通すだけで本質的に必要がないコードや、それを書くために無駄に費やす労力がかったるいと思うことが多々あります。
カバレッジが求められるのは品質を担保するための単純な1指標だからであると思うのですが、それを奪われると何で品質を担保できているといえばいいのだろうか・・・
あるのかなぁ・・・
【孤独な読書会 1-3】 リファクタリング 3章
今回はリファクタリング第3章を読み進めていく。
3章のタイトルである「コードの不吉な臭い」の通り
内容としては、何やら怪しく「臭い」コードってこんなものといった導入部分である。
なかなか、リファクタリングテクニックには入らないものだ・・・
第3章 コードの不吉な臭い
本章で取り上げられている不吉な臭いは以下22個である。
特に前半は名が体を表しているというか、よく見聞きするものである。
- 重複したコード
- 長すぎるメソッド
- 巨大なクラス
- 長すぎるパラメータリスト
- 変更の偏り
- 変更の分散
- 特性の横恋慕
- データの群れ
- 基本データ型への執着
- スイッチ分
- パラレル継承
- 怠け者クラス
- 疑わしき一般化
- 一時的属性
- メッセージの連鎖
- 仲介人
- 不適切な関係
- クラスのインターフェース不一致
- 未熟なクラスライブラリ
- データクラス
- 相続拒否
- コメント
これらに関して、言葉でそれぞれ説明がされている。
正直コードにすごく慣れ親しんでいるわけではない私からすると、半分ぐらいしか理解できていない気がして仕方がない・・・
この問題は後で出てくる〇〇という手法を使えば解決できるぜ!という論法であるため、軽い気持ちで読んで、また戻ってくるのが良いぐらいの章なんだろうなぁ・・・
最後に
コメントを使うのが問題と書いているわけではなく。
コードの難解さを覆い隠すようにコメントを「臭いコードの消臭剤」として使うことが問題と書いてあった。
なるほどなぁ。
【孤独な読書会 1-2】 リファクタリング 2章
さて前回に引き続きリファクタリングを読んでいく。
第2章 リファクタリングの原則
そう第2章はリファクタリングの原則である。
リファクタリングはどういうものかといった定義が概念を伝えてくれる章であり
一般的な書籍でいうところの第1章にくる内容である。そう。眠たい内容でした・・・
とは言いながら、本ブログの目的は自己研鑽の割合が大きいため真面目に記載します。
定義
さてまずは用語の定義である。一応以下記載する
リファクタリング(名刺):
外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように
ソフトウェアの内部構造を変化させること
リファクタリング(動詞):
一連のリファクタリングを適用して外部から見たふるまいの変更なしに、ソフトウェアを再構築すること
いかに管理者を説得するか
そう誰もが悩むであろう、リファクタリング最大の敵「管理者」である。
リファクタリングは開発者であれば、その必要性を「リファクタリング」という言葉だけで理解してくれる人が多いとは思いますが、スケジュール優先の管理者にとっては「本当に必要なものかどうか」を理解してもらいにくいものです。
そんなとき、この本ではこうすると良いと書いてあります。
「だまってリファクタリング」
私は本書を2度見してしまいました。
え、いや。確かに有効かもしれませんが・・・
要は、リファクタリングしたほうが全体として早く終わるから黙ってやってても、WinWinだからやっちまおーぜ!ということらしいです。激しく同意します。
Martinさん!そこにしびれるあこがれるぅ!尊敬します!
リファクタリングの問題点
リファクタリングの問題として以下2つが向いていないと明言しております
- データベース
- インターフェースの変更
特にインターフェースですが、インターフェース帰るとそれを実装しているクラス全部に影響でるからなかなかできない。ということでした。
それに対応するのに、非推奨を表すdeprecatedを使うなどして、古いコードは既存は残しつつリファクタリングしていくしかないそうです。
私自身基盤を作っている人間なので、ここは初期設計でしっかりやらねばと思いました。
まとめ
さて、第2章を読みましたが
リファクタリング手法そのものを学べると思っていたのですが、1行もコードがなくお預けをくらい
ちょっと(かなり)眠たかったです。。。
コードプリーズ!
はやく、
【孤独な読書会 1-1】 リファクタリング 1章
前置き
孤独な読書会と題して、読んだ本のまとめ・感想を読んだ分だけ記載できたらと思っております。要はただの本の感想・まとめ記事です。
今回はIT業界では名著と言われているMartin Flowloer[著] のリファクタリングです。
https://www.amazon.co.jp/dp/B01IGW5MG0/
私は本書を半年ほど前に購入したものの、その重厚さも相まってモチベーションが上がらず積み上げておりました。ブログを書くということをモチベーションに読破しようというのが本目的になります。 名目上読書会なので、1章ずつ読んではまとめるというスタンスで実施していこうと考えております。 さて、前置きが長くなりましたが本題に入っていきたいと思います。
1章
全体の感想
1章は本書にも記載されていますが「リファクタリングってこんなもの」という雰囲気を知ることができる章になってます。 一般に本書のような書籍およびカンファレンスは以下のように続くことが多いです。
1章. 歴史や定義・あるいは意義
2章. 本題
3章. ・・・
つまり、1章で眠たくなる・飽きるのですが、本書は1章で実際のコードを用いて「こんな風にリファクタリングってするんだぜ!詳細は後で説明するけどな!」というスタンスで記載してくれています。 そのため、この本を購入するかどうか検討されているかたがいらっしゃいましたら、是非第1章を一度読んでいただいて、ご検討いただければと思います。(「amazonのなか見!検索」で1章のほとんどを読むことができるので、購入の検討はそこでできるかと思います)
気になったところ
第一章では、上述のとおり「リファクタリングってこんなもの」という雰囲気を実際のコードをリファクタリングする様子から感じとる章になっています。そのため、各リファクタリング手法?は後で出てくるから、今はよくわからないだろうけど使うぜ!というスタンスで使われていきます。 それらの手法は、感覚として知っているものもあれば感覚に反するものもありました。 1章で出た手法と私の感覚を対比してみると以下の通りになりました。
■感覚通りの手法
■感覚通りではない手法
- 一時変数の置き換え
さて、この感覚通りではない一時変数の置き換えですが、例えば以下のようなことをしております。(forループ条件は適当)
MethodA() { Target target; int conter = 0 String result = ""; for(hoge) { result = Method(target); counter = counter + target.getNum(); } result = result + counter; }
こんなコードの一時変数counterがダメなので以下のようにメソッド化して置き換える。
MethodA() { Object target; for(hoge) { Method(target); } result = result + getCount(); } int getCount(Target target){ int rtnValue = 0; for(hoge){ rtnValue + target.getNum(); } return rtnValue; }
さて、こうするとMethodAのコード量は確かに短くなってよさそうに見えるのですが、全体のコード量は増えたばかりか、forループを2回まわすことになり 計算量として高々定数倍ですが増加してしまいます。そのため、私は今まで上のようなコードを書いていたのですが以下のような観点から下にすべきだそうです。
1.リファクタリング時は「かもしれない」パフォーマンスはあまり気にしなくて良い。
高々定数倍でしか速さは変わらないため一般的にパフォーマンスの影響度合いは低い。そのため、まずは修正してしまってパフォーマンスチューニングのタイミングで変更が必要であれば変更すれば良いし、リファクタリングしておいたほうが変更するときに問題個所の特定および修正が容易だそうです。
2.再利用することを考えるとたしかに使いやすい(私の考え)
確かに例えば、今回のgetCountなどループ処理で一緒に行う処理を取り出してみるとそれ単品で意味がある処理に変わっていると感じました。 つまり、他の処理でも使いやすく、再利用しやすい形に変わっているとも理解しました。 以降の章で詳細に説明してもらう箇所が楽しみです!!
よくわからなかったところ
ある意味全部・・・・ 今回は「リファクタリングってこんなもの」という雰囲気だけだったため、各手法の詳細な話はなにもありませんでした。 自分自身でこんな感じだろうなと思う部分はありましたが、現状よくわかっていない部分が大きいです。 上述しましたが、各手法の詳細をきちんと学ぶことができることが非常に楽しみです!
アジャイルソフトウェア開発技術者検定試験合格体験記
受験目的
社内でアジャイル開発ができるという地位を確立したく、アジャイル開発の資格を調べたのですが、どれも高額だったため「アジャイルソフトウエア開発技術者検定試験」という資格を受験しました。
この資格についてネット上ほとんど情報がないため本記事にてまとめてみます。
アジャイル開発の資格って?
世の中にはアジャイル開発の資格もといスクラムの資格はいくつかあります。※スクラムがわからない方は別途ググってください。
さて、このアジャイル資格はアジャイル関連の資格まとめ | masaytan's blog
でまとめてくださっているように、おおよそ以下3つがあります。
- Scrum Alliance®公認研修
- Scrum Inc.認定資格セミナー
- アジャイルソフトウェア開発技術者検定試験
それぞれの費用が以下の通りである。
Scrum Alliance®公認研修(認定スクラムマスター) | 約30万 |
Scrum Inc.認定資格セミナー | 約20万 |
アジャイルソフトウェア開発技術者検定試験(レベル1) | 1万 |
はい。その通りです。上司を相当うまく丸め込まないと高額のためアジャイルソフトウェア開発技術者検定試験以外の資格を取得することなんてできません。
もちろん、ポケットマネーで受験しようとも思いません。。。。
そのため、アジャイルソフトウェア開発技術者検定試験(レベル1)を受験したわけです。
さて本題を記載していきます。
勉強方法
- 公式ドキュメント(学習参考資料 | アジャイルソフトウェア開発技術者検定試験) のみ
- 1週間ぐらいで2周したぐらい(割とちゃんと読みました)
とは言え、以前からスクラムブートキャンプザブック、カイゼンジャーニー、アジャイルサムライ読んだり研修受けたり、講演聞いたりしているので参考値にしてください。
後述しますが、公式ドキュメントに記載している用語の読み替えが必要になってくるため、他の本1冊ぐらい触れておくと良いかと思います(イテレーションとスプリントなど)。
ちなみに、合格基準は80%で上記勉強内容で得点は90%でした。
合格基準が80%であることからもわかるように、あまり点数に余裕がないため きっちりと勉強しておく必要があります。
試験内容について
アジャイルソフトウェア開発宣言超重要
アジャイルソフトウェア開発宣言およびアジャイル宣言の背後にある原則で言われていることを選べといった問題やアジャイル宣言からわかることを選べ。みたいな問題が感覚的に半分ぐらいを占めていました。
意味と共に丸覚えしてもいいレベルかと思います。
各種用語について
公式参考書ではスクラムの話は出てきませんが、スクラムおよびスクラムの中の用語とかも普通に出てくるので、公式参考書だけでは足りません。もう一冊ぐらい別の本を読んどいた方が良いです。ただし他の本では微妙に違う事を言っているかもしれないため、最後に公式参考書の言っていることをインプットしておくと良いかと思います。
各用語の言い換えは理解しておく事
などなど
会議体とロールを把握しましょう
各会議体に誰が参加することが望ましいのか
例えばイテレーション計画会議の前半と後半で何が違って、それぞれ誰が参加するのかなど把握しておかなければならない
やはりアジャイルソフトウェア開発宣言超重要
一般的に考えた場合とアジャイル宣言から考えた場合で思考はきっちり分けなければならない
→一般的に考えて2択までしか減らせなかった問題があったりした。
その他
常時結合、リファクタリング、テスト駆動開発、ペアプロの目的及びメリットは抑えておく必要がある。それぞれ少なくとも1問は出たと記憶しております。
私の勉強不足かもしれませんが、2択までしか減らすことができない問題があるように思えます。あとは運ですね。
まとめ
アジャイルソフトウェア開発宣言超重要!これにつきます。
基本的にアジャイルソフトウェア開発宣言のそれぞれの理解の仕方は公式ドキュメントに記載されているので熟読すれば問題ないかと思います。