20th Embarcadero Developer Camp

Similar documents
// このクラスの有効期間中の各呼び出しに使用される キャッシュされた Socket オブジェクト Socket socket = null; // 非同期処理が完了したことを通知するために信号を送るオブジェクト static ManualResetEvent clientdone = new Ma

デザインパターン第一章「生成《

intra-mart Accel Platform — IM-BloomMaker プログラミングガイド   初版  


Microsoft PowerPoint - はじめてのDataSnapアプリケーション_

Prog2_12th

Android プログラム ガイド

Indyを利用したメール送信機能開発

11 ソフトウェア工学 Software Engineering デザインパターン DESIGN PATTERNS デザインパターンとは? デザインパターン 過去のソフトウェア設計者が生み出したオブジェクト指向設計に関して, ノウハウを蓄積し 名前をつけ 再利用しやすいようにカタログ化したもの 各デ

21st Embarcadero Developer Camp T8

TestDesign for Web

新OS使用時の留意事項

Microsoft PowerPoint ppt

知って得する!現役ヘルプデスクが答えるDelphiテクニカルエッセンス

PowerPoint Presentation

intra-mart Accel Platform — IM-Repository拡張プログラミングガイド   初版  

TFTP serverの実装

SiTCP ユーティリティユーザガイド 2014 年 6 月 18 日 0.73 版 Bee Beans Technologies 1

22nd Embarcadero Developer Camp G6

Micro Focus Enterprise Developer チュートリアル メインフレーム COBOL 開発 : MQ メッセージ連携 1. 目的 本チュートリアルでは CICS から入力したメッセージを MQ へ連携する方法の習得を目的としています 2. 前提 使用した OS : Red H

Microsoft PowerPoint - ●SWIM_ _INET掲載用.pptx

Java言語 第1回

CodeGear Developer Camp

プロセス間通信

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

24th Embarcadero Developer Camp

C#の基本

21st Embarcadero Developer Camp T8

Microsoft PowerPoint - visualprogram.ppt

PowerPoint プレゼンテーション

eWide利用者ガイド

アルファメール 移行設定の手引き Outlook2016

PowerPoint Presentation

Thunderbird(Windows) 設定マニュアル 目次 1 POP 系の設定 初めて設定する場合 ( 追加メールアドレスの設定 ) 設定内容の確認 変更 メールアドレス変更後の設定変更 メールパスワード変更後の設定変更

PowerPoint プレゼンテーション

Microsoft Word - XOOPS インストールマニュアルv12.doc

ご利用のコンピュータを設定する方法 このラボの作業を行うには 事前設定された dcloud ラボを使用するか 自身のコンピュータをセットアップします 詳細については イベントの事前準備 [ 英語 ] とラボの設定 [ 英語 ] の両方のモジュールを参照してください Python を使用した Spar

5th CodeGear Developer Camp [A5]

目次 はじめに... 3 システムの必要条件... 3 サンプルアプリケーションの作成... 3 手順 手順 手順 手順 手順 手順 終わりに... 23

NP-500 V-860/V-980用

CashDrawer ライブラリ API 仕様書 2014/07/09 CashDrawer ライブラリ API 仕様書 Rev / 10

Prog2_15th

CoIDE 用 F4D_VCP の説明 V /07/05 USB の VCP( 仮想 COM ポート ) による非同期シリアル通信を行うプログラムです Free の開発ツール CoIDE で作成した STM32F4 Discovery 用のプロジェクトです プログラムの開始番地は 0x

1.SqlCtl クラスリファレンス SqlCtl クラスのリファレンスを以下に示します メソッドの実行中にエラーが発生した場合は標準エラー出力にメッセージを出力します (1)Connect() メソッド データベースへ connect 要求を行います boolean Connect(String

LogisticaTRUCKServer-Ⅱ距離計算サーバ/Active-Xコントロール/クライアント 概略   

Developer Camp

目次 1. 概要 動作環境

Microsoft Word - IPC-intro.docx


承 認

ネットキーの操作手順について

開発者が知りたい実践プログラミングテクニック! ~明日から使えるテクニック集~

Si 知識情報処理

PowerPoint プレゼンテーション

Microsoft Word - Win-Outlook.docx

Microsoft Word - tutorial3-dbreverse.docx

インストール手順 2 セットアップの種類 [ 標準インストール (S)] [Thunderbird を既定のメールプログラムとして使用する (U)] にチェックを入れ [ 次へ (N)] をクリックします インストール手順 3 セットアップ設定の確認 [ インストール (I)] をクリックします 2

「DataSnapユースケース研究」 多層技術の概要と最適化、実践テクニック

PowerPoint プレゼンテーション

まず,13 行目の HardwareTimer Timer(1); は,HardwareTimer というクラスを利用するという宣言である. この宣言によって Timer というインスタンスが生成される.Timer(1) の 1 は,OpenCM に 4 個用意されているタイマのうち,1 番のタイマ

クラス図とシーケンス図の整合性確保 マニュアル

1. USB の VCP( 仮想 COM ポート ) について USB の VCP( 仮想 COM ポート ) は USB を非同期シリアル通信として使用するための USB のドライバです PC には VCP ドライバをインストールする必要があります USB の VCP( 仮想 COM ポート )

intra-mart Accel Platform — イベントナビゲータ 開発ガイド   初版  

Delphi/400でFlash動画の実装

PCL6115-EV 取扱説明書

Webコンポーネントのカスタマイズ入門

導入編設定編設計手順書の構成 設定を行う前にお読みください 1 ケーブルモデムの設置 ケーブルモデムの概要と接続についてご説明いたします 設定手順書です 設定の際にお読みください 2 TCP/IP の設定 ネットワークの設定についてご説明いたします 3 インターネットオプションの設定 インターネット

PowerPoint プレゼンテーション

目次 移行前の作業 3 ステップ1: 移行元サービス メールソフトの設定変更 3 ステップ2: アルファメール2 メールソフトの設定追加 6 ステップ3: アルファメール2 サーバへの接続テスト 11 ステップ4: 管理者へ完了報告 11 移行完了後の作業 14 作業の流れ 14 ステップ1: メー

Origin 2017 と 2018 のプロダクトキーは共通なので 両方のバージョンを合わせてご契約 台数までしかインストールすることができません あらかじめご了承ください Origin を使用する PC を変更したい場合は 元の PC でライセンスを取り外してから 別の PC に同じプロダクトキー

VFD256 サンプルプログラム

知って得する!現役ヘルプデスクが答えるDelphiテクニカルエッセンス 8.0

ユーザーライセンス管理ツール操作マニュアル

10th Developer Camp - B5

1 検証概要 目的及びテスト方法 1.1 検証概要 Micro Focus Server Express 5.1 J の Enterprise Server が提供する J2EE Connector 機能は 多くの J2EE 準拠アプリケーションサーバーについて動作検証がなされています 本報告書は

アルファメールプレミア 移行設定の手引き Outlook2016

Cuoreテンプレート

CLUSTERPRO for Linux PostgreSQL HowTo

Microsoft Word - ssVPN MacOS クライアントマニュアル_120版.doc

1. 概要 この章では HDE Controller X LG Edition をお使いの方に向けて LGWAN 接続に特化した設定の説明をします HDE Controller X LG Edition 以外の製品をご利用のお客様はこの章で解説する機能をお使いになれませんのでご注意ください 452

メール送信テストツール手順書

User Support Tool 操作ガイド

外周部だけ矩形配列

第 2 章インタフェース定義言語 (IDL) IDL とは 言語や OS に依存しないインタフェース定義を行うためのインタフェース定義言語です CORBA アプリケーションを作成する場合は インタフェースを定義した IDL ファイルを作成する必要があります ここでは IDL の文法や IDL ファイ

JAVA とテンプレート

メディプロ1 Javaプログラミング補足資料.ppt

Javaの作成の前に

GettingStartedTK2

PowerPoint プレゼンテーション

Microsoft Word - USB60BCR_10.doc

Manual_Win81_JP.md

DJM-900nexus アップデート方法 for Microsoft Windows 7 A. 展開したファイルの内容を確認してください : 1. ダウンロードしたファイルを展開します ダウンロードしたファイルを右クリックし 表示されたメニューから すべて展開 を選びます 展開先を指定してファイル

スライド 1

PowerPoint プレゼンテーション

28th Embarcadero Developer Camp

認証システムのパスワード変更方法

スクールCOBOL2002

1 ユーザ認証を受けた権限で アプリケーションを利用するために ログインプロキシにアクセスします 2 ログインプロキシにより Shibboleth SP から Shibboleth IdP の認証画面にリダイレクトされます 3 ブラウザに認証画面を表示します 4 認証画面にユーザ / パスワードを入

intra-mart Accel Platform — イベントナビゲータ 開発ガイド   初版   None

データアダプタ概要

Transcription:

17 Th Developer Camp G6 ライトニングトーク State パターンを Delphi で実装する 東洋テクニカルシステム株式会社システム開発部福士光 1

17 Th Developer Camp 1 基本知識 2

状態とは? 状態 (State) とは? 同じ入力に対しても状態が異なれば振る舞いも異なる 同じ話を同じ人にしても そのときの気分 (= 状態 ) で反応が異なる みたいなこと 3

状態の遷移とは? 状態の遷移とは 外部からの入力や内部的な動作によって状態が変化してゆくこと 状態とその遷移を考えるときは 一定の間そこに留まるものだけを 状態 として考える 一瞬だけその状態に属し 何かをし終わったら別の状態に遷移する といったものは基本的に状態として扱わない 4

デザインパターンとは? パターン ( パターンランゲージ ) とは? もともとは建築家のクリストファーアレグザンダー (Christopher Alexander) が建築物をデザインするときの手法として考案した ソフトウェアに対してパターンという考え方を適用した 問題とその解決方法 そして適用した結果やトレードオフ そしてそれらの組み合わせに名前をつけたもの デザインパターンとは? デザイン ( 設計 ) における問題を解決して適切な構造をコードに与えるための手法 5

GoF のデザインパターンとは? GoF(Gang of Four) のデザインパターンとは? オブジェクト指向の設計に対してデザインパターンをンを適用 設計上の課題とその典型的な解決方法 ( コーディング ) に名前をつけたもの 3つのカテゴリー 23のパターンに分類している あくまで一つの考え方です ( 絶対的なものとして捉えないなほうがいいでしょう ) GoF 本 ( 参考文献 (1)) の著者である Erich Gamma Richard Helm Ralph Johnson John M. Vlissidesの 4 人をGang of Fourと呼んでいます 6

State パターンとは? State パターンとは? GoF の 振る舞いに関する パターンの一つ オブジェクトが内部状態に従って振る舞いを変えるような状況に適用する 詳細はGoF 本 ( と付属のCD-ROM) をお読みください Delphiではクラス参照型の変数とその仮想関数が有効に機能するので C++ のように状態毎のインスタンスを生成しない実装が可能 ( 状態の持つ内部情報はコンテキスト側に保持する ) 7

State パターンを使わない場合 if 文やcase 文で実装 ( 発生事象と状態で二重になる?) あるいは関数テーブルで実装 Stateパターンの実装は関数テーブルをDelphiのVMT ( 仮想メソッドテーブル ) に任せたもの と考えることができるかも 8

17 Th Developer Camp 2 サンプルについて 9

サンプルについて 今回のサンプルは TCP/IP で接続して郵便番号を問い合わせると該当する 住所を返してくれるサーバがあり このサーバとの通信を 行う という要求を想定する 応答には時間が掛かるかもしれないし エラー ( 応答が 不正だったりタイムアウトしたり ) が発生するかもしれない 10

サンプルについて ポート番号は 32100( 適当 ) 手抜きです 電文のデリミタは CR(0x0D) 0D) 要求電文 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 0 0 0 0 SP G E T SP # # # # # # # CR シーケンス番号要求郵便番号 (7 桁 ) 回答電文 00 01 02 03 04 05 06 07 08 09 0 0 0 0 SP O K SP SP X CR シーケンス番号応答住所 (Shift_JIS) 00 01 02 03 04 05 06 07 08 09 0 0 0 0 SP N G SP SP X CR シーケンス番号 応答 メッセージ 11

17 Th Developer Camp 3 分析 12

分析 状態遷移図 アイドル 理解をまとめる程度 適当でよい Standby Idle スタンバイ Request Disconnected 接続待ち 切断待ち Connected 回答待ち RecvAnswer Notify 13

17 Th Developer Camp 4 設計 14

設計 状態マトリクス 縦方向に状態 ( 状態クラスとして実装 ) を 横方向に事象 ( メソッドとして実装) を配置 グループ化された状態も考慮しておくとよい No 状態 Entry Exit Go Idle Go StandBy Request addr Connected Receive answer Disconnected Error 0 Idle N/A N/A 無視 1 無視無視無視無視無視 1 Stand by タイマ停止 N/A 0 無視 2 無視無視無視無視 (Connected) タイマ開始 N/A 切断 0 無視無視無視無視 1 エラー通知 1 2 Wait to connect タイマ開始接続 N/A 切断 0 無視 無視 要求送信 3 無視 1 エラー通知 1 3 Wait answer タイマ開始 N/A 切断 0 無視無視無視 回答通知 4 1 エラー通知 1 4 Wait to disconect タイマ開始切断 N/A 切断 0 無視無視無視無視 1 エラー通知 1 15

17 Th Developer Camp 5 実装 16

実装 画面 都合により Delphi 2007 です ソースコードはダウンロードできるようにする予定です ( テスト用サーバも ) 17

実装 ( 状態クラスの宣言 /1) { TCommStatus : Status class (abstract) } TCommStatus = class(tobject) public class function GetDescription: String; virtual; class procedure EntryState(DM: TDataModuleComm); virtual; class procedure ExitState(DM: TDataModuleComm); virtual; class procedure GoIdle(DM: TDataModuleComm); virtual; class procedure GoStandby(DM: TDataModuleComm); virtual; class procedure RequestAddr(DM: TDataModuleComm; const APostalCode: String); virtual; class procedure Connected(DM: TDataModuleComm; Socket: TCustomWinSocket); virtual; class procedure ReceiveAnswer(DM: TDataModuleComm; Socket: TCustomWinSocket; const RecvData: String); virtual; class procedure Disconnected(DM: TDataModuleComm; Socket: TCustomWinSocket); virtual; class procedure SocketError(DM: TDataModuleComm; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); virtual; class procedure ReceiveError(DM: TDataModuleComm; Socket: TCustomWinSocket; const Data: String); virtual; class procedure TimeoutError(DM: TDataModuleComm); virtual; 18

実装 ( 状態クラスの宣言 /2) type { TCommStatusIdle : Idle } TCommStatusIdle = class(tcommstatus) public class function GetDescription: String; override; class procedure GoStandby(DM: TDataModuleComm); override; { TCommStatusStandby : Standby } TCommStatusStandby = class(tcommstatus) public class function GetDescription: String; override; class procedure EntryState(DM: TDataModuleComm); override; class procedure GoIdle(DM: TDataModuleComm); override; class procedure RequestAddr(DM: TDataModuleComm; const APostalCode: String); override; { TCommStatusConnected : Connencted (abstract) } TCommStatusConnected = class(tcommstatus) public class procedure EntryState(DM: TDataModuleComm); override; class procedure GoIdle(DM: TDataModuleComm); override; class procedure Disconnected(DM: TDataModuleComm; Socket: TCustomWinSocket); override; class procedure SocketError(DM: TDataModuleComm; Socket: TCustomWinSocket; ErrorEvent: E TErrorEvent; E var ErrorCode: Integer); override; class procedure ReceiveError(DM: TDataModuleComm; Socket: TCustomWinSocket; const Data: String); override; class procedure TimeoutError(DM: TDataModuleComm); override; 19

実装 ( 状態クラスの宣言 /3) type { TCommStatusWaitToConnect : Wait to connenct } TCommStatusWaitToConnect = class(tcommstatusconnected) public class function GetDescription: String; override; class procedure EntryState(DM: TDataModuleComm); override; class procedure Connected(DM: TDataModuleComm; Socket: TCustomWinSocket); override; { TCommStatusWaitToAnswer : Wait answer } TCommStatusWaitAnswer = class(tcommstatusconnected) public class function GetDescription: String; override; class procedure ReceiveAnswer(DM: TDataModuleComm; Socket: TCustomWinSocket; const RecvData: String); override; { TCommStatusWaitToDisconnect :Wait to disconnect } TCommStatusWaitToDisconnect = class(tcommstatusconnected) public class function GetDescription: String; override; class procedure EntryState(DM: TDataModuleComm); override; 20

実装 ( 状態クラスの定義 /1) { TCommStatusIdle } class function TCommStatusIdle.GetDescription: String; Result := ' アイドル状態 '; class procedure TCommStatusIdle.GoStandby(DM: TDataModuleComm); DM.CommStatus := TCommStatusStandby; { TCommStatusStandby } class function TCommStatusStandby.GetDescription: String; Result := ' スタンバイ状態 '; class procedure TCommStatusStandby.EntryState(DM: y TDataModuleComm); DM.DoStopTimer; class procedure TCommStatusStandby.GoIdle(DM: TDataModuleComm); DM.CommStatus t := TCommStatusIdle; t class procedure TCommStatusStandby.RequestAddr(DM: TDataModuleComm; const APostalCode: String); DM.FPostalCode := APostalCode; DM.CommStatus := TCommStatusWaitToConnect; 21

実装 ( 状態クラスの定義 /2) { TCommStatusConnected } class procedure TCommStatusConnected.EntryState(DM: TDataModuleComm); DM.DoStartTimer; class procedure TCommStatusConnected.GoIdle(DM: TDataModuleComm); DM.DoDisconnect; DM.CommStatus := TCommStatusIdle; class procedure TCommStatusConnected.Disconnected(DM: TDataModuleComm; Socket: TCustomWinSocket); DM.CommStatus := TCommStatusStandby; class procedure TCommStatusConnected.SocketError(DM: TDataModuleComm; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); DM.NotifySocketError(Socket,ErrorEvent,ErrorCode); ErrorCode := 0; DM.DoDisconnect; DM.CommStatus := TCommStatusStandby; class procedure TCommStatusConnected.ReceiveError(DM: TDataModuleComm; Socket: TCustomWinSocket; const Data: String); DM.NotifyReceiveError(Socket,Data); DM.DoDisconnect; DM.CommStatus := TCommStatusStandby; 22

実装 ( 状態クラスの定義 /3) class procedure TCommStatusConnected.TimeoutError(DM: TDataModuleComm); DM.NotifyTimeoutError; DM.DoDisconnect; DM.CommStatus := TCommStatusStandby; { TCommStatusWaitToConnect } class function TCommStatusWaitToConnect.GetDescription: String; Result := ' 接続待機状態 '; class procedure TCommStatusWaitToConnect.EntryState(DM: TDataModuleComm); inherited; DM.DoConnect; class procedure TCommStatusWaitToConnect.Connected(DM: TDataModuleComm; Socket: TCustomWinSocket); DM.DoSendRequest(Socket); DM.CommStatus := TCommStatusWaitAnswer; 23

実装 ( 状態クラスの定義 /4) { TCommStatusWaitAnswer } class function TCommStatusWaitAnswer.GetDescription: String; Result := ' 回答電文受信待ち状態 '; class procedure TCommStatusWaitAnswer.ReceiveAnswer(DM: TDataModuleComm; Socket: TCustomWinSocket; const RecvData: String); DM.NotifyReceiveData(Socket,RecvData); DM.CommStatus := TCommStatusWaitToDisconnect; { TCommStatusWaitToDisconnect } class function TCommStatusWaitToDisconnect.GetDescription: String; Result := ' 切断待機状態 '; class procedure TCommStatusWaitToDisconnect.EntryState(DM: TDataModuleComm); inherited; DM.DoDisconnect; 24

実装 ( データモジュールの宣言 /1) type TCommStatus = class; TCommStatusClass = class of TCommStatus; TNotifyReceiveEvent = procedure (Sender: TObject; const RecvData: String) of object; TNotifyMessageEvent = procedure (Sender: TObject; const Msg: String) of object; TDataModuleComm = class(tdatamodule) ClientSocket: TClientSocket; TimerTimeout: TTimer; procedure DataModuleCreate(Sender: TObject); procedure DataModuleDestroy(Sender: TObject); procedure ClientSocketConnect(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocketDisconnect(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); procedure ClientSocketError(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); procedure TimerTimeoutTimer(Sender: TObject); private FCommStatus: TCommStatusClass; FRecvBuf: String; FSeqNo: String; FPostalCode: String; FOnStatusChanged: TNotifyEvent; FOnReceive: TNotifyReceiveEvent; i t FOnError: TNotifyMessageEvent; procedure SetCommStatus(const Value: TCommStatusClass); (to be continued...) 25

実装 ( データモジュールの宣言 /2) protected procedure DoConnect; procedure DoDisconnect; procedure DoSendRequest(Socket: TCustomWinSocket); procedure DoStartTimer; procedure DoStopTimer; procedure NotifyReceiveData(Socket: TCustomWinSocket; const RecvData: String); procedure NotifySocketError(Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; ErrorCode: Integer); procedure NotifyReceiveError(Socket: TCustomWinSocket; const Data: String); procedure NotifyTimeoutError; procedure DoStatusChanged; virtual; procedure DoReceive(const RecvData: String); virtual; procedure DoError(const Msg: String); virtual; public procedure SetServerParams(const IPAddress: String; const Port: String); procedure GoIdle; procedure GoStandby; procedure SendRequest(const APostalCode: String); property CommStatus: TCommStatusClass read FCommStatus write SetCommStatus; property OnStatusChanged: TNotifyEvent read FOnStatusChanged write FOnStatusChanged; property OnReceive: TNotifyReceiveEvent read FOnReceive write FOnReceive; property OnError: TNotifyMessageEvent read FOnError write FOnError; 26

実装 ( データモジュールの定義 /1) procedure TDataModuleComm.ClientSocketRead(Sender: TObject; Socket: TCustomWinSocket); var Recv: String; Position: Integer; RecvData: String; SeqNo: String; Response: String; while True do Recv := Socket.ReceiveText; if Recv = '' then Exit; FRecvBuf := FRecvBuf + Recv; while FRecvBuf <> '' do Position := AnsiPos(#13,FRecvBuf); if Position <= 0 then Break; RecvData := Copy(FRecvBuf,1,Position - 1); Delete(FRecvBuf,1,Position); SeqNo := Copy(RecvData,1,4); Delete(RecvData,1,5); (to be continued...) 27

実装 ( データモジュールの定義 /2) if SeqNo = FSeqNo then Response := Copy(RecvData,1,2); Delete(RecvData,1,5); if Response = 'OK' then CommStatus.ReceiveAnswer(Self,Socket,RecvData); end else CommStatus.ReceiveError(Self,Socket,RecvData); 28

実装 ( フォーム ) procedure TFormClient.Button1Click(Sender: TObject); FDataModuleComm.GoStandby; procedure TFormClient.Button2Click(Sender: TObject); FDataModuleComm.GoIdle; procedure TFormClient.Button3Click(Sender: TObject); FDataModuleComm.SetServerParams(Edit1.Text,Edit2.Text); FDataModuleComm.SendRequest(Edit3.Text); procedure TFormClient.CommStatusCahnged(Sender: TObject); Edit5.Text := FDataModuleComm.CommStatus.GetDescription; procedure TFormClient.CommReceive(Sender: TObject; const RecvData: String); Edit4.Text := RecvData; Edit6.Text t := ''; procedure TFormClient.CommError(Sender: TObject; const Msg: String); Edit6.Text := Msg; Edit4.Text := ''; 29

17 Th Developer Camp デモンストレーション 30

17 Th Developer Camp 6 参考文献 31

参考文献 (1) オブジェクト指向における再利用のためのデザインパターンン ( 改訂版 ) Erich Gamma Richard Helm Ralph Johnson John M. Vlissides 著 本位田真一 吉田和樹監訳 ソフトバンククリエイティブ ISBN4-7973-1112-6 (ISBN978-4797311129) 5,040 円 http://www.sbcr.jp/products/4797311126.html html http://www.amazon.co.jp/dp/4797311126 32

参考文献 (2) Head First デザインパターン Eric Freeman Elisabeth Freeman Kathy Sierra Bert Bates 著 木下哲也 有限会社福龍興業訳 佐藤直生監訳 ソフトバンククリエイティブ ISBN4-87311-249-4 4,830 円 http://www.oreilly.co.jp/books/4873112494/ /b /4873112494/ http://www.amazon.co.jp/dp/4873112494 33

17 Th Developer Camp Q & A 34

想定される質問とその回答 (1) サンプルプロジェクトを開こうとするとエラーになるんですけど 設計時パッケージ CodeGear Socket Components をIDEにインストールする必要があります IDEのメインメニューからコンポーネント パッケージのインストールでDelphiのインストール先のbinディレクトリにある dclsocketsxxx.bpl (Delphi 2007 なら dclsockets100.bpl ) を追加してから サンプルプロジェクトを開きなおしてください Delphi 2007 以外ではサンプルプロジェクトは動作しないんですか? Delphi 2007 およびそれ以前のバージョンであれば基本的に動作するはずです Delphi 2009 以降では String = UnicodeString となっている関係から そのままではコンパイルすら通りません ( 申し訳ない ) TClientSocket/TServerSocket とインタフェースしている部分を AnsiString とすることで動くのではないかと思いますが 35

想定される質問とその回答 (2) LTでの説明がはしょりすぎでよくわからなかったんですけど すいませんすいませんすいませんとりあえずこの資料とサンプルコード できれば参考文献のHead Firstデザインパターンをよくお読みください その上での不明点は公式フォーラムか Delphi ml で質問していただければと思います Embarcadero Discussion Forums: Delphi https://forums.embarcadero.com/forum.jspa?forumid=14 Delphi freeml http://www.freeml.com/delphi users 36

想定される質問とその回答 (3) サンプルプログラムの使い方を教えてください まずテスト用サーバ (TestSvr.exe) を起動します 待機ポートを確認してOpenボタンをクリックするとサーバソケットがlisten 状態になります Closeボタンでlisten 状態が解除されます Delay には電文を受信してから回答を送信するまでの時間を msec 単位で指定します また シーケンス番号を置き換える チェックボックスをチェックオンにすると回答電文に含まれるシーケンス番号が受信した要求電文と一致しなくなります 実装は手抜きされているので 1500045 と 1020072 以外の郵便番号はエラーになります 37

想定される質問とその回答 (4) 次にクライアント (TestClient.exe) を起動します 起動直後はアイドル状態になっていますので Standbyボタンをクリックしてスタンバイ状態に移行します ここでサーバのIPアドレス ポート番号を確認して問い合わせたい郵便番号 (7 桁 ) を入力し 問い合わせボタンをクリックするとサーバへの問い合わせのシーケンスが発動します 正常に回答を受信したときは住所が表示されます またエラーのときはエラーメッセージが表示されます なおクライアント側の通信タイムアウトは5000msec 固定です 38

想定される質問とその回答 (5) どのくらい複雑なケースならStateパターンを適用するべきでしょうか? もちろんケースバイケースですが Idleステート Standby ステートを含め4 状態以上ある場合は適用することを考慮していいのでは? というのが個人的な意見です Idleステートの存在意義がわかりません プログラム起動直後やプログラムの環境設定を行っているとき あるいはプログラムを終了しようとしているときなど 一連のシーケンスが発動してほしくないときに状態を Idleステートにしておく という使い方を想定しています エラー発生時にリトライしないとかずいぶん手抜きじゃないですか? Stateパターンを考える上での本質ではないので外しました もちろん現実のプロジェクトに適用するときはエラー発生時のリトライや 必要ならその際のウェイトなどもシーケンスに組み込む形で設計 実装されるべきだと思います 39

想定される質問とその回答 (6) ところでIDEに標準でインストールされていないTClientSocket/ TServerSocketコンポーネントを使うのはいかがなものかと TClientSocket/ TServerSocketコンポーネントを使用するのは確かにあまりお勧めできません (SMP 環境下で不具合があるとかいう話を聞いたことがあります ) 本当はIndyにするべきなんでしょうけれども Indyはブロッキング動作が基本なのでUIとはスレッドを分ける必要があるとか 非ブロッキング動作のWinSockをIndyでわざわざブロッキング動作にしているものをまた非ブロッキング動作にして使うのはどうなんだろう? とか いろいろあってこういうサンプルになっています 有償でもいいので非ブロッキングで使用できるお勧めのSocket 通信コンポーネントはありませんか? 40

17 Th Developer Camp ありがとうございました 41