ソフトウェア開発」カテゴリーアーカイブ

eclipseの起動に失敗する (解決)

昨日のエントリーで書いたeclipseのエラー。
ある程度詳しく書けば、きっと誰かの目に留まるはずっ!!って言う他力本願寺な考えで書いたのですが願ったりかなったり。
コメントに書いてもらえました。

Extensionsのrename

昨日読むのをめんどくさくて辞めてしまったURLにこのエラーの回避方法が書いてあったようです。

I’ve encountered the same error as the original poster,
using eclipse-java-helios-SR1-macosx-cocoa-x86_64.tar.gz on Mac OS/X 10.6.4
with JavaForMacOSX10.6Update2.dmg installed (java version “1.6.0_20” as
reported by java -version).

There was nothing in ~/Library/Java/Extensions, nor in
/Library/Java/Extensions.
However, in /System/Library/Java/Extensions I found a number of files.
I took the step of renaming /System/Library/Java/Extensions to
/System/Library/Java/Extensions.old, and then tried launching “eclipse -clean”
again.

This time it worked. Hope that helps somebody.

(https://bugs.eclipse.org/bugs/show_bug.cgi?id=318046#c22)

平たく言うと、Java/Extensionsフォルダを名前変更してcleanしやがれ!ってことらしい

f:id:krote:20110719005837p:image

早速、名前を変更してターミナルからcleanオプションつけて起動してみたら、ちゃんと起動した。
うーん、なんだろう?Extensionsフォルダにある何かが悪さをしているのだろうか??
ちょっと原因そのものは謎だ。
これ、名前変更したままでいいんだろうか・・・

Scala IDEのインストール

Eclipseがなんとか動いたので、早速Scala IDE をインストールする。

PluginのインストールはHelpメニューからInstall New Softwareを選択する

f:id:krote:20110719005838p:image

今回追加するのはScala IDE。

Scala IDE
http://download.scala-ide.org/

これを見る限りだと、「Recommended for most users」とされているのがBETA RELEASES RELATIVE TO SCALA 2.9.0-1になっているので素直にこれに従ってみる。
それにしてもBetaが推奨されるというのは、ちょっと違和感を感じるのだが・・・大丈夫であろうか。

f:id:krote:20110719005839p:image

全部インストールしていくと、New Projects の選択肢としてちゃんとScala Projectが出てくるようになった

f:id:krote:20110718180229p:image

とりあえず、「ちゃんと動くのかよ、これ?」ってことでHello, Scalaなんぞを作ってみたりしたが、動いているようだった。

object Test {
def main(args:Array[String])
{
println(“Hello, Scala”)
}
}

>Hello, Scala

いやいや、実際は

トントン拍子に行ったように書いているScala IDEのインストールだが、実はこれにもちょっとハマった。
指定したURLを、最初参考にしていたURLに従って入力を行ったのだがそれがずいぶんと古い記事でScala 2.7がインストールされてしまった。さらにその後で2.9を入れたりしたらまともにビルドできない状態になってしまったのだ。
Pluginを消してみたりもしたけどうまく行かず、最終的にはEclipseフォルダごと消して、もう一度やり直してみたらうまく行った。

うーん、なんだかIDEそろえるだけでここまで手間がかかるとは思っていなかったので、少し疲れたなぁ
ま、何はともあれ環境がようやくそろったので、もうちょっと遊んでみよう。

eclipseの起動に失敗する

Scalaの本を読み続けているのですが、REPL上ではミスが許されないのでそれなりの規模のコードを書くのはつらい。
という訳でIDEを利用しての開発を行おうと考え、手っ取り早くすみそうだと感じたeclipseをインストールしようとしているのですがうまく行かない。

Macへのeclipseインストール

ネット上を見る限りでは、Macへeclipseをインストールするのは何も難しいことではなく

  1. ダウンロード
  2. 解凍
  3. eclipse.appのダブルクリック

で終わるように思う。
これは、Windowsと異なりMacでは最初からJavaがインストールされているためにそれらのことを考えなくていいかららしい。

どこにもミスが介在するような余地が残されていないように感じるのだが、起動しようとするとエラーが発生してしまい起動が出来ないのである。

とりあえず状況の整理だ

まずは、障害対策の基本に立ち返って現状の整理を行う。

  • Javaのバージョン

javaが正しく認識できるか?また、バージョンはいくつだろうか?
確かめるためにはターミナル上で「java -version」で確認が出来る

java version “1.6.0_26”
Java(TM) SE Runtime Environment (build 1.6.0_26-b03-384-10M3425)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02-384, mixed mode)

うん、一応認識しているね。
まぁ、この辺りはMacの場合はユーザー側ではなくApple側が管理しているゾーンのような気がするのでそんなに心配はしていないんだけど。

  • ダウンロードしているファイルが間違っていないか

次にありがちなのが、一生懸命インストールしようとしている対象が間違っているというオチ。
MacOSなのにWindows版をインストールしようとしていたり32bitOSに64bitOS向けのものを利用していたり・・・だ。

私が利用している2011年に新発売されたモデルのiMacはデフォルトで64bitが利用されているようだ

Mac OS X v10.6:64 ビットのカーネルを使う Mac
http://support.apple.com/kb/HT3770?viewlocale=ja_JP

念のためにシステムプロファイラを起動してみても、「64ビットカーネルと拡張機能」項目は「はい」になっている。
先のjavaバージョン情報を見ても、64-Bit Server VMとなっているし64bitでいいようだ。

最新のIndigoはこちらからダウンロードが可能なので、MacOSX向けの64bit版を選ぶことになる

Eclipse Downloads
http://www.eclipse.org/downloads/

やりたいのはScalaなので何でもいいのかもしれないが、Javaが入っているにこしたことは無いので「Eclipse IDE for Java EE Developers」を選択してダウンロード。解凍する

やっぱりエラーになる

解凍したEclipse.appを起動すると、エラーになってしまう。

f:id:krote:20110718004949p:image

ログの中身を全部出すと長くなってしまうのだが、かいつまんで出せるほど詳しくもないので出してみる。うまく行ってない人間が中途半端な情報を出すとろくなことが起きないので。

!SESSION 2011-07-18 00:44:05.827 ———————————————–
eclipse.buildId=I20110613-1736
java.version=1.6.0_26
java.vendor=Apple Inc.
BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=ja_JP
Framework arguments: -product org.eclipse.epp.package.jee.product -keyring /Users/krote/.eclipse_keyring -showlocation
Command-line arguments: -os macosx -ws cocoa -arch x86_64 -product org.eclipse.epp.package.jee.product -keyring /Users/krote/.eclipse_keyring -showlocation

!ENTRY org.eclipse.equinox.p2.core 4 0 2011-07-18 00:44:07.140
!MESSAGE Provisioning exception
!STACK 1
org.eclipse.equinox.p2.core.ProvisionException: Unknown repository type at file:/Users/krote/Dev/eclipse/configuration/org.eclipse.osgi/bundles/281/data/listener_1925729951/.
at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.fail(AbstractRepositoryManager.java:393)
at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.doCreateRepository(AbstractRepositoryManager.java:282)
at org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager.createRepository(MetadataRepositoryManager.java:41)
at org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener.initializeMetadataRepository(RepositoryListener.java:109)
at org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener.<init>(RepositoryListener.java:59)
at org.eclipse.equinox.internal.p2.reconciler.dropins.DropinsRepositoryListener.<init>(DropinsRepositoryListener.java:82)
at org.eclipse.equinox.internal.p2.reconciler.dropins.Activator.watchDropins(Activator.java:532)
at org.eclipse.equinox.internal.p2.reconciler.dropins.Activator.start(Activator.java:172)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:389)
at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1130)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:559)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:544)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:457)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:243)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:438)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:1)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)
!SUBENTRY 1 org.eclipse.equinox.p2.metadata.repository 4 1005 2011-07-18 00:44:07.140
!MESSAGE Unknown repository type at file:/Users/krote/Dev/eclipse/configuration/org.eclipse.osgi/bundles/281/data/listener_1925729951/.

!ENTRY org.eclipse.equinox.p2.reconciler.dropins 4 0 2011-07-18 00:44:07.142
!MESSAGE FrameworkEvent ERROR
!STACK 0
org.osgi.framework.BundleException: Exception in org.eclipse.equinox.internal.p2.reconciler.dropins.Activator.start() of bundle org.eclipse.equinox.p2.reconciler.dropins.
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:734)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:389)
at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1130)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:559)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:544)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:457)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:243)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:438)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:1)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)
Caused by: java.lang.IllegalStateException: Could not create metadata repository for: file:/Users/krote/Dev/eclipse/configuration/org.eclipse.osgi/bundles/281/data/listener_1925729951/
at org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener.initializeMetadataRepository(RepositoryListener.java:112)
at org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener.<init>(RepositoryListener.java:59)
at org.eclipse.equinox.internal.p2.reconciler.dropins.DropinsRepositoryListener.<init>(DropinsRepositoryListener.java:82)
at org.eclipse.equinox.internal.p2.reconciler.dropins.Activator.watchDropins(Activator.java:532)
at org.eclipse.equinox.internal.p2.reconciler.dropins.Activator.start(Activator.java:172)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
… 12 more
Root exception:
java.lang.IllegalStateException: Could not create metadata repository for: file:/Users/krote/Dev/eclipse/configuration/org.eclipse.osgi/bundles/281/data/listener_1925729951/
at org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener.initializeMetadataRepository(RepositoryListener.java:112)
at org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener.<init>(RepositoryListener.java:59)
at org.eclipse.equinox.internal.p2.reconciler.dropins.DropinsRepositoryListener.<init>(DropinsRepositoryListener.java:82)
at org.eclipse.equinox.internal.p2.reconciler.dropins.Activator.watchDropins(Activator.java:532)
at org.eclipse.equinox.internal.p2.reconciler.dropins.Activator.start(Activator.java:172)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:702)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:683)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:381)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:389)
at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1130)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:559)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:544)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:457)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:243)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatc
hEvent(StartLevelManager.java:438)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:1)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)

!ENTRY org.eclipse.osgi 4 0 2011-07-18 00:44:07.529
!MESSAGE Application error
!STACK 1
org.osgi.service.application.ApplicationException: No application id has been found.
at org.eclipse.equinox.internal.app.EclipseAppContainer.startDefaultApp(EclipseAppContainer.java:262)
at org.eclipse.equinox.internal.app.MainApplicationLauncher.run(MainApplicationLauncher.java:29)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:344)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
at org.eclipse.equinox.launcher.Main.run(Main.java:1410)

さてはて。気になるところとしては最初に発生している「org.eclipse.equinox.p2.core.ProvisionException: Unknown repository type at file」ですよね。
ただ、だからどーせいっちゅーねん!って感じ。

Javaのバグなのか?

ちょっと気になるものを見つけた

https://bugs.eclipse.org/bugs/show_bug.cgi?format=multiple&id=318046

うーん、コメント長いwwww

読んでいけばわかるのだろうか。今日はちょっとここまでにしよう。
ただ、「Scalaがしたい」のであって「Eclipseを使いたい」という訳ではない。
なので、いっそのこと違うIDEを利用するということも視野に入れるべきなんだろう。
こんなことに多大に時間を費やしてしまっていてなんだかバカバカしくなってきてしまったし・・・。

というわけで、続かないかもしれません><

文字コード技術入門

ちょっと前から気になっていた本を読んだ

基礎、基礎、基礎

私のように、会社に入ってからプログラムを触り始めた人間は、基礎の積み上げがない。普通であれば、早期にそれらを積み上げて行くんだろうけど、私の適当な性格が災いして結局のところまともな基礎ができていない。
そのせいで、結構苦労していたりする。ただ、それはわかっていても基礎はめんどくさいものだ。

本書が題材としている「文字コード」に関してもやはりそういう基礎の一つだろう。以前どこかのブログか雑誌で紹介されており、プログラマなら必読だ!みたいなことが書いてあったのを覚えている。プログラマってひとくくりにして必読って言うのもなんだかなぁという気がしないではない。
ある程度のところまでは適当にかじった程度で通じるんだけど、それ以上になるとちょっと頭がこんがらがる。そんな内容だ。

前半の文字コードがこれまでどういう変遷をたどってきたのかということに関しては、興味がなければ飛ばしてしまうのが一番のように思える。
なんとなくの文字コードの現在の形。そして、各コード体系間の変換において何が問題となるのかを把握しておくのが大事なんだろう。
。。。
って、そうやって飛ばすと基礎にならないかな。。。?

偶然にも

偶然の産物であるが、本書を読んでいるうちにたまたま文字コードに起因するトラブルを2回ほど経験した。一つはShift_JISから中国の簡体字であるGB2312へのコード変換。
もう一つはありがちではあるがShift_JISとUnicodeとのコード変換時に発生する波ダッシュにまつわる問題。

本書を読んだからと言って直接的な解決に結びつくわけではないんだけど、何が起きているのか?と言うことの理解には間違いなく貢献してくれた。
そういう意味では個人的にはとてもタイムリーでよかったが、そういうことがなければ結局使う場面がなくて忘れてしまったかもしれない。。。

文字にまつわるプログラミングをする人にとっては結構大事な技術要素ではあるんだけど、そんなに複数の異なるコード体系を用いたプロジェクトに従事していなければ、あまり意識しなくてもなんとかなってしまうのもまた事実かと。
人それぞれってところなんでしょうね。

VSSからSubversionへの移行

社内でVSSによって管理されていたプロジェクトがいくつかあったんだけど、それを一気にSubversionで管理しましょうということになった。
理由としては、一部管理されているファイルをSJISではなくUTFにする必要性があったのだが、VSSの相違点比較ではUTFの比較が対応されてなかったのが一因。
また、チェックインからの環境への配置をできるだけ自動化したいという試みがあったためである。

VSSからSubversionへ移行するにはss2svn.exeを使う方法があるらしいが、Webで見ている限りではうまく言ってないようだ。
それに代わるものとして、ss2svn.plを利用した方法が紹介されていたが、これが思ったようにはいかずにずいぶんと手こずってしまったのでまとめたい。

参考サイト

前提

  • VSSのバージョン
    • VSSはちょっと古いVisualStudio6のもの。ただ、基本的にはVisualStudioの後継でもそんなに大きな変更はないのではないかと思っている。VisualStudio2008はUTFに対応しているらしい(未確認)ので、もしかしたら構造が違うのかもしれない。
  • Subversion
    • 面倒なのでTracLightningを利用している

インストールするもの

  • ss2svn.pl
  • ActivePerl
  • JCode(パールモジュール)
  • File-MMagic(パールモジュール)
    • JCodeとFile-MMagicはPPMを利用すると楽

C:\>ppm install Jcode
C:\>ppm install File-MMagic

準備

  • PATHにVSSのパスをセットする

SET PATH=%PATH%;C:\Program Files\Microsoft Visual Studio\COMMON\VSS\win32

  • SSDIRにVSSのレポジトリをセットする

SET SSDIR=\\SERVERNAME\REPO_PATH
※「\\SERVERNAME\REPO_PATH」はVSSのデータディレクトリへのパス

  • SSJP.DLLの退避(VSSフォルダのWin32内のSSJP.DLLをリネームする)

実行

  • 1.移行先のSubversionインストールサーバーにてレポジトリを生成する。
    • TracLightningを利用していると、通常はTracまで作られてしまうのでsvnadminコマンドでSubversionのレポジトリのみ作る。ここでTracまで作ってしまってもいいのだが、この場合はTrac上のタイムラインが、すべて移行実行日のコミット扱いになってしまう。

svnadmin create E:\TracLight\project\hoge

  • 2.pre-revprop-change.bat設定
    • 中身をexit 0のみにしたpre-revprop-change.batをsvnのhooksに入れる。怖いからsvnのレポジトリフォルダにも入れておいた
  • 3.Subversion側にユーザーを追加
    • 予め、VSS側に登録されていたユーザーを登録しておく。この時、例え実際には違ったとしてもユーザ名とパスワードを同一にしておくと楽
  • 4.ss2svn.plの認証部分を変更する
    • 1462行目付近でSvnへのログイン認証設定があるのでここを改変する。

$cmd = “$cmd –username \”$self->{user}\” “
. “–password \”$self->{password}\””;

$cmd = “$cmd –username \”$self->{user}\” “
. “–password \”$self->{user}\””;

に変更。認証を通すようにした

  • 5.ss2svn.plを実行する

vss2svn.pl –vssproject $/REPO/NAME –svnrepo http://REPO/URL –setdates –utf8 –vsslogin”admin;”
※「$/REPO/NAME」は移行対象のプロジェクトへのSSDIRからの相対パス
※「http://REPO/URL」は移行先Subversionのレポジトリへのパス

よくわからないが、–vsslogin設定がないと反応なしになった

  • 6.TRACの作成
    • create-project.batを一部改編してcreate-project2.batを作る。以下の2行を削除

if exist “%TL_PROJECT_HOME%\svn\%PROJNAME%” goto :EOF
svnadmin create “%TL_PROJECT_HOME%\svn\%PROJNAME%”

コマンドでプロジェクト作成

C:\>create-project.bat hoge

後処理

・SSJP.DLLを元に戻す

苦労した点

一番手こずったのはss2svn.plを実行時にFATAL ERRORが発生したこと。これが何度やっても同じバージョンで失敗する。
VSSのデータが破損しているのかと疑いをかけ、VSSのDataフォルダに対してAnalyzeコマンドを実行してみると「一貫性エラーが発生した」と出た。
AnalyzeでVオプションを追加しても意味なかったけど V4オプションを追加して実行してみると、問題となったファイルが発覚。どうやら、バージョンの途中でSJISからUTFに変換したファイルが、相違点をチェックしようとした際に問題を起こしていたみたい。
幸い、そういうファイルは少なかったのでこれは移行後に手動でコミットする形にして実行したら実行できた。

言語の比較

久しぶりにDBマガジンを読んでみた。

今月号の特集では同一のWebアプリを4言語で開発をしてみてその比較をすることでより言語別の特色を把握しながら勉強しようというもの。選ばれている言語は

  • Java(Struts2)
  • .net (.NET ASP)
  • PHP(CakePHP)
  • Ruby(Rails)

それぞれの言語を利用して開発をする…という発想自体は面白いもので、期待してみたのだがちょっと無理やり枠におしこめた感があって、中途半端になってしまっている気がした。
まぁ、そもそも雑誌の一特集でそれらすべてを網羅しようということ自体に無理があるのかもしれない。

個人的には今回紹介されている内容は、どれも中途半端な知識しかないので少しは押さえておきたいところ。仕事で今使わないからどうしても割ける時間は限られてしまう。
かといって、本を読んだだけで自分でコードが書けるようになれるほど自分は器用ではない。
必然的にどれかに絞って学んでいかなければ・・・って、そもそも自分自身今やっていることもあるし。うむむむ

器用貧乏になりそうだ。
とりあえず、今は自分の仕事をこなしつつ次なる目標やプロジェクトを温めていくことに徹するのがいいのかもしれません

分からないとしてしまってはいけない

今日は久々にCをいじっていた。
久々といっても自分がかかわったことのないプロジェクトの産物で、しかもC++から始めたようなものである私にとってCはどちらかというとなじみのない言語。
カタコト的に取り扱っているレベルだ。

問題が起きている個所に対して調査用のログを出力するように変更してコンパイル実行。
ところが、リンカが文句を言いだす。

エラー LNK2001 外部シンボルXXXXが未定義です

見よう見まねで用意されたmakefileを使用してnmakeしているだけなのだが、うまくリンクができていないようだ。
書き換えた部分が問題とも思えなかったが、一応元に戻して実行しても同じエラーが出てしまう。
つまり、最初から用意されていた環境が悪かったことになる。エラーとされている関数はデバッグ用に使われている関数のようだが、そもそもリリース用にコンパイルしているので使っていないはずなのだが…。

当該ファイルは10年以上前のプロジェクト。当然移り変わりの激しい社内にこのプロジェクトに詳しい人間はいない。
これは困った。どうしていいかわからない

分からないのか。考えてないのか

さて、今回困ってしまったのは

  • 自分の関わったことのないプログラムだった
  • そもそもCに自信がない
  • プロジェクトに詳しい人間がいない
  • 変更前の状態であっても動かなかった
  • これまではそれで動いていた?

等々の理由があったのだ。
結論から言うと、今回の問題は、複数のmakefileのうち、いくつかがリリース用のコンパイル時にまでデバッグとしてコンパイルするような文言が記述されていたことにあった。
恐らく、何かの調査のタイミングで一時的にmakefileを変更したものの、それを元に戻さずにいたことが今回の問題を引き起こしたのだと思う。

だが、今回解決できたのは論理的に答えを見つけたというよりはどちらかというと”手探りで”とか”手当たり次第に”的な手法によったもの。
後々考えてみると、

  • リンクのエラー
  • 当該関数はデバッグ用のものと思われる
  • makefileが正しいことを証明できる人間がいない
  • リリース用のコンパイルオプション指定にもかかわらずデバッグ用関数が混ざる

等の事柄から、

  • 変更したオブジェクト周りのmakefileに何かしら問題がある
  • 変更したオブジェクト周りにDEBUG条件付きコンパイル以外の個所でデバッグ用関数が用いられている

可能性を考え、答えに結びつけることはできたはずだ。
それを行わずに思考停止してしまったのは問題だ。

自分にとって不利な状況だとか、逃げ口上になりそうな内容があるとすぐにそちらへ行こうとしてしまい思考が停まってしまう。いけない傾向にある。
忙しいことは言い訳にはならないので、しっかりと。頭を使うよう教訓として覚えておこう。

見積もりに対する考察

昨日に引き続きアート・オブ・プロジェクトから

アート・オブ・プロジェクトマネジメント ―マイクロソフトで培われた実践手法 (THEORY/IN/PRACTICE)
Scott Berkun
オライリー・ジャパン
売り上げランキング: 96079
おすすめ度の平均: 4.5

5 バイブルにしています
4 プロジェクトマネジメントに関する教科書的な一冊
5 プロマネ、必読
4 プロジェクト大災害で大炎上
5 真のマネジメントがここにある

精度か正確さか

見積もりの精度はよく問題にはなるが、どれだけ精度が高くても正確でなければ意味が無いというのが本書で言わんとするところだ。ここで言う”精度”とは数字上の精度。
言ってしまうと、小数点桁何桁まで出した数字だろうと、その出す過程が根拠を伴って出されてない限り、何の意味も持たないってことだ。では、根拠のある数字を出す過程とはどんなものだろうか。

ソフトウェアの開発では、いわゆる機械による大量生産のように同じものをひたすらに作るわけではなく、常に一品モノの物作りとなる。
時には技術的に不明確な部分に対して切り込まなければならない開発。。。というよりは”研究”に近いのかもしれないこれら作業を正確に見積もることなんてできるのだろうか?
しかし、お客様に「いくらかかるか分からないし、いつ完成するかわからないけど頑張ります」なんて言った途端に「それじゃ、いつ発注するかわかんないよ?」なんて言われてしまうかもしれないわけで、なにかしら見積もりはしないといけない。

規模が小さい開発であればそこそこの正確さを持った見積もりが出てくるが、規模が大きくなればなるほど見積もり誤差は大きくなる。自己負担分も増えていく。(デスマーチの)鼓笛隊の歩む音が聞こえてきそうだ。

これは経験にゆだねるしかないのだろうか。

一つの答えとしては多分そうなんだろう。ただし、その”経験”は、”会社としての経験”であって”個人としての経験”であっては困るわけだ。
見積もりに対する根拠・仮説を記録しつつ、結果を検証することを繰り返す必要がある。これは積もり積もったデータベースとして、組織の財産としての扱いを受けるべきだろう。

そもそも誰が見積もるのか

ここまで書いて、ふと思ったのは、”見積もりをしているのはだれなのか?”という事だ。
これは”仕様や設計を行っているのはだれなのか?”という事に置き換える事も出来るかもしれない。

本書では見積もりの精度に関して”優れた設計から生み出される”としている。

優れた見積もりというものは、信頼性の高い設計と要求が揃って初めて生みだされるという事です。そしてエンジニアリングにおける優れた情報と優れたエンジニアという2つが揃って初めて生みだされるのです。(P.40)

そんなに多くの事例を見たことがあるわけではないので断言できるわけではないのだが、見積もりや設計を行うのは実際にコーディングを行うプログラマーやプログラマーのリーダーではなく、”過去にプログラムを組んでいた管理職”か、”プログラムを組んだことのない管理職”が多いのではないだろうか?
そして、何かしらの根拠があって見積もっているわけではなく、感覚論で見積もってしまっているのではないだろうか?

そうであるならば、見積もりはリーダーだけでなくプログラマ、品質を管理する担当者(テスター含む)等にも参加してもらい、そもそも出来あがる機能が、業務的に本当に有益な形でお客様に提供できるようになっているのか?等、様々な角度から求め
ていかなければいけないだろう。

ただ、未受注の機能に対してここまで大がかりな見積もり体制を築き上げてしまうと、実は中小のソフトウェア会社では回らなかったりする。要するにお金になるのか分からない作業に対して人を割り当てる余裕が無いということだ。もちろん、そういう企業の場合はプログラマからテスターまで多くの作業を兼任するので必然的に少人数にはなるだろうが、それはそもそも人が足りないわけで、逆にノリで見積もりをしそうだ。

私が所属している組織において、本書でいう”正しい見積もり”が完全に機能しているとはとても言えない。見積もりが個人のスキルによってしまい、引き継ぎも出来ないうえに当たり外れが出始めている。
銀の弾丸が無いとはいえ、組織内において蓄積された基準や、見積もる上でのプロセスを見直す必要がある。
動かなければいけないな

マイクロソフトのプロジェクトはアートなのか

このプロジェクトマネジメントを続けてはだめだ!!もういい加減に成長しなければいけない。
そんな思いからアート・オブ・プロジェクトマネジメントを読んだ

アート・オブ・プロジェクトマネジメント ―マイクロソフトで培われた実践手法 (THEORY/IN/PRACTICE)
Scott Berkun
オライリー・ジャパン
売り上げランキング: 96079
おすすめ度の平均: 4.5

5 バイブルにしています
4 プロジェクトマネジメントに関する教科書的な一冊
5 プロマネ、必読
4 プロジェクト大災害で大炎上
5 真のマネジメントがここにある

目次

  • 計画
    • スケジュールの真実
    • やるべきことを洗い出す
    • すぐれたビジョンを記述する
    • アイデアの源
    • アイデアを得た後にすること
  • スキル
    • 優れた仕様書の記述
    • 優れた意思決定の行い方
    • コミュニケーションと人間関係
    • メンバーの邪魔をしない方法
    • 問題発生時に行うこと
  • マネジメント
    • リーダーシップが信頼に基づく理由
    • ものごとを成し遂げる方法
    • 中盤の戦略
    • 終盤の戦略
    • 社内の力関係と政治

そもそもなぜソフトウェア業界はこんなにもプロジェクトマネジメントを声高にする必要があるのだろうか。
事業規模で考えれば他業界でもっと大きなプロジェクトはたくさんある。もちろん、それらプロジェクトがすべからく成功を収めているかというとそうとは言い切れない部分はあるが、、、

本書はプロジェクトマネジメント全般にわたって書かれてはいるが、ここではこの頃私を悩ませている仕様書に関しての話題に言及したい

仕様書は必要か?

本書ではプロジェクトに必要となる書類として以下のものを定義している

  • 要求仕様
    • プロジェクトに期待される様々な物事を文書化するため、作業によって達成されるべきすべての要求と責任の概要を記述する
  • 機能仕様
    • 顧客の視点から見た特定のシナリオやシナリオ群における振る舞いや機能を記述したもの。ソフトウェアの機能をユーザーインターフェースを通じて解説し、なるべく技術的な詳細に踏み込まないようにしつつ、物事の動作方法を解説する。要求の一覧ではなく、それを実現するための機能の一覧。
  • 技術仕様
    • 機能仕様を満足するために必要となるエンジニアリングアプローチの解説。もっとも複雑なコンポーネントや、他のプログラマが再利用する可能性のあるコンポーネントを開設したり、機能仕様に必要な作業項目に対して技術的な裏付けを提供できるだけのレベルで十分。
  • 作業項目一覧(WBS)
    • 機能仕様を満足するために必要となるプログラミング上のタスクを解説したもの。
  • テスト基準とマイルストーン達成基準
    • 各テストケースの優先順位と、各マイルストーンにおける品質目標を満足するためには、コードが該当テストケースにおいてどの程度正しく動作する必要があるのかという目標。

私のこれまで携わったプロジェクトでは、要求仕様や機能仕様を合わせて外部仕様書と読んだり、機能仕様と技術仕様がごちゃっとなって内部仕様書と読んだりしていた。ちなみにWBS、テスト基準等はそれぞれの文書として独立させることになる。
恐らく本書で述べられているこれら内容は別に独立した文書である必要はなく、それらを網羅するべきということなんだろう。

私の場合は転職経験があるわけでも、大学でソフトウェア関連のことを学んだことがあるわけではないので他にどういう形の文書があるのかは知らないのが現実だ。
内部仕様書に記述する技術仕様は、どの程度まで記述するのかが問題となるのではないだろうか。仕様書を書くことが本来達成するべき仕事ではないので、これらの切り分けをどうしていくのか…。内部仕様書に関しては、社内の誰に対して文書を書くか?ってことになるのかもしれないなぁ

仕様書と設計書の違い

設計段階では仕様は固まっていない。未確定な内容が含まれており、それに対する議論や検証を行う必要がある。それらを経て、実際のモノづくりを行う作業の前に仕様書を作るべき。
設計書と仕様書を同時に作成しようとした場合、設計の変更に伴う仕様書の修正工数ばかりが増大していき、仕様書は意味のあるものとして成り立ちづらい。もしくは計画そのものが破たんする。これらは全く別のプロセスとして動かす必要があるだろう。

ううん、言っていることは分かるが…。
実際のところ、現場では設計書と内部仕様と作業指示がめちゃくちゃになっている。内部仕様書が正しく仕様書としてなりたっておらず、中途半端な設計書になっているだけだった。
だからこそ、”何の文書を書くのか”ということが明確になっておらずに、文書の作成に行き詰ってしまっているのだと思う。
そう考えると、これらを全く別のプロセスとして捉えて取り組むというのは分かる話ではあるのだが…。
ううん、時間がないっていう言い訳をしてはいけないのは分かるが時間がない。時間を捻出する手立てを立てなくてはいけないなぁ

多くのすぐれた仕様書では、設計が階層に分けられた上で記述されている。まず最初に、顧客のエクスペリエンスが顧客の言葉で記述されている。次に、基本オブジェクトの大まかな概要とアーキテクチャが記述されている。そして最後に、エンジニアリングにおける、設計上の複雑かつ詳細な問題が記述されている。

ふむぅ
やはり、仕様書か設計書か。
どうしても私は今自分が見ている”仕様書”が頭に入ってしまっていてここで述べている”仕様書”との間には隔たりがあるようだ。この隔たりを解消するにはどうしたものか…。やはりここでいうところの”優れた仕様書”を見てみるのが一番だと思う。

Joel on Softwareでおなじみのジョエル氏のページには氏が”優れた仕様書”のサンプルを出している

んー・・これ見たことあるな…。たぶんJoel on Softwareにそのまま載ってるな…。

はい、出直してきます

形あるものと形なきもの

私の管轄しているプロジェクトではないのだが、別プロジェクトが火を吹いている。
なんでもお客様からの品質に関する要望に対して提出している書類が思うように理解されないというものだった。

最初からプロジェクトがつつがなく進行している場合は問題がないのだが、数度問題が発覚するとお客様側の担当者としても黙ってはおれず、チェックが厳しくなる。
ただ単にチェックが厳しくなっているだけならばそれほど問題ではないのだが、ソフトウェアに対する品質管理を担当したことがないお客様がチェックを厳しくしようとするのが結構問題なのだ。

まず、言葉が通じない。
一通り書類を書いたところで、言葉の定義を一つずつ教えていかないとその文書を読むことが出来ていない。普通なら「こんな感じかな~?」っていうニュアンスで乗り切るのだが、”疑いの目で品質チェックをしようとしている”お客様としてはそうはいかない。
もちろん、書き方の問題もある。一言”モジュールテスト”だとか”ユニットテスト”だとか言っても、ソフトウェア業界ですら会社によって言葉が何を指すのかがバラバラな状態であることをよく聞く。
このあたりは、いわゆる製造業だとかその他産業との歴史の差が出ているのかもしれない。ソフトウェアの品質管理においての業界標準となりえるとすれば、国際的にはISTQB規格。日本ではJSTQBになるのだろうか

JSTQB
http://jstqb.jp/

しかし、”ユニット”の定義に関して明確になっているわけでは無いんじゃないだろうか?正直なところJSTQBとろうと思ったことないから分からないのだが…。
ただ、いわゆる目に見える機械の”部品”と、ソフトウェアのプログラム上の”部品”とでは実際に手にすることが出来ない分、考え方を変えていかないといけない。

もっとも、お客様にそこまで疑問視されるようなところまでいっている時点で問題なんだけどね。
ただ、ソフトウェアの場合は目に見えないものであるがゆえに、別業界の人に説明する時、言葉に関しては最新の注意を払わないと余計なコストをひたすらにかけることになってしまうなぁ、と思った。
ただ…気をつけないとって言ったところで、自分がその矢面に立たされた時に乗り切れるだろうか?ちょっと考えてしまうなぁ

IIS + Tomcat

2003年ごろに出版された本に、Tomcatを単独でWebサーバー/JSPコンテナとして使用するよりも、IISをWebサーバーとして使い、Tomcatをサーブレット/JSPコンテナとして使うほうが性能が向上すると書いてあった。ここで言う”性能”が何を意味するのかは気になるところではあるけど、ネット上を見てみると、そう言った事例はいくつか見受けられる。
今回の要求内容としては、同一サーバーにてServletによるサイトとASP.NETによるサイトを共存させたいという事。「別にServlet側は8080使えばいーじゃん」って言ってしまうとそれまでなのだがそうもいかないらしい。
あちこちに情報は載っているのだが、情報が分散してしまっているのか”この設定は当たり前だよね”という事なのか、実際にやろうとして手間取ってしまったのでここをチラシの裏としてメモする。
ここではTomcatのバージョンは6.0.18。WindowsはVista(32Bit)でIIS7.0。使用したisapi_redirect.dllは1.2.28になる。

isapi_redirect.dllの配置

http://apache.justdn.org/tomcat/tomcat-connectors/jk/binaries/win32/
から最新版のisapi_redirect.dllを入手する(isapi_redirect-1.2.28.dllをダウンロードしてファイル名を変更)。
任意のディレクトリへコピーする。ここでは「C:\Tomcat6\bin\isapi」へコピーしたとする。

ここでは32BitのOSでの話なので64Bitでは別なファイル(http://apache.justdn.org/tomcat/tomcat-connectors/jk/binaries/win64/)になる。

isapi_redirect.propertiesファイル作成

isapi_redirect.dllをコピーした場所で「isapi_redirect.properties」ファイルを作成する。中身は以下の通り

extension_uri=/jakarta/isapi_redirect.dll
log_file=C:\Tomcat6\logs\isapi_redirect.log
log_level=debug
worker_file=C:\Tomcat6\conf\workers.properties
worker_mount_file=C:\Tomcat6\conf\uriworkermap.properties
uri_select=unparsed

 

この内容はレジストリでも代用できる。その場合は「HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Isapi Redirector\1.0」に対して同様の内容を設定することになるが、ここでは割愛する。レジストリを使うべきなのかもしれないが、代替案があるのであれば、極力触りたくはないものだ。

workers.propertiesファイル作成

isapi_redirect.properiesファイルで指定した場所(ここでは”C:\Tomcat6\conf\”)に「workers.properties」ファイルを作成。
ファイルの中身は以下の通り

ps=\
worker.list=jakarta
worker.jakarta.port=8009
worker.jakarta.host=localhost
worker.jakarta.type=ajp13

 

uriworkermap.propertiesファイル作成

isapi_redirect.properiesファイルで指定した場所(ここでは”C:\Tomcat6\conf\”)に「uriworkermap.properties」ファイルを作成。
ファイルの中身は以下の通り。ここでは、”examples”サイトへのリダイレクト設定を行う

examples/*=jakarta

 

IISに対する全てのアクセスをTomcatに対してリダイレクトする場合には「uriworkermap.properties」ファイルに対して
/*=jakarta
のように書く形で設定する。「uriworkermap.properties」ファイルの記述方式としては
[URL]=[WORKER_NAME]
になっている。

例えば、JSPとServletに対してはTomcatで処理するけどそのほかはIISで処理したい時には

examples/*.jsp=jakarta
examples/servlet/*=jakarta

のように記述することになる。ASPとJSPの同一サイト内での共存が可能に!需要あるのか?

IISに対する設定

  1. IISマネージャにてサーバーホームより「ISAPIおよびCGIの制限」を開き”isapi_redirect.dll”を追加する。説明は適当で。
  2. IISマネージャにてサイト配下の”Default Web Site”を選択。”ISAPIフィルタ”を開き同様に”isapi_redirect.dll”を追加する。名前はなんでもいい
  3. IISマネージャにて、”Default Web Site”に対して”仮想ディレクトリ”の追加を行う。エイリアスには”jakarta” 。物理パスは”C:\Tomcat6\bin\isapi”を入力する。
  4. 追加した仮想ディレクトリを開き、”ハンドラマッピング”を開く。”スクリプトマップの追加”を実行し、下記内容を設定する。

要求パス:*
実行可能ファイル:C:\Tomcat6\bin\isapi\isapi_redirect.dll
名前:jakarta

    1. IIS再起動

 

上記手順によって、”http://localhost/examples/“に対してのアクセスがTomcat側にredirectされる形になった。TomcatがWebサーバーとして動作する”http://localhost:8080/examples/index.jsp“は当然としてIIS側からもちゃんと動作するって言う事ね。

この話を聞いた私の最初の理解だと、仮想ディレクトリ”jakarta”に対してアクセスを行った場合にTomcatに対してリダイレクトするのだと思っていた。だが実際は違って、IISのサイトに対してアクセスがあった場合に拡張設定された仮想ディレクトリ”jakarta”を利用してisapi_redirect.dllが起動。uriworkermap.propertiesに記述されたサイトでフィルタがかかりTomcatにリダイレクトされるって言う事かな?このあたりの理解はまだ足りないかもしれない。