この講座で開発するプログラムについて説明します。
開発するプログラムは「レシピ管理プログラム」です。
この講座の目的は「自分の開発チームにリーダブルなコードが当たり前な文化の作り方を持ち帰る」ことです。
目的を達成するために課題を通じて「リーダブルコードを発見できるようになること」と「リーダブルの基準を共有すること」を目指しますが、「リーダブルコードのテクニックをたくさん覚えること」や「難しいプログラムでも実装できるようになること」、「速く実装できるようになること」は目指すことではありません。そのため、次の点に注意して開発するプログラムの仕様を用意しました。
- 言語の基本的な機能のみで実現できる。
- ライブラリーを知っていることや使えることは重要ではない。
- 難しいロジックを必要としない。
- 効率のよいアルゴリズムを考えることは重要ではない。
- 段階的に改良していく。
- 書き捨てのプログラムではなく継続的に開発するプログラムであることは重要である。
- すべての仕様を実装しなくてもよい。
- 今回の実装時間は165分で仕様は13個ある。平均して12分で1つ実装するとすべての仕様を実装できるが、「速く実装できるようになること」は目的ではないので、すべての仕様を実装することは重要ではない。
開発するコードは「今の自分で最高にリーダブルなコード」にしてください。そのとき、「どうしてこのコードはリーダブルと言えるのか」の理由も考えてください。例えば、「 do_something では何かをするのはわかるけど何をするのかわからないが、 open_file ならファイルを開くということがすぐわかるのでリーダブルだ」といった具合です。
理由を考えるのは、理由をつけられるくらい考えていれば応用が効くからです。前述の例の理由からは「何をするのかわかる名前がよい」という基準を見つけられます。この基準を使えば、違うコードでもリーダブルなコードを書けます。
1つ、リーダブルコードを書くためのヒントを伝えます。それは、「書く時に読む人の視点を持つこと」です。
リーダブルコードとはどのようなコードだと思いますか?読む人がリーダブルだと思ったら、それはその人にとってリーダブルコードです。読む人にとって前提知識が違うので、より多くの人がリーダブルだと思うコードもありますし、同じ開発チームの人たちだけがリーダブルだと思うコードもあります。どちらを選ぶかは「読む人」をどのように設定したかに依存します。必ずしも「より多くの人」を選ぶことが妥当なわけではありません。例えば…、と書き始めるとヒントではなくなってしまいますね。ここで止めておくことにします。
書く時は「どんな人が読むコードか」を意識してみてください。それが、読む人の視点を持つことにつながります。
プログラムを1から開発します。後述する仕様を実現するようにプログラムを開発します。仕様は複数の段階があり、仕様1を実装したら、そのプログラムを改良して仕様2を実装する、というように、同じプログラムを改良しながら仕様を実現していきます。最終的には、1から12までのすべての仕様を満たす単一のプログラムと、仕様13を満たすもう1つのプログラムができあがるという想定です。
すべての仕様をいかに速く実装するか、ということは目的では ありません 。「リーダブルコードを発見できるようになること」が目的です。「1番速く実装したけどリーダブルコードはなにも発見できなかった」というケースは、この講座では失敗ケースです。目的を見失わないようにしましょう。
1つ仕様を実装する毎にGitHubにcommit + pushしてください。
例:
- 仕様1を実装
- commit + push
- プログラムを改良して仕様2を実装
- commit + push
- プログラムをさらに改良して仕様3を実装
- commit + push
- ...
仕様を実装した状態でcommit + pushしていれば、1つの仕様を実装する間に何回commit/pushしても構いません。
例:
- 仕様1を実装開始
- 仕様1を30%実装
- commit
- 仕様1を60%実装
- commit + push
- 仕様1を90%実装
- commit
- 仕様1を100%実装
- commit + push
- ...
コミットメッセージにはどの仕様を実装しているかがわかるマークを入れてください。具体的には、コミットメッセージの最初に spec${仕様番号}: と入れてください。
仕様1を実装しているときのコミット例:
% git commit -m "spec1: add a sample script"
% git commit -m "spec1: 並び替え機能を追加"
仕様3を実装しているときのコミット例:
% git commit -m "spec3: fix a typo"
% git commit -m "spec3: 異常値のときのテストを追加"
これは、どの仕様を実装しているかをわかりやすくするためです。後からこのコードやコミットログを「読む人」がいるということを思い出してください。
それぞれの仕様には次の2点を明記しています。仕様を実装した後は、各自、これらを使って仕様を満たしているかどうかを確認してください。不安な場合はチューターに質問したり、確認をお願いしてください。
- 入力
- 期待する結果
なお、各仕様の実現例や実行例は、仕様を最低限満たす実装の例に基づいています。仕様から逸脱していなければ、例と全く同じに実装する必要はありません。
レシピのタイトルとして「オムライス」と出力するプログラムを新しく作ってください。
レシピのタイトルの出力先は問いません。コンソールに出力しても構いませんし、ファイルに出力しても、ウィンドウを作ってそこに出力しても、Webブラウザーに表示させても構いません。
なし
- プログラムが実行されたら、なんらかの形で「オムライス」と出力する。
recipe.sh:
#!/bin/sh
echo "オムライス"
実行:
% chmod +x recipe.sh
% ./recipe.sh
オムライス
仕様1を実現したらチューターに声をかけて結果を確認してもらってください。仕様1は練習です。仕様1でうまくできていたら仕様2以降もうまくやれるはずです。
同じグループの人があなたが書いたプログラムを実行できるように、実行手順を書いたREADME.mdを用意してください。
なし
- グループの他の人がREADME.mdに書かれた手順に従って操作して、このプログラムが仕様1を満たしていることを確認できる。
今はプログラム中に「オムライス」のレシピが埋め込まれているはずです。そのレシピ情報をデータとして別のファイルに保存し、プログラムとは分離してください。
データファイルのフォーマットは問いません。
どのようにしてデータファイルをプログラムに指定したり読み込ませたりするかの方法も問いません。
データファイルをどのようなフォーマットにしたか、どのようにデータファイルを指定するかはREADME.mdに記述してください。
- データファイル
- ファイル名は任意。例: recipe-data.txt
- 中身は「オムライス」というレシピ情報1つだけ。
- データファイルはリポジトリーに入れること
データファイルは、例えば次のような内容:
% cat recipe-data.txt
オムライス
-
ププログラムが実行されたら、なんらかの方法でデータファイルを読み込み、データファイル内にある「オムライス」というレシピ情報をロードして、そのレシピ情報を出力する。
実行例:
% ./recipe.sh recipe-data.txt オムライス -
グループの他の人がREADME.mdに従って、ファイルを作成してプログラムにレシピ情報をロードできる。
今のデータファイルにはレシピ情報は「オムライス」1つだけしか登録されていません。これを、次の3つのレシピ情報を登録できるようにします。
- オムライス
- 親子丼
- 杏仁豆腐
また、プログラム実行時には登録されているすべてのレシピ情報を出力してください。
レシピ情報のフォーマットは問いません。
どのようなフォーマットにしたかはREADME.mdに記述してください。
- データファイル
- ファイル名は任意。例: recipe-data.txt
- 中身は次の3つのレシピ情報。
- オムライス
- 親子丼
- 杏仁豆腐
データファイルは、例えばこういう内容です。
% cat recipe-data.txt
オムライス
親子丼
杏仁豆腐
-
プログラムが実行されたら、なんらかの方法でデータファイルを読み込んで、データファイル内にある3つのレシピ情報をロードし、すべてのレシピ情報を出力する。
実行例:
% ./recipe.sh recipe-data.txt オムライス 親子丼 杏仁豆腐 -
グループの他の人がREADME.mdに従って、同様のデータファイルを作成できる。
今のプログラムは、同じ料理のレシピを複数登録すると区別できません。登録されたレシピにプログラム内で自動でID(レシピを一意に識別できる識別子)を振ってレシピを区別できるようにしてください。IDは数値でも文字列でも一意であればなんでも構いません。
出力するときはIDも出力してください。
- データファイル
- 中身は前の仕様と同じ次の3つのレシピ情報。
- オムライス
- 親子丼
- 杏仁豆腐
- 中身は前の仕様と同じ次の3つのレシピ情報。
データファイルは、例えばこういう内容です。
% cat recipe-data.txt
オムライス
親子丼
杏仁豆腐
-
プログラムが実行されたら、読み込んだレシピ情報になんらかの方法でIDを降り出し、すべてのレシピ情報をID付きで出力する。
実行例:
% ./recipe.sh recipe-data.txt 1: オムライス 2: 親子丼 3: 杏仁豆腐
今のプログラムは読み込んだレシピをすべて表示します。IDを指定した場合は指定したIDのレシピだけを表示してください。
IDの指定方法は問いません。
IDの指定方法はREADME.mdに記述してください。
指定されるIDは必ず存在するIDと仮定してください。
IDを指定されなかった場合の挙動は変えないでください。
- データファイル
- 中身は前の仕様と同じ次の3つのレシピ情報。
- オムライス
- 親子丼
- 杏仁豆腐
- 中身は前の仕様と同じ次の3つのレシピ情報。
- レシピID(省略可能)
-
レシピ情報のIDを伴ってプログラムが実行されたら、全てのレシピ情報を読み込み、その後、指定されたIDのレシピ情報のみを出力する。
実行例:
% ./recipe.sh recipe-data.txt 2 2: 親子丼 -
レシピ情報のIDを伴わずにプログラムが実行されたら、全てのレシピ情報を出力する。
実行例:
% ./recipe.sh recipe-data.txt 1: オムライス 2: 親子丼 3: 杏仁豆腐 -
グループの他の人がREADME.mdに従って、レシピIDを指定できる。
今のプログラムはレシピの料理名しか情報を持っていません。それぞれのレシピに説明文を関連付けられるようにしてください。説明文には料理の作り方を書きます。
出力時は、レシピIDの指定の有無にかかわらず、料理名と説明文の両方を表示してください。
説明文は長くても4KiBまでとします。
この条件を満たさない説明文が指定されることはないと仮定して構いません。
データファイルのフォーマットは問いません。
どのようなフォーマットにしたかはREADME.mdに記述してください。
- データファイル
- ファイル名は任意。例: recipe-data.txt
- 中身は次の3つのレシピ情報。
- オムライス
- 親子丼
- 杏仁豆腐
- それぞれに説明文を関連付けること
- レシピID(省略可能)
データファイルは、例えばこういう内容です。
% cat recipe-data.txt
オムライス 卵を焼いてごはんにのせる
親子丼 鶏肉を焼いて卵でとじてごはんにのせる
杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める
-
レシピIDの指定の有無に関わらず、プログラムが実行されたら、説明文入りの全てのレシピ情報を読み込み、レシピ情報を出力する。
実行例(レシピIDの指定無しの場合):
% ./recipe.sh recipe-data.txt 1: オムライス 卵を焼いてごはんにのせる 2: 親子丼 鶏肉を焼いて卵でとじてごはんにのせる 3: 杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める -
グループの他の人がREADME.mdに従って、説明文を関連付けたデータファイルを作成できる。
今のプログラムはレシピ情報の集まりをロードして出力するだけです。これに、だれが集めたレシピ情報かという情報を関連付けられるようにしてください。「だれ」のことを「ユーザー名」と呼ぶことにします。レシピ情報を出力するときは、レシピIDの指定の有無にかかわらず、ユーザー名も出力してください。
ユーザー名に使える文字は次の通りとします。
- 小文字のアルファベット
- 数字
- ハイフン
- アンダーバー
ユーザー名は長くても10文字までとします。
この条件を満たさないユーザー名が使われることはないと仮定して構いません。
ユーザー名を関連付ける方法は問いません。
どのような方法でユーザー名を関連付ける仕様にしたかはREADME.mdに記述してください。
ユーザー名の出力方法は問いません。
- データファイル
- ファイル名は任意。例: recipe-data.txt
- 中身は次の3つのレシピ情報。
- オムライス
- 親子丼
- 杏仁豆腐
- それぞれに説明文を関連付けること
- レシピに関連付けるユーザー名
- レシピID(省略可能)
データファイルは、例えばこういう内容です。
% cat recipe-data.txt
オムライス 卵を焼いてごはんにのせる
親子丼 鶏肉を焼いて卵でとじてごはんにのせる
杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める
-
レシピIDの指定の有無に関わらず、プログラムが実行されたら、レシピ情報とそれに関連付くユーザー名を受け取り、ユーザー名と読み込んだレシピ情報を出力する。
実行例(レシピIDの指定無しの場合):
% ./recipe.sh kou recipe-data.txt ユーザー名: kou 1: オムライス 卵を焼いてごはんにのせる 2: 親子丼 鶏肉を焼いて卵でとじてごはんにのせる 3: 杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める実行例(レシピIDの指定ありの場合):
% ./recipe.sh kou recipe-data.txt 2 ユーザー名: kou 2: 親子丼 鶏肉を焼いて卵でとじてごはんにのせる -
グループの他の人がREADME.mdに従って、レシピ情報にユーザー名を関連付けられる。
今のプログラムは1人のユーザーのレシピ情報だけを扱えますが、これを4人のユーザーのレシピ情報も扱えるようにしてください。
出力するときはユーザー毎にレシピを出力してください。
各ユーザー名とそのユーザーのレシピ情報の関連付けの方法は問いません。
どのような方法で各ユーザー名とレシピ情報を関連付ける仕様にしたかはREADME.mdに記述してください。
ユーザー名は重複するかもしれません(同名の別ユーザーが出現するかもしれません)。
プログラム実行時にレシピIDが指定された場合の挙動は、前の仕様に準じます。 その際、IDを指定されたレシピに関連付けられていないユーザー名の出力をどう扱うかは問いません。
- ユーザー名とデータファイルのペアを4つ
- 各データファイル内のレシピ数は3つ
- 1つはこれまで使ってきたデータファイルを使うこと
- 残りの3つはこれまで使ってきたデータファイルを参考に新しく作ること
- 異なるユーザーで同じレシピ情報を持っているかもしれない
- 例:ユーザー1とユーザー2のどちらにも「オムライス」がある
- すべてのレシピは異なるIDを持つこと
- すべてのデータファイルはリポジトリーに入れること
- レシピID(省略可能)
データファイルは、例えば次のような内容です。
% cat recipe-data1.txt
オムライス 卵を焼いてごはんにのせる
親子丼 鶏肉を焼いて卵でとじてごはんにのせる
杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める
% cat recipe-data2.txt
オムライス 卵を焼いてごはんにのせる
鶏の唐揚げ 鶏肉にから揚げ粉をまぶして揚げる
カレー 野菜を切って煮込んでカレー粉を入れる
% cat recipe-data3.txt
トマトサラダ トマトと野菜を切ってまぜる
生ハムサラダ 生ハムと野菜を切ってまぜる
和風サラダ 豆腐と野菜を切ってまぜて醤油ベースのドレッシングをかける
% cat recipe-data4.txt
チョコケーキ 薄力粉とココアと卵とバターをまぜて焼く
スイートポテト 蒸したさつまいもと砂糖とバターと生クリームをまぜて焼く
杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める
-
レシピIDの指定の有無に関わらず、プログラムが実行されたら、各レシピ情報とそれに関連付くユーザー名を受け取り、ユーザー名と読み込んだレシピ情報を出力する。
実行例(レシピIDの指定無しの場合):
% ./recipe.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt kou recipe-data4.txt ユーザー名: kou 1: オムライス 卵を焼いてごはんにのせる 2: 親子丼 鶏肉を焼いて卵でとじてごはんにのせる 3: 杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める ユーザー名: piro 4: オムライス 卵を焼いてごはんにのせる 5: 鶏の唐揚げ 鶏肉にから揚げ粉をまぶして揚げる 6: カレー 野菜を切って煮込んでカレー粉を入れる ユーザー名: okkez 7: トマトサラダ トマトと野菜を切ってまぜる 8: 生ハムサラダ 生ハムと野菜を切ってまぜる 9: 和風サラダ 豆腐と野菜を切ってまぜて醤油ベースのドレッシングをかける ユーザー名: kou 10: チョコケーキ 薄力粉とココアと卵とバターをまぜて焼く 11: スイートポテト 蒸したさつまいもと砂糖とバターと生クリームをまぜて焼く 12: 杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める実行例(レシピIDの指定ありの場合):
% ./recipe.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt sunaot recipe-data4.txt 5 ユーザー名: kou ユーザー名: piro 5: 鶏の唐揚げ 鶏肉にから揚げ粉をまぶして揚げる ユーザー名: okkez ユーザー名: kou -
グループの他の人がREADME.mdに従って、各レシピ情報に各ユーザー名を関連付けられる。
今のプログラムは同じユーザー名だと区別できません。指定されたユーザーにプログラム内で自動でID(ユーザーを一意に識別できる識別子)を振ってユーザーを区別できるようにしてください。IDは数値でも文字列でも一意であればなんでも構いません。
出力するときはIDも出力してください。
プログラム実行時にレシピIDが指定された場合の挙動は、前の仕様に準じます。
- ユーザー名とデータファイルのペアを4つ
- 各データファイル内のレシピ数は3つ
- 1つはこれまで使ってきたデータファイルを使うこと
- 残りの3つはこれまで使ってきたデータファイルを参考に新しく作ること
- 異なるユーザーで同じレシピ情報を持っているかもしれない
- 例:ユーザー1とユーザー2のどちらにも「オムライス」がある
- すべてのレシピは異なるIDを持つこと
- レシピID(省略可能)
データファイルの内容は、前の仕様に準じます。
-
レシピIDの指定の有無に関わらず、プログラムが実行されたら、読み込んだユーザーになんらかの方法でIDを降り出して、出力するユーザー名にそのIDを付与する。
実行例(レシピIDの指定無しの場合):
% ./recipe.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt kou recipe-data4.txt ユーザー: 1: kou 1: オムライス 卵を焼いてごはんにのせる 2: 親子丼 鶏肉を焼いて卵でとじてごはんにのせる 3: 杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める ユーザー: 2: piro 4: オムライス 卵を焼いてごはんにのせる 5: 鶏の唐揚げ 鶏肉にから揚げ粉をまぶして揚げる 6: カレー 野菜を切って煮込んでカレー粉を入れる ユーザー: 3: okkez 7: トマトサラダ トマトと野菜を切ってまぜる 8: 生ハムサラダ 生ハムと野菜を切ってまぜる 9: 和風サラダ 豆腐と野菜を切ってまぜて醤油ベースのドレッシングをかける ユーザー: 4: kou 10: チョコケーキ 薄力粉とココアと卵とバターをまぜて焼く 11: スイートポテト 蒸したさつまいもと砂糖とバターと生クリームをまぜて焼く 12: 杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める実行例(レシピIDの指定ありの場合):
% ./recipe.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt sunaot recipe-data4.txt 5 ユーザー名: kou ユーザー名: piro 5: 鶏の唐揚げ 鶏肉にから揚げ粉をまぶして揚げる ユーザー名: okkez ユーザー名: kou
今のプログラムはすべてのユーザーを表示します。ユーザーIDが指定された場合はそのIDのユーザーだけを表示してください。
ユーザーIDの指定方法は問いません。
ユーザーIDの指定方法はREADME.mdに記述してください。
指定されるユーザーIDは必ず存在するものと仮定して構いません。
ユーザーIDが指定されなかった場合の挙動は変えないでください。
ユーザーIDとレシピIDの両方が指定された場合は、該当ユーザーの該当レシピ情報だけ表示してください。レシピIDは、指定されたユーザーが持っているレシピのIDであると仮定して構いません。
- ユーザー名とデータファイルのペアを4つ
- 各データファイル内のレシピ数は3つ
- 1つはこれまで使ってきたデータファイルを使うこと
- 残りの3つはこれまで使ってきたデータファイルを参考に新しく作ること
- 異なるユーザーで同じレシピ情報を持っているかもしれない
- 例:ユーザー1とユーザー2のどちらにも「オムライス」がある
- すべてのレシピは異なるIDを持つこと
- ユーザーID(省略可能)
- レシピID(省略可能)
データファイルの内容は、前の仕様に準じます。
-
プログラムが実行されたら、各ユーザー名とそれぞれに対応するレシピ情報を読み込むみ、その後、指定されたIDのユーザーのレシピ情報のみを出力する。
実行例(レシピIDの指定無しの場合):
% ./recipe.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt kou recipe-data4.txt 4 ユーザー: 4: kou 10: チョコケーキ 薄力粉とココアと卵とバターをまぜて焼く 11: スイートポテト 蒸したさつまいもと砂糖とバターと生クリームをまぜて焼く 12: 杏仁豆腐 牛乳と砂糖をまぜてゼラチンで固める実行例(レシピIDの指定ありの場合):
% ./recipe.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt kou recipe-data4.txt 4 11 ユーザー: 4: kou 11: スイートポテト 蒸したさつまいもと砂糖とバターと生クリームをまぜて焼く実行例(レシピIDの指定あり、ユーザーIDの指定無しの場合:ここではユーザーIDに
-1を指定したら指定無しと扱うものと仮定):% ./recipe.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt kou recipe-data4.txt -1 11 ユーザー: 1: kou ユーザー: 2: piro ユーザー: 3: okkez ユーザー: 4: kou 11: スイートポテト 蒸したさつまいもと砂糖とバターと生クリームをまぜて焼く -
グループの他の人がREADME.mdに従って、ユーザーIDを指定できる。
ユーザー・レシピ管理部分をライブラリーとして分離し、複数のプログラムから再利用できるようにしてください。これまでの挙動をするプログラムは、この分離したライブラリーを使うアプリケーションとしてください。すべての挙動は変えないでください。
次の入出力部分はライブラリーではなく、アプリケーションプログラム側に入れてください。
- このプログラムの利用者からユーザー名やレシピ情報などの入力を受け取る部分
- データファイルを読み込む部分
- 結果を出力する部分
プログラムをビルドする方法や実行方法が変わった場合はREADME.mdを更新してください。
仕様11に準じます。
仕様11に準じます。
ライブラリーを使用して、結果をCSVで出力する別のプログラムを作ってください。
出力フィールドは左から順に次のとおりにしてください。
- ユーザーID
- ユーザー名
- レシピID
- レシピ名
- レシピの説明
README.mdに実行方法を追記してください。
仕様11に準じます。
-
プログラムが実行されたら、各ユーザー名とそれぞれに対応するレシピ情報を受け取り、ユーザー名と対応するレシピ情報をCSV形式で出力する。
実行例(ユーザーID、レシピIDの指定無しの場合):
% ./recipe-csv.sh kou recipe-data1.txt piro recipe-data2.txt okkez recipe-data3.txt kou recipe-data4.txt 1,kou,1,オムライス,卵を焼いてごはんにのせる 1,kou,2,親子丼,鶏肉を焼いて卵でとじてごはんにのせる 1,kou,3,杏仁豆腐,牛乳と砂糖をまぜてゼラチンで固める 2,piro,4,オムライス,卵を焼いてごはんにのせる 2,piro,5,鶏の唐揚げ,鶏肉にから揚げ粉をまぶして揚げる 2,piro,6,カレー,野菜を切って煮込んでカレー粉を入れる 3,okkez,7,トマトサラダ,トマトと野菜を切ってまぜる 3,okkez,8,生ハムサラダ,生ハムと野菜を切ってまぜる 3,okkez,9,和風サラダ,豆腐と野菜を切ってまぜて醤油ベースのドレッシングをかける 4,kou,10,チョコケーキ,薄力粉とココアと卵とバターをまぜて焼く 4,kou,11,スイートポテト,蒸したさつまいもと砂糖とバターと生クリームをまぜて焼く 4,kou,12,杏仁豆腐,牛乳と砂糖をまぜてゼラチンで固める -
グループの他の人がREADME.mdに従って、プログラムを実行できる。
チューターに仕様を聞いてください。