-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path_model_to_code_design.html
1425 lines (1386 loc) · 58.2 KB
/
_model_to_code_design.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.23">
<meta name="description" content="この文書は、モデリングツールにastah*を使って、ソフトウェアの開発にUMLを使う方法について学ぶチュートリアルです。">
<meta name="author" content="株式会社チェンジビジョン">
<title>モデルを使ってソフトウェアを開発しよう: UML初学者向けチュートリアル</title>
<link rel="stylesheet" href="css/mystyle.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<style>.toc-current{font-weight: bold;} .toc-root{font-family: "Open Sans","DejaVu Sans",sans-serif;
font-size: 0.9em;} #content{display: flex; flex-direction: column; flex: 1 1 auto;}
.nav-footer{text-align: center; margin-top: auto;}
.nav-footer > p > a {white-space: nowrap;}</style>
</head>
<body id="_model_to_code_design" class="book toc2 toc-left">
<div id="header">
<h1>モデルを使ってソフトウェアを開発しよう: UML初学者向けチュートリアル</h1>
<div class="details">
<span id="author" class="author">株式会社チェンジビジョン</span><br>
<span id="revnumber">バージョン html_0779,</span>
<span id="revdate">2024-12-20</span>
</div>
<div id="toc" class="toc2">
<div id="toctitle">目次</div>
<p><span class="toc-root"><a href="tut_uml_modeling_bs.html">モデルを使ってソフトウェアを開発しよう: UML初学者向けチュートリアル</a></span></p><ul class="sectlevel1">
<li><a href="_preface.html">はじめに</a>
</li>
<li><a href="_copyright.html">注意事項</a>
</li>
<li><a href="_preparation.html">1 準備</a>
</li>
<li><a href="_structure_design.html">2 スコアシートの構造を調べる</a>
</li>
<li><a href="_model_to_code_design.html"><span class="toc-current">3 モデルとコードの対応づけ</span></a>
<ul class="sectlevel2">
<li><a href="_model_to_code_design.html#_対応づけ検討用モデルの作成">3.1 対応づけ検討用モデルの作成</a>
</li>
<li><a href="_model_to_code_design.html#_変換ルールを使ったコードを確認する">3.2 変換ルールを使ったコードを確認する</a>
</li>
<li><a href="_model_to_code_design.html#_まとめ_2">3.3 まとめ</a>
</li>
</ul>
</li>
<li><a href="_behavior_design.html">4 スコアやフレームの状態を調べる</a>
</li>
<li><a href="_program_test.html">5 できあがったプログラムを試す</a>
</li>
<li><a href="_summary.html">6 まとめ</a>
</li>
<li><a href="_other_diagrams.html">7 他の図、他の機能など</a>
</li>
<li><a href="_appendix-01.html">付録 A: モデルやプログラムの作成例</a>
</li>
<li><a href="_bibliography.html">参考文献</a>
</li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="_model_to_code_design"><a class="anchor" href="#_model_to_code_design"></a>第3章 モデルとコードの対応づけ</h2>
<div class="sectionbody">
<div class="paragraph lead">
<p>プログラムがどのように動作するのか検討するときには、振る舞いのモデルを使います。
振る舞いのモデルを作成する前に、構造のモデルと振る舞いのモデルがどのようなコードとして実現されるのかについて、このチュートリアルで用いる方式を決めておきましょう。
このことを「モデルとコードの対応づけ」と呼ぶことにします。</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="ヒント"></i>
</td>
<td class="content">
このような対応づけを「モデル変換ルール」と呼ぶこともあります。また、開発プロセスのなかでこの対応づけを検討する工程を「方式設計」と呼ぶ人もいます。
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>モデルとコードの対応づけを決めてそれを前提にして設計する(モデルを作る)ことは、実装に依存する情報と依存しない情報の分離を促します。
また、このような考え方は、実装に依存しないモデルを作る上でとても重要で、実務的なモデルを作成する際にも大いに役立ちます。</p>
</div>
<div class="sect2">
<h3 id="_対応づけ検討用モデルの作成"><a class="anchor" href="#_対応づけ検討用モデルの作成"></a>3.1 対応づけ検討用モデルの作成</h3>
<div class="paragraph">
<p>このチュートリアルでは実装にRubyを使うことにしました。
サンプルモデルとサンプルモデルに対応するRubyプログラムを作ってみることで、対応づけの方式の基本的な考え方を決めておこうというわけです。</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="注記"></i>
</td>
<td class="content">
<div class="paragraph">
<p>この章で検討したいことは、ボウリングのスコアに関するモデルの問題領域とは直接の関係はありません。
こういった別の領域の問題を、これまで検討していたボウリングのスコアに関する問題領域と、ここで検討したいことが混在してしまい、說明も受け取り手も混乱してしまうでしょう。
そんなわけで、別の問題として分けて検討するために、この章を用意してあります。</p>
</div>
<div class="paragraph">
<p>もし、この章の役割がピンとこない、実装についての議論にはあまり関心がないのであれば、最初はこの章を読み飛ばしてみてもかまいません。
しかし、後の章へ進むと、実装する人がモデルを使う際には、モデルとコードを対応づける必要があり、ここで実装方式を決めておかなければ、実装者がそのことについて考える必要がある(特定の実装者に依存しないよう設計しておくべきことを実装する各人に委ねてしまっている)ことに気づくでしょう。
そのときは、この章に戻って、どうして実装方式の設計が必要なのか考えてもらえたらと思います。</p>
</div>
</td>
</tr>
</table>
</div>
<div class="sect3">
<h4 id="_対応づけ検討用プロジェクトを用意する"><a class="anchor" href="#_対応づけ検討用プロジェクトを用意する"></a>3.1.1 対応づけ検討用プロジェクトを用意する</h4>
<div class="paragraph">
<p>「モデルとコードの対応づけ」の検討用に astah* で別のプロジェクトを作成しましょう。</p>
</div>
<div class="sect4">
<h5 id="_対応づけ検討用プロジェクトを作成する"><a class="anchor" href="#_対応づけ検討用プロジェクトを作成する"></a>対応づけ検討用プロジェクトを作成する</h5>
<div class="ulist">
<ul>
<li>
<p>astah* で新規プロジェクトを作成する。</p>
</li>
<li>
<p>作成したプロジェクトをいったん保存する。</p>
</li>
<li>
<p>モデルファイルの名前は「stm_sample.asta」とする。</p>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="add_stm_sample_class_diag"><a class="anchor" href="#add_stm_sample_class_diag"></a>検討用プロジェクトにクラス図を追加する</h5>
<div class="paragraph">
<p>プロジェクトが保存できたら、プロジェクトにクラス図を追加しましょう。</p>
</div>
<div class="ulist">
<ul>
<li>
<p>構造ツリーで、プロジェクト名をクリックしてポップアップメニューを開く。</p>
</li>
<li>
<p>「図の追加>クラス図」でクラス図を追加する。</p>
</li>
<li>
<p>プロパティーから、クラス図の名前を「クラス図」に変更する。</p>
</li>
</ul>
</div>
<div id="add_stm_sample00" class="imageblock">
<div class="content">
<img src="images/GSW-20220213-005309.png" alt="GSW 20220213 005309" width="50%">
</div>
<div class="title">図 3.1 対応づけの説明に使うプロジェクトにクラス図を追加した</div>
</div>
</div>
<div class="sect4">
<h5 id="add_sample_class00"><a class="anchor" href="#add_sample_class00"></a>クラス図に「Sample」クラスを追加する</h5>
<div class="paragraph">
<p>対応づけの説明用に、簡単なクラス「Sample」の定義から始めましょう。
このクラスは、操作「Play」と属性「attr_a」「attr_b」を持つクラスとします。
これをUMLのクラスとして表してみましょう。</p>
</div>
<div class="ulist">
<ul>
<li>
<p>パレットからクラスを選択し、クラス図に追加する。</p>
</li>
<li>
<p>クラス名を「Sample」にする( <a href="_model_to_code_design.html#sample_class01">図 3.2</a> )。</p>
</li>
<li>
<p>クラスに操作「play」を追加する。</p>
</li>
<li>
<p>クラスに属性「attr_a」「attr_b」を追加する。</p>
</li>
</ul>
</div>
<div id="sample_class01" class="imageblock">
<div class="content">
<img src="images/GSW-20220212-220754.png" alt="GSW 20220212 220754" width="75%">
</div>
<div class="title">図 3.2 クラス図に「Sample」クラスを追加した</div>
</div>
</div>
<div class="sect4">
<h5 id="_sampleクラスの最初のサンプルコード"><a class="anchor" href="#_sampleクラスの最初のサンプルコード"></a>Sampleクラスの最初のサンプルコード</h5>
<div class="paragraph">
<p>対応づけルールの1つ目として、 <a href="_model_to_code_design.html#sample_class01">図 3.2</a> を表したRubyのコードは <a href="_model_to_code_design.html#ruby_sample01">リスト 3.1</a> のように書きたいと決めることにします。</p>
</div>
<div id="ruby_sample01" class="listingblock">
<div class="title">リスト 3.1 【Ruby】「Sample」クラスを表すRubyのコード</div>
<div class="content">
<pre class="prettyprint highlight"><code data-lang="ruby">class Sample <i class="conum" data-value="1"></i><b>(1)</b>
def initialize <i class="conum" data-value="2"></i><b>(2)</b>
@attr_a = true <i class="conum" data-value="3"></i><b>(3)</b>
@attr_b = true <i class="conum" data-value="3"></i><b>(3)</b>
end
def play <i class="conum" data-value="4"></i><b>(4)</b>
end
end</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>クラス「Sample」の定義の始まり</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>初期化メソッド(コンストラクタにあたるメソッド)</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>このクラスのインスタンス変数</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>メソッド「Play」の定義の始まり</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_クラスにステートマシン図を追加する"><a class="anchor" href="#_クラスにステートマシン図を追加する"></a>3.1.2 クラスにステートマシン図を追加する</h4>
<div class="paragraph">
<p>このサンプルにおいては、いま追加した操作「play」が、「Sample」クラスの振る舞いを提供しているとします。
しかし、クラス図に描いた「Sample」クラスに操作「play」を追加しただけでは、その処理内容はわかりません。
どこかに「play」の処理内容を表した図が必要です。</p>
</div>
<div class="paragraph">
<p>そこで、「Sample」クラスに対して、操作「play」の振る舞いを表すステートマシン図を追加します。
ここで、図を追加する対象を「Sample」クラスにしているのは、このステートマシン図が「Sample」クラスの振る舞いのモデル図であるとわかるようにするためです。</p>
</div>
<div class="sect4">
<h5 id="add_stm_sample01"><a class="anchor" href="#add_stm_sample01"></a>クラスにステートマシン図を追加する</h5>
<div class="paragraph">
<p>「Sample」クラスにステートマシン図を追加します。</p>
</div>
<div class="ulist">
<ul>
<li>
<p>構造ツリーから「Sample」クラスを選択する。</p>
</li>
<li>
<p>右クリックしてポップアップメニューを表示する( <a href="_model_to_code_design.html#add_stm_sample02">図 3.3</a> )。</p>
</li>
<li>
<p>「図の追加>ステートマシン図」を選択すると、ステートマシン図が追加される。</p>
</li>
</ul>
</div>
<div id="add_stm_sample02" class="imageblock">
<div class="content">
<img src="images/GSW-20220213-020944.png" alt="GSW 20220213 020944" width="75%">
</div>
<div class="title">図 3.3 「Sample」クラスにステートマシン図を追加する</div>
</div>
<div class="ulist">
<ul>
<li>
<p>プロパティーから図の名前を編集し、「Sampleのplayのステートマシン図」とする( <a href="_model_to_code_design.html#add_stm_sample03">図 3.4</a> )。</p>
</li>
<li>
<p>ダイアグラムエディタのタイトルやタブにも図の名前が反映される。</p>
</li>
</ul>
</div>
<div id="add_stm_sample03" class="imageblock">
<div class="content">
<img src="images/GSW-20220213-013034.png" alt="GSW 20220213 013034" width="75%">
</div>
<div class="title">図 3.4 追加したステートマシン図に名前をつける</div>
</div>
<div class="sidebarblock">
<div class="content">
<div class="title">【参考】ステートマシン図を学ぶチュートリアル</div>
<div class="paragraph">
<p>ここでは、モデルとコードの対応づけを説明するために、振る舞いのモデルの一種であるステートマシン図を作成しています。
ステートマシン図を使って振る舞いを設計する方法については、次のチュートリアルも参考にしてみてください。</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">ステートマシン図 & 状態遷移表チュートリアル</dt>
<dd>
<p><code><a href="https://www.changevision.co/tutorial-statemachine-japanese.html" class="bare">https://www.changevision.co/tutorial-statemachine-japanese.html</a></code></p>
</dd>
</dl>
</div>
</div>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="注記"></i>
</td>
<td class="content">
<div class="paragraph">
<p><a href="_model_to_code_design.html#add_stm_sample02">図 3.3</a> では、Sampleクラスの振舞いを表すステートマシン図とわかるようにと考えて、クラスに対してステートマシン図を割り当てました。
この他、 astah* では、メソッドに対してステートマシン図を割り当てることもできます。
任意のメソッドの処理を示すステートマシン図の割当てとしては、後者のほうが好ましいでしょう。
ここでは、クラスの振舞いということを意識して、クラス図に割当ててみています。
どちらの方法を使うにしても、クラスの振舞いを担当するメソッドを対応づけすることは必要になるでしょう。</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_ステートマシン図に状態を追加する"><a class="anchor" href="#_ステートマシン図に状態を追加する"></a>3.1.3 ステートマシン図に状態を追加する</h4>
<div class="paragraph">
<p>次に、追加したステートマシン図に、状態を追加します。</p>
</div>
<div class="olist arabic">
<div class="title">ステートマシン図に状態を追加する</div>
<ol class="arabic">
<li>
<p>パレットから「状態」を選択し、ステートマシン図に状態を追加する。</p>
<div class="ulist">
<ul>
<li>
<p>追加した状態の状態名は「状態0」(数字は追加の都度変わる)となっている( <a href="_model_to_code_design.html#add_stm_sample04">図 3.5</a> )。</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div id="add_stm_sample04" class="imageblock">
<div class="content">
<img src="images/GSW-20220213-093229.png" alt="GSW 20220213 093229" width="75%">
</div>
<div class="title">図 3.5 新しい状態を追加した</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>「状態0」を選択し、プロパティーの「ベース」タブの「名前」を編集して、状態の名前を「ST0」にする( <a href="_model_to_code_design.html#add_stm_sample05">図 3.6</a> )。</p>
<div class="ulist">
<ul>
<li>
<p>状態「ST0」は、このサンプルの例示用に使う状態名の1つ。</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div id="add_stm_sample05" class="imageblock">
<div class="content">
<img src="images/GSW-20220213-104448.png" alt="GSW 20220213 104448" width="75%">
</div>
<div class="title">図 3.6 新しい状態に状態名をつけた</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="3">
<li>
<p>このサンプルでは3つの状態を使いたいので、状態をもう2つ追加する( <a href="_model_to_code_design.html#add_stm_sample06">図 3.7</a> )。</p>
<div class="ulist">
<ul>
<li>
<p>「ST1」、「ST2」を追加した。</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div id="add_stm_sample06" class="imageblock">
<div class="content">
<img src="images/GSW-20220213-111820.png" alt="GSW 20220213 111820" width="75%">
</div>
<div class="title">図 3.7 新しい状態に状態名をつけた</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="3">
<li>
<p>開始疑似状態、終了疑似状態を追加した( <a href="_model_to_code_design.html#add_stm_sample07">図 3.8</a> )。</p>
</li>
</ol>
</div>
<div id="add_stm_sample07" class="imageblock">
<div class="content">
<img src="images/GSW-20220213-112341.png" alt="GSW 20220213 112341" width="75%">
</div>
<div class="title">図 3.8 開始疑似状態、終了疑似状態を追加した</div>
</div>
</div>
<div class="sect3">
<h4 id="_ステートマシン図に状態遷移を追加する"><a class="anchor" href="#_ステートマシン図に状態遷移を追加する"></a>3.1.4 ステートマシン図に状態遷移を追加する</h4>
<div class="paragraph">
<p>状態が追加できたので、こんどは状態遷移を追加しましょう。
ステートマシン図には、通常の状態のほかにいくつかの「疑似状態」が登場します。
たとえば、「開始疑似状態」は、この図における最初の状態を示すのに使います。
「終了疑似状態」は、その図における最後の状態(1つとは限りません)を示すのに使います。</p>
</div>
<div id="add_stm_trans00" class="olist arabic">
<div class="title">状態遷移を追加する</div>
<ol class="arabic">
<li>
<p>パレットから「遷移」を選択して、「開始疑似状態」の内部へマウスカーソルを移動し、青枠が表示されるのを待つ( <a href="_model_to_code_design.html#add_stm_trans01">図 3.9</a> )。</p>
</li>
</ol>
</div>
<div id="add_stm_trans01" class="imageblock">
<div class="content">
<img src="images/add_stm_transition_58.png" alt="add stm transition 58" width="75%">
</div>
<div class="title">図 3.9 開始疑似状態の内側で青枠を表示させる</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>青枠が表示されたらマウスカーソルをドラッグする(マウスのボタンを押したままマウスカーソルを移動する)。</p>
</li>
<li>
<p>マウスカーソルを「ST0」へドラッグして青枠が表示されるのを待つ( <a href="_model_to_code_design.html#add_stm_trans02">図 3.10</a> )。</p>
</li>
</ol>
</div>
<div id="add_stm_trans02" class="imageblock">
<div class="content">
<img src="images/add_stm_transition_73.png" alt="add stm transition 73" width="75%">
</div>
<div class="title">図 3.10 「ST0」へマウスカーソルをドラッグして青枠が表示されるのを待つ</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="4">
<li>
<p>「ST0」でも青枠が表示されたらマウスのボタンを離すと状態遷移が引かれる( <a href="_model_to_code_design.html#add_stm_trans03">図 3.11</a> )。</p>
</li>
</ol>
</div>
<div id="add_stm_trans03" class="imageblock">
<div class="content">
<img src="images/add_stm_transition_81.png" alt="add stm transition 81" width="75%">
</div>
<div class="title">図 3.11 「ST0」でも青枠が表示されたらマウスのボタンを離すと状態遷移が引かれる</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="4">
<li>
<p>ほかの状態についても <a href="_model_to_code_design.html#add_stm_trans04">図 3.12</a> と同じように状態遷移を追加する。</p>
</li>
</ol>
</div>
<div id="add_stm_trans04" class="imageblock">
<div class="content">
<img src="images/add_stm_transition_215.png" alt="add stm transition 215" width="75%">
</div>
<div class="title">図 3.12 ほかの状態遷移も追加する</div>
</div>
</div>
<div class="sect3">
<h4 id="_状態とイベントと状態遷移の関係"><a class="anchor" href="#_状態とイベントと状態遷移の関係"></a>3.1.5 状態とイベントと状態遷移の関係</h4>
<div class="sect4">
<h5 id="_状態とイベント"><a class="anchor" href="#_状態とイベント"></a>状態とイベント</h5>
<div class="paragraph">
<p>ステートマシン図において、状態は「イベント」の発生を待っているところです。
多くの場合、イベントは、そのクラス自身の操作では処理を先に進められなくなるようなできごとです。
たとえば、外部からの入力(操作待ちや受信待ちなど)や、一定の時間経過などがイベントの候補になります。</p>
</div>
</div>
<div class="sect4">
<h5 id="_状態遷移"><a class="anchor" href="#_状態遷移"></a>状態遷移</h5>
<div class="paragraph">
<p>状態遷移は、ある状態において待っていたイベントが発生して、別の状態へ移ることを表しています。
イベントには、イベントが発生したとき、実際に遷移するか判定する条件を追加できます。
この条件のことを「ガード条件」と呼びます。
ガード条件つきのイベントでは、イベントが発生したときにガード条件を評価し、条件が真なら状態遷移します。
ガード条件が偽のとき、イベントは起きたことになります(消費されると呼びます)が、状態は遷移しません。</p>
</div>
<div class="paragraph">
<p>そして、状態遷移には、イベントが発生したときに実行したい処理を追加できます。
この処理のことを「アクション(またはエフェクト)」と呼びます。</p>
</div>
<div class="paragraph">
<p>イベントが発生すると、ガード条件つきのイベントならさらにガード条件も真なら、状態遷移に伴うアクションが実行され、それから次の状態へ遷移します。</p>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_ステートマシン図にイベントやアクションを追加する"><a class="anchor" href="#_ステートマシン図にイベントやアクションを追加する"></a>3.1.6 ステートマシン図にイベントやアクションを追加する</h4>
<div class="paragraph">
<p>まず、「ST0」から「ST1」への状態遷移を、イベントが「ev1」でガード条件は「gd(が真)」のとき、アクション「act1」を実行するよう編集してみましょう。</p>
</div>
<div id="add_evt_act00" class="olist arabic">
<div class="title">状態遷移にイベントやアクションを追加する(1)</div>
<ol class="arabic">
<li>
<p>「ST0」から「ST1」への状態遷移を選択し、この遷移のプロパティーを表示し、ベースタブを開く。</p>
</li>
<li>
<p>プロパティーを編集する( <a href="_model_to_code_design.html#add_evt_act01">図 3.13</a> )。</p>
<div class="ulist">
<ul>
<li>
<p>「トリガー」にイベント名を設定する。ここでは「ev1」というイベントを設定する。</p>
</li>
<li>
<p>「ガード」にガード条件を設定する。ここでは「gd1(が真)」を設定しする。</p>
</li>
<li>
<p>「アクション」にアクションを設定する。ここでは「act1」という処理があるとして、これを設定する。</p>
<div class="ulist">
<ul>
<li>
<p>act1は、2つの引数(イベントとパラメーター)を持つメソッドと想定する。</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div id="add_evt_act01" class="imageblock">
<div class="content">
<img src="images/GSW-20220215-071155.png" alt="GSW 20220215 071155" width="75%">
</div>
<div class="title">図 3.13 「ST0」から「ST1」への状態遷移のイベントとアクションを編集する</div>
</div>
<div class="paragraph">
<p>次に、「ST1」からの「ST2」への遷移です。
この遷移に割り当てるイベントは、「ev2」、アクションを「act2」とします。
そして、このアクションの実行後、ガード条件「gd2」が真なら「ST2」へ、偽ならアクション「act3」を実行してから「ST1」へ遷移するように変更してみます。</p>
</div>
<div class="paragraph">
<p>遷移先が2つあるなら、状態遷移を別々に引けばよさそうです。
ところが、同じイベントを待ってる遷移先が2つ以上あると、どちらの状態へ遷移するのか決定できなくなります(あいまいな状態遷移と呼びます)。
そこで、1つのイベントによる遷移先が状況によって変わる場合には「選択疑似状態」を使います。</p>
</div>
<div id="add_evt_act02" class="olist arabic">
<div class="title">状態遷移にイベントやアクションを追加する(2)</div>
<ol class="arabic">
<li>
<p>パレットから「選択疑似状態」を選択し、ステートマシン図に追加する( <a href="_model_to_code_design.html#add_evt_act03">図 3.14</a> )。</p>
</li>
</ol>
</div>
<div id="add_evt_act03" class="imageblock">
<div class="content">
<img src="images/add_stm_trans45.png" alt="add stm trans45" width="75%">
</div>
<div class="title">図 3.14 「選択疑似状態」をステートマシン図に追加する</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="2">
<li>
<p>「ST1」から「ST2」への状態遷移を選択し、「ST2」側のハンドル(丸印)をマウスでつまみ、「選択疑似状態」へつなぎ直す( <a href="_model_to_code_design.html#add_evt_act04">図 3.15</a> )。</p>
</li>
</ol>
</div>
<div id="add_evt_act04" class="imageblock">
<div class="content">
<img src="images/add_stm_trans120.png" alt="add stm trans120" width="75%">
</div>
<div class="title">図 3.15 既存の状態遷移を追加した「選択疑似状態」へつなぎ直す</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="3">
<li>
<p>「選択疑似状態」から「ST0」と「ST2」への状態遷移を追加する( <a href="_model_to_code_design.html#add_evt_act05">図 3.16</a> )。</p>
</li>
</ol>
</div>
<div id="add_evt_act05" class="imageblock">
<div class="content">
<img src="images/add_stm_trans218.png" alt="add stm trans218" width="75%">
</div>
<div class="title">図 3.16 「選択疑似状態」から「ST0」と「ST2」への状態遷移を追加する</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="4">
<li>
<p>それぞれの遷移のプロパティーを編集する( <a href="_model_to_code_design.html#add_evt_act06">図 3.17</a> )。</p>
<div class="ulist">
<ul>
<li>
<p>トリガーに「ev2」、ガード条件はなし、アクションを「act2」に設定する。</p>
</li>
<li>
<p>ガードにガード条件「!gd2(gd2ではない)」、アクションを「act3」に設定する。</p>
</li>
<li>
<p>ガードにガード条件「gd2」に設定する。</p>
</li>
</ul>
</div>
</li>
</ol>
</div>
<div id="add_evt_act06" class="imageblock">
<div class="content">
<img src="images/add_stm_trans589.png" alt="add stm trans589" width="75%">
</div>
<div class="title">図 3.17 状態遷移のイベントとアクションを編集する</div>
</div>
<div class="olist arabic">
<ol class="arabic" start="5">
<li>
<p>同様にして、もう2つほど状態遷移を追加する( <a href="_model_to_code_design.html#add_evt_act07">図 3.18</a> )。</p>
</li>
</ol>
</div>
<div id="add_evt_act07" class="imageblock">
<div class="content">
<img src="images/GSW-20220216-045358.png" alt="GSW 20220216 045358" width="75%">
</div>
<div class="title">図 3.18 さらに状態遷移とイベントとアクションを追加した</div>
</div>
</div>
<div class="sect3">
<h4 id="_ステートマシン図に対応するコードを作成する"><a class="anchor" href="#_ステートマシン図に対応するコードを作成する"></a>3.1.7 ステートマシン図に対応するコードを作成する</h4>
<div class="paragraph">
<p>ステートマシン図ができたので、この図に合うようなRubyのコードを作成すルールを考えましょう。</p>
</div>
<div class="sect4">
<h5 id="_状態を保持する変数を追加する"><a class="anchor" href="#_状態を保持する変数を追加する"></a>状態を保持する変数を追加する</h5>
<div class="paragraph">
<p>まず、「Sample」クラスに状態を保持するインスタンス変数を追加します( <a href="_model_to_code_design.html#ruby_sample02">リスト 3.2</a> )。
初期値は、最初の状態( ST0 )にします。</p>
</div>
<div id="ruby_sample02" class="listingblock">
<div class="title">リスト 3.2 【Ruby】状態を保持するインスタンス変数を追加する</div>
<div class="content">
<pre class="prettyprint highlight"><code data-lang="ruby">class Sample
def initialize
@state = :ST0 <i class="conum" data-value="1"></i><b>(1)</b>
@attr_a = true
@attr_b = true
end
# 略
end</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>現在の状態を保持する変数を用意し、 ST0 で初期化する。「 :ST0 」はRubyのシンボルの表記法。シンボルは名前付きの数値定数。</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_状態遷移を担当するメソッドを作成する"><a class="anchor" href="#_状態遷移を担当するメソッドを作成する"></a>状態遷移を担当するメソッドを作成する</h5>
<div class="paragraph">
<p>ステートマシン図に書いた状態遷移を担当する操作「play」をplayメソッドとして作成します( <a href="_model_to_code_design.html#ruby_sample03">リスト 3.3</a> )。
ルールの検討用なので、途中には処理の確認用の表示処理を書いておきます。</p>
</div>
<div id="ruby_sample03" class="listingblock">
<div class="title">リスト 3.3 【Ruby】状態遷移を担当するメソッドを作成する</div>
<div class="content">
<pre class="prettyprint highlight"><code data-lang="ruby">class Sample
def initialize
# 略
end
def play(evt, param)
puts "#{@state} ->" <i class="conum" data-value="1"></i><b>(1)</b>
puts " event:#{evt}, param: #{param}" <i class="conum" data-value="2"></i><b>(2)</b>
case @state <i class="conum" data-value="3"></i><b>(3)</b>
when :ST0
st0_proc(evt, param) <i class="conum" data-value="4"></i><b>(4)</b>
when :ST1
st1_proc(evt, param)
when :ST2
# none
end
puts " -> #{@state}" <i class="conum" data-value="5"></i><b>(5)</b>
puts 'finished.' if @state == :ST2 <i class="conum" data-value="6"></i><b>(6)</b>
end
end</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>遷移前の状態を表示する。</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>イベントとパラメーターを表示する。</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>状態ごとの処理を case文を使って分岐する。</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>状態ごとの詳細な処理を担当するメソッドを呼び出す(ここでは st0_proc) 。</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>遷移後の状態を表示する。</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>終了状態になったことを知らせる。</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_ガード条件の判定用メソッドを作成する"><a class="anchor" href="#_ガード条件の判定用メソッドを作成する"></a>ガード条件の判定用メソッドを作成する</h5>
<div class="paragraph">
<p>このサンプルのステートマシン図には、状態遷移のガード条件として「gd1」「gd2」が登場します。
これらをrubyのメソッドとして作成します。
rubyでは、真偽値を返すメソッドには「?」をつける習慣がありますので、これにしたがってメソッド名は「gd1?」「gd2?」とします。
サンプルとして、属性の値を使った演算を割り当てました( <a href="_model_to_code_design.html#ruby_sample04">リスト 3.4</a> )。</p>
</div>
<div id="ruby_sample04" class="listingblock">
<div class="title">リスト 3.4 【Ruby】ガード条件のメソッドを作成する</div>
<div class="content">
<pre class="prettyprint highlight"><code data-lang="ruby">class Sample
def initialize
# 略
end
def play
# 略
end
def gd1? <i class="conum" data-value="1"></i><b>(1)</b>
@attr_a && @attr_b <i class="conum" data-value="2"></i><b>(2)</b>
end
def gd2? <i class="conum" data-value="3"></i><b>(3)</b>
!@attr_a || @attr_b
end
end</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>「gd1」用のメソッド。真偽値を返すメソッドに「?」をつけるRubyの習慣に倣った。</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>属性値を使った条件式の例。</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>「gd2」用のメソッド。</td>
</tr>
</table>
</div>
</div>
<div class="sect4">
<h5 id="_状態遷移を追加する1"><a class="anchor" href="#_状態遷移を追加する1"></a>状態遷移を追加する(1)</h5>
<div class="paragraph">
<p>状態ごとの処理を受け持つメソッドを作成します。
メソッド名は、状態名を小文字して「_proc」をつけるというルールにします。
したがって、状態名「ST0」の場合、メソッド名は「st0_proc」になります( <a href="_model_to_code_design.html#ruby_sample05">リスト 3.5</a> )。</p>
</div>
<div id="ruby_sample05" class="listingblock">
<div class="title">リスト 3.5 【Ruby】「ST0」の状態遷移のメソッドを作成する</div>
<div class="content">
<pre class="prettyprint highlight"><code data-lang="ruby">class Sample
def initialize
# 略
end
def play
# 略
end
def st0_proc(evt, param)
case evt <i class="conum" data-value="1"></i><b>(1)</b>
when :ev1 <i class="conum" data-value="2"></i><b>(2)</b>
if gd1? <i class="conum" data-value="3"></i><b>(3)</b>
puts " gd1: #{gd1?}"
act1(evt, param) <i class="conum" data-value="4"></i><b>(4)</b>
@state = :ST1 <i class="conum" data-value="5"></i><b>(5)</b>
else <i class="conum" data-value="6"></i><b>(6)</b>
puts " <<< gd1: #{gd1?}, transition is ignored. >>>"
end
when :ev3 <i class="conum" data-value="7"></i><b>(7)</b>
act3(evt, param)
@state = :ST2
end
end
# gd1?, gd2? が続く
end</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>イベントで場合分けする。</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>イベントが「ev1」の場合。イベントはRubyのシンボルを使って表す。</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>ガード条件による判定。</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>アクション「act1」の呼び出し。</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>次の状態「ST1」への遷移。</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>ガード条件が偽だったとき。イベントが無視されたことを表示する。</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>イベントが「ev3」の場合。</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>この部分のRubyのコードとステートマシン図の対応を図で表してみましょう( <a href="_model_to_code_design.html#ruby_sample06">図 3.19</a> )。</p>
</div>
<div id="ruby_sample06" class="imageblock">
<div class="content">
<img src="images/ruby_sample05.png" alt="ruby sample05" width="100%">
</div>
<div class="title">図 3.19 Rubyのコードとステートマシン図の対応関係(1)</div>
</div>
<div class="paragraph">
<p>おおむねのことは <a href="_model_to_code_design.html#ruby_sample06">図 3.19</a> を読めばわかるでしょうが、対応関係を説明しておきます。</p>
</div>
<div class="sidebarblock">
<div class="content">
<div class="title">ガード条件のある状態遷移をRubyのコードで表すルール</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>遷移元の状態で待っているイベントごとに場合分けする。</p>
</li>
<li>
<p>ガード条件なしのときは(アクションがあればそれを呼び出して)、次の状態へ遷移する。</p>
</li>
<li>
<p>ガード条件があるときは、先にガード条件を評価して、真であればアクションを実行して次の状態へ遷移する。</p>
</li>
<li>
<p>ガード条件が偽のときは、アクションは実行されず、状態も遷移しない。</p>
</li>
</ol>
</div>
</div>
</div>
</div>
<div class="sect4">
<h5 id="_状態遷移を追加する2"><a class="anchor" href="#_状態遷移を追加する2"></a>状態遷移を追加する(2)</h5>
<div class="paragraph">
<p>こんどは、「ST1」からの状態遷移に対するメソッド「st1_proc」です( <a href="_model_to_code_design.html#ruby_sample07">リスト 3.6</a> )。</p>
</div>
<div id="ruby_sample07" class="listingblock">
<div class="title">リスト 3.6 【Ruby】「ST1」の状態遷移のメソッドを作成する</div>
<div class="content">
<pre class="prettyprint highlight"><code data-lang="ruby">class Sample
def initialize
# 略
end
def play
# 略
end
def st0_proc(evt, param)
# 略
end
def st1_proc(evt, param)
case evt
when :ev2 <i class="conum" data-value="1"></i><b>(1)</b>
act2(evt, param) <i class="conum" data-value="2"></i><b>(2)</b>
puts " gd2: #{gd2?}"
if gd2? <i class="conum" data-value="3"></i><b>(3)</b>
@state = :ST2 <i class="conum" data-value="4"></i><b>(4)</b>
else
act3(evt, param) <i class="conum" data-value="5"></i><b>(5)</b>
@state = :ST0 <i class="conum" data-value="6"></i><b>(6)</b>
end
when :ev3 <i class="conum" data-value="7"></i><b>(7)</b>
act3(evt, param)
@state = :ST0
end
end
# gd1?, gd2? が続く
end</code></pre>
</div>
</div>
<div class="colist arabic">
<table>
<tr>
<td><i class="conum" data-value="1"></i><b>1</b></td>
<td>イベントが「ev2」の場合。</td>
</tr>
<tr>
<td><i class="conum" data-value="2"></i><b>2</b></td>
<td>アクション「act2」の呼び出し。</td>
</tr>
<tr>
<td><i class="conum" data-value="3"></i><b>3</b></td>
<td>選択疑似状態におけるガード条件による判定。</td>
</tr>
<tr>
<td><i class="conum" data-value="4"></i><b>4</b></td>
<td>次の状態「ST0」への遷移。</td>
</tr>
<tr>
<td><i class="conum" data-value="5"></i><b>5</b></td>
<td>選択疑似状態からの遷移におけるアクション「act3」の呼び出し。</td>
</tr>
<tr>
<td><i class="conum" data-value="6"></i><b>6</b></td>
<td>次の状態「ST2」への遷移。</td>
</tr>
<tr>
<td><i class="conum" data-value="7"></i><b>7</b></td>
<td>イベントが「ev3」の場合。</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>この部分のRubyのコードとステートマシン図の対応を図で表してみましょう( <a href="_model_to_code_design.html#ruby_sample08">図 3.20</a> )。</p>
</div>
<div id="ruby_sample08" class="imageblock">
<div class="content">
<img src="images/ruby_sample08.png" alt="ruby sample08" width="100%">
</div>
<div class="title">図 3.20 Rubyのコードとステートマシン図の対応関係(2)</div>
</div>
<div class="paragraph">
<p>おおむねのことは <a href="_model_to_code_design.html#ruby_sample08">図 3.20</a> を読めばわかるでしょうが、対応関係を説明しておきます。</p>
</div>
<div class="sidebarblock">
<div class="content">
<div class="title">選択疑似状態がある状態遷移をRubyのコードで表すルール</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>選択疑似状態の前の状態遷移については、<a href="_model_to_code_design.html#ruby_sample06">図 3.19</a> のルールで賄う。</p>
</li>
<li>
<p>その後で、選択疑似状態の後の状態遷移のガード条件を評価する。</p>
</li>
<li>
<p>評価結果によって(アクションがあれば実行してから)、次の状態へ遷移する。</p>
</li>
<li>
<p>選択疑似状態の後の状態遷移は、ガード条件による場合分けで漏れる場合がないように注意する。</p>
</li>
</ol>
</div>
</div>
</div>
<div class="paragraph">
<p>このサンプルでは、アクション「act1」、「act2」、「act3」は、定めたルールを確認しやすいメソッドにしておきます( <a href="_model_to_code_design.html#ruby_sample09">リスト 3.7</a> )。
これらのアクションと、先に挙げたガード条件をチェックするメソッドは、「Sample」クラス内部のメソッドだけが使います。そこで、Rubyのコードでもこれらのメソッドのスコープを「private」にしましょう。Rubyでは、「private」キーワードを追加してその後にメソッドを配置します。</p>
</div>
<div id="ruby_sample09" class="listingblock">
<div class="title">リスト 3.7 【Ruby】「ST1」の状態遷移のメソッドを作成する</div>
<div class="content">
<pre class="prettyprint highlight"><code data-lang="ruby">class Sample
# initialize、play、st0_proc、st1_proc の定義を省略
praivate <i class="conum" data-value="1"></i><b>(1)</b>
def act1(evt, prm)
puts " act1: event:#{evt}, param: #{prm}"
end
def act2(evt, prm)
puts " act2: event:#{evt}, param: #{prm}"
end
def act3(evt, prm)
puts " act3: event:#{evt}, param: #{prm}"