2015年の抱負
だいぶ出遅れた感あるけど去年の振り返りとともに一応書いておく。
この1年は結構大きな変化があった。
※長いわりに大した内容はないのでそっとタブを閉じること推奨。
2014年
仕事
年内で辞めた。
社員10数名(だいぶ流動的)、創立10年ちょいの会社に4年間いた。
組織の規模が小さいことと人材の流動が激しいことからいつの間にかベテラン扱いになっていた。
エンジニアは結構大事にされていたし、裁量もそれなりにあってまあまあ働きやすい環境だったんだけど、だんだん自分の成長具合が鈍化してきているなと感じていた。
小さい組織なので製品開発から受託開発、インフラ、技サポまで色々やる必要があって、最初はすごく成長しているような気がしていたが、1年、2年と経っていつの間にか「あれ、もしかして俺、器用貧乏なのでは?」と思うようになった。
自分である程度上から下までできるけど(デザイン除く)、いわゆる「これだけは負けないぜ!」という得意分野がないのが悩みになった。
※強いて言えば技サポは得意だった。ユーザーが何を求めているか判断して、いかにして少ない労力で満足してもらうかとか。
そしてこのままの環境でこの悩みは解決しなそうだなあとも。
※どうしても組織で求められるのがジェネラリストだったので。
またエンジニアの絶対数が少なく、新しもの好きタイプの人もいなかったので、刺激が少なかった。 生活の多くの時間をさく仕事で、この環境はエンジニアにとってあまり良くないと感じていた。
それでも2年間位は組織自体の改善に興味があったし、「こんな小さい規模の組織を変えられないようじゃどこ行っても同じだ」みたいな意識の高いことを思って残り続けていたが、それも「もうそろそろ良いかな…」と思う時期にきていた。 変えられたものは僅かしかないが。。。
気付けば現在30代前半で結婚もしてはいたが、共働き子供なしの状態だ。
再チャレンジするなら今だ。
結構勢いで辞める段取りをはじめたけど、半年前に申告・説得してからなるべく迷惑かけないようにしたり、後輩に残せるものは残せるようにしたりと結構気を使って辞めた(重要)。
この辞め方は自分でも義理人情的には良かったと思うけど、辞めると決めたチームで半年働くのはモチベーション管理が大変だった。。。
他人にはおすすめしない。
辞めはしたけど、中途で入ってペーペーに毛が生えたところから鍛えてもらったので感謝している。
ワープアからも引き上げてもらえたし(超重要)。
プライベート
2013年は妻が体調を壊したため、2014年は心を入れ替えて家庭を大事にするつもりだった。ある程度は気をつけられて気がするんだけどまだイマイチだったかも。
また個人プロジェクトやりたいなと思いつつも、仕事ばかりに追われて手につかなかった。
仕事は大体3ヶ月単位くらいで忙しかったり少し余裕ができたりだったんだけど、繁忙期に放置していた社内プロジェクト的なのをやったりして、結局プライベートでも仕事のことを考えてる時間が多かった。。
まあ仕事嫌いではなかったけどもう少し何とかしたかった。
2015年
仕事
しばらくは主夫を生業とする。
半年ぐらい主夫経験を積んだのち、エンジニアとして再就職したい。
希望はベタだけど自分よりできるエンジニアが多いところ。
良くも悪くも「俺はこの技術で勝負するぜ!」っていうのがないので、考え方が合いそうなところと出会えればそこで必要とされることをやりたい。
小さい会社にいて実感したけど経営理念って結構本当に会社の空気に反映されるのでソリが合うかは重要。
とりあえず無職のうちは積ん読を片付けたり、今まであまり触れなかったり深堀りしなかったところを勉強し直したい。
一例
- OS自作(楽しそう)
- 電子工作(楽しそう)
- 数学(コンプレックス)
- デザイン(少しは出来るようになりたい)
専門性がないのが不安で辞めたとか言ってる割にまとまりがなくむしろ逆方向だな。。。
休み中に専門分野を作ろうかとも思ったけど、方向性を決めてないし、縁のある仕事と出会ったら突き詰めるって方が効率がよいと感じているので今は興味の趣くままにやりたい。
最悪今のスキルセットでも、前職みたいな小規模な組織で手広くやれる人間が欲しいってところでなら充分役に立てると思うし。
あとGithubが完全にROM専になっているのでもうちょっとアウトプットしたい。。。
プライベート
とにかく無職のうちに家事レベルを上げる!
子供が欲しいなーと考えているのだけど、前職みたいな生活をしていたら妻にばかり負担がかかってしまう。新しい職場がもし忙しくても、効率よく家事を回せる実力を養う。
これも結構退職理由の大きな部分を占めてるかも。
タイムリーにこんな記事が流れてきたけど、これの悪いパターンにならないように生活を改めたい。
ひとまず今年はほぼ毎日妻に御飯作ってる。
洗濯機、掃除機など家電の見直しもはかって効率よくできるようにしたい。
あと無職になるというわがままな選択を許して応援してくれる妻への感謝を忘れないようにする。
まとめ
というわけで無職をエンジョイする!
RubyのJSON.parseでキーをシンボルにする
symbolize_names
をtrue
にすればよかった。
リクエストできたハッシュと内部で持ってたハッシュをマージした後に色々やってて「なんかおかしいなー」と思ったらハッシュのキーが文字列とシンボルでずれてた… 10分くらいハマってた…
余談だけどpryが便利で良い。
JS書くときとかブラウザのコンソールで色々試しながら書いてておかげで捗るけど、それに近い感じでできる。ドキュメントとかもその場で見れるのでさらに便利。
$ pry [1] pry(main)> ri JSON.parse JSON.parse (from ruby core) ------------------------------------------------------------------------------ parse(source, opts = {}) ------------------------------------------------------------------------------ Parse the JSON document source into a Ruby data structure and return it. opts can have the following keys: * max_nesting: The maximum depth of nesting allowed in the parsed data structures. Disable depth checking with :max_nesting => false. It defaults to 100. * allow_nan: If set to true, allow NaN, Infinity and -Infinity in defiance of RFC 4627 to be parsed by the Parser. This option defaults to false. * symbolize_names: If set to true, returns symbols for the names (keys) in a JSON object. Otherwise strings are returned. Strings are the default. * create_additions: If set to false, the Parser doesn't create additions even if a matching class and create_id was found. This option defaults to true. * object_class: Defaults to Hash * array_class: Defaults to Array
仰せのままに。
[2] pry(main)> str = '{"a": 1, "b": 2, "c": 3}' => "{\"a\": 1, \"b\": 2, \"c\": 3}" [3] pry(main)> JSON.parse(str) => {"a"=>1, "b"=>2, "c"=>3} [4] pry(main)> JSON.parse(str, {symbolize_names: true}) => {:a=>1, :b=>2, :c=>3}
便利。
Haskell 超入門に行ってきた
これ行ってきた。 Haskell 超入門 (2014/09) - connpass
Haskellおもしろそうだなーと思ってたけど題材もこれといって見つからず放置してたところにこんなイベントがあったのでありがたかった。
基本的な文法とか再帰の練習が中心で、モナドとか難しい話題は入り込まなかったんだけど十分楽しかった(バブルソートが意外と難しくて屈辱をうけた…クイックソートの方が実装簡単とは…)。
事前にテキストがQiitaで用意されていてそれに沿って七誌さん講義を受ける形。
- Haskell 超入門 - Qiita
- Haskell - HUnit 超入門 - Qiita
- Haskell 代数的データ型 超入門 - Qiita
- Haskellによる代数計算入門 - Qiita
「Haskell 代数的データ型 超入門」まで進んで「Haskellによる代数計算入門」までは届かず。 今回うまく書けなかったところも含めて自習しよう。
講師の七誌さんの説明がとても分かりやすかった。テキスト作ってくれて6時間がっつり講義とかすごい。これで1000円ぽっきりで良いのだろうか。。。
この勉強会は 池袋バイナリ勉強会・初回編 - connpass の準備編らしいのでこちらも参加しようと思う。
UbuntuでのJDK管理
最近仕事でJavaを使う雰囲気になってきた。
Javaは昔少しやったきりであんまり分かってない。
しかも色々あってJava6以降対応みたいな感じで作ることになりそう。
JDKの複数バージョンってどう管理すれば良いんだろう?
Windowsで昔さわったときは環境変数JAVA_HOMEを切り替えてたけど。
OpenJDKとOracleJDK
調べ始めたらそもそもOpenJDKとOracleJDKのどっちが良いの?となった。
https://help.ubuntu.com/community/Java
OpenJDK
JDKのオープンソース実装でUbuntの公式リポジトリでサポートされている。
単にJREでJavaアプリケーションを動かすだけならこちらの系統で良さそう。
OracleJDK
SUNの流れを組むOracle様の実装。
wgetでダウンロードできないなど不満はあるけど一般的には所謂JDKとはこちらを指していそう。
仕事で使うなら素直にこちらを使えば良さそう(根拠薄)。
OpenJDK推奨みたいなシチュエーションって何かあるんだろうか?
JDKの切り替え
update-alternatives
さっきのURLにもあるけど基本的にはupdate-alternatives
使えとある。
http://askubuntu.com/questions/56104/how-can-i-install-sun-oracles-proprietary-java-jdk-6-7-8-or-jre
あと例では、解凍なりなんなりしたJDKのディレクトリは/usr/lib/jvm/
に置いているのでそういう流儀なのかな?
「JDK 複数バージョン」などでググるとやはりupdate-alternatives
が多い。
JAVA_HOME
update-alternatives
は詰まるところ/etc/alternatives
内のシンボリックリンクをいじってバージョンの変更を実現しているのでまあ理屈は分かりやすいと思った。
ただ最初に登録するのがjava, javac, jwsと書いてあって、「他のbinの下のコマンドは登録しなくていいの?」とか、「なんで別々に登録したコマンドがsudo update-alternatives --config java
でまとめて変更できるんだろう?」とか疑問が発生した。
というかJAVA_HOMEの変更じゃダメなの?
OpenJDKはapt-getした時点でalternativesの管理下になってしまうので難しいのかな?
そうしたら同じような疑問をもった人がいたらしい。
The 2 mechanisms are related but can be used together or independent of each other, it really depends on the Java application which mechanism is preferable.
つまりupdate-alternatives
とJAVA_HOMEを変更する方式は共存できるとのこと。
じゃあJAVA_HOMEの変更の方がシェルスクリプトからも使いやすいし自分の好みだ。
結局自分はどうしたか?
とりあえずは自分のデスクトップで複数バージョンが使えれば良いので、必要にかられるまではJAVA_HOMEの変更でいくことにした。
またインストール先は/opt以下にした。理由はOpenJDKと混ぜると自分が混乱しそうだから。
たぶんOracleJDKとOpenJDKの混在を見慣れてくれば問題ないことだけど。
個人のデスクトップマシンだから/optにしたけど~/optでも良いと思う。
$ tail -n 4 ~/.profile export JAVA_HOME=/opt/jdk1.6.0_45 #export JAVA_HOME=/opt/jdk1.7.0_65 #export JAVA_HOME=/opt/jdk1.8.0_11 PATH=$JAVA_HOME/bin:$PATH
まだ試してないけどupdate-alternatives
に登録するときは以下で見れるコマンドを登録するのが良いのだろう。
$ ls -l /etc/alternatives/ja* lrwxrwxrwx 1 root root 41 Jun 22 00:22 /etc/alternatives/jar -> /usr/lib/jvm/java-7-openjdk-amd64/bin/jar* lrwxrwxrwx 1 root root 51 Jun 22 00:22 /etc/alternatives/jar.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/man/man1/jar.1.gz lrwxrwxrwx 1 root root 47 Jun 22 00:22 /etc/alternatives/jarsigner -> /usr/lib/jvm/java-7-openjdk-amd64/bin/jarsigner* lrwxrwxrwx 1 root root 57 Jun 22 00:22 /etc/alternatives/jarsigner.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/man/man1/jarsigner.1.gz lrwxrwxrwx 1 root root 46 Jun 22 00:53 /etc/alternatives/java -> /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java* lrwxrwxrwx 1 root root 56 Jun 22 00:53 /etc/alternatives/java.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/jre/man/man1/java.1.gz lrwxrwxrwx 1 root root 43 Jun 22 00:53 /etc/alternatives/javac -> /usr/lib/jvm/java-7-openjdk-amd64/bin/javac* lrwxrwxrwx 1 root root 53 Jun 22 00:53 /etc/alternatives/javac.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/man/man1/javac.1.gz lrwxrwxrwx 1 root root 45 Jun 22 00:22 /etc/alternatives/javadoc -> /usr/lib/jvm/java-7-openjdk-amd64/bin/javadoc* lrwxrwxrwx 1 root root 55 Jun 22 00:22 /etc/alternatives/javadoc.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/man/man1/javadoc.1.gz lrwxrwxrwx 1 root root 43 Jun 22 00:22 /etc/alternatives/javah -> /usr/lib/jvm/java-7-openjdk-amd64/bin/javah* lrwxrwxrwx 1 root root 53 Jun 22 00:22 /etc/alternatives/javah.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/man/man1/javah.1.gz lrwxrwxrwx 1 root root 43 Jun 22 00:22 /etc/alternatives/javap -> /usr/lib/jvm/java-7-openjdk-amd64/bin/javap* lrwxrwxrwx 1 root root 53 Jun 22 00:22 /etc/alternatives/javap.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/man/man1/javap.1.gz lrwxrwxrwx 1 root root 48 Jun 22 00:30 /etc/alternatives/javaws -> /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/javaws* lrwxrwxrwx 1 root root 58 Jun 22 00:30 /etc/alternatives/javaws.1.gz -> /usr/lib/jvm/java-7-openjdk-amd64/jre/man/man1/javaws.1.gz
追記 2014.01.10
Macでの話も書いた。
MacでのJDK管理 - my coredump
golangでC言語のincludeみたいにカレントディレクトリのファイルを読み込めないのか?
ちょっとハマったのでメモ。
ちょろっとしたコード書きたいけど長くなってきたからファイル分けたい! ってときにmainからどう呼び出すのが良いのか?
知っている範囲だと、みんな同じパッケージにするかサブディレクトリ作ってサブパッケージみたいにする必要がある。
こんなmain.goがあったとすると、、、
main.go
package main import ( "./sub" ) func main() { Foo() sub.Bar() }
パッケージ名の修飾なしで使いたい関数とかはmainパッケージで定義する。
foo.go
package main import "fmt" func Foo() { fmt.Println("Foo!!!") }
パッケージを分けたい場合はサブディレクトリを作ってやる必要がある。
sub/bar.go
package sub import "fmt" func Bar() { fmt.Println("Bar!!!") }
必ずサブディレクトリ作ってやらなきゃいけないのが面倒かなーとも思うけどまあこんなもんか…
と思ったらビルド時にもう一つ落とし穴。
go build main.go foo.go
としてやる必要があった。
runの時も同じく。
go run main.go foo.go
barはimportしてるから解決してくれるけどfooは場所が分からないのかな? なんとなくgoツールの作法からはずれそうだから素直にサブディレクトリ切るのがよさそう。
もっとサクッとやる方法ないものか。ちょっとトライアンドエラーしにくい。
まああんまサクってやるのはgolangの守備範囲害なのかな?
jQueryでイベントをはがさないでハンドラを実行させない方法
jQueryにevent.stopImmediatePropagation()
ってメソッドがあった。
http://api.jquery.com/event.stopimmediatepropagation/
有名なstopPropagation()
はイベントが親要素へ伝播(バブリング)していくのを防ぐけど、
このstopImmediatePropagation()
の方はさらに同じ要素にバインドされた他のイベントハンドラの実行も防いでくれる。
イベントバブリング | 同要素内の他のハンドラ | |
---|---|---|
stopPropagation | 防ぐ | 実行する |
stopImmediatePropagation | 防ぐ | 実行しない |
知らなかった。
色々な役目を背負い過ぎてしまった可哀想な要素を救うのに一役買いそう。
無論そんなケースに遭遇する時点で何かがおかしい気もするけど。
過去に一度だけこのメソッドを知ってたら、、という記憶があるけどそのプロジェクトは他にも色々カオスだった。
node.jsでコマンドを作ってコマンド名で実行させる
node.jsでコマンドっぽいものを作ったときに、できればコマンド名だけで実行できるようにしたい。
node /path/to/script.js
とかするのは面倒だしださい。
結論としてはpackage.jsonにbinプロパティを記述すれば良い。
$ mkdir hello && cd $_ $ npm init # <- 全部yesでOK
生成されたpackage.jsonを以下のような感じに編集する。最小限な感じに色々省いた。
{ "name": "hello", "version": "0.0.0", "description": "", "bin": { "hello": "./bin/hello" } }
コマンドのコードを書く。
$ mkdir bin $ cat <<EOF > ./bin/hello #!/usr/bin/env node console.log("hello command"); EOF
試しにインストールしてみる。
ちなみにnpmは公開してなくてもローカルディレクトリを指定してそこからインストールできる。
便利。
# カレントディレクトリからグローバルにインストール $ npm install -g .
これで/usr/lib/node_modules/hello/
にインストールされ/usr/bin/hello
にシンボリックリンクが張られる。
ちなみにnpm install hello
でプロジェクトローカルにインストールしたときは、カレントディレクトリのnode_modules/hello
にインストールされるとともに、node_modules/.bin/hello
にhelloのシンボリックリンクが張られる。
この場合package.jsonのscriptプロパティでコマンド名だけで利用できるようになる。
ちなみにWebアプリ作るときはexpressとか使うフレームワークの作法に従えば良いし、
ライブラリを作るときはproject/lib/
以下に実装書いてproject/index.js
にrequire
するコードを書いてた。そうするとrequire package
したときにproject/index.js
を読んでくれる。
コマンド形式のものを作るときのノウハウが分からなかったので調べてみた次第。
ライブラリのときの話に関しては多分package.jsonで動作変えられるしもっと良い方法があるのかも。