元茹でガエルなエンジニアの記録

ちょっとやってみたことや考えたことなどを不定期に書き残していきます

OKRに振り回されない

OKRって設定するのムズかしいなーと思っていたのですが、少しこう考えるとよさそうかな、というのが見えてきたので今の時点の考えを残しておこう。

本当はOKRをうまく使うことで、いろいろあるやらないといけないことの中で優先度を意識できたり、とはいえ今はこれに集中しよう、という拠り所になると思っている。だけど、OKR設定をミスると、逆にOKRに縛られて振り回されて、OKRでこう決めたから今月中にこれをやらないとダメなんです!みたいなおかしな事になってしまう。OKRってそんは窮屈なものでは無く、何を目指すか、どんな状態を目指しているのかを具体的に目線あわせするツールなんじゃないかと思う。

OKRとは?

そもそもOKRってなに?っていうことを簡単に書いておきます。 Objectives and Key Resultsの略。日本語では「目標と主要な成果」と訳されたりします。

自由度のあるOKR

Objectiveは定性的な表現で良いので、目指す姿や理想をおく。 Key Results で定性的な表現を補完して、具体的にはこんな状態のこと、というのを説明する。

分かりやすい例としてダイエットで考えてみる。

Objective: 半年以内に痩せて細マッチョな格好いいカラダになる

Key Resultsとして、痩せて細マッチョな状態をより具体的に定義する。

こんな感じ。ポイントは、「やること」といった手段の話を含めない。あくまでResultsの話する。 こうすることで、結果にフォーカスし、手段に自由度が生まれる。結果さえ出れば手段はいろいろやれば良いのである。逆に言うと、結果が出なければ手段にいくらこだわっても意味が無いので、この形が良いと考えている。

そのうえで、行動指標を置きながら取り組むのが良いと思う。 行動指標というのはたとえば、毎日5km走る、とか、摂取カロリーを2000kcal/dayにする、とか。

逆に、僕がこれまで見てきた、もしくは自分でもやってしまった良くないOKRのような感じでかくとこうなる。

Objective: 半年以内に体重 xx kgの細マッチョ体系になる

Key Results

  • 毎日5kmのランニングを週に80%以上継続
  • 食事摂取カロリーを2000kcal/dayを守る

こんな感じ。これだと、Key Resultsを達成しても、Objectiveが達成できないかも知れない。それなのに、Key Resultsを達成しようとするインセンティブが強く働くので、「手段の目的化」が始まることになる。

それよりも、手段は問わないから、こんな状態になっているといいね、という目標設定のほうが良いと思う。 そうすると今度は、手段の有効性がある程度早く評価できないといけない。なので、先行指標を考えましょう、となるわけです。遅行指標、結果指標ではなく先行指標。

やってみて、指標の変化を評価して、次どうするかを考えて、、、のループを回せると良いなぁと考えている。

【翻訳】15年後のデザインパターン

オブジェクト指向におけるデザインパターンを世に送り出したGoFの3人(1名はすでに他界)が出版から15年後に対談した内容の翻訳です。 https://www.informit.com/articles/article.aspx?p=1404056

【翻訳】15年後のデザインパターン

ラリー・オブライエン:この1年あまりの間に、8万5千ものiPhone用アプリが開発され、展開されています。グローバルにアクセスできる "Hello, World!こんにちは、世界! 時刻はXです "というウェブページをPHPで1行で書くことができる。「オブジェクト指向ソフトウェアの設計は難しい」というのが、デザインパターンの第一声である。この言葉は今でも正しいのだろうか?

リチャード・ヘルム:ソフトウェア設計は常に難しいものです。最近の開発環境の多くは、再利用可能なライブラリやツールキットによって複雑さを軽減していますが(EclipseAppleMicrosoft)、ビジネス上の問題に対するソフトウェアソリューションを設計することは、依然として難しいのです。

エリック・ガンマ:そうですね、iPhoneの話をされるのは面白いですね。iPhone SDKは、AppKitのようなNeXTStepオブジェクト指向フレームワークがベースになっています。15年前に私たちが「Design Patterns」(以下DP)を書いたときにはすでに存在しており、インスピレーションの源のひとつとなりました。実際に私たちのパターンのいくつかでこのフレームワークを参照している。Adapter、Bridge、Proxy、Chain of Responsibilityなどです。

リチャード: これは、優れたデザインの永続的な性質と、それがさまざまな技術的表現に耐えられることを示す素晴らしい例です。

ラルフ・ジョンソン:1行のプログラムを書くというのは、通常、デザインという意味ではありません。ソフトウェアはここ数年で大きく進歩し、以前は入念な設計が必要だったシステムの多くも、今では他のソフトウェアを再利用することで構築できるようになりました。しかし、そのように構築できないシステムもたくさんあり、10万行の新しいコードを書くことは、15年前と比べてそれほど簡単ではありません。より多くのことができるようになりますが、コストは同じです。

ソフトウェアを設計するのは大変です。だからこそ、楽しいのです。ソフトウェアを設計するのが得意な人は、難しい問題を解決すること、混沌に秩序をもたらすこと、困難に打ち勝つことを楽しんでいます。昔は難しかったことが今は簡単になっていますが、20年前には不可能だったような問題に取り組むようになったのです。オブジェクト指向プログラミングは、設計の難しさを解消するものではありません。

ラリー:この本の次のフレーズは、「...再利用可能なオブジェクト指向のソフトウェアを設計することは、さらに難しい」です。再利用は、90年代前半には、オブジェクト指向の主な利点として紹介されていました。しかし、この10年間で、多くの主流の開発者は、再利用をフレームワークの設計者に任せることにしたようだ。今必要なものを開発し、進化させる必要があれば最小限のリファクタリングを行い、質問されれば「You Ain't Gonna Need It」というカードを出す。再利用可能な設計を目指すことは、今日の開発者にとって重要な目標なのでしょうか?

リチャード:洗練されたレベルの進化があったのだと思います。再利用可能なソフトウェアは、ツールキットやフレームワークとして、基盤となるシステムや言語に移行しており、そのほとんどは専門家に任されるべきものです。

多くのソフトウェア開発者にとっての目標は、依然として変化を想定した設計であり、そこでの議論は、それを早い段階で行うのか(予見可能な状態で)、それとも遅い段階で行うのか(より多くのことが判明し、それが必要だと分かってから)、ということです。多くの場合、設計はリファクタリングされるべきであり、パターンはそのための目標を提供する。

エリック:実は今、「...最も難しいのは、再利用可能なオブジェクト指向ソフトウェアを進化させることだ」という言葉を付け加えようと思っています。これについては、「Design Pattern」の中でも少し触れています。例えば、Factory、Adapter、Facadeは、再利用可能なライブラリーを変更したり、進化させたりする際に役立ちます。この問題に対しては、さらにいくつかのパターンがあり、それを捕捉することは価値があるだろう。

耐久性のあるAPIを設計するには、さらに洗練されたレベルが必要であることに同意します。今日下す決断は、明日できることに影響を与えます。しかし、専門家でさえ、最初からうまくいくのは難しいのです。例えば、EclipseAPIに潜入すると、プリファレンスを保存するためのAPIに3つの異なるバージョンがあることがわかります。

ラルフ:ほとんどのプログラマーは、再利用可能なソフトウェアを書くために雇われているわけではありません。ただし、そのソフトウェアが数年後に要件が変わり、世界が変わったときにも使えるようにする必要があるという意味では、再利用可能なソフトウェアを書くために雇われているのです。しかし、再利用可能なソフトウェアがどのように機能するかを知る必要はありますし、私たちのパターンは再利用可能なソフトウェアでは一般的なものなので、平均的なプログラマーが知っていても役に立つでしょう。この本は、どのパターンを使おうかと考えている人に向けるのではなく、他の人が選んだパターンを使っている人に向けた方が、今はいいのかもしれませんね。

エリック:私はこのアイデアが好きです。先ほどのiPhone SDKを学んだとき、使用されているパターンを知っていたので、すぐにライブラリに親しみを感じることに気づきました。

ラリー:一時期、あらゆるものが "パターン" になっていましたね。建築、組織行動、分析などのパターンがありました。しかし、あまり明らかではなかったのは、デザインパターンカタログの23のパターンが、他のデザインパターンによって拡張されたり、例えば、アーキテクチャのパターンに関連したりするような進化を遂げていたことです。世の中にはたくさんのパターンがあります。新しい「図1.1」はないのだろうか。デザインパターンの関係」?

ラルフ:「お渡しするフィギュアはありますか」という意味であれば、答えは「ありません」です。もし「誰かが新しいフィギュアを作るべきか」という意味なら、答えは「Yes」です。

エリック:リンダ・ライジングの『パターン・アルマナック2000』というのがありますが、これは多くのパターンを捉えようとしたものです。これはかなりの労力を要しましたが、コミュニティではそれほど大きな支持を得られませんでした。私は、ソーシャルフィルタリングによって、最も人気のあるパターンを見つけ出し、「このパターンが役に立った人は、このパターンも好きだった」というようなヒントを得ることができるのではないかと思い始めました。つまり、すべてのパターンが同じ関連性と重みを持っているわけではないのです。DPでパターンの良いサンプルを選んだのは、かなり幸運でした。

ラリー:DPで使われている記述テンプレートは、「名前」「意図」「構造」以外にも多くの特徴がありました。パターンの流行に乗った人たちが皆、それらの要素をすべて提供しているわけではありません。もし、今、そのテンプレートをリファクタリングするとしたら、どんなことをしますか?

ラルフ:このテンプレートは、私たちの本に載っているような低レベルのオブジェクト指向パターンには適していました。それ以外の目的には向いていませんでした。人々はすぐにそのことに気づき、別のテンプレートを選びました。すべてのパターンのコレクションには標準的なテンプレートが必要ですが、どのテンプレートもすべてのパターンに適しているとは思えません。だから、私はテンプレートについての議論はつまらないと思います。

エリック:私は、特定のテンプレートに執着しているわけではありません。でも、最終的に1つのテンプレートに合意し、それにこだわったことはよかったと思います。例えば、用途がわかっているか、その結果を記述しているか、などです。

ラリー:パターンブームの後、"アンチパターン" という流れがありました。アンチパターンはパターンと同じように価値があるのでしょうか?

リチャード:おそらくある。失敗を共有し、そこから学ぶ方法を提供します。

ラルフ:私は「コード・スモーク」、「デザイン・スモーク」、「アーキテクチャー・スモーク」などの概念を好むんです。それらは常に間違いとは限りません。時には、一緒に生きていかなければならない問題であることもあるのです。例えば、「ストーブパイプ」システムは、企業がシステムを相互接続する良い方法を持っていなかったこと、技術が急速に変化していたこと、企業のさまざまな部分が協力しなかったことなどが原因で、発展しました。成熟し、ゆっくりと成長している企業では、ストーブパイプシステムは、おそらくSOAと強力なアーキテクチャチームによって排除されるべきアーキテクチャの臭いです。しかし、他社を買収して急成長している企業では、ストーブパイプは新会社を統合するのに時間がかかることが原因です。いくらアーキテクトがリーダーシップを発揮しても、この問題は解消されない。

私の生徒の中には、"Big Ball of Mud"(泥だんご) のパターンを書いた者もいる。パターンを読むほとんどの人にとって、これは何としても避けなければならないアンチパターンだ。しかし、多くのIT組織、特に私が見てきた政府のIT組織では、より良いものを作るための十分な専門知識がないのです。彼らが作ったものは、数年のうちにその構造を失い、他のすべてのものとつながってしまうのです。

エリック:デザインパターンを使う動機付けとして、コードスメルやアンチパターンを使うのは貴重なことです。デザインパターンを使う前と後のコードを見なければ、デザインパターンの価値を理解することは難しい。

ラリー:GoFは、OOPが主流のパラダイムになった比較的早い時期に登場し、良くも悪くも、「パターン」はOOPアプローチと結びついているようです。関数型やダイナミック型の支持者が、自分たちの言語にはパターンが「必要ない」と自慢しているのを耳にすることさえあります。これに対して、あなたはどう答えるだろうか?

エリック:余談ですが、私たちがデザインパターンを書いたのは、JavaC#が登場する前だということも忘れがちです。

ラルフ:そのような言語では、問題を解決する別の方法が用意されているので、デザインパターンのいくつかのパターンを必要としないものもあるんだ。私たちのパターンは、C++からSmalltalkまでの言語、つまり「オブジェクト指向」と呼ばれるあらゆるものを対象としていますが、すべてのプログラミング言語のためのものではないのは確かです。他の言語のプログラマーはパターンを必要としない、とは誰も言っていないと思います。

エリック:デザインパターンはどんな言語でもいずれは出てくるものです。デザインのデジャヴは言語に依存しません。こうした経験は必ずしもパターンとして捕捉されるわけではありませんが、実際に存在するのです。Erlangのデザイン原則が思い浮かびます。

ラリー:動的言語関数型言語のパターンについて学ぶには、どこに行けばよいのでしょうか?誰が良い貢献をしているのでしょうか。

ラルフ:「動的」というのがSmalltalkRubyPythonのような動的オブジェクト指向言語のことであれば、私たちのパターンが適用可能です。関数型言語には別のパターンが必要ですが、誰がそれに取り組んでいるのかは知りません。

ラリー:OOPは静的な構造と動的な構造の組み合わせを提供し、設計意図をいくつかの異なる軸で(少なくとも異なる図で)伝えることを可能にします。現在は、関数型やメタプログラミングのアプローチが重視されているため、静的な構造はそれほど多くありません。その代わりに、"ドメイン固有の言語 "や "流動的なインターフェース "の文脈でAPIを作成することによって、設計意図を伝えることが多く語られるようになっている。これらのアプローチは、DPのパターンに取って代わるものなのでしょうか、それとも補完するものなのでしょうか?

リチャード:補足します。優れたデザインで構成されたリッチなクラスライブラリは、ドメイン特化型言語の機能・特性を引き継ぎます。よく設計されたユーザーインターフェースツールキットのコードを読むことは、GUIのためのドメインスペシフィック言語を読むようなものです。ライブラリのコンストラクトは、ドメイン固有言語の動詞と名詞になるのです。例えば、Interviews/Unidraw(John Vlissidesとの共著)のコードを遡って見てみると、言語はC++ですが、GUIの作り方を知っている人なら容易に理解できるコードになっています。

エリック:DPのパターンを補完する一方で、メタプログラミングが設計に使われるデザインパターンに取って代わることも確かにあり得ます。JUnit 3からJUnit 4への進化が思い浮かびます。JUnit 3はComposite、Template Method、Commandといったいくつかのパターンを使用した小さなフレームワークでした。JUnit 4 は、J2SE 5.0 で導入されたメタプログラミング機能である Annotations を活用しています。パターンの使用はなくなり、フレームワークは、小さなアノテーションのセットと、アノテーションされたJavaコードを実行するテストランナーインフラストラクチャに進化した。

ラリー:ジェネレーティブパターンです。A Pattern Languageには253のパターンがあり、DPには23のパターンがあります。DPのカタログは、Alexanderの「(パターン・ランゲージは)配置のルールを教えてくれるだけでなく、そのルールを満たす配置を好きなだけ構築する方法を示してくれる」という命令を満たしていると思いますか?

リチャード:いいえ、杓子定規なガイドでも生成的なガイドでもありません。エンジニアやデザイナーが本棚に手を伸ばし、クラッチや2ストロークエンジンの一般的な機械設計を見つけるような工学ハンドブックから、よりインスピレーションを受けました。

ラリー:「Design Pattern」をリファクタリングするとしたら、どのようになりますか?

エリック:この演習は2005年に行いました。以下は私たちのセッションのメモです。私たちは、オブジェクト指向の設計原則とパターンのほとんどが、当時と変わっていないことを発見しました。私たちは、分類を変更し、新しいメンバーを追加し、またいくつかのパターンを削除したいと思いました。議論の大半は、分類の変更と、特にどのパターンを削除するかについてでした。

どのパターンを捨てるか議論したところ、やはりどのパターンも好きだということがわかりました。(本当は、Singletonをやめることに賛成なのですが。その使用は、ほとんど常にデザイン上のくさいニオイがします)。

そこで、その変更点をご紹介します。

  • InterpreterFlyweightは、他のパターンとは別物なので、「Other/Compound」という別のカテゴリに移動させるべきでしょう。Factory MethodはFactoryに一般化する。

  • カテゴリは次のようにする。Core、Creational、Peripheral、Otherです。ここでは、重要なパターンを強調し、使用頻度の低いパターンから分離することを意図している。

  • 新しいメンバーは以下の通り。Null Object, Type Object, Dependency Injection, Extension Object/Interface (プログラム設計のパターン・ランゲージ3, Addison- Wesley, 1997の「Extension Object」参照)である。

  • カテゴリー分けはこちら

    • Core: Composite, Strategy, State, Command, Iterator, Proxy, Template Method, Facade
    • Creational: Factory, Prototype, Builder, Dependency Injection
    • Peripheral: Abstract Factory, Visitor, Decorator, Mediator, Type Object, Null Object, Extension Object
    • Other: Flyweight, Interpreter

上に書いたように、これはあくまで草稿の状態でのメモです。テストケースを作らずにリファクタリングを行うのは、常に危険です...。

この記事を読んで

15年(なんならもっと前)とはソフトウェア開発自体も進化/変化しているので、これらのパターンの中には、自分で実装することが減ったものもあると思います。ですが、関心ごとの切り出し方や分離の界面をどうしようか、というヒントとしては今でも役に立っています。個人的にはSingletonをやめることに賛成、と言っていることが印象的でした。自分は使っているので。。

アジャイル開発をやっていると、イテレーティブに機能を追加していきます。そのとき、変更や拡張がしやすい柔軟な 設計であるかどうかが重要になってきます。変更の必要が生じたときに、その場限りのツギハギのように増築していくのではなく、だったらここでXXXパターンを適用して少しリファクタリングしてから機能追加しよう、とできると良いように思います。

仕事をする上で参考になったものたち

自分の仕事のやり方や資料作成において参考になった情報源などを、他の誰かにお勧めするときにシェアしやすいようにまとめておくことにする。

スライド作成

プレゼン資料の作り方とプレゼンそのものセットで、この2つだけで十分だと思う。他にもいろいろ読んだりしたが、まずはこれらをしっかり読み込んで修得するだけでやっていけると思っている。

見やすいプレゼン資料の作り方

SlideShareで公開されている。 見やすい、分かりやすい、伝わりやすいスライドの作り方をたくさん解説してくれています。 無料でこんなレベルの学びができるなんて素晴らし過ぎます。

見やすいプレゼン資料の作り方 - リニューアル増量版

エバンジェリスト養成講座

マイクロソフトエバンジェリストをつとめる西脇資哲さんの本。同名の研修もあって、この研修がとてもオススメです。研修受講と書籍のセットがおすすめ。 余談ですが、私はこの研修を2回受けました。

アジャイル関連

いちばんやさしいアジャイル開発の教本

薄くて読みやすいが、内容は濃い。アジャイル開発の本質をきちんと押さえてくれている。

Ryuzee.com

アジャイルコーチなどをされているRyuzeeこと吉羽龍太郎さんのサイト。

こちらのリンク以外にも、スライドやブログなど、良質なコンテンツがたくさんあります。

アジャイルについてマネージャーが知るべき97のこと | Ryuzee.com

新規事業関連

i2keyさんのスライド

黒田樹(i2key)さんのSlideShareたち。キラキラ事例ではない、実際のビジネスの現場でのリーンスタートアップアジャイル開発のはなしがたくさんあります。本当に素晴らしい内容なので、全部目を通すことをおすすめします。 リーンスタートアップと顧客開発とアジャイル開発を一気通貫するッ #devlove #devkan

仕事汎用

イシューからはじめよ

問題解決のアプローチとして、解くべき問題を見定める部分にしっかり時間をかけることを教えてくれます。

世界で一番やさしい会議の教科書

会議をより良いものにしたい人向け。他にもファシリテーションについて述べたもっと情報量の多い本などもあるが、まずはこの本の内容を修得して実践するところから、がちょうど良い。ファシリテーションのテクニックなどはその先かな。

Podcast

fukabori.fm

iwashiさんがホストとなって、毎回いろんな人をゲストに呼んで深掘りトークを行う。アジャイル開発からデザインパターン、技術的なコアな話など、テーマは多岐にわたります。興味ある回からつまみ聴きすると良いです。

fukabori.fm | Podcast on Spotify

texta.fm

PIXTAのCTOである後藤さんとt_wadaさんの1on1的な対話を配信。エンタープライズアプリケーションアーキテクチャの話などのtech寄りの話題が面白い&ためになる。

texta.fm | Podcast on Spotify

テスト自動化のもたらすもの

テストコードを整備してテスト自動化を実現することで、何がうれしいのか。自分として現時点の見解を言語化しておく。
なお、自身の経験をもとにモヤモヤしていたところに、t-wadaさんの動画やpodcastによって、視界が開けたというのが正直なところです。

前提

ここでは、『テスト自動化』は、テストを自動的に実行できる状態にすることを言います。
テストコードをいつ書くのかはとくに限定せず、テストファーストテスト駆動開発でもよいし、あとからテストコードを書くスタイルでもよい。
いずれにせよ大事なことは、人手を介さず自動的(手動トリガー含む)に同じテストを繰り返し実行できる状態であることです。

テスト自動化の語彙について

テスト自動化に関してはいくつかの用語がある。 いちばん広い概念がテスト自動化で、その中でも、先にテストコードを書いてから実装に着手するやり方をテストファーストという。さらにテストファーストの中でも、あるルールに沿って小さなリファクタリングとテストを繰り返して実装を進めていく、テスト駆動開発という手法がある。

テスト駆動開発についての動画:[動画で解説]和田卓人の“テスト駆動開発”講座:連載|gihyo.jp … 技術評論社

テスト自動化の意義

もともと自分は、テスト自動化の意義は、アジャイル開発などにおける "品質の確保" だったり、毎回手動テストするのではなく自動化することで"コスト削減" すること、ぐらいのイメージで捉えていた。

つまり、開発とリリース(デリバリー)を繰り返していくとき、毎回リリース前の動作確認を手作業で実施していては追いつかないから、テスト自動化が必要になってくると考えていた。
実際にそれは正しいのだが、それ以外にもテスト自動化のメリットはある事が見えてきたので、言語化しておく。
そのひとつが、自動テスト可能なものは積極的なリファクタリングが可能になる、ということである。

テストコードがない場合、ある機能追加をしようとしたときに、設計の良し悪しではなく、単に差分の少ない方を選択してしまうことが起こりがちである。
大胆な変更による影響範囲が見えないので、変更量を少なくすることで、既存部への影響を抑えたい気持ちになる。(これを俗にdiffの小さい開発と言ったりする)

しかしテスト自動化がきちんと整備されていれば、差分の多さや構造変更を気にせずに、本来あるべき構造、正しい設計を採用しやすくなる。他の箇所への影響があったときに気付くことの出来る自動テストというセーフティネットがあるからだ。 これによって、技術的負債をため込まずに済む。少なくとも負債をため込まずに返済しやすくなる。

そうすると、長い目(とはいえ1か月で損益分岐点はおとずれるとされている)で見れば、開発のスピードを落とさずに、かつ(外部および内部)品質の高いソフトウェアを作り続けることが可能になる。 それはつまり、ビジネスにおける仮説検証や要求デリバリーのリードタイムを短縮することにつながる。

また、テスト自動化ができていれば、任意のタイミングで何回でもテストを走らせることも可能になる。
例えばスクラムで開発を進めている場合、リグレッションテストを人間が行う場合だと、どうしてもある程度タイミングを決めて、スプリントの後半でテストを実施することになる。
そうすると、デグレが発覚するのもそのタイミングになる。

一方でテスト自動化している場合は、もっと小刻みに、例えばプルリクのタイミングなどでテストを実施することも可能なので、開発の影響によるデグレをより早く検出できる。
これはいわゆるシフトレフトと呼ばれる状態で、開発してすぐにバグが見つかる方が、記憶も新しいので修正コストも低くできる。
また、デグレによる手戻りがスプリント後半で発覚すると、場合によってはスプリント内でデリバリー可能なものが出来上がらず、スプリントゴールが達成できない事態も起こりうる。 スプリントの成果物を安定してデリバリーするには、こまめな動作確認ができるほうが良い。

手動テストは無くなるか?

では、手動テストは不要になるのか、無くせるのかという点についても述べておく。 現時点の私の結論としては、無くならない。というか、無くしてはいけない。

テスト自動化が担保してくれることは、結局のところ『テストコードで書いた振る舞いが、今も変わらず同じ動きをしていること。』である。つまり、前と変わっていないということが保証されるだけといえる。

つまり、『そもそもそんな動きをするとは思っていなかった』といった未知のバグを見つけることは、テスト自動化のみでは現状はまだ難しい。したがって、そこは人間の出番となる。

人間が探索的にテストを実施し、発見したバグを再現(検出)するテストコードを追加していくことで、次回以降はそのバグは起こっていないことが保証される。

また、仕様どおりに動き、自動テストがすべて合格していても、ユーザーとしての使用感がまずいことだってあり得る。 単体機能の操作では良いものに見えていたものが、実際のユーザーとしての一連の体験の中で触れてみると、メンタルモデルとのズレによって違和感が生じる場合もある。

これからの品質保証人材には、①『具体化可能なテスト内容を自動化するスキル』と、②『具体化できない未知の不具合を見つけ出せるスキル』が必要だと考えている。

※正確には、前者のような確認をチェッキング、後者のような探索要素を持つものをテスティングと呼ぶらしいが、今回はどちらもテストと表現しています

まとめ

テスト自動化のもたらすもの
(これまでの文中に書けていない事も挙げています、すみません)

  1. テスト実施工数の削減
  2. 安定した一貫性のあるテスト実施内容の実現 (機械はミスをしないし、合格基準もあいまいではテストが書けないので、そうなる)
  3. リファクタリングに対するハードルを下げ、内部品質を高めやすくなる
  4. スプリントごとのデリバリーの安定化
  5. 外部環境の変化による動作不良の早期発見
  6. (主にユニットテスト)テスト自動化を進めていくと、自然と外部とのI/Fに依存する部分と、そうでない部分を分けていくインセンティブが働く。その結果、外部依存の高い箇所を疎結合にする設計実装のスキル獲得にもつながる

リーンスタートアップとかアジャイル開発

リーンスタートアップシリコンバレーで盛り上がり、日本にも上陸してかなり浸透していると思う。 一方、最近になってとくに大企業では新規事業でイノベーションだ!みたいな話がよくあるが、リーンスタートアップ自体を知らないままに「仮説検証」とか「MVP」とかのワードだけを何となく使っている組織をよく見かける。

リーンスタートアップの出自

リーンスタートアップアジャイル開発が似ている、と言う人がいるが、それはそのとおりである。 なぜなら、リーンスタートアップの生みの親であるエリック・リースが、師匠(と呼ぶのかは微妙だが)であるスティーブン・ブランクの提唱する顧客開発モデルという手法に、ソフトウェア開発のアジャイル開発を掛け合わせて創り上げたのがリーンスタートアップだからである。

アジャイル開発との違い

アジャイル開発との違いは、アジャイル開発がソフトウェア開発(ハードウェア開発の場合もある)にフォーカスしているのに対し、リーンスタートアップは、事業アイデアの種を世に出し、事業としてスケールするまでの広い範囲をスコープとしている。

ただし、具体的なアイデア出しの方法や、ソフトウェア開発手法については扱っていない。 スタートアップのやりかたとして、あらゆることを仮説として捉え、それを検証しながら進めていくというやりかたである。

違い、と書いたが、実際には違いではなく包含関係にあるといえる。高速に仮説検証を回して学びを得ながらプロダクト開発をする。そのために開発手法はアジャイル開発を採用する、という理解が良いように思う。

なお、高速なアジャイル開発は、いざやろうとすると高度な技術レベルと幅広いスキル、ツールの選定と使いこなしが開発チームには求められる。 どこかの誰かに委託してそう簡単に実現できるモノではないが、そこが分かっていないままにリーンスタートアップを取り入れようとするチームが、古めの企業にはとても多い。

リーンスタートアップにとって大事なこと

リーンスタートアップが目指しているのは、資金の少ないスタートアップが一撃死するような大きな失敗を避けることである。逆に、小さく失敗することについては許容することが重要である。早めに気づいて方向転換しましょう、ということ。 失敗というより、仮説を検証した結果、間違っていたことを学んだ、という姿勢を持つことがポイントになるが、これが実際の起業や社内新規事業においては難しい。 都合の良い結果解釈をしがちである。

このあたりは、どうすればうまく仮説検証結果から次の動きを見いだせるか、まだ自分も試行錯誤している。

AWSで手軽に使えるアクセス制限

はじめに

不特定多数に公開するWebアプリではない場合、セキュリティの観点からするとできればサインイン画面まで到達する前にアクセス制限をかけ、そもそもWebアプリまで到達できないようにしたい。 サインイン認証をMFAなどで強固にすることで不正アクセスの対策にはなるが、そもそもアクセスされてサインイン試行されまくるとそれだけでサーバーに負荷がかかる。

そこで今回はAWSマネージなサービスだけでアクセス制限を実現する方法を整理したいと思います。

アクセス制限する方法

クライアントからのアクセスを制限する方法はいくつか考えられる。

  • 接続元のIPアドレスによる制限
  • クライアント証明書による認証
  • 外部IdPによる認証

AWSサービスによってこれらの利用可否が異なるので、整理します。

AWSサービスごとの利用可能なアクセス制限方法

ざっくりまとめると次の表のとおり。

IPによる制限 クライアント証明書 外部認証 その他
API Gateway △Cognitoのみ Lambdaオーソライザで作り込みが可能
ALB × 〇 OIDC対応
WAF × × SQLインジェクションなどアプリレイヤーでのセキュリティ強化

API Gateway

  • 接続元のIPアドレスによる制限が可能。リソースポリシーを使用することで実現可能。
  • mTLSによるクライアント証明書の認証が可能
  • APIキーによる制限
    • APIキーを知っていれば結局どこの誰からでもアクセスできるため強度としては不十分。
  • Cognitoユーザープールによる認証。アクセスしてくるユーザーをCognitoで管理することが前提となる。

ALB(Application Load Balancer)

  • 接続元IPアドレスによる制限が可能。
    • WAFでも制限できる。WAFを使うほうがより高度な設定/制限が可能なため便利。
  • OpenID Connect(OIDC)やCognitoによるユーザー認証が使える。ALBアクセス時にユーザー認証を要求する。 認証済みのリクエストのみをALBのターゲット(Webアプリ)に送信する。
  • クライアント証明書による認証はできない。

WAF

  • 接続元のIPのアドレスによる制限が可能
  • クライアント証明書認証は不可
  • 外部IdPによる認証は不可

なお、WAFを適用できるAWSサービスは以下のとおり

まとめ

いろんなサービスで少しずつ取れる手段が異なるので注意が必要。 うまく自身の構成で使うことができれば簡単かつ管理不要でセキュリティ強度を高めることができるので積極的に使っていきたいところ。 AWS IoTで使われているような、クライアント証明書の発行とアクセス認証をセットで簡単に使えるといいなぁと期待しています。

ALBの設定でAuth0でOIDCでクライアント認証をやってみたのでメモ

はじめに

AWSのALB(Application Load Balancer)にOIDCによる認証を設定しました。

認証を追加することで、ALB(の後ろにいるWebアプリ)へのリクエストがあった際、不特定多数のリクエストをWebアプリ側に到達させることなく、ALB側で拒否することができます。 特定の人にしか使わせない想定のアプリの場合、IPで制限するなどの手段もありますが、IP以外の方法でフィルタすることができますので、より使いやすいです。 アクセス制限には以下のようないくつかのやり方があると思います。

  1. 接続元IPアドレスを制限する方法
  2. クライアント証明書による認証をする
  3. OIDCなどによるクライアント認証

今回は一番最後のアプローチを採用しました。ALBでは1か3のやり方ができますが、IPによる制限はリモートワーク環境では使いづらいためです。

また、OIDCのIdPとしてAuth0を使ったのですが、ALB側の設定項目がAuth0の場合は何を設定すれば良いのか少し分かりづらかったのでメモを残しておきます。

設定内容

ALBのリスナー設定画面

リスナーの認証設定

発行者

https:// + Auth0のDomainの値をつなげて、https://xxxxx.jp.auth0.com/形式にする

最後に/をつけるのを忘れないこと。私はこれをつけ忘れて一日ハマりました。。。

認証エンドポイント(認可エンドポイント)

https://<YOUR_AUTH0_DOMAIN>/authorize

トークンエンドポイント

https://<YOUR_AUTH0_DOMAIN>/oauth/token

ユーザー情報エンドポイント

https://<YOUR_AUTH0_DOMAIN>/userinfo

クライアントID

 ・Auth0でApplicationを作成すると生成されるClient IDの値

クライアントのシークレット

 ・Auth0でApplicationを作成すると生成されるClient Secretの値

これでOKです。

感想

いい感じです。 Webアプリのセキュリティを確保する上で、そもそもWebアプリまで到達できるユーザーは絞っておきたいです。
ログイン認証を強固にすることももちろん大切ですが、それだけではセルフマネージなサーバーに対してログイン試行はできてしまうので、アクセス負荷がかかります。 できるだけ、AWSマネージな仕組みでアクセスをフィルタリングできたほうが楽ですよね。