同僚の外国人プログラマ観察記録

概要

1ヶ月くらい一緒にお仕事している外国人プログラマさんを観察した記録です。

スペック

性別: 男性

仕事内容:
うちの会社のプログラマは、ざっくり JS 等のフロントエンドと、 Java 等のバックエンドエンジニアにわかれているのですが、彼はどちらもやっているようです。

好きな食べ物: はちみつ

たまに、くまさんのようにはちみつを舐めていました。

性格

彼はめんどくさがり屋です。

同僚の Windows ユーザの手伝いをしている時、 "C:¥Program Files¥..." みたいなパスを打ちながら、「めんどくさい。 ああ めんどくさい」
と 100回くらいつぶやいていました。
(普段の彼の環境は mac なので /usr/local/bin)

パスワードを覚えるのもめんどくさいので 1Password で管理しているようです。


PC スペック

マシン: Macbook Pro
メモリ: 16GB
記録媒体: SSD

私が Macbook のメモリを 8G にして喜んでいたら、 「8G 少ないね 16G は無いと」
と言ってきました。

彼にとって、速さは優先度がとても高いようです。

次の日、私の Macbook のメモリは 16G になり、とても快適になりました。
次は SSD にしようと思います。

Jenkins

私が部署を移動した初日、初めて彼と出会った日、彼はチームの Jenkins サーバが遅くて捗らないので、高性能なサーバを用意して載せ替えていました。

その後、 Jenkins Job の設定がモノリシックでのろのろしてめんどくさかったらしく、細かなジョブに分けて、Build Pipeline で繋げる形に書き換えていました。

その日から、デプロイに失敗しても、ビルドを再実行する必要がなくなりました。

未使用のソースコード

チームのソースには他のプロジェクトから横展開して持ってきたものが含まれていました。
中には使われていないソースもありましたが、そのままになっていました。

彼はソースを触る時、使われていないソースを見るのも考慮するのも面倒だったので、未使用のソースを grep するスクリプトを書き、プロジェクトのソースをごりごり削除していました。

ソースコードの行数がチーム能力の指標となる異世界に住んでいたならば、チームの能力は著しく下がったことでしょう。

DB migration

当初、チームの DB 操作は phpMyAdmin で行われていました。
彼は面倒だったので、 flyway を導入し、 DB migration を自動化しました。

JS minify

それまで、チームは js minify を手動で実行していました。
彼は面倒だったので、 Jenkins を使って自動化しました。

minify には、速度と性能のバランスが良い UglifyJS を使っていました。
(たしかね。。)

UglifyJS と Grunt の組み合わせで問題が起きた時、彼は数時間後に pull request していました。

パフォーマンスチューニング

サーバのパフォーマンスが悪く、私はアクセスログや SQL 実行ログでちまちまと確認をしていました。

一方、彼は New Relic を入れて、すべてを見えるようにしました。

CUI

めんどくさがりな彼は GUI よりも CUI を好んでいるようです。
バージョン管理ツール等も、 GUI を使わず、コマンドで済ませています。

log, merge, cp... どれも GUI な私よりも早いです。

彼は ack を使っていました。
なにそれ通信プロトコル? って思っていたら、頭のいい grep なのだそうで、口に出さなくてよかったです。

Java IDE

彼は Eclipse を使っています。
設定を共有するのが面倒なので、 yoxos で管理しているようです。

仮想マシン

私が mac 用の VMWare Fusion を買い、マウスでポチポチ CentOS を入れて喜んでいる頃、彼は Vagrant仮想マシン構築を自動化していました。

私が Chef で頑張っている時、彼は Berkshelf で楽をしていました。

速さ

私の好きな JVM を、彼は嫌いです。
理由を聞いてみたら、「起動が遅いから」といっていました。

私が 5秒かけて JVM を起動している間に、彼は 10回くらい node を起動します。

テキストエディタ

私がぐぐりながら init.el を書いている時、彼は Sublime Text 2 を使いこなしていました。

だろうなっていう気は、若干していました。

異動

そんな彼が、先週、部署異動で去って行きました。
寂しかったので、思い出しながらブログを書いてみました。

私は彼の事が大好きでした。

Scala と null と 型パラメータ

追記 3/24 コメントでご指摘頂いたとおり、 Scala では null よりも Option を使う方が望ましいと思います。
この記事は、 JavaScala 両方を使ったプログラムを書いている時に、 null を扱う必要があって悪戦苦闘していた時の記録です(*ノωノ*)

Option については、以下の様なブログが参考になりますー
http://yuroyoro.hatenablog.com/entry/20100710/1278763193




Scala で型パラメータ T 型の関数から null を返したい時

つまり、こんなことがしたい時、

  def foo[T](t: T): T = {
    if (true) t
    else null
  }

こんなエラーになっちゃいます。

Expression of type Null doesn't conform to expected type T. (by IDEA)

こんな時は、こうすればいいのかな?
(もっとシンプルなやり方あるのかしら。。)

  def foo2[T >: Null](t: T): T = {
    if (true) t
    else null
  }

これはつまり、 T は null のクラスである Null のスーパークラスだよぉって教えてあげるんですね。

f:id:rinu:20130301014000p:plain


Scala ではプリミティブとオブジェクトに共通の Any クラスがあるので、こうしないと T と Null の関係は以下のようになってしまって、 null は T ではないと言われてしまうんです(か?)。

f:id:rinu:20130301015540p:plain

この件、ちょっとハマってしまって。。
こんなふうにしたりして、「ダメだぁ。。」って悩んでました。

  def foo2[T <: AnyRef](t: T): T = {
    if (true) t
    else null
  }

これはクラス図で言うと、こんな感じ ↓ なので、ダメなんですね。。

f:id:rinu:20130301014100p:plain

たぶんね。。。

(ホントは Option を使うのがいいのでしょうね)

svn な人のための これだけ読めば (もしかしたら) わかる (かもしれない) git の考え方

はじめに

svn を使っていたあなたが、さくっと git の考え方を理解できますように (*・人・*)

git リポジトリのイメージ

git リポジトリのイメージを絵にしてみました。

絵の中の登場人物について、このあと触れますー

f:id:rinu:20130225021226p:plain

 

リポジトリ 

リポジトリは複数のファイルの変更履歴を記録する入れ物です。

 

リポジトリを使用するときは、どこかにある、誰かのリポジトリを、自分のマシンにまるっとクローンを作って使用します。

 

(対して svn はある時点でのファイルのみを、ローカルに持ちます)

 

 

コミット(図の黄緑の四角いあいつ)

ファイル達に変更を重ねていくと、変化したファイル達の状態が、リポジトリに保存されていきます。

このリポジトリへ変更した内容を保存することを「コミットする」といい、保存されたファイル達の、変化の履歴の1つ1つを「コミット」といいます。

 

それぞれのコミットは 「0abe...」 みたいな英数字の羅列を ID として持っています。

 

また、コミットは、直前のコミット(親コミットといいます)の事も知っています。

図でコミットから前のコミットに向けて線が伸びているのは、そのことを表しています。

 

(対して svn のコミット ID は、増加する数字ですね)

 

(svn とは違い、コミットと他リポジトリへの同期は別のものです。コミットは自分のリポジトリへコミットを保存するのみです)

 

ブランチ(灰色の四角いあいつ)

ブランチは、一連のコミットの流れの最新のコミットを指し示すものです。

 

ブランチに対してコミットを行うと、新しいコミットが作成され、ブランチはそのコミットを指し示すように変更されます。

 

ブランチは、あまり関連しない別々の作業をそれぞれ別のブランチで行い、最後に1つのコミットにあつめるというような使い方をするんですー

 

例えば以下の図では、3つの異なる作業のために、3つのブランチを作ってます。

f:id:rinu:20130225021205p:plain

 

 

master メイン作業用です。これまで start -> abc2 -> 201f という変化の歴史を作って来ました。
バグ修正用 master で起きたやばいバグを修正するために使ってます。master から分岐し、 2cfc というコミットをおこないました
新機能用 これまで start -> abc2 -> bc01 -> efa0 という歴史を。。

 

(svn の trunk ブランチは、 git では master という名前です)

 

HEAD(白くて四角いあいつ)

HEAD はブランチを指し示すものです。

前の例だと、 HEAD は master を指していますね。

 

HEAD は、私が今まさに使っているブランチを指しているものですー

普段は master で開発してて、バグを直す気になったら HEAD を 「バグ修正用」に移動し、新機能を実装したくなったら 「新機能用」 に移動する。。みたいな感じに使うんです。

 

そんな風に HEAD を動かす時、 checkout っていう操作をしますー

 

リモート

ここからは、自分のリポジトリとみんなのリポジトリの間でいろいろする時に使うものたちの説明ですー

 

f:id:rinu:20130225021226p:plain

 

リモート

自分のリポジトリ以外のリポジトリのことを「リモート」と呼ぶんです。

 

自分のコミットをみんなとシェアするには、このリモートを使ってヤリクリしますー

 

この例の私のリポジトリでは、他のリポジトリに対して origin という名前をつけてます。

 

ローカルブランチとリモートブランチ

世の中には2種類のブランチがあります。

ローカルブランチと、そうじゃないブランチです。

 

ローカルブランチ: 自分専用ブランチです。

 

リモートブランチ: リモートに存在するブランチのコピーです。

見ることはできますが、コミットはできません。

変更する時は、ローカルブランチから push という操作を行います。

 

ローカルブランチはリモートブランチと関連付けることができ、この時、このローカルブランチのことをリモート追跡ブランチと呼びます。

 

この例では、私のリポジトリには、 以下のブランチがあります。

origin/master リモートブランチ origin の master ブランチのコピー
master ローカルブランチ(リモート追跡ブランチ) origin/master のリモート追跡ブランチ

 

私が直接コミットできるのは master だけですが、 master から origin/master へ push することで、変更を origin/master へ反映することができます。

 

 

リモートへローカルのコミットを反映

push という操作を行うことで、リモートブランチを変更することができます。

 

まず、上で出てきた例の状態から私のリポジトリの master へコミットを行うと、以下の状態になります。

f:id:rinu:20130225022106p:plain

ここで master から origin/master へ push することで、以下の状態になります。

f:id:rinu:20130225022125p:plain

 

私のリポジトリにあり origin にないコミットが origin に追加され、 origin/master の位置も更新されています。

 

この時、 origin/master から master へ fast-forward 出来る必要があります。

これは後述しますー

 

 

リモートからローカルへコミットの取り込み

リモートの内容は、みんなが変更しているので、その変更内容を取り込みたくなりますよね。

その変更を取り込むには fetch という操作を行います。

 

例えば、こんな風に origin の master に他のユーザが abf3 というコミットを行なっています。

私も master に 3457 というコミットを行なっています。

(私的には origin の master は 201f だと信じています)

 

f:id:rinu:20130225022155p:plain

ここで fetch を行うと、 origin に存在し、私のリポジトリに存在しないものをすべて取り込んで、さらに origin/master が移動して、こんな感じになります。

 

f:id:rinu:20130225022205p:plain

 

例の場合、 201f からの変更が 2つあるため、自分のコミットと、他の人のコミットを両方含んだ状態になります。

 

(svn はこの時点でコンフリクトしたりしますね。git の場合、この例のように分岐するので、後でマージすることになります)

 

私。。 git の事よくわからないけど。。 ここのイメージを持てるかどうかは重要かなーって。。思うの。。

 

例えば、話変わって複数のリモートがあって、それを取り込む時。。

 

f:id:rinu:20130225022215p:plain

 

この mako, tune を両方取り込むと

 

f:id:rinu:20130225022230p:plain

 

全部を組み合わせた状態になります!

 

マージ

リモートから取り込んだ場合や、明示的にブランチを分けた場合等、最終的にはいっぱいあるブランチを 1つにまとめてあげないといけません。

 

新機能がついたアプリ、バグが直ったアプリ、別々にリリースしても怒られちゃいます。。

欲しいのは新機能がついて、バグの直ったアプリです( ー`дー´)

 

マージ

例えばこんなふうに、 origin/master と master に差異がある状態で、 origin/master の abf3 コミット内容を master に取り込みたい場合

f:id:rinu:20130225022257p:plain

 

マージをするとこんな風になります。

f:id:rinu:20130225022314p:plain

 

新しくできた 4d21 というコミットは、親コミットを2つもっています。

(svn とは違い、両方の親コミットのことを知っているため、マージした後も両方の履歴を辿ることができます)

 

master と origin/master が同じファイルの同じ場所を編集していたりすると、マージが失敗(コンフリクト)することもあります。

 

失敗したら、がんばって直します><

 

fast-forward

特定の状況で使われるマージ処理です。

通常のマージとは違い、新しいコミットを作りません。

 

例として、さっきのマージの例を見てみますー

 

master に origin/master をマージしたので、 4d21 というコミットができていますね。

この状況で origin/master に master をマージしたらどうなるでしょう。

 

この場合、結果は 4d21 とおなじになるはずですよね。

そのため git は新しいコミットを作らず、単純に origin/master の位置を移動します。

f:id:rinu:20130225022311p:plain

 

これが fast-forward です。

 

4d21 コミットはすでに存在しますし、以前に検証も済んでいるはずです。

そのため、この fast-forward はとても安全なマージ処理といえます。

 

 

いつもの流れ

ここまで、 git のイメージを書いてきましたが、ここからはちょっと視点を変えて、

実際に使うときの流れを元に説明していきますー

 

コマンドラインで説明しますが、 GUI でも流れは変わらないかと思うです!

 

さいしょにやること

ユーザ名とパスワードの設定

$ git config --global user.email "メアド"

$ git config --global user.name "名前"

 

clone でリモートのリポジトリをコピーします 

$ git clone URL 

 

デフォルトではクローン元のリモートに origin という名前が付けられます。

そして origin の master 用に origin/master というリモートブランチができます。

これは origin リモートの master ブランチです。

 

さらに、 origin/master に紐づいた、 master というリモート追跡ブランチができます。

 

日々やること

リモートブランチからローカルブランチを作成します

clone 時に origin/master に紐づいた、 master というリモート追跡ブランチができています。

 

origin/master 以外のリモートブランチを使用したい場合、まず、リモートブランチからローカルブランチを作成します。

 

例えば origin/b1 ブランチを使いたい場合、こんなかんじです。

$ git checkout -b b1 origin/b1

 

このローカルブランチ b1 に対してコミットし、最終的に push することで、リモートブランチ origin/b1 へ変更を反映出来ます。

 

コミット

コミットしたい内容をインデックスというものへ入れます。

このインデックスに入れたものだけがコミットされるので、ひとまとまりの関係のある内容だけをインデックスに入れてコミットすることができるんです。

 

インデックスへ入れます

$ git add ファイル

 

コミットします

$ git commit

 

リモートの変更を取り込む

さくっとやるなら

$ git pull

 

この pull が実際に何をしているかというと、、

 

まずはリモートの変更を取り込みます

$ git fetch

 

次に、リモートブランチからローカルブランチへ、内容をマージします。

$ git merge origin/master

 

リモートへ変更を反映する

$ git push

 

自分専用のブランチを作り、切り替える

$ git checkout -b my_branch

 

とりあえずこんなところでしょうかー

 

 

 

Java プログラマさんのための - Scala 紹介 -

はじめに

Scala を始めたいけど、いろいろ不安。。

そんな私のような Java プログラマさんが Scala のはじめの一歩を踏み出せるように。。

そんな意図で書いてます。

 

Scala 入門記事はすてきな記事が沢山公開されているので、ここでは

  • JavaScala はどこが同じで、どこが違うの?
  • Scala という言語はわかったけど、取り巻くツールやライブラリはどうなの?

なんて感じで、 Scala の全体像をざっくりまとめたいなーと思っています。

 

(書いてる私は Scala 初学者です。 間違いがありましたら教えていただけるとうれしいです。)

(2012年 12月 時点での内容です)

 

Java と比べた Scala の魅力

まずは、そもそも Scala ってなにが魅力なんでしょうー

そんな Scala の魅力は、例えばこちらのページにとっても詳しく書いてあります(*´ω`*)

Java使いをScalaに引き込むサンプル集

 

私も Scala 好きなんですが、とくにこんなところが好きです(*´ω`*)

  • Java と同じように使えます
    後ほど触れますが、導入の敷居が低いです。
    (Scala といえば関数型プログラミング
    関数型プログラミングは難しい用語がいっぱい出てくる。
    だから Scala は難しい!?
    でも、 Scalaオブジェクト指向言語としてもすぐれているので、 無理に関数型のスタイルを使わなくてもだいじょぶですー)
  • Java の冗長な記述を省いて簡潔に書けます
    冗長な記述は、書くのが面倒で、読むときにはノイズになったりします。 これを省くことができるのはうれしいんですー
  • Scala だと部品の共通化が捗るんです
    Scala は関数を変数として扱うことができ、このため Java では共通化が 難しいような処理も共通化することができるんです。
  • 標準ライブラリがとても強力
    リストなどのコレクションを操作したり、プロセスを制御したり、 並列処理を行ったり、、
    そんなライブラリがとても充実しているんです。

Scala の抵抗を感じる部分

いいところもあれば、抵抗を感じるところもあるものです。

私的に、ちょっと抵抗を感じる部分トップ3(´;ω;`)

  • 関数型プログラミングは難しい
    知らないものは難しいのです。。
    Scalaオブジェクト指向よりの言語なので、関数型プログラミングを無理に行う 必要はありません。それでも、関数型のスタイルで書かれたコードを読むのは関数型に不慣れなうちはなかなか大変なのです。。
    (Scala の問題じゃないですが。。) 
  • バイナリ互換性
    後述しますー
  • 開発環境
    Scala は言語として優れている反面、取り巻く環境はまさにいま発展中なう
    という感じですね。

    後述します

どんな企業が使っているの?

ここに一覧があります。

http://www.scala-lang.org/node/1658

Twitter, LinkedIn, Foursquare 等、 名だたる企業が使っているんですねー

 

なかでも Twitter はかなりのヘビーユーザーです。 いっぱいオープンソース化してますねー

http://twitter.github.com/

 

日本の企業だと GMO さんとかですかねー???

http://jp.scala-users.org/top%E3%83%9A%E3%83%BC%E3%82%B8/scala-cases-in-japan

 

逆に Scala から Java に移行した例として、 Yammer があります。

http://www.infoq.com/jp/news/2011/12/yammer-scala

Scala 導入を検討する際には、かなり気になる記事です。。

記事内容の正当性に対するコメントがコメント欄にあるので、 記事を読む際はコメント欄もぜひ参考にしてくださいませ。

 

JavaScala - 同じ所・違うところ

一言でいうと、 Java で作成したプログラムの一部を Scala に変更できる程度には、 JavaScala は相互運用性が高いんです。

も少し詳しく見ていきますね。

同じ所

ScalaJava はとっても仲がいいんです。

また、 Scalaソースコードをコンパイルすると Java と同様のクラスファイルになります。

なので、

違うところ

  • getter/setter のお作法
    Java の getter/setter は getFoo/setFoo のようなメソッドです。
    Scala はこれらを遜色なく使用できます。
    それに加え、 Scala は専用の getter/setter 機能を持っており、 そして、通常はこちらを使用します。
    そのため、 Java の getter/setter を要求するライブラリ (Jackson等) を Scala で使用する際には、 以下のいずれかのような対策をしなければだめなんです。
    1. Java と同様に getFoo/setFoo を定義
    2. Java の getter/setter を生成する Scala アノテーションを使用する
    3. Scala のお作法を扱えるライブラリを使用する
      (jackson-module-scala 等)
  • ビルド/ライブラリ管理ツール
    Java と同様 maven も使えますが、 Scala では sbt がよりメジャーです。 (sbt は Maven と、リポジトリやディレクトリ構造に互換性があります)
  • ライブラリのバイナリ互換方針/ライブラリの命名規約
    Scala のクラスファイルは、 Scala のバイナリバージョン※というものが変わると互換性がなくなります。
    つまり、 Scala 2.9.1 に対してビルドされたライブラリ(バイナリバージョン 2.9.1)は、 再コンパイルしないと Scala 2.10.x(バイナリバージョン 2.10) では使えません。

    また、そのため、ライブラリの名前にバイナリバージョンが入ります。
    例: lift-json_2.10 (バイナリバージョン 2.10 用の lift-json というライブラリ)
    ※ バイナリの互換性を表すバージョンナンバー。
  • IDE のサポート度合い
    Java の IDE は非常に高機能です。
    Scala の IDE も高機能ですが、 Java には見劣りしてしまいます。。

    Scala IDE でできること、できないことの一例 (IntelliJ IDEA 12 の場合)

    • リファクタリング: 名前変更/移動
    • × リファクタリング: メソッドシグネチャの変更
    • ○ 変数/メソッド等の使用箇所の列挙
    • ○ 補完(不自由なく可能。 ただし、 Java より遅いです)
    • ○ 定義先へのジャンプ
    • ○ 各種コード生成
    • × 依存ライブラリの自動 DL
      (DL には手動でコマンドを実行する必要があります。 対して、 IDE の Maven プラグインはとても賢いですよね)

    手前味噌ですが、こちらにもちょっと書いています。

    http://d.hatena.ne.jp/rinu/20120417/1334636425

 

長くなってしまったので、続きは後日。。 Scala を取り巻くライブラリやツールについて書こうと思いますー