なぜあなたはJavaでオブジェクト指向開発ができないのかを読んでみました

なかなか挑戦的なタイトルの本です。

なぜ僕はJavaでオブジェクト指向開発が出来ないんでしょうか。
その謎を解き明かしていきたいと思います。
Javaでと書くとJava以外だと出来るみたいに見えますが出来ませぬ…

全体の感想

モデリングの考え方が特に参考になった。
・仕様を見て何をクラス化するのか
・そのクラスから生み出されるインスタンスにどういう属性を持たせるか
・どういう操作を持たせるか
は時間をかけてしっかり吟味する。

吟味するためにも仕様はしっかりと書き出す。
モデリングにただ一つの正解はない。
自分ではわかりやすいつもりでも他の人から見たらわかりにくいかもしれないことは頭に入れておく。
デザインパターンを使えるといいのはこういうところだと思う。

コラムも凄く良かった。

ただオブジェクト指向プログラミングに全く触れてない人だと難しいかもしれない。
オブジェクト指向プログラミングの入門書を読んでみて、その入門書に書いてあることはなんとなく理解できるけど実際の現場でどう使うのかがわからないとか、使えているかどうか自信がない人向けだと思う。

今後の自分の課題

  • クラス設計を簡易にするために難しい例でも仕様をしっかりと書き出せるようになること(ユースケースをマスターする)
  • UML図を使いこなせるようになること
  • メモリ管理を意識したプログラムを書けるようになること

以下簡単なまとめ

Lesson 1 オブジェクト指向をなぜ難しいと感じるのか

オブジェクト指向は、ソフトウェアを効率的に開発するために生まれた技術
効率的というのは拡張とか再利用しやすいとかってことだと思う。

プログラミングの手順は、3つのステップに分かれている

  1. コンピュータに行わせたいことを理解する
  2. 理解したことを説明できるレベルまで整理する
  3. コンピュータにわかる言葉に翻訳する

プログラミングができない理由は1と2が出来ていないことが多い。
自分が先生とコンピュータが生徒という例えはしっくりきた。
人に何かを教えることができている = 自分が理解できている
1、2が出来ていないというのは自身がコンピュータに教える内容を理解できていないということだと思う。

Lesson 2 オブジェクト指向は本当に必要なのか

プログラミングにおいて最も難しいのは、仕様のわかっているソフトウェアを最初から作ることではありません。一度作ったソフトウェアに対して変更や機能追加をしていくことなのです。

全くもってその通りだと思うし、以前自分が書いたコードを最近後輩に触ってもらうことがあって修正しにくいコード修正させているなあと思った。
ほんとごめんなさい笑

極論を言うと変更、機能追加がなければプログラムはどんなに見にくくても要求通り動いてさえいればいいと思う。
変更、機能追加があることの方が多いので変更や機能追加がしやすくなるように初期の段階から考えていかなければならない。
ただし、

  • 既にそうなっていないもの
  • 初期の段階では想定できなかったもの
  • 想定して開発したつもりが後々手を付けてみると変更が難しかったもの
  • 時間の制約によりそこまで手が回らなかったもの

等に関しては後々適切にリファクタリングを行いたい。

一度作成されたプログラムの変更は根本的に難しい

これもっと世に広まってほしい…簡単と思われると辛い…笑
出来るだけ初期の段階で良いものを作りたい

Lesson 3 オブジェクト指向でのソフトウェア開発

  • オブジェクト指向とは人間の言葉をできるだけそのままコンピュータへ伝えるための方法として考えられたもの
  • オブジェクト指向で度々使われる操作とはメッセージをきっかけとしたオブジェクトの振る舞いのこと

余談だがコード例の下の辺りはenumを使って管理した方がいいとeffective javaに書かれていた気がする。

public static final int STONE = 0; // グー
public static final int SCISSORS = 1; // チョキ
public static final int PAPER = 2; // パー

Lesson 6 より複雑なソフトウェアの作成

オブジェクト指向で重要なのは明確に役割を分担すること
現実世界にできるだけ合わせるのはそうしたほうがわかりやすいためでありマストではない。
あくまで役割を明確に分担が最優先

モデリング手順

  1. 仕様を決める
  2. クラスを抽出する
  3. オブジェクト間のメッセージを考える
  4. 各クラスの操作を洗い出す
  5. 各クラスの属性を洗い出す

■仕様を決める
仕様を決定する段階ではユースケースという手法が一般的。

ユースケースとは
ユーザがソフトウェアをどのように利用するかというシナリオを文章として記述する。
ユースケースを書くことによって、ソフトウェアを使う側の視点に立って、それが「どうあるべき」を明確に整理することができる。

■クラスを抽出する
絶対的な正解があるわけではない。
どれをクラス化してどれをしないかをしっかり考える。
クラスの抽出に関しては、後に行う洗い出しの最中にまた戻って分析した方がいいこともある。

■オブジェクト間のメッセージを考える
以下の3点を考える

  • どのクラスからどのクラスへメッセージを送るのか
  • どのようなメッセージを送るのか
  • メッセージを受け取った結果、どのように振る舞うのか

クラス間に関連がある = それらのクラス間で何らかのメッセージをやり取りする可能性がある。

・各クラスの操作を洗い出す
そのインスタンスがどういう振る舞いをするのか

・各クラスの属性を洗い出す
外部に影響しない属性は不要

1〜5のモデリングが終わったらクラス図にまとめる。

Lesson 7 既存のソフトウェアの再利用
Lesson 8 再利用を考慮したソフトウェアの設計
Lesson 9 フレームワークを利用したソフトウェア開発

オブジェクト指向を使ってソフトウェアを効率的に開発していくには?
継承とか移譲とか自作フレームワークとかを使って共通点をモデリングしていく

例えばトランプの場合、全部でカードが54枚ということは共通している
ゲームによってはジョーカーを使用しない場合があるので52枚とジョーカー2枚でそれぞれクラス化した方がいいのかもしれない。
手札を使うゲーム(ババ抜き、大富豪)、使わないゲーム(神経衰弱)などもあるので、ここでも分けることもできる。
継承(is-a)や移譲(has-a)をうまく使っていく。
継承は誤るとわかりにくくなるので注意

モデリングのキレイなプログラムがよいプログラムがよいプログラムか? → △
近年だとコンピュータの処理速度が高くなっているため、拡張性・再利用性ばかり重視されて実行速度はあまり気にされないことが多い。
とはいえ無駄なループ、無駄なオブジェクトの生成はしないようにしっかり注意する。

結論:自分がJavaでオブジェクト指向開発が出来ない理由

モデリングが雑すぎることが一つの大きな原因だと思った。
振り返ってみるとモデリングを雑に起こっているがために
コーディング中にこのメソッドが足りなかっただの、これはいらなかっただの
ってことがある。
さらにいけないのがそれをその場で修正して結果的にそのクラスのインスタンスに相応しくない属性やメソッドが入っていたりするケースがあった。
もちろんプルリク通らず修正し直した。

今後は、
・自分がコンピュータに説明できるまで理解できているか
・Lesson 6 にあったモデリング手順の実践
・コーディング中にモデリングが甘かった部分が出てきたら手順を振り返ってクラス図を見ながら吟味する。
を意識して開発を行っていきたいと思った。
モデリングするための課題も見えたのであわせて学習していく。

新人プログラマーが「リーダブルコード」を読んでみた(前編)

お久しぶりです。
いきなりですが、僕は、大学時代にかなりわがままなコードを書いていました。
そんなわがままコードを矯正するために、名著「リーダブルコード」を読んだので、
その感想を書いていきます。

この本の副題は「より良いコードを書くためのシンプルで実践的なテクニック」です。
それでは、早速そのテクニックを見てみましょう!

注)
この記事は、ひたすら読書感想文が続きます。
それでも許せますよ!という人だけ読んでいただければ幸いです。

1. 理解しやすいコード

<重要ポイント>

  • コードは、他の人が見て最短時間で理解できるように書かなくてはならない。
  • 「このコードは理解しやすいだろうか?」と自問自答してから、次のコードを書く。

僕のような新人プログラマーは、コードを書くのが非常に遅いです。
なので「早く終わらさなきゃ!」という気持ちになることが多いです。
しかしそのコードは他の人が見るものなので、理解しにくいコードは他の人の時間を奪います。
もちろん、バグの温床にもなります。
他の人が最短で理解できるコードを、常に意識したいですね。

2. 名前に情報を詰め込む

<重要ポイント>

  • 目的を明快に表す単語を用いて、変数や関数の命名をする。
  • 汎用的であることに意味がある場合以外は、汎用的な命名を避ける。
  • 名前に単位などの情報を付与することで、誤解を生まない分かりやすい命名となる。

この章の内容は、意識することはできれど実践は難しいと感じました。
しかし、できるようにならなくてはいけません。
英単語の語彙を増やせるよう努力します。
オープンソースのプロジェクトを読み、
どのような命名をしているのか勉強するのも良さそうですね!

3. 誤解されない名前

<重要ポイント>

  • 名前を決定する前に、その名前を「このように誤解されないだろうか」と想像する。
  • ある単語に、「ユーザーがどのような期待を持っているか」
  • を考える。

この章は、前章で取り上げられた命名法の、さらに踏み込んだ内容を説明していました。こちらについても、常に他の命名がないかと意識することで、次第に上達していくのかなぁという感想です。

4. 美しさ

<重要ポイント>

  • 複数のコードブロックで同じような処理のとき、コードのシルエットも同じようにする。
  • コードの「列」を揃えることで、コードの概要が理解しやすくなる。
  • ある場所で決めた処理や順序は、他の場所でも同じ順序にする。
  • 空行を駆使し、論理的な段落を作る。
  • 「一貫性」のあるスタイルは、「正しい」スタイルよりも大切。

コードの美しさは非常に重要です。
見にくいコードって誰も触りたくないですよね。
そんなコードを生まないためのテクニックが、この章には詰まっていました。
中でも「一貫性」>「正しい」というのは、意識したことがなかったので、今後注意したいです。

5. コメントすべきことを知る

<重要ポイント>

  • コードからすぐに分かることはコメントに書かない。
  • コメントには、考えの過程や意見など、自分の思考を記述する。
  • 全体像を要約するようなコメントはグッド!
  • 優れたコード > 酷いコード + 優れたコメント

この章は、コードへのコメントについてです。
ここは、非常に耳が痛い章でした。
というのも、私自身、コメントマシーンのようになっていたからです。
思えば、大量のコメントは、自分のコードに自信がないということの表れだったように思います。
今後は「シンプルなコード」+「補足コメント」を意識しようと思います。

6. コメントは正確で簡潔に

<重要ポイント>

  • 曖昧な代名詞の使用を避ける。
  • 関数の正確な動作を書くべきなのか、関数の意図を書くべきなのか考える。
  • 情報密度の高い言葉を選択する。

前章に引き続き、コメントに関する章です。
こちらでは、具体的にどのようなコメントを書くのかというテクニックを紹介していました。
命名法と同じく、常に意識することや、他のコードをよく読むことが大事だと思います。

7. 制御フローを読みやすくする

<重要ポイント>

  • if/else 文では、条件文は肯定形を先に書き、否定形を後に書くようにする。
  • 肯定形が複雑になってしまう場合は、上述の限りでない。
  • 比較の条件を使うときは、変動するものを先に、安定したものを後に書く。
  • 三項演算子は、どうしても使わなければいけないというとき以外は使わない。
  • 条件のネストは、早めに値を返すなどしてできるだけ浅くする。

制御フローをどのように見やすくするかというテクニックが詰まった章です。
大学時代は、比較的複雑なフローを書く機会が多かったので、意識できている内容が多かったです。
もちろん、意識していないこともあったので、それは自分のものにしなくてはならないです。

8. 巨大な式を分割する

<重要ポイント>

  • 「説明変数」を用いて、複雑な式を簡略化する。
  • 複雑なロジックは、ド・モルガンの法則を使ってより簡潔にする。
  • 短く理解しにくいコードよりも、少し長くて明快なコードを書く。

この章では、
① exp->foo->bar
のようなメソッドに次ぐメソッドや、
② (A && !B) || (!A && C)
のような複雑なロジックをどのように簡潔に書くのかという章です。

ちなみに、①は説明変数を用いて簡略化できます。
②は ド・モルガンの法則を使うと、!A || B || A || !C となり、
A または NOT A となります。つまり、いつでも通るみたいな条件文になります。
これらのテクニックは覚えておく必要がありますが、問題は使いどころです。
その判断の目を養わなくてはならないと感じました。

まとめ

今回は、以上です。
各章で、シチュエーションごとのテクニックを紹介していましたが、
共通して伝えていることは、「そのコード大丈夫?もっと見やすくできないの?」
ということです。
この言葉を、常に意識してコードを書かなきゃですね。
残りの章については、また後日記事にしようと思います。

PHPUnitでDeprecatedエラーに止められない方法

テストを書いている中でDeprecatedエラーに阻まれるシーンがあったので、備忘録として記します。

PHPUnit\Framework\Error 内にあるDeprecated.phpを開くとファイル下部に
「 You can disable deprecated-to-exception conversion by setting 」とあるので何か設定を行うと無効にできるようです。

 * <code>
 * PHPUnit_Framework_Error_Deprecated::$enabled = FALSE;
 * </code>

この<code></code>に囲まれた部分を該当するテストに張り付けるだけです。
再度実行するとDeprecatedは表示されますが、処理はそれを無視して続けることができます。

他にも PHPUnit\Framework\Error 内にはNoticeやWarningについての設定方法もあるので同じように設定することが可能です。ですが、根本的な解決方法でないので注意が必要です。

エンジニアのための時間管理術を読んでみました

業務効率改善のために「エンジニアのための時間管理術」を読みました。
感想などを書いていきたいと思います。

呼んでみようと思った理由
タスク管理ツールなどを使ってなんとなくでやっていた時間管理を
一度体系的に学んでベターな時間管理をしたいと考えたから。

感想
タイムマネジメントって難しいと改めて感じた。
今抱えているものだけでなく
急に厳しい期限で新しいタスクが入ってくることがあるというのは
タイムマネジメントを難しくする要因の中で上位だと思う。
1ヶ月先までの期限の仕事を後回しにしていて、
別の優先度が高い作業を始めて急に最優先でやらなければ仕事が入ってきて
後回しにしていた作業もあって地獄を見るなんてのは…考えたくないです。

本書で例えばプログラムを書いている場合に
メールが来ること、
突然話しかけられること、
チャットが来ることなどを
じゃまが入るというどストレートな表現してたのは面白かった。

作業を完了するには中断なしで丸1日、
実際には1ヶ月という言葉も面白かった。
他の人の仕事も実際こんな感じなんだろうと思う。
自分から見て他の人の作業が「その作業もっと早く終わるはずなのに」
というものがあってもその人なりの事情があるのだと感じた。
その事情を把握して自分にできることがあれば手助けしたいし、
逆に自分も事情を説明してどうすれば早くなるかを相談したい。
またじゃまにならないような割り込ませ方も考えたい。
新しい仕事を振る時はこの時間の時にするとか。

実はプログラマ向けの本ではないとばっさり書かれているが、
自分でも当てはまったし、読んだ感じ社会人向けの本として有用だと思う。
完全なプログラマ向けのやつがあるなら読んでみたいと思った。

自分みたいにあまりちゃんと時間管理をやってなかった人が
本書に載っていることを全部やってみるのは困難だと思う。
無理のない範囲で取り入れていきたい。

以下章ごとのまとめ、プチ感想など

1章 タイムマネジメントの原則
原則として以下の6つがある。

  1. タイムマネジメント情報を1つの「データベース」にまとめる
    タスク管理ツールなどを色々使わない。一つにする。
  2. 能力は重要な作業のために温存しておく
    プロジェクトAを行っている場合はそれ以外のことは考えない、忘れる。
    プロジェクトBのことが気がかりな場合、その気がかりをメモしておいて脳では忘れる。
    やっている作業のこと以外は考えない
  3. 日課を定め,それらに従う
  4. 習慣やモットーを養う
  5. 「プロジェクトタイム」の間は集中力を保つ
  6. 日常生活の管理にも,仕事で使用するのと同じツールを使用する
    日常で練習して仕事に活かすのもあり

2章 集中と割り込み
集中しやすい環境を作る。
メーラーは基本的に閉じて2〜3時間おきにみる。
迷ったら捨てる、閉じる。
自分の場合は開きっぱなしが多すぎる。
自分の集中力のピーク時を認識し、その時間に最重要タスクをこなす。
基本はマルチタスクが当たり前だが、
ストレスが溜まっている時、睡眠不足の時は避ける
割り込みされた時は委任することも大事
委任できなかったら諦めて頑張りましょう。

3章 ルーチン
出来るだけ余計なことを考えないようにルーチンは作れるなら作るべき
考えることは重要な仕事に回す。
ただ定期的にルーチンの見直しはやったほうがいいと思う。

4〜7章 サイクルシステム
自分の記憶力を信用しない
サイクルシステムを作成する。

  1. 365日分の作業リスト(作業日誌)
  2. 今日のスケジュール
  3. 約束のカレンダー
  4. メモ(人生目標などを記載)

そして,毎日を以下のサイクルで繰り返す.
・今日のスケジュールを作成する
・今日の作業リストを作成する
・優先順位を付け,スケジュールを調整する
・予定に取り組む
・1日の終わり
・会社を出る
・繰り返す

結構大変そうなので最初は緩く始めてもいいかも

目標を立てないと
「単純に作業をうまく進められるようになるだけ」
になってしまう。
・”何を” 実現したいのか
・”いつ” それを実現したいのか

以下の期間で立てる
・短期(1ヶ月)
・中期(1年)
・長期(5年)

こういうのが苦手なのはなんとかしたい、特に長期。

8章 優先順位
自分で優先順位を決める。
ただ上司が考える優先順位とは異なっているかもしれないのでその辺りは確認する。
自分は今、Aという仕事とBという仕事があって~な理由でAを優先して行うつもりですけどよろしいですか等

9章 ストレスの管理
自分に合ったストレスの管理方法、発散方法を見つける。
自分は体の健康が心の健康につながると思うので運動を継続的に行う。
自分の場合はマッサージはその時は楽になるけど応急処置感があってすぐに戻ってしまう。

10章 電子メールの管理
不必要なメールはどんどん消す。
検索があるとはいえ多いことにいいことはない
メーラーはこの時間に開くなどを決めておく
メールが来たらすぐ返さないといけないことがある場合は難しいけども…
社内チャットツールなども緊急の場合は口頭で伝えてもらうようにお願いして2、3時間おきに見るとかでいいと思う。

11章 時間の浪費
水漏れをしている床を毎回吹くのではなく水漏れしている原因に対処するというのはいい例えだと思った。
根本を解決することに時間を費やす。

仕事上に対しての時間の浪費を減らすのはもちろんだが、
日常生活についても書かれていた。
レンタルビデオ店に行かずNetflixで見ると移動時間が減るなど。
別にそこまで気にしすぎなくてもいいのではと感じたが。
レンタルビデオ店は今では自分も行かないが
書店は実際に足を運びたくなったりするし、
結局 amazonの方が安かったりしてamazonで買うこともある。
ゲームとかもそう。

12章 文書化
文書化はすべきだと思う。
ただし、細かすぎる文書化をすればいいわけではないので注意する。
アップデートが頻繁なサービスの文書化などはしょっちゅう見た目が変わったりするので

13章 自動化
この辺はすべき。
事務的な作業でもpythonとか使って効率化できるとこはしていけるといいなあと思う。

Scala リストに要素を追加する &その時の注意事項

ScalaのSeq型の一つである、List型の宣言は下記のようにします。

var ages = List(42, 61, 29, 64)

リストの末尾に要素を追加する場合には、次のようにします。

ages :+ 10

で、この時の注意なんですが、いかにも ages ってリストに 10 という要素が足されたようになってますが、そうではありません。

object Main extends App {
  var ages = List(42, 61, 29, 64)
  println(s"The oldest person is ${ages.max}")

  ages :+ 10
  println(s"The youngest person is ${ages.min}")

}

上記の出力は次のようになります。

The oldest person is 64
The youngest person is 29

ほげえええ

ages :+ 10 とやったときに、なんと新しいSeqが生まれていて、そこに追加されているのです。元のagesに追加されているわけではないのです。

下記のように変更してみます。

object Main extends App {
  var ages = List(42, 61, 29, 64)
  println(s"The oldest person is ${ages.max}")

  var new_ages = ages :+ 10
  println(s"The youngest person is ${new_ages.min}")

}

出力は次のようになります。

The oldest person is 64
The youngest person is 10

あー、よかった、できたできた。(๑>◡<๑)