OmniAICreator/Qiita-1.07M huggingface dataset:
日記アプリのMVP化工程記録・2

# 着手
[前回の記事](https://qiita.com/poin-settia/items/4fd1b864fec8b6365acf)で宣言したとおり、勉強用日記アプリのMVP化に取り掛かりました。
で、
> 当然PresenterをViewとModelの間に設置する事になる。

みたいな事書きましたが、いきなりPresenterをおきました！なんて実装は普通しません。
（普通しません、なんて言い出したら途中からアーキテクチャ変えるなんて修正の方がありえませんが、勉強用として反面教師にしといてください。）

# MVP化ブランチは
https://github.com/poin-settia/Diary/tree/feature-MVP
として専用に切り分けました。万が一を考えて元のブランチは `master`として残しておきます。
執筆時点では[Presenter / Repository / Contract の新規作成](https://github.com/poin-settia/Diary/commit/2b79ff82ac46a1e4e9c78ba76967f61d28930219)がコミットされたところです。

# 今回着手したこと
コミット名にも書きましたが新しく `Presenter `と`Repository `、`Contract ` クラスを増やしました。Presenterを増やすだけでなくRepositoryクラスも必要になったのです。

[前回の記事](https://qiita.com/poin-settia/items/4fd1b864fec8b6365acf)でクラス図を展開しましたがModelにはPersonRealmHelperという名前のRealmDBのクエリをまとめたクラスがあります。
かといってFragmentにごちゃまぜになってるDB操作をHelperに移設する訳にもいかないので、
そこらへんのデータ整形はRepositoryにお願いする事になります。

## Contract
MVP化のあかつきにはModel,View,Presenterは皆Contractインタフェースを実装することになります。
Contractの中身はMVPがそれぞれどんな役割を持っているのかを明確に縛る為、事前に機能の切り出しが必要になります。

## 機能の切り出し準備
最大の問題点である `Fragmentに色んな機能ごちゃまぜな件 `を解決するべく、まずはこんな事から始めました。

```java:PersonFragment
// 元の場所
int fromIndex = viewHolder.getAdapterPosition();
// 移動後の場所
int toIndex = target.getAdapterPosition();
// ★リストの入れ替えイベント・Presenter
// ★インデックスの入れ替えを行う・Model
indexReplace(fromIndex,toIndex);
// ★入れ替え後の通知を行う・View
mAdapter.notifyItemMoved(fromIndex,toIndex);
return true;
```

★マークが入ったコメントがありますね。
ここはItemTouchHelper内のonMove、つまりリストの入れ替えイベントが発生した歳に呼び出されるわけですが、機能でいうと３つに分けられます。
1. リストの入れ替えイベントが発生する
2. インデックスの入れ替えを行う
3. 入れ替え後の通知を行う
ちょうどPresenter、Model、Viewの順番で機能が細分化できそうなので、コメント末尾に移管先のクラス名をつけておきました。Contractには★コメントに沿って実装していけば良いわけです。
MVP化のあかつきには
1. Presenterにリストの入れ替えイベントが通知される、
2. PresenterがModel（Repository）に対してインデックスの入れ替えを指示する
3. Modelからの完了通知をうけて、PresenterはViewに対して入れ替え後の通知を行うよう指示を出す
といった切り分けが叶いそうですね。


# 困難は分割せよ
最後になんかそれっぽい事書いてますが、MVPもMVVMも機能が分割することによって役割が明確化され、難しい困難も分割できてゆくのではないのではしょうか。

結局のところ、困難になる前にちゃんと設計してMVPで書いておけばよいって話になるんですが、そこは勉強用、ということで割きましょう。

# 次回
★マーク通りにContractは実装しており、あとは機能の移管を勧めていくことになると思う。
きっとRepositoryの移管作業らへんでRxJavaを導入しそうな気配。
Mac上でVimをGUIアプリのように起動する


## Vimビギナーの課題
vimを使い始めたいけど、Finder上でファイルを触ることが多く、そこからTerminal→vim起動だと手間が多く、挫折が多い。手軽に起動できる環境が欲しい。
「Dock上のアイコンクリックでvim起動。テキストファイルをダブルクリックでvim上で開く」などGUIのテキストエディタのように起動したい。

##環境
OS X El Capitan 10.11.6 
Automator Version 2.6 

## 解決法
Automatorを用いて、Terminal上のVim起動をアプリ化する。

###1. Automatorを起動,`⌘+N`で新規でAppliationを作成
ファイル名はVimLauncherとかで。
![Screen_Shot_2017-10-31_at_02_34_25.png](https://qiita-image-store.s3.amazonaws.com/0/77619/8a153c00-021b-f0eb-e99b-0a1c829cfc17.png "Screen_Shot_2017-10-31_at_02_34_25.png")


###2. 検索バーから`run`と検索、ダブルクリックでRun Applescriptを右のワークフローに追加
![Screen_Shot_2017-10-31_at_02_37_29.png](https://qiita-image-store.s3.amazonaws.com/0/77619/02e50cb8-9d92-c2db-f0ed-c734ec550b14.png "Screen_Shot_2017-10-31_at_02_37_29.png")
今回はApplescriptでターミナルを起動、スクリプトを実行させますが、これはJavascriptでも記述可能です。こちらで書きたいなら、Run Javascriptをワークフローに追加しましょう(コードはご持参ください)。このコードはmac標準アプリのScript Editorでコーディング、実行できて、試すには良いです。



###3. テキストボックスに以下を貼り付け

```
on run {input}
	if input is {} then
		set cmd to "vim"
	else
		set the_path to POSIX path of input
		set cmd to "vim " & quoted form of the_path
	end if
	tell application "System Events" to set terminalIsRunning to exists application process "Terminal"
	tell application "Terminal"
		activate
		if terminalIsRunning is true then
			do script with command cmd
		else
			do script with command cmd in window 1
		end if
	end tell
end run

```
今回起動アプリはvimとなっていますが、僕はnvimに書き換えneovimを起動しています。最初のif文でinputであるファイルパスが渡されたかどうかを分岐しています。inputがなければ純粋にvimを起動します。tell application "System Events"の意味はよくわからないままのコピペです。


###4. 保存してapp化し、/System/Library/Applicationsに追加
###5. Dockに追加やテキストファイルのダブルクリックvim起動化
Dockに追加は、appファイルをDockにドラッグで。テキストファイルのダブルクリックvim起動化は、そのテキストファイルを「右クリック→情報を見る」で起動アプリを選択します。「Change All」を選択でその拡張子のファイルはすべて選択したアプリで起動されます。

![Screen_Shot_2017-10-31_at_03_38_35.png](https://qiita-image-store.s3.amazonaws.com/0/77619/26c2da03-e1c5-42cf-9fa9-59d5453af5bf.png "Screen_Shot_2017-10-31_at_03_38_35.png")





##おまけ
アプリなんだからアイコンがデフォルトのままは嫌ですね。
これは変更は可能です。最高のアイコンにしちゃいましょう。

![Screen_Shot_2017-10-31_at_02_57_32.png](https://qiita-image-store.s3.amazonaws.com/0/77619/348aae85-d981-62dc-6703-021092f9d4a4.png "Screen_Shot_2017-10-31_at_02_57_32.png")

1. 好きな画像をpngで作ります。常識的に背景は透過にしましょう。
2. https://iconverticons.com/online/ でアイコンに変換しダウンロード
3. ダウンロードしたファイルを右クリック→「情報を見る」でポップアップ。左上のアイコンを選択しコピー
4. アイコンを変えたいアプリを右クリック→「情報を見る」でポップアップ。左上のアイコンを選択し貼り付け。


##参考
* https://superuser.com/questions/139352/mac-os-x-how-to-open-vim-in-terminal-when-double-click-on-a-file
* https://qiita.com/ikmski/items/d95a9dab3ab33b311304
Max/MSPで外部プロセスを実行する（Windows/Mac）


`aka.shell`や`shell`でもよいのですが、Windowsでも使用したい事があり、mxjで書くようにしました。

* 標準出力はそのままmax consoleへ垂れ流しています。
* 環境変数は特に設定していません。（必要であればProcessBuilderのenvironmentに設定すればよいかと）
* 動けばいいで書いてるので何かあったらすみません。。 :bow:

# mxjの実装
```java
import com.cycling74.max.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class MxjExec extends MaxObject {
    private boolean mIsRunning;
    private Thread mRunThread;
    private Process mProcess;

    public MxjExec() {
        mIsRunning = false;
        declareIO(1, 0);
    }
    public void exec(Atom[] args) {
        if (mIsRunning) {
            post("Running");
            return;
        }

        String[] cmds = new String[args.length];
        for (int i = 0; i < args.length; i++) {
            cmds[i] = args[i].getString();
        }

        try {
            mIsRunning = true;
            ProcessBuilder pb = new ProcessBuilder(cmds);
            pb.redirectErrorStream(true);

            mProcess = pb.start();
            post("Execute Process");
            mRunThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    String str;
                    BufferedReader br = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
                    try {
                        while((str = br.readLine()) != null) {
                            post(str);
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            br.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        mIsRunning = false;
                    }
                }
            });
            mRunThread.start();
        } catch (Exception e) {
            mIsRunning = false;
            e.printStackTrace();
        }
    }

    public void stop() {
        try {
            if (mProcess != null)
                mProcess.destroy();
            mProcess = null;
            mIsRunning = false;
            post("Stop Process");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void notifyDeleted() {
        stop();
    }
}
```

ビルド後にclassファイルをcodeディレクトリに入れて下さい。

# リポジトリ
* https://github.com/rinsyan0518/MxjExec

#使い方
`exec`から始めればプロセスが実行されます。
私がMacでよくやるのはパッチを起動しているときは、以下のように`caffeinate`コマンドでスリープにならないようにしています。
![screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/51292/7579c9f9-a14a-4679-1930-7975fdd39e38.png "screenshot.png")

Windowsでも`exec echo hello`みたいな感じで実行されます。
Vue.jsでFirebaseを始めよう 4.送信してみる編

### データをサーバーに送信してみよう
なんでもいいから、とりあえずサーバーに送信してみよう。バックエンドに何も実装してないのに送信したらちゃんと保存してくれるfirebaseのいい加減さを体験してみよう。

まずtemplateに送信ボタンを追加する。

```HTML
<button type="button" class="btn btn-default" @click="pushData">
  送信
</button>
```

関数`pushData`の実装。データベースのインスタンスも忘れずに。

``` Javascript
export default {
  ...
  methods: {
    ...
    pushData () {
      firebase.database().ref('myBoard/').push({
        name: 'test',
        message: 'foo'
      })
    }
  }
}
```

ブラウザの画面に「送信」ボタンが出てるから、勇気を出して押してみよう……なにも起こらない。データベースを表示する部分がまだ実装していないからだ。firebaseのconsole画面へ行って確認してみよう。

<img width="772" alt="fire-vue_–_Database_–_Firebase_console.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/a8a51bdb-6514-9196-4ff0-c109e7363f2f.png">

おぉ〜、サーバー側にしっかりと送信できたではないか？！ これでfirebaseへ第一歩を踏み出した！

[Vue.jsでFirebaseを始めよう 5.リストを表示させる編](https://qiita.com/renowan/items/b8222f2b873cc29a462d)
Vue.jsでFirebaseを始めよう 3.ユーザーログイン編

Firebaseは数種類のログイン方法を提供している。Twitter, Facebookなどメジャーなものが簡単に使えるようになっている。今回はシンプルに作りたいので、auth設定で匿名ログインを許可し、ユーザーはすべて匿名ユーザーとしてアプリケーションにログインして使う。

### ログイン設定
メニュー「Authentication」から「ログイン方法」に入って、「匿名」を選択する。これで匿名ログインできるようになる。

<img width="757" alt="fire-vue_–_Authentication_–_Firebase_console.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/a67066cb-04ed-10b2-f381-3453bf2a72cb.png">

### フロント環境の立ち上げ
```
npm run dev
```

### 認証しているかを確認
App.vueの`created`にユーザー認証が済んでいるかを確認するコードを書いてみよう

``` Javascript
export default {
  ...
  created () {
    firebase.auth().onAuthStateChanged( user => {
      if (user) {
        // User is signed in.
        console.log('is login.')
      } else {
        // No user is signed in.
        console.log('No user is signed in.')
      }
    })
  },
}
```
まだなにもしていないので、consoleは`No user is signed in.`と出るはずだ。

### 匿名でログインする機能を実装
認証しないと何も始まらないので、ワンクリックで匿名ログインするボタンを実装しよう。

templateタグの中にボタンを追加する

``` html
<button type="button" class="btn btn-default" @click="login">
  匿名ユーザーでログイン
</button>
```

scriptタグで関数`login`を実装しよう

``` Javascript
export default {
  ...
  methods: {
    login () {
      firebase.auth().signInAnonymously().then(e => {
        // ログイン成功
        console.log(e)
      }).catch((error) => {
        // エラーメッセージ
        var errorCode = error.code;
        var errorMessage = error.message;
        console.log('エラーメッセージ', errorCode, errorMessage)
      });
    },
  }
}
```

ブラウザ上の「匿名ユーザーでログイン」ボタンを押してみよう。通信が発生してこう帰ってきたらログイン成功だ。そして一度ログインしたら、Local Storageに情報が残るので、リロードしてもログイン状態は維持される。

<img width="574" alt="vue-fire.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/7f8b1545-092e-313c-9a81-14b8cf88b262.png">

これ以後はすべてログインした状態で作業を進めるので今一度ログインできたか確認しよう。

[Vue.jsでFirebaseを始めよう 4.送信してみる編](https://qiita.com/renowan/items/6f7823b20491de63011e)
Vue.jsでFirebaseを始めよう 2.Vueプロジェクト準備編

vueのプロジェクトを作成する。今回はvue-cliを使うことにした。vue-cliをインストールしてない人はこれを
```
npm install -g vue-cli
```

### vue-cliでプロジェクトを作成
フロント用vueプロジェクト「vue-fire」を作成する。最低限しか使わないからオプションは全部「No」にする。
<img width="377" alt="pic_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/fd2c8c8e-b77f-fc75-693e-43643d45d41f.png">

いつもの
```
cd vue-fire
npm install
```

### プロジェクトを起動
```
npm run dev
```
下の画面が出たら成功。
<img width="688" alt="vue-fire.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/eaceb982-f55e-d683-c853-b71d272b7407.png">

### フロント用firebase設定コードを取得
「ウェブアプリにFirebaseを追加」を押して
<img width="947" alt="fire-vue_–_概要_–_Firebase_console.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/d5bb346e-84f4-fd73-dc82-a443268592db.png">

コードをHTML下部に貼り付ける

<img width="775" alt="fire-vue_–_概要_–_Firebase_console.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/63b3917c-fba2-8457-9c69-31363bbe7ce7.png">

### App.vueを空にしておく
```
<template>
  <div id="app">

  </div>
</template>

<script>

export default {
  name: 'app',
  components: {

  }
}
</script>

<style>

</style>
```

これで準備完了だ。次はFirebaseと連携しながらvueをコーディングしていく。
[Vue.jsでFirebaseを始めよう 3.ユーザーログイン編](https://qiita.com/renowan/items/bf1747aabc874bfd85ab)
Vue.jsでFirebaseを始めよう 1.プロジェクト作成編

フロント専門の人、作品を作るときちょっとした永続化をしたいときあるよね？自分でバックエンドをゴニョゴニョするのはかなりエネルギーが必要だ。最低限の労力で、javaやらphpやら触らずにバックエンド実装できるのがFirebaseだ。

このチュートリアルでVueとfirebaseで掲示板っぽいものを作ってみよう。

※Firebaseについては[この辺とか](https://qiita.com/alingogo/items/100e6c62d849058e89f9)を参照してください。

全編
[Vue.jsでFirebaseを始めよう 1.プロジェクト作成編](https://qiita.com/renowan/items/559bfb721362134b715c)
[Vue.jsでFirebaseを始めよう 2.Vueプロジェクト準備編](https://qiita.com/renowan/items/96d1116e8635455abca9)
[Vue.jsでFirebaseを始めよう 3.ユーザーログイン編](https://qiita.com/renowan/items/bf1747aabc874bfd85ab)
[Vue.jsでFirebaseを始めよう 4.送信してみる編](https://qiita.com/renowan/items/6f7823b20491de63011e)
[Vue.jsでFirebaseを始めよう 5.リストを表示させる編](https://qiita.com/renowan/items/b8222f2b873cc29a462d)
[Vue.jsでFirebaseを始めよう 6.入力＆送信編](https://qiita.com/renowan/items/2717cc28d4763deb433c)

## 始める前に

### ゴール設定
簡単な掲示板を作る。
フロントエンド：Vue.js
バックエンド：Firebase

### 注意
本稿はあくまでFirebaseを触る第一歩という目的で書いたもので、作品やサンプルなどちょっとしたものを作るなら問題ないが、サービスとなると別途データ構造やらルール設定を勉強してください。

### 必要なスキル
- vue.js 2.xの基本スキル
- jsonでデータを扱う知識
- やる気

## 必要なもの
- Firebaseプロジェクト
- vue-cliをインストール `npm install -g vue-cli` or [ここ参照](https://qiita.com/sin_tanaka/items/29769266b3b078ea0f7c)

## ではスタート

まずはGoogleへログインして[firebaseのコンソール画面](https://console.firebase.google.com/)へ
### 新規プロジェクトを作成
<img width="676" alt="Firebase_console_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/f1ed9b9f-bbe5-e30a-91ab-ed4b272dd95d.png">

### プロジェクト名を入力
<img width="511" alt="Firebase_console_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/a5ab6507-ea46-77de-c5b6-c120b8593c0f.png">

### 認証方法設定
<img width="769" alt="Firebase_console_3.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/aca58180-a476-0e02-3567-dfa57c670c3e.png">

<img width="830" alt="Firebase_console_4.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/035f195f-4a8a-332d-5a28-f6c93d231b6e.png">

### 今回は匿名にする
<img width="838" alt="Firebase_console_5.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/3d3768a6-8f7a-a384-9586-f2864c3439e6.png">

### 準備完了
firebaseの設定はこれで完了。とりあえず、プロジェクトのデータベースを確認してみよう。「fire-vue-3b40d」はデータベースのルートだ。まだ何も入っていない空の状態だ。
<img width="764" alt="Firebase_console_6.png" src="https://qiita-image-store.s3.amazonaws.com/0/2972/bdab5b54-e85e-309a-2bdc-f46a02c702c7.png">

次はVueプロジェクト準備編。
[Vue.jsでFirebaseを始めよう 2.Vueプロジェクト準備編](https://qiita.com/renowan/items/96d1116e8635455abca9)
Linuxでユーザを追加する

今更ですが、必要時に毎回調べているので今後はきちんと覚えたい。

**ユーザ追加**

```
/usr/sbin/useradd ユーザ名
 -u [uid]　ユーザID指定
 -g [group]　グループ指定
 -d [home dir]　ホームディレクトリ指定
 -m ディレクトリ作成
 -s [/bin/sh] シェル指定

例）$ /usr/sbin/useradd -u 888 -g users -d /home/test -m test
```

**ユーザ更新**

```
/usr/sbin/usermod ユーザ名
 -u [uid] ユーザID変更
 -g [group]　グループ変更
 -s [/bin/sh]　シェル変更
```

シェルや、グループの指定方法はいつも忘れてファイルを直編集しているので、きちんとコマンドで制御したい。
Web超簡易電卓 HTML＋JavaScript

#超簡易電卓

3つテキストボックスに入力してボタン押すだけのページです。

![スクリーンショット 2017-10-31 1.50.11.png](https://qiita-image-store.s3.amazonaws.com/0/180727/e05e93bd-e722-133d-cd0a-263c10d92912.png)


getElementByIdメソッドで、（　）内に指定されたidを持つ要素を丸ごと取得する。
（getElementByIdの引数は変数でも代替可能）
（同じIDが同じドキュメント内に重複していた場合は、最初に合致した要素が取得される）

```html

<html>
<head>
<title>Tutorial: Add and Multi</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>

<h1>Tutorial: Add or Multi</h1>

<form action="/tutorial/addMulti/" method="get">
	<input type="text"  id="arg1"/>
	<input type="text"  id="arg2"/>
	<input type="text"  id="arg3"/>
	<input type="button" name="test"   value="足し算" onclick="OnButtonClickPlus();"/>
	<input type="button" name="test"   value="掛け算" onclick="OnButtonClickMulti();"/>
	<span id = "output">=結果</span>
</form>

<script type="text/javascript">
function OnButtonClickPlus() {
		 		 	
		 	//変数定義は基本的には、var 変数名;
            //innerTextで開始タグと終了タグの間の文字列（要素の内容＝コンテンツ）を取ってくる
			var outInnerText = document.getElementById("output").innerText;
			console.log(outInnerText);
			var outTextContent = document.getElementById("output").textContent;
			console.log(outTextContent);
			var outInnerHTML = document.getElementById("output").innerHTML;
			console.log(outInnerHTML);
			
			//document.getElementById("arg1").valueで、フォームの入力内容を読み取る
			var num1 = parseInt(document.getElementById("arg1").value);
			var num2 = parseInt(document.getElementById("arg2").value);
			var num3 = parseInt(document.getElementById("arg3").value);
			
			var result = num1 + num2 + num3;
			document.getElementById("output").textContent = result;
}
	
function OnButtonClickMulti() {
		 
			var out = document.getElementById("output").innerText;
			console.log(out);
						
			var num1 = parseInt(document.getElementById("arg1").value);
			var num2 = parseInt(document.getElementById("arg2").value);
			var num3 = parseInt(document.getElementById("arg3").value);
			
			var result = num1 * num2 * num3;
			document.getElementById("output").textContent = result;
}
</script>
 
</body>
</html>
```

innerTextとinnerHTMLの違いは理解していますが、textContentとの違いはまだ良くわからず。
基本的には同じ働き、というざっくりしたイメージの現在です。とりあえず上記コードでは違いは発生しませんでした。

javascriptでは変数のデータ型が宣言時にvarで統一されているため、
データ型に関してはかなり緩いですが、緩過ぎて戸惑います。。。

※個人的メモ
JavaScript は動的型付け言語であるため、変数宣言時にデータ型を指定する必要がなく、またスクリプト実行時に必要に応じてデータ型が自動的に変換される。
秘密鍵から公開鍵を作成する

秘密鍵だけしか見つからなかった時以下で公開鍵を取得できます。
これで標準出力に出力されます。

```
$ /usr/bin/ssh-keygen -y -f <秘密鍵のパス>
```
[-y] This option will read a private OpenSSH format file and print an OpenSSH public key to stdout.


※以下、全く関係ないメモです
今日、ファイルをtarでまとめている時に利用している
オプションの意味を考えてしまいました。
まとめるとき：-zcvf
内容見るとき：-ztvf
展開するとき：-zxvf
z] --gzip filter the archive through gzip
c] --create create a new archive
v] --verbose verbosely list files processed
f] --file use archive file or device ARCHIVE
t] --list list the contents of an archive
x] --extract, --get extract files from an archive
rubyのモジュールとクラスの概念について

クラスは、オブジェクトになることが出來る。要するにインスタンスの能力をもち、インスタンスメソッドやクラスメソッドを格納することができる。

モジュールはインスタンス能力はないが、メソッドを格納することができる。

また、クラスにモジュールを取り込むことをmixinといい、コードでは、includeという記述を使う。
isinstance(XXX, type)のtypeってなんだ？


unittestパッケージのソースコードリーディングをする中で遭遇したisinstance(XXX, type)について整理します。Pythonのバージョンは3.6.3です。

#isinstance関数とは
[公式ドキュメント](https://docs.python.jp/3/library/functions.html#isinstance)にあるように，あるオブジェクトの型（Class）を判定するときに利用します。

利用例

```py3:
>>> a = 2
>>> isinstance(a, int)
True
>>> b = [1,2]
>>> isinstance(b, list)
True
```
#unittestでの利用方法

unittestのmain.pyの236行目に以下のコードがあります。

```py3:
236  if isinstance(self.testRunner, type):
```
この第2引数に指定されている"type"は何でしょうか。これは上記で示した"int","list"といったクラスではなく，メタクラスと呼ばれるものです。

#メタクラスとは？
Pythonのオブジェクトはクラスのインスタンスとして生成されます。また，Pythonではクラスもオブジェクトです。そして，クラスはメタクラスのインスタンスとなります。このため，上記で示したunittestのコードは，"self.testRunner"オブジェクトがtypeのインスタンスであるかどうか，つまりクラスであるかどうかを判定しています。main.py:234行目の上を確認すると，isinstance関数の第1引数である"self.testRunner"にrunner.pyで定義されたTextTestRunnerクラスがif文を満たす場合に代入されることからもそれがわかります。

```py3:
232  if self.testRunner is None:
233      self.testRunner = runner.TextTestRunner
234  if isinstance(self.testRunner, type):
```

isinstanceの例からも，そのことがわかります。

```py3:
>>> isinstance(int, type)
True
>>> isinstance(list, type)
True
```
#Pythonにおけるtypeとは
typeは型を返す組み込み関数として利用するのが一般的ですが，引き数を３つ指定した場合，クラスを生成することができます。

```py
>>> type(list)
<class 'type'>
>>> a = list()
>>> type(a)
<class 'list'>
```
```py3
>>> X = type('X', (object,), dict(a=1))
>>> isinstance(X, type)
True
>>> X.__dict__
mappingproxy({'a': 1, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'X' objects>, '__weakref__': <attribute '__weakref__' of 'X' objects>, '__doc__': None})

>>> class Y(object):
...     a = 1
... 
>>> isinstance(Y, type)
True
>>> Y.__dict__
mappingproxy({'__module__': '__main__', 'a': 1, '__dict__': <attribute '__dict__' of 'Y' objects>, '__weakref__': <attribute '__weakref__' of 'Y' objects>, '__doc__': None})
```

typeからみれば，すべてのクラスはインスタンスです。これはすべてのクラスの親クラスとなるobjectも例外ではありません。また，type自身もtypeのインスタンスです。

```py3:
>>> isinstance(object, type)
True
>>>
>>> isinstance(type, type)
True
```

#typeとobjectの関係
typeはメタクラスなので，すべてのクラスのクラスとなります。このため，objectもtypeのインスタンスになりますが，継承関係においては，objectがtypeの親クラスとなります。

```py
>>> issubclass(type, object)
True
>>> issubclass(object, type)
False
```
BracketsのショートカットをAtom風にする

#BracketsのショートカットをAtom風にする
Atomのショートカットに慣れすぎてしまっているので、BracketsのショートカットをAtomに寄せた。

##keymap.jsonの修正
`デバッグ→ユーザーキーマップを開く`でkeymap.jsonを開く

```json:keymap.json
{
    "documentation": "https://github.com/adobe/brackets/wiki/User-Key-Bindings",
    "overrides": {
      "Ctrl-D":"cmd.addNextMatch",
      "Ctrl-Shift-D":  "edit.duplicate",
      "Ctrl-Shift-K":  "edit.deletelines",
      "Ctrl-Down":  "edit.lineDown",
      "Ctrl-shift-Down":  "view.scrollLineDown",
      "Ctrl-Up":  "edit.lineUp",
      "Ctrl-shift-Up":  "view.scrollLineUp"    
    }
}
```
自分が主に使っているのを修正したけど、まだまだいっぱいあると思う。 :kobito:
Kotlinプロジェクトに対してsourceJarを生成するときにソースコードがjarに含まれないときの対処法

Kotlinでライブラリを作るときに、sourceJar内にソースコードのファイルが上手く入らなくて小一時間悩んだので、簡単にまとめておきます。

## 環境

- macOS Sierra
- Android Studio 3.0
- Gradle 4.1
- Android Plugin for Gradle 3.0.0
- kotlin, kotlin-gradle-plugin 1.1.51

## 問題

たとえば、Androidプロジェクトを新規に立ち上げて、 `app/build.gradle` にこんな感じの設定を書いて、

```app/build.gradle
//...

task sourceJar(type: Jar) {
    classifier = "sources"
    from android.sourceSets.main.java.sourceFiles
}
```

定義したタスクを実行すると、 `app/build/libs/app-sources.jar` が生成される

```
$ pwd
/path/to/sample

$ find app/src/main -name "*.java"
app/src/main/java/com/litmon/app/sample/MainActivity.java

$ ./gradlew sourceJar
$ ls app/build/libs/
. .. app-sources.jar
```

この `app-sources.jar` の中身を見てみると、

```
$ jar tf app/build/libs/app-sources.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/litmon/
com/litmon/app/sample/
com/litmon/app/sample/MainActivity.java
```

javaのソースコードは含まれている（これは想定通り）

このプロジェクトの `MainActivity.java` をKotlinに変換して、再度gradleタスクを走らせてjarを再生成して、中身を見てみると、

```
# After Convert Java File to Kotlin File
$ find app/src/main -name "*.kt"
app/src/main/java/com/litmon/app/sample/MainActivity.kt

$ ./gradlew sourceJar
$ jar tf app/build/libs/app-sources.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/litmon/
com/litmon/app/
com/litmon/app/sample/
```

なんと `MainActivity.kt` ファイルが含まれていない！！（想定外）

## 解決策

`app/build.gradle` の `from ~~~.sourceFiles` の部分を、 `from ~~~.srcDirs` にすると解決する

```app/build.gradle
//...

task sourceJar(type: Jar) {
    classifier = "sources"
    from android.sourceSets.main.java.srcDirs // <- ここ
}
```

```
$ ./gradlew sourceJar
$ jar tf app/build/libs/app-sources.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/litmon/
com/litmon/app/
com/litmon/app/sample/
com/litmon/app/sample/MainActivity.kt
```

## 原因は？

よく分かりません。詳しい方がいたら教えてください :cry: 
http://google.github.io/android-gradle-dsl/current/com.android.build.gradle.api.AndroidSourceDirectorySet.html#com.android.build.gradle.api.AndroidSourceDirectorySet:sourceFiles

> FileTree sourceFiles
> The list of source files as a FileTree

うーん。
分からん。

https://developer.android.com/studio/build/build-variants.html#configure-sourcesets とかでは、 `android.sourceSets.main.java.srcDirs` を触っているので、基本的にここにソースコードが含まれると思ったほうがいいってことなんだろうか？

以下、上記サイトから一部抜粋

```
android {
  ...
  sourceSets {
    // Encapsulates configurations for the main source set.
    main {
      // Changes the directory for Java sources. The default directory is
      // 'src/main/java'.
      java.srcDirs = ['other/java']
```

## ちなみに

Javaプロジェクトの方で `srcDirs` にしても、問題なくjarファイルにソースコードは含まれます

```app/build.gradle
//...

task sourceJar(type: Jar) {
    classifier = "sources"
    from android.sourceSets.main.java.srcDirs
}
```

```
$ ./gradlew sourceJar
$ jar tf app/build/libs/app-sources.jar
META-INF/
META-INF/MANIFEST.MF
com/
com/litmon/
com/litmon/app/
com/litmon/app/sample/
com/litmon/app/sample/MainActivity.java
```

## 結論

基本は `from android.sourceSets.main.java.srcDirs` を使っていきましょう。
map関数の返り値

同じ内容は溢れてるけど、自分がハマったのでメモ。

# map関数
なにかしらの関数にリストの全要素を読ませるための高階関数。
無名関数(lambda)の場合はこんな感じ。

```
map(lambda x: x + 2, [1,2,3,4])
```

defにするなら

```
def add(x):
    return x + 2

map(add, [1,2,3,4])
```

# 返り値
で、問題はこのmapの戻り値。mapはリストに対して関数を実行した値を返すわけではなく、**イテレータを返す**。リストを返すわけではない。

つまり

```
print(map(lambda x: x + 2, [1,2,3,4])
```

とするとイテレータを含むmapオブジェクトが返ってくる。
そのまま扱うにはいいが、例えば

```
output = map(lambda x: x+2, [1,2,3,4])
print(np.array(output) * 2)
```

こんな感じで計算をかけるとTypeErrorを吐かれる。
というわけでmapをかけたあとに計算に持ち込むにはlist化しておく。

```
output = list(map(lambda x: x+2, [1,2,3,4]))
print(np.array(output) * 2)
```

これでめでたく返りは

```
[6, 8, 10, 12]
```

となりました。

# 引き渡し
interp2dを使うためにリストをxとyを自作関数に投げる場合。

```
x = [1,2,3,4]
y = [7,8,9,10]
xnew, ynew = np.meshgrid(x, y)

def func(x, y):
    return f(x, y)

z = list(map(func, xnew, ynew))
inter = interpolate.interp2d(x, y, z, kind='cubic')
```

とするわけだが、funcの内容によっては問題が発生する(した)。
この場合、mapがfuncに渡すのはxnew[0]である[1,2,3,4]のリストを渡す。
ちゃんとfuncが考えられていればいいが、たまにリストで渡されるとエラーする関数が生まれる。(例えば、受け取った引数をそのままtxtに吐き出して別exeに引き渡す時とか)

そういう時はravelでバラして引き渡すとうまくいく。

```
x = [1,2,3,4]
y = [7,8,9,10]
xnew, ynew = np.meshgrid(x, y)

def func(x, y):
    return f(x, y)

z = list(map(func, xnew.ravel(), ynew.ravel()))
```

# 参考
https://qiita.com/croissant1028/items/94c4b7fd360cfcdef0e4
https://qiita.com/hitoshi_xyz/items/ec82e108c3ec827512a3

それぞれもっとうまい書き方あるだろうなあ。
ドメイン駆動設計関連情報のググるときのコツ

## DDD関連でほしい情報は英語であるという覚悟を決める。

これは冗談のようですが本当です！笑<br>英語と日本語でDDD情報は本当に格差がある！！

なのでまず英語で調べるという覚悟を決めましょう。


## アメリカのgoogleにアクセスする

日本のgoogleで「domain driven design」と調べても日本語の資料がたくさん出てきてしまいます。それを回避するために、以下のURLからアメリカのgoogleを使用しましょう。

https://www.google.com/webhp?gl=us&hl=en&gws_rd=cr

これはパラメーターに意味があります。

* gl=us：国がUSであることを指定。
* hl=en：言語が英語であることを指定。
* gws_rd=cr：リダイレクトを無効にする設定。これがないとgoogole.co.jpにリダイレクトされます。

このURLをブックマークしておくとよいでしょう。

## 最近の和訳ツールや字幕ツールに頼る

英語に自信がなくても、最近のツールを使うとかなり楽に英語情報を読むことができます。

一押しなのがこちら

[Google 翻訳](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb?hl=ja)

Chrome限定ですが、google翻訳のアドオンです。マウスオーバーするだけで即和訳を表示してくれるので、これは非常に助かります。

ページまるまる翻訳ではなく、選択したところの訳なので多少おかしな訳も原文と見比べて理解することができます。

(より便利に設定する方法を[こちらの記事](http://little-hands.hatenablog.com/entry/2017/11/03/google-translator)に書きました。)

また、youtubeの動画も最近は英語の自動字幕生成機能があるので、ヒアリングができなくてもその字幕を頼りに戻って進んですれば意味を拾うことができます。


あとは慣れです。エンジニアはもう英語情報読めてなんぼです。ツールの力を借りつつもたくさん読んでればなんとかなります。頑張りましょう。笑

### 関連記事
[なぜDDD初心者はググり出してすぐに心がくじけてしまうのか](http://little-hands.hatenablog.com/entry/2017/09/24/005903)
[ドメイン駆動設計の定義についてEric Evansはなんと言っているのか](http://little-hands.hatenablog.com/entry/2017/09/27/014403)
要素0とnullと空文字の違い（リストで確認）

## [ ]0　要素0

```java

List<String> sampleList1 = new ArrayList<String>();
System.out.println(sampleList1);
System.out.println(sampleList1.size());
```
##中身はnull

```java

List<String> sampleList2;
//System.out.println(sampleList2);	←ローカル変数 sampleList2 が初期化されていない可能性があります　というコンパイルエラー
```
##[ ]1　中身は空文字の要素がひとつだけ

```java
List<String> sampleList3 = new ArrayList<String>();
sampleList3.add("");
System.out.println(sampleList3);
System.out.println(sampleList3.size());
```
Windows版Qtでファイル拡張子からアイコンを取得する

ファイルの実体が存在しているときは、`QFileIconProvider`というクラスを利用して、アイコンを取得することができます。拡張子だけわかっていて、その拡張子に関連付けられたアイコンを取得するには次のようにします。

``` c++
static QIcon iconFromExtension_(QString const &ext, UINT flag)
{
	QIcon icon;
	QString name = "*." + ext;
	SHFILEINFOW shinfo;
	if (SHGetFileInfoW((wchar_t const *)name.utf16(), 0, &shinfo, sizeof(shinfo), flag | SHGFI_ICON | SHGFI_USEFILEATTRIBUTES) != 0) {
		if (shinfo.hIcon) {
			QPixmap pm = QtWin::fromHICON(shinfo.hIcon);
			if (!pm.isNull()) {
				icon = QIcon(pm);
			}
			DestroyIcon(shinfo.hIcon);
		}
	}
	return icon;
}

QIcon iconFromExtensionLarge(QString const &ext)
{
	return iconFromExtension_(ext, SHGFI_LARGEICON);
}

QIcon iconFromExtensionSmall(QString const &ext)
{
	return iconFromExtension_(ext, SHGFI_SMALLICON);
}
```

シェルAPIを利用すると共に、`QtWin::fromHICON()`というWindows専用の特殊なQt関数を使用します。そのため普段はあまり見慣れないファイルを`include`する必要があります。

``` c++
#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
#include <commoncontrols.h>
#include <QtWinExtras/QtWinExtras>
```

ビルドするときは、`winextras`を有効にし、`shell32.lib`と`user32.lib`をリンクします。Qtのプロジェクトファイルには下記のように記述します。

```
win32:QT += winextras
win32:LIBS += -lshell32 -luser32
```

上記サンプルでは、Small（16x16）とLarge（32x32）のアイコンを取得しました。普通はこれでいいのですが、シェルAPIのイメージリストからExtraLargeなアイコンも取得することができます。

``` c++
QIcon iconFromExtensionExtraLarge(QString const &ext)
{
	QIcon icon;
	QString name = "*." + ext;
	SHFILEINFOW shinfo;
	if (SHGetFileInfoW((wchar_t const *)name.utf16(), 0, &shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES) != 0) {
		IImageList *pImageList;
		if (SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void **)&pImageList) == S_OK) {
			HICON hIcon;
			if (pImageList->GetIcon(shinfo.iIcon, ILD_TRANSPARENT, &hIcon) == S_OK) {
				QPixmap pm = QtWin::fromHICON(hIcon);
				if (!pm.isNull()) {
					icon = QIcon(pm);
				}
				DestroyIcon(hIcon);
			}
			pImageList->Release();
		}
	}
	return icon;
}
```

ExtraLargeサイズは、もしかしたら拡張子によっては取得できないかもしれません。

通常は、Large（32x32）でいいと思うので、以下のようにして使います。取得できなかった場合は、QFileIconProviderから、既定のアイコンで代用します。

``` c++
	QIcon icon = iconFromExtensionLarge("html");
	if (icon.isNull()) {
		icon = QFileIconProvider().icon(QFileIconProvider::File);
	}
```

※ このプログラムはWindowsの機能に依存していますので、LinuxやmacOSでは使えません。
[MacOS]MacAppStore申請時のハマリポイントの共有

Bluetoothを使ったチャットアプリ（Mac版）のストアリリースを行いました。
ハマった点が技術記事から見つからず苦戦したため、その内容を共有したいと思います。

主にビルドを提出する段階や、審査で抜けやすいポイントなどを纏めています。

アプリの宣伝込みなため、ご了承くださいm(_ _)m

## リリースしたアプリの概要

https://itunes.apple.com/jp/app/blemes/id1294000305?l=ja&ls=1&mt=12

## 開発環境
Mac OS 10.13
Xcode 8.3.3
iOS 11 (本アプリのiOS版をデバッグで使用)
Swift 3.2

## アプリの機能
CoreBluetoothのGATTプロトコルを使ってユーザが標準入力したテキストを加工し、メッセージとして送受信する機能を持ったチャットアプリ。相手がアプリ起動中しか送信できない。バックグラウンド可。

## 特徴
##### Wi-Fiなどのネットワーク接続を使用しない。
##### 相手を登録しなくてもアプリを起動していれば送信できる。
##### iOS端末とMacOS端末間で通信が可能。

## ターゲット層
##### 災害時に使用したいなど。

## ハマった内容
~~_ビルド後、出力したストア向けのパッケージがフリーズする。_~~
~~> 理由 : productbuildを実行していなかったため。~~
~~>> https://stackoverflow.com/questions/8038788/mac-app-store-productbuild~~

~~> iOS開発のノリでやるとはじめに躓きます。~~
>> ※2021/3/12現在ではビルドアーカイブを作成した後、以下の選択でストアに申請が可能になりました。
>> 情報が古かったので更新しました。

![スクリーンショット 2021-03-12 10.09.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90301/0332425f-efe7-5afc-575d-a3a37172a819.png)

![スクリーンショット 2021-03-12 10.09.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90301/0a34fc02-3224-5acb-c359-2886f5e9d018.png)

_CoreBluetoothの機能が開発では動いていたが、ストア向けにビルドすると機能しなくなった。_
> 理由 : 指定するsandboxの値の中にcom.apple.security.device.bluetoothが漏れていたため。アプリで使用する機能はsandboxでの指定が必須となります。僕の場合はストアに申請する際にcodesignを行うためのシェルを作り、パッケージに反映して申請しました。
>> 参考 : https://github.com/nanoporetech/lamprey/blob/master/tools/mac/sign-app 

>> ストアリリース用のビルドシェルを用意することをオススメします。

_背景色を開発側が決め打ちで指定していたためリジェクトを受けた。_
> ユーザが自由に色を選べるようにしないといけないらしい。
> https://developer.apple.com/macos/human-interface-guidelines/visual-design/color/

> この辺りはよくガイドラインを読んで理解した上で申請しないといけなかったです。

_ストア申請でテスト手順を示さなかったため、「画面がblankだよー」と突き返される。_
> Youtubeなどで説明動画を用意して提示すると良いです。

_クラッシュするよ、と突き返される。_
> クラッシュレポートを解析するための手順備忘録以下参照。
> https://qiita.com/yu_okb/items/82b41f08882d578c2f25

_資料がネット上に不足していたため、StackOverFlowをメインに調べながら作業を進めた。_
> 言語知識と英語をもっと勉強しよう...

## 補足
MacAppStoreへの審査においてはiOSアプリ同様ガイドラインが用意されており、一通り読解しておいた方がいいと思います。Appleが各国の文化をガイドラインに反映していたり、Apple独自の決まりがあったりするので、それに合わせたデザインをコーディングする必要があります。

リジェクトを受けた際は、どこがダメだったのかをアピールコメントで聞いてみると良いかと思います。
Factorybotのアソシエーション(belongs_to)

Factorybotのアソシエーションについてgithubに書かれているものをまとめる。
ちなみにFactorybotとは以前のFactorygirlと同じものである。


#belongs_toの関係
postモデルがauthorモデルに対してbelongs_toの関係にあるとき。

factoryで定義している名称がモデル名と一致するとき。

```
factory :post do
  # ...
  author
end
```

factoryで定義している名称がモデル名とは異なるとき。

```
factory :post do
  # ...
  association :author, factory: :user, last_name: "Writely"
end
```
associationメソッドの第一引数はモデルの名称、第二引数はモデルで定義しているfactoryの名称、第三引数以降はfactoryで定義している属性を上書きしたいときに使用。

　よってfactoryで定義している名称がモデル名と一致するときの記述は以下のものと同じことを示す。

```
factory :post do
  # ...
  association :author, factory: :author
end
```
SSHでセキュリティよくする。

#sshでrsa認証する
###rootユーザでログインしてると、とてもまずいので別のユーザーを作成します。
userのところは変えてください。

```bash:bash
adduser user
usermod -G sudo user
su user
mkdir ~/.ssh
```
###MACで鍵を作成する。

```bash:bash
mkdir ~/.ssh
cd ~/.ssh
ssh-keygen -t rsa
```
###公開鍵を送信する。

```bash:bash
scp id_rsa.pub user@123:45:67:89:/home/user/.ssh
```
###SSHのポートを変更すると相手から、接続しづらくなります。

```bash:bash
sudo nano /etc/ssh/sshd_config
```

```nano:/etc/ssh/sshd_config
port 10022　　　　　　　#好きな番号で

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      %h/.ssh/id_rsa.pub

PasswordAuthentication no
```
コマンドラインでLINEにメッセージを送付する（LINE Notify）

以下の記事を参考にしました。
https://engineering.linecorp.com/ja/blog/detail/88

今更ネタですが、、、。メールサーバを構築したけど未読メールが溜まるばかりで、都度メーラーに張り付くわけにもいかず、気付ける仕組みとしてこちらを導入したいと思います。まだ規約を読み込めてないので、もし適切な使い方でない場合は別の仕組みを考えなきゃ。。。

やりたい！と思ってからものの５分で実装できました。
すごい時代になったものですね！！

では実装してみます。
**ブラウザからLINEに入ってアクセストークンを発行します**
![access.png](https://qiita-image-store.s3.amazonaws.com/0/110457/b10904c0-65e7-84eb-5ba3-5a2553842aa2.png)

**メッセージの内容と宛先を指定**
![select.png](https://qiita-image-store.s3.amazonaws.com/0/110457/6341abc5-01a3-44ec-48a5-c4bf46f1cded.png)


**curlコマンドでAPIにアクセスする**

```
$ curl -X POST -H'Authorization: Bearer <access token>' -F 'message=you got mail!' https://notify-api.line.me/api/notify
```

**LINEにメッセージがくる**
![名称未設定.png](https://qiita-image-store.s3.amazonaws.com/0/110457/e10f49c9-31aa-3b34-1483-1635bea52930.png)

まだ規約やSLAをきちんと理解できていませんが、シンプルに利用できて素晴らしいAPIとC&Cでした。もっと色々な使い方ができそう。
【IDDD本ポイントメモ】ドメインイベント8.1~8.3あたり

今日都内某所でIDDD本の読書会があり、参加してきたのですが、
テーマが８章だったので8章の１節〜3節あたりでポイントになりそうな部分を自分なりの理解でまとめてみました。
今後は他の章についてもまとめてみたりしようと思います。

参考
https://codezine.jp/article/detail/10392

#ドメインモデルからのイベント発行
・軽量オブザーバパターン使う
![軽量オブザーバパターン.png](https://qiita-image-store.s3.amazonaws.com/0/121811/6aef7eda-7632-ca09-102b-f482532b282f.png)
引用元：https://codezine.jp/article/detail/10392?p=2

#アプリケーションサービス
・サブスクライバのインスタンス化
・サブスクライバをパブリッシャーに登録
・リポジトリを使って必要な集約やエンティティのインスタンスを取得？
・集約のコマンドを実行

#集約
・ドメインイベントのインスタンス作成
・ドメインイベントをパブリッシュ(パブリッシャーに渡す)

#ドメインイベントクラス
・イベントのプロパティ名はイベント発生元のコンテキストのユビキタス言語に従う
・イベントクラスには通知先で必要になる情報をプロパティとして設定する
・不変クラスになるため、コンストラクタでは値の設定のみ&読み取り専用
 (一般的に、イベントの受信側は複数回イベントが送信されてくることを考慮し、「一意な識別子」を用いて重複排除を行う)
・ドメインイベントの名前は過去に起こったことが分かる名前にする
・ドメインイベントに持たせるプロパティ例
　→発生時刻
　→発生元の集約
　→イベント発生に必要なパラメータ

#パブリッシャ
・サブスクライバ登録
・イベント種別の確認
　→サブスクライバのsubscribeToEventType()を使ってイベント種別が正しいか判別
・イベントのハンドリング
　→サブスクライバのhandleEvent()を呼び出す

#サブスクライバ
・subscribeToEventType()で反応するイベントタイプを指定
・handleEvent()メール送信等イベントに関連する処理を行う

認識に誤りなどありましたらコメント頂けると嬉しいです！
【JavaScript】オブジェクト配列のGroupBy

Array.prototype.reduce()で色々できますので、一部例を残します。

```JavaScript:GroupBy_MaxRow
const groupby_max = (datas, groupItems, maxItem) => {
  const group = datas.reduce((result, dataRow) => {
    const key = groupItems.map(item => dataRow[item]).join('');

    if (Object.prototype.hasOwnProperty.call(result, key)) {
      result[key].push(dataRow);
    } else {
      result[key] = [dataRow];
    }

    return result;
  }, {});

  return Object.keys(group).map(key => {
    group[key].sort((a, b) => {
      // 降順
      if (a[maxItem] < b[maxItem]) return 1;
      if (a[maxItem] > b[maxItem]) return -1;
      return 0;
    });
    return group[key][0];
  });
};
```

**使用例：**

```
const datas = [
  {a: 1, b: 1, c:1},
  {a: 1, b: 2, c:1},
  {a: 1, b: 3, c:2},
  {a: 2, b: 4, c:2},
  {a: 2, b: 5, c:3},
  {a: 2, b: 6, c:3},
];

// [a, c]でGroupByし、[b]の最大値の行を返す
groupby_max(datas, ['a', 'c'], ['b']);
```

**実行結果：**

```
| a | b | c |
|---|---|---|
| 1 | 2 | 1 |
| 1 | 3 | 2 |
| 2 | 4 | 2 |
| 2 | 6 | 3 |
```

```JavaScript:GroupBy_Sum
編集中
```
VPSやクラウドにWindowsのインストールはライセンス違反なのか？

[某クラウドにWindows10をインストールした](https://qiita.com/CloudRemix/items/65896d97f12ce29b8e32)際、ライセンス的にOKか気になったので調べてみました。

## とりあえず検索
Google大先生にお伺いしたところ、答えとなりそうな記事を発見
[Windows Server を VPSにインストールするのはライセンス違反か？ | Butaman-kun Project](https://btmn.jp/2012/07/17/windows-server-vps/)

コメント欄をみると

 > 日本マイクロソフトに問い合わせてみました。
 > パブリッククラウド、VPS等共有ハードウェア環境にお客様がパッケージ版やボリューム ライセンス (VL)版にて所有されている Windows Server OS、Windows Client OS を導入することは許諾を超えたご利用にあたる為、できません。
 > 
 > パッケージ版や VL 版 Windows Server OS などは、「お客様」のサーバーに対して、ライセンスを割り当てることが許諾されております。
 > 
 > 従いまして、お客様専有のハードウェア (ハウジング型のサービスなど)であれば可能でございます。
 > 
 > とのことでした。

**絶望的です。**

## 公式サポートに聞く
ダメそうですが日付は2012年、現在は変わっている可能性があります。
よって公式サポートに聞いてみます。

私「VPSとかクラウドにWindowsをインストールしていいですか？」

MSサポート「どのOSですか？」

私「Windows10 or Windows Server 2012です。」

MSサポート「少々お待ちください...」

・・・・

MSサポート「お待たせしました。下記窓口にご相談ください。」
MSサポート「サポート契約センター（有償）、一回5万円～」

私「・・・ありがとうございました。」

**私には無理です**

## もう一度ネットで検索
希望を捨てずもう一度ネットサーフィンを楽しみます。

すると、Windowsサーバも提供するIDCFクラウドとニフティクラウドに求めた記事を発見

[IDCFクラウド](https://www.faq.idcf.jp/app/answers/detail/a_id/73/~/%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88windows-os%E3%82%92%E6%8C%81%E3%81%A1%E8%BE%BC%E3%82%80%E3%81%93%E3%81%A8%E3%81%AF%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%81%8B)

 > **クライアントWindows OSを持ち込むことは可能ですか**
 > 
 > Windows XP,7,8,10などの（クライアントWindows OS）はサーバーライセンスではございませんので、仮想マシンにご利用いただきますと Microsoftのライセンス違反となります。
 > Windows OSの仮想マシンを利用する場合は、弊社テンプレートをお使いいただくか、SPLAにてWindows Serverライセンスをご準備いただく必要があります。

[ニフティクラウド](http://cloud.nifty.com/cs/catalog/cloud_faq/catalog_120416000842_1.htm)

 > **ニフティクラウド上にMicrosoft製品を導入する場合の注意点はありますか?**
 > 
 > ■ニフティクラウドの専有環境上でのご利用について 
 > ※専有環境：専有サーバー、専有コンポーネント、プライベートクラウド
お客様のボリュームライセンスまたはSPLAを通じて購入した製品をニフティクラウド上に展開することが可能です。 
 > 
 > ■ニフティクラウドの共有環境上でのご利用について 
 > ※共有環境：共有サーバー 
 > （略）
 > お客様のSPLAをご利用する場合 
 > [サービス プロバイダー製品使用権説明書 (SPUR](https://www.microsoft.com/ja-jp/licensing/product-licensing/products.aspx#SPUR))においてDCP対象となっている製品についてはお客様のSPLAを利用して展開いただくことができます。
 > その場合、ニフティクラウド上で利用されたお客様のSPLAライセンスについては、お客様自身で適切な購入を行ってください。 

※SPLA：[Microsoft Services Provider License Agreement](https://www.microsoft.com/ja-jp/Licensing/licensing-programs/spla-program.aspx)

# まとめ
VPSやクラウドに手持ちのクライアントOS（Windows7, 8, 10）をインストールすることはライセンス違反となる。（評価版は不明）
Windows Serverシリーズであれば、SPLAという特殊ライセンスを使うことでインストールが可能となるがオープンプライス（絶対高い）である。
しかも、サブスクリプションライセンスのため半永久的にライセンス料が発生する。（その代わり最新版が使用可能）
ただ、専用サーバであればクライアントOSも含めてOKの可能性が高い。

そのため、さくらやIDCFのようなWindowsサーバが用意されているサービスを使ったほうが現実的です。
Use Case Refactoring

# Use Cases Refactoring

以前に書いたメモを記録に残す。
最近は、ユースケースを書くことも少なくなったし、あまり役に立たないかも。

## 動機
ユースケースを作成したり、レビューしたりしていく中で、コードのリファクタリングのように行うことができないかというアイデアから、とりあえずリファクタリングカタログを作成してみた。

## リファクタリングカタログ(基本編)

### 1-1.ユースケースの削除(Delete Use Case)
アクタに価値のないユースケースは、削除する。

### 1-2.ユースケースの抽出(Extract Use Case)
事後条件の異なるフローが1つのユースケースに書かれている。代替フローを別のユースケースとして抽出する。

### 1-3.ユースケースの抽象化(Abstract Use Case)
似たようなユースケースを、ひとつに纏められないか検討する。似たような手順のフローで基本フローしかないようなユースケースがたくさん出た時、それらはシステムが同じサービスを提供しているのかもしれません。

### 1-4.ユースケースの具象化
事前条件が複雑なユースケースは、複数に分けられないか検討する。事後条件が抽象的でシステムの提供サービスが理解しづらいかもしれません。ユースケースを元にテストを実施するとした場合、事後条件の確認が簡単であるかが判断基準となります。

### 1-5.共有利用されたユースケースをフロー内のステップへ移動
ユースケース記述に1行程度しか書かれていない基本フローがあり、このユースケースが複数の箇所から利用(include)されている場合、利用している側のユースケースでフロー中の1ステップに記述できないか検討する。

### 1-6.基本フローと代替フローの入替
代替フローの方が、事後条件を達成するのにシンプルな場合、基本フローと入れ替える。

### 1-7.データ更新によるinclude関連の削除
あるユースケースが内部データを更新し、その更新をもって起動されるユースケースは、include関連をつけてしまう。しかし、前者のユースケースと後者のユースケースの役割(サービス)が異なるならば、include関連を結ぶ必要はない。ユースケース記述に内部データのことは、書かれているはずである。ユースケースは役割(サービス)を見出すために書かれているはずが、データを抽出し機能を抽出するDFDを書くことになってしまっている。

### 1-8.ユースケースを非機能要求へ移動
ログ出力のユースケースなどの製品特有の機能でないユースケースは、非機能要求とする。こうすることで、ユースケース図の可読性を高め、システムの全体像を捉えやすくする。無駄なincludeの線も消すことができ、ユースケース図がすっきりとする。

## リファクタリングカタログ(記述編)

### 2-1.数値名称によるマジックナンバーの置き換え
数値がそのまま記述されている箇所は、本来なにかの変数である可能性があります。システムが変更された場合、分析や設計でも定数や変数として定義されることになります。数値のままにせず、数値名称を記載しましょう。どうしても数値も記載したい場合は、備考欄に記載します。

### 2-2.重複するフロー内のステップを共有利用するユースケースへ移動
複数のユースケースのユースケース記述に重複するステップがある場合、まとめて共有利用するユースケースにできないか検討する。

## リファクタリングカタログ(拡張編)

### 3-1.拡張ユースケースの削除(Delete External Use Case)
要求分析などの結果から、不要な拡張ユースケースは削除する。

### 3-2.拡張ユースケースの代替フロー化(Change External Use Case to Altanative Flow)
要求分析などの結果から、拡張予定のないユースケースは、代替フローとしてベース側のユースケースへ組み込む。

### 3-3.拡張ユースケースの抽出(Extract External Use Case)
要求分析などの結果から、拡張予定のある機能は、拡張ユースケースを追加する。

### 3-4.代替フローのユースケース化
要求分析などの結果から、拡張予定のあるフローは、拡張ユースケースに変更する。

## 参考文献
* ユースケース実践ガイド(Writing Effective Use Cases)
* リファクタリング ～プログラミングの体質改善テクニック (Refactoring:Imporving The Design of Existing Code)
baserCMSでマルチサイトを実装する

## はじめに

baserCMS４では、サブサイト機能が追加され、複数のWebサイトを一つのCMSで管理できるようになりました。
ただし、標準の機能では、追加されたWebサイトは、サブフォルダに配置されたようなURLになってしまうので、マルチサイトとは言い難いのが現状なんですね。

実は！baserCMS４では、複数ドメイン、サブドメインを見越した設計がされており、テスト段階として表向きには機能提供されていませんが、ちょっとした設定を行う事で、本当の意味でのマルチサイトに対応する事ができるのです。

あくまでテスト段階の機能という事で、利用する場合は自己責任でお願いします。（そもそもオープンソースなので利用は自己責任前提ですが）

## 前提条件

利用できる前提条件としては、サブドメインや、別のドメインについて、同じディレクトリをドキュメントルートとして設定できる環境である必要があります。
VirtualHost を自由に設定できる環境であれば、特に問題ありません。

## サブドメインでのマルチサイト

### マルチサイトを設計する

マルチサイトの構成を検討します。例えば以下のようなドメインをマルチサイトとして定義する事を前提とします。

- main.com
- sub.main.com
- sub2.main.com

### メインドメインを定義する

管理システムを配置する前提のメインとなるサイトのドメインをメインドメインと呼ぶ事にします。
`app/Config/install.php` の、以下の行を探しメインドメインを記述します。

```
Configure::write('BcEnv.mainDomain', 'メインドメインとなる文字列');
```

今回の例であれば、以下のようになります。

```
Configure::write('BcEnv.mainDomain', 'main.com');
```

### 管理システムでサブサイトを追加する

サブサイト管理より、サブサイトを追加します。エイリアスに、サブドメイン名を登録します。
例えば、今回の例であれば、`sub` や、`sub2` となります。

### データベースの値を調整する

テスト段階という事で、UI がない為、追加したサブサイトのレコードを直接変更します。
phpMyAdmin 等のツールで、`mysite_sites` というテーブルを探し、対象レコードの以下のフィールドの値を変更します。
※ プレフィックスを変更している場合は、 `mysite_` の部分を変更したプレフィックスに読み替えてください。

- use_subdomain : 1 に変更します
- domain_type : 1 に変更します

### VirtualHost を設定する

サブドメインを VirtualHost で設定する際、ドキュメントルートについて、メインドメインと同じディレクトリを参照するように設定します。

以上で、サブドメインでのマルチサイトの設定は完了です。
後は、サブサイトごとに、テーマを変更したり、トップディレクトリでレイアウトファイルを変更したりするなどして、デザインを切り分けてみてください。

## 別ドメインでのマルチサイト

基本的に、サブドメインでのマルチサイトと設定手順は同じです。
違う点は以下の２点です。

- エイリアスにドメイン丸ごとぶっこむ
- domain_type を 2 に設定する

## まとめ

複数のサイトを管理してて、それぞれにbaserCMSをインストールして、それぞれでユーザーを作成して、、、
面倒ですよね。この機能を利用すると一つの baserCMS で複数のWebサイトを管理できます。
あくまでテスト段階の機能という事で自己責任で試してくださいね。
Spring BootのSpring BatchでのCommandLineRunnerの使われ方

Spring Bootでコンソールアプリケーション作るやり方を調べたところ、reference guide読む感じだと```CommandLineRunner```か```ApplicationRunner```を使う、と書いてある。

ところで、```CommandLineRunner```の実装クラスをなんとなく調べたら```JobLauncherCommandLineRunner```というSpring BootでSpring Batchを動かすためのクラスがあった。このクラスのデフォルト動作はそのコンテキスト内のすべての```Job```を実行する。ただし、```jobName```を指定することで特定のジョブを実行することもできる、と書いてある。この実装どうやってるのか気になったので、該当部分のソースを見てみた。

```java:JobLauncherCommandLineRunner
public class JobLauncherCommandLineRunner
	implements CommandLineRunner, ApplicationEventPublisherAware {

	@Autowired(required = false)
	public void setJobs(Collection<Job> jobs) {
		this.jobs = jobs;
	}

	@Override
	public void run(String... args) throws JobExecutionException {
		logger.info("Running default command line with: " + Arrays.asList(args));
		launchJobFromProperties(StringUtils.splitArrayElementsIntoProperties(args, "="));
}


	private void executeLocalJobs(JobParameters jobParameters)
			throws JobExecutionException {
		for (Job job : this.jobs) {
			if (StringUtils.hasText(this.jobNames)) {
				String[] jobsToRun = this.jobNames.split(",");
				if (!PatternMatchUtils.simpleMatch(jobsToRun, job.getName())) {
					logger.debug("Skipped job: " + job.getName());
					continue;
				}
			}
			execute(job, jobParameters);
		}
}
```

Spring Boot起動後に```CommandLineRunner```の```run```メソッドが実行される。ここの実装でジョブを起動している。また、```setJbos```のインジェクションですべての```Job```のコレクションが入れられる。次に```executeLocalJobs```メソッドで、そのすべての```Job```をいっこずつ起動している。その際、もし```jobName```の指定があればマッチするジョブだけ起動して他はスキップしている。

コンソールアプリで何らかのキーで特定の機能だけ実行するのってどうやるんかな～```CommandLineRunner```が複数あっても全部実行されるしな～と思ってたけど、こんな作りにすればよさそう。
RMagickでSVGを扱うと黒く化けちゃうときのWorkAround

# ハロウィンですね

RMagick(と言うかたぶんImageMagick)でSVGを読んでpngに書き出した時、何故か色が黒になってしまったり、背景の具合によってはべったり真っ黒になってしまうことがある。ハロウィンだからというわけではなくて、たしかこれは半年くらい前にも起きていた。二回目なので対応策をメモ。

# 現象
```
canvas = Image.new(size,size){
  self.background_color = 'transparent'
  self.format = 'png'
}
icon = Magick::ImageList.new(iconfile)
icon.resize_to_fit!(size-radius,size-radius)
canvas.composite(icon, CenterGravity,OverCompositeOp)
```
こんな感じのコードでpngに書き出そうとすると、

![svg.png](https://qiita-image-store.s3.amazonaws.com/0/30743/23ebc57a-67a0-f835-0207-db5e55622f18.png)

こういうSVGなのに、書き出すとこうなっちゃう

![info_icon_29_75px.png](https://qiita-image-store.s3.amazonaws.com/0/30743/ccd4a723-2078-909a-95b7-227c7108cb9a.png)

# 対策

根本的な原因はわからないのだけど、回避策として、SVGの書き出し方を変えてあげると正しく扱えるようになった。

SVGファイルをillustratorで開いて、*Save AS* - *SVG*で保存すると、SVGのオプションダイアログが出る。Advanced Optionというのがあるので、
*CSS Property*が*Style Element*になっているところを
*Presentation Attributes*に変えて保存し直してあげると、ImageMagickでも扱えるようになる。

![SVG_Options.png](https://qiita-image-store.s3.amazonaws.com/0/30743/51a9c81b-4c6c-9a29-3498-bbf255ece272.png)

# 問題の起きたバージョン

```
$ ruby -v
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-darwin16]
$ gem list rmagick

*** LOCAL GEMS ***

rmagick (2.16.0)
$ convert -version
Version: ImageMagick 6.9.9-20 Q16 x86_64 2017-10-15 http://www.imagemagick.org
```
ちょっとずつ読むドメイン駆動設計 第三部 より深い洞察へ向かうリファクタリング 第九章 暗黙的な概念を明示的にする1

# 暗黙的な概念を明示的にする

実際にどのように深いモデルを見つけ出すかがこの章のテーマ。

最初のステップはドメインにおける本質的な概念を、荒削りでもなんとかしてモデルで表現すること。
その後、知識の噛み砕きとリファクタリングを繰り返して改良していきます。
そして、このプロセスは、重要な概念が開発者によって認識され、モデルと設計の中で明示的にされたときに起動に乗ります。

## 概念を掘り出す

というわけで、どのように重要な概念が認識できるようになるか。

まず、前提として、このような概念は暗黙的に潜んでいるので、**手がかりに対して敏感でなければならず、時には積極的に探さなければならない**のであります。

## 手がかりはどこにあるか

暗黙的な概念はどこにあるか。その手がかりのためのヒントをEricが示してくれています。

1. **チームの言語に耳を傾ける**
2. **設計のぎこちない点・エキスパートの発言で矛盾すると思われる点を詳細に調べる**
3. **ドメインに関する文献を読む**
4. **大量の実験をする**

明日からはこの手がかりについてそれぞれ読んでいきます。
Docker Swarm V17.10でnodeのJOINがエラー（ｼﾞｮｲﾝ後にSTATUS=DOWN）になるときの対策



# はじめに
CentOS7でmaster managerをdocker swarm initで作成した後、nodeをdocker swarm joinすると、STATUS=DOWNになりました。V12で作成したswarm環境をyum updateして上げてきたので、そのどこかで入った問題だと思います。

# 症状
- workerは問題なくjoinできるのにmanagerだと、joinコマンドがフリーズする。
- master側で docker node ls するとSTATUS=DOWN

# 環境
- オンプレでプロキシー下
- CentOS7 on VMWare　（masterも追加nodeも）
- Docker V17.10 (V17.09でも同じ現象が発生しました。）

# 解決策
下リンクのイシューで助けられました。
[moby/moby のissue #35046](https://github.com/moby/moby/issues/35046)

### http-proxy.conf　に　NO_PROXY　で全ノードのIPアドレスを列挙する

ことで復旧。
続けて systemctl daemon-reload && systemctl restart docker.serviceしたらmanagerを docker swarm join できました。
なお、http-proxy.conf の場所は systemctl status docker で表示された/etc/systemd/system/docker.service.d の直下。
反映されたか確認するときは systemctl show docker で。
Git(lab)を絡めた開発環境の作成手順備忘録

##Gitlabでリモートリポジトリを作成する
'New Project'ボタンをクリックして、名前(ここでは"sample.git")を付けて'Create Project'

##自分のPCからGitBashでリモートリポジトリの複製をローカルにつくる
方式は2つ

git bashで...
1. sampleフォルダに移動する
2. git clone [方式]

https方式
git clone https://gitlab.com/sample/sample.git

SSH方式
git clone git@gitlab.com:sample/sample.git


##ローカルのsampleフォルダにソースを格納する

##蛇足①(AWS絡みの備忘録)
AWS lambdaへの転送設定（本項とは関係ない）以下コマンドプロンプトで...
1. sampleフォルダに移動する
2. npm install --dev
3. aws configure

```text:lambda-config.js
AWS Access Key ID:********************
AWS Secret Access Key:****************************************
Default region name：ap-northeast-1
Default output format：json

- PCにつき1度だけ実行すれば良い
- 'Access Key ID'と'Secret Access Key'はAWSのIAMからユーザの認証情報タブで生成する
- 日本は'ap-northeast-1'というregion nameになるらしい
```


##蛇足②(AWS絡みの備忘録)
1. AWSのIAMにロール(ここでは"lambda_exec_role")を作成する
2. 作成したロールに対して'AWSLambdaExecute'の'ポリシーをアタッチ'する
3. lambda-config.jsの内容をIAMの"アカウント番号"と"ロール名"に合わせて編集する

```js
:lambda-config.js
exports.getDeployFile = function(filename){
  filename = filename.replace(/.js/,'');
  return {
    region: 'ap-northeast-1',
    handler: filename + '.handler',
    role: 'arn:aws:iam::************:role/lambda_exec_role',
    functionName: filename,
    timeout: 10,
    runtime: 'nodejs6.10'
  }
}
//'************'部分はAWSのAccount番号
```

##git bashで...
1. sampleフォルダに移動する
2. git add .
3. git commit -m "Add source code"
4. git push

##蛇足③(AWS絡みの備忘録)
AWS lambdaへの転送設定（本項とは関係ない）以下コマンドプロンプトで...
1. sampleフォルダに移動する
2. gulp deploy-lambda
Docker runで「getsockopt: connection refused」

# 開発環境
* Ubuntu 16.04
* Docker 17.09.0-ce
* プロキシサーバ利用

# エラー内容
```bash:console
$ sudo su -
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
docker: Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp xxx.xxx.154.207:443: getsockopt: connection refused.
See 'docker run --help'.
```

# 原因
Dockerにプロキシサーバを設定していない場合、上記の接続エラーになる

# 対応手順
Dockerにプロキシサーバーを設定

```bash:console
# docker.service.dを作成してproxy設定を記述
$ mkdir /etc/systemd/system/docker.service.d
$ vi /etc/systemd/system/docker.service.d/http-proxy.conf

    [Service]
    Environment="HTTP_PROXY=http://proxy.example.com:80/"
    Environment="NO_PROXY=localhost,127.0.0.0/8"

# reloadして設定内容を確認したらrestart
$ systemctl daemon-reload
$ systemctl show --property Environment docker
Environment=HTTP_PROXY=http://proxy.example.com:80/ NO_PROXY=localhost,127.0.0.0/8
$ sudo systemctl restart docker
```

設定したらもう一度docker runして確認

```bash:console
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
5b0f327be733: Pull complete
Digest: sha256:07d5f7800dfe37b8c2196c7b1c524c33808ce2e0f74e7aa00e603295ca9a0972
Status: Downloaded newer image for hello-world:latest

Hello from Docker! 
```

#補足
* プロキシ設定済みでも別の原因で上記エラーが出る場合があります
* 参考：https://stackoverflow.com/questions/23111631/cannot-download-docker-images-behind-a-proxy