2017年4月19日星期三

7.用語辞書 8.画面設計

7.用語辞書
会話の背景:
システム分析段階では、用語辞書の作成を大事にしなければならない。
ユースケースやコンセプト図または詳細設計時のクラス図などもこの辞書で定義される用語に基づいて作成する必要がある。
用語辞書のライフサイクルはプロジェクトまたはシステムと同じであり、用語辞書をシステム分析からメンテナンスまで、ずっと維持する必要がある。また、すべてのプロジェクト参加者は、必要に応じて用語辞書を参照しなければならない。そうすることにより、コミュニケーション上(じょう)で起こる相互理解の不足や誤解を回避(かいひ)することができる。
登場人物:
近藤― システムアーキテクト
鈴木― PL
山田、田中―PG
会話:
鈴木:こんばんは。今日の昼には時間がなかったため、午後のミーティングはいまからしますが、よろしくお願いします。
そろそろユースケースの作業が終わり、前回議論していたコンテキスト図やコンセプト図なども作成しています。今日は近藤さんに用語辞書のことを皆さんに説明してもらいたいと思います。
田中:われわれも辞書を作るのですか?
近藤:そうです。ここでの用語辞書と言うのは、われわれがこのシステムを開発するために必要な辞書のことです。
田中:それにはなにを載せるのでしょうか?
近藤:基本的には、われわれがいまから使う言葉、名詞や動詞でも、用語辞書に入れてもらいます。
田中:その辞書の目的は?
近藤:そうですね。今、われわれは分析をしていますが、これから詳細設計に入り、その後はコーディングをします。そのときクラスを定義したり、メソッドを定義したりしますから、用語をちゃんと定義しないと、今話していることが、これから開発するシステムと整合性が取れなくなる恐れもあると思います。
田中:そうすると、各項目には、どんなものがありますか?
近藤:これははっきりとルールはないですが、われわれの経験だと、ひとつの項目には名前、英語名、意味・記述、連語、用例などが必要と思います。
鈴木:例をあげていただけるでしょうか?
近藤:いいです。
たとえば、見積という項目を例として、以下のようになると思います。
名前:見積
別名:見積もり
英語名:Quotation
意味.記述:お客様が注文する前に、品物の値段や品番などをまず調べる。そのときの問い合わせは見積と定義する。
連語:見積依頼、見積書作成、見積情報の照会など。
用例:お客様が見積を依頼する。
山田:それはわかりやすいですね。これだと開発するときにはみんなで、同じ言葉を使うことができます。
近藤:用語辞書は開発するときに使うだけではなく、メンテナンス時にも使います。こんな辞書がないと、メンテナンスの人は大変ですから。
山田:そうすると、この用語辞書のライフスタイルはプロジェクトまたはシステムとおなじになりますね。
近藤:そうです。
全てのプロジェクト参加者は用語辞書を参照しますから、システム分析からメンテナンスまで、用語辞書をずっと維持する必要があります。
鈴木:それはいいですけど、しかし、だれが責任を持ってこの辞書を作るか、誰が責任を持ってこの辞書を維持いていくかが問題ではないかと思いますけど。
近藤:その通りです。用語辞書に関しては、まず作成また編集の責任者が重要です。というのは、用語はシステムの各側面から出てくるので、できるだけ、みんなから集める必要があります。その集める方法を考えなければなりません。
鈴木:そうですね。用語辞書の配布(はいふ)も問題になると思います。これまでのやり方だと、紙に印刷して開発チームメンバーに配ることはできます。しかし、特に特に分析設計段階では用語辞書もよく変更されますので、いちいち配布すると、紙も無駄だし、皆に混乱を生じる恐れもあります。
近藤:最近、ウエブの方法で用語辞書を作ったり管理したりする方法が普及して来ました。というのは、用語辞書のサイトを立ち上げれば、皆が追加することができます。またどこでもいつでも参照することもできます。いかがでしょうか?
鈴木:それはいいと思います。
山田:最近WIKIというものを見ました。あれを使えば、チームメンバーが自由に追加したり、参照したりすることもできます。できれば、適当なWIKIエンジンを使って、用語自称を作ったらどうでしょうか?
鈴木:それはいい考えかもしれませんね。早速参考にして作ってみましょう。
今日はここまでにしましょう、近藤さん、どうもありがとうございました。皆さん、どうもありがとう。
皆:どうもありがとうございました。

8.画面設計
会話の背景:
詳細設計に入る前に、最後の作業として画面設計と帳票設計がある。
ここでいう画面設計とは画面の衣装設計ではなく、システムとしての完成予想図をユーザーに伝えるために設計のことである。また、ウエブ系のシステムの画面設計は従来のクライアント・サーバー系と相当違いがあるので、十分気をつけなければならない。
登場人物:
石田― プロジェクトマネージャー
鈴木― PL
山田、田中― PG
会話:
石田:こんにちは。
今週までに、ユースケースをはじめ、用語辞書までできあがりましたので、いわゆる要求分析段階のドキュメントはほとんどできました。今週からは画面設計に入りたいのですが。
山田:画面設計とは、先日鈴木さんなどが画面のレイアウトなどをやっていたことを時々(ときどき)みましたが、それのことですか?
鈴木:ええ、それは画面設計ともいえますが、少し、違います。私が先週からよその意匠設計専門の方と打ち合わせとしたりして、今回のシステムの全て画面のレイアウトやアイコン、また会社ロゴなどは大体決まりました。
石田さんが言った画面設計とは、おそらくわれわれのシステムの全部の画面作成だと思います。そうでしょう、石田さん?
石田:その通りです。
今日皆を集めて、画面設計をやってもらうことは、われわれのシステムの完成予想図を示すためのものです。もっと具体的に言うと、今回はウエブシステムなので、HTMLですべてのデモができる画面を作り出すことです。
山田:HTMLなら簡単だとおもいますので、大丈夫だと思います。
鈴木:そんなに簡単とは思わないのですけど。今回皆に作ってもらうHTML画面はシステムの紙芝居のように動かないといけないという要求があります。とういうのは、各画面では、たとえば特定のリンクを押すと、指定した画面へ遷移することが必要です。
田中:それは大変ですね。
鈴木:そうですけど、いわゆる紙芝居のようなものなので、たとえば10行のリストがあり、リストの各行には追加、削除というボタンがあるという場合に、設計したHTML画面中の各行に追加と削除ボタンをつけますが、おそらくただ一行だけ追加ボタンが有効で、また別のある行だけでは削除ボタンを有効にしているかもしれません。全ての行にすべてのボタンを有効にする必要はありません。
田中:なるほど。しかし、それでも工数が必要ですね。
石田:そうですが、やはりやらないといけないと思います。
なぜかとういうと、まずは、われわれここまでユースケースなどをたくさん書きました。これらはユーザーさんのIT部門の方にチェックしていただきますが、普通のエンドユーザーには、それだけだと、ちゃんと理解するのに無理があります。それで、このシステムの完成予想図として、動いているようなものを見せないといけない。エンドユーザーに、開発できたらシステムはこのようなものだ、といいたい訳ですから。
鈴木:これには、相当的な工数がかかりますが、むだとは思いません。われわれは今回の実際的なシステムでは、画面の部分はJSPで書きますので、HTMLで書いた画面設計のファイルを徐々にJSPへ作り直していけばいいと思いますから。
今の画面のレイアウトやアイコン、また会社ロゴなどができましたので、サンプルとして皆に配布します。皆がこれをベースにして、各自のユースケースに基づいて作ってもらいたいです。
山田:ユースケースだけだと、画面と機能のつながりが不明なことがよくありますが、どうすればいいでしょうか?
鈴木:これはいい質問です。私の方は一つの機能リストを書きました。このリストでは各画面上でどんな機能がありそうだ、どこへ遷移するなど、大体書きましたので、皆に参考してもらいます。
それと、皆の作業に伴い、私の方がこの機能リストを画面遷移フローへ変換しますから。最後には、私たちの画面設計と私の画面遷移フローと一緒に開発ドキュメントとして納品するつもりです。
山田:わかりました。
ところで、いまのHTMLで作るウェブの画面設計と以前のクライアントサーバーの画面設計との違いがあるのでしょうか?
鈴木:そうですね。ウェブの画面にはいくつかの特徴があります。まずは、特にビジネスあるいは基幹系のシステムでは、ウェブの画面はなるべく簡単にする必要があります。例えば、大抵(たいてい)一つの画面では一つのテーブルしかなく、一つのテーブルには2,3個のボタンが独立存在するようなものです。旧来のクライアントサーバー系の画面設計のように、一つ画面では複数のテーブルやコンポリストがあって、あちこちの連動することはウェブには相当無理があるそうです。
それと、ウェブじょうではセッションの概念があるので、複雑で長いセッションはあまり好ましくありません。いまの画面設計とあとの実現では、ビジネスのアクションをできるだけ単純で短くしたほうがいいと思います。いくつかのビジネスアクションが連続していて長くなると、ネットワーク上(じょう)でなか発生するのか予想できませんから。
山田:通常のウェブサイトでは皆がフラッシュなどをよく使って、動画的な効果を出していて、感動しますが、われわれも使いますか?
鈴木:それはケースバイケースですね。動画的な効果にはコストがかかると思いますから。今回われわれが開発しようとするシステムはビジネスシステムなので、ビジネスの正確性、操作の簡単さ、システムのパフォーマンスなどが最優先なので、動画的な効果はなくてもいいでしょう、残念ですけど。
山田:そうですか。わかりました。
石田:それでは、皆さん、鈴木さんの書いた機能リストと各自分担したユースケースにより、画面設計の作業に進んでください。きょうのミーティングはここで終わりにします。皆さん、ありがとうございます。
皆:どうもありがとうございます。

2017年4月18日星期二

5.ユースケースを書く 6.コンテキスト図とコンセプト図

5.ユースケースを書く
会話の背景:
ユーザーの要求を明確に記述するために、ユースケースを書く。
ユースケースはシステムと外部との相互作用を表現するもので、システムの機能仕様であり、あるいは、ユーザーと開発者間の契約とも言える。
なぜなら、これらは、われわれが開発しようとするシステムが、どのようになるかをユーザーに説明するもので、ユーザーとのコミュニケーションの大事な手段ともなる。
また、ユースケースはシステム開発プロセスを駆動する中心的なドキュメントでもある。
登場人物
鈴木ー PL
佐藤、田中- PG
会話:
鈴木:おはようございます。
これまでに、われわれはユーザーの要求をよく聞き、現場の資料も集めました。これからは、もっと厳密にユーザーの要求を記述しなければなりません。そのために、これからユースケースを書いて、要求を整理しましょう。
佐藤:ユースケースについて聞いたことがありますが、実際に書いたことがまだありませんので、簡単に、紹介してもらえますか?
鈴木:そうですね。ユースケースはわれわれが開発しようとするシステムの機能をユーザーに説明する手段です。ユースケースでは、さらにシステムの境界を定義します。つまり、だれがこのシステムを使い、このシステムがどこまでの機能を持つのかということを定義します。
佐藤:わかりました。でも、どんなドキュメントを書くでしょうか?
鈴木:ユースケースのドキュメントは二つの種類があります。まずはユースケース図です。二番目はユースケース記述です。
佐藤:ユースケース図の記号と要点は、何でしょうか?
鈴木:各々(おのおの)ユースケースは一つの機能または操作を記述するので、基本的には誰が何をするかを記述します。そのため、ユースケース図では基本的にユースケース名(楕円)、アクター(人型)、関係(接続線)を含んでいます。
佐藤:例で説明してもらえるでしょうか?
鈴木:はい。たとえば、車両見積もり作成という機能では、ユースケース名は「車両見積を作成する」で、アクターは営業マンと外部のデータベースで、アクターとユースケース名の間は、連続線で結びます。
田中:すみませんが、営業マンがアクターになることはわかりますが、なぜデータベースもアクターになるでしょうか?
鈴木:そうですね。ユースケースは実現しようとするシステムの立場から記述するので、このシステム以外で、システムと相互作用をする特定の機能を持つもの、または特定の操作を行う別のもの、たとえば外部のシステムやデータベースなどを操作するものならば、すべてはアクターと呼ばれます。
田中:そうですか、わかりました。
それと、もしシステムの機能が複雑で、一つのユースケースでうまく表現できない場合はどうすればいいでしょうか?
鈴木:そんなことはよくあります。そこで、ユースケースの間には包含、拡張の関係があるので、これらの関係を使えば、一つの大きなユースケースをいくつかに分離し、いろいろなユースケース間の関係を表現できると思います。
田中:なるほど。それでは、ユースケース記述の方法を教えていただけますか?
鈴木:はい。ユースケース記述を照会しましょう。
ユースケース記述はユースケース図より正確に定義する手段として、ある機能のイベントフローを記述します。もちろん、このイベントフローはシナリオ図で書くこともできますが、シナリオ図はイベントフローの一つインスタンスだと思えばいいと思います。ユースケース記述はユースケース図より詳しく機能の流れを記述できます。実際には、ユースケース図よりユースケース記述のほうがもっと重要だと思います。ユースケース図は、他人に説明をするなら、また、システム全体を理解するには有効ですが、ユースケース図だけでは、機能の仕様を表すには、十分ではありません。
田中:それは助かります。ユースケース図記述を行うときの要点はなんでしょうか?
鈴木:ユースケース記述に関しては、UML標準の中では統一されていませんが、大抵以下の部分を含んでいると思います。ユースケース名、概要、基本フロー、代替(だいたい)フロー、例外フロー、事前条件、事後条件、などです。
佐藤:概念は大体わかりましたが、ユースケース図でもユースケース記述でも、サンプルをいただけるでしょうか?
鈴木:それは後で、例を挙げましょう。
佐藤:最後ですが、ユースケースに関してどんな参考文献がありますか?
鈴木:そうですね。たとえば、アリスターコーパンさんが書いた「ユースケース実践ガイド―効果的なユースケースの書き方」という本は参考にできると思います。訳本(やくほん)は翔泳社が出版しました。それ以外にもいろいろありますが、サンプルと一緒にリストしておきましょう。
佐藤:どうもありがとうございました。
鈴木:それでは、皆さんには今回車両販売管理システムのユースケースを書いてもらいます。がんばってください。きょうのミーティングはここまでです。

6.コンテキスト図とコンセプト図
会話の背景:
システム分析段階ではユースケースを作成することが中心的な作業であるが、しかしながら、ユースケースだけではうまく表現できない部分も相当ある。たとえば、システムの全体に関する概念や機能、また外部との情報交換など。それに対していろいろな手段がある。ここではコンテキスト図やコンセプト図を紹介する。
登場人物:
近藤―システムアーキテクト
鈴木― PL
山田、田中:PG
会話:
鈴木:こんにちは。
これまでに、皆さんにユースケースを書いてもらいました。大変お疲れ様です。なにか問題があるでしょうか?われわれはどう対処(たいしょ)すればいいか、などを議論してもらいましょう。
山田:そうですね。ユースケースの書き方はなんとかわかってきましたが、具体的なユースケースを書くと、システムの全体に関する概念や機能などが見えなくなる恐れがありますが、それにたいして何かいい方法あるでしょうか?
近藤:はい。まず、よくやっている方法はユースケースリストです。すなわち、一つの画面(図形の方法)また一枚のページ(テキストの方法)で、全てのユースケースのタイトルを番号で関係をつけながら、集めてリストしておきます。
山田:OK、わかりました。
もう一つは、実際的な現場のユーザーには、データの流れを表現していないユースケース図は、直観的に理解しにくく、データの流れを表すDFDのような設計図のほうがわかりやすいではないでしょうか?
田中:すみませんが、DFDとは?
鈴木:DFDはData Flow Diagramの略です。すなわち、データの流れを表すためのダイアグラムです。
近藤:そうですね。一部のオブジェクト指向の本によると、DFDなどはオブジェクトの概念とは反対のものなので、あまり使わないように薦めています。しかし、私の経験では、それは参考にはなりますが、まったくその通りにやる必要はないかもしれません。
ユースケース図は、やはり開発するシステム機能に早く集中する傾向があり、開発対象とするシステム外のほかのシステムや要素とのつながりが漏らしてしまうことがあるようです。また、ユースケース図はシステムの範囲を決めるべきだが、システム開発の初期では、範囲をはっきり決めるのはなかなか難しいこともよくあります。
山田:そうですか。
近藤:そのため、全ての人が理解できる、システムを一枚の図で表すようなものが必要です。これにはコンテキスト図が向いています。ここで言うコンテキスト図は一種のDFDですが、システム外(そと)とのデータのやり取りのみを記述し、システム内部のデータについては何も記述しないものです。また、コンテキスト図は、ユーザー側の企画書などにすでにある場合は、それをチェックして、開発側で流用できるケースもあると思います。
そうすると、この前言ったように、ユースケースが顧客とのコミュニケーションに使われるというのとちょっと矛盾するようにおもわれますが、やはり現実には、同じようなものの違った表現が必要です。
山田:どうもありがとうございます。コンテキスト図に関してはわかりました。ところで、各ユースケースで出てきた概念や名前など名詞は、これからはクラスになると聞きましたが、そうでしょうか?
近藤:それの答えはYesでもありNoでもありますね。各ユースケースで現れた名詞はクラスになる可能性が十分ですが、必ずクラスになるかどうか、いまの時点ではまだわかりません。そのため、コンセプト図を導入することが必要だと思います。
田中:コンセプト図とは?
近藤:コンセプト図は一種のクラス図ともいえますが、分析レベルのものです。普通のクラス図ではクラスの属性と操作などの記述が必要ですが、ここではおもに名前だけを整理した図になります。とういうのは、基本的にはユースケースから出てきた名詞を整理したうえで、重要な意味をもつ名詞、あるいはオブジェクトらしい名詞をリストし、それらの名詞の間の関係をつけてみます。その目的は、重要な概念をみつけ、重要ではない概念を捨てることです。コンテキスト図と同じように、できるだけ、一枚の図でこのシステムの重要な概念をお客様にみせたほうがいいと思います。
田中:わかりました。われわれもコンセプト図を書きましょう。
それと、ユースケース記述を表すためにシーケンス図を使うこともできるでしょうか?
近藤:そうですね。クラス図と同じように、シーケンス図でも分析レベルと実装レベルの区別があると思います。一般的にいうと、実装レベルのシーケンス図はオブジェクト間のメッセージ通信です。しかし、分析段階ではオブジェクトそのものがまだはっきりしていないので、オブジェクト間のメッセージ通信より、システムの流れを表します。言い換えると、ユースケース記述の替わりに、図で表現するものです。われわれは、このようなシーケンス図をシナリオ図とよんでいます。シナリオ図の主な特徴は明確的なオブジェクトはもっていません。
田中:大体、かんじはつかめましたが、まだ十分に理解できていないようです。例で説明してもらえますか?
近藤:わかりました。
たとえば、「車両の注文書」を作成するというユースケースでは、その流れは、以下のようになっている。
・お客様の注文情報を入れて、
・システムがデータベースから対応する見積情報を引き出し、
・その見積情報に基づいて注文書のデータを纏め、また今回注文の情報を付け加え、
・最後にそのお客さんの注文書を作成し、
・確認したうえで、印刷する。
このような流れをシナリオ図で表すことができます。
田中:わかりました。これからは、われわれもユースケースリスト、コンテキスト図、コンセプト図、および一部のシナリオ図を書いてみましょう。
鈴木:それがいいでしょう。がんばりましょう。

2017年4月17日星期一

3.成果物と納品物 4.実行環境と開発環境

3.成果物と納品物
会話の背景:
開発スケジュールを完成させるために、作業内容とその期間だけではなく、各期間で作成すべき開発ドキュメントなどの成果物を決めなければならない。
プロジェクトが始まる時に、最終的な納品物となる成果物の種類と内容を、お客さんと打ち合わせて、明確にする必要がある。
登場人物
石井- お客様
石田- プロジェクトマネージャー
鈴木、斉藤- 開発チームリーダー
会話:
石田:こんにちは。
先週スケジュールを立てましたが、それに対して各段階の開発ドキュメントを決めないといけません。もちろん、一番大事なことは最終納品物をお客様と確認することです。
石田:井上様、納品物となる成果物の種類ですが、どのようなものをお考えでしょうか?
井上:この前も言いましたように、要求仕様書の取りまとめはお願いします。それと、最終納品としてはインストールの説明書とユーザーマニュアルももちろん必要ですね。
また、納品の一部ともいえますが、そちらの開発ドキュメントも一セットいただきたいです。
石田:わかりました。
それなら、これから開発ドキュメントに関して検討してみましょうか?
斉藤:まずは、もちろん要求仕様書の取りまとめを行います。それと、新ストール説明書とユーザーマニュアルもわれわれが作成します。
鈴木:そうですね。開発チームの立場から考えると、開発ドキュメントは以下のように想定しています。
システム分析と設計段階には、コンテキスト図とコンセプト図、ユースケース図とユースケース記述、用語辞書、またHTMLで表現できる画面設計書を作成する予定です。
詳細設計段階には、クラス図、シーケンス図、状態図(ステートチャート)、データベース設計書、帳票設計書などを開発します。
斉藤:それと、コードはもちろんですが、リリースノートとともにテストリポートも一緒に出します。
最終納品ではないですが、開発段階とメンテナンス段階では、バグリポートや変更連絡票なども発生しますので、お客様が必要であればこちらも提示できると思います。
井上:なるほど。
ところで、いつ頃、何をもらえるかを説明いただけますか?
石田:なるほど。
基本的には、開発終了時点で、お客様への納品としては全部提出します。ただし、こちらは反復型のアプローチを使っていますので、開発途中でもドキュメントは徐々に完成していくと思います。
鈴木:時期的には、十月末頃にはシステム分析と設計がほぼ終わる予定なので、コンテキスト図とコンセプト図、ユースケース図とユースケース記述および用語辞書ができると思います。
井上:画面設計書もシステム分析と設計の成果物といわれましたけど。
石田:そうですね。十月末には画面設計書はほぼできるとおもいますが、われわれの経験では詳細設計までには相当変更があります。コーディングに入ると安定してきます。
そのため、十一月末や十二月の初めになると、画面設計書と、クラス図、シーケンス図、状態図(ステートチャート)、データベース設計書、帳票設計書などとあわせて出すつもりです。
井上:なるほど。勉強になりました。
石田:それと、要求仕様書は十月には提出します。これは今回の開発のベースになると思います。リリースノートは各リリースについていきます。また、二月末ごろにはインストール説明書とユーザーマニュアルを納入します。
井上:わかりました。ドキュメントの共有や、やり取りに関しては、何かいい方法があるでしょうか?
石田:いまの計画では専用のウェブサーバーを立ち上げて、これらのドキュメントはバージョンをつけてウェブサイト載せますから、VPNなどを使えば全部見えると思います。
井上:その通りです。
それでは、井上様ありがとうございました。
(開発メンバーに対して)みなさんもお疲れ様でした。
今日のミーティングはここまでです。


4.実行環境と開発環境
会話の背景:
実際の作業に入る前に、実行環境と開発環境をきちんと決める必要がある。
一般的には実行環境はお客様の要求により決まるが、開発環境はほとんど実行環境により制約される。時には、ユーザーから開発環境に対しても要求があることもある。
今回のミーティングは開発チームの内部ミーティングである。
登場人物
石田- PM
鈴木- PL
山田、佐藤- チームメンバー
会話:
石田:こんにちは。
これまでに、スケジュールと成果物も決まりましたので、そろそろ実際的な作業に入ります。その前に、今日は、われわれの実行環境と開発環境を明確にしましょう。まず、鈴木君から、お客様と実行環境に関して打ち合わせをした内容を皆さんに伝えてもらえますか?
鈴木:はい。午前中に井上さんをはじめとするお客様と打ち合わせをしました。お客様の要求は、サーバーはオープンソースのものを使いたいことで、Linuxになりました。
山田:Linuxといっても、いくつかのディストリビューション(distribution)がありますけど、RedHatでしょうか?
鈴木:そうです、RedHat V8.0になりました。ただし、われわれのシステムはビジネスシステムであり、ローレベルのOSとは直接関係があまりないので、別のLinuxディストリビューションたとえばTurboLinuxでもいいと思います。
それと、ウェブサーバーはapacheとTomcatの組み合わせでできると薦めました。お客様もこれでいいということでした。
佐藤:データベースは?
鈴木:データベースもオープンソース系なので、やはりPostgreSQLにしたい、とお客様から要望がありました。
佐藤:われわれは最近までのプロジェクトでは、ほとんどMysqlを使ってきましたが、今回のpostgreSqlとMysqlはどのように違いますか?
鈴木:これまでつかってきたMysqlもPostgreSQLもオープンソースのデータベースです。MySQLのほうが簡単で、使いやすくて、また単純なくえりーだと、速いです。それに対して、PostgreSQLの方はより丈夫で、データの容量も大きいです。とくにトランザクション機能もちゃんとサポートできますので、商用データベースと同じようにエンタープライスの場合はよく使われています。
佐藤:そうすると、われわれの開発環境でもPostgreSQLで行いますか?
鈴木:そうです。原則としては、特別な理由がなければ、開発環境はできるだけ実行環境と同じようになればいいと思います。それで、今回の開発環境では、データベースはPostgreSQLで、ウェブサーバーはApacheとTomcatの組み合わせになります。
山田:もしかすると、われわれのマシンにもLinuxにする必要でしょうか?
鈴木:これはイェスノーですね。
先に話したLinuxとはサーバーマシンをしていましたが、クライアントマシンについては言っていませんでした。われわれの開発サーバーはもちろんLinuxにするが、各開発メンバーの開発マシンは、特別な要求がないため、今まで通りWin7を使います。現実的に言えば、現場のユーザーさんのクライアントはwin7を使っていますから。
山田:それで、開発環境はなんでしょうか?
鈴木:今回は、われわれはEclipseを使います。EclipseはオープンーソースのIDEとして、数年まえから大好評を博していました。欧米では20%のjava開発者がEclipseを使っているという報告もあります。
山田:そうですか。われわれの中ではこれまでにWebSphere Studioを使ったこともありますが、なにか特別の違いがありますか?
鈴木:実はWebSphere StudioはIBM社がEclipseの上(うえ)に構築したもので、その核はEclipseでした。私は個人的にも去年からずっとフォローしてきましたが、あまり差異はなさそうです。
山田:そうですか。それはいいと思います。
最後に聞きたいですが、今回のドキュメントは今まで通り、MS Officeを使うのでしょうか?
鈴木:そうです。MS OfficeのWordやExcelをそのまま使ってください。
Eclipseではこれらのファイルフォーマットもサポートしているそうです。また、Eclipse上でCVSにより情報共有が簡単にできるので、今回は全ての開発ドキュメントをEclipseのプロジェクトに入れて、バージョン管理をします。Eclipse上(じょう)では、バイナリファイルも、ソースコードと同じようにチェックインやチェックアウトすることができますから。
山田:それはいいですね。
石田:それでは、実行環境も開発環境もだいたい決まりましたので、それに対して必要なツールやフレームワークのインストールなど作業は鈴木にお願いいます。
鈴木:わかりました。分担してやります。
石田:そのほかなにか質問があるでしょうか?
山田:ちょっとききたいのですが、テスト環境はどうなるでしょうか?
石田:これはいい質問ですね。サーバーの方(ほう)がいいですが、同じように作っておきましょう。クライアントの方は私の聞いたところではユーザーさんの現場ではwin7とwinxp両方があるので、気をつけないといけませんね。
鈴木:その件については、私の方で調べさせてもらいましょう。
石田:それは、助かります。
それでは、今日はこれで終了しましょう。

2017年4月16日星期日

1.案件の打ち合わせ。2.スケジュールの計画

会話の背景:
プロジェクトが発足する前の顧客との打ち合わせである。
開発がはじめるということが決定し、この開発に関する正式な会議である。このミーティングでは、このプロジェクトの背景、範囲、また現状などについてユーザーのなまの声を聞く。
登場人物:
井上、石井ー お客様
石田ー プロジェクトマネージャー
鈴木ー 開発チームリーダー

会話:
石田:こんにちわ。お忙しい中、お集まりいただいて、ありがとうございます。
今日は、はじめての会議ですので、各自の自己紹介のあと、この案件の概要を把握し、今後の作業の進め方について、検討できればと考えています。
私は日成ソフトウエア株式会社の石田と申します。今回開発のプロジェクトマネージャーを担当させていただくことになっています。まず、お互いにはじめてのかたもおられるとおもいますので、名刺を交換いたしましょうか?
(名刺交換)
石田:それでは、申し訳ありませんが、各自の自己紹介をお願いいたしたいと思います。まず、安井自動車株式会社の井上様の方(ほう)からお願いできるでしょうか?

井上:私は、安井自動車株式会社の井上と申します。今回うちの車両販売管理システムを開発するため、日成ソフトウェアにお願いすることにしました。これからよろしくお願いします。
鈴木:こんにちは、私は日成ソフトウェアの鈴木と申します。今回の開発のチームリーダーを担当させていただきます。車両販売管理システムに関しては初めてなので、勉強させていただきます。どうぞよろしくお願いします。
(自己紹介)
石田:次に、この案件の背景目指すところについて、お客様の立場から、説明いただければ、と思います
井上:では、私から概要を説明したいと思います。詳細は、後ほど石井のほうから説明いたします。
車両販売管理システムはいくつかの機能を持ってほしいです。大きくいうと、顧客からの問い合わせまた見積、販売会社への見積、顧客の注文、納品管理などがあります。各情報に対して、照会や一覧表など統計情報が必要です。
石井:続いて、現場の状況、改善点、要望について説明いたします。従来はほとんど手作業でやっていますが、販売会社の情報は外部データとして参考にできると思います。ユーザーの立場から見ると、顧客情報を正しく、早いうちに参照したいのです。
うちの場合はみんながコンピューターには詳しくないので、画面の設定などはできるだけ簡単にしていただきたいです。しかし、帳票などはできるだけ現在使っているものと同じようにしてもらいたいですね。ビジネスのプロセスはあまり変わってはいけないですから。このシステム開発の窓口はわたしなので、何かありましたら対応しますから、ご遠慮なくご連絡ください。
石田:大体わかってきましたが、細かい点はいろいろとまだあるとおもいます。
こちらは鈴木君に今回チームリーダーをやってもらいますから、こちらの窓口ともいえます。
それでは、とりあえず、ちょっと休憩をいれましょうか?その後はプロジェクトに関する質問や今後の予定について見当できればと思います。
(休憩)

2.スケジュールの計画

会話の背景:
要求から纏まってきたので、具体的な開発すげジュールを立てる。
スケジュールを立てるためには、開発プロセスおよび開発手法を決める必要がある。それには、多くの場合、ユーザーからの制約があり、それをベースにしてスケジュールを作ることは実際によくある。

登場人物
井上- お客様
石田- プロジェクトマネージャー
鈴木- 開発チームリーダー

会話:
石田:おはようございます。今日は、要求もかなり見えてきましたので、そろそろ具体的開発スケジュールを検討したいと思います。お客様も交えて、関係するSEやチームリーダーにも集まってもらって、率直に話しをしたいと思います。
それでは、まずは客様からお願いします。
井上:ユーザーの立場から言うと、このシステムの本稼動は来年の四月の初めを予定しています。システムの導入と移行の期間を一ヶ月と考えると来年の三月の初めには、開発を終了してもらいたいです。
石田:なるほど。たとえば、要求変更や開発のリスクを減らすために、開発プロセスとしては、反復型RUPを参考にして、計画を立てたらいいと思います。大雑把に考えると、全工程で六ヶ月ぐらい必要です。今、八月ですから、九月から始まるとして計画すればいいかもしれません。
鈴木:もっと具体的に詳細を検討しましょう。
石田:大きくは二つのサイクルで、第一サイクルは最初の三ヶ月で、二番目のサイクルは更に一ヶ月ごとに三回小さいサイクルになると思います。また、最後の一ヶ月は一つのサイクルではありますが、ほとんどシステムのパッケージングやドキュメント周りの作業になると思います。
井上:そうすると、最初の三ヶ月はプロトタイプを作るということですか?
石田:そうですね。そのようにもいえますが、われわれの経験では、第一サイクルの終わるところは、ちょっと動いているシステムを出さなければなりません。バージョン0.6,0.7,0.8,0.9の順番でリリースしていくことになります。
井上:そうですか。それなら、最初の三ヶ月はどう分割すればいいでしょうか?
石田:これはまだ深く考えていませんが、おそらく以下のように計画しようかと思います。
最初の一ヶ月は要求定義を中心に、ユースケースなどシステム分析、またアーキテクチャー設計をします。それと同時に、画面設計も開始します。この一ヶ月の終わりには、プロトタイプとはいえないですが、動いている画面設計あるいは紙芝居のようなものができるはずです。
その後の二ヶ月のうち、前半の一ヶ月は詳細設計に入り、そのためクラス図やデータバース設計などを完成しなければなりません。後半の一ヶ月にはコーディングに入って、すばやくコーディングします。
私の言うとおりにうまくいけば、この時点で、システムの基礎となるインフラが出来て、一部の機能も出来ていると思います。
井上:概要はわかりました。ちょっとコーディングの時間が少ないようですね。それと、もし、なにか予想以外のことが発生したら、どうなるでしょう。
石田:われわれはほかの販売システムをいくつか開発したこともありますし、また品質と進捗の管理をきちんとやっています。毎週、品質と進捗の管理ミーティングを行います。問題があればすぐ必要なサポートを入れます。予定通り進んでいくと思いますから、あまり心配しないでください。
鈴木:そうですね。われわれは分析や設計を重視しています。コーディングには、いろいろなツールもありますし、これまでに作ったソフトウェアの部品やライブラリーもありますから。
石田:それで、コーディングに入ると、要因を追加したり、打てる手も増えるので、大丈夫だと思います。
井上:それならばいいと思います。
石田:それでは、スケジュール表の概要は私が作成します。成果物のリストには鈴木に作ってもらいましょう。
鈴木:わかりました。私の方は、スケジュールの各段階に対応した成果物のリストを作ります。
石田:また、このスケジュールにしたがって、井上様をはじめお客様との打ち合わせのスケジュールとリリースプランも私のほうで作成いたします。皆さん、よろしいでしょうか?
みんな:結構です。
石田:それでは、今日のミーティングはここまでにしますが、以上で決まったスケジュール表、成果物のリスト、お客様と打ち合わせスケジュール、およびリリースプランは来週の初めに終わらせるようにがんばりましょう。
石田:井上様ありがとうございます。
(開発メンバーに対して)皆さん、お疲れ様です。
井上:お疲れ様でした。
みんな:どうもありがとうございます。

2017年4月13日星期四

面试 棉结

はじめまして、○と申します。自己紹介させていただきます。
私は、XXXX年にソフト開発の仕事をはじめ、今年でXX年目になります。200X年に日本に来て、いろいろなプロジェクトをやりました。SEやPLとして基本設計、詳細設計、基盤構築、製造、テストなどさまざまの仕事をやりました。Web系の開発においては特に得意です。長い開発の経験を持っているながら、常に最新のスキルを学び、自宅で開発を通してスキルを磨い(みがく)てきました。技術力には自信があります。今は週末を利用してボランティア講師としてIT開発技術を授業して、とても楽しいです。
以上です。本日はどうぞよろしくお願いいたします。

2017年4月9日星期日

抽出文本文件中特定的行

package test;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RWFile3 {
/**
* 行処理 get the [001 \t Request-URI \t /g01c/index.php] by regx
*
* @param srcLineString
*            行の全文字列
* @param fileNo
*            ファイルの開始の数字。例:001
*/
public static String getStringByRegxFromLine(String srcLineString, String fileNo) {

String ret = "";
// [Request-URI:XXXXXXXXXX.\n] => [XXXXXXXXXX]
// (?<=Request-URI:) (?=\\.$) 零宽断言
String requestURIPattern = "(?<=Request-URI:).*(?=\\.$)";
String imapPattern = "(?<=Request Command:)TAG.*?(?=,\\sResult)";

// Request-URI
Pattern rRequestURI = Pattern.compile(requestURIPattern);
Matcher mRequestURI = rRequestURI.matcher(srcLineString);
if (mRequestURI.find()) {
ret = "\t" + fileNo + "\tRequest-URI\t" + mRequestURI.group(0);
} else {
// Request Command:TAG
Pattern rIMAP = Pattern.compile(imapPattern);
Matcher mIMAP = rIMAP.matcher(srcLineString);
if (mIMAP.find()) {
ret = "\t" + fileNo + "\tIMAP\t" + mIMAP.group(0);
}
}
return ret;
}

/**
* 使用BufferedReader类读文本文件
*/
public static int readLogAndWrite(String filePath, BufferedWriter out) {

int ret = 0;
// fileNoを取得 例:001
String fileNo = filePath.replaceAll("(?<=\\d{3})_.*txt", "").replaceAll(".*(?=\\d{3})", "");

String line = "";
try {
BufferedReader in = new BufferedReader(new FileReader(filePath));
line = in.readLine();
ret++;
String resultLine = "";
while (line != null) {
// 行処理
resultLine = getStringByRegxFromLine(line, fileNo);
if (!"".equals(resultLine)) {
out.write(resultLine + "\r\n");
ret++;
}

line = in.readLine();
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return ret;
}

/**
* フォルダに全体のログを操作
*
* @param path
*            ログフォルダ
* @param resultPathFile
*            結果ファイル
*/

public static void doAllFileInDir(String path, String resultPathFile01, String resultPathFile02) {

try {
BufferedWriter out01 = new BufferedWriter(new FileWriter(resultPathFile01));
BufferedWriter out02 = new BufferedWriter(new FileWriter(resultPathFile02));

File f = new File(path);
File[] fs = f.listFiles();
int lineCnt01 = 0;
int lineCnt02 = 0;
for (int i = 0; i < fs.length; ++i) {
File f2 = fs[i];
if (f2.isDirectory()) {
// doAllFileInDir(f2.getPath());
} else if (f2.getName().contains("01.txt")) {
String filePath = f2.getPath();
lineCnt01 = readLogAndWrite(filePath, out01);
} else if (f2.getName().contains("02.txt")) {
String filePath = f2.getPath();
lineCnt02 = readLogAndWrite(filePath, out02);

int cntDiff = lineCnt01 - lineCnt02;
if(cntDiff>0){
for(int j = 0; j< cntDiff; j++){
out02.write("\t-\t-\t-\r\n");
}
} else if(cntDiff<0){
for(int k = 0; k< -cntDiff; k++){
out01.write("\t-\t-\t-\r\n");
}
}
}
}
out01.close();
out02.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

public static void main(String[] args) {
String path = "C:/21log/t";
String resultPathFile01 = "C:/21log/r1.txt";
String resultPathFile02 = "C:/21log/r2.txt";
doAllFileInDir(path, resultPathFile01, resultPathFile02);
}
}

2017年4月6日星期四

java IO操作 读写文件

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;

public class FileUtil {

    /**
     * 按行读取文件
     */
    public static void ReadFileByLine(String filename) {
        File file = new File(filename);
        InputStream is = null;
        Reader reader = null;
        BufferedReader bufferedReader = null;
        try {
            is = new FileInputStream(file);
            reader = new InputStreamReader(is);
            bufferedReader = new BufferedReader(reader);
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != bufferedReader)
                    bufferedReader.close();
                if (null != reader)
                    reader.close();
                if (null != is)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 按字节读取文件
     *
     * @param filename
     */
    public static void ReadFileByBytes(String filename) {
        File file = new File(filename);
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            int index = 0;
            while (-1 != (index = is.read())) {
                System.out.write(index);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (null != is)
                    is.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("-----------------------------------");
        try {
            is = new FileInputStream(file);
            byte[] tempbyte = new byte[1000];
            int index = 0;
            while (-1 != (index = is.read(tempbyte))) {
                System.out.write(tempbyte, 0, index);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (null != is)
                    is.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 按字符读取文件
     *
     * @param filename
     */
    public static void ReadFileByChar(String filename) {
        File file = new File(filename);
        InputStream is = null;
        Reader isr = null;
        try {
            is = new FileInputStream(file);
            isr = new InputStreamReader(is);
            int index = 0;
            while (-1 != (index = isr.read())) {
                System.out.print((char) index);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != is)
                    is.close();
                if (null != isr)
                    isr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 通过OutputStreamWriter写文件
     *
     * @param filename
     */
    public static void Write2FileByOutputStream(String filename) {
        File file = new File(filename);
        FileOutputStream fos = null;
        // BufferedOutputStream bos = null;
        OutputStreamWriter osw = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            fos = new FileOutputStream(file);
            osw = new OutputStreamWriter(fos);
            osw.write("Write2FileByOutputStream");
            // bos = new BufferedOutputStream(fos);
            // bos.write("Write2FileByOutputStream".getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != osw) {
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 通过BufferedWriter写文件
     *
     * @param filename
     */
    public static void Write2FileByBuffered(String filename) {
        File file = new File(filename);
        FileOutputStream fos = null;
        OutputStreamWriter osw = null;
        BufferedWriter bw = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            fos = new FileOutputStream(file);
            osw = new OutputStreamWriter(fos);
            bw = new BufferedWriter(osw);
            bw.write("Write2FileByBuffered");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != bw) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != osw) {
                try {
                    osw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 通过FileWriter写文件
     *
     * @param filename
     */
    public static void Write2FileByFileWriter(String filename) {
        File file = new File(filename);
        FileWriter fw = null;
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
            fw = new FileWriter(file);
            fw.write("Write2FileByFileWriter");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        String filename = "D:/testfile.txt";
        // ReadFileByLine(filename);
        // ReadFileByBytes(filename);
        // ReadFileByChar(filename);
        String writeFile = "javawrite2file.txt";
        // Write2FileByOutputStream(writeFile);
        // Write2FileByBuffered(writeFile);
        Write2FileByFileWriter(writeFile);
    }
}