2019/11 読んだ本まとめ

読んだ本について振り返る

なぜ科学はストーリーを必要としているのか──ハリウッドに学んだ伝える技術

博士課程を修了したにも関わらずハリウッドで映画監督になろうとしている著者が、科学者がハリウッドに習うべきことを記した本。
論文やこのサイトの記事などを書くときに参考になりそうな内容が詰まっていた。

基本的にはABT(And, But, Therefore)を繰り返すときに読者にわかりやすい文書が書けるようになるという内容だった。
内容は一つのことを繰り返している印象だったけど、その一つのことが結構説得力がある内容だった気がした。
最近は文書を書くときに気にかけている。

硬めの文章を書きつつ、説得感をもたせたい人におすすめ
自分は文章を書いているうちに何を書いてるかを忘れちゃうので、この本は結構参考になった。

スタンフォード式 人生デザイン講座

スタンフォードで教えられているライフデザインの講義の内容をまとめたもの。
内容についてはなるほどなーと思わされるものが結構あった。
しかし、読んでから1ヶ月くらい経ったけど講義の内容があんまり出来ていない。
なので、もう一回読み直しながら講義の内容をやろうと思っている。

結構人生をどう行きていこうという人にはおすすめ。

「ついやってしまう」体験のつくりかた――人を動かす「直感・驚き・物語」のしくみ

任天堂出身の著者がなぜゲームがこれほどの没頭感を生み出しているのかについて仕組みを解説した本。
僕は基本的には参考文献とかがしっかりしていない本はあんまり読まないけど、友達が面白かったと言っていたので読んでみた。

マリオの例などは面白くて、マリオの操作方法は誰も教えてくれないのに誰でも操作方法が分かるという設計になっていた。という説明は目から鱗の話であった。
ストーリーとかのデザインをする人は結構読んでおくと面白いかもなーと思った。

SINGLE TASK 一点集中術――「シングルタスクの原則」ですべての成果が最大になる

マルチタスクではなく、シングルタスクに専念することによって効率的に仕事を終わらせられるという本。
マルチタスクが良いと思っている人にはぜひとも読んでほしいなという本。
自分は結構知っている内容があったので、再確認という感じ。

シングルタスクは良いとわかっているが、なんやかんやで他のことをやりながら作業してしまうという事があるのでたまに読んで意識しておきたいなあと思った。
内容は是非読んでくださいな。

実践Rust入門 [言語仕様から開発手法まで]

プログラミング言語であるRustの入門書。
Rustは公式ドキュメントがしっかりしているので正直買わなくてもなんとかなるかなと思ってずっと買わずにいた。
しかし、この本を読んで今まで買わずにいたことを後悔するくらい良い本だった。
この本を読んだことがないRust入門者はぜひとも読んでほしい。

最初の方も結構良かったけど、7~10章あたりがすごく参考になった。
今でもRustでプログラミングをするときは結構参考にしている。
プログラミングをしているときによく読み返したくなるので、Kindleで買ったのは正解だったなと思った。

11章のActixの例は、新しいバージョンが全然違ってなかなか進めづらかった。
現在はRustいAsync・Awaitが追加されているらしいので、そこら辺は自分で調べながらやる必要があると思う。

テスト駆動開発

有名なTDDの説明をしている名著。
テスト駆動を例を示しながら進めている。
著者がテスト駆動開発で開発を行いながら書いているので著者がどういう思考で進めながら開発をしているのかというのが進めながら分かる。
また、後半ではテスト駆動開発に有用なデザインパターンやTDDの歴史などが書いてあり結構面白かった。
一度目は特に写経などはせずに読み進めたが、読み終えたときに写経すればよかったなあと思って2周目に突入中。

TDDのことを誤解していたなあと思って、テスト駆動開発素晴らしいという気持ちがすごい。
今後はTDDを取り入れて開発を行いたいと思った。

最後に

以上11月はこんな感じで本を読みました。
自分は本にハマる時期とプログラミングにハマる時期が交互に来るらしく、前半は普通に読書を後半はプログラミング関係の本を読むという生活でした。
あと、論文も5本くらい読んだ気がする。
12月に入ってからは本ではなくGoなら分かるシステムプログラミングにハマっていてしばらくはこれをやるかなあという感じ。
現在は2冊くらい本が溜まっている状態なので来年に持ち越さずに読み切りたいなあと思っています。

とりあえずおすすめとしては

非プログラミング系ならSINGLE TASK、プログラミング系ならテスト駆動開発という感じです。

efm-langserverの設定について今更ながらやってみた(Go言語)

efm-langserverが出たときにめっちゃ便利そうやんーと思っていたんですが、色々ハマったりして時間もなかったのでしばらく放置していましたが、ついに設定してみました。

efm-langserverとは

General purpose Language Server that can use specified error message format generated from specified command. This is useful for editing code with linter.

efm-langserverは特定のコマンドから生成されるエラーメッセージに特化したLanguage Serverです。
例えばlinterとかが例に入ります。

導入例

efm-langserverを導入する利点は以下のような点が挙げられると思います。

  • 言語のLSが存在しないが、Linterは存在する場合
  • LSはあるが、Linterを使いたい場合

1つ目の利用方法はefm-langserverのREADMEを見てもらえば出来ると思うので、今回は下について考えながら設定していきたいと思います。

なぜefm-langserverを利用するか?

linterのエラーを出力するプラグインとしてはALEが有名だと思います。
ALEはすごく便利なプラグインで、Linterさえ導入すればVimにエラー文などを出力してくれます。
しかし、便利な反面プラグインとして大きすぎるという欠点があります。

そこで今回はvim-lspだけで全てが完結するような設定を目指します。

早速設定

今回はGo言語の利用例について考えながらやります。
Go言語ではgoplsというLanguage Serverを使います。
また、efm-langserverで使うlinterとしてgolintを使用します。

早速設定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if executable('gopls')
au User lsp_setup call lsp#register_server({
\ 'name': 'go',
\ 'cmd': {server_info->['gopls']},
\ 'whitelist': ['go'],
\ 'workspace_config': {'gopls': {
\ 'usePlaceholders': v:true,
\ 'completeUnimported': v:true,
\ }},
\ })
endif

if executable('efm-langserver')
augroup LspEFM
au!
autocmd User lsp_setup call lsp#register_server({
\ 'name': 'efm-langserver',
\ 'cmd': {server_info->['efm-langserver', '-c='.$HOME.'/.config/efm-langserver/config.yaml', '-log='.g:log_files_dir.'/efm-langserver.log']},
\ 'whitelist': ['go'],
\ })
augroup END
endif

1つ目がgoplsの設定で2つ目がefm-langserverの設定です。

そして、~/.config/efm-langserver/config.yamlに以下のような設定を行います。

1
2
3
4
5
languages:
go:
lint-command: 'golint -set_exit_status=1'
lint-formats:
- '%f:%l:%c:%m'

これで両立可能です!
以下の画像が実際の様子です。
関数のHellohelloがタイポしているので起こっているエラーがgoplsのエラーです。
Helloという公開関数に対してコメントを書きなさいと怒られているエラーがgolintのエラーです。
ちゃんと設定できてますね!


これで終わりでもいいのですが、efm-langserverについての補足を少しだけします。

linterのexitステータスは1である必要がある

efm-langserverはexistステータスに以上がある場合にエラーをlinterの内容を出力する設定になっています。
golintは何故かexitステータスがデフォルトだと0になるようになっているみたいなので、-set_exit_status=1というように指定する必要があります。

lint-formatsを設定する

lint-formatsはefm-langserverの設定でデフォルトだと、%f:%l:%m%f:%l:%c:%mの2つが設定されています。
この2つでパースするとgolintは両方の設定に成功してしまします。
そして、Diagnosticsが2つ送られて来てしまい、Diagnosticsが2つ存在してしまいます。
なので、lint-formats:で正しい方のフォーマットを指定しました。

ちなみに、エラーformatはVimのエラーフォーマット構文を使っているみたいなので、こちらを参考にしてください。

まとめ

goでgoplsの他にgolintのエラーも出るようになった!

( 2019/12/06 追記

11月末に取り込まれた変更によってexitステータスが0でも行けるようになりました。
その場合以下のような設定でいけます。

1
2
3
4
5
6
languages:
go:
lint-command: 'golint'
lint-ignore-exit-code: true
lint-formats:
- '%f:%l:%c:%m'

読書内容を覚えるためのライフハック作った

僕はライフハックが結構好きで、自分でも色々考えてはあれやこれやと試したりしてます。
今回はその中でプログラミングを用いたライフハックが今の所結構いい感じなのでブログにしたためようと思います。

作ったものの背景

僕はかなり読書が好きで、しばしば自分の貯金を圧迫するほど本を買ったりしています。
しかし、長年の悩みとして本で読んだことをすぐに忘れてしまうということがありました。様々な本を読んでも同じ悩みを持っている人は多いように思います。そこでは覚える方法として、2度読むとかメモを取るといった手法が提案されてたりしました。しかし、どの手法も僕にはしっくり来ませんでした。
そこで自分にしっくり来るようなアプリを作ってしまおうと思い立ち、作ることにしました。

作る上で参考にしたものや考えたこと

今回作る上で最も参考になったのが「Learn better」という本です。
この本はどうすれば学びを深めることが出来るのかということに焦点を当てて、科学的に書いた本です。
その中で僕が気になったのが検索練習という方法です。
検索練習とは、学んだことに対して自分に問いかけてそれを思い出すという練習方法です。

検索練習が気になった理由としては以下の実験があります。
その実験では文章を覚えるのに、4回同じ文章を読んだグループと1回だけ文章を読んでその後3回思い出すというグループでどちらのほうが覚えているかについて数日後にテストを行いました。
その結果思い出す試みをしたグループの方がはるかに文章を覚えていました。
つまり、2度読みするより1度読んで何回か思い出すためのテストを行ったほうがよいという結果でした。

また、僕も受験勉強のときは、参考書を読むよりも実際に問題を解いた方が理解が深まりやすいという実感を持っていたのも気になった理由に入ると思います。

ここで、それに特化したアプリがありそうだなと思って調べたところANKIというアプリが見つかりました。
このアプリは忘却曲線に沿って、最適なタイミングで問題を出してくれるというアプリです。
僕もまあアプリをがむしゃらに作るよりは既存のものを使った方が効率的なので、ANKIを試したみました。
しかし、僕はこのアプリは全然長続きしませんでした。
毎日ANKIを開くというたった1ステップが続かなかったのです。
この毎日復習をするという習慣をどうにかして作る必要があります。

そこで、僕は自分が毎日行っている習慣に復習を組み込むといいんじゃないか?という結論に至りました。
これは科学的にも証明されており、新しい習慣を作るときに既存のものに組み込むという手法はよく使われています。
(参考文献はまた探しておきます。)
それで僕は毎日行っているLINEを開くという習慣に復習を行うという行動を組み込むことにしました。
LINEなら毎日必ず確認するし、僕はLINEに未読のものがあるのが許せないたちなので、とりあえず問題を開くというところまでは習慣になるだろうと思いました。

(ちなみに、習慣について深く知りたいという人には「小さな習慣」という本がおすすめです)

作ったもの

作る工程はとりあえずさておき、下の画像が完成したものです。
LINEではAPIが公開されており、自分の好きなアカウントを作成することができます。
アイコンや背景もカスタマイズ出来ると思うんですが、めんどくさくてやってません。
「ガリ勉くん」という名前も適当につけました。


僕は毎日以下のような手順で問題を解いています。

  1. 毎朝問題がある決まりに従って出題されます。(今の所毎日5問ずつ)
  2. 出題された問題に対して、自分なりの答えを考えます。
  3. 「答えを見る」ボタンを押します。
  4. 答えと一緒に「正解・不正解」ボタンがきます
  5. もし、自分の答えがあっていたら正解ボタン・間違っていたら不正解ボタンを押します
  6. これを全問題に対して行います。

こうすることで、毎日ランダムに問題について思い出すことができます。
問題は以下のようにGoogleスプレッドシートに書いたものがランダムに出される用になっています。


これで本を読んだときに、「これは覚えときたいなー」と思った内容をスプレッドシートに問題形式に書いておけば、毎日問題が届けられるわけです。

終わりに

今回は自分がどのようなものを作ったかについて書きました。
現在のところ、毎日続けて問題を解いているしかなり覚えてきたなーと思うようになってきました。
また、スプレッドシートにまとめることで見返したときに自分結構頑張ってるなという感じがして嬉しいです。

しかし、問題を出す決まり(アルゴリズム)はめちゃくちゃ適当に書いてます。
また、不正解ボタンを押したときに何の反応もありません。
不正解だったときに、もっと自分が悔しくなるような工夫を設ければもっと記憶定着率は上がる気がします。

今回は一応形になりつつ、復習にもなっているのでブログにしたためてみましたが、これからもっと改良していきます。
また、プログラミング的な内容については後日ブログで書こうかなと思っています。

もし、どういうふうにやっているか気になる人がいれば以下のリポジトリを参考に見てください。
https://github.com/kitagry/go-learner

hexoをGitHub Pagesで使うための設定

せっかくなのでブログを1つくらい更新しようかなと思います。

現在僕はGitHub Pagesとhexoを使ってページを公開しています。
まあ、探せばやり方はいくらでもあると思うのですが、意外と検索しても出てこなかったので僕の設定の備忘録として残しておきます。

hexoとは?

hexoとは静的サイトジェネレーターです。
基本的にはマークダウンファイルを書くだけでブログを更新できます。
また、テーマなども複数ありかなり応用が効きそうです。
(僕自身は現在hexo3日目なので、あまり良くわかっていませんが。。)

Github Pagesについて

Github PagesとはGithubにプッシュするだけでウェブサイトを表示してくれるサービスです。
無料でWebページが作成出来るのでかなり便利です。
ただし、ページを公開するための制約が何個かあります。

  1. 静的ファイルしか公開することができない
  2. masterブランチまたはgh-pagesブランチにあるファイルを公開する

つまり、静的ファイルを公開する場合には、サーバーやドメインを借りるという手間を削減出来るのでかなり良いと思います。

デプロイをするときの問題点

実はhexoではマークダウンで書いた後に、hexo generateと実行することで静的ファイルを子ディレクトリの中に作成します。そして、多くのGithub Pagesはmasterブランチの /docs 以下をウェブサイトとして公開することができます。つまり、hexoの _config.yaml を以下の用に書き換えればいいわけです。

1
2
3
4
5
6
7
8
9
# Directory
source_dir: source
public_dir: docs # <-- ここをdocsにする
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render:

それを masterブランチかgh-pagesブランチにプッシュして、設定で変更すればそのまま公開することができます。

しかし、僕のサイトのような{username}.github.ioというリポジトリでは上の方法が使えません。何故か、先程のようなリポジトリ名ではmasterブランチに直接静的ファイルを置かないとGithub Pagesを使えないらしいのです。

したがって、僕はこの理不尽な仕様に対応するためにちょっとしたコードを書きました。このときに得た知見をブログで共有しようかなと思います。もし、hexoとGithub Pagesで自分のサイトを運用したいなという人がいれば、参考にしていただけると幸いです。

解決策を書く前に

実は上の仕様は以下の簡単なステップで回避することができます。しかし以下の方法には少しだけ欠点があります。
hexo deployとはhexoのウェブページをデプロイするための機能です。今回は _config.yml の該当箇所を以下のように直せば動かすことができます。

1
2
3
4
5
6
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repo: git@github.com:{your github name}/{your github name}.github.io.git
branch: master

これを書いた後、 hexo deployと入力することで、Githubのmasterブランチに静的ファイルをプッシュしてくれます。この問題点としては、つまりマークダウンファイルなどのhexoに関係する設定ファイルをGitに残すことができないということです。僕としてはこれは結構辛い問題で、hexoの設定ファイルのバックアップが取れないのでもしものときに設定ファイルを引き継ぐことができません。

おそらく賢い人なら「じゃあ、masterブランチにdeployをしておいて、他のブランチでバックアップを取っておけばいいじゃん」ってなると思います。そうです。つまりウェブページを公開する用とソースコードを管理する用のブランチを分けてしまおうというわけです。これなら、バックアップも取れます。しかし、これだとバックアップとデプロイをいちいちやらないと行けなくなります。これは結構面倒でデプロイを忘れたりしてしまうことが頻発してしまいそうです。そこで、僕はバックアップをしたら自動でデプロイをするような仕組みを作成しました。(無料です。)

ではやっと解決策

今回のやり方は以下の記事を参考にしました。僕の説明が不十分だと感じたら以下の記事を見てみてください。

ではやっと本題へ。

今回の方針としては、masterブランチとは別に deployブランチというものを用意してそのブランチへプッシュされたら、Travis CIで hexo deployを実行するという単純なものです。

hexo deployの設定については先程の hexo deployを使う通りに _config.yml を変更してください。

Travis CIの設定

Travis CIの設定については3つのステップがあります。

  1. masterブランチにプッシュするための公開鍵の用意
  2. travis CIで使うための秘密鍵の用意
  3. travis.ymlの設定

これらを順に解説していきます。

masterブランチにプッシュするための公開鍵の用意

まずはmasterブランチにプッシュするためのssh keyファイルを用意します。
以下のコマンドを {username}.github.ioディレクトリの下で実行してください。

1
$ ssh-keygen -t rsa -N '' -f deploy_key

これを実行することで、 deploy_key(秘密鍵)と deploy_key.pub(公開鍵)の2つができます。
これらは間違ってコミットしないように .gitignoreに登録しておきましょう。
では、deploy_key.pubをGitHubに登録しましょう。

まず、GitHubの{username}.github.ioの設定ページへ行ってください。そこに、 Deploy Keysというタブがあると思います。そこへ行って、add deploy keyというボタンをクリックします。このフォームへ先程のdeploy_key.pubの中身を登録します。必ず Allow write accessにチェックをつけてください。

さあ、これで公開鍵の登録は終了しました。
次にTravisの方で秘密鍵を使うための設定を行っていきます。

Travis CIで使うための秘密鍵の用意

まずはtravisのCLIを導入していきます。

1
2
3
4
$ gem install travis

# Githubアカウントでログインする
$ travis login

次に、先程作成した秘密鍵を暗号化し、travisに設定します。

1
$ touch .travis.yml && travis encrypt-file ./deploy_key --add

これを実行すると deploy_key.encファイルと .travis.ymlが作成されているのが分かると思います。
次に .travis.ymlファイルの中を見ると以下のようなコードが挿入されていると思います。

1
2
3
before_install:
- openssl aes-256-cbc -K $encrypted_77965d5bdd4d_key -iv $encrypted_77965d5bdd4d_iv
-in deploy_key.enc -out ./deploy_key -d

これで秘密鍵の設定は完了しました。
** deploy_key.encファイルをGitで管理するということを忘れないでください。**
.encファイルは暗号化されているのでGithubにプッシュしても大丈夫です。
では最後にtravisの設定をしていきましょう。

travis.ymlの設定

.travis.ymlの設定は以下の通りです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sudo: false
language: node_js
node_js:
- 12
cache: npm
branches:
only:
- deploy
before_install:
- openssl aes-256-cbc -K $encrypted_77965d5bdd4d_key -iv $encrypted_77965d5bdd4d_iv
-in deploy_key.enc -out ./deploy_key -d ### ここは先程のコードです。
- eval "$(ssh-agent -s)"
- chmod 600 ./deploy_key
- echo -e "Host $SERVER_IP_ADDRESS\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
- ssh-add ./deploy_key
script:
- hexo generate
- hexo deploy

これらの簡単な解説をします。
branches: はどのブランチでこのtravisを実行するかを設定しています。今回の場合は deployブランチにプッシュされた場合にのみmasterへデプロイするという宣言を行っています。

次に before_install についてです。このコードはsshキーの設定を行っています。最初の openssl ....は先程作成した deploy_key.encを復号化するためのコマンドです。それ以下では復号した deploy_keyをsshキーとして使う設定を行っています。
before_installは以下の scriptの前に実行されます。

最後に scriptについてです。といってもこれについては解説する意味もなさそうですね。笑
ただ、hemlにコンパイルを行い、それらをdeployするだけです。

自動デプロイしてみる

それではここまでが終わったら、deployブランチにプッシュしてみましょう。
そうすると travisのページを確認するとCIが走っているのが確認出来ると思います。
もし、ログインしていない場合は travisにGithubアカウントでログインしてみましょう。

もし、CIがうまくはしればmasterにデプロイが完了しているはずです。
お疲れさまです。

最後に

今回は自分がこのブログを構築するためにした設定についてのブログを書いてみました。
もし、読んでいる人の参考になればとても嬉しいです。

もしバグが起こった場合

Travisで以下のようなエラーが起った場合についてです。

1
2
iv undefined
The command "openssl aes-256-cbc -K $encrypted_77965d5bdd4d_key -iv $encrypted_77965d5bdd4d_iv -in deploy_key.enc -out ./deploy_key -d" failed and exited with 1 during .

これについてはこのissueが参考になりました。
僕の場合の解決方法です。

1
$ travis encrypt-file ./deploy_key --pro

これを実行したときに出てくる openssl ... をtravis.ymlの同じ部分を置き換えて、新しくできた deploy_key.enc と一緒にプッシュしてみましょう。