kbigwheelのプログラミング・ソフトウェア技術系ブログ

プログラミング・ソフトウェア技術系のことを書きます

「GraphQLは90%のウェブサービス開発者にはまだ時期尚早ではないか」に対する僕のアンサー

数ヶ月前にAWS AppSyncを使ってGraphQL APIを実装していました。 実装を進めるうえでGraphQLの詳細についていろいろ疑問や疑念が浮かんだのでいろいろ調べていました。

その中でQiitaに書かれた以下の記事が非常によかったのでそこで挙げられた疑念や欠点の指摘について2019/04時点でわかる範囲でアンサーしようと思います(主に僕の思考の整理のために 😋)。

GraphQLは90%のウェブサービス開発者にはまだ時期尚早ではないか - Qiita

免責

先に断っておくと、この記事は元記事の批判ではありません。 言及先の記事は2017/07時点での周辺ライブラリの状況や不完全な情報提供を踏まえると非常に良い記事で優れた洞察を示しています。 本記事ではそこから2年経った今の状況の反映しつつ、GraphQL APIを実装する上で僕が持った知見・意見を書きます。

元文への言及と僕の意見

LSUDsとSSKDs

一方、社内マイクロサービスにアクセスする時にはまずデータ量を減らすことに対するインセンティブが減ります。つまりGraphQLのメリットは弱まります。また、使う対象もある程度は把握できるので、最初からそこまで大量の使うかどうかも分からないデータをレスポンスに乗せない、ということもできます。

完全に同意できます。ただ、ある程度使う対象がわかっているとはいえそれらのマイクロサービスを使った新しいサービスを作るときはGraphQLで最初から書いていたほうが余計な手間が少なくて済みます。

最初からそこまで大量の使うかどうかも分からないデータをレスポンスに乗せない、ということもできます。

これをやってしまうと将来作れるサービスの可能性を狭めてしまうかもしれないわけですね。

当然ながらGraphQLでAPIを実装することはSSKDs向けの固定的なREST APIと比べてコストがかかるためROI次第ですが、僕はマイクロサービスの利点は複数の社内マイクロサービスを組み合わせて今までなかったソリューション・サービスが低コストで作れること、新アイデアの低リスク化だと思っているのでSSKDs向けのAPIでもGraphQLでそれらの未来に投資することは結構ありだと思っています。

なお、RESTに対して「サイズが小さくできる」というのが圧倒的な強みみたいに言われますが、RESTだって同じことをやっちゃいけない、ということはありません。GoogleAPIはfieldsというパラメータを付けることで結果に含まれるレスポンスのカラムを絞る機能を提供しています。

いわゆるfieldsパラメータですね。多くのREST APIでサポートされています。(これはかなり複雑な方ですがelasticsearchの例)

これも書かれている通りだと思います。それを踏まえてRESTに対するGraphQLのメリットを挙げると、APIごとにフォーマット・実装が違うfieldsパラメータを仕様化したことと概ね1階層のfieldsしか指定できないfieldsパラメータが多い中でJSONのネストされた階層構造でもfieldsをわかりやすく統制された方法で指定できるようにしたことだと思います1。 そのメリットがGraphQLを導入することによる複雑性の増加のデメリットと比較して割に合うかはまた別の問題ですが・・・。

他の某所のチャットで話題になったところによると、バッチでまとめてもってくるのもメリットとしてあげられるけど、SSKDsならBFF: Backend for Frontend使えばいいよね、という話もありました。また、ウェブブラウザからリクエストを送信するときにも、multipart formを使うバッチリクエストをGoogleは提供していたりします。Microsoftガイドラインでも見かけた気がしたけどソースがみあたりませんでした。

これに関してもRESTでも同じことできるよねはその通りだと思います。 RESTに対してGraphQLを使うメリットを挙げるとそのバルクリクエストの方式が公開された仕様として定まっていること、つまり実装しやすく知識の使い回しができるので利用もしやすい、という点が1つあります。

もう1つのメリットがリクエスト-レスポンスレイテンシーの低減です。 これはBFFにはできません。

こちらの例を用いて説明します。

REST APIのデメリットとしてこのページでは複数の親子関係のあるリソースの例が用いられています。 BFFを使った場合、クライアントのブラウザないしネイティブアプリからのリクエストは1つで済みますが、BFFがこの3種類のリソースへのリクエストを肩代わりすることになります。

この際REST APIがhttpベースのAPIでありネットワーク的な距離を考えるとどうしても1リクエストに付き最低でも数msのレイテンシーが発生します。 これはhttp/2のようなHTTPリクエストを束ねることができる技術でも解消できません。 なぜなら2度目、3度目のクエリでどのidのリソースを取得するかは1度目のリクエストの結果をparseしないとわからないからです。 GraphQLはそのIDをlookupしていく過程をサーバサイドで肩代わりしてくれるわけですね2

そのためネットワークレイテンシが大きいケース、親子関係が長いケースほどGraphQLを使えば行って帰っての回数を減らすことができます。結果的に描画の高速化につながるでしょう。

クラサバ時代に戻るデメリットとメリット

ではサーバー側は、というとSQLのエンジン相当を各サーバーの実装者が書かないといけない、ということです。パーサーはあるでしょう(少なくともNode.jsには)。クエリーを見てストレージエンジンにアクセスして結果を整形して返すところは実装が必要です。

これに関しては僕も結構大変そうだなーと感じていたのですが、Resolverというデファクトスタンダード的な仕組みがあります。 これが結構便利で例えばAppSyncだとDynamoDBのResolverはこんな感じになります。

{
    "version": "2017-02-28",
    "operation": "Query",
    "index": "todoid-index",
    "query": {
        "expression": "todoid = :todoid",
        "expressionValues": {
            ":todoid": {
                "S": "$context.source.id"
            }
        }
    }
}

DynamoDBのクエリ文法がxxxxなので一見長いように見えますが、これSQLで言うとSELECT * from Todo where todoid = ?に過ぎません。 fieldのフィルタリングなどは自動的にやってくれます3

詳細に寄って、個別のfieldごとにResolverを書くこともできます。上の方のREST APIの例で言うとフォロワー全員の名前を文字列の配列として返す場合などをイメージしてください。トップレベルのリソースのデータを取ってくるクエリとそのフォロワー名を取ってくるクエリを別々のResolverにできます4

DBへのクエリの効率化のため、JOINを使ったクエリを一度だけ発行してそれをpackingする場合はこんなに簡単には行きませんが、このResolverという考え方・仕組みはうまく複雑性の増加を緩和してGraphQL APIの実装を理解しやすく取り回しやすいものにしていると思います。

GraphQLが圧倒的な勝者になる条件が1つあります。それはGraphQLをネイティブで実装したミドルウェアやデータベースエンジンが登場し、サーバーコードを実装しなくてもGraphQLが簡単に扱えるようになることです。SQLを使うRDBのGraphQL版です。

2019/04現在、ほぼほぼそれに当たるものが登場しつつあります。 AppSyncはDynamoDBやMySQL(Aurora Serverless)に対して簡単かつ権限管理機能もついたGraphQLアクセッサとして機能していますし、今日名前を初めて知ったんですがArrangoDBというものもネイティブでGraphQLをサポートしているようです

データベースをインターネットに晒す格好にはなりますが・・・

前述のAppSyncなどではユーザー認証とアクセスできるデータを組み合わせてそこそこ細かく制御できるので(いわゆる認可機能)、サーバレスでDBエンドポイントを公開することもありになってきたんではないでしょうか5

まとめ

作っているサーバーのユーザーはSSKDsでしょうか?それなら今は使う必要はないと思います。利用しているウェブサービスにアクセスするためのクライアントとしての利用だけで我慢しておくほうがいいんじゃないでしょうか?あるいは簡単に使えるミドルウェアやストレージエンジンが出てくるまで待つほうがいいでしょう。

前述の通りすでに対応するストレージエンジンやDBラッパー、GraphQLのBFFサービスなどが出てきています。 Scalaでもsangriaライブラリはすでに十分なスターを集めていますし、2019/04現在十分に成熟しつつあると言っていいんじゃないでしょうか。

僕の周りではGraphQLを擁護する声は無かったけど、課題は「サーバー開発工数(複雑さがここに集中してメンテナンスとか大変かも?というのも含めて)」の一点なので、ここを論破すれば状況は変わりますので、反論エントリーお待ちしています!

ここは上でも書きましたが一からAPIサーバを実装する場合は比較的辛いままだと思います。 AppSyncのようにマネージドサービスにGraphQLの皮をかぶせたり組み合わせ可能にしたりするサービスが使えれば非常に楽かと。あとDBにGraphQLエンドポイントがある場合も使いやすいでしょうね(その場合は独自で認証・認可の仕組みが必要そうですが)。

ここから蛇足: 1週間GraphQLを調べつつ実装した感想

僕のGraphQLに対する感情はガートナー ハイプサイクルをたどって今ちょうど幻滅期を抜けたあたりです。 実際に実装せず上辺だけ調べていた時期はREST APIであやふやなあれこれの仕様(ページングやエラーハンドリング)なども合わせて定めてくれるのかと思っていましたが実際に触ってみるとfieldの絞り込みと引数、あと型定義以外はほとんど何も定められておらず結構がっかりしました。 そこを超えて単なるクエリのためのDSLとして捉えるとそこまで悪いものでもないかなと今は思っている感じです。

今後の社内マイクロサービスでGraphQLをどの程度使いたいかというとまだ微妙な温度感で、多数のリソースの種類があってしかもそれに親子関係があり、フロントなどから一度のクエリでjoinして取ってきたいという要望がある場合はGraphQLを使ってもいいと思います。 リソースの種類が少なく相互関係性が希薄なAPIなら6REST APIやgrpcのようなgraphQL以外の選択肢も十分ありです。

たまにGraphQLはネクストRESTだ、REST APIはオワコンになる的な論調で記事を書いているのを見かけますがそうは思えません。ステータスコードなどに与えるエラーの仕様がない、相変わらずhttpヘッダはGraphQLの場合も使う必要があるなどRESTのほうが優れていると感じる点も多いです7

まとめると、GraphQLを使うときはサーバサイドでJOINできる、ネストされて構造化されたデータのfield絞り込みができるという機能を有効活用できるときにしましょう。 そのときもGraphQLをあくまでクエリのためのDSLだと捉えればREST APIからスムーズに移行したりうまく既存のREST APIと協調することができるでしょう。


  1. 実際GraphQLの仕様の中核はこれだと思います。AliasやVariableなんかは別になくてもなんとでもなるので。むしろあれいるのでしょうか・・・

  2. 元記事ではそれも踏まえてクラサバとあとで批判されているわけですが

  3. まだ利用していませんがscalaのgraphqlライブラリsangriaも同様の仕組みのはず

  4. まあ今話しているようなtype定義は実は良くないんですけどね。普通に小fieldとしてfollowerオブジェクト自体を持って、そのfolloerのnameフィールドを定義してやったほうがいいです

  5. 余談ですがこの辺Firestore, realtime databaseのようなfirebase系DBの影響が見えるような気がします

  6. そもそもAPIサービスで相互関係が希薄な複数のAPIを提供すること自体がほぼほぼありえないといえばありえませんが

  7. たぶん実際にGraphQLのAPIを実装した・使ったことがないかGraphQLの未来に過剰な妄想を書いているか、アオリ記事書いてPV稼ぐのが目的の人間が書いているのでしょう

JavaScriptのAsync/Awaitにかかえていた違和感

JavaScriptのAsync/Awaitの仕様を数年前に見たときからなにか違和感を感じていたのだが、以下の記事で改めて全体を見通した時にその違和感の元に気づいた。

【初心者向け】JavaScriptの非同期処理を理解する callback、Promiseそしてasync/awaitへ - Qiita

Promiseの結果を取得するためにawaitが必要なことは直感的にわかる。 問題はasyncだ。これは単に返り値がPromiseであることを示すマーカーであり、返り値の型を明示する必要がないJavaScriptの思想とはそぐわない気がする。 これは例えばPythonのyieldとよく似ている。yieldは返り値の型をGeneratorにするが、その関数へasyncのような修飾子をつけることはない。

幸いにも疑問点に気づけば回答はネットに転がっていた。

どうやらawaitが予約後でなかったことと、parserの解析が簡単であることからasyncが用いられているようだ。 その理由に納得はしないものの、とりあえずの回答が得られたのはよかった。

正しい意思決定(判断)の価値

disclaimer

以下の文章は私個人の意見であり、特定の企業や人物を揶揄する目的のものではありません。

本文

僕はプログラミングが好きでずっとプログラミングをやっていたせいか、エンジニアで手を動かさない仕事の価値というものが長いことよくわからなかった。 8年ぐらいのエンジニア生活の中で、合理的で効果的な意思決定がなされたシーンを実感してこなかったこともその一因かもしれない1

だからいわゆるアーキテクトや上流過程というものを結構長いこと軽視していたのだけど、以前こんなことがあった。 過去のある時点でAWS上にEC2で動くアプリケーションを作ったのだけど、実はそれに相当するサービスが開発開始当時からAWSに存在した。 そちらを使えば内製するより運用費が安く、4~6人月を投資する必要がなく、保守の手間も全くかからなかったことが発覚したのだ。

言い換えればこのアプリケーションを自分たちで作ると判断した人間は数千万をドブに捨てたわけだ(AWSについての知識がなかったがために)。 だから、(もちろん考え方にもよるが)このときAWSのサービスを知っておりそれを使うという判断が出来たら数千万円を使わずに済んだことになる。

これに気づいたとき、僕はこの意思決定には数千万円分の価値があったと言えるのだろうか?とふと思った。

こんなことがあってから、僕は意思決定についての価値をもう少し考えるようになった。 現在自分が行おうとしている意思決定がどれくらいのコストを生むか(一時的コスト・継続的コスト)、それが将来的にどれくらいの利益を生むか(短期的な利益・長期的な利益)。

そうして考えながら仕事中に意思決定をしていると、この意思決定というものが思っていた以上に危険なことがわかった。もちろん会社がどの分野・どの部署・どのプロダクトに投資するのかといったことは重要な意思決定なのは自明だが、僕のような平のエンジニアでさえ、何気ない判断で会社に長期に渡って数千万、数億の損失を生む意思決定ができてしまう。

ソフトウェアエンジニアの間違った意思決定の多くの場合現金ではなく、将来のエンジニアリングコスト(人・時間)であるため計測しづらい。結果的に多くの会社でそういった損失は計測を行わず振り返りも反省もなされない2。そのため大手IT企業などでも正しい判断基準を持たずランダムウォークするようなアーキテクト・マネージャが散見され、数億や数十億以上のコストを見えずに垂れ流したりあり得たはずのサービスの可能性を潰したりしている。

そう考えると、もし意思決定を適切・慎重に正しく行えるものがいてその人物が継続的に意思決定を行えば会社はたくさんの潜在的損失を回避できることになる。 僕は従来マネージャや管理職・アーキテクトといった立場の人間を軽視していたが、上のような人物がいればその利益は計り知れない。

それこそ業務時間の90%でコードを書いて残り10%で間違った意思決定をしてしまうプレイングマネージャーよりも、業務時間の98%寝ていても残りの2%の時間で正しい意思決定をしてくれる優秀なマネージャーははるかに会社へ貢献していることになる。

だから、僕は相変わらずコーディングが好きなことは変わらないけども、最近は自分の意思決定そのものや自分以外の意思決定する人物・役職のことを見直している。 果たしてその意思決定(者)が本当に正しく、長期的に見て正解だったと言えるかどうかを。


  1. むしろ記憶に残っているのは知識の足りていない人間が間違った方向に意思決定してしまった場面ばかりだ

  2. 余談だが、そのため一部のエンジニアは意識的か無意識的かわからないが間違った意思決定のツケを払う数年後には転職していなくなってしまうようなことが常態化している。ウェブ業界では特に顕著だ

会社の開発用PCをMacBook ProからデスクトップPC(ubuntu)へ切り替えた

tl;dr

  • 会社で使うPCをMBPからデスクトップPC(ubuntu)へ切り替えた
  • dockerがよりシンプル・高速に走るlinuxが今は良い
  • 自宅もubuntuなのでショートカットキーなどを揃えたかった背景も

もう少し長い背景説明

MacBookは素晴らしい。

まずbrewの信頼性が高い。 イケてる開発ツールが多い。WIndows, Linuxでも提供しているツールも多いがSequel ProなどMacでしか提供されていない素晴らしいツールも多い。 なにより利用者が多い & LinuxWindowsのようにディストリビューション/バージョン間の差異が少ないことから多くのノウハウがウェブ上にあり、周りに使っている人間が多いためヘルプも頼みやすい。 見た目もイケてるし、ミッションコントロールワークスペース間の移動などUIも洗練されている1

なぜやめるか。

一つは自宅で使用しているubuntuとショートカットキーやUIが違うことによる操作への最適化限界がきになったからだ。 ubuntuOSXではワークスペースの移動のキーなど多くのOS標準操作方法が違う。 そのためショートカットキーを覚えることが難しく、毎回設定を参照するようなことをしていた。 また、ubuntuではCtrlが使われるケースでMacはMetaキーを使うため、ブラウザ操作などショートカットを多用するシーンにおいて間違ったキーを押すことが多かった。 OSXのUIは明らかにubuntuより優れているため自宅のデスクトップをiMacないしMac Proにすることも考えたが、コストパフォーマンス面でPC/AT互換機と比べて格段に悪くまたMac Proが年単位で放置された過去を鑑みるとアップデートサイクルをこちらで制御しにくい点も欠点となり、自宅でOSXを使うことは断念した。

となると可能なら会社で使うPCをubuntuにしたいところだったのだが、ずっと諦めていた。 というのは以下の点で会社所属のエンジニアにMacBookを渡すことは合理的であるためだ。

  1. 会議室など自席以外でプロジェクタ・大型モニタを使う時にノートブックは有用
  2. MBPなどapple製品はブランドイメージが高くエンジニア受けも比較的良い
  3. エンジニア全体でMBPに統一するとトラブルシュートや(情シスなどによる)サポートが簡単
  4. 開発チームとしてもPCをMacBookに統一すると環境差がなくなり開発しやすい

が、先日MacBookによるコンパイルの重さ・HDDへのアクセスの遅さ・メモリの足りなさに辟易としているときに気がついた。

  1. うちの会社はMac, ubuntu, windowsバラバラ
  2. 退職者の比較的高性能なデスクトップPCが余っている
  3. 会社に私用のMBA持っていっているので会議用はそれで事足りる
  4. ローカル環境での開発にDockerを利用しているため開発環境の差が吸収できている
  5. CPU使用率を見ているとdockerの特にIO部分で負荷が高いが、これはDocker for Maclinux VM内でdockerを動かしているため。linuxで直接dockerを動かすとこの負荷はかなり軽減できる(はず)

以上のような理由でむしろubuntu(linux)を使わない理由がないことに気がついた2

現在ほぼubuntuへの移行が終わった状態だが、メモリやCPUなどが相対的に強化されたこともあり非常に快適に感じている。 特にDocker周りの動作が非常に軽く、レスポンスが早くなった。

MacBook Proからubuntuに移ったデメリット

当初は特にubuntu移行のデメリットはないかと思っていた(UIが劣るのは織り込み済み). が、最近徐々に手を出し始めていたxcodeによるiOSアプリ開発ができないことは少し頭が痛い。 手元のMBAは非力で開発にまったく使えないため、この点に関しては何らかの対策を打つ必要がある。

一般的な新卒ソフトウェア系エンジニアにとってUbuntu(Linux)は第一選択肢になるか

たぶんならない。僕がubuntuを使えるのは所属している会社がスタートアップで各々の裁量が大きいこと、特にソフトウェアエンジニア内でMacBookに揃えようという方針がないこと、ubuntuの経験がそこそこあり他人を頼らなくても自力で大抵の問題は解決できることなどが背景にある。

新卒や大企業のソフトウェアエンジニアの場合、いろんな要因でapple製品に統一したかったりするメリットがある。そもそもMacBookが強い会社は新卒もMacBookを使ってくれたほうが教えやすいし教えてもらいやすい。

ただ、今後長いことソフトウェア技術の核となるdockerがmac上では遅いというのは軽視できないデメリットで、Dockerを効率的に使う視点から長期的には開発PCでもlinuxの利用が増えていく可能性はあると思う3


  1. ubuntuではウィンドウ毎にワークスペースを分けて管理することができない。ショートカットも統一された方針を持たず、キーバインドのコンフリクトがしょっちゅう発生する

  2. 新卒のときにwindows機でのweb開発に苦しみ、MBPでの快適さに感動した経験から視野が狭くなっていたのだと思う

  3. linuxはもう少しUI・UXがなんとかならないとエンジニア間ですら支持が広がらないかもしれないが

@kmizuさんのimplicitlyについての記事を読みながら思い返したこと

この記事を読んでていくつか感じたことと思い出したことをツールドフランス第15日目観戦しながら書き出します。 特にまとまってない。

記事中の黒魔術という表現についての個人的な補足

僕の勘違いでなければ、@kmizuさんは implicitly が静的に(コンパイル時に)一意に決定する、しかもそれがメタプログラミングやマクロ・リフレクションなどのコンパイル処理の外側ではなくコンパイル処理(= ファーストレベルの言語仕様1)として決まる点を指して黒魔術ではない、と行っていると思いました。

ただ、implicitlyを黒魔術的だと認識しているような人にはそこら辺の文脈・ニュアンスが伝わりづらい気がして非常に良い記事だけに少し惜しく感じました。

implicit parameterと型クラスの親子関係

おそらく、 implicit parameterという概念(もしくは、その元ネタである型クラス)

implicit parameterって型クラスから派生した概念でしたっけ?と少し引っかかりました。

implicitは特に型クラスを意識せず実装されたけれど、後々型クラスにも使えることがわかったために型クラスの表現方法としてimplicit + context boundが利用されている、とどこかで読んだような (もしかしたら説明を単純にするためにあえてこう書いているのかも)。

2019/07/26 追記

@kmizuさんにその後詳しく教えていただいたのですが、広く一般には知られていないものの紛れもなくimplicit parameterは型クラスのための機能として作られたとのこと。

詳細はこちら。

implicitlyを理解することの困難さ

元の記事は簡潔にまとまったスクロール3画面分ほどの記事なんですが、僕はここで説明されていることを完全に理解できるようになったのは真剣にScalaを触り続けて3,4年経った後だったと思います。

この記事の中ではimplicitlyに到達するまでの道のりがだいたい以下のように提示されています2

  1. implicitの使い方・作用
  2. context boundの意味
  3. implicitlyの使い方・作用

Haskellなどのバックグラウンドのない、Javaを触ったことのある程度の人間(だいたい10年前の僕)がもうちょっと補足するとこうなります。

題目 僕が理解した時期(Scala使い始めからの年数) 理解にかかる労力
implicitの使い方・作用 1~2年 めっちゃ大変
context boundの意味 3~4年 型クラスを理解していると一瞬。 理解していないと使い方・概念がさっぱりわからない
型クラスの概念 4~6年 大変。数回の挫折をはさみつつ足掛け5年かけてすごいHaskellたのしく学ぼう!独習 Scalaz — 独習 Scalazで理解した
implicitlyの使い方 1 ~ 2年 それ自体は死ぬほど理解が単純。
型クラスとしての使い方に気づいたのは型クラスを理解した後だった

上に書いていますが、僕が元の記事をだいたい理解できるようになったのは型クラスをぼんやり理解し始めた4年目以降でした。

こう書くとお前どんだけ頭悪いんだよと思われるかもしれませんが、実際のところ3つの職場で一緒にScalaを書いた同僚諸氏で確実に僕より早く・より深く上を理解していたのは10人中2,3人程度でした。 勉強への熱意や理解の早さはともかく、実際にScalaを使っている人でもかなりの人がimplicitやcontext boundなどをよくわからず使っている、またはそれらを知らなくても十分Scalaを使えていると思います。

implicit は本当にわかりにくい

改めて考えるとscalaのimplicitは本当にわかりにくいと思います。これはimplicitに多数の側面やシンプルでない仕様があるからだと思います。 以下implicitのわかりにくい点。

  1. 文字通りの暗黙的な関数パラメータという側面
    • sttpのbackendのような、メソッド呼び出しの中で本質的ではないパラメータをメソッド呼び出しへ書かないことでよりメソッドの本質に集中する機能
    • implicitで渡されるパラメータは環境・コンテキストなどのイメージ
    • 多用により可読性の低下を招くと言われていたimplicitはこの用法のイメージ
  2. 型クラスとしての活用の側面
  3. implicitという修飾子がメソッドの外側・内側両方で作用する点3
  4. implicitが探索するスコープのルール
    • 暗黙のパラメータ解決優先順位 | eed3si9nがよくまとまっていますが、継承、import、local宣言、パッケージオブジェクトなど片手に余る様々な方法でimplicitの値は渡すことができます
    • Scala熟練者が多用するにも関わらず初心者が知らない概念の一つに暗黙のスコープ (implicit scope)があります

      2) 探している implicit の型に少しでも関係のある様々なコンパニオンオブジェクトやパッケージオブジェクトから成る暗黙のスコープ (implicit scope) (具体的には、型のパッケージオブジェクト、型そのもののコンパニオンオブジェクト、もしあれば型の型コンストラクタのコンパニオン、もしあれば型の型パラメータのコンパニオン、型の親型や親トレイトのコンパニオンなど)。

結論

何が言いたいか。

1. implicit / context bound / 型クラス / implicitly わからないのは当たり前

それらがすぐにわからないからと言って、自分が頭が悪いと思ったりScalaに絶望しなくていもいいと思います。これらの概念は広範に普及しているプログラミング言語の中でもかなり難しい概念ではないかと。

2. implicit なんて全く使わなくても better java としてそこそこ使える

過去にimplicitもFutureもモナドも使わないScalaによるAPIサーバをScala初心者の人たちと一緒に書きましたが、Future・モナド・implicitを半端な理解で乱用したアプリケーションより10倍良いコードでした このように単なるbetter javaとしてscalaを使うことは全然ありだと思います4

3. implicitly が黒魔術に見えている人はimplicitly以前にimplicitそのものや型クラス、型クラスを実現するためのcontext boundというsyntax sugarという概念がわかっていない

ここで話が最初の記事に戻ってきます。 元々の記事は非常によくまとまっていて内容は正しいのだけど、最低でもScala数年触っているような人じゃないとあれ読んですぐ理解するのは難しいんじゃないかと思いました。

4. 型クラスはちゃんと理解したほうがいい

implicitはScala 3でなくなるそうですが、型クラスの概念は多少変遷しうるもののおそらく今後20年, 30年以上プログラミング技術の中で使用される可能性が高いです。 すごいHaskellから逃げずに(!?)頑張って勉強しておきましょう。それにより得られるリターンは本当に大きいと思いますし、実際大きかったです(プログラミングの表現の幅が広がった)。


  1. これ、もうちょっと適切な言い回しがある気がする

  2. 実際にimplicitlyだけを読み解くならこの全道筋を理解する必要はないけど、記事中で言及されているようなcontext boundのsyntax sugarと組み合わせた用法を理解するにはたぶんすべてを理解する必要があるでしょう

  3. 参考: implicitが内向き外向き両方の意味になってしまっている。

  4. 最もこのようなケースではJavaでいい気もするのでケースバイケース。特にScalaはリクルーティングがしづらくて・・・

ヘビーカロリーな問題の解決方法

この前、久しぶりに非常にヘビーカロリーなコードを書いた。 僕は普段コーディングをしている日はScalaの場合テスト含めて100~300行程度のコードを書いているのだけど、機能まで書いていたコードは5~10日で100コード程度しか書いていなかった。 というのも内容がhttp clientの低レベルな実装とAWS V4 signatureの実装に関するコードで問題がかなり難しかったため。 この問題、そもそも自分で解決できるかどうかギリギリレベルの難易度だったのだが、なんとか解決することはできた。

ここでは後のためにその解決方法を言語化しておく。

1. 何が問題なのかをはっきりさせる

今回の場合、根本的に何が問題なのか、何ができないのか、何をやればいいのかを調べだすのに丸2日分ぐらいの時間がかかった。 資料が少ないためでもあったが、まず問題の原因をはっきりさせることは基本であり絶対。 ここがあやふやなママ試行錯誤しても効率は上がらない。

2. 取りうる手段を列挙・検討する

取れうる手段を検討する。 今回の場合は既存のライブラリを頼ることが難しいことがある程度調べてわかった。 その結果、妥協して定期作業が必要な認証にするかそれともきちんと自分で実装するかの選択肢が出た。 最終的に後者を選んだ。

上長やチームへ説明するためにもトレードオフできる選択肢を出すことは大事。 それで自分がしようと思っていた以外の選択肢が選ばれたり新しい選択肢が出ることもままある。

3. 実装したつもりが動かない。

まず絶対に動く例を作る。例えば今回のケースではpythonのサンプルコードが会った。 まずそれを動くようにして、徐々に動かないコードと近づけていって、どこで動かなくなるかを調べた。

スクラムマスター研修受けてきた

取り急ぎまとめ。

  • 昨日・今日の2日でスクラムマスター研修を受けてきた
  • 目的はスクラムを導入しているがイマイチうまく言っていない現在のチームの改善、人にスクラムを教わることでよりよいプロセスにできるのではないかという期待
  • 基本的に自分のキャリアのためであること、会社を説得することが面倒であること、そもそも会社が出してくれそうにないこと、また取得後数ヶ月で転職するとさすがに申し訳ないこと(今のところ具体的な転職予定はないが、申し訳無さで転職の選択肢が取りづらくなることを嫌って)私費で行った
    • 税込みで計216,000円也
  • 結論から言うと非常に良かった
    • 一番良かったのはたぶん30~50回行われた参加者とガビィ、原田氏とのQ&Aで、スクラムガイドや一般的なスクラム本で語られないところ、語られても深くは掘り下げれらないところを細かく、背景を交えつつ聞けたところ
  • 参加者のやる気も非常に高かった。AWSの公式講習を受けたことがあるが(こちらも1回2~3日、20万円ぐらいかかる)、ずっと参加者のやる気は低かった
    • 実際に体を動かしたりポスターを作るなどよりアクティブなアクションが多かったのがよかった理由の1つ
  • 参加者の背景も多様で面白かった。組み込み系企業のいわゆるテックリードのように、新しい手法・技術を指導する立場にある人、会社の資格取得推奨制度をきっかけに来ている人(AWSの資格コンプリーター!)、技術コンサルをされている社長さんで、コンサル先でスクラムを指導できるように来た人など
    • 女性の参加者は全体の1/6~1/5ぐらいに見えた(6人チームに平均1人いた感じ)。比較的ソフトウェアエンジニアリングの世界より女性比率が多いように感じたが、講師が女性であるため参加しやすかったのかも
    • 年齢層も幅広く20代から40代までいた
  • たくさん勘違いや心得違いも見つかった。ごく単純な誤解から、背景を理解せず字面だけを読んだ結果真意を理解していないケースまで
  • 基本的に引きこもり・出不精なので、1日目はすごく緊張した。同じチームでやった2日目になるとだいぶお互いの人柄の理解が進んで話がしやすくなった
  • 1日目も2日目も無茶苦茶疲れた。頭いっぱいでへとへとになって自宅に返った感じ。自分は参加者の中では比較的長くスクラム(あるいはスクラムのようなもの)をしていたほうで、キーワードだけは比較的知っている方だったのにそれほど負荷が高かったので、よりスクラムに親しんでいない人はもっと大変だったかも

以下取ったメモから順不同で書き出す

  • 絵を沢山書こう
  • リファクタリングはストーリー(タスク消化)の一部。タスクと分離しない。恒常的なリファクタリングの時間をタスク見積もりに含める。恒常的にリファクタリングをする
  • 大規模チームでも編成できる。車のファームウェアのチームなどは数百人単位
  • walking skeleton
  • リモートスクラムを最初からやるのは難しい。合宿あるいはonboardingで最初しばらく一緒に仕事をすると成功しやすい
  • output ではなく outcome(機能数より具体的な成果)
  • chaos reportによると80%の機能はほとんど使われていない
  • チームがこなれてくるとスクラムマスターはお互いのタスクを交換して苦手なタスクをやらせる
    • 一時的にベロシティが下がることを許容する。しかしその後よりチームは強くなる
  • 弁当が美味い
  • スクラムマスターはポストイットが基本、jiraなどのツールを最初から使うとツールに踊らされる
  • スクラムマスターはあくまでコーチ的。開発メンバーに指示をせず、解決策も直接提示しない
  • 不要だと判断された機能はきちんと削除する
  • スクラムは経験主義をバックグラウンドとしている
    • 経験主義については個人の経験に基づいての判断ではないことに注意。ここはもうちょっと読んで理解したほうがよいかも
  • CIは重要。完成の定義をストーリーごとにクリアするにはCIで自動化しないと現実的ではない
    • 一方でCIに関するタスクをそのままPBIにしないこと
  • アーキテクチャの改善やサーバ・環境の用意、ホワイトボード・付箋・部屋・PCの用意などはスクラムで規定されていない。それらはスプリント0として扱うような方式もあるが、原田さんはあまり推奨していない。あくまでスクラム開始前に用意しておくこと。
  • 未完了は再見積もりをしてバックログに戻す(つまり未完了になったタスクのベロシティは行ってしまうと失われることになる)
  • スクラムマスターはドミナントにならないよう、必要であれば会議を意図的に欠席したりincognitoしたりする
  • 特に初心者のスクラムマスターは開発メンバーと兼任するべきではない
    • 最初のX日(1週間だっけ?)はチームを観察する、よく観察する
  • やる気のないメンバー、スクラムに反対するメンバーなどに対する手法は基本的にスクラムは規定しない
    • それらはスクラムの外側で対処するべき問題だが、やる気のないメンバーはスプリントごとのデモで自身を取り戻させることができるかもしれない
    • プロダクトオーナーが協力的でない場合は、開発メンバーはビーチに繰り出す
      • 不要な機能を作ることはむしろ害悪。削除に追加でコストがかかる
      • プロダクトオーナーがPBを持ってくる来る時に備えてビーチに繰り出し英気を養うのが開発チームの最善
    • スクラムの反対するメンバー(デイリースクラムに参加しない、など)はチームから一時的に取り除くなどの対処を取る
  • 上にも関係するが、あくまでスクラムはプロダクトマネージメントのフレームワークであり、開発で発生する問題や意思決定すべてに関する回答リスト・規定ではない
  • プロジェクトマネージメントではなくプロダクトマネージメント
  • トヨタの片山さんいわく、イテレーション(繰り返し)ではなく改善のサイクル
  • スクラムマスターとしてはチームに干渉しすぎない。自分たちで問題を発見させ、答えを聞かれたら5 whyメソッドを使って自身に考えてもらう
  • 見積もりがあんまり大変なので、最初はS, M, L, XLの4つ程度に分ける
    • それぞれSP3, 5, 8, 13に割り当てる うまくいくチームがある程度パフォーマンスを出すまで3ヶ月(原田さんのいうある程度のパフォーマンスってどのレベルのイメージだろう?)
  • 2,3ヶ月ごとに2,3名入れ替わるようなチームは安定度が足りない
  • 完成の定義はすべてのPBIに適用される汎用的なもの。acceptance criteriaはPBIごとのもの
  • Goalはステークホルダーからわかることが重要
  • CXOがスクラムに不安を感じている場合は、とりあえずミニマムで試してみることが重要
    • 一方でスクラムが成果を出すまで一定の期間が必要なので、スプリントごとのデモでステークホルダーや開発メンバー自身に手応えを掴んでもらわないと続けにくそう。
  • 優秀なスクラムマスターは日本人的シーンで場が凍っても待つ。いくらでも待つ
    • たぶんそこで待たないとメンバーは責任感を持たず、自主的に動かないからだと思う
  • 報酬制度を個々人でやるのは危険

講義中のメモ

iot企業ハードウェアチームとの連携 絵をたくさん書く

先行しているプロダクト、リファクタリングが必要。 プロダクト要求を進められない。

手分けしやすい、スケールしやすい、 なんでわけるの? PM以内の大丈夫? 大規模チーム? スケールスクラム 早めに手に入る。 要求分析 今は発注側がしんどい スクラムのメインフィールドはイノベーション イノベーションは外注できない

walking skeleton

scrum of scrum

遠隔地は最初からは難しい、一度一緒に飯を食べて、しばらく仕事をすると、リモートにしても成功しやすい。

outputではなくoutcome chaos report

機能数より成果 最初からチームで機能横断的である必要はない、レビューを繰り返すとフルスタックチームになる。

旧来のチーム、前職のようなチームではどうする? スクラム部署を小さく作り始める。デンソーの例

スクラムマスターはいつかけしかける、自分の苦手なタスクをする。

挨拶、ボールゲームで推測の難しさ、 スクラムイベント、うまい弁当、アジャイル宣言

リスクに対するテクニック、ウォーキングスケルトン 細かく作る。 シンプルなケースを作る。 80%の人を救うケースを作る、それがウォーキングスケルトン。

そもそもの問題が見えてない、マネージャーがこない?部屋がコンフリクト?

プロダクトバックログ、あまり長過ぎると管理が大変。 せいぜい100個が上限 でもの重要性

リファインメントはスプリントの10% 2週間でクソみたいなものを出すのは大事。 工数感を共有できるから。

スクラムマスターはポストイットでマスターする。

経験主義は科学分野から

POの最大の価値はプロダクトバックログ

リファクタリングをプロダクトバックログに入れろ、普段のタスクでリファクタリングしろ

機能は削除しろ。

デザイナーのためのCIを回して、積極的に参加してもらう。 チームに参加してもらう。 CIがキモ

セキュリティアーキテクチャ設計書に連絡先を書いてこちらです、にしておく

SIヤーではお客様はプロダクトオーナーではない。プロダクトオーナーは社内で建てる。 お客様はステークホルダーに過ぎない。

featureフラグでdoneにする。 デプロイは開発が任意。

プロダクトバックログには誰でも突っ込める。 優先順位を入れ替えられるのはPOだけ。

二日目

未完了は再見積もりしてバックログに戻す

デイリースクラムはマスターに報告しがちなので、マスターは隠れるなど メールが来る、登録する、日本語と英語がある、50問か30問かわからない、4択、制限時間は1時間、二回受けて2回とも落ちた人は居ない。72%で合格

ドラッカーもdone is better than doing

特に初心者のスクラムマスターは開発メンバーとも兼任するべきでない。 プロダクトバックログはvalidate 開発チームはバックログ通りに作っていることを保証するべき イテレーション、繰り返しではなく改善のサイクル、トヨタの片山さん曰く

優秀なスクラムマスターは待つ。気まずくても待つ。

スクラムマスターとしてチームに干渉し過ぎない。責任をチームに持たせるため、自ら解決させる。

    でも、そうするとスクラムマスターはやることなくない?

プロダクトオーナーが休み、病気は代理を立てる。

ビーチに行っていい?

どこまでやるんだっけ、はプロダクトオーナーと相談

3,5,8,13をSMLXLに割り当てる

high priorityかつXLは潰す。

環境構築のような機能に直結しないタスクはどうなる?

スクラムはプロジェクトマネジメントの手法ではなくプロダクトマネジメントの手法

上手く立ち上がる3/2のチームがある程度パフォーマンスが出るまで3ヶ月ぐらい。 二、三ヶ月ごとに2,3名入れ替えるのは安定度が足りない。

product ownerはend targetを決める。

今、definition of doneは完了の定義ではなく完成の定義という訳語にして曖昧さをなくした。

完成の定義は、汎用的なもの。 acceptance criteria はPBIごとのもの。

サーバの用意やインスタンスの用意はスプリント外で事前に用意する。

Goalはstake holderからわかることが重要

リファインメントはミーティングを短くする

CXOの不安を解消するため、試してみる。

試作品でもwalking skeletonを作る。 ソフトウェアでハードウェアがきちんと動いていることをテストするようにすれば、すごく高速に設計できる。 あとシミュレータをガチガチに作る。 スプリントを回すため、

何がやりたいと聞く。 報酬制度は個々人でやるのは危険

5 whyはガビーもやるテクニック

これはと思ったら、病院へ