OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleColaboratoryでTwitterのデータ分析をしてみた

今回は、Google Colaboratoryを利用して、ぼくのフォロワー200名を対象に、フォロー数とフォロワー数の散布図を描いてみました。

※先日この記事を読んで、GoogleDriveから環境構築無しでPythonが使えることがわかったので、実際にやってみました。
[Google DriveでPythonの実行環境を整える方法をまとめてみた](https://note.mu/daikawai/n/n3e7432f0dbaa)

## 今回やったこと
今回のチャレンジは全部で３つの目的のもと行っています。

1. 自分のフォロワーの「フォロワー数」を確認する
2. 自分のフォロワーの「フォロー数」と「フォロワー数」の関係を可視化する
3. Google Colaboratory でAPIを試してみる


１，２については、どちらも知りたいのは、「自分のツイッターをフォローしてくれている人は、どんな人なのか」ということです。

例えばフォロワーがみんな、「フォロー数」はめちゃくちゃ多いけど、「フォロワー数」は大したことないと仮定すると、そんなに影響力がなかったり、そもそもフォローすること自体を目的にしているようなアカウントにフォローされていることになります。

３はこのツールでどこまで出来るのかが試してみたかったので、APIをいじってみたかったというのが主な理由です。どうも機械学習系のライブラリはすでに入っているらしく、しかもGPUが無料で利用できるということなので、この先いろいろと遊べそう。


## やり方１：Google Colaboratory を準備する
これは最初の記事に書いてるので、簡単な説明に留めます。やり方はいたって簡単で、下記４ステップです。

1. Google Driveにログインする
2. 「新規」＞「その他」＞「アプリを追加」を選択
3. 検索窓にて「Google Colaboratory」と検索
4. 「＋接続」を選ぶ

これで準備完了です。
利用するときには、「新規」＞「その他」＞「Colaboratory」をクリックでファイルを作成します。

そして三角が横向きに出ている箇所があるので、そこにお馴染みHello Worldのプログラムを書いてみます。

```hello.py
msg = "Hello World"
print(msg)
```

もうこれだけでとりあえずPythonが動く環境ができています。


## やり方２：Tweepyのセットアップ

まず標準ではGoogle ColaboratoryにTweepyが入っていないので、次のプログラムを実行しておきましょう。

```console:Console
!pip install tweepy
```

正直事前準備はこれくらいです。あとはAPI使ううえでTwitterに事前申請が必要なので、こちらを参照にやっておいてください。

[PythonでTwitter API を利用していろいろ遊んでみる](https://qiita.com/bakira/items/00743d10ec42993f85eb)



## やり方３：実際にコード書いてみる
今回使ったライブラリはTweepyとMatplotlibの２つだけ。
まずコードの全体像はこんな感じです。

```tweepy.py
# 必要なライブラリをインポート
import tweepy
import matplotlib.pyplot as plt

# 各種キーをセット
CONSUMER_KEY = 'xxxxxxxxxxxxxxxx'
CONSUMER_SECRET = 'xxxxxxxxxxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxxxxxxxxxx'
ACCESS_SECRET = 'xxxxxxxxxxxxxxxx'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

#APIインスタンスを作成
api = tweepy.API(auth)

#自分のフォロワーのIDを取得
ids = api.followers_ids("taikomegane")

#フォロワー数とフォロー数を格納するリストを用意
follower_list = []
friend_list = []

#取得したIDそれぞれについて処理を繰り返す
for id in ids:
  #IDからユーザ情報を取得
  user_info = api.get_user(id)
  
  #ユーザ情報からフォロワー数を取得、格納
  follower = int(user_info.followers_count)
  follower_list.append(follower)

  #ユーザ情報からフォロー数を取得、格納
  friend = int(user_info.friends_count)
  friend_list.append(friend)

# フォロワー数、フォロー数のヒストグラムをそれぞれ描画
plt.hist(follower_list,bins=30)
plt.hist(friend_list,bins=30)

# フォロワー数、フォロー数の散布図を描画
plt.scatter(follower_lists,friend_list)

print("終了しました")
```

やっていることは、次の４ステップ。

1. TwitterのAPIインスタンスを生成
2. 自分のフォロワーのIDを取得
3. それぞれのIDについて、フォロワー数、フォロー数を取得
4. フォロワー数、フォロー数を用いて、ヒストグラムと散布図を描画


実際の結果はこんな感じで・・・・・・と言いたいところですが、なんだかんだでエラーを処理しているうちにAPIの実行回数が制限を超えてしまいました。データの読み取りは追記で行います。


さて割と簡単なコードだけでここまでできました。しかも全部GoogleDrive上で動く。
少し調べてみると、これスプレッドシートとの連携もできそうです。
もうちょっと何ができるか調べたいところですが、とりあえず今回はここまで。

改めて技術チュートリアルって、最初からそれを書くつもりでやらないとなかなか難しいですね。
多少きれいにしたやつが作れたら、noteで販売しようかな。

それでは、本日も最後までお付き合いいただきありがとうございました。



## 追記：結果出ました。

このあとダメ押しでもう一度実行したら出来ました。

![20180717000357.png](https://qiita-image-store.s3.amazonaws.com/0/182535/ceac6e51-5d92-8aa2-d7b0-ecc80fe78c37.png)


で、お気づきの通り、１つしか出てきませんでした。
matplotlibは複数描画してくれと頼んだ場合、再描画してしまうので、前のものは消えてしまうようです。

本記事はこちらの転載になります
[GoogleColaboratoryでTwitterのデータ分析してみた](https://www.taikomegane.com/entry/2018/07/16/235422)
Ruby | 開発 で gem を build する時は rake を使おう

`$ bundle gem` で作成されたディレクトリであることが前提。

# rakeの場合

```
$ rake build 
```

- コマンドが簡潔
- pkg ディレクトリにgemがビルドされる ( `.gitignore` されているので git差分を汚さない )

# gem コマンド

```
$ gem build yourgem.gemspec
```

- コマンド引数にgemspecを指定しなければいけない
- カレントディレクトリにgemファイルがビルドされてしまう


# 環境

- Bundler version 1.16.2
- gem 2.7.6

# 関連

- [はじめての Ruby gem 作成が死ぬほど簡単で笑えた件 (失敗談もあるよ) - Qiita](https://qiita.com/YumaInaura/items/90a3d02342486a62da43)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
[Ruby] チートシート 書きかけ

## 文字列

文字列に変換

```
1.to_s
=> "1"
```

class名

```
'kotaro'.class == String
=> true
```


条件は式は値で判定される

```
'kotaro' == 'kotaro'
=>true

'kotaro' == String.new('kotaro')
=> true
```

文字列変換

```
# 文字列の先頭を大文字
'kotaro'.capitalize
=> "Kotaro"
```

## 配列
配列の変換

```
(1..10).to_a
=> [1, 2, .. 10]
```

配列の作成

```
%w[foo bar baz]
=> ["foo", "bar", "baz"]
```

## ハッシュ
ハッシュの初期化

```
>> h = {}
>> h['foo']
=> nil

h = Hash.new(0)
>> h['foo']
=> 0
```

## Range

```
(1..10) == Range(1, 10)
=> true
```

## Ruby on Rails
OSXにXGBoostをインストールする方法

##　概要
公式チュートリアルやその他の[ナレッジ記事](https://qiita.com/xkumiyu/items/aa3a517f1e2fb0eea5cf)を見て`pip install xgboost`を試しても中々インストールに成功しなかったが[こちらの記事](https://towardsdatascience.com/installing-xgboost-on-osx-e17e77c00635)の通りに実行するとうまく行ったので、Qiitaに載せておきます。

## 実行環境
| OS       |       Python |
|:-----------------|------------------:|
| High Sierra 10.13.2            |              3.6.4 |


## インストール手順
1. In your terminal, install homebrew if you haven’t already. 

```terminal.
 /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 
```

 If you encounter errors in this step, you should refer to this website “https://computers.tutsplus.com/tutorials/homebrew-demystified-os-xs-ultimate-package-manager--mac-44884”
  
2. Also in the terminal, you should 

``` terminal.
brew install gcc — without-multilib`
``` 
the without multilib should help with multi-threading errors that we may encounter later. This may take some time, but if this doesn’t work try 

``` terminal.
sudo apt-get install gcc
sudo apt-get install g++
```

3. cd into wherever you want your directory to be, I simply put mine at my root directory, but make sure that this is not within another directory! (we don’t need any pregnant repos)

4. Clone the repository wherever you want your directory to be using this line

``` terminal.
git clone — recursive https://github.com/dmlc/xgboost
```

5. cd into your new directory called xgboost 

```terminal.
cd xgboost
```

6. Open the make/config.mk. If you have your computer formatted correctly, simply typing “open make/config.mk” may work. 
7. 
If not you can use the GUI to open it in your favorite text editor, or another command. Uncomment these two lines of code : “export CC = gcc
export CXX = g++”. Depending on which version of gcc you installed, you may need to change them to “export CC = gcc-6
export CXX = g++-6”. Make sure you save this and then move on to the next step.

7. cd into xgboost (if you’re not already there), and then “cp make/config.mk .
make -j4

8. Final step : “cd python-package; sudo python setup.py install”
CloudBuildでビルド中にS3からデータをもってきて配置する方法

リポジトリに置きたくない、StreamingAssetsに配置するデータとか、ビルド時の中間処理用の定義ファイルだったりとか、S3においといて、環境非依存で使えるようにする、、というのはわりとやりたい人多いと思う。

今回それを実装したので、自分が忘れたときようにメモ。

### 実装について

やり方は色々あるだろうけど、

- awscliは使えないので、システムコールで誤魔化すのは無理
- AWS SDKを組み込むのは 嫌だ

という前提のもと、

- APIGateway + S3 で配信側を作って、HttpClient でダウンロード

という汎用的な実装で解決を図った。構成としてはこういう感じ。

![スクリーンショット 2018-07-20 7.59.56.png](https://qiita-image-store.s3.amazonaws.com/0/6047/db772126-fe9d-0300-ffb7-ab18c8fca2d7.png)

### AWS側の設定のハマりどころ

S3のバイナリデータをAPIGatewayで単純に返すのって、意外と分かりやすい例がなくて、ハマった。

失敗例は書くと際限がないので、成功例の最低限の設定項目を列挙しておく。

#### グローバル > 設定 > バイナリメディアタイプ

- 必要なタイプを列挙、、すると不毛なので、Internal用途で荒れば、割り切って "*/*" と書いておくのが吉。

#### リソース

- GETクエリを設定
	- パスパラメータを使おうと思ったが、それやると、多段パスの引数取りたいときにメンドくさいことになるので、RootにGETを設定して、S3のリソース指定は全てクエリでセットする方針で

#### リソース > GET > メソッドリクエスト

- APIキー
	- 専用のものを用意するのが無難
- リクエストの検証
	- "クエリ文字列パラメータおよびヘッダーの検証"
- URLクエリ文字列パラメータ
	- accept | 必須 => Clientは "*/*" を指定
	- bucket | 必須 => Clientは Bucket名を指定
	- item | 必須 => Clientは ObjectのPathを指定

#### リソース > GET > 総合リクエスト

- 統合タイプ
	- "AWSサービス"
- AWSリージョン
	- 一番近いところを指定
- AWSサービス
	- "S3"
- HTTPメソッド
	- GET
- パス上書き
	- {bucket}/{item}
- 実行ロール
	- S3/CloudFront のRead権限を付与したロールを設定
- コンテンツの処理
	- パススルー
- デフォルトタイムアウトの使用
	- On（Offにして手動設定しても、どうせデフォルト値の29秒よりは大きくできない）
- URLパスパラメータ
	- item | method.request.querystring.item
	- bucket | method.request.querystring.bucket
- HTTPヘッダー
	- Accept | method.request.querystring.accept

#### リソース >	GET > メソッドレスポンス

- HTTPのステータス > 200 のレスポンス本文 > コンテンツタイプ
	- application/octet-stream
- HTTPのステータス
	- 400, 500 をそれぞれ追加（内容は未設定で良い）

#### リソース > GET > 総合レスポンス

素の状態だとエラーでも200が返って、クライアントのエラー処理がめんどくさいことになるので、エラーコードをS3 Integrationが返してきた時用に、エラーコードをMappingする。

これにより、存在しないファイルを指定した時や、APIKeyミスった場合にエラーがちゃんとかえるようになる。

- 設定追加（正規表現の記法に注意）
	- 4\d{2} | 400 | パススルー
	- 5\d{2} | 500 | パススルー

------------------------

本当は、Serverless Frameworkで定義しておきたかったけど、S3 Integration ないみたいなので断念。

Terraformは定義量が尋常ではなくなるので、論外。（やりたいことに対するコストが見合わない）
Data Structures

<p>Despite the advancement of computer's hardware: the high speed and great performance of its processors as it can handle millions of mathematical computations in some seconds, still the way how to organize and store the data can have big impact on the performance and the speed of resolving the problems as Data can become huge and will impact considerably on the speed of the best processors available.
for that purpose there were many different ways to store Data and it depends on the developer to choose the best way that can suit its type of Data.</p>
<ul>these are the most used Data structures:
<li><strong><em>Pointers : </em></strong>very primitive data structure used with the first programming languages as C and C++, the new programming languages handle pointers implicitly behind the scenes</li>
<li><strong><em>Arrays : </em></strong>most used and most simple used data structure very convenient in case the number of data can be determined </li>
<li><strong><em>List Node : </em></strong>can hold an unknown number of data as it can easily change size to add or delete items</li>
<li><strong><em>Queues : </em></strong>commonly used for routers using the principle of <strong>FIFO</strong> First In First Out</li>
<li><strong><em>Stacks : </em></strong>the opposite of Queues using the principle of <strong>LIFO</strong> Last In First Out</li>
<li><strong><em>Trees : </em></strong>as it is name says, it is a data structure composed by nodes where the first node is considered as the root and can have zero or more children(child nodes)</li>
<li><strong><em>Binary Trees : </em></strong>the only difference with Trees Data Structure that every set of record is indexed by a key and one node can not have more than 2 nodes which explain the title "binary" with the condition that the key value of the left node is less than its parent and the right key value is greater than its parent</li>
<li><strong><em>Priority Queues : </em></strong>with a major difference with ordinary Queues ,the Priority Queues accept states, which are saved in methods as result it can easily pull out the state that has the least cost</li>
<li><strong><em>Hash Tables : </em></strong>unique data structure where every set of record has keys and every key has an associated value</li>
</ul>
main source used for this article : <a href="https://www.topcoder.com/community/data-science/data-science-tutorials/data-structures/" target="_blank">Top Coder</a>.
素数を求める

#素数のテーブルを作る
javascript で素数を求めるプログラムを書いてみました。特にテクニカルなことはやっていません。小さい数からその倍数を消していくという総当り方式です。

```getsosu.js

// mSosuは得られた素数のテーブルのポインターです。
	var mSosu=null;
// nn より小さい数で素数となるものを探します。
	function fSosu(nn){
		var i,j,k,m;
		var cnt=0;
		var temp =Array(nn);
		for(i=0; i<nn; i++) temp[i]=0;
		m = Math.floor(Math.sqrt(nn)); // ルートnnまでチェックします。

		for(i=2; i<=m; i++){
			if(temp[i]==1) continue;
			k=Math.floor(nn/i);　// i*k までチェックします。
			for(j=2; j<=k; j++){
				temp[i*j]=1; // i*j は素数ではありません。
			}
		}

		for(i=2; i<nn; i++) if(temp[i]==0) cnt++; //素数の数
		mSosu = new Int32Array(cnt); //テーブルのメモリー確保

		for(i=2,j=0; i<nn; i++){
			if(temp[i]==0){ //テーブルに素数を格納
				mSosu[j]=i; j++;
			}
		}

		return cnt;
	}

```

##どこまで大きなテーブルを作れるか？

nn にどこまで大きな数字を入れることができるか、計算時間とともにチェックしました。

```check.js
	var nn=2;
	for(var i=0; i<25; i++){
		nn*=2;
		var start_ms = new Date().getTime();
		if (!fSosu(nn) ) break;
		var elapsed_ms = new Date().getTime() - start_ms;
		console.log(nn + ' : ' + mSosu.length + ' : ' + elapsed_ms);
	}
```

私の環境
 - Windows 7 32bit
 - Intel Core i5 M450 @2.4GHz
 - Chrome 67

で計算したところ、nn = 67108864 は10秒前後で計算が終了ます。
しかし、nn=134217728はエラーでChromeが落ちます。
rbenv install 2.5.1 失敗中...一時クローズ

----------------------
rubyのインストールを諦めました。。。
本来、node.jsのsocket.ioで別々のページでのセッションを共有する為にrubyが必要だと思っていました。何かの記事で読んだのだと思います。
これまでインストールに挑戦しましたが（休みながら１ヶ月くらい）、必要が無いことが分かりました。

`socket.io-redis` で出来るようなのでコチラを試してみたいと思います。

この記事は一旦クローズです。

でもアレですね、インストールは諦めたけど、その間色々調べたことでunixの知識が増えました。windows系の開発しかしてないので、真っ黒なコンソールはとても新鮮。

分からないことも多いけど、エンジニアに成り立ての頃を思い出す。

ある程度知識が溜まると、応用が効くようになってきて、一気に思い通りになっていく感覚。

----------------------

```
make[2]: ディレクトリ `/tmp/ruby-build.20180720064308.22306/ruby-2.5.1/ext/-test-/dln/empty' に入ります
compiling empty.c
linking shared-object -test-/dln/empty.so
/bin/ld: /usr/local/lib/libssl.a(methods.o): 再配置 R_X86_64_32 (`.rodata' に対する) は共有オブジェクト作成時には使用できません。-fPIC を付けて再コンパイルしてください。
/usr/local/lib/libssl.a: シンボルを読み込めませんでした: 不正な値です
collect2: エラー: ld はステータス 1 で終了しました
make[2]: *** [../../.ext/x86_64-linux/openssl.so] エラー 1
make[2]: ディレクトリ `/tmp/ruby-build.20180720064308.22306/ruby-2.5.1/ext/openssl' から出ます
make[1]: *** [ext/openssl/all] エラー 2
make[1]: *** 未完了のジョブを待っています....
make[2]: ディレクトリ `/tmp/ruby-build.20180720064308.22306/ruby-2.5.1/ext/-test-/dln/empty' から出ます
make[1]: ディレクトリ `/tmp/ruby-build.20180720064308.22306/ruby-2.5.1' から出ます
make: *** [build-ext] エラー 2
```
(´･ω･`)？？
出て行かないで...

rbenv で上手く行かないから、rubyをサイトからダウンロードして、インストールを試みた。
rbenvの時と同じ雰囲気でエラーに。
少し調べてみたら、どうやらopensslのコンパイルで失敗している模様。

```
$ cd ruby-2.5.1/ext/openssl
$ sudo make
linking shared-object openssl.so
/bin/ld: /usr/local/lib/libssl.a(methods.o): 再配置 R_X86_64_32 (`.rodata' に対する) は共有オブジェクト作成時には使用できません。-fPIC を付けて再コンパイルしてください。
/usr/local/lib/libssl.a: シンボルを読み込めませんでした: 不正な値です
collect2: エラー: ld はステータス 1 で終了しました
make: *** [../../.ext/x86_64-linux/openssl.so] エラー 1
```

opensslは単体でソースからインストールしてあるんだけど、Rubyで改めてコンパイルする必要はあるのだろうか...? 必要なければコンパイルから外したいんだけど、どうしたら良いんだ。

だ、誰か教えて...

`make clean` でクリアしてもう一回
`sudo make`

```
compiling ossl_x509ext.c
compiling ossl_x509name.c
compiling ossl_x509req.c
compiling ossl_x509revoked.c
compiling ossl_x509store.c
linking shared-object openssl.so
/bin/ld: /usr/local/lib/libssl.a(methods.o): 再配置 R_X86_64_32 (`.rodata' に対する) は共有オブジェクト作成時には使用できません。-fPIC を付けて再コンパイルしてください。
/usr/local/lib/libssl.a: シンボルを読み込めませんでした: 不正な値です
collect2: エラー: ld はステータス 1 で終了しました
make: *** [../../.ext/x86_64-linux/openssl.so] エラー 1
```
`compiling ossl_x509store.c`
この辺りのコンパイルでエラーなのか。
CFLAGSに-fPICを付けてるんだけどな...

てか、ossl_x509store.cはMakefileの最後のソースじゃないか。
うーん...リンクで失敗してるのかな？
sudo rbenv install コマンドが動かない...を解決した


```
$sudo rbenv install 2.5.1
rbenv: no such command 'install'
```

(´･ω･`)？

rbenvのプログラム内で、プラグインのコマンドを実行する時に、

`{$RBENV_ROOT}/plugins`

を参照するようです。
なので、$RBENV で設定されているパスのフォルダ内にpluginsが無いと実行できない。

僕の場合は、~/.rbenv/plugins にあったから、リンクを設定し参照できるようにしました。

`ln -s ~/.rbenv/plugins /usr/local/rbenv/plugins`

動作を確認するには以下のコマンド

`sudo rbenv install -l`

これで、バージョンの一覧が表示されれば設定完了...かな？

実はこれを書いている時点で、rubyをrbenvでインストール中。

```
$ sudo rbenv install 2.5.1
Downloading ruby-2.5.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.bz2
Installing ruby-2.5.1...
```

いやもう、２日ほどインストールできなくて四苦八苦している...
今度こそはインストールできますように！！

それにしてもインストール長いな...30分くらいはいつも待たされる...
Google Cloud Text-To-Speechに、嫌そうにしゃべってもらう

Google Cloud Text-To-Speechが、[高品質なWavenet音声に対応している件](https://qiita.com/tinoue@github/items/9772b8a41348264b3ca6)について先日書きましたが、Wavenet音声の場合、pitchパラメータを大きく変更してもそれなりの音声でしゃべることがわかりました。

pitchを変えることで、いつもの明るい声とは違うテンションで喋らせることができます。エラー通知とかに使えそうです。

- [普通の声](https://drive.google.com/open?id=17y4l7sJcdYdd3QuNJQj5cI7IOglgOMem) (pitch = 0.0)

- [嫌そうな声](https://drive.google.com/open?id=1GPNfS01jPxNVAmcRqrfJ0RD4nXQpcIoy) (pitch = -8.0)

- [死にそうな声](https://drive.google.com/open?id=1xO6qgkR593La7qkVsJ3ekw1ibG9Fchqu) (pitch = -20.0)

ちなみに、pitchをプラス方向に変えてもかすれ声になる一方で、あまり使えそうな感じはありませんでした。
Hulu 同時字幕で英語学習

[![hulu_dual_subtitle.jpg](https://qiita-image-store.s3.amazonaws.com/0/69351/bafdec08-23d1-28db-097c-be24baf39ce9.jpeg)](https://www.youtube.com/watch?v=c1HAwD42Xvo)

Huluで英語字幕と日本語字幕を同時に表示させて英語学習が出来るChrome拡張機能を公開しました。

- 3秒巻き戻し機能。巻き戻し秒数は設定から変更できます。
- 再生速度の変更が出来ます。0.2倍速から2.0倍速までです。
- セリフの終了直前に一時停止機能
- ひとつのセリフをリピート再生
- 字幕の英単語をクリックして意味の表示

[デモ動画をYoutubeに投稿しました](https://www.youtube.com/watch?v=c1HAwD42Xvo)

よろしくお願いいたします。

#Chrome拡張機能のダウンロードはこちらから
[Hulu 同時字幕で英語学習](https://chrome.google.com/webstore/detail/lmmahellpnmhbpmimpebhikpjhiojhok)
[Netflix 同時字幕で英語学習](https://chrome.google.com/webstore/detail/gibmkmmdicoffkhjkfimmjkojjopoagg) (Netflix版もあります)

#Huluで配信されている英語字幕付きの海外ドラマ一覧
[こちら](https://www.happyon.jp/features/English_subtitles)にあります。フレンズやウォーキングデッドなどがあります。シリコンバレーというドラマが面白かったので、また続きを配信して欲しいです。お願いしますHulu様。
Aphorism for Software Engineer - ソフトウェア技術者のための格言集

# 概要
Aphorism for Software Engineer (略称：SEアフォ)は、ソフトウェア技術者のための格言集です。

# 格言
## 共通
- 繰り返しを避けよ（DRY : [Don't repeat yourself](https://ja.wikipedia.org/wiki/Don%27t_repeat_yourself)）
- 簡潔に単純にしておけ : [KISSの原則](https://ja.wikipedia.org/wiki/KISS%E3%81%AE%E5%8E%9F%E5%89%87) (Keep it short and simple.)
- それはきっと必要にならない （YAGNI ： You ain't gonna need it）

## オープン系
- 設定より規約（Convention over Configuration）

## 組み込み系
TBD...
Delphi Starter Edition で作成したプロジェクトに Delphi Community Edition で Win64 が追加できない件について

# Delphi Starter Edition で作成したプロジェクトに Delphi Community Edition で Win64 が追加できない件について

Community Edition で新規に作成したプロジェクトに、ターゲットプラットフォームとして 64bit Windows を追加することはできるのですが、以前に Starter Edition で作成したプロジェクトには出来ないという問題に遭遇しました. (プラットフォームの追加メニューがグレーアウトしててできない)

Community Edition で新規に作成したプロジェクトの dproj ファイルを眺めたところ 64bit Windows が追加される前から、以下のように Win64 の記述があるようです.
※ dproj は XML ファイルです. 念の為.

```xml
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    ....
    <ProjectExtensions>
        ....
        <BorlandProject>
            ....
            <Platforms>
                <Platform value="Win32">True</Platform>
                <Platform value="Win64">False</Platform>
            </Platforms>
        </BorlandProject>
        ....
    </ProjectExtensions>
    ....
</Project>
```

この`<Platform value="Win64">False</Platform>`を Starter Edition で作成したプロジェクトの dproj に加えたところ、メニューのグレーアウトがなくなり、64bit Windows が追加できました.
Review for recently Udemy classes

## Review for recently Udemy classes

### 1. [Unity 3D迷路ゲーム開発入門](https://www.udemy.com/unity3d-maze/)
- ３Ｄのパックマンもどきのゲームを作成する。
- 基本的にオブジェクトはプリミティブなものの組み合わせでマテリアルやシェーダーについては色を変える程度。
- 敵の動きをごく簡単なＡＩで制御し、自機を追いかける動きを作る。
- 書く量多め。Ｃ＃で実装するが、ラムダ式を多用するため慣れてないと書き方に戸惑うことになる。（習得の材料にもなる）
    - ソースファイルの量も割と多く、クラスや関数がそれなりに複雑に絡み合うので、プログラム書いたことがない人間にはちょっとキツそう。 
    - 継承・値／参照渡しなどの概念も入ってくるため、このあたりが全く分からないとたぶんしんどい。
- スタート／ゴールはあるがシーンの切り替えはなく、ゲーム自体は１シーンで完結する。ボタン等のＵＩも実装するが、Unity備え付きのもの。
- ある程度のプログラミング知識・思考が求められるが、そこさえクリアできるならとっつくためのクラスとしては良い感じと思う。

### 2. [【初心者でも簡単】はじめてのUnity 3D ゲームデザイン](https://www.udemy.com/unity-3d-game-design/)
- **Mac使用が前提なので、Unity自体はともかく公開のためのアプリ導入・設定等Windowsで行う場合はそれなりに読み替えるスキルが必要。**
    - Macというよりコマンドライン操作が重要なので、おそらくLinuxならほぼ同じ操作をトレースできる。LinuxでUnity使いたい人間がどれだけいるかは置いといて。
    - やり方が悪いのかはわからないが、Cygwin使用は失敗。
- ゲーム自体は非常に単純。プリミティブなオブジェクトに多少のライトや素材サイトから持ってきたモデル・テクスチャを当て、その中を移動する程度。
    - コードは書かない。基本的にStandardAssetsや持ってきた素材を組み合わせて「歩き回れるステージを構築」する程度と考えるべき。
- トークがなんだかなれなれしい。
- 初心者＝Unity触るの初めて・プログラミング自体できない人間、と読み解くべき。
- 特徴的なのは後半で、Firebaseを使用したゲームの公開方法を説明している。他の講座で作ったゲームをこの方法で公開してみるのはアリだろう。
    - ここに価値を見出せない場合、多少でもUnityを使った経験があるなら見るべき箇所は無いだろう。
- どうでもいいけど、本当にプログラミング知識がゼロ（一切自力でのコーディングはしない）の場合、どの程度のゲームが作れるんだろう。探せばすごいのがありそうだけど。
    - でもそれならUnrealEngineでいい気がする。

### 3. [Create a simple 3D Unity Game from Scratch](https://www.udemy.com/create-a-simple-3d-unity-game-in-2-hours-from-scratch/)
- **英語**。字幕もないのでなにいってるのかよくわからないけど、タイトルと操作追いかけていけば概ねやることはわかる。
- ３Ｄステージ上で、はずむボールを操作して次々に上空に現れるタイルにどんどん乗っていき、スコアを稼ぐ。
- 最後のスコア・ハイスコアが記録される。クリアは無いが、スタート画面→ゲーム画面の遷移処理や、ゲームオーバーに伴う逆の遷移がある。
- [#1](https://qiita.com/we-yu/items/a34efbba6c1d45e0b3a7#1-unity-3d%E8%BF%B7%E8%B7%AF%E3%82%B2%E3%83%BC%E3%83%A0%E9%96%8B%E7%99%BA%E5%85%A5%E9%96%80)と比べるとコード自体は非常に単純だが、RigidbodyやAddForceを使った物理演算処理が入ってくる。
    - 従って「３Ｄゲーム」である必然性は高め。
- テキストやボタン処理でＵＩも絡んでくるが、Unity既存のもの。
- ビルド実施してのexeファイル生成も行う。
- これといって特筆すべき点は無いが、タイトル通りスクラッチからごく単純なゲームを作りたいというニーズには合っている。
半年間のAWS学習

# エンジニアとして、今までやってたこと
1. 業務ロジックの実装
    1. Winform（C#）
    2. Web（開発）
    3. などなど
2. CI/CDの自動化
3. などなど

自分の小っちゃい世界に限定されたものばかりです。

# AWS触った感想
前にもAWSのSimpleDBというサービスを使ったことがありましたが、他のサービスには全く触られなかった。
今年03月10日の[JAWS DAYS 2018](https://jawsdays2018.jaws-ug.jp/)のインベントを参加しました。その場で、新しい言葉をたくさん聞いた。

- Serverlessどか
- VUIとか

がありました。

---
参加するプロジェクトの都合で、AWSを触るチャンスがありましたので、AWSを全力で勉強し始めました。なぜこんなサービスが必要なのか、こんな役割があるか、のような繰り返しで、徐々自信も増えています。
AWSのサービスが沢山が有りますが、サービス単体でできるものが少ないですが、様々な組み合わせで、それぞれなシステムの要件を満たすアーキテクチャーを構築できる気がします。
AWSの情報が多すぎで、何でも勉強すれば、何でも出来ないかと思うんですが、アーキテクチャーとセキュリティーを中心に勉強しています。

# 今まで取得したAWSの資格
目標まで、まだまだですが、今までに、下記の資格を手に入れました。
## AWS Certified Cloud Practitioner
![AWS Certified Cloud Practitioner](https://qiita-image-store.s3.amazonaws.com/0/149595/fab69557-5808-cf2f-0228-af5db0a0711c.png)
## AWS Certified Solutions Architect - Associate
![AWS Certified Solutions Architect - Associate](https://qiita-image-store.s3.amazonaws.com/0/149595/744bb6a6-b2fd-352b-e535-f574dfa60da4.png)

# 勉強するために読んだ本

## 合格対策 AWS認定ソリューションアーキテクト - アソシエイト
[![合格対策 AWS認定ソリューションアーキテクト - アソシエイト](https://qiita-image-store.s3.amazonaws.com/0/149595/c3bdf9d6-a761-6c35-0d41-049baab1c796.png)](https://www.amazon.co.jp/dp/B01LZ2CBKB/ref=rdr_kindle_ext_tmb)

## Amazon Web Services実践入門
[![Amazon Web Services実践入門](https://qiita-image-store.s3.amazonaws.com/0/149595/2155840b-1984-61fe-815b-227e205b5681.png)](https://www.amazon.co.jp/dp/4774176737/ref=olp_product_details)

## Amazon Web Services パターン別構築・運用ガイド 改訂第2版
[![Amazon Web Services パターン別構築・運用ガイド 改訂第2版](https://qiita-image-store.s3.amazonaws.com/0/149595/d2e140ef-9c31-1a82-2c26-a9d0019a6b2c.png)](https://www.amazon.co.jp/gp/product/4797392576/ref=oh_aui_detailpage_o03_s01)

## Amazon Web Services企業導入ガイドブック
[![Amazon Web Services企業導入ガイドブック](https://qiita-image-store.s3.amazonaws.com/0/149595/94d4f195-002b-2b05-e54d-2fa37ef08121.png)](https://www.amazon.co.jp/gp/product/4839952337/ref=oh_aui_detailpage_o03_s01)

## AWSによるサーバーレスアーキテクチャ
[![AWSによるサーバーレスアーキテクチャ](https://qiita-image-store.s3.amazonaws.com/0/149595/d645701f-634e-9077-da3c-6bc44ffd27cb.png)](https://www.amazon.co.jp/gp/product/4798155160/ref=oh_aui_detailpage_o03_s00)

## Amazon Web Services 定番業務システム12パターン
[![Amazon Web Services 定番業務システム12パターン](https://qiita-image-store.s3.amazonaws.com/0/149595/490b8de4-f728-7691-424c-ab8de363fa5e.png)](https://www.amazon.co.jp/gp/product/4822237559/ref=oh_aui_detailpage_o01_s00)

## Amazon Web Services 業務システム設計・移行ガイド
[![Amazon Web Services 業務システム設計・移行ガイド](https://qiita-image-store.s3.amazonaws.com/0/149595/4d36bbd5-a283-e200-a9ae-f1808bc3013b.png)](https://www.amazon.co.jp/gp/product/4797392568/ref=oh_aui_detailpage_o01_s00)

# 今後の行き方
AWSに対する熱情を保ち続けて、AWSだけでなく、AzureやGCPも少し勉強しようかと考えています。あと、勉強した内容を適当に整理するかと考えています。
## クラウド以外にも
### 勉強したいやつ
1. コンテナー
    - Docker
    - k8s
2. DevOps 

### 面白うそうなやつ
1. AI
2. Big data
3. Blockchain

## 雑談
技術が日進月歩なので、目標を選定して、あるポイントに注力するのも大事だと思います。
良い明日を、皆さんも一緒に頑張りましょう。
Mac上でFTDI USBデバイスをD2XX APIから使いたい

Bit-bangモードで快適なパラレルポート生活を送りたい！
あとで知ったけれど、どうもYoutube上に[公式のビデオ](https://www.youtube.com/watch?v=Ir2PVz1870E)があるようだ。

# ドライバ
## ダウンロード
[FTDI社のページ](http://www.ftdichip.com/Drivers/D2XX.htm)から、D2XXなるドライバをダウンロードする。D2XX API (`ftd2xx.h`)を通じてデバイスを列挙したり、開いたり閉じたりできるようになる。

## Apple社製ドライバとの競合
[参考サイト](https://stackoverflow.com/questions/28461433/unable-to-open-a-connection-to-an-ftdi-device)（実際には、[公式ビデオ](https://www.youtube.com/watch?v=Ir2PVz1870E)でもさらっと紹介されていた）

Appleからデフォルトで提供されているFTDI社製チップのドライバが、D2XXを使う際に邪魔になる：

+ デバイスを列挙する際にデバイスの状態が`flag = 1 (USED)`になってしまい、ベンダーIDやシリアル番号を取得できない
+ `FT_Open()`で開こうとしても、返り値が`3 (FT_DEVICE_NOT_OPENED)`でエラーになってしまう

Apple社製ドライバは、`kextstat`なるデバイスドライバマネージャコマンドを使うことで確認できる：

```
$ kextstat | grep FTDI
  896    0 0xffffff7f83af4000 0x6000     0x6000     com.apple.driver.AppleUSBFTDI (5.0.0) (... 以下シリアル番号など)
```

D2XXからデバイスを操作したい場合、ここで得たドライバ情報を使ってドライバを無効化してやる必要がある：

```
$ sudo kextunload -b com.apple.driver.AppleUSBFTDI
$ kextstat | grep FTDI
$ 
```

# その他
一身上の理由でフリーの[libFTDI](https://www.intra2net.com/en/developer/libftdi/)は使っていないけれど、ドライバ競合の問題はおそらくこちらでも起きるのではないか。

またやる気が出たら、bit-bangプログラミングの一連の流れをまとめたい。
ローカルのMongoDBを2系から4.0にアップデートする

## 概要
MongoDBの4.0が[リリース](https://dev.classmethod.jp/server-side/db/introducing-mongodb-4/)され、トランザクションがサポートされるようになりました。  
ローカルの開発環境で試そうと思いましたが、バージョン2系がインストールされていたので、まずは4.0にアップデートしていきます。

## 手順
手順としては下記になります。

1. 動いているmongodbの停止
2. バックアップの取得
3. 既存バージョンの削除
4. 3系へのアップデート
5. 4系へのアップデート

一気に4.0へアップデートさせようとしたところ、起動時にエラーが発生しました。
ログを確認してみると、3.6を経由する必要があると読み取れたため、まずは3.6を目指して順番にアップデートしてから、4.0にします。

```
UPGRADE PROBLEM: The data files need to be fully upgraded to version 3.6 before attempting an upgrade to 4.0
```

ちなみに現在のバージョンは下記です。

```
$ mongo
MongoDB shell version: 2.6.12
```

### 1. 動いているmongodbの停止

```
service mongod stop
```

### 2. バックアップの取得

```
mkdir ~/mongo_dump
mongodump -v --dbpath /var/lib/mongo --out ~/mongo_dump/
```

### 3. 既存バージョンの削除

```
yum remove mongo-org*
yum list installed | grep mongo
```

### 4. 3系のインストール

#### 3.xのインストール
##### repo用意

```:/etc/yum.repos.d/mongodb-org-3.x.repo
[mongodb-org-3.x]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.x/x86_64/
gpgcheck=0
enabled=1
```

##### インストール実施

```
yum install -y mongodb-org-3.x
```

##### 立ち上げ

```
service mongod start
```

##### 停止

```
service mongod stop
```

##### 削除

```
yum remove -y mongo-org*
```

### 3.4→3.6のときの対応

3.4から3.6にアップデートするときも下記のエラーが発生しました。  

```
UPGRADE PROBLEM: The data files need to be fully upgraded to version 3.4 before attempting an upgrade to 3.6; see http://dochub.mongodb.org/core/3.6-upgrade-fcv for more details.
```

リンク先に飛んでみるとコマンドの実行を求められたので、コマンドを実行します。

```
// バージョンの確認
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )
{ "featureCompatibilityVersion" : "3.2", "ok" : 1 }

// バージョンの変更
> db.adminCommand( { setFeatureCompatibilityVersion: "3.4" } )
```

このコマンドは3.6→4.0でも使うので覚えておくようにしましょう。

### 5. 4系のインストール

[公式の手順](https://docs.mongodb.com/master/tutorial/install-mongodb-on-red-hat/)に従ってインストールしていきます。

#### repo用意

```:/etc/yum.repos.d/mongodb-org-3.2.repo
[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
```

#### インストール実施

```
yum install -y mongodb-org-4.0.0 mongodb-org-server-4.0.0 mongodb-org-shell-4.0.0 mongodb-org-mongos-4.0.0 mongodb-org-tools-4.0.0
```

#### 立ち上げ

```
service mongod start
```

##### 起動確認

```
$ mongo
MongoDB shell version v4.0.0
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 4.0.0
```

これでインストールができました。
データの破損も見受けられなかったので、アップデートも問題なさそうです。

最後まで読んで頂きありがとうございました。

## 参考資料
* [Install MongoDB Community Edition on Red Hat Enterprise or CentOS Linux — MongoDB Manual](https://docs.mongodb.com/master/tutorial/install-mongodb-on-red-hat/)
* [MongoDBがダウンするようになったので、v2.4.5からv3.0にアップデートした話](https://webmake.info/mongodb%E3%81%8C%E3%83%80%E3%82%A6%E3%83%B3%E3%81%99%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F%E3%81%AE%E3%81%A7%E3%80%81v2-4-5%E3%81%8B%E3%82%89v3-0%E3%81%AB%E3%82%A2%E3%83%83/)
wheelグループにユーザー追加(sedによるファイル変更手順)


#前提条件
・RHEL6.x
・rootに昇格できる管理者ユーザで実施

#経緯
有識者の手順通りにやってみたものの、手順はすべて「ファイルをviで編集」の文字ばかり。
サーバ何十台もあるのにそれはやってられん・・・というわけで、なにか楽な方法がないかと思案。
思い立ったらすぐ計画、行動。天才じゃない私にはそれしかできぬ。


#やりたいこと
ある特定のユーザを、su(root=管理者権限)に昇格させたい。

###管理ユーザーでログイン、root昇格

```bash
\[User01@hostname ~]$ su -
\[root@hostname ~]#
```

###対象ファイルのバックアップ

```bash
[root@hostname ~]# cp /etc/group /etc/group_yyyymmdd_bak
[root@hostname ~]# cp /etc/pam.d/su /etc/pam.d/su_yyyymmdd_bak
```

###wheelグループにユーザ追加

```bash
[root@hostname ~]# sed -i -e '/wheel:x/s/$/,ユーザ名/g' /etc/group
```

-iで上書き保存に指定。
-eで検索条件と追加文字(シングルクォーテーション)。
「'/wheel:x」で検索行を抽出。「/s/$/」で追加する文字列を記載。
「,ユーザ名」のカンマは、すでにwheelにユーザを記載している場合にだけ必要であるため注意。
サンプルは以下。

```bash
[root@hostname ~]# sed -i -e '/wheel:x/s/$/,User02/g' /etc/group
```

```bash:/etc/group(変更前)
wheel:x:10:User01
```

```bash:/etc/group(変更後)
wheel:x:10:User01,User02
```


####/etc/pam.d/suの有効確認
前提条件が満たせていれば、おそらく実施済みの認識。

```bash
[root@hostname ~]# cat /etc/pam.d/su
```

```bash:/etc/pam.d/su
～～～～
auth  sufficient pam_wheel.so trust use_uid
auth  required pam_wheel.so use_uid
～～～～
```

以上のauth～の行がない、または先頭行に「#」があれば
追記か#を削除して、以上の状態になるように追記修正する。

###設定確認(単体チェック)
```bash
[root@hostname ~]# diff /etc/group /etc/group_yyyymmdd_bak
[root@hostname ~]# diff /etc/pam.d/su /etc/pam.d/su_yyyymmdd_bak
```

変更分のみ差分として出ればOK。


###設定確認(機能性)
設定したホストにSSH接続。
先ほどwheelに追加したユーザ名でログインしてsu-実施。
rootに昇格できればOK.

```bash
[User02@hostname ~]$ su -
[root@hostname ~]# 
```

#Linuxの感想
コマンドライン文化はラクや～～。
WindowsはGUI文化ですから。

#終わりに

[Lenny Kravitz - Low (Official Video)](https://www.youtube.com/watch?v=BilaShsQphM)

レニークラヴィッツお兄さんの新曲。娘さんのゾーイクラヴィッツさんは、『MADMAX怒りのデスロード』(北斗の拳の元ネタ映画)にヒロインとして出ていたり、親子ともに大活躍です。
レニー兄さんの曲も相変わらず渋くてかっこいいです。本曲の「フー！」などの甲高い掛け声は、故マイケルジャクソンの地声らしいっす。フォー！
Angularでngrx shematicsを使う

# ngrx schematicsを使う

## [ngrx](https://github.com/ngrx/platform/blob/master/docs/store/README.md)とは

[Redux](https://redux.js.org/)に影響を受けたAngular用のstate manager
## ngrxを使う理由
個人的に3つのどれかが該当すれば、というより基本的にngrx使うことが多い。Angularを導入するプロジェクトに小規模のものがないと思ってるから。

基本的には以下3つが基準だとおもってます。

- component間の継承が多い(@Input()や@Output()など)
- componentが肥大化してしまっている
- service loginがcomponentにまで影響を与えている

### schematicsを使う理由

_ng XXX_コマンドでfileの作成と雛形を作成する便利さと、
directory構成、file構成に秩序を[schematics](https://github.com/ngrx/platform/blob/master/docs/schematics/README.md)によってもたらしてくれる。

## Schematicsを使う

### angular projectの作成

```terminal
$ ng new <my-project> --style=scss
$ cd <my-project>
$ npm install
```
Angularのプロジェクトの作成とdefault styleをscssに設定。

### ngrx schematicsを導入する

```terminal
$ cd <my-project>
$ npm install @ngrx/schematics --save-dev
$ npm install @ngrx/{store,effects,entity,store-devtools} --save
$ ng config cli.defaultCollection @ngrx/schematics
```
上記により依存関係のpackageのインストールと、schematicsコマンドを使うことができるようになります。

### schematicsコマンドを使う

```terminal
$ ng generate @ngrx/schematics:feature App --root --module app.module.ts
```
基本的には
ng generate @ngrx/schematics:[schematics] [Name] --module [ModuleName]
でschematicsを使えます。

[参考](https://github.com/ngrx/platform/blob/master/docs/schematics/README.md)

そんな感じです。
基本的には:feature -g をよく使います。
schematicsは以下、

- Action
- Container
- Effect
- Entity
- Feature
- Reducer
- Store
AlexaのカスタムスキルをTypeScriptで作るテンプレートを作ってみた。

## 経緯
先日、[TypeScriptでAlexaスキルを作ったことについてLTする機会があった](https://speakerdeck.com/minamo173/trying-to-build-alexa-skill-with-typescript-2018-07-13)ので、あわせて（？） [alexa-skill-typescript-template](https://github.com/minamo173/alexa-skill-typescript-template/) というリポジトリでAlexaスキルをTypeScriptで作るテンプレートを公開しました。

AlexaのカスタムスキルはAWS Lambdaを使って開発することが多いかと思うのですが、調べていた限りではなかなかTypeScriptで開発されているドキュメントはあまり多くありませんでした。

自分としてはTypeScriptで開発した方が今までのAWS Lambdaを使った開発の中でも効率が良かったと感じたので、自分が公開しているAlexaスキルの開発でも利用しているもので共有出来る部分をテンプレートとして公開してみました。

（また、2018年4月にリリースされた`Alexa Skills Kit SDK v2 for Node.js`は、TypeScriptで開発されており、型定義が元々されているため、AlexaスキルをTypeScriptで作るのは一段とフィットしていると自分は考えています。）

## このテンプレートで出来ること
+ TypeScriptファイルからJavaSctiptファイルへのコンパイル。

+ コンパイルされたJavaScriptファイルを含めたフォルダをAWS Lambdaの関数としてパッケージング。

+ [AWS SAM ( Serverless Application Model )](https://github.com/awslabs/serverless-application-model)でAlexaスキルで利用するAWS Lambda関数をはじめとした各AWSリソースのデプロイ。

## 利用するにあたって必要なもの
### TypeScriptのインストール
```bash
$ yarn global add typescript
```

### AWS SAM CLIの準備
+ AWS SAM CLIのインストール

```bash
$ pip install aws-sam-cli
```

+ AWSの認証情報の設定  
お使いのAWSアカウントのIAMの認証情報を下記の通り設定します。  
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-config-files.html  


### デプロイするLambda関数をアップロードするためのS3バケットの用意
AWS Lambdaの関数としてデプロイする際に、前段階として後述で出てくる `$ sam package` というコマンドでAWS Lambdaの関数としてJavaScriptファイルをパッケージングしてS3にアップロードする必要があるため用意します。

## 主なファイル・フォルダについて
+ `skill/src` フォルダ
開発では主にこのフォルダの内容を編集します。
  + `skill/src/index.ts`  
AWS Lambdaの関数として使うメインのファイルです。

+ `skill/dist` フォルダ
このフォルダは`skill/src`フォルダの内容をコンパイルし、必要なパッケージをインストールした状態で格納されます。

+ `template.yml`
AWS SAMのテンプレートです。
デフォルトでは　`skill/dist` フォルダをAWS Lambdaの関数としてデプロイするよう指定してあります。
（なお、自分のAlexaスキル開発ではスキルで使うDynamoDBも一緒にこのファイルで管理しています。）

## 使い方
### AWSに各リソースをデプロイする場合
```bash
$ sam package --template-file template.yaml \
--output-template-file serverless-output.yaml \
--s3-bucket 「アップロード先のS3バケット名」

$ sam deploy --template-file serverless-output.yaml \
--stack-name 「スタック名」 \
--capabilities=CAPABILITY_IAM
```

※「アップロード先のS3バケット名」と「スタック名」は任意に変更してください。

### TypeScriptファイルをコンパイルする場合
```bash
$ cd src/
$ yarn build
```

### 上記2つをまとめて1度にやる場合
```bash
$ sh deploy.sh
```

※このシェルスクリプト内も「アップロード先のS3バケット名」と「スタック名」は任意に変更してください。
Jupyter NotebookのNbextensionsで邪魔なscratchpadのサイズを変更する

# Jupyter Notebookの機能を拡張する、NbextensionのScratchpadが邪魔
標準の見た目
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254192/104a0717-d655-3375-e8de-b957f6ac8255.png)
↑をこう↓する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254192/0f488ee3-802d-c25b-1674-51645d1d7aed.png)

# 変更手順
## 簡単なバージョン：jupyterのコード中で変更する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254192/ce2f991c-ec22-a48c-cb5a-b9e264a8507d.png)

セル中でHTMLを指定し、実行するだけで↑の図のようになる。

```{任意のCodeセル.ipynb}
%%HTML
<style>
/* コード記載部の位置と幅と背景色変更 */
#notebook-container {
    /* 左寄せにする。Contentsの表示など使わないなら0でもよい */
    margin-left:40ex;
    /* 幅を指定　40%くらいでもよいけど、お好みで。 */
    width: 105ex;
    /* 背景色 */
    background-color:#d0d0d8;
}

/* scratchpadの幅と背景色の変更 */                                 
#nbextension-scratchpad { width: 80ex; background-color: #d0d0df; }

/* 以下おまけ */
/* 背景の色 */
body.notebook_app{ background-color:#a0a0a8; }
/* ヘッダーの色 */
#header { background-color:#d0d0d8; }
/* 実行番号 In [] 部分の幅 */
.prompt.input_prompt { min-width: 11ex; }
/* マークダウンのセルの背景 */
.text_cell_render.rendered_html { background-color:#f0f0f8; }

</style>
```

## 手間のかかるバージョン：いちいち設定したくない方向け（Windows）
### コード記載部分の設定
C:\Users\ユーザー名\\.jupyter\custom\　の「custom.css」を編集

```{custom.css}
/* コード記載部の位置と幅と背景色変更 */
#notebook-container {
    /* 左寄せにする。Contentsの表示など使わないなら0でもよい */
    margin-left:40ex;
    /* 幅を指定　40%くらいでもよいけど、お好みで。 */
    width: 105ex;
    /* 背景色 */
    background-color:#d0d0d8;
}

/* scratchpadの幅と背景色の変更 */                                 
#nbextension-scratchpad { width: 90ex; background-color: #d0d0df; }

/* 以下おまけ */
/* 背景の色 */
body.notebook_app{ background-color:#a0a0a8; }
/* ヘッダーの色 */
#header { background-color:#d0d0d8; }
/* 実行番号 In [] 部分の幅 */
.prompt.input_prompt { min-width: 11ex; }
/* マークダウンのセルの背景 */
.text_cell_render.rendered_html { background-color:#f0f0f8; }

/* これ以降は変更しない */

```

### Nbextensionsの設定
Anaconda Promptなど、pythonを実行できる環境で、下記を実行

```{}
jupyter contrib nbextension install --user
```

（詳細は、
https://github.com/ipython-contrib/jupyter_contrib_nbextensions
の「2. Install javascript and css files」を参照してください）

すると、C:\Users\ユーザー名\AppData\Roaming\jupyter\nbextensions\scratchpad\ など
Nbextensionsの一連の機能に関するフォルダが作られるので、scratchpadフォルダの「scratchpad.css」を開いて「#nbextension-scratchpad」の部分を編集する。

```{scratchpad.css}
#nbextension-scratchpad {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 90ex; /* 標準は50% */
  background-color: #d0d0df; /* 標準は #F8F5E1; */
  border-left: 1px solid #aaa;
  border-top: 1px solid #aaa;
  z-index: 105;
}
```

★おススメ：スクラッチパッドの高さを変えたい人は、「main.js」も編集する
height: site_height　の部分。
*0.7くらいあると、スクラッチパッドの上部にスペースがあいて、
ブラウザを狭く使ってコードとスクラッチパッドが重なってもコードが見える。

```{main.js}
//85行目以降に、スクラッチパッドを開いた時の高さの定義があるので、site_hight*0.7くらいで高さを調整
  Scratchpad.prototype.expand = function () {
    this.collapsed = false;
    var site_height = $("#site").height();
    this.element.animate({
      height: site_height*0.7,
    }, 200);
```

# 参考
- Jupyter Notebookの見た目をカスタムする方法  
https://www.lisz-works.com/entry/jupyter-theme
- extensionを追加してもっと快適なJupyter環境を構築する  
https://qiita.com/sasaki77/items/30a19d2be7d94116b237
トリプルウィンマネジメントのココロガケ

こんにちは。へっぽこマネージャーです。
ここ数年の経験と知識を持ってマネージャーが守らなければならない
トリプルウィンマネジメントについて心掛けておきたいことを言語化します。

# Triple Win Management
まず **トリプルウィンマネジメント** が何を指しているかなのですが
それは、3方良しのプロジェクト推進の指針です。

# プロジェクトにおける3方
ここで言う3方は以下と定義します。
- 顧客(もしくは消費者)
- 会社
- プロジェクトメンバー


# Win-Winの関係は？
Triple Winを考える前にWin Winを考えます。

Win-Winは
会社間で言えば、自社と顧客の双方に利益があることですね。
これ自体は当たり前の事だと思うのですが、

ちょっと待って会社間で儲かればいいの？？？誰かないがしろにされていないか？
というのをちょっと考えてみるのがトリプルウィンマネジメントです。

# 3方がバランス悪いとき

- 顧客が損をする時
法外な見積もりで仕事をする時！
例えば「WEBページ1ページ作るのにひと月と100万円かかります。」
みたいな話があって会社儲かる、プロジェクトメンバーの工数は実際は2,3日で楽勝。


- 会社が損をする時
メンバーがサボる。とにかくサボる。
十分な工数があるにも関わらず、納期も過ぎてもサボるとくにかくサボる。
おかげで会社が請け負っていた仕事が終わらず、売り上げに悪影響を与える。


- プロジェクトメンバーが損をする時
案件の単価が良い！だが工数が短い。メンバーがとにかく頑張る、とにかく頑張る。
達成する。顧客喜ぶ、会社潤う。メンバー倒れる。


# つまり
顧客、会社に関しては割りと考えてると思います。
でもプロジェクトメンバーの幸せ考えた事ありますか？

メンバーの**良し**は単に労働時間がすくなければOKとかそういうレベルじゃないと思います。

- 仕事の日々を楽しく過ごせるように**動機付け**をする事
- いま携わっている技術に**興味関心**を持って取り組めているか
- 何かで気を落としてないか、そこを**カバー**できているか

と、人なのでいろんな要因で気持ちが上がったり、下がったりすると思います。

マネージャーとしてプロジェクトに関わる上でメンバーの幸せを考えること
すなわち、トリプルウィンマネジメントはとても大切なことだと忘れないようにココロガケてます。

小生もへっぽこなので実現できていない事も多いですし、意見が間違っているかも知れません。
この考えもアップデートしたいですし、チラ見してくれた方にでも響けばと思います。
リモートデスクトップで複数接続を許可する

#はじめに
Windows Serverではデフォルトの設定では、同時にリモートデスクトップ接続できる数が制限されています😥
これでは困る❗という場合は以下の設定を変更しましょう😁

# 設定方法
「ファイル名を指定して実行」を立ち上げます
「gpedit.msc」と入力します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/228400/6fb6dc8f-7aea-1aa5-bfe2-beb149300d1b.png)
↓
ローカルグループポリシーエディターが開くので、以下のように展開していきます

「ローカルコンピューターポリシー」
-「コンピューターの構成」
--「管理用テンプレート」
---「Windowsコンポーネント」
----「リモートデスクトップサービス」
-----「リモートデスクトップセッションホスト」
------「接続」

↓
「リモートデスクトップサービスユーザーに対してリモートデスクトップサービスセッションを１つに制限する」を「無効」にします

これで複数接続が可能になりました😆
機密情報をLambdaで使いたいとき

AWS Systems Manager パラメータストアを使いましょう。

ソースコードに書きたくない、環境変数にも残したくない。そういったときにパラメータストアが役に立ちます。

パラメータストアでは暗号化もサポートしているので、機密情報はこれを使って保存します。

パラメータストア自体の使い方はGUIからできるので省略しますが、Lambda(Python)では次のような感じでサクッと利用することができます。

```
ssm = boto3.client('ssm')
ssm_response = ssm.get_parameters(
  Names = [
    (パラメータストアキー名),
  ],
  WithDecryption=True
)
print(ssm_response['Parameters'][0]['Value'])
```

IAMポリシーはこんな感じです。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:GetParameters"
            ],
            "Resource": [
                "arn:aws:ssm:*:*:parameter/(パラメータストアキー名)"
            ],
            "Effect": "Allow"
        }
    ]
}
```
sympyで「連立方程式(Simultaneous equation)」をやってみた

オリジナル


解は大まかに言って
1.変数の数の方が多いならば、（変数の数） − （方程式の本数）の分だけ変数を自由に定めることができ、解が一つに定まらない。
2.変数の数と方程式の本数が一致するならば、解が存在し、**一つに定まる。**
3.方程式の本数の方が多いならば、制約が過剰なので、解が存在しない。
〈

https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%9E%8B%E6%96%B9%E7%A8%8B%E5%BC%8F%E7%B3%BB



# sympyで

``` fullscript.py
from sympy import *
var("a11 a12 a21 a22 b1 b2")
var("x y")
var("A B C D")
print(solve([x+2*y-5, 2*x+3*y-8]))

A =Matrix(([a11,a12], [a21,a22]))
B =Matrix(([b1],[b2]))
C=A.inv() * B
D=C.subs({a11:1,a12:2, a21:2, a22:3, b1:5, b2:8})
print(C)
print(D)
pprint(C)
pprint(D)
print("x=",D[0],"y=",D[1])
# {x: 1, y: 2}
# Matrix([[-a12*b2/(a11*a22 - a12*a21) + a22*b1/(a11*a22 - a12*a21)], [a11*b2/(a11*a22 - a12*a21) - a21*b1/(a11*a22 - a12*a21)]])
# Matrix([[1], [2]])
# ?        a???b?              a???b?     ?
# ?- ───────────────── + ─────────────────?
# ?  a???a?? - a???a??   a???a?? - a???a???
# ?                                       ?
# ?       a???b?              a???b?      ?
# ? ───────────────── - ───────────────── ?
# ? a???a?? - a???a??   a???a?? - a???a?? ?
# ?1?
# ? ?
# ?2?
# x= 1 y= 2
```
文字化けの箇所は、pprintをテキスト表示しています。
# wolframalphaで

http://www.wolframalpha.com/input/?i=x%2B2*y%3D5,+2*x%2B3*y%3D8

解
x = 1, y = 2
ブラウザのタブに時計を表示

```html:tab-clock.html
<!DOCTYPE html>
<html>
	<head>
		<title>tab clock</title>
	</head>
	<body>
		<script>
			const element = document.getElementsByTagName("title")[0];
			setInterval(function() {
				element.innerHTML = (new Date()).toLocaleString();
			}, 250);
		</script>
	</body>
</html>
```

![tab-clock_ie11.png](https://qiita-image-store.s3.amazonaws.com/0/127130/edc7bcf2-b1e2-a705-a6d9-94cbe3379bba.png)
rmのaliasを調べていたらskelの話になった件について


※コメントでご指摘をいただき調べなおしたところ、最初の記載に誤りがあったので、一部修正しました。

#rmと侠気

侠気（きょうき、おとこぎ）とは、_強きをくじき弱きを助ける心だて（広辞苑）_、だそうだ。

~~最近のシステムでは、`rm`は`rm -i`にaliasがはられている。これは侠気なのかもしれない。~~rmにiオプションのaliasがはられている場合、ほんとうにこのファイルを消してもいいのかという迷いや弱さを助けているのだろう。

ちなみに、設定されているaliasを無視したい時は、（[POSIXの仕様を工夫して](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html)）コマンドの前か途中にバックスラッシュをはさむなどのテクニックが使われる。

#aliasについて

`aliases`(_aliases(5)_)じゃなく`alias`。ここでは`bash`(_bash(1)_)や`tcsh`(_tcsh(1)_)の方向から見ていく。たとえば私の`ll`はこうなっている。`ls -l`と同じということであり、上記の通り`\ll`と入力すればただの`ll`となる。

```
% alias | grep ^ll
ll      ls -l
```

#いつからrmにはiオプションがついているのか？

でもって先日、ゆたかさんのツイートなどをみてふと思ったのが、

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">問い合わせなしにファイルが削除されるのが精神的にしんどいので、rmコマンドはエイリアスで「-i」オプションを付けるようにしているのですが、昔々職場の先輩に「そんなもん付けているのかよ」って言われた覚えがあります。</p>&mdash; ゆたかさん (@yutakakn) <a href="https://twitter.com/yutakakn/status/1018505479037652993?ref_src=twsrc%5Etfw">2018年7月15日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Red Hat系Linuxはrootユーザだと「rm -i」でエイリアスされているそうです。Fedora28では確かにそうなっていました。 <a href="https://t.co/FD4lA74K0B">pic.twitter.com/FD4lA74K0B</a></p>&mdash; ゆたかさん (@yutakakn) <a href="https://twitter.com/yutakakn/status/1018868549958287361?ref_src=twsrc%5Etfw">2018年7月16日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


そういえば自分は手動でaliasはってないのに、`rm`は`rm -i`になってるよねと思ってaliasを見たら設定済みだった。

```
% alias | grep ^rm
rm      rm -i
```

寝ている間に小人さんが設定したというケースは除いて、となると、ユーザ作成時にすでにそうなっていたということなの~~だろう。~~だろうか？

#skelを覗く

「覘く」という使い方は常用ではないらしい。－－それはともかくとして、useradd(8)をみると、（指定すれば）/etc/skel の中身が新規ユーザの$HOMEにコピーされる、とある。Windowsの世界でいうところのデフォルトプロファイルみたいなもの、ともいえるかもしれない。[^1]

それで/etc/skel/ を見てみてみると、たしかに.bashrcとかがある。（環境によっては、/usr/local 以下にskelディレクトリがあるだろう。）その.bashrcとかに、書いてあるのだった。

___(追記)ただし、lsなどのaliasは書いていたが、ズバリrmにiオプションのaliasは無かったように見える。じゃあどこで設定されているのだろうか？___

~~なので、強引にまとめると、ほぼほぼ最近のシステムであれば、`rm` には `-i` オプションがaliasで設定されていて、（初学者は）それを気にしないで入力しているということになる。~~

設定したことが無くても、 `alias` と入力してrmにiオプションがついていることがあって、その時は、初学者が「rmのiオプション」を知らなくても、「rmを入力したら確認が出るのだな」と思うのだろう。


あとUbuntuでは「超最小構成」ってのがあって、－－Ubuntu Minimal Cloud Imagesという－－、まあそもそもIoTというか人間じゃないユーザ向け[^2]のやつなんですけど、このへんまでいくと__スクリーンエディタもないっていう状態__なので、勉強にはおすすめかもしれませんね。


#参考など

- http://inaz2.hatenablog.com/entry/2013/05/16/213211
--シェルのエイリアス展開を無効化するには頭にbackslashをつける（ももいろテクノロジー）,2013/05

この記事でPOSIXのことを思い出しました。ありがとうございます。

- http://gihyo.jp/admin/clip/01/ubuntu-topics/201807/13
--Ubuntu Weekly Topics 2018年7月13日号　Ubuntu Minimal Cloud image，ArtfulのEOL


[^1]: 窓のデフォルトプロファイルを作る方がめんどくさい（手順が煩雑）な気がするんだけど、Windows10くらいからましになったとかどうとか。:smirk:

[^2]: 人間じゃないユーザ＝逸般人ともいえますよね（ぉ
【Docker】Laradock で Laravel の開発環境を構築

Docker で Laravel の開発環境を構築しようとしたときに、 [Laradock](https://github.com/laradock/laradock)  というものを見つけて、とても便利だったので使い方の復習も兼ねて共有。

※ Docker はインストール済み想定

参考：[PHPフレームワーク「Laradock」で、手軽にLaravel+Dockerな開発環境を構築する](https://liginc.co.jp/364089)

## 構築する環境

1. PHP
1. MySQL
1. apache

各バージョンは簡単に変更できるので後ほど。

## 作業ディレクトリの作成

```bash
$ mkdir my_project
$ cd my_project
$ mkdir src
```

my_project ディレクトリの中に Laradock をクローンする。
src ディレクトリに、コンテナにインストールする Laravel をマウントする。

## Laradock をクローン

```bash
$ git clone https://github.com/laradock/laradock.git
```

## 設定ファイルを編集

`env-example` をコピーして `.env` を作成する。

```bash
$ cp env-example .env
```

.env ファイルを編集する。

```.env
// 変更前
APP_CODE_PATH_HOST=../

// 変更後
APP_CODE_PATH_HOST=../src/
```

## PHPのバージョンを変更する

.env の `PHP_VERSION` を編集する。
7系と 5.6 が選べるみたいですね。

```.env
# Select a PHP version of the Workspace and PHP-FPM containers (Does not apply to HHVM). Accepted values: 7.2 - 7.1 - 7.0 - 5.6
PHP_VERSION=7.2
```

## MySQL を変更する

.env を編集

```.env
// 変更前
MYSQL_VERSION=latest

// 変更後
MYSQL_VERSION=5.7
```

※ ちなみに MySQL 8系から認証が変わったらしく、 Laradock の mysql ディレクトリの設定を変更しないと、 PHP からコネクトするときにエラーになります。

参考：[stackoverflow](https://stackoverflow.com/questions/49194719/authentication-plugin-caching-sha2-password-cannot-be-loaded)

めんどくさい人は5.7で作業しておいてください。

私は変更前に `docker-compose up` 8系で作業してしまって、５.7に変更したのに反映されず困りました。
`~/.laradock/data/mysql` にデータが残っていたみたいです。
.env を `5.7` に編集してから以下の作業を行いましょう。

```bash
// 止める
$ docker-compose stop

// フォルダを削除
$ rm -r ~/.laradock/data/mysql

// 起動
$ docker-compose up -d mysql
```

## Docker コンテナの起動

`nginx` を使いたい場合は `apache2` を置き換えるだけでうまくいくはずです。

```bash
$ docker-compose up -d apache2 mysql
```

`http://localhost` にアクセスすると、`404` か ディレクトリ一覧が表示されます。
nginx やったら 404 かな？

## Workspace コンテナを起動して接続

起動します。

```bash
$ docker-compose up -d workspace
```

接続します。

```bash
$ docker-compose exec workspace bash
```

接続して Laravel とかインストールしてみましょう！

## Laravel のインストール

composer はすでにインストールされています。
パスも通っています。

```bash
$ composer create-project --prefer-dist laravel/laravel ./
```

インストール終わったら、 http://localhost/public にアクセスしてみましょう。
Laravel の初期画面が表示されていますね？

コンテナから exit して、最初に作成した `src` ディレクトリに Laravel プロジェクトがマウントされているはずです。

## MySQL の設定

`.env` ファイルを編集

```.env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
```

変えたい場合は `Laradock` ディレクトリの `.env` ファイルの `mysql` の設定が書かれた項目をいじってください。

## PhpMyAdmin を使う

```bash
$ docker-compose up -d phpmyadmin
```

以上です。
`http://localhost:8080` へアクセス！！！

## DBを確認する

以下のコマンドでさくっと作ってもらいましょう。

```bash
$ php artisan migrate
```

MySQL を確認するとテーブルが作成されているはずです。

## 最後に

今回は触れてませんが、 redis を使う場合なども `docker-compose up` で redis を追加して、 Laravel の .env に設定を書いてあげるだけです。

便利ですね！！！
【String型 vs StringBuilder】文字列結合における処理速度の違い

#はじめに
Javaで文字列結合をする際、String型で`+=`で繋いでいくか、StringBuilderの`append()`でつなぐか、２通りの手段があります。


結果はどちらも同じですが、処理速度に差が出ます。

#Stringでやったとき
例えばこんなコード

```java
String stringResult = null;
    // Stringオブジェクトによる文字列結合
    for (int i = 0; i < 10; i++) {
      String str = Integer.toString(i);
      stringResult += str;
    }
```
String型とはStringオブジェクトのことなので、String型の変数が宣言される＝Stringオブジェクトが生まれる、ということになります。


なので、文字列結合をしている`stringResult += str;`のタイミングでStringオブジェクトを生成しています。


つまり、for文のループの回数分だけStringオブジェクトが生まれるわけです。


#StringBuilderでやったとき
例えばこんなコード

```java
StringBuilder sb = new StringBuilder();
    // StringBuilderによる文字列結合
    for (int j = 0; j < 10; j++) {
      sb.append(Integer.toString(j));
    }
```

結果はStringの例と同じです。


しかし、`append()`はStringオブジェクトを作りません。末尾に追加していくだけです。


Stringオブジェクトを生成しない分、処理が速い。

#どれくらい速度が違う？
下記のようなプログラムで、StringとStringBuilderとの処理時間の違いを測ってみました。

```java
public class StringBuilderSample{
  public static void main(String[] args) {
    final int MAX_COUNT = 100;
    System.out.println("結合回数：" + MAX_COUNT + "回のとき");
    /********************* String型の場合 *********************/
    String stringResult = null;

    // Stringでの処理にかかった時間
    long sTime;

    // 開始時間
    long startTime = System.nanoTime();

    // String型による文字列結合
    for (int i = 0; i < MAX_COUNT; i++) {
      String str = Integer.toString(i);
      stringResult += str;
    }

    // 終了時間
    long endTime = System.nanoTime();

    // 処理にかかった時間を算出
    sTime = endTime - startTime;

    System.out.println("Stringでの処理時間：" + sTime + "ナノ秒");

    /********************* StringBuilderの場合 *********************/
    StringBuilder sb = new StringBuilder();

    // StringBuilderでの処理にかかった時間
    long sbTime;

    // 開始時間
    startTime = System.nanoTime();

    // StringBuilderによる文字列結合
    for (int j = 0; j < MAX_COUNT; j++) {
      sb.append(Integer.toString(j));
    }

    // 終了時間
    endTime = System.nanoTime();

    // 処理にかかった時間を算出
    sbTime = endTime - startTime;

    System.out.println("StringBuilderでの処理時間：" + sbTime + "ナノ秒");
    System.out.println("StringBuilderの方が " + (sTime - sbTime) + " ナノ秒速い");
  }
}
```

文字列結合を`MAX_COUNT`の回数だけ行ったときの処理速度を表示するプログラムです。

以下、`MAX_COUNT`の値を100, 1000, 1万, 10万と増やしていきながら処理時間の違いを見ていきます。

ちなみに、ナノ秒とは10 ^ (-9) 秒（＝0.000000001秒）のことです。


##100回実行したとき
![スクリーンショット 2018-07-19 23.11.48.png](https://qiita-image-store.s3.amazonaws.com/0/159675/bbbec012-acb9-1b4c-f65a-f834e4ee68e7.png)


##1000回実行したとき
![スクリーンショット 2018-07-19 23.12.23.png](https://qiita-image-store.s3.amazonaws.com/0/159675/e804c83c-50ad-3e7b-4bd5-e5cc47a4dfbc.png)

##1万回実行したとき
![スクリーンショット 2018-07-19 23.13.53.png](https://qiita-image-store.s3.amazonaws.com/0/159675/45f1be05-6b27-102e-02d8-b1fbd74182d2.png)
約0.57秒速い

##10万回実行したとき
![スクリーンショット 2018-07-19 23.14.49.png](https://qiita-image-store.s3.amazonaws.com/0/159675/dcca2fa2-06ec-1b81-a5bf-40a2bda0802f.png)

約27秒速い

#StringBuilderのほうが速かった！
1000回ぐらいまでならせいぜいマイクロ秒（10 ^(-6)）単位での違いなので、そんなに気にはならない。


1万回超えたあたりから処理時間の差が気になるレベルになってくる。


まあ何回実行するにしてもStringBuilderの方が速いことは確かなので、特別な理由がない限り文字列結合はStringBuilderでやったほうがいいですね。

2018 07/21 追記：続編書きました → [【java】appendの中で"+"は使わない！](https://qiita.com/tor_2085/items/754180f91a8c1554287d)