スパイラル2では、スパイラル1で実装した機能に加えて、ユーザ関係の機能を追加しよう。
SP2のユースケースは以下の7つである。
- 管理ユーザは入力欄に必要事項を記入し「登録」ボタンを押す。
- 登録ボタンが押されたことがユーザ制御パネルに通知される。
- ユーザ制御パネルは入力情報を取り出し、ユーザ管理者に渡し登録を依頼する。
- ユーザ管理者はデータベース管理者に新規ユーザ情報を渡し登録を依頼する。
- データベース管理者はデータベースに新規ユーザを登録する。
- ユーザ管理者はユーザリストを更新する。
- 管理ユーザはユーザリストのユーザをクリックする。
- クリックされたことがユーザ制御パネルに通知される。
- ユーザ制御パネルはリスト内の情報を取り出し、入力欄に設定する。
- 選択されたユーザの背景色が変わる。もし以前に選択されていたユーザがあれば、その背景色は元に戻る。
- 管理ユーザは選択されているユーザの情報を変更し「修正」ボタンを押す。
- 修正ボタンが押されたことがユーザ制御パネルに通知される。
- ユーザ制御パネルは入力情報を取り出し、ユーザ管理者に渡し修正を依頼する。
- ユーザ管理者はデータベース管理者に既存のユーザ情報を渡し修正を依頼する。
- データベース管理者はデータベースのユーザ情報を修正する。
- ユーザ管理者はユーザリストを更新する。
- 管理ユーザは「削除」ボタンを押す。
- 削除ボタンが押されたことがユーザ制御パネルに通知される。
- ユーザ制御パネルはユーザ管理者に削除するユーザのIDを渡し削除を依頼する。
- ユーザ管理者はデータベース管理者にユーザIDを渡し削除を依頼する。
- データベース管理者は渡されたユーザIDのユーザを削除する。
- ユーザ管理者はユーザリストを更新する。
- 管理ユーザは管理画面を開く。
- ユーザ管理者はデータベース管理者にユーザリストを要求する。
- データベース管理者はデータベースからユーザリストを取り出しユーザ管理者に渡す。
- ユーザ管理者はユーザリストを更新する。
- ユーザが年と月と会議室を入力して表示ボタンを押す。
- 表示ボタンが押されたことが制御パネルに通知される。
- 制御パネルは、年と月と会議室名を取り出して、その情報をシステム管理者に通知する。
- システム管理者は、年と月と会議室の情報をデータベース管理者に渡して、予約リストの取り出しを依頼する。
- データベース管理者は、指定された年月と会議室の予約リストをデータベースから取り出しシステム管理者に渡す。
- システム管理者は予約リストをカレンダー管理者に渡して、表示の更新を依頼する。
- カレンダー管理者がカレンダーを更新する。
- ユーザが会議室予約システムのページを開く。
- 制御パネルはデータベース管理者に会議室リストを要求する。
- データベース管理者はデータベースに問い合わせて会議室リストを得て、制御パネルに渡す。
- 制御パネルは会議室のドロップダウンメニューを更新する。
- 制御パネルは現在の年と月の値をテキストボックスに設定する。
- 制御パネルは、現在の年と月と“全会議室”を使ってシステム管理者にカレンダーの更新を依頼する。→ここから先は予約の閲覧と同様。
本来の開発ならば、すべてのユースケースについてシナリオを書くべきである。 シナリオはオブジェクト抽出の基本であるから。
しかし、ここではシナリオとユースケース記述がほぼ同じになることから、シナリオの記述は省略する。
以下の6つのオブジェクトを抽出した。
シーケンス図のオブジェクト間のメッセージやり取りの関係からクラスの関係を導くと以下のようになる。
なお、ここではオブジェクトとクラスは一致している。
クラス名を以下のように英語表記に変更した。
詳細シーケンス図は以下のようになる。
最後の仕様変更に伴い、DBManager.setSymCp()は廃止される。
詳細シーケンス図から詳細クラス図を作成すると次のようになる。
<?php
/**
* パラメータ:
* year : 年
* month : 月
* room : 会議室名
*/
$year = $_POST['year'];
$month = $_POST['month'];
$room = $_POST['room'];
$next_year = $year;
$next_month = $month + 1;
if ($next_month == 13) {
$next_year = $year + 1;
$next_month = 1;
}
$q = "select
v.id,r.name as room,v.start_dt,v.end_dt,u.name as user,v.last_modified
from
reservations v inner join users u on v.user_id=u.id
inner join rooms r on v.room_id=r.id
where
start_dt >= :start_dt and end_dt < :end_dt";
if ($room != "全会議室") {
$q = $q . " and r.name = :room;";
} else {
$q = $q . ";";
}
try {
$pdo = new PDO("mysql:host=mysql514.db.sakura.ne.jp; dbname=forcreate_fuchida; charset=utf8", "forcreate", "junior2015");
$s = $pdo->prepare($q);
if ($room != "全会議室") {
$sa = array(':start_dt' => "$year/$month/1",
':end_dt' => "$next_year/$next_month/1",
':room' => "$room");
} else {
$sa = array(':start_dt' => "$year/$month/1",
':end_dt' => "$next_year/$next_month/1");
}
$s->execute($sa);
//$arr = array('q' => $q, 'y' => $year, 'm' => $month, 'r' => $room, 'sa' => $sa);
//print json_encode($arr);
print json_encode($s->fetchAll());
} catch (PDOException $e) {
print json_encode(array("msg" => $e->getMessage()));
}
$pdo = null;
<?php
try {
$pdo = new PDO("mysql:host=mysql514.db.sakura.ne.jp; dbname=forcreate_fuchida; charset=utf8", "forcreate", "junior2015");
$q="select name from rooms";
$s=$pdo->prepare($q);
$s->execute();
print json_encode($s->fetchAll());
} catch (PDOException $e) {
print json_encode(array("msg" => $e->getMessage()));
}
$pdo = null;
<?php
try {
$pdo = new PDO("mysql:host=mysql514.db.sakura.ne.jp; dbname=forcreate_fuchida; charset=utf8", "forcreate", "junior2015");
$q="select * from users";
$s=$pdo->prepare($q);
$s->execute();
print json_encode($s->fetchAll());
} catch (PDOException $e) {
print json_encode(array("msg" => $e->getMessage()));
}
$pdo = null;
<?php
// 新規ユーザを登録する
// un: ユーザ名
// pw: パスワード
// lv: ユーザレベル 0:一般ユーザ 1:管理ユーザ
try {
$pdo = new PDO("mysql:host=mysql514.db.sakura.ne.jp; dbname=forcreate_fuchida; charset=utf8", "forcreate", "junior2015");
$q = "insert into users (name,password,level) values (:name,:password,:level);";
$s = $pdo->prepare($q);
$sa = array(":name" => $_POST['un'],
":password" => $_POST['pw'],
":level" => $_POST['lv']);
$s->execute($sa);
//$arr = array('q' => $q, 'un' => $_POST['un'], 'pw' => $_POST['pw'], 'lv' => $_POST['lv'], 'sa' => $sa);
//print json_encode($arr);
print json_encode(array("result" => $s->rowCount()));
} catch (PDOException $e) {
print json_encode(array("msg" => $e->getMessage()));
}
$pdo = null;
<?php
// 既存ユーザを修正する
// id: ID
// un: ユーザ名
// pw: パスワード
// old_pw: 古いパスワード
// lv: ユーザレベル 0:一般ユーザ 1:管理ユーザ
try {
$pdo = new PDO("mysql:host=mysql514.db.sakura.ne.jp; dbname=forcreate_fuchida; charset=utf8", "forcreate", "junior2015");
$q = "update users set name=:name,password=:password,level=:level where id=:id and password=:old_password;";
$s = $pdo->prepare($q);
$sa = array(":id" => $_POST['id'],
":name" => $_POST['un'],
":password" => $_POST['pw'],
":level" => $_POST['lv'],
":old_password" => $_POST['old_pw']);
$s->execute($sa);
//$arr = array('q' => $q, 'un' => $_POST['un'], 'pw' => $_POST['pw'], 'lv' => $_POST['lv'], 'sa' => $sa);
//print json_encode($arr);
print json_encode(array("result" => $s->rowCount()));
} catch (PDOException $e) {
print json_encode(array("msg" => $e->getMessage()));
}
$pdo = null;
<?php
// 既存ユーザを削除する
// id: ID
// pw: パスワード
try {
$pdo = new PDO("mysql:host=mysql514.db.sakura.ne.jp; dbname=forcreate_fuchida; charset=utf8", "forcreate", "junior2015");
$q = "delete from users where id=:id and password=:password;";
$s = $pdo->prepare($q);
$sa = array(":id"=>$_POST['id'],
":password" => $_POST['pw']);
$s->execute($sa);
//$arr = array('q' => $q, 'un' => $_POST['un'], 'pw' => $_POST['pw'], 'lv' => $_POST['lv'], 'sa' => $sa);
//print json_encode($arr);
print json_encode(array("result" => $s->rowCount()));
} catch (PDOException $e) {
print json_encode(array("msg" => $e->getMessage()));
}
$pdo = null;
<!DOCTYPE html>
<html>
<head>
<title>会議室予約システムSP2</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="js/libs/jquery/jquery.js"></script>
<script type="text/javascript" src="js/DBManager.js"></script>
<script type="text/javascript" src="js/SystemManager.js"></script>
<script type="text/javascript" src="js/CalendarManager.js"></script>
<script type="text/javascript" src="js/ControlPanel.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<link type="text/css" rel="stylesheet" href="css/index.css">
</head>
<body>
<div id="title"><h1>会議室予約システムSP2</h1></div>
<div id="control_panel">
<input id="year" type="text" size="5"/>年
<input id="month" type="text" size="3"/>月
会議室:<select id="room">
<option value="全会議室">全会議室</option>
<option value="中会議室">中会議室</option>
</select>
<input type="button" value="表示する" id="bt_disp"/>
<span id="manage">
<a href="admin.html">管理</a>
</span>
</div>
<div id="reservation_list">
<table id="reservation_table" border="1">
<tr><th>予約ID</th><th>会議室</th><th>開始日時</th><th>終了日時</th><th>予約者</th><th>予約日</th></tr>
</table>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>管理ページ</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="js/libs/jquery/jquery.js"></script>
<script type="text/javascript" src="js/DBManager.js"></script>
<script type="text/javascript" src="js/UserManager.js"></script>
<script type="text/javascript" src="js/UserControlPanel.js"></script>
<script type="text/javascript" src="js/admin.js"></script>
<link type="text/css" rel="stylesheet" href="css/admin.css">
</head>
<body>
<div id="top">
<a href="index.html">カレンダーに戻る</a>
</div>
<div id="user_manager">
<table>
<tr><th align="right">ユーザID:</th><td><span id="user_id"></span></td></tr>
<tr><th align="right">ユーザ名:</th><td><input id="user_name" type="text" size="20"></td></tr>
<tr><th align="right">パスワード:</th><td><input id="user_pw" type="password" size="20"></td></tr>
<tr><th align="right">パスワード(再):</th><td><input id="user_pw2" type="password" size="20"></td></tr>
<tr><th align="right">レベル:</th>
<td>
<select id="user_level">
<option value="user">一般ユーザ</option>
<option value="admin">管理ユーザ</option>
</select>
</td>
</tr>
<tr><th align="right">古いパスワード:</th><td><input id="user_old_pw" type="password" size="20"> ※修正、削除用</td></tr>
</table>
<p>
<input id="bt_regist" type="button" value="登録"/>
<input id="bt_modify" type="button" value="修正"/>
<input id="bt_delete" type="button" value="削除"/>
</p>
<table id="user_list" border="1">
<tr><th>ID</th><th>氏名</th><th>レベル</th></tr>
</table>
</div>
<div id="room_manager"></div>
</body>
</html>
html,body{
margin:0px;
width:100%;
height:100%;
}
div#title{
padding:8px;
position:absolute;
top:0px;
left:0px;
right:0px;
height:50px;
background-color:#ccccff;
}
div#title h1{
margin:0px;
}
div#control_panel{
padding:8px;
position:absolute;
top:50px;
left:0px;
right:0px;
height:40px;
background-color:#ffffcc;
}
div#reservation_list{
padding:8px;
position:absolute;
top:90px;
left:0px;
right:0px;
bottom:0px;
background-color:#ccffcc;
}
table#reservation_table{
width:100%;
border-collapse: collapse;
background-color:white;
}
#manage{
position:absolute;
right:8px;
}
html,body{
margin:0px;
width:100%;
height:100%;
}
#top{
box-sizing: border-box;
padding:8px;
position:absolute;
left:0px;
top:0px;
right:0px;
height:40px;
background-color:#ccccff;
}
#user_manager{
box-sizing: border-box;
padding:8px;
position:absolute;
left:0px;
top:40px;
bottom:0px;
width:50%;
background-color:#aaccff;
}
#room_manager{
box-sizing: border-box;
padding:8px;
position:absolute;
top:40px;
right:0px;
bottom:0px;
width:50%;
background-color:#ffff99;
}
table#user_list{
width:100%;
border-collapse: collapse;
background-color:#ffffff;
}
table#user_list tr.user_row:hover{
background-color:#ccff99;
}
table#user_list tr.user_row_selected{
background-color:#aaaaff;
}
// データベース管理者クラス
var DBManager = function () {
// 予約リストを得る
this.getReservationList = function (y, m, r, sym) {};
// 会議室リストを得る
this.getRoomList = function (cp) {};
// ユーザリストを得る
this.getUserList = function (usm) {};
// ユーザを登録する
this.registUser = function (un, pw, lv, usm) {};
// ユーザを修正する
this.modifyUser = function (id, un, pw, old_pw, lv, usm) {};
// ユーザを削除する
this.deleteUser = function (id, pw, usm) {};
// エラー処理
this.handleError = function (data) {};
};
// システム管理者クラス
var SystemManager = function (dbm, cam) {
// カレンダーを更新する
this.updateCalendar = function (y, m, r) {};
// 予約リストが得られた
this.reservationListGot = function (rl) {};
// 生成
this.dbm = dbm;
this.cam = cam;
};
// カレンダー管理者クラス
var CalendarManager = function () {
// リストを更新する
this.updateList = function (rl) {};
};
// 制御パネルクラス
var ControlPanel = function (sym, dbm) {
// 表示ボタンが押された
this.dispPushed = function () {};
// 会議室リストを得る
this.getRoomList = function () {};
// 会議室リストが得られた
this.roomListGot = function (rl) {};
// 生成
this.sym = sym;
this.dbm = dbm;
$("#bt_disp").click($.proxy(this.dispPushed, this)); // thisを自分にしておく
var now = new Date();
$("#year").val(now.getFullYear());
$("#month").val(now.getMonth() + 1);
};
// ユーザ管理者
var UserManager = function (dbm) {
// ユーザ制御パネルの設定
this.setUcp = function (ucp) {};
// ユーザリストの更新
this.updateUserList = function () {};
// フォームのクリア
this.clearForm=function(){};
// ユーザリストが得られた
this.userListGot = function (ul) {};
// ユーザを登録する
this.registUser = function (un, pw, lv) {};
// ユーザを修正する
this.modifyUser = function (id, un, pw, old_pw, lv) {};
// ユーザを削除する
this.deleteUser = function (id,old_pw) {};
// ユーザが登録された
this.userRegisted = function (res) {};
// ユーザが選択された
this.userSelected = function (ev) {}
// ユーザが修正された
this.userModified = function (res) {};
// ユーザが削除された
this.userDeleted = function (res) {};
// 生成
this.dbm = dbm;
this.ucp = null;
this.selected_user_tr = null;
$('#user_list').on('click', 'tr.user_row', {usm: this}, this.userSelected);
};
// ユーザ制御パネル
var UserControlPanel = function (usm) {
// 登録ボタンが押された
this.registPushed = function () {};
// 修正ボタンが押された
this.modifyPushed = function () {};
// 削除ボタンが押された
this.deletePushed = function () {};
// 生成
this.usm = usm;
$('#bt_regist').click($.proxy(this.registPushed, this));
$('#bt_modify').click($.proxy(this.modifyPushed, this));
$('#bt_delete').click($.proxy(this.deletePushed, this));
};
// ページ読み込み時の処理
$(function () {
});
// ページ読み込み時の処理
$(function(){
});