新・日々録 by TRASH BOX@Eel このページをアンテナに追加 RSSフィード

2016-09-19

Swift 2.2.1から3.0に更新したらSegmentation faultが多発するようになった話

Ubuntu 14.04.5にAppleSwiftを入れて遊ぼうとしていたのだが、Swift 2.2.1から3.0に差し掛かえたらSegmentation faultが多発するようになった。

$ swift
Welcome to Swift version 3.0 (swift-3.0-RELEASE). Type :help for assistance.
  1> 1 + 3
Segmentation fault (コアダンプ)
$ _

REPLで式を入力したらSegmentation faultとか、現象として直面すると――「そんな品質でリリースするようなプロジェクト・チームだなんて考えられないよなあ」という常識の壁との衝突ゆえに、非常に当惑するものである。

実のところ3.0-RCの頃から同じ現象が起きていたのだが、「リリース版じゃないからなあ」と軽く考えて、2.2.1に差し戻していた。これが、リリース版でも起きる(しかもネット上で騒ぎになっていない)となると、少々問題である。

解決の鍵となる情報は意外なところから得られた。Swiftプロジェクトの公式サイトのドキュメントを参考にhello, worldをビルドしようとしたところ、こんなエラーが発生した。

$ mkdir -p Hello
$ pushd Hello/
$ swift package init --type executable
Creating executable package: Hello
Creating Package.swift
Creating Sources/
Creating Sources/main.swift
Creating Tests/
$ swift build
<unknown>:0: error: cannot open file '/opt/apple/swift-3.0-RELEASE-ubuntu14.04/usr/lib/swift/CoreFoundation/module.modulemap': Permission denied
Can't parse Package.swift manifest file because it contains invalid format. Fix Package.swift file format and try again.
error: invalidManifestFormat
$ _

実はSwiftをホームディレクトリではなく/opt/apple配下にroot権限で手動インストールしていたのだが:

$ sudo mkdir -p /opt/apple
$ sudo tar xf swift-3.0-RELEASE-ubuntu14.04.tar.gz -C /opt/apple
$ sudo ln -s /opt/apple/swift-3.0-RELEASE-ubuntu14.04 /opt/apple/swift
$ _

どうも展開されたファイルの読み込み権限がオーナーとグループにしか付いていないようだ。

$ ls -l /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap 
-rw-r----- 1 root root 200  9月 14 06:17 /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap
$ _

オーナーとグループのどちらもrootのため、root以外のユーザでは、パッケージで提供されているモジュールなどのファイルを読み込むことができない。

どうもそれが原因ではないかと考えて、安直に全ファイルに読み込み権限を付加したところ、どうやら動くようになったようだ。

$ sudo chmod -R +r /opt/apple/swift
$ ls -l /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap 
-rw-r--r-- 1 root root 200  9月 14 06:17 /opt/apple/swift/usr/lib/swift/CoreFoundation/module.modulemap
$ swift build
Compile Swift Module 'Hello' (1 sources)
Linking ./.build/debug/Hello
$ swift
Welcome to Swift version 3.0 (swift-3.0-RELEASE). Type :help for assistance.
  1> 1 + 2
$R0: Int = 3
  2> :q
$ _

まあでも現状では、UbuntuSwiftを入れる時にホームディレクトリ以外を選択する人は少ないだろうから、この問題にハマる人なんていないだろう。

2016-09-17

プログラマと予習 事前学習はどの程度必要か?

ちょっと前の記事で、もう下火になっているから、言及してもいいか。

少なくとも、上記の記事では「プログラミング」を念頭に議論しているようだ。なのでこちらも、プログラミングに的を絞ろう。

この記事では、プログラミングにおける予習の役割・予習すべき量についての考え方・現実における予習のタイミング・予習の優先順位について書き記す。

初めての試みは必ずどこか失敗する――のを軽減のが予習の役割

器用・不器用などによる違いはあれども、全く初めてで未経験の分野に挑戦する場合、大抵はどこかしらで大なり小なり失敗を犯す結果となってしまうものだ。予習とは、未経験の分野に取り組む際に、失敗の数を減らしたり、失敗による被害を抑えるために行う作業だ。

私見だが、プログラミングにおいては、全く初めての分野に挑戦する場合、プログラマが対象について暗黙のうちに頭の中に描いているメンタルモデルが、対象についての適切な概念モデルと比較して、どれほどの差異があるのかが鍵となる。差異が小さければ、開発の初期に構築されたメンタルモデルを流用しつつ、枝葉を選定することで、対象についての適切な概念モデルに転用することが可能となる。これは、経験豊富なプログラマが取りうる手法の一つだ。しかし、差異があまりにも大きかったり、そもそもメンタルモデルを構築することすらできなかった場合には、五里霧中の状態にて手探りで物事を始めなくてはならない。プログラミング初心者が途方に暮れるのと似たことだ。

例えば、今までファームウェアデバイスドライバの開発しかしたことのない人が、急にGUIアプリケーションの開発に放り込まれた場合、少なくとも初っ端は難儀するものだ。一方で、MFCによるWindows GUIアプリケーションの開発経験が豊富な人が、急遽未経験の「QtによるクロスプラットフォームGUIアプリケーション開発」に放り込まれた場合、Qt独特の部分*1に慣れる必要はあるものの、前者ほど難儀することはない。

古典的な「OS上で動作するGUIアプリケーション」は、次のような技術要素で構成されていることが多い。

これらの要素は、使用する言語やツールキットによって細かな差異があり、それゆえに「最適なアプローチ」が環境によって異なってくる。しかし一方で、抽象化された視点では共通点が多いため、あるプラットフォームでの知見を別のプラットフォームに適用可能であることが多い。例えば「通信に時間がかかるから、UIのイベントループでブロッキングしない実装にしよう。あと、通信中は余分なボタンを押せない状態にして、通信終了したら元に戻そう」という発想は、多数のプラットフォーム通用するだろう。だが、その発想を実現するために最適なアプローチは、各プラットフォームで微妙に異なるはずだ。

全く初めての分野で、しかも近縁分野に触れたこともないとなれば、まずメンタルモデルを構築することすら不可能であるし、仮に構築できたとしても、対象についての適切な概念モデルとは全くもって異なる姿であろう。この状態――「なにも知らない」以前に「『何を知らないか』すら分からない」ままに徒手空拳で突き進むと、慣れてくるまでとんでもないソースコードを量産してしまうだろうし、下手をすると出口にたどり着くことすらできなくなる。

一方で、初めての分野であっても、近縁分野に触れたことがあるのならば、対象についてメンタルモデルを構築することは比較的容易であるし、構築されたメンタルモデルは、対象についての適切な概念モデルとの差異が比較的小さなものとなる。小手先のテクニックでなんとかなるのは、このレベルからだ。とはいえ、前述の例でいうなら、MFC的な発想で突き進んだQtアプリソースコードは、後世にて「いやいや、なんでシグナルとスロットを使って疎結合にしてくれなかったの?」とメンテナが嘆く代物と化す可能性を秘めている。

Qtを使っているのに「シグナルとスロットを使って疎結合にしてくれなかった」GUIアプリケーションは、失敗といえば失敗だが、「GUIアプリ特性を理解せずに気合いでやり抜いた努力の結晶」よりは、はるかに良い。だがQtによるGUIアプリケーションとしては、少々失敗していると言わざるをえない。

プログラマにとっての予習は、未経験分野に挑戦する際に、失敗の数を減らしたり、失敗による被害を抑えるために行うものだ。

その方法は単純だ。未経験であることによる「知識・経験の欠如」を解消すればよい。それにより、まずメンタルモデルを構築できるようになるし、欠如の解消が進めば、メンタルモデルが対象についての適切な概念モデルに近くなる。典型的な手段としては、以下が挙げられる。

  • 公式ドキュメントや関連書籍による、知識の充足
  • サンプルコードを読んだり改造したりすることによる、知識と経験の充足
  • テスト・プロジェクトなどで実際にコードを書いてみることによる、経験の充足

職業プログラマ作業のうち、公知の技術の利用においては、ドキュメントやサンプルコードを読むことや、実験用のプロダクトで実際に当該技術を使用してみることによる学習は、資料を得やすいこともあり、比較的容易だ。

予習すべき量≒(知らないことの量−近縁分野の知識や経験)×重要度×担当範囲の広さ

当該分野について未経験であることによる「知識・経験の欠如」を解消するのが予習の役割である以上、予習すべき量は「知らないことの量」に比例する。

単純な話、Prototype.jsからjQueryへの過渡期にWebクライアントサイドの開発をしていた人が数年のブランクを経てクライアントサイド開発にカムバックするのと、プログラミングすら初めての素人がクライアントサイド開発に挑戦するのでは、当然ながら前者の方が予習すべき量――まともなコードを書けるようになるために必要な知識・経験の量は少ないはずだ。

ただし、当該分野については知らなくとも、近縁分野の知識や経験があるのなら、予習すべき量は減少する(先に述べた「QtによるGUIアプリケーション開発」の例を参照)。

挑戦する分野により近い近縁分野の経験があるならば、当該分野についての断片的な情報をネットで漁ったり、サンプルコードを眺めるだけでも十分な効果を得られる。だが、今まで経験した分野が挑戦する分野から離れていくほど、書籍や「公式サイトで公開されているドキュメント・サンプルプログラム一式」などのまとまった資料が欲しくなるし、実験用のコードを書いて試してみたくなる。

予習すべき量を左右する別の要因としては、「それがどれだけ重要か?」という点がある。

重要度の1つが「それがシステムの根幹に近いか否か?」だ。例えばjQueryからAngularJS(でもReact.jsでもお好きなものをどうぞ)に移行する場合、要は「フレームワークの導入」である訳で、開発対象のクライアントサイド全体に影響を及ぼす。AngularJSというフレームワークの元での「行儀のよいコード」は、AngularJSの流儀に従ったコードだ。決してjQueryの流儀に従ったコードではない。なので、AngularJSについて重点的に予習するべきだといえる。

もう1つは、開発対象のドメイン固有の視点での重要度だ。例えば「新規開発か否か?」という点は重要だ。最初に築かれた土台が「『誤ったアプローチ』を力技で強引に使える代物に仕立て上げた(でも気づかなかった漏れが多々ある)グダグダ感あふれるもの」だと、後世に禍根を残すことになり、メンテナが発狂するものだ。スピード感は重要だが、同時に腰を据えて「そこそこ理にかなった真っ当な品質」を達成するべきでもある。

経験豊かなベテランの強みの1つは、近縁分野の経験を流用することで予習量を減らせることだ。ただしこの方法は、取り扱いを間違えると「COBOL臭いJavaのコード」や「BASIC臭いC言語のコード」のような例を生み出してしまう危険性がある。この問題を回避するためにも、対象の重要度を慎重に検討しなくてはならない。「言語の違い」が大きな影響を及ぼす点に気づく必要があるのだ。

担当範囲の広さも、予習すべき量を左右する。ここで興味深いのが、開発対象そのものの規模との関係だ。

開発対象が小規模なら、当然ながら予習すべき量は少なめとなる。ここから、開発対象の規模が大きくなっていくにつれて予習すべき量が増えていくのだが、ある段階より、今度は逆に予習すべき量が減少し始める。なぜなら、規模が増えることで、開発部隊のメンバーの増員と分業化が進むからだ。

そのため、実は大規模開発よりも、中途半端な規模の開発の方が、担当範囲が広く、予習すべき量が多かったりする。中途半端な規模なので増員もできず、少ないメンバーでシステム全体をカバーしなくてはならなかったりするものだ。

さて、「開発対象について知らないことが多く、近縁分野の知識や経験も乏しいのに、比較的重要な部分を任された上に、把握すべき範囲が意外と広い」というワーストケースでは、「本10冊」ではないが予習すべき量が跳ね上がる。

個人的な経験では、少数精鋭で組込みLinux機器の新規開発に関わった時は、明らかに業務経験だけではカバーできない分野が多かった。

開発に加わった時点で、私が業務で関わった主な技術分野は、次のような具合だった。

一方、開発で必要だった知識は、こんな感じ。

言語も違えばツールも違うとなると、徒手空拳で突っ込むのは危険であるし、ネット上の情報だけだと分散していて探すのに手間がかかる可能性がある。

いきおい書籍などの「ある程度まとまった情報源」を求めることになるのだが……ここまで幅があると、棚から一掴みで各分野ごとに2冊ほど買い求めただけで合計10冊になってしまうものだ。

だから、極端なケースでは「本10冊」という可能性はありえなくもない。もっとも「それ、マネジメント(開発者のアサイン)としてどうなのよ?」という視点での問題はあるかもしれないが。

いつ予習するか?

ここまでに述べたように、未経験の分野に挑戦した際の失敗の規模を抑えるのが予習の役割であり、今までの経験から離れていくほど予習の量が増える傾向にある。

で、ワーストケースでは比喩ではなく「本10冊」というのもあり得るのだが……はっきり言って本番直前に全部消化するのは無理である。というのも、実際に「本10冊」が起こりうるケースは、「1分野で合計10冊」よりも「5分野で合計10冊」であることが多い。要するに範囲が広すぎるのである。

ではどうするかといえば――本来は、業務の一環として必要である以上、会社として学習機会を設けるなどの対応をすべきなのだが――現状では直接業務以外の場面で知識・経験を補っている人が多いのが実情だろう。

例えば、先の私の例の場合、社内サーバの管理用にWSH + JScriptでツールを作成していた*3ので、JavaScriptECMAScript 4)の言語本体については知らなくもなかった。また、趣味でMinGWではあるがGCCGDBを触っていたし、愛用のテキストエディタVim(ただしWindows版)だった。一部の技術要素については、直接業務で深く関わったことはなかったものの、間接業務や業務外(趣味)で触れたことがあったのだ。

だから、開発に加わる時点で全く知らなかった部分(予習すべきこと)はある程度減少していたし、DOMPrototype.jsのように「基礎(JavaScript)を知っているから、リファレンス片手にぶっつけ本番でも何とかなる」レベルに力技で持ち込めた部分もあった。

もっとも、当該業務へのアサインは、そういった個人的事情とは一切無関係に決定されていた。なので、社内サーバ管理ツールVBScriptで作成していたり、趣味でMinGWではなくVisual Studio Expressを触っていたりしたら、本当に何も知らない状態でコードを書く羽目になっていたはずだ。

――ところで、こういう話はあくまで「(酒の席での)オッサンの武勇伝」に留めておくべきだ。会社組織としては、理想的には、当該分野を多少なりとも経験している人をアサインするとか、経験者と未経験者をセットでアサインしてフォロー体制を整えるとか、そういう配慮をするべきだろう。事前に何らかの形で学習機会を設けてもらえると、なおよい。趣味のような「個人の事情」に左右されることを是としていては、業務の属人化がより一層進んでしまうものだ。その人が倒れてしまったら、目も当てられない。

実のところ、ある程度ベテランになってくると、未経験の分野であっても、多少なりとも近隣分野の経験があることが多いこともあり、コードを書いているうちに段々と慣れてきて、最終的にはそこそこ理に適ったコードを書けるようになる。ではあるものの、スケジュール等の関係で「慣れる前に書いてしまっためためたなコード」は書き直されないままリリースされてしまうことが多いし、そのコードが将来の災いとなることは結構多いものだ。そういう、目に見えにくいコストも考慮すべきなのだが、そうではないのが実情だったりする。

予習の優先順位を設ける

現状では、未経験の分野について「すみません、事前に予習させてください……」と要求することが難しいことが多い*4。仮に何とか時間を捻出できたとしても、予習すべき分量をとてもまかないきれないことが大半だろう。

そうなると、予習に優先順位をつけて、優先度の高いものから手を付けることになる。

優先順位をつけるには、重要度・影響範囲・難易度・必要となる時期のバランスを勘案する必要がある。

重要度
例えばシステムの肝の部分(そこがうまくいかないと、システムとして落第点となってしまう)の予習に時間を割くのは、間違っていないだろう。
影響範囲
例えば、使用する言語・フレームワークについて誤った認識を持ったままコードを書き始めてしまうと、後で問題に気づいたときには「不適切なソースコード」が大量に存在していて、修正が大変になるだろう。事前準備に時間をかけることは、間違いとは言い難い。
難易度
時間の余裕があるなら、難易度の高い部分の予習に時間を割くべきだろう(難易度の低い部分は、最悪でも「リファレンス片手にぶっつけ本番」で何とかなる可能性が高い)。一方、時間の余裕がないのなら、難易度の低い部分を予習で総ざらいしてしまい、精神的余裕のある状態で残りの難易度の高い部分に取り組む、という方法もある。
必要となる時期
開発スケジュール後半に必要となる内容なら、優先度を下げてもよいだろう。

まとめ

  • 予習の役割は「未経験分野に取り組む際に犯してしまうだろう失敗の量の低減、失敗による被害の抑制」である。
    • 予習ですべきこと≒未経験であることによる「知識・経験の欠如」を解消することで、第一に対象システムについてメンタルモデルを構築できる状態に到達し、第二にメンタルモデルと「対象システムについての適切な概念モデル」の差異を減らす。
  • 予習すべき量は、知らないことの量に比例するが、近縁分野の知識や経験によって抑制できる余地がある。また予習すべき内容の重要度や、担当範囲の広さも影響を与える。
  • 本来は未経験分野に取り組む前に予習期間を設けるべきだが、現実には間接業務や業務外(趣味)の時間に充足している人が多いと思われる。
  • 本来は十分な予習期間を設けるべきだが、現実には期間が限られるので、予習の優先順位を設けることになる。その際には「重要度・影響範囲・難易度・必要となる時期」を考慮することになる。

予習すべき具体的な量はケースバイケースだが、一つ目安として「対象システムについてメンタルモデルを構築できること」と、「構築されたメンタルモデルがそこそこ妥当である(≒『対象システムについての適切な概念モデル』との差異が少ないこと)」あたりが参考になるのではないかと思う(少々主観的な目安だが)。

*1:「シグナルとスロット」などのQt作法(≒Qtらしいアプローチ)、Qt独自のクラスライブラリ群、Qt Creatorやqmakeなどの各種ツール。

*2:例えば、動作モードや「選択されているアイテムの種類」などによって、メニュー表示の内容を変化させるようなものなど。

*3:しかも、なぜかオライリーの『JavaScript 第5版』や『JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス』を買って言語本体の勉強をしていた。

*4個人的には、もうちょっと融通を利かせてほしいところではあるが……。

2016-09-14

書籍購入:『続・インタフェースデザインの心理学』

インタフェースデザインの心理学 ―ウェブやアプリに新たな視点をもたらす100の指針』の続編。続編なので、できれば前書も読みましょう。

前書と同じく、認知心理学から見たインターフェースのデザインについての本。人間の脳が物事をどう認識するかについて平易に説明されていて、そこからインターフェースをデザインする時に留意すべき指針が導かれている。

基本的には、前書以降に発見された知見についてまとめられている。本書は『インタフェースデザインの心理学』のアップデート(改訂)ではなく、あくまでも続編なので、できれば両方とも読むほうが良い。どちらも読みやすく、分量もそれほど多くないので、両方読んでも大丈夫だろう。

2016-09-09

ANOMALY: use of REX.w is meaningless (default operand size is 64)

Windows 10に移行してから、私の環境ではコマンドプロンプトでコンソールアプリを使う度に、高い確率で次のようにエラーメッセージが出力されるようになった。

[0x7FFFB4DF70E3] ANOMALY: use of REX.w is meaningless (default operand size is 64)

ただし上記のメッセージが表示されるだけで、コマンド自体は正しく実行される。

興味深いことに、Windows 10標準の外部コマンド(例えばpingipconfig)でも発生する。またコマンドプロンプトからGUIアプリ(例えばメモ帳)を起動する場合には発生しない。

C:\tmp>ping -n 4 -w 100 192.0.2.12
[0x7FFD1AEC70E3] ANOMALY: use of REX.w is meaningless (default operand size is 64)

192.0.2.12 に ping を送信しています 32 バイトのデータ:
192.0.2.12 からの応答: バイト数 =32 時間 <1ms TTL=64
192.0.2.12 からの応答: バイト数 =32 時間 <1ms TTL=64
192.0.2.12 からの応答: バイト数 =32 時間 <1ms TTL=64
192.0.2.12 からの応答: バイト数 =32 時間 <1ms TTL=64

192.0.2.12 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 0ms、最大 = 0ms、平均 = 0ms

C:\tmp>notepad.exe

C:\tmp>_

エラーメッセージ中の「REX.w」はx86-64絡みのオペコードだ。実際に、この問題は32bit実行ファイルでは発生せず、64bit実行ファイルで発生する。

試しにC言語でhello, worldを書いてみたが、MinGW-w64(gcc 6.1.0)やVisual Studio 2013でビルドした64bit実行ファイルでは同じ症状が見られた。一方で、Visual Studio 2013でビルドした32bit実行ファイルでは起きなかった。

原因は不明だが、とりあえずWindows 10移行時に人柱としてインストールしたウイルスバスタークラウド11を終了させると、上記の症状は発生しなくなる。設定でリアルタイムスキャンを停止しただけでは駄目だったので、起動したプロセスに対するヒューリスティック(ふるまい)検知あたりで問題が起きているのではないかと妄想している。

複合的な要因によるものかもしれないので断言はできないが、少なくともウイルスバスタークラウド11が(結果的に)片棒を担ぐ感じになっているようだ。

悩ましいことに、これが原因でGit for Windows 2.10.0 64bitのGit GUIの起動に失敗しまう。一方でgitkの起動は大丈夫なようだ。gitコマンドも、リポジトリ操作系のコマンドでは上記エラーメッセージが発生して煩わしいのだが、「git --version」などでは発生しない。どういうことだろう?

さて、どうしようか? 試しにウイルスバスタークラウド10に入れ替えてみるか、ウイルスバスターをこまめにON/OFFするという運用に徹するか、他の逃げ道を探るか。

追記:2016-09-12

コメントをいただいたとおり、ウイルスバスタークラウド11の例外設定に追加することにした。

本来は安全のためにも個々の実行ファイルごとに例外設定を追加すべきだが、対象となる実行ファイルが分からなかったため、「<Git for Windowsインストール先>\mingw64\libexec\git-core」というフォルダを丸ごと除外した。これでGit GUIの問題は回避できるようだ。

追記:2016-09-24

Cygwin付属のirbも動作しなくなっていた。irbREPLに入らずに終了してしまう。

この問題は、Cygwin付属のruby.exeだけウイルスバスタークラウド11の例外設定に追加することで回避できるようだ。

2016-08-28

改訂版:WindowsにNode.jsを手動インストールする方法

id:eel3:20140309:1394294944 から若干状況が変化したようで、Node.jsWindowsに手動インストールする方法がほんの少しだけ楽になった。

以前の方法では、node.exeとnpmのアーカイブを別々に取得してセットアップしていたのだが、いつの間にかnode.exeとnpmが一緒になったアーカイブが配布されるようになっていた。そこで、そのアーカイブを使うことにする。

  1. 公式サイトダウンロード一覧にアクセスする。
  2. LTSかCurrentか、使用したいものを選択する。
    • 今回はv6.4.0 Currentを使用するものとする。
  3. ダウンロード一覧のページの「All download options」というリンク経由で、ダウンロード可能なファイル一式にアクセスできる。この中から「node-<バージョン番号>-win-<x64ないしx86>.zip」のような名前のファイルをダウンロードする。
  4. ダウンロードしたアーカイブ・ファイルを展開する。アーカイブ・ファイル名から拡張子を除いた名前のフォルダに展開されるので、そのフォルダ名を「node」のような名前に変更する。
  5. 前述の展開されたフォルダを任意の場所に移動する。
    • 今回はCドライブ直下に移動する(結果として「C:\node」ができる)。
  6. 環境変数Pathに、前述のフォルダ内のnode.exeが置いてある位置のパスを追加する。
    • 今回は「C:\node\node.exe」なので、環境変数Pathには「C:\node」を追加する。
  7. 環境変数NODE_PATHを追加し、node_modulesのパスを登録する。
    • 今回は「C:\node\node_modules」。node_modulesはnode.exeと同じパスに置いてあるはず。
  8. 最後にnpmを最新版にする(公開されているアーカイブが最新版だとは限らないため)。「npm update -g」でOK。

だいたいこんな感じになっているはず。

C:\node
|   CHANGELOG.md
|   LICENSE
|   node.exe
|   npm
|   npm.cmd
|   README.md
|
\---node_modules
    \---npm

# NODE_PATH=C:\node\node_modules

若干ファイルが増えているものの、node_modules・node.exe・npm.cmdの配置場所は、以前の手動インストール方法と同じになる。

この構成で「npm install -g <some-package>」とオプション `-g' 付きでパッケージをインストールすると、「C:\node\node_modules」直下にパッケージのフォルダが作成され、その中にファイル一式が配置される。

Node.jsは、デフォルトでは「C:\node\node_modules」直下のパッケージを認識しない。環境変数NODE_PATHで登録する必要がある。

後でNode.jsバージョンアップする方法は?

後でNode.jsバージョンアップしたくなった場合には、公式サイトからnode.exe単体をダウンロードして、C:\node\node.exeに上書きしてしまえばよい。

npm本体は「npm update -g」で更新できるので、わざわざ手作業で差し替える必要はない。