この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
そしてソースカツ丼となった
前回までのあらすじ
以下のゲームで、
牧場経営ソーシャルゲーム:
ユーザーは牧場を経営する。また、牧場などで育てたものを調理し、食べる事が出来る。
ユーザーにはステータスが存在し、様々な行動によってステータスが変動する。ある一定のステータスを伸ばすと出来る事が増える。
ステータスは割合で決定されており、どれかのステータスを上げると他のステータスが落ちる。
一度得た能力は消えない。
味噌カツを作る事が決定しました。
提示された仕様書を読み込み、それに対して曖昧な点や改善すべき点を会話して解消、サーバーエンジニアがすべき事が明確になった後に仮実装、暫定での実機確認が完了。その後に仮実装で適当に作っていた部分をちゃんと作り込み、テストコードも作り、実装を一旦完了させました。
コーディング完了後にすべき事
コーディング完了してそれで全て終わりにしてしまうと、後々負の遺産が溜まっていく事になります。
そうしてしまうと、そのコードを他者が弄る事になった時に、「ク・ソ・コォォォォドゥォォォォォォォォオオオオオオ」とかその人に叫ばれたりとか、ずーっと誰にも気づかれないまま潜んでいたバグが唐突に本番環境で発生したりとか、そんな事が起きてしまう可能性がとても高くなっていきます。
※クソコードによる影響はどこかしこに記事やブログとして載っているのでここでは書きません。ただ、クソコードはクソだからクソコードと呼ばれるのです。クソコードはクソだからクソコードと呼ばれるのです。
そんな事を極力防ぐ為に、例えば、以下のような事をしましょう。
実装完了後の仕様書の読み合わせ
味噌カツ作りを実装がサーバー、クライアント、デザイナー、プランナー全ての担当が完了し、繋ぎ込みも一旦終わった後に、仕様に対して漏れや差異がないかなどを再確認しましょう。
くらいあんとえんじにあ「追加するって言ってたこの仕様、仕様書から漏れてるよ」
ぷらんなー「えっ」
さーばーえんじにあ「あ、後から追加されたこの仕様に対して実装するの忘れてた……」
くらいあんとえんじにあ「えっ、あっ、ここデフォルトデータしか入ってないじゃん……」
でざいなー「UI出来たので本画像渡します、仕様書のここの仮画像、本画像に差し替えておいて下さい」
ぷらんなー「りょーかい」
さーばーえんじにあ「……実装してから気づいたけど、仕様書通りだと、これこれこういう場合にこんな挙動になるけど、これで良いの?」
ぷらんなー「あー、これ、駄目だな、仕様から直します」
くらいあんとえんじにあ「影響はサーバーだけ?」
さーばーえんじにあ「そですね」
要するに、実装の上で認識のズレが生じていないかの確認が出来ます。
その認識のズレは基本的にQAチェックなどを行えばある程度はバグとして弾く事が出来ますが、QAもバグを100%弾ける訳ではありません。
そして、こういう事をしないでQAチェックまでそのまま通って本番に反映されてしまうと、
ぷらんなー「何か変な挙動するんだけど」
さーばーえんじにあ「えっ……あー、これは、仕様です」
ぷらんなー「バグっぽいんだけど」
さーばーえんじにあ「仕様書通りの仕様です」
みたいな事が起きたりします。確認を何度も挟んだとしても起きる可能性はありますが、チェックを複数段階で行なう事でその可能性を減らす事は出来ます。
影響範囲を纏める
基本的に新規実装となるとQAチェックもその新規実装に対して全面的にチェックする、という簡単な構造になるのですが、既存コードへの修正はテストコードも改修して通ったとしても、ある程度はQAチェックを挟む必要があります。
また、新規実装の為に既存コードにも手を加えた、という事に関しては仕様書への記載としてはSV側の改修点として見えない時もあります。
なので既存コードに対して修正を入れたならば、それもきちんと纏め、QAチェックを依頼しましょう。
デバッグツールを作る
QAが確認する際に、既存のデバッグツールでは時間が掛かる、などと言った苦情が来る可能性があります。
余裕があったら必要そうなものを先んじて作っておいても良いでしょう(こういう事こまめにやっておくと好感度UPするんじゃないかな……)。
さーばーえんじにあ「特定の味噌カツのレシピを作れる素材を一括付与するとか、作っといたら便利かな?」
コードレビューを行なう
第三者を招いてコードレビューを行いましょう(今更ですが、実装が複雑だったり、実装者が初心者だったりするのならば実装する前に設計レビューも設けた方がいいです、書くの忘れた……)。
コードレビューの際には、コードを直接見せるのとは別途、追加したデータ構造などを記載したエクセルなども用意しておくと分かりやすくなります。
さーばーえんじにあ「今回は味噌カツ作りの実装を行いました。
まずは、新規追加したモデルの構造から話します。
マスタに関してですが、味噌カツ作りの為に新規マスタを二つ追加してあります。
まず一つ目は、味噌カツの親マスタで……、
次にユーザーデータは、ログが一つです、このログはユーザーの味噌カツ作成履歴を保存、更新しており……、
……インデックスは、ユーザーIDとレシピコードでユニークなのでそれでユニークインデックスを張ってあります……。
……です」
れびゅあー「マスタインポート時のチェックはどの位やってる?」
さーばーえんじにあ「指定された素材の存在確認くらいですね」
れびゅあー「explain取った?」
さーばーえんじにあ「マスタはメモ化してあるのでクエリは初回しか行われませんし、インデックス張ってある親コード単位とかでしか取ってきてないのでしてないです……。ユーザーデータもそんな感じですね……、問題無いとは思うのですが、余裕があったらやっておきます」
れびゅあー「問題ないと思うが、やっといてね」
さーばーえんじにあ「次に今回の基幹となる、指定された素材群からレシピを確定するというロジックの説明をします。
ここのロジックですが、これこれこういう風に作られるレシピを確定しています」
れびゅあー「そこ、計算量がO(n2 )で、マスタの数が大幅に増えたら計算量ヤバくならない? 改善出来ないかなぁ……」
さーばーえんじにあ「nはマスタの数ですよね、マスタそんなに今は数多くないので現状は大丈夫だと思いますが……でも改善出来そうなのでやっておきますね」
れびゅあー「わかった、その時はまたレビュー頼む」
さーばーえんじにあ「わかりましたー」
れびゅあー「あ、後、もうちょっとコメントあった方が良いと思う。コード自体に問題なくても、仕様がちょっと複雑だから」
さーばーえんじにあ「はーい」
自分自身の観点からだと、クソコードもクソコードだと気づけない場合が良くあります。クソコードでなくとも、ぱっと見では分からない複雑さになっていたりとか。
文章とかでもそうですが、一旦時間を置いてまた読み直してみると、前には気付けなかった欠点などにも気付けたりします。
コーディング後のチェックが完了したら
そうして、自分のコードに対する影響や、後々に対するコスト、QA確認の為の事柄などを鑑みた上で他者からのお墨付きを貰う事で、最終的に味噌カツ作成のサーバー実装が完了となります。
上記以外にも、バグや後々のリスクなどを防ぐ為に出来る事は色々とあると思いますが、時間も有限ですし、出来る事柄をやったとして、それら全てをやって全てに効果があるかもやや不明でしょう。
確認行為などを行うにせよ、それをマニュアル的に行うのではなく、どういう目的の為に行うのか、それを念頭に入れて行いましょう。
より良い実装の為に(まとめ)
サーバーに限らず、クライアントも同じ事だと思いますが、
実装の最終目標は、仕様に沿った動くコードを作りあげ、追加/新規機能を実現する事です。しかしながら実装=コーディングではありません。
ただ動くコードを作り上げるのではなく、後々のコストが肥大化しない為に、シンプル且つ柔軟で拡張性のあるコードを作り上げる事。認識の齟齬から後々の不具合を生み出さない事。既存部分への影響を鑑み、それに対する問題がないかの確認。そんな将来に向けた配慮が必須となります。
上記の実装に対する例は自分が実装をしている時はこんな感じで進めているというようなものですが、これでも不完全な部分はあるでしょうし、改善出来る部分はしていきたいと思っています。
さーばーえんじにあ「腹減ったし、今日はソースカツ丼でも食べるか」
ぷらんなー「は?」
さーばーえんじにあ「昨日味噌カツ食べたので」
ぷらんなー「よーしよしよしよしよし」
多分終わり