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

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

「リモートチームでうまくいく」感想&まとめ

How toだけ書くのは本質から離れるという意見もあるが、やり方を書かないと忘れる。 のでHowを書く。

Amazon.co.jp: リモートチームでうまくいく eBook: 倉貫義人: Kindleストア

  1. 場所は離れていても同じ時間帯に働く

  2. 朝来たら挨拶を書く、帰るときはお疲れさまでしたと書く。

  3. カメラで存在を確認する。
  4. timesチャンネルのようなもので独り言を簡単につぶやける環境を作る。

上記はすべて論理出社、物理的な出社をシミュレートするためにある。

掲示板の機能はissueで代用できている気がする。

  1. リモートチームでの信頼関係の気づき方

一緒の問題・タスクに向かうことで信頼は築かれる。 タスク管理はzenhubでOKな気がする。 スケジュールはcalendarでOK? いつから、何日という発言は不要にしてgoogle calendarへ一本化するのは有りかも。

リモートワーカーを少数派にしない

これは難しい。ただでさえインフラという他のチームとの協業が必要な部署なのにその上リモート化を推し進める。 契約上の話もあるし厳し目。

5. 毎日の習慣とリズムを作ろう

オンカメラ、10分程度の朝会はやったほうがいいかも。時間は要相談だが10時くらい?

一番最後のリモートワークに至るまでの道は今の自分たちの参考になった。 リモートワークだと全員が平等に情報を得られるようにというのが繰り返し書かれているけど、それが今すぐ難しいとき、それをどうやって実現まで持っていくか、過程状態でも上手くやってくにはどうすればいいのかのヒントになりそう。

個人的リファクタリング史

年齢 できごと
15 プログラミングを始める。何もわからずひどいコードのパッチワークで半端なものすらできない
16 自分のコードがひどいことはわかるのだがどう改善すればいいかわからない状態
17 デザインパターンやテストの概念とともにリファクタリングの概念と出会う
17 Eclipseの自動リファクタリング機能に衝撃を受ける。リファクタリングの威力を初めて実感
18 ~ 24 リファクタリングを自動テストやOOPなどと組み合わせつつ実践
24 就職。最初に入った現場でリファクタリングがまったく実践・考慮されておらずひどいコードがそのまま放置されていることに衝撃
25 自分が初期から書いていないプロダクトでレビューの文化(仕組み)がなく自動テストもない場合、よそ者がリファクタリングするのは非常に困難だと実感。またリファクタリングの価値を説明できず理解してもらえなかったことにも失望
25 継続的にリファクタリングを試みるが主に本番稼働しているコードを変更することへの恐怖・リスクからチーム内で同意が得られない。それらを自分たちで書いたメンバーはコードの構造の特殊な癖も十分に理解しており改善に対するインセンティブが薄かった
26 ~ 27 新規プロダクトでたくさんのコードを書く。納期優先でひどいコードも量産。リリース後にリファクタリングを行ったが構造が複雑でテストがあってもリファクタリングが劇的には進まず、そもそもそのプロダクトに関して改修案件が全く来ずコード改善の効果が低かった。この辺でリファクタリングの価値について疑問を持つ
2x ファウラーだかの言葉で「リファクタリングするより1から作り直したほうが早いときはそうするべき」というものに衝撃を受ける。それまでどんなにひどいものでも作り直すよりかはリファクタリングしたほうが早いと思っていたのだが、基本設計がひどい場合はリファクタリングでも改善できない、そういったケースがあることを初めて認識する(それまでリファクタリングは良くないコードに対する銀の弾丸だと思っていた)
2x 確率的に犠牲的 - steps to phantasien ここらへんからもリファクタリング・改善一度ではないのだなと認識
2x (これもファウラーかIDDDあたりだったはず) 良いものを作るには最初から正しく作らないとだめだ1という主張を読む。今までのプロダクト開発を振り返るに否定する材料がない。リファクタリングを無力に感じる
30 ~ 31 自分の書いた新規コードと過去のメンバーが書いたコードが混在するプロダクトで、リファクタリングとコード修正のサイクルが初めてまともに回る。これはPull Requestの仕組みでレビューが制度化されたこととリファクタリングについての共通認識をチーム内で醸成できたこと、そしてなにより機能追加や改修の前にその地ならしとしてリファクタリングをするというやり方がチームへ受け入れられたことが大きいと思っている。一方で開発したプロダクトは商業的には成功せず、このときリファクタリングなんてかなぐり捨てて新規機能開発へ全力を注いだほうが組織としては価値があったのではないかという疑念は残った
32 リファクタリングは相変わらず大好きだが年をとってステークホルダーへ説明責任を果たす役割が増えた今、その価値をどう説明するか、リファクタリングをどう活かすかについて悩んでいる

「りろんはしってる」状態

ある技術やツール、フレームワーク、ライブラリなどについて入門記事や概要の解説記事は読んだがまだチュートリアルもこなしていない状況。

入門記事や概要解説の記事などは理想的な条件が前提であったり業務であるシチュエーションより大幅に単純なシチュエーションが扱われる事が多い。また機能や利便性について針小棒大にかかれていることもよくある。そのため多くの場合実際に使ってみなければ自分たちの現場で使えるかはわからない。実態と自分のイメージが大きくずれていることもよくある。

この状態で実際の現場への導入イメージや活用の細部を話し合うのは非常に危険。せめてチュートリアルだけでも一度こなしたほうがよい。

元ネタ

f:id:den8:20191231183103j:plain
"よつばと! 第3巻 第19話 「よつばとぞう」 - 8月14日" より

よつばと! 3 (電撃コミックス) | あずま きよひこ |本 | 通販 | Amazon

AWSサンドボックスアカウント運用のすすめ

AWSサンドボックスアカウントとは?

AWS基盤上でサービス開発をしている企業において、サービス開発に携わるすべてのエンジニア1が自由にAWSのサービスを試用・実験・検証できるAWSアカウント。

作り方

AWSの機能としてサンドボックスアカウントなどという物があるわけではないので以下の手順で作ります。

  1. それぞれの社内規定に従いサンドボックスアカウント用の予算を確保します
  2. それぞれの社内手順に従いAWSアカウントを作ります2
  3. すべてのエンジニアがAdministratorAccess権限3でログインとawscliコマンドを打てるようにします
  4. サンドボックスアカウント用に AWSのコスト予測アラートを設定します
  5. 下記のサンドボックス利用ルールとログイン方法を社内のエンジニアに周知します

利用ルール

MUST

  • 仕事上使う、使いたい、使えるか検討したいAWSサービスがあれば本番環境アカウント・開発環境アカウントなどではなくここでそのサービスを試行(テスト)してください

SHOULD

  • サンドボックスアカウント上に作られたリソースは一日ごとにすべて削除される、またはされる可能性があります4。それでも問題のない使い方をしてください

RECOMMENDED

  • リソースが日毎に消える可能性があるためCloudFormationやTerraformなどのInfrastructure as a Codeを利用することをおすすめします5

SHOULD NOT

  • 不必要なまでにコストがかかる実験・試用はしないでください
  • 大きなコストがかかるが必要性のある実験・試用をする場合はサンドボックスアカウントの運用責任のある部署へ先に一方ください。調整します

MUST NOT

AWSサービスの試行・検証・テストは自由ですがサービスへの攻撃を含むテストはAWSへの申請なしにしてはいけません。こちらで詳細を確認して可能なテスト種別であればAWSへ申請をして実行してください。

目的

tl;dr

  • 新サービス・新機能・使ったことのないサービスの試行を促進することで開発を高速化
  • 失敗してもいい空間(アカウント)を作ることで試行そのものを安全に高速化
  • 開発環境AWSアカウントなどで実験してはぐれインスタンスなどを残さないため

長い説明

AWSのサービスを実際に使用してみることなくサービス開発で利用することは非常に難しいです。AWSのリリースやドキュメントを読んだだけでサービスへ組み込もうとするとイメージと実体が乖離していたりパフォーマンスや機能などが期待と大きくずれていたりします。 そのためシステム設計の前にしろ後にしろどこかのフェイズでAWSのサービスを試行することになりますが、この際いくらかの問題を感じてきました。

  • インフラ構築中の開発環境アカウント/本番環境アカウントなどで試行する
  • → 試行中のリソースと実際のシステムの一部のリソースが混じり合う
  • → 間違ってシステムの一部のリソースを削除してしまったりする
  • → 試行自体が抑制される
  • → 知らないAWSサービスや新しいサービスが使いにくくなる
  • → システムがEC2インスタンスベースで構築される
  • → 運用コスト・保守コストが高くなる

こういったことが開発組織では起こりがちです。 こうなるとエンジニア含め会社全体が嬉しくないので、それを解決するために既存AWSアカウントと分離したサンドボックスアカウントという手段を考えました。


  1. クラウドエンジニアやインフラエンジニア、バックエンドエンジニアなどと呼ばれる普段からAWSを触ることが多い職種だけではなく、フロントエンドのエンジニアやアプリのエンジニアなどクラウド基盤を直接・間接問わず使用するすべてのエンジニア

  2. AWS Organizationを使うのがおすすめです

  3. 請求情報などを平エンジニアに見せたくないなどといった要望がある場合は制約を加えてもいいかもしれませんが基本的に悪手です。各々のエンジニア自身に自分たちの運用しているサービスのコスト感を意識させる意味でもコスト系も開放することをおすすめします

  4. コストへの配慮のため。お金じゃぶじゃぶの企業はこの項目いらないかも

  5. 実際のシステム構築でCloudFormationやTerraformなどを使ってもらいたいことも一因です

Terraform meetup tokyo#3 参加してきました

お疲れさまです、2019/11/01から株式会社Speeeの方でSREとして飯を食わせていただいています! 新しい会社ではインフラストラクチャの構成管理がTerraformということで、Terraformについていろいろ勉強していくうちに流れでTerraform meetup tokyo#3 - connpassにてLT発表することになりました1

本記事では各発表の僕の感想を書いていこうと思います。

Journey to Terraform Enterprise

Terraform EnterpriseはTerraformのノウハウへ料金を払っていると思っている。Terraformの専門家を1人雇うよりこちらのほうが経済的

という趣旨の発言や、Root Module(tfstate)を統合していった、それによる不便は特に感じてないなどが印象に残っています。

terraform と cdkの違い / oracle

docs.google.com

cdkとの比較。cdkは最近流れがきているんじゃないかとも感じています。

前回のアンケート結果でCI/CDしてるのが3割しかなかったので、初心者向けに手軽にCI/CDできるよってお話 / dehio3

Github Actions + Terraformの入門のような感じ。弊社でもTerraform CIは回せていないのでこれを参考に導入させていただきます!

Deep Dive HCL / Keke

Go言語とtfの相互変換性について。tfコンフィギュレーションの自動生成の方法。思った以上に簡単でした。 モジュール以上の共通化・柔軟性を実現したいときはこれを使う感じ?

インフラもオブジェクト図を描いてドメイン分割してからコーディングに進もう / Toshihiko Nozaki

個人的にはこの発表がMVPでした。 話の進め方が上手くて聞いていて非常に理解しやすかったです。 今までインフラを表現するのにシステム構成図で満足していたんですがUMLを使うのもありかなと思いました。 今までそういった発想がなかったためまだその価値も理解できていない感じ。

あとたしかこの発表だと思うのですが1つのサービスでも各要素をライフサイクルごとにRoot Module(tfstate)へ分割しているとおっしゃっていたのは面白かったです。たしかによくVPC / subnetなどネットワークレベルとEC2/ECSなどインスタンス・サービスでRoot moduleを分割するのですが、それを言語化するとライフサイクルごとと言えるのかもしれません。

tfstate分割粒度の種類とそのメリット・デメリットを考えてみた / k_bigwheel

拙作ですが私の発表です。 後のworld cafeで話を聞いてみると2-Bパターンが比較的多くworkspace利用者が若干少ないようでしたがどのパターンもそれぞれ一定数の利用者がいるようでした。 また各々がよいと考えている手法もバラバラです。

突撃!隣のTerraform

これがある意味最もインパクトのある発表でした。 メルカリの社内共通モジュールを作ってQAシェルでYes/Noを選択していくと各チーム向けのマイクロサービスtfコンフィギュレーションセットができるという構成は強いと感じました。 そのまま真似できるものではないものの、社内モジュールの作成・共有の必要性を強く感じました。


このあとのworld cafeも非常に良かったのですが割愛。 あの進め方は懇親会の方式として非常に良いと思いますので他のイベントでも広がっていったらいいなと思います。


  1. ちなみに流れというのは一般参加枠がいっぱいでLT枠が余っていたというのが理由です

「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稼ぐのが目的の人間が書いているのでしょう