フレームワークの強制力
iOSやAndroidなどのモバイルアプリフレームワークのいいところの一つは、ずぶの素人が作っても、フレームワークレベルでの強制力が働くため、そこそこきれいなコードになること。
例えばiOSであればStoryboardというGUIでViewを書いていける機能があって、これ自体素人がとっつきやすいという一方で、Storyboard上でできることってのも割と厳しく制限されているので、MVCが明らかに混入してしまうことも少なくなる。
受託開発に出したいときなんかには便利で、発注先のレベルがわからない場合にもXcode使ってStoryboard使う前提で発注しさえすれば、最低限のMVCは確保できるはず。
逆にiOS, Android共通で作れるから便利という理由で、例えばPhonegapみたいな共通フレームワーク指定で受託開発だすと、この強制力働かないのでかなりぐちゃぐちゃなものが納品されたりする。
Storyboardは使いづらいとか、viewが再利用しづらいのでコードがきれいにならないとかいろいろ批判はあるけど、僕みたいな低レベル技術者的意見で言えば、裏に潜んでるメリットも忘れてはいけないと思う。
YAGNI:すぐに使わんもの作るなの理由
まさに言いたいこと全部wikipediaに書いてある。
「あとで使うだろうとの予測の元に作ったものは、実際には10%程度しか使われない。」
とあるけれど、新規事業つくるスタートアップの観点で言うと、仮にこの実際に使う10%に入ったとしても、作ったのと使い始めが数ヶ月とか半年とかずれていると、この期間に導入された他の新機能とちゃんと一緒に動くかとか新たにテストしなければいけなくなるし、担当した開発者がその機能だけを担当しているわけではないので、数ヶ月前に作った機能のことなど正直いって大体忘れている。
「あとで使う」コストってのは想像以上に重い。
金融の用語で割引現在価値っていうのがあるけど、
スタートアップの開発でも同様で、将来に使うであろう機能を現在において実装する場合には、そもそも使わない、存在するといろいろ複雑になる、(上記の)あとから改めて使うこと自体のコストなどなど考えて、大幅に価値が割り引かれることになる。
できるだけあとで作るべきだ。
掘ってもなにも出てこなさそうなところ:iOS画面遷移の分岐
iOSで、ある画面から条件によって(ユーザの種類とか)別の画面に遷移させたくて、きれいに書ける方法ないかと思って考えたり探したりしてもなかなかいい方法ない。
そもそもsegueでやる方法の何が不満かというと、条件分岐で別画面に遷移させた場合って、遷移先の画面も管理下に置きたいという気持ちがある。(せっかく別画面に遷移させたのに同じ画面に合流しないようにロジック組みたいとか)
でもこれって複数画面にまたがる知識になってしまうので、よくない。
なので、segueを使うんだけど、その上でsegueでつないだ一連の画面をきれいに管理する方法ないかって考えてみた。
綺麗に管理する方法とか、ベストプラクティスとか考えるときに真っ先に思いつくのがデザインパターンとか、オブジェクト指向のベストプラクティスだとおもう。
けれど、segueでつないだ一連の画面って、各々の画面はクラス(ViewController)なんだけど、それ自体は全体としてクラスではない。
オブジェクト指向のベストプラクティスとかデザインパターンは、オブジェクト指向言語でクラスを書くときに、その関係性や書き方について語っているので、クラスではないこの一連の画面には全く適用できないことを思い知らされた。
なので、結論としては遷移先画面を分けたいときは
①同じViewControllerのなかで複数のviewを出したり消したりで遷移させて、条件分岐させて、1つのクラス内なので心置きなく全体を管理する
②とくになにも考えずにsegueつかって条件分岐させて、問題が出たらまた考える
オブジェクト指向的な武器が使えないところでいろいろいい方法考えていろんなところ掘ってみてもなにも出てこないと思うので、美しいとはいえないけれど、iOSが標準で用意してくれているsegueなどの画面遷移を素直に使って、問題があればその都度考えるということでいいと思う。
アンチパターンの良さ:パターンの再発明は難しい
今日作ったコードの、今日作った設計の、良い所を一般化してまとめておこうとするとすごく難しい。
それがほんとにベストの書き方だったかを検討するのって、他の可能性をできるだけ多く検討する必要があるので、自分より上級のプログラマと時間をとってペアプログラミングができるとかっていう状況でもない限り、時間がかかりすぎる。
また、そうやって時間をかけて色々検討した結果、結局旧来のデザインパターンに行き着いたとか、そもそもパターン化できるようなものではなかったとかってことがある。
これはこれで勉強になっていいんだけど、もっと良いパターンあるか、もっと良いものあるか病になってくるんで、程々にしておいた方がいい。
一方でアンチパターンは、自分が痛い目見たパターンを覚えておくだけなので、他のアンチパターンと比較する必要ないし、何がいいかを説明するより、何がダメだったかを説明するほうが簡単だし、自分が痛い目見てるんで記憶にも残る。
なんで、ピカピカのベストプラクティスツールボックスには偉人が発明してくれたパターンを詰めておいて、個人レベルの経験値をアンチパターンツールボックスに入れていく、という方針は悪くない、というか現実的にすごくいい。
受託開発と自社サービス開発の、システム開発の思想の違い
受託開発の場合、XXXという仕様のものを作るとXXX円払いますよという仕事なので、プロセスとしてまず「どういうものを作るか」という仕様を決める必要がある。
この仕様はできるだけ詳細に詰めておく方がよくて、(なぜなら後々曖昧な仕様に漬け込まれて作業量が増えないようにするため)、調べるのに時間がかかってもやっておくべきである。
また、仕様が一旦決まると、今度はそれが聖域になって、決められた時間内にその仕様を満たすものを作るということが契約となり、うまく時間内に収めるというのが目標になってくる。
一方で自社サービス開発の場合、多くの人に使ってもらえるシステムを作らなければいけないので、そのサービスにどんな価値が有るかを検証する、というのがまず優先事項になる。
受託開発の場合と違って、特定の仕様のものを完成させるのが目的ではないので、価値の仮説が十分に検証できる範囲で、できるだけコストがかからないように最小のものを作る、というのが目標になる。
受託開発方式に慣れている人が自社サービス開発やる場合には、目標が違うということをしっかり意識しながら最適な開発方法を選択していかないと、「しっかりと仕様の細かいところまで検討して、期間の見積もりをして、さあつくろう。」とかやっているうちに、必要最小のものを最適につくるという思想がないから、時間とコストが不必要に掛かって、気づけばなにもできずにキャッシュ切れみたいなことになりうるので、よくよく考えてやる必要がある。
アプリのweb APIをRailsで作った時のアンチパターン
①エラーメッセージしっかり作りこまなくても意外と大丈夫
HTTPエラーコードはRailsが勝手に吐いてくれるので(Not FoundとかUnauthorizedとか)、小さいチームでサーバもアプリも作る場合は意外と大丈夫。
②配列の書き方統一する
has_manyのデータの列挙の書き方とModel#indexのデータの列挙の書き方が違ってたりする。
users#indexとかで取ると
{
age:30
gender:female
},
{
age:20
gender:male
},
みたいにカラムのみの列挙の一方で、has_many friendsを埋め込むときは
{
age:20
gender:male
friends:{friend:{age:30...}}{friend:{age:20...}}
},
要素ごとにmodel名入ってたりして非対称になってるとか。
③最初から汎用的なAPI目指さずに、アプリで使いやすい書き方とか、具体的なドキュメントの書き方する
いきなり外部ユーザの利用を見込んで無理に完全にRESTであったり、抽象的なドキュメント作らなくていい。わかりにくくて生産性落ちる。ドキュメントにはアプリのどの画面でどうやって使ってるとかまで書いちゃっていいと思う。
④OAuth2とかまで作りこんでしまう
理想的にはやるべきなんだけど、(僕みたいな)技術力があまりない場合は無理せず負荷のない認証方法採用する。認証なくてもよければやらない。
OAuth2とかまでやっちゃうと試しに叩いてみるのも結構たいへんになっちゃうので、がっつり作りこむ必要なければ最初は見送る。
認証とアプリのマルチスレッドなんかが絡むとかなり複雑なことになる。認証ってユーザにとってメインの価値ではない。
⑤rablとか使って書くと便利なんだけど気をつけて書かないとパフォーマンス落ちる
n+1問題にも注意
⑥静的なデータはrails使わなくても、テキストファイルに固定のjson書いてS3にでもおいておけばOK
例えば、アプリに更新があったかを示すjsonとか
latest_version: "1.2.0"
とかだけのために、バカ正直にrailsでModel作ってテーブル作ってデータ登録してってやってたけど、そんなに更新されるもんじゃないし、更新されても手作業で書いたほうが早いってやつは、ただのテキストでつくっておいておけばよし。
更新チェックだと毎回アプリ起動時に呼ばないといけないので、テキスト化すればパフォーマンスもあがる。
S3もcloudfront(CDN)組み合わせれば早いしパフォーマンス落ちないからいいコトだらけ。
エンジニアのやる気を削ぐアンチパターン
エンジニアあるある。
①つくったもの使わない
説明不要で、空振り感、虚しさ感がすごい。フィードバックからブラッシュアップという流れを経ることができないので、使った技術のメリット・デメリットを腹落ちして理解できないという面も☓
②根拠の無い「決め」
ここがこうであれば、圧倒的に作りが美しくなるのに・・・。という不満は、日々パターンの改善、パフォーマンスの向上等々、ロジカルに理詰めで改善活動を突き詰めているエンジニアにとっては悪夢。爪に火を灯して毎日100円づつ貯めている妻から酒代を10000円奪っていくようなもの。「決め」の背後に理由があればいいけど、鶴の一声とかやめてほしい。
③技術の追求できない
ライブラリ制限される、フレームワーク使えない、言語古い、割合数%切った旧バージョンOS対応など。swift書ける人にobjective-cでお願いねとか。すでにソースはスパゲッティだけど、動いてるからロジック変えずに保守お願いねとか。
④過度のドキュメント化
ドキュメントってかなり役に立つんだけど、本音はドキュメント書くならコード書かせて。テストドキュメントかくなら自動テスト書かせて。
⑤作業効率の低下
眠い時は眠りたい。効率落ちるから。大丈夫、ネタ時間の分埋め合わせられるリフレッシュした僕を見てくれ。お昼寝大好き。
⑥作業の中断
前提を3つくらい頭に詰め込んで、バグが起きている原因の可能性を5つくらい仮説たてて考えているときに話しかけないでくれ!また積み直し!