Professional Documents
Culture Documents
実習先:合資会社 e ラーニングサービス
所属:琉球大学工学部情報工学科
学籍番号:055717A
報告者氏名:金城佑典
2007/09/20
概 要
私が今回実習させていただいた「合資会社 e ラーニングサービス」は e ラーニングのコンサルティング/
設置/管理/カスタマイズや e ラーニングに関する講習会/ワークショップなどを行う企業である。
実習期間は 20 日間で1日8時間の計 160 時間の実習を行った。
その際私が担当したのは以下の6つのカスタマイズの課題である。
1. moodle の課題一括ダウンロードブロック作成
2. moodle の文字コード変換ブロック作成
3. moodle の学生管理ブロック作成
4. moodle の question ブロックで webct で問題をアップロードした際に発生する文字化けの解決
5. moodle のフォーラムダウンロードブロック作成
6. moodle のサンプルモジュール作成
この報告書では上記課題を作成中に得られた知見について報告する。
1
目次
1 moodle について 3
2 課題の解決からから得られた知識 3
2.1 課題一括ダウンロードブロック作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.1 ディレクトリ内のファイル検索とコピー . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.2 zip 圧縮しながらの強制ダウンロード . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2 文字コード変換ブロック作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.1 文字コード問題に関するメモ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 学生管理ブロック . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3.1 CSV ファイルからの情報の取得 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3.2 データベースからの情報の取得 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.4 moodle の question ブロックで webct で問題をアップロードした際に発生する文字化けの解決 6
2.5 イメージファイルフィルタの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.5.1 画像サイズの取得 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.6 フォーラムファイルダウンロードブロック作成 . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.6.1 階層構造を残したままの zip 圧縮 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.7 サンプルモジュールの作成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3 プログラム作成にあたって注意しなければならないこと 8
3.1 ソースコード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2 ユーザインタフェース . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 ドキュメント . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.4 セキュリティ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.5 動作テスト . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4 感想 11
2
1 moodle について
http://download.moodle.org/ からダウンロードできるオープンソース(GNU GENERAL PUBLIC LI-
CENSE Version 2 1 )の e ラーニングプラットフォーム、PHP,MySQL そして一部は javascript がつかわれて
おりこれらが動作するほとんどの OS で動作する。
今回の実習ではこの moodle で動作するプラグイン(ブロック, モジュール, フィルタ)を作成した。
• ブロック
ページの左右に配置される方形のプラグイン、ファイル構成は以下のようになる。
dataroot/blocks/作成するブロック名/block_作成するブロック名.php #本体
dataroot/blocks/作成するブロック名/config_instance.html #設定画面の定義
dataroot/blocks/作成するブロック名/db/ #データベースを使うブロックを作成するときに使う
dataroot/lang/文字コード名/block_作成するブロック名.php #プログラム中で使う日本語を定義
• モジュール
日本語では「活動」と表示されるプラグイン、cron を用いて定時実行を行うことができる、ファイル構
成は以下のようになる。
dataroot/mod/作成するモジュール名/db/mysql.php #アップグレード時の設定
dataroot/mod/作成するモジュール名/db/mysql.sql #データベースの作成
dataroot/mod/作成するモジュール名/icon.gif #「活動」ブロックで使われるアイコン、サイズは 16x16
dataroot/mod/作成するモジュール名/index.php #コース内のインスタンスを表示する画面
dataroot/mod/作成するモジュール名/lib.php #ライブラリ
dataroot/mod/作成するモジュール名/mod.html #設定画面
dataroot/mod/作成するモジュール名/version.php #バージョンなど
dataroot/mod/作成するモジュール名/view.php #選択したインスタンスを表示する画面
dataroot/lang/文字コード名/作成するモジュール名.php #プログラム中で使う日本語を定義
オプション
dataroot/mod/作成するモジュール名/config.html #サイト全体での設定をする画面
• フィルタ
ファイル構成は以下のようになる。
dataroot/filter/作成するフィルタ名/defaultsettings.php #デフォルトの設定を定義
dataroot/filter/作成するフィルタ名/filter.php #本体
dataroot/filter/作成するフィルタ名/filterconfig.html #設定画面の定義
dataroot/lang/文字コード名/作成するフィルタ名.php #プログラム中で使う日本語を定義
2 課題の解決からから得られた知識
2.1 課題一括ダウンロードブロック作成
moodle には教師が簡単に課題を作成し学生に解かせることができる課題ブロック(assignment block)と
いうものがある、しかしこのブロックでは学生が提出したファイルをダウンロードする際に提出物ひとつひと
つへのリンクをクリックしてダウンロードすることしかできず、提出物の数が増えると不便だった。
そこで課題ごとに提出物を一括ダウンロードできるブロックを作成した、ここではその際に得られた知識に
ついて報告する。
このブロックで最も問題になったのは zip ファイルの強制ダウンロードについてだった、ヘッダの使い方を
よくわかっていなかったため時間がかかってしまった。
1 オープンソースのライセンス、このライセンスがついたプログラムは好きなように利用することができる、ただしそれを利用したプ
3
2.1.1 ディレクトリ内のファイル検索とコピー
そこで取得したものが「.」「..」やディレクトリだった場合は無視することにした。
$targetfilesnum = count($targetfiles);
$countdown = $targetfilesnum-1;
require_once(’zip.lib.php’);
$filename = basename($targetfiles[$countdown]);
$zipfile $->$ addFile($contents, $filename );
$countdown--;
}
$zip_buffer = $zipfile$->$file();
print $zip_buffer;//(download)
}
4
zip ファイルのバッファ(バイナリ)を倍なりコードのまま print 文で出力している、また上記のヘッダが
ついているので zip ファイルを生成する必要はない。(もちろん一度 zip ファイルを生成してそのファイルを
fopen − > fread − > print してもいい)
「Content-Type:」に記述されているのは MIME タイプで、これを変更すれば様々なファイル形式に応用で
きる。
2.2 文字コード変換ブロック作成
moodle にアップロードされたテキストファイルと HTML ファイルの文字コード変換するためのブロック
を作成した。
ここでつまづいたのは文字コード問題だった、文字コードを変換するには元の文字コードと変換後の文字
コードを指定しなければならないがテキストファイルから読み込んだ文字の文字コードの判定が大変だった。
2.2.1 文字コード問題に関するメモ
2.3 学生管理ブロック
このブロックではデータベースからのユーザ情報を取得しその情報をもとに当該コース(講義)のロール
(参加者)に加えるという作業を行った、またユーザの絞り込み検索や CSV ファイルからのユーザの追加も
できるようにした。
ロールへの追加は専用の関数(enrole student / unenrole student)が用意されていたのでそれらを使用
しデータベース(MySQL)からのユーザ情報の取得ならびに検索と CSV ファイルからの情報の取得を主に
行った。
2 http://moodle.org/mod/forum/discuss.php?d=38860
5
2.3.1 CSV ファイルからの情報の取得
2.3.2 データベースからの情報の取得
実際は「ユーザのユーザ名を取得」
「ユーザの最終アクセス日を取得」などの個別の関数はあるが、moodle
の関数はバージョンに大きく依存する上、関数を使うと複数条件を指定しての検索ができないので高度な処理
(例えばユーザをユーザ名、最終更新日、所属グループで絞り込み検索する等)の場合は難しい。
よって SQL 文を直接記述した方がいいが、ここで問題になるのは moodle のバージョン問題である、moodle
ではバージョンによってデータベースのテーブルが変更されていたり、最悪なくなっていたりもするのでバー
ジョンごとに対応する必要がある、しかし関数の仕様の変更を追うよりは対応しやすいと思われる。
だった、iconv は文字コード変換のための関数だが第1引数が変換前の文字コード、第2引数が変換後の文字
コード、第3引数が変換する文字列である。上の場合では変換前の文字コードが「Windows-1252」と指定さ
れているのでそれ以外でかかれたファイルから問題をアップロードしようとすると文字化けが発生していた。
そこで mb convert encoding 関数を使用して以下のように変更した。
$line = mb_convert_encoding($line,’UTF-8’,’auto’);
ここで、第3引数の「auto」は変換前の文字コードは自動的に判別するという意味である。
2.5 イメージファイルフィルタの作成
引数として「画像ファイルのパス」
「最大幅」
「最大高さ」を渡すとその画像がもとのアスペクト比を保持し
たまま「最大幅」「最大高さ」以内の大きさで表示されるように HTML の img タグの引数を返すプログラム
を作成した、
6
2.5.1 画像サイズの取得
以下のような関数を作成した
function imagesize_filter($imagefile=’’,$maxwidthsize=0,$maxhightsize=0) {
$imgstring = ’’;
if($imageinfo = getimagesize($imagefile)){
$setpercenttage = array(100,95,90,85,80,75,70,75,70,65,60,55,50,45,40,35,30,25,20,15,10,5,4,3,2,1);
$maxcount = count($setpercenttage);
$count = 0;
while($imageinfo[0]*$setpercenttage[$count]*0.01 > $maxwidthsize){
if ($count+1 >= $maxcount){
break;
}
$count++;
}
2.6 フォーラムファイルダウンロードブロック作成
フォーラムに添付されたファイルを一括ダウンロードするブロックを作成した。
前述の「zip 圧縮しながらの強制ダウンロード」のときに用いた関数だと解凍したあとに階層構造が残って
いない、もし引数としてファイルのパスではなくディレクトリのパスを渡すと渡されたディレクトリが 0Kbyte
の実行ファイルとして圧縮されてしまう。
そこで以下のように「ファイルの検索」→「zip ファイルの作成」→「zip ファイル(バイナリ)を出力」と
いう手順を取った、ここで zip files() は zip ファイルを作成する moolde 関数、header() はヘッダを出力する
moolde 関数、readfile() はファイルの内容を標準出力に出力する PHP 標準関数である。
if (!zip_files(圧縮したいファイル(もしくはディレクトリ)の絶対パスの配列,zip ファイルの絶対パス)) {
error(get_string("zipfileserror","error"));
}else{
echo ’success!!’;
}
7
//print header
header( "Content-Type: application/octet-stream" );
header( "Content-disposition: attachment; filename=ダウンロードするファイル名" );
if(!readfile(zip ファイルの絶対パス)){
printf(’can not read %s ’,$zipfilename);
}
2.7 サンプルモジュールの作成
moodle のモジュールのサンプルを作成した、公式サイトからダウンロードしたサンプルモジュール 3 は
README.txt の指示に従った修正をしても動作しない、README.txt では mysql.sql ファイルの編集は option
になっているが実際は以下の内容で mysql.sql を作成しなければならない。
以下はモジュール名を「sample」とした場合
ーー
CREATE TABLE prefix_sample (
id int(10) NOT NULL auto_increment,
course int(10) NOT NULL default ’0’,
timemodified int(10) NOT NULL default ’0’,
name varchar(255) NOT NULL default ’’,
moodle のドキュメントは古いものが多くドキュメントの信用度は低い、ドキュメント通りに入力しても想
定通りに動かない場合は他のプログラムと違い「ドキュメント自体が間違っている」という可能性も考慮しな
ければならない。
3 プログラム作成にあたって注意しなければならないこと
3.1 ソースコード
今回の課題においても問題になっていたがバージョン問題は非常に難しい問題だ、とくに moodle のような
オープンソースソフトウェアは更新頻度が高く機能が大きく変わることもあるのですべてのバージョンに対
応するのは非常に難しい、よってプログラムの作成時点で「コメントをつける」「デバッグ用の文を残してお
く」「環境依存の関数はなるべく使わない」など次回のバージョンアップを意識しておいたほうがよい。
また moodle の場合は「ある関数がまた別の関数を呼び出し、その関数がまたさらに別の関数を呼び出す」
というような非常にややこしい構造をしていた、このような記述は処理の追跡を困難にし使用する関数で一つ
でも使えないものがあると動作しなくなるためバージョン問題の影響も受けやすいのでなるべくしないほうが
いいだろう。
3.2 ユーザインタフェース
利用者の観点からみればユーザインタフェースがもっとも大切なものである、ユーザはプログラムのソース
コード読むはずもなく、マニュアルも確実に熟読するとはかぎらない、またプログラマが想定していない操作
をすることもありえる。
3 http://download.moodle.org/plugins16/mod/NEWMODULE.zip
8
今回の課題では「課題一括ダウンロードブロック」においてこのような行き違いが生じデバッグに多くの時
間を割かれてしまった、プログラマの常識がユーザの常識ではない以上あらゆる状況を推測してインタフェー
スを作成する必要がある。
想定していない動作はマニュアルに注意書きを書くのではなくその動作ができないようなインタフェースに
すべきである、たとえば日付などはテキストボックスにして入力させるのではなくプルダウンメニューなどの
選択式にすると「全角で日付が入力されていてプログラムがうまく動作しなかった」というような罠に陥らず
に済む。
ユーザがプログラマが想定していない操作をした際に発生する問題はプログラマ側では再現することが非常
に難しく、ユーザ側もそんなことでプログラムが破綻するとは思っていないのでなかなか発見することができ
ない、よってユーザインタフェースを作成する時点でユーザが決して想定外の入力や操作ができないようにす
るべきである。
3.3 ドキュメント
ドキュメントは想定されるユーザのレベルによって内容を考えなければならない、たとえば一般ユーザが対
象ならば図表を多用して操作手順を事細かに指示しつつ専門用語や内部動作などある程度の知識が必要な内容
は削除すべきである、他方ドキュメントの対象が開発者なら内部動作やデータベースの構造を詳しく解説すべ
きだし、サイト管理者向けならばインストール方法などを説明すべきだろう。もし時間があるならばぞれぞれ
のユーザのレベルに合わせたドキュメントを複数用意するとよいだろう。
• 一般ユーザ
プログラムの動作には知識も興味もなくわかりやすい操作で正しい結果が返ってくることを望んでいる、
エラーが発生しても原因は追求せずマニュアル通りで動かないならそれはプログラムの方が悪いと考え
る、よってドキュメントには動作手順や制限事項(「日本語には対応していない」など)を詳細に解説
すべきである。
• 管理者
ある程度プラグインに関する知識を持っているがプログラムが理解できるほどではない、ドキュメント
には動作に必要な環境と設置方法やエラーメッセージの意味と対処法なども記述すべきだろう。
• 開発者
プログラムには詳しく全体的な動作よりも参考にしたい機能の実装方法に興味がある、よってドキュメ
ントには開発環境やテスト環境とファイル構成/データベースの構造/プログラムのおおまかな内部動
作などを記述し、ソースコードに関数などの解説(引数/処理/返り値など)を記述したほうがいいだ
ろう。
3.4 セキュリティ
CGI のプログラムではセキュリティが非常に重要だ、CGI プログラムのセキュリティホールは最悪の場合
4
サーバの故障や情報漏洩につながる非常に大きな問題なので CGI の弱点であるセキュリティ面の弱さ に注
意したプログラムを作成する必要がある。
9
moodle では capability が細かく設定できるのでアクセス権の確認を行い権限のないユーザには何もできな
いようすることもできるが攻撃者(故意かミスかはさておき)が現れる可能性はのこる、moodle では主に以
下の二つに気をつけたプログラム作成を行うべきである。
• 性善説に基づいた設計
「攻撃者は存在しない」という前提に基づいてプログラムを作成するのはろんがいである。
「実行したいコマンドを入力させる」
「SQL のクエリを入力させる」
「ファイルのパスを入力させる」な
どサーバに直接渡すデータを入力させるのは絶対にしてはならない、もしやるとしても必ず文字列チェッ
クをすること。
絶対にしてはいけない例
ーーー
$cmd = optinal_param(’cmd’,’’,’RAW’);
exec($cmd);
ーーー
例えば rm コマンドなどを使われるとサービスの停止どころかサーバを破壊される恐れもある。
悪い例
ーーー
$str = optinal_param(’cmd’,’’,’RAW’);
echo $str;
ーーー
• 入力ミスはないという前提
moodle ユーザには初心者も多い、よって入力ミスは多発すると考えてプログラムを作成すべきである。
例えば以下のようなプログラムだと、ユーザの入力によってはループの回数が膨大になり大量の資源を
消費してしまう、そしてサービスの停止に追い込まれ最悪の場合サーバが故障を招く恐れがある。
ーーー
$count = optinal_param(’cmd’,’’,’INT’);
while($count > 0){
printf("roop %d",$count);
$count--;
}
ーーー
たとえプルダウンメニューで回数を選択するようなプログラムでも、上のようになっていると URL 欄
で回数を操作できるので非常に危険である。
(すこしなれたユーザだと URL 欄で引数を操作することも
十分に考えられる)
3.5 動作テスト
プログラム作成後は動作テストを行う、moodle プログラムの利用者はまったくの初心者ばかりで場合によっ
てはコンピュータに触ったことすらない人も含まれるのでそれを見越した設計やテストを行うことが重要であ
る、具体的には通常のプログラムの動作以外に「マニュアルを読まずに操作できるか」「エラーメッセージが
わかりやすいか」「エラーが起きた際に簡単に戻せるか」など初心者ユーザ目線でのテストもしなければなら
ない。
10
• プログラム作成者によるテスト
プログラム作成者は「入力に対してプログラムした通りの結果が返ってくるか」をテストする、このと
きわざとエラーが発生する入力をして「きちんとエラーが返ってくるか」も確認しなければならない、
プログラムを作成しながらこまめにテストを繰り返さないと後で大幅な修正を強いられる場合もある。
• プログラム作成者以外によるテスト
プログラム作成者は「何をどうしたらどんな結果が返ってくるか」知っているため「ユーザがやるかも
しれない」とプログラマ自身が想定した操作しかできない、よって「プログラマが想定していない操作
をした時の結果」をテストするためにはプログラムの内容を知らない人にテストしてもらう必要がある。
• 利用者によるテスト
たとえ仕様書に遵守していてマニュアルも完璧でも依頼者にしかわからないミスもある、たとえば「と
くになにもいわなくても当然できると思っていた」というような要求仕様書に記載されていない要求も
存在する。
4 感想
今回の実習では実際の企業でのプログラミング作業が体験できた。「クリアしなければならない要件」から
曖昧で途中で要件が追加されることやとくに指定されていない隠れた要件があり、ユーザのことを強く意識し
て「ユーザが求めていること」
「ユーザ側からみた使い勝手」等々利用者の立場に立って考えることが必要で、
また講義課題のように「提出すればおわり」というわけではないので今後のことも考えた書き方(環境依存の
関数はなるべく使わない、コメントをつける等)や動作原理よりも動作することが大切といった考え方など普
段とは違う実際の仕事にそくしたプログラミングを体験することができ、とても勉強になった。
参考文献
[1] moodle
http://moodle.org/course/view.php?id=14
11
合資会社 e ラーニングサービス 秋山實 印
12