Shiopon Labo

しおぽん(@shiopon01)の個人ブログです。

VSCodeの設定・拡張機能を環境間で共有する

追記

こんなものがあるらしい

github.com

本題

VSCodeの設定を環境間で共有するのはまあまあ面倒くさい(自分はMac/Ubuntuで設定を共有している)。この記事ではそのあたりについて言述する。

共有したい設定

VSCodeで共有しておきたい設定は次の2つ。

settings.json はOSによって保存場所が違うみたいで、例えば UbuntuLinux) だと .config の下とかに保存されているが、 Mac だともっと深いところに保存されている。

  • Windows %APPDATA%\Code\User\settings.json
  • Mac $HOME/Library/Application Support/Code/User/settings.json
  • Linux $HOME/.config/Code/User/settings.json

setting.json は bashrc のように dotfiles のリポジトリ等でファイルを管理して、上記の場所にシンボリックリンク等を張れば共有することができるので、難しくはない。

ln -s $HOME/rc/settings.json $HOME/.config/Code/User/settings.json

code.visualstudio.com

曲者なのが拡張機能で、拡張機能本体の容量がまあまあ大きいのでそのままリポジトリ等で管理するわけにはいかない。(できないこともないが、 push や clone にめっちゃ時間がかかったりする)

そのため、拡張機能拡張機能の名前のリストのみ管理することにする。これには code --list-extensions コマンドが利用でき、これでインストールされている拡張機能のリストを出力することができる。(Maccode コマンドを使うのに少し設定が必要らしい https://code.visualstudio.com/docs/setup/mac

$ code --list-extensions
bungcip.better-toml
codezombiech.gitignore
Compulim.vscode-clock
dbaeumer.vscode-eslint
...

この出力結果をファイルに保存してリポジトリとかで管理して共有する。

code --list-extensions > $HOME/rc/extensions

このファイルから1発でインストールできたらいいけど、ドキュメント見たかんじ欲しいコマンドは無さそう…。

code.visualstudio.com

出力した拡張機能リストからのダウンロードには code --install-extension を使う。ただし、ドキュメントにあるように1つづつしかダウンロードできないため、ファイルの行をループして1つづつインストールしていく。このスクリプトも extensions のファイルと一緒に管理しておこう。

while read ext; do
  code --install-extension $ext
done <$HOME/rc/extensions

一応、実行したらこんなかんじ。

$ sh install.sh 
Found 'bungcip.better-toml' in the marketplace.
Installing...
Extension 'bungcip.better-toml' v0.3.2 was successfully installed!
Found 'codezombiech.gitignore' in the marketplace.
Installing...
Extension 'codezombiech.gitignore' v0.6.0 was successfully installed!
Found 'compulim.vscode-clock' in the marketplace.
Installing...
Extension 'compulim.vscode-clock' v0.0.1 was successfully installed!
Found 'dbaeumer.vscode-eslint' in the marketplace.
Installing...
...

まとめ

環境の共有には次の手順が必要。

$HOME/rc/vscode/settings.json$HOME/rc/vscode/extensions が存在している状態なら次のスクリプトでなんとかなる。(Windowsなし)

# setting.json

if [ "$(uname)" == 'Darwin' ]; then
  SETTINGS_PATH="$HOME/Library/Application Support/Code/User/settings.json"
elif [ "$(expr substr $(uname -s) 1 5)" == 'Linux' ]; then
  SETTINGS_PATH="$HOME/.config/Code/User/settings.json"
elif [ "$(expr substr $(uname -s) 1 10)" == 'MINGW32_NT' ]; then                                                                                           
  echo "Windows is not supported."
  exit 1
else
  echo "Your platform ($(uname -a)) is not supported."
  exit 1
fi

ln -s $HOME/rc/vscode/settings.json $SETTINGS_PATH

# install extensions

while read ext; do
  code --install-extension $ext
done <$HOME/rc/vscode/extensions

echo 'done.'

ドラゴンクエストビルダーズ2

もう1月7日、そして仕事初めです。時間が経つのが早すぎる。

さて今年の自分の正月は、Switch版 ドラゴンクエストビルダーズ2 に溶かされたと言っても過言ではありません。1月2日に購入してから1月6日まで、起きてる殆どの時間をビルダーズ2で消化しました。ときには1日14時間近くやってたり…。

ドラゴンクエストビルダーズ2

簡単に言うと、Minecraftドラクエ版にストーリーを付けたゲーム。

Minecraftライクなゲームなだけあって寄り道しようと思ったらいくらでも寄り道できるゲーム性、長いストーリー、豊富なやりこみ要素など、時間泥棒要素が詰め込まれたゲームです。1度初めてしまうと自分の意思ではゲームを終了できなくなるほど面白くて、永遠にプレイできそう。

ストーリーは主人公が島をめぐり、モノづくりの心を失った住人をモノづくりに目覚めさせて一緒に島を開拓するというもの。プレイしてるうちに、住人といっしょに自分もモノづくりに目覚めていくことを実感できます。死であるとかそういったダークなテーマもところどころ差し込んでくるのはドラクエっぽい。

(これやってると 少年ヤンガスと不思議のダンジョン を無性にやりたくなってくる。あとドラクエⅡも)

今年初買いの ドラゴンクエストビルダーズ2 は圧倒的に良ゲーで人にオススメできる作品でした。SwitchかPS4を持ってる人はぜひ時間を溶かしてみてください。

https://www.amazon.co.jp/dp/B07GWVTKBC/

その他

焼肉初めは1月4日。

この日はスタバの ごまごまごまフラペチーノ も飲みました。スタバ初め。

f:id:shiopon01:20190105051545j:plain

MacOSのクリーンインストール後にはやっぱりbrew bundle

年末にMacBook Proクリーンインストールしたので、そのついでの記事。さらにそのついでに、自分のBrewfileを晒している。

Homebrew

HomebrewはMacユーザーなら知らぬものはいない、有名なパッケージマネージャー。

ふつうパッケージをインストールするときは brew install を使うが、Brewfileを使って複数パッケージをまとめてインストールすることもできる。RubyでのGemfile、Nodeでのpackage.jsonみたいなもので、使ってない人はとりあえず使ったほうが良い。

とりあえずHomebrewのインストール。公式のやつをコピペしよう。

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

brew.sh

この後すぐBrewfileを用意して brew bundle を行う。

自分が普段使っているBrewfileはこちら。こう見るとぜんぜん使ってないものばっかりだ。(人のこういうファイルを見るのが好きなのでみんな晒してくれ)

gist.github.com

追加で brew install したくなった時は気持ちをぐっとこらえ、このファイルに追記して brew bundle を行う。

使い方としては、このファイルをローカルに落として brew bundle を実行するだけ。App Storeのアプリを落としてくれる mas では初回の警告が出るかもしれない。また、 ## mas kakin 以下の行は課金アプリで購入していないと普通にエラーを吐くと思うので、そのまま使う場合はコメントアウトするなりしてもらいたい。

$ curl https://gist.githubusercontent.com/shiopon01/a584cc20552cf3eed3012865c0b020c5/raw/298d9ff2a48783ac64ac4f2bd5c40177213b47c3/Brewfile > Brewfile
$ brew bundle

インストール後はインストールした Alfred 3Karabiner-Elements などいくつかの常駐アプリの起動と設定、 nodenvgoenv でのプログラミング言語インストールを行う。

ショートカット

SkitchのスクショのショートカットがMacOSのものと被るので注意。自分はMacOSの方をOFFにしている。

f:id:shiopon01:20190102024539p:plain

Dock

Dockは左派です。

f:id:shiopon01:20190102025600p:plain

明けましておめでとうございます。抱負など

明けましておめでとうございます!

1995年生まれ男の自分は今年は猪年の年男でもあり、本厄の年でもあります。厄年でもあるので慎重に、しかし猪年らしく 一意専心 に何事にも取り組んでいける年にできたらなと思います。

ちなみにFGO福袋は酒呑童子が出ました。はじめての★5アサシンありがとう!

f:id:shiopon01:20190101013631j:plain

新年の抱負

抱負なのであんまり公言するものでもありませんが、2019年は何かまじめなサービスをリリースすることを考えています。ユーザー○人獲得とかではなくて、単純にリリースすることが目標です。

これは実は2018年後半から考えていて、せっかく個人のサービスなら流行りのアーキテクチャとか技術をもりもり積んでいこうということで、そういうインプットをなんやかんや去年からやっています。(勉強すればするほど学ばないといけないことが増える辛さ)

具体的に自分がずっと学生時代から作りたいともんもんと考えていたアプリは次の2つ。

どちらも設計の段階で他のアプリの劣化のように思えてきて何度か挫折してきたものです。

学生の頃はOICのメディアフロンティアのためにRailsとかでこれらのプロトタイプを作成したりしましたが、こういう挫折もあって方向性を見失い、結局お蔵入りとなったり…。

どちらも大きくシェアを取っているアプリがすでに存在している分野でもあるので、今更同じ土俵にあがるのも…と気負いするところでもありますが、まあ個人アプリなんで、そのあたりは気にせず良い所はパクる精神で今年はゆるゆる作っていけたらなと思います。

他の抱負で言うと、最近練習し始めた絵描きでマシな絵を書けるようになるとか、結局学ぶだけ学んで大したものを生み出せてないAfter Effectsで映像作品を作るなど。文字だけでなく動画や音声でのアウトプットを行ってみたいという気持ちもあるので、そういうのもあります。

あ、あとIIDXで十段を取りたい!(PEN以来まともにやってないブランクもあって現在悲しみの1曲目落ち)

f:id:shiopon01:20190101021149j:plain

以下まとめです。2019年の shiopon01 の活躍にご期待ください。

  • サービスをリリース
  • After Effectsで映像作品を作る
  • マシな絵を書けるようになる
  • 映像や音声でのアウトプット手段の模索
  • IIDX十段取得
  • TOEIC 500点
  • etc(考え中)

(絵の練習はPixivのSenseiがまじで良いです)

sensei.pixiv.net

2018/1/1のステータス

  • 身長:174cm
  • 体重:77.2kg
  • TOEIC:310点くらい

今年は体重を減らすか、キープか増えるにしても筋肉で……が目標…。

Node.jsの初見殺し (x) => (y) => { ... }

引数定義する部分が2つある関数定義、まさに初見殺し。

const a = (x) => (y) => {
 console.log(x * y)
}

ただでさえ function (x) { ... }シンタックスシュガーみたいな (x) => { ... } (アロー関数)があったりするのに、アロー関数には引数定義が2つ付いた (x) => (y) => { ... } みたいな定義方法もある。調べても情報が多くないように思うし、そもそも調べ方もよく分からないかんじがある。この記事はこれの話。( this とかには触れない)

カリー化

さて、結論から言うとこれは カリー化 と呼ばれるもので、先述した関数定義は次の構文のシンタックスシュガーみたいなものである。カリー化についてはいろいろ記事があると思うので 部分適応カリー化 で検索してもらえたらと思う。

const a = function (x) {
  return function (y) {
    console.log(x * y)
  }
}

これは見たとおり、定義した a は引数 x を受け取って新しい関数を生成する関数だ。ここで生成される関数は最初に渡される x を保持しているので、 function (y) の中でも x を利用できる。

実際に 2 を渡して実行してみても、関数が生成されていることが分かる。この関数はもちろん 2 を保持している。

$ node
> const a = (x) => (y) => {
... console.log(x * y)
... }
undefined
> a (2)
[Function]

生成された関数は引数 y を受け取って console.log するだけのものだ。計算に使う x は最初の a (2) で渡したものが引き継がれている。

次の2つは呼び出し方は違うが、結果は同じものである。これは生成された関数に 3 を渡してそのまま実行するパターン。

> a (2)(3)
6

そしてこれが、関数を一旦変数にいれてから 3 を渡して実行するパターン。そのまま実行するパターンではカリー化するメリットが無いので、ふつうはこうやって使う。

> const b = a(2)
[Function]
> b (3)
6

ちなみに関数定義ではいくらでも引数の定義をアローで繋げることができて、つなげた分だけ階層を深くすることができる。好きなだけ繋げるべし。

> const c = (x) => (y) => (z) => {
... console.log (x + y + z)
... }
undefined
> c (1)(2)(3)
6

使い方

この構文を使うタイミングについて少し言述する。

カリー化とはつまり、新たな関数を生み出して処理の共通化を行うためのアプローチだ。関数を生成する際に様々な設定値などを渡すことで、最適な新たな関数を生み出すことができる。この結果、何度も呼び出すが決め打ちの引数が入る煩わしい関数のをスマートに定義することができるようになる。

ありがちだが、例えば次のプログラムは消費税を計算するものだ。ここでは calcJPTax という日本の消費税を計算する新しい関数を生成している。この関数を生成する際に渡す数値を変えて複数定義すれば、国に対応した消費税計算関数を簡単に作成することができる。

const product = (tax) => (value) => {
  return (value * tax)
}

const calcJPTax = product (1.08)

console.log(calcJPTax(100)) //=> 108

少し難しいが、カリー化する際に関数を渡すこともできる。これを使うことで好きな処理を関数に差し込むことができる。

これはコンソールに値を出力する関数で、最初に渡す関数の返り値によって内容を変更できる。

const say = (func) => (value) => {
  return console.log(func(value))
}

const sayHello = say ((name) => {
  return 'Hello, ' + name
})

sayHello('Mario') //=> 'Hello, Mario'

などなど。様々な場面で使いみちがある。

E: パッケージ ○○ を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。

E: パッケージ virtualbox-6.0 を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。

こいつに時間食われたのでシェア。

やりたいこと

こいつを消したい。

$ sudo dpkg -l | grep virtualbox-6.0
iFR virtualbox-6.0        6.0.0-127566~Ubuntu~bionic        amd64    Oracle VM VirtualBox

minikube start したらVirtualBoxでエラーが出たので、 dpkg -i virtualbox〜〜 とかやってたらますますおかしくなったパターン)

いけたやつ

もし debconf: DbDriver "config": /var/cache/debconf/config.dat is locked by another process: Resource temporarily unavailable のエラーが出たらとりあえず rm /var/cache/debconf/*.dat したらなんとかなる。

自分の場合はこれでいけた。

$ sudo rm /var/cache/debconf/*.dat 

$ sudo dpkg -P --force-remove-reinstreq virtualbox-6.0
dpkg: 警告: --force が有効なので、問題を無視します:
dpkg: 警告: パッケージが非常に矛盾した状態に陥りました。
削除を行う前にこのパッケージを再インストールすべきです
(データベースを読み込んでいます ... 現在 223431 個のファイルとディレクトリがインストールされています。)
virtualbox-6.0 (6.0.0-127566~Ubuntu~bionic) を削除しています ...
virtualbox-6.0 (6.0.0-127566~Ubuntu~bionic) の設定ファイルを削除しています ...
dpkg: 警告: virtualbox-6.0 の削除中、ディレクトリ '/usr/lib/virtualbox/sdk/bindings/xpcom/python/xpcom/server' が空でないため削除できませんでした
dpkg: 警告: virtualbox-6.0 の削除中、ディレクトリ '/usr/lib/virtualbox/sdk/bindings/xpcom/python/xpcom/client' が空でないため削除できませんでした
shared-mime-info (1.9-2) のトリガを処理しています ...
hicolor-icon-theme (0.17-2) のトリガを処理しています ...
desktop-file-utils (0.23-1ubuntu3.18.04.2) のトリガを処理しています ...
mime-support (3.60ubuntu1) のトリガを処理しています ...

一応、こうしてVirtualBoxをインストールできたのであった。

$ sudo dpkg -i virtualbox-6.0_6.0.0-127566_Ubuntu_bionic_amd64.deb

Minikubeも動いた。

$ minikube start
Starting local Kubernetes v1.10.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.

いけなかったやつ

$ sudo dpkg -r virtualbox-6.0
dpkg: パッケージ virtualbox-6.0 の処理中にエラーが発生しました (--remove):
 パッケージが非常に矛盾した状態に陥りました。
削除を行う前にこのパッケージを再インストールすべきです
処理中にエラーが発生しました:
 virtualbox-6.0
$ sudo dpkg -p virtualbox-6.0
dpkg-query: パッケージ 'virtualbox-6.0' はまだ利用可能でありません
アーカイブファイルを調べるためには dpkg --info (= dpkg-$ sudo dpkg -p virtualbox-6.0
dpkg-query: パッケージ 'virtualbox-6.0' はまだ利用可能でありません
アーカイブファイルを調べるためには dpkg --info (= dpkg-deb --info) を、
その内容一覧を表示するには dpkg --contents (= dpkg-deb --contents) を使います。deb --info) を、
その内容一覧を表示するには dpkg --contents (= dpkg-deb --contents) を使います。
$ sudo apt install --reinstall dpkg
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
E: パッケージ virtualbox-6.0 を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。
$ sudo apt install -f
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
E: パッケージ virtualbox-6.0 を再インストールする必要がありますが、そのためのアーカイブを見つけることができませんでした。

炎上プロダクトと、従事したエンジニアの心情

今年は初めて受託開発の炎上を経験したので年が明ける前にその時の心情を書き記しておこうと思う。あくまで従事したエンジニアの心情であるので、案件については言述していない。

本題

自分の経験した炎上はスケジュールが圧倒的に短くて発生したタイプの炎上だった。この記事ではスケジュールが短すぎた場合、エンジニアの心情はどういったものか、プロダクトはどうなるかを記述する。

スケジュール

とりあえず、納期や工数をマネージャー層が全て決定した状態でエンジニアに丸投げするのはやめよう。

ふつう案件にアサインされたエンジニアは要求仕様書から機能の洗い出しを行うが、この時点で 納期が短すぎるのでは? となった場合はその時点からマネージャーに対して 強い不信感 を抱き始める。(逆に、期間が長いと感じたらマネージャーへの好感度は上がる!)

納期を変えることはできないのでしぶしぶ開発は始めるが、実際に時間が足りなくなった時は クソみたいな見積もりをしたマネージャーの尻拭いをさせられている という考えが絶対に付きまとうので、精神上も良くない。そしてこの時のモチベーションは世界最低ランクだ。

この現象の対処法としては、やはりアサインが想定されるエンジニアも見積もりに参加させることが一番良いと思う。作業者自身もマネージャーと一緒に見積もりを行うことで、作業者に納期への納得感を与えることができるし、なにより技術を良く分かっていないマネージャーの適当なクソ見積もりを防ぐことができる。

この点からも、やはり現役エンジニア(実際の作業者推奨)を見積もりに参加させるのは必須と感じた。

プロダクトの品質

開発(プログラミング)に費やす時間の多くは アルゴリズムを考える 時間でもある。自分は特にその傾向が強く、一旦の実装をとりあえず作ってから綺麗なコードに書きなおすことが多い。

これは実際に案件のスケジュールが完全に遅れた状態になって分かったのだが、スケジュールが切羽詰っていると自分は製品を作るためのプログラミングではなく 帰るためのプログラミング を行うようになるらしい。

帰るためのプログラミングが何かというと、先述した アルゴリズムを考える 時間を大幅に省き、一旦の実装( HACK 的実装)のままどんどん機能追加を行うことだ。なんたって時間の余裕がないので、 綺麗なコードへの書き直し = 追加の残業 となる状態で自分はコードのリファクタリングまで行えなかった。なぜなら、絶対に残業はしたくなかったからだ。(結局時間が足りず、機能追加で残業や徹夜までしたが)

これがプロダクトの品質に悪いのは明白だが、エンジニアの精神状態にも大きなダメージを与える。コーディングする度に自分やチームメンバーのソースコードを見てリファクタリングしたい気持ちを抑え、「俺はこんな実装をしたいわけじゃないのに…」と思いながら新しい機能を追加していたあの頃は、きっとエンジニアとしては死んでいたのかもしれない。

プロダクトの品質はそのまま改修のしやすさにも繋がる。一時的な実装が多いということは、次に機能追加や改修の案件を担当した人に負債がのしかかるということだ。時間が無いなら仕方ないが、出来るだけ綺麗なコードを心がけたい…。

テスト

リファクタリングを行う時間が無いと言うことは、単体テスト結合テストのコードを書く時間も無いということだ。いや今回の場合、初めの頃はなんとかテストを書くスタイルだったが、度重なる機能追加と機能変更などの作業増加によって書く時間が明らかに無くなったと言ったほうが正しい。

今回で言うとテストチームがバグ出しを頑張ってくれたので、プロダクトとして最低限の品質は保障できた。中には単体テストをちゃんとやっていれば出ないようなバグも数あり、テストの大切さを改めて実感。(何よりも余裕を持ったスケジュールのほうが大事だけどな)

自分への影響

自分の精神的なストレス耐性は低いらしく、残業と徹夜はかなりしんどい思い出だった。

生きる活力がかなり削がれていたし、具体的には唇がよく切れるようになった。メロンパンを食べた時は、かじった部分が赤くなっていたくらいだ。

おわりに

この遅れが見積もりの失敗であれマネジメントの失敗であれ、どちらにせよ 遅れ (極端に言えば炎上)はプロダクトの寿命を縮めることに繋がることに間違いはない。

それは純粋なコードの品質の低さ、テストの未実施などもあるが、何より疲弊したモチベーションの低いエンジニアから生み出されたプロダクトが良いものであるはずがないからだ。マネージャーにはエンジニアのモチベーションを第一に考え、慎重に見積もりやマネジメントを行ってもらいたい。

そしてやはり、残業は悪い文明である。