はじめに
UMLモデリングを通して、一歩一歩作ってみる 「UMLモデリング練習帳アプリ」第二回目です。
今回は、前回作ったものをWebアプリとして実装すること考えてみたいと思います。
前回はこちら
(https://qiita.com/tomohiro_odan/items/48a96141a2a96916f3b2)
作るものを考える
では、ざっくり作るものを考えましょう
前回は、CUIベースでplantUMLを利用した作成UMLモデルと解答UMLモデルを比較するプログラムを作成しました。
「でもなぁ…サービスなんだから、UMLモデル作成も含めて、Webブラウザ上でやりたいよねー。」
そんな要望きたということにします。
…ということで、今回はWebブラウザ上でできる仕組みを考えていきます。
概念
今回も、UMLモデル学習者がUMLモデルを作成し、与えられた問題に対して、作り切れたかを確認することを考えます。(詳細は前回...)
ユースケース
それでは、そういった概念の中でどこをUMLモデリング練習帳アプリの範囲として開発していくか考えます。
ユースケースを考えてみると、「UC1.UMLモデルを作成する」、「UC2.UMLモデルを確認する」の二つを考えていました。
今回は、考えたユースケースは、ブラウザ上で実施したいので、「UC1.UMLモデルを作成する」を新たに含め、どちらも「UMLモデリング練習帳アプリの範囲」としました。
ユースケースのシナリオ(シーケンス)
続いて、ユースケースのシナリオ(シーケンス)を検討していきます。
前回からの変更点は、「UMLモデルを作成する()」を「UMLモデリング練習帳アプリ」で行うことです。
また、それに伴い、ユースケースのシナリオとして、UMLモデリング練習帳アプリは、下記の二つの機能を追加で開発することになりそうです。
- 今回追加で開発するUMLモデリング練習帳アプリ機能
- UMLモデリング問題表示
- UMLモデル記述
ユースケースと機能
先ほどの分析結果からユースケースとアプリの機能の対応は以下となりました。
作るものを決めよう
さて、作るべき機能が明確になったので作るものを決めていきましょう。
Pythonを開発言語としていますが、今回はWebブラウザ上のアプリを想定しています。
そのため、配置や実装に加えて、画面について考える必要がありそうです。
今回は、簡素で使いやすいflaskを利用することにしました。
画面
遷移
今回は単純な1つの画面(index.html)だけで実現することを考えることにしました。
イメージ
画面では、UMLモデル記述用の一つのテキストフィールドとモデル確認用のボタンを持つものを考えました。
結果を受けて、最初は何も表示されていませんが、解答結果表示を行う想定です。
(問題文表示を書き忘れてますが、上部に表示する想定です…)
配置
前回は、main.pyというファイルに全て作成していましたが、今回は、server.pyというファイルに機能を実装することにしました。
UMLモデリング学習者は、Google ChromeなどのウェブブラウザでそのURLにアクセスします。そのため、server.pyは、'localhost:8000'にアクセスできるようにします。
モデル確認ボタンを押すと、画面からUMLモデル記述が書かれたテキストエリアの内容を読み取り、解答UMLモデルスクリプトの記述と比較し、UMLモデルの画像ファイルを出力し画面上に表示します。
また、今回から構築が容易なCentos7上で動作を想定としました。
[フォルダ構成]
server.py(「UMLモデリング練習帳アプリ」サーバースクリプト)
|_static(画像、CSS、Javascriptなどの静的ファイル置き場)
| |_plantuml.png(ダミーUMLモデル画像)
| |_forminput.png(出力UMLモデル画像)
|
|_templates(HTMLのテンプレート置き場)
| |_index.html(トップページhtml)
|
|_answers(解答UMLモデルスクリプト置き場)
| |_usecase001a.pu(解答UMLモデルスクリプト)
|
|_run_plantuml.sh(UMLモデル画像の出力用shellファイル)
|_forminut.pu(出力UMLモデルスクリプト)
実装
それでは実装していきます。
今回もかなりべた書き…。
[server.py]
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, render_template, request
import subprocess
import sys
import difflib as diff
app = Flask(__name__)
# キャッシュをなくす(入れないと画像が古いままになる)
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
# 最初のページ
@app.route('/', methods=['GET'])
def index():
return render_template('index.html', \
image_pass = "/static/plantumlimage.png" )
# UC2.UMLモデルを確認する
# モデル確認を実行する
@app.route('/', methods=['POST'])
def model_conform():
# UMLモデル解析
# plantumlファイル作成
file = "forminput.pu"
fileobj = open(file, "w", encoding = "utf_8")
fileobj.write("@startuml{static/forminput.png}\n")
fileobj.write(str(request.form['modelingform'])+"\n")
fileobj.write("@enduml\n")
fileobj.close()
# 差分出力
with open("./forminput.pu","r") as f:
submit = f.readlines()
with open("./answers/usecase0001a.pu","r") as f:
answer = f.readlines()
# 差分をunified形式で取得
difflist = list(diff.unified_diff(submit, answer, fromfile=str("submit model"), tofile=str("answer model")))
# 確認結果を表示
if len(difflist) == 0 :
result = "確認結果:OK"
else :
result = "確認結果:NG"
# png画像出力
subprocess.Popen(["pwd"], shell=True)
completed_process = subprocess.run(["./run_plantuml.sh"], shell=True)
# 解答結果表示
return render_template('index.html', \
image_pass = "/static/forminput.png", \
check_result = result, \
diffs= difflist)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
[index.html]
<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
</head>
<body>
<h1>UMLモデリング練習帳アプリfrom index.html</h1>
<label for="title">問題①</label><br>
<p>下記の文章からユースケース図を作成しなさい。</p>
<p>UMLモデル学習者は、UMLモデルを作成する。</p>
<form action="/" method="POST">
<textarea name="modelingform" id="modelingform">{{ request.form['modelingform'] }}</textarea><br>
<input type="submit" value="モデル確認"><br>
</form>
<p><img src={{ image_pass }} ></p>
<p>{{ check_result }}</p>
{% for diff in diffs %}
<p>{{ diff }}</p>
{% endfor %}
</body>
</html>
[usecase0001a.pu]
@startuml{static/forminput.png}
usecase UC1.UMLモデルを作成する
UMLモデリング学習者 --> (UC1.UMLモデルを作成する)
@enduml
[run_plantuml.sh]
前回と同様のため省略。
[forminput.pu]
初期は、何も記載されていないので省略。
動きをみてみよう
実装し終えたので、今度は動作を確認しましょう。
実行結果
plantuml,Graphvizは利用できるように環境変数を登録しておきます。
アプリを起動し、動作を確認してみましょう。
$ export FLASK_APP=server.py
$ flask run --host=0.0.0.0 --port=8000
出力結果
確認結果がOKの場合
画像が古いやつですが、イメージ的に下記のような内容になります。差がない場合は、「確認結果:OK」のみが表示されます。
確認結果がNGの場合
「確認結果:NG」と提出したUMLモデルスクリプトと解答UMLモデルスクリプトとの差分が表示されます。
ちなみに、前回は補足できていませんでしたが、差分はunified形式で行の差分が出力されます。
以上で、確認結果が出力できることを確認できました。
次回に向けて
今回はwebブラウザで実現できるようにしてみました。なんとなくアプリらしくなってきました。
しかし…
「これだと1問しかできないじゃん。出題者が問題を登録したりできるようにしたいよ。」
と言われてしましました。
ということで次回は、UMLモデリング出題者というアクターが新たに登場し、問題を登録・削除・編集できるようにすることに取り組んでいきます。
参考文献
- plantUML
以上。