<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.10nin.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.10nin.com/" rel="alternate" type="text/html" /><updated>2024-11-28T18:24:25+09:00</updated><id>https://www.10nin.com/feed.xml</id><title type="html">10nin.com</title><subtitle>“Study hard what interests you the most in the most undisciplined, irreverent and original manner possible.” —— Richard Feynmann</subtitle><entry><title type="html">手元のGitブランチを整理するPowerShellスクリプトを書いてみた</title><link href="https://www.10nin.com/git/powershell/2022/04/25/powershell.html" rel="alternate" type="text/html" title="手元のGitブランチを整理するPowerShellスクリプトを書いてみた" /><published>2022-04-25T00:00:00+09:00</published><updated>2022-04-25T00:00:00+09:00</updated><id>https://www.10nin.com/git/powershell/2022/04/25/powershell</id><content type="html" xml:base="https://www.10nin.com/git/powershell/2022/04/25/powershell.html"><![CDATA[<p>仕事で開発をしていると、リモートでマージされたブランチがいつまでも手元の環境に残ってしまう事があり、不便に感じていました。</p>

<p>そこで、まるっと削除を行う次のようなPowerShellスクリプトをこさえました。</p>

<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">git</span><span class="w"> </span><span class="nx">branch</span><span class="w"> </span><span class="nt">-v</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Select-String</span><span class="w"> </span><span class="s2">"\[gone\]"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="p">{</span><span class="bp">$_</span><span class="w"> </span><span class="o">-split</span><span class="w"> </span><span class="s2">" +"</span><span class="p">}</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">Select-String</span><span class="w"> </span><span class="s2">"feature|fix|hotfix"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="p">{</span><span class="n">git</span><span class="w"> </span><span class="nx">branch</span><span class="w"> </span><span class="nt">-D</span><span class="w"> </span><span class="bp">$_</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>要するに <code class="language-plaintext highlighter-rouge">[gone]</code> のブランチのうち、 <code class="language-plaintext highlighter-rouge">feature</code>, <code class="language-plaintext highlighter-rouge">fix</code>, <code class="language-plaintext highlighter-rouge">hotfix</code> を含んでいるブランチを <code class="language-plaintext highlighter-rouge">git branch -D</code> で消すという操作です。</p>

<p>Linux環境でも似たようなスクリプトを使っていたのですが、Windowsだとgrepすら無くて調べるのに時間を要してしまいました。</p>

<p>今の所結構快適に動いてくれていて、手元のブランチもスッキリして良い感じです。</p>

<p>次は、ブログのエンジンをHugoに移そうと考えているので、そのあたりの作業ができたらまとめたいと思っています。</p>]]></content><author><name></name></author><category term="git" /><category term="powershell" /><summary type="html"><![CDATA[仕事で開発をしていると、リモートでマージされたブランチがいつまでも手元の環境に残ってしまう事があり、不便に感じていました。]]></summary></entry><entry><title type="html">Visual Studioでビルドする時に、 C:\Users\ユーザ名\AppData\Local\Tempな場所でエラーが出る場合の対処法</title><link href="https://www.10nin.com/dotnet/csharp/visualstudio/2022/04/11/builderror.html" rel="alternate" type="text/html" title="Visual Studioでビルドする時に、 C:\Users\ユーザ名\AppData\Local\Tempな場所でエラーが出る場合の対処法" /><published>2022-04-11T00:00:00+09:00</published><updated>2022-04-11T00:00:00+09:00</updated><id>https://www.10nin.com/dotnet/csharp/visualstudio/2022/04/11/builderror</id><content type="html" xml:base="https://www.10nin.com/dotnet/csharp/visualstudio/2022/04/11/builderror.html"><![CDATA[<p>なんだかんだとハマってしまったのでメモ。</p>

<p>具体的には、ビルドする際に <code class="language-plaintext highlighter-rouge">WoerkerExtensions.csproj</code> が見つからないといったエラーが出る場合の対処法になる。</p>

<p>ソリューションをクリーンしても、リビルドしても、システムを再起動しても解決しないこの現象は、複数のソリューションやプロジェクトを行き来する中で、NuGetで取得して使っている共通名称のパッケージを削除したような場合に発生していると思われます。</p>

<p>この現象に遭遇した場合、NuGetのキャッシュを削除することで対処します。<br />
具体的には</p>

<ol>
  <li>ツール → NuGetパッケージマネージャ → パッケージマネージャ―設定でダイアログを開く</li>
  <li>“すべてのNuGetキャッシュをクリア” ボタンを押す</li>
  <li>OKボタンでダイアログを閉じる</li>
  <li>再度ビルドする</li>
</ol>

<p>少なくとも、私の環境では上記手順で問題を解決することができました。</p>]]></content><author><name></name></author><category term="dotnet" /><category term="csharp" /><category term="visualstudio" /><summary type="html"><![CDATA[なんだかんだとハマってしまったのでメモ。]]></summary></entry><entry><title type="html">WSL上のUbuntu環境に.NETの環境を整える</title><link href="https://www.10nin.com/linux/dotnet/csharp/2022/03/31/dotnet-on-linux.html" rel="alternate" type="text/html" title="WSL上のUbuntu環境に.NETの環境を整える" /><published>2022-03-31T00:00:00+09:00</published><updated>2022-03-31T00:00:00+09:00</updated><id>https://www.10nin.com/linux/dotnet/csharp/2022/03/31/dotnet-on-linux</id><content type="html" xml:base="https://www.10nin.com/linux/dotnet/csharp/2022/03/31/dotnet-on-linux.html"><![CDATA[<p>LTSもぼちぼち次のバージョンが出てくるので、今更感のあるメモですが。</p>

<h2 id="署名キーとパッケージリポジトリの追加">署名キーとパッケージリポジトリの追加</h2>

<p>次のコマンドでMicrosoftの署名キーを信頼し、dotnetの関連パッケージをAPT経由で取得できるようにパッケージリポジトリの追加を行う。</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> /tmp <span class="c"># 適当な作業フォルダで作業すると良い</span>
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb <span class="nt">-O</span> packages-microsoft-prod.deb <span class="c"># パッケージ取得</span>
<span class="nb">sudo </span>dpkg <span class="nt">-i</span> packages-microsoft-prod.deb <span class="c"># インストール</span>
<span class="nb">rm </span>packages-microsoft-prod.deb <span class="c"># 後始末</span>
</code></pre></div></div>

<h2 id="net6環境のインストール">.NET6環境のインストール</h2>

<p>記事執筆時点では.NET6がLTSで利用できるので、次のコマンドで.NET6の開発環境をインストールする。</p>

<p>開発についてはSDKがあれば十分だと思う。</p>

<p>もしランタイムが必要な場合は、記事末尾の参考リンクにある情報に従って、ASP.NET Coreサポートのあるなしで、自身の環境に適した方をインストールすると良い。</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get update<span class="p">;</span> <span class="se">\</span>
  <span class="nb">sudo </span>apt-get <span class="nb">install</span> <span class="nt">-y</span> apt-transport-https <span class="o">&amp;&amp;</span> <span class="se">\</span>
  <span class="nb">sudo </span>apt-get update <span class="o">&amp;&amp;</span> <span class="se">\</span>
  <span class="nb">sudo </span>apt-get <span class="nb">install</span> <span class="nt">-y</span> dotnet-sdk-6.0
</code></pre></div></div>

<p>インストールが完了したら、インストールされた.NETのバージョンを確認しておく。</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dotnet <span class="nt">--version</span>
</code></pre></div></div>

<h2 id="参考リンク">参考リンク</h2>
<p><a href="https://docs.microsoft.com/ja-jp/dotnet/core/install/linux-ubuntu">Ubuntuに.NETをインストールする</a></p>]]></content><author><name></name></author><category term="linux" /><category term="dotnet" /><category term="csharp" /><summary type="html"><![CDATA[LTSもぼちぼち次のバージョンが出てくるので、今更感のあるメモですが。]]></summary></entry><entry><title type="html">Ubuntuでcargo-editのインストール時にNo package ‘openssl’エラーになった時の対処</title><link href="https://www.10nin.com/rust/cargo/2022/03/25/CargoEdit.html" rel="alternate" type="text/html" title="Ubuntuでcargo-editのインストール時にNo package ‘openssl’エラーになった時の対処" /><published>2022-03-25T00:00:00+09:00</published><updated>2022-03-25T00:00:00+09:00</updated><id>https://www.10nin.com/rust/cargo/2022/03/25/CargoEdit</id><content type="html" xml:base="https://www.10nin.com/rust/cargo/2022/03/25/CargoEdit.html"><![CDATA[<p>新しいPCにRust環境を構築していて、cargoの便利ツールであるcargo-editの導入時に表題のエラーでつまずいたのでメモ。</p>

<p>Ubuntuで</p>

<p><code class="language-plaintext highlighter-rouge">cargo install cargo-edit</code></p>

<p>した時に、 <code class="language-plaintext highlighter-rouge">No package 'openssl'</code> エラーになったら</p>

<p><code class="language-plaintext highlighter-rouge">sudo apt-get install libssl-dev</code></p>

<p>することで解決できる。ちなみに、 <code class="language-plaintext highlighter-rouge">pkg-config</code> パッケージも必要なようなので、不足している場合は同時に <code class="language-plaintext highlighter-rouge">apt install</code> するのが良いと思います。</p>]]></content><author><name></name></author><category term="rust" /><category term="cargo" /><summary type="html"><![CDATA[新しいPCにRust環境を構築していて、cargoの便利ツールであるcargo-editの導入時に表題のエラーでつまずいたのでメモ。]]></summary></entry><entry><title type="html">OneMix4を買いました</title><link href="https://www.10nin.com/pc/gadget/2022/03/24/NewGear.html" rel="alternate" type="text/html" title="OneMix4を買いました" /><published>2022-03-24T00:00:00+09:00</published><updated>2022-03-24T00:00:00+09:00</updated><id>https://www.10nin.com/pc/gadget/2022/03/24/NewGear</id><content type="html" xml:base="https://www.10nin.com/pc/gadget/2022/03/24/NewGear.html"><![CDATA[<h2 id="抑えられなかった物欲">抑えられなかった物欲</h2>
<p>普段私用で使っているPCはASUSのゲーミングノートで、CPUにAMD Ryzen7を搭載して、GPUもちゃんと載っている等スペックにこだわった分大きくて、ノートPCながらバッテリの持ちが悪く、ちょっと自室からリビングに持ち出して家族の居るところで何か作業しようとしてもなかなか面倒臭さが先立ってしまう状況でした。</p>

<p>そんな折、ここひと月ほど「スペック高めのUMPC的なサブ機が欲しいなあ」という気持ちが高まっており、高みに達した結果、OneMix4という10インチクラスのモバイルPCを購入しました。</p>

<h2 id="求めた条件">求めた条件</h2>
<p>私は日本語キーボード使いなので、日本語キーボードを使えることが必須でした。そして今買うならという事でWindows11に対応している事。</p>

<p>さらに持ち歩きしやすいサイズなので、10インチ以下のサイズで収まる事と、重さも1kgを切っている製品を探しました。</p>

<p>CPU/GPUヘビーなタスクは母艦であるゲーミングPCでこなすので、そういうのは必要ありません。とはいえ勉強用のコードを書くぐらいのことはしたいのと、外付けのディスプレイに接続することも考えてHDMIポートと16GB程度のメモリが載っているのが望ましいという条件で探し始めました。</p>

<p>条件を絞れば絞るほど候補は少なく、UMPCの雄であるGDP Pocket 3は日本語キーボードが無いために購入候補から外れました。</p>

<p>こうなると、OneMix3S、OneMix4、少し大きくなりますがSurfaceシリーズぐらいしか選択肢になりません。</p>

<p>Surfaceはタブレット用途に特化していて私のようにPC用途中心で使うには使いづらそうに感じたので、OneMix3SかOneMix4かに絞り込みました。</p>

<p>で、結局OneMix4を購入したわけです。</p>

<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=10nin-22&amp;language=ja_JP&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=as_ss_li_til&amp;asins=B08WQ6S25D&amp;linkId=c785fd01a77d222348ed085a87669f05"></iframe>

<p>画像や動画を扱う事はほぼ無いので、ストレージは512GBにしました。<br />
購入にあたっては、ハイビーム秋葉原本店を利用。店員さんに直接疑問点を聞くこともできる上、実機を触りながら比較検討出来て、とても良い購買体験でした。</p>

<h2 id="使って一晩経ってみて">使って一晩経ってみて</h2>
<p>その場でお持ち帰り…したかったのですが、在庫が無いという事で後日配送になりました。</p>

<p>楽しみに待つこと数日、ようやく手元に届いたのが昨晩の事です。そこから新しいオモチャを手に入れた子供のように遊んでみていますが、その中で気づいた良い点と悪い点について一度まとめておこうと思います。</p>

<h3 id="よかったポイント">よかったポイント</h3>

<ul>
  <li>指紋認証はすばらしい</li>
  <li>持ち歩くのを躊躇しない重さと大きさ</li>
  <li>タッチスクリーンの感度は良好</li>
  <li>バッテリの持ちは今のところ気になるほどでなく、ネットワークも快適</li>
</ul>

<h3 id="いまいちなポイント">いまいちなポイント</h3>

<ul>
  <li>キーピッチは十分な大きさがあるのですが、変則的なキー配列になっているために右手側のキーが特にタイプしにくいと感じます。</li>
  <li>トラックパッドはクリック感が悪い</li>
  <li>画面が小さいため、一部ソフトウェアが操作できないぐらいのウィンドウサイズになるが、救済機構がない</li>
  <li>画面がギラリと反射するグレア加工なので反射が気になる</li>
  <li>タッチ操作すると画面に指紋つきがち</li>
</ul>

<h2 id="総括">総括</h2>
<p>キーボード周りについては、PowerToysを導入してあれこれ使いやすいようにキーの位置を変更するようにしました。<br />
画面のグレア加工についても、別途保護フィルムを調達することにしたので、それが届けば満足いく環境になるのではないかと思っています。</p>

<p>新しいマシンで勉強やブログの更新がはかどると良いなと思っています。</p>]]></content><author><name></name></author><category term="pc" /><category term="gadget" /><summary type="html"><![CDATA[抑えられなかった物欲 普段私用で使っているPCはASUSのゲーミングノートで、CPUにAMD Ryzen7を搭載して、GPUもちゃんと載っている等スペックにこだわった分大きくて、ノートPCながらバッテリの持ちが悪く、ちょっと自室からリビングに持ち出して家族の居るところで何か作業しようとしてもなかなか面倒臭さが先立ってしまう状況でした。]]></summary></entry><entry><title type="html">OKRについてまとめる</title><link href="https://www.10nin.com/okr/2022/03/09/okr.html" rel="alternate" type="text/html" title="OKRについてまとめる" /><published>2022-03-09T00:00:00+09:00</published><updated>2022-03-09T00:00:00+09:00</updated><id>https://www.10nin.com/okr/2022/03/09/okr</id><content type="html" xml:base="https://www.10nin.com/okr/2022/03/09/okr.html"><![CDATA[<p>それなりのキャリアの中で何回かOKRをやってみて、OKRの難しさであるとか、チームとしてつまずいたなあと思うようなポイントが複数あったので、少しまとめておこうと思います。<br />
メモを列挙している形に近いのでだいぶ長いですが、参考になれば幸いです。<br />
（OKRとはなんぞや？という話は書いていません。OKRそのものについて知りたい方は、末尾にあげる参考書籍や他のサイトをご覧いただくのが良いと思います）<br />
いずれも、私が職務遂行の中でOKRを実践した経験によるもので、科学的な根拠やOKRの正式なトレーニングを受けたことによるモノではありません。</p>

<h2 id="oとkrの決め方">OとKRの決め方</h2>
<p>OとKRの決め方は毎回悩むところです。<br />
なにしろ、書籍(1.)によると「重要で、具体的で、行動を促し、（理想を言えば）人々を鼓舞するようなものだ」なんて言われていて体力を使う会議になりがちですし、別の書籍(1.)では「OKRを２週間以内に設定できなければ、優先事項を見直す必要がある。会社が結束するためのゴールを設定する以上に重要な仕事などない。」なんて書かれているので、事業にコミットしようという気持ちが強ければ強いほど、言葉尻に熱意を注ぐような、重箱の隅をつつく議論になりがちだからです。</p>

<p>OKRを決めるときに必ず守りたいのは、「Oから決める」という事です。<br />
KRから決めると、大抵の場合ムーンショットにならなかったり、お飾りのOになってしまうからです。</p>

<h3 id="oを決めるためのプラクティス">Oを決めるためのプラクティス</h3>
<p>まずは、私が何度かOKRをやってきた中で良いと思ったOを決めるためのプラクティスを紹介します。<br />
ただ、これもやってみた感触として良かったなと思える方法なだけで、正解ではないと思いますし、こうして立てたOも期の最後に振り返ると全く達成できていないケースもありましたので、参考程度に見ていただくのが良いと思います。</p>

<h4 id="考えたoはミッションやバリューの方向を向いているか">考えたOは、ミッションやバリューの方向を向いているか</h4>
<p>目の前の仕事に目がいくと、ミッションやバリューの方向を向いていないOを定めがちです。</p>

<p>OKRのOはムーンショットと呼ばれる達成困難に思える高い目標を掲げるわけですが、これは高い目標を達成するために集中する事で、通常とは異なるイノベーティブな発想ややり方を生み出すためでもあります。<br />
そのためには、Oが自分たちのチームやプロダクトが出すべきミッションやバリューに向かっている必要があります。<br />
Oの決定で行き詰まってしまった時は、一度ミッションやバリューがなんだったかを思い返すと良いです。</p>

<p>例えばECサイトを構築しているとして、顧客から伝票出力についてのクレームが入っているタイミングでOKRを決めようとすると、このクレームに目をつぶって議論することが難しくなります。<br />
それでも、自分たちのミッションやバリューに立ち返って、そこから演繹的に議論する事で、Oを議論するタイミングに入ってきているノイズから自分たちの価値観を守ることができると思います。</p>

<h4 id="アウトカムで考える">アウトカムで考える</h4>
<p>「定量的なOではなく、定性的なOにするべき」というのは多くのOKR関連書籍で言われている事ですが、本家OKR宣伝書とも言える書籍(1.)を参照すると、決してその限りではない事がわかります。<br />
そこで、Oについては、アウトプットではなくアウトカムを狙うというのもひとつの方法だと思います。<br />
すなわち、OKRの実施期間である3ヶ月が経過したときに、周りからどのように見られていたいか？この3ヵ月、ミッションやバリューに向かって活動した結果、何を得ていたいのかをOとして掲げる方法です。<br />
これは、アウトプットを重視したO（XXの達成を目指す系のO）に比べると感情に訴えかけるものになりやすく、やる気を出すOを掲げるコツでもあるかなと思いました。</p>

<h4 id="期間を強く意識する">期間を強く意識する</h4>
<p>ミッションやバリューの方向を向くと、どうしても高い目標を掲げがちになってしまいます。<br />
しかし、OKRは3ヶ月とか半年のサイクルで回っていくものなので、この部分を考えてみると、OKRを実践した期間で、今の時点よりもミッションやバリューが目指しているものに近づいていけば良いということに気付きます。<br />
そこで、例えば3ヶ月でやるなら3ヶ月という期間を強く意識して、その中でのムーンショット的なOを考えるのが良いと思っています。<br />
不思議なもので、期間を強く意識するとより現実味のあるOが議論の俎上に上る率が高かったように思います。<br />
保守的になりすぎて、ルーフショット（屋根の上）程度の目標になってしまう事も度々見られましたが、そこはチームの目標であればチームによる議論で、個人の目標であれば上長との議論で誤りを訂正していけるはずです。<br />
期間を強く意識してOをブレイクダウンさせなければいけない目安としては、これまでやってきたOKRで、毎回Oが同じ事を指していて変わらないとすれば、それはもっと小さなOを複数達成すると到達できるOなのかもしれないと思います。</p>

<h4 id="そのoは地に足がついているか">そのOは地に足がついているか？</h4>
<p>OKRについては、常々「ムーンショットな目標を立てる」と言われているため、圧倒的に高い目標を立ててしまいがちです。<br />
これを「マーズショット」と表現するケースがありますが、月に行く目標を立てないといけないのに、月を飛び越して火星に行く目標を立ててしまうケースが起こりえます。<br />
火星に行く目標は大抵の場合とても抽象的で、カッコいい言い回しで表現できるので魅力的なOに映ってしまいがちです。また、言葉の力強さに押し切られてチームの目指すものがこの手のOに決まってしまうこともあります。</p>

<p>けれども、真に価値のある、有効なOを打ち立てるためには、一旦立ち止まって「その前に月に行けていないよね？」というような視点の議論が必要です。<br />
まずは肉眼で大きく見えている目標から順に切り崩していくのが良いと思います。<br />
（空を見上げてみればわかるように、月は火星よりもずっと大きく、はっきり見えているはずです）</p>

<h4 id="さあ今oを出そうをやめる">さあ、今Oを出そう！をやめる</h4>
<p>「OKRを決める会議をします」と言って人を集めて、その場でOKRを出させるやり方はあまり良いやり方ではありませんでした。<br />
事業規模が小さく、全員が「今何をしなければ自分たちの明日が無いか」を常に意識している状態であればこのやり方でも良いと思いますが、その段階を超えている事業であれば、事前に個々人にOKRを考えさせてくるのが良いと思います。</p>

<p>ただ、このとき大切なのは心理的安全性です。どんなOKRを立てて発表したとしても、会議の場で辱められたり惨めな気持ちになったりしない人たちの集まりでなければ、考えてきたOを出し合って決めるのは難しい仕事になると思います。</p>

<p>もし心理的安全性が醸成されていないチームでOKRを取り入れようと思うのであれば、まずはバカな事を言っても辱められたり惨めな気持ちになったりしないチームビルディングを優先させるべきだと思います。</p>

<h4 id="githubのissueやpullrequestに上げて各人で読んでコメントしようは避けるべき">「GitHubのIssueやPullRequestに上げて、各人で読んでコメントしよう」は避けるべき</h4>
<p>管理する側にとっては、皆がOKRに対して何かやってくれていることが見えますし、各人の掲げたOやKRを読んでくれていること、そしてそこでコメントによる議論が行われることで活発に動いているように見えるので、とても良い方法であるように錯覚してしまいます。</p>

<p><strong>けれども、私の経験的からすると、これはよくない議論の進め方です。</strong></p>

<p>なぜなら単に議論が長引いたり重箱の隅をつついたりするような、内容の薄いものに力をかけてしまいがちで、「OKRを決める」という作業に無駄に時間を持っていかれた結果、本来やらなければならい価値を創造する仕事をするための時間が削がれていくからです。<br />
最悪なものを挙げると、ちょっとした誤字を指摘するコメントがついてしまったり、語尾の言い回しを指摘するような議論に発展してしまったり、ファイル名に日本語を使っているのがよく無いなどという全く実りのないコメントが飛び交ってしまってチームが疲弊するケースがあります。<br />
（いずれも私が実際に経験したものです）<br />
本来の価値を出すための目標を決めるのに、価値を出せない時間が増えていくのは本末転倒だと言えます。</p>

<p>議論するのであれば、各人で持ち寄って、ある場を設けて一気に議論するべきで、腰を据えて誰かの考えたOKRを批評するような時間を設けるべきではありません。</p>

<h4 id="細部にこだわらない">細部にこだわらない</h4>
<p>（これは「OKRの白い本」による罪だと思いますが）Oにはムーンショットや具体的である事などの諸条件に加えて「わくわくして、ベッドから飛び起きたくなるようなもの」を設定するように言われています。</p>

<p>これによって、語尾のちょっとした言い回しや嵌め込む単語など細部にこだわった議論が展開されてしまう可能性があります。<br />
Oの意図するところが全員に齟齬なく伝わっているのであれば、細部の言い回しや単語の置き換えにはこだわらないのが良いでしょう。</p>

<p>「ヨーロッパに行く」というOを掲げた結果、チームの皆がフランスやドイツやイタリア等、異なる国々を思い描いて仕事をしていたのでは、本当の目的地であるスイスにたどり着けないワケですが、「スイスに行く」といも目標を立てられたのであれば、「スイスに行ってやる！」「目指せスイス！」などといった、（Oの本質が変化しない）言い回しの違いを決めるために時間を使うべきではないです。</p>

<h3 id="krを決めるためのプラクティス">KRを決めるためのプラクティス</h3>
<p>つづいてKRを決めるためのプラクティスです。<br />
先述したとおり、Oを決めてからKRを決めるワケですが、主要な結果(KeyResult)という語感が良くないのか、KRを「達成するべき数値目標」と捉えてしまうケースが多いようです。</p>

<p>計測可能であることは大切な事ですが、KRは達成するべき数値目標ではなく、バロメータである事を理解する必要があります。</p>

<p>つまり、今Oに向かって正しく歩けているか、歩けているとしてそれはどのぐらいの速度か、といった情報を得るためのものがKRであって、達成するべき目標はあくまでOなのです。</p>

<p>したがって、一見するとOに対応するように見える「OOをXXの状態にする」とか「XXを4つリリースする」とか「現在と同等の水準を維持できるようにする」とか「YYの手法を共有する」などといったKRは良いKRとは言えません。</p>

<p>「KRは、OKRを進める中でバロメータとして機能してくれるものである」というのが、設定するうえでの大切な条件になると思います。</p>

<h4 id="krには具体性を持たせる">KRには具体性を持たせる</h4>
<p>たとえば、「O月X日までに」といった文言を入れるなど、締め切りを定めるようなやり方は良いやり方です。<br />
「ムーンショットだから計画は立てられない、だから日付も入れられない」という議論を展開する人が出てくるかもしれませんが、「ムーンショットを実現するために計画を立てなければいけない」というのが本質なので、日付を入れて計画をもってのぞむのが大事だと思います。<br />
日付も入れられないほどのムーンショットであれば、それは月よりも先を目指しているか、月に行くための手立てが何も見えていない、もっと小さい目標から着手しなければならない事を示しています。</p>

<h4 id="変化を追いかけることでoの達成度をはかることのできる指標にする">変化を追いかけることで、Oの達成度をはかることのできる指標にする</h4>
<p>理想は週次で変化を追いかけられるものにする事です。<br />
例えば、悪い例としてあげたXXを4つリリースするというのは数値目標でかつ行動目標になっているため、良いように思えます。<br />
けれども、このKRは変化を追いかけることでOの達成度をはかるのが難しいです。<br />
この手の指標を立てた場合、よく観察してみるとKRの達成を目指してしまっていて、Oの達成を脇に置いてしまっているケースがたくさんありました。</p>

<h4 id="違っていると感じたら勇気をもって見直す">違っていると感じたら、勇気をもって見直す</h4>
<p>一度立てた目標を変える事を嫌がる傾向がありますが、違っていると感じたら、早々に勇気をもって見直しをかけることも大事だと感じます。<br />
せっかく立てた目標だからとか、あれだけ議論して間違っていたというのを認めたくない気持ちはわかりますが、間違ったものに向かって進んでいたら、OKRが形骸化するか、目的としていた成果が得られず、OKRの効果を実感できないか、いずれにせよ良くない結果をもたらすからです。</p>

<h3 id="健康度健全度はズルしてないかを見るためのもの">健康度/健全度は、ズルしてないかを見るためのもの</h3>
<p>健康度/健全度は、書籍(1.)に出てくるフォードの例によれば、目標達成のために削ってはいけない事を削って達成していないかを見るためのものです。<br />
「これが犠牲になっていたら、目標達成できてもかかえるリスクが大きくなりすぎる」というパラメータを2-3個設定するのが良く、健康度/健全度に設定したい内容がそれ以上の数出てくるようであれば、Oをもっと細かい領域に細分化して考えるべきケースが多いです。</p>

<h2 id="これからやりたいことに対してokrをはじめるための土壌は整っているか">これからやりたいことに対して、OKRをはじめるための土壌は整っているか？</h2>
<p>上からの号令でOKRをやることになったものの、OKRをはじめるための土壌がないために頓珍漢なOKRを立ててしまって、達成できずに挫折し、果てはOKRを捨ててしまったチームも見てきました。<br />
そういう状態にならないために、OKRをはじめる土壌としてどんな環境が必要なのかを考えてみます。</p>

<h3 id="組織としてのマインド">組織としてのマインド</h3>
<p>「とはいえ」等のキーワードを使って、OKRで定めた以外の事柄に目を向けさせるチームだとOKRはうまく機能しません。<br />
例えば駆け出しのモール型ECサイトで、OKRとして購入してくれるユーザに対するものを掲げているのに、「とはいえ」というキーワードを使って出店する店舗の側を向いた機能開発をしてしまうようなマインドの組織だとOKRを適用するのは時期尚早です。</p>

<p>OKRはチームやプロダクトに対して本当に必要な、価値のある仕事に一極集中することで高い価値創造と一点突破する突破力を発揮できるフレームワークなので、「もったいない精神」とか「八方美人精神」が働いてしまうチームの場合、まずはそのマインドセットを改めるところから手を付ける必要があると思っています。</p>

<h3 id="無意味なkrを設定しないための下準備">無意味なKRを設定しないための下準備</h3>
<p>上からの号令でOKRを設定した場合、魅力的なOを設定できてもそれを測るためのKRの設定に苦労するケースが多くみられます。<br />
KRは、普段から取っている統計情報をベースに定められると心強いので、普段から統計情報を取っていないチームでは、これらの情報を定期的にとるところから着手すると良いです。<br />
例えばコードメトリクスやテストカバレッジ、顧客満足度や契約件数などの数値を定期的に取得するような組織体制を整えることが何よりも先にやることだと思います。<br />
（付け焼刃で設定したKRでOを測定しても、正しい計測にならないことがほとんどです）</p>

<h2 id="2サイクル目移行のokrはどう進めたら良いか">2サイクル目移行のOKRはどう進めたら良いか</h2>
<p>OKRについて紹介している書籍の多くは、だいたいやり方を解説するだけで、継続する際のポイントについては触れられていない事が多いです。<br />
そこで、私が経験したチームで2サイクル目以降のOKRをどう進めていたかをメモしようと思います</p>

<h3 id="振り返りをする">振り返りをする</h3>
<p>1回目のOKRが終わったら、必ず振り返りをします。<br />
振り返りのフレームワークは何でもいいと思いますが、続けたい事と改善したい事(問題点)、また進める上で不安に感じていた事をまとめられると良いと思います。</p>

<p>振り返りでは、全員でKRの目標値と達成値の差を眺めて、どの程度達成できているのか、達成できた(できなかった)要因は何かを議論して振り返ると良いです。<br />
この振り返りではチームとして結論を出す必要はなく、多く出た意見をまとめるようにすると、次のサイクルで成果を出しやすくなると感じました。<br />
（例えば、チームメンバー6名中4名が似たような要因を感じていたとか）<br />
そのため、誰かの出した意見を否定する振り返りは行わないように注意します。<br />
特に声の大きな人や議論を引っ張るタイプの人から否定的な意見が出ると、チーム全体としてどのような状態にあったのかも見えづらくなるので注意が必要です。</p>

<h3 id="okrは見直しても良いし継続しても良い">OKRは見直しても良いし、継続しても良い</h3>
<p>KRにして6-7割達成できたのであれば、次はより遠い目標を立てても良いと思います。<br />
達成率が0に近いのであれば、Oを見直すか、そもそもKRが正しくOの動きを測れるものでなかったのではないかという疑いをかけるべきです。<br />
（というか、日々仕事をしていて、1週間の間でKRが目的とする方向に動いていないとすれば、KRの設定が間違っているか、やっている仕事が間違っているかなので早めに見直しをかけたほうが良いです）<br />
KRの達成率が3-4割であれば、引き続き同じパラメータで継続しなおしても良いと思います。<br />
ただ、KRはより遠くに設定するようにしないと、単にゴールが近づいてくるだけの状態になるので注意が必要です。</p>

<h2 id="okrは正しく使えば強い武器になる">OKRは、正しく使えば強い武器になる</h2>
<p>つらつらとOKRに対する経験則をならべてきましたが、OKRをあきらめてしまうチームがある一方で、少しずつでも軌道修正しながらOKRにくらいついていくチームでは、高い効果を発揮できる武器である事も実感しました。<br />
私の経験が、今OKRに悩んでいる人の一助になれば幸いです。</p>

<h2 id="参考書籍">参考書籍</h2>
<ol>
  <li><a href="https://amzn.to/3CvphtY">Measure What Matters</a></li>
  <li><a href="https://amzn.to/3hT8V4M">OKR（オーケーアール）</a></li>
  <li><a href="https://amzn.to/3vYMBia">本気でゴールを達成したい人とチームのためのOKR</a></li>
  <li><a href="https://amzn.to/35ZW6ms">最短最速でもくひょうを達成するOKRマネジメント入門</a></li>
</ol>]]></content><author><name></name></author><category term="okr" /><summary type="html"><![CDATA[それなりのキャリアの中で何回かOKRをやってみて、OKRの難しさであるとか、チームとしてつまずいたなあと思うようなポイントが複数あったので、少しまとめておこうと思います。 メモを列挙している形に近いのでだいぶ長いですが、参考になれば幸いです。 （OKRとはなんぞや？という話は書いていません。OKRそのものについて知りたい方は、末尾にあげる参考書籍や他のサイトをご覧いただくのが良いと思います） いずれも、私が職務遂行の中でOKRを実践した経験によるもので、科学的な根拠やOKRの正式なトレーニングを受けたことによるモノではありません。]]></summary></entry><entry><title type="html">オランウータンが肉食した記事を深追いしてみた</title><link href="https://www.10nin.com/animal/orangoutan/2022/01/05/orangoutan.html" rel="alternate" type="text/html" title="オランウータンが肉食した記事を深追いしてみた" /><published>2022-01-05T00:00:00+09:00</published><updated>2022-01-05T00:00:00+09:00</updated><id>https://www.10nin.com/animal/orangoutan/2022/01/05/orangoutan</id><content type="html" xml:base="https://www.10nin.com/animal/orangoutan/2022/01/05/orangoutan.html"><![CDATA[<p>お正月休みににネットサーフィンをしていたら、GIZMODOで面白い記事を見つけました。</p>

<p><a href="https://www.gizmodo.jp/2022/01/bornean-orangutan-caught-killing-and-eating-a-slow-loris.html">GIZMODO: オランウータン、猛毒の哺乳類を貪り食う</a></p>

<p>動画ではモッチャモッチャとスローロリスを食べるオランウータンの様子が。<br />
とても興味深かったので、少し深掘りして調べてみることにしました。</p>

<p>元の記事は<a href="https://www.iflscience.com/plants-and-animals/wild-bornean-orangutan-caught-killing-and-eating-a-slow-loris-for-first-time/">IFLSの記事</a>です。</p>

<p>内容はほとんどGIZMODOと同じで、「ボルネオオランウータンがスローロリスを捕食した事例が観察された」というもの。</p>

<p>ボルネオオランウータンは、動物園で掲示されている解説パネルや図鑑では、「草食で稀に昆虫や鳥の卵をを食べる」事が書かれているのみで、基本的に肉食はしない生き物として知られているだけに今回の肉食（しかも猛毒を持つことで知られているスローロリスの捕食）は結構驚くべきことなんじゃないかと思います。</p>

<p>（以前に、とある動物園の解説ガイドで聞いた限りでは、スマトラオランウータンも含めると、空腹のときにネズミを食べた事例や死んだ鳥を食べている捕食事例はあるようですが、いずれにしても空腹に耐えかねての緊急事態での捕食事例ではないかとガイドされていました）</p>

<p>そういうわけで、<a href="https://link.springer.com/article/10.1007/s10329-021-00960-4">元論文</a>を当たってみます。<br />
ちょっと探すのに苦労しましたが、残念なことにOpen Accessにはなっておらず、Abstractしか読むことができませんでした。</p>

<p>Abstractを読む限り、捕食したのは空腹状態のアンフランジオスで、メスとその子供（3歳半）と共に行動していたようです。</p>

<p>オスがロリスを食べている間、メスと子供はその様子を観察しながら、時折ロリスを分けてほしい要求をしていたようですが、オスはそれに応じず、オスだけがロリスを食したようで、とても面白い行動観察なのではないかと思います。</p>

<p>ボルネオオランウータンはとても好きな生き物のひとつなので、機会があれば論文も詳細に読んでみたいです。</p>]]></content><author><name></name></author><category term="animal" /><category term="orangoutan" /><summary type="html"><![CDATA[お正月休みににネットサーフィンをしていたら、GIZMODOで面白い記事を見つけました。]]></summary></entry><entry><title type="html">昨年の振り返りと今年の目標など</title><link href="https://www.10nin.com/2021/lookback/2022/01/04/LookBack.html" rel="alternate" type="text/html" title="昨年の振り返りと今年の目標など" /><published>2022-01-04T00:00:00+09:00</published><updated>2022-01-04T00:00:00+09:00</updated><id>https://www.10nin.com/2021/lookback/2022/01/04/LookBack</id><content type="html" xml:base="https://www.10nin.com/2021/lookback/2022/01/04/LookBack.html"><![CDATA[<p>個人的に、2021年は結構濃密な一年だったと思うので、やったことを振り返りつつ、今年何をしようと考えているかをまとめてみようと思います。</p>

<h2 id="仕事回り">仕事回り</h2>
<p>昨年</p>

<blockquote>
  <p>来年は、2年ほどWebサービスづくりをやってみた結果、データベース的なサイトやECサイトを構築するのよりも、生産に関連するような技術や古いソフトウェア資産が作り出した情報資産を将来にわたって持続可能な形にしていく技術が好きだなあと強く感じたので、そういう方面で頑張れるように努力したいと考えています。</p>
</blockquote>

<p>なんて書いていたのですが、狙ってか成り行きか、この度また転職をすることができました。<br />
それも、希望していた製造系の業界への転職です。</p>

<h3 id="転職活動の期間と活用したサービス">転職活動の期間と活用したサービス</h3>

<p>今回の転職は多少苦労した印象で、ざっと半年以上転職活動をしたと思います。<br />
最初はマイナビ転職に絞って転職活動をしていましたが、マイナビクリエイターだとか何とかと関連するサービスにあれこれ登録させられたり、エージェントを名乗る人間が登場したりした割に一向に決まらず、しびれを切らしてリクナビ転職とGreenも併用することにしました。</p>

<p>思い返してみれば、前回もマイナビを通じた転職では中々決まらず、Greenで転職活動をはじめて、比較的短期間で決まった印象があるので、マイナビは転職先が決まりづらいのかもしれないという印象を持ちました。<br />
（マイナビ転職、マイナビエージェント、マイナビクリエイターという3種類の異なるサイトを使わないといけないのが結構なストレスで、エージェントを介したものは、紹介される仕事内容が微妙というのもあり、1,2件面談をしただけでその後使わなくなってしまいました）</p>

<p>結局、今回もGreen経由で紹介された製造系の企業に転職を決めることができました。<br />
私とGreenの相性がなかなか良いのかもしれません。</p>

<h2 id="健康面">健康面</h2>

<h3 id="鬱的な症状になったり治ったりなんか色々ありました">鬱的な症状になったり、治ったり、なんか色々ありました</h3>
<p>体調や環境の変化もあるのだと思いますが、心身ともにずいぶんやられた一年だったと感じます。<br />
2022年はもう少し健康的に生きたいなと思う次第です。</p>

<h2 id="取り組んだ技術">取り組んだ技術</h2>

<p>Rust/Go/F#あたりを書いてみるのをしていましたが、結局長続きせず。<br />
今は次の職場で使う技術である点も鑑みて、再びC#の復習をしています。<br />
主戦場は.NET Coreに移り、LTSの.NET 6がリリースされ、C#も10になり…<br />
加えてASPまわりもすっかり変わってしまっていて、学ぶことが多そうです。</p>

<p>並行しながらRustは継続して学んでみようと思っているところです。</p>

<h2 id="今年は">今年は…</h2>

<p>まずは仕事を覚えて新しい職場になれるというのを念頭にやっていこうと思います。<br />
その他の目標として、C#を使って簡単なWebアプリケーションを書いてみようと考えています。<br />
楽しい一年になることを期待しています。</p>]]></content><author><name></name></author><category term="2021" /><category term="lookback" /><summary type="html"><![CDATA[個人的に、2021年は結構濃密な一年だったと思うので、やったことを振り返りつつ、今年何をしようと考えているかをまとめてみようと思います。]]></summary></entry><entry><title type="html">私は何に不満を感じているのか</title><link href="https://www.10nin.com/essay/2021/09/11/gripe.html" rel="alternate" type="text/html" title="私は何に不満を感じているのか" /><published>2021-09-11T00:00:00+09:00</published><updated>2021-09-11T00:00:00+09:00</updated><id>https://www.10nin.com/essay/2021/09/11/gripe</id><content type="html" xml:base="https://www.10nin.com/essay/2021/09/11/gripe.html"><![CDATA[<p>普段から、あまり不満を表に出さないようにして仕事に取り組んでいるのですが、先日ちょっとカチンときて語気強めにちょっとした不満を吐き出してしまいました。</p>

<p>そこでふと、何を不満にかんじているのか整理してみるのも面白いなと思って、書き起こしてみました。</p>

<p>書いたところで何がある訳でもありませんが、私はこういう所に不満を感じる性格だというのが見えてくるかなと思います。<br />
（仕事の内容に直結している部分への不満が多いので、ボカしています）</p>

<h3 id="-根本的な所">■ 根本的な所</h3>
<ul>
  <li>今やっている仕事がつまらない</li>
  <li>サービスに対して愛着を持つことができない。→必要のないものを作っている感覚が常にある。社会的に求められていないものを作っている感じ。</li>
  <li>ECモールを作るという事に未だに疑問を感じている。
    <ul>
      <li>→ 他人のふんどしで相撲を取っている感じ。自分たちで作っているものじゃない所に本質的な価値がある感覚がしている</li>
    </ul>
  </li>
  <li>どれだけ仕事をこなしてもむなしい。物事が終わっても緊張感が続く感じで、達成感みたいなものはここ1年味わってないと思う。</li>
</ul>

<h3 id="-これまで経験した事柄によるところ">■ これまで経験した事柄によるところ</h3>
<ul>
  <li>昨年12月～1月は、大学院受験をするつもりで準備していて、その話を1on1でもしてきたが、土壇場で年末に大型案件にアサインされ（しかも元々業務を持っていたのはリーダーだったはず）道を潰された事への恨みがある</li>
  <li>ある部署とのやり取りが生じる仕事が、朝起きあがるのが嫌になるほどストレスになっているという話をしたのに、その仕事が終わって一息つく間もなく、また同じ仕事に戻されようとしている<br />
　- → 2度と関わりたくないという強い気持ちがあるが、やむなく業務でやるとしても、きちんと強いストレスであることを伝えているにも関わらず、再度またそこに当て込まれるのは嫌がらせだと感じる</li>
  <li>年末年始にアサインされた大型案件では精神的にすっかり参ってしまって、病院のお世話になるほどだった。<br />
　- → その状況下にあっても、手助けをしてくれたのは個人的なつながりで手を貸してくれた人たちであって、チームとして、リーダーがリードして支えるような動きはしてもらえなかった所に、チームは助けてくれない感覚の根っこがあると思う</li>
  <li>あれだけ毎朝進捗の報告をして、週次でタスクの状況共有をしているのにガントチャートが無いと負荷状況がわからないって、何を聞いているの？何を話させられているの？という無力感がある</li>
  <li>50%の稼働で入っていた派遣さんは６月から、７月から、８月からフルで入る！と言われていたので、その都度「じゃあ教育を目標に…」として仕事に取り組んだが、それに対して会社は応えてくれなかった。会社はおまえの期待に応えないが、おまえは会社の期待に応えろと言われている感じで辛い。
    <ul>
      <li>→ できないは結構だが、できそうにないなら早い段階で目標もピボットしたかった気持ちがある。</li>
      <li>結局その派遣さんは９月末で退職してしまうことになり、教育として私が色々つぎ込んだリソースは無に帰した</li>
    </ul>
  </li>
  <li>チーム内でお互いの目標を共有していないので、相手が何を達成すれば評価アップにつながるのかが見えていなくて、普段の動きの中で何をアシストすると良いのか判断がつかない
    <ul>
      <li>→ 加えて、目標立てたら、その目標に沿うように仕事をアサインしてもらえたり、仕事を選べたりするのなら多少意味があると思うが、仕事の中で達成するためのフォローアップは何もない</li>
    </ul>
  </li>
  <li>1on1は、週次で進捗報告する場が1カ所増えているだけで煩わしく、仕事の内容はその評価アップを狙った無いようにフォーカスしていない事が多いので、週次で成果が出ているわけもなく、毎週できなかったことに焦点を合わせて同じ内容の議論をするのが辛い</li>
</ul>

<h3 id="-感じているところ">■ 感じているところ</h3>
<ul>
  <li>スケジュールを組めとか、予定を出せというけれど、人を動かせる裁量が与えられていないのにやらされるのは非常に辛い</li>
  <li>リーダーの、相手に対する敬意が感じられない。（相手への問いかけが子供に対するようなものであったり、10年近いキャリアを持っている人を相手にしているとはとても思えないやり取りだったり）
    <ul>
      <li>→ リーダー自身から発せられる「今日は調子が悪くて応対が悪くなるかも」とか、「体調がどうの」というのは別にエクスキューズしなくていいので、そういう状況なら休んでほしい。</li>
      <li>→ 機嫌がいいのは社会人として最低限のマナーという世界で仕事をしてきた身からすると、社会人として基本的な部分ができていない人がリーダーになっている感があって絶望的</li>
    </ul>
  </li>
  <li>リーダーの仕事に対する姿勢が、「やりすぎ」感が強い。設計とか早い段階で責務がどうこうとか分けすぎていると感じるし、一般に悪いといわれるような設計であっても、小さく、わかりやすく作っておいて、後から気軽に壊して変更が効くように作るのが良いと習ってきた世界の人間からすると文化的なギャップが大きい
    <ul>
      <li>退職する派遣さんに任せているコードだって、ほぼ書き直しに近いような修正を幾度もさせているのはどうかと感じる。それこそ、9月でそチームを離れるという所が頭から抜けているのでは？とすら感じる。</li>
      <li>金額的に高額な業務委託の人に任せた仕事も、全部調査したり全部直したりすると工数がかかりすぎるから、ミニマムの内容でやりたいという要件だったはずなのに、結局数度も調査やり直しを命じて１か月かけさせている。やらせた側の満足で終わっていて、かけた期間に見合う結果が出ていないのでは？と感じる</li>
      <li>ペイする仕事をしろと口酸っぱく言われてきた人間としては、仕事を通じた成長とか、プロダクトの品質の方に極端に振っている仕事のやり方はついていけない。</li>
    </ul>
  </li>
</ul>]]></content><author><name></name></author><category term="essay" /><summary type="html"><![CDATA[普段から、あまり不満を表に出さないようにして仕事に取り組んでいるのですが、先日ちょっとカチンときて語気強めにちょっとした不満を吐き出してしまいました。]]></summary></entry><entry><title type="html">RSpecを書く上でのちょっとしたメモと、ActiveStorageのspec実行でつまずいたこと</title><link href="https://www.10nin.com/ruby/ror/rspec/circleci/2021/08/24/rspec.html" rel="alternate" type="text/html" title="RSpecを書く上でのちょっとしたメモと、ActiveStorageのspec実行でつまずいたこと" /><published>2021-08-24T00:00:00+09:00</published><updated>2021-08-24T00:00:00+09:00</updated><id>https://www.10nin.com/ruby/ror/rspec/circleci/2021/08/24/rspec</id><content type="html" xml:base="https://www.10nin.com/ruby/ror/rspec/circleci/2021/08/24/rspec.html"><![CDATA[<p>私は、テストフレームワークの中でも、とりわけRSpecが嫌いです。<br />
不思議なドメイン言語を覚えなければいけないところや、テストを読み下すときに脳のメモリを余計に使うところ、書き味の悪さや周辺エコシステムの複雑さ、またRSpecの界隈に集まっているエンジニアの雰囲気が苦手というのもあって、Railsと同じぐらい、使わなくて済むならば使いたくないと感じているフレームワークです。</p>

<p>しかし、Railsで飯を食べている以上避けることができないのもまたRSpecの嫌な所で、いやいややるので一切覚えることができず、毎回あらゆることをGoogle先生にお尋ねしながら開発を進めています。</p>

<p>そんな中で、解決するのに手こずった内容があったのでメモしておきます。</p>

<h2 id="モデル同士のアソシエーションのrspec">モデル同士のアソシエーションのRSpec</h2>
<p>「こんなのやる意味あるのか？」と私は思うのですが、どうやらアソシエーションが設定されている事を確認するSpecを書きたいという要求があるようです。<br />
やる意味あるのか？と思ったのはあながちおかしくないようで、それをやっている例があまり出てきませんでした。<br />
具体的にはこんな風に書きます。</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="no">RSpec</span><span class="p">.</span><span class="nf">describe</span> <span class="no">SampleModel</span><span class="p">,</span> <span class="ss">type: :model</span> <span class="k">do</span>
  <span class="n">describe</span> <span class="s1">'References'</span> <span class="k">do</span>
    <span class="n">it</span> <span class="p">{</span> <span class="n">is_expected</span><span class="p">.</span><span class="nf">to</span> <span class="n">belogs_to</span><span class="p">(</span><span class="ss">:hoge</span><span class="p">)</span> <span class="p">}</span>
    <span class="n">it</span> <span class="p">{</span> <span class="n">is_expected</span><span class="p">.</span><span class="nf">to</span> <span class="n">have_one</span><span class="p">(</span><span class="ss">:fuga</span><span class="p">)</span> <span class="p">}</span>
    <span class="n">it</span> <span class="p">{</span> <span class="n">is_expected</span><span class="p">.</span><span class="nf">to</span> <span class="n">have_many</span><span class="p">(</span><span class="ss">:piyo</span><span class="p">)</span> <span class="p">}</span>
  <span class="k">end</span>
  <span class="c1">#...</span>
<span class="k">end</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">has_many/has_one</code>でアソシエーションを設定するのに、Specでは<code class="language-plaintext highlighter-rouge">have_many</code>でチェックしないといけないところはややわかりづらいですね。</p>

<h2 id="activestorageでアップロードを伴うspecを書く">ActiveStorageでアップロードを伴うSpecを書く</h2>

<p>画像のバリデーションを用意しているとかで、ファイルをアップロードして、それに対するバリデータの動きを見るようなSpecを書く場合です。<br />
StackOverFlowにはごっついアップロードコードを用意しろという回答が出てきますが、<code class="language-plaintext highlighter-rouge">fixture_file_upload</code>というメソッドを使えば、それよりは簡単に書くことができます。</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#sample.imageのimage部分がActiveStorageで関連付けられたモデルだと思ってください</span>
<span class="n">context</span> <span class="s1">'...'</span> <span class="k">do</span>
  <span class="n">before</span><span class="p">{</span> <span class="n">sample</span><span class="p">.</span><span class="nf">image</span> <span class="o">=</span> <span class="n">fixture_file_upload</span><span class="p">(</span><span class="s1">'/images/100x100.png'</span><span class="p">)</span>
  <span class="n">it</span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre></div></div>
<p>ここで、アップロードするファイルは<code class="language-plaintext highlighter-rouge">spec/fixtures/images</code>ディレクトリ配下に配置します。<br />
（<code class="language-plaintext highlighter-rouge">fixture_file_upload</code>のrootディレクトリが<code class="language-plaintext highlighter-rouge">spec/fixtures</code>になる訳です）</p>

<h2 id="activestorageを使ったspecをcircleciで走らせるとエラーでコケる">ActiveStorageを使ったspecをCircleCIで走らせるとエラーでコケる</h2>

<p>具体的に出ているエラーは、こんな具合のものです。</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Errno::EEXIST:
  FIle exists @ dir_s_mkdir - /home/circleci/...
</code></pre></div></div>

<p>上記のエラーでネットを探すと、Windowsのディレクトリ名の扱いに関係したページばかりが出てきますが、原因は別の所にあります。<br />
これは、ActiveStorageの保存先を設定するときに、storage.ymlに</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">local</span><span class="pi">:</span>
  <span class="na">service</span><span class="pi">:</span> <span class="s">Disk</span>
  <span class="na">root</span><span class="pi">:</span> <span class="s">&lt;%= Rails.root.join("/public/images/active_storage") %&gt;</span>
</code></pre></div></div>

<p>などと設定している場合で、サーバの構成の都合上、<code class="language-plaintext highlighter-rouge">/public/images</code>がシンボリックリンクに設定されているような環境で、なおかつCircleCIが利用する環境向けの設定ファイル（例えば<code class="language-plaintext highlighter-rouge">environments/test.rb</code>等）に</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">config</span><span class="p">.</span><span class="nf">active_storage</span><span class="p">.</span><span class="nf">service</span> <span class="o">=</span> <span class="ss">:local</span>
</code></pre></div></div>
<p>と設定してあるケースで発生します。<br />
手元ではシンボリックリンクが活きているのでエラーになりませんが、CircleCI上に上げたとたんにシンボリックリンクが使えないものになっているので、このエラーになるというわけです。</p>

<p>解決方法としては、（どうせCircleCI上のコンテナは使い捨てなので）storage.ymlにシンボリックリンクでないディレクトリを使うストレージの設定を用意して、それを使うようにします。</p>

<p>具体的には</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">local</span><span class="pi">:</span>
  <span class="na">service</span><span class="pi">:</span> <span class="s">Disk</span>
  <span class="na">root</span><span class="pi">:</span> <span class="s">&lt;%= Rails.root.join("/public/images/active_storage") %&gt;</span>

<span class="na">cci</span><span class="pi">:</span>
  <span class="na">service</span><span class="pi">:</span> <span class="s">Disk</span>
  <span class="na">root</span><span class="pi">:</span> <span class="s">&lt;%= Rails.root.join("/tmp") %&gt;</span>

</code></pre></div></div>
<p>等とCircleCI用のストレージ設定を用意しておいて、環境別の設定の方にも <code class="language-plaintext highlighter-rouge">config.active_storage.service = :cci</code> として、専用の設定を使うように記述してあげれば良いです。</p>

<h2 id="まとめ">まとめ</h2>

<p>RSpecのように、テストを書くのが面倒なフレームワークを使っていると、テストを書くこと自体が億劫になって、結果としてプロダクトの品質に負の影響を及ぼす事になると感じています。</p>

<p>私のこれまでの経験から、プロダクトは生き物なので、下手に秘伝のソースを継ぎ足して構築していくよりも、部分的にでも刷新し続けられる状況を保つようにするべきと感じます。</p>

<p>刷新作業の際に、勇気をもってプロダクトにメスを入れられるようになるためにも、テストを書きやすく、保守しやすいフレームワークが求められていると感じます。</p>]]></content><author><name></name></author><category term="ruby" /><category term="ror" /><category term="rspec" /><category term="circleci" /><summary type="html"><![CDATA[私は、テストフレームワークの中でも、とりわけRSpecが嫌いです。 不思議なドメイン言語を覚えなければいけないところや、テストを読み下すときに脳のメモリを余計に使うところ、書き味の悪さや周辺エコシステムの複雑さ、またRSpecの界隈に集まっているエンジニアの雰囲気が苦手というのもあって、Railsと同じぐらい、使わなくて済むならば使いたくないと感じているフレームワークです。]]></summary></entry></feed>