思考の進め方

あくまで個人の経験による思考のテンプレート例です。
これに従えとかそういう物ではありません。
こういう考え方の人間も居るんだなぁくらいに思ってください。

# 工程
ワークフロー、パイプライン、セットアップ、ツール作成様々な事を行うにあたって
基本的には

- 問題・目的定義
- 現状把握
- 原因特定
- 解決案候補作成
- 実証

の5段階で構成しています。


# 目的定義

目的が定まってない状態では何も出来ないので、まずはゴールを簡潔かつ明確に設定します。


ここで注意しなくてはならないのが、目的と手段がごっちゃにならないようにすることです。

例えば

- **目的：ツールを作って作業効率を上げる！**

という目的を設定したとします。

実はこれは悪い例だと考えています。
目的は　**作業効率を上げる**　であって、
**ツールを作る**　は　**作業効率を上げる**ための手段の１つなのです。

このような目標を立ててしまった場合、
ツールを作ることに捉われてしまい、
ツールを作る以外での作業効率を上げる方法を考える前から捨ててることが多いです。

なので、

- **目的：作業効率を上げる！**

が適切かなと思います。

# 現状把握

## 定義
**作業効率を上げたい**のですが、そもそも**効率を上げる**とは？

つまりは**効率が上げられそうな部分**を探して、アップデートするわけですが、
**効率が上げられそうな部分**については2種類考えられます。

- **現状問題は無いが、どっかで見た新しい技術に置き換えられる部分**

こちらについては常に最先端の技術と既存のフローの細部まで把握していることが前提になります。
たまたま見かけた技術で　あ、これ使えそう　という偶然の出会いでしか発生しないので能動的には少し難しいです。

- **単純に効率が悪い部分**

ひとまず今回は　**効率が上げられそうな部分 = 効率が悪い部分** という定義で進めます。

なので、アップデートして
**目的：現在効率が悪い部分の作業効率を改善する**
とします。

## 把握

現在効率が悪い部分を特定する為に現状を把握します。

一連の作業工程を確認し、他の工程と比べて効率が悪い工程、
ミスが多かったり工数がかかりすぎている工程を探しだします。

今回は過去に実際にあった
**リグ作業において、モデルデータの更新内容次第では2度手間になるので工数がかかる事がある**

という件で考えてみます。


# 原因特定

問題を解決する為には

 **a, 問題が起きた後に対処する方法を追加する**
 **b, 問題を引き起こしている原因を突き止めて、原因を除去する**

という対応が考えられます。
よっぽど時間がない時以外はbを選択した方がいいです。

aを選択した場合、自動手動に関わらず結局工程が１つ追加されてしまうので、
別の問題の原因になったり、別の問題の原因を探すときに邪魔になってしまいます。

原因を突き止める際に重要なのは、**真の原因を突き止めること** です。

こういった作業で残念な結果に終わる多くの場合が、
**原因**　ではなく　**原因から結果に行き着く途中の部分**　を原因と**誤認**して進めてしまっています。
根本的な原因が取り除けていないので結果的に何の解決にもならず、ワークフローやパイプラインをただ汚すだけになります。

真の原因を突き止めるためには、
フローの起点から終着点へ　終着点から起点へ　両端から各工程結果を確認し、
**ここまでは正しい**  が  **ここからがおかしい** というポイントを探します。
その上で、　**ここからがおかしい**の**原因**となっているものがだいたい真の原因です。

## 実際のケースにて確認
モデルの更新があった場合のざっくりとしたフローはこのような流れ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/5a458055-b87c-4526-97bc-f67681ae61f9.png)

2度手間になってしまう流れはこんな感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/cec48f75-9a77-b64d-78a7-23a54b02fbf9.png)

更新内容確認でモデルの更新申し送りがなかった場合、
スキンウェイトの更新必要なしと判断し同一のウェイトでリグを組みなおします。
しかし意図した・しないに関わらず実はモデルが更新されており挙動確認でデフォーム破綻が発覚すると、
モデルの更新内容を再チェックのフローを行った上で、更新作業を行う事になります。

最初の更新内容確認の時点で**更新内容を正しく把握**できていれば、直接更新作業に入れます。
なので、**モデルデータの更新内容を正しく把握できていない事**が今回の原因と思われます。

## ヒアリング

とりあえず、モデルの出荷セクションに申し送り内容について聞いてみました。

想像を想像のままにしておくと、正しい状況把握ができないので　想像の部分についてはヒアリングするなり調査するなりして現実の状況を把握することが重要です。

- 後工程からの修正依頼があった場合はその内容を明記する
- 自主リテイク(修正作業中に発見した　別の要修正箇所)は基本的に明記しているが、完璧ではない	
- 作業中に偶発的に起きてしまった更新については作業者も把握できていないことが多く、明記できていない。

つまり、申し送りの内容は　把握している限りは明記しているが、把握できていない部分は明記できていない。
その把握できていない箇所がセットアップ時のデフォームに関わる部分であった場合、先述の2度手間問題に発展していそうです。

やはり **モデルデータの更新内容を正しく把握できていない事** が原因であるようです。

# 解決案作成

**モデルの更新内容を正しく把握できない** 問題を解決する為に、　
**モデルの更新内容を正しく把握する方法** を考えますが
その前に

解決案を考えるにあたって

 - どんなにくだらない方法でもリストする。  
 - 詳しいやり方や実装難易度は考えない。とにかくリストする。  
 - 複数人で行う場合には、他者の意見を否定しない・馬鹿にしない。  

これらを念頭に置いた上で考えます。

## とりあえずリスト
とりあえず思いついた案を並べてみました。

- 更新前のデータと比較するシステムを作る。  
- モデル作業者が詳細な作業ログを作成する。  
- モデルの作業ログ作成するシステムを作る。    
- 申し送り時にデータを詳細に見比べて取りこぼさないように気をつける。  
- そもそも何か更新されている前提でモデルを受け取る。  
- モデルの更新内容確認リストを作成して、手動で毎回確認する。  

リストの内容を簡単に検証しつつ、試行するための優先順位をつけます。
自身・他者が見直した際に採用・不採用の理由がわかるように、各案のメリット・デメリット・懸念事項などをメモしておきます。
この時点でスクリプト書いたり、詳細な検証を行う必要はありません。

## 個別に確認&メモ

- **更新前のデータと比較するシステムを作る**  
更新前後のデータを読み込んで
オブジェクト名の差分抽出
共通するオブジェクト名を抽出
共通するオブジェクトに関してはポリゴン数を比較
UV情報も比較する？
比較自体は難しくないが、２つ読み込むのでメモリが心配
オブジェクト総当りなので処理時間が心配  


- **モデル作業者が詳細な作業ログを作成する**  
意図していない更新内容のほとんどが、ツールなどの目に見えない部分での挙動なので操作すべてをログとらなくてはならない。
取れたとして、その内容をフィルタリングする必要がある。
ログの量が膨大になる。

- **モデルの作業ログ作成するシステムを作る**  
一つ前と基本的には一緒。
スクリプトエディターの内容をダイレクトに書き出し続けるとか？
save / open / 強制終了　などでログがごちゃごちゃになるのが予想される。
該当データの純粋な作業ログだけを抽出する方法が必要
ログ取り処理によって、重くならない？

- **申し送り時にデータを詳細に見比べて取りこぼさないように気をつける**
:::note warn
基本的に出た案は否定してはいけないが、この手の気をつけましょう系の案は最低の部類に入ります。
この案は作業者の注意力に頼るものであり、根本的な解決になっていません。
つまり現状維持と同じ意味になります。
:::

- **そもそも何か更新されている前提でモデルを受け取る。**
ある意味根本的な解決策。
2度手間を回避するのであれば、
モデルが何かしら更新入っている前提ですべて作業すればコスト的に省略できるところを無視することにはなるが2度手間にはならない。
ツールなどの開発もいらないので、開発的にはほぼ不要
:::note
ここで思い出したいのが目的設定の際に悪い例とした**ツールを作って作業効率を上げる**という物です。
この案、すごく効率は上がっていないものの、1回の作業でリリースできるデータの確実性はあがるので
結果的には効率はよくなっているといえるのではないだろうか？
ツール！ツール！と盲目的に叫ぶ前に、落ち着いた目で全体を俯瞰視して考えることで別の解決策も見えてくるはずです。
:::

- **モデルの更新内容確認リストを作成して、手動で毎回確認する。**
チェックリストを作成して確認する。
手動なので、ヒューマンエラーが起こりえる。
1つ目の **更新前のデータと比較するシステムを作る** を手動で行う感じ。
1つ目が実装できなかった際にリストは残して転用可能。

## 順位付け

- **更新前のデータと比較するシステムを作る**
わりといけそうなので　第1候補とします。  

- **モデル作業者が詳細な作業ログを作成する**  
- **モデルの作業ログ作成するシステムを作る**  
正確なログの抽出が難儀そうなので　第2候補とします。  

- **申し送り時にデータを詳細に見比べて取りこぼさないように気をつける**
論外なので外します。  

- **そもそも何か更新されている前提でモデルを受け取る。**  
最低限の保険としておきます。  

- **モデルの更新内容確認リストを作成して、手動で毎回確認する。**    
リスト自体の作成はしておいて損はないので　第1候補と一緒にやっておくことにします。  

:::note
最低限の保険
これが割と重要です。
- 効果は薄いが、確実に成果を出せる。  
- 確実に成果は出るが、あまりスマートではない。  
- 効果は出るが、実装はかなり面倒くさく泥臭い。  

と、あまりいい案には見えませんが、
保険となる案を1つでも用意できると、全滅が防げるので確実に成果を上げられます。
なによりも保険があると気が楽になります。
:::


# 解決案実証

**更新前のデータと比較するシステムを作る**
第1候補のこの内容で試作します。
で、いきなりスクリプトを書き始めない、まだ書かない。
まずは文字でフローを作成します。

## スタートとゴールの設定
スタートとゴールを定義します。
+ 新ファイルと旧ファイルを指定する  
+ なんやかんや
+ 比較結果をファイルに書き出す  

## 処理の追加 
処理を並べる時は、スタートからゴールへではなく
ゴールからスタートへ向けて作成していった方がやり易い場合もあります。
- CをやるためにはBが必要
- Bを用意するためにはAが必要  

という具合に、目的を実現するために必要なものを逆算していきます

+ **新ファイルと旧ファイルを指定する**
+ 新・旧をリファレンスする
+ それぞれのメッシュ名をすべて取得する
+ 共通のメッシュ名・それ以外をリストする
+ 共通のメッシュ同士で、ポリゴン数を比較する
+ 共通のメッシュ同士で、UVを比較する
+ **比較結果をファイルに書き出す**  

処理を細かく書く必要はなく、1行でかけるレベルで十分です。
やるべき内容をわかりやすく、小難しい日本語とか使わないようにします。
誰が見ても同じ内容を想像できるレベルの日本語を使うことをお勧めします。  

## よくある駄目な例
+ **新ファイルと旧ファイルを指定する**
+ ```ls　-type mesh namespace + ”:*”; ```でオブジェクトをリストする。  
+ リストした内容を```string $newMesh[] / string $oldMesh[] ```にそれぞれ格納する
+ **比較結果をファイルに書き出す**  

コマンドやスクリプトを書き込んだり変数書き込んだり、
この段階で実装っぽい事を始めてしまうとフローの設計がやりづらくなるのでお勧めしません。

処理を簡潔に書くことで、
- 実装すべき処理の数
- 共有できる処理
- 処理個別の実装難易度

などが整理できます。
このフロー図に関しては、あくまで計画表なので実装作業中に随時アップデートしていきます。

##  実装作業
もし実装中にエラーが起きたら？
原因を突き止める為にやることは　原因特定　でのやり方と同じです。

## 結局のところ

規模が異なるだけで、進める方法はすべて同じで対応できるとおもいます。

- 問題・目的定義
- 現状把握
- 原因特定
- 解決案候補作成
- 実証

あとはまぁ

- 常に俯瞰で全体を見てバランスを取り続ける
- 難解な言い回しを避ける
- 頭の中でこねまわさず、目に見える形に起こしてみる
- 言い方や見方を変えることで情報を単純化する
- 常に自分の答えを疑う

この辺を常に頭の隅に置いておきます。

## といいつつも

あくまで進め方の一例なので、
自分にあった思考の進め方を確立できるのが一番ですね。