10月 2005 - 投稿
ここのところ,更新をさぼっているのよりももっと長いこと
・開発プロセス
・メトリクス
・マネージメント
・パターンプラクティス
と上流工程に関する本ばかりを読んでいました。そこで「コンストラクション」に回帰してみることに。
※コンストラクション 実際にコードを作る工程。コーディングとテストを包括して言う場合が多い
なのでやっぱりここは
・CODE COMPLETE
http://www.microsoft.com/japan/info/press/JPN_ViewMsPress.asp?Book_id=1005&list_id=1
でしょう。
ということでもう一度読むことに。
そして読み返し始めた初日。せっかくだから最初から最後までCOMPLETEしてみようと。
そこで「電球がともる」フレーズに。
コンストラクションはどんなプロジェクトにも必ず存在する工程である
ごもっとも!!
要求分析,設計,マネージメント。
どれをとっても重要な工程ですし,事実ここでの生産性が後々に響くと思ったからこそ,
ここのところ,それに注力してきました。
でも,
現実のプロジェクトでは
・要求分析がおこなわれないまま,なし崩しに開発に取り掛かる
・設計について議論する前に構築が始まる
・バグ改修に終われるあまり,テストがおろそかになる
どれも,現実をある意味写し取っています。
が!!
それでも,コンストラクションは絶対になくならない。
コンストラクションはソフトウェアを作る作業そのものだから,これなくしてソフトウェアは成り立たない。
あー。
そうだよな。
当たり前なんですけれど,「電球がつきました」
ちょっともう一度読むのがますますたのしくなってきましたなのです。
ポリモーフィズム:多態性,多相性
仮想関数のデザインを利用して,
実装時に仮想関数によるメソッド呼び出しを行っておくと,
将来の仕様拡張が起こったときに,仮想関数呼び出し部分のほとんどを書き換えなくてよくなる。
という,オブジェクト指向言語の利点のひとつ。
が。
これが利用できるのは,
きわめて凝集度が高くて,疎結合なメソッドに限られる。
もしくは,
メソッドを凝集度が高くて,疎結合なメソッドにデザインする必要がある。
無計画にポリモーフィズムを利用しようとしても,
結局は仮想関数では対応できなくなってしまって,
別メソッドを立てなければならなくなってしまう。
これを防ぐためには,
とにかく問題領域のモデリング。
仮想関数を高度に概念化して,モデル時点で機能をしっかり切り分ける。
これって,未来を予想しているよ?
モデリング時点で,
将来の発展性を把握していないと,そのレベルのモデリングはできない。
・将来このシステムは Web に乗っかるかもしれない。
・将来この課金計算メソッドは,課税情報が変わるかもしれない。
こんな情報も把握していなければ,
その時点での最適なモデリングは望めなくなってしまう。
アーキテクトは,変更管理委員会ではないし,ましてや経営マネージャーではない。
どうするか?
やっぱり,ヒアリングか。
我々情報処理技術者には,
扱っているものが,「情報」というだけで,
それが流れている全てのプロセスに
(受注,生産,把握,経営なんでも,今の時代情報が流れないプロセスはビジネスに存在しない)
ある程度の知識が求められる。
だから,ここは世界の縮図で,中心なのかもしれない。。。
Windows に関する重要な更新やセキュリティパッチをダウンロードして設定するプラットフォームは
今までは,
・Windows Update
・Office Update
など,バラバラに運用されていました。
これが,今は「Microsoft Update」として統合されていっています。
今は,従来の Windows Update の機能と Office Update の統合程度ですが,今後はさまざまな製品の更新を一括で管理していけるようになるのではないでしょうか?
ですが,
SECURITY SUMMIT 2004 ではあれほど熱く主張していた Microsoft Update ですが,
エンドユーザーにはまだまだ知られていないんではないでしょうか?
既定では何もしなければ「Windows Update」に接続してしまいます。
Windows Update のホームに 「Microsoft Update にアップグレードしてください」の告知が出ていますが,
そもそも更新に無関心な層のユーザーが明示的にこれをクリックするのは稀ではないかと思います。
せっかくの統合ソリューションなので,もっともっと広めていってもいいのかなと思います。(トピックとしては非常に古いですが。。。)
Microsoft Update にアップグレードしてしまうと,Windows Update に接続してもリダイレクトされてしまうのでご注意を。
ちょっと前にアップされていたようなんですけど,気づいてませんでした。
Pattern & Practice に SQL Server のパフォーマンスに関するコンテンツがアップされています。
第14章 SQL Server のパフォーマンス向上
http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetchapt14.asp
ざっと目を通したんですが,
読み応えもあるし,一方でプロジェクトに関係あるところだけ拾い読みするだけでも効果がある
かな,と。
2時間程度のちょっとしたプロセス改善ミーティングなどでいかがでしょう?
Pattern & Practice Home
http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetchapt14.asp
PressPass にのりました。
スティーブン シノフスキーが語るOffice “12” における PDF 形式のサポートについて
http://www.microsoft.com/japan/presspass/detail.aspx?newsid=2436
便利になりますなぁ。
がんばって崩れないように変換してほしいです。
10/4 は SECURITY SUMMIT 2005 に参加してきました。
基調講演は,本社 バイスプレジデントの マイク・ナッシュ 氏が担当されました。
大枠として,
Trustworthy Computing 構想を採用したことによる成果を報告と,
そして,より一層この Trustworthy Computing を推進していくことが訴えられました
中でも目を引いたのが
Windows Vista に向けて開発が進められている IE 7 の新機能のデモです
・ActiveX Opt
・Fishing Filter
のデモが行われました。
さらに,日本向けで特に重要なのが,
「Winny」に対するワーム「Antinny」を削除するツールを無償で提供することが発表されました。
これは,10/12 から Windows Update やダウンロードセンタからダウンロードになるようです。
SECURITY RESPONSE CENTER にも力を入れていくそうなので,IT Pro の方は要チェックですね。
先日,ブログに書いた日本語長音「ー」の問題ですが,
http://blogs.timberlandchapel.com/blogs/timberlandchapel/archive/2005/10/02/443.aspx
MVP の河端さんがさらに細かく検証してくださいました。
SQL Server 2005 Sep CTP: 文字列処理の問題
http://blogs.sqlpassj.org/yoshihirokawabata/archive/2005/10/04/14414.aspx
結果的に,
CTP Sep でも問題は解決されていません。
また,SQL Server 2000 の Japanese_CI_AS のときと同じように 「AA」「Aー」問題などがやはり存在しています。
より多くの検証と,フィードバックが必要になると思います。
引き続きレポートしていきたいと思います。
この記事は@IT さんの Database Expert 会議室に投稿した記事のフォローアップです。
解決のために
問題の概要
SQL Server 2005 CTP June において,
Japanese_90_CI_AS,Japanese_CI_AS 照合順序を使用して,
LIKE 演算子に 「ー」(日本語長音)を含む2文字以上の文字列を処理すると
正しく抽出ができなくなる。
問題の再現
再現方法は C# MVP の中さんが簡潔にまとめてくださっています。
http://blogs.wankuma.com/naka/archive/2005/09/29/18540.aspx
ここでは,簡単におさらいを
varchar または,nvarchar を格納するテーブルを作成して,
「ー」(日本語長音)を含む2文字以上の文字列(ここでは「クー」)を条件とするクエリを発行します。
クエリは,実験するためのテーブルを準備して,実験コードを実行した後,後処理を実行します。
create database CollateTest
go
use CollateTest
go
create table JpnTest ( [Data] nvarchar(50) collate Japanese_CI_AS);
go
insert into JpnTest([Data]) values('クーリング')
insert into JpnTest([Data]) values('カーリング')
insert into JpnTest([Data]) values('ケビン')
select * from JpnTest where [Data] like '%クー%'
go
drop table JpnTest
go
create table JpnTest ([Data] nvarchar(50) collate Japanese_bin);
go
insert into JpnTest([Data]) values('クーリング')
insert into JpnTest([Data]) values('カーリング')
insert into JpnTest([Data]) values('ケビン')
select * from JpnTest where [Data] like '%クー%'
go
drop table JpnTest
go
期待される結果は,両方とも「クーリング」が返されることですが,
[Japanese_CI_AS] では期待する結果が返ってきません。
「ー」ではなく「〇」(漢数字の零)が長音文字になっている
結果的に,[Japanese_CI_AS] で,「クーリング」をヒットさせるには,
WHERE [Data] LIKE '%ク〇%'
として,「漢数字の〇」を長音文字としてあててあげなければなりません。
これは日本語の処理としては非常に不適切です。
SELECT [DATA]
FROM [CollateTest].[dbo].[JpnTest]
WHERE [DATA] LIKE '%ク〇%' COLLATE Japanese_90_CI_AS
SELECT [DATA]
FROM [CollateTest].[dbo].[JpnTest]
WHERE [DATA] LIKE '%ク〇%' COLLATE Japanese_BIN
GO
検証での考え方
さて,ここからはちょっと趣向を変えて,
「漢数字の零」が長音文字の代わりにヒットしてしまっている
ということを発見するまでに,TLC が何を考えたのか?
について書いてみたいと思います。
このなんでもない探求法を使ってみれば,みなさんでもおかしな動きの検証ができるようになるのではないでしょうか?
まず始めに,
[Japanese_CI_IS] は [SQL Server 2000] でもおかしな動きをしていた
という知識がありました。
特に長音記号に関する部分は,アルファベットなどの文字と組み合わせると不思議な動きをしてくれます。
この時から,「特定の文字」と「特定の文字」を組み合わせる状況によって「不審な動作をする」という経験的な知識が出来上がっていたのです。
この前提に立つと,
今回の動作も「ー」の代わりに何かの文字が代わりにヒットするのではないか?
という疑いが浮かんできます。
このアイデアが浮かびさえすれば,後は
総当り的に文字を試してみることで検証ができるのです。
実行したいことは,
「クー」の「ー」の部分をいろいろな文字に置き換えて,実際にクエリを投げてみてみることです
そうすると,
SQL ステートメントの nchar() 関数が使えそうだと思いつきます。
後は,nchar() 関数を使用して総当たり戦をうまく挑むだけですね。
実は,この辺は,それぞれの得意分野に持ち込んでもいいかも知れません。
つまり,ADO.NET を使用してクエリを組み立てるほうが,T-SQL ステートメントを操作するよりも得意な場合は,
通常のプログラミングの世界でループを組めばいいわけです。
ただし,このときには「追加で使用するテクノロジとのつなぎ目の部分で検証の範囲が広がってしまう」ということを念頭においておくことが必須です。
なるべくシンプルに検証できた方がよいわけですね。
さて,それでは実際に使用したコードです。
DECLARE @count int
DECLARE @limit int
DECLARE @CMD nvarchar(1000)
SET @count = 0
SET @limit = @count + 65535
WHILE @count < @limit
BEGIN
SET @count = @count + 1
SET @CMD = 'SELECT [DATA],'
+ CAST(@count AS nvarchar) +
' AS [char] FROM [TestDB].[dbo].[JpnTest] WHERE [DATA] LIKE ''%ク'
+ nchar(@count) + '%'' COLLATE Japanese_CI_AS'
EXEC sp_Executesql @CMD
END
GO
実行していることは,
クの直後の文字を総当り的に置き換えて,結果を返させているだけです。
結果の検証
このクエリを実行すると,クーリングをヒットさせる文字が3種類あることがわかります。
その3種類とは,
- 「_」(アンダーバー)
- 「%」(パーセント)
- 「〇」(漢数字の零)
です。
前半2つはなんてことはありません
単純にク「ー」リングが「任意の一文字」か「任意の文字列」にヒットしているだけです。
探していた問題の文字は漢数字の零だった,ということになりますね。
しかし,この検証には一つ問題がありまして,
クエリが先頭の100結果セットしか画面表示しない
ことです。
このため,100以上の結果セットでは,結果の件数しかわからないんですね。
(この場合は返ってくるかこないかがわかればよいので,さほど問題にはなりませんが)
よって,最初のクエリを投げた後,結果が返ってきている大まかな場所に
あたりをつけて,
もうすこし限定したクエリを投げます。
結果セットの表示文字列の 25000 行あたりに「(1行処理しました)」がありますから,問題は12000ぐらいだろうと予想するわけです。
DECLARE @count int
DECLARE @limit int
DECLARE @CMD nvarchar(1000)
SET @count = 12200
SET @limit = @count + 100
WHILE @count < @limit
BEGIN
SET @count = @count + 1
SET @CMD = 'SELECT [DATA],'
+ CAST(@count AS nvarchar) +
' AS [char] FROM [TestDB].[dbo].[JpnTest] WHERE [DATA] LIKE ''%ク'
+ nchar(@count) + '%'' COLLATE Japanese_CI_AS'
EXEC sp_Executesql @CMD
END
GO
こうすることで,問題の部分の結果を得ることができました。
このように,わりとシンプルなアイデアを実現することによって,実現できる部分が多くあると思います。
みなさんもぜひトライしてみてください。
この記事は Microsoft SQL Server 2005 CTP June
に基づいて記述しています。
この記事は@IT さんの Database Expert 会議室に投稿した記事のフォローアップです。
シナリオと要件
T-SQL ステートメントのエラー状態によって処理を分岐させ,その状態をイベントログに記録します。
今回は [RAISERROR],[IF~BEGIN~ELSE] を使用します。
[アドホックメッセージ] を利用する
[RAISERROR] の機能だけを利用して,メッセージを記録します。
この機能では SQL エラー番号 50000 としてログ記録されます。
USE TestDB
DECLARE @DBID INT
DECLARE @DBNAME NVARCHAR(128)
SET @DBID = DB_ID()
SET @DBNAME = DB_NAME()
BACKUP DATABASE TESTDB TO DISK = 'E:\test.bak'
IF @@ERROR = 0
BEGIN
RAISERROR ('ID :%d, NAME:%s Backup success.', 1, 1, @DBID, @DBNAME) WITH LOG
END
ELSE
BEGIN
RAISERROR ('ID :%d, NAME:%s Backup fail.', 1, 1, @DBID, @DBNAME) WITH LOG
END
GO
事前に [sp_addmessage] でメッセージを定義しておく。
この機能では SQL エラー番号 やログ記録のオン/オフなどを事前に定義しておくことができます。
EXEC sp_addmessage @msgnum = 50001, @severity =1,
@msgtext ='ID :%d, NAME:%s Backup success.',@with_log=True
EXEC sp_addmessage @msgnum =50002, @severity =1,
@msgtext ='ID :%d, NAME:%s Backup fail.',@with_log=True
GO
USE TestDB
DECLARE @DBID INT
DECLARE @DBNAME NVARCHAR(128)
SET @DBID = DB_ID()
SET @DBNAME = DB_NAME()
BACKUP DATABASE TESTDB TO DISK = 'E:\test.bak'
IF @@ERROR = 0
BEGIN
RAISERROR (50001, 1, 1, @DBID, @DBNAME)
END
ELSE
BEGIN
RAISERROR (50002, 1, 1, @DBID, @DBNAME)
END
GO
この記事は Microsoft SQL Server 2000
Developer Edition Service Pack 4 に基づいて記述しています。