失敗しづらいアプリ開発へのアプローチ

タイトルは少しキャッチーにしてますが、「僕はこうしてみたよ」という話です
プロジェクトによって千差万別ですし私自身もケースバイケースでやってます

この話がアプリ開発を作ってる人たちにとって、何かしらのヒントになればと思います

# 前提と要旨

**前提**

- JavaScript/TypeScriptで書かれたWEBアプリのクライアント(SPA)を作る場合の話です
- 「何を作るか」ではなく「どう作るか」が話のテーマです

**要旨**

- 開発がわかる人がデザインする
- エンジニアはデザイナーのやる作業を想像する
- 使い捨てするようなHTMLモックは作らない

## 登場人物

* エンジニア担当：業務ロジックと対応する画面を作る人
具体的に言うと、ViewModelや各種ロジックとHTMLテンプレートを書くのが主な作業です

* デザイン担当：デザインを調整する人
具体的に言うと、HTMLテンプレートとCSS(Sass/LESS)を書くのが主な作業です

* エンジニア兼デザイン担当：上記２つとも出来る人

# 開発の進め方

## 1. お絵かき

絵かAdobeXDのようなプロトタイピングツールで画面のイメージを作ります

プロジェクト上、ここでちゃんとした絵を書き上げる必要がないのであればワイヤーレベルの絵で終わっても良いです

デザインはデザイン担当とエンジニア兼デザイン担当が考えます

どんな画面か、UXをどう考えるか、と言う話から始まると思いますが、それは一概に語れる話でもないのでその話は省略します

ここで大事なことは`ある程度設計を意識したデザインにしておくこと`です

具体的にはこんなことを考えます

### 部品の流用を想像する

最終的には、用語は色々あるかもしれませんが、Component/Fragmentといった画面部品に分解されて開発されます
Atomic Designのような感じです

私の場合は「ラベルやタブといったコア部品」「部品の集合であるコンポーネント」「コンポーネントの集合であるページ」の３段階ぐらいで考えてます

「あの部品をここでも使うから、こんな見た目になるよね」とか考えながら絵を描きます
これは以前投稿した[失敗しづらいUIへのアプローチ](https://qiita.com/megumu-u/items/b96b7fc7b0a57d72a47f)に通じますが、画面のルールを統一することに繋がります
逆に意識しなかった場合、微妙に違う見た目を実現するためにエンジニア担当が変な実装をする可能性があります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/05252f41-ce72-1ab3-094a-2c4dc6892e09.png)


### 性能を想像する

明細を何行も表示するような画面を描く場合、性能問題が起きないか想像しておく必要があります
大量データの性能問題としては通信量や通信回数、レンダリング性能への影響を気にしておきます
最近の端末は早いので量が多くても結構サクサク動きますが(IE以外)、それでも明細の数が3桁のオーダーになると動きが厳しくなって来ます
テーブルの仮想化が使えるのか、使えないとしたらページングをするのか、など考えておく必要があります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/0655746d-130b-bd2b-b702-d0bdf3fe46be.png)


### 性能を想像する その２

サーバーと通信して取得したデータを画面上に表示すると思いますが、もしAPIが事前に決まってるのであれば何回通信が発生するのか想像しておきます

最近はスマホでも１画面複数回通信しても問題なく動くのでよっぽど酷くなければクライアント側は問題は起きませんが、サーバーの負荷についても考慮しておきましょう
外部システムへのアクセスやDBアクセスが発生するAPIの呼び出しが集中するような作りは避けた方が後々幸せになります
ここでいう「集中」とはユーザーの1端末内での出来事を指してるわけではなく、サーバーにとって集中してアクセスが来ることを指してます
DBアクセス等はなくてメモリ折り返しで応答がもらえる場合はそれほど気にする必要はありません
ただし、それでも限界を超えるアクセスが来るとWEBサーバーのコネクションが枯渇する可能性があることは知っておく必要があります

逆に、APIはまだ決まっていないが性能の懸念が予想される場合、デザイン側からサーバーサイドの設計にリクエストを出しておく必要があります

### レスポンシブか想像する

PC/タブレット/スマホで表示する要件がある場合、同じ部品でいけるのか考えておきます
少し工夫するだけで同じ部品での流用ができそうであれば、デザインの方を変えてしまうことを検討します

例えば、私個人としてはテーブルよりもカードでの表現が好きです
見た目がオシャレですし、レスポンシブに作りやすいです
どっちでも良いのであればカードにした方がPCでもスマホでも同じ部品で表示できるかもしれません

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/c2039058-4155-6833-bb70-f37343b9f750.png)

### 実現可能か想像する

ブラウザで動作するWEBアプリとして実装不可能または品質や保守性の面で不安のあるデザインは避けます
たいていの場合、技術の選定は終わっている思いますので、実装可能なデザインか考えておきます

少し違う話かもしれませんが、WEBアプリに対して普通のアプリのようなデザインを希望されることがあります
モバイルSafari/Chromeで表示する場合は普通のアプリ通りにはいかない場合もあるので注意です
例えば、画面の下の方にボタンやタブを置いた場合、ブラウザでは１回のタップで反応しない可能性があります
（タップするとブラウザの戻るとかブックマークとかのバーが表示される）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/e4d2b193-8075-d5d7-a931-a9f7cccf06df.png)


## 2. モックの実装

モックと言いつつ、Angularなどの実際に使う予定のフレームワークを使って、本当に動くものを作り始めます

この作業は絵を見ながらエンジニア担当とエンジニア兼デザイン担当が作ります
最近だとプロトタイピングツールからデザインスペックの連携ができるので、活用できる場合は活用します

モックなのでサーバーとの通信はしませんし、ロジックも画面表示に必要最低限の実装しかしません
理想としては、データ仕様が決まっているのであればDI等を利用してデータ取得部分をモック化してやれると、後の工程での作業を減らすことができます

ここで、エンジニア担当はデザインを無理に作り込む必要はありません
この工程の後で、デザイン担当がデザインをあてます

エンジニア担当は次のようなことを気にしておきます

### エンジニア担当は余計なclassを指定しない

中途半端にデザインを調整するぐらいなら何もしない方が良いです
たいていの場合、見本通りには出来ないからです
見本通りにデザインをHTMLで作るというのはかなり難しい作業です

中途半端に作り込んだ場合、デザイン担当からすると「このclassには何か意味があるのかもしれない。このままにしておこう。」となって無駄なclass定義が残る可能性があります

実際、エンジニア側にはclass/styleを一切指定しなくて良い、と言って開発してみたこともあります
もちろんDOMの構造だけは意味を考えてちゃんと書きます
それはそれで凄くスムーズに開発が進みました

それだとデザインあてるのが大変という場合は、「暫定的な調整だよ」という意味で全てstyleで直接書いておいて、後でデザイン担当がそれを消しながらデザインを調整するという流れでも良いかもしれません



### エンジニア担当は気軽にGridレイアウトを使わない(CSSフレームワークにあるcol-6とか)

CSSフレームワークを使う場合、col-6等でレイアウトを指定してくれる機能がよくあります

　Bootstrap の Grid system
　https://getbootstrap.com/docs/4.3/layout/grid/

気軽についつい書きがちなのですが、画面サイズを変えると変に余白が広がってたりして、おかしくなることが多いです

エンジニア担当は何もしない方が良いですし、やるにしても本当にこの指定が必要なのかちゃんと考えましょう


### エンジニア担当はDOM構造に依存したロジックを書かない

(モックの時点ではあまり書かないかもしれませんが、)デザイン担当がDOM構造を入れ替えたくなる可能性があります

そもそも、可読性・保守性も良くないのでDOM構造に依存したロジックは可能な限り避けましょう


### エンジニア担当はHTMLのbodyタグにUserAgentやOSを表すclassを設定しておく

IEだけとかiOSだけ、Androidだけとかでstyleを変えたい場合があります

bodyにUserAgentやOSの種類を表すclassを指定しておいてあげると、デザイン担当はCSSだけで対応できるようになります

これがない場合、「JavaScriptでこの時だけこうしてくれ」という依頼がデザイン担当から来ることになります

````sass
// 例
.hoge {
  background: white
  .ios & {
     // iOSの時だけ枠線を引きたい
     border: 1px solid black;
  }
}
````

### 状態によって見た目を変える場合、エンジニア担当は状態を表すclassを設定しておく

チェックを入れたら赤にするとか、何かしら色を変えることあると思います

後からデザイン担当から「ここの色をこの時に変えたい」と言われなくて済むように、事前にclassを設定してあげておきましょう

````html
<div class="hoge">foo</div>

↓　状態が変わった

<div class="hoge stateA">foo</div>
````

## 3. デザインの適用

エンジニア担当が作ったものに対してデザイン担当がデザインを適用していきます

ここでいくつかのclassは事前に定義してデザイン担当に作業をお願いします

例えば以下のような定義です

````sass
.font_L {
  font-size: $font_size_L;
}
````

これの意図は2つあります

1つは、ちゃんと定義して使いまわすことでアプリ全体としての品質・統一感を高めるため

もう1つは、「.font14」とか「.margin4」という感じの設定値を含めた命名を推奨しないためのアピールです
抽象化された名前にしておかないと後々で修正が面倒になります
抽象化しないのであればstyleに直接スタイルを書くのとあまり大差ないと思います

こういったアプリ全体で使えるCSSの定義と、いくつかの画面の Scoped CSS の定義をエンジニア兼デザイン担当がしておくと、デザイン担当は作り方に迷わなくなると思います


## その後の工程へ

モックを使ったステークホルダーとのレビューや、実際のロジックの実装へと進みます
後の工程も同じで、先に動くものを作ってからデザインをあてていきます
またイテレーションを回して段階的に作っていくことも可能です


# メリット

他のやり方と比較検証したわけではないので「メリットだと思っている」という内容です

**無駄なHTMLモックを作る手間がなくなります**

使い捨てのHTMLモックを作るのは勿体無いと思っています
もちろん、ここまで作って「全然違う」と言われると困るので、お絵かきの時点でステークホルダーとの合意は取っておく必要はあります

**無駄な実装を軽減できます**

部品化を前提としてデザインを考え、モックの段階で実際に部品化されています
その結果、ある部品を１箇所修正したら全ての表示箇所が変わるので、「この画面だけ表示を変える」という特殊なパターンを抑止できるので無駄な実装をしなくて良くなります
言い換えると、いざ部品化しようと思うと困る部分が事前に潰せているので、モックとしての品質が高くなります

**見本とのデザインのズレを軽減できます**

デザイナーが作った見本を見てエンジニアが実装するという流れの場合、デザインがズレてもおそらくエンジニアは気づきません
絵を見ながら同じ絵を描け、と言われても描けないのと同じです（違うか？）
モックと言いつつ実際にもう作っていて、そのモックを見てもらうので最終的な仕上がりとのズレが軽減できます

**開発期間を短くできます**

開発に入る時点で、既に結構できちゃってます


# デメリット

**モックが見れるようになるまでが時間がかかります**

見た目に関係ない部分の開発もやる必要があるので、モックを見てもらうのが少し遅くなる可能性があります
部品化しながら作ってますし、テンプレート内に if や foreach が使えるので生産性が高くなる部分もあります
モック完成までは思ったよりは短い期間で出来ると思います

**デザイン担当も開発の仕方を学ぶ必要があります**

デザイン担当にもAngularなどを使った開発の仕方を学んでもらう必要があります
ただ、テンプレート部分とスタイルの開発だけであれば学習コストは高くはないと思います

# まとめ

最初は「エンジニアとデザイナーの分業」といったタイトルでTips的な内容にしようと思ったのですが、進め方自体があまり一般的ではないかもしれないと思い、開発全体の流れについての話にしました
少しポエミーだったかもしれません
開発プロセスや体制、使用する言語やフレームワークの違いによっては当てはまらないものもあると思いますので、役に立ちそうなところだけ参考にしてもらえればと思います
(例えばWEBデザイナーがデザインの実装をしてくれるとしても、Reactだと少し大変になるかもしれません）

この方法の大事な点は`デザイナーの視点とエンジニアの視点の両方を持った人材`がいることです
その方が開発がスムーズになるのではないかと思っています
開発だけでなく、お客さんと画面の話をした時に指摘やコメントもらっても「（開発の手間や実現性を考慮した上で）じゃあこんな感じですかね？」とその場で画面を書き換えて会話できるとスムーズに話が進みます
また、Fluid Interfacesに代表されるように昨今のUI/UXの動きを見ると、デザインとロジックは別々に存在できるものではなく、融合して来てるように感じます
そうした場合、複数の領域に跨って専門性を持った人材の重要性が増すのではないかと感じています