SIerの売り上げ計算法を変革すれば人月商売も変わるんじゃないか。

http://d.hatena.ne.jp/gothedistance/20090723/1248331426

この記事を読んで経営も会計も素人だけど考えてみた事を思いのままに書き殴ってみる。突っ込み歓迎。

人を売る商売

上記のブコメにも書いたけど、人月商売を辞められない原因はSIerの会計制度(といか売上計算法)にあると思ってます。
たとえば、某SIer(オイラが知ってる某大手SIer)は情報サービスの売上をこんな感じで計算しています。
人月単価×投入期間
これって要は、「人が商品です」って言ってる様なもの。
口では「サービスを提供します!」とか言ってるけど、結局の所会計上は「人を何人月売れば売上達成です!」となってる。
この計算方法だと、生産性があがる=値引きしている、と同じ事になるので、売り上げに直結しない。
(生産性を上げると逆に干されるのはこの辺に原因があると思ってます。)
経営者がどんなきれい事並べようと、現場がどんなに生産性をあげようと、中間層は売上で評価されちゃうんで、どうしても稼働率至上主義になっちゃう。

じゃあどうしよう。

1つの方法として「サービス」を提供しているのであれば、それを売り上げの単位として使えば良いんじゃないか。
システム開発なら「実装した機能」(的なもの)を単位として、
 納品した機能数×機能単価
これを売り上げとすれば生産性が上がれば上がるほど売り上げも上がる、お客さんもハッピーのWin-Win関係になれる筈。

もちろん簡単じゃない。

制度というのは要するにシステム。皆さんもご存じの通り、システムを移行するというのは大きいシステムほど移行時の負荷が大きい。「大手」がやろうとするならば相当な痛み(それこそアイデンティティを失うほどの)が伴うでしょう。
「機能単位」と言ったってその粒度も様々だろうし、単価設定をどうするのかとか、開発ならともかく保守・運用はどうするんだとか、下手すると客の方に「良くわかんないから人月でやって」と言われる可能性だってある。(というか、実際にやろうとして言われた事があります・・・)
でも、これを乗り越えることが出来れば先の暗い人月商売から脱却することが出来るんじゃないでしょうか。

中小こそチャンス?

ちょっと本題からそれますが、いまは中小企業こそチャンスだと思っています。
なぜなら、上でも書いたとおり制度移行のインパクトは会社の規模にあわせて小さくなりますし、アジャイル開発も小規模では適用事例もぼちぼちと出てきています。さらには、クラウドについてはインフラ構築・運用を丸投げできる(ちょっと語弊がありますが・・・)ので大手がやるようなトータルでの提案も可能になってくるのではないでしょうか。

考える技術・書く技術

「書く技術」が「核技術」と変換されるのはご愛敬。

4年くらい積み本になっていたけど、ようやく読了。
正直、文章を書いていると何を書いて良いか分からなくなるときが結構多いので、この本で得た知識は結構重宝しそう。
具体的には、

  • 文章の書き出しは、状況-複雑化-疑問で読み手を引きつけること。
  • 疑問とそれに対する回答をはっきりとさせること。
  • 回答にはそれぞれ理由付けをすること。

の3点か。(この「だいたい3点にまとめる」っていうのもあったな)

で、この中でも書き出しの話がかなり役に立った。というのは、言いたい事はあるんだけどどう書き出したら良いか分からなくなるときというのが結構あって、そういうときは「状況(相手が分かっていること)」と「複雑化(疑問の引き金)」を書く事で文書に自然と入り込める、ということ。これは今後も活用していきたいなぁ。

疑問とそれに対する回答をはっきりさせるというのは、実際何となく文章を書いていると,だんだん自分が何を言いたかったのか、という事がある。で、そういうときは疑問と回答を意識することで、文章に芯が入ってくる、という事と解釈。
理由付けは言わずもがな。根拠はどうあれ、なぜ?に答えられない文章は納得感がない。

文書書きが苦手なおいらには非常に助かる一冊でした。

はてスタ。

今更だけど、これはすばらしい仕組みだとしみじみ思う。特にブログの方でもらうのはブコメでもらうのとはまた違う嬉しさがある。
これをもらうと随分テンション上がってまたなんか書こうって気分になる。やっぱ自分の考えを肯定してもらうってのは良い気分だよなぁ。単なる相づちみたいなモノだとしても。
また、手軽さも良い。やる事は、『うん』と思ったら☆をクリック。それだけ。手軽さってのはアクションを起こすのには重要なファクターだしね。

成功する要求仕様 失敗する要求仕様。

結局のところは『デスマーチ』でも言われている「トリアージ」に限る。全部の仕様変更を受け入れる訳にはいかないが(デスマーチ直行コース)、全部の仕様変更をはねつける訳にもいかない(誰が得するの?このシステム?)。その中間点で落としどころを見つける。そのための方法論としての、要求リスト作成とトリアージのプロセス。
その中でも「ちょうど十分(Just Enough.)」な状態に持って行く方法論はネゴシエーションスキルとしても通用する部分があると思う・・・というか、ネゴシエーションそのものなんじゃないか?お互いの利益を調整し、「出来る・出来ない」、「絶対に必要」と言った極論を廃して「○○%の確率で成功できる」「この機能が含まれていれば○○円の利益になる」という数字を使った交渉によって最適解を模索する。
著者はアジャイルプロセスには懐疑的だけど、アジャイルでもSCRUMのフィーチャリストとか、XPのTODOリストで要求を管理してるはず。別に要求を管理していない訳じゃ無い。結局、どんな方法論でも要求管理は大事ってこと。

付録の要求に点数をつけるやつは、実際のレビュー等でも使えそう、というか使ってみよう。誤字脱字とかばっかり指摘することが多いけど、それってあんまり重要じゃない。仕様の不備とか矛盾とかの方が重要。

Eric Sink on the Business of Software.

おそらく最も一般的な誤りは、ソフトウェア製品を作りたいと思いながら、それについて何もしないということだろう。
(p.265 エピローグ)

なんというか、この一言に尽きるなぁ、と。
何度も「とにかく失敗をたくさんすることだ」ということを繰り返しているように、結局は「何かをする」って事なんだろうなー。
そこからISVを始めるための最低限必要なツール群をおもしろおかしく(時には自分の失敗談を絡めつつ)紹介しているかんじ。
特に、最初の方で本当にWinnable Solitaire(必ず勝てるソリティア)を作って売っちゃったところとか、体を張ってネタを提供しているのが凄い。日本のビジネス書じゃこうはいかないだろうなぁ。

実際にISVをやるかどうかはともかく、マーケティング、財務、採用といった、経営とはなんぞや、と言う事を大雑把に知る事ができた。
いつもと違う視点で他の部署の人たちの動きを見られそうだー。

ジェネレーションギャップ的な。

ちょっと故あって、40代後半、いわゆるバブル世代の人と腰を据えて話す機会があった。
で、その人今おいらと同世代(アラサー、氷河期)の部下がいて扱いに悩んでるそうで。
内容は、

  • その二人はいわゆる「社運をかけた」プロジェクトを担当していて、そのプロジェクトマネージャーとプロジェクトリーダー
  • このリーダー、どうもその意識が欠けている様で、いまいち仕事に対する熱意を感じない
  • 取り替えられれば良いんだけど、他に代わりにつとまる様な人材もいない
  • プロジェクト的には、このリーダーが頑張ってくれないと不味い

と言うこと。
で、そのマネージャーさんの対策として、

  • いかにこのプロジェクトが会社に取って大事なのか
  • プロジェクトが成功すれば、本人の評価が上がって給与も上がるはず

と言うことを言って聞かせてるが,いまいち効果が無い。全然ノってくれない。
まぁ、そりゃそうだろうなぁ。おいらがそのリーダーの立場でもあんまりやる気がしないっていうか逆に引いちゃう気がする。
だって、給与が上がるとか言われたって、今までその辺に関してはエセ成果主義やら年功序列の崩壊やらでことごとく裏切られてるだろうし、会社に取って大事とか言われても、帰属意識なんて薄れてるからふーんそりゃ良かったねーって感じ。(聞いてみたら、やっぱりそのリーダーは客先常駐ばっかりだったらしい)
そんなことよりは、本人のキャリアにどうプラスになるのかとか、どんな面白いことが出来るのかとか、そういうことの方が大事。
やっぱこの辺がジェネレーションギャップというか、バブル世代の『会社のためになる事をすれば待遇も良くなる、給与の額こそステータス』的な考え方と、氷河期世代の『会社なんかにゃ期待しない、給料の額より自分のやりたい事優先』的な考え方の差なのかなぁと思ったり。
いざ、自分の時にこういったジェネレーションギャップをどう乗り越えていくかを考える良い機会になりました。

あと、例のマネージャさんには
「もうちょっと違うインセンティブを提示してみたら良いんじゃないですか?」と言ってはみたものの、どこまで伝わったやら。

OMakeその3。

さて、前回
OMakeその2。 - 技術屋日和
の続き。
何とかビルドが通るようになったので、次は単体テストとのリンクと自動実行。
まずは単体テストビルド用のオマケファイル。

/test/OMakefile

CFLAGS += -g
LDFLAGS += -lcunit
INCLUDES += ../include

CFILES =
add_test
test_main

LIBS =
../src/libadd

MAIN = test

.DEFAULT: $(CProgram $(MAIN), $(CFILES))

こんな感じ?ローダに対するオブションはLDFLAGSで指定してあげれば良いみたい。(この辺はMakefileと一緒?)
で、実行結果

*** omake: reading OMakefiles
*** omake: finished reading OMakefiles (0.00 sec)
*** omake: 30/33 targets are up to date
*** omake: failed (0.09 sec, 0/3 scans, 1/5 rules, 0/91 digests)
*** omake error:
File c:\Program Files\OMake\lib\omake\\build\C.om: line 570, characters 4-32
rule failed to build target: test\test

あれー、ターゲットのビルドに失敗したとか言われるな・・・
でも、なぜかtest.exeはビルド出来ている罠。

つか、ビルドして出力されるファイルってtest.exeなのにターゲット名がtestっておかしくないか?
と思ってエラー出力されているファイルを確認してみると

C.om

public.CProgram(name, files) =
#
# Generic program
#
private.OFILES = $(addsuffix $(EXT_OBJ), $(files))
private.NAME = $(file $(name)$(EXE))

(...中略...)

$(NAME): $(OFILES) $(LFILES)
$(CC) $(CFLAGS) $(LDOUT)$@ $,(OFILES) $(LFILES) $(LDFLAGS)

return $(NAME)

第一引数の値にEXEの値をくっつけてターゲット名にしてるっぼい。
ってことはEXEの値を指定して上げれば良いって事かな?
と言うわけでEXEの指定をオマケファイルに追加。

/test/OMakefile
(一部を抜粋)
LIBS[] =
../src/libadd

EXE = .exe

MAIN = test

こんな感じ。で、リトライ。

$ omake
*** omake: reading OMakefiles
*** omake: finished reading OMakefiles (0.00 sec)
*** omake: done (0.02 sec, 0/3 scans, 0/5 rules, 0/69 digests)

大丈夫っぼいかな。
ちゃんとtest.exeもビルド出来てるし。

お次はCUnitの自動実行。オマケファイルをこんな感じに変更。

/test/OMakefile

.PHONY: run

CFLAGS += -g -Wall
LDFLAGS += -lcunit
INCLUDES += ../include

CFILES =
add_test
test_main

LIBS =
../src/libadd

EXE = .exe

MAIN = test

CProgram($(MAIN), $(CFILES))

.DEFAULT: run

run: $(MAIN)$(EXE)
./$(MAIN)$(EXE)

ポイントは.PHONY(ターゲットが作られなくても無視する。)と新しく作成されたバイナリを実行するターゲットを作成したところ。
で、デフォルトをそのターゲットに変更すると。
基本的な書き方はMakefileと変わらないみたい。

では実行

*** omake: reading OMakefiles
*** omake: finished reading OMakefiles (0.02 sec)
- build test
+ ./test.exe


CUnit - A Unit testing framework for C - Version 2.1-0
http://cunit.sourceforge.net/


*************** CUNIT CONSOLE - MAIN MENU ***********************
(R)un all, (S)elect suite, (L)ist suites, Show (F)ailures, (Q)uit
Enter Command :

ちゃんとCUnitのコンソールが起動された。

が、このままではomakeするたびにコンソール起動されてうざいので、勝手にテスト実行するようにテストスイートの方を修正。
CUnitその3。 - 技術屋日和

int main()
{
CU_pSuite suite;

CU_initialize_registry();

suite = CU_add_suite("Sort", NULL, NULL);

CU_add_test(suite, "test_001", test_add_001);

// CU_console_run_tests();
CU_basic_run_tests(); //Basicモードでテスト実行

CU_cleanup_registry();

return 0;
}

CU_console_run_tests()をCU_Basic_run_tests()に変更してあげるだけ。*1
で、実行結果。

 *** omake: reading OMakefiles
 *** omake: finished reading OMakefiles (0.02 sec)
 - build test
 + ./test.exe


CUnit - A Unit testing framework for C - Version 2.1-0
http://cunit.sourceforge.net/



 --Run Summary: Type Total Ran Passed Failed
suites 1 1 n/a 0
tests 1 1 1 0
asserts 1 1 1 0
 *** omake: done (0.20 sec, 1/3 scans, 3/6 rules, 3/100 digests)

ばっちりですな。

最後に目玉のファイル監視機能を試してみる。

$omake -P
*** omake: polling for filesystem changes

となったところで、テストケースを一個追加してみる。

add_test.c

void test_add_001(void)
{
CU_ASSERT(add(1,1) == 2);
CU_ASSERT(add(2,2) == 4); // 2 + 2のテストを追加
}

ここでファイルを保存すると、

*** omake: file test\add_test.c changed
*** omake: rebuilding
- build test
+ ./test.exe


CUnit - A Unit testing framework for C - Version 2.1-0
http://cunit.sourceforge.net/



--Run Summary: Type Total Ran Passed Failed
suites 1 1 n/a 0
tests 1 1 1 0
asserts 2 2 2 0
*** omake: done (0.22 sec, 1/4 scans, 4/9 rules, 4/107 digests)

おお、ちゃんとリビルドしてテストまで実行してくれた。こいつはすごい。

さぁ、ようやく環境が整ったので、次はいよいよCでなんか作ろう。

*1:includeにCUnit/Basic.hが必要