2006年11月08日

DocumentDiffer クラス (6)

これまでご紹介した DocumentDifferクラス20061108_DocumentDiffer_v100.txt にまとめました。

おまけとして toStringWithLabel()関数 を追加しています。 toString()関数 ではフィールド名(アイテム名)をそのまま使うため、出力結果は開発者にしかわからないものでした。 こちらはフィールド名に対応した表示名を指定するラベルを渡すことにより、よりわかりやすい出力になっています。

更新ログをユーザーも参照することがある場合、こちらの使用をお勧めします。 またこちらは、ラベル登録したもの以外は出力しない仕様になっていますので、いちいち removeItem() しなくてすむので、その意味でも使いやすいです。

使い方の例はこちら。
Sub Postsave(Source As Notesuidocument)
Call aDocumentDiffer.process(Source.Document)

Dim targetList$ List
targetList$("Title") = "タイトル"
targetList$("Description") = "概要"

Msgbox aDocumentDiffer.toStringWithLabel(targetList$)
End Sub

続きを読む
posted by yamachan at 23:00| Comment(7) | TrackBack(0) | my設計パターン

2006年11月02日

DocumentDiffer クラス (5)

DocumentDiffer クラス (4) に引き続き、今回はお遊びコードをご紹介します。

ネタ元は LotusScript に対する不満?(2) Variant の名前でクラスを扱う、というあたり。カッコ良く言えば レイト・バインディング(late binding) を利用した実装ですね。 たぶんね。

DocumentDiffer クラスに、以下のような workWith() メソッドを追加します。 引数としては Variant を指定しています。 指定したオブジェクトと適切に連動する、という仕様書に書くと怒られるようなアバウトな仕様。

今回のコードでは、以前にご紹介した ログ生成用クラス との連携を実装してみます。 ログに変更点を書き出してくれるという目論見です。
Sub workWith(coWoker As Variant)
  If coWoker Isa "CoreLog" Then
    Call coWoker.logText(toString())
  End If
End Sub
が、このコードは僕の環境では動作しませんでした。 謎です。 なにせ、次のコードは動作するのですから...。
続きを読む
posted by yamachan at 01:16| Comment(0) | TrackBack(0) | my設計パターン

2006年09月26日

DocumentDiffer クラス (4)

DocumentDiffer クラス (3) に引き続き、コードをご紹介します。

まずはベタですが、チェック対象のフィールドを追加したり外したりする add/removeItem() 関数。 例えば更新履歴のフィールドなど、removeItem("updateHistory") などと外しておくのがお勧めデス。
Sub addItem(doc As NotesDocument, itemName$)
Dim tmpItem As NotesItem

Set tmpItem = doc.getFirstItem(itemName$)
If Not(tmpItem Is Nothing) Then
Call tmpItem.CopyItemToDocument(Me.oldDoc, itemName$)
End If
End Sub

Sub removeItem(itemName$)
Call Me.oldDoc.removeItem(itemName$)
End Sub

続きましては、更新されたフィールドの以前の値を得るための getOldValue() 関数です。 あると意外と便利なのと、内部の仕組みをあるていど隠蔽するために実装してみたり。
続きを読む
posted by yamachan at 23:51| Comment(0) | TrackBack(0) | my設計パターン

2006年09月21日

DocumentDiffer クラス (3)

超操縦メカMG にハマって更新が止まっている今日この頃。 僕らの世代を狙い撃ちのゲームだとおもうんですが、意外に売れてないみたいですね...。

さて今回も DocumentDiffer クラス (2) に引き続き、コードをご紹介します。

今回は、実際に差分を作成する process関数 です。 process関数の引数は、更新後のNotes文書 (NotesDocument) です。

実際に処理をおこなっているのは、Forall の部分です。 New で必要なフィールドのみ oldDoc にコピーしているので、今度はそれを1つずつ、更新後の文書の同名フィールドと比べているわけです。
続きを読む
posted by yamachan at 09:44| Comment(287) | TrackBack(0) | my設計パターン

2006年09月20日

DocumentDiffer クラス (2)

DocumentDiffer クラス (1) に引き続き、コードをご紹介します。

今回はコンストラクタ部分です。 コンストラクタは、対象のNotes文書を引数にします。

DocumentDiffer はインスタンス生成の際、後の差分作成(process 関数)の実行に備え、必要なフィールドを全て保持しようとします。 具体的には、内部にテンポラリ文書を作成し、必要なフィールド(NotesItem)をコピーしておきます。

保持しておくフィールドは、とりあえず 日付・名前・数値・テキストに限定しています。 また '$' 文字で始まるフィールドは、システムで利用するフィールドが多いので、保持する対象からはずしています。

さて、実際のコードをみてみましょう。
続きを読む
posted by yamachan at 00:57| Comment(301) | TrackBack(0) | my設計パターン

2006年09月09日

DocumentDiffer クラス (1)

先日、職場のヒトが ソックス の話をしていたので、ニーソックス絶対領域 に関する熱い話題 を期待して近づいていったら、J-SOX 法に関する話題でした... orz

なんちて。

最近、J-SOX だの 内部統制 だのの流れで、システムの要件に厳密な権限管理や、詳細ログの保存等が盛り込まれることが多いようです。

知り合いも既存の Notes DB に、文書の変更ログ機能 を追加するよう言われていました。 変更のあったフィールドを、基本的にはすべてログする必要があるとのことです。 フィールドの数が多いので眩暈がすると嘆いていました。

いい機会ですので、(頭の隅の)倉庫に眠っていた DocumentDiffer クラスをご紹介します。
続きを読む
posted by yamachan at 21:40| Comment(0) | TrackBack(0) | my設計パターン

2006年08月22日

ログ生成用クラス (6)

三回に分けて掲載した LotusScript コードを 20060822_CoreLog_v100.txt にまとめました。 使用する時は適当なスクリプトライブラリの Declarations セクションにでも貼りつけてください。

CoreLog クラスは最低限の機能しか実装していないため、誰が書いても似たようなコードになると考えます。 著作権等を主張することはありませんので、自由にご利用ください。

なにか不具合を発見された方、より良いコードを書かれた方、フィードバックいただければ嬉しいです。続きを読む
posted by yamachan at 00:10| Comment(0) | TrackBack(0) | my設計パターン

2006年08月21日

ログ生成用クラス (5)

ログ生成用クラス (4) に引き続き、CoreLog クラスの残りの実装をみていきましょう。 まずは処理のメインとなる2つのメソッドです。
  ' ---- Public methods ----

Public Sub logText(message$)
Me.getLog().AppendText(message$)
Call Me.getLog().AddNewLine(1)
End Sub

Public Sub traceText(message$, level%)
If level% <= Me.getTraceLevel() Then
Me.getTrace().AppendText(message$)
Call Me.getTrace().AddNewLine(1)
End If
End Sub
続きを読む
posted by yamachan at 22:48| Comment(0) | TrackBack(0) | my設計パターン

2006年08月20日

ログ生成用クラス (4)

ログ生成用クラス (3) に引き続き、CoreLog クラスの実装をみていきましょう。 今回はゲッターとセッターを抜き出してみました。

関係ありませんが、ゲッター と言えば、僕の心に浮かぶのは このページ。 いつも僕に勇気をくれます。
  ' ---- Getter/Setter methods ----

Public Sub setTraceLevel(level%)
If (0 < level% And level% < 100) Then
Me.traceMaxLevel% = level%
Else
Me.traceMaxLevel% = 0
End If
End Sub

Public Function getTraceLevel() As Integer
getTraceLevel = Me.traceMaxLevel%
End Function

Public Function getLog() As NotesRichTextItem
Set getLog = Me.itemDetail
End Function

Public Function getTrace() As NotesRichTextItem
Set getTrace = Me.itemTrace
End Function
続きを読む
posted by yamachan at 07:27| Comment(0) | TrackBack(0) | my設計パターン

2006年08月19日

ログ生成用クラス (3)

ログ生成用クラス (2) で使い方をご紹介した CoreLog クラスの実装を順にみていきましょう。 まずは最低限ということで、内部変数コンストラクタ 部分のみを抜き出してみます。
Public Class CoreLog
Private traceMaxLevel As Integer
Private logDoc As NotesDocument
Private itemDetail As NotesRichTextItem
Private itemTrace As NotesRichTextItem
Private timeStart As NotesDateTime

' ---- Constractor/Destractor methods ----

Sub New(doc As NotesDocument, level%, logType$)
Dim session As New NotesSession

If doc Is Nothing Then
Set Me.logDoc =
session.CurrentDatabase.CreateDocument
Me.logDoc.Form = "fLogCore"
Else
Set Me.logDoc = doc
End If
Set Me.timeStart = New NotesDateTime(Now())
Me.logDoc.Start = Me.timeStart.LSLocalTime
Me.logDoc.Executant = session.UserName
Me.logDoc.Status = "pending"
Me.logDoc.Type = logType$
Set Me.itemDetail =
createRichtextMember(logDoc, "Detail")
Set Me.itemTrace =
createRichtextMember(logDoc, "Trace")
Me.setTraceLevel(level%)
End Sub

Sub Delete
Delete Me.timeStart
End Sub

End Class

続きを読む
posted by yamachan at 00:02| Comment(0) | TrackBack(0) | my設計パターン

2006年08月18日

ログ生成用クラス (2)

ログ生成用クラス (1) に引き続き、ログ生成用クラスの使い方をご紹介します。

ログ機能は常に出力されるものですが、トレース情報 はレベル付けされた出力になります。 以下の単純な例を見てみてください。
  Dim aCoreLog As New CoreLog(Nothing, 2, "Sample")

Call aCoreLog.traceText(|レベル0|, 0)
Call aCoreLog.traceText(|レベル1|, 1)
Call aCoreLog.traceText(|レベル2|, 2)
Call aCoreLog.traceText(|レベル3|, 3)
Call aCoreLog.traceText(|レベル4|, 4)

Call aCoreLog.closeLog()
CoreLog クラスを生成する時の、第二引数が最大のトレースレベルの指定になります。 そして traceText() メソッドの第二引数が、出力する情報のレベル値を指定しています。

最大トレースレベル以下のレベル値が指定された場合のみ、メッセージがトレース欄に追記されます。 上記の例では最大トレースレベルとして 2 が指定されていますから、レベル0〜レベル2 の行だけが実際のログ文書に保存される仕組みになっています。
続きを読む
posted by yamachan at 00:15| Comment(0) | TrackBack(0) | my設計パターン

2006年08月17日

ログ生成用クラス (1)

Java: デザインパターン、JUnit、Log4J にも書きました、ログ生成用の簡単な LotusScript クラスをご紹介します。 まずは簡単な使い方をみてください。
  Dim aCoreLog As New CoreLog(Nothing, 2, "Sample")
Call aCoreLog.logText(|処理 開始|)

' 実際の処理...

Call aCoreLog.logText(|処理 終了|)
Call aCoreLog.closeLog()
"Sample" の部分はログのタイプを示す文字列で、自由に設定が可能です。続きを読む
posted by yamachan at 00:04| Comment(0) | TrackBack(0) | my設計パターン

2006年08月15日

プロフィール文書に関する愛憎劇 (2)

プロフィール文書に関する愛憎劇 (1) のようにプロフィール文書の扱いに悩んでいたのは、実は過去のこと。 最近の僕は 「通常の文書とプロフィール文書のハイブリッド」 な設計にしています。

仕組みは簡単で、管理ビューを1つ作成し、設定情報を通常の文書として管理するようにします。 で、その文書の更新の際に、Postsave で変更をプロフィール文書に反映させます。 例えば以下のような感じで。
続きを読む
posted by yamachan at 00:17| Comment(0) | TrackBack(0) | my設計パターン

2006年08月14日

プロフィール文書に関する愛憎劇 (1)

僕がとっても愛用し、かつ常に悩まされている仕組みに プロフィール文書 があります。

例えば僕の管理している Web システムは三桁近い数の Web サイトがあって、それぞれが独立した Notes DB です。 見た目はいろいろバラエティ豊かですが、設計は統一されています。 細かいところまで全部、プロフィール文書で設定できるようにしてみました。

プロフィール文書は手軽に使用できますし、システムにキャッシュされるだけあってパフォーマンスも良さげなんですが、、、トラブル発生時に問題解決に手間取ることも多いです。 普通の文書と違って、簡単にはアクセスできないのが困りものです。
 続きを読む
posted by yamachan at 05:06| Comment(0) | TrackBack(0) | my設計パターン

2006年08月12日

Querysave 依存症からの脱却?

他人の開発した Notes DB の修正を依頼されることがあります。 その場合にまず確認するのは、主に使用されているフォームの Querysave ルーチンですね。Querysave 部分が非常に長い場合、可能ならばその依頼を断ることにしています。

元の設計者にまったく罪は無くて、単に僕の趣味にあわないコードなだけなんですが、それはきっと僕にとって、あまり楽しくない仕事になるだろうから...。

常に必須なフィールドのチェックが無ければ、僕の Querysave はたいてい、以下のようにシンプルなものです。
Sub Querysave(Source As Notesuidocument, Continue As Variant)
If Source.FieldGetText("SaveControl") = "on" Then
Msgbox "アクションボタンを押して処理してください (破棄する
場合は保存の問い合わせで「いいえ」を選択)"
Continue = False
End If
End Sub
続きを読む
posted by yamachan at 00:28| Comment(535) | TrackBack(0) | my設計パターン