標準クエリ演算子

表計算ソフトがExcel一色ではなかった頃、大変マイナーなソフトで三洋電機のGOALというものがありました。計算はセルに計算式を埋め込むのではなく、独自のマクロを使います。

1
D = A*B {C<1000}

上の式はC列が1000以下の行に対して、D列にA列とB列を掛けたものを代入します。余り複雑なことはできませんでしたが、一つの式で複数行の処理ができて単純明快でした。

同様の処理をVisual Basicなどのプログラミング言語で行うとループで回す処理が必要になります。Visual Studio 2008では繰り返し処理を簡潔に書けるように標準クエリ演算子とシンタックスシュガーである.NET統合言語クエリ(LINQ)が導入されました。モデルになっているのはデータベースに使われるSQLで複数行の計算を一文で書けます。SELECTはフィルタリング、INSERTは挿入、DELETEは削除、UPDATEは更新を行います。

1
UPDATE TableName SET D=A*B WHERE C<1000

このうちLINQではSELECTを処理してくれます。そのため上に書いた式で「A*B WHERE C<1000」の複数行の結果を作り出すことはできても素直な方法ではDへの代入はできないので、最終的にはループを回して代入する必要があります。

Visual Visual Studio 2005で比較しています。

現在Visual Basicを使っているのは、記述は冗長だが読みやすいという点を買っています。Modula-2,DelphiなどPascalライクな文法を持つ言語が好みということもあります。

VB vs C#(NET Framework)

Visual BasicとC#、変換ツールが存在するほど互換性の高い言語ですが、いざどちらを使うかとなると判断に困ることもあります。Visual
BasicとC#の比較については書籍が発行されていたり、他のWebサイト上でも同様の記述はたくさんありますが、私見を書いてみました。Visual
Studio 2015時点で比較しています。

項目 VB C# 内容 経過
機能有無 匿名メソッド × VBで同等のことをするには、メソッド内で使用する変数などをカプセル化するクラスが必要 VS2010でVBも同等機能が追加された
メソッドの引数省略 × C#ではオーバーロードで対応する。 VS2010でC#も同等機能が追加された
Handles句 × C#ではメンバ変数に代入するたびに-=,+=によりハンドラの除去、追加を行わなければならない。
yield return × yield returnで列挙に限ってコルーチンが実現できる。アーキテクチャーパターンの一つであるPipe&Filterパターンを採用した場合に省メモリで見通しの良いコーディングができる VS2012でVBも対応
Option Strict Off × 通常Option Strict Onにしているが、Office VBAを呼び出すような状況において型チェックを外すとシンプルに書ける。また実行環境にOfficeがなくてもOffice呼出以外の機能は使える。 VS2010でdynamicが追加されC#でも問題解消
With文 × C#では一時変数で対応する。
多分岐 C#のswitchは使いにくい(breakが必要とか、範囲指定できないとか)
staticインポート × VBは別のクラスでモジュール名を指定しないでメンバーを呼び出せる。 VS2015でC#も対応
Like演算子 × C#は正規表現で代用
unchecked × 通信プログラムなど負の数を符号無し数値に変換するときに必要となる。これがないと一旦拡張変換してビット論理積をとるなどの対応が必要になる。
書きやすさ 制御構造 × C#は複文の時に中括弧を使う。C#はif,swithなどの制御構造を追加するときなどインデントが崩れると右括弧がどれに対応しているのかわからなくなる。
文末・行末 × C#はセミコロンが必要、タイピングが面倒。VBは逆に行継続文字が必要な場合がある。常にセミコロンがつきまとうC#が不便
ラムダ式 × C#の記述は簡潔
括弧 × VBは引数、型引数、配列のいずれも小括弧を使うので複雑に入り組んだ文で混乱しがち。C#はそれぞれ小括弧、山形括弧、かぎ括弧と分かれるので見やすい。但し、if,whileなどに制御構造に小括弧が必要
IDE支援 コード補完 × VBのコード補完は高速動作、End Subなど制御構造終端が補完された後の記述がしやすい。 VS2013でC#も終端括弧補完
リファクタリング × C#は名前の変更だけでなく、フィールドのカプセル化・パラメータの順序変更など多くのリファクタリングが利用できる。VBは名前の変更のみ VS2015でVBも対応
注意点 比較演算子 VBは等号でString.EmptyNothingを同一視する。あえて区別したいときはEqualsメソッドを使用するなどの対応が必要。便利な場面が多いがこの動作を理解していないとはまることがある。C#では上記2つを区別するので、同一視したいときはIsNullOrEmptyメソッドで対応。

現在C#を主に使っています。お客様のご要望に応じてVisual Basicも使います。私が使っている範囲ではそれぞれ一長一短があり甲乙付けがたいと感じています。

参照

BindingSource

NETFrameworkは汎用的なフレームワークなので、データバインディングについてもデータベース連結だけをターゲットに組まれているわけではありません。そのため、データベース応用システム開発に使用した場合、Accessなどのテータベース開発ツールと比べると少しずつ回りくどいというか使いにくい面があります。そのためデータバインディングやTableAdapterなどの枠組みを使わずもっと単純なクラスのみを使って開発するPONO(Plain Old Net Object)という考え方があるようです。もともとはPOJOから派生した言葉らしいです。Visual Basic 6においてもDataEnvironmentを使って開発する方は意外に少なかったと記憶しています。

私はNETFrameworkに用意されている枠組みを活かしながら、使いにくいところは別のクラスで置き換えたり、拡張したりしながら使っています。TableAdapterは基底型がObjectでありライブラリ化が難しいのでほとんど使わず、同等機能のクラスを新たに作成しました。BindingSourceはこれを継承してデータベース連結に特化したTableBindingSourceを作成して使用しています。またTextBoxなどUI部品はNullの扱いが苦手なので、Nullも自然に扱えるように拡張しています。このような拡張ができてしまうのもNETFrameworkの汎用性のおかげなのですが。

このような拡張の中で少し引っかかった点がありますのでご紹介します。BindingSourceにはバインドがサスペンドしている状態があります。DataTableに全くデータがない場合に暗黙的にサスペンド状態になります。明示的に状態を切り替えるにはSupendBindingとResumeBindingを使います。IsBindingSuspendedがその状態を取得するのに使われます。ところがIsBindingSuspendedが内部で保持しているサスペンドの状態を必ずしも表していないことがあるようです。データが全くなくなって暗黙的なサスペンド状態でAddNewを呼び出しても再開してくれない場合があったので、ResumeBindingを呼び出しました。しかしそれでも再開してくれないのです。

1
2
3
If IsBindingSuspended Then SuspendBinding() 'バグ対策、内部状態が一致しない場合がある
Dim newRow As Object = AddNew()
ResumeBinding() 'バグ対策、SuspendBindingに関連して必要

そこで対策としてIsBindingSuspendedの場合にSuspendBinding()を呼ぶことで本当のサスペンド状態?になってAddNew後のResumeBindingが働くようになりました。

ジェネリック(クラス)

型引数を持ったクラスを使い、Formの生成にジェネリックを応用した例を紹介します。

IDEを使ってWindowsFormを設計すると、Formの派生クラスが作られていきます。Formを生成する汎用的なプロシージャを作ろうとすると、それぞれのフォームが異なる型を持つことがネックになります。Win32版のDelphiならクラス参照型によってあっさり実現できるのですがNet
Frameworkではそうも行きません。一つの方法としてはReflectionを使ってそれぞれの型に応じたコンストラクタを呼び出す方法があります。これはコンストラクタを取得するのに比較的複雑なコードを書かなければなりませんし、アプリケーションアーキテクチャーとしてReflectionを使うのならまだしも、Formを生成するのにReflectionを持ち出してくることはエレガントとは言えません。そこでジェネリックを使うのです。

以下のクラスは汎用的にフォームを生成・オープンするメソッドを持つクラスです。

1
2
3
4
5
6
7
8
9
Public Class OpenFormCommand(Of TForm As {Form, New})
Dim _form As TForm

Public Sub Execute(ByVal sender As Object, ByVal e As EventArgs)
If _form Is Nothing OrElse _form.IsDisposed Then _form = New TForm
_form.Show()
_form.BringToFront()
End Sub
End Class

型引数TFormはオープンするフォームの型です。型制約としてFormとNewを指定しています。一度生成されたら2度目以降同じオブジェクトを再利用するようにしています。Executeが生成・オープンするメソッドです。イベントハンドラとして扱えるようにsenderとeを付けていますが、これらの引数は使用していません。

このクラスを利用するフォームのコードです。フォームには2つのボタンが配置してあり、ボタンを押せばそれぞれ異なるフォームを表示することを想定しています。メインメニューではありがちなインタフェースだと思います。

1
2
3
4
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AddHandler Button1.Click, AddressOf (New OpenFormCommand(Of Form2)).Execute
AddHandler Button2.Click, AddressOf (New OpenFormCommand(Of Form3)).Execute
End Sub

フォームのロード時に、OpenFormCommandクラスのExecuteメソッドを2つのボタンのクリック時イベントハンドラとして登録しています。このようにするとイベントハンドラをボタン毎に記述する必要がなくなります。

オブジェクト解放(デリゲートによる参照)

Visual Basic 6など、COMでは参照カウントによってオブジェクトの解放を管理していました。オブジェクトに参照カウントを持たせておき、代入などにより参照されるときにカウントアップ、Nothingや別のオブジェクトの代入、オブジェクト変数のスコープが外れたときなど参照されなくなったときにカウントダウンし、参照カウントが0になったときに、どこからも参照されていないから不要と見なして解放する仕組みです。参照されている限りオブジェクトは解放されないので破棄されたオブジェクトにアクセスしてエラーが発生することはありません。参照カウントの仕組みは単純なオブジェクトではうまく動作しメモリ管理を楽にしてくれました。

しかしオブジェクトが循環参照を持つ場合にはいつまでもオブジェクトが解放されず、不必要なメモリを消費したりエラーの原因となったりしました。この場合、どのオブジェクトが循環参照を生じているのか解析しながら注意深く循環参照の連鎖を切る必要があり、面倒な作業を強いられました。

一方Net Frameworkでは、オブジェクト解放の仕組みが変わりガーベジコレクタが使われるようになりました。ガーベジコレクタはルートオブジェクトからたどって参照されているオブジェクトを有効と見なすので、循環参照が生じてもルートからたどれなくなっていれば解放されます。このため循環参照を気にする必要がなくなり管理がずいぶんと楽になりました。ガーベジコレクタはプログラマが明示しなくても適当なタイミングで実行されますがGC.Collect()によっても明示的に実行させることができます。

オブジェクトの解放と関連して、Net FrameworkにはIDisposableインタフェースを備えたクラスがあります。WindowsアプリケーションではControl、Formなどがそうです。これらのDisposeメソッドを呼び出すと、アンマネージリソースの解放、該当オブジェクトが参照しているオブジェクト変数へのNothingの代入が行われます。注意点としてマネージリソースは即時解放されるのではなくて次回ガーベジコレクタが働いたときに他のオブジェクトから参照されていなければ解放されること、Disposeメソッドが呼び出されたオブジェクトが解放されるわけではないということです。しかしDisposeが呼び出されたオブジェクトはまともに動作する状態ではありませんので再び必要になれば改めて生成する必要があります。Dispose呼び出し済かどうかはControlのIsDisposedメソッドで確認できます。

既定の動作ではフォームを閉じたときにはDisposeメソッドが呼び出されます。フォームを参照している変数がないと仮定して、フォームが閉じた後にGC.Collectを呼び出せばフォームおよびフォームが所有していてたオブジェクトは完全に解放されるはずです。しかし、フォームを解放したはずなのに解放したフォームが所有しているオブジェクトが解放されずにエラーが発生することがありました。

状況としては呼び出し元フォームをForm1、呼び出し先フォームをForm2として、Form2の所有するオブジェクトEventSinkTestがForm1のイベントを補足するためForm1への参照を持っています。具体的にはClickイベントを補足して、Form1がクリックされればメッセージが表示されるようになっています。Form2を閉じるとDisposeメソッドが呼び出され使用できない状態になります。さらに、GC.Collect()を呼べばEventSinkTestも解放されることを期待しますが、そのようにはならず、依然としてEventSinkTestがForm1のイベントを補足し続けます。

この状況でForm1からForm2のEventSinkTestへの参照がないと考えたのが間違いのようでした。イベントソース(この場合Form1)からイベントシンク(EventSinkTest)への参照はデリゲートを介して存在しており、構文上気がつきにくいオブジェクト図の波線で表した参照があることでEventSinkTestが解放されなかったのです。

これを回避するためFormがDisposeされるときEventSinkTestからForm1への参照もなくしてしまうと、期待通りイベントの発生が止まりました。実際にEventSinkTestが解放されるのはガーベジコレクションのときですがイベントはすぐに止まります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
'呼び出し元フォームのコード
Public Class Form1

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim Form2 As New Form2
Form2.Show()
Form2.Initialize(Me)
End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
GC.Collect()
End Sub
End Class

'呼び出し先フォームのコード
Public Class Form2
Public Class EventSinkTest
Dim WithEvents _form As Form

Public Property Form() As Form
Get
Return _form
End Get
Set(ByVal value As Form)
_form = value
End Set
End Property

Private Sub _form_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles _form.Click
MsgBox("Form_Click")
End Sub
End Class

Dim es As EventSinkTest

Public Sub Initialize(ByVal form As Form)
es = New EventSinkTest()
es.Form = form
End Sub

Private Sub Form2_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
'オブジェクトを解放するためには以下の行を追加する。
'es.Form = Nothing
End Sub
End Class

コントロール既定値設定

アプリケーション開発において、各画面で意匠に統一性を持たせることは要求仕様なることが多いと思います。例えばラベルの色を統一することもその一つでしょう。多くの画面で使用するすべてのラベルについて、プロパティウィンドウで色を設定していく作業は結構な手間になります。また、別の色に変えたいときにも同じ作業が発生してしまいます。Webサイトの意匠設計ではスタイルシートを使って色などを一カ所で設定することが可能になります。このようなことができないでしょうか。

NET Frameworkでは出来合いのコントロールから継承して新たなカスタムコントロールを作ることができます。そこでカスタムコントロールのコンストラクタでBackColorプロパティに望みの色を設定するようにすれば良さそうです。しかしそれだけではコンストラクタとInitializeComponentメソッドで2回設定され無駄が生じますしIDE操作の上でも望ましいと言えません。これを解決するためにはBackColorプロパティにDefaultValue属性を設定します。

属性による既定値設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Public Class MyLabelDesigner
Inherits System.Windows.Forms.Design.ControlDesigner

Public Overrides Sub InitializeNewComponent(ByVal defaultValues As IDictionary)
MyBase.InitializeNewComponent(defaultValues)
With Cast(Of MyLabel)(Control)
.AutoSize = False
.Text = Nothing
End With
End Sub

Private Sub SetDefaultValue(Of componentType, propertyType) _
(ByVal properties As IDictionary, ByVal propertyName As String, ByVal value As String)
properties(propertyName) = TypeDescriptor.CreateProperty(GetType(componentType), _
Cast(Of PropertyDescriptor)(properties(propertyName)), _
New DefaultValueAttribute(GetType(propertyType), value))
End Sub

Protected Overrides Sub PreFilterProperties(ByVal properties As IDictionary)
MyBase.PreFilterProperties(properties)
SetDefaultValue(Of MyLabel, Color)(properties, "BackColor", "FloralWhite")
SetDefaultValue(Of MyLabel, BorderStyle)(properties, "BorderStyle", "Fixed3D")
End Sub
End Class

<Designer(GetType(MyLabelDesigner))> _
Public Class MyLabel
Inherits Label

Public Sub New()
MyBase.New()
BackColor = Color.FloralWhite
BorderStyle = BorderStyle.Fixed3D
End Sub
End Class

素直にDefaultValue属性を設定する例はMSDNを参照してください。この方法をそのまま当てはめた場合の問題は属性を設定するためにわざわざプロパティをオーバーライドまたはシャドウしなければならないことです。属性が必要なのはデザイン時だけですから別の方法で属性を設定する方法を考えてみました。

MyLabelのBackColorプロパティとBorderStyleプロパティにDefaultValue属性を設定するのにMyLabelDesignerクラスを使用します。MyLabel本体はコンストラクタのオーバーライドだけになっています。SetDefaultValueはMyLabelDesignerのメンバーとしていますが汎用的に作ってあるので他のModuleのPublicメソッドにしても問題有りません。Castメソッドはジェネリックのページで例示した物ですが一般的にはCTypeを使えばよいでしょう。上記程度のサンプルにはジェネリックを使う必要はありませんがそのまま残してあります。InitializeNewComponentはなくてもかまいませんが、Textプロパティにコントロール名が設定されるのは便利とは言い難いので空白になるようにしているのとAutoSizeがTrueになることを防いでいます。サンプルコードを試される方はSystem.Design.dllへの参照をプロジェクトに追加してください。

MSDNを見るとメモ : このメソッドは、.NET Framework version 2.0 で新しく追加されたものです。と書いてあるのを見かけます。カスタムコンポーネントを作っていると新しく追加されたメソッドをよく使っています。version 1.Xを使っていたら結構不便に思ったかもしれないです。

ジェネリック

Net Framework 2.0ではジェネリックが搭載されました。ジェネリックについては以前に型総称性で紹介しました。このときにはC++でテンプレートが使えたもののJava Genericは搭載されたばかりで盛んに使われている状況にはありませんでした。今ではNet Frameworkに当然のようにクラスライブラリに使われ、アプリケーションプログラマにとっても身近な存在になったと感じています。

コレクションなどで提供されているジェネリックライブラリを使うことはそれほど難しいことではないと思います。一方メソッドやクラスを作るのにもジェネリックを使うと今までにないものができます。

単純な例でVisual BasicのIIf関数のジェネリック版です。

1
2
3
Public Function IIf(Of T)(ByVal expression As Boolean, ByVal truePart As T, ByVal falsePart As T) As T
If expression Then Return truePart Else Return falsePart
End Function

(Of T)のTは型引数と呼びます。上記IIfを使うとReturn値のデータ型が、引数に合致したものと型推論されるので、以下のように文字列変数に代入するときにもいちいち型キャストする必要がなくなります(Strict
Onでも)。

1
Dim s As String = IIf(True, "True", "False")

型推論を使わずにIIf(Of String)と明示的に型を指定してもOKです。
つぎにキャストを行う関数を作ってみました。

1
2
3
Public Function Cast(Of Destination)(ByVal Source As Object) As Destination
Return CType(Source, Destination)
End Function

こうなるとただのシンタックスシュガーなのですが次のような使い方ができます。

1
Dim s As String = Cast(Of String)(123)

型引数を持ったクラスを作ることもできます。C++のテンプレートはプリプロセッサで実現されているので、型引数が指定(実体化)されないかぎりコンパイルチェックが掛かりません。それに対しNet Frameworkではジェネリッククラスそのものにコンパイルチェックが掛かり、型引数に対して定義されていないメソッドやプロパティの呼び出しはできません。それは安全性が増していて、生成されるコードも小さくなることを意味します。型引数にはどんな型が指定されるかわからないのにどうしてメソッドやプロパティを呼び出せるのかとの疑問がわきます。実際上記のIIfでは関数内でtruePartやfalsePartに対するメソッド・プロパティ呼び出しはすべてのデータ型の基底型であるObjectのメソッドしか使用することができません。

そこで使用するのが型制約です。型制約は型引数に指定できる型を制限する代わりに制約に指定した型のメソッド・プロパティを呼び出せるようにする物です。型制約は(Of T As Control)のようにAsを使って指定します。

以下余談、Visual Basicに有ったらいいなと思うもの、無名メソッド(C#)・typedef(C#)・プロパティによるインタフェース委任(Delphi)・メソッド解決節(Delphi)。

Net Frameworkとは関係のない余談ですが、Delphi for Win32にはクラス参照と呼ばれる、型を変数として扱えるものがあります。これとジェネリックを組み合わせると非常に柔軟なプログラミングができるような気がします。

データアクセス(ADO.NET)

当方では従来データベース応用システムはAccessを使っていましたが、今年からVisual Basic 2005(以後VB2005と記述)に置き換えています。置き換えには当初の想定よりも手間取りました。言語の違いは本格的なオブジェクト指向の機能を備えたVB2005になれるのにそれほど時間は掛かりませんでしたが、ライブラリの違いにはなかなかなれることができませんでした。

Accessでは、フォームにRecordsetの機能が最初から備わっているなど、思い切った割り切りによってデータベース処理に特化しているのですが、VB2005というかNET
Framework 2.0ではデータアクセスのパーツが細かく分かれていてこれらパーツの関連を把握するのに時間が掛かりました。

右の図は私が把握しているデータベースアクセスクラスの関連を表しています。XXDataTableとXXTableAdapterはIDEが生成するクラスです。

AccessやCOMベースのADOとの最も大きな違いはデータベースエンジンとの接続のあり方でしょう。従来はアプリケーションの実行開始から終了まで接続状態でデータアクセスするスタイルでしたが、ADO.NETではDataTableに一気に読み込んでから、処理を行い、結果を戻すスタイルが標準的な動作になります。接続は読み込みと結果を戻すときだけ行います。

Web開発ではこのような接続方法が求められるのですが、これをクライアント/サーバに応用した場合には次の得失がありそうです。

Accessではユーザインタフェース上でデータを変更したら即座にデータベースも変更されます。そのため「保存」「取消」ボタンを作ろうとすれば一旦ワークテーブルにデータを読み込んでワークテーブルに対して編集を行うようにするなどの一工夫が必要になります。それに対してADO.NETではユーザインタフェース上での変更はオンメモリのDataTableが変更されるだけで、データベースへの変更はXXTableAdapterのUpdateメソッドで一気に行われるため、「保存」「取消」ボタンを簡単に実装できます。

それに対してスクロールしながら一覧表示するような画面ではメモリ上に一気に読み込むことからデータ量が多い場合のメモリ使用量・パフォーマンスに別の配慮が必要になります。

UML

数年前SI様からプログラムの構造をドキュメント化するのにクラス図をご要望されたのをきっかけにUMLの使用を始めました。UMLについては既に広く知られていると思うので解説はしませんが、当方がどのように使っているかを紹介します。

UMLのツールは無償の物から大変高価なものまでいろいろとありますが、ここ2年ほどメインに使っているのは SparxSystems JapanのEnterprise Architectです。これ以外にJude Communityという無償のツールもお客様の指定がある場合に使用します。いろいろな図をサポートしていることDelphiのリバース・フォワードができること、表現力が豊かであること、価格面からEnterprise Architectの導入を決めました。ライセンス体系は独特でサポートに重点を置いています。返事が早いこと、問い合わせにより挙がった修正項目に丁寧に対応し修正が早いことなどサポートの質は高く、機能が改善・強化された物がダウンロードできますので、合理的なライセンス体系であると判断しています。

UMLはいろいろな図があります。講習を受けたときよく使う重要な図はクラス図シーケンス図と教えられたのですが、その当時はシーケンス図の必要性が理解できなかったのです。なぜならば当時携わっていたプロジェクトではクラスとクラスの呼び出し関係が単純でわざわざシーケンス図を描くほどのこともなかったからです。Accessなどのツールに組み込まれているGUI部品を使ってアプリケーションを開発する場合にはシーケンス図は要らないと思いますが、GUIそのものを作るような開発に着手したとき必要性を痛感しました。

シーケンス図が必要かどうかの分岐点のひとつはコールバックがあるかどうかによると思います。単純にメソッドを呼び出すだけのシーケンスではそれぞれのメソッドの役割だけを理解して中身をブラックボックスと見なすことができるので、そこからどのクラスのメソッドが呼ばれようと考慮する必要がないと理解することもできます。しかし、呼び出し元に返ってくる場合はそうはいかなくなります。相互に状態変化をもたらすのでどのような状況で呼ぶのか細かく制約されるからです。

Visitorパターンや、フォームとコントロールのように親子関係のあるクラスが相互に連係しながら動作する場合には、このような状況が現れます。

当方は通常分析段階からシステム構築をしていますので、アプリケーションの大まかなフローを描くのにアクティビティ図、業務フローを描くのにBPMN(UMLではない)、ユーザの分類と使用する機能の関係を表すのにユースケース図、コンピュータやプログラムの配置を表すのに配置図を使っています。一つのシステムをいろいろな角度から俯瞰できますので、単にヒアリングした項目を列挙するだけの場合に比べて抜けが少なくなります。Enterprise Architectで作成した図をWordに貼り付けて提案資料としてお打ち合わせ時に使っています。

Linux(Ubuntu,Fedore Core 6)

LinuxはWebアプリケーションを構築するときに開発環境として使用しています。実行環境ではレンタルサーバを使用してバックアップ・ウィルスチェックなど管理をプロバイダに任せられるところを選んできました。 最近ではグループウェアを所望されるお客様の声が増えてきました。その場合レンタルサーバではなく自社内にサーバを持ちたいとの意向もあるかと思います。私が今まで手がけてきた小規模業務システムではせいぜい5、6端末でしたのでお客様の事務所にサーバを導入する場合はWindows2003サーバを使用していました。しかしグループウェアとなると担当者1人に1台と考えると端末数は増えてCAL(クライアントアクセスライセンス)費用が大きくなります。

そこでLinuxをお客様に導入することも想定して、改めてLinuxディストリビューションを見直すことにしました。当方の場合はSI様を通じてシステムを導入しますので、SI様にわかりやすいインストール手順、管理用ユーザインタフェースが必要です。またオンラインバックアップが行えること、ファイヤーウォールなどのセキュリティが設定しやすいことも重要です。Fedora Core 6とUbuntuをインストールしてみました。使い込んだわけではなくインストールしてみた印象ととらえてください。

項目 Fedora Core 6 Ubuntu 6.10 desktop-ja
OSインストール ウィザード形式で難しくはない ウィザード形式で難しくはない
CDからOSを起動してインストーラを実行
試したユーザインタフェース GNOME
GNOME
バックアップ インストール時にLMVの選択がある Alternate版にしないとLVMが選択できない
パーティション構成によってはAlternate版でもLVMにならない
セキュリティ ファイヤーウォールが設定しやすい
調査中、Fedora Coreよりアクセス制御が難しそうな印象あり
その他 パッケージの更新が素直に実行できなかった(更新通知サービスを止める必要があった) Widowsを含め他のパーティションを自動マウント
SAMBA(Windows共有)が容易に導入できる
サーバソフトに使用するデーモン自動起動の設定に多少癖がある(aptを使わなかった場合に引っかかった)
デフォールトでインストールされるパッケージが少ないのでソフトをインストールするときに依存するパッケージを追加インストールする必要があった。

Ubuntuのデフォールト環境は結構良くできている印象がありました。しかしサーバとしての細かい設定となると強力なGUIやaptによるインストールは役に立たない気がしました。細かい設定を行わなければならないソフトはそんなに多くはないのでそれ以外のソフトをaptに任せてしまうと良さそうです。

Ubuntu, Fedora Core 6