<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>202 Accepted</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://202accepted.com/"/>
  <updated>2021-08-16T14:23:52.221Z</updated>
  <id>https://202accepted.com/</id>
  
  <author>
    <name>cho0o0</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>リモートなら非同期を優先せよ</title>
    <link href="https://202accepted.com/2021/08/16/embrace-async-work-style/"/>
    <id>https://202accepted.com/2021/08/16/embrace-async-work-style/</id>
    <published>2021-08-16T23:19:00.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<h2 id="オフィス環境を再現する努力はナンセンス"><a href="#オフィス環境を再現する努力はナンセンス" class="headerlink" title="オフィス環境を再現する努力はナンセンス"></a>オフィス環境を再現する努力はナンセンス</h2><p>私はリモート環境でオフィスでの働き方を頑張って再現し、今までのノウハウをはめようとする行動に賛同できません。<br>いきなりのリモートに慣れず、トランジッションの一環としてオフィスでの振る舞いを再現させることは理解できます。<br>しかし、リモートでオフィス環境を再現させることが無理で可能な限り再現しようとしたらその努力がペイしないし、リモートワークの特徴を生かす効率化が期待できないと考えています。<br>例えば、全員が常時ビデオ通話のオンライン状態にキープするアプローチがよく聞きますが、社員のストレスが溜まる一向で、作業に集中しやすいというリモートワークのメリットを抹殺してしまいます。<br>また、オンライン参加が可能だが集まれる人がオフラインで集まって開催するミーティングがいろんな所でやられていますが、コンテキストが共有しにくく、コミュニケーションがスムーズにならないのでオフラインのデメリットとオンラインのデメリットを顕在化させるだけのプラクティスだと考えています。</p><h2 id="非同期優先"><a href="#非同期優先" class="headerlink" title="非同期優先"></a>非同期優先</h2><p>リモートでやるなら、リモートの特徴にあわせ、同期性の高いワークフローを排除し、非同期をメインにすべきだと思います。<br>ミーティングの量を最小限にして、コミュニケーションをテキストベースに持っていくことはわかりやすい実践例でしょう。<br>ただ、非同期優先というのはやり方の話だけではなく、考え方の話も含まれます。どちらかと言いますと、考え方の方が遥かに大事だと実感しています。<br>まず、<strong>相手のことを常にポジティブに解釈する</strong>というマインドセットが大事です。テキストがメインになり、ビデオ通話の場合でも同じ物理空間にいるわけじゃないため、五感を生かしてニュアンスを理解することが無理です。故に、ネガティブな気持ちで説明されたことをポジティブに考えることとポジティブに表現されたことをネガティブに解釈することがありえます。経験上、後者の方がトラブルの元になるケースが圧倒的に多いです。なので、相手の本当の気持ちはともあれ、とりあえずポジティブに解釈することは全員のマインドセットに入れないといけないです。<br>それに付随し、<strong>コンテキストを最小限に収める</strong>ことに心掛けるべきでしょう。前述のように、コンテキストを伝えることがリモート環境において難しいと言えます。曖昧さを回避し、言うことをはっきり言った方が効率的だと考えます。リアルタイムの対話なら参考情報を文脈の中に差し込むことが難しかったりしますが、テキストだとそんな制限がない為、リンクをどんどん貼り付けても構わないのでそういうリモートこその特徴を生かすべきでしょう。<br>さらに言うと、リモートになることでアプローチできる人材マーケットは日本に限らなくなるはずなので、全世界から優秀な人材を確保できるメリットが出てきます。異文化間のコミュニケーションにおいて、コンテキストを抑えることが大事なので、そういう意味でもコンテキストを最小限にする必要性があります。<br>また、<strong>アウトプットベースで物事を考える</strong>マインドセットが大切になるでしょう。従業員の生産時間ではなく、成果物で従業員の価値を決めるべきという考え方はだいぶ前から言われ始めましたので、ここで強調する必要がありません。<br>ただ少し脱線しますが、最近大きな反響を呼んでいるGoogleの給料カットの話についてアウトプットベース思考の角度から分析をしてみたいと思います。この給料カットの話を要約すると、Googleは今までのシリコンバレー水準ではなく従業員が住んでいる場所の生活コストに合わせた給料を支払いたいとのことです。従業員が生活コストが低いところに移すなら、給料が減少するわけです。実際にGoogle以外、TwitterやFacebookのようなIT大手も同じ仕組みを導入しています。なぜこうなるかと言いますと、今までの採用戦略がリモートベースじゃなかったからだと考えます。残念ながら会社は従業員のアウトプットで給料を支払っているわけではなく、あくまでもその従業員を確保するために最も合理的な（大体一番安い）コストを支払っているわけです。すなわち、ローカルマーケットの相場が決定的な要素だと考えても良いでしょう。<br>しかしよく考えたら、これは昔のプライシングのオペレーションに似ていませんか？メーカーが商品の価格を決める際に、商品の生産コストを計算し、そこから業界平均のマージンを上乗せ、定価を決めるやり方でやっていました。一方で、今のマーケティング界では基本的にはコストでなく、商品の価値から逆算して定価を決めるようになってきています。<br>話を人材業界に戻しますが、リモートが主流になってきますと、ローカルマーケットの相場に合わせることはナンセンスになりますので、時間がかかりますが、従業員に支払う給料が従業員のアウトプットの価値に左右されるようになるでしょう。</p><h2 id="生産性の担保"><a href="#生産性の担保" class="headerlink" title="生産性の担保"></a>生産性の担保</h2><p>戦略的な話の後、戦術的なことについて考えてみましょう。リモートワークの生産性を担保するのに何が必要でしょうか？大きく分けて物理環境と情報だと思います。<br>まずは物理環境。リモートじゃなければ、会社が従業員の生産性を向上させる為に、オフィスを整備したりしてきたと思います。同様に、会社が社員のリモートワークの環境整備に支援することはリモート時代において欠かせないです。実際にGitLabやShopify、日本だと<a href="https://speakerdeck.com/miyasho88/we-are-hiring?slide=39" target="_blank" rel="noopener">SmartHR</a>などの会社がそうしていると言われています。<br>物理環境と比べ、情報整備の重要性が気づきにくいものの、非常に大事だと考えます。非同期のワークフローが主流になることで、作業に必要な情報が素早く手に入るかによって、作業効率が大きく変わります。<br>ケーススタディーを一つ挙げます。GitLabが情報整備の重要性に気づき、「Single source of truth」を掲げ、<a href="https://about.gitlab.com/handbook/handbook-usage/" target="_blank" rel="noopener">ハンドブックファースト</a>という考え方を実践してきました。私のようなエンジニアが「Single source of truth」を見ると、すぐ<a href="https://en.wikipedia.org/wiki/Single_source_of_truth" target="_blank" rel="noopener">データマネジメントのイメージ</a>が浮かんでくると思いますが、角度が違うもののGitLabのハンドブックはまさに「Single source of truth」の思想を体現しています。<br>GitLabは、ハンドブックを静的サイトとしてメンテナンスし、ソースコードをGitLab上のリポジトリとしてホストしています。従業員みんなが常時その内容を確認・更新し、それを信頼できる唯一の情報源として利用しています。そのため、何かわからないことがあったら、迷わずハンドブックを調べますし、何か聞かれたら直接ハンドブック内のリンクを送ります。ハンドブックがGitLabのワークフローの中核にあると言っても過言ではないと思います。<br>GitLabのハンドブックを100%再現する必要がないと思いますが、今までのリモート経験から見て、<strong>信頼できる唯一のレファレンス</strong>をメンテナンスすることはリモートワークにおいて非常に価値のあることだと感じています。利用するツールは不問ですが、下記の特徴を備えているレファレンスがあればリモートワークの質が高まるはずです。</p><h3 id="１、わかりやすいカテゴライズ"><a href="#１、わかりやすいカテゴライズ" class="headerlink" title="１、わかりやすいカテゴライズ"></a>１、わかりやすいカテゴライズ</h3><p>辞書と同じ、調べにくいレファレンスは価値がないと思います。その為、カテゴライズを重要視すべきです。わからないことがあったらどこから辿ればいいかがわかる、書きたいノウハウがあったらどのページに書いたら良いかがわかる状態は理想的でしょう。情報が拡張・アップデートされたら、既存のカテゴリーの合理性にも影響を及ぼすかもしれないから、常時見直すことが大事です。</p><h3 id="２、全文検索可能な状態"><a href="#２、全文検索可能な状態" class="headerlink" title="２、全文検索可能な状態"></a>２、全文検索可能な状態</h3><p>カテゴライズが大事ですが、分類がいくらうまいと言って、レファレンスの情報量が多くなればなるほど、正攻法で調べることが難しくなります。その時、デジタルレファレンスだからこそできる全文検索が役に立ちます（なぜヤフーの代わりにGoogleが主流になったかを考えれば理解しやすい）。ツールによって全文検索の質がかなり異なりますので気をつけたほうがいいと思います。</p><h3 id="３、相互リンクできる"><a href="#３、相互リンクできる" class="headerlink" title="３、相互リンクできる"></a>３、相互リンクできる</h3><p>ObsidianやRoamの台頭によって再び注目され始めた相互リンク（Bidirectional Link）ですが、レファレンスにとっても非常に重要だと思います。そもそも情報というものがお互いに繋がっている為、その構造を再現することは使い勝手の良さに関係すると考えます。</p><h3 id="４、変更に気付かせる仕組みがある"><a href="#４、変更に気付かせる仕組みがある" class="headerlink" title="４、変更に気付かせる仕組みがある"></a>４、変更に気付かせる仕組みがある</h3><p>知識を常にアップデートしないと時代についていけないことはみんなが知っていると思います。レファレンス上の情報が更新されたら、人の頭に記憶されている情報を同期しないとトラブります。GitLabではバンドブックの変更がMerge Request経由で実施されていてその変更が常に通知される仕組みになっています。GitLabやGitHub以外、Notionにもバージョン管理機能とそれをチャットツールへ通知する機能があるので、使用するサービスにあわせ変更に気づかせる仕組みを設けるべきだと思います。</p><h2 id="最後に"><a href="#最後に" class="headerlink" title="最後に"></a>最後に</h2><p>個人の思いも込めていますが、これからのIT業界はリモート主流の時代になるべきで、なってほしいと考えています。それにあわせ、今までの働き方により構築してきたノウハウをしっかりと精査し、活かせるべき経験を活かし、捨てるべき経験をちゃんとUnlearnしなければ、リモートワークの価値が最大限まで利用できないと思っています。</p><p>「<strong>Embrace remote, embrace async-first work style.</strong>」</p><h2 id="参考資料"><a href="#参考資料" class="headerlink" title="参考資料"></a>参考資料</h2><ul><li><a href="https://www.coursera.org/learn/remote-team-management" target="_blank" rel="noopener">How to Manage a Remote Team</a></li><li><a href="https://learn.gitlab.com/coursera-remote-work/" target="_blank" rel="noopener">The Remote Playbook</a></li><li><a href="https://basecamp.com/books/remote" target="_blank" rel="noopener">Remote</a></li><li><a href="https://nttcom.github.io/remote-work-handbook/" target="_blank" rel="noopener">リモートワーク ハンドブック</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;オフィス環境を再現する努力はナンセンス&quot;&gt;&lt;a href=&quot;#オフィス環境を再現する努力はナンセンス&quot; class=&quot;headerlink&quot; title=&quot;オフィス環境を再現する努力はナンセンス&quot;&gt;&lt;/a&gt;オフィス環境を再現する努力はナンセンス&lt;/h2&gt;&lt;p&gt;私はリモート環境でオフィスでの働き方を頑張って再現し、今までのノウハウをはめようとする行動に賛同できません。&lt;br&gt;いきなりのリモートに慣れず、トランジッションの一環としてオフィスでの振る舞いを再現させることは理解できます。&lt;br&gt;しかし、リモートでオフィス環境を再現させることが無理で可能な限り再現しようとしたらその努力がペイしないし、リモートワークの特徴を生かす効率化が期待できないと考えています。&lt;br&gt;例えば、全員が常時ビデオ通話のオンライン状態にキープするアプローチがよく聞きますが、社員のストレスが溜まる一向で、作業に集中しやすいというリモートワークのメリットを抹殺してしまいます。&lt;br&gt;また、オンライン参加が可能だが集まれる人がオフラインで集まって開催するミーティングがいろんな所でやられていますが、コンテキストが共有しにくく、コミュニケーションがスムーズにならないのでオフラインのデメリットとオンラインのデメリットを顕在化させるだけのプラクティスだと考えています。&lt;/p&gt;&lt;h2 id=&quot;非同期優先&quot;&gt;&lt;a href=&quot;#非同期優先&quot; class=&quot;headerlink&quot; title=&quot;非同期優先&quot;&gt;&lt;/a&gt;非同期優先&lt;/h2&gt;&lt;p&gt;リモートでやるなら、リモートの特徴にあわせ、同期性の高いワークフローを排除し、非同期をメインにすべきだと思います。&lt;br&gt;ミーティングの量を最小限にして、コミュニケーションをテキストベースに持っていくことはわかりやすい実践例でしょう。&lt;br&gt;ただ、非同期優先というのはやり方の話だけではなく、考え方の話も含まれます。どちらかと言いますと、考え方の方が遥かに大事だと実感しています。&lt;br&gt;まず、&lt;strong&gt;相手のことを常にポジティブに解釈する&lt;/strong&gt;というマインドセットが大事です。テキストがメインになり、ビデオ通話の場合でも同じ物理空間にいるわけじゃないため、五感を生かしてニュアンスを理解することが無理です。故に、ネガティブな気持ちで説明されたことをポジティブに考えることとポジティブに表現されたことをネガティブに解釈することがありえます。経験上、後者の方がトラブルの元になるケースが圧倒的に多いです。なので、相手の本当の気持ちはともあれ、とりあえずポジティブに解釈することは全員のマインドセットに入れないといけないです。&lt;br&gt;それに付随し、&lt;strong&gt;コンテキストを最小限に収める&lt;/strong&gt;ことに心掛けるべきでしょう。前述のように、コンテキストを伝えることがリモート環境において難しいと言えます。曖昧さを回避し、言うことをはっきり言った方が効率的だと考えます。リアルタイムの対話なら参考情報を文脈の中に差し込むことが難しかったりしますが、テキストだとそんな制限がない為、リンクをどんどん貼り付けても構わないのでそういうリモートこその特徴を生かすべきでしょう。&lt;br&gt;さらに言うと、リモートになることでアプローチできる人材マーケットは日本に限らなくなるはずなので、全世界から優秀な人材を確保できるメリットが出てきます。異文化間のコミュニケーションにおいて、コンテキストを抑えることが大事なので、そういう意味でもコンテキストを最小限にする必要性があります。&lt;br&gt;また、&lt;strong&gt;アウトプットベースで物事を考える&lt;/strong&gt;マインドセットが大切になるでしょう。従業員の生産時間ではなく、成果物で従業員の価値を決めるべきという考え方はだいぶ前から言われ始めましたので、ここで強調する必要がありません。&lt;br&gt;ただ少し脱線しますが、最近大きな反響を呼んでいるGoogleの給料カットの話についてアウトプットベース思考の角度から分析をしてみたいと思います。この給料カットの話を要約すると、Googleは今までのシリコンバレー水準ではなく従業員が住んでいる場所の生活コストに合わせた給料を支払いたいとのことです。従業員が生活コストが低いところに移すなら、給料が減少するわけです。実際にGoogle以外、TwitterやFacebookのようなIT大手も同じ仕組みを導入しています。なぜこうなるかと言いますと、今までの採用戦略がリモートベースじゃなかったからだと考えます。残念ながら会社は従業員のアウトプットで給料を支払っているわけではなく、あくまでもその従業員を確保するために最も合理的な（大体一番安い）コストを支払っているわけです。すなわち、ローカルマーケットの相場が決定的な要素だと考えても良いでしょう。&lt;br&gt;しかしよく考えたら、これは昔のプライシングのオペレーションに似ていませんか？メーカーが商品の価格を決める際に、商品の生産コストを計算し、そこから業界平均のマージンを上乗せ、定価を決めるやり方でやっていました。一方で、今のマーケティング界では基本的にはコストでなく、商品の価値から逆算して定価を決めるようになってきています。&lt;br&gt;話を人材業界に戻しますが、リモートが主流になってきますと、ローカルマーケットの相場に合わせることはナンセンスになりますので、時間がかかりますが、従業員に支払う給料が従業員のアウトプットの価値に左右されるようになるでしょう。&lt;/p&gt;&lt;h2 id=&quot;生産性の担保&quot;&gt;&lt;a href=&quot;#生産性の担保&quot; class=&quot;headerlink&quot; title=&quot;生産性の担保&quot;&gt;&lt;/a&gt;生産性の担保&lt;/h2&gt;&lt;p&gt;戦略的な話の後、戦術的なことについて考えてみましょう。リモートワークの生産性を担保するのに何が必要でしょうか？大きく分けて物理環境と情報だと思います。&lt;br&gt;まずは物理環境。リモートじゃなければ、会社が従業員の生産性を向上させる為に、オフィスを整備したりしてきたと思います。同様に、会社が社員のリモートワークの環境整備に支援することはリモート時代において欠かせないです。実際にGitLabやShopify、日本だと&lt;a href=&quot;https://speakerdeck.com/miyasho88/we-are-hiring?slide=39&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SmartHR&lt;/a&gt;などの会社がそうしていると言われています。&lt;br&gt;物理環境と比べ、情報整備の重要性が気づきにくいものの、非常に大事だと考えます。非同期のワークフローが主流になることで、作業に必要な情報が素早く手に入るかによって、作業効率が大きく変わります。&lt;br&gt;ケーススタディーを一つ挙げます。GitLabが情報整備の重要性に気づき、「Single source of truth」を掲げ、&lt;a href=&quot;https://about.gitlab.com/handbook/handbook-usage/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ハンドブックファースト&lt;/a&gt;という考え方を実践してきました。私のようなエンジニアが「Single source of truth」を見ると、すぐ&lt;a href=&quot;https://en.wikipedia.org/wiki/Single_source_of_truth&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;データマネジメントのイメージ&lt;/a&gt;が浮かんでくると思いますが、角度が違うもののGitLabのハンドブックはまさに「Single source of truth」の思想を体現しています。&lt;br&gt;GitLabは、ハンドブックを静的サイトとしてメンテナンスし、ソースコードをGitLab上のリポジトリとしてホストしています。従業員みんなが常時その内容を確認・更新し、それを信頼できる唯一の情報源として利用しています。そのため、何かわからないことがあったら、迷わずハンドブックを調べますし、何か聞かれたら直接ハンドブック内のリンクを送ります。ハンドブックがGitLabのワークフローの中核にあると言っても過言ではないと思います。&lt;br&gt;GitLabのハンドブックを100%再現する必要がないと思いますが、今までのリモート経験から見て、&lt;strong&gt;信頼できる唯一のレファレンス&lt;/strong&gt;をメンテナンスすることはリモートワークにおいて非常に価値のあることだと感じています。利用するツールは不問ですが、下記の特徴を備えているレファレンスがあればリモートワークの質が高まるはずです。&lt;/p&gt;
    
    </summary>
    
      <category term="org" scheme="https://202accepted.com/categories/org/"/>
    
    
      <category term="remote" scheme="https://202accepted.com/tags/remote/"/>
    
      <category term="work-style" scheme="https://202accepted.com/tags/work-style/"/>
    
  </entry>
  
  <entry>
    <title>Token Ringについて</title>
    <link href="https://202accepted.com/2021/02/07/token-ring-introduction/"/>
    <id>https://202accepted.com/2021/02/07/token-ring-introduction/</id>
    <published>2021-02-07T23:39:54.000Z</published>
    <updated>2021-08-16T14:23:52.222Z</updated>
    
    <content type="html"><![CDATA[<p>Token RingというLANの規格が既に過去形になってしまいましたが、設計思想が面白く、採用しているRing Passingなどは他の技術でも活用されている基礎的な考え方なので、Token Ringを紹介するスライドを作成しました。</p><script async class="speakerdeck-embed" data-id="a20428acc668491b83397b914bfe9788" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Token RingというLANの規格が既に過去形になってしまいましたが、設計思想が面白く、採用しているRing Passingなどは他の技術でも活用されている基礎的な考え方なので、Token Ringを紹介するスライドを作成しました。&lt;/p&gt;&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;a20428acc668491b83397b914bfe9788&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="network" scheme="https://202accepted.com/tags/network/"/>
    
  </entry>
  
  <entry>
    <title>モック用便利サービス6選</title>
    <link href="https://202accepted.com/2021/01/17/mock-tools/"/>
    <id>https://202accepted.com/2021/01/17/mock-tools/</id>
    <published>2021-01-17T22:51:50.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p>Web 開発を行う際に、ダミーコンテンツを利用したいシーンがしばしば出てきます。データベース内のデータじゃなくてもいいものの、それなりのリアリティが求められるケースも多いです。今日は私が気に入ったモック用サービスを紹介したいと思います。</p><h2 id="Mockaroo"><a href="#Mockaroo" class="headerlink" title="Mockaroo"></a><a href="https://www.mockaroo.com/" target="_blank" rel="noopener">Mockaroo</a></h2><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> MOCK_DATA (<span class="keyword">id</span>, first_name, last_name, email, gender) <span class="keyword">values</span> (<span class="number">1</span>, <span class="string">'Therine'</span>, <span class="string">'Cawsey'</span>, <span class="string">'tcawsey0@issuu.com'</span>, <span class="string">'Female'</span>);</span><br><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> MOCK_DATA (<span class="keyword">id</span>, first_name, last_name, email, gender) <span class="keyword">values</span> (<span class="number">2</span>, <span class="string">'Melvin'</span>, <span class="string">'Barthrup'</span>, <span class="string">'mbarthrup1@mozilla.org'</span>, <span class="string">'Male'</span>);</span><br><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> MOCK_DATA (<span class="keyword">id</span>, first_name, last_name, email, gender) <span class="keyword">values</span> (<span class="number">3</span>, <span class="string">'Salim'</span>, <span class="string">'Iacobassi'</span>, <span class="string">'siacobassi2@uiuc.edu'</span>, <span class="string">'Male'</span>);</span><br><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> MOCK_DATA (<span class="keyword">id</span>, first_name, last_name, email, gender) <span class="keyword">values</span> (<span class="number">4</span>, <span class="string">'Gilemette'</span>, <span class="string">'Pittam'</span>, <span class="string">'gpittam3@rediff.com'</span>, <span class="string">'Female'</span>);</span><br><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> MOCK_DATA (<span class="keyword">id</span>, first_name, last_name, email, gender) <span class="keyword">values</span> (<span class="number">5</span>, <span class="string">'Gaylord'</span>, <span class="string">'Elliker'</span>, <span class="string">'gelliker4@opensource.org'</span>, <span class="string">'Male'</span>);</span><br></pre></td></tr></table></figure><p>氏名を始め、住所や電話番号、IP アドレス等々、いろんなダミーデータが作成できます。作成できたデータは CSV だけでなく、直接 JSON と SQL 等に書き出せる機能は非常にありがたいです。無料ユーザでしたら、1000 件までしか作れませんが、一時的にテストをする目的であれば十分だと思います。ただ、英語しか対応していなく、日本語のデータ作成ができないことは難点として挙げられます。</p><h2 id="avataaars-generator"><a href="#avataaars-generator" class="headerlink" title="avataaars generator"></a><a href="https://getavataaars.com/" target="_blank" rel="noopener">avataaars generator</a></h2><p><img src="https://avataaars.io/?avatarStyle=Circle&topType=LongHairStraight&accessoriesType=Blank&hairColor=BrownDark&facialHairType=Blank&clotheType=BlazerShirt&eyeType=Default&eyebrowType=Default&mouthType=Default&skinColor=Light" alt="avataaars generator"></p><p>好みの問題もありますが、アバタ作成ツールの中、こちらの使い勝手が最も良いと考えています。シンプルでありながら、細かい調整ができ、イメージタグまで自動的に作成されるので、コピペの効率がグッと上がります（笑）。使ったことありませんが、React の専用ライブラリもあるようです。</p><h2 id="Identicon-generator"><a href="#Identicon-generator" class="headerlink" title="Identicon generator"></a><a href="https://identicon-1132.appspot.com/" target="_blank" rel="noopener">Identicon generator</a></h2><p>Identicon と言われたらピンっと来ない方が多いと思いますが、GitHub や SlackOverflow をよく利用している方であればこんなアイコンにはきっと出会ったことがあるはずです。</p><p><img src="https://identicon-1132.appspot.com/1432900262?s=20&p=7" alt="Identicon generator"></p><p>こちらのサービスはシンプルさをきわめたもので、余計な内容が全く入っていないと言っていいほどでしょう。パラメータが少ないゆえ基本的に GET クエリを弄るだけで話が済みますので、こっちの方が使いやすいと思いますよね。</p><h2 id="Placehold"><a href="#Placehold" class="headerlink" title="Placehold"></a><a href="https://placehold.co/" target="_blank" rel="noopener">Placehold</a></h2><p><img src="https://placehold.co/600x400/333/white?text=202Accepted&font=roboto" alt="Placehold"></p><p>画像プレースホルダーを作成するサービスがいくつかもあり、正直大した差がないと感じています。こちらの方はテキストとそれのフォントや色まで指定できるから、地味に便利だと思い、利用し続けています。パラメータが直感的なので、迷うことがないと思います。</p><h2 id="httpstat-us"><a href="#httpstat-us" class="headerlink" title="httpstat.us"></a><a href="https://httpstat.us/" target="_blank" rel="noopener">httpstat.us</a></h2><p>テキストや画像だけではなく、ダミーレスポンスを入れたい場合がよくあります。そういう時はこちらのサービスを愛用しています。例えば、<code>https://httpstat.us/202</code>をリクエストすれば、<code>202 Accepted</code>のレスポンスが戻って来ます。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">HTTP/1.1 202 Accepted</span><br><span class="line">Date: Sun, 17 Jan 2021 14:48:08 GMT</span><br><span class="line">Content-Length: 0</span><br><span class="line">Connection: close</span><br></pre></td></tr></table></figure><p><code>sleep</code>パラメータがサポートされているので、遅い処理をシミュレーションしたい場合だと非常に役に立ちます。</p><h2 id="Webhook-site"><a href="#Webhook-site" class="headerlink" title="Webhook.site"></a><a href="https://webhook.site/" target="_blank" rel="noopener">Webhook.site</a></h2><p>こちらは最近見つけたサービスですが、痒い所に手が届いた感覚でした。Bot サービスを作成やテストする時、ダミーの Webhook が欲しくなったりします。今まではローカルにダミーサーバーを立てて、ngrok でセットアップするやり方を利用して来ましたが、このサービスを使った方がスムーズだったりします。なので、これからも活用していきたいと考えています。</p><h2 id="さいごに"><a href="#さいごに" class="headerlink" title="さいごに"></a>さいごに</h2><p>以上私が気に入ったモック用サービスを 6 つ紹介しました。おまけに、GitHub の Octocat を自作するサイトを合わせて紹介したいと思います。モックのプロフィール画像を作成するのに使えるかもしれませんので、興味ある方はぜひ<a href="https://myoctocat.com/" target="_blank" rel="noopener">遊んでみてください。</a></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Web 開発を行う際に、ダミーコンテンツを利用したいシーンがしばしば出てきます。データベース内のデータじゃなくてもいいものの、それなりのリアリティが求められるケースも多いです。今日は私が気に入ったモック用サービスを紹介したいと思います。&lt;/p&gt;&lt;h2 id=&quot;Mockaroo&quot;&gt;&lt;a href=&quot;#Mockaroo&quot; class=&quot;headerlink&quot; title=&quot;Mockaroo&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://www.mockaroo.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Mockaroo&lt;/a&gt;&lt;/h2&gt;&lt;figure class=&quot;highlight sql&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;into&lt;/span&gt; MOCK_DATA (&lt;span class=&quot;keyword&quot;&gt;id&lt;/span&gt;, first_name, last_name, email, gender) &lt;span class=&quot;keyword&quot;&gt;values&lt;/span&gt; (&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Therine&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Cawsey&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;tcawsey0@issuu.com&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Female&#39;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;into&lt;/span&gt; MOCK_DATA (&lt;span class=&quot;keyword&quot;&gt;id&lt;/span&gt;, first_name, last_name, email, gender) &lt;span class=&quot;keyword&quot;&gt;values&lt;/span&gt; (&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Melvin&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Barthrup&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;mbarthrup1@mozilla.org&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Male&#39;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;into&lt;/span&gt; MOCK_DATA (&lt;span class=&quot;keyword&quot;&gt;id&lt;/span&gt;, first_name, last_name, email, gender) &lt;span class=&quot;keyword&quot;&gt;values&lt;/span&gt; (&lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Salim&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Iacobassi&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;siacobassi2@uiuc.edu&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Male&#39;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;into&lt;/span&gt; MOCK_DATA (&lt;span class=&quot;keyword&quot;&gt;id&lt;/span&gt;, first_name, last_name, email, gender) &lt;span class=&quot;keyword&quot;&gt;values&lt;/span&gt; (&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Gilemette&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Pittam&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;gpittam3@rediff.com&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Female&#39;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;into&lt;/span&gt; MOCK_DATA (&lt;span class=&quot;keyword&quot;&gt;id&lt;/span&gt;, first_name, last_name, email, gender) &lt;span class=&quot;keyword&quot;&gt;values&lt;/span&gt; (&lt;span class=&quot;number&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Gaylord&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Elliker&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;gelliker4@opensource.org&#39;&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&#39;Male&#39;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;氏名を始め、住所や電話番号、IP アドレス等々、いろんなダミーデータが作成できます。作成できたデータは CSV だけでなく、直接 JSON と SQL 等に書き出せる機能は非常にありがたいです。無料ユーザでしたら、1000 件までしか作れませんが、一時的にテストをする目的であれば十分だと思います。ただ、英語しか対応していなく、日本語のデータ作成ができないことは難点として挙げられます。&lt;/p&gt;&lt;h2 id=&quot;avataaars-generator&quot;&gt;&lt;a href=&quot;#avataaars-generator&quot; class=&quot;headerlink&quot; title=&quot;avataaars generator&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://getavataaars.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;avataaars generator&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://avataaars.io/?avatarStyle=Circle&amp;topType=LongHairStraight&amp;accessoriesType=Blank&amp;hairColor=BrownDark&amp;facialHairType=Blank&amp;clotheType=BlazerShirt&amp;eyeType=Default&amp;eyebrowType=Default&amp;mouthType=Default&amp;skinColor=Light&quot; alt=&quot;avataaars generator&quot;&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="mock" scheme="https://202accepted.com/tags/mock/"/>
    
  </entry>
  
  <entry>
    <title>wevox values cardをコードネーム風にアレンジしたらウケが凄くよかった話</title>
    <link href="https://202accepted.com/2021/01/01/mix-wevox-values-card-with-codenames/"/>
    <id>https://202accepted.com/2021/01/01/mix-wevox-values-card-with-codenames/</id>
    <published>2021-01-01T00:15:00.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p>去年 2 月あたりにオフサイトを企画しまして、その時アイスブレイクのコンテンツとして wevox values card をコードネーム風にアレンジしたゲームをみんなに遊んで頂きました。かなり反響がよかったので年末年始の時間を使って当時実施したゲームのルールを整理し、チームビルディングのアイスブレイクコンテンツで悩んでいる方のヒントにできればと思います。</p><h2 id="紹介"><a href="#紹介" class="headerlink" title="紹介"></a>紹介</h2><p>まず wevox values card とコードネームを軽く紹介したいと思います。<br>wevox values card はアトラエ社より出しているカードで、計 90 枚あって、それぞれのカードに価値観を表す一つの単語が書かれています。詳しい説明は<a href="https://wevox.io/valuescard" target="_blank" rel="noopener">公式サイト</a>を参照していただければと思います。wevox values card のメリットとしてはコンセプト通り価値観の相互理解へ有益だと思います。書かれている単語は全て価値観なので、カード間の優劣が存在していなく否定することは起こり得ないはずです。一方で、既存ルールのゲーム性が弱く盛り上がらない恐れがあります。さらに、チームワークの要素があんまりないので、チームビルディングの目的が果たしにくい面もあります。<br>一方、コードネームはチェコのヴラーダ・フヴァチルによって 2015 年に考案され、2016 年のドイツ年間ゲーム大賞も受賞した人気ボードゲームです。ルールがシンプルの上、大人数で遊びやすいとの定評があります。<a href="https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%89%E3%83%8D%E3%83%BC%E3%83%A0" target="_blank" rel="noopener">Wikipedia のページ</a>があるので、そちらをご参照頂ければわかりやすいと思います。</p><h2 id="ルール"><a href="#ルール" class="headerlink" title="ルール"></a>ルール</h2><h3 id="準備フェーズ"><a href="#準備フェーズ" class="headerlink" title="準備フェーズ"></a>準備フェーズ</h3><p><img src="/assets/mix-wevox-values-card-with-codenames/before.jpeg" alt="準備フェーズ"></p><ul><li>wevox values card のセットからランダムで 25 枚を引き、5 X 5 の形になるように卓上へ並べておく。</li><li>5 X 5 のマス目がある正解用紙を用意する（コードネームのキーカードと同じコンセプトで各マス目は卓上のカードとそれぞれ対応しているイメージになる）。</li><li>チームを二つ組んで頂き、それぞれのチームからリーダー（コードネームで言うスパイマスター）を一人選び、他の方はチームメンバー（コードネームで言うエージェント）になる。</li><li>リーダー達がじゃんけんで先攻を決め、先攻側のリーダーはチームリーダー同士以外誰も見えないように正解用紙を持ち、自分が大事にしている価値観のマスへ丸をつけ、後攻側のリーダーにペンを渡す。</li><li>後攻側のリーダーは同様に自分が大事にしている価値観のマスへバツをつける。但し、既にマークされたマスは選択不可。</li><li>丸 6 つ、バツ 5 つになるまで両リーダーが上記のマーク作業を繰り返す。</li></ul><h3 id="進行フェーズ"><a href="#進行フェーズ" class="headerlink" title="進行フェーズ"></a>進行フェーズ</h3><p><img src="/assets/mix-wevox-values-card-with-codenames/in-progress.jpeg" alt="進行フェーズ"></p><ul><li>マーク作業が終わったら、先攻側のチームメンバーからゲームを開始し、自チームのリーダーの人柄や性格を十分分析した上リーダーが選択した価値観を予測する。</li><li>その予測結果は先攻チーム（すなわち自チーム）のリーダーが選んだ価値観ならカードを反時計回りに 90 度回転し、逆に後攻チームのリーダーが選んだ価値観なら時計回りに 90 度回す。誰も選んでいなかった価値観なら裏返す。</li><li>自チームのリーダーが選んだ価値観を正しく当てたら、そのまま次のカードを選んで構いません（但し、継続せずスキップを選択しても問題ない）。誰も選んでいなかった価値観、もしくは相手チームのリーダーが選んだ価値観でしたら、相手チームの予測ターンになる。</li><li>終了条件を満たすまで上記のフローを繰り返す。</li></ul><h3 id="終了フェーズ（終了条件）"><a href="#終了フェーズ（終了条件）" class="headerlink" title="終了フェーズ（終了条件）"></a>終了フェーズ（終了条件）</h3><p><img src="/assets/mix-wevox-values-card-with-codenames/after.jpeg" alt="終了フェーズ"></p><ul><li>反時計回りに 90 度回転したカードが 6 つに到達した場合先攻チームの勝ちになり、逆に時計回りに回したカードが 5 つに到達した場合後攻チームの勝ちになる。</li></ul><h2 id="反響"><a href="#反響" class="headerlink" title="反響"></a>反響</h2><p>思った以上にウケがよかったです。みんな楽しそうに遊んで頂きましたし、フィードバックアンケートの中に「面白かった」・「またやりたい」のような声が多く、「リーダーの意外な一面が知れた」みたいなコメントも頂きました。なので、狙い通りだったと思います。昨今のご時世によりオフラインでの開催が難しくなってきたと思いますが、ちょっと工夫すれば、オンラインで実施することも不可能じゃないと考えていますので、活用していただければと思います。</p><p><em>ちなみに、本日は2021年の元日です。明けましておめでとうございます！</em></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;去年 2 月あたりにオフサイトを企画しまして、その時アイスブレイクのコンテンツとして wevox values card をコードネーム風にアレンジしたゲームをみんなに遊んで頂きました。かなり反響がよかったので年末年始の時間を使って当時実施したゲームのルールを整理し、チームビルディングのアイスブレイクコンテンツで悩んでいる方のヒントにできればと思います。&lt;/p&gt;&lt;h2 id=&quot;紹介&quot;&gt;&lt;a href=&quot;#紹介&quot; class=&quot;headerlink&quot; title=&quot;紹介&quot;&gt;&lt;/a&gt;紹介&lt;/h2&gt;&lt;p&gt;まず wevox values card とコードネームを軽く紹介したいと思います。&lt;br&gt;wevox values card はアトラエ社より出しているカードで、計 90 枚あって、それぞれのカードに価値観を表す一つの単語が書かれています。詳しい説明は&lt;a href=&quot;https://wevox.io/valuescard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;公式サイト&lt;/a&gt;を参照していただければと思います。wevox values card のメリットとしてはコンセプト通り価値観の相互理解へ有益だと思います。書かれている単語は全て価値観なので、カード間の優劣が存在していなく否定することは起こり得ないはずです。一方で、既存ルールのゲーム性が弱く盛り上がらない恐れがあります。さらに、チームワークの要素があんまりないので、チームビルディングの目的が果たしにくい面もあります。&lt;br&gt;一方、コードネームはチェコのヴラーダ・フヴァチルによって 2015 年に考案され、2016 年のドイツ年間ゲーム大賞も受賞した人気ボードゲームです。ルールがシンプルの上、大人数で遊びやすいとの定評があります。&lt;a href=&quot;https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%89%E3%83%8D%E3%83%BC%E3%83%A0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Wikipedia のページ&lt;/a&gt;があるので、そちらをご参照頂ければわかりやすいと思います。&lt;/p&gt;&lt;h2 id=&quot;ルール&quot;&gt;&lt;a href=&quot;#ルール&quot; class=&quot;headerlink&quot; title=&quot;ルール&quot;&gt;&lt;/a&gt;ルール&lt;/h2&gt;&lt;h3 id=&quot;準備フェーズ&quot;&gt;&lt;a href=&quot;#準備フェーズ&quot; class=&quot;headerlink&quot; title=&quot;準備フェーズ&quot;&gt;&lt;/a&gt;準備フェーズ&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;/assets/mix-wevox-values-card-with-codenames/before.jpeg&quot; alt=&quot;準備フェーズ&quot;&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="org" scheme="https://202accepted.com/categories/org/"/>
    
    
      <category term="team-building" scheme="https://202accepted.com/tags/team-building/"/>
    
      <category term="boardgame" scheme="https://202accepted.com/tags/boardgame/"/>
    
  </entry>
  
  <entry>
    <title>働きながらUoPeopleのMBAを取った話</title>
    <link href="https://202accepted.com/2020/12/25/graduated-from-uopeople/"/>
    <id>https://202accepted.com/2020/12/25/graduated-from-uopeople/</id>
    <published>2020-12-25T00:01:00.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p><em>こちらは <a href="https://adventar.org/calendars/5977" target="_blank" rel="noopener">【増枠】社会人学生 Advent Calendar 2020</a> 25 日目の記事です。<strong>メリークリスマス！</strong></em></p><p><img src="https://www.uopeople.edu/wp-content/uploads/2018/01/logo_uopeople.png" alt="UoPeople"></p><p>まず具体的なタイムラインを紹介しますと、2018 年春の Term 4 から授業を取り始め、今年の Term 3 にて最後の Capstone を修了し、3 月 31 日に卒業申請を出してから 2 ヶ月強を待ち、6 月 8 日に学位記が届き、晴れて Alum と名乗れるようになりました。</p><h2 id="UoPeople-とは"><a href="#UoPeople-とは" class="headerlink" title="UoPeople とは"></a>UoPeople とは</h2><p>UoPeople は University of the People の略称でアメリカの非営利オンライン大学です。ググれば Wikipedia の記事や内容を紹介するブログが一杯出てくるので、説明は割愛させて頂きます。ただ、入学記が多いものの、卒業後の感想を述べる記事はあんまり見当たらなかったので、自分の振り返りを兼ねて軽く綴りたいと思います。</p><h2 id="なぜ-UoPeople-の-MBA-を取ろうと考えたか"><a href="#なぜ-UoPeople-の-MBA-を取ろうと考えたか" class="headerlink" title="なぜ UoPeople の MBA を取ろうと考えたか"></a>なぜ UoPeople の MBA を取ろうと考えたか</h2><p>転職して今の会社に入社した後、ビジネス・企画側とコミュニケーションをする機会が増え、技術畑を歩んできた私が自分の知識不足を実感していました。そしてピンポイントで埋められる感覚じゃなかったので、体系的に学べる MBA プログラムの方が良さそうと感じました。<br>リアル通学も考えていましたが、会社は相対的に寛容な方だとはいえ、業務時間内で大学に通わせる制度がありませんでした。それに対し、Coursera や AI-Class（Udacity の前身）で MOOC 形式の授業をうけることが普通にありましたので、オンライン通学にあんまり違和感を感じませんでした。更に言うと、会社の中では英語が相対的に得意な方ですので、無駄にしたくなかった気持ちもありました。<br>当時、オンライン MBA の選択肢がそんなにありませんでした。自分が色々調べた結果、選択肢として上がって来たのは<a href="https://onlinemba.illinois.edu/" target="_blank" rel="noopener">UIUC の iMBA プログラム</a>と UoPeople の MBA のみでした。<br>大学の知名度及びコースの質的には、当時まだ無名に近い UoPeople が新しく出したプログラムより、UIUC のプログラム（iMBA プログラム自体は新しいけれど）の方が圧倒的に強かったと思います。<br>一方で、安い方だと言われた学費（2 万ドル）は当時の私にとってやはり高いと感じました。そして、mortar-and-brick 的な大学の MBA を取る方々は基本的にソーシャルコネクションを重要視している方だと思い、オンライン環境だとそれが厳しい上、あくまで授業の内容だけ気にしている私にとって、UoPeople の方がコスパがいいかと考えました。</p><h2 id="授業をとってみた感想"><a href="#授業をとってみた感想" class="headerlink" title="授業をとってみた感想"></a>授業をとってみた感想</h2><p>一言で感想を述べますと、思ったより遥かに大変だったと言わざるを得ません。前述した通り、それまでも何回かオンラインで授業を受けていたので、あんまり変わらないイメージでコースを始めましたが、いきなり多量な Material を読まされ、「読んだ資料を踏まえ、Essay 二本を書いて水曜日まで提出してね」みたいな感覚でした。今振り返ってみたら、初週の宿題は楽勝な方だと言ってもいいですが、当時は「無理や、やめよう」と考えていたくらいでした。<br>その為、基本的には毎週の週末が潰される感覚で二年間を送ってきました。もちろん、Term と Term の間に 2 週間ほど（場合によって 3 週間もあり得る）空きが出るので、そこは一息を入れるチャンスでした。とはいえ、後述しますが、その時間も無駄にしてはいけないと考えています。なので、理解して下さって、この 2 年間支えてくださった家族と同僚に感謝の気持ちで一杯です。<br>語学力の問題だと考える方もいらっしゃると思います。もちろん英語力が高ければ読み書きのスピードがある程度上がるはずです。とはいえ、英語力が高くても時間がかかると私が思います。普通に Assignment が多いからです笑。MBA の授業を取ってる方の半数以上（今海外での知名度も上がってきているので比率が下がっているかもしれませんが）はアメリカ人です。Yammer（学生同士のコミュニケーションツール）で検索すればわかりますが、思ったより大変だとの投稿がちらほらあります。<br>かといって、慣れればなんとかなります。自分は 5 つ目の授業までは毎 Term 1 コースしか取っていませんでしたが、5 つ目のところから若干力の余裕を感じ始めました。最初から二年間で修了すると決めていたから、授業を同時に 2 つ取ってみようとチャンレンジしました。同様に初期は全然慣れなくて、宿題を書くために有給をガッツリ使う羽目になってましたが、最終的に有給を取らなくてもやり過ごせるようになっていました。運動と同じく、トレーニングが必要だったと考えています。</p><h2 id="コースの内容について"><a href="#コースの内容について" class="headerlink" title="コースの内容について"></a>コースの内容について</h2><p>当初の期待を裏切ることなく、有益な二年間だと私が評価しています。<br>NYU Stern の教授が作成に関わったからか、コース全体の設計が合理的だったと思います。財務・マーケティング・組織論・ビジネス戦略など、知識を全面的に学び、段階的に進むことができ、知らなかった知識をたくさん身に付けることができました。使っているケーススタディは基本的に Harvard Business Review や定番教科書から取ってきた代表的なやつでオフラインの MBA で学習する内容と大体一緒じゃないかと考えます。逆に、オンラインである故に、アメリカの話はもちろん、ヨーロッパや東南アジア・アフリカのことを他の生徒の Essay から知ることができ、視野を広げるいいきっかけだったと感じます。<br>もちろん、コミュニケーションが取りにくいなどオンライン授業としてのデメリットが諸に出ていましたし、宿題の Peer Review を含む授業システムに賛否両論なところもありました。特に入学が簡単だったから、最初の授業で適当に宿題を書いて提出する学生がそれなりにいました。ただ、後半になればなるほど、Discussion と Written Assignment の質が高くなる傾向でした。乱暴に単語数で例をあげますが、最初の授業の Discussion 投稿はせいぜい 200~500 単語くらいでしたが、最後の授業では 1000 単語を下回る投稿が見当たらなく、逆に 2000 以上が散見されていました。<br>その他、Instructor と Program Advisor が無責任で生徒が放置されているとの意見も見たことありますが、自分は出会ったことがなく、指摘と質問をそのたびに適切に対処してくれていました。</p><h2 id="自分に役に立った-Tips"><a href="#自分に役に立った-Tips" class="headerlink" title="自分に役に立った Tips"></a>自分に役に立った Tips</h2><h3 id="Drop-を活用する"><a href="#Drop-を活用する" class="headerlink" title="Drop を活用する"></a>Drop を活用する</h3><p>UoPeople の学生は毎 Term 最大で 3 授業をとることができます（Degree Seeking Student になる前もしくは GPA が足りない時は 1 か 2 になります）。自分は毎回最大限までとっていました。もちろん 1 Term で 3 つのコースを学習する余裕がなかったし、やったこともありませんでした。しかし、第一週目で Learning Guide を読み、学生リストを見ればその授業の雰囲気を推測することができます。そこで自分の仕事状況等に合わせて今 Term 取りたいコースを決めて他のコースを Drop することは私の常套手段でした。コース申込時得られる情報と比べ、第一週目で得られる情報量が圧倒的に多いので、判断を毎 Term の始まりに先延ばした方が良いと思います。しかも第一週目の時 Drop する場合、何の記録も残ることなく、費用もかからないので損することが一切ないと思います。</p><h3 id="資料をちゃんと残す"><a href="#資料をちゃんと残す" class="headerlink" title="資料をちゃんと残す"></a>資料をちゃんと残す</h3><p>前述した通り私は Learning Guide を読んでから授業を落としたりしました。その場合、読んだ Learning Guide を一旦保存していました。MBA プログラムのコースの選択範囲がそんなに広くなく、「今 Term は取りたくないものの、いずれ取らなければいけない」ケースがよくありました。その場合、Term と Term の間になったら、Learning Guide を読んで予習することができます。さらに余裕があれば、宿題を書き始めることもできます。そうすれば、Term に入ってからのワークロードが減るので、ストレスなくコースをうけることができます。<br>また、Learning Guide のみならず、自分が提出した Assignment（Written だけじゃなく Discussion や Group Work も）を全部保存すべきかと思います。それらは後続のコース、特に BUS 5117（Strategic Decision Making and Management）と BUS 5910（Management Capstone）の授業で再び閲覧したくなるかもしれません（自分はしました）。</p><h3 id="コミュニティを使って孤独感を解消し、ノウハウを得る"><a href="#コミュニティを使って孤独感を解消し、ノウハウを得る" class="headerlink" title="コミュニティを使って孤独感を解消し、ノウハウを得る"></a>コミュニティを使って孤独感を解消し、ノウハウを得る</h3><p>やはりオンライン通学は孤独な旅に例えられます。私は家族と上司の理解を得られて（ありがたいことにMBA 申請用の推薦状も当時の上司に書いて頂きました）、相対的に良い方だと思いますが、それでもしばしば辛く感じていました。人間は社会的動物なので、周りと違う行動を継続的に行うと、違和感を感じたり孤独を感じたりすることは当たり前だと私が思います。その場合、Yammer で投稿を読んだりコミュニケーションを取ることで、自分と同じ道を歩んでいる方と交流でき、その孤独感がかなり解消できます。<br>その上、Yammer や <a href="https://www.reddit.com/r/UoPeople/" target="_blank" rel="noopener">Reddit</a> の投稿から知らなかった情報を入手することもできます。例えば、MBA の学生は Degree Seeking Student になった後、GPA が一度リセットされる情報は Yammer の投稿から初めて知りました。そういう情報を入手することで、もっとスムーズに計画を行うことができると思います。</p><h3 id="Term-の-Gap-を視野に入れる"><a href="#Term-の-Gap-を視野に入れる" class="headerlink" title="Term の Gap を視野に入れる"></a>Term の Gap を視野に入れる</h3><p>Term の Gap を指しているのは、何の授業も取らない Term を挟むことです。今のルールが変わったかわかりませんが、 Term を 3 つまで Gap しても休学扱いにならないルールだったと思います。仕事の激務もあって、自分は一時期あんまりにもしんどくて、宿題をやるたびに吐きそうな感覚だったので、その次の Term を Gap することを決意しました。決断に当たって結構迷いがあって、進捗がさらに遅れる罪悪感と「このままやめてしまうんじゃないか」との心配がありました。でも結果的に元気になってまた気持ちよく学べるようになりました。なので、本当に辛くなったら、無理せず Gap したり、コースを Withdraw したりして、一休みを設けた方が効率的かもしれません。UoPeople のカレンダーに Term が 5 つもあるので、1 Term が空いてもそこまで問題にならないと思います。</p><h2 id="さいごに"><a href="#さいごに" class="headerlink" title="さいごに"></a>さいごに</h2><p>2020 年 12 月現在、UoPeople はまだ National Accreditation の大学（<a href="https://www.uopeople.edu/student-experience/quality/accreditation/" target="_blank" rel="noopener">Regional Accreditation 申請中</a>）で知名度と評判も発展途上です。とはいえ、周囲の環境に左右されず、自ら目標を定め、純粋に知識を学習したい方にとっては有効な選択肢じゃないかと私が思います。まとまってない文章ですが、今後 UoPeople に通いたい方、今通っている方の参考になれれば幸いです。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;em&gt;こちらは &lt;a href=&quot;https://adventar.org/calendars/5977&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;【増枠】社会人学生 Advent Calendar 2020&lt;/a&gt; 25 日目の記事です。&lt;strong&gt;メリークリスマス！&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://www.uopeople.edu/wp-content/uploads/2018/01/logo_uopeople.png&quot; alt=&quot;UoPeople&quot;&gt;&lt;/p&gt;&lt;p&gt;まず具体的なタイムラインを紹介しますと、2018 年春の Term 4 から授業を取り始め、今年の Term 3 にて最後の Capstone を修了し、3 月 31 日に卒業申請を出してから 2 ヶ月強を待ち、6 月 8 日に学位記が届き、晴れて Alum と名乗れるようになりました。&lt;/p&gt;&lt;h2 id=&quot;UoPeople-とは&quot;&gt;&lt;a href=&quot;#UoPeople-とは&quot; class=&quot;headerlink&quot; title=&quot;UoPeople とは&quot;&gt;&lt;/a&gt;UoPeople とは&lt;/h2&gt;&lt;p&gt;UoPeople は University of the People の略称でアメリカの非営利オンライン大学です。ググれば Wikipedia の記事や内容を紹介するブログが一杯出てくるので、説明は割愛させて頂きます。ただ、入学記が多いものの、卒業後の感想を述べる記事はあんまり見当たらなかったので、自分の振り返りを兼ねて軽く綴りたいと思います。&lt;/p&gt;&lt;h2 id=&quot;なぜ-UoPeople-の-MBA-を取ろうと考えたか&quot;&gt;&lt;a href=&quot;#なぜ-UoPeople-の-MBA-を取ろうと考えたか&quot; class=&quot;headerlink&quot; title=&quot;なぜ UoPeople の MBA を取ろうと考えたか&quot;&gt;&lt;/a&gt;なぜ UoPeople の MBA を取ろうと考えたか&lt;/h2&gt;
    
    </summary>
    
      <category term="life" scheme="https://202accepted.com/categories/life/"/>
    
    
      <category term="uopeople" scheme="https://202accepted.com/tags/uopeople/"/>
    
  </entry>
  
  <entry>
    <title>純粋なCSSで実現するアクセス解析</title>
    <link href="https://202accepted.com/2020/12/24/css-analytics/"/>
    <id>https://202accepted.com/2020/12/24/css-analytics/</id>
    <published>2020-12-24T10:31:28.000Z</published>
    <updated>2021-08-16T14:23:52.220Z</updated>
    
    <content type="html"><![CDATA[<p>アクセス解析は昨今のウェブサービスを実装する上で欠かせない要件になってきています。アクセス解析を実現するのに、いろんなツールやソリューションを活用することができます。その中で最も利用されているのは恐らくGoogle Analyticsだと思います。Google Analyticsから提供してくれたスクリプトタグをHTMLファイルに埋め込むだけで来訪者のデバイス情報やブラウザ情報等を把握できてしまいます。一方で、Google Analyticsのようにスクリプトタグを埋めることはJavaScriptを使うことです。もしユーザがそのスクリプト（もしくはJavaScriptの実行自体）をブロックしたら、当然ながら情報の収集ができなくなります。そのような場合、アクセス解析が不可能になるでしょうか？簡易的ではありますが、実は純粋なCSSでもある程度代用できたりします。</p><h2 id="メディアクエリを使ってデバイス情報を取得する"><a href="#メディアクエリを使ってデバイス情報を取得する" class="headerlink" title="メディアクエリを使ってデバイス情報を取得する"></a>メディアクエリを使ってデバイス情報を取得する</h2><p>まずHTMLファイルに見えない要素を一つ置いておきます。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">"invisible-element"</span>&gt;</span><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br></pre></td></tr></table></figure><p>そして<a href="https://developer.mozilla.org/ja/docs/Web/CSS/url()" target="_blank" rel="noopener"><code>url</code>関数</a>を活用し、こういうCSSを書けばOKです。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@<span class="keyword">media</span> screen and (orientation: portrait) &#123;</span><br><span class="line">  <span class="selector-class">.invisible-element</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">url</span>(https://example.org/analytics?orientation=portrait);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@<span class="keyword">media</span> screen and (orientation: landscape) &#123;</span><br><span class="line">  <span class="selector-class">.invisible-element</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">url</span>(https://example.org/analytics?orientation=landscape);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>ユーザのデバイスが縦長の向きになっている場合、<code>orientation=portrait</code>のGETリクエストが<code>https://example.org/analytics</code>に飛ばされるので、そちらのエンドポイントで集計することが可能になります。<a href="https://developer.mozilla.org/ja/docs/Web/CSS/@media#Media_features" target="_blank" rel="noopener">メディアクエリで使えばメディア特性</a>なら通用するので、ビューポートの向き以外、スクリーンのサイズやresolutionを検知することも可能です。例えば、<code>@media screen and (min-resolution: 2dppx)</code>を使えば、ユーザのデバイスがRetinaかどうかは判断できるようになります。</p><h2 id="supportsを使ってブラウザの情報を取得する"><a href="#supportsを使ってブラウザの情報を取得する" class="headerlink" title="@supportsを使ってブラウザの情報を取得する"></a>@supportsを使ってブラウザの情報を取得する</h2><p>メディアクエリのケースと似ていますが、下記のようなコードを使えば、ユーザが相対的に新しいブラウザを使っているか分かるようになります。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@<span class="keyword">supports</span> (display: inline-grid) &#123;</span><br><span class="line">  <span class="selector-class">.invisible-element</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">url</span>(https://example.org/analytics?new-browser=true);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@<span class="keyword">supports</span> not (display: inline-grid) &#123;</span><br><span class="line">  <span class="selector-class">.invisible-element</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">url</span>(https://example.org/analytics?new-browser=false);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>ユーザが使っているブラウザとバージョンによってCSS特性のサポートができていない、もしくは廃止されているかもしれません。よって、条件を組み合わせば、ユーザが使っているブラウザのバージョンまで特定できるでしょう。</p><h2 id="疑似クラスを使ってユーザの行動を統計する"><a href="#疑似クラスを使ってユーザの行動を統計する" class="headerlink" title="疑似クラスを使ってユーザの行動を統計する"></a>疑似クラスを使ってユーザの行動を統計する</h2><p>下記のような2つのリンクがあるとします。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">id</span>=<span class="string">"product-1"</span> <span class="attr">href</span>=<span class="string">"https://example.com/product-1"</span>&gt;</span>Buy Product 1<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">id</span>=<span class="string">"product-2"</span> <span class="attr">href</span>=<span class="string">"https://example.com/product-2"</span>&gt;</span>Buy Product 2<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure><p>ユーザが実際にクリックした回数だけではなく、興味を示してくれた回数を統計したい要望があり得ます。以下のようなCSSコードを使えば、カーソルが載せた（Hoverの）回数を集計できるようになります。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#product-1</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">    <span class="attribute">content</span>: <span class="built_in">url</span>(<span class="string">'https://example.org/analytics?hover-product=1'</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#product-2</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">    <span class="attribute">content</span>: <span class="built_in">url</span>(<span class="string">'https://example.org/analytics?hover-product=2'</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>擬似要素を使っている為、別のDOM要素を設ける必要すらありません。もちろん、<code>:hover</code>以外に、<code>:focus</code>や<code>:active</code>に適用することが可能です。さらに、<a href="https://developer.mozilla.org/ja/docs/Web/CSS/var()" target="_blank" rel="noopener"><code>var()</code>関数</a>を活用すれば、ユーザを特定するところまで行えます。<br>やり方は簡単です。まず下記のようにHTMLをレンダリングする側がユーザIDが含まれているURLを作成し、該当要素のstyle属性に埋め込みます。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">id</span>=<span class="string">"product-1"</span> <span class="attr">href</span>=<span class="string">"https://example.com/product-1"</span> <span class="attr">style</span>=<span class="string">"--analytics-hover-product-1: url('https://example.org/analytics?user-id=10000&amp;hover-product=1');"</span>&gt;</span>Buy Product 1<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">a</span> <span class="attr">id</span>=<span class="string">"product-2"</span> <span class="attr">href</span>=<span class="string">"https://example.com/product-2"</span> <span class="attr">style</span>=<span class="string">"--analytics-hover-product-2: url('https://example.org/analytics?user-id=10000&amp;hover-product=2');"</span>&gt;</span>Buy Product 2<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br></pre></td></tr></table></figure><p>それからCSS側で変数として使うだけで完成です。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#product-1</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">    <span class="attribute">content</span>: <span class="built_in">var</span>(--analytics-hover-product-1);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#product-2</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">::before</span> &#123;</span><br><span class="line">    <span class="attribute">content</span>: <span class="built_in">var</span>(--analytics-hover-product-2);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>HTMLとCSSのみで実現でき、JavaScriptを一切介していないので、スクリプトをブロックしても集計ができてしまいます。しかし、流石にここまでやると、わざわざスクリプトをブロックしたユーザに怒られそうですね笑。</p><h2 id="まとめ"><a href="#まとめ" class="headerlink" title="まとめ"></a>まとめ</h2><p>使っている技術が別に目新しくなく、実装自体もシンプルだと思います。どちらかと言いますと、こういうアイデアがなかなか思い付かないんじゃないかと思います。ただ、泥臭い部分がどうしてもありますので、Google Analyticsが使えればGoogle Analyticsを使いますけどね。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;アクセス解析は昨今のウェブサービスを実装する上で欠かせない要件になってきています。アクセス解析を実現するのに、いろんなツールやソリューションを活用することができます。その中で最も利用されているのは恐らくGoogle Analyticsだと思います。Google Analyticsから提供してくれたスクリプトタグをHTMLファイルに埋め込むだけで来訪者のデバイス情報やブラウザ情報等を把握できてしまいます。一方で、Google Analyticsのようにスクリプトタグを埋めることはJavaScriptを使うことです。もしユーザがそのスクリプト（もしくはJavaScriptの実行自体）をブロックしたら、当然ながら情報の収集ができなくなります。そのような場合、アクセス解析が不可能になるでしょうか？簡易的ではありますが、実は純粋なCSSでもある程度代用できたりします。&lt;/p&gt;&lt;h2 id=&quot;メディアクエリを使ってデバイス情報を取得する&quot;&gt;&lt;a href=&quot;#メディアクエリを使ってデバイス情報を取得する&quot; class=&quot;headerlink&quot; title=&quot;メディアクエリを使ってデバイス情報を取得する&quot;&gt;&lt;/a&gt;メディアクエリを使ってデバイス情報を取得する&lt;/h2&gt;&lt;p&gt;まずHTMLファイルに見えない要素を一つ置いておきます。&lt;/p&gt;&lt;figure class=&quot;highlight html&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;invisible-element&quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;name&quot;&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;そして&lt;a href=&quot;https://developer.mozilla.org/ja/docs/Web/CSS/url()&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;url&lt;/code&gt;関数&lt;/a&gt;を活用し、こういうCSSを書けばOKです。&lt;/p&gt;&lt;figure class=&quot;highlight css&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;@&lt;span class=&quot;keyword&quot;&gt;media&lt;/span&gt; screen and (orientation: portrait) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;selector-class&quot;&gt;.invisible-element&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;attribute&quot;&gt;background&lt;/span&gt;: &lt;span class=&quot;built_in&quot;&gt;url&lt;/span&gt;(https://example.org/analytics?orientation=portrait);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;@&lt;span class=&quot;keyword&quot;&gt;media&lt;/span&gt; screen and (orientation: landscape) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;selector-class&quot;&gt;.invisible-element&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;attribute&quot;&gt;background&lt;/span&gt;: &lt;span class=&quot;built_in&quot;&gt;url&lt;/span&gt;(https://example.org/analytics?orientation=landscape);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="css" scheme="https://202accepted.com/tags/css/"/>
    
  </entry>
  
  <entry>
    <title>ストーリーポイントを効率よく見積もる為に</title>
    <link href="https://202accepted.com/2019/08/18/story-points-estimation/"/>
    <id>https://202accepted.com/2019/08/18/story-points-estimation/</id>
    <published>2019-08-18T20:30:25.000Z</published>
    <updated>2021-08-16T14:23:52.222Z</updated>
    
    <content type="html"><![CDATA[<p>ストーリーポイントはどのように見積もっていますか？PO がユーザーストーリーを紹介した上、各自が手元のプランニングポーカーから一枚を引き（もしかしたらアプリかもしれません）、「せーの」と唱えった後おもての数字を見せ合います。もし違いが存在していたら、互いに説明をし、最終的に同じ数字に揃えるようにします。とても定番的なやり方ですよね。しかし、そのやり方を貫くだけで、上手く行くとは限りません。例えば、A さんが 1 を出しているものの、B さんがその数字をはるかに上回った 5 とかを出しているケースが頻出していたら、回し方に問題が潜んでいるはずです。自分の経験上、以下の 3 点に関する問題が起因となった可能性が高いです。</p><h2 id="バックログアイテムがうまく作成されていない"><a href="#バックログアイテムがうまく作成されていない" class="headerlink" title="バックログアイテムがうまく作成されていない"></a>バックログアイテムがうまく作成されていない</h2><p>正確なストーリーポイントが出せていないというのはあくまで事象で、そもそも土台に当たるバックログアイテムが見積もりにくい状態になっていることはよくあります。バックログアイテムの完成度を判断するのによく使用されているのは「I.N.V.E.S.T」という基準です。要するに、取り扱いやすいアイテムは以下の基準を満たさなければいけません。</p><ul><li>Independant (独立している)</li><li>Negotiable (交渉できる)</li><li>Valuable (価値がある)</li><li>Estimatable (見積れる)</li><li>Small (サイズが小さい)</li><li>Testable (検証できる)</li></ul><p>ネット上「I.N.V.E.S.T」を説明する<a href="https://dev.to/code2bits/user-story-guidelines-l2e" target="_blank" rel="noopener">良い記事</a>がたくさん存在している為、細かい説明は割愛しますが、ここで Independant と Estimatable に注目したいです。例えば、「上のアイテムを完成しないと、下のアイテムが見積もれないよ」という言い方はよく聞きます。それは恐らく独立性の不足を表している証拠です。上手く切ったユーザーストーリーなら、お互いに干渉しないし、不確実性の急増がしません。</p><p>また、Estimatable も大事です。ストーリーポイントを出す前、開発チームが見積もる対象のスコープと情報を理解していなければ、正しい見積もりが出せません。もしバックログアイテムが見積もりにくいと感じたら、リファインメントもしくはプランニング 1 のタイミングで開発チームと PO が擦り合わせを行うべきです。</p><h2 id="ストーリーポイントの定義に関する理解が異なっている"><a href="#ストーリーポイントの定義に関する理解が異なっている" class="headerlink" title="ストーリーポイントの定義に関する理解が異なっている"></a>ストーリーポイントの定義に関する理解が異なっている</h2><p>ストーリーポイントを効率よく出す為に、ストーリーポイントの定義をしっかり理解するという前提条件があります。ストーリーポイントと時間の関係性を説明する記事が世の中にいっぱい出回っていますが、理論上ストーリーポイントと時間は換算できないし、すべきではありません。ストーリーポイントはチームの<strong>努力</strong>を<strong>相対的</strong>に表している単位で、投資しなければいけない時間はあくまで参考基準の一つに過ぎません。技術的なチャンレンジが含まれているユーザーストーリーは当然ながら大きな努力を要しますので、時間だけで考えるとストーリーポイントの趣旨と異なってしまいます。</p><p>正確には、ストーリーポイントを通して見たいことはバックログアイテム間の差です。仮にアイテム A のストーリーポイントは 1 で、アイテム B のストーリーポイントは 5 でしたら、アイテム B を消化させる為に 5 倍ほどの努力をしなければいけないことを意味します。PO はそれを重要な参考材料とした上でアイテム間の順位を決めることになります。さらに、もし前スプリントにおいてアイテム B を消化できたものの今スプリントでは５ポイント消化できなかったら、それを振り返り時の客観的材料として利用することができます。ストーリーポイントの定義を正しく理解していなければ、当然ながら見積もりが上手くいかないはずです。</p><h2 id="見積もる際に考える軸が定まっていない"><a href="#見積もる際に考える軸が定まっていない" class="headerlink" title="見積もる際に考える軸が定まっていない"></a>見積もる際に考える軸が定まっていない</h2><p>上記の前提条件をクリアしたとしても見積もりが上手くいかなかったりします。議論の内容を聞けばわかるはずですが、ストーリーポイントを出す時考慮した要素が異なるケースは度々現れます。例えば、A さんが仕様の複雑性を配慮し 3 を出したが、B さんが技術上実現しやすいという考えで 1 を出したりします。無論話し合いにより抜けた観点が補完され、最終的に目線が合わせられますが、効率性を考えれば、最初から合わせた方が有益でしょう。すなわち、ストーリーポイントを見積もる際に考慮したい軸を事前に共有しあい、みんながそれに従って考えることで観点の抜け漏れを未然に防ぐイメージです。ここで二つの考え方を紹介したいと思います。</p><p>一つ目は<a href="https://www.mountaingoatsoftware.com/blog/what-are-story-points" target="_blank" rel="noopener">Mike Cohn 先生の定義</a>に従った考え方です。ストーリーポイントを見積もる時、以下の三要素から考えるイメージです。</p><ul><li>作業量</li><li>複雑度</li><li>不確実性またはリスク</li></ul><p>この考え方の実用例として Michael Lant さんの Effort Matrix があります。上記の 3 つめの要素、不確実性を複雑度へマージしたマトリクスです。</p><p><img src="https://i2.wp.com/michaellant.com/wp-content/uploads/2010/08/EffortMatrix.png" alt="Effort Matrix"></p><p>この手法に関するモチベーション、やり方およびフィードバックは Michael Lant さんのブログにて詳しく紹介されていますので、詳細は<a href="https://michaellant.com/2010/07/05/estimating-effort-for-your-agile-stories-2/" target="_blank" rel="noopener">そちら</a>をご参照ください。</p><p>もう一つは<a href="http://www.gp-training.net/training/communication_skills/consultation/equipoise/complexity/stacey.htm" target="_blank" rel="noopener">Stacey matrix</a>の思想を借りて、仕様難易度（Requirements）と実装難易度（Methods）二軸で考えることです。下記の図は実用化されているメトリクスを表しています。縦軸は仕様難易度で横軸は実装難易度です。緑は「セーフティゾーン（Safety Zone）」、黄色は「ハザードゾーン（Hazard Zone）」で、赤は「デンジャーゾーン（Danger Zone）」です。</p><p><img src="/assets/story-point-matrix.png" alt="Story Point Matrix"></p><p>仕様難易度が 2、実装難易度が 3 でしたら、ストーリーポイントが 5 点になり、ハザードゾーンに入ります。すなわち、許容できるものの、できれば避けたい粒度です。もしストーリーポイントの結果がデンジャーゾーンに落ちたら、アイテムの分割が上手くいっていないと考えられます。運用している際に、仕様難易度はちょうどユーザーストーリーの What 部分に当たり、実装難易度は How の部分に当たるため、イメージしやすいと評価されていました。</p><h2 id="最後に"><a href="#最後に" class="headerlink" title="最後に"></a>最後に</h2><p>上記の内容はあくまで経験則に過ぎないので、全てのチームに合致しているとは考えにくいです。例えば、成熟しているチームなら、わざわざ二軸に分けてストーリーポイントを考えることはむしろ過剰だと思います。結局のところ、自分のチームへ最も相応しい方法を見つけ出すことは一番大事ですよね。</p><h2 id="参考記事"><a href="#参考記事" class="headerlink" title="参考記事"></a>参考記事</h2><ul><li><a href="https://www.scruminc.com/story-points-why-are-they-better-than/" target="_blank" rel="noopener">Story Points: Why are they better than hours?</a></li><li><a href="https://www.scrum.org/resources/blog/why-do-we-use-story-points-estimating" target="_blank" rel="noopener">Why do we use Story Points for Estimating?</a></li><li><a href="https://medium.com/@mdalmijn/12-common-mistakes-made-when-using-story-points-f0bb9212d2f7" target="_blank" rel="noopener">12 common mistakes made when using Story Points</a></li><li><a href="https://medium.com/the-liberators/on-complexity-why-your-software-project-needs-scrum-13c36305c866" target="_blank" rel="noopener">On Complexity: Why Your Software Project Needs Scrum</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;ストーリーポイントはどのように見積もっていますか？PO がユーザーストーリーを紹介した上、各自が手元のプランニングポーカーから一枚を引き（もしかしたらアプリかもしれません）、「せーの」と唱えった後おもての数字を見せ合います。もし違いが存在していたら、互いに説明をし、最終的に同じ数字に揃えるようにします。とても定番的なやり方ですよね。しかし、そのやり方を貫くだけで、上手く行くとは限りません。例えば、A さんが 1 を出しているものの、B さんがその数字をはるかに上回った 5 とかを出しているケースが頻出していたら、回し方に問題が潜んでいるはずです。自分の経験上、以下の 3 点に関する問題が起因となった可能性が高いです。&lt;/p&gt;&lt;h2 id=&quot;バックログアイテムがうまく作成されていない&quot;&gt;&lt;a href=&quot;#バックログアイテムがうまく作成されていない&quot; class=&quot;headerlink&quot; title=&quot;バックログアイテムがうまく作成されていない&quot;&gt;&lt;/a&gt;バックログアイテムがうまく作成されていない&lt;/h2&gt;&lt;p&gt;正確なストーリーポイントが出せていないというのはあくまで事象で、そもそも土台に当たるバックログアイテムが見積もりにくい状態になっていることはよくあります。バックログアイテムの完成度を判断するのによく使用されているのは「I.N.V.E.S.T」という基準です。要するに、取り扱いやすいアイテムは以下の基準を満たさなければいけません。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Independant (独立している)&lt;/li&gt;&lt;li&gt;Negotiable (交渉できる)&lt;/li&gt;&lt;li&gt;Valuable (価値がある)&lt;/li&gt;&lt;li&gt;Estimatable (見積れる)&lt;/li&gt;&lt;li&gt;Small (サイズが小さい)&lt;/li&gt;&lt;li&gt;Testable (検証できる)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;ネット上「I.N.V.E.S.T」を説明する&lt;a href=&quot;https://dev.to/code2bits/user-story-guidelines-l2e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;良い記事&lt;/a&gt;がたくさん存在している為、細かい説明は割愛しますが、ここで Independant と Estimatable に注目したいです。例えば、「上のアイテムを完成しないと、下のアイテムが見積もれないよ」という言い方はよく聞きます。それは恐らく独立性の不足を表している証拠です。上手く切ったユーザーストーリーなら、お互いに干渉しないし、不確実性の急増がしません。&lt;/p&gt;&lt;p&gt;また、Estimatable も大事です。ストーリーポイントを出す前、開発チームが見積もる対象のスコープと情報を理解していなければ、正しい見積もりが出せません。もしバックログアイテムが見積もりにくいと感じたら、リファインメントもしくはプランニング 1 のタイミングで開発チームと PO が擦り合わせを行うべきです。&lt;/p&gt;
    
    </summary>
    
      <category term="org" scheme="https://202accepted.com/categories/org/"/>
    
    
      <category term="scrum" scheme="https://202accepted.com/tags/scrum/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript のプリミティブ型</title>
    <link href="https://202accepted.com/2019/08/02/primitive-type-in-javascript/"/>
    <id>https://202accepted.com/2019/08/02/primitive-type-in-javascript/</id>
    <published>2019-08-02T23:44:30.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p>JavaScript 言語において、データ型は恐らく基礎中の基礎だと言われてもおかしくありません。しかし、JavaScript をよく使用している方でも、データ型に関する知識が曖昧もしくは間違っているかもしれません。スコープが広がり過ぎないように、プリミティブ型に焦点を当て、JavaScript のプリミティブ型にまつわる落とし穴について解説してみたいと思います。</p><h2 id="JavaScript-の型"><a href="#JavaScript-の型" class="headerlink" title="JavaScript の型"></a>JavaScript の型</h2><h3 id="プリミティブ型"><a href="#プリミティブ型" class="headerlink" title="プリミティブ型"></a>プリミティブ型</h3><p>執筆時の最新パージョンである ECMAScript 2019(略称：ES2019/ES10)の中に、データ型は全部で 7 種類です。そのうちプリミティブ型は下記の 6 つです。</p><ul><li>Number</li><li>String</li><li>Boolean</li><li>Null</li><li>Undefined</li><li>Symbol</li></ul><p>C 言語のように、integer や double を区別することがなく、数字系なら Number 型一択です。ただ、Number 型に特殊な値が 3 つ存在します：<code>+Infinity</code>（無限大）、<code>-Infinity</code>（無限小）および<code>NaN</code>（Not a number/数字ではない）です。<br>Java でしたら、String はオブジェクトになりますが、JavaScript に String というプリミティブ型が存在します。意味は同じく文字列を表現する型です。<br>Boolean、Null と Undefined の値は限られています。Boolean の値は true と false 二つのみです。Null の値は<a href="https://www.ecma-international.org/ecma-262/10.0/#sec-ecmascript-language-types-null-type" target="_blank" rel="noopener">null</a>だけで、Undefined の値は<a href="https://www.ecma-international.org/ecma-262/10.0/#sec-ecmascript-language-types-undefined-type" target="_blank" rel="noopener">undefined</a>のみです。<br>Symbol は ES2015(通称：ES6)にて<a href="https://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-symbol-type" target="_blank" rel="noopener">新しく追加されたデータ型</a>です。MDN を含む、Symbol は ES2016 で追加されたとの記述が散見されますが、それは間違い（タイポ？）です。<br>また、2019 年 6 月に開催された TC39 ミーティングにて、BigInt という新しいプリミティブ型は<a href="https://github.com/tc39/tc39-notes/blob/master/meetings/2019-06/june-4.md#bigint-to-stage-4" target="_blank" rel="noopener">Stage 4 へ進むことが許可されました</a>。よって、ES2020 の言語仕様へ組まれることがほぼ決定になっています。<code>BigInt</code>は文字通り、今までの Number 型だと取り扱えない大きな数字を処理する為に導入される型です。一部の資料では ES2019 の新機能だと説明されていますが、残念ながらそれは間違いです。確かに一時期 ES2019 へ入れられるんじゃないかと見られていましたが、まだ仕様へ入っていません。ただ、<a href="https://v8.dev/blog/bigint" target="_blank" rel="noopener">Chrome</a>や<a href="https://wingolog.org/archives/2019/05/23/bigint-shipping-in-firefox" target="_blank" rel="noopener">Firefox</a>、<a href="https://node.green/#ESNEXT-candidate--stage-3--BigInt" target="_blank" rel="noopener">Nodejs10.8+</a>ではすでに実装されていますので、JavaScript のプリミティブ型としてカウントされていることもあります。</p><h3 id="オブジェクト型"><a href="#オブジェクト型" class="headerlink" title="オブジェクト型"></a>オブジェクト型</h3><p>7 種類の中、唯一プリミティブじゃない型は Object 型ですが、恐らく普段のコーディングの中でもっともよく使われている型でしょう。<code>{ age: 1 }</code> のように作ったのは当然ながら Object ですし、クラス(class)、関数(function)、配列、Date や正規表現はすべて Object です。この記事のスコープはプリミティブ型に絞っていますので、解説は割愛します。</p><h3 id="プリミティブ型とオブジェクト型の違い"><a href="#プリミティブ型とオブジェクト型の違い" class="headerlink" title="プリミティブ型とオブジェクト型の違い"></a>プリミティブ型とオブジェクト型の違い</h3><p>JavaScript において、プリミティブ型は値のみでプロパティがありません。なので、プリミティブ型の変数を識別する時は値を利用するしかありません。値を変えたら別のプリミティブ値になりますので、プリミティブ値は不変（Immutable）なんです。一方、オブジェクトはプロパティを持ち可変（Mutable）です。オブジェクトを識別する際に参照(Reference)を利用します。その為、同じ値を持っているとしても別々のオブジェクトとして識別されるかもしれません。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> === <span class="number">1</span> <span class="comment">// =&gt; true</span></span><br><span class="line">[<span class="number">1</span>] === [<span class="number">1</span>] <span class="comment">// =&gt; false</span></span><br></pre></td></tr></table></figure><p>逆に、値を変えても同じオブジェクトになり得ます。下記のコードは好例です。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> b = a = &#123; <span class="attr">i</span>: <span class="number">1</span> &#125;;</span><br><span class="line">b === a; <span class="comment">// =&gt; true</span></span><br><span class="line">a.i = <span class="number">0</span>;</span><br><span class="line">b === a; <span class="comment">// =&gt; true</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> d = c = <span class="number">1</span>;</span><br><span class="line">d === c; <span class="comment">// =&gt; true</span></span><br><span class="line">c = <span class="number">0</span>;</span><br><span class="line">d === c; <span class="comment">// =&gt; false</span></span><br></pre></td></tr></table></figure><h2 id="混乱ポイント"><a href="#混乱ポイント" class="headerlink" title="混乱ポイント"></a>混乱ポイント</h2><p>上記の記述だけ読むと、JavaScript の型システムは他のオブジェクト指向言語とは大した差がないように感じるかもしれません。しかし、なぜ数多くのプログラマーが JavaScript の型に惑わされ・苦しめられてきたのでしょうか？主な理由は以下の三つだと思います。</p><h3 id="自由過ぎる型変換"><a href="#自由過ぎる型変換" class="headerlink" title="自由過ぎる型変換"></a>自由過ぎる型変換</h3><p>JavaScript は多くのスクリプト言語と同じく、動的型付け（Dynamic Typed）という特徴を持っています。その為、型はコンパイル時ではなく、実行時動的にチェックされます。さらに、型に関するチェックが緩く、PHP と一緒に <code>loosely typed</code>　または <code>weakly typed</code> （弱い型付け）と呼ばれています。<a href="https://wiki.python.org/moin/Why%20is%20Python%20a%20dynamic%20language%20and%20also%20a%20strongly%20typed%20language" target="_blank" rel="noopener">Python</a>や Ruby が loosely typed と説明している記事もありますが、恐らく動的型付けと混同していたからです。動的型付けと弱い型付け、この二つの特徴により、下記の JS コードは問題なく動作します。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">a = <span class="string">"hello"</span>;</span><br><span class="line">a = <span class="number">1</span>;</span><br><span class="line">b = a + <span class="string">"world"</span> <span class="comment">// =&gt; "1world"</span></span><br></pre></td></tr></table></figure><p>Python や Java の場合、例外が発生するはずですが、JavaScript では型は自動的に判断され、暗黙的に変換されます（implicit coercion）。同じ変数へ別の型の値を代入しても上書きが発生するだけで Runtime に怒られません。そのゆえ、プログラマーにとって型を把握することが難しいです。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">false</span> + <span class="literal">null</span> == <span class="string">'0'</span> <span class="comment">// =&gt; true</span></span><br></pre></td></tr></table></figure><p>例えば、上記の式の評価結果は Boolean 型の true になります。強い型の言語に馴染んでいる方にとってあり得ないでしょう。なぜなら、Boolean 型の値と Null 型の値の和は String 型の値に等しいと示されているからです。<br>また、プリミティブ型とオブジェクト型の相互変換もあります。先程プリミティブ型はプロパティを持っていないと説明していましたが、下記のコードはエラーになりません。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"hello world"</span>.length <span class="comment">// =&gt; 11</span></span><br></pre></td></tr></table></figure><p>なぜなら、String 型の<code>&quot;hello world&quot;</code>は<a href="https://www.ecma-international.org/ecma-262/10.0/#sec-toobject" target="_blank" rel="noopener">ToObject</a>という抽象オペレーション（Abstract Operation）により、暗黙的に String ラッパーオブジェクト(Wrapper Object)へ<a href="https://www.ecma-international.org/ecma-262/10.0/#sec-getv" target="_blank" rel="noopener">変換</a>され、その後ラッパーオブジェクトの length プロパティへアクセスしに行くわけです。要するに、上記のコードは以下のように解釈されます。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>(<span class="string">"hello world"</span>).length <span class="comment">// =&gt; 11</span></span><br></pre></td></tr></table></figure><p>実際に、loosely typed という特徴は非常にパワフルではありますが、上記のようなデメリットが JavaScript のコミュニティにおいても問題視されてきました。それを改善すべく、<a href="https://jshint.com/docs/options/#eqeqeq" target="_blank" rel="noopener">jshint</a>や<a href="https://eslint.org/docs/rules/eqeqeq" target="_blank" rel="noopener">eslint</a>のルールで暗黙的な型変換がない <code>===</code> が推奨されたり、強い型付けの特徴を持つ TypeScript が流行るようになりました。<br>その為、ES2015 以降追加された Symbol とこれから追加される予定の BigInt もこのような暗黙的な変換に対し消極的振る舞いを見せています。例えば、<code>1 + 1n</code> という Number（<code>1</code>） と BigInt（<code>1n</code>） 型の足し算すら TypeError になり、<code>Cannot mix BigInt and other types, use explicit conversions</code> （BigInt 型は別の型と混合することができません。明示的な型変換を使ってください）とのメッセージが表示されます。</p><h3 id="惑わしい-typeof"><a href="#惑わしい-typeof" class="headerlink" title="惑わしい typeof"></a>惑わしい <code>typeof</code></h3><p>JavaScript では、型を実行中に確認したい場合、<code>typeof</code>という演算子(operator)を使います。<code>typeof &#39;hello world&#39;</code> は string になり、 <code>typeof false</code> は boolean になります。<br>しかし、この演算子はいくつか直感に反するところがあります。<br>まず一番よく指摘されているのは null 問題です。上記のルールに従えば、 <code>typeof null</code> は当然ながら null になるはずですが、その結果はなんと object になります。いろんな解釈が提唱されていましたが、結局<a href="https://2ality.com/2013/10/typeof-null.html" target="_blank" rel="noopener">バグ説</a>に落ち着きました。しかもこのバグの存在を前提とした実装がすでに世の中に広がっている為、今後も修正されない予定です。<br>また、上でも言及していましたが、JavaScript 内のプリミティブ型は全部で 6 つでそれ以外はすべて Object です。よって、<code>typeof</code>の結果は 7 つしかないと考えられるはずです。しかし、8 つ目、function という結果も存在します。プリミティブ型とオブジェクト型以外に、Function 型が存在するように見えそうですが、そんなことはありません。この振る舞いはただの負債です。ECMAScript の仕様によると、<code>[[Call]]</code>という内部メソッド(internal method)を持つオブジェクトに限って、評価結果は<a href="https://ecma-international.org/ecma-262/10.0/#table-35" target="_blank" rel="noopener">function</a>になると定義されています。<br>さらに、各ベンダーの実装違いが火に油を注いでいました。例えば、Chrome の早期バージョンにおいては、正規表現（<code>typeof /s/</code>）は<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof#Regular_expressions" target="_blank" rel="noopener">function</a>になっていたり、IE に<a href="https://docs.microsoft.com/en-us/openspecs/ie_standards/ms-es5ex/4bb7d565-d737-4ce7-a4c0-bd90c1059869" target="_blank" rel="noopener">unknown と date</a>が存在していたりしていました。幸い、近年 ECMA-262 の台頭により、このような差分が無くなりつつであります。</p><h3 id="不思議な-NaN"><a href="#不思議な-NaN" class="headerlink" title="不思議な NaN"></a>不思議な <code>NaN</code></h3><p>上で紹介されている通り、<code>NaN</code> は Not a Number(数字ではない)という意味を表している Number 型の値です。しかし、他の Number 型の値と違い、比較・計算することは不可能です。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="literal">NaN</span> &gt; <span class="number">0</span> <span class="comment">// =&gt; false</span></span><br><span class="line"><span class="literal">NaN</span> &lt; <span class="number">0</span> <span class="comment">// =&gt; false</span></span><br><span class="line"><span class="literal">NaN</span> === <span class="number">0</span> <span class="comment">// =&gt; false</span></span><br><span class="line"></span><br><span class="line"><span class="number">1</span> + <span class="literal">NaN</span> <span class="comment">// =&gt; NaN</span></span><br><span class="line"><span class="literal">NaN</span> / <span class="number">0</span> <span class="comment">// =&gt; NaN</span></span><br></pre></td></tr></table></figure><p>上記のように比較はすべて false という結果になり、計算結果は全部 NaN です。さらに、多くの JS プログラマーを困惑させたのは、NaN は自分自身とも等しくないことです。すなわち、<code>NaN === NaN</code>の結果は false です。<br>実はこれは驚くべきことではありません。ECMA-262 の仕様に<a href="https://www.ecma-international.org/ecma-262/10.0/#sec-terms-and-definitions-nan" target="_blank" rel="noopener">記述</a>されている通り、NaN は IEEE 754-2008 標準の Not-a-Number を表していますので、上記の振る舞いはあくまで IEEE の標準を<a href="https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html" target="_blank" rel="noopener">忠実に表現している</a>だけです。とはいえ、プログラムの中で値は NaN であるかをチェックしなければいけないユースケースはきっと存在するはずです。自分自身と等しくない値は NaN しかないので、ECMAScript5(ES5)まではその特徴を利用するプラクティスが多かったです。この方法は今でも使えますが、黙示的な表現に見えますので、ECMAScript 2015(ES6)の仕様に<code>Number.isNaN</code>という<a href="https://www.ecma-international.org/ecma-262/10.0/#sec-number.isnan" target="_blank" rel="noopener">専用メソッド</a>が追加されました。値が<code>NaN</code>の時だけ true になり、それ以外は false を返してくれます。しかし、惑わしさはまだ残っています。なぜなら、グローバルオブジェクト(Global Object)にも<code>isNaN</code>というメソッドが<a href="https://www.ecma-international.org/ecma-262/10.0/#sec-isnan-number" target="_blank" rel="noopener">存在します</a>。両者の関係は下図のようです。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Global Object</span><br><span class="line">├───isNumber</span><br><span class="line">├───Number</span><br><span class="line">    └───isNumber</span><br><span class="line">...</span><br></pre></td></tr></table></figure><p>その上、<code>isNaN</code>はまず引数を暗黙的に Number 型へ変換してから NaN であるかを判断する為、<code>Number.isNaN</code>の振る舞いと異なります。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">isNaN</span>(<span class="string">"hello"</span>)  <span class="comment">// =&gt; true</span></span><br><span class="line"><span class="built_in">Number</span>.isNaN(<span class="string">"hello"</span>) <span class="comment">// =&gt; false</span></span><br><span class="line"><span class="built_in">isNaN</span>(&#123;<span class="attr">a</span>: <span class="number">1</span>&#125;) <span class="comment">// =&gt; true</span></span><br><span class="line"><span class="built_in">Number</span>.isNaN(&#123;<span class="attr">a</span>: <span class="number">1</span>&#125;) <span class="comment">// =&gt; false</span></span><br></pre></td></tr></table></figure><p>上記の理由によって、<code>NaN</code>を取り扱う時の惑わしさを減らす為に、グローバルオブジェクトの<code>isNaN</code>の使用は基本的に推奨されていません。</p><h2 id="まとめ"><a href="#まとめ" class="headerlink" title="まとめ"></a>まとめ</h2><p>JavaScript の型チェックが緩く、暗黙的な変換が多い為、型を意識しなくてもコードを触ることができたりします。しかし、型をはっきり認識していなければ、予期に反する実行結果が出る可能性が高いです。特に歴史的な原因などによって、JavaScript の型システムが直感と相反するケースが多いです。そのため、言語仕様をしっかりと理解することが大切だと感じますね。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;JavaScript 言語において、データ型は恐らく基礎中の基礎だと言われてもおかしくありません。しかし、JavaScript をよく使用している方でも、データ型に関する知識が曖昧もしくは間違っているかもしれません。スコープが広がり過ぎないように、プリミティブ型に焦点を当て、JavaScript のプリミティブ型にまつわる落とし穴について解説してみたいと思います。&lt;/p&gt;&lt;h2 id=&quot;JavaScript-の型&quot;&gt;&lt;a href=&quot;#JavaScript-の型&quot; class=&quot;headerlink&quot; title=&quot;JavaScript の型&quot;&gt;&lt;/a&gt;JavaScript の型&lt;/h2&gt;&lt;h3 id=&quot;プリミティブ型&quot;&gt;&lt;a href=&quot;#プリミティブ型&quot; class=&quot;headerlink&quot; title=&quot;プリミティブ型&quot;&gt;&lt;/a&gt;プリミティブ型&lt;/h3&gt;&lt;p&gt;執筆時の最新パージョンである ECMAScript 2019(略称：ES2019/ES10)の中に、データ型は全部で 7 種類です。そのうちプリミティブ型は下記の 6 つです。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Number&lt;/li&gt;&lt;li&gt;String&lt;/li&gt;&lt;li&gt;Boolean&lt;/li&gt;&lt;li&gt;Null&lt;/li&gt;&lt;li&gt;Undefined&lt;/li&gt;&lt;li&gt;Symbol&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;C 言語のように、integer や double を区別することがなく、数字系なら Number 型一択です。ただ、Number 型に特殊な値が 3 つ存在します：&lt;code&gt;+Infinity&lt;/code&gt;（無限大）、&lt;code&gt;-Infinity&lt;/code&gt;（無限小）および&lt;code&gt;NaN&lt;/code&gt;（Not a number/数字ではない）です。&lt;br&gt;Java でしたら、String はオブジェクトになりますが、JavaScript に String というプリミティブ型が存在します。意味は同じく文字列を表現する型です。&lt;br&gt;Boolean、Null と Undefined の値は限られています。Boolean の値は true と false 二つのみです。Null の値は&lt;a href=&quot;https://www.ecma-international.org/ecma-262/10.0/#sec-ecmascript-language-types-null-type&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;null&lt;/a&gt;だけで、Undefined の値は&lt;a href=&quot;https://www.ecma-international.org/ecma-262/10.0/#sec-ecmascript-language-types-undefined-type&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;undefined&lt;/a&gt;のみです。&lt;br&gt;Symbol は ES2015(通称：ES6)にて&lt;a href=&quot;https://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-symbol-type&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;新しく追加されたデータ型&lt;/a&gt;です。MDN を含む、Symbol は ES2016 で追加されたとの記述が散見されますが、それは間違い（タイポ？）です。&lt;br&gt;また、2019 年 6 月に開催された TC39 ミーティングにて、BigInt という新しいプリミティブ型は&lt;a href=&quot;https://github.com/tc39/tc39-notes/blob/master/meetings/2019-06/june-4.md#bigint-to-stage-4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Stage 4 へ進むことが許可されました&lt;/a&gt;。よって、ES2020 の言語仕様へ組まれることがほぼ決定になっています。&lt;code&gt;BigInt&lt;/code&gt;は文字通り、今までの Number 型だと取り扱えない大きな数字を処理する為に導入される型です。一部の資料では ES2019 の新機能だと説明されていますが、残念ながらそれは間違いです。確かに一時期 ES2019 へ入れられるんじゃないかと見られていましたが、まだ仕様へ入っていません。ただ、&lt;a href=&quot;https://v8.dev/blog/bigint&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Chrome&lt;/a&gt;や&lt;a href=&quot;https://wingolog.org/archives/2019/05/23/bigint-shipping-in-firefox&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Firefox&lt;/a&gt;、&lt;a href=&quot;https://node.green/#ESNEXT-candidate--stage-3--BigInt&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Nodejs10.8+&lt;/a&gt;ではすでに実装されていますので、JavaScript のプリミティブ型としてカウントされていることもあります。&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="javascript" scheme="https://202accepted.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>JestでDateのコンストラクタをモックする</title>
    <link href="https://202accepted.com/2019/03/02/jest-mock-date/"/>
    <id>https://202accepted.com/2019/03/02/jest-mock-date/</id>
    <published>2019-03-02T00:12:15.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p>下記の関数があるとしましょう。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">calcDuration</span>(<span class="params">date: <span class="built_in">string</span></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">Math</span>.abs(<span class="keyword">new</span> <span class="built_in">Date</span>().getFullYear() - <span class="keyword">new</span> <span class="built_in">Date</span>(date).getFullYear());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>この関数のテストを書くのに、注意しなければいけないことが1点あります。もう気づいたと思いますが、<code>new Date()</code>の結果を固定値にしないと、テストの結果が実行時の日付に依存してしまいますので、環境依存が発生し許容できないでしょう。Jestにはモジュールモックを含め、<a href="https://jestjs.io/docs/en/mock-functions.html" target="_blank" rel="noopener">いくつのやり方</a>がありますが、標準ビルトインオブジェクトかつコンストラクタの場合、どうモックするか、ドキュメントには詳しく書かれませんでした。ウェブで検索してみた<a href="https://stackoverflow.com/q/52828824/6279569" target="_blank" rel="noopener">結果</a>、<code>jest.spyOn(global, &#39;Date&#39;)</code>という感じで書くのは一番直感的で柔軟性が高いと感じました。よって、テストのコードはこうなるかと思います。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">test(<span class="string">"mock"</span>, <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> dateToUse = <span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">"2015-01-01"</span>);</span><br><span class="line">  jest.spyOn(global, <span class="string">"Date"</span>).mockImplementation(<span class="function"><span class="params">()</span> =&gt;</span> dateToUse);</span><br><span class="line">  <span class="keyword">const</span> duration = calcDuration(<span class="string">"2011-01-01"</span>);</span><br><span class="line">  expect(duration).toBe(<span class="number">4</span>);</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>しかし、上記のコードの実行結果は<code>[Jest] Expected value to be (using Object.is): 4, Received: 0</code>というエラーになるでしょう。理由は簡単です。<code>calcDuration</code>関数内で<code>Date</code>コンストラクタは二回も呼ばれ、そして常に<code>dateToUse</code>が返ってきます。よって、差分が0になるのは正しい振る舞いです。そこを修正する為に、<code>mockImplementation</code>にて条件分岐を作ればシンプルに解決できます。引数が空の場合<code>dateToUse</code>を返し、それ以外は元々のビルドインオブジェクトを使わせます。結果は下記の感じです。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">test(<span class="string">"mock"</span>, <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  <span class="keyword">const</span> OriginalDate = <span class="built_in">Date</span>;</span><br><span class="line">  <span class="keyword">const</span> dateToUse = <span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">"2015-01-01"</span>);</span><br><span class="line">  <span class="keyword">const</span> mocked = jest.spyOn(global, <span class="string">"Date"</span>).mockImplementation(<span class="function">(<span class="params">arg</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> arg ? <span class="keyword">new</span> OriginalDate(arg) : dateToUse;</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="keyword">const</span> duration = calcDuration(<span class="string">"2011-01-01"</span>);</span><br><span class="line">  expect(mocked).toHaveBeenCalledTimes(<span class="number">2</span>);</span><br><span class="line">  expect(duration).toBe(<span class="number">4</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>他に<code>mockImplementationOnce</code>でやる方法も考えられますが、実装を意識しないと書けなさそうと思いましたので、上記のやり方を採用することにしました。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;下記の関数があるとしましょう。&lt;/p&gt;&lt;figure class=&quot;highlight typescript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;calcDuration&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;date: &lt;span class=&quot;built_in&quot;&gt;string&lt;/span&gt;&lt;/span&gt;) &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Math&lt;/span&gt;.abs(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;().getFullYear() - &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;(date).getFullYear());&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;この関数のテストを書くのに、注意しなければいけないことが1点あります。もう気づいたと思いますが、&lt;code&gt;new Date()&lt;/code&gt;の結果を固定値にしないと、テストの結果が実行時の日付に依存してしまいますので、環境依存が発生し許容できないでしょう。Jestにはモジュールモックを含め、&lt;a href=&quot;https://jestjs.io/docs/en/mock-functions.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;いくつのやり方&lt;/a&gt;がありますが、標準ビルトインオブジェクトかつコンストラクタの場合、どうモックするか、ドキュメントには詳しく書かれませんでした。ウェブで検索してみた&lt;a href=&quot;https://stackoverflow.com/q/52828824/6279569&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;結果&lt;/a&gt;、&lt;code&gt;jest.spyOn(global, &amp;#39;Date&amp;#39;)&lt;/code&gt;という感じで書くのは一番直感的で柔軟性が高いと感じました。よって、テストのコードはこうなるかと思います。&lt;/p&gt;&lt;figure class=&quot;highlight typescript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;test(&lt;span class=&quot;string&quot;&gt;&quot;mock&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; =&amp;gt;&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; dateToUse = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;&quot;2015-01-01&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  jest.spyOn(global, &lt;span class=&quot;string&quot;&gt;&quot;Date&quot;&lt;/span&gt;).mockImplementation(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; =&amp;gt;&lt;/span&gt; dateToUse);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; duration = calcDuration(&lt;span class=&quot;string&quot;&gt;&quot;2011-01-01&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  expect(duration).toBe(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;しかし、上記のコードの実行結果は&lt;code&gt;[Jest] Expected value to be (using Object.is): 4, Received: 0&lt;/code&gt;というエラーになるでしょう。理由は簡単です。&lt;code&gt;calcDuration&lt;/code&gt;関数内で&lt;code&gt;Date&lt;/code&gt;コンストラクタは二回も呼ばれ、そして常に&lt;code&gt;dateToUse&lt;/code&gt;が返ってきます。よって、差分が0になるのは正しい振る舞いです。そこを修正する為に、&lt;code&gt;mockImplementation&lt;/code&gt;にて条件分岐を作ればシンプルに解決できます。引数が空の場合&lt;code&gt;dateToUse&lt;/code&gt;を返し、それ以外は元々のビルドインオブジェクトを使わせます。結果は下記の感じです。&lt;/p&gt;&lt;figure class=&quot;highlight typescript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;test(&lt;span class=&quot;string&quot;&gt;&quot;mock&quot;&lt;/span&gt;, &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; =&amp;gt;&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; OriginalDate = &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; dateToUse = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;&quot;2015-01-01&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; mocked = jest.spyOn(global, &lt;span class=&quot;string&quot;&gt;&quot;Date&quot;&lt;/span&gt;).mockImplementation(&lt;span class=&quot;function&quot;&gt;(&lt;span class=&quot;params&quot;&gt;arg&lt;/span&gt;) =&amp;gt;&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; arg ? &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; OriginalDate(arg) : dateToUse;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; duration = calcDuration(&lt;span class=&quot;string&quot;&gt;&quot;2011-01-01&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  expect(mocked).toHaveBeenCalledTimes(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  expect(duration).toBe(&lt;span class=&quot;number&quot;&gt;4&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="jest" scheme="https://202accepted.com/tags/jest/"/>
    
      <category term="typescript" scheme="https://202accepted.com/tags/typescript/"/>
    
  </entry>
  
  <entry>
    <title>List of Whatever Cases</title>
    <link href="https://202accepted.com/2018/11/26/list-of-whatever-cases/"/>
    <id>https://202accepted.com/2018/11/26/list-of-whatever-cases/</id>
    <published>2018-11-26T23:42:59.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<table><thead><tr><th>Name</th><th>Example</th></tr></thead><tbody><tr><td>flat case</td><td>samplenamingconvention</td></tr><tr><td>pascal case / capital camel case</td><td>SampleNamingConvention</td></tr><tr><td>camel case</td><td>sampleNamingConvention</td></tr><tr><td>kebab case / chain case / spinal case / lisp case / caterpillar case</td><td>sample-naming-convention</td></tr><tr><td>train case</td><td>Sample-Naming-Convention</td></tr><tr><td>snake case</td><td>sample_naming_convention</td></tr><tr><td>screaming snake case / macro case</td><td>SAMPLE_NAMING_CONVENTION</td></tr></tbody></table><h2 id="References"><a href="#References" class="headerlink" title="References"></a>References</h2><ul><li><a href="https://www.chaseadams.io/most-common-programming-case-types/" target="_blank" rel="noopener">https://www.chaseadams.io/most-common-programming-case-types/</a></li><li><a href="http://tbpgr.hatenablog.com/entry/2016/11/18/232657" target="_blank" rel="noopener">http://tbpgr.hatenablog.com/entry/2016/11/18/232657</a></li><li><a href="https://stackoverflow.com/questions/11273282/whats-the-name-for-hyphen-separated-case" target="_blank" rel="noopener">https://stackoverflow.com/questions/11273282/whats-the-name-for-hyphen-separated-case</a></li><li><a href="https://github.com/bholben/Naming-Conventions" target="_blank" rel="noopener">https://github.com/bholben/Naming-Conventions</a></li></ul><p><em>なんちゃらケース系の用語が多すぎるからまとめてみました。以上</em></p>]]></content>
    
    <summary type="html">
    
      &lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Example&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;flat case&lt;/td&gt;&lt;td&gt;samplenamingconvention&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;pascal case / capital camel case&lt;/td&gt;&lt;td&gt;SampleNamingConvention&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;camel case&lt;/td&gt;&lt;td&gt;sampleNamingConvention&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;kebab case / chain case / spinal case / lisp case / caterpillar case&lt;/td&gt;&lt;td&gt;sample-naming-convention&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;train case&lt;/td&gt;&lt;td&gt;Sample-Naming-Convention&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;snake case&lt;/td&gt;&lt;td&gt;sample_naming_convention&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;screaming snake case / macro case&lt;/td&gt;&lt;td&gt;SAMPLE_NAMING_CONVENTION&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h2 id=&quot;References&quot;&gt;&lt;a href=&quot;#References&quot; class=&quot;headerlink&quot; title=&quot;References&quot;&gt;&lt;/a&gt;References&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.chaseadams.io/most-common-programming-case-types/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.chaseadams.io/most-common-programming-case-types/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://tbpgr.hatenablog.com/entry/2016/11/18/232657&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://tbpgr.hatenablog.com/entry/2016/11/18/232657&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/11273282/whats-the-name-for-hyphen-separated-case&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/questions/11273282/whats-the-name-for-hyphen-separated-case&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/bholben/Naming-Conventions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/bholben/Naming-Conventions&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;なんちゃらケース系の用語が多すぎるからまとめてみました。以上&lt;/em&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="programming" scheme="https://202accepted.com/tags/programming/"/>
    
  </entry>
  
  <entry>
    <title>「Kotlin Fest 2018」参加レポート</title>
    <link href="https://202accepted.com/2018/08/25/kotlin-fest-2018/"/>
    <id>https://202accepted.com/2018/08/25/kotlin-fest-2018/</id>
    <published>2018-08-25T21:26:51.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p>Kotlinは趣味でちょろっとしか書いていませんが、Kotlinの哲学である実用主義・簡潔・安全・相互運用性に魅了され、理想と現実のバランスをうまくとっているなと感心しましたので、<a href="https://kotlin.connpass.com/event/91666/" target="_blank" rel="noopener">Kotlin Fest 2018</a>へ参加してきました。とても楽しかったし、勉強にもなった為、レポートとしてまとめたいと思いました。</p><h1 id="Kotlinもう一歩"><a href="#Kotlinもう一歩" class="headerlink" title="Kotlinもう一歩"></a>Kotlinもう一歩</h1><p>最初に参加したセッションはヤフーの森さんによる「Kotlinもう一歩」でした。Kotlinのタイプシステムを用いてGenericsとType Projectionを紹介していました。プレゼンの内容をよくまとめたのは下記の一枚です。</p><script async class="speakerdeck-embed" data-slide="139" data-id="0e565744058742a0bec85809578db5c8" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script><p>タイプシステムの観点で不変・共変・反変を説明してくれてとても印象的だと感じました。タイプシステムを一言で説明すれば、「タイプAが期待される全ての箇所で、タイプBが使用可能であれば、タイプBはサブタイプだと言える。逆に、タイプAはスーパータイプである。」になります。この一言さえ分かれば、「タイプAは自分自身のサブタイプであり、スーパータイプでもある」ということは理解できるでしょう（ちなみに、これは<code>isSubtypeOf</code>と<code>isSupertypeOf</code>で検証できる)。また、「<code>String</code>は<code>String?</code>のサブタイプ」というのもわかるはずです。</p><h1 id="How-to-Test-Server-side-Kotlin"><a href="#How-to-Test-Server-side-Kotlin" class="headerlink" title="How to Test Server-side Kotlin"></a>How to Test Server-side Kotlin</h1><p>実例を交えた説明でわかりやすかったです。特に技術選定時に考えたこととハマったポイントの紹介はとても参考になりました。テストコードを書きやすくする為に作られた<a href="https://github.com/maeharin/factlin" target="_blank" rel="noopener">Factlin</a>と<a href="https://github.com/suusan2go/kotlin-fill-class" target="_blank" rel="noopener">kotlin-fill-class</a>は確かに使いやすそうだなと感じました。</p><script async class="speakerdeck-embed" data-id="2abdade602b34c82beb23733132a8bdb" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script><p>全体のイメージとして、Kotlin製のテストライブラリはまだまだ少ないと感じました。ただ、Javaの資産は基本的にそのまま使えるので、それほど困らないです。クラスがFinal、Immutable、Null許容しないなどの特性によってハックしなければいけないケースがあるものの、その場合はOSSで提供されているラッパー(i.e. <a href="https://github.com/nhaarman/mockito-kotlin" target="_blank" rel="noopener">mockito-kotlin</a>)かプラグイン(i.e. <a href="https://kotlinlang.org/docs/reference/compiler-plugins.html" target="_blank" rel="noopener">all-open</a>)、もしくはコード上の設定(i.e. <code>@JvmStatic</code>)を使えば大体回避できます。</p><h1 id="Kotlin-Linter"><a href="#Kotlin-Linter" class="headerlink" title="Kotlin Linter"></a>Kotlin Linter</h1><p>KotlinのLinterについて、一番主流の<a href="https://github.com/shyiko/ktlint" target="_blank" rel="noopener">ktlint</a>しか知りませんでした。実際にktlint以外、<a href="https://github.com/arturbosch/detekt" target="_blank" rel="noopener">detekt</a>(detectの意味?w)とアンドロイド用のandroid-lintが存在します。その比較は下記のスライドにてまとめられています。</p><script async class="speakerdeck-embed" data-slide="148" data-id="7b962f63e61c42f6b42db2a8482be3d7" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script><p>ktlintと比べてdetektは標準ルールがたくさんありますし、個別の設定ができるし、メッセージ表示も詳しいです。さらに、detekt-formattingを使えばktlintのルールすらサポートできてしまいます（formattingと言いつつも、自動フォーマットと無関係）。整形できないのは状況によって痛いかもしれませんが、選択肢として考えられますね。<br>また、ktlintのカスタムルールの作成方法は以下のようになります。</p><ol><li>Rule抽象クラスを継承したカスタムルール用のクラスを作成し、visitメソッドを実装する</li><li>RuleSetProviderを継承したカスタムプロバイダークラスを作成し、ルールを登録する</li><li>カスタムプロバイダーの情報をメタファイルに記述し、Jar化する</li></ol><p>detektの場合、issue（サマリー情報）を作成する必要があります。さらに、visitのパターンは複数存在していて選ぶ必要があります。それ以外は大体一緒です。</p><h1 id="Kotlinで愛でるMicroservices"><a href="#Kotlinで愛でるMicroservices" class="headerlink" title="Kotlinで愛でるMicroservices"></a>Kotlinで愛でるMicroservices</h1><script async class="speakerdeck-embed" data-id="8b7d8bd62d2b4a64966d3762c1923678" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script><p>こちらはFRESHLiveの実例紹介でした。マイクロサービスを採用した理由は以下の２点らしい。</p><ol><li>可用性の向上と障害の局所化</li><li>サービスごとに違う言語と技術が使える</li></ol><p>FRESHLiveはほとんどGolangで書かれていましたが、APIをGoでいっぱい書いてくのは辛い（筋肉痛）らしく、gRPCサポート・高階関数／拡張関数／データクラスがある・Null安全のJavaが欲しくなったわけです。よって、Kotlinを採用し始めました。Router Function DSLでRESTful APIを書いているのは印象的でした。マイクロサービスっぽい話は少ししか触れませんでした。パッケージングは<a href="https://www.helm.sh/" target="_blank" rel="noopener">helm</a>を使っていて、prometheus/JVM micrometerを使って監視を行っているそうです。</p><h1 id="How-to-Kontribute"><a href="#How-to-Kontribute" class="headerlink" title="How to Kontribute"></a>How to Kontribute</h1><p>磯貝さんによるコントリビュートしかたの紹介です。Kotlinのリポジトリをクローンすることや、IDEとプラグインを用意することは特に目新しくないですが、JDK10だけじゃなく1.7、1.6まで必要だそうで、大変だなと思いました。<br><a href="https://youtrack.jetbrains.com/issues/KT" target="_blank" rel="noopener">公式youtrack</a>から<strong>up-for-grabs</strong>タグがついているIssueをとって作業し、GitHub上でPRを出すのは一般的なワークフローみたいです。わからないことがあったら、<a href="slack.kotlinlang.org">Slack</a>の<code>#kontributors</code>チャンネルで聞けば良いらしいです。<br>基本的には以下のステップを踏んでコントリビュートすれば挫折しなさそうです。</p><ol><li>Readmeを更新する</li><li><a href="https://kotlinlang.org/api/l/jvm/stdlib/index.html" target="_blank" rel="noopener">ライブラリの公式ドキュメント</a>を更新する</li><li><a href="https://youtrack.jetbrains.com/issue/KT-20357" target="_blank" rel="noopener">サンプル</a>を作成する</li><li>プラグインを開発する(特にinspection機能の開発が多いらしいです)</li></ol><p>Kotlinのみならず、他のOSSでも適用できそうな手順ですね。</p><h1 id="Kotlin-コルーチンを理解しよう"><a href="#Kotlin-コルーチンを理解しよう" class="headerlink" title="Kotlin コルーチンを理解しよう"></a>Kotlin コルーチンを理解しよう</h1><p>このセッションは残念ながら聞けませんでしたが、とても気になっていたので、スライドをチェックしてみました。</p><script async class="speakerdeck-embed" data-id="237e32d7cf2a40e19e84951de4804f7d" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script><p>紹介編かなと思っていましたが思ったより深く触れていたようです。ただ、KotlinConf 2017のプレゼン（<a href="https://youtu.be/_hfBv0a09Jc" target="_blank" rel="noopener">Introduction to Coroutines by Roman Elizarov</a>、<a href="https://youtu.be/YrrUCSi72E8" target="_blank" rel="noopener">Deep Dive into Coroutines on JVM by Roman Elizarov</a>）と被ってそうな内容だと感じました。</p><h1 id="その他"><a href="#その他" class="headerlink" title="その他"></a>その他</h1><p><img src="https://i.imgur.com/VoOCxa7.jpg" alt="Kotlin Fest 2018"></p><p>各スポンサーのノベルティはすごく豪華でした。サーバーエージェントさんとミクシィさんがKotlinのクイズゲームを企画していたのは新鮮で面白かったです。特にミクシィさんから頂いたプランニングポーカーは今後使えそうですね（<a href="https://kotlinquiz.com/" target="_blank" rel="noopener">ここ</a>より抜粋した問題らしい）。<br>食事が美味しかった上、お菓子、デザート、飲み物まで無料で提供されていたのは最高でした。<br>唯一の不満で言えば、Wifiですかね。こういう大規模なイベントでWifiの接続が不安定になったり、繋がりにくくなったりしますよね。施設より提供しているWifiと別に、イベントの為に用意する必要がありそうと思いました。<br>今年のKotlinConfはアムステルダムで行うようでチェックしてみましたが、チケットはすでに完売になったみたいです。来年の今、実務でKotlinを使えて、KotlinConfに参加できたらいいなと思いましたね。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Kotlinは趣味でちょろっとしか書いていませんが、Kotlinの哲学である実用主義・簡潔・安全・相互運用性に魅了され、理想と現実のバランスをうまくとっているなと感心しましたので、&lt;a href=&quot;https://kotlin.connpass.com/event/91666/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Kotlin Fest 2018&lt;/a&gt;へ参加してきました。とても楽しかったし、勉強にもなった為、レポートとしてまとめたいと思いました。&lt;/p&gt;&lt;h1 id=&quot;Kotlinもう一歩&quot;&gt;&lt;a href=&quot;#Kotlinもう一歩&quot; class=&quot;headerlink&quot; title=&quot;Kotlinもう一歩&quot;&gt;&lt;/a&gt;Kotlinもう一歩&lt;/h1&gt;&lt;p&gt;最初に参加したセッションはヤフーの森さんによる「Kotlinもう一歩」でした。Kotlinのタイプシステムを用いてGenericsとType Projectionを紹介していました。プレゼンの内容をよくまとめたのは下記の一枚です。&lt;/p&gt;&lt;script async class=&quot;speakerdeck-embed&quot; data-slide=&quot;139&quot; data-id=&quot;0e565744058742a0bec85809578db5c8&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;&lt;p&gt;タイプシステムの観点で不変・共変・反変を説明してくれてとても印象的だと感じました。タイプシステムを一言で説明すれば、「タイプAが期待される全ての箇所で、タイプBが使用可能であれば、タイプBはサブタイプだと言える。逆に、タイプAはスーパータイプである。」になります。この一言さえ分かれば、「タイプAは自分自身のサブタイプであり、スーパータイプでもある」ということは理解できるでしょう（ちなみに、これは&lt;code&gt;isSubtypeOf&lt;/code&gt;と&lt;code&gt;isSupertypeOf&lt;/code&gt;で検証できる)。また、「&lt;code&gt;String&lt;/code&gt;は&lt;code&gt;String?&lt;/code&gt;のサブタイプ」というのもわかるはずです。&lt;/p&gt;&lt;h1 id=&quot;How-to-Test-Server-side-Kotlin&quot;&gt;&lt;a href=&quot;#How-to-Test-Server-side-Kotlin&quot; class=&quot;headerlink&quot; title=&quot;How to Test Server-side Kotlin&quot;&gt;&lt;/a&gt;How to Test Server-side Kotlin&lt;/h1&gt;&lt;p&gt;実例を交えた説明でわかりやすかったです。特に技術選定時に考えたこととハマったポイントの紹介はとても参考になりました。テストコードを書きやすくする為に作られた&lt;a href=&quot;https://github.com/maeharin/factlin&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Factlin&lt;/a&gt;と&lt;a href=&quot;https://github.com/suusan2go/kotlin-fill-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;kotlin-fill-class&lt;/a&gt;は確かに使いやすそうだなと感じました。&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="kotlin" scheme="https://202accepted.com/tags/kotlin/"/>
    
  </entry>
  
  <entry>
    <title>Vuex Plugin 101</title>
    <link href="https://202accepted.com/2018/05/23/vuex-plugin-101/"/>
    <id>https://202accepted.com/2018/05/23/vuex-plugin-101/</id>
    <published>2018-05-23T23:12:20.000Z</published>
    <updated>2021-08-16T14:23:52.224Z</updated>
    
    <content type="html"><![CDATA[<p>「<a href="https://vuejs-meetup.connpass.com/event/82065/" target="_blank" rel="noopener">Vue.js Tokyo v-meetup #7</a>」にて発表させて頂きました。<br>スライドは<a href="https://speakerdeck.com/cho0o0/vuex-plugin-101-full-ver-dot/" target="_blank" rel="noopener">こちら</a>です。</p><script async class="speakerdeck-embed" data-id="3ea698ce58a24bd7a5137a32a69794cc" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script><h1 id="発表したこと"><a href="#発表したこと" class="headerlink" title="発表したこと"></a>発表したこと</h1><ul><li>Vuexのプラグインは簡単に作れますよ。</li><li>VuexのプラグインはよくsubscribeというストアインスタンスのAPIを使ってます。</li><li>ただし、subscribeのコールバックはmutate後呼ばれますので、もっと早い段階で処理を加えたければ、2.5.0から導入されたAPI(subscribeAction)を使いましょう。</li><li>Vuexのプラグインを探したければ、<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a>リポジトリはいいところです。</li></ul><h1 id="尺の関係で話せなかったこと-スライドに入れました"><a href="#尺の関係で話せなかったこと-スライドに入れました" class="headerlink" title="尺の関係で話せなかったこと(スライドに入れました)"></a>尺の関係で話せなかったこと(スライドに入れました)</h1><ul><li>名前通りあくまでsubscribeなんで、いわゆるAOPのような使い方は期待しないでください。</li><li><a href="https://www.npmjs.com/package/vuex-shared-mutations" target="_blank" rel="noopener">vuex-shared-mutations</a>というタブ間の状態を同期してくれる素晴らしいVuexプラグインがあるが、実は考え方はとてもシンプルです。</li><li>他にも色んな有用なプラグインがありますよ。</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;「&lt;a href=&quot;https://vuejs-meetup.connpass.com/event/82065/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vue.js Tokyo v-meetup #7&lt;/a&gt;」にて発表させて頂きました。&lt;br&gt;スライドは&lt;a href=&quot;https://speakerdeck.com/cho0o0/vuex-plugin-101-full-ver-dot/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;こちら&lt;/a&gt;です。&lt;/p&gt;&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;3ea698ce58a24bd7a5137a32a69794cc&quot; data-ratio=&quot;1.77777777777778&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;&lt;h1 id=&quot;発表したこと&quot;&gt;&lt;a href=&quot;#発表したこと&quot; class=&quot;headerlink&quot; title=&quot;発表したこと&quot;&gt;&lt;/a&gt;発表したこと&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;Vuexのプラグインは簡単に作れますよ。&lt;/li&gt;&lt;li&gt;VuexのプラグインはよくsubscribeというストアインスタンスのAPIを使ってます。&lt;/li&gt;&lt;li&gt;ただし、subscribeのコールバックはmutate後呼ばれますので、もっと早い段階で処理を加えたければ、2.5.0から導入されたAPI(subscribeAction)を使いましょう。&lt;/li&gt;&lt;li&gt;Vuexのプラグインを探したければ、&lt;a href=&quot;https://github.com/vuejs/awesome-vue&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;awesome-vue&lt;/a&gt;リポジトリはいいところです。&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;尺の関係で話せなかったこと-スライドに入れました&quot;&gt;&lt;a href=&quot;#尺の関係で話せなかったこと-スライドに入れました&quot; class=&quot;headerlink&quot; title=&quot;尺の関係で話せなかったこと(スライドに入れました)&quot;&gt;&lt;/a&gt;尺の関係で話せなかったこと(スライドに入れました)&lt;/h1&gt;&lt;ul&gt;&lt;li&gt;名前通りあくまでsubscribeなんで、いわゆるAOPのような使い方は期待しないでください。&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.npmjs.com/package/vuex-shared-mutations&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vuex-shared-mutations&lt;/a&gt;というタブ間の状態を同期してくれる素晴らしいVuexプラグインがあるが、実は考え方はとてもシンプルです。&lt;/li&gt;&lt;li&gt;他にも色んな有用なプラグインがありますよ。&lt;/li&gt;&lt;/ul&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="vue.js" scheme="https://202accepted.com/tags/vue-js/"/>
    
      <category term="vuex" scheme="https://202accepted.com/tags/vuex/"/>
    
  </entry>
  
  <entry>
    <title>ある条件を満たすDOM要素を抽出するコード</title>
    <link href="https://202accepted.com/2018/03/26/extracting-all-dom-elements/"/>
    <id>https://202accepted.com/2018/03/26/extracting-all-dom-elements/</id>
    <published>2018-03-26T20:37:31.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p>週末にデモプログラムを作成する時、ある要素の中から、指定された条件を満たすDOM要素を抽出する機能が必要だった為、下記のようなコードを作りました。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> selectAll = <span class="function"><span class="params">el</span> =&gt;</span> condition =&gt; [el,</span><br><span class="line">  ...Array.from(el.children)</span><br><span class="line">    .map(<span class="function"><span class="params">child</span> =&gt;</span> selectAll(child)(condition))</span><br><span class="line">    .reduce(<span class="function">(<span class="params">arr, i</span>) =&gt;</span> arr.concat(i), [])</span><br><span class="line">].filter(condition)</span><br></pre></td></tr></table></figure><h1 id="考え方"><a href="#考え方" class="headerlink" title="考え方"></a>考え方</h1><p>実は、主な作業は２つだけです。</p><ol><li>全ての要素を羅列します。</li><li>条件に満たしている要素をフィルターリングで抽出します。</li></ol><p>コードを書けばこうなります。(allElements=全ての要素、condition=条件)</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> selectAll = <span class="function">(<span class="params">allElements, condition</span>) =&gt;</span> allElements.filter(condition)</span><br></pre></td></tr></table></figure><p>関数の再利用を考えたら、<a href="https://en.wikipedia.org/wiki/Function_composition_(computer_science)" target="_blank" rel="noopener">コンポジション</a>を採用した方がいいでしょう。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> selectAll = <span class="function"><span class="params">allElements</span> =&gt;</span> condition =&gt; allElements.filter(condition)</span><br></pre></td></tr></table></figure><p>1つ目の作業はどう実現するかは問題です。DOMはツリー構造なので、親要素の元に要素があり、その要素の中に、さらに子要素が存在する。ツリー構造のケースに対処する場合、再帰を使用することは一般的です。関数型風に書きたかったので、Array.prototye.mapと<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax" target="_blank" rel="noopener">スプレッド構文</a>を利用することにしました。DOM要素のchildrenはHTMLCollection型で、map関数が備えていません。よって、まず<code>Array.from()</code>で配列に変換する必要があります。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> selectAll = <span class="function"><span class="params">el</span> =&gt;</span> condition =&gt; [el, ...Array.from(el.children).map(<span class="function"><span class="params">child</span> =&gt;</span> selectAll(child)(condition))]</span><br></pre></td></tr></table></figure><p>しかし、上記のコードだと関数<code>selectAll</code>の戻り値は配列になります。そのまま再帰してしまうと、配列内に配列が格納されることになります。reduceを使って、<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce" target="_blank" rel="noopener">flatten効果</a>を果たさせます。</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> selectAll = <span class="function"><span class="params">el</span> =&gt;</span> condition =&gt; [el,</span><br><span class="line">  ...Array.from(el.children)</span><br><span class="line">    .map(<span class="function"><span class="params">child</span> =&gt;</span> selectAll(child)(condition))</span><br><span class="line">    .reduce(<span class="function">(<span class="params">arr, i</span>) =&gt;</span> arr.concat(i), [])</span><br><span class="line">].filter(condition)</span><br></pre></td></tr></table></figure><p>こんな考え方で、今回のコードを完成させました。</p><h1 id="使用例"><a href="#使用例" class="headerlink" title="使用例"></a>使用例</h1><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 全てのdiv要素を抽出する</span></span><br><span class="line"><span class="built_in">console</span>.log(selectAll(<span class="built_in">document</span>.querySelector(<span class="string">'body'</span>))(<span class="function"><span class="params">el</span> =&gt;</span> el.tagName === <span class="string">'DIV'</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">// IDはappの要素の中から高さが300px以上になっている要素を抽出する</span></span><br><span class="line"><span class="built_in">console</span>.log(selectAll(<span class="built_in">document</span>.querySelector(<span class="string">'#app'</span>))(<span class="function"><span class="params">el</span> =&gt;</span> el.clientHeight &gt;= <span class="number">300</span>));</span><br></pre></td></tr></table></figure><h1 id="結論"><a href="#結論" class="headerlink" title="結論"></a>結論</h1><p>やはりJSで関数型プログラミングするのは気持ちいいw</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;週末にデモプログラムを作成する時、ある要素の中から、指定された条件を満たすDOM要素を抽出する機能が必要だった為、下記のようなコードを作りました。&lt;/p&gt;&lt;figure class=&quot;highlight js&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; selectAll = &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;params&quot;&gt;el&lt;/span&gt; =&amp;gt;&lt;/span&gt; condition =&amp;gt; [el,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  ...Array.from(el.children)&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .map(&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;params&quot;&gt;child&lt;/span&gt; =&amp;gt;&lt;/span&gt; selectAll(child)(condition))&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    .reduce(&lt;span class=&quot;function&quot;&gt;(&lt;span class=&quot;params&quot;&gt;arr, i&lt;/span&gt;) =&amp;gt;&lt;/span&gt; arr.concat(i), [])&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;].filter(condition)&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h1 id=&quot;考え方&quot;&gt;&lt;a href=&quot;#考え方&quot; class=&quot;headerlink&quot; title=&quot;考え方&quot;&gt;&lt;/a&gt;考え方&lt;/h1&gt;&lt;p&gt;実は、主な作業は２つだけです。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;全ての要素を羅列します。&lt;/li&gt;&lt;li&gt;条件に満たしている要素をフィルターリングで抽出します。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;コードを書けばこうなります。(allElements=全ての要素、condition=条件)&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="javascript" scheme="https://202accepted.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>2017年Product Huntで紹介されたプロダクト12選</title>
    <link href="https://202accepted.com/2018/03/05/top-products-introduced-on-ph/"/>
    <id>https://202accepted.com/2018/03/05/top-products-introduced-on-ph/</id>
    <published>2018-03-05T22:26:19.000Z</published>
    <updated>2021-08-16T14:23:52.222Z</updated>
    
    <content type="html"><![CDATA[<p>Product Huntより公開された電子ブック「<a href="https://www.producthunt.com/posts/the-best-product-launches-of-2017" target="_blank" rel="noopener">The Best Product Launches of 2017</a>」を読み終えました。全体的に人工知能系と仮想通貨系（特に下半期）のモノが多かったと感じています。ここで、個人的に気になった12つのプロダクトを紹介したいと思います。（読む前にすでに使用している・知っているプロダクトは含まれていません。）</p><h2 id="12-The-Startup-Way"><a href="#12-The-Startup-Way" class="headerlink" title="12. The Startup Way"></a>12. <a href="http://www.thestartupway.com/" target="_blank" rel="noopener">The Startup Way</a></h2><p><img src="https://images-na.ssl-images-amazon.com/images/I/51DY%2BK7oF8L._SX356_BO1,204,203,200_.jpg" alt="Cover of The Startup Way"></p><p>ひとことコメント：ベストセーラー「<a href="http://theleanstartup.com/" target="_blank" rel="noopener">The Lean Startup</a>」の作者の新作です。</p><h2 id="11-Product-Frameworks"><a href="#11-Product-Frameworks" class="headerlink" title="11. Product Frameworks"></a>11. <a href="https://www.product-frameworks.com/index.html" target="_blank" rel="noopener">Product Frameworks</a></h2><p><img src="https://i.imgur.com/nVLnvmA.png" alt="Product Frameworks introduces Basecamp Product Cycles"></p><p>ひとことコメント：（プログラミングではなく）プロダクト開発でよく使われているフレームワークをまとめてくれたサイトです。</p><h2 id="10-Intercom-on-Starting-up"><a href="#10-Intercom-on-Starting-up" class="headerlink" title="10. Intercom on Starting up"></a>10. <a href="https://www.intercom.com/books/starting-up" target="_blank" rel="noopener">Intercom on Starting up</a></h2><p><img src="https://marketing.intercomassets.com/assets/books/startups/chapter-2x-d37833f148ecba33445d140f2469aa5aa3d7b37578ef3001c2feccb6c6c688ea.png" alt="Intercom on Starting up"></p><p>ひとことコメント：Intercomから出したスタートアップに関する書籍で、GoodReadsで<a href="https://www.goodreads.com/book/show/34908337-intercom-on-starting-up" target="_blank" rel="noopener">4.2の高評価</a>をマークしています。</p><h2 id="9-AutoDraw"><a href="#9-AutoDraw" class="headerlink" title="9. AutoDraw"></a>9. <a href="https://www.autodraw.com/" target="_blank" rel="noopener">AutoDraw</a></h2><p><img src="https://i.imgur.com/KMev72D.png" alt="Draw a cat in AutoDraw"></p><p>ひとことコメント：画力がなくてもイラストが描けるようになります。</p><h2 id="8-Startup-School"><a href="#8-Startup-School" class="headerlink" title="8. Startup School"></a>8. <a href="https://startupschool.org" target="_blank" rel="noopener">Startup School</a></h2><p><img src="https://www.startupschool.org/assets/logo-e53cd2cb71abaa517fb2f3dff77f4ed932e2439b1f3b6965dc7991ee07fe61ab.png" alt="Startup School by Y Combinator"></p><p>ひとことコメント：あのY Combinatorより出した<a href="https://ja.wikipedia.org/wiki/Massive_open_online_course" target="_blank" rel="noopener">MOOC</a>です。</p><h2 id="7-Devhints"><a href="#7-Devhints" class="headerlink" title="7. Devhints"></a>7. <a href="https://devhints.io/" target="_blank" rel="noopener">Devhints</a></h2><p><img src="https://assets.devhints.io/previews/index.jpg" alt="Screenshot of devhints.io"></p><p>ひとことコメント：チートシートが多量に網羅されている便利サイトです。</p><h2 id="6-Feather-Icons"><a href="#6-Feather-Icons" class="headerlink" title="6. Feather Icons"></a>6. <a href="https://feathericons.com/" target="_blank" rel="noopener">Feather Icons</a></h2><p><img src="https://i.imgur.com/mVwPtM8.png" alt="Feather Icons"></p><p>ひとことコメント：<a href="https://fontawesome.com/" target="_blank" rel="noopener">Font Awesome</a>以外の選択肢。</p><h2 id="5-First-Users"><a href="#5-First-Users" class="headerlink" title="5. First Users"></a>5. <a href="https://www.firstusers.io/" target="_blank" rel="noopener">First Users</a></h2><p><img src="https://i.imgur.com/bvnqAx8.png" alt="First Users"></p><p>ひとことコメント：有名なテクノロジー企業はどうやって最初のユーザーを獲得できたか、を教えてくれます。</p><h2 id="4-LOOPY"><a href="#4-LOOPY" class="headerlink" title="4. LOOPY"></a>4. <a href="https://github.com/ncase/loopy" target="_blank" rel="noopener">LOOPY</a></h2><p><img src="https://i.imgur.com/S8c7E8o.gif" alt="Animation of LOOPY"></p><p>ひとことコメント：因果関係が一目瞭然に。</p><h2 id="3-Wildfire"><a href="#3-Wildfire" class="headerlink" title="3. Wildfire"></a>3. <a href="https://wildfire.ai/" target="_blank" rel="noopener">Wildfire</a></h2><p><img src="https://wildfire.ai/screen-2.png" alt="Screenshot of Wildfire"></p><p>ひとことコメント：ちょっとした重複作業から解放してくれる、Seleniumより入りやすい自動化ツールです。</p><h2 id="2-WhatRuns"><a href="#2-WhatRuns" class="headerlink" title="2. WhatRuns"></a>2. <a href="https://www.whatruns.com/" target="_blank" rel="noopener">WhatRuns</a></h2><p><img src="https://www.whatruns.com/images/home/whatruns_animated_image_forever_v3.gif" alt="WhatRuns"></p><p>ひとことコメント：<a href="https://www.wappalyzer.com/" target="_blank" rel="noopener">Wappalyzer</a>より精度が高く、感知内容が多いようです。</p><h2 id="1-Nomad-List"><a href="#1-Nomad-List" class="headerlink" title="1. Nomad List"></a>1. <a href="https://nomadlist.com/" target="_blank" rel="noopener">Nomad List</a></h2><p><img src="https://i.imgur.com/VLtCgDn.jpg" alt="Screenshot of Nomad List"></p><p>ひとことコメント：世界各地の生活コストと注意事項をわかりやすく紹介してくれるサイトです。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Product Huntより公開された電子ブック「&lt;a href=&quot;https://www.producthunt.com/posts/the-best-product-launches-of-2017&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The Best Product Launches of 2017&lt;/a&gt;」を読み終えました。全体的に人工知能系と仮想通貨系（特に下半期）のモノが多かったと感じています。ここで、個人的に気になった12つのプロダクトを紹介したいと思います。（読む前にすでに使用している・知っているプロダクトは含まれていません。）&lt;/p&gt;&lt;h2 id=&quot;12-The-Startup-Way&quot;&gt;&lt;a href=&quot;#12-The-Startup-Way&quot; class=&quot;headerlink&quot; title=&quot;12. The Startup Way&quot;&gt;&lt;/a&gt;12. &lt;a href=&quot;http://www.thestartupway.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The Startup Way&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://images-na.ssl-images-amazon.com/images/I/51DY%2BK7oF8L._SX356_BO1,204,203,200_.jpg&quot; alt=&quot;Cover of The Startup Way&quot;&gt;&lt;/p&gt;&lt;p&gt;ひとことコメント：ベストセーラー「&lt;a href=&quot;http://theleanstartup.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;The Lean Startup&lt;/a&gt;」の作者の新作です。&lt;/p&gt;&lt;h2 id=&quot;11-Product-Frameworks&quot;&gt;&lt;a href=&quot;#11-Product-Frameworks&quot; class=&quot;headerlink&quot; title=&quot;11. Product Frameworks&quot;&gt;&lt;/a&gt;11. &lt;a href=&quot;https://www.product-frameworks.com/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Product Frameworks&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/nVLnvmA.png&quot; alt=&quot;Product Frameworks introduces Basecamp Product Cycles&quot;&gt;&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="product" scheme="https://202accepted.com/tags/product/"/>
    
      <category term="ranking" scheme="https://202accepted.com/tags/ranking/"/>
    
  </entry>
  
  <entry>
    <title>オブジェクトにあるプロパティが存在するかをチェックする</title>
    <link href="https://202accepted.com/2018/02/18/check-properties-in-an-object/"/>
    <id>https://202accepted.com/2018/02/18/check-properties-in-an-object/</id>
    <published>2018-02-18T15:38:25.000Z</published>
    <updated>2021-08-16T14:23:52.220Z</updated>
    
    <content type="html"><![CDATA[<h1 id="手法"><a href="#手法" class="headerlink" title="手法"></a>手法</h1><p>JSのオブジェクトを扱う際に、あるプロパティが存在するかをチェックする作業はしばしば発生します。実は、この一見簡単そうな作業を実施する為に、いくつかのやり方が存在します。考え方で分けて見れば、以下の2種類になるかと思います。</p><h2 id="該当プロパティの値をチェックする"><a href="#該当プロパティの値をチェックする" class="headerlink" title="該当プロパティの値をチェックする"></a>該当プロパティの値をチェックする</h2><p>よく見かける手法は<code>undefined !== obj[prop]</code>もしくは<code>undefined !== obj.prop</code>でしょう（<code>obj</code> = オブジェクト、<code>prop</code> = プロパティ）。まずオブジェクトからプロパティを出して値をみます。もしオブジェクトに該当プロパティが存在しなければ、値は<code>undefined</code>になりますので、この特性を利用する手法ですね。<br>この手法の異種として、<code>void(0) !== obj[prop]</code>があります。void演算子が分かればすぐ理解できるでしょう。<code>void(0)</code>の戻り値が<code>undefined</code>になるからですね。<br>また、<code>&#39;undefined&#39; !== typeof obj[prop]</code>という書き方もあります。値の型を取得し、<code>undefined</code>型であるかを判別する考えです。<br>更に、もっとお洒落な書き方も存在します。<code>!!obj[prop]</code>です。下記のように書くことが可能になります。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(!!obj.prop) <span class="keyword">return</span> <span class="string">'OK'</span>;</span><br></pre></td></tr></table></figure><p>エクスクラメーションマークを2つ先頭に追加することで、結果の反転を二回行います。「False→True→False」みたいに、元の結果に戻すやり方ですね。</p><p><code>undefined !== obj[prop]</code>がもっと直感的なのに、なぜわざわざ<code>void(0) !== obj[prop]</code>や<code>&#39;undefined&#39; !== typeof obj[prop]</code>を使うか、疑問を感じたので、<a href="https://www.measurethat.net/Benchmarks/ShowResult/9195" target="_blank" rel="noopener">ベンチマックを行ってみました</a>。実は後二者の効率は前者の３倍程になります。なるほど〜<br>あともう一つ気を付けなければいけないのは元々プロパティの値は<code>undefined</code>になっているケースです。上記の手法を使ってしまったら、該当プロパティが存在していても、<code>false</code>が出てしまいます。<br>特に<code>!!obj[prop]</code>を使用する時、もっと注意を払わなければなりません。<code>0</code>や<code>null</code>の反転結果は<code>true</code>になるから、該当プロパティに入る値の型を100％把握していなければ、使用するのをやめておいた方が安全でしょう。</p><h2 id="該当プロパティの存在を確認する"><a href="#該当プロパティの存在を確認する" class="headerlink" title="該当プロパティの存在を確認する"></a>該当プロパティの存在を確認する</h2><p>抽出を行わず、直接チェックする方法もあります。<code>in</code>もしくは<code>hasOwnProperty</code>の使用です。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// in</span></span><br><span class="line"><span class="keyword">if</span>(prop <span class="keyword">in</span> obj) <span class="keyword">return</span> <span class="string">'OK'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Object.prototype.hasOwnProperty</span></span><br><span class="line"><span class="keyword">if</span>(obj.hasOwnProperty(prop)) <span class="keyword">return</span> <span class="string">'OK'</span>;</span><br></pre></td></tr></table></figure><p>両者の一番の違いはプロトタイプチェーンを辿るかどうかです。<code>in</code>の場合、プロトタイプチェーンを遡って親のプロパティまで確認する一方、<code>hasOwnProperty</code>は名前通り、自分自身のプロパティを見るだけです。どっちを使用するかはケースバイケースかもしれませんが、「辿らなくてもいい」・「辿らないでほしい」ケースが多い印象です。<br>もう一つ細かい違いは実装されたバージョンです。<code>in</code>はJavaScript 1.4から使用可能になりましたが、<code>hasOwnProperty</code>は一歩遅れて、1.5になります。ただし、ES5さえ古いと感じている今、ES3時代の違いは流石に考えなくても良いでしょう。</p><p>また、<a href="http://underscorejs.org/docs/underscore.html" target="_blank" rel="noopener">underscore.jsのソースコード</a>を読んだことがある方でしたら気づいてたかもしれませんが、<code>hasOwnProperty</code>の使い方は下記のようになります。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// underscore.jsのソースコードより</span></span><br><span class="line">_.has = <span class="function"><span class="keyword">function</span>(<span class="params">obj, key</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> obj != <span class="literal">null</span> &amp;&amp; hasOwnProperty.call(obj, key);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>わざわざ<code>call</code>を使っていますね。理由は簡単です。<code>var obj = {}</code>の書き方で生成されたオブジェクトでしたら、<code>Object</code>のメソッドをそのまま継承していますが、<code>var obj = Object.create(null)</code>みたいに生成すると、<a href="https://stackoverflow.com/a/12017703/6279569" target="_blank" rel="noopener">そんな継承が発生しません</a>。当然ながら、<code>hasOwnProperty</code>というメソッドを持ちません。こんなケースに対応する為に、<code>call</code>を使ったわけです。</p><h1 id="まとめ"><a href="#まとめ" class="headerlink" title="まとめ"></a>まとめ</h1><p>じゃ、結局何を使えばいいでしょうか。ケースバイケースのような定番フレーズを避けたいので、<strong>できれば<code>hasOwnProperty</code>の利用を推奨します。</strong> 理由は三つ。</p><ol><li>プロパティの値は何であろうと、一切関係ないです。</li><li>メソッド名でやりたいことが自己解釈できます。</li><li>速いです。</li></ol><p>以上です。</p><h1 id="リンク"><a href="#リンク" class="headerlink" title="リンク"></a>リンク</h1><ul><li>機能テストのために作成したデモ：<a href="https://jsfiddle.net/0j16gm2u/" target="_blank" rel="noopener">https://jsfiddle.net/0j16gm2u/</a></li><li>作成したベンチマークテスト：<a href="https://www.measurethat.net/Benchmarks/ShowResult/9195" target="_blank" rel="noopener">https://www.measurethat.net/Benchmarks/ShowResult/9195</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;手法&quot;&gt;&lt;a href=&quot;#手法&quot; class=&quot;headerlink&quot; title=&quot;手法&quot;&gt;&lt;/a&gt;手法&lt;/h1&gt;&lt;p&gt;JSのオブジェクトを扱う際に、あるプロパティが存在するかをチェックする作業はしばしば発生します。実は、この一見簡単そうな作業を実施する為に、いくつかのやり方が存在します。考え方で分けて見れば、以下の2種類になるかと思います。&lt;/p&gt;&lt;h2 id=&quot;該当プロパティの値をチェックする&quot;&gt;&lt;a href=&quot;#該当プロパティの値をチェックする&quot; class=&quot;headerlink&quot; title=&quot;該当プロパティの値をチェックする&quot;&gt;&lt;/a&gt;該当プロパティの値をチェックする&lt;/h2&gt;&lt;p&gt;よく見かける手法は&lt;code&gt;undefined !== obj[prop]&lt;/code&gt;もしくは&lt;code&gt;undefined !== obj.prop&lt;/code&gt;でしょう（&lt;code&gt;obj&lt;/code&gt; = オブジェクト、&lt;code&gt;prop&lt;/code&gt; = プロパティ）。まずオブジェクトからプロパティを出して値をみます。もしオブジェクトに該当プロパティが存在しなければ、値は&lt;code&gt;undefined&lt;/code&gt;になりますので、この特性を利用する手法ですね。&lt;br&gt;この手法の異種として、&lt;code&gt;void(0) !== obj[prop]&lt;/code&gt;があります。void演算子が分かればすぐ理解できるでしょう。&lt;code&gt;void(0)&lt;/code&gt;の戻り値が&lt;code&gt;undefined&lt;/code&gt;になるからですね。&lt;br&gt;また、&lt;code&gt;&amp;#39;undefined&amp;#39; !== typeof obj[prop]&lt;/code&gt;という書き方もあります。値の型を取得し、&lt;code&gt;undefined&lt;/code&gt;型であるかを判別する考えです。&lt;br&gt;更に、もっとお洒落な書き方も存在します。&lt;code&gt;!!obj[prop]&lt;/code&gt;です。下記のように書くことが可能になります。&lt;/p&gt;&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt;(!!obj.prop) &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&#39;OK&#39;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;エクスクラメーションマークを2つ先頭に追加することで、結果の反転を二回行います。「False→True→False」みたいに、元の結果に戻すやり方ですね。&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="javascript" scheme="https://202accepted.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>OptionalのorElseとorElseGet</title>
    <link href="https://202accepted.com/2017/12/24/orelse-vs-orelseget/"/>
    <id>https://202accepted.com/2017/12/24/orelse-vs-orelseget/</id>
    <published>2017-12-24T22:27:45.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<p>最近Optionalの<code>orElse</code>と<code>orElseGet</code>の区別は社内でちょっと話題になっていました。これらは同じように見えますが、使い方に気をつけなければハマってしまうかもしれません。まあ、まずJavaDocをみてみましょう。</p><h1 id="定義"><a href="#定義" class="headerlink" title="定義"></a>定義</h1><p>オラクルのドキュメントの中に<code>orElse</code>の定義は<a href="https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html#orElse-T-" target="_blank" rel="noopener">下記のように</a>書かれています。</p><blockquote><p><code>public T orElse(T other)</code><br>存在する場合は値を返し、それ以外の場合はotherを返します。</p><p>パラメータ:<br>other - 存在する値がない場合に返される値、nullも可</p><p>戻り値:<br>値(存在する場合)、それ以外の場合はother</p></blockquote><p>一方、<code>orElseGet</code>は<a href="https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html#orElseGet-java.util.function.Supplier-" target="_blank" rel="noopener">こんな感じ</a>です。</p><blockquote><p><code>public T orElseGet(Supplier&lt;? extends T&gt; other)</code><br>値が存在する場合はその値を返し、そうでない場合はotherを呼び出し、その呼び出しの結果を返します。</p><p>パラメータ:<br>other - Supplier(値が存在しない場合は、これの結果が返される)</p><p>戻り値:<br>値(存在する場合)、それ以外の場合はother.get()の結果</p><p>例外:<br>NullPointerException - 値が存在せずotherがnullの場合</p></blockquote><p>やはり説明も似ていますね。でも、nullについての説明は違います。前者の説明の中に、<code>nullも可</code>が入っていますが、後者にはそれがなく、逆に<code>NullPointerException</code>という例外の説明が入っています。すなわち、<code>Optional.ofNullable(null).orElse(null)</code>はnullを返してくれますが、<code>Optional.ofNullable(null).orElseGet(null)</code>は例外をスローしてしまいます。<br>それはそうでしょう。引数は確実に違うからですね。<code>orElse</code>の引数は値で、<code>orElseGet</code>はSupplierというラムダ式を取っています。Supplierのgetメソッドに通じて値を取得するので、Supplier自体がnullになってしまったら、NullPointerExceptionがスローされてもおかしくありません。</p><h1 id="遅延実行"><a href="#遅延実行" class="headerlink" title="遅延実行"></a>遅延実行</h1><p>でしたら、下記のコードの実施結果は同じように思えますよね。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest1</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> Supplier&lt;String&gt; test = () -&gt; &#123;</span><br><span class="line">        <span class="keyword">final</span> String result = <span class="string">"test"</span>;</span><br><span class="line">        System.out.print(result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.print(Optional.of(<span class="string">"test"</span>).orElseGet(test));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTest2</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">final</span> <span class="keyword">static</span> String <span class="title">test</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">final</span> String result = <span class="string">"test"</span>;</span><br><span class="line">        System.out.print(result);</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        System.out.print(Optional.of(<span class="string">"test"</span>).orElse(test()));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>実行してみれば、すぐ分かりますが、前者は<code>test</code>を出力している一方、後者は<code>testtest</code>を出力しています。<code>test</code>というSupplier変数はラムダ式であることを忘れてはいけません。Cay S. Horstmannが著書<a href="http://amzn.to/2ByKov4" target="_blank" rel="noopener">Java SE 8 実践プログラミング</a>の中でラムダ式を紹介する時、「すべてのラムダ式の重要な点は、遅延実行（deferred execution）です。」、「ラムダ式を使用する主な理由は、適切な時期までコードの実行を遅延させることです。」と説明しています。上記の違いはまさにそれを証明する実例になります。もしOptional内の値はnullじゃなければ、<code>orElseGet</code>内の式が評価される必要がありません。その為、<code>System.out.print(result);</code>が実行されません。当然ながら<code>test</code>の出力はありません。</p><h1 id="まとめ"><a href="#まとめ" class="headerlink" title="まとめ"></a>まとめ</h1><p>上記のようなコードであれば、まだそんなに問題になりませんが、例えば「Optional内の値はnullの場合、データベースにレコードを挿入し、割り当てられたIDを返す」、「Optional内の値はnullの場合、某APIを叩き、データを取ってくる」みたいなロジックを実装する際に、該当ロジックは常に実行されるので、<code>orElse</code>を使ってはいけません。間違って使ってしまうと、速度が大幅に遅くなってしまう上、データの整合性が取れなくなってしまうでしょう。<br>要するに、ラムダの「遅延実行」特性をちゃんと覚えようということですね。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;最近Optionalの&lt;code&gt;orElse&lt;/code&gt;と&lt;code&gt;orElseGet&lt;/code&gt;の区別は社内でちょっと話題になっていました。これらは同じように見えますが、使い方に気をつけなければハマってしまうかもしれません。まあ、まずJavaDocをみてみましょう。&lt;/p&gt;&lt;h1 id=&quot;定義&quot;&gt;&lt;a href=&quot;#定義&quot; class=&quot;headerlink&quot; title=&quot;定義&quot;&gt;&lt;/a&gt;定義&lt;/h1&gt;&lt;p&gt;オラクルのドキュメントの中に&lt;code&gt;orElse&lt;/code&gt;の定義は&lt;a href=&quot;https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html#orElse-T-&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;下記のように&lt;/a&gt;書かれています。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;public T orElse(T other)&lt;/code&gt;&lt;br&gt;存在する場合は値を返し、それ以外の場合はotherを返します。&lt;/p&gt;&lt;p&gt;パラメータ:&lt;br&gt;other - 存在する値がない場合に返される値、nullも可&lt;/p&gt;&lt;p&gt;戻り値:&lt;br&gt;値(存在する場合)、それ以外の場合はother&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;一方、&lt;code&gt;orElseGet&lt;/code&gt;は&lt;a href=&quot;https://docs.oracle.com/javase/jp/8/docs/api/java/util/Optional.html#orElseGet-java.util.function.Supplier-&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;こんな感じ&lt;/a&gt;です。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;public T orElseGet(Supplier&amp;lt;? extends T&amp;gt; other)&lt;/code&gt;&lt;br&gt;値が存在する場合はその値を返し、そうでない場合はotherを呼び出し、その呼び出しの結果を返します。&lt;/p&gt;&lt;p&gt;パラメータ:&lt;br&gt;other - Supplier(値が存在しない場合は、これの結果が返される)&lt;/p&gt;&lt;p&gt;戻り値:&lt;br&gt;値(存在する場合)、それ以外の場合はother.get()の結果&lt;/p&gt;&lt;p&gt;例外:&lt;br&gt;NullPointerException - 値が存在せずotherがnullの場合&lt;/p&gt;&lt;/blockquote&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="java" scheme="https://202accepted.com/tags/java/"/>
    
  </entry>
  
  <entry>
    <title>「Vue.js Tokyo v-meetup ＃6」参加レポート</title>
    <link href="https://202accepted.com/2017/12/14/vuejs-tokyo-meetup-6/"/>
    <id>https://202accepted.com/2017/12/14/vuejs-tokyo-meetup-6/</id>
    <published>2017-12-14T23:05:16.000Z</published>
    <updated>2021-08-16T14:23:52.224Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://connpass-tokyo.s3.amazonaws.com/thumbs/ec/c6/ecc6672d65b7f4e1c1562d6681bb9a29.png" alt="Vue.js Tokyo v-meetup #6"></p><p>12月13日に開催された「<a href="https://vuejs-meetup.connpass.com/event/69761/" target="_blank" rel="noopener">Vue.js Tokyo v-meetup #6</a>」に参加してきました。前回のMeetupがVue.jsを用いたサーバーサイドレンダリングの魅力を見せてくれたと言えるなら、今回のMeetupは2017年、Vue.jsのエコシステムがますます繁栄してきたアピールになった年と言えるのではないでしょうか。開発環境、テストツール、コーディング規約、UIフレームワーク、強力な公式サポートのおかげでWebのフロントエンド開発における欠かせないものを全部用意してくれています。一年前と比べて、今のVue.jsはすでにフロントエンドのギークたちのオモチャから、プロダクションレディで成熟したフレームワークになってきていると実感しています。</p><h1 id="TypeScriptサポート"><a href="#TypeScriptサポート" class="headerlink" title="TypeScriptサポート"></a>TypeScriptサポート</h1><p><img src="https://cdn-images-1.medium.com/max/1600/1*vB-z-t961mJnd4a6re02Iw.png" alt="TypeScript + Vue.js"></p><p>Vue.jsのバージョン2.4まで、Vue.jsにおけるTypeScriptのサポートは不足していました。TypeScriptでVue.jsプロジェクトを作成すること自体は問題ないですが、型定義の恩恵は受けにくい状況だったように感じます。@maeharinさんが<a href="https://speakerdeck.com/maeharin/10nian-qian-falseregasisisutemuwovue-dot-js-typescript-elementdehururiniyuarusiteiruhua-number-vuejs-meetup6" target="_blank" rel="noopener">発表</a>の中で紹介して頂いたように、Vue.js2.5以前、object型構文の内ではthisの型推論はできませんでした。そもそも、TypeScriptはこのような推論をサポートしていませんでしたので、Vue.js側のサポートも厳しかったでしょう。とは言え、Vue.jsの場合、「<a href="https://github.com/vuejs/vue-class-component" target="_blank" rel="noopener">vue-class-component</a>」を利用しない限り、object型構文は基本なので、かなり致命的な問題だったと考えられます。めでたいことに、TypeScriptのプルリクエスト<a href="https://github.com/Microsoft/TypeScript/pull/14141" target="_blank" rel="noopener">#14141</a>によって、objectリテラル内のthisの型推論が可能になりました。そして、Vue.jsのプルリクエスト<a href="https://github.com/vuejs/vue/pull/6391" target="_blank" rel="noopener">#6391</a>において、型定義の追加を含み、TypeScript向けの改善が行われた為、バージョン2.5以降、Vue.js+TypeScript開発が一気に便利になってきました。例えば、プロパティの補完とタイプミスを避けるために、@maeharinさんがプロジェクトの中にAPIの型定義を入れました。<a href="https://github.com/swagger-api/swagger-codegen" target="_blank" rel="noopener">swagger-codegen</a>というツールを使い、RubyクライアントとTypeScriptの定義を自動生成できました。自動生成されたTypeScriptの型定義はフロントの開発で利用されていますので、非常に効率の良い開発を行ったようです。ちなみに、swagger-codegenで使用されるAPI定義ファイルも<a href="https://github.com/springfox/springfox" target="_blank" rel="noopener">SpringFox</a>によって自動生成されているため、無駄な重複作業がかなり排除できたんじゃないかと思います。</p><h1 id="Visual-Studio-Code-Vetur"><a href="#Visual-Studio-Code-Vetur" class="headerlink" title="Visual Studio Code + Vetur"></a>Visual Studio Code + Vetur</h1><p><img src="https://upload.wikimedia.org/wikipedia/commons/f/f3/Visual_Studio_Code_0.10.1_icon.png" alt="Visual Studio Code"></p><p>Web開発を行う際に、使いやすい開発環境は非常に大事な要素になっています。Vue.js0.1Xの時代からAtomやSublime Text上のプラグインがすでに提供されて来ましたが、自動補完が足りなかったり、Lintができなかったり、とても使いやすいとは言えないでしょう。しかし、これらの問題はVSCodeの素早い進化とプラグイン<a href="https://github.com/vuejs/vetur" target="_blank" rel="noopener">Vetur</a>の登場によって解消されました。今回の会場提供者でもある、マイクロソフトの井上さんがデモの中に見せて頂いたように、VSCode+VeturコンビでVue.jsの開発を行えば、デバッグを含み、IDE並の開発体験ができるはずです。VSCodeがデフォルトでサポートしているEmmetと前述のTypeScript（実は、マイクロソフトは<a href="https://github.com/Microsoft/TypeScript-Vue-Starter" target="_blank" rel="noopener">TypeScript-Vue-Starter</a>というテンプレートを提供していますよ）を使えば、さらにスムーズな開発が期待できますね。</p><h1 id="UIフレームワーク"><a href="#UIフレームワーク" class="headerlink" title="UIフレームワーク"></a>UIフレームワーク</h1><p><img src="https://camo.githubusercontent.com/462f24153b8e8739c8ea71f7102585c4cb0e1575/68747470733a2f2f63646e2e7261776769742e636f6d2f456c656d6546452f656c656d656e742f6465762f656c656d656e745f6c6f676f2e737667" alt="Element UI"></p><p>TypeScriptの話と別に、@maeharinさんがスライドの中で、UIフレームワークである<a href="http://element.eleme.io/" target="_blank" rel="noopener">Element</a>を絶賛していました。Elementは中国のウェブベンチャーElemeが主導して開発したVue.jsのUIフレームワークです。デザインがシンプルで、多くのUIコンポーネントが提供されているため、人気を博し、Vue.jsのUIフレームワークの中で、もっとも人気があるフレームワークのひとつです。<code>Vue.use</code>の中にロケールの設定と一緒に入れるだけで日本語がサポートされるし、Veturの自動補完にも対応しています。さらに、各コンポーネントの設定項目が豊富で、バリデーションもかなりやりやすいそうです。Vue.jsのプロジェクトを試しに作りたい場合、Elementと組み合わせれば、素早く開発できそうな予感がしますね。当然ながら、Vue.jsのUIフレームワークはこの一つだけではありません。例えばスライドの中に挙げて頂いた、グーグルのマテリアルデザインに従っている<a href="https://vuetifyjs.com/" target="_blank" rel="noopener">vuetify</a>や、Bootstrapスタイルの<a href="https://bootstrap-vue.js.org/" target="_blank" rel="noopener">bootstrap-vue</a>などもそれなりに成熟できているので、迷ってしまうほど多くの選択肢があると思います。</p><h1 id="コーディング規約とリンター"><a href="#コーディング規約とリンター" class="headerlink" title="コーディング規約とリンター"></a>コーディング規約とリンター</h1><p><a href="https://docs.google.com/presentation/d/1nJ8gsRr_-lxzCprLu8CU0FwloXSNdU0QKk-kP42k40k/" target="_blank" rel="noopener"><img src="https://lh4.googleusercontent.com/xEOUw3_WrT-HnGqwrMuS9NdwKdNeqwMF953FieE50GkCBSsGSgBW4feQfgNrSxUC3RpjRA=w1200-h630-p" alt="eslint-plugin-vue"></a></p><p>複数人による大規模な開発の場合、可読性やメンテナンスのしやすさは重要なポイントです。そのため、ソフトウェア開発工程の中で、コーディング規約は欠かせないものです。当然ながら、プロントエンドのプロジェクトも例外ではありません。純粋なJavaScriptなら、<a href="https://github.com/airbnb/javascript" target="_blank" rel="noopener">Airbnb</a>と<a href="https://standardjs.com/" target="_blank" rel="noopener">Standard JS</a>は最も高い人気を誇っていますが、フレームワークの場合、Reactが圧倒的な優位に立っています。AirbnbがReactを採用しているため、2015年に「<a href="https://github.com/airbnb/javascript/blob/master/react/README.md" target="_blank" rel="noopener">Airbnb React/JSX Style Guide</a>」を公開し、すでに多くの開発現場で使用されているそうです。また、ESlintのプラグインである「<a href="https://github.com/yannickcr/eslint-plugin-react" target="_blank" rel="noopener">eslint-plugin-react</a>」も同時期に登場したため、「<a href="https://www.npmjs.com/package/eslint-config-airbnb" target="_blank" rel="noopener">eslint-config-airbnb</a>」と合わせて利用すれば、コーディング規約とリンターの設定を心配する必要がありません。それに対し、Vue.js界ではそれほど優れたプラグインや普及できている規約がなく、羨むしかできませんでした。しかし、こんな状況は改善されつつあります。まず、公式スタイルガイドがつい最近<a href="https://jp.vuejs.org/v2/style-guide/" target="_blank" rel="noopener">リリース</a>しました（まだBeta版ですが・・）。必須、強く推奨、推奨、使用注意、四段階に分けて様々なルールが盛り込まれています。それに、わざわざ静岡からお越しになった@mysticateaさんが自ら開発している「<a href="https://github.com/vuejs/eslint-plugin-vue" target="_blank" rel="noopener">eslint-plugin-vue</a>」も公開になりました。ルールはまだ追加中ではありますが、すでに数十種類を備えているため、十分に使えると思います。例えば、「no-parsing-error」というルールはHTMLやテンプレートの埋込式に構文エラーが無いかチェックしてくれますので、JavaScriptじゃなくてもeslintの恩恵が受けられます。公式スタイルガイド内のルールをサポートする予定なので、かなり期待できますね。ちなみに、現在開発リソースがまだ足りていない状況のようですので、興味ある方ぜひ参加してみてください。</p><h1 id="ユニットテスト"><a href="#ユニットテスト" class="headerlink" title="ユニットテスト"></a>ユニットテスト</h1><p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Creative-Tail-test_tube_2.svg/128px-Creative-Tail-test_tube_2.svg.png" alt="テスト"></p><p>実はVue.jsのユニットテストに関して、「v-meetup #4」の時、@hypermktさんが一回<a href="https://speakerdeck.com/hypermkt/vuekonponentofalseyunitutotesuto" target="_blank" rel="noopener">発表</a>を行っていました。しかし、公式テストツールはまだ開発段階だった為、@hypermktさんはavoiazの紹介をしていました。約半年後の今、公式テストツールであるvue-test-utilsはすでに<a href="https://github.com/vuejs/vue-test-utils/releases/tag/v1.0.0-beta.8" target="_blank" rel="noopener">v1.0.0-beta.8</a>になり、だいぶ安定して来ました。@lmiller1990さんが<a href="https://github.com/lmiller1990/lt-demo" target="_blank" rel="noopener">発表</a>の中で、コンポーネントの分離（shallow機能）、イベントのシミュレーション（trigger機能）、データの設定（setData機能）およびvuexのサポートを実演しながら紹介して頂きました。開発の中で、コンポーネント間の依存が複雑になるケースが多々あると思いますので、コンポーネントを切り離すことはユニットテストを行う際に不可欠な一歩だと考えています。これらの機能を使えば、その作業がある程度便利になります。vue-test-utilsの開発はavoiazの作者が主導している為、avoiazの良いところを継承しています。今Vue.jsのユニットテストツールを検討しているのであれば、vue-test-utilsは恐らく一番妥当な選択だと思います。</p><h1 id="その他"><a href="#その他" class="headerlink" title="その他"></a>その他</h1><script async class="speakerdeck-embed" data-slide="19" data-id="7d437d38c31b46318998d120b2d9c929" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script><p>Vue.jsのエコーシステムはこれだけではありません。上記のプロジェクト以外にも、注目すべきなプロジェクトがたくさんあります。例えば、私が気になっている「<a href="https://github.com/vuejs/vue-component-compiler" target="_blank" rel="noopener">vue-component-compiler</a>」はもうすぐ世に出るそうです。今までVue.jsシングルファイルコンポーネントのコンパイルロジックはプロジェクト依存でした。その為、単独利用が難しく、コンパイルロジックを使ったちょっとした拡張がやりにくかったです。「vue-component-compiler」が使えるようになれば、バンドルツールに依存せずコンポーネントのコンパイラの使用が可能になり、<a href="https://parceljs.org/" target="_blank" rel="noopener">Parcel</a>のような新しいバンドルツールにも迅速に対応できるようになるでしょう。また、@kazuponさんの発表の中にもあったように、公式クックブックとvue-cliの刷新プロジェクトもすでに動き出したそうで、Vue.js本体のメインバージョンアップも予定されているようです。Vue.jsのさらなる進歩が楽しみですね。</p><h1 id="まとめ"><a href="#まとめ" class="headerlink" title="まとめ"></a>まとめ</h1><p>2017年のウェブ開発において、JSフレームワークの利用はようやく定着化してきたと思います。特に、Vue.jsは直感的で理解しやすいというメリットを持ち、多くの支持を得ることができました。今回のMeetupの中で、@lovalottaplusさんがデザイナーさんにVue.jsを使用してもらう<a href="https://docs.google.com/presentation/d/1s1clv2XmtQRI6izjbsWJjpkYrfk0ALUEuKVoaPVwjwg/" target="_blank" rel="noopener">事例</a>を紹介して頂きました。コンポーネントを活用し、内部ロジックをうまく隠蔽すれば、プログラミング知識がそれほど豊富じゃないデザイナーでも開発できることはとても印象的でした。これはまさにVue.jsがずっと提唱して来たプログレッシブの好例だと思います。触りくらいなら、既存コンポーネントを使用すればすぐ開発できる、遠くまで行きたければ、TSなりRxJSなり使ってもよし・・・多種多様なケースに対応できることはVue.jsの長所であり、それに加え、エコシステムのより一層の充実により、2018年のVue.jsには更に期待できそうですね。<br>今回のMeetupは本当に有益でした、次回のMeetupも楽しみにしています。頑張ってLT枠を取りたいですね（笑）</p><p><em>今回の記事は同僚のこうめいさんに査読して下さいました。本当にありがとうございました。</em></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://connpass-tokyo.s3.amazonaws.com/thumbs/ec/c6/ecc6672d65b7f4e1c1562d6681bb9a29.png&quot; alt=&quot;Vue.js Tokyo v-meetup #6&quot;&gt;&lt;/p&gt;&lt;p&gt;12月13日に開催された「&lt;a href=&quot;https://vuejs-meetup.connpass.com/event/69761/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vue.js Tokyo v-meetup #6&lt;/a&gt;」に参加してきました。前回のMeetupがVue.jsを用いたサーバーサイドレンダリングの魅力を見せてくれたと言えるなら、今回のMeetupは2017年、Vue.jsのエコシステムがますます繁栄してきたアピールになった年と言えるのではないでしょうか。開発環境、テストツール、コーディング規約、UIフレームワーク、強力な公式サポートのおかげでWebのフロントエンド開発における欠かせないものを全部用意してくれています。一年前と比べて、今のVue.jsはすでにフロントエンドのギークたちのオモチャから、プロダクションレディで成熟したフレームワークになってきていると実感しています。&lt;/p&gt;&lt;h1 id=&quot;TypeScriptサポート&quot;&gt;&lt;a href=&quot;#TypeScriptサポート&quot; class=&quot;headerlink&quot; title=&quot;TypeScriptサポート&quot;&gt;&lt;/a&gt;TypeScriptサポート&lt;/h1&gt;&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1600/1*vB-z-t961mJnd4a6re02Iw.png&quot; alt=&quot;TypeScript + Vue.js&quot;&gt;&lt;/p&gt;&lt;p&gt;Vue.jsのバージョン2.4まで、Vue.jsにおけるTypeScriptのサポートは不足していました。TypeScriptでVue.jsプロジェクトを作成すること自体は問題ないですが、型定義の恩恵は受けにくい状況だったように感じます。@maeharinさんが&lt;a href=&quot;https://speakerdeck.com/maeharin/10nian-qian-falseregasisisutemuwovue-dot-js-typescript-elementdehururiniyuarusiteiruhua-number-vuejs-meetup6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;発表&lt;/a&gt;の中で紹介して頂いたように、Vue.js2.5以前、object型構文の内ではthisの型推論はできませんでした。そもそも、TypeScriptはこのような推論をサポートしていませんでしたので、Vue.js側のサポートも厳しかったでしょう。とは言え、Vue.jsの場合、「&lt;a href=&quot;https://github.com/vuejs/vue-class-component&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vue-class-component&lt;/a&gt;」を利用しない限り、object型構文は基本なので、かなり致命的な問題だったと考えられます。めでたいことに、TypeScriptのプルリクエスト&lt;a href=&quot;https://github.com/Microsoft/TypeScript/pull/14141&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;#14141&lt;/a&gt;によって、objectリテラル内のthisの型推論が可能になりました。そして、Vue.jsのプルリクエスト&lt;a href=&quot;https://github.com/vuejs/vue/pull/6391&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;#6391&lt;/a&gt;において、型定義の追加を含み、TypeScript向けの改善が行われた為、バージョン2.5以降、Vue.js+TypeScript開発が一気に便利になってきました。例えば、プロパティの補完とタイプミスを避けるために、@maeharinさんがプロジェクトの中にAPIの型定義を入れました。&lt;a href=&quot;https://github.com/swagger-api/swagger-codegen&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;swagger-codegen&lt;/a&gt;というツールを使い、RubyクライアントとTypeScriptの定義を自動生成できました。自動生成されたTypeScriptの型定義はフロントの開発で利用されていますので、非常に効率の良い開発を行ったようです。ちなみに、swagger-codegenで使用されるAPI定義ファイルも&lt;a href=&quot;https://github.com/springfox/springfox&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SpringFox&lt;/a&gt;によって自動生成されているため、無駄な重複作業がかなり排除できたんじゃないかと思います。&lt;/p&gt;&lt;h1 id=&quot;Visual-Studio-Code-Vetur&quot;&gt;&lt;a href=&quot;#Visual-Studio-Code-Vetur&quot; class=&quot;headerlink&quot; title=&quot;Visual Studio Code + Vetur&quot;&gt;&lt;/a&gt;Visual Studio Code + Vetur&lt;/h1&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="vue.js" scheme="https://202accepted.com/tags/vue-js/"/>
    
  </entry>
  
  <entry>
    <title>Vue.jsでプレースホルダを用いたローディングを実装する際のトランジション</title>
    <link href="https://202accepted.com/2017/12/11/use-transition-for-placeholder-in-vuejs/"/>
    <id>https://202accepted.com/2017/12/11/use-transition-for-placeholder-in-vuejs/</id>
    <published>2017-12-11T21:35:24.000Z</published>
    <updated>2021-08-16T14:23:52.224Z</updated>
    
    <content type="html"><![CDATA[<p><strong>この記事の実装例は<a href="https://www.webpackbin.com/bins/-L-ycPbJmEtxhmi2BOgQ" target="_blank" rel="noopener">こちら</a>です。</strong></p><h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>UX向上の観点により、読み込みが遅いもの（特に大きなイメージファイルなど）が存在する場合、先に枠を表示し、ダウンロードできた後本物に置き換える設計は<a href="https://medium.com/@shunsukematsumoto/%E3%83%97%E3%83%AC%E3%83%BC%E3%82%B9%E3%83%9B%E3%83%AB%E3%83%80%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%AD%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0ui-571f896738a6" target="_blank" rel="noopener">最近増えてきています</a>。そのうち、下の図で示されているようなFacebookのロード画面は好例の一つだと言えるでしょう。</p><p><img src="https://i.stack.imgur.com/ocOS7.jpg" alt="Facebookローディング画面のプレスホルダー"></p><p>この設計をVue.jsで実装するのはそれほど難しくないでしょう。いくつかのVue.js製のプレスホルダーはすでに公開されている（<a href="https://github.com/StevenYuysy/vue-content-placeholder" target="_blank" rel="noopener">その一</a>、<a href="https://github.com/michalsnik/vue-content-placeholders" target="_blank" rel="noopener">その二</a>）ため、それらを<a href="https://jp.vuejs.org/v2/guide/conditional.html" target="_blank" rel="noopener">条件付きレンダリング（Conditional Rendering）</a>と合わせ、ディレクティブ<code>v-if</code>と<code>v-else</code>を活用するだけで実現可能です。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">placeholder</span> <span class="attr">v-if</span>=<span class="string">"content === null"</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">my-content</span> <span class="attr">v-else</span> /&gt;</span></span><br></pre></td></tr></table></figure><p>こういう風に実装してもダメとは言えませんが、コンテンツの切り替えにトランザクションが全く存在しないため、唐突の感は免れません。よって、置き換えが発生した際に、フェードイン／フェードアウト効果を追加した方がUX的に優しいと思われます。</p><h1 id="トランジションモード"><a href="#トランジションモード" class="headerlink" title="トランジションモード"></a>トランジションモード</h1><p>Vue.jsでトランジションを追加するのに、非常に簡単なやり方が存在します。そう、<a href="https://jp.vuejs.org/v2/guide/transitions.html#単一要素-コンポーネントのトランジション" target="_blank" rel="noopener"><code>Transition</code>というラッパーコンポーネント</a>で囲み、CSSで定義する方法です。</p><p><img src="https://vuejs.org/images/transition.png" alt="トランジションの状態定義"></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">&lt;transition name=&quot;fade&quot;&gt;</span><br><span class="line">  &lt;placeholder v-if=&quot;content === null&quot; /&gt;</span><br><span class="line">  &lt;my-content v-else /&gt;</span><br><span class="line">&lt;/transition&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">// 省略</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style&gt;</span><br><span class="line">.fade-enter-active, .fade-leave-active &#123;</span><br><span class="line">  transition: opacity 1s;</span><br><span class="line">&#125;</span><br><span class="line">.fade-enter, .fade-leave-to &#123;</span><br><span class="line">  opacity: 0;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>しかし、これだけでは変な動きが出てきます。一時的にプレスホルダーと本物が同時に画面上に現れるわけです。<br>理由は単純です。<code>transition</code>内の子コンポーネントのアニメーションが同時に開始するため、プレスホルダーのフェードアウトアニメーションが再生されている間に、本物のコンポーネントがすでに出てきてしまいました。<br>これを回避するために、Vue.jsがトランジションモードを用意してくれました。現時点では<code>out-in</code>と<code>in-out</code>2種類が提供されていて、<code>out-in</code>を利用すれば、コンポーネントAが消失した後、コンポーネントBを出現させることは可能になります。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">&lt;transition name=&quot;fade&quot; mode=&quot;out-in&quot;&gt;</span><br><span class="line">  &lt;placeholder v-if=&quot;content === null&quot; /&gt;</span><br><span class="line">  &lt;my-content v-else /&gt;</span><br><span class="line">&lt;/transition&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">// 省略</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style&gt;</span><br><span class="line">.fade-enter-active, .fade-leave-active &#123;</span><br><span class="line">  transition: opacity 1s;</span><br><span class="line">&#125;</span><br><span class="line">.fade-enter, .fade-leave-to &#123;</span><br><span class="line">  opacity: 0;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><h1 id="より良い表現を求めて"><a href="#より良い表現を求めて" class="headerlink" title="より良い表現を求めて"></a>より良い表現を求めて</h1><p>上記の解決策は悪くないと思いますが、もう少しいい表現ができると思いました。今の場合、トランジション効果は一つずつ再生されるため、所用時間が長くなり、入れ替わる感が感じにくくなっています。その為、やはりフェードアウトとフェードインは同時に行って欲しいですね。となると、トランジションモードの使用を取りやめ、その代わりに、CSSの<code>position</code>で二つのコンポーネントの位置を同じところに固定すれば、望んでいた効果が出せるはずです。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">&lt;transition name=&quot;fade&quot;&gt;</span><br><span class="line">  &lt;placeholder v-if=&quot;content === null&quot; class=&quot;my-content&quot; /&gt;</span><br><span class="line">  &lt;my-content v-else class=&quot;my-content&quot; /&gt;</span><br><span class="line">&lt;/transition&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">// 省略</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style&gt;</span><br><span class="line">.fade-enter-active, .fade-leave-active &#123;</span><br><span class="line">  transition: opacity 1s;</span><br><span class="line">&#125;</span><br><span class="line">.fade-enter, .fade-leave-to &#123;</span><br><span class="line">  opacity: 0;</span><br><span class="line">&#125;</span><br><span class="line">.my-content &#123;</span><br><span class="line">  position: absolute;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>しかし、見た目は完璧でしょうが、この方法はトランジションモードの方法より扱いにくいはずです。なぜかと言いますと、<code>position: absolute;</code>の使用によって、コンポーネントらがドキュメントフローから出てしまうので、CSS上で配慮しなければいけないものが増えてしまいます。</p><h1 id="まとめ"><a href="#まとめ" class="headerlink" title="まとめ"></a>まとめ</h1><p>もっといい方法があるのではないかと思いますが、今回はただの実験なので、これ以上追求しませんでした。一見簡単そうなテーマでしたが、完璧に実現することは意外と難しいということを感じましたね。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;strong&gt;この記事の実装例は&lt;a href=&quot;https://www.webpackbin.com/bins/-L-ycPbJmEtxhmi2BOgQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;こちら&lt;/a&gt;です。&lt;/strong&gt;&lt;/p&gt;&lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;UX向上の観点により、読み込みが遅いもの（特に大きなイメージファイルなど）が存在する場合、先に枠を表示し、ダウンロードできた後本物に置き換える設計は&lt;a href=&quot;https://medium.com/@shunsukematsumoto/%E3%83%97%E3%83%AC%E3%83%BC%E3%82%B9%E3%83%9B%E3%83%AB%E3%83%80%E3%82%92%E7%94%A8%E3%81%84%E3%81%9F%E3%83%AD%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0ui-571f896738a6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;最近増えてきています&lt;/a&gt;。そのうち、下の図で示されているようなFacebookのロード画面は好例の一つだと言えるでしょう。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i.stack.imgur.com/ocOS7.jpg&quot; alt=&quot;Facebookローディング画面のプレスホルダー&quot;&gt;&lt;/p&gt;&lt;p&gt;この設計をVue.jsで実装するのはそれほど難しくないでしょう。いくつかのVue.js製のプレスホルダーはすでに公開されている（&lt;a href=&quot;https://github.com/StevenYuysy/vue-content-placeholder&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;その一&lt;/a&gt;、&lt;a href=&quot;https://github.com/michalsnik/vue-content-placeholders&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;その二&lt;/a&gt;）ため、それらを&lt;a href=&quot;https://jp.vuejs.org/v2/guide/conditional.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;条件付きレンダリング（Conditional Rendering）&lt;/a&gt;と合わせ、ディレクティブ&lt;code&gt;v-if&lt;/code&gt;と&lt;code&gt;v-else&lt;/code&gt;を活用するだけで実現可能です。&lt;/p&gt;&lt;figure class=&quot;highlight html&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;placeholder&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;v-if&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&quot;content === null&quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;my-content&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;v-else&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="vue.js" scheme="https://202accepted.com/tags/vue-js/"/>
    
  </entry>
  
  <entry>
    <title>Hexoブログのカスタムホームページの作り方</title>
    <link href="https://202accepted.com/2017/11/26/how-to-create-a-custom-index/"/>
    <id>https://202accepted.com/2017/11/26/how-to-create-a-custom-index/</id>
    <published>2017-11-26T22:14:22.000Z</published>
    <updated>2021-08-16T14:23:52.221Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>デフォルトの設定でHexoのブログを作っている場合、ホームページ(index)がすでに存在しています。かなり便利でありがたい機能ですが、カスタマイズしようとしたら、手数がやや掛ってしまいます。<br>具体的に言うと、テーマ内の<code>index.ejs</code>ファイルに記入されているコードは<code>layout.ejs</code>の<code>&lt;%- body %&gt;</code>に入ります。すなわち、indexページのレイアウトは<code>index.ejs</code>のほか、layoutフォルダ内の<code>layout.ejs</code>にも左右されます。別に悪い仕様とは全然言えませんが、ホームページだけは通常のテンプレートに適用されたくないというユースケースもあるでしょう。<br>それを回避するために、HexoのGitHub上のIssueを調査したり、何回か試したりして、ようやく分かりましたので、ここで整理してみたいと思います。</p><h1 id="手順"><a href="#手順" class="headerlink" title="手順"></a>手順</h1><ol><li><code>hexo-generator-index</code>というプラグインを削除します。自分でインデックスページを作るので、当然ながら自動生成の機能は不要になります。Hexoプロジェクトのルートディレクトリに行って、<code>npm uninstall hexo-generator-index</code>を打てば問題ないはずです。</li><li>sourceフォルダーの中で<code>index.md</code>というファイルを作ります。こちらのファイルはエントリーポイントになります。</li><li><code>layout.ejs</code>内に以下のような条件分岐を加えます。</li></ol><figure class="highlight erb"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">%</span></span></span> if (page.source == 'index.md') &#123; <span class="xml"><span class="tag">%&gt;</span></span></span><br><span class="line"><span class="xml">  <span class="tag">&lt;<span class="name">span</span>&gt;</span>こちらはホームページのテンプレート<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">%</span></span></span> &#125; else&#123; <span class="xml"><span class="tag">%&gt;</span></span></span><br><span class="line"><span class="xml">  <span class="tag">&lt;<span class="name">span</span>&gt;</span>こちらはその他のページのテンプレート<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">%</span></span></span> &#125; <span class="xml"><span class="tag">%&gt;</span></span></span><br></pre></td></tr></table></figure><h1 id="参考リンク"><a href="#参考リンク" class="headerlink" title="参考リンク"></a>参考リンク</h1><ul><li><a href="https://github.com/hexojs/hexo/issues/887" target="_blank" rel="noopener">https://github.com/hexojs/hexo/issues/887</a></li><li><a href="https://github.com/hexojs/hexo/issues/959" target="_blank" rel="noopener">https://github.com/hexojs/hexo/issues/959</a></li><li><a href="https://github.com/hexojs/hexo/issues/1491" target="_blank" rel="noopener">https://github.com/hexojs/hexo/issues/1491</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;デフォルトの設定でHexoのブログを作っている場合、ホームページ(index)がすでに存在しています。かなり便利でありがたい機能ですが、カスタマイズしようとしたら、手数がやや掛ってしまいます。&lt;br&gt;具体的に言うと、テーマ内の&lt;code&gt;index.ejs&lt;/code&gt;ファイルに記入されているコードは&lt;code&gt;layout.ejs&lt;/code&gt;の&lt;code&gt;&amp;lt;%- body %&amp;gt;&lt;/code&gt;に入ります。すなわち、indexページのレイアウトは&lt;code&gt;index.ejs&lt;/code&gt;のほか、layoutフォルダ内の&lt;code&gt;layout.ejs&lt;/code&gt;にも左右されます。別に悪い仕様とは全然言えませんが、ホームページだけは通常のテンプレートに適用されたくないというユースケースもあるでしょう。&lt;br&gt;それを回避するために、HexoのGitHub上のIssueを調査したり、何回か試したりして、ようやく分かりましたので、ここで整理してみたいと思います。&lt;/p&gt;&lt;h1 id=&quot;手順&quot;&gt;&lt;a href=&quot;#手順&quot; class=&quot;headerlink&quot; title=&quot;手順&quot;&gt;&lt;/a&gt;手順&lt;/h1&gt;&lt;ol&gt;&lt;li&gt;&lt;code&gt;hexo-generator-index&lt;/code&gt;というプラグインを削除します。自分でインデックスページを作るので、当然ながら自動生成の機能は不要になります。Hexoプロジェクトのルートディレクトリに行って、&lt;code&gt;npm uninstall hexo-generator-index&lt;/code&gt;を打てば問題ないはずです。&lt;/li&gt;&lt;li&gt;sourceフォルダーの中で&lt;code&gt;index.md&lt;/code&gt;というファイルを作ります。こちらのファイルはエントリーポイントになります。&lt;/li&gt;&lt;li&gt;&lt;code&gt;layout.ejs&lt;/code&gt;内に以下のような条件分岐を加えます。&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;highlight erb&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; if (page.source == &#39;index.md&#39;) &amp;#123; &lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;こちらはホームページのテンプレート&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;name&quot;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &amp;#125; else&amp;#123; &lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;こちらはその他のページのテンプレート&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;name&quot;&gt;span&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;%&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &amp;#125; &lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;h1 id=&quot;参考リンク&quot;&gt;&lt;a href=&quot;#参考リンク&quot; class=&quot;headerlink&quot; title=&quot;参考リンク&quot;&gt;&lt;/a&gt;参考リンク&lt;/h1&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="hexo" scheme="https://202accepted.com/tags/hexo/"/>
    
  </entry>
  
  <entry>
    <title>ポリモーフィズムクイズ</title>
    <link href="https://202accepted.com/2016/12/26/a-polymorphism-puzzle/"/>
    <id>https://202accepted.com/2016/12/26/a-polymorphism-puzzle/</id>
    <published>2016-12-26T14:12:00.000Z</published>
    <updated>2021-08-16T14:23:52.220Z</updated>
    
    <content type="html"><![CDATA[<h1 id="問題"><a href="#問題" class="headerlink" title="問題"></a>問題</h1><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyTest</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">String message = <span class="string">"hello"</span>;</span><br><span class="line">Consumer&lt;String&gt; hello = s -&gt; System.out.print(message + s);</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">hello</span><span class="params">(String s)</span> </span>&#123; <span class="keyword">this</span>.hello.accept(s); &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">String message = <span class="string">"ハロー"</span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">hello</span><span class="params">(String s)</span> </span>&#123; <span class="keyword">this</span>.hello.accept(s); &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">A b = (A) <span class="keyword">new</span> B();</span><br><span class="line">b.hello(<span class="string">" world"</span>);</span><br><span class="line">System.out.print(<span class="string">"/"</span>);</span><br><span class="line">b.hello.accept(<span class="string">" world"</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上記のコードの実行結果は</p><ul><li><input disabled type="checkbox"> A. ハロー world/hello world</li><li><input disabled type="checkbox"> B. ハロー world/ハロー world</li><li><input disabled type="checkbox"> C. hello world/ハロー world</li><li><input disabled type="checkbox"> D. hello world/hello world</li><li><input disabled type="checkbox"> E. コンパイルエラー</li></ul><h1 id="正解"><a href="#正解" class="headerlink" title="正解"></a>正解</h1><p>答えは</p><ul><li><input checked disabled type="checkbox"> D. hello world/hello world</li></ul><h1 id="説明"><a href="#説明" class="headerlink" title="説明"></a>説明</h1><p>一見複雑そうですが、実はポリモーフィズムをちゃんと理解できれば、すぐ解けるはずです。それでは、<code>main</code>メソッドの処理を追って見ましょう。</p><ul><li><code>main</code>メソッドの一行目では<code>A</code>型<code>B</code>実装の変数<code>b</code>を宣言しました。<code>(A)</code>というアップキャストの処理が書かれていますが、実はコンパイラが自動的に行ってくれる作業なので、ただの目障りで意味がありません（勿論エラーにもなりませんが・・）。</li><li><code>b</code>のメソッドを利用する際に、コンパイラはまず実装型にそのメソッドがあるかどうかを見ます（二行目）。クラス<code>B</code>に<code>hello</code>というメソッドがありましたね。オーバーライドが明記されていませんが、シグネチャに違いがない為、親クラスの<code>hello</code>メソッドがオーバーライドされていることは分かります。ポリモーフィズムのルールによりクラス<code>B</code>の<code>hello</code>メソッドが実行されます。</li><li><code>hello</code>いうメソッドは<code>hello</code>というコンシューマー関数のフィールドを呼んでいますが、残念ながら<code>A</code>クラスにしか<code>hello</code>が存在しません。その為、やむを得ず<code>A</code>クラス内の<code>hello</code>関数を利用することになります。（ちなみに、メソッド名とフィールド名の重複は許されますので、コンパイルエラーになりません）</li><li><code>hello</code>という関数は<code>message</code>というフィールドを使います。クラス<code>A</code>の<code>message</code>は<code>hello</code>ですので、出力結果は<code>hello world</code>になります。クラス<code>B</code>にも<code>message</code>というフィールドが存在しますが、今使っている<code>hello</code>関数とは無関係ですね。</li><li>さらに<code>main</code>の四行目ですが、<code>b</code>オブジェクトの<code>hello</code>関数を利用しているように見えますね。しかし、フィールド変数のオーバーライドが存在しないことを忘れてはいけません。<code>hello</code>関数は<code>hello</code>メソッドと同じく処理手続きを定義するものですが、本質的には<code>message</code>のようなフィールド変数です。その為、どのフィールドが利用されるかは宣言時の参照型によります。<code>A</code>として宣言された為、クラス<code>A</code>の<code>hello</code>関数が利用され、二行目の出力結果と同じようになります。</li></ul><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><ul><li><a href="https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html" target="_blank" rel="noopener">https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html</a></li><li><a href="https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Consumer.html" target="_blank" rel="noopener">https://docs.oracle.com/javase/jp/8/docs/api/java/util/function/Consumer.html</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h1 id=&quot;問題&quot;&gt;&lt;a href=&quot;#問題&quot; class=&quot;headerlink&quot; title=&quot;問題&quot;&gt;&lt;/a&gt;問題&lt;/h1&gt;&lt;figure class=&quot;highlight java&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;MyTest&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;A&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		String message = &lt;span class=&quot;string&quot;&gt;&quot;hello&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		Consumer&amp;lt;String&amp;gt; hello = s -&amp;gt; System.out.print(message + s);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(String s)&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.hello.accept(s); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&lt;span class=&quot;keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;A&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		String message = &lt;span class=&quot;string&quot;&gt;&quot;ハロー&quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;hello&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(String s)&lt;/span&gt; &lt;/span&gt;&amp;#123; &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.hello.accept(s); &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(String[] args)&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		A b = (A) &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; B();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		b.hello(&lt;span class=&quot;string&quot;&gt;&quot; world&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		System.out.print(&lt;span class=&quot;string&quot;&gt;&quot;/&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;		b.hello.accept(&lt;span class=&quot;string&quot;&gt;&quot; world&quot;&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;	&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;&lt;p&gt;上記のコードの実行結果は&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;input disabled type=&quot;checkbox&quot;&gt; A. ハロー world/hello world&lt;/li&gt;&lt;li&gt;&lt;input disabled type=&quot;checkbox&quot;&gt; B. ハロー world/ハロー world&lt;/li&gt;&lt;li&gt;&lt;input disabled type=&quot;checkbox&quot;&gt; C. hello world/ハロー world&lt;/li&gt;&lt;li&gt;&lt;input disabled type=&quot;checkbox&quot;&gt; D. hello world/hello world&lt;/li&gt;&lt;li&gt;&lt;input disabled type=&quot;checkbox&quot;&gt; E. コンパイルエラー&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;正解&quot;&gt;&lt;a href=&quot;#正解&quot; class=&quot;headerlink&quot; title=&quot;正解&quot;&gt;&lt;/a&gt;正解&lt;/h1&gt;&lt;p&gt;答えは&lt;/p&gt;
    
    </summary>
    
      <category term="tech" scheme="https://202accepted.com/categories/tech/"/>
    
    
      <category term="java" scheme="https://202accepted.com/tags/java/"/>
    
  </entry>
  
</feed>
