nazolabo

フリーランスのWebエンジニアが近況や思ったことを発信しています。

OKRでありがちな間違い2点

ドキュメント(OKRはGoogleのものではありませんが…)ちゃんと読もうシリーズ第二弾です。(第三弾は多分ないです)

Google re:Workに書いてある内容のうち、間違った運用をされてそうな2点をピックアップしてみました。

一部に独自の解釈が含まれていますので、詳細は上記リンクなどを参照してください。またre:Workに書いてある内容ベースなので、OKRの正しい解釈としてはもう少し違う可能性があります。

1. 「OKR は、従業員を評価するためのツールではありません。」

評価するためのツールではないということは、OKRで評価しちゃ駄目なの?

普通に解釈したらそうなるのではないでしょうか。

なんで駄目なの?

OKRは、達成率が60%~70%が理想的とされています。簡単には達成できないような目標を設定して大きな成果を上げるのが目的だからです。しかしそれを個人の評価にしてしまうと、達成できなかった場合にマイナスにしてしまう可能性があります。達成できるかできないか微妙な目標で達成できなくてマイナスというのは理不尽なのではないでしょうか。

また、OKRでは、目標を達成できなくてもその過程で個人は大きな進化をするだろうとしています。「大きな目標に対して努力をする」ということが既に成果になっていて、それは評価されるべき内容となっているので、OKRの達成と個人の評価は関係がないということがわかります。

2. 「OKR は、社内共有のタスク管理ツールではありません。」

タスク管理ツールじゃないの?

そもそもOもKRもタスクではないのでタスク管理ツールではありません。

OにもKRにもタスクを入れないなら、OとKRの違いって何なの?

Oには数値ではない(定性的な)大きな目標を入れ、KRにはOを達成するための具体的な(定量的な)数値指標を入れる、とされています。

Oには会社規模であれば「世界一の〇〇を作る」みたいな感じの、とにかくすごそうな内容を入れておくのが良いでしょう。チームであればもう少しフォーカスを絞って「UIを改善する」とか「利益率を上げる」とかでもいいでしょう。

KRは、Oを達成するための具体的な数値を指定します。OKRの達成はKRの数値を0.0~1.0の範囲で評価できる状態にするというのがありますので、数値で評価できないものはKRにはなりません。

そうはいってもKRに具体的な話を書きたいんだけど…

「なお、OKR はチェックリストではありません。」ともあります。詳細はそこを読んでいただきたいのですが、あくまで「チームをどうしたか」を決める指針であり、具体的な内容を並べる場所ではありません。

まとめ

  • OKRで評価するのはやめましょう。
  • Oには大きな到達点、KRにはタスクではなく結果から見える数値指標を採用しましょう。
  • OKRのフォーマットが合わない場合はそこから外れても別にいいとは思いますが、その場合はOKRとは名乗らず「我々の手法」として利用しましょう。組織に合わせた適切なフォーマットを使用するのが一番です。

TerraformのWorkspaceはstaging/productionの切り替えに使うべきではない

Workspaceって何だっけ?

簡単に言うと「同一のtfファイル群を別のtfstateとして扱う、それを切り替える」機能です。

なんでだめなの?

公式がそう言っているからです。

In particular, organizations commonly want to create a strong separation between multiple deployments of the same infrastructure serving different development stages (e.g. staging vs. production) or different internal teams. In this case, the backend used for each deployment often belongs to that deployment, with different credentials and access controls. Named workspaces are not a suitable isolation mechanism for this scenario. State: Workspaces - Terraform by HashiCorp

どういうこと?

公式の言い分としては、「全く同じ環境のコピーを作るならいいけど、そうじゃない場合(staging/productionのような)は資格情報とか認証情報とか合わないから使えないよ」ということです。これは例えばstagingとproductionで別のAWSアカウントを使用している場合に該当すると思います。この場合は向いていないのが直感的に理解できるかと思います。

また、公式では「その場合は再利用可能なモジュールを使うべき」としています。つまり、部分的にモジュール化したものを組み合わせて別の構成として取り扱うべきとしています。これであればどのような構成でも部分的にモジュールを組み合わせて使う形になるので、自由な構成を組むことが可能です。

現実では小さい環境であれば片方の環境からコピペして必要なところだけ書き換えて新しい環境を作る、という感じでも最初のうちは困らないことが多いと思いますが、環境が増えそうであれば早めにモジュール化していくのが良いでしょう。

公式が言ってたらダメなの?使えるから使っても良くない?

以下は私の独自見解になります。

大前提として「stagingとproductionのtfstateは分けるべき」と考えています。これはapply時の影響範囲を狭めることができるためです。

その上で、私としては「そんなにstagingとproductionって同一環境ではないのでは?」というような理由で、Workspaceをその用途に使うべきではないのではと思っております。

The Twelve-Factor Appでは、外部環境は本番環境と開発環境のギャップがないようにすべきとされています。これは「開発環境ではローカルメモリに保存するけど本番はMemcached」のような、プロトコルレベルで違うようなものを使うと、それによるアダプターの実装の差異による思わぬ事故が発生する可能性があるためです。

一方で、外部リソースはアタッチされたリソースとして扱うというのもあり、そこでは「リソースを簡単に切り替えることができるようにしておく」とされています。

つまり、「アプリケーションレベルでは常に同一の対象に対してアクセスしているように振る舞うが、その先の通信対象が何なのかはアプリケーションが関与しない」ということです。これは問題が発生したときに責任がどちらにあるのか明確になり、性能限界などでの差し替え時にも容易に差し替えることができるためスケールしやすいアプリケーションになります。

これを踏まえた上で、一般的によくあるケースとして「本番ではメールを送信したいがstagingではメールを送りたくない」といったケースがあります。この場合、本番では普通のメールサーバーを構築します(外部のサービスを使うかもしれません)が、stagingでは「送信したメールを全て吸収してWeb上で表示してくれるサービスに送る」というようなことをすることがあります。具体的にはMailHogMailtrap.ioといったようなものです。私は前者を使うことが多いので、前者用のインスタンスをstagingのみで組み込んでおくということをします。

同様に、AWSでは「stagingではシンプルなRDSを使うが、本番ではAuroraクラスタを組む」というようなケースもよくあります。これも大幅に設定が変わる内容になります。Auroraクラスタまでいかなくても、DBのパラメーターを細かく変えることはあると思いますので、それをWorkspaceでどうにかするのはなかなか大変ではないかと思います。

上記の観点から、そもそもWorkspaceでstaging/productionのような「似てるようで用途が違うもの」の切り替えには向いていないのではないかと思います。が、これらを理解した上で「それでもWorkspaceで切り替えるのがベストだ!」となるのであれば、それでもいいかもしれません。

それじゃWorkspaceって何のためにあるの?

公式では以下のようになっています。

A common use for multiple workspaces is to create a parallel, distinct copy of a set of infrastructure in order to test a set of changes before modifying the main production infrastructure. For example, a developer working on a complex set of infrastructure changes might create a new temporary workspace in order to freely experiment with changes without affecting the default workspace. State: Workspaces - Terraform by HashiCorp

簡単に言うと、「インフラの変更のテスト用にもう1つ作っておいてそこで試すため」とあります。Terraformは実際にapplyする時の挙動は当然apply先のクラウドサービスに依存していますので、applyするまでどうなるかわからないということは多々あります。そのような場合を試すのにはベストなケースだと思います。

同様に、「本番環境と全く同じものを作って、そこでないと発生しないようなバグのテストをする」というようなケースにも良いのではないかと思います。

どちらにしても、「Workspaceを切り替えて複数環境を作れるようにする(しておく)」というのは設計上欠かせない要素になります。必要な設定を切り出しておいて、いつでもWorkspaceで切り替えれる状態を作っておくようにしましょう。

まとめ

  • 公式がそう言っているのでなるべく従いましょう。
  • stagingとproductionってそこまで同一環境ではないので、公式が言ってなくても向いていないのではないかと思います。
  • Workspace機能自体は常に使える準備をしておきましょう。

UUUM System Meetupで登壇させて頂きました #sysuuum

uuum.connpass.com

スライド

これは何か?

あまり良いとは言えない状態のプロダクトを良い状態まで改善していった時に気にした点について紹介しています。

個別の技術については世にいくらでも情報があるので今回は省略しましたが、どこかのタイミングで個別に取り上げていくかもしれません。

ビジネスとの判断

会社というのはお金を生み出さないと継続できないものなので、ビジネスを止めないで改善していくことが望ましいです。

一方で、ある程度止めないといけない場合も存在しますが、それでもビジネスを止める期間を最小限にするというのがエンジニアに要求されていると思っております。

「エンジニアが快適に作業するため」ではエンジニアの自己満足になってしまいますので、それがどうビジネスに繋がるのかをちゃんと説明する義務があると考えております。もちろん多くの場合は間接的に繋がるのですが、内容によっては今やるべきではないというようなこともあると思います。

先にやるか、後にやるか

ビジネスを止めずに〜とは言ったものの、ある程度は先に行う必要があります。

一番は「データベースなどのストレージが止まる可能性があるもの」で、これはデータ量が大きくなればなるほど停止しての作業が困難になります。ここに該当する作業は真っ先に行ったほうが良いです。必然的にインフラ要因のものは最速で問題がないかチェックすべきでしょう。

具体的にやる項目

今回は「私が行うなら〜」という観点でいくつか紹介しました。ここに書いていない項目もありますし、そもそも私も完璧ではないので抜けているような内容があるかもしれません。そのあたりは柔軟に対応していくのが良いかと思います。

とはいえ、ほとんどが基本的なことだと思いますし、また形式的にやるだけではなく継続的に意味のある改善していないような環境では、現代において他の優秀なサービスの成長に勝てることもないと思います。

今回話さなかったこと

質疑応答であったのですが、あくまで第一段階として行う話として話しました。もちろんここから設計方針とか深い話まで行けるといいですが、最初にやることとしてはこのあたりから考えるのがいいのではないかなと思います。

まとめ

スライドの最後にも書きましたが、そもそも最初にやっておけば苦労しない話なので、最初から高いレベルで環境整備を行いましょう。特にlintレベルは後から上げるのは本当に大変です…。

UUUMの皆様、退職した身にも関わらず、このような機会を用意していただきありがとうございます。

UUUMではエンジニアも募集していますので、興味がある方は応募してみると良いかと思います。ここで話したような内容はちゃんと実践されている環境です。他の方の紹介でもありましたが、労働環境としても常識的な労働時間でリモートワークも可能ですので、非常に働きやすいのではないかと思います。

職業Webエンジニアにおける「実績」と「やりきる力」

※私はWeb系のエンジニアです。以下「エンジニア」というのは「Web系のプログラマー」と読み替えて頂くのが適切な場合があります。

経歴の浅い人にキャリアについて相談された時に「まず目の前のプロジェクトをちゃんとやりきったほうがいいよ」と言うようにしています。

エンジニアにおける「やりきった状態」とは

Web系プロジェクトというのはリリースしたら終わりではなく、運用に乗ってある程度安定した状態になって初めて「十分な品質で世に送ることができた」と言えます。

運用に乗せてみると「負荷に耐えられない」「必要な機能を満たしていない」といった問題が現れることがよくあります。たいていの場合はそのまま運用を継続することはできませんので改修することになります。こうしてリリース時の機能が安定して運用できるようになった状態で「やりきった」と言えるのではないかと思います。

ただし、初期の想定を大幅に超えるデータ量やアクセス数により限界になった、というようなケースはここでは別の話になると思います。あくまで「初期の想定通りのものがリリースできているか」という点になります。

やりきっていない成果とは

やりきった状態に達していない場合、極端な話「何も手を付けていない」と「完成していたが世に出なかっただけ」の違いはわかりません。また、「完成していたが世に出なかっただけ」だとしても、それが本当に「十分な品質だったか」を判断することは本人にも不可能です。

極端な例だと、明らかに大して関わっていない巨大有名プロジェクトに短期間いただけで「あれは私が作った」というケースもありますが、さすがにそこまでいかなくても、実際まともに機能するものではなかったとか、その人が退職した後にすべて作り直されたというようなケースは多々存在します。

見えていない作業

やりきっていない成果には、「見えていない作業」が抜けている場合があります。

例えば「レビューの指摘に対応する」「周辺環境を成果に合わせて変更する」「想定以上のデータがあった場合の負荷に対応する」「実際の利用率を高い状態にする」「テストを書いて品質が高い状態でリリースする」というようなものです。

現代は雑なコードを書いてとりあえず動いていれば良いという時代ではなく、継続性の高いコードを書くことが要求されます。たとえ瞬間的なリリース直後の状態で問題なくても、その後誰も手がつけられないようなコードを書いてしまっている場合は「やりきっていない」と言って良いのではないかと思います。「リリース時の想定で動いているじゃん」と言いたいところですが、リリース時に「その後継続して機能改修する」というのを想定していない人は誰もいないのではないかと思います。

プロジェクトから逃げない

例えば巨大なプロジェクトだったり炎上しているようなものだと、つい逃げたくなりがちです。

ビジネスというのは(最終的に)お金を生むためのもので、そのためにプロダクトというのは完成してからがスタートで、それが利用されなくてはいけません。

利用される段階にまで達しなかったプロダクトというのはビジネス的には価値がないものとなります。エンジニアとして何かを得た可能性はあっても、それを途中で投げ出すというのは会社から見ると何の意味もありません。

エンジニア界隈で何らかの評価を得られるかもしれませんが、会社から評価を得られるのは「ビジネスになるプロダクトを作り上げた人」です。さらにそれを連続して達成すると、「この人なら安心して任せられる」という評価に繋がり、次の大きなポジションへと繋がります。

技術力?

この相談を受けた時に、「技術力を上げたい」という相談がセットでついてくることが多いです。漠然と「今後どうしたらいいのかわからない」という不安から来るようです。

現実的な業務におけるエンジニアの作業内容は「要件をまとめて、それを適切に実装する」ということです。もちろん場合によっては技術的に難易度が高いものも登場しますが、ほとんどの日常業務で登場することは稀です。

技術的に難易度が高いものを学ぶのが不要だというわけではなく、多くの会社でビジネスとしての比重が高いのは「日常的に比率の高い作業を確実にこなせる人材」です。まずはそれをできるようになってからでいいのではないでしょうか。

まとめ

自分のキャリアもちゃんとしていないのに他人のキャリアの相談を受ける身分なのだろうかという疑問はありつつも、最近こういうことについて何度か話したので考えをまとめてみました。

なんだかんだで「やりきることが困難な状態」というのは、周りのサポートが良くない場合というのが一番多いと思いますので、チームが一丸となって問題解決に取り組める環境だと良いのではないかと思います。チームビルディング大事。

主観が強い内容ですが、「やりきる」重要性というのはエンジニアとか関係なく大事なのかなーと思います。創作界隈でも「下手でもいいから世に出す」みたいなのはよく言われてる内容なので、結局そういうことなのかなと思います。

退職しました

  • from: UUUM株式会社(2015.06-2019.10)
  • to: まだないしょ

在籍期間中に会社の技術ブログに書いた記事は以下になります。

NESエミュレーターでRustの勉強をした

年明けから特にやることがなかったので、ファミコンのエミューレータを書くのは新しい言語に触れるのにちょうどいいとのことなので、RustでNESエミュレーターを書いてみました。全然動きません。Hello World!が辛うじて動くくらいです。

github.com

Rustってどんな言語?

C/C++の厳しいところを言語レベルで制約をガチガチに加えて安全にした言語、という印象です。最初、GCのあるLL感覚で学習していたのですが、それだと理解が圧倒的に厳しく、「C++のスマートポインタをデフォルトにした言語」と解釈すると圧倒的に理解しやすくなりました。

特に、以下の解説が参考になりました。

qiita.com

imoz.jp

Web系の方でも、ObjCでiOS開発しているのであれば比較的近い概念が登場するのでとっつきやすいかと思いますが、RubyPHPのような言語しか書いたことがないという人は概念が違いすぎて大変なのではないかと思います。

最初のうちはコンパイルエラーにとにかく悩まされるのですが、コンパイルエラーにヒントが出ることも多くて解決しやすく、次第にコンパイルエラーになりそうな場所がわかるようになります。一方で、ある程度書いてると「そもそも設計がダメだとビルドにたどり着けない」という現象に遭遇し、場合によっては大幅に書き直しを迫られる場面もありました。設計力も事前にある程度必要なのかと思います。

ただし型制約が厳密と言っても、Vec(配列)の範囲外アクセスなどで簡単に実行時に落ちます。このあたりはパターンマッチなどでそもそも構造的に範囲外アクセスできないようにするなどのテクニックが必要になってくるのかと思いました。

WebをRustで書くというのはあまり想像できませんが、WebAssemblyや組み込み、リアルタイム性が必要な部分などで登場する機会が増えるのではないかと思います。

C/C++を書いていたころを思い出し、書いていてとても楽しいと思いました。普通のWeb系だとGoもあるのでここまで持ち出す必要がなさそうですが、もっと本格的に書いてみたいので、どこかで仕事として書く機会があると楽しいのではないかなと思います。

NESエミュレーターって書きやすいの?

今回初めて書いたのですが、昔より日本語資料が圧倒的に多く、誰でも気軽に参入できる状態だと思います。参入しても何かいいことがあるわけではないですが…。

昔、似たような(もっと高級な)環境の上でプログラムを書いたことがあるので、アーキテクチャの理解は他の人より早いと思います。

冒頭に紹介した記事でもあるように、新しい言語を覚えるのには規模としてちょうどいいレベルではないかと思います。皆さんも是非挑戦してみてください。

ワンポイントTwelve-Factor App(12) : 管理プロセス

この記事は、The Twelve-Factor Appを補足し、実際に現代的なWebアプリケーションで適用する場合の注意点などを紹介するシリーズです。下記の原文を読んだ上でのワンポイント解説になります。

12factor.net

概要

  • 管理プロセスはアプリケーションの実行環境と同一リリースで行う
  • 単発の処理を実行できる仕組みを用意しておく

これは何を表しているか

DBのマイグレーションや単発のスクリプトを実行する場合でも、アプリケーションの実行環境と同じリリースで実行することによって、処理の実行の差を少なくすることができます。

リリースというのは「5. ビルド、リリース、実行」で解説しましたが、コードベースをビルドしたものに環境要因の設定を合成したものです。実行環境と全く同じ構成になっているので、例えば実行環境のWebサーバーを bundle exec … で起動している場合、単発スクリプトbundle exec… で実行することによって全く同じ状態で実行できるようになります。

また、REPLシェルが提供されていると、単発のスクリプトを自由に実行することが簡単になります。本番環境ではSSHなどを通じてリモートからコマンドを叩けるようになっているのが良いでしょう。

実際に運用する場合

Docker環境の場合、単発スクリプトをWebアプリケーションと全く同一のイメージ・同一の環境変数で、 docker run … で起動することによって、確実に同じリリースで実行することができます。コンテナオーケストレーションツールにはこのような単発実行の仕組みが用意されていると思いますので、それらを利用するのが良いでしょう。

本番環境へのSSHに関しては、セキュリティの懸念点や、リリース(「5. ビルド、リリース、実行」)を変更できてしまうという点、autoscaling環境ではそもそも接続先がはっきりしないという点などから、現代では可能な限り行わないほうが良いとされています。本番では実行できる単発処理を制限し、決められた単発処理だけリモートから実行できるような仕組みにしておくのが良いでしょう。