OmniAICreator/Qiita-1.07M huggingface dataset:
rspecのletとlet!の違いについて学んだことをメモ

## はじめに
今年ももう少しですね。
個人的にQiitaの下書きが上限いっぱい溜まってしまったので
少しづつアウトプットを心がけていこうと身が引き締まる思いです。
1日いちQiita(1日Qiitaを1記事アウトプットしてみようという試み) を今日から個人的に勝手にとりあえず今年いっぱい始めてみようかなと思います。
インプットは楽しいのですが、アウトプットはついつい後回しにしがちなのですが
少しづつ成長していきたいです。

## この記事で書くこと :pen_fountain: 
- rspecの `let` と `let!` の違いを次に同じ失敗をしないように残すという取り組み。

## 「そうだ、テスト書こう」 :cat: :musical_note: 
と思い至って早xx日。日々未来の自分やチームメイトのため、ひいてはエンドユーザのため（QA的な）にせっせとテストを書く毎日を送っています。楽しいです。


## 記事を書くにあたって1時間くらいハマってしまったテストケース(一部わかりやすいように変更してあります。)

```ruby
describe 'update callback' do
   context 'when user name will be changed,' do
      let(:user) { create(:user, name: "隣の アルパカさん") }
      let(:offer) { create(:offer, status: 'offered', user_id: user.id, user_name: user.name) }
      it 'update user_name of processing offers.' do
        # 古い情報を変数へ入れる
        old_user_name = user.name
        user.update(last_name: "隣の", first_name: "ねこさん") # 処理１
        offer.reload
        expect(offer.user_name).to eq "隣の ねこさん" # 処理２
      end
    end
end

```

テストしている処理としては、
（処理１）userオブジェクトの名前を変更（ `last_name` と `first_name` を結合したものが `name`  になる）
  - 処理１が実行されると `after_update callback` を利用して、そのユーザに紐付いた進行中の申込みを更新。
（処理２）申込みのユーザ名が、変更されたユーザ名と一致しているかどうかを確認。

なのですが、

```bash
Failure/Error: expect(offer.user_name).to eq "隣の ねこさん"

       expected: "隣の ねこさん"
            got: "隣の アルパカさん"
# な、なにがおきているのか、、、
```

## letとlet!の違い

今回テストケースが失敗したのはなぜだったのか？
僕たちは「こう動いてほしい。こういう意味で書いている」という気持ちでコードを書きますが、
その気持と、書いてある内容は一致しているとは限りません。
「なぜ失敗している？」「なぜこう動かない？」というのはすべて「そうなるように書いている」からそうなるのです。だから今回も僕の書き方に問題があったのです。
そこで学んだ違いが以下のものです。

`let`　は、その定義された値がテストケースの中で使用されたときに初めて定義される。
`let!` は、blockが定義された時に定義される。

この違いを知らずに自分は大分時間を使ってしまいました。
今回は 

```bash
let!(:user) { create(:user, name: "隣の アルパカさん") }
``` 
こうしないといけなかったんですね。
この学びを糧にして、よりよいソフトウェアを作っていこうと思います。

## 参考
迷ったときに立ち返りたいBetter Specs
http://www.betterspecs.org/#let
ずんだのハロウィン問題 bash編

もとねた: [「ずんだのハロウィン問題 Ruby編」](https://qiita.com/tbpgr/items/1f2ed0e14e5d94775963)

1行野郎は男の浪漫--ということで、保守性や可読性を無視して、上記記事の条件を満たすワンライナーを書いてみました。

```bash
echo "trick treat sushi poyayou tamakatsu" | sed 's/\s/\n/g' | shuf -n 1  | awk '{print $0; print match($0, /^tr/) ? "happy halloween" : "sleepy" }'
```

さすがに読みずらすぎるので、わかりやすく整形し、適宜コメントを加えたものが以下になります。

```bash
echo "trick treat sushi poyayou tamakatsu" |
# 空白区切りを改行区切りに変更する。
sed 's/\s/\n/g'                            |
# 入力をシャッフルし、最初の1行を取り出す。
shuf -n 1                                  |
# 入力の内容にかかわらず、その内容をそのまま出力した後
# 入力がtrickまたはtreatの場合は、happy halloweenを出力する。
awk '{
  print $0;
  print match($0, /^tr/) ? "happy halloween" : "sleepy"                                  
}'
```

もうちょっと工夫できそうですね(´・ω・｀) とくに最後の`awk`は無理やり感が出ている。ここもパイプでスマートに書くことができれば、シェル芸人の仲間入りができる--はず。

***

おまけとして、以下のようなスクリプトを作りました。

```bash
seq 1000 | while read x; do
  echo "trick treat sushi poyayou tamakatsu" | 
    sed 's/\s/\n/g'                          | 
    shuf -n 1                                | 
    awk '{print $0; print match($0, /^tr/) ? "happy halloween" : "sleepy" }'
done > zunda.log
```

これは問題の1行野郎を1000回実行し、その出力結果を`zunda.log`に記録するというものです。実行後に生成される`zunda.log`の内容は膨大なものになるため、とりあえず前の30行だけ見てみましょう(`head -n 30 zunda.log`)。

```
poyayou
sleepy
poyayou
sleepy
tamakatsu
sleepy
sushi
sleepy
tamakatsu
sleepy
trick
happy halloween
treat
happy halloween
poyayou
sleepy
poyayou
sleepy
poyayou
sleepy
sushi
sleepy
sushi
sleepy
tamakatsu
sleepy
treat
happy halloween
treat
happy halloween
```

trick, treat, sushi, poyayou, tamakatsuがランダムに生成され、trickまたはtreatの場合は続いてhappy halloweenが、それ以外の場合はsleepyが出力されている状態が確認できますね。ちなみにそれぞれの単語の出現回数は次のようなコマンドで確認することができます。

```bash
cat zunda.log | sort | uniq -c | sort -n
```

この実行結果は以下の通りで、それぞれの単語がある程度均等に出力されていることが分かります。また$165+179+196+223+237=1000$となり、1000回ちょうど実行されていることも確認可能です。

```bash
    165 trick
    179 sushi
    196 treat
    223 poyayou
    237 tamakatsu
    361 happy halloween
    639 sleepy
```
CharとVarcharについて復習

アプリの開発の時はMySQLを使っているのだが、文字列型の適切な選択や、判断方法についてはあやふやだったので、まずはcharとvarcharについて復習してみた

## MySQLの文字列型の種類
MySQLには大きく分けて、以下の8つの型が存在する。

- CHAR
- VARCHAR
- BINARY
- VARBINARY
- BLOB
- TEXT
- ENUM
- SET

#### CHAR型(M)
- 固定長文字列
- Mで文字数を指定
- 0から255文字まで可能
- 取得する時に末尾についた空白は削除された上で取得される

**[補足] 固定長文字列**
> 指定した文字数以下の文字を格納した場合には文字列の末尾に空白を必要なだけ付け加えて指定の長さの文字列として格納する


**consoleで確認(Rails)**
childテーブルにはchar型のcharカラムが存在するとする

```
irb(main):005:0> a.char = "a"*254
irb(main):006:0> a.save! #=> 成功

irb(main):005:0> a.char = "a"*255
irb(main):006:0> a.save! #=> 失敗

irb(main):007:0> a.char = "あ"*254
irb(main):006:0> a.save! #=> 成功

irb(main):009:0> a.char = "あ"*255
irb(main):006:0> a.save! #=> 失敗
```
文字数に依存していることがわかる

#### VARCHAR型(M)
- 可変長文字列
- Mはバイト数を指定する
- 0~65535バイト

**[補足] 可変長文字列**
> 末尾に空白を付けるようなことはしません。また現行のバージョンでは末尾に空白がある文字列であっても空白が付いたまま格納される


consoleで確認(Rails)
aモデルにはvarchar型のvarcharカラムが存在するとする
varchar(21800) DEFAULT NULLで設定した

```
irb(main):024:0> child.varchar = 'b'*21800
irb(main):025:0> child.varchar.bytesize #=> 21800
irb(main):027:0> child.save! #=> 成功


irb(main):024:0> child.varchar = 'b'*21801
irb(main):028:0> child.varchar.bytesize #=> 21801
irb(main):027:0> child.save! #=> 失敗

irb(main):024:0> child.varchar = 'あ'*21800
irb(main):030:0> child.varchar.bytesize #=> 65400
irb(main):027:0> child.save! #=> 成功


irb(main):024:0> child.varchar = 'b'*21801
irb(main):032:0> child.varchar.bytesize #=> 65403
irb(main):027:0> child.save! #=> 失敗
```
bytesizeメソッドでbyteサイズが測れる

### VARCHARは65532までが最大有効長なのに、なぜ今回は21800にしているか
`UTF-8は最大3バイト`食うので、utf-8を使っている場合は、**入力文字が全て3バイトだった時の文字数しか使えない！！**
なのでMAXでもVARCHARでは、 `65532➗3　= 21845文字`になります。

#### VARCHARで、バイト数を指定する時の決め方

tokensテーブルにtokenをvarcharで保存するとする時、Railsではマイグレーションを下記のように記述する

```db/migrate/20181029165624_create_tokens.rb
class CreateTokens < ActiveRecord::Migration[5.2]
  def change
    create_table :tokens do |t|
      t.string :token, limit:1500

      t.timestamps
    end
  end
end
```

今回は、tokenのバイト数の指定を1500としているが、バイト数の決め方の判断として
サンプルtokenのバイト数を計測し、保存するであろうtokenが必ず治るバイト数を指定するのが望ましいと考えられます。

```console
$ sample_token = "hoge..........."
$ sample_token.bytesize #=> 15

# sample_tokenが暗号化前の時は、
$ len   = ActiveSupport::MessageEncryptor.key_len
$ salt  = SecureRandom.random_bytes(len)
$ key   = ActiveSupport::KeyGenerator.new('password').generate_key(salt, len)
$ crypt = ActiveSupport::MessageEncryptor.new(key)   
$ crypt.encrypt_and_sign(sample_token).bytesize # => 138になる！
```

暗号化の方法に関してはこちらを参照にしました
https://api.rubyonrails.org/v5.2.1/classes/ActiveSupport/MessageEncryptor.html
RHEL、CentOSのTIPS

# RHEL7.4
## ネットワーク
### デフォルト無効を有効に変更
ネットワーク設定を開いて、右下の歯車ぼたんをクリック。
左側のリストで「Identify」を選択して、「自動接続する」にチェックを付ける。

## その他
### 画面ロックを無効化
[システムツール]-[設定]-[privacy]設定画面を開いて、「画面ロック」の設定を"オン"から"オフ"に変更する。
## スクリーンセーバーを無効化
[システムツール]-[設定]-[Power]設定画面を開いて、「ブランクスクリーン」の設定を"5分"から"しない"に変更する

# Cent OS 7.5.1804

## インストール
間違えてGUIパッケージをインストールするのを忘れた場合のメモ
### ネットワークに繋がらない(NICを認識していない)

```shell
nmtui
<GUIで設定>
systemctl restart NetworkManager
```
nmtuiコマンドでコンソール上でGUIで設定が可能。

1.OSインストール直後のネットワークに繋がらない状態
![image.png](https://qiita-image-store.s3.amazonaws.com/0/187121/0e830f2a-8a01-4b8f-b780-d3a06bfd0929.png)

2.nmtuiを起動
![image.png](https://qiita-image-store.s3.amazonaws.com/0/187121/8857d784-a41a-8491-2bc2-77d505e30379.png)

3.「Edit a connection」を選択し、認識しているNICを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/187121/6e794437-730a-0991-d10f-03aa34553359.png)

4.「Automatically connect」にチェックが外れているので、チェックを付けて「OK」で閉じる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/187121/8f444db9-3a37-d666-9837-cb475e321d68.png)

### GUIパッケージをインストール

```shell
yum groupinstall "GNOME Desktop"
startx
```
何度か確認が出るので、「Y」で進めていく。

### 日本語化
![image.png](https://qiita-image-store.s3.amazonaws.com/0/187121/707d76a3-36ad-1f7e-7adc-7440fe456264.png)

localeの設定とグラフィカルログインの設定をする

```shell
localectl set-locale LANG=ja_JP.UTF-8
systemctl set-default graphical.target 
```
git add しようとしたら全然できなくて困った話

## git addをしようとした時に事件は起きた

新しくリポジトリを作ったので
・new repositoryの作成
・sshキーを作り登録
とか諸々を行なった上で

```
rails new hoge
```
してRails　プロジェクトを作成



```
git add .
```
としたところ

```
warning: unable to access '/Users/myname/.config/git/ignore': Permission denied
warning: unable to access '/Users/myname/.config/git/attributes': Permission denied
```
と権限がないと怒られてしまった。

[こちら](https://stackoverflow.com/questions/41829366/git-unable-to-access-home-old-user-config-git-ignore-permission-denied "こちら")を参考に~/.bashrc fileを編集したところ

```
warning: unable to access '/Users/myname/.config/git/attributes': Permission denied
```
のみのエラーになった。

このエラーがなかなか解決しなかったのですが、色々と探してみたところ

[こちら](https://askubuntu.com/questions/852265/should-i-change-config-folder-ownership-that-is-in-my-own-home-directory-why-i?rq=1 "こちら")のなかにある

```
sudo -u root -H env
```
を試したところ、エラーが消えました。

無事にadd commit pushまでできました。

うーん、なんだったんだろうか。権限問題。。
Ultra96立ち上げ時に困ったこと


<追記事項>
18.11.02追記
再現実験で完全な再現性がなかったため、`困ったこと２`の解決、Twitterの箇所を取り下げました。
本当に超苦労させられるボードです。。。orz

##はじめに
大学研究室時代からこよなくFPGAを愛している（生業にしてます)、ひこすたと申します。
本稿がQiita初投稿記事になります。
自分がUltra96立ち上げ時に困ったことを記録しておきます。
今後、Ultra96の立ち上げでお困りの、どなたかのお力になれば幸いです。

##立ち上げ時 開発環境（18.11.01追記)
Xilinx Vivado(SDK) 2018.2 @ Windows10
Ultra96 Board File v1.2 (ひでみのアイデア帳さんを参考にさせて頂きました。https://sweetcafe.jp/?*20180704-214319)


##困ったこと1：Avnet製 UART/JTAG-USB PODボード使用時、UARTがなぜか2つ見え、どちらが使えるのかわからなかった

###現象
Ultra96 Tutorial2 Hello Worldで、指示通りにやっているとUARTが一つしか見えないはずなのに、UARTが二つ見える。（例：windows10 デバイスマネージャー上でCOM2/COM3)

###解決
上記例ですと、COM3、要するに二つ目のCOMが正解です。

###原因
なぜ二つ見えるのかはわかっていません。。。

###Twitterにも挙げておきました。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ultra96さん、PodボードでやっとUART出力が見れた。これでフルにデバッグしていける。二つ目のポートが正解だった。tutorialと差異ありでした。SDKプロジェクトの作り方で成否が変わりそう。vivadoからlaunchするとダメなのか。もう少し見てみる。ここらへんはやっぱxilinxらしいかも。</p>&mdash; ひこすた (@hikostar) <a href="https://twitter.com/hikostar/status/1055878196674015232?ref_src=twsrc%5Etfw">2018年10月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


##困ったこと2：Tutorial2のHello Worldでpsu_init 99%でハングアップする

###現象
Ultra96にJTAGをつないでSDKからRunさせると、psu_init 99%でハングアップし、端末にHello Worldが表示されない。

###解決
~~Tutorial2通りにやれば回避できましたorz~~
~~いつもの癖で、VivadoのLaunch SDKで起動していましたが、文書通り、SDKを単体で起動してWorkspaceを指定、プロジェクトを作成し、Runさせることで動作させることができました。~~
18.11.02追記
**再現実験を試みたところ、完全な再現性がないため、解決の箇所を取り下げておきます。**

###原因
なぜこうなるのかはわかっていません。
いつも通りのXさんのツールバグ？

###Twitterにも挙げておきました。
18.11.02追記
**再現実験を試みたところ、完全な再現性がないため、Twitterの箇所を取り下げておきます。**


##最後に
再現性はまだ確認していませんが、情報は以上です。
ご助力できましたら幸いです。

それでは、良いUltra96ライフを！
【Rails】中間テーブルの組み方

##中間テーブルを実装したい

以前の記事でお送りした`user`と`school`のテーブルについて、
実際にコードで実装しようと思います。

`user`

|id|user|
|---|---|
|1|a|
|2|b|
|3|c|
|4|d|
|〜|〜|

`school`

|id|school|
|---|---|
|1|A小学校|
|2|B中学校|
|3|C高校|
|4|D大学|
|5|E大学院|
|6|Foreign_University|
|〜|〜|


`user_school`　←中間テーブル

|id|user|school|
|---|---|---|
|1|a|A小学校|
|2|a|B中学校|
|3|a|C高校|
|4|a|D大学|
|5|b|A小学校|
|6|b|B中学校|
|〜|〜|

## モデルのアソシエーション
テーブルとテーブルに関係性を持たせるには、
モデルに記述を追加して、アソシエーションを構築します。


```user.rb
class User < ApplicationRecord
 has_many :user_schools
 has_many :schools, through: :user_schools
end
```

```school.rb
class School < ApplicationRecord
 has_many :user_schools
 has_many :users, through: :user_schools
end
```

```user_schools.rb
class UserSchool < ApplicationRecord
 belongs_to :user
 belongs_to :school
end
```

親テーブルに
`has_many :テーブル名（複数形）`

子テーブルに
`belongs_to :テーブル名（単数形）`

のように記述します。


このとき、`user`テーブルと`school`テーブルは相互に複数のデータに関連を持ちます。
＜aさんは、A小学校も、B小学校も卒業＞
aさん→`user`テーブルのデータが、A小学校、B中学校、`school`テーブルに対して複数関連を持っている

＜B中学校は、aさんも、bさんも卒業＞
B中学校→`school`テーブルのデータが、aさん、bさん、`user`テーブルに対して複数関連を持っている


## 中間テーブルは子テーブル
`user_schools`のテーブルに入ってるデータは、
そのひとつのデータから見ると、`user`テーブル `school`テーブルともにひとつしかありません。

|id|user|school|
|---|---|---|
|1|a|A小学校|
＜`a` も `A小学校`もそれぞれ`user`テーブル、`school`テーブルにはひとつのみ＞

そのため、中間テーブルのモデルには`belongs_to`の記述でアソシエーションを記述する点に注意が必要です。


今日はこのあたりで失礼します。
Unity Teamsを使ってみる

## Unity Teamsとは
複数人でUnityプロジェクトを開発するためのツール。(Unity版gitのようなもの)
チームでのプロジェクト共有・バージョン管理のUnity Collaborateと、クラウドリソースを使ってプロジェクトをビルドしてくれるUnity Cloud Buildが統合されたもの。

- 3人まで無料で使えるBasicプラン
- 有料で大人数で使えるAdvancedプラン

があるが今回はBasicプランを使ってみる。

## Unity Teamsに登録する
[こちら](https://unity3d.com/jp/get-teams)でプランを選んで登録できる。

登録が完了したら共有するUnityプロジェクトを開く。

1. 右上の雲のマークをクリックする
2. SERVICESという画面が出てくるので、(言われるがまま)ProjectIDを発行する  
発行済みの場合は勝手に出てくると思う。
<img width="1440" alt="こういうイメージ.png" src="https://qiita-image-store.s3.amazonaws.com/0/250619/5cb8f3ae-e92c-8b26-cdb4-1f7efde609d2.png">

入力が完了するとUnity Teamsのサービス一覧が表示される。
<img width="362" alt="UnityTeamsサービス一覧.png" src="https://qiita-image-store.s3.amazonaws.com/0/250619/bc29b910-fa88-e0aa-2e0d-c4b6b3971420.png">

利用したいサービスを選択してアクティベートする感じ。

## Collaborateを使う
CollaborateをONにしたら以下のような項目が表示される。
<img width="375" alt="Collaborate.png" src="https://qiita-image-store.s3.amazonaws.com/0/250619/ec6ceafb-880c-ebc4-d0b1-23e488b6bbfe.png">

### 変更を登録する
Publishを選択。このPublishがgitでのコミットとプッシュに相当する。
Publishメッセージもある。
### 変更を確認する
Historyを選択すると変更ログが確認できる。
<img width="542" alt="スクリーンショット 2018-10-31 23.20.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/250619/1e9f572a-454f-aa12-cc88-7bfe5f758b9a.png">
### メンバーを追加する
ツールバー上のコラボと書かれたところを押下するとメンバー追加のボタンが表示される。
押すとUnity Dashboardに飛ばされてメールアドレスからメンバーを追加できる。
当然、直接Unity Dashboardに飛んで、Setting>Usersを選択してもできる。
### Slackと連携する
ベータ版だが、Slackと連携もできる。
プロジェクトのUnity Dashboard から
Setting>Integrationsから

## 感想
- Collaborateは便利だけど、やはりgitと比べるとブランチ等の機能が弱いと思う。
- 他の機能も試したら追加していきたい。
- 思ったより簡単に出来たので記事にする必要がなかった気がする。
勾配降下法の練習の為によくある頭の体操を解いてみる

よくSNSでシェアされるIQを図る系の問題

```
1 +  5 = 18
2 +  7 = 27
3 +  9 = 36
5 + 10 = 45

4 + 20 = ??
```
という頭の体操（？）をjsで勾配降下法で解いてみる。

```.js
const inputLayer = [
  [1, 5],
  [2, 7],
  [3, 9],
  [5, 10],
];

const labels = [
  18,
  27,
  36,
  45,
];
```
教師データと正解ラベル

```.js
let bias = [0, 0, 0, 0,];
const output = (w, x) => w[0] * (x[0] + x[1]) + w[1] * x[0] + w[2] * x[1] + w[3];
```
適当に作った評価式

```.js
function targetFunction(bias) {
  let error = 0;
  for (let i = 0;i < inputLayer.length;i++) {
    let input = inputLayer[i];
    let b = output(bias, input);
    error += Math.pow(labels[i] - b, 2);
  }
  return error;
}
```

errorが0に近ずくように学習していく

```.js
const n0 = bias.length;
for (let i = 0;i < 100;i++) {
  for (let j = 0;j < n0;j++) {
    let old = bias[j];
    let before = targetFunction(bias);
    bias[j] = old + 0.001;
    let after = targetFunction(bias);
    bias[j] = old + (before - after) * 1;
  }
  if (targetFunction(bias) < 0.0001) {
    break;
  }
  console.log(i, targetFunction(bias));
}
```

実行した結果

```
99 0.0004953073198085481
[ 2.9489024031645927,
  0.03969341058294724,
  0.054454721873473506,
  0.0034584048363291682 ]
4 + 20 =  72.02498416058782
```
100回ぐらい回せば収束した
どうも二つの数字を足したものに3辺りを掛けたものが答えらしい。
本当の正解は知りません。

[ソースコード](https://gist.github.com/horitaku1124/c5fa8d13709ec80482ad8ae270cb9540)
Swiftでバイナリデータをstructで扱う

※Swift4です

# Swiftでバイナリデータを扱う

SwiftではバイナリデータをData型で扱うことができます。

```swift
let data = Data(...)

data[0] // -> UInt8
data[1] // -> UInt8
...
```

`Int8`は1バイトのデータのことであるため、data配列をいい感じに操作すればバイナリデータを扱うことができそうです。

# structで扱いたい

たとえば、バイナリデータが `|type 2byte|data 4byte|type 2byte|data 4byte|...`というデータの並びになっているとき、

```swift
struct SingleData {
  let type: UInt16
  let data: UInt32
}
```

上↑のようなstructを用意して、読み込んだ後に配列に変換してから操作すると楽そうです。

```swift
var isEnd = false
var counter = 0;
var datas: [SingleData] = []
while isEnd {
  let type: UInt16 = 
    UInt16(data[counter * 0]) << 8 + 
    UInt16(data[counter * 1])
  let data: UInt32 = 
    UInt32(data[counter * 2]) << 8 * 3 +
    UInt32(data[counter * 3]) << 8 * 2 +
    UInt32(data[counter * 4]) << 8 * 1 +
    UInt32(data[counter * 5]) << 8 * 0

  datas.append(SingleData(type: type, data: data))
}

... // 以下、datasを好きに使う
```

...けっこう大変ですね。

C言語だと、「共用体」と呼ばれる複数の型として操作できる型を使うことでバイナリデータをわりと簡単にstructとして扱うことができましたが、Swiftではどうなのでしょうか。

# Swiftでバイナリデータをstructとして扱う

答えは、「`withUnsafeBytes`を使う。」です。これによってそれなりに簡単にstructに変換することができるようになります。

```swift
// 値を return すると withUnsafeBytes の戻り値となる
let results = data.withUnsafeBytes({(ptr: UnsafePointer<SingleData>) -> [SingleData] in
  let count = data.count / MemoryLayout<SingleData>.size // データの個数を計算
  var tmp = ptr // ptr を var にしたい
  var results: [SingleData] = []
  for i in 0..<count {
    // ptr.pointee で中身にアクセスできる。 *ptr みたいなもの？
    results.append(ptr.pointee)
    // ポインタを隣に移動する。 ptr++ みたいなもの？
    ptr.successor()
  }
})

... // results を好きに操作する
```

## 注意

structのプロパティにはlittle endianでアクセスします。
したがって、読み込むデータ(2byte以上)によってはbig endianでアクセスする必要があります。

|type|data|
|----|----|
|`0x0001`|`0x12345678`|
|`0x0002`|`0x12345678`|
|`0x0003`|`0x12345678`|

上↑のようなデータだったとき、`results[0].type == 256(0x0100)`となってしまいます。
もし、データがbig endianで格納されているのであれば、`bigEndian`プロパティを使ってアクセスしましょう。

こうです。

```swift
print(results[0].type.bigEndian)
```

JPEGを読み込むプログラムを書こうと思ったのですが、big endianでアクセスするのがめっちゃ面倒だったので、諦めました。

以上です。よろしくお願いいたします。
cronでdateコマンドうまくいかない？

#想定読者
- まだまだshellとかcronとか書く経験があまりないかた
- dateコマンドがうまくいかねーーーーと発狂しそうなかた(一番下の章だけお読みください)

# dateコマンド

バックアップファイル作成時なんかに使用するdateコマンド(今回はLinuxのみ対象にしています。動作確認したのはCentOS系のみ)

```ruby:コマンド
# date +%Y%m%d
20181031
```

よくやりますよね。
# cp とdateコマンドの合わせ技
個人的にかっこいいと思ってる小技

```ruby:コマンド
# cp messages messages-`date +%Y%m%d`

# ls -la | grep messages
-rw-------.  1 root     root     574762 Oct 31 10:01 messages
-rw-------.  1 root     root     574762 Oct 31 10:04 messages-20181031 <-cpで作成されたファイル
```
ポイントは﻿﻿dateコマンド前後の \`  \`です。
\`  \`ないと悲しいことになります。


# 本題のcronでの使用時
まずコマンドでcrontab -e　を叩きます。
日時指定部分は今回は一切関係ないので省きます

```ruby:cron
cp /var/log/messages var/log/messages-`date "+\%Y\%m\%d"`
```

伝わりづらいのですが、`dateの前後`と`%`の前を見てください。
・ \` と"を使用
・ %の前に`\ `を使用
この２つくらいの気遣いがないとうまくいかないです。
dockerコンテナでPHPからのメール送信とhttpsに対応する

Docker を使ってローカル環境をサクッと手元に用意しようとして、
不便（？）だった箇所をどうにかしようと色々試行錯誤したメモです。

# 環境構成

コンテナはDocker Hubの公式リポジトリから持ってきたPHPとMySQLを使い、
こんな構成にしてみました。

- Debian 9.5
- PHP 7.2.11
- Apache 2.4
- MySQL 5.7.24

## 対応したいことがいくつか

公式リポジトリから持ってきたままだと、いくつか不便なところがあったのですが、
今回対応したいのはこれら2つです。

- PHPからメールが送れない
- httpsに対応したい（自己署名証明書で良い）


# PHPからメール送信

PHP の mail 関数でメールを送ろうとしたら、エラーになってどこにも届かず。。
まぁそりゃそうですよねー。
仕方ないのでSMTPサーバーを立てようかと思いましたが、[MailHog](https://github.com/mailhog/MailHog) が便利そうだったので導入してみました。

## 導入

こちらの記事を参考にさせてもらいました。
 [MailHogを利用してメール送信テスト環境をdockerコンテナ上に作る](https://qiita.com/kobatei/items/1b8b0ca5e8737235dccd)
こちらに書いてあるとおり、`docker-compose.yml` にコンテナを追加して、build し直すだけで完了します。
簡単ですね。

```yml:docker-compose.yml
mailhog:
    image: mailhog/mailhog
    ports:
      - "8025:8025"
      - "1025:1025"
```

しかし、このままでは SMTPサーバーの設定をしてあげないと送信できません。
単純に mail 関数で送りたかったので、もうちょっと調べてみると、sendmail を置き換えるものとして mhsendmail というものが用意されていました。
こちらはビルドされたバイナリがあるので、落とせばそのまま使えそうです。

`Dockerfile` に下記を追記して、build し直します。

```dockerfile:Dockerfile
RUN curl -sSLO https://github.com/mailhog/mhsendmail/releases/download/v0.2.0/mhsendmail_linux_amd64 \
    && chmod +x mhsendmail_linux_amd64 \
    && mv mhsendmail_linux_amd64 /usr/local/bin/mhsendmail \
    && echo 'sendmail_path = "/usr/local/bin/mhsendmail --smtp-addr=mailhog:1025"' > /usr/local/etc/php/conf.d/sendmail.ini
```

オプションの `--smtp-addr=` でSMTPサーバーとポートを指定してます。
`mailhog` は `docker-compose.yml` で設定しているサービス名です。

では、mail 関数から送ってみます。

```php
mail('test@example.com', 'テストだよ', '届いてるかな？', 'From: from@example.com');
```

ブラウザで `http://localhost:8025/` にアクセスして確認すると、無事に届いていました。
バッチリです。

![MailHog.png](https://qiita-image-store.s3.amazonaws.com/0/287186/06c7980b-57c6-56ca-d8c4-88759e71b3e5.png)

## メールデータが消えないようにしたい

MailHog は、デフォルトではメールデータをメモリに保存するため、コンテナを停止したり、削除するとデータが消えてしまいます。
そこで、保存先をファイルに変更することで消えないようにします。

環境変数の `MH_STORAGE` に `maildir` を指定することでファイルに保存するようにし、
`MH_MAILDIR_PATH` に保存するディレクトリを設定します。
さらに、volumes の設定で、ローカルの `mailhog` ディレクトリにファイルを保存するようにしてあげればOKです。

```yml:docker-compose.yml
mailhog:
    image: mailhog/mailhog
    ports:
        - "8025:8025"
        - "1025:1025"
    environment:
        MH_STORAGE: maildir
        MH_MAILDIR_PATH: /tmp
    volumes:
        - "./mailhog:/tmp"
```

# httpsへの対応

本番環境は、https であることがデフォルトになりつつあるので、
ローカルで開発する時も https に対応しておきたいなと。
Let's Encrypt なども考えましたが、ローカルですし自己署名で良いかなと。

色々と調べてみましたが、単純に自己署名証明書を作ってあげれば良さそうです。
`Dockerfile` に下記を追記して、build し直します。

```dockerfile:Dockerfile
RUN openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/ssl-cert-snakeoil.key -out /etc/ssl/certs/ssl-cert-snakeoil.pem -subj "/C=AT/ST=Vienna/L=Vienna/O=Security/OU=Development/CN=localhost"
RUN a2enmod rewrite \
    && a2enmod headers \
    && a2ensite default-ssl \
    && a2enmod ssl
```

自己署名なのでブラウザのエラーは出てしまいますが、無事 https に対応できました！

![https.png](https://qiita-image-store.s3.amazonaws.com/0/287186/aec90120-e6f1-e213-1285-4f0db36942b8.png)


さぁ、ここまで出来れば、あとはもう開発するだけです！
SwiftとObjective-C連携 with Xcode

# 環境

Xcode 9.3

![Screen Shot 2018-10-31 at 23.15.26.png](https://qiita-image-store.s3.amazonaws.com/0/70065/2dd585a3-6e48-bb51-4a3c-2202e85ba81d.png)

# 書いたこと

* SwiftからObjective-Cコードを呼び出す方法
* Objective-CからSwiftコードを呼び出す方法

# SwiftからObjective-Cコードを呼び出す方法

## 流れ

1. `Build Settings` を設定
2. `Bridging-Header.h` の追加
3. Swiftから呼び出すファイルを2で追加したブリッジングヘッダーにimportする

### 1. Build Settings を設定

**Packaging** の **Define Modules** 項目を **true** にする。

![Screen Shot 2018-10-31 at 22.38.00.png](https://qiita-image-store.s3.amazonaws.com/0/70065/1dd610c6-4bed-be8f-2c3a-4bafde7dd6a8.png)

### 2. Bridging-Headerの追加

新規ファイルの追加から `Objective-C` ソースファイルを追加するとダイアログが表示されるので、 **Create Bridging Header** ボタンを押下。

![Screen Shot 2018-10-31 at 22.41.22.png](https://qiita-image-store.s3.amazonaws.com/0/70065/0b57fc62-257e-9bb7-b022-7f4572e99fca.png)

**Build Settings** で Bridging-Headerに、 **\<ProjectName\>-Bridging-Header.h** ファイルが指定されていることを確認する。

![Screen Shot 2018-10-31 at 22.46.17.png](https://qiita-image-store.s3.amazonaws.com/0/70065/8cef9168-d918-11b0-05d1-35e2004043e2.png)

### 3. Bridging-Headerにインポート

```objective_c:SwiftCallObjc-Bridging-Header.h
// Swiftから呼び出すObjファイルをimportする
#import "Foo.h"
```

# Objective-CからSwiftを呼び出す方法

## 流れ

1. `Build Settings` を設定
2. Swift APIを呼び出す **.m** ファイルで **\<Product_Module_Name\>-Swift.h** ファイルを import する

### 1. Build Settings を設定

**Packaging** の **Define Modules** 項目を **true** にする。

### 2. **\<Product_Module_Name\>-Swift.h** ファイルを import する

`Product Module Name` は、 ※*Build Settings** で確認できる。

```objc:Foo.m
// モジュール名がObjcCallSwiftの場合 (以下のファイルは自動的に生成される）
#import "ObjcCallSwift-Swift.h"
```

**NOTE:** 英数字以外の文字が使われている場合は、 その部分をアンダースコアに置き換える。

```objc:Foo.m
//モジュール名が Swift-Objcの場合
#import "Swift_Objc-Swift.h"
```

# まとめ

タイトルで **With Xcode** とした理由は、 `\<ProjectModuleName\>-Bridging-Header.h` や `\<ProjectName\>-Swift.h` は、あくまでもXcodeを介した機能であるため。
Xcodeを介さない場合は、それぞれモジュール化してimportする方法がある。
以下を参照してください。
[[swift] Cライブラリーのモジュール化](https://qiita.com/ysn551/items/83e06cf74ae628cb573c)

# 参照

* [How can I import Swift code to Objective-C?](https://stackoverflow.com/questions/24102104/how-can-i-import-swift-code-to-objective-c)
* [How do i call swift function from objective c file in same project? [duplicate]](https://stackoverflow.com/questions/50047459/how-do-i-call-swift-function-from-objective-c-file-in-same-project)
* [Importing Project-Swift.h into a Objective-C class…file not found](https://stackoverflow.com/questions/26328034/importing-project-swift-h-into-a-objective-c-class-file-not-found)
* [[Qiita]どーーーしても、Objective-CからSwiftのインスタンスをいじりたい場合に気をつけること](https://qiita.com/shirahama_x/items/49843588138434dac07b)
* [[Qiita]Swiftのattributeまとめ[Swift4対応]#@objcMembers](https://qiita.com/shtnkgm/items/a793f26445f2b8390bee#objcmembers)  
  ※ タプルはobjにならない。
Spring FEST 2018に参加した感想

今回SpringFest2018に参加してきましたが、数あるセッションの中でも、一つのセッションに注目しました。
その概要と個人的感想を中心にシェアできたらと思い作成しました。
セッションの詳しい内容につきましては、後日公開される予定である公式ページの資料をご確認ください。
公式ページ：　http://springfest2018.springframework.jp/

---
## イベント概要

SpringFest2018とは、SpringFrameworkを使用するユーザ間での情報交換や交流の場であり、更なるSpringFrameworkの普及促進を目指すイベントです。

![980c5fe716efb66c936eebe1937d5489.png](https://qiita-image-store.s3.amazonaws.com/0/272691/9361b7d6-8f9e-9f4f-8832-99a9b09725d4.png)

---
## 参加したセッション

- RakutenTravel and Spring
- KeyNote
- エンタープライズ・マイクロサービスの格言
- Observability with Spring-Based Distributed System
- 業務で使いたいWebFluxによる　Reactiveプログラミング

---
### 今回注目したのは...

## **RakutenTravel and Spring**

by Kalburgi Gajraj さん （from 楽天トラベル）

---
### 概要

楽天トラベル開発で用いられているSpringに関連する技術についての紹介

---
#### コンテンツ

1. Spring Initializer
2. Spring Cloud Config
3. Spring Boot Actuator
4. Spring Boot Admin
5. Swagger

---
### Spring Initializer

- プロジェクトやモジュールを作る際に必要な構成を作るのを手助けしてくれる便利なもの
- WebUIでプロジェクト構成を設定すると、自動的に生成してくれる
- IntelliJ IDEAの有償版を使用している場合は標準プラグインとして使用できる

---


以下のキャプチャのように簡単に生成できる!
- URL : https://start.spring.io/
![スクリーンショット 2018-10-31 17.19.52.png](https://qiita-image-store.s3.amazonaws.com/0/272691/06e213f0-6a74-709e-bfc8-01f283ef6d3b.png)


---
### Spring Cloud Config

- 分散システムにおいて複数のアプリケーションの設定を一元化することをサポートしてくれるもの（設定の共通化??）
- 簡単にいうと設定ファイルを集約してくれるらしい
- 公式ドキュメント：https://cloud.spring.io/spring-cloud-config/

---
### Spring boot’s Actuator

- システムの状態を確認するためのエンドポイントを追加してくれる
- メトリクスやSpringに登録されているbean一覧を確認できる
- 代表的なものを挙げると、以下のようなものがある

①/health 　②/info  　③/env  　④/loggers

---
##### 使い方

1.build.gradleに依存性を追加

```groovy:build.gradle
repositories {
    mavenCentral()
}

dependencies {
    implementation('org.springframework.boot:spring-boot-starter-actuator')
    implementation('org.springframework.boot:spring-boot-starter-web')
    testImplementation('org.springframework.boot:spring-boot-starter-test')
}
```

---
##### 使い方
2.公開したいエンドポイントを設定


```yml:application.yml
management:
  endpoints:
    web:
      exposure:
        include: env,beans,loggers,health,info

```

---
##### 使い方
3.こんな感じでcurlする

```terminal
-> % curl "http://localhost:8080/actuator/env"
{"activeProfiles":[],"propertySources":[{"name":"server.ports","properties":{"local.server.port":{"value":8080}}},{"name":"servletContextInitParams","properties

-> % curl "http://localhost:8080/actuator/health"
{"status":"UP"}% 

```

---
### Spring boot Admin

- Spring boot Applicationのための管理画面を提供してくれる
- メトリクスやログ、アプリで実行されているスレッドなどを確認できる
- サーバー側の設定とクライアント側の設定（モニタリングされる側）が必要
- ガイド：http://codecentric.github.io/spring-boot-admin/current/

---
##### ざっくりした使い方
1.Server側のbuild.gradleに依存性を追加
2.Server側に@EnableAdminServerを付与
3.Client側のアプリのbuild.gradleにも依存性を追加
4.Client側のapplication.ymlにAdminServerへの接続情報を追加
5.エンドポイントにアクセスすると管理画面が表示される

---
### Swagger

- APIの開発を高速化する
- API情報の可視化をしてくれる
- エンドポイントのテストを容易にする
- 公式ページ：https://swagger.io/

---
### 感想

- 己のSpringFrameworkの仕様に関する理解度不足を知った
- 業務上使ってるアノテーションなどの身近な部分から、SpringBootの全般的な内部動作までを復習しようと思いました！
- やる気が出た！
[Swagger Editor] Swagger Editor でオブジェクト内の配列を表現したい

[Swagger Editor](https://editor.swagger.io/#) を使う機会があったのだが、その際にオブジェクトの中に配列を持つデータ構造を表現するのにハマったので備忘録として残す。

## やりたいこと

次のような ｢ **オブジェクトの中に配列を持つ** ｣ データを Swagger Editor を使って表現したい｡

```json:表現したいデータ
{
  "data": {
    "id": 0000001,
    "name": "hogehogehogehoge",
    "child_id": [
      "child_00001",
      "child_00002",
      "child_00003",
      "child_00004"
    ]
  }
}
```

## 実現方法

Swagger Edtitor は YAML で記述するので次の内容となる。

### 単純にそのまま書く場合

```yaml:実現するための記法
definitions:
  SampleData:
      type: object
      properties:
        data:
          type: object
          properties:
            id:
              type: string
              example: 0000001
            name:
              type: string
              example: hogehogehogehoge
            child_id:
              type: array
              items:
                type: string
              example:
                - child_00001
                - child_00002
                - child_00003
                - child_00004
```

### $ref を使う場合

```yaml:実現するための記法($refあり)
definitions:
  SampleData:
      type: object
      properties:
        data:
          type: object
          properties:
            id:
              type: string
              example: 0000001
            name:
              type: string
              example: hogehogehogehoge
            child_id:
              $ref: "#/definitions/ChildIdList"

  ChildIdList:
    type: array
    items:
      type: string
      example:
        - child_00001
        - child_00002
        - child_00003
        - child_00004
```

## どこにハマっていたか

```child_id``` を配列で表現する記法がわからなかった。

### 試行錯誤の例1(エラーになる)

```yaml:試行錯誤の例1(エラーになる)
child_id:
  type: array
  items:
    - child_00001
    - child_00002
    - child_00003
    - child_00004
```

としたらエラーになり、

### 試行錯誤の例2_YAML(配列の中に配列ができる)

```yaml:試行錯誤の例2_YAML(配列の中に配列ができる)
child_id:
  type: array
  example:
    type: string
    items:
      - child_00001
      - child_00002
      - child_00003
      - child_00004
```

としたら

```json:試行錯誤の例2_JSON(配列の中に配列ができる)
"child_id": [
  [
    "child_00001",
    "child_00002",
    "child_00003",
    "child_00004"
  ]
],
```

となったり、とかなり時間をロスした。


## まとめにかえて

試行錯誤して上記を解決したあとに気づいたのだが、[Swagger Editor](https://editor.swagger.io/#) には **Convert to YAML** という機能があって、JSON データを YAML にコンバートしてくれる。
これを利用すればもう少し早く解決できたと思うので、今後記法でつまづいたら

1. まず JSON で実現したデータを書く
1. そのデータを Swagger Editor で YAML にコンバートする

という手順を行う、というところでまとめにかえる。
「ふれあいまつり 」プロジェクト概要

10月27日、28日の両日、奥多摩町で「奥多摩ふれあいまつり（以下「ふれあいまつり）」が行われました。
奥多摩日本語学校では、「ITブース」を企画して出展。VRとARの技術を体験できるブースにしました。
詳しい開発内容については、個々の担当者にお任せするとして、ここでは、このプロジェクトの概要を説明します。

# 「ふれあいまつり」プロジェクトとは？
## これまでの経緯
　奥多摩日本語学校は、昨年10月に開校したばかりの学校です。「ふれあいまつり」への参加は、今年で3回目になります。
1回目は、提携校の学生に協力してもらい「奥多摩日本語学校」を広く知ってもらう活動にしました。
2回目は、10月に入学したばかりの1期生が運営し、やはり、学校や学生を知ってもらうための活動になりました。主に、出身国や学校の紹介のため、自国の料理の無料配布などを行いました。
今回、満を持しての3回目の参加。「奥多摩日本語学校」らしさをアピールするにはどうすればいいのか？と頭を悩ませていました。
## プロジェクトの課題
　奥多摩日本語学校ではプロジェクトをベースにした授業を行っており、これまで、奥多摩町の課題を解決するためのサービスやプロダクトのプロトタイプを製作するという課題に取り組んできました。実際に奥多摩町の住民を学校に招いて、日本語でプレゼンをするということを行ってきました。

　それらのプレゼンでは、町の方々から直接、有意義なフィードバックをもらうことができましたが、中には、「普段あまりパソコンを使わないので、よくわからない」とか「操作が難しそう」など、町の方々が、日常的にIT技術に接していないという現状を突きつけられる機会にもなりました。IT技術で課題を解決したいという目標と現状に大きな乖離があるように感じました。

　そこで、多くの奥多摩住民が集まる「ふれあいまつり」で、この問題の切り口になるような活動ができないかと考え、下記のような課題を提案しました。

- **課題① PC、スマホ操作に慣れていない人でも楽しめるプロダクトを製作する**
- **課題②「ふれあいまつり」で使えるツールを製作する**
- **課題③ ①②で製作したプロダクトは「ふれあいまつり」で実際に使用し、フィードバックを得る**

# 開発スケジュール
今回のプロジェクトは、以下のようなスケジュールで進めました。

|日程|       | 活動内容 |
|:----------:|:---------:|:------------|
| 10/15 (月) | 活動① | 課題の提示・ブレインストーミング・チーム分け |
| 10/16 (火) | 活動② | 開発作業|
| 10/18 (木) | アウトプット① | プロトタイプのプレゼン・フィードバック |
| 10/22 (月) | 活動③ | 開発作業 |
| 10/23 (火) | 活動④ | 開発作業 |
| 10/25 (木) | アウトプット② | 最終プロダクトのプレゼン・フィードバック |

秋学期（10月〜12月）は、月曜日と火曜日を「活動」の時間、木曜日を「アウトプット」の時間とし、毎週木曜日に、プロトタイプをプレゼンするというサイクルで授業を進めています。

# 授業の様子
## 活動① ブレインストーミング
「PC、スマホの操作に慣れていない人」というお題は、学生たちも身を以て感じているので、どんなものがいいのか非常に頭を悩ませていました。とりあえず、全員でブレスト。
![alt](https://drive.google.com/uc?export=view&id=1fXNyjX2dsXyHMy2sL1z-ps8xR4c1EcsW)

議論の結果、「VR体験チーム」と「ゲーム＆クイズチーム」ができました。

## 活動② 開発作業
「VR体験チーム」は、やりたいことが決まり、どんどん作業が進んでいきました。
一方、「ゲーム＆クイズチーム」は「PC、スマホの操作に慣れていない人」が引っかかり、なかなかアイデアがまとまらない様子。最終的に「ARを使ったゲーム」に決定。木曜日のアウトプットの時間に、開発は間に合うのか？？

## アウトプット①
第1回目のプロトタイプのプレゼン。両チームとも、まだまだ改善の余地がありそう。
「VR体験チーム」は、コンテンツも少なく、画面構成にも手直しが必要そう。
「ARゲームチーム」は、悩みに悩んだ結果、「宝探しゲーム」を提案しました。ゲームの内容としては面白そうですが、オペレーション全体を考えると、果たして運用が可能なのか、疑問が残るプレゼンになりました。

## 活動③④
本当は、ここで課題②に取り掛かる予定でしたが、両チームとも、こちらの予想以上に高度な技術への挑戦を始めたため、開発の時間にもっと時間が必要だと判断。課題①の開発を続けることになりました。
ただし、課題③の「フィードバックを得る」という課題をどのようにするのか問題提起をしたところ、フィードバックを集計するツールを並行して開発することになりました。
VRチームは、コンテンツの質を上げるために、試行錯誤しました。
ARチームは、ここにきて、全く新しいゲームを考案。一からの出直しになりました。
この2日間、ひたすら開発作業を続けました。

## アウトプット②
この日は、当校の取材に訪れた大学関係者と企業の方、計7名が授業見学に入りました。
初めてプロダクトを見るゲストに、実際に体験してもらいながらプレゼンを行い、フィードバックをもらいました。
様々な角度から、有益なフィードバックがいただけた様子。
この後、フィードバックをもとに、授業外でも開発を続けていきました。

# 当日の活動の様子
当日の様子を、写真でお届けします。
詳しい開発秘話については、開発担当者に書いてもらいましょう。

<img src="https://drive.google.com/uc?export=view&id=15U5V8Kn5iMkYAinU5jRTtWwklTJJG6PS" width=60%>
VRチームの様子

<img src="https://drive.google.com/uc?export=view&id=142ldPRdCONy4gGmQed4OFo2_euhfOsZC" width=60%>
ARチームの様子


今までの「ふれあいまつり」ではなかなか見られなかった「ハイテクブース」
多くの「WOW」がお届けできたのではないかと思います。

# リンク
↓「ふれあいまつり」チラシ（奥多摩町公式ホームページより）
[奥多摩ふれあいまつり](http://www.town.okutama.tokyo.jp/sangyo/kanko/documents/2018hureai.pdf)

写真の貼り付けには、下記を参考にしました ↓
[Google Drive に保存した画像を直接呼び出せるURLの取得](https://qiita.com/arribux/items/0394968fa318d9309d33)

(2019年1月8日追記）
写真が大きいな〜と思ったので、サイズを変えてみました。下記記事参照。
[Qiitaに貼った画像がなんかデカいなあ〜と思ったら](https://qiita.com/hkusu/items/1ba2de200f731e5ef374)
GR-Lycheeを使うならば参考にするサイト

GR-Lycheeは、Renesas Webコンパイラと、mbed、IDE for GR,e2Stduioでコンパイル可能です。

公式HP
http://gadget.renesas.com/ja/product/lychee.html

mbedは
https://developer.mbed.org/platforms/Renesas-GR-LYCHEE/

Renesas Webコンパイラ
http://gadget.renesas.com/ja/product/lychee_sp/1.html

IDE for GR
http://gadget.renesas.com/ja/product/lychee_sp/2.html

e2studio
http://gadget.renesas.com/ja/product/lychee.html#e2studio
です。

AIoTLTハンズオンのコンパイル済みファイルです。
 Webコンパイラでコンパイルできるようです。
https://japan.renesasrulz.com/gr_user_forum_japanese/f/gr-lychee/5347/aiotlt

USBは、真ん中のものを使用することで書き込み可能です。
Windows10以前は、ドライバー必要な場合があるようです。
http://os.mbed.com/media/downloads/drivers/mbedWinSerial_16466.exe

私は、IDE for GRを使用していますが、Renesas Webコンパイラで出来るならば、こっちの方が楽ですかね?
QMKセットアップ時の警告

この前の技術書典でcrkbdを買ったので、自作キーボード初挑戦中です。
個人的備忘録用兼、同じ事起きた人用に残して起きます。

OS:macOS High Sierra 10.13.16

ファームウェアの設定で
https://docs.qmk.fm/#/newbs_getting_started
見ながら進めてたら、セットアップのところで警告を吐かれた。
HomeBrewのupdateと被ったせいか、もしくはinstallが長くて、少しスリープに入っちゃったせいかも？
とりあえず警告の内容が

```
$ ./util/qmk_install.sh

Already up-to-date.
Warning: osx-cross/avr/avr-gcc@7 7.3.0 is already installed and up-to-date
To reinstall 7.3.0, run `brew reinstall avr-gcc@7`
Warning: px4/px4/gcc-arm-none-eabi 20171218 is already installed and up-to-date
To reinstall 20171218, run `brew reinstall gcc-arm-none-eabi`
Warning: dfu-programmer 0.7.2 is already installed and up-to-date
To reinstall 0.7.2, run `brew reinstall dfu-programmer`
Warning: avrdude 6.3_1 is already installed and up-to-date
To reinstall 6.3_1, run `brew reinstall avrdude`
Warning: dfu-util 0.9 is already installed and up-to-date
To reinstall 0.9, run `brew reinstall dfu-util`
```

で書いてある通りだけれど``内の打ってもう一度インストールし直せって事なので、もう一度インストールし直す。

これでやってみるがうまくいかず、ビルドが通らない。

色々探し回って、
https://github.com/osx-cross/homebrew-avr/issues/76
で書かれてることを試してみた。

```
$ brew remove avr-gcc avr-binutils
$ brew untap osx-cross/avr
$ brew cleanup -scf
$ brew upgrade
$ brew tap osx-cross/avr
$ brew install avr-gcc
```

で、もう一回

```
$ ./util/qmk_install.sh
```
をやって見たが警告は消えない。

ただ、ビルドは通った。

何がいけなかったんだろうか？
Webページの認証を1行の記述だけでやってみる

最近はWebアプリを作る時に設計書とか書かずにさっさとプロトタイプを作ってデプロイして見せることが多い。

そこで気になるのが公開範囲。限定した人にだけ見せたいけど、そのために認証システムを毎回ちゃんと実装するのはめんどくさい。NgixでのBasic認証とかもめんどくさい。

とりあえず共通パスワードで知ってる人だけ入れてそれ以外は弾く仕組みが最低限あれば良い。厳密性とかいいから、だいたい動けば良い。という前提で考え抜いた結果行き着いたのが以下。


```javascript
(prompt('合言葉は？') !== 'たこやき') && document.write('だめだこりゃ')
```


である。このスクリプトをHTMLの適当な場所に仕込めば良い

```html
<html>
<body>
<h3>ようこそ!</h3>
<script>;(prompt('合言葉は？') !== 'たこやき') && document.write('だめだこりゃ')</script>
</body>
</html>
```

的なことをすると、

<img width="694" alt="Screenshot 2018-10-31 22.36.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/14107/77d13541-b6bb-2657-a370-4c59ee42a723.png">

みたいな感じになる



## 処理の解説

[`window.prompt(message)`](https://www.w3schools.com/jsref/met_win_prompt.asp)はダイアログを表示するブラウザのビルドインの関数で、ユーザーの入力値を戻り値として返す。

[`document.write(content)`](https://developer.mozilla.org/en-US/docs/Web/API/Document/write)はhtmlのbodyを書き換える関数。



ユーザー入力結果がベタ打ちのパスワードと一致したら何もせず、一致しなかったらhtmlの中身を全部消してしまう、という処理。

## もう一歩進化させる

ただしまだ問題がある。ページをリロードするたびに聞かれるのでウザい。

一度OKになったらもう聞かないようにしたい。

localStorageを使えば解決だ。

```javascript

(localStorage.getItem('authorized') == 'YES' || (prompt('合言葉は？') === 'たこやき')) ? localStorage.setItem('authorized', 'YES') : document.write('だめだこりゃ') 
```

## まとめ

* とにかく楽な認証は一行でできる
* セキュリティ的にはゆるゆる(パスワードべた書き、クライアント側で処理)
* 良い子は真似しちゃだめよ
数値計算でハマりやすいポイント～浮動小数点～

身近な場面で、浮動小数点絡みの問題に遭遇したので、その話をシェアしたいと思います。

# 後輩からの質問「ヒストグラムが上手く描けない」

後輩から質問が来ました。
「ヒストグラムが上手く描けない」とのことでした。

グラフ作成ライブラリmatplotlibでヒストグラムを書こうとして、失敗したようです。
後輩が描こうとしたヒストグラムがこちら。

```python
import matplotlib.pyplot as plt
import numpy as np

s = np.array([0, 1, 1, 1, 2, 2, 2, 3])
mins = s.min()
maxs = s.max()

plt.hist(s, bins=int(maxs - mins + 1), range=(mins, maxs+1), alpha=0.3, color='deepskyblue', ec='deepskyblue', align='left')
plt.xticks(np.arange(mins, maxs+1, step=1))
```
出力：
![ヒストグラム.PNG](https://qiita-image-store.s3.amazonaws.com/0/254780/3139ad0e-73da-4daf-331f-d39cf67f33a9.png)
***

これは、上手く描けている例です。
いつもは、このやり方で描けていたのに、今日は上手く描けなかったので、私のところに質問に来たようです。
その例がこちら。

```python
import matplotlib.pyplot as plt
import numpy as np

s = np.array([0, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.3])
mins = s.min()
maxs = s.max()

plt.hist(s, bins=int((maxs-mins)*10 + 1), range=(mins, maxs+0.1), alpha=0.3, color='deepskyblue', ec='deepskyblue', align='left')
plt.xticks(np.arange(mins, maxs+0.1, step=0.1))
```

出力：
![ヒストグラム2.PNG](https://qiita-image-store.s3.amazonaws.com/0/254780/4830a6a6-6b5c-f68c-15d8-b302c86aec56.png)
***

基本的に、スケールが違う点以外は、初めの例と同じです。
変数の値をprintしてみましたが、一見おかしな所は見つかりませんでした。

```python
print(s)  # data
print(int((maxs-mins)*10 + 1))  # bin
print(mins)  # range 
print(maxs+0.1)  # range
print(maxs)
```
出力：
[0.  0.1 0.1 0.1 0.2 0.2 0.2 0.3]
4
0.0
0.4
0.3
***

この結果を見て、私も「なぜ？」と思いました。
そして、もう少し調べてみることにしました。

# 答え「浮動小数点」

さらに突っ込んで変数の中身を見てみると、**変数maxsは、一見0.3の値が正確に入っているように見えるが、実は厳密には0.3とは異なる値が入っていることが分かりました。**
その証拠がこちら

```python
print(maxs)
print(type(maxs))
print(maxs/3.0)
```
出力：
0.3
class 'numpy.float64'
0.09999999999999999
***

s = np.array([0, 0.1, 0.1, 0.1, 0.2, 0.2, 0.2, 0.3])に対して、s.max()で最大値を取った値を3で割っても、0.1になっていません。
これは、sの最大値、maxsがnumpy.float64型という、64bitの浮動小数点で表されているためです。表示上は、maxsに正確に0.3の値が入っているように見えていましたが、マシン内部では、2進数の近似値で保持されており、厳密には0.3と違う値が入っていたのです。

※pythonの浮動小数点の扱いに関する詳細は[こちら](https://docs.python.jp/3/tutorial/floatingpoint.html)

今回の例では、0.3なのか、0.29999999999999999なのかという微妙な違いが影響して、上手くヒストグラムが描画できなかった、ということが分かりました。

# 今後への教訓

数値計算のプログラムを書いていると、閾値判定で処理を分岐するというケースもあるかと思います。その時に、浮動小数点の問題を意識せずにコーディングすると、思いもよらない結果になりそうです。
float型での演算を繰り返した後で、境界値で閾値判定を行うのは危険、ということを再認識しました。

# 参考
[15. 浮動小数点演算、その問題と制限]
(https://docs.python.jp/3/tutorial/floatingpoint.html)
メッシュの名前を「MESH_オブジェクト名*たち*」にする (Python for Blender クックブック)

# メッシュの名前を「MESH_オブジェクト名*たち*」にする

Pythonを使ってBlenderでできる事をまとめています。解説もあります。
[はじめに](https://qiita.com/KTakahiro1729/items/5de5f60982af37d23aa0)
[レシピ一覧](https://qiita.com/KTakahiro1729/items/57f4e1f5495c5e54d431)

Pythonの難易度: ★★★☆☆
### 動機
オブジェクトの名前を変更しても、メッシュの名前までは変わりません。
いちいち変えるのも面倒くさいので、Pythonにやってもらいましょう。

### 細かい仕様
- メッシュ名を「MESH_オブジェクト名」にしてください。
- 複数のオブジェクトに共有されている場合、オブジェクト名の間を`_`で繋いでください
- オブジェクトに使われていないメッシュは「MESH_NOUSER」と名付けてください。

## サンプルコード

```python
import bpy

meshes = bpy.data.meshes

mesh_obj_dict = {mesh.name:[] for mesh in meshes} # mesh_obj_dictを初期化

for obj in bpy.data.objects: # mesh_obj_dictのvalueを埋める
    if obj.type == "MESH":
        mesh = obj.data
        mesh_obj_dict[mesh.name].append(obj.name)

for mesh, objs in mesh_obj_dict.items(): # meshの名前を変更する
    if len(objs) == 0:
        meshes[mesh].name = "MESH_NOUSER"
        continue
    meshes[mesh].name = "MESH_{0}".format("_".join(objs))
```


上記サンプルコードを、Blender内蔵のテキストエディタに貼り付けた後、<kbd>Alt</kbd>-<kbd>P</kbd>を実行してください。

## 解説
### 全体の流れ
まず、`{メッシュ:そのメッシュを使っているオブジェクトのlist}`（コード中では`mesh_obj_dict`）を初期化し、最初のfor文で完成させます。

その次のfor文では`mesh_obj_dict`を元にmeshの名前を上書きしています。

### `mesh_obj_dict`
オブジェクトからそれ**が**使用しているメッシュを知るには`object.data`を除けばいいだけです。
一方、メッシュからそれ**を**使用しているオブジェクトをたどる事は（一発では）出来ません。どうしてかは知りません。
そのため、bpy.data.objects内を探して、各オブジェクトが参照するメッシュごとに分類しています。

また、オブジェクトやmaterialなどデータの名前を一度変えてしまうと、そのデータを探すのが非常に難しくなります。
そのため、最初のfor文では名前の変更はしません。
FirstVRでのゲーム開発で詰まったところをまとめる

今回は、以前あったFirstVR&Unity勉強会( https://firstvr.connpass.com/event/105634/ )でも話させていただいた、FirstVRでのゲーム開発で詰まったポイントを書いていこうと思います。

ちなみにその時使ったスライドも公開してあるので、よければご覧ください。
http://bit.ly/2PrRVGi

##FirstVRとの接続が不安定
Androidでの開発している時、FirstVRとスマホとの接続に時間がかかる、ということが結構ありました。
その理由については、FirstVRのSlack( https://first-vr.com/firstvr-slack-community/ )にて回答があります。
>AndroidでのFirstVRコントローラの接続についてですが，Androidが搭載されたスマートフォンの機種のBluetoothのアンテナの実装位置や機種によるBluetoothの実装変更によっては，接続まで時間がかかる場合があるようです．それは，スマートフォンとFirstVRコントローラの接続は，BLEのdBmから推測されるデバイス間の距離で開始されるからです．そのため，Bluetoothのアンテナの実装位置や機種によるBluetoothの実装変更によっては，接続まで時間がかかる場合があるようです．

その場合の対処は、「接続時にFirstVRコントローラをAndroidが搭載されたスマートフォンの機種の背面上部，あるいはバッテリが配置されていない位置に接触させる」だそうです。
アプリを起動する際にFirstVRをスマホにくっつけておくと、接続に時間がかかるというのはなくなりそうですね。

##FirstVRが繋がらなくなった
ゲーム開発をしている途中で、いきなりFirstVRの接続ができなくなる現象が起きました。
![are_.PNG](https://qiita-image-store.s3.amazonaws.com/0/307844/6be06fe8-27ec-971f-d42b-73b8b248c867.png)

![are_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/307844/004ed174-e6e8-a1c1-9c07-1d28b58e2bd9.png)
つまり、シーンに元々あったFVRContainerが消え、新しいFVRContainerがシーン上に作られているため、シーンにはFVRContainerがあり一見問題なく動くように思われます。
しかし、FirstVRの接続判定をする奴が元々あったFVRContainerを見ているのでうまく接続できなくなっていた、というオチでした。

##Recenter()が反応しない
開発している際に必ずほしい機能の一つでリセンターがあると思います。
そんな時に使うのがRecenter()なのですが、APIを見てみると２つ存在します。
![Reference.PNG](https://qiita-image-store.s3.amazonaws.com/0/307844/2a57cabd-ecf0-bec4-1c78-021226724e82.png)

![Connection.PNG](https://qiita-image-store.s3.amazonaws.com/0/307844/32c2fed1-7bd0-48f7-cc64-4d3db9243872.png)
![Connection_2.PNG](https://qiita-image-store.s3.amazonaws.com/0/307844/98eb4b9d-2ccb-23e0-1930-fd883b2a68bb.png)

私は最初、ReferenceクラスのRecenter()を使っていました。
これが動かない原因でした。

APIを見ると、コントローラーのリセンターを行うにはFVRConnectionの方のRecenter()を行わなければいけないらしいです。


#最後に
以上が今回のゲーム開発で詰まったポイントでした。
他に分からないことなどがあれば、FirstVRのslackで聞いてみるのも良いかもしれません。
https://first-vr.com/firstvr-slack-community/
React時代のWeakMap

ES6からJavaScriptに加わった`WeakMap`ですが、Reactと組み合わせて使ってみても意外と便利かなと思い始めました。

## `WeakMap`とは

`WeakMap`も、単なるオブジェクトやWeakでない`Map`と同様に、キーと値の組み合わせを管理するための仕組みです。ただ、

* `WeakMap`がキーにできるのは、関数・DOMノード・配列などを含め、オブジェクトだけ（プリミティブは使えない）
* 今あるキーの一覧を取得する方法がない
* キーのオブジェクトがガベージコレクトされると、`WeakMap`内のキー・値ペアも消滅する

というような仕組みになっています。ふつうの`Map`と違って、入れておいても「キーが」ガベージコレクションされうる、という意味でのWeakです。

## よく言われる使いみち

よく`WeakMap`の使う道として言及されるのは、

* jQueryの`.data`と同様な、DOMノードにデータを紐付けるために使う
* `WeakMap`インスタンス自体をモジュールに封じきることで、オブジェクトに対して`package private`的なデータの置き場に使う

などです。確かに、いまのところJavaScriptに`private`はありませんので、これもこれでありなのは間違いなさそうです。

## Reactとの組み合わせ

もちろん、Reactで「DOMノードと値を紐付ける」なんて操作をやっても誰も嬉しくならないです。ただ、Reactの中では[破壊的変更に頼らないデータ管理](https://reactjs.org/docs/optimizing-performance.html#the-power-of-not-mutating-data)が推奨されていますので、この観点から考えれば、特定のオブジェクトに値を結び付けられる`WeakMap`は便利に運用できます。

### `props`から計算したデータのキャッシュ

時折、`render`すべきデータが、`props`に対して複雑な計算（典型的な例としては、配列の絞り込み・ソートなど）を行ったものとなる、という場面があります。もちろん、「毎回計算する」でも結果は正しくなるのですが、毎回不要な計算をするオーバーヘッドが積もってきてしまいます。

そして、「`state`に計算結果を置いておく」という手段もありますが、それも`props`の更新と同期させるのが煩雑となるということで、[Reactの公式ブログ](https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization)でも、「別途でキャッシュの仕組みを入れる」ことを推奨しています。

当該のブログでは、`memoize-one`として「同じオブジェクトである間キャッシュする」という仕組みとなっているため、キャッシュ関数自体をコンポーネントインスタンスに紐付ける必要が出てきていますが、`WeakMap`であれば全部まとめてキャッシュを管理しても全く問題ないので、関数コンポーネントに対しても運用できます。

### イベントハンドラ

Reactでコンポーネントを何階層も重ねていくと、「`<Parent>`で特定の動作を起こすためのハンドラ関数を下に引き回していくけれど、実際にハンドラに渡す値が供給されるのは孫コンポーネント」というような場面もよくあります。このような場合、孫コンポーネントの側で`onClick={() => doParentAction(param)}`のようにバインドすると、`render`ごとに無名関数が作り直しとなって、非効率になります。

ここでも、キーを親から降りてくる`doParentAction`とした`WeakMap`を作れば、関数コンポーネントでもキャッシュが可能ですし、破棄の心配もありません。

## 注意点

上記のように、キャッシュとして「きちんと消えてくれる」`WeakMap`が必要な場合、Polyfillでは**実現できません**。IE 10以下には本物がないので、そこでは動かせないのは要注意です。
旧バージョンのApache Tomcatのダウンロードのやり方


# はじめに
今回Tomcat8のバージョン8.5.24版が必要になったのですが、Apache Tomcatのホームページで公開されているのは、Tomcat8.5.34版で、Tomcat8系の旧バージョン入手までに若干手間取ったので備忘録としてまとめておこうかと思います。

# 旧バージョンの入手方法 
1. [Apache Tomcatのホームページ](https://tomcat.apache.org/index.html)に飛びます。

2. **Download**メニューの**Archives**を[クリック](https://archive.apache.org/dist/tomcat/)します。
![1.JPG](https://qiita-image-store.s3.amazonaws.com/0/143107/e8297881-ce04-fb0a-5f2d-7e82fb93b131.jpeg)

3. 今回はTomcat8系が欲しいので、**Tomcat-8/**を[クリック](https://archive.apache.org/dist/tomcat/tomcat-8/)します。
![2.JPG](https://qiita-image-store.s3.amazonaws.com/0/143107/ae2d0389-e83b-10e2-f0be-4b9cc9743311.jpeg)


4. 3の手順で飛んだページでTomcat8系のバージョン一覧が確認できます。

5. 欲しいバージョンのリンクをクリックします。![3.JPG](https://qiita-image-store.s3.amazonaws.com/0/143107/8c54e53c-0910-f440-1619-dd87161ea3b7.jpeg)

6. **src/**をクリックします。
![4.JPG](https://qiita-image-store.s3.amazonaws.com/0/143107/d6ec64b2-3f37-3bad-9dc6-5c62d6f4ef99.jpeg)

7. Windowsならzipファイル、MacやLinuxなら.gzファイルを選択。クリックすると、ダウンロードが始まります。
![5.JPG](https://qiita-image-store.s3.amazonaws.com/0/143107/44ecdbb7-8c49-7941-93c3-38ce8770e5b4.jpeg)


8. 解凍したフォルダを任意のディレクトリに配置して完了。
KerasのfunctionalAPIの使い方

#KerasのfunctionalAPIの使い方
##はじめに
自分が初心者なので，初心者向けです。
おかしいところや間違っているところなどがあれば，指摘していただけたら嬉しいです……！
こちらの記事の方が参考になるかもしれません。
[Kerasはfunctional APIもきちんと理解しよう](https://qiita.com/shu_marubo/items/eb297b2245040e50c00f)

またはKerasのチュートリアルも参考になります。
https://keras.io/ja/getting-started/functional-api-guide/

##functionalAPIを使うことの利点
![NN.png](https://qiita-image-store.s3.amazonaws.com/0/241671/cc1ec1d3-33fb-b1a9-1a0c-faffb114ea32.png)

こんなネットワークが簡単に作れます。

```python
inputs_1 = Input(shape=(20,), dtype='float32')
inputs_2 = Input(shape=(20,), dtype='float32')
inputs_3 = Input(shape=(20,), dtype='float32')

hidden1_1 = Dense(10, activation='relu')(inputs_1)
hidden1_2 = Dense(10, activation='relu')(inputs_2)
hidden1_3 = Dense(10, activation='relu')(inputs_3)

hidden1_m = Multiply()([hidden1_1, hidden1_2, hidden1_3])

hidden2 = Dense(10, activation='relu')(hidden1_m)

hidden2 = Dense(20, activation='relu')(hidden1_m)

predictions = Dense(7, activation='softmax')(hidden2)

model = Model(inputs=inputs, outputs=predictions)

model.compile(optimizer=RMSprop(), loss='categorical_crossentropy', metrics=['accuracy'])

model.fit([x_train[0], x_train[1], x_train[2]], t_train, epochs=10000, verbose=1, batch_size=100)

```

こんな感じで実装できます。
もう少し詳しく見ていきます。

##複数の入力層を作る
```python
inputs_1 = Input(shape=(20,), dtype='float32')
inputs_2 = Input(shape=(20,), dtype='float32')
inputs_3 = Input(shape=(20,), dtype='float32')
```
こんな風にして入力層は増やせます。

##どこの層に結合させるか
中間層から出力層はこのようにして，どこの層と結合させるかを指定できます。

```python
hidden1_1 = Dense(10, activation='relu')(inputs_1)
```
右の(inputs_1)が結合する層です。

##層の合体
層を結合させるには，このように結合させた層をリストで渡します。

```python
hidden1_m = Multiply()([hidden1_1, hidden1_2, hidden1_3])
```
もちろん，次のように書いてもOKです。

```python
hiiden1 = [hidden1_1, hidden1_2, hidden1_3]
hidden1_m = Multiply()(hidden1)
```

##複数の入力のモデル作成

```python
model = Model(inputs=[inputs_1, inputs_2, inputs_3], outputs=predictions)
```
こういう感じで，リストで渡します。
もちろん，こちらもこれでOK。

```python
inputs = [inputs_1, inputs_2, inputs_3]
model = Model(inputs=inputs, outputs=predictions)
```

##複数の入力の学習
入力する学習データのリストを与えます。

```python
model.fit([x_train[0], x_train[1], x_train[2]], t_train, epochs=10000, verbose=1, batch_size=700)
```

##結論
こういう分岐するネットワークもfunctionalAPIなら簡単にかけます！
新人SEのリーダブルコードリーディング

#目的
リーダブルコードでの学習をアウトプットすることで、知識の定着を図る
#実施内容
１章から隔週で読み込みを行い、
その内容から得られた知見やポイント・所感などを記述していく。

##第一章 理解しやすいコード
優れたコードを書く上で最も押さえておかなければならないこと・コンセプトは
**「他者が最短時間で理解できるように書かなければいけない」**ということである。
コードは自分だけのものではない。コードは保守しやすいように書かなければならない。
相手のことを「想う」ことが大切なんだと感じた。

##第二章 名前に情報を詰め込む
使用するメソッドや変数の名前のつけ方に関しての作法が記述されている。
ここでもポイントとなるのは、「最短時間で理解できるように」である。
これを根本に置いたうえで、そのためにはどのような方式で名前を決定していけば良いのだろう。
本を読んでみて、「意味のある名前を付ける」「それはわかりやすい意味とする」
「特に動詞の部分を明確にしてみる」「複数名詞を羅列する場合はアンダーバーなどを用いる」
「名詞に関しては大きさ（単位など）や状態を追記する」
「これらは具体化しすぎない」「その塩梅はコードの影響範囲と関係している」
「抽象的な名前を用いるのであれば、なるべく固める」
辺りがKEYとなるのかと感じた。
また、先輩からはこの章に関連して
**ひとつの変数・ひとつのメソッドにはたった一つの責任のみを負わせるようにする**
とのアドバイスを受けた。
これにより、名前と中身が完全に一致し、齟齬やバグの防止につながるという。
またUTにおいてもスムーズな作成につながる。


##第三章 誤解されない名前
前章では使用するメソッドや変数において、情報を埋め込む必要があることを知った。
本章では、その情報を**「適切に設定しているか」**検証する必要があることを主題としている。
主に、誤解されないかに着目している。
境界面に注意をしたほうが良い。min,maxやfirst,lastを用いて範囲を明確にすること。
ブール値に関しては、どんな状況にtrue/falseになるのか、is○○やcan○○などで表現すること。
単語に対する一般的な期待値に注意すること。
先輩からは、一般的な基準とずれた場合が名前を考え直すポイントと伺った。


##第四章　美しさ　第五章　コメントすべきことを知る　　　　　
本章は「美しさ」についての記載である。
ごちゃごちゃしている汚らしいコードは保守性に欠けるなどの負の影響を及ぼす。
ポイントは**大事なところを他者にわかりやすく理解させるようにする**ということ。
そのために、「無駄にコメントを書かない」ことや「インデントの活用」
「同じような処理は切り出して、それを呼び出して使うようにする」などを実施する必要がある。でないと、埋もれてしまうからだ。
このテーマに関して、先輩は「コメントつけるか迷っているということは、それはメソッドや変数名の定義に問題がある証拠」というアドバイスをいただいた。確かに、【優れたコード ＞ 汚いコード + よいコメント】の理論からして、その通りだと感じた。
redux-localstorageを使ってlocalstorageにstateを保存する

# 概要
reduxを用いた開発でデータの永続化をするためにlocalstorageにstateを保存する方法について見ていきます。
# インストール
まずはターミナルからredux-localstorageをインストールします。

```terminal
npm install --save redux-localstorage
```
# 使い方

```javascript
import { compose, createStore } from "redux";
import persistState from "redux-localstorage";


compose(persistState())(createStore);
```

reduxからcompose、redux-localstorageからpersistStateを取ってくることが必要になります。

上記のようにcomposeとpersistStateを使うことによってstate情報をlocalstorageに保存することができ、データの永続化ができるようになります。

私が実際に書いたコードが下記になります。
ルーティングを実装しているので見えづらいかもしれません。
composeとpersistStateを使っているところを見てください。

```javascript:store/store.js
import {
  createStore as reduxCreateStore,
  combineReducers,
  applyMiddleware,
  compose
} from "redux";
import { routerReducer, routerMiddleware } from "react-router-redux";
import todoReducer from "../reducers/todo";
import persistState from "redux-localstorage";



export default function createStore(history) {
  return compose(persistState())(reduxCreateStore)(
    combineReducers({
      todo: todoReducer,
      router: routerReducer
    }),
    applyMiddleware(
      routerMiddleware(history)
    )
  );
}
```



#感じたこと

今回この記事を書いたのは自分が実際にreduxを用いて開発する中でデータを永続化させることに苦戦したからです。
いろいろ調べた結果redux-localstorageを使うのが一番簡単でわかりやすいのではと感じました。


以上です。参考になれば幸いです。