そろそろFlutter?
どうも、慎重派モバイルアプリエンジニアです。
1年以上ぶりに仕事探しているんですが、Flutter案件すごく増えてますね。
そろそろFlutterか?とも思ってるんですが、観察してると結構たいへんそうで、iOSとAndroidのコストを半分でできるという感じでもなさそうですね。
当然「Flutterの単価は2倍」ともならないので、Flutterエンジニアはかなり枯渇してるイメージがあります。あくまでイメージですが。
高単価を多く取り扱ってるエージェントに聞くと、Flutter案件は「そこそこ増えてきた」そうです。
Wantedlyあたりだとかなりあるので、プロジェクトの状況次第ですね。
私もチャンスが有ればと思ってるんですが、果たしてどうなるか。
スキル持っておいて損はないと思うんですが、なんかRxSwiftと同じ雰囲気になりそうに思えます。つまり引き継ぎが大変なパターン。
いや、RxSwiftと同じ雰囲気なら高単価を見込めるのかも?
なぜ軍隊は未だにピラミッド型組織なのか?アジャイル型組織との比較
Q.なぜ士官学校を卒業した人が上に行くのか、その方が合理的なのか、叩き上げの人間は登用しないのか?
これは組織の大きさと、管理職と実行職の役割がどのくらい異なっているかに依存するかなと思っています。
例えば沢山の人数(例えば1億人)で1つのミッションをすることを想像してみると、
タスクを分解して、命令を出し、実行し、結果を受け取って、評価する
という一連の流れを細分化して構造化していかないと上手く動かないと気づけると思います。1億人総フラットは難しいです。全員が同じタスクをする工場のようなミッションならともかく、複雑なミッションなら一人ひとりにタスクを割り振らなければなりません。
1000万人総フラットも難しいでしょうし、100万人フラットも難しいです。
大きな組織ではそうやってだんだん階層が深くなっていきます。
階層が深くなると、それだけ伝言ゲームが多くなっていくので、伝達ロスが増えていきます。伝言ゲームの回数が増えていって組織が変な動きをしてはいけないので、変な自己判断をせず、命令を忠実に熟すことが求められてきます。
つまり組織が大きくなる≒階層が深くなるほど、命令を忠実に守らせる必要があり、結果上階層と下階層で役割が明確に分かれることになるわけです。
軍隊というのはやや特殊な環境下にあるので、この一般論だけでは語れないと思いますが、軍隊はとにかく大きな組織ですので、それだけピラミッド型組織じゃないと上手く動かないのだと思います。
そしてピラミッド型そしきであるほど管理職と実行職の役割が明確にわかれるので、叩き上げが発生しづらくなるといえるでしょう。
社会におけるピラミッド型組織
よく見かけるのは公務員ですが、IT業界においてはSIerがそれにあたるでしょう。
あれは人集めという観点もあるので厳密に上記の理由ではないと思いますが、1万人月近い工数を捌くような規模を考えるとやはりピラミッド型組織にならざるを得ないのだと思います。
ボーダーラインがどこにあるのか、私なりに観察してみると約1000人を超えたあたりからピラミッド型組織以外が厳しくなる印象です。
ピラミッド型組織の弱点
- 動きが遅い
- 上ばかり得をするため不満が起こる
- 指揮官が無能だったり死ぬと瓦解する
現代の多くの会社がピラミッド型組織から少しずつ脱却しつつあるのはこういうったデメリットにより競争力が落ちるからだと思います。
ただし規模が大きい会社ではやはり未だにピラミッド型組織になっているでしょう。そうでないとしたら、ミッションごとに組織を分けるなど工夫しているのだと思います。
ゲリラ的組織
よくピラミッド型組織の比較対象に上がるのがゲリラ的組織だと思います。
ゲリラ的組織はピラミッド型の「動きが遅い」「指揮官が無能だったり死ぬと瓦解する」を解決するために小さい集団が各々同じミッションを目指すような形です。
会社ではあまり見かけることがないかもしれませんが、例えば1つの新技術に対して上場を目指すベンチャーが100社立ち上がったりした場合、それはゲリラ的組織に見えると思います。
フラット組織・アジャイル型組織
近年IT業界でよく見かけるのがフラット型だったりアジャイル型組織です。
これはピラミッド型組織の「動きが遅い」「上ばかり得をするため不満が起こる」を解決します。
そのお陰でベンチャー企業が大企業より良いサービスを作ったりするのですが、ただやはり限界はあると感じています。約300人くらいからこの形態を愚直に反映するのは難しくなると思います。
逆に300人以下の規模では実行職と管理職の仕事の差異が小さいこともあり、ポストを十分用意することが難しいケースもあるのでフラット・アジャイル型組織の方が向いているような気がします。
そう考えると、大企業か中小企業かで学ぶべきことも様変わりするでしょうから、キャリアパスを考える際は注意が必要ですね。
MVVMやCleanArchitectureやDDDを採用しない理由
- 書き方が曖昧で合意が取れてないから
- 難しい割にメリットが薄いから
- 外部知識を入れるデメリットが大きいから
- 可読性が落ちるから
- 書けないiOSエンジニアが多く、学習コストも大きいから
- プロジェクトの進みが遅くなるから
- リードするチームが場当たり的チームだから
私のスタンスは、例えばCOBOLかJavaかというシーンで、市場にCOBOLエンジニアが多いならCOBOLを採用するし、時代がJavaに切り替わってるならJavaを採用するみたいな感じです。
Swiftなんかはバージョン4.1あたりでObjective-Cから完全移行しました。2.3では早かったですね(2.3から触ってました)
以下詳細。
書き方が曖昧で合意が取れていない問題
「◯◯は良いものだ」
「◯◯は難しくてよくわからない」
この2つの意見が並んでいる時、私は非常に警戒します。
現代のソフトウェア開発はチーム戦ですから、書き方にある程度の合意が取れているか、他人が書いたコードの意図を読み取れなければなりません。
なのでこのような難しく曖昧な方法を採用する際にはチーム内で合意が取れていなければなりませんが、それができるチームとできないチームがあります。
できないチームでは採用するべきではありません。
難しい割にメリットが薄いから
これは経験則なのですが、未採用プロジェクトと採用プロジェクトのどちらでより大変なことになっているか比較した場合、採用したプロジェクトのほうがより多くの問題を抱えていることが多いです。
一体なんの問題がまずあって採用したのかいつも不明です。
一つあるのは自動テスト可能化ですが、自動テストがプラスに働いているプロジェクトがまずわずかです。多くのプロジェクトでは不要な自動テストをたくさん書いています。
敢えて指摘しませんけど。
外部知識を入れるデメリットが大きいから
例えばライブラリーを導入する場合にはライブラリーについて勉強が必要です。
新しい概念を用いるときにはそれについて多くの勉強が必要になります。例えばそのデザインパターンがWeb由来のものであれば、Webにおいて発生した諸問題という前提について理解しておく必要があります。
それらをプロジェクトメンバーに強いるというのは非常に重いし現実的ではないプロジェクトのほうが多いのです。
可読性が落ちるから
よくFatなControllerを避けて可読性をあげるみたいな話がありますが、登場するclassなどのコンポーネントは何倍にも増え、コードの総量は明らかに増えます。
増えた結果、依存関係が曖昧になり、スコープが曖昧になるのでどこまでコードを読めばいいかが非常に難しくなります。
書けないiOSエンジニアが多く、学習コストも大きいから
自慢じゃないですが、ここ5年で10案件以上やってきましたし、面接は100件以上やってます。面接官も20件以上していますし、接してきたiOSエンジニアは結構多いと思っています。
その上で、書けるエンジニアは半分以下だし、ちゃんと書けるエンジニアは2割くらいなんじゃないかと思います。地頭で言えば大学偏差値65以上くらい。
「じゃあうちはお金があるからその優秀な2割だけ雇うよ」みたいな会社もあるんですが、エンジニアの絶対数が少ないのでそれが成立していません。また、やはり熟練者だけで見ても書き方の合意が取れていません。
プロジェクトの進みが遅くなるから
エンジニアという生き物は不思議なことに品質やコードの設計は意識するのに開発スピードには無頓着です。これは長引いた方がエンジニア的には儲かるという昨今のビジネス上の構造問題だと思うのですが、デザインパターンを導入したことによって10年以上のベテランがよってたかって改修しても全然進まないみたいなプロジェクトが散見されます。
敢えて指摘しませんけど。
そういうプロジェクトでは大抵デザインパターンを導入したエンジニアは既に退職していて、かつ今のデザインパターンをやめましょうという人間は一人も出ません。
リードするチームが場当たり的チームだから
特にフリーランスが中心のチームでは、誰がコードを触るかがわかりません。
業界内では未だに「新規開発は優秀なチームでやり、保守はもっと安い人材にやらせる」という風潮があります。(これは現代のモバイル開発では明らかに間違いです。継続開発のほうが難易度が高い)
そのため新規開発の時の優秀なリーダーが最新の難しい設計を試して挙げ句居なくなるというケースが起きます。彼にとっては良いでしょうがプロジェクトにとっては最悪でしょう。
ベンチャーなどでは、1人の社員リーダーだけはそのプロジェクトの面倒を見切るというケースも多く見られますが、その場合でも難しいデザインパターンを採用してしまってエンジニアが見つからずプロジェクトが遅延したり、高い報酬を支払うみたいなケースをよく見ます(そんなプロジェクトの話ばかり来る)
もちろん潤沢な資金と優秀な開発メンバーを社員で抱えているような企業では自由にデザインパターンを選択すればいいと思いますが、ほとんどの人はそうではないはずです。(そのような会社の人がフリーになって上記のような流れができるんですけどね)
その他、採用してないやつ
RxSwfit
async/await
SwiftUI
私としては早く採用できる段階に来てほしいんですけどね。
すなわち、エンジニア市場的にできる人が半分以上で、書き方の合意がある程度取れている状態です。
「秘伝の方法」みたいな一部の人しか理解できないものは要らないのです。
難しいなと感じた時点でアウトです。
じゃあどのような書き方をするのか
デザインパターンのような総論じゃなくて各論でいいと思います。
実際私が長年「こんな書き方がよさそうだなー」と思って書いてるのはCleanArchitectureに似ています。でも100%CleanArchitectureではありません。新しい概念を用いず、小さいスコープでどうするべきか議論していく、でいいと思います。
総論でなければ書き方の強制にはなりませんから、とりあえずスピードは落ちないでしょう?
個人的に思うMVVMの問題点
正直詳しくないんですが、まずMVVMってデータバインディングありきじゃないですか、その時点でRxSwift導入必須みたいな話になるんですよ。重い。
Androidでは採用されていますが、Androidはデータバインディングが標準装備なので前提が違います。
しかもAndroidのMVVMはMVVMじゃないとか言い出す人も居るので内ゲバもあるんですよ、怖い。
あと元々Windows Presentation Foundationでできた概念なのに、私がそのWPFについて詳しくないから、どういう問題があってMVVMが誕生したのかの文脈が追えないというのもあります。
の割に設計方法が明確というわけでもなく。
じゃあ皆何のために導入してるのか探ってみると、どうやらテスト可能化のためっぽいんですけど、自動テストをしたいっていうよりTDDをしたいっていうタイプらしいんですよね。そして私はTDD懐疑派なので、じゃあ採用する理由無いじゃんというわけです。
個人的に思うRxSwiftの問題点
あれは結局「書き方を変える」とう話なんだと思います。
「それ、C#でも書けるよ」みたいな話です。
個人的に思うCleanArchitectureの問題点
一番問題なのは、提唱者の本のレビューに結構否定意見が多いことです。
この時点で書き方のコンセンサス取れるわけないじゃないですか。
他のデザインパターンよりもふわっとしてますしね。
私は最初は思想だと思ったので良いなと思ったんですが、気づけはお作法みたいに捉えてる人が多かったのでなんか違うなとなりました。
結論
Apple様の言うとおりにする。
CombineはRxSwiftと同質なんですけど、SwiftUIを使うなら必須らしいのでいずれ皆やることになるでしょう。なるんですかね?
なぜ10年以上エンジニアをやった私が「分からないことだらけ」なのか?
アプリなんてちょっとしたものなら初学者でもリリースしてるし、15人月規模のアプリでも2年目の新人3人でリリースすることができました。
でも10年以上iOSエンジニアをやってる私でも「分からないことだらけ」と思うことが多いです。これはどういうことなんでしょうか?という話。このロジックは若手のうちには気づきにくいんです。
大きく3つあります。
1.書き方がたくさんあって、プロジェクトによって書き方が違うから
特にフリーランスになったりするとこれにぶち当たります。1つの機能を作るのにも、やりかたが何通りかありますよね。あれのうち1つだけあればとりあえず動かせるのですが、メンテナンスしようとすると他人のコードを読まなければなりません。他人はいろんな方法のコードを書くので、全部読める必要があります。
機能だけではなく設計方針もそうです。たくさんの思想があるため、それを引き継ぐには設計方法をたくさん知り、そのコードから思想を読み取る必要があります。
この点だけでも「10年あっても足りない」くらいです。
2.書き方がどんどん変わっていく上に、昔のコードも残っているから
初学者は、今ならiOS14,iOS15、Swift5の書き方を覚えればいいかもしれません。しかしいろんなプロジェクトではiOS7の時から使用しているコードが合ったり、Objective-Cがあったりと、地層のようなコードになっていることがあります。
成功しているプロジェクトほど昔からやっているのでその傾向が強いです。
それらを読めるためには、{1の複数の書き方}×{時代ごとの仕様}分の知識が必要になります。
3.頭良い人が難しいコードを書くから
難解な設計、難解な主張、コメントのないコードによって、素人目(?)に見たらスパゲティコードにしか見えないものを頭いい人は生成します。
それを理解するにはやはり10年でも足りないです。
あとは自分の得意な分野以外の知識が必要になるケースもあったりしますし、それらも上記1〜3が発生していることがあるので、分からないことは雪だるま式に増えていくわけです。
たぶん30年かけても無理でしょうから、全てを理解しようとするのはどこかで諦めなければならないでしょう。しかし界隈的には「そういうのを勉強していくべき」という風潮もあるので、バランスを上手く取らないと挟まれて苦しくなってしまうので気をつけたいところです。
プロジェクトの難易度を上げすぎると窒息死する話(エンジニア採用)
最近何社からか「良い人材がいない」とか「みんなすぐ辞めてしまう」みたいな相談を受けたのですが、「そりゃこんな難易度のプロジェクトできる人材なんてそうそう居ないよ」みたいなのばっかだったのでそう言う話をします。
モバイルアプリの人材を5段階で考えてみる
以下のように5段階で考えてみます。
私はiOSばっかりやってるのでiOSです。Androidも似たりよったりだと思いますが。
Aランク 頭がいい上に10年前後の経験がある
Bランク Aよりは劣るがベテランの域である、リーダー経験もある
Cランク フリーランスとしてでもやっていけるレベル、有名企業の若手とか
Dランク 慣れてきたかなーというくらいのレベル
Eランク 初級者
私はBランクです。たぶん一生Aにはなれない。
地方旧帝大卒くらいの頭だとB止まりな気がしてます。才能如何もありますけど。周りでも似た感じなので。
金を積んでも見つからないのがAランク
AまたはBでいいなら頑張れば見つかります。ただし金は積む必要があります。
Aランクは大抵どっかの重要ポジションに居るので中々出てきません。
Cランクは結構居ます。フリーランスで適当に月80万くらいで雇えばCかDランクが来ます。
A,Bランクは人数が限られる
育つのに時間がかかりますし、重要なポジションには既にA,Bの人がついていたりするので、Cが今後A,Bになるには数年の時間がかかります。
とにかく2022年時点でもA,Bが不足しています。
あと、A,Bランクにいるような地頭のいい人は他の技術に移動することも多いので、常にこの層は不足します。下手するとその技術においてA,Bの人材が居ないということもありえます。
例えばiOS(swift)から10年選手が出ていくことはあっても戻ってくることって稀じゃないですか?
プロジェクトが安定するのは「C以上で運用可能な難易度」
Cくらいならすっと育つんです。これは体感ですが。
DでもOKになるとより安定しますが、今度はやりがいが薄めになるのでエンジニアは不満かもしれません。
A,Bは、A,Bにしか理解できない難易度のプロジェクトを作ってしまいがち
コードの難易度がどんどん上がって、Cお断りやBお断りのプロジェクトが作られてしまいます。
そうするとまあ詰みはしませんがスケールはしません。
そんなに難易度を上げる必要があるかというのはやや疑問です。研究職というわけでもないので。ただ職人気質な人は得てしてそういう局所最適な動きをする生き物なので諦めましょう。事業最適な行動を取るような人はやはりB止まりなんだと思います。戦闘狂じゃないと。
難易度Aのプロジェクトを作らないようにしよう
とはいいますが、Aの人に任せればどうやってもAになります。
それで人事部が頭を抱えてしまうみたいな会社をいくつもも見たことがあります。
というかBランクになると難易度Aのプロジェクトに誘われることが多いので、最近はそういうのばっかりです。
Bランクの人ですら読み解くのに時間がかかるコードが生成されてしまう感じです。
Aの人に期待するのは難しいので、プロジェクトマネージャー観点でどうするべきか考えるとすると、Aの人を投入するタイミングの調整だと思います。
大体上場前後がベターかなと思っています。その際にプロジェクトにDの人材を入れましょう。Cではだめです。Dが理解できるレベルで設計するとうまくいくと思います。
一度上がった難易度を落とすのは不可能です。
まあ私はフリーランスなのでどっちでもいいいですけど。
どうあがいても難易度Aのプロジェクトに行くことになるので・・・
エンジニアは難易度Aの案件に気をつけましょう
気をつけると言うか、付き合い方を考えないと病むと思います。
でも正社員で入ったらどうすればいいんでしょうね?わかりませんね。
そうそう、最近気づいたんですが
Aの人は複数の会社で関わってたりするからAの人が居ない会社で難易度Aを錬成してることもあります。天才だけど人災。
連番のボタン名がなぜ良くないかを言語化する
これ
元:
https://twitter.com/ohbashunsuke/status/1495900842389610498
何か凄い燃えそうだし斧投げすぎるの良くないかなと思ったんですが、テーマとして面白そうだったのでブログ書きます。
とりあえずコメントを見るに「どうやら皆良くないと思っているらしい」というのはわかるんですが、「なぜ良くないか」を言語化しようとすると難しいですよね。
案外きちんと反論できない人も多いのでは?
問題・テーマの一般化
問題の一般化からちょっと手こずるんですが。トライしてみます。
仕様変更に強い命名は大事だ。ボタンを「OKボタン」や「Noボタン」と名付けていたらヤバいかも。ゲーム開発に仕様変更はつきもの。開発中盤「OKボタンの色を使ってキャンセルボタンを作りたい」というケースもある。結論、用途ではなく機械的な名前をオススメ。後の参画メンバーの混乱は避けるべき。
「OKボタン」などの用途名はやめよう、「ボタン1」とかにしよう。という話です。
動機は仕様変更であり、「後で変わるかもしれないから」です。
あと、おそらくこれは共有パーツの話だと思います。
流石に特定画面内の1パーツを連番にしようという話ではないと思うんです。合ってるかな・・・?
なのでテーマとしては
テーマ:共通クラス名は、ある初期仕様における用途名で作るべきであなく、連番のような機械的な名前にするべき。は正しいか?
で合ってると思います。
具体的に課題に感じているのは
例えば「OKButton」と名付けたのに後々別の用途でも使う事になった。
名前変更がコストかつリスクである。
だと思います。
ちなみに前提として「最近のゲーム開発である」があります。
たぶん誤解されているテーマ
誤解というか、似た別の例として捉えている方が多い印象です。
・特定画面のパーツの名前を用途名にするか、機械的にするか?
・OK/Cancelを混同していいかという問題
これは汎用性の話
エンジニアという生き物は少ないルールで多くのことを表現したがります。
昨今の仕様が動くことを前提にした開発においては、たしかに汎用的に作った方が楽なように思えます。
さもないと、代わりに例外が増えます。例外が増加すると状態数が増えて訳がわからなくなります。
ボタンを汎用的に作りたいという要求→機械的な名前
例えば序盤の仕様では緑のOKボタンがあったとします。
それをOKButtonとしたら、次の仕様では「次へボタン」も同じ緑のボタンでした。
そこでOKButtonをPositiveButtonとリネームしました。
すると次の使用では「戻るボタン」も緑でした。
そこでPositiveButtonをGreenButtonとリネームしました。
すると「戻るボタン」は特定条件でオレンジに変化することがわかりました。
というようなことがあって、「じゃあ最初からButton_1でいいじゃん」という主張担ったんだと思います。
こういうの、皆さんはどうしていますか?
Button_1の致命的な問題
何のボタンかがわかりません。
これは本当に致命的です。
こうなると、いつどのボタンがButton_1になるのか、Button_1の正しい仕様は何で、正しくない動きは何かなどが分からなくなっていきます。
凝集度とかそういうレベルじゃなく、スパゲティコード(神クラス)になっていきます。
後任者はButton_1を「どのように使われているか」でしか判断できなくなります。
(きちんとした外部ドキュメントがあれば別ですけど、まあ大体ないですよね)
※神クラスの厳密な定義からすると私の意図しているものとちょっとずれるかもしれません。支配的なクラスと言うより、何でも詰め込まれたFatなクラスというイメージで使っています。
どのように使われているかしか判断できない可読性最悪なクソClassが神クラスになる
これって何か名前ついてないんですかね?
私は過去十数年でこういうClassに何度も何度も何度も何度も出会ってきました。こいつに出会うと数日、下手したら数週間苦しみます。
今回の例では「青いボタン」のような共通した見た目のデザインがあるからいいですが、そうではない場合は本当にわかりません。
例えば、OKボタン、進むボタン、戻るボタン、で使用されていたButton_1があったとして、「同意するボタン」にはButton_1を適用するべきでしょうか?例えば、「同意するボタン」にButton_1を適用する場合、Button_1を少しカスタマイズしなければならないとしたらどうでしょうか?Button_1をカスタマイズしますか?ほら、神クラスの誕生です。
汎用的な名前をつけるとFatな神クラスができる
例えばiOSの界隈では数年前に「BaseViewController作るのやめよう」って流れあったんですが、あれです。
全ViewControllerがBaseViewControllerを継承しているという神クラス状態なのがまずいのと、あとは「Base」という汎用的な名前が危険というのが一点。
もっと端的に言うなら「単一責任の原則の逸脱を誘発する」からダメだと思います。
抽象度を上げると可読性が下がる
そもそもなんですけど、プログラミング全般において汎用性を上げるということは抽象度を上げるということであり、結果的に可読性は下がります。汎用性というのは色んなパターンに対応するということであり、読み手はそのクラスが取りうる全空間を理解しなければきちんと使いこなしたり改修することができません。
どういうわけか、最近周囲では抽象度を上げることに躍起になっており、可読性がかなり犠牲になっているんですが何故なんでしょうか?
すいません脇道でした。
機械的な名前というのは「抽象度を最大限取った」ということですよね。可読性は死にます。後任者はこちらの方が混乱すると思います。というか地獄。
結論
テーマ:共通クラス名は、ある初期仕様における用途名で作るべきであなく、連番のような機械的な名前にするべき。は正しいか?
正しくない。
・スパゲティコード化(神クラス化)を誘発するからよくない
・可読性がゼロだからよくない
対策
結論では具体的な課題は解決されていません。
例えば「OKButton」と名付けたのに後々別の用途でも使う事になった。
名前変更がコストかつリスクである。
これについて、ブコメでは命名の工夫などが挙げられました。
私も概ね賛成というか、ハードウェアレベルのコストでないのであれば随時名前変更した方が良いと思います。また、積極的に「似た異なるクラス」を作ってもいいと思います。1個で全てまかなおうとしないでください。
それ以前に、Mixinの仕組みが備わっているのであればClassを作成せずそれを活用するのが良いと思います。iOSで言えばextensionやprotocolです。
Mixin - Wikipedia
Swiftのprotocol extensionでmixin的なものを実現する - Qiita
それでも連番のような抽象的な名前が発生するケース
門外漢ですが。
例えばそもそも汎用的なハードウェアであれば、ボタン1、ボタン2、ボタン3、のような命名は致し方ないシーンがあると思います。
あとは公開APIのパラメータやデータベースのような、後で命名変更するコストが甚大なケースはしょうがないのかもしれません。
ただその場合もできるだけ具体名にすることを諦めるべきではないと思いますし、そもそもアジャイルな開発手法は向いていないと思います。
今回は「最近のゲーム開発」という文脈ですので、おそらく仕様変更に対応しやすい仕組みが導入されているのではないかと思いました。知らんけど。
おわりに
でも少し昔は普通にそういう実装多かったし今でもありますよね。
たぶん今回はみんなのトラウマを呼び起こしたんだと思います。
もうコードリーディングしたくない・・・