読者です 読者をやめる 読者になる 読者になる

main() blog

プログラムやゲーム、旅、愛する家族について綴っていきます。

バグを出さないプログラマになるための「心得」

はじめに

長年コンシューマゲーム開発に携わってきた中で毎回思うことがある。
開発の終盤には必ずテストプレイが行われ、毎回大量のバグと闘っている。
なぜ大量のバグが出ているのか、どうしたら大量のバグが出なくなるのかについて考え、まとめてみることにした。

バグは「潰す」のではなく「出さない」ことに注力すべき!

バグを「出さない」ようにするためには以下の2つを心掛ける必要がある。

「自分」のところでいかにして「バグを出さない」ようにするか。

  • 実装確認をする
  • 自己完結させる
  • 常に自分を疑う

「他の人」のところでいかにして「バグを出させない」ようにするか。

  • エラーは早い段階でエラーとして処理する
  • エラーを分かりやすく教えてあげる

バグを「出している」というのは新人でもベテランでも一緒。
たとえ学術的なコーディングスキルがあっても、新人が書いたコードでもバグは出る。
実装範囲の大小も関係ない。

いかに「責任」を持って取り組んでいるかで、バグを出すか出さないかに違いが出てくる。

これがイケてる(=バグを出さない)プログラマである。



1.現状の問題点

  • 大量の不具合報告
  • 大量のバグを潰すのは相当の労力を必要とする
  • 精神衛生上もよろしくない

コンシューマ開発において一つのプロジェクトでの不具合報告が数千件を超えるケースも珍しくない。
それが仕様の増大化、複雑化によるものなのか、短期のプロジェクトによるものなのか原因は色々考えられる。
最近ではゲームのボリュームやオンライン要素などに伴いテストプレイは最低でも2カ月、3か月かけて行われるようになっている。

※以下あくまでもイメージとしての事例

  • 事例①

ジャンル:アクションRPG
プラットフォーム:PSVitaPS3
言語:日本、北米、欧州
オンラインによるマルチプレイあり

不具合報告件数:5000件
テストプレイ期間:3ヶ月

  • 事例②

ジャンル:アクション
プラットフォーム:PSVita
言語:日本
オフラインのみ

不具合報告件数:2000件
テストプレイ期間:2ヶ月

プロジェクトの規模、内容にもよるが、概ねこれくらいの期間のテストプレイが行われ、これぐらいの不具合報告の件数がある。

バグが多ければ多いほどデバッグの工数が増える。
当然コストも膨れ上がる。

大量のバグのチケットを捌くことで本来のテストプレイの質も下がり致命的な不具合が見過ごされる可能性がある。

2.対応方法、解決方法は?

ここに挙げたのは一例でプロジェクトに合わせて実践したり、導入したりしている。

コーディング規約は保守性は高くなる。
導入コストも低く、プロジェクトでやっているところも多い。
プロジェクトで徹底させる必要がある。

ユニットテストは社内ライブラリやプロジェクト共有のプログラムで継続的に使用されるようなケースでは適用できる可能性はある。
ゲーム側の場合、短期の開発で導入が困難であったり、ゲーム側の場合テストする範囲としての切り出しが困難だったりする。

静的解析はあると良い。
ただし、ちゃんと運用しないと意味がない。
大量の報告があると放置されたり、どう対処すべきかなどのスタディが必要になってくる。

コードレビューも継続するのが大変。
どう指摘するのが良いのか、レビュワーのスキルによってもばらつきが出やすい。

コンシューマ開発でペアプログラミングを実践しているところはあるのだろうか?

デバッガはバグを追うのには必須。
ただステップで見ていくだけでなく、使い方もちゃんと習得する必要がある。
でも、大量不具合が出ている場合は大量に潰すことには変わりない。

CIは安定的なビルドを提供するために必要。
ただ、ビルドは通っているけど朝の最新版で起動したら落ちたという場合もある。

手法はたくさんあるが全てを導入したり、継続的に行うのは困難なものある。

3.まずは「心掛け」を考えよう

  • 方法論を駆使すれば効率は良くなるかもしれない
  • 方法論はまた別の機会にでも議論する
  • それ以前にコーディングする人の「心掛け」一つでバグは減らせる

バグを出さないように「心掛ける」ができていないと、方法論を駆使しても結局バグが出ることには変わりがない。

4.そもそも大量に出ているバグは…

  • それって本当に致命的な不具合?
  • デバッグ期間を実装確認と勘違いしていないか?
  • プログラムなんだから「バグ」が出て当然と思っていないか?

5000件出ている不具合の全てがプログラムによるものではない。
仕様的な不具合や文言の不具合、キャラクタモデルの形状のチェックやフィールドのコリジョンチェック、モーションのチェックなどリソースの不具合も相当な数含まれている。

ただ、この様な不具合の報告もあったりする。

  • 不具合報告①
特定のスキルを使用すると必ずハングアップします。
再現頻度:10回/10回中
手順:
1.主人公のレベルを50にします。
2.それで習得できるスキル「×××」を使用します。
3.ハングアップします。

他のスキルを使用してもハングアップしません。
:
:
  • 不具合報告②
ステータス画面で特定のキャラクタを開くと必ずハングアップします。
再現頻度:10回/10回中
手順:
1.キャラクター「○○○」を選択します。
2.ステータス画面を開きます。
3.ハングアップします。
:
:
  • 不具合報告③
オプションメニューのカーソル移動時のSEが再生されていません。
再現頻度:10回/10回中

この場合、カーソル移動音が再生されるのが適切かと思われます。
手順:
:
:

これは単に実装漏れというか、テスト前に誰も確認していないのか?
実装したプログラマ、仕様を書いたプランナー、音をつけるサウンドエンジニア、もちろんディレクターも。
誰もチェックしていないのにテストプレイで指摘って、実装者が確認すれば見つけられたバグもあるはず。

デバッグ期間は商品としてのクオリティを上げるための作業、もっと致命的なバグを見つけるための期間だということを忘れていないか?

5.どうしてバグが出ているの?

  • とりあえず動いているから大丈夫
  • サンプルプログラムをそのまま流用
  • バグを人のせいにする
  • テスターさんからのツッコミがあったら修正

とりあえず動いているから大丈夫

誰でもとりあえず動いているものは大丈夫だと思う。
そして当然のことながら不具合が出ない限りは何もしない。
ところがこういった実装が自分とは全く関係ないところに影響を及ぼす可能性があり、
不具合が起きた時に特定しづらいケースを生むことがよくある。
エラーチェックを強化した途端、動かなくなることもしばしばある。

サンプルプログラムの流用

SDKのサンプルプログラムや書籍のサンプルプログラムをそのまま流用しているケースも見かける。
サンプルプログラムはあくまでもサンプル。
動作保証はまったくない。
バグあって当然だと思わなければならない。

昔、DirectXのサンプルプログラムにIMEを使ったサンプルがあり、そのサンプルに不具合があった。
それをそのまま流用しているケースが多々あり、マイクロソフトのセミナーでも「こういう対応をお願いします」という話をしていた。

バグを人のせいにする

ベテランでも初心者でもある。
自分のところは大丈夫と誰もが思う。
ベテランの場合はさらに厄介なのが自分の非をなかなか認めない。

テスターさんからツッコミがあったら修正

とりあえず実装してみてテスターさんからツッコミがあったら修正。
最近はプログラマだけでなく、プランナー側でもよくあるケース。
メッセージやテキストなどの文言であればまだしも(本当はこれも良くはないが)、ヘタをするとフローまで変更する可能性まで出てくる場合がある。

テストの段階では仕様も含めてFixしている必要がある。

仕様通りに実装すればよいというものではない。
なぜなら完璧な仕様書は存在しないのだから。

こんな心構えで実装しているから大量のバグが出ている!(かも?)

  • とりあえず動いている大丈夫

    「とりあえず動いている」は「動いていない」と思うようにする。

  • サンプルプログラムを流用

    サンプルプログラムはコピーしない。
    参考にしても良いが自分でちゃんと咀嚼し、理解して実装すること。

  • バグを人のせいにする

    自分の不具合は素直に認めよう。

  • テスターさんからのツッコミがあったら修正

    実装してみて問題があるところや改善点があるのであれば早くフィードバックしよう。

6.「たち」の悪いバグ

メモリ、リソース関連のバグ

メモリリークやメモリ破壊、エージングバグはマスター直前になって現れる「たち」の悪いバグ。

再現性が低く、原因を特定するのがものすごく困難な厄介なバグ。
関連している人全員が疑われるために出してはいけない。

が、こういった不具合こそ真の不具合である。

アクションゲームの事例

組み合わせのワーストのチェックが抜けていた。
マスター提出後に特定のキャラクタ、装備、ミッションでメモリ不足が起きた。
各キャラクタ、装備でのメモリ使用量のリスト、各フィールドのメモリ使用量、各ミッション開始時のメモリ使用量のリストを出力してテスターに連絡はしていてもこういったチェックが抜けてしまうケースがある。

60時間後に出た不具合

MMOのプロジェクト。
クライアントにもASSERTと同様の処理を仕込んでおき、エラーが出たらその時のログをファイルに出力してユーザーに報告してもらっていた。
大概は「起動できません」といった内容の報告で低スペックによるドライバのエラーなどによるものが大半を占めていた。
もちろん有益な情報のフィードバックもある。
あるときの報告のエラーで普段とは違うエラーが来ていた。
自前のwidgetの実装で、そのwidgetをゲーム側で用意したHANDLEで管理していた。
そのHANDLEが枯渇してASSERTに引っかかっていた。
調べてみるとアイテムウィンドウの詳細ウィンドウの中のタブを切り替えるとウィンドウのHANDLEがリークしていた。

デバッグ機能でウィンドウのHANDLE数の表示を追加し、一定数を超えたらゲーム中にワーニングを表示するようにした。
また、シーンの遷移(といってもMMOなのでタイトル画面に戻る時)にリークチェックを挟むようにした。

メモリ、リソースの使用量は常に把握しておく必要がある!

他人のバグ

他人のバグも厄介。
自分のところにきたバグのチケットが調べてみたら他人のバグによるものだった。

MMOの事例

MMOのプロジェクトで運営が開始されてからクライアント側でファイル読み込み中に読み込みに失敗する不具合報告があった。
クライアント側と疑って、読み込みのところのエラーチェックを強化したり、データの整合性チェックする機能を入れたりしたが原因が特定できずにいた。
あるときランチャの機能更新があったためエラーチェックを強化したところファイルのダウンロード処理でエラー処理が正しく行われていなかったことがわかった。
これによりデータの一部が不正な状態になっていたためにクライアント側で該当のファイルを読みに行った時にエラーになっていた。

自分(当事者)が出したバグが他の人たちに影響を与えていることは確か!

7.自分のところでバグを「出さない」

メインプログラマだと…

  • メインプログラマになると自分のバグより他人のバグに関わる方が多くなる
    • 不具合報告のチケットの割り振り
    • 良くわからないバグは担当じゃなくても調査しなければならない

不具合のチケットの割り振りも意外に時間がかかる。
プログラム以外の不具合であっても担当が不明な場合はメインプログラマにチケットが回ってくる。
内容を精査し、原因、対応方法なども追記してチケットを担当に割り振る。

再現性が低いものは考えられるケースや可能性も検討し、他の人の不具合であっても継続的に調査しなければならない。

正直、自分のバグに付き合っている時間が無い。

どういった「心掛け」が必要?

  • 自分のところではバグは出さない!
  • 自分のバグは自分のところで完結させる!
  • バグを出してもすぐに特定できるようにする!
エラーチェックを強固に!

当たり前のことだがエラーをエラーとして処理することが重要!
ASSERTをとにかく仕込むようにする。
値をセットする場合は有効な範囲かどうかチェックする。
配列にアクセスする場合は要素の範囲をチェックする。
引数や返却値で受け取ったポインタのチェック。
ロジック的に通らないような場所にもASSERTを仕込む。
switch文でdefaultが不定であればASSERTにする。

void Chara::SetHP(int hp)
{
    if(!(hp >= 0 && hp <= MaxHP()))
    {
        // 範囲外であればASSERT.
        // 不正な値をセットしないようにreturnで抜けておく.
        ASSERT(false);
        return;
    }

    HP = hp;
}
void hoge(const Chara *chara)
{
    // 引数で受け取ったポインタをチェック.
    // そもそも参照渡しにすべきという話もあるが、ポインタで受け取った場合はエラーチェックを仕込む.
    // リリースビルドでもハングしないようにnullだったらreturnさせておく.
    if(!chara)
    {
        ASSERT(false);
        return;
    }

    chara->SetState(State::Attack);
}
void hoge()
{
    const Chara* chara = GetChara();

    // ここでのcharaの取得でnullは想定されていないのであればASSERT.
    if(!chara)
    {
        ASSERT(false);
        return;
    }

    chara->Damage(10);
}

以下の様な実装だとRESULT_OK,RESULT_ERROR以外の処理が想定されていない。

void hoge()
{
    result = GetResult();

    switch(result)
    {
        case RESULT_OK:
            break;
        case RESULT_ERROR:
            break;
    }
}

関数の仕様が変わって返却値が変更されたとしても最初の想定から外れた値が返ってきてもエラーを拾える。
SDKやライブラリなども更新されると挙動が変更される可能性がある。
続編や移植などの際はこういったところのエラー処理も強化しておく方が良い。

void hoge()
{
    result = GetResult();

    switch(result)
    {
        case RESULT_OK:
            break;
        case RESULT_ERROR:
            break;
        default:
            ASSERT(false,"Invalid result:[%d]",result);
            break;
    }

最近では続編や移植で追加、拡張が行われてもエラーチェックを仕込んでおかないと動作してしまう可能性がある。
そのようなケースも含め早期にエラーを検出できるので、パフォーマンスに影響がない限りはとにかくASSERTを仕込むようにする。

メンバ変数は全て初期化!

リリース版のエージングで起きる不具合で、まれに挙動がおかしくなったり、場合によってはハングする不具合を引き起こす。
最近では通信、オンラインなどのタイトルも増えているため、同期エラーの原因にもなる。

普段から意識して初期化しておかないと、最終的にはCoverityなどの静的解析ツールのやっかいになる。

テストケースを考える!

自分の実装確認という意味でも最低限のテストケースは考えておく。
エンバグを防ぐ意味でも考えておき、実装、修正などを行った後で実装のチェックをする。
過去のプロジェクトでは実装者がテスト用のチェックリストを作成し、実装者自らチェックしてからテストに回すということもあった。

保守性は重要!

そうは言ってもやっぱり保守性は重要。
プロジェクトでも他の人のソースも読まなければいけなくなし、続編や移植などで再利用される可能性もある。
なるべくシンプルで読みやすいコーディングを心がける。

ライブラリ、コンパイラすら疑え!

ライブラリやコンパイラが引き起こす不具合もある。
この場合はきちんと原因を特定するまで調査する必要がある。

コンパイラの事例

とあるコンパイラで64bitの比較演算子に不具合があった。

移植案件でとりあえず動作はしていたが、なぜか特定の挙動だけ呼ばれないという報告が来た。
調べてみると以下のようなコードでif文がtrueにならないことが分かった。
defineによる定数と64bitの変数の比較演算子が正しくないようだ。

#define ITEM_MAX (64)

func()
{
    int64 itemNum = 10;

    if(itemNum < ITEM_MAX)
    {
        // trueにならない!?
    }
}

これを64bitの変数同士での比較や、defineの定数をキャストなどして動作することを確認。

コンパイラのメーカーに問い合わせたら「コンパイラのバグです」とのこと。
こんなことが、と思うかもしれないが実際にあった話だ。

報告しないでゲーム側でこの箇所だけ修正してしまったら、どこか他の場所で同じような不具合が出ても気が付かないままになっていたかもしれない。

ライブラリの事例

とある携帯機で通信プレイ中にスリープモードに移行した際にハングアップするとの報告が来た。
頻度はかなり低く、1日のテストプレイで回しても1、2回程度。

ライブラリに渡すパラメータを直前でチェックしたり、ライブラリが返す返却値も全部チェックし、適切に処理するようにしても改善されず稀に不具合が発生した。

原因が分からないので問い合わせをしたら不具合が発生したらダンプファイルを送って欲しいとの事。
マスター直前だったため土日かけてテストをし、ようやく再現したのでダンプファイルを送ったところ、後日「ライブラリの不具合です。次回のアップデートで修正しますので今回の不具合は問題ありません」とのことだった。

8.他の人のところでバグを「出させない」

ゲーム開発では多くの人が作成に関わっている。
大規模なプロジェクトになると50人とか100人、もっと多いプロジェクトだってある。
関わった人の分だけバグが出る。
プランナー、レベルデザイン、アーティスト、サウンド、こういったメンバーも当然バグを出す。

当然、その分プログラマの作業も増える。

最後に不具合の原因を突き止めて解消できるのはプログラマのみ。
いかにバグを出させないようにするかが重要。

プログラマによるバグ

パラメータ、スクリプトなどのリソース化に伴い非プログラマのバグも増えてきている。
この様な場合、エラーを早い段階でエラーにする必要がある。

パラメータをExcelで管理し、CSVでエクスポートしてデータテーブルとしてゲーム側で読み込ませている。
プランナーがパラメータの上限が100にも関わらず110と入力してしまった。
さらにゲーム中はカスタマイズなどでこのパラメータに係数がかかり、実際のパラメータは補正されてしまう。

エラーチェックが無い場合

テストプレイからの報告で「なんかダメージの値がおかしい気がします」。
何度も繰り返し検証を行い、統計を取って不具合かもしれないという不具合報告。
プログラマが不具合報告を受けてキャラクタに設定されているパラメータの値を確認する。
範囲外の値が設定されているのでプランナーに指示をしてバグチケットを回す。
プランナーは修正してチケットを戻す。
テスターは修正されたビルドで繰り返しテストを行い、問題ないことを確認してチケットを終了にする。

パラメータの設定なのに問題が起こるところまでが遠い。

エラーチェックがある場合

プログラマがキャラクタのパラメータにセットする段階でエラーチェックを仕込んでいたら…

ASSERT:Invalid attack param:[110] chara_status.cpp line:[253]

不正なパラメータがセットされた段階でエラーにできる。

データテーブル(CSV)を読み込んだタイミングでエラーチェックしていたら…
起動時のパラメータテーブルの読み込みのタイミングで整合性チェックをしてエラーにできる。

起動直後にエラーにできる。

Excelからエクスポートするタイミングでエラーチェックをしていたら…
プランナーが入力して、エクスポートしたタイミングでエラーにできる。

データ入力時にエラーにできる。

つまり、早い段階でエラーチェックができればゲームを起動しなくてもバグを防ぐことができることになる。
不具合の責任の所在もはっきりする。

テストプレイの繰り返しのチェックも、プログラマの確認も不要になる。

開発当初から防げるバグも…

開発当初はリソースが無かったり、パラメータが仮であっても開発の効率化という名目でとりあえず動作させてしまう。
そのまま開発を続けていると結局終盤やテストプレイ前にそれらを潰していく必要が出てくる。

リソースの不備やパラメータの設定ミスをワーニングとして分かりやすく画面に表示する。

WARNING:Effect_Fireを設定しているノード名'Eff_1'が存在しません。effect.csvの設定を確認してください。

ただし、たとえ画面に表示しても非プログラマの担当者は指摘をされないと修正はしない。
本来であればエラーなのでASSERTで停止させるのが望ましい。

また、テストプレイの段階で仕様バグが出るとフローの見直しであったり、それに関連するグラフィックリソースの手直し、
再実装など修正の範囲が大きくなることがある。

仕様バグを早めに問題化、表面化させるために1ヶ月単位などのイテレーション開発が効果がある。
1ヶ月ごとに成果物を確認し、仕様面での不具合やブラシュアップを早めることで仕様バグを減らすことができる。

自動化の重要性

毎日動作するものをリリースする。

さらに自動チェック、エージングの環境も整える。
ビルドが通るだけでなく、起動チェック、例えば先ほどの起動時のパラメータのチェックが実装されていればこの時点でパラメータの不備が検出できる。
人力のテストプレイにも限界はあるので自動化の環境は早めに準備する方が良い。

また、エージング環境が整えば人が作業しない時間を有効に活用できる。
例えば、アクションゲームでバトルシーンをキャラクタの組み合わせを変更しながらAIでプレイさせ、ミッションを繰り返しプレイするエージング環境を用意したとする。
退社する時間から出社するまでの時間、例えば22時から9時までエージングをかければ11時間×機材分のテストプレイが行える。

もちろん人の手でしか出せないバグもあるだろうがエージングで発見できるバグも存在するし、逆に不具合が出なければ正常に動作している実績にもなる。

これらを問題視して環境の構築、改善ができるのはプログラマのみ。

最後に

  • バグを完全に出さなくすることは不可能…
  • でも、バグを減らすことは可能!
  • 「バグは出て当たり前」という考えは捨てよう!
  • バグは「潰す」のではなく「出さない」ことに力を注ぐべき!
  • 個人が少し意識するだけでも格段に「バグ」は減るハズ

商品のクオリティを向上させるためにも、開発終盤のデバッグのストレスを軽減するためにも「心掛ける」ようにしよう。

【記憶のゴミ箱】MZ-80Cと将来の夢

あの「MZ-80C」が手のひらサイズで復活!?

 

f:id:takezoh_1127:20170522123932j:plain

 

ハル研究所から「PasoconMini MZ-80C」という新商品が発売されるとのニュースをネットで見かけた。

 

www.pcmini.jp

 

流石に手のひらサイズでキーボードもディスプレイも、そもそもテープレコーダーもどうするんだ?と思いきや、中身は「Raspberry Pi」で、USBやら画面出力用のHMDIを備えているらしい…

 

 

それでも、これを見ると欲しくなってしまう。

 

 

 

もう30年以上前の話。

 

当時、小学5年生だったろうか。

父親がMZ-80Cを家に持って帰って来た。

買ったかどうかは不明ではあったが、とにかく家にマイコンがやって来た。

 

銀色のカバーを外すと漂う電子機器の独特な匂い。

ブラウン管、キーボード、テープレコーダーが一体型のマイコン

臙脂色、黒、シルバーの筐体。

電源を入れるとディスプレイに表示される緑一色のフォント。

テープレコーダーで数分読み込ませてようやくBASICの入力が行えるようになる。

 

 

とにかく興奮したことは覚えてる。

小学生で理解出来る範囲は限られているので最低限のことだけ教えてもらい、父親のいない平日でも勝手に起動して遊んでいたものだ。

 

ゲームもいくつかあって遊んだりしていた。

汚染されていく建物の中から汚染を食い止めるために壁の隙間に防御壁を埋めつつ、倒れている人を救い出すゲームや、着陸用のロケットを月面に着陸させるゲーム、左右に揺れるバルーンを障害物を避けながらゴールに導くゲームなど、ASCIIで表現されたゲーム画面にくらいついて遊んでいた。

 

そのうちBASICでプログラムも始め、文法も理解しないまま、雑誌のプログラムを入力しては動かない、入力間違いを探してようやく動いたを繰り返していた。

それだけでも大喜びだった。

 

 

それに飽き足らず自分で作るようになり(自分で考えて作ると言ってもPRINT、GOTOだけの簡単なテキストアドベンチャーだった。たいていは途中で作るのをやめてしまっていたが…)作っては友達に見せたりしていた。

 

そんな小学生だったせいか、小学校の卒業文集の「将来の夢」にはこうかいてあった。

 

プログラマー

サラリーマン

 

プログラマーという言葉を知っていたのか分からないがプログラムをする人になりたいと言うことで書いたのだろうか?

それからサラリーマン…

なにかカッコイイものと勘違いでもしていたのか?それとも他に夢もなく書いていたのか?

 

とにかく将来の夢にはこんなこと書いていた。(ハズ)

 

中学にあがるとMSXを持ってる友達の家に行ってはBASICでプログラムをしていたがすぐにゲームに夢中になってしまい、その後はTRPGPCエンジンと移っていき、プログラミングはしなくなっていった。

 

高校になると友達の家でPC98でたまにゲームは遊んでいたが、プログラミングからは遠退いて行った。

 

専門に進みロボット工学の様な学科でハードもソフトも学ぶ中で再びプログラミングに出会い、プログラムで作る楽しさ、表現できるものはやはりゲームだと思い、就職はゲーム業界に進んだ。

 

小学生の時に書いた将来の夢が2つとも叶ってしまった。

 

その後20年ゲーム業界にいるがゲームプログラマーやらゲームディレクターとしていくつものゲームを作ってきた。

 

ただ、最近は仕事になりすぎている感がある。

もちろん作ることは楽しいがどこか仕事としてこなしている部分があるような気がする。

 

MZ-80Cの記事を読んで遠い昔の忘れていた熱い気持ちを思い出させてくれた。

現状に満足せずに何か新しいことを始めてみよう。

 

 

 

あのMZ-80Cはまだ実家に眠っているだろうか。

年に一度帰るかどうかだが、今度実家に帰る機会があったら探してみるか。

 

 

【書籍】リーダブルコード より良いコードを書くためのシンプルで実践的なテクニック

感想

リーダブルコードを読みました。

もっと早く読んでおくべきだったと思います。
初心者は良い勉強になりますし、むしろベテランにも読んでもらいたい本です。

自分は読みながら胸を痛めている側で、「あー、あるある」と思いながら読み進めていましたし、
読む前から実践していたことが出てくると「やってて良かったんだ」と思えたりします。
読んでいても楽しいのぜひ読んでみてください。

あくまでも「こうしたら良くなるよね」という主観的な意見で正解が無いというか、
コーディング規約なども含めてこのような内容は宗教論争になりそうですが、
事例を踏まえて書かれていて読み物としてうまくまとめられていると思います。

「技法」の紹介もありますが「考え方」のお話としてまとめられています。
でもこれって大切なお話だと思います。

コモンセンスがあるとプログラマ同士でもコミュニケーションも取りやすくなります。
コードレビューなどをする際にも、今まではなんとなく「こうだよね」としか言えず
お互い曖昧なままだったりしていましたが、もう少し具体的に話ができてお互いに納得できるようになります。

どちらにしても関わるひとには読むように勧めていきたいです。
もしくはコーディングスタイル(プロジェクトでの推奨の書き方)の様なものにまとめ直して運用するのもありだと思います。
本に書かれていることを全部をやらなくても部分的に取り入れるだけでも効果はあると思います。

でもこの本の一番の効果はコーディングに対する意識が変わることだと思います。

この本を読んだ後では自分のコードを何度でも読み返すようになります。

意識を忘れないためにも数カ月に一度目を通すだけでも本を読み直した方が良いと思います。

概要

1章 理解しやすいコード

コードは理解しやすくなければいけない。
コードは他の人が最短時間で理解できるように書かなければいけない。

第Ⅰ部 表面上の改善

2章 名前に情報を埋め込む

名前に情報を埋め込む

  • 明確な単語を選ぶ
  • 汎用的な名前を避ける(あるいは、使う状況を選ぶ)
  • 抽象的な名前よりも具体的な名前を使う
  • 接尾辞や接頭辞を使って情報を追加する
  • 名前の長さを決める
  • 名前のフォーマットで情報を伝える

気取った言い回しよりも明確で正確なほうがいい。

3章 誤解されない名前

名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する。

4章 美しさ
  • 読み手が慣れているパターンと一貫性のあるレイアウトを使う。
  • 似ているコードは似ているように見せる。
  • 関連するコードをまとめてブロックにする。

一貫性のあるスタイルは「正しい」スタイルよりも大切だ。

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

コメントの目的は、書き手の意図を読み手に知らせることである。

  • コメントすべきでは「ない」ことを知る。
  • コードを書いているときの自分の考えを記録する。
  • 読み手の立場になって何が必要になるかを考える。

コードからすぐにわかることをコメントに書かない。

コメントすべきでは「ない」こと:

  • コードからすぐに抽出できる
  • ひどいコード(例えば、ひどい名前の関数)を補う「補助的なコメント」。コメントを書くのではなくコードを修正する。

記録すべき自分の考え:

  • なぜコードが他のやり方ではなくこうなっているのか(「監督のコメンタリー」)。
  • コードの欠陥をTODO:やXXX:などの記法を使って示す。
  • 定数の値にまつわる「背景」。

読み手の立場になって考える:

  • コードを読んだ人が「えっ?」と思うところを予想してコメントをつける。
  • 平均的な読み手が驚くような動作は文章化しておく。
  • ファイルやクラスには「全体像」のコメントを書く。
  • 読み手が細部に捕らわれないように、コードブロックにコメントをつけて概要をまとめる。
6章 コメントは正確で簡潔に

コメントは領域に対する情報の比率が高くなければいけない。

第Ⅱ部 ループとロジックの単純化

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

条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く。

行数を短くするよりも、他の人が理解するのにかかる時間を短くする。

変更するときにはコードを新鮮な目で見る。一歩下がって全体を見る。

8章 巨大な式を分割する

巨大な式は飲み込みやすい大きさに分割する。

9章 変数と読みやすさ

変数のことが見えるコード行数をできるだけ減らす。

変数を操作する場所が増えると、現在値の判断が難しくなる。

第Ⅲ部 コードの再構成

10章 無関係の下位問題を抽出する
11章 一度に1つのことを

コードは1つずつタスクを行うようにしなければいけない。

12章 コードに思いを込める
13章 短いコードを書く

最も読みやすいコードは、何も書かれていないコードだ。

第Ⅳ部 選抜テーマ

14章 テストと読みやすさ

他のプログラマが安心してテストの追加や変更ができるように、テストコードを読みやすくする。

コードを完全にテストする最も単純な入力値の組み合わせを選択しなければいけない。

テストには最もキレイで単純な値を選ぶ。

15章 「分/時間カウンタ」を設計・実装する

【Git】GitHubをはじめよう!

はじめに

GitHubをはじめる前にGitの環境をインストールしておく必要があります。
下記のページを参考にインストールをしてください。

GitHubのアカウント登録

まずはGitHubのアカウントの登録を行います。

GitHub

ユーザー名とメールアドレス、パスワードを入力します。

github_000.png

プランを選択します。
Freeで進めます。

github_001.png

自分の経験にあった内容を選択してsubmitします。

github_002.png

登録が完了しました。
メールでメールアドレスの確認を求められるので確認しておきます。

github_003.png

早速、リポジトリを作成してみます。

github_004.png

無事にリポジトリが作成されました。

github_005.png

後は今まで通りの手順でGitHubの共有リポジトリで作業できるようになります。

GitHubに作成した共有リポジトリで作業

まずは先ほど作成した共有リポジトリをクローンします。
TortoiseGitで作業してみます。

github_006.png

URLに先ほど作成した共有リポジトリのURLを入力します。
ディレクトリはローカルのパスを指定してください。

これ以降はGitHubの共有リポジトリにpushできるようになります。

GitHub Desktop

GitHub Desktopもインストールしてみます。

GitHub Desktopをインストー

githubdesktop_000.png

インストール中…

githubdesktop_001.png

GitHubのアカウントでログイン

GitHubのアカウントを入力してログインします。

githubdesktop_002.png

コンフィグを設定

今までに設定したユーザー名とメールアドレスを入力します。

githubdesktop_003.png

インストール完了

githubdesktop_004.png

リポジトリの追加

ここで今までに作成したリポジトリを追加してみましょう。
Desktopで表示されるようになりました。

githubdesktop_005.png

初夏の庭

今日は妻の庭造りのお手伝いです。

 

派手な色はあまり好まないので地味な感じになりそうですが落ち着いた雰囲気が涼しげな空間を生んでくれます。

 

f:id:takezoh_1127:20170508004217j:image

f:id:takezoh_1127:20170508004231j:image

f:id:takezoh_1127:20170508004243j:image

f:id:takezoh_1127:20170508004252j:image

f:id:takezoh_1127:20170508004259j:image

 

ナメクジと大量のゾウリムシと闘いながらなんとか作業は終わりました。

 

庭をやってる時に見たことのない野良猫がやって来ました。

下の子は「なお!(にゃお)なお!」と興奮し、お姉ちゃんは勝手に「ジンナイ」と名前を付けていました。

眼光鋭い野良猫でしたが意外に人懐っこく子供たちが着いてまわっても一向に逃げる気配がありません。

そのうちトカゲを見つけて臨戦態勢に。

お尻を振り始め、飛びつくまでを三人で観戦してました。

シャーッと飛びつくとものの見事シッポ切って逃げて行きました。

お姉ちゃんも切れたシッポは初めてだったらしく「動いてる!動いてる!」とギャーギャー騒いでいました。

f:id:takezoh_1127:20170508010223j:image 

 

 

【GW】39.5℃の涙

5/3(水)

幕張メッセのフリマに行った。

ブログ書こうかなぁ、あまりネタないし、疲れたから明日にするか…

 

その日の夜中…

2時過ぎにもの凄い寒気で目が醒める。

マズイ…

確実に熱が出てる…

とりあえずママを起こす。

「ママ…ママ…熱出てる…」

途端に吐き気が。

そのままトイレに駆け込み嘔吐。

熱を測ると39℃。

身体が痛い…

先週まで上のお姉ちゃんがインフルエンザだったから移ったか?

それとも今日行ったイベントで風邪でももらったか、変なものでも食べたか?

 

とにかく隣で寝てる下の子に移さないようにママの布団に移動して布団も離して横になる。

ママが水まくらを持って来てくれて、一応バケツも枕元に用意。

胃がムカムカするし、頭がグワングワンするがとりあえず寝るしかない。

 

5/4(木)

7時に起きて熱を測っても39℃。

休日当番医を調べても車で20分のところしかない。

小さい子もいるので自分で行くしかない。

9時くらいに病院に着いたけどすでに沢山の人。

手続きを済ませて、なんとか座れたけどずっと朦朧としたままでどれだけ待ったことか…

呼ばれたのは2時間後…

「とりあえずウィルス性の胃腸炎かな」

「インフルエンザは明日にならないとわからないから、熱が続いたらまた診てもらって」

整腸剤と解熱剤だけ処方。

 

帰ってすぐにくすりを飲んで横に。

とにかく身体が痛い。

寝てるのか起きてるのか分からないまま夜に。

熱を測ると38.5℃。

少しだけおかゆを口にして薬を飲んで横に。

下の子が寂しそうに部屋を覗き込んでいた顔がなんとも言えない。

f:id:takezoh_1127:20170506232512j:image 

 

夜中の2時に目が醒める。

身体が痛い。

熱を測ると39.5℃。

ヤバイ…

とにかく解熱剤飲んで横に。

寝てるのか起きてるのか分からない…

 

5/5(金)

7時に目が覚めて熱を測ると38℃。

もう一度病院に行かねば。

 

 近所だと耳鼻科メインの担当医しかないようだ。

行ってみるとやはり激混み。

1時間半くらいでようやく呼ばれて中に入ると診察台?

「これ反応出てないよねぇ?」

大丈夫か?と思いつつもインフルエンザでは無かったようです。

 

結局また胃腸炎だろうという事で、整腸剤と抗生物質、解熱剤が処方。

 

 帰って一眠りしたところで汗がドバッと。

体温も37℃まで下がりました。

 

5/6(土)

朝、体温を測ると36.7℃。

子供の顔を見に行ったら下の子が起きていて顔見たら「パパ!」と笑顔で言ったけどすぐに布団で顔を隠してた。

 

 

せっかくのゴールデンウィークなのに遊んでやれなくてゴメンね。

それからママもありがとう…

 

 

【Git】Gitのインストール手順(TortoiseGit)

インストー

下記のページを参考にインストールしてみます。
こちらもとても参考になりますので是非読んでください。

TortoiseGitのインストールの前にGit for Windowsをインストールしておく必要があります。
下記のページを参考にインストールしてください。

1.ダウンロードしてくる

TortoiseGit

現状の最新版は2.4.0.2です。(2017/4/7)

TortoiseGit-2.4.0.2-64bit.msiをダウンロードします。
日本語化パック(TortoiseGit-LanguagePack-2.4.0.0-64bit-ja.msi)もあわせてダウンロードします。

Git for Windowsはインストール済なのでTortoiseGitのインストールを開始します。

2.TortoiseGitのインストー

インストーラを実行します。
基本的には[Next>]で進めていけば問題ありません。

tortoisegit_000.png

tortoisegit_001.png

SSHクライアントの選択は一番上を選択しておきます。

tortoisegit_002.png

カスタムセットアップも変更がなければそのまま進めます。

tortoisegit_003.png

tortoisegit_004.png

tortoisegit_005.png

インストールが完了しました。

tortoisegit_006.png

起動してみます。
日本語化パックをインストールしていないのでここはEnglishのまま進めます。

tortoisegit_007.png

tortoisegit_008.png

tortoisegit_009.png

ユーザー情報もGit Bashで設定した情報が表示されているのでこのまま進めます。

tortoisegit_010.png

tortoisegit_011.png

これで初期スタートの設定も完了です。

3.日本語化パックのインストー

langpack_000.png

langpack_001.png

langpack_002.png

インストールが完了しました。

日本語に切り替えます。
右クリックのTortoiseGitのsettingを選択してください。

langpack_003.png

GeneralのLanguageを日本語に切り替えてください。

langpack_004.png

これで日本語への切り替えが完了しました。