OmniAICreator/Qiita-1.07M huggingface dataset:
break-inside:avoid-column

### 段組セットが崩れた場合はbreak-insideを指定する。
```css
.pair{columns:16rem}
.pair>li{break-inside: avoid-column/*avoid-page*/;width:16rem}
```

### 比較
```css
@import url('//gnjo.github.io/schoolmono.css');
.pair{list-style:none;font-family:schoolmono;font-size:14px;}
.pair>li{list-style:none;display:flex;flex-direction:row;line-height:1;
 justify-content:space-between;padding-top:6px;border-bottom:1px solid #ccc}
.pair>li:hover{border-color:#111}

.pair{columns:16rem}
.pair>li{break-inside: avoid-column/*avoid-page*/;width:16rem}
.pair.igavoid>li{break-inside:unset;}
```
```html
<ul class="pair">
<li><div>KEY0</div><div>VALUE0</div></li>
<li><div>KEY1</div><div>VALUE1</div></li>
<li><div>KEY2</div><div>VALUE2</div></li>
<li><div>KEY3</div><div>VALUE3</div></li>
<li><div>KEY4</div><div>VALUE4</div></li>
<li><div>KEY5</div><div>VALUE5</div></li> 
<li><div>KEY6</div><div>VALUE6</div></li>
<li><div>KEY7</div><div>VALUE7</div></li>
<li><div>KEY8</div><div>VALUE8</div></li>
</ul>

<hr>

<ul class="pair igavoid">
<li><div>KEY0</div><div>VALUE0</div></li>
<li><div>KEY1</div><div>VALUE1</div></li>
<li><div>KEY2</div><div>VALUE2</div></li>
<li><div>KEY3</div><div>VALUE3</div></li>
<li><div>KEY4</div><div>VALUE4</div></li>
<li><div>KEY5</div><div>VALUE5</div></li> 
<li><div>KEY6</div><div>VALUE6</div></li>
<li><div>KEY7</div><div>VALUE7</div></li>
<li><div>KEY8</div><div>VALUE8</div></li> 
</ul>
```
[Ethereum] MetaMaskと連携

#概要
chromにMetaMaskという素敵なプラグインがある。
コントラクトを作った後web3等でノードに接続するとき、ノードを自分で指定するのではなくMetaMaskの設定使えたら便利だなぁ。
というかちょっと格好いいので連携させる

<img width="362" alt="スクリーンショット 2018-04-16 12.30.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/236641/dd69c34b-4095-2916-948a-10f4dccdf2eb.png">

#やり方
MistかMetaMaskのプラグインを入れていて接続されている場合、web3に値が入っている。
なので、画面が読み込まれた時にweb3をチェックして存在していればそれを引数にWeb3を生成すればいい。

```html

<head>
    <script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" />
    <script language="javascript" type="text/javascript" src="web3.min.js" />
</head>

<body>
<script>
    window.addEventListener('load', function() {
        if (typeof web3 !== 'undefined') {
          web3js = new Web3(web3.currentProvider);
        } else {
            //入れてない時の処理。エラーなりベタ打ちなり
        }
    });
</script>
</body>
```

参考：
https://cryptozombies.io/jp
よく使う外部サービス連携。key, secret取得の備忘録

# よく使う外部サービス連携。key, secret取得の備忘録
Web開発をしていると、facebookやtwiiter、google、instagramからAPI呼び出しをする機会は避けて通れません。
呼び出す為には、開発者登録を行い、key,secretを発行しアプリケーションに組み込む必要があります。
これらは一つ一つ場所が違っているし、毎回「助けてGoogle先生 ~ 」と泣きつくので、この機会に備忘録として記載したいと思います。
同じ境遇の人の少しでも手助けになれば幸いです。

※1 2018年1月時点のものです。(ずっと下書きのままだった)
※2 状況により異なるため、アプリケーションへの実装までは載せていません。
※3 私が必要だったもので、設定するプロダクトや設定は各人異なるケースがあります。

## 対象一覧
- Facebook
- Twiiter
- <del>Instagram</del> 未記入
- <del>google tag manager</del> 未記入
- google maps
- <del>google analytics api</del> 未記入
- recaptcha

## Facebook

### 何のため
Facebookのアプリとの連携、APIのために使用。よく使うのはFacebook Login

### 必要なもの
- Facebook アカウント
- WebサイトのURL

### 手順
URL: [開発者コンソール](https://developers.facebook.com/?locale=ja_JP)
1. 対象のFacebook アカウントでログイン
2. マイアプリ > 新しいアプリをクリック
3. 新しいアプリIDを作成
4. 製品を追加 > 今回はFacebook ログイン (ドキュメントに従い設置)
5. ダッシュボードから<b>アプリID、app secret</b>を取得

## Twiiter

### 何のために
Twitter ログイン

### 必要なもの
- twitter アカウント
- WebサイトのURL

### 手順
URL: [Application Management](https://apps.twitter.com/)
0. 電話番号紐付けがまだならやっておく(http://phiary.me/twitter-api-key-no-japanese/) 一回これでめっちゃ嵌った。。。
1. Create New App
2. Name(何でもいい)。Description(何でもいい)。WebSite(何でもいい)。Callback URL(重要：指定されているコールバック先)

## Google OAuth Login

### 何のため
Google Loginをするため

### 必要なもの
- Google アカウント
- WebサイトのURL

### 手順
URL: 「Google Cloud Platform」(https://developers.google.com/maps/?hl=ja)
google様。アクセスするたびUIが変わってます。辛い...
1. プロジェクトを作成(なければ)
2. 左の認証情報 > 認証情報を作成 > OAuth クライアント ID 

## Google Map Api

### 何のために
Webサイトに地図を表示するため

### 必要なもの
- Google アカウント
- WebサイトのURL

### 手順
URL: 「Google Cloud Platform」(https://developers.google.com/maps/?hl=ja)
1. プロジェクトを作成(なければ)
2. 左のAPIとサービスをクリック
3. ライブラリ > Google Maps Javascript APIから有効にする
4. 認証情報から取得

### 注意
1日の上限は25000回で、それ以上は有料

## reCAPTCHA

### 何のために
ユーザー認証を攻撃から守るために使用する。デファクトスタンダートだと思ってる。よくある、「ロボットではありません」のアレ

### 必要なもの
- Google アカウント
- WebサイトのURL

### 手順
URL: [Googleの公式](https://www.google.com/recaptcha/intro/index.html)
1. 右上の「Get reCAPTCHA」をクリック
2. 「Register a new site」 のLabel(わかりやすい名前)。Choose the type of reCAPTCHAはInvisible reCAPTCHA」。Domain(Webサイトのドメイン。テストなら127.0.0.1とかlocalhostとか。ポートは不要)。
3.<b>Site keyとSecret key</b>を取得
pythonでvSphere操作　その7　VMスナップショット作成

#本題

基礎さえ出来てしまえばあとは簡単。

```python:py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pyVim.connect import SmartConnectNoSSL, Disconnect
from pyVmomi import vim, vmodl
import atexit, argparse, sys
from datetime import datetime
from pyVim.task import WaitForTask

def time():
    #log time
    d = datetime.today().strftime("%Y-%m-%d %H:%M:%S") + " "
    return d

def set_args():
    parser = argparse.ArgumentParser(
             description='required arguments for retreiving infos from vcenter.')

    parser.add_argument('-s', '--host',
                        required=True,
                        action='store',
                        help='specify vCenter IP')

    parser.add_argument('-o', '--port',
                        type=int,
                        default=443,
                        action='store',
                        help='specify port')

    parser.add_argument('-u', '--user',
                        required=True,
                        action='store',
                        help='specify login User')

    parser.add_argument('-p', '--password',
                        required=True,
                        action='store',
                        help='specify Password')

    parser.add_argument('-m', '--vmname',
                        required=True,
                        action='store',
                        help='specify VM name to make')

    parser.add_argument('-n', '--snapname',
                        required=False,
                        default='snapshot@'+ time(),
                        action='store',
                        help='specify snapshot name')

    parser.add_argument('-d', '--snapdescription',
                        required=False,
                        default='default snapshot descreption',
                        action='store',
                        help='specify VM name to make')

    args = parser.parse_args()
    return args

def main():
    #make connection
    args = set_args()
    si = SmartConnectNoSSL(host=args.host,
                           user=args.user,
                           pwd=args.password,
                           port=args.port)

    #set action at the end
    atexit.register(Disconnect, si)

    #fetch vminfo
    content = si.RetrieveContent()
    vmachine = content.searchIndex.FindByDnsName(None,
                                                 args.vmname,
                                                 vmSearch=True)
    #take snapshot
    print time() + 'start snap operation'
    task = vmachine.CreateSnapshot_Task(name=args.snapname,
                                        description=args.snapdescription,
                                        memory=True,
                                        quiesce=True)
    if WaitForTask(task):
        print time() + 'finish snap operation'

if __name__ == "__main__":
    main()

```

searchIndexは便利。
iOS のズームやスクロールを止める

## iOS で勝手にズームやスクロールがされてしまう問題

- iOS11 から body 100% で作っても縦方向のスクロールが走ってしまう。
- ズームさせたくないのにダブルタップするとズームされてしまう。


### ズームの抑制は、viewport の設定で対応できないの？

iOS 10 から　user-scalable=no　が動作しなくなりました。

## 対応

- 拡大やスクロールはブラウザが実装している挙動なので preventDefalut を叩けば止めることができます。body や document で bubbling で受けて標準挙動をキャンセルする、といった対応にすれば子要素に影響を与えず、そのままで対応することができます。

- 現象は iOS10以降から発生するのですが、それより古いバージョンで止めても問題はないだろう、ということで　iOS 丸ごと止めます。

- ダブルタップを preventDefalut （時間は要調整　350msecから500msecぐらい）
- ２本指の拡大を preventDefalut
- preventDefalut をコールするので、passive はfalse

## 対応したコード

ソースについて解説するほどでもないのでリンク貼っておきます。
たいしたものではないのですが、ライブラリにしてみました。

https://github.com/coa00/pizas

メンテするモチベーションが上がるので リポジトリの star　くれたら嬉しいです。


雑な文章で申し訳ありません。最近、qiita サボってます。
ReduxFormでformatとvalidateを同時に使う際の注意点

個人的メモ。

redux-formでformatとvalidateを同時に使うときには実行順序に注意。
下記のような書き方をした場合は `validate` => `format` の順に実行される。
つまりフォーマット前の値がバリデーションに渡される。これでハマったりする。

```jsx
<Field
  name="price"
  format={formatNumberWithCommas}
  validate={numericStringWithComma}
/>
```

フォーマット後の値をバリデーションさせたい場合には上記の書き方ではなく下記のように `asyncValidate` を使って書く。

```jsx
<Field
  name="price"
  format={formatNumberWithCommas}
/>

...

reduxForm({
  ...
  asyncBlurFields: ['price'],
  asyncValidate: ({ price }, dispatch, props, fieldName) => {
    if (fieldName === 'price') {
      return Promise.delay(0)
        .then(() => ({ price: numericStringWithComma(price) }))
    }
  }
})
```
Anaconda+python3.6でOpencvの動画機能を使う

Opencvの動画機能を使おうとしましたが、色々と試してもうまくいかなくて、
何とか使えるようになったので記録します。

環境
Vmware Workstation 14.1.1
CentOS 7.4
Anaconda 4.5.1
python 3.6.3

AnacondaでインストールしたLinux向けバイナリパッケージは動画の入出力をサポートしていない
ようなので、ソールからbuildしましたが、cv2.soが見つからず途方に暮れかけたのですがたまたま
以下を見つけました。

[conda-forge  / packages / opencv 3.4.1](https://anaconda.org/conda-forge/opencv)

新しそうなので、試しに実行してみました。

```
conda install -c conda-forge opencv 
```

実行するとOpencv 3.4.1がインストールされます。
Opencvの情報を確認します。

```
$ python -c 'import cv2; print(cv2.getBuildInformation())'

General configuration for OpenCV 3.4.1 =====================================
  Version control:               373d1d1
(中略)
  Video I/O:
    DC1394:                      NO
    FFMPEG:                      YES
      avcodec:                   YES (ver 57.64.101)
      avformat:                  YES (ver 57.56.101)
      avutil:                    YES (ver 55.34.101)
      swscale:                   YES (ver 4.2.100)
      avresample:                YES (ver 3.1.0)
    GStreamer:                   
      base:                      YES (ver 1.8.0)
      video:                     YES (ver 1.8.0)
      app:                       YES (ver 1.8.0)
      riff:                      YES (ver 1.8.0)
      pbutils:                   YES (ver 1.8.0)
    libv4l/libv4l2:              NO
    v4l/v4l2:                    linux/videodev.h linux/videodev2.h

(後略)
```

Opencvの動画機能が使えるようになりました。
Material UI TextField について備忘録

TextField で Chrome　の　オートコンプリートをOFFにするには、

```
autoComplete='off'
```

readOnly にするには、

```
inputprops={{
  readOnly: true,
}}
```
disabled プロパティはドキュメントにもあるのですが、こんな指定もできるようです。

```
inputprops={{
  readOnly: Boolean(readOnly),
  disabled: Boolean(readOnly),
}}
```

こんな感じです。

```
<TextField
  value={this.state.value}
  inputprops={{
    readOnly: true,
  }}
  autoComplete='off'
  required
  fullWidth={true}
  label="Name"
  name="name"
  margin="normal"
  defaultValue={"test"}
/>
```
macのエディター「mi」設定

ほぼ自分用。

## 右端のジャンプリスト、最近使ったファイルを消す。

じゃまなので消す。

<img width="1260" alt="スクリーンショット 2018-04-16 11.13.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/42110/a54e2c55-b32b-52d5-d637-dbb3c3afd5ab.png">

上部メニューバー > 表示 > 情報ペインカラム表示切り替え を押す


## 右端で折り返すようにする

折り返してくれー

<img width="818" alt="スクリーンショット 2018-04-16 11.17.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/42110/5dbda75d-f598-fdc0-4948-93ac5d7fd3da.png">

上部メニューバー > ドキュメント > 行折り返し > 折り返しあり（ウィンドウ幅） を押す
ECR push をやってみた

# はじめに
弊社環境の ECR に docker push を行うにあたりちょっと詰まったのでメモ。

# 前提
config と credential は以下

```~/.aws/config
[default]
region = ap-northeast-1

```

```~/.aws/credential
[default]
aws_access_key_id = my_access_key_id
aws_secret_access_key = my_secret_access_key

[production/developer]
role_arn = arn:aws:iam::000000000000:role/developer
mfa_serial = arn:aws:iam::000000000000:mfa/my_user_name
source_profile = default

[production/admin]
role_arn = arn:aws:iam::000000000000:role/admin
mfa_serial = arn:aws:iam::000000000000:mfa/my_user_name
source_profile = default
```

# ECR push までの手順
IAM でアカウントが払い出されていて適切に権限も付与されていることを想定しています。
手順と言っても、ECR にプッシュコマンドを表示とあるのでほぼそのとおりでいい。MFAを設定していると認証を求められる。６桁のアレを入力。

```
$ aws ecr get-login --no-include-email --region ap-northeast-1 --profile production/developer
```

↑を叩くとコマンドが返却されるのでそのままコピペして実行。`--profile` の指定に注意。楽したいなら `eval` です。下記は例。

```
｀eval $(aws ecr get-login --registry-ids ${OWN_AWS_ID} --region ap-northeast-1 --no-include-email)｀
```

```
Login Succeeded
```

となれば OK。`docker build` もします。

```
$ docker build --build-arg HOGE_TOKEN=HOGEHOGE -t fuga .
```

私の環境だとトークンを渡してあげないといけなかったので `--build-arg` で環境変数を渡した。ちなみにこれは image 内に残らないのでセキュリティも担保されている。

最後に push。

```
$ docker push 000000000000.dkr.ecr.ap-northeast-1.amazonaws.com/fuga:latest
```

push する前に ECR でリポジトリを作っておくのを忘れずに。`docker build` 時に tag 打つのも忘れずに。
YYPHP#34 イベントレポート「BEAR.Sunday紹介/どんな自動テストしてるか？Vue.js便利情報」

これは2018年4月13日に開催したPHPerイベントYYPHP#34のイベントレポートです。

YYPHPは一言で「PHPerの部室」です。PHPについて、雑に、ゆるく、ワイワイ話し合う集いです。毎回お題を決めずに雑談を出発点にいろいろなことを突発的にやります。集まった人でコードリーディングをすることもあれば、一緒に開発ツールを触ってみたり、フレームワークについての情報交換をすることもあります。開催は毎週19:00に高田馬場にて。(曜日は金曜か水曜！)

今回からDiscordでの音声配信を開始しました！
[Discordはこちら](https://discord.gg/DMTUGNT)
会場に来れない人でもDiscordやSlackでリモート参加できます！歓迎です！

## 参加者 8名
* PHP歴の分布
    * 10年〜: 4名
    * 5〜9年: 1名
    * 2〜4年: 1名
    * 1年未満: 2名

## BEAR.Sundayの紹介
* DI, AOPのフレームワーク
* Resource
* [BEAR.Sundayの説明](https://www.youtube.com/watch?v=mW4a2BKM3Kg&list=PLvmZlQTxBpGJFYVFD62rac8K-gmo_31KY&index=11)
* [(71) PHPerKaigi 2018 - 03/10 30分 BEAR.Sunday / 郡山昭仁 - YouTube](https://www.youtube.com/watch?v=mW4a2BKM3Kg&list=PLvmZlQTxBpGJFYVFD62rac8K-gmo_31KY&index=11)

## Home Brew / tapが無くなった？

* brewでphpが入れられなくなった
* いまはDockerでやる方向では？
    * 簡単に導入できる
    * 簡単にバージョンが変えられる
    * 最初に全部pullしておけば通信環境が悪くても大丈夫
* これは今日出てた homebrew の関連の話でしょうか。
    * [Mac OS Homebrew の PHP 関連の formulae 変更されて大変だった (2018年4月) - Qiita](https://qiita.com/katzueno/items/5e65ddc65f09cc1e1ec7)

## 古いPHPを最新のOSで動かすパッチ

* [PHP5.1.6 install to CentOS7](https://gist.github.com/horitaku1124/34872fc29426c056adcf9d60ac37df9b)

## 皆さんどんな自動テストしてるか

* いまJavaなのでJUnitでやってる
* DBの接続テスト
* PHPはPHPUnitでやる
* RubyはRspecで
* どこまでテストするか。画面、e2eなど

気になる https://www.cypress.io/

## どんなときにAWSを使うのか

* 個人的にはさくらのVPSを使っている
    * なんとなく
* クラウドのほうが割高だけど機能が多い
* VPSは
    * スペックが固定
    * APIで操作できない
* クラウドは
    * プライベートネットワークが作れる
    * 従量課金
    * クラウドネイティブ(サーバレス)の環境を用意できる

## Vue.js
* [Vue.js 2.3 Complete API Cheat Sheet](https://vuejs-tips.github.io/cheatsheet/)
* [Vuex CheatSheet](https://vuejs-tips.github.io/vuex-cheatsheet/)
* [Vue CLI 3](https://blog.logrocket.com/vue-cli-3-the-deep-dive-41dff070ac4a)
* [Vuejs Developers](https://vuejsdevelopers.com/)
* [Home · ratiw/vuetable-2-tutorial Wiki](https://github.com/ratiw/vuetable-2-tutorial/wiki)

### 公開されているAPIの叩きかた

* Vuejsだったら、[Axios](https://github.com/axios/axios)
* PHPからだったらcurlか[Gazzle](https://github.com/guzzle/guzzle)

## PHPer Kaigiはどうだったか
* ラウンドテーブルが新しくできた、ベテランといろいろ話せる
* ビールを飲みながらビールを飲んだ
* 来年は2019年 3/29,30,31の予定

## 5月

* 希望があったので、YYPHPを土曜日開催してみる
macでwindowsキーボードを使う  Karabiner-Elements 12.0.0以降の注意

macOSでKarabiner-Elements12.0.0でjis配列のキーボードで入力できなくなった
調べたら仮想キーボードが廃止されmacOS標準のキーボードの設定で設定してほしい感じに変更された。

https://github.com/tekezo/Karabiner-Elements/blob/master/NEWS.md

これまでは、Karabiner-ElementsでJIS配列キーボードとして設定するのだが、これをmacOSのシステム環境設定のキーボードで設定する。

![スクリーンショット 2018-04-16 11.01.40.png](https://qiita-image-store.s3.amazonaws.com/0/142882/b633169a-24b6-a5d4-79fa-95dd2a86f1cc.png)

![スクリーンショット 2018-04-16 10.56.39.png](https://qiita-image-store.s3.amazonaws.com/0/142882/385cbf8f-500a-28e3-8821-e69b51b23d11.png)

[キーボードの種類を変更...]ボタンを押してあとはダイアログの指示通りにするが
左のshiftキーを押せというが認識されない場合はエラーとなるが無視してOK
Word2vecのCBOWについて

#はじめに
[前回](https://qiita.com/edad811/items/559024d9a9784b005642)の続きとして、Word2Vecのもう一つのモデルCBOWについて説明する。

##CBOW
Continuous Bag-of-Word Model（CBOW）はSkip-Gramと逆に、周囲の単語が与えられたとき、中心語となる単語を予測する。そのモデルは以下のように定式化できる。

```math
\max\prod_{t=1}^{T}\mathbb{P}(w^{t}|w^{(t-m)},...,w^{(t-1)},w^{(t+1)},...,w^{(t+m)})
```

対数を取ることで、次のように定式化できる。

```math
\min-\sum_{t=1}^{T}\log \mathbb{P}(w^{t}|w^{(t-m)},...,w^{(t-1)},w^{(t+1)},...,w^{(t+m)})
```

ここで、周囲の単語$w_{o_{1}},...,w_{o_{2m}}$から中心語$w_{c}$を生成する確率は以下のように与える。ここでは、逆に背景語を$\textbf{v}$、中心語を$\textbf{u}$と表す。

```math
\mathbb{P}(w_{c}|w_{o_{1}},...,w_{o_{2m}})=\dfrac{\exp[\textbf{u}_{c}^{T}
(\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}})/(2m)]}
{\sum_{i \in \textit{V}}\exp[\textbf{u}_{i}^{T}(\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}})/(2m)]}
```

パラメータに関する勾配の計算は次のようになる。

```math
\dfrac{\partial \log \mathbb{P}(w_{c}|w_{o_{1}},...,w_{o_{2m}})}{\partial \textbf{v}_{o_{i}}}= \dfrac{1}{2m}(\textbf{u}_{c} - 
\sum_{j \in \textit{V}}\dfrac{\exp[\textbf{u}_{j}^{T}(\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}})/(2m)]}{\sum_{i \in \textit{V}}\exp([\textbf{u}_{i}^{T}\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}})/(2m)]}\textbf{u}_{j})
```

```math
\dfrac{\partial \log \mathbb{P}(w_{c}|w_{o_{1}},...,w_{o_{2m}})}{\partial \textbf{u}_{c}}=
\dfrac{\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}}}{2m} - \dfrac{\exp[\textbf{u}_{c}^{T}(\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}})/(2m)]}{\sum_{i \in \textit{V}}\exp[\textbf{u}_{i}^{T}(\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}})/(2m)]}\cdot\dfrac{\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}}}{2m}
```

また、上の式はそれぞれ以下のように変形できる。

```math
\dfrac{\partial \log \mathbb{P}(w_{c}|w_{o_{1}},...,w_{o_{2m}})}{\partial \textbf{v}_{o_{i}}}=
\dfrac{1}{2m}(\textbf{u}_{c} - \sum_{j \in \textit{V}}\mathbb{P}(w_{j}|w_{o_{1}},...,w_{o_{2m}})\textbf{u}_{j})
```

```math
\dfrac{\partial \log \mathbb{P}(w_{c}|w_{o_{1}},...,w_{o_{2m}})}{\partial \textbf{u}_{c}}=
\dfrac{\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}}}{2m} - \mathbb{P}(w_{c}|w_{o_{1}},...,w_{o_{2m}})\dfrac{\textbf{v}_{o_{1}}+...+\textbf{v}_{o_{2m}}}{2m}
```

ここで、上の式から分かるように、勾配を計算するとき、Skip-Gramと同様に計算量が大きいという問題が生じる。したがって、CBOWの学習には、通常Hierarchical Softmax（階層ソフトマックス）という手法が使われることが多い。これによって、計算量がO($|V|$)からO($\log|V|$)まで大きく減少される。
Chrome 62で導入された画面キャプチャが便利過ぎました


```
Ctrl + Shift + cで Inspect Element モードを起動する。

Inspect Element モードの状態で、Ctrlを押しながらマウスで範囲を指定
（クリックしたところ～クリックを離したところまでが範囲になる）
```
https://developers.google.com/web/updates/2017/08/devtools-release-notes

---

問題は同じ画面で何度もキャプチャ取りたいとき。
毎回Inspect Element モードを起動しないといけないのが面倒です。
誰かInspect Element モードに固定する方法と解除する方法教えて下さい。
AWSでRedHat OSを用いたHDP環境を構築する際にエラーが返る

## 概要
特定の環境において、AWS EC2のRedhatインスタンスを用いてHDP環境を構築する際にエラーが返る。日本語ドキュメントが少ないので、ドキュメントに残しておく。

## 環境
* Red Hat Enterprise Linux 7.5 (HVM), SSD Volume Type　を用いたすべてのインスタンスだが、問題の本質は以下の通りデフォルトでは `libtirpc-devel` が入っていないために、RedHatOSで発生する。

## 原因
`libtirpc-devel` というライブラリがないため。

## 対処
```
yum-config-manager --enable rhui-REGION-rhel-server-optional
yum install libtirpc-devel
```

## 備考
* Ubuntuで検証したところ特に問題がない。AWS EC2で構築するのであればUbuntu OSでHDPクラスタを構築することをオススメする。
ReactNativeのAnimatedはCSSの％変化には使えない

個人的メモ。

パーセントを変化させるためにAnimatedを使おうとしても動かなかった。
文字列と結合せず、直接変数を指定しないとダメなのかも。

```
// Not Working
<Animated.View style={[styles.gauge, {width: `${gaugePercentage}%`}]} />

// Working
<Animated.View style={[styles.gauge, {width: gaugeWidth}]} />
```
AWS EC2とRDSでWordPressインストール（簡単版）

# AWS EC2とRDSでWordPressインストール（簡単版）

インストールを行ったメモを自分用の備忘録としてメモ。
AWSにはWordPressがすぐに使えるものがマーケットプレイスにあるが、EC2＋RDSの組み合わせを使うために自分でインストールしてみる。

**注意**：本家の説明から、ユーザの管理といったセキュリティ的な部分を削ぎ落として、最低限こうすればWordpressが動くよ！という簡単な内容になっています。本格的なサイト運用を行う場合はご注意ください。（基本的には問題ないと思うけど・・・）

## EC2とRDSのインスタンス作成
こちらは割愛

## wordpress用のDBスキーマを作成
EC2から直接繋ぐ場合は以下のコマンドでつながる。事前にRDS側で3306ポートでEC2からアクセスできるように設定しておくこと。詳しい話は割愛。

```bash
$ mysql -h [RDSのエンドポイント] -P 3306 -u[ユーザ名] -p
```

接続できたら以下のSQLを実行。スキーマ名は好きな名前でOK

```
CREATE DATABASE wordpressで使いたいスキーマ名;
```

## WordPress本体の配置
ルートディレクトリ、またはブログ用のパスを切る場合はそのディレクトリにWordPressファイルをアップロードします。
WordPressの本体は[公式サイト](https://ja.wordpress.org/ "日本語 — WordPress")よりダウンロードしてください。
インストール先がルートディレクトリとサブディレクトリでは**ファイルの構成が異なります。** 気をつけましょう。

### ルートディレクトリの場合
ダウンロードした、wordpressフォルダの**中身**を全て配置します。
例：```/var/www/html/ここに中身をぶちまける```

### サブディレクトリの場合
**ダウンロードした、wordpressフォルダをそのまま配置**します。フォルダ名は適宜変更しましょう。
wordpressの名前のままだと攻撃を受けやすくなります。（たぶん）
例：```/var/www/html/好きな名前に変更/中身```


## WordPressのインストール
1. ファイルを配置後、以下のURLにブラウザからアクセス。
EC2の設定でHTTPまたはHTTPSの接続を許可しておきましょう。詳しくは割愛。
・ ルートディレクトリの場合
https://example.com/wp-admin/setup-config.php
・ サブディレクトリの場合
https://example.com/blog/[自分で変えたwordpressディレクトリの名前]/wp-admin/setup-config.php

2. アクセスすると、初期設定画面が出るので、次へ進むをクリック
3. DBの情報入力画面が出てくるので、以下の通り入力

| 項目 | 入力内容 |
|:--|:--|
| データベース名 | [先ほど作成したDBスキーマ名] |
| ユーザー名 | RDSインスタンス作成時に設定したユーザ名 |
|パスワード|RDSインスタンス作成時に設定したマスターパスワード|
|データベースのホスト名|RDSインスタンスのエンドポイント|
|テーブル接頭辞|wp_|

最後ににブログタイトル、ユーザ情報などを入力
タイトル、ユーザ名、パスワードは好きに設定すればOK。忘れないように。

これでWordPressの導入は完了です。なんて簡単なんでしょうか。
後は好きにカスタマイズして、自分好みのサイトに仕上げていきましょう！
AWSを使ってSSLを独自のドメインにコーポレートサイトを公開する

# この記事は単なるまとめである。
もし自社のコーポレートサイトを独自のドメインにSSL付きで公開したいとする。AWSを使ってこの目的が達成できる。

## 使っているサービス：
- S3
- Route53
- CloudFront
- ACM

S3を使ってコーポレートサイトが公開できる。ネット上で様々な記事があるようだか、やはり公式ガイドの方が便利だと思うので
[https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html]

ファイルをまとめてS３にアップロードしたいなら
[https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/using-s3-commands.html]

ACMでSSL証明書を申請
https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/acm-overview.html

CloudFrontで独自の証明書を設置し、Route53でアリアスを設置。
独自のドメインをCloudFrontで生成するドメインに指向する。

以上。
seabornをなぜ as snsとしてimportするのか

# import seaborn as snsのsnsとは？
pythonを使ってデータ分析を進めて行く中で、seabornは毎回お世話なると思います。
しかしながら、どうして以下のようにsnsとするのか疑問に思ったことはないでしょうか？

```python
import seaborn as sns
```

## 結論
[stackoverflow](https://stackoverflow.com/questions/41499857/seaborn-why-import-as-sns?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa)に同様の質問があり、回答がありました。（本当かは不明ですが）
それによると、[The West Wing](https://en.wikipedia.org/wiki/The_West_Wing)というTVシリーズに、[Samuel Norman Seaborn](https://en.wikipedia.org/wiki/Sam_Seaborn)というキャラクターがおり、そこからきているらしいです。

これからは、Samuel Norman Seabornに思いを馳せながらデータ分析を進めて行きたいと思います。

## 参考
- [Seaborn - Why import as sns?](https://stackoverflow.com/questions/41499857/seaborn-why-import-as-sns?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa)
- [Sam Seaborn](https://en.wikipedia.org/wiki/Sam_Seaborn)
- [The West Wing](https://en.wikipedia.org/wiki/The_West_Wing)
表示がおかしいとユーザから言われたときに確認したい３３項目

ユーザから使われているサービスの「表示がおかしい」とカスタマーサポート部隊に問い合わせがあった場合、
一般的なサービスでざっと考えられるだけでも、原因の調査には次のようなフローとなるはずです。
（サービスやシステム構成によって依存するので実際にはもっとあります・・・）
<img width="832" alt="スクリーンショット 2018-04-16 8.57.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/55077/54ad6a4e-4c5b-908d-b5b3-eb58b0e267ca.png">


解決への道筋はわかっていたとしても
修正対応するかも含めて迅速な情報収集と判断が必要となります。
（対応プラットフォームのシェアが少ない＝サービスへのインパクトが少ないor特定の限られた条件のみしか再現しない）

# リリース時に修正した内容から推測する

リリースした直後に修正した画面が動かなくなったという場合は
修正した画面に関連するクライアント側のソースコードやAPI側に原因があることがほとんどです。
まずは、そこを重点的に探します。

# エラーログ・クラッシュログから推測する

ブラウザ側のエラーは[Rollbar](https://rollbar.com/)を使うとどのブラウザでどのJSエラーが起きたかわかります。
APIの5xx系エラーはAPIサーバ側でエラーログに出力するように設計します。
サーバ側の負荷は[Datadog](https://www.datadoghq.com/)などで監視します。
スマホネイティブアプリの場合は、容赦なくアプリが落ちるので[Crashlytics](https://firebase.google.com/products/crashlytics/?hl=ja)にてどこでアプリが落ちたか確認します。

# ユーザIDといつアクセスしたかのログでたどる

サーバ側のログが残っていれば、

* ユーザのユーザエージェント
* ユーザの操作履歴（APIアクセス履歴）

からどのようなユースケースやプラットフォームで再現するか推測・確認することができるはずです。
また[Hotjar](https://www.hotjar.com/)などのサービスを使えば、ユーザの操作が動画で出力されるので確認することができます。
Django2 公式チュートリアルのPollsアプリの機能追加【pollsの新規登録】

#公式チュートリアルにはない機能を追加
https://docs.djangoproject.com/ja/2.0/intro/tutorial01/

第一弾として、pollsをユーザが新たに登録する機能を解説します。

##既存viewの編集

```views.py
#下の3つを追加
from django.urls import reverse_lazy
from django.contrib import messages
from .forms import QuestionForm

（中略）
#CreateViewを追加
class CreateView(generic.CreateView):
    model = Question
    form_class = QuestionForm
    success_url = reverse_lazy('polls:index')

    def form_valid(self, form):
        result = super().form_valid(form)
        messages.success(
            self.request, '「{}」を新規作成しました'.format(form.instance))
        return result    
```

##既存URLの編集
```polls/urls.py
    path('create/', views.CreateView.as_view(), name='create'), #追加
```

##forms.pyを新たに作成

```polls/forms.py
from django import forms
from .models import Question

class QuestionForm(forms.ModelForm):
    """
    Question モデルの作成、更新用。
    """
    class Meta:
        model = Question
        fields = ['question_text', 'pub_date']
```

###question_form.htmlを作成

```question_form.html
<form method="post">
    {{ form }}
    <button>保存</button>
    {% csrf_token %}
</form>
```

##index.htmlを編集
```index.html
<hr>
<h3>Questionを新規追加</h3>
<a href="{% url 'polls:create' %}">新規作成</a>

```

以上でしっかりと動くと思います。
EdgeRouterでIPv6 PPPoEの設定

# EdgeRouter-Xを購入
自宅の光回線は[フレッツ 光ネクスト ファミリー・ハイスピードタイプ](https://flets.com/next/fm/)をずっと使っていたのですが、さすがに遅さを感じていたため、[フレッツ 光ネクスト ファミリー・ギガラインタイプ](https://flets.com/next_gigaline/)に変更することに。
同時にこれまでつかっていたルーターを[NEC UNIVERGE IX2015](https://jpn.nec.com/univerge/ix/download_IX2015_S.html)から変更する必要があるため、いろいろと検討したところ、[Ubiquiti Networks EdgeRouter X](https://www.ubnt.com/edgemax/edgerouter-x/)が安くて良さそうだということで購入。
amazon.co.jpで購入するとPSE認証付き電源[^1]が付属するとのことで、amazonで購入した。
[^1]: 中身は秋月電子の電源でした。

# 問題発覚
IPv4の設定も一通り終わり、IPv6の設定を行おうとしたところ、問題が発覚。
どうも、IPv6のみのPPPoEだとまともに動かないらしい。

#### 参考

* [EdgeRouterLiteでPPPoE IPv6接続ができない件（未解決） - /home/tnishinaga/TechMEMO](https://tnishinaga.hatenablog.com/entry/2015/05/10/185741)
* [IPv6 only PPPoE = FAIL - Ubiquiti Networks Community](https://community.ubnt.com/t5/EdgeRouter/IPv6-only-PPPoE-FAIL/td-p/1558417)

いろいろと試してみたところ、スクリプトを作成することによりとりあえず対応できそう。

# やったこと
EdgeOSにsshでログイン

rootシェルにログインし、スクリプトを作成

```shell-session
$ sudo su -
# vi /config/scripts/ppp/ipv6-up.d/ipv6olny
```

```shell:/config/scripts/ppp/ipv6-up.d/ipv6olny 
#!/bin/sh

OLD_IFNAME=$1
ipparam=($6)
NEW_IFNAME=${ipparam[0]}

if [ -z "`ip a show dev $NEW_IFNAME | grep 'inet '`" ]; then
  . /etc/ppp/ip-pre-up.d/0002rename-pppoe $*
  ip link set dev $NEW_IFNAME up state up

  for f in `ls /var/run/pppoe-client-sessions/*@$OLD_IFNAME 2> /dev/null`; do
    mv $f $(echo $f | sed -e s/$OLD_IFNAME/$NEW_IFNAME/)
  done

  /etc/ppp/ip-up $NEW_IFNAME $2 $3 $4 $5
fi
```

```shell-session
# chmod 755 /config/scripts/ppp/ipv6-up.d/ipv6olny
```

## やっていること
IPv4アドレスが付与されていなければ、次の処理を実施。

* ```/etc/ppp/ip-pre-up.d/0002rename-pppoe```を動かし、デバイス名の変更を行う。
* ```/var/run/pppoe-client-sessions```内のinterface名を変更。
* ```/etc/ppp/ip-up```を実行。ここでDHCPv6-PDの処理などが行われる。

# 制限事項
ログに```Couldn't get PPP statistics: No such device```が５秒に１回でてきます。
したがって、ログローテートの設定は必須になります。[^2]
pppdを修正し、```/etc/ppp/ipv6-pre-up```対応すればよいらしいのですが、EdgeOSのソースが見つからず、修正できません。
デバイス名の変更ではなくて、pppoeの名前でダミーデバイスを作成してpppデバイスとブリッジするといいような気もしてます。
パフォーマンスは落ちそうですが。
[^2]: とりあえずサイズ1MB、ファイル数5つにしてます。
使いやすい レポート ビューにしておきたい

Power Query エディターでデータを収集変換しデータモデルにロード。リレーションシップや集計に必要なメジャーを作成し "モデリング" を完了した。では、そのあと何をすればよいのか。主たる目的は使いやすいレポート/データモデルにするということだけど、それらが影響する関連の機能についても知っておいた方がよいなと思うのです。

[Online analytical processing (OLAP)](https://docs.microsoft.com/en-us/azure/architecture/data-guide/relational-data/online-analytical-processing) とか Semantic datamodel とか重要だけど小難しい話はちょっと置いといて。

# 非表示にしたり、列を階層化したり
## 使用しないものは非表示に(必須)
レポート上に配置するビジュアルに使われることがない列やメジャーそしてテーブルは **非表示** にしてしまった方がよい。だって、たくさん並んでたらよくわからないから。

**キー列**
リレーションシップの定義に使用される列は非表示とすべき対象。

**使わない列**
そもそもレポートに不要な列はデータモデルにロードする時点で除外されていることは前提として、レポートに配置するビジュアルに使用しない列は非表示に。列を非表示としてもページやレポートなどフィルタに使用できるし、メジャーで集計する要素であっても計算されないことはない。

**メジャー / テーブル**
定義したメジャーを変数のように参照する使い方をしていて、単独で使用されることがないメジャーは非表示としてよい。また、多対多のリレーションを実現するためなどで追加したテーブルはデータモデルには重要だけどレポートには必要ないので非表示。

**ファクト テーブルの列**
ファクト テーブルは ディメンジョン テーブルとの間で定義するキー列と集計対象となる列のみとなるのが理想で、明示的なメジャー以外は非表示に。

## 関連する列は階層(Hierarchy)
[年] → [月] → [日] とか [商品区分] → [商品名] など、関連が強い列どうしはひとつの階層(Hierarchy)にまとめる。ビジュアルに使用するときはまとめて配置されるし、ドリルスルーなどでその列の順序を使用することができる。

## 暗黙のメジャーを使わない
**メジャーは明示的に定義**する。
暗黙のメジャーはいろんな集計ができて一見便利そうだけど、集計結果に影響するフィルター コンテキストを考慮した集計ができない。また、"合計額" や "平均点", "ユニークユーザー数"とか集計する種類を明示的にしておいた方が使いやすい。

*メジャーを明示的に定義しないことが起因して解決まで遠回りしちゃってる方をしばしばお見受けする感じ。*

# やってみる
こんな感じになります。
![2018041101.png](https://qiita-image-store.s3.amazonaws.com/0/193509/96f71b1a-8e77-24c7-d958-fe36c233e005.png)
*表示が期待通りにならないときは、[フィールド]ペイン を一度閉じるとよい*

**非表示にした列**
レポート ビューの [フィールド]ペインで表示されない。スッキリ

**メジャー テーブル**
メジャーだけになったテーブルは、アイコンが変わって先頭に表示されるようになる。いわゆる メジャー テーブルに。

**階層化した列**
定義した列の順序が維持されることが重要。
階層に含めた列であってもフィルターに使用することもできる。
![2018041101.png](https://qiita-image-store.s3.amazonaws.com/0/193509/e32dcb42-be5a-c128-fe62-f059df0ca08c.png)

データモデルをシンプルにする **非正規化** も忘れず検討。テーブルが減るし、この非正規化に階層を使うとイイ感じになるはず。

## ほかに影響すること
### クイック インサイト
中の人がデータモデルの構造やデータなどを解釈しイイ感じに起きたことや状況を提案してくれる機能。

- [Power BI を使用してデータ インサイトを自動的に生成する](https://docs.microsoft.com/ja-jp/power-bi/service-insights)
- [Power BI でサポートされているインサイトの種類](https://docs.microsoft.com/ja-jp/power-bi/service-insight-types)

で、ポイントになるのが **[Power BI クイック インサイト用のデータの最適化](https://docs.microsoft.com/ja-jp/power-bi/service-insights-optimize)**

- 列の表示/非表示(階層の列は非表示扱い)
- テーブルの表示/非表示
- リレーションシップ

主にこれらの要素の状況で AI によるインサイトを調整できる。無意味なサジェスチョンを得ることは避けましょうっていう内容で、試してみるとその違いは歴然。

使いやすさ重視でメジャー用のテーブルを用意するという手段があるのだけど、クイック インサイトで期待する結果を得られない可能性が非常に高い。影響をわかったうえで使うのであればご自由にってことです。
### Power BI の レポート ビュー以外の ビュー
例えば、[Excel で分析]を利用するとき、設定した 列の表示と階層が提供される。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/193509/3d1c3dec-67e8-e1f4-196e-5b1731e4ced0.png)
*Power BI には SSASのパースペクティブのような機能はない。*



# その他
- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
Laravel　ログイン時のエラーメッセージの日本語化

Laravelの標準エラーメッセージは英語表記になっています。
こちらについては、以下の方法で日本語化できました。

エラーメッセージ日本語化
https://qiita.com/Rock22/items/1db96c801d78ebafb7cc

ただ、ログインIDの「email」と「password」が不一致だった場合は、以下のような英文表記されます。
「These credentials do not match our records.」

validation.phpに以下の変換文を追加してみたのですが、変わりありませんでした。

// 追加
'failed' => 'ログインIDとパスワードが一致していません。',

何か他に方法ありますでしょうか。
const 重要

以下、私が仕事でメインで使っているのが C++ なので、その観点です。ruby などではまた違った考えが必要だと思います。

# const おじさん現る
私の PRレビューで 非常によく見かける指摘の1つに「これ `const` にできますね」というのがあります。

一昔前 staticおじさん というのがある種の人々を揶揄する語として流行ったことがありますけど、 それに倣うなら `const`おじさんと呼ばれそうなくらいに。
（なお、C++11 からは `constexpr` もあるので、場合によっては `constexpr` おじさんにもなります）

# 精神的負担について

ただ、これにはわけがあって、C/C++ において `const` と書いた場合、それは設計意図の表明であり（同時にコンパイラに対する制約とヒントともなる） 、レビューという活動が設計に対するフィードバックをその第一義としているのであれば当然すべきフィードバックだから、です。

もっと噛み砕いて言うと、  **const があるのと無いのとでは そのコードを理解しようとする人（レビュワーだけとは限らない）にとって 精神的負担が 2倍、、、いや 10倍くらい違うから** です。

# 脳内スタック消費理論

変数なり、構造体のフィールドなりが出てきた時に、`const` が付いていたら「この値は初期化されて以降 金輪際変化しない」ことが強く確信できるのですが、そうじゃない場合「この値はこの先のどこかで変更されるかもしれない」という可能性を常に頭の中に置きながら読み進める必要があります。

つまり「読み下すために覚えておかなければいけないこと」が増え、脳内スタックを消費します。そのような変数が複数あった場合、（特に私のように脳内スタック容量が小さい人にとっては）とてもとてもとっっっても負担です。

# そして割れ窓理論へ

「でもでもすごく局所的だし、変数の寿命も限られたスコープ内だからいいよね!?」と思うかもしれませんが、これはいわゆる [割れ窓理論](https://ja.wikipedia.org/wiki/%E5%89%B2%E3%82%8C%E7%AA%93%E7%90%86%E8%AB%96) ってやつで、そういうものも看過できません。

# Google C++ Style Guide では...

[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) でも、そうできるところでは極力 const を使いなさい、ということが書かれています。ここには Pros/Cons も書かれていますので参考まで。

> ### Use of const
> Use const whenever it makes sense. With C++11, constexpr is a better choice for some uses of const.

# 他の言語でも

参考まで、と言えば、変数といえば immutable （つまり const）なものがデフォルトで、 mutable にしたい場合は敢えてそう書かないとイケないようになっている言語もあります。

たとえば、 Objective-C だと 文字列型 `NSString` 配列型 `NSArray` 辞書型 `NSDictionary` などはすべて immutable で、値のセットは初期化時にのみ行なえます。途中で値が変更される可能性がある場合はそれぞれ `NSMutableString` `NSMutableArray` `NSMutableDictionary` と mutable であることが明示された型を使う必要があるわけです。
（ これらはクラスなので厳密には Objective-C の言語機能そのものとは関係ありませんが、 Objective-C はその成立過程の背景から、クラスライブラリおよびランタイム実装含めてその言語の世界の構成物＝設計思想を実体化しているもの の一つである、というスタンスで書いています）

# 結論： 思いやりの心

、、、とここまでつらつらと 「私はいかにして `const` おじさんになったのか」を語ってきました。

レビューに出すあなたはひょっとしたら脳内スタック容量が大きいのかもしれませんが、そうじゃない人もいるんだ、と **思いやりの心** でぜひとも `const` には気をつけてください。いや、お願いだから。

ただヒトコト、 `const auto` とだけのPRコメントで ぶっきらぼうだしひょっとしたら機嫌悪いのか、とか思うかもしれませんが、本当は思いやりに飢えているだけなんです。優しくしてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17097/9bfff7d0-4821-df29-3132-c5dbb7bf8a43.png)
Google 翻訳を使って、ESP8266 で TextToSpeech するライブラリ

実際には、ESP8266 は喋らないので、タイトル詐欺です。

# できること
繰り返しますが、ESP8266 は一言も喋りません。
Google 翻訳を使って、喋らせたいテキストから、音声ファイル (mp3) の URL を作るだけです。
作った URL から音声ファイルのダウンロードもしません。

要は、node.js 用モジュールの **[google-tts-api](https://github.com/zlargon/google-tts)** の再発明です。

音声ファイルのダウンロードや再生は、各自で実装いただければ。

# インストール
やってみたかったので、Arduino IDE のライブラリ マネージャーに登録してみました。
**[ここ](https://github.com/arms22/arduino-wiki-ja/wiki/Arduino-IDE-1.5:-%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E4%BB%95%E6%A7%98)**に書かれたとおりに必要なファイル (library.properties とか) を作り、**[こんな感じ](https://github.com/arduino/Arduino/issues/7323)**に **[Arduino の公式リポジトリ](https://github.com/arduino/Arduino)**で issue を登録すると、翌日くらいにサクっと登録されます。

こんな簡単に公開できて、品質は全く問われないのは、ある意味怖いですね。

ライブラリ マネージャのおかげで、インストールは楽ちんです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/90361/63ec164a-43c2-eab5-1af4-dd92a267541a.png)

# 使い方

```c++
#include <google-tts.h>
#include <ESP8266WiFi.h>

const char* ssid     = "<REPLASE_YOUR_WIFI_SSID>";
const char* password = "<REPLASE_YOUR_WIFI_PASSWORD>";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  TTS tts;
  Serial.println(tts.getSpeechUrl("こんにちは、世界！", "ja"));
  Serial.println(tts.getSpeechUrl("Hello, World!"));

}

void loop() {
  // put your main code here, to run repeatedly:

}
```



メソッドは、`getSpeechUrl` のみで、第一引数に音声にしたいテキスト、第二引数に言語情報を入れるだけです。日本語の場合、`ja` を指定してください。
第二引数を省略すると、`en` (英語) として実行します。

# 今後
これが何に使えるか考えてます。
初投稿

# 投稿内容
はじめまして、こんにちは。
私の記事では、機械学習系とそれに必要な数学の知識の記事を主に書いていこうと思います。
理論を分かりやすく簡潔にまとめられたらな～と思ってます。

# 背景
私は社会人になってから機械学習に興味を持ち、いつかAIエンジニアになって仕事していきたいな～と考えています。
とりあえずこの1年でCoursera、Aidemyで機械学習について学んできました。
自分の学んだことの整理する場所がほしいな～と思い、どうせならQiitaに投稿しようってことで、これから記事を書いていこうと思ってます。

# まとめ
AIエンジニアを目指しながら、自分の学んだことを分かりやすくまとめていきます。
社会人になってAIエンジニア目指してる仲間ほしいなぁ。
![o.jpg](https://qiita-image-store.s3.amazonaws.com/0/250830/0ad449c7-a155-935a-3039-f16022a13d0e.jpeg)
Riot.jsで簡単な入力値チェック

# はじめに
少量のコードで入力値チェックを実装したので備忘録として…

# 実装
これだけです。

``` html:test.tag
<test>
 <input onInput={check_num.bind(this,"num_fx")}>
 <input ref="num_fx" type="button" value="確定">
 <script>
    check_num(nm,e){
      var f = isNaN(e.target.value);
      self.refs[nm].disabled=f;
      self.refs[nm].value=f?"数値を入力してください":"確定";
    }
 </script>
<test>
```

__個人的に嫌なところ__
引数に対象としたい要素名を入れなければならないのが少し嫌…
あと、```f?"数値を入力してください":"確定"```も固定値なのが嫌…
Riot.jsであみだくじ

# 概要
あみだくじのサイトを利用したのだけど思ったようなものがなかったので作成してみた。

__完成品は下記__
[https://hashito.biz/amidacuji/](https://hashito.biz/amidacuji/)

# 作成内容
## 仕様
あみだくじサイトは下記のような仕様にて作成した。
* 参加者名/決定項目名を入力可能とする。
* 参加人数を最初に指定可能
* あみだくじは最初隠れており、任意のタイミングで公開可能
* 公開後はどの参加者がどの項目になったかを表示可能とする

## ソースコード解説
### あみだくじ作成部分

```javascript
      self.usr_cnt    = usr_cnt;// 参加人数
      self.vlines = new Array(usr_cnt);//参加人数分用意
      for(var i=0;i<usr_cnt;i++){
        var _d=(i%2==0);
        self.vlines[i]=new Array();
        // あみだくじの横線は作成予定数の2倍用意する。
        // これは奇数と偶数部分で線が重ならないようにするため。
        for(var l=0;l<(ami*2);l++){
          var _dd=(l%2==0);
          if(_d)_dd=!_dd;
          if(l==((ami*2)-1))_dd=true;//最後は強制０ ←表示上一番下の項目が下の要素と重なるため…
          self.vlines[i].push({
            d:((_dd)?0:Math.round(Math.random()-0.2))
          });
        }
      }
```

### あみだくじ結果検索部分

```javascript
    // i = 検索対象の参加者のインデックス
    // f = クラスをどうするかの指定 ("remove" or "add"） 
    in_search(i,f,e){
      var idx      = i*1;//念の為 数値化
      var tgclass  = 'active-in';//追加/削除するクラス名
      var ng_user  = self.usr_cnt-1;//対象外参加者インデックス（最後の横線は無視する）
      if(self.status!=2)return false;//あみだくじが公開されていないときは処理しない
      self.refs['in'+idx].classList[f](tgclass);//参加者ボックスに要素を追加 or 削除
      for(var l=0;l<(ami*2);l++){
        //tate
        self.refs["tate"+idx+"-"+l].classList[f](tgclass);//縦線に要素を追加 or 削除
        //yoko 横線に要素を追加 or 削除
        if((ng_user!=(idx))&&self.vlines[idx][l].d){
          self.refs["yoko"+idx+"-"+l].classList[f](tgclass);
          idx=idx+1;//右に移動する
        }else if(idx&&self.vlines[idx-1][l].d){
          idx=idx-1;//左に移動する
          self.refs["yoko"+idx+"-"+l].classList[f](tgclass);
        }
      }
      self.refs['an'+idx].classList[f](tgclass);//項目ボックスに要素を追加 or 削除
    }
```
docker runでpipenvを使ったpythonプロジェクトを動かす

## ディレクトリ構成

```
project_name/
    Dockerfile
    src/
        Pipfile
        Pipfile.lock
        main.py
```

## Dockerfile

```
FROM python:3.6-alpine
RUN pip install pipenv
RUN mkdir /app
COPY ./src/Pipfile /app
COPY ./src/Pipfile.lock /app
WORKDIR /app
RUN pipenv install
ENTRYPOINT ["pipenv", "run"]
CMD ["python", "main.py"]
```

## build

```
docker build -t project_name .
```

## 実行
-vオプションを使うので，srcの変更後にビルドは必要ない．ただし，Pipfileが変わった場合は再ビルドが必要．

```
docker run --rm -v $(pwd)/src:/app project_name
```

## main.pyの例
### simple case

```python
def main():
    print("Hello world from python")


if __name__ == '__main__':
    main()
```

### argparse

CMDが上書きされるので，argparseを使ってpython scriptにコマンドライン引数を渡すこともできる．main.pyしか実行されない場合，ENTRYPOINTに["python", "main.py"]も含めても良いかもしれない．

```python
import argparse


def main(args):
    print("Hello %s" % args.user_name)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--user-name', type=str, default="")
    args = parser.parse_args()
    main(args)
```

実行は以下のようにすれば良い．

```
docker run --rm -v $(pwd)/src:/app project_name python main.py --user-name hoge
```
windowsにweexをインストールする

# 初めに
クロスプラットフォームのネイティブアプリを作成できるweexをWindowsにインストールする。
実機はAndroidで確認だけ。

## 1.事前準備
1. node.jsをインストールする
 - https://nodejs.org/en/
 - (nvmを使う場合はこっち) https://github.com/coreybutler/nvm-windows/releases
- yarnをインストールする
 - https://yarnpkg.com/lang/ja/docs/install/#windows-stable
- jdkをインストールする
  - http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
  - 環境変数JAVA_HOMEにjdkのパスを設定する
- Android Studioをインストールする
  - https://developer.android.com/studio/index.html?hl=ja
- Android SDKをインストールする
  - Android Studioを起動->configure->SDK Manager->Android SDKを選択してインストールする
  - configure->SDK Manager->Android SDK->SDK tools->Google USB Driverを選択してインストールする
  - 環境変数ANDROID_HOMEにAndroid SDKのパスを設定する
  - 環境変数PathにAndroid SDK直下にあるplatform-toolsのパスを設定する

## 2.weexのインストール
1. npm install -g weex-toolkit
2. weex -v
3. npmのバージョンが合わないと言われたらログに出力されたコマンドでnpmを再インストールする

## 3.プロジェクト作成
1. weex create weex_sample
2. cd weex_sample
3. weex platform add android

## 4.ローカルで実行
2. npm start

## 5.実機(Android)で実行
1. 実機をUSBでつなげる(USB debugをON)
2. weex run android
初心者も『プログラミング』

　『プログラミング』と言っても　種類がたくさんあります。  
エンジニアの方は、ふうつに使っている言葉、言語も 
＊＊　初心者には　ちんぷんかんぷん？？？？ 　
『そんな時にあなたは、どう説明してますか？』

　＜プログラミング言語＞
言語もたくさんあるので、いろいろな人が書いているので、
検索してみると、わかりやすいのがありますよ。

　HTML＋css を勉強しておくと、やはり何においてもいいのかと思います。

　プログラミングは教えてくれる人が　得意な言語を選ぶのが早いと書いてありますね。

　まず、最初に私が出会ったのは　小学生にもオススメの　
プログラミングしたら、すぐに、結果が見える　LEDが簡単に光る！　
＜＜IchigoJam ＞＞　（読み方、イチゴジャム）   
多くの人の答えは、パンにぬるジャム！と勘違いしますが、食べれないマイコンです。

緑の基盤　
私が好きだった＊宇宙開発をしている東工大の松永先生の研究室の
＊＊小型衛星CUTE＊＊に似ていた。
あ、これマスターしたら、私も　衛星も作れるかも！！と、
大きな期待を持ち、楽しんでみようかなと、購入し、はんだごてもしました。
　　高校生の時に物作りが好きで、溶接の初心者用試験も合格し、一輪車を改造したことがありますが、、、公道を走れませんでした。が＞＜

　ものづくり、デザインやアイデアが好きなこと、が、初心者には大切！
エンジニアではないので、初めて少し経つと、いろいろな壁にぶちあたり、やめてしまい、しばらくおいたままのことがありました。悩みながら、きました。
それを、初心者に伝えてあげたいです。
そして、チームを作りたいです。
　ここに書き出したのは、その思いを話したある先生からの、アドバイスです。

　小中では、文科の選挙ポスターや海外への絵画で、入賞して、NHKに出たり新聞にも乗ったことがあります。
何かをする時に、賞を取ること、褒められることは、本当に嬉しいです。

　プログラミングをして、ついた時、とっても喜んでくれる、教えてあげた人が。

楽しいことを、広げましょう。🎶

　いろいろなプログラミングがあるので、いろいろみてみて、
自分がしてみたいものを、してみたらいいのよ！


　確かに難しくて、壁があり、
教えてくれる、優秀なエンジニアは初心者の悩みがわからないから、書いてみたらと言われ、
　だから、ここをはじめました。
 
　
　もちろん食べる🍓イチゴジャム🍓　も、作りましょう！

作ることの喜びや、お弁当のでザイン配置も、　
エンジニアには大事だと　母親目線からもおすすめよ！
Rails 5 webpackerで webpack-dev-serverが動かなくなった時のメモ

Rails5 + webpack(webpacker)で、npm installとかした時にwebpack-dev-serverが以下のようなログはいて動かなくなるのでその時の対処法のメモ。

```
/bundler/gems/webpacker-aa885545e4a8/lib/webpacker/dev_server_runner.rb:47:in `exec': No such file or directory - /(perjectのパス)/node_modules/.bin/webpack-dev-server (Errno::ENOENT)
```

webpackerをyarnでアップグレードすると治る

```
yarn upgrade webpacker
```
【Ruby on Rails】インスタンス変数がViewに渡らない

# 2018/05/08 追記
あれこれ書いてますが問題解決したので追記。

```ruby:development.rb
config.reload_classes_only_on_change = false;
```
これ追加したら↓が解決した。


# ほんとシンプルなコードではまる
```ruby:posts_controller.rb
class PostsController < ApplicationController

  def index
    @posts = Post.all
  end

end
```

```ruby:index.html.erb
<% @posts.each do |post| %>
  <%= post.title %><br>
<% end %>
```

index.html.erbの方で@postsがnilだと怒られる。
コントローラーからビューに変数が渡らないぞー

# ちなみに環境
- Windows 10
- Vagrant + VirtualBox
- CentOS 6.9
- Ruby 2.4.0
- Rails 5.1.3

# Pumaサーバーを再起動したら治った

```
rails s -b 0.0.0.0
```

Pumaサーバー立ち上げっぱなしで作業していたんですが
そうするとインスタンス変数の変更は反映されないんですか？

まじか。。。
そんなばかな。。。

と思うわけだが
事実サーバー再起動すると変更が反映され
再起動しない限り反映されないのだ。


いろいろ試したところ、サーバー立ち上げっぱなしでも

- viewの変更は反映される。
- コントローラーの変更は反映されない。

という振る舞い。

サーバー立ち上げた時点でrb側はプリコンパイルされてるんかな
実行速度考えればそっちのがいいと思うけど
そういう仕様なのかな？
俺の環境がふぁびょってるのかな

うーんわからん

## 追記、根本的な解決方法はまだわからないけれど

Vagrantの共有フォルダにプログラム一式を置いていることが影響しているっぽい。
ちなみに共有フォルダはリアルタイムに同期されるプラグイン`vagrant-vbguest`を導入している。

# railsアプリを作るときはこんな感じでやっていた
```bash
cd /vagrant
rails new myapp
cd ~/
ln -s /vagrant/myapp myapp
```

railsのアプリ一式は共有フォルダに置き
homeにシンボリックリンク`myapp`を作っている。

試しに

```bash
cd ~
rails new hoge
```

としてファイルの実態もhomeに置き適当なページを作って試したところ
Pumaサーバーを再起動せずともcontrollerの変更が検知された。

共有フォルダのパーミッションかユーザー、グループあたりの問題だろうか？

viewもcontrollerもパーミッションは同じ。だのに
viewの変更は反映されて、controllerの変更は無視される
ということで

Linuxとはお戯れ程度の付き合いしかない俺にはまだ難しいようです。
R備忘録 #RStudio

#Mac→Winの日本語文字化け対策
[Tools] > [Global Options…] > [コード] > [Saving] > [Default text encoding] → "UTF-8"
（2018年4月）

*KITAMIX: R Studioの文字コード設定（Shift-JISからUTF-8など）*
http://kitamix.net/archives/default-text-encoding-with-r-studio/900
Atom環境構築 -インストールからプロキシ設定まで-

Atomの環境構築についてまとめます。この記事ではインストールからプロキシ設定の話をします。いろいろ書こうとしたら長編になりかけたのでこの2つで終わらせます。
参考までに、僕は
 * Python
 * C/C++
 * LaTeX
の編集によく使っています。そちらに関しては別記事で（というかそっちの話を本当はしたい）。ちなみに、僕の経験から言うとAtom関係の記事は、1年とか更新されてない記事に関しては情報がだいぶ古かったりするので、（いいサイトも多いので）参考にしつつ疑いつつで環境構築するのがいいと思います。

# Atomのインストール
公式からやるのが一般的かなとも思うんですけど、コマンドライン信者なのでそちらを紹介しようかなと思います。
## Windows（Chocolateyインストール済み環境）
> ```
choco install atom
```

## Linux
[こちら](https://qiita.com/N0_0b/items/2b748728cff6266d7677)を参照。

僕個人がUbuntuとWindowsしか使っていないので、Macに関してはよくわからないです。

インストールできたら、ターミナルを開いて
> ``` 
apm --version
```

を実行してみてください。なんかいろいろとバージョン情報が出ると思います。出ればOK。パッケージの管理とかは`apm`でやった方が楽だと僕は思います。

## プロキシ環境での設定
プロキシ環境下であれば、そちらの設定もしてしまいましょう。

> ```
apm config set https-proxy = http://proxy-example.com:0000
```

でいけます。`proxy-example.com`はホスト名で`0000`はポート番号です。適宜変えてください。因みに

> ```
apm config edit
```

とすると、プロキシ情報その他が書いてある`.apmrc`が何かしらのエディタで開かれるので、そちらを直接書き換えても問題ないです。`.apmrc`は`~/.atom/`の下にあるので直接エディタで開くという方法も可能です。要するに書き換えられればなんでもいい。

因みに、現在の設定はプロキシのところだけ見たければ
> ```
apm config get https-proxy
```

とすればよいですし、全部を見たいということであれば
> ```
apm config list
```

とすれば確認できます。なぜプロキシに関して厚くしてしまったか、それは僕が苦戦したから。
warning: already initialized constant Bootstrap::VERSION

最近`Rails`を初めて現在色々とお試し中ですが、`Bootstrap`を入れてみた時になんかずっとwarningが出て気になったのでその対処法を収めて見ました。

#実行環境
- Mac OS High Sierra 10.13.4
- Rails 5.1.5

#本記事で用いている用語
- user_name:自分のPCの名前
- directory:中間の階層

#warning: already initialized constant Bootstrap::VERSION
ずっとで続けてても特に問題なく動いていたのですが、さすがに気になっていたので今回は`warning`を処理していきたいと思います。

```bash:bash
$ rails s
/Users/user_name/directory/vender/bundle/ruby/2.5.0/gems/bootstrap-sass-3.3.7/lib/bootstrap-sass/version.rb:2: warning: already initialized constant Bootstrap::VERSION
/Users/user_name/directory/vender/bundle/ruby/2.5.0/gems/bootstrap-4.0.0/lib/bootstrap/version.rb:2: warning: previous definition of VERSION was here
/Users/user_name/directory/vender/bundle/ruby/2.5.0/gems/bootstrap-sass-3.3.7/lib/bootstrap-sass/version.rb:3: warning: already initialized constant Bootstrap::BOOTSTRAP_SHA
/Users/user_name/directory/vender/bundle/ruby/2.5.0/gems/bootstrap-4.0.0/lib/bootstrap/version.rb:3: warning: previous definition of BOOTSTRAP_SHA was here
=> Booting Puma
=> Rails 5.1.5 application starting in development
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.11.3 (ruby 2.5.0-p0), codename: Love Song
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```

##解決策
中国のサイトのようで、中国語は読めないので翻訳に頼りきっていますがとても参考になったので気になる方は見てみるといいかもしれないですね！
- [warning: already initialized constant Bootstrap::VERSION](https://ruby-china.org/topics/34046)

`Bootstrap`を使いたかったのと`sass`を使いたかったので、それぞれのライブラリを`Gemfile`に書き込んでいました。

```ruby:Gemfile
gem 'bootstrap'
gem 'bootstrap-sass'
```

ですが下の`gem 'bootstrap-sass'`だけでいいようなので`gem 'bootstrap'`をコメントアウトして実行してみました。

```ruby:Gemfile
# gem 'bootstrap'
gem 'bootstrap-sass'
```

```bash:bash
$ rails s
=> Booting Puma
=> Rails 5.1.5 application starting in development
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.11.3 (ruby 2.5.0-p0), codename: Love Song
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```

ちゃんと`warning`が消えました！！
お疲れ様でした！！＼＼\\٩( 'ω' )و //／／

#ちょっとした雑談
今回はちょっとしたwarningの解消だったので、短めの記事になりましたね( ´ ▽ ` )
これからも少しずつ自分の勉強ログを残していけたらなと思います!

#参考にした記事
[warning: already initialized constant Bootstrap::VERSION](https://ruby-china.org/topics/34046)
AWS Cloud9 で PHP7.1、7.2 へ変更する

AWS Cloud9 を EC2 で立ち上げると、PHPは5.6が導入されています。
PHP7系へ上げるには、通常のLinux同様にyumでインストールが可能です。

執筆時点では、Amazon Linux AMI release 2018.03 が適用されていました。

```bash
ec2-user:/ $ cat /etc/system-release
Amazon Linux AMI release 2018.03
```

### yumを更新します

```bash
sudo yum -y update
```
### PHPを導入します

PHP 7.1 の場合

```bash
sudo yum -y install php71 php71-mbstring php71-pdo
```

PHP 7.2 の場合

```bash
sudo yum -y install php72 php72-mbstring php72-pdo
```

### PHPへのリンクを変更します

/usr/bin/php からPHP5.6へのリンクが張られているため、PHP7への張替えを行います

#### リンクの削除

```bash
sudo unlink /usr/bin/php
```
#### リンクの張り直し

```bash
sudo ln -s /etc/alternatives/php7 /usr/bin/php
```

以上で、PHPのバージョンが変更完了です。

```bash
ec2-user:/usr/bin $ php -v
PHP 7.1.15 (cli) (built: Mar 27 2018 18:02:08) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
```
[ Rails初心者向け ]Rails5.1以上のバージョンでjQueryを使う

初心者の方で、jqueryを使ってviewをいじったり、Ajax通信を実装したりしようとしてググってきたコードを貼り付けても動かないということは多いと思います。

それは、Rails5.1から仕様変更により、jQueryが標準実装されなくなったためです。

安心してください！めちゃくちゃ簡単です！

慌てることなく、しっかりと使えるようにやっていきましょう！

```app/assets/javascript/application.js
//= require jquery
//= require jquery_ujs
```
次にGemfileにgemを追加します

```
gem 'jquery-rails'
```
追加し終わったらターミナルで

```
$ bundle  
```
を実行しましょう。
これjQueryを使うことができると思います！
railsアプリをherokuで公開して動かない時にはgit push master originのみでなくdb:migrateが必要

ruby on railsのチュートリアルをやっていて、
herokuにコードのpushは出来ているっぽいのに
アクセスしても反映されないとき。

下記コードによってDBの作成が必要だった。
railsのアプリを作ったフォルダに行って以下のコードを実行。

```terminal:terminal
heroku run rake db:migrate
```
railsで作ったDBの中身を確認する

ターミナルで

```terminal:terminal
rails dbconsole
```

と打つと、

```terminal:terminal
sqlite>
```
となるので、

```terminal:terminal
sqlite>.headers on
```

として、カラム名の表示をONにして、SQL文を打つと見られる。

```terminal:terminal
sqlite> select * from users;
id|name|email|created_at|updated_at
1|Kohei！！|kishimotogmail@gmail.com|2018-04-15 15:45:22.055691|2018-04-15 15:45:45.757233
```

exitでターミナル終了

```terminal:terminai
sqlite> exit
```
依存関係逆転の原則(DIP: Dependency Inversion Principle)

## 依存関係逆転の原則
- 上位のモジュールは下位のモジュールに依存してはならない
 - どちらのモジュールも「抽象」に依存すべきである
- 「抽象」は実装の詳細に依存してはならない
 - 実装の詳細が「抽象」に依存すべきである
- 従来の開発手法の目標の一つは上位モジュールから下位モジュールの呼び出し方を定義したプログラムの階層構造を作ることだった
- 上手に設計されたオブジェクト指向プログラムの構造は従来の手続き型で見慣れた依存構造を**逆転**したものになる
- アプリケーションの存在理由を決定づけているのは上位のモジュールであるにも関わらず、上位モジュールが下位モジュールに依存すると下位モジュールの変更が直接上位モジュールに影響を与え、上位モジュールまで変更を余儀なくされる
- 立場的にアプリケーションの方針を上位レベルのモジュールが実装の詳細を担当している下位レベルのモジュールに影響を与えるべきである


## 「抽象」に依存する
- 依存関係逆転の原則を一言で言うと「抽象に依存せよ」という経験則だと言える
 - 荒削りではあるが的確にDIPの本質を言い当てている
- この原則はプログラムは具体的なクラスに依存してはいけないこと、プログラム内の関係は全て抽象クラスかインターフェースで終結すべきであることを提言している
- この経験則によると:
 - 具体的なクラスへのポインタやリファレンスを保持するような変数があってはならない
 - 具体的なクラスから派生するクラスがあってはならない
 - 基本クラスで実装されているメソッドを上書きしてしまうようなメソッドがあってはならない

## 結論
- 伝統的な手続き型のプログラミングでは方針が実装の詳細に依存する構造になる
 - そうなると「方針」が詳細の変更に影響されるので好ましくない
- オブジェクト指向プログラミングでは方針と実装の詳細を「抽象」に依存させることで悪しき依存関係を**逆転**させることができる
- 依存関係の逆転が織り込まれていることこそ、良いオブジェクト指向設計の顕著な特徴と言える
- 依存関係が逆転していればオブジェクト指向設計と言え、依存関係が逆転していなければ手続き型設計
- 依存関係逆転の原則は、オブジェクト指向技術の様々な利益を享受するために必要不可欠な下位レベルのメカニズム
- 変更に耐えられるコードを構築するためにも非常に重要
- この原則を適用すれば抽象と実装の詳細は完全に切り離され、コードを保守するのがずっと楽になる