OmniAICreator/Qiita-1.07M huggingface dataset:
ruby モジュールに定義する処理で、

# モジュール内の定義する処理の実装方法で、

外から呼び出せる可視性みたいなのを制御したい場合には、どうするのがいいんすかね？

下記１～５の実装方式では、それぞれスコープも違うし使用目的も違ってくるんですが、
なんか一般的なガイドラインみたいなのとかってあるんすかね？

という質問です

```m.rb
# モジュールに定義する処理で、
module M
  # ■ 1. （たぶん簡単に）外から呼べない - クラスインスタンス変数のラムダ
  @class_var_proc = -> arg do
    puts "  @class_var_proc: #{arg}"
  end
  
  # ■ 2. （たぶん簡単に）外から呼べない - クラスインスタンスのprivateメソッド
  class << self
    private
    def private_method(arg)
      puts "  private_method: #{arg}"
    end
  end
  
  # 〇 3. 外から呼べる - 定数のラムダ
  CONST_PROC = -> arg do
    puts "CONST_PROC: #{arg}"
    private_method(arg)   # 中から呼ぶ
    @class_var_proc[arg]  # 中から呼ぶ
    puts '----------'
  end
  
  # 〇 4. 外から呼べる - クラスメソッド
  def self.class_method(arg)
    puts "class_method: #{arg}"
    private_method(arg)   # 中から呼ぶ
    @class_var_proc[arg]  # 中から呼ぶ
    puts '----------'
  end
  
  # 〇 5. 外から呼べる - モジュールファンクション
  module_function
  def module_function_method(arg)
    puts "module_function_method: #{arg}"
    private_method(arg)   # 中から呼ぶ
    @class_var_proc[arg]  # 中から呼ぶ
    puts '----------'
  end
end

if __FILE__ == $0
  M::CONST_PROC[1] # 外から呼ぶ

  M.class_method(2) # 外から呼ぶ

  M.module_function_method(3) # 外から呼ぶ
end
```

↑の出力結果

```
CONST_PROC: 1
  private_method: 1
  @class_var_proc: 1
----------
class_method: 2
  private_method: 2
  @class_var_proc: 2
----------
module_function_method: 3
  private_method: 3
  @class_var_proc: 3
----------
```
Play Framework の Request Body をスマートにパースする

# はじめに

私は Action で Request Body の JSON からクラスにマッピングする、といった処理を良く書きます。
Action 内のコードでパースすることもできますが、 Play の機能を上手く使えば簡潔に書けるので、その方法をご紹介します。

# 問題のコード

素直に書くとこのような感じになります。

```Scala
class MyController extends InjectedController {

  case class MyRequestBody(foo: String)

  implicit val myReads: Reads[MyRequestBody] = Json.reads[MyRequestBody]

  def myAction = Action { request =>
    request.body.asJson match {
      case None => UnsupportedMediaType
      case Some(json) => json.validate[MyRequestBody] match {
        case _: JsError => BadRequest
        case JsSuccess(body, _) =>
          // some process
          Ok
      }
    }
  }

}
```

Request Body が Json でなければ Unsupported Media Type 、Json を クラスにマッピングできなければ Bad Request を返す、というコードです。
一度だけならあまり問題にはなりませんが、毎回書くとなるとかなり煩わしいです。

# 改善後のコード

`parse.json[A](implicit reader: Reads[A])` を使うことで、 Action の実行前にパースします。

```Scala
class MyController extends InjectedController {

  case class MyRequestBody(foo: String)

  implicit val myReads: Reads[MyRequestBody] = Json.reads[MyRequestBody]

  def myAction: Action[MyRequestBody] = Action(parse.json[MyRequestBody])  { request =>
    val body: MyRequestBody = request.body
    // some process
    Ok
  }

}
```

かなり簡潔になったのではないでしょうか。
このコードでも前のコードと同様に Unsupported Media Type と Bad Request を返せます。

# おわりに

Action の実行前に Request Body をパースする方法をご紹介しました。
仕様によって細かく分岐させなければいけない場合などもありますので、いつでも使えるわけではありませんが、多くのケースに適用できるのではないでしょうか。
是非使ってみてください。
タイムゾーンを調べるのにdateを打つのは間違っている！！

# Q. OSのローカルタイムゾーンを調べよ

よくある回答

```bash
$ date
# Fri Nov 16 12:39:52 JST 2018
```

# 今回見つけた事象

見つけた場所： Docker containerのOS（dockerのゲストOS）のubuntuさん

```bash
$ date
# Fri Nov 16 12:39:52 JST 2018

$ cat /etc/timezone
# Etc/UTC <- システムが参照するのはこっち
```

( ﾟдﾟ)ｴｯ!!!

# 原因

`export TZ="JST-9"`

`TZ`は、Linuxでタイムゾーンを指定する環境変数ですが、 `/etc/timezone` や `/etc/localtime` には、無影響なようです。
そのため、MySQLなどのように`TZ`を参照してくれるものは、正しくタイムゾーンが設定されますが、
`/etc/timezone`や`/etc/localtime`しか参照してくれないアプリケーションの場合は、`TZ`しかタイムゾーンの指定をしていない場合、UTCで管理されることになると思うので気をつけてください。
（後半のところ、直面しました。）
postgRESTの認証でドはまりしたメモ

# この記事は
postgreSQLにWebからアクセスするためのAPIを提供するpostgRESTをつかおうとしたときに、認証周りで失敗した話です。

- postgREST http://postgrest.org/en/v5.1/index.html

# 失敗の経緯
- 提供されているdocker-composeで動かして、とりあえずうまく行っていた
- そろそろ認証をかけたいなと思ったときに、色々な勘違いにより失敗した。

# はじめに
ちょっとした経緯で、またWebアプリを書くことになりました。

データベースに格納されたデータを参照して、意思決定をしたいということで、supersetやらmetabaseを使えばよさそうなんだけれども、ちょっとインタラクションをこだわりたいみたいな話があり、やむなくBootstrapベースでフルスクラッチすることに。
(((要求抽出が進んで、これってMetabaseでよくね？となってきたのですが、それはおいておいて…)))

今回は認証周りで色々ハマったので、忘備録として軽くメモ書きします。

結論を早く知りたい人は、一番下にまとめてあるので、それを参照ください。

# 環境 (バージョンは割愛 ちょっと古いです)
- CentOS
- docker
- docker-compose
- postgres (docker container) 

# やったこと
機能の概要は分かったので、とりあえず公開されているdocker-compose.ymlを少し改変して動作させる

```yml:docker-compose.yml
version: '3'
services:
  server:
    image: postgrest/postgrest
    # ports:               #ポート3000は公開せずに別のnginxコンテナでリバースプロキシする
    #  - "3000:3000"
    links:
      - db:db
    environment:
      PGRST_DB_URI: postgres://app_user:password@db:5432/app_db
      PGRST_DB_SCHEMA: public
      PGRST_DB_ANON_ROLE: app_user #In production this role should not be the same as the one used for the connection
    depends_on:
      - db
  db:
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: app_db
      POSTGRES_USER: app_user
      POSTGRES_PASSWORD: password
  # Uncomment this if you want to persist the data.
  # volumes:
  #   - "./pgdata:/var/lib/postgresql/data"
```

このコンテナを立ち上げて、nginxでproxy設定を書いてやると、なるほど、いいじゃないか！
ということで、採用。

# 認証について知るために、あとからチュートリアルをやる
postgRESTはチュートリアルが2段階で用意されており、Tutorial 0(http://postgrest.org/en/v5.1/tutorials/tut0.html) は主にインストールの話、Tutorial 1は認証の話です。

自分は既にdockerでインストール済なので、Tutorial 1から始めました。

# tutorial.conf?
Step 1でユーザを作って、Step 2で秘密鍵を作るのですが、その秘密鍵を```tutorial.conf```に記述せよと。dockerをやっている範囲ではそんなもん書いていないので、ここで一度ハマる。

とはいえ、どうせ環境変数で設定するんだろうとタカをくくり、

```shell-session
docker-compose exec server bash
***# env
```
とやって環境変数を確認。案の定、```PGRST_JWT_SECRET```というエントリがあったので、適当なパスワード(```password```的な)のを登録して```docker-compose up -d server```でサーバを再起動。

# まったく認証が動作している気配がない。
JWTの設定をしても```app_db```の内容が全部参照できてしまう。これはどうしたことか、、、と思案するなかで、ここで初めてTutorial 0に戻る。すると

```config:tutorial.conf
db-uri = "postgres://postgres:mysecretpassword@localhost/postgres"
db-schema = "api"
db-anon-role = "web_anon"
```

```docker-compose.yml``` では ```db-anon-role``` が同じスーパユーザに設定されているために、**認証に失敗してAnonymousで入った結果、すべて参照できるようになっていた**とわかる。
```PGRST_DB_ANON_ROLE```を存在しないユーザに設定し、想定通り403が返ってくるようになった。

# 認証が通らない
ここで、jwt.ioで認証トークンを作成して、curlのヘッダに登録すると、次は401で認証エラーが返ってくるようになった。

良く調べると(というか、ちゃんと書いてあるんだけれど)**秘密鍵は32文字以上必要**とのこと。

# というわけで、
秘密鍵を32文字以上にしたら動くようになった。


# まとめ
docker-composeでpostgRESTを動かした後はこの手順で設定すればよい。

- Anonymous Roleを設定する 
    - ```PGRST_DB_ANON_ROLE```をスーパユーザ以外に設定する
    - 接続先のDBにロールを作成し、Anonymous用の権限を付ける
- 秘密鍵を設定する
    - ```PGRST_JWT_SECRET```の環境変数エントリを設定し、**32文字以上の秘密鍵**を平文で書く
    - JWT.ioにアクセスし、Payloadに ``` {"role": アクセスしていいユーザ}```を設定する
         - 何も考えないと```app_user```になるが、スーパユーザはなぁ、と思う人はもう一人別のロールを作って権限設定をする。
    - Signatureの「ここだよ」と書いてあるところに秘密鍵を入力する

# ついでに分かったこと 
-  ```postgres/postgres``` dockerイメージは```/etc/postgrest.conf```を参照している。環境変数でなく、confファイルを直接参照させたい人は、このファイルをホストからコントロールできるようにすればいい
NASのフォルダ名に隠れて"-1"が付く

# きっかけ
NAS上のデータにアクセスしつつ作業をしている時、なぜかアクセスできなくなった。ファインダー上のフォルダー名には変化は見られなかったが、ターミナルで確認するとフォルダ名に"-1"がついていた。

# ググる
はるか昔のアップルコミュニティに同様な質問を発見。
https://discussionsjapan.apple.com/thread/10041209
私も原因はおそらく、NASをマウントしたままの状態でログアウトしたためでしょう。
接続していないのに、フォルダー名が残っていました。

#解決法
sudo rmdir hoge

#注意
NASには接続していない状態を確認してから、名前だけ残っているフォルダを消します。
【Unity(C#)】VRでのフェードイン、フェードアウト


　　
　　
　　

この記事は

**『プログラミング完全未経験からUnityでの開発現場に迎え入れてもらえた世界一の幸せ者』**

の記事です。そのつもりでお読みください。
  
  

##VRでのフェードイン、フェードアウト

####☆下準備☆
①Asset Storeから`SteamVR Plugin`をDL＋Import
②Add ComponentでSteam　VR_Fade(Script)を検索して
③[CameraRig]のCameraにAdd Component

以下スクリプトです。
  

  　　

名前空間の追加

```C#
using Valve.VR;
```


publicで宣言すればInspectorで設定可能

```C#

    public float fadeDuration; //フェードしていく秒数
    public Color before_color; //フェード前の色
    public Color after_color;  //フェード後の色
```

フェードインならスタート時に呼び出し、
フェードアウトはフェードアウトさせたい処理の後に呼び出し

```C#
  SteamVR_Fade.Start(before_color, 0f);

  SteamVR_Fade.Start(after_color, fadeDuration);
```

とっても便利。
How to make animation on scroll ?

There have so many animation for icon scroll, but today we will do animation type arrow run down like animated last post.
####Start with element  html
You just simple put html will is:
`<div class="icon-scroll"></div>`
and if you use `pug` to code it will is: 
`.icon-scroll`
####Start with scss
*There're we will create square color orange has width 80px:

```ruby:
.icon-scroll{
  background: #ec8806;
  position: relative;
  z-index: 10;;
  cursor: pointer;
  width: 90px;
  left: 0;
  right: 0;
  top: 20px;
  padding-bottom: 45px;
  margin: auto;
  color: #fff;
  text-align: center;
  transition: 2s;
}
```
*Next, we will add two `Pseudo-Elements` is `before` and `after` like this:
##### `before`: 
```ruby:
   &:before{
    content: "";
    display: block;
    position: absolute;
    bottom: 0;
    right: 0;
    left: 0;
    margin: auto;
    width: 1px;
    height: 18px;
    background-color: #FFF;
    transform-origin: left bottom;
    transform: scaleY(0) rotate(70deg);
    animation: arrowA 1.8s ease-in-out 0s infinite;
   }
```
##### `after`: 
```ruby:
   &:after{
     content: "";
     position: absolute;
     width: 1px;
     height: 40px;
     margin: auto;
     bottom: 0;
     left: 0;
     right: 0;
     animation: arrowB 1.8s ease-in-out 0s infinite;
     background-color: #FFF;
   }
```
####Start with keyframes
##### Keyframes `arrowA` for `before`: 
```ruby:
@keyframes arrowA {
  0% {
    transform:rotate(35deg) scaleY(0) translate(0px, 0px);
    height: 15px;
  }
  40% {
    transform:rotate(35deg) scaleY(0) translate(0px, 0px);
    height: 15px;
  }
  55% {
    transform:rotate(35deg) scaleY(1) translate(0px, 0px);
    height: 15px;
  }
  80% {
    transform:rotate(35deg) scaleY(1) translate(0px, 0px);
    height: 15px;
  }
  100% {
    transform:rotate(35deg) scaleY(1) translate(0px, -15px);
    height: 0px;
  }
}
```
##### Keyframes `arrowB ` for `after`: 
```ruby:
@keyframes arrowB {
  0% {
    transform:scaleY(0);
    transform-origin:50% 0;
  }
  20% {
    transform:scaleY(0);
    transform-origin:50% 0;
  }
  45% {
    transform:scaleY(1);
    transform-origin:50% 0;
  }
  55% {
    transform:scaleY(1);
    transform-origin:50% 100%;
  }
  85% {
    transform:scaleY(0);
    transform-origin:50% 100%;
  }
  100% {
    transform:scaleY(0);
    transform-origin:50% 100%;
  }
}
```
Done! :innocent:
Ahhhhh... It's so simple...  :hugging::hugging::hugging::hugging:
![aniamtion.gif](https://qiita-image-store.s3.amazonaws.com/0/316492/9cb8d0dd-cdd4-eacf-e61c-b6c13ef9e2a4.gif)
VMWare をパブリッククラウドに移行するなら

主なPublicクラウドのVMWare対応状況をまとめてみました
(2018年11月現在)

## VMware Cloud on AWS
AWS基板上にある物理サーバを専有で契約し、VMWare環境を稼働させるため、自社のオンプレミスにあるVMware環境と同じ操作感覚でクラウドサービスを利用できる。

2018年11月12日 から東京リージョンでの提供を開始

## VMware virtualization on Azure

Azure のベアメタルサーバにハイパーバイザを乗せる
基本的にはAWSと同様
Migrationのための仕組みとして無料の移行ツール「移行プロジェクト(Azure Migrate)」がある

現在は米国リージョンのみのサポート

## GCP
手動でエクスポート・インポート
サービスとしては提供していない
(手順はガイド有　リンクは[こちら](https://cloud.google.com/compute/docs/images/import-existing-image?hl=ja))
Mojaveで強化された、ユーザープライバシー保護機能 の設定をリセットする

##あのウインドウもう一回見たいの！
Mojaveからは、マイク、カメラへのアクセスもユーザの許可が必要になりました。iOSみたいですね！
プライバシーに配慮するのは良いことだとは思います。
一方で、マイク、カメラを利用するアプリの開発をしてると、この許可リスト自体を一旦クリアにしてから、もう一度 "許可する" っていう画面を出したくなったりしませんか？？

僕はあります、ありました！！

マニュアル作るんだってさ〜。へーそうですか。。

##前置きは良いからやり方を
プライバシーの保護機能 は TCC(Transparency Consent and Control) という名前がついてるようで（知りませんでした！）
リセットするには、ターミナルから コマンドをたたけばOKでした。

~~~
tccutil reset <プライバシー項目名>
~~~

プライバシー の項目名は下記を。Camera や Microphone もありますね

~~~
Accessibility
AddressBook
All
AppleEvents
Calendar
Camera
Facebook
LinkedIn
Liverpool
Location
MediaLibrary
Microphone
Photos
PhotosAdd
PostEvent
Reminders
ShareKit
SinaWeibo
Siri
SystemPolicyAllFiles
SystemPolicyDeveloperFiles
SystemPolicySysAdminFiles
TencentWeibo
Twitter
Ubiquity
Willow
~~~
エンジニアとモデリングツール

#対象
・Microsoft Visioが使えない環境にいる
・でも資料はいっぱい作らなければならない
・cacooでUML描いている

#モデリングツール(＋ドローツール)の必要性
お客様の食指を動かすためにはインパクトかつ簡潔な資料作成がエンジニアには求められる。それに時間をかけていたら本来の設計に時間が取れなくなる。提案や設計には必須だと思っているが、なかなかいいツールに出会えていなかった。会議資料やメンバーへの伝達、クラス設計の検討には欠かせないツールだと思う。
頻繁にお客様と打合せする必要があって、毎回見栄えの良い資料を時間かけて作っていたら、本来の設計や開発に割り当てる時間が減ってしまう。エンジニアはプログラムや設計、コミュニケーション能力も大事だけど資料作成の能力も必要だと思う。

#Microsoft Visioという選択肢
有料だけあってかなりいい。10年くらい前MSDNサブスクリプション入っていた頃は、これだけで設計周りの資料は作れていた。プレゼンテーションもPowerPointとPhotoshop、Illustrator で不自由なかった。プレゼンテーションソフト、写真加工、ベクタイメージソフトがあるのならこの組み合わせで十分な生産性が確保できる。自由度も制限がないのでお勧め。イラレは本当に重宝する。

#有料ツールが使えない場合
有料のドローイングツールが使えない時はどうするか。出向とかしているなら現場の環境も関係してくる。
長い間Visioが使えない現場にいたのでAmaterasやastahも使ってみたけど、機能の割にもっさりしていて使いづらい。あと、これだけのためにEclipse入れたりするのもめんどくさい。ただでさえEclipseは重いのに、全ソース80万行、クラス数1000超えるC++のUMLなんて誰も描きたくない。

お客様の了承を頂くことができたので色々探してみてcacooに落ち着いていました。そこそこ軽いし一通りの機能はあるのでそれなりの図は作れる。ブラウザだけあればインストール不要ですぐ作成できる。しかし、無料でできることにすぐに限界を感じたので自腹で有料プランに切り替えて仕事することに。

#Excel方眼紙大好きな老害SE
モデリングツールの有用性を理解していない老害SEがいる現場だと「そんなツールにお金かけるの？Excelでいいでしょ？」とか平気で言ってくる。大手SIerによくみられる日本独特のExcel方眼紙にシコシコと仕様書や図を描いている風景を見ると、こんな作業に高い金払って若い有能なエンジニアの可能性を吸い取っていると思うと残念でならない。

#cacooはクラス図が作りにくい
これが一番ストレスの貯まる作業だった。設計段階でクラス図に落とし込む場合は何度も修正が必要なので、cacooで製図していたら時間がかかってしまう。ノートやエディタである程度、設計をまとめてからでないと作る気になれない。
スキルの低いおっさんの設計したクラスの指摘なんかは口頭のレビューで説明しても理解できないので、cacooでUML描いて説明していたけどそれを作るのすらストレスになってしまう。

#cacooのいいところ
これは豊富なテンプレートと図形。AWS構成図やプレゼン用の資料に使う図形はそこそこ短時間で作成できる。かゆいところに手が届かない時もあるが、そこは他のツールで十分まかなえる。AWS構成図やネットワーク配置図はcacooは便利。モバイルアプリのワイヤーフレームも直感的にどんどん作れるので生産性は高い。あとbacklogと連携もできるので、そこはまだ使える。でも、backlog自体どうなのかと思うところはある。

#UML描くならdraw.io
最近draw.ioを使ってみている。UMLやクラス図はcacooとは比べ物にならないくらい生産性が高い。Google Driveとの連携も申し分ない。UMLやER図、定型的なお絵かきをするならdraw.ioが優れている。残念な部分は使える図形が少しダサい？このあたりはcacooで清書すればいいのかもしれないが、素早く図を描いてチームに展開する必要があるならdraw.ioはかなり使える。

#まとめ的なアレ
テンプレートも豊富でカラフルなインパクトのある図が作れそうなので、しばらくはcacooとdraw.ioの2つでやってみようと思う。ドキュメントは使う用途、趣旨でツールを使い分けるのがいいと思う。draw.ioを色々使い倒して、いけると判断したらcacooは解約でもいいかもしれない。
初学者のためのPython講座　オブジェクト指向編4　初期化メソッド

# インスタンスの初期化

ここまでは、**インスタンス生成後**にクラス変数やインスタンス変数の更新・追加する方法などを学習しました。しかし、**クラス変数はすべてのインスタンスで共通の変数、インスタンス変数はそのインスタンス固有の変数であるべき**、という点からも変数は慎重に扱わなければならず、このようなプログラムはあまり推奨されません。通常は、**初期化メソッド**という特殊なメソッドを使ってインスタンス変数を定義します。


## 初期化メソッド
Pythonでは**初期化メソッド**と呼ばれる、初期化のための特殊なメソッド`__init__()`が用意されています。初期化メソッドは`init`の前後に`__`(2つのアンダーバー)を付けて記述します。

```【書式】初期化メソッド.py
def __init__( self, 引数2, 引数3,…):
    初期化の処理内容
```

初期化メソッドは**インスタンスが生成されるとき自動的に呼び出されます**。
まずは、初期化メソッドがどのように実行されるか、確認してみましょう。

```initsample.py
class Sample:
    # メソッドを定義する
    def __init__(self):
        print("インスタンスが生成されました")

# インスタンスを生成する
s1 = Sample()
```

実行してみましょう。

```
インスタンスが生成されました
```

このように、処理内容は通常のメソッドと同じように定義することができますが、初期化メソッドはインスタンス生成時に呼び出され、その処理が実行されます。

## クッキークラスに初期化メソッドを定義する
先ほどはクッキーインスタンス**生成後**にクッキーの味`taste`データを設定していましたが、クッキーを生成するたびに、いちいちデータを呼び出して設定するのは手間がかかるうえに、設定を忘れる可能性もあります。また、データの種類が増えた場合はさらに大変でしょう。
そこで、インスタンス**生成時**に呼び出される初期化メソッドを利用して、**インスタンス変数の初期値**を設定します。これによって、生成時に各インスタンスへ固有のインスタンス変数を与えることができます。

では、初期化メソッドを使ってクッキークラスを定義しましょう。

```cookie_init.py
class Cookie:
    # クラス変数を設定する
    name = "クッキー"
    # 初期化メソッドでインスタンス変数を定義する
    def __init__(self, taste):
        self.taste = taste
    # メソッドを定義する
    def bake(self):
        print(self.taste, self.name, "が焼けました")

# インスタンスを生成する
cookie1 = Cookie("プレーン")
cookie2 = Cookie("チョコ")
cookie3 = Cookie("チョコチップ")

# インスタンスを指定してメソッドを呼び出す
cookie1.bake()
cookie2.bake()
cookie3.bake()
```

実行してみましょう。

```
プレーン クッキー が焼けました
チョコ クッキー が焼けました
チョコチップ クッキー が焼けました
```

初期化メソッドによって、クッキーインスタンスの生成と同時に各クッキーの味`taste`データが設定できました。

## メソッドでインスタンス変数を使う
メソッド定義の`self.taste`、`self.name`という記述に注目してみましょう。 
メソッド定義では`self`を記述することで**インスタンス自身**を参照します。つまりメソッド定義の`self.変数名`は**インスタンス変数**をあらわしています。 
初期化メソッドの以下の書式と、インスタンス変数を設定する書式を比較してみましょう。 
 
```【書式】初期化メソッドでインスタンス変数を設定する.py
def __init__(self, 引数2):
    self.インスタンス変数名 = 引数2
```

```【書式】インスタンス変数を設定する.py
インスタンス名.インスタンス変数名 = 値
```
 
2つの書式を比べると、初期化メソッドでインスタンス変数を設定していることがわかります。今回の場合だと、`cookie1`インスタンス生成時には引数`プレーン`が渡され`cookie1.taste = "プレーン"`が実行されることになります。**メソッド定義でインスタンス変数を呼び出す書式**`self.変数名`はとても**重要**なのでよく覚えておきましょう。 
ちなみに`self.taste = taste`の右側のように、**引数を変数名と同じにする必要はありません**が、**慣習的**にこのように記述します。 
また、初期化メソッドで設定する変数はインスタンス変数であって、**クラス変数ではありません**。例えばクッキークラスの変数として`Cookie.taste`を呼び出そうとしても、存在しないためエラーになります。 
 
 
### なぜインスタンスの初期化が必要か
初期化メソッドを使うメリットは先述の通りですが、実際にプログラム上でオブジェクトを生成する場合、必要となるのが**メモリ上の空領域**です。言い換えると、クラスを基にした実際の値としての**データ(インスタンス)を入れる領域を確保する**ことが、インスタンスの生成です。メモリ上にインスタンスの領域が割り当てられることで**実体をもった**といえるのです。 
ただし、領域を確保しようとしても、何も無い事を意味する**null値**や**0**のデータが入っていたり、**メモリ上の前のデータ(ゴミ)**がそのまま残っていることもあります。そこで、必要になるのが**初期化**です。その領域を使える状態にするため、期待している値で上書きしておく必要があります。

***
[初学者のためのPython講座　オブジェクト指向編1　オブジェクト指向とは](https://qiita.com/kotakahe/items/9de3b515f8faf01510f0)
[初学者のためのPython講座　オブジェクト指向編2　クラスとインスタンス](https://qiita.com/kotakahe/items/3de8d471ea871b0a7024)
[初学者のためのPython講座　オブジェクト指向編3　メソッド](https://qiita.com/kotakahe/items/3360898ff84c2c141a1b)
[初学者のためのPython講座　オブジェクト指向編4　初期化メソッド](https://qiita.com/kotakahe/items/db3e9fa9d547bb6e9014)

随時追加予定
初学者のためのPython講座　オブジェクト指向編3　メソッド

# メソッドを定義する
メソッドとは、オブジェクトに対する何かしらの操作、または、オブジェクト自身が備えている固有の機能と捉えられます。
メソッドの定義は通常の関数と同じようにdef文を使って定義しますが、class文の下にあり、第1引数に必ず`self`を指定する、という点が関数の定義と異なります。この`self`はインスタンス自身を表す引数ですが、まだどういうことか理解する必要はありません。今はメソッド定義の決まりごととして覚えておきましょう。

```【書式】メソッドの定義.py
class クラス名:
    def メソッド名(self, 引数2, 引数3,…):
        処理内容
```

また、インスタンスを指定してメソッドを実行するには以下の書式で記述します。メソッドを呼び出すときは第1引数`self`は不要です。引数に入れる値は、`self`を飛ばして2つ目以降の引数に割り当てられます。


```【書式】インスタンスにメソッドを実行する.py
インスタンス名.メソッド名(引数2, 引数3,…)
```

ここでは例として簡単なメソッドを定義しましょう。

```method_sample1.py
class Sample:
    # メソッドを定義する
    def sum_method(self, a, b):
        print(a + b)
# インスタンスを生成する
s1 = Sample()
# インスタンスを指定してメソッドを呼び出す
s1.sum_method(2, 3)
```

`self`の部分を除けば、通常の関数の定義と変わりないことがわかります。実際に、クラスとインスタンスを作成せずに、メソッドではなく関数で記述すると以下のようになります。

```method_sample2.py
# 関数を定義する
def sum_func(a, b):
    print(a + b)
# 定義した関数を実行する
sum_func(2, 3)
```

このように、書式はメソッドも関数もほとんど違いがありません。では、なぜメソッドと関数を使い分けるのか？メソッドの利点は何か？
一般的に、小規模なプログラムでは関数、大規模なプログラムではメソッド(クラス)を使用するほうが良い、とされています。現時点でその違いを理解するのは難しいかもしれませんが、今後この違いを意識しながら学習していくことで、オブジェクト指向への理解がさらに深まるでしょう。

***
[初学者のためのPython講座　オブジェクト指向編1　オブジェクト指向とは](https://qiita.com/kotakahe/items/9de3b515f8faf01510f0)
[初学者のためのPython講座　オブジェクト指向編2　クラスとインスタンス](https://qiita.com/kotakahe/items/3de8d471ea871b0a7024)
[初学者のためのPython講座　オブジェクト指向編3　メソッド](https://qiita.com/kotakahe/items/3360898ff84c2c141a1b)
[初学者のためのPython講座　オブジェクト指向編4　初期化メソッド](https://qiita.com/kotakahe/items/db3e9fa9d547bb6e9014)

随時追加予定
初学者のためのPython講座　オブジェクト指向編1　オブジェクト指向とは

## はじめに
Pythonの学習教材を作成することになって、これを書いています。
とはいえ、私自身プログラミング経験ゼロ、初めて触れる言語がPythonです。
書籍やネット、学習サイト等いろいろ調べながら書き進めていますが、自分では正解がわからない！ということで、ぜひ皆様のコメントをいただきたく、ここに公開することにしました。


## 対象
* 初めてのプログラミング言語にPythonを学習する
* 基礎（条件分岐、ループ、配列、関数など）は習得済み
* 「オブジェクト指向」はこれから

という人を対象にしています。
そのため、あまり深い内容には触れられませんが、できる限りわかりやすく、誤りがなく、誤解を与えない表現となるように心がけています。また、上記の理由から、他の言語との比較もしていませんのであしからず。

***
ここからが本文

# オブジェクト指向とは

オブジェクト指向とは、単にプログラムの文法や手順のことではなく、プログラムをどう作るか、という考え方にあたります。直訳すると、**オブジェクト**は**「モノ」**、**指向**は**「〜を中心に」**、**オブジェクト指向**とは**「モノ（オブジェクト）を中心にした」**という意味になります。 

オブジェクト指向プログラミングの基本的な考え方は、**プログラムの操作手順よりも操作対象に重点を置き、オブジェクトという単位でプログラムを捉えること**です。プログラムにおける一連のデータや関数などは、オブジェクトまたはオブジェクト間の関係として表されます。機能ごとに複数のオブジェクトを作り、相互作用させることでプログラムを構築していく手法です。

一般的にプログラムが大規模になるほど、その内容をすべて把握することは難しくなります。楽にプログラムを組み立て、修正できるように、オブジェクト指向という考え方が持ち込まれました。現在では、多くのプログラミング言語がオブジェクト指向を基本概念として開発されており、Pythonもまた、オブジェクト指向のプログラミング言語です。

### オブジェクトとは
オブジェクト指向のプログラムでは、関連する**データ(属性)**の集合と、それに対する**操作(メソッド)**を**オブジェクト**と呼ばれる一つのまとまりとして管理します。

もう少し具体的に**自動車**を例に、オブジェクトについて考えてみましょう。
自動車には、**タイヤ、ボディ、エンジン**があり、**アクセルを踏む(進む)、ブレーキを踏む(止まる)、ハンドルを切る(曲がる)**といった方法で操作されます。
タイヤやボディ、エンジンなどはより良い素材や性能のものに変更すれば、スピードが上がりますが、これ自体が何か動作を引き起こすものではありません。また、アクセルやブレーキ、ハンドルを使った操作はどの自動車も共通しています。
つまり「自動車」オブジェクトは、**「タイヤ、ボディ、エンジン」**という**データ**と**「アクセルを踏む(進む)、ブレーキを踏む(止まる)、ハンドルを切る(曲がる)」**という自動車に対する**操作(メソッド)**の組み合わせによって定義できます。


### オブジェクト指向のメリット

自動車を運転する場合、運転手は自動車の**複雑な内部機構がどのように動いているかを知る必要はなく**、ただ運転方法さえ知っていれば、自動車の運転ができます。また、**別の車種**の自動車に乗り換えたとしても、**あらためて運転方法を学ぶ必要はなく**、すぐに運転が可能です。
また、自動車を製造する場合も、**設計図を基に量産したり、互換パーツを使い回す**ことができます。


オブジェクト指向においても、**操作されるオブジェクト(自動車)の変更に対して、操作する側(運転手)は影響を受けない**というメリットがあります。また、オブジェクトという単位で扱うことで、**機能をまとめ、容易に量産・再利用ができます**。さらに、オブジェクトは**内部状態が保たれる**ため、バグの発生を最小限に抑えることが可能です。こうした利点から、多くのプログラミング言語がオブジェクト指向を取り入れています。


***
[初学者のためのPython講座　オブジェクト指向編1　オブジェクト指向とは](https://qiita.com/kotakahe/items/9de3b515f8faf01510f0)
[初学者のためのPython講座　オブジェクト指向編2　クラスとインスタンス](https://qiita.com/kotakahe/items/3de8d471ea871b0a7024)
[初学者のためのPython講座　オブジェクト指向編3　メソッド](https://qiita.com/kotakahe/items/3360898ff84c2c141a1b)
[初学者のためのPython講座　オブジェクト指向編4　初期化メソッド](https://qiita.com/kotakahe/items/db3e9fa9d547bb6e9014)

随時追加予定

Markdown難しい。
laravel5.4で古いコントローラーが参照されてしまう現象

##現象
`SampleController.php`というファイルを参照して欲しいのに、同ディレクトリ内の`SampleController_20181111.php`というバックアップのためにとっておいた古いファイルを参照してしまっていました。

ステージング環境で起きた現象なのですが、ローカル環境で変更した内容をステージング環境へ適用する前に、ステージング環境にある`SampleController.php`をバックアップとして`SampleController_20181111.php`にリネームしておき、`git pull`で`SampleController.php`を持ってきたという状況です。
するとステージング環境での動きがおかしく、どうも変更した内容が反映されていないっぽいということに気付き（これに気付くまでも時間がかかりました…）、`SampleController_20181111.php`を削除して`SampleController.php`のみの状態にしたのですが、`SampleController_20181111.phpというファイルがありません`みたいなエラーになって、なんでそっち参照しようとするの？ってなりました。


##原因
<del>キャッシュされている…っぽい？
けどよくわからないです…</del>
コメントしていただいたのですが、実ファイルを変更しても`/vendor/composer/autoload_classmap.php`が変更されてないとダメで、その不整合を`composer dump-autoload`で書き直してくれるということらしいです。
それが今回の原因っぽいです。

##対応
とりあえず`php artisan optimize`をしたら正しいファイルを読み込んでくれました。
※コメントしていただいたのですが、`php artisan optimize`はversionによって何をやっているかが全然違うみたいなので注意です。

その後ネットで調べていて、`composer clear-cache`や`composer dump-autoload`で解決できるらしいです。私はまだ試していないですが。
参考1：[Laravel 5.4 using old controller in controllers directory](https://stackoverflow.com/questions/45010169/laravel-5-4-using-old-controller-in-controllers-directory)
参考2：[Laravel ClassLoader trying to load an old version of my model](https://stackoverflow.com/questions/23725610/laravel-classloader-trying-to-load-an-old-version-of-my-model)

1年以上同じ環境でやっていて今までもバックアップファイル作ったりしていたけれど、初めてのことだったので戸惑いました…。
git取り消しのメモ

## 間違ってステージングにあげてしまった！（ターミナル操作で全部 `git add .`みたいなの）
個人的解釈メモ
`git reset`で`git add`しちゃったもの＝ステージングにあげた操作を取りやめしたい的な
（ステージングにあがっているものを取り消す）

### 操作
`add`したファイルを取りやめ
`git rest path名`

例）
`src/components/user.js`を間違ってあげてしまった！場合は
`git reset src/components/users.js`とやる

### 全て取りやめしたい（`git add.`しちゃったものを全てステージングからさげる）
`git reset HEAD`　（HEADは小文字でもいける）
addをまるっと取り消す※HEADは省略可能みたい※

`$ git reset HEAD`
この操作は`git add`したものを取りやめるだけなので、変更点に関してはそのまま残る
Python（Jupyter）でmecabを動かすまで

## 参考URL
* [pythonによる日本語前処理備忘録](https://datumstudio.jp/blog/python%E3%81%AB%E3%82%88%E3%82%8B%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%89%8D%E5%87%A6%E7%90%86%E5%82%99%E5%BF%98%E9%8C%B2)
* [Word２Vec, MeCab, ComeJisyo で病気の症状類似語を出してみた](https://qiita.com/quvo/items/9ef250d58971eadf6e1a)
* [UbuntuでmecabにComeJisyo（医療用語辞書）を追加する（コマンドのみ）](https://qiita.com/tatsuya-takahashi/items/711f55587067ffcccf99)
* [今更ながらPythonとMeCabで形態素解析してみた](http://tech.innovation.co.jp/2017/07/28/mecab.html)

## mecab
日本語形態素解析エンジンのデファクト。
先人の残したブログ記事が多数存在しているため、僕のような初心者はこれを使うことをお勧めします。

ただし、設定時に色々と手こずったので動かすまでの手順をまとめます。

## 環境

* os
    * macOS 10.13.6
* シェル
    * zsh
* Python
    * 3.6.4
* 環境分離ツール（[詳しくない方はこの記事がおすすめ](https://qiita.com/shibukawa/items/0daab479a2fd2cb8a0e7)）
    * pyenv
    * pyenv+virtualenv

## 1.mecabをjupyterで動かす
Python環境が正しく構築できてないと、ここで1週間くらい溶かします。（→僕がそうでした）
特にAnacondaで環境を作ってる方。
（さらに、何もわからずにブラウザからAnacondaを落として適当にインストールした方→これも僕です）
当てはまる方はAnaconda環境を爆破して、
[この記事を参考に](https://qiita.com/shibukawa/items/0daab479a2fd2cb8a0e7)、再度環境を作り直すことをお勧めします。
（→これも僕です。環境作るのは1日もかからないです）


### mecabと辞書をインストール
```zsh:zsh
#mecabをインストール
brew install mecab
#mecabの辞書をインストール
brew install mecab-ipadic
```

### mecab-python3をインストール


```zsh:zsh
#mecab操作用のpythonライブラリをインストール
pip install mecab-python3
```

### 試しに動かしてみる

```python3:python
import MeCab

tagger = MeCab.Tagger('')
print(tagger.parse('私は貝になりたい'))

#私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
#は	助詞,係助詞,*,*,*,*,は,ハ,ワ
#貝	名詞,一般,*,*,*,*,貝,カイ,カイ
#に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
#なり	動詞,自立,*,*,五段・ラ行,連用形,なる,ナリ,ナリ
#たい	助動詞,*,*,*,特殊・タイ,基本形,たい,タイ,タイ
#EOS
```
問題なく動いてそうです。
通常の用途であればこれで完成！

## 2.mecabに辞書を追加する
mecabでは、利用する辞書を変更することが可能。
今回は医療用の辞書、ComeJisyoを入れてみる。

### ComeJisyoをダウンロード
ここからダウンロードしてください。

### ComeJisyoのCSVを加工する
### csvから辞書を生成する
### 所定のディレクトリに辞書を格納する
### mecab設定ファイルに追加した辞書のパスを追加する
### 動かしてみる
anacondaコマンドチートシート


#環境
macOS Mojave 10.14
#コマンド一覧

###仮想環境作成
```
conda create -n name python=version anaconda
```
name:任意の仮想環境名
version:pythonのバージョンの指定

###作成した仮想環境一覧の表示
```
conda info -e
```

###作成した仮想環境に入る
```
source activate name
```
name:作成した仮想環境名

###現在の仮想環境から出る
```
source deacrivate
```

###仮想環境の削除
```
conda remove -n name
```
name:削除する仮想環境名

###anacondaのアップデート
```
conda update conda
```

###現在の仮想環境のパッケージ確認
```
conda list
```

###インストール可能なパッケージの検索
```
conda search package
```
package:パッケージ名

###パッケージのインストール
```
conda install package
```
package:パッケージ名

###パッケージのアップデート
```
conda update package
```
package:パッケージ名

###全てのパッケージのアップデート
```
conda update --all
```

###パッケージのアンインストール
```
conda uninstall package
```
package:パッケージ名


###使われていないパッケージ及びキャッシュの削除
```
conda clean --all
```
###pythonのアップデート
3.6.0や3.6.1から3.6.2にする場合

```
conda update python
```
3.5系や3.6系から3.7系へアップデートする場合

```
conda install python=3.7
```
lgtm.in 終わるってよ

> LGTM.in is shutting down on 2018-10-01. I've been busy with a lot of things, and cannot spend time on this. The source is available on github.com/rahulsom/lgtmin and can be used to spin up a similar service. If you're interested in purchasing the domain and continuing to run this service, let me know, and we can work something out.


とのこと。
10月1日に終わると言いつつまだ生きている

近いうちに消滅するか、他の運営が引き継ぐかだと思います。
テーブル間の依存関係について、名前から推測してくれるのはありがたいけれど、どこまでやってくれているのか


##目的・前提
Ruby on Railsではテーブル作成に使うマイグレーションファイルにテーブルの依存関係を数行追加するだけで
簡単に依存関係が構築できます。しかし、僕はいつもチュートリアルを読むとき、「どこまでがRuby on Railsで推測してくれるのか」についてわからなくります。
今回は、マイグレーションファイルで使用する.references型についてまた不明点がでてきましたので、現時点で調べた結果を記載します。

Railsチュートリアル「13.1.1 基本的なモデル」より
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-the_basic_model
内容としては、
・テーブル「Users」で管理されているユーザが、ツイッターのようなテキストを投稿する。
・テーブル「Microposts」でユーザが投稿したテキストを管理する。
なのですが、Micropostsで管理されるテキストがどのユーザが投稿したものなのかを管理吸うために２つのテーブルを紐付ける必要があります。
そのために、「Microposts」にあるカラム「user\_id」は「Users」テーブルの「id　」カラムと紐付けることにします。という処理が必要になります。

下記２テーブルの関係について記載します。
<small>#図1, 図2はいずれも[Ruby on Rails チュートリアル: 実例を使って Rails を学ぼう](https://railstutorial.jp/)より引っ張ってきています。</small>

![image.png](https://qiita-image-store.s3.amazonaws.com/0/266073/e07cc0af-4c65-c2a2-4156-6c5d3a88f1f4.png)
図１．Usersテーブル

![image.png](https://qiita-image-store.s3.amazonaws.com/0/266073/1d53eb5c-cc32-594b-a125-2e84c9dd6bb7.png)
図2．Micropostsテーブル

##コード
```Userモデル.rb
class User < ApplicationRecord
  has_many :microposts, dependent: :destroy
  #micropostモデルに依存されています、という記載
  #userモデルのレコードを削除したらそれに紐付いたmicropostモデルの記事も削除される
end
```
```Micropostモデル.rb
class Micropost < ApplicationRecord
  belongs_to :user
  #userモデルに依存します、という記載
end
```

```マイグレーションファイル.rb
class CreateMicroposts < ActiveRecord::Migration[5.1]
  def change
    create_table :microposts do |t|
      t.text :content
      t.references :user, foreign_key: true
      #userモデルに外部制約キーを付ける

      t.timestamps
    end
    add_index :microposts, [:user_id, :created_at]
    #user_idにindexを付ける
  end
end
```
###Micropostモデルに記載のbelongs_to :userについて
belongs\_to関連付けを行なうと、他方のモデルとの間に「1対1」のつながりが設定されます。
"belongs\_to :user"と記載すれば、Usersモデルのテーブル「Users」でデフォルトで必ず作成される「id」に依存する、とRailsで判断されます。
依存するとは、例えば、テーブル「Users」の「id」が「１０」であるユーザが削除されると、そのユーザが投稿したテキストも自動的に削除される、ということです。
この関連付けのためにはUserモデルの方でも記載が必要です。
それが"has\_many :microposts"です。

###Userモデルに記載の"has\_many :microposts"について
>has\_many関連付けが使用されている場合、そのモデルのインスタンスは、反対側のモデルの「0個以上の」インスタンスを所有します。
>[「2.3 has_many関連付け」](https://railsguides.jp/association_basics.html#has-many%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91)より

この場合の"反対側"とは"belongs\_to :user"を記載したMicropostモデルを指します。つまり
・belongs\_to :user　：　Userモデルに依存します。
・has\_many :microposts　：　たくさんのMicropostモデルを所有します。
という親「Userモデル」、子「Micropostモデル」の関係がこれで築かれます。

"dependent: :destroy"によって、もしUsersテーブルにあるユーザが削除されたとき、そのユーザが作成したMicropostの記事は連動して削除されます。

###t.references :user, foreign\_key: trueについて
".references"を記載すると”指定したモデル名\_id”のカラムが追加されます。
この場合":user"と記載しているので、カラム"user\_id"が追加されます。
同時にuser\_idにはindexが付与されます。なので単にindexを付与するための下記の記載は不要となります。

```
index: true
```
"foreign\_key: true"を記載すると指定したモデル名\_idに外部キー制約を付与します。つまりこのuser\_idからむはモデル「User」で作成されたテーブル「Users」のデフォルトで必ず作られる「id」を参照して紐づけます。

###残った課題
上記でUserモデルとMicropostモデルの依存関係の構築は完了しましたが、.referencesで指定した際に自動的にindexが付与されのであれば

```
add_index :microposts, [:user_id, :created_at]
```
の行がいらないはずです。これはRailsチュートリアルの後の章で説明される複合キーインデックスを扱うために必要とのことです。
それについて、覚えていたら後から記載しようと思います。
Qiitaにコメントを投稿する前にHRTを確認出来るChrome拡張機能をつくった

この記事は[個人開発 #2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/private-developmen2)の1日目です。
さっそく糞アプリでごめんね！

# なぜ作ったのか

時折、言いたいことは分かるがもう少し工夫すればお互いに良い気分になれるようなコメントを見かける
時折、自分自身が配慮に足りないコメントをする傾向があるため（マウンティング？好戦的？）

# 作った物
<img width="793" alt="スクリーンショット 2018-11-30 19.47.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/180411/30ea72df-243f-f9e0-0722-31846e0012d0.png">
こういう入力欄を
<img width="816" alt="スクリーンショット 2018-11-30 19.47.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/180411/04206fa7-1b3c-f6f0-023c-4fb0127fae0f.png">
こんな感じにするChrome拡張です

TODO (URLを乗せておく)

11日30日現在、chromeウェブストアのデベロッパーダッシュボードから
拡張機能の登録(zipアップロード）ができない不具合に遭遇中のため掲載できず・・・・


# 使い方

コメント欄にHRTを自己チェックできる欄を追加します。
コメントを投稿するまえに一呼吸置いて書いたコメントを見直す時間を作ります


# 問題点

この機能が欲しいと思えるような人は心にHTRが宿っているのでたぶん不要
そして心ない人はこれを必要としないので不要
無理矢理インストールさせることが出来ないので不要

つまり産廃を作ってしまったと言うことだ。


# ポエム

自分がマーケットをよく知らないのに聞きかじった事をベースにサービスを作り
こういうの作ったから便利だから使えよ　みたいな感じでやってしまう事が多い気がする。
ほとんどの場合、自己満足で終わる。そのため途中までつくって放置する事が多い。
しかし、形にして公開する所までやるようになったのは成長したのか？
PowerBIのKPIについてまとめてみた

# はじめに
エンジニア？アナリスト？サイエンティスト？歴5ヶ月めの新卒社員が最近学んだことをちょっとずつまとめてみたもの。今回は記念すべき第7弾です、そうラッキー7！！偶然ではありますが、　ここ最近好きな名前もラッキー7なんです。そしてただいまひとりAdvent Calendar中！！あくまで備忘録としての投稿がメインなので、拙い記事ではあるんですが、気になる記事は見ていただけると嬉しいなぁ。
なお、直近3回の記事はこちら。第5弾からが今回のAdvent Calendarにあわせて書き始めたものです。
[第4弾](https://qiita.com/icchy_sh33p/items/dcaa650f57687c9bbaec)
[第5弾](https://qiita.com/icchy_sh33p/items/c9dccc1bffcdbf7f5c8c)
[第6弾](https://qiita.com/icchy_sh33p/items/03e09a14f0c0bad9c823)

ちなみに今回はあまり開発、分析系ではなくちょっとビジネス的要素の方が強いかも。

# PowerBIを通じて得られた知識
- KPI・・・**主要業績評価指標（Key Performance Indicatorの略）** のこと。組織やチームで設定した最終的な目標を達成するための、過程を計測・評価する中間指標
- どういうときに使用するか
    - 進行状況（目標より進んでいるのか／遅れているのか）を測定するとき
    - 目標到達までの距離（どの程度進んでいるのか／遅れているのか）を測定するとき
- 必要になるもの
    - 値に対して評価される基本メジャー
    - ターゲットとなるメジャー、または値
    - 基準となるしきい値、あるいは目標

# KPIとKGI
- KGI・・・**重要目標達成指標（Key Goal Indicatorの略）** のこと。企業全体の戦略的な目標設定
- イメージとしては、
    - KGI→会社全体の最終目標（戦略目標）
    - KPI→会社の最終目標（KGIとして設定したもの）に到達するための中間目標（先述の決定）
という違いがある。→KPIを見たうえで**具体的なアクションを決めていく**必要がある

# PowerBIにおけるKPI
- KPIの達成の程度を視覚的に確認するためのツール
    - インジケーター・・・値として見たいものを設定（売上額、グラフにおける縦軸）
    - トレンド軸・・・時間軸を設定（グラフにおける横軸）

    ![](https://i.imgur.com/aoLbS09.jpg)

    - なお、図の数字は
        - 現状の達成の具体的数値
        - 達成基準の数値
        - 達成基準に対してどの程度現状足りていないのかを示したパーセンテージ
        を示している。
        
- ビジュアルの設定→ペイントローラーアイコンを押すと、設定画面に
    - インジケーター・・・インジケーターの表示単位と小数点以下の表示桁数を設定
    - トレンド軸・・・[オン] に設定すると、トレンド軸がKPIビジュアルの背景として表示される
    - 目標・・・[オン] に設定すると、ビジュアルに目標、および目標からどの程度離れているかがパーセンテージとして表示される
    - その他、ビジュアルについて設定できる。画面は下のような感じ
    
    ![](https://i.imgur.com/aJVswk3.png)

- 使用することによるメリット
    - 確認したい数値の推移と、現状の総合計、目標までの未達成の程度をKPIひとつで確認できる
    - 複数の視覚化ツールで本来設定するものがひとつで済むため、ほかのデータ表示にその分のスペースをまわすことができる
    - 色の設定で状況によって色が変化するように設定が可能→状況に対する数値的評価が見やすい

- 使用することによるデメリット
    - ひとつのデータの中に見る情報が多く入っている
        - 人によってはどこをどうやって見ればよいのかわからない→見方についてのレクチャーが必要？
        - 見るべき情報が精査されきれていないのでは？

# 感想
KPIについては、正直PowerBIで見るまでは恥ずかしながらあまり聞いたことのない単語だったので、これを機に調べてみて社会人として成長できたかなぁなんてポジティブシンキング。
ただ、今回はちょっと毛色が違う記事になっちゃいました。Advent　Calendar的にはこれ、オッケーなのかな？まあ、試行錯誤も成長の上では大事でしょう！**きっと、きっと！！！！！！！** ←しれっと強調
また明日も更新できるよう、業務も勉強もしっかりやっていきまーす^^
開発初心者の為の、コマンドプロンプト便利帳（Windows）

#あの黒い画面を使いこなす！
開発の現場で避けて通ることのできないもの。
それはコマンドプロプトの画面です。
私が社会人になった2001年ごろは、LAN環境を変えるたびにデフォルトゲートウェイの設定を直して再起動するという不便な状態だったので、しばしばコマンドプロンプトの画面を開きpingやipconfigといったコマンドを打っていました。
しかし開発となるとこれでは足りません。
そこでこの記事では開発初心者にまずは知っておきたいコマンドプロンプトの使い方を書かせていただきます。
（たいそうなことを言っているようで、実は自分用のメモです）

#コマンド編
| 　コマンド　 | 　内容　 |
|:----------------:|:-----------------|
|pwd |現在位置を示す|
|ls |現在のフォルダ内にある、ファイル、フォルダの一覧を示す。|
|ls <ディレクトリ>|＜ディレクトリ＞内にある、ファイル、フォルダの一覧を示す。|
|ls -la|lsで示される内容に対して、さらにファイルサイズ、権限等の詳細情報を示す。|
|cd |フォルダの移動。cdの後にパスを指定します。|
|cd .. |一つ上の階層に移動|


#ショートカット編
| 　ショートカット　 | 　内容　 |
|:----------------:|:-----------------|
| ALT + C |選択した個所のコピー|
| ALT + V |貼り付け|
| Ctrl + A |カーソルを先頭に移動|


これからもどんどん追加したいと思います。
Oracle10g→Oracle11gの移行で少しハマったので手順メモ

#はじめに
Oracle10gがある環境で、10g→11gのマイグレーション(移行)をしていた時になかなかうまく行かなかったので手順メモ

#作業環境
WindowsServer2008
Oracle10g

#その1:Oracle10gを完全に削除する
これをしないで11gをのんきに入れていたらうまく行かなかったです(今考えれば当たり前)
Oracleの削除はわりとめんどくさくて、ただアンインストールするとかじゃなくてレジストリ単位で削除する必要があります。

##前準備
以下の場所の確認
・ORACLE_HOME ディレクトリの場所
　→レジストリ、HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMEn\ORACLE_HOMEで確認可能(コンピューター名を指定して実行→regeditと入力でレジストリに飛べる)
・ORACLE 関連のディレクトリの場所

Administratorでログイン

##レジストリ削除
以下のレジストリを削除します。レジストリがない場合もあります(私の環境では半分くらいはなかったです)

```
　　1-1　□　HKEY_LOCAL_MACHINE\SOFTWARE\ORACLEキー

　　1-2　□　HKEY_LOCAL_MACHINE\SOFTWARE\odbc\odbcinst.ini\Oracle ODBC Driverキー

　　1-3　□　HKEY_LOCAL_MACHINE\SOFTWARE\odbc\odbcinst.ini\Oracle in <ORACLE_HOME名>キー

　　1-4　□　HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\<当該DSN名>キー

　　1-5　□　HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC Data Sourcesキー

　　1-6　□　HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Servicesの下の ORACLEで始まるすべてのキー

　　1-7　□　HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Applicationの下の ORACLEで始まるすべてのキー

　　1-8　□　HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstallの下の ORACLEで始まるすべてのキー

　　1-9　□　HKEY_CLASSES_ROOT をオープンし、HKEY_CLASSES_ROOT の下の ORA またはORCL から始まるすべてのキー

　　1-10　□　HKEY_LOCAL_MACHINE\SOFTWARE\Classes の下の ORA または ORCL から始まる全てのキー

　　1-11　□　HKEY_CURRENT_USER\Software\Oracle キー

　　1-12　□　HKEY_USERS\...\Software\Oracle キー
```

##環境変数削除
※環境変数をいじる前は絶対にテキストか何かにバックアップを取ること(備えあれば憂いなし)

・PATH:編集
→インベントリの下のJREのbin、および、削除対象のORACLE_HOMEのbin が、値として含まれている場合はこの値からそれらのみを削除するよう編集します。環境変数自体は削除してはいけません。

・CLASSPATH:編集
→削除をするORACLE_HOMEを含むPATHが、値として含まれている場合は、この値からそれらを削除します。CLASSPATH が Oracle製品にのみ構成されている場合は、環境変数 CLASSPATH 自体を削除することができます。

・JSERV:削除

・wv_gateway_cfg:削除

・OLAP_PATH:削除

・環境変数 TEMP で指定されるディレクトリにある OraInstall から始まるディレクトリ(例: OraInstall2018-11-45) を全て削除

##スタートメニューの削除
<system_drive>:\Winnt\Profiles\All Users\スタートメニュー\プログラム\Oracle 関連のアイコンを削除

##フォルダの削除
<system_drive>:\Program Files\Oracleを削除

##コンピュータの再起動
してください
その後、すべての ORACLE_HOME ディレクトリ、および ORACLE 関連のディレクトリを削除して、コンピュータの管理から、ORA_DBA グループを削除してください(私の場合はこれはありませんでした)

#その2:DB作成、ユーザー作成、インポート
その1でOracle10を完全に削除できていればDBは普通にインストールできます。

##ユーザー作成
sqlplusでログインする

```sql
 sqlplus hoge/hoge as sysdba
```

ユーザー作成

```sql
 >SQL create user hoge identified by hoge;
```

権限付与→それぞれ必要な権限を選んで付与してください

```sql
 >SQL grant dba to hoge;
 >SQL grant unlimited tablespace to hoge;
 >SQL grant create table to hoge;
 >SQL grant sysdba to hoge;
 >SQL grant create session to hoge;
 >SQL grant exp_full_database to hoge;
```

##インポート
```sql
 imp hoge/hoge file=D:¥xxxx¥xxxxx¥xxxx¥poipoi.dmp fully=y log=D:¥xxxx¥xxxxx¥xxxx¥poipoi.txt
```

##終わりに
作業メモなので多めに見て欲しいですが、明らかな間違えは編集リクエストお願いします！
window.open() の覚え書き

#内容
1.オプション
2.外部pdfファイル表示

#オプション
よく忘れがちなのでメモメモ

### アドレスバー非表示
```
location=no
```
### urlのみ非表示
```
hideurlbar=yes
```
### Doneボタン文言変更
```
closebuttoncaption=完了
```
### ナビゲージョンボタン非表示
```
hidenavigationbuttons=yes
```
### ズームインズームアウト
```
EnableViewPortScale=yes
```

# 外部PDFファイル表示
### iOSの場合
#### オプションなし
ソースコード

```
window.open('http://xxxx.xx.xx/xxx.pdf', "_blank", "");
```
実行結果
![ios_default.png](https://qiita-image-store.s3.amazonaws.com/0/175762/6dc2013c-5069-d055-7a3e-f8534cd8f296.png)

#### オプションあり
ソースコード

```
window.open('http://xxxx.xx.xx/xxx.pdf', "_blank", "location=no,toolbar=yes,EnableViewPortScale=yes,closebuttoncaption=完了,hidenavigationbuttons=yes");
```
実行結果
![ios_options.png](https://qiita-image-store.s3.amazonaws.com/0/175762/3ceba581-2ede-e3b7-9463-9dca0526b3b0.png)

### Androidの場合
#### オプションなし
ソースコード

```
window.open('https://docs.google.com/viewer?url=http://xxxx.xx.xx/xxx.pdf&embedded=true', "_blank", "");
```
実行結果
![android_default.png](https://qiita-image-store.s3.amazonaws.com/0/175762/ff51d4a3-72ce-6bd9-6189-f401577e9dbe.png)

#### オプションあり（PDF表示する際にGoogleDocViewを利用）
ソースコード

```
window.open('https://docs.google.com/viewer?url=http://xxxx.xx.xx/xxx.pdf&embedded=true', "_blank", "hideurlbar=yes,hidenavigationbuttons=yes");
```
実行結果
![android_options.png](https://qiita-image-store.s3.amazonaws.com/0/175762/c67bf27e-3f06-5105-9bec-6d2624ddf3e5.png)

以上です。
C#でAlexa用のテーブルにデータを追加。さらにやりなおし。（高レベルAPI編）

#はじめに
AWS SDK for .NETにはC#からDynamoDBにアクセスするAPIが含まれているわけですが、それには低レベルAPIと高レベルAPIの2つがあります。
低レベルAPIというのが、これまで説明してきたやつです。
格納するデータのタイプまで指定する必要がありました。

これに対して高レベルAPIというのは名前のとおり、詳細をさらに隠して使いやすくなっています。

#高レベルAPIを使ったデータの追加

高レベルAPIを使うと、データの追加を以下のように書くことができます。
データの構築には`AttributeValue`ではなく`Document（Amazon.DynamoDBv2.DocumentModel名前空間）クラスを使用します。

`AttributeValue`では指定しなくてはならなかったデータのタイプなどは`Document`クラスがうまく隠してくれていて、データ型を気にする必要なくインスタンスにキーとデータをセットで放り込んでいくだけでOKという形になっています。
すばらしい。


```csharp
            AmazonDynamoDBClient client = new AmazonDynamoDBClient(); //今回、裏方に回った。

            //目的のテーブルを取得
            var table = Table.LoadTable(client, tableName);

            //データはAttributeValueではなくDocumentを使って構築する。
            //attributes列に入れるデータの構築
            var attr2=new Document();
            attr2["sign"] = "ふたご座";//文字列でも
            attr2["number"] = 5;//整数でも
            //気にせずに入れられる。

            //挿入するレコードの構築
            var item=new Document();
            item["id"] = "testuser2";//id列
            item["attributes"] = attr2;//attributes列。上で作成したattr2を入れる。

            var result2= table.PutItemAsync(item).Result;
```

#実行結果
これを実行すると、DynamoDBのテーブルには以下のようなデータが追加されます。
`testuser2`というのが今回追加したデータです。
データの型が正しく指定されて格納されています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/e114e069-baf8-cd95-0d69-7c989910dc1e.png)


##おまけ
このDocumentクラスですが、どんな型でも突っ込めるのかなということで、`List<string>`をいれてみました。
以下のように。
これでテーブルにデータを突っ込むと、どういう形で格納されるのか見てみましょう。

```csharp
            //目的のテーブルを取得
            var table = Table.LoadTable(client, tableName);

            //データはAttributeValueではなくDocumentを使って構築する。
            //attributes列に入れるデータの構築
            var attr2 = new Document();
            attr2["sign"] = "ふたご座";//文字列でも
            attr2["number"] = 5;//整数でも
                               
            //気にせずに入れられる。

            //試しにList<string>を入れてみる
            var list = new List<string>
            {
                "hello1",
                "hello2",
            };
            attr2["list"] = list;

            //挿入するレコードの構築
            var item = new Document();
            item["id"] = "testuser2";//id列
            item["attributes"] = attr2;//attributes列。上で作成したattr2を入れる。

            var result2 = table.PutItemAsync(item).Result;

```

DynamoDB側はこのようになります。
「SS」というのは「文字列のセット（String Set）」という意味ですね。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/245438/253093bd-b8e7-e604-da7c-ee94b80db169.png)

何も考えずにどんどん突っ込んでいけるのはとても便利ですね。
PowerAppsをつかって爆速でQRコードを読み取ろう

# 概要

PowerAppsのスキャン関数を利用してQRコードを読み取るアプリを作ろうと思います。
Android版でのみ動作を確認しています。
※現在(2018/11/16)時点でプレビュー版の機能ですので何かしらの変更があり動かなくなる可能性がありますがあらかじめご了承ください。

# 注意
この記事はすでに古いものになっています。
現在は ios、Android用にバーコードスキャンコントロール（ボタン）が追加されましたのでそちらをご利用ください。

# 準備

- PowerAppsが利用できる環境 (Office365 F1以上　や プラン１、プラン２、試用版でも構いません)
- QRコード (お好きな文字列が入ったQRコードを用意しましょう。ない場合は以下をご利用ください）

![qrcode_201811161054.png](https://qiita-image-store.s3.amazonaws.com/0/183354/696c0fbb-ef47-d632-eef5-1db045fdbf7e.png)


# 動作イメージ

ボタン押下→QR読み取り→読み取った値が表示＋成功 or 失敗の通知

を実装します。

# 設定

アプリの設定→詳細設定→実験的な機能の中のバーコードのスキャン関数を有効にするをオンにします。

# 読み取り実装

まずは全体のイメージです。
![1.JPG](https://qiita-image-store.s3.amazonaws.com/0/183354/688e05d7-ed5f-094c-54d1-c2d39a57cb40.jpeg)

空のアプリを作成後ボタン、ラベルを挿入し名前をそれぞれ

| 変更前     |       変更後 |  
|:-----------------|------------------:|
| Label1             |              ScanLabel |  
| Button1           |            ScanButton | 

とわかりやすいように変更しました。

次にスキャン関数を ScanButton に対して実装します

ScanButtonを選択し、OnSelect式に対して次のような数式を実装します。

```
ClearCollect(
    hoge,
    ScanBarcode()
);
If(
    IsBlank(Text(First(hoge).Value)),
    Notify(
        "QR コードが読み取れませんでした",
        NotificationType.Error
    ),
    Notify(
        Text(First(hoge).Value),
        NotificationType.Information
    )
)

```

それぞれに関して上から説明します。

### ClearCollect

変数宣言です。この関数ではClear関数 の後に Collect関数が実装されます。
つまり今回の使い方だと、 hoge 変数に対して ScanBarcode関数の戻り値(結果)を挿入している形になります。

###  Clear
変数の中身を空にします。

### Collect
変数に対して値を追加します。

公式にわかりやすい例がありましたのでこちらをご覧ください。
![2.JPG](https://qiita-image-store.s3.amazonaws.com/0/183354/ef9e51e7-96c8-1b79-167b-6303289d5184.jpeg)

### ScanBarcode
こちらの関数が今回の肝です。QR読み取りを起動し、読み取った結果をテーブルで返します。

### If

条件が true の場合とそうでない場合とで異なる結果を返すかアクションを実行します。
if(条件,true,false)といった形になります。

### IsBlank
値が空白であるかどうかを調べて true false を返します。
ここでいう空白とはwhitespaceや空の事ではなく正確には **"値がない" または "不明な値" の場合**という点にご注意ください。

### First
テーブルの最初のレコードを返します。
今回は ScanBarcode で返ってきたテーブルの最初の行の値を取得している形になります。
この値が空白の場合Notify関数(Error)を実行します。

### Notify
アラートを実行します。
×ボタンで閉じるか時間経過で自動的に消えます。

### NotificationType
Notifyの状態(色)を決めます。
今回利用した Error Information 以外に Worning Success があります。
指定しない場合は Information となります。


## 表示の実装
最後にラベルを実装します。
先ほど結果はhoge変数に入っている為、それをそのまま使います。

ScalLabelのTextに

```
Concatenate("結果:", Text(First(hoge).Value))
```

を実装します。

### Concatenate
文字列を連結します。
カンマ区切りでいくつでも連結できます。

# 実行する

Android端末でGooglePlayからPowerAppsをダウンロードし、ログインを行い起動します。
downloadに時間がかかったり、読み込みから失敗するときもありますので、何度か開きなおすことをお勧めします。

ボタンを押すとcameraの許可が求められますので許可してください。
無事読み取れましたね。
![Screenshot_20181116-105903.jpg](https://qiita-image-store.s3.amazonaws.com/0/183354/520114da-241e-665c-5545-94c6c0d7461b.jpeg)


失敗通知を出したい場合はQR読み取りを戻るボタン等で中止すると表示確認できます。
![Screenshot_20181116-103235.jpg](https://qiita-image-store.s3.amazonaws.com/0/183354/fca7c96e-fcbe-35b2-e711-cea30711ccbf.jpeg)


以上で終了です。
非常に簡単に実装できますので、社内でQRを使ったアプリを使う場合はぜひ参考にしてみてください。(利用者は各プランに入る必要があります詳細は[こちら](https://powerapps.microsoft.com/ja-jp/pricing/))

# 参考

- https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/formula-reference
ずんだのさくらんぼ計算問題 Ruby編

さくらんぼ計算については、

* [さくらんぼ計算とはなんぞ？このやり方はいつから始まった？ | 小学校入学女子のママ日記](https://js-mama-onayamikaiketsu.com/1833.html)

など、Webを参照ください。

## ルール
* 入力として 1-9 の整数が2つ与えられます。1つ目を a とし、 2つ目を b とします
* 入力される a と b の合計は必ず 10 以上になるものに限定されます
* さくらんぼ計算を行い b の整数を2つに分割します。これを b1, b2 とします。 a + b1 が 10 になります
* 出力は a,b1,b2 の形式で行ってください

## プログラム(Ruby)
```ruby
inputs = ARGV.map(&:to_i)
b2 = inputs.last - (10 - inputs.first)
b1 = inputs.last - b2
inputs[1] = b1
inputs << b2
print inputs.join(",")
```

## 出力例
```
$ ruby t.rb 1 9
1,9,0
$ ruby t.rb 3 9
3,7,2
$ ruby t.rb 8 5
8,2,3
```
Storybook駆動開発はいいぞ

はじめに

＊こちらはオプトテクノロジーズの社内勉強会LT資料になります
~~LT資料ってあえて書いたのは資料が短いので許してねという前置きです~~

---

# Storybookとは

> Storybook is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components.

[公式doc](https://github.com/storybooks/storybook) より引用

---

## 結局なによ

ReactなどのViewライブラリで作成したコンポーネントを単独で描画して、見た目をカタログちっくに見れる画面作成のためのライブラリ。

コンポーネントにわたす状態を固定値で入れたりして見た目のコントロールを自由に出来るため、異常系など含めたいろいろなUIパターンを検証するのに非常に効果的。

ローカルで開発する時にサーバー（モック含む）に意図したデータを返させるようにするのは大変！という開発中の悩みが解決！最高！

---

コンポーネントライブラリでstorybookを公開してるものもあるので参考までに。
http://airbnb.io/react-dates/?selectedKind=DateRangePicker%20%28DRP%29&selectedStory=default&full=0&addons=1&stories=1&panelRight=0&addonPanel=storybook%2Factions%2Factions-panel

---

# どういいのか

- 導入は簡単
- 使うのも簡単
- コンポーネントの異常系の状態を簡単に表現しながら開発できる
    - コンポーネントのデータ量が多いときにどうなるかとか
    - バリデーションエラーの状態とか
    - ローディングとか
- 見た目の実装と状態管理やAPIリクエストなどのロジックの実装を完全に分業しやすい
    - 今まではロジックがないと作りにくい部分が多かったと思うが、データを自分で簡単に入れながら作れるので協業がめっちゃしやすい
- 開発中に「あのコンポーネント使いまわそうかな」と思った時に簡単に取り込める
    - コンポーネントの使い方まで含めてコードで表現されることになるので、他の画面から「コピペしなきゃ・・・」みたいなのがなくなる
    - 使い方も統一される
- visual testと相性がよく、見た目のリグレッションテストを簡単に導入できる
    - [reg-suit](https://github.com/reg-viz/reg-suit) + [zisui](https://github.com/Quramy/zisui)がめっちゃ捗る
    - プルリク出したらコンポーネントの見た目をmasterブランチのものと比較してその差分を通知してくれる
    - サンプルのプルリク： https://github.com/sisisin-sandbox/try-visual-testing/pull/2


---

# デモ

（時間があれば）

---

# さいごに

悪いことは言わん、Storybookを入れろ！
[初投稿]受け入れテスト

Qiitaに初投稿。

ちゃんとした記事は追々あげるとして
とりあえず最近のプロジェクト状況で感じた事をひとつ。

『総合テスト大事』

ずっとインフラ畑(しかもNWエンジニアリング)だった自分としては
今回参画したプロジェクトで初めてプロジェクト開発の進行状況を
間近で見る事が出来た。
その中でもお客さんと二人三脚で進める受け入れテストの
状況をリアルタイムで見れたのはとても良い経験になっていると思う。

で、その受け入れテストでは日々2～3件、お客さんから
これができない、あれができないというコメントが上がってくる。
手順書の記載ミスが原因のものもあるんだけど、ほとんどが

「原因不明。調査します。」

システムリリース前の最終確認でこれだと今回開発した
プログラムはもちろん、ウチの会社に対する信頼も損なって
今まで頑張ってきた事が台無し。

なので、お客さんに公開する受け入れテストの前の
総合テストで潰せてなかったのかなあと思いを馳せつつ
総合テストはホント大事だなあと、横で見ながら感じる今日この頃。
ECS + Fargate + gRPCを使ったマイクロサービス構成

バックエンドサーバは機能毎にマイクロサービスとして分割し、サーバ間通信には gRPC を使ってモダンな感じにしたい。

## 最初のインフラ構想

まず Node.js アプリケーションをコンテナベースにして、Code Pipeline + CodeBuild + ECR + ECS + Fargate で継続的デプロイ＆オートスケールする仕組みを作った。

![aws-ecs-grpc1.png](https://qiita-image-store.s3.amazonaws.com/0/19292/a9de0e49-102a-962b-ecbc-a4ac342ccb29.png)

でもバックエンドの gRPC でサーバ間通信を行う部分で `Unavailable`, `transport is closing ` というエラーになってしまいうまくいかなかった。
この ALB を使って ECS タスクに対して負荷分散させる構成は gRPC を使わずに REST API でならうまくいった。

## HTTP/2 の gRPC は ALB と相性が悪い

gRPC は HTTP/2 が必須となり、ALB も HTTP/2 に対応しているが、それはフロントエンドのみ。ALB によってバックエンドに転送する場合は強制的に HTTP/1.1 になってしまい、gRPC としての通信が失敗してしまう。

![aws-ecs-grpc2.png](https://qiita-image-store.s3.amazonaws.com/0/19292/04d6609e-6f1d-a376-3aab-117a91340f0f.png)

* [gRPC アプリケーションを AWS で動かすときの注意点
](https://blog.manabusakai.com/2017/06/grpc-on-aws)
* [gRPCアプリをAWS ELBで負荷分散してみた](https://dev.classmethod.jp/cloud/balancing-grpc-app-by-elb)

じゃあ ALB を諦めて CLB にするしかないか…と変更しようとしたが、ECS + Fargate を使う場合、ECS のネットワークモードが `awsvpc` 固定となり、ロードバランサーには ALB 以外を選ぶことができない。  
つまり gRPC の負荷分散のために CLB を使うなら Fargate は諦めて ECS + EC2 で運用するということになり、インスタンス管理コストの低下という大きなメリットを享受できなくなってしまう。  
それだったら gRPC は諦めて Swagger(OpenAPI) で REST API にするしかないかなぁという雰囲気になりつつあった。

## ECS サービスディスカバリを使うことで解決

悩んでいたところ、ECS サービスディスカバリが使えるのではないかと教えてもらった。  

* [How to setup Service Discovery in Amazon Elastic Container Service
](https://medium.com/containers-on-aws/how-to-setup-service-discovery-in-elastic-container-service-3d18479959e6)
* [ECSでgRPC+ServiceDiscoveryな構成を試してみました
](https://dev.classmethod.jp/server-side/grpc-sd-sample/)

ECS でクラスターとサービスを作ると、サービス名が Route53 で自動的に [複数値回答レコード](https://dev.classmethod.jp/cloud/aws/route53-multivalue-response/)としてドメイン登録され、ECS タスクの数だけ IP アドレスが割り振られる。  

![AWS Networking.png](https://qiita-image-store.s3.amazonaws.com/0/19292/e8acd309-4735-8d34-a56c-28cb7d31feb3.png)

例えば ECS で `game-server` というサービス名にし、3 つのタスクを起動した場合は 3 つの内部 IP アドレスそれぞれに `game-server.local` というドメイン名が割り当てられ、同一 VPC 内であればアクセスできるようになる。

<u>**Route 53**</u>

|Name|Type|Value|
|---|:---:|---|
|game-server.local.|A|10.0.0.1|
|game-server.local.|A|10.0.0.2|
|game-server.local.|A|10.0.0.3|

複数値回答レコードはドメイン `game-service.local` にアクセスすると、最大 8 つの IP アドレスをランダムでクライアントに返す。上記の場合は `10.0.0.1`, `10.0.0.2`, `10.0.0.3` の 3 つのアドレスが返る。  

試しに同じ VPC に [AWS Cloud9](https://aws.amazon.com/jp/cloud9/details/) （起動直後から EC2 にログインした状態になるので確認するのに便利）を立ち上げ、ターミナルから `dig` コマンドを試してみると次のような結果となる。

```bash
$ dig +short game-service.local
10.0.0.1
10.0.0.2
10.0.0.3
```

なお、Route53 側で Hosted zones の `local.` にチェックをいれ、Associated VPC に対象の VPC が含まれていないと参照できないので注意。  

あとはクライアント実装次第となるが、通常はラウンドロビンされた値が使われることになる。`curl` や `wget` だと 1 番目の値しか使われなかったが HTTP Client ライブラリの [axios](https://github.com/axios/axios) はラウンドロビンされて使われていた。

これで ALB を使わなくとも負荷分散できる。

## ECS サービスディスカバリとヘルスチェック

ECS のタスク定義で Docker コンテナの HEALTHCHECK を指定できる。  
ヘルスチェックが失敗すると異常と判定され、ECS はタスクを終了してから新しいタスクを自動起動してくれる。  
これが ECS サービスディスカバリとも連携してくれるので、タスクが終了すると同時に、タスクの内部 IP アドレスに割り当てられた `game-server.local` も削除され、活きてるタスクにしかルーティングされなくなる。とても便利。
StorybookをNuxt.jsのアセットに対応させる

Nuxt.jsでアセットを取り扱うのって、めっちゃ楽ですよね。
[アセット - Nuxt.js](https://ja.nuxtjs.org/guide/assets/)
この書き方に慣れちゃって、CSS内で

```css
background: url('~/assets/images/{イメージ名}.jpg');
```

とかよく使ってるんですけど、これだとStorybookでは`http://localhost:6006/assets/images/{画像名}.jpg`になっちゃって、うまい事引っ張ってくれないんです。

ということで、NuxtのWebpackの中身を見ながら、対策練ってみました。

# 環境
Nuxt v1.3.0
Storybook vue v3.4.11

# 結論
`/.storybook/webpack.conf.js`で css-loader の option に alias を追加すれば読み込めます。

```javascript:/.storybook/webpack.conf.js
const path = require('path')
const rootPath = path.resolve(__dirname, '../')

module.exports = (baseConfig, env, defaultConfig) => {

  defaultConfig.resolve.alias['@'] = rootPath
  defaultConfig.resolve.alias['~'] = rootPath
  defaultConfig.resolve.alias['vue$'] = 'vue/dist/vue.esm.js'

  const vueLoader = defaultConfig.module.rules.find(({test}) => {
    return test.toString() === '/\\.vue$/'
  })

  vueLoader.options = {
    loaders: {
      css: [
        'vue-style-loader',
        {
          // この部分
          loader: 'css-loader',
          options: {
            importLoaders: 0,
            alias: {
              '/assets': rootPath + '/assets'
            }
          }
        }
      ]
    }
  }

  const cssLoader = defaultConfig.module.rules.find(({test}) => {
    return test.toString() === '/\\.css$/'
  })
  cssLoader.use = [
    { loader: 'vue-style-loader' },
    {
      // この部分
      loader: 'css-loader',
      options: {
        importLoaders: 0,
        alias: {
          '/assets': rootPath + '/assets'
        }
      }
    }
  ]

  return defaultConfig
}
```

Nuxt 2系から`~/assets`が`~assets`になったらしいので、alias 部分を

```javascript
alias: {
  'assets': rootPath + '/assets'
}
```
に変えてあげると良さそう（試してない）。