Island Life

2010/02/23

アメリカと言っても広うござんす

米国で外国人が仕事するのに最大の障壁がビザであることには同意する。 他の国の話を聞いてみても米国がとりわけ大変なようだ。 ただ、ビザ関係は文字通りのケースバイケースであることに注意が必要だ。 個人のバックグラウンドやつながり、そして時期によっても 話がころころ変わる。このエントリに書いてることも、 今だと状況が変わってる可能性あり。 個々のエピソードはひとつのケースとして参考にはなるだろうけれど、 正しい情報は「移民弁護士に聞いてね」としか言えない。

以下、引用はすべてshi3zさんのブログエントリ 『で、実際に海外で働くとどうなるか』 より。

20代のうちにアメリカできちんと働くには理系四大卒が必須。中退だとビザすらもらえない。

アメリカは失業者対策として労働者人口を著しく制限している。

その結果、いわゆる「サラリーマンのような仕事(寿司職人とか俳優とか特殊なものでない仕事)」に就こうと思ったらビザかグリーンカードが必須。

僕は電通大中退なので、当然これにひっかかってビザを申請するまで非常に大変だった。

これにかかる弁護士費用は軽く100万円を超え、それでもビザが通るかどうかわからなかった

えーとまず、寿司職人や俳優でもビザは必要。単に違うカテゴリになって 取りやすさが変わるってだけ。まあでも話を広げすぎてもわかりにくいので、 以下ではプログラマのような技術者が単身 (日本の会社に所属して駐在とか、配偶者がビザ/GC/市民権持ちとかでなく) 米国就職する場合に絞る。

この場合、ほとんどはH-1Bというカテゴリのビザを取ることになる。 これは「米国で探したけど必要な技術を持ってる人が見つかりませんでした」という 前提で発行されるビザなので、「業務に関連する学部卒、もしくは同等の業務経験」 が必須である、というのは確か。

ここで「同等の業務経験」とは、目安として3年の業務経験=学部の1年と換算すると聞いた。 したがって2年大学に行ってそれなりに単位を取り、その後6年、関連する業界で 働いてれば、20代後半でH-1Bは取れる。 実際に取れるかどうかは弁護士の腕にもよる (上の換算もあくまで目安であって、 最終的には弁護士が「この人物の経験値は米国内でおいそれとは見つけられない」と 移民局を説得できるかどうかにかかっている)。 弁護士費用100万というのは私が聞いた中では破格に高いが(2000年前後では、$1,000〜$2,000くらいというのを良く聞いた)、 これも個々の状況によって話が大きく変わってくるので、一概には言えない。 準備についても自分で色々用意しなくちゃならなかったりした人もいれば、 働いていたことの証明のレターだけ用意してあとは弁護士におまかせ、って人もいる。

ただ、おそらく一番重要なのがタイミングだ。 上述の通り、「米国内で見つけられないので外国人を雇います」という建前であるので、 不景気で同程度のキャリアの米国人が職にあぶれている時期には非常に取りくくなる。 一方、好景気を予感すると企業はばんばん外国人を採り始めるが、 H-1Bの発行数は年間で上限が決められてて、これが埋まっちゃうとその年度は もうおしまい。年によってはこの枠が一瞬で埋まることもあれば、 年度の終わりまで埋まりきらないこともある。 2007年10月からの枠は受付初日で定数をはるかにオーバーして抽選になった。 一方で、2000年前後はハイテク産業の好景気のためにH-1Bの発行数が臨時に 大幅増になっていて (通常65000の枠が最高で195000まで拡大された)、 この頃はかなり取りやすかったはず。 つまり、枠の大きさと景気の具合によってビザの取りやすさには天地の差が出る。

ボスの気分を損ねたらその瞬間にクビ

日本では即日解雇は違法行為だが、アメリカでは合法。よほどのことがない限り、解雇に正当な理由は必要ない。

州によって微妙に違うようだけれど、基本的には "at will" と言って即日解雇可能。一方で被雇用者の方も予告無くその日に「辞めます」 といって辞められる。両者の力関係は景気によってどちらにも傾く。 不景気ならこの制度は雇用者にとって有利だけど、好景気で どこも人を探している時は被雇用者にとって有利。 まあ今みたいな状況だと被雇用者は大変だ。

ただ、馘を切るのにもコストがかかる。切るだけならいいんだけど、 その後に適切な人を探してこなくちゃならないからね。 経営が安定してる企業のオーナー社長なら一存で部下を馘にできるかもしれないが、 中間管理職が部下をバンバン馘切ってたら多分その本人が馘になる。 それに、レイオフが続くと社員の士気に露骨に影響する。 ましてや理不尽な解雇をや。

もうひとつ、転職が日常茶飯事なので、会社をまたいだ人脈の つながりが非常に大きい。会社は人を探す時にまず人脈に頼るし、 人が就職先を探す時もそう。なので気分で馘を切ってる職場があったとしたら、 業界内でどういう評判になるかは推して知るべし。 「それでも働きたい」と人が集まる会社なら、それは馘のリスクを 上回る魅力があるわけだ。

(なお、米国の「会社に対する帰属意識の薄さ」というのは、 この人脈からなるコミュニティへの帰属意識の濃さでもってバランスされている ような気がする。「かつての同僚」とは転職後も頻繁に連絡を取り合い、 カンファレンスがあればそこでプチ同窓会をやるなんてこともよくある。)

賄賂のやりとりは当たり前。仕事が欲しければメリットをよこしな

一部の大企業では取引をするに当たって担当者に賄賂を送ることが通例化していることがある。

日本ではいまどきその手のリベートを要求されることは滅多に無い。

これはそういう取引をしたことがないからわからない。 末端の零細技術者の身ではあまり縁のないことかもしれない。

ただし、シリコンバレーはどうかわからないが地方都市では 大きな取引はけっこう財閥みたいなものがあって、新参者が食い込むのは 大変だという話は聞く。

お前の代わりはいくらでもいる

僕の場合、給料は年棒制だった。僕は十分な給料を得ていたから給料に不満はなかったけど、他の人は例えば給料が10年間変わっていないなんていうこともあった。

人間は仕事に習熟すればそれだけ業務効率がアップするわけで、同じ給料なんておかしい、と思ったのだが、同じ仕事をし続けている限りは同じ給料であり、日本のように下積みを重ねてキャリアアップすることは最初から想定されていない。

給料は業務内容で決まるので、同じ業務内容なら何年勤めようと給料は 原則として変わらない。ここでの「業務内容」というのは雇用契約に 書かれている仕事の内容のことで、実際にどれだけ仕事をしたか、ではない。

雇用契約とはそもそもそういうものだ。「これだけの仕事をしてね」 「その報酬としてこれだけ払いますよ」という契約を結んでいるわけなんで、 それ以上の仕事をしてもらってもおいそれと追加で払うわけにはいかない。 給料を上げて欲しければ契約内容を更新することが必要だ。 (逆に、契約どおりの業務をこなせていない場合、 減給にするのにも契約の更新という話になる。)

ただ、会社は基本的に「この人がいるからこういう業務やってもらおう」という 考えではなく、「こういう業務が必要だから人を雇おう」と考える。 同一会社内で、ある部署でレイオフすると同時に別の部署で求人をかけたり することも珍しくない。 したがって、ひとつの社内で同じ系統の業務をこなしながら 契約内容を変えてゆくということはやりにくい。会社がダイナミックに 変わって行くのでもなければ、給料を上げる基本手段は転職ということになる。

「下積みを重ねてキャリアアップ」という考え方は米国にもあるけれど、 それはひとつの会社でずっと重ねるものじゃなく、ある会社で3年間ジュニアレベル で下積みをして、その経験を使って次の会社でインターミディエートレベルの 仕事に就き…というふうにキャリアアップしてゆくのがよくあるパターン。

但し、ビザワーカーは転職にあたって相手先企業にビザをとってもらわないと ならないので、この点で相当不利な立場になる。 H-1Bで働きながら、雇用者を通じてグリーンカードを申請するというのが 定番のパターンなんだけれど、雇用者経由のグリーンカード申請は何年もかかるうえ、 転職しちゃうとリセットされて最初からやり直しになってしまうため、 条件が悪くても転職できない、という立場におかれる恐れも多分にある。

シリコンバレーの特殊なメリットを盛んに述べる人は多いけれど、 正直、ビザが米国にとってのアキレス腱だなあと感じるなあ。 (だからベンチャー起業家ビザ (和訳)なんて話が出たりするんだろうけど。)

(追記2010/02/25 02:53:08 UTC): このエントリで「ビザ」と言っているのは、正式には 「非移民ビザ (nonimmigrant visa)」のこと。一方、いわゆる「グリーンカード」 は正式には「移民ビザ(immigrant visa)」と呼ばれる。 日常のコンテキストで「ビザ」と言えば非移民ビザのことだと思って良いのだが、 米国政府のドキュメントやニュースではグリーンカードのことが immigrant visaと表記されることが多いので注意。

Tag: Career

2010/02/21

gitのワークフロー

仕事でgitを使い始めた。分散SCMを使ったのは初めてだったので最初は モデルを頭の中に作るのに苦労したが、自分なりのワークフローが 何となく出来てきたのでメモっとく。 gitの機能のまだほんの一部しか使ってないと思うけど。

まず案件の前提。

  • 開発者は10数人。
  • 開発はチケット毎にパッチを作ってレビューを受ける。
  • 本家のリポジトリのブランチは開発バージョンに沿って切られており、 複数バージョンの開発が同時進行してる。

以下のワークフローはこの前提のもとでの作業。 前提が違えばフローも違ってくると思われる。

  1. リモートリポジトリをミラーしているブランチ (e.g. origin/version1.1 に対する version.1.1 とか) は原則として完全に同期させとく。以下のコマンドは適宜実行する。
    $ git checkout version1.1
    $ git fetch
    $ git fetch --tags
    $ git merge origin/vesion1.1
    
  2. チケットが来たら、メインのブランチからトピックブランチを切って移動。 トピックブランチはwork-* と名づけている。
    $ git branch work-FOO
    $ git checkout work-FOO
    
  3. 作業してこまめにコミット。この時のコミットログは自分しか見ないのでメモ程度で良い。
    $ git commit -a -m 'simple log'
    
  4. 作業が終了したら(あるいは適宜)、メインから上流の変更を取り込み。
    $ git merge version1.1
    
  5. conflictしたら編集して、以下の手順で解決。
    $ git add source/with/conflict.cl
    $ git commit -m 'conflict resolution'
    
  6. mergeが済んでテストも通ったら、パッチ作成用ブランチを作る。 パッチ作成用ブランチはwrap-*と名づけている。
    $ git checkout version1.1
    $ git branch wrap-FOO
    $ git checkout wrap-FOO
    
  7. 作業ブランチから変更を取り込み。この時--squashして、コミットをひとつにまとめる。 また、ちゃんとしたフォーマットに沿ったcommit logを用意してコミットする。
    $ git merge --squash work-FOO
    $ git commit -F commit.log
    
  8. これがうまくいったら、メインブランチに変更をマージ。というのは、 パッチをレビューに回すスクリプトが別にあって、 こいつがorigin/${version}と${version}間のパッチを作るようになってるもんで。 パッチを送ったらメインブランチはリモートと同期させておく。 (wrap-FOOをマージした状態のままリモートからmergeするとパッチの順番が 前後して色々面倒になるので)
    $ git checkout version1.1
    $ git merge wrap-FOO
    $ パッチ生成、レビューに回す
    $ git reset origin/version1.1
    
  9. パッチが受理されて本家にpushされたら、wrap-FOOは消していい。 メインブランチもreset --hardでリモートに合わせとく。 work-FOOの方は、後で問題が出てパッチがrevertされた時に使うかもしれないので とりあえず取っておく。
    $ git branch -D wrap-FOO
    $ git reset --hard origin/version1.1
    

wrap-* が必要なのかどうかはまだよくわからない。 こうして書いてみるとversion1.1に直接merge --squashしちゃってもいい感じだけれど、 wrap upからパッチ作成の段階で試行錯誤してる時期があって (rebase -iとか使ってみたり)、 その間に別のトピックブランチを切る必要が出てきた時に 手つかずのversion1.1がある方が便利だったので、こういうフローにした。 全部merge --squash一発で済むならwrap-*を省いてもいいかも。

もっと使い込んだら変わってくるかもしれないけど、今のところはこんな感じ。

Tag: Programming

2010/02/19

マップリテラル

Lispのハッシュテーブルには伝統的にリテラル表記(外部表現)が無い。 他の主要なデータ構造ではread/write invariance (WiLiKi:Scheme:ReadWriteInvariance) が 保証されているので、残念なことである。 ハッシュテーブルは手頃な大きさのマップ(キーから値への写像を表現するデータ構造) に 便利だが、組み込みのマップ型にリテラル表記を備えている言語も増えていて、 Lispに移った時に不便に感じることもある。 (但し、マップを必ずしもハッシュテーブルで実装する必要はない。 Lispの場合、とりあえず読み書きしたかったらalistでいいじゃん、 という要因はあったかもしれない。)

なので、新しいLisp拡張を考える時にハッシュテーブルのリテラル表記を、 と思うのは自然なのだけれど、Common LispやSchemeでハッシュテーブルリテラルが 無いのには理由がある。最大の理由は、 「ハッシュテーブルを再現するには、各要素だけでなくハッシュ関数および比較関数の情報が必要」 という点だろう。

一般的なクロージャのポータブルなリテラル表記は無いので、 これらの関数が自由に指定できる場合、ハッシュテーブルの リテラル表記がいつでも可能とは限らない。 それに関数を書き出せたとしても、 それが人間にとって読み書きしやすいものにはならないかも。 (特に、プログラム中にリテラルとして書きたい場合とか。)

アプリケーションが決まればハッシュ関数と比較関数は固定される ことが多いだろうから、そしたらリードマクロを使って リテラル表現を自由に決めてください、ってのがたぶんCommon Lispの立場。 例えば比較関数をeql決め打ちで

  { :foo => 1
    :bar => 2 }

なんてのをハッシュテーブルとして読み込む、とかいうコードはすぐ書ける。

つまり、ハッシュ関数と比較関数が言語で決め打ちになっていれば (たとえカスタマイズできるとしても、大部分のケースをカバーできる関数がデフォルトに なっていれば)、言語としてリテラルを決めてしまってもいい。 マップリテラルがある他の言語は、そういうことだ。 ハッシュ/比較関数の自由度と、リテラルの便利さがトレードオフになっているわけだ。

Lispには比較関数がいくつもあって、これはプログラマの 選択肢をできるだけ用意しとくって精神なんだろうけど、敢えてデフォルトに 絞り込もうとすると「eqかeql」とequalp (Schemeなら「eq?かeqv?」とequal?) が考えられる。 この二つは甲乙つけがたい。基本的に、前者はオブジェクトとしての同一性、 後者は値としての同一性を見ていると考えられるけど、 どちらも同じくらい必要なことが多いからだ。

ところでClojureはマップリテラルを持っている。 その理由は、Clojureではオブジェクトの同一性よりも値の同一性の方が はるかに重要なので、比較関数を = に決め打ちしてしまってもほぼ問題にならないから。 で、なぜ値の同一性の方がそんなに重要になるかというと、 Clojureのデータ構造が原則immutableだから。 immutableなデータ構造では、値の同一性のみが問題になる (メモリ上の同一番地にあろうが別の場所にあろうが、それらのオブジェクトは 操作に対してまったく同様に振る舞うので、区別できない)。

だもんでClojureに関して言えば、データ構造のmutabilityを捨てたら マップリテラルが自然についてきた、という感じだ。

マップリテラルがあるかどうかには、 「等しい」とは何か、という問いが隠されている、という話。 俺言語を設計するときにでも参考にされたし。

Tags: Programming, Lisp

2010/02/16

「Xで使うべき」だからといって「X以外では使うべきじゃない」ってわけじゃない。けれど…

From バカが征く:

http://blog.practical-scheme.net/shiro/20100215-when-you-should-use-lisp-2

でも、そうだとすると、自分には関係のない世界に なっちゃいますね (笑)。『極めて複雑な処理が必要で』 っていうのは、自分の能力的にないでしょうから。

いや、確かに対比のために「他の言語でも困らないような分野で わざわざLispを使うのはハンディがあるよ」と書いたけれど、 強調したかったのは「これこれこういう分野ならLispの力を活かせるよ」って方。 それ以外の分野であっても周囲の条件次第ではハンディにならない 場合はあるだろう。偶然チームにLisperばかり集まってたとか :-)

それはそれとして、逆に、1つの言語ですべてを済ます ことをあきらめたら、選択肢がかなり広がるともいえるん じゃないでしょうか。Gaucheにしても、Rubyにしても、 C言語との親和性を重視してると思いますし。Clojureに しても、Javaをスッ飛ばしてJNIで書くこともできるん じゃないでしょうか。

もちろん全ては可能であり、そこにはトレードオフがあるだけなんだけど。

複数言語のギャップを越えるオーバヘッドがどれくらいかは ケースバイケースで、それこそ別コンポーネントと言えるくらい 疎結合にできる場合なら問題無いだろうけど、 意味的に単一コンポーネントとして切り離せないんだけど言語を 混ぜて使わなくちゃならない、って場合は、オーバヘッドは結構大きいと思う (例えばバイナリの構造体を共有しなくちゃならないとしたら? 定義を二ヶ所に 書いておきたくはない。ひとつの定義から各言語のソースを生成するのは 定番だけど、それによって確かにビルド工程やデバッグは複雑化する。)

言語を混ぜて使うことをサポートするツールはたくさんあるし、 そういう環境に慣れてればどうってことないと思うかもしれない。 言語に限らず、OSやハードウェアだって、今あるものの上で済ませられる 話はたくさんある。たぶん仕事として喰って行くのに充分なくらい。

でも、時には手を止めて、今見えている地平線の向こうに想いを馳せるのも悪くない。 地平線というのは、今、手にしている道具や手法、そして自分の能力で、 コスト的に限界に達するところ。けれども道具や手法を工夫したら、 能力は変わらなくても、その向こうが見えるかもしれない。 (過去50年のコンピュータエンジニアリングの進化を思えば、 道具や手法が能力よりもはるかに生産性に寄与しているのは確かだろう。 今仕事で組んでるそのコード、全部アセンブラで書けって言われて書ける?)

新しい言語の話やハードの噂がついつい気になっちゃうのって、 今は手がとどかない、地平線の向こうを見てみたいっていう気持ちなんじゃないかな。

Tags: Programming, Lisp

2010/02/15

仕事でLispを使うこと(2)

仕事でLispを使うことの続き。

Lispが力を発揮する一例として、高レベルから低レベルまでの アクセスが必要な場合というのをあげたけれど、もう少し考えを進めてみる。

さくっと作れることが利点である言語、まあいわゆるLLと呼ばれてる 言語同士を比べるとき、「さくっと作れること」という点では それほど差は出ない。その場合、むしろライブラリの豊富さや デベロッパーの多さなど、外部的な要因が重要になる。 なので、既存のライブラリやサービスをうまく利用して新しいサービスを 素早くローンチする、といった分野では、Lispは相対的には不利であろう。

Lisp(やMLやHaskell)が「仕事として向いている」、つまり競争力を持っているのは、 むしろ複雑度が極めて高く、かつ性能も頑健性も要求されるような 分野ではないか。DBMSとかコンパイラとか VMとかOSとか。というのは複雑度が上がるにつれ 検証の手間というのがどんどん増えてくるので、 目的に合わせた漏れの少ない高度な抽象化と、 メタ情報にアクセスして検証を自動化する手法は 不可欠になってゆくだろうと思うからだ。

(余談だが、この観点では、現在のLispはメタ情報の扱いが弱いと思う。 マクロは強力だが、ローカルなソースコードの表面にしかアクセスできない という欠点がある。つまりプログラム全域を見て演繹できる情報を利用できない。)

もちろん、そういうインフラ系に目を向けるからといって、 Lispの持つ動的な性質を活かさないということではない。 繰り返しになるが「インフラも書けるLL」であるところがポイントなのだ。 高性能で頑健なコンパイラ。でも改良したくなったらちょろっとスクリプトを 忍び込ませることができる。そういうノリである。

Paul Grahamが普通のやつらの上を行けとかもうひとつの未来への道で 「サーバ側で走るプログラムは言語の縛りが無いんだから一番強力な言語を使うべき」 と書いた頃は、一般向けサーバサイドアプリの黎明期であったこともあり、 サーバ側の階層をあまり意識せずひとくくりに論じていた。 10年経って、現実にアプリケーションはサーバ側に移動し、 サーバ側で色々なコンポーネントをどう構成するのが良いかという点に 関心は移っている。 一方で、クライアントマシン側にも計算の一部を振り分けることも一般化してきた。

現代のアプリケーションは、クライアント側とサーバ側に分散した 多数のコンポーネントが協調して動作する、分散プログラムだ。 Paul Grahamは、クライアントサイドのアプリはOSに制約されるために OSのAPIによる言語選択のバイアスを受けるとしたが、例えばクライアントサイドの JavaScriptエンジン、とかゲームスクリプティング、なんてものは OSとはあまり関係ないコンポーネントだったりする。

というわけで現在の環境では、クライアントかサーバか、という分け方よりも、 コンポーネント単位で考えるべきだろう。 独立性が比較的高く、そのコンポーネント内では極めて複雑な処理が必要で、 かつ柔軟に進化してゆくことが望ましいもの。そういうところが狙い目だ。

Tags: , Programming, Lisp

More entries ...