Skip to content

Commit 761c556

Browse files
authored
Merge pull request #312 from smalruby/adr-stop-self-when
docs: add adr - Stop using self.when, don't use reserve words
2 parents eb3eee0 + 05668c1 commit 761c556

File tree

3 files changed

+265
-0
lines changed

3 files changed

+265
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
# Stop using self.when, don't use reserve words
2+
3+
- User Story: smalruby/smalruby3-gui#309
4+
- Status: accepted
5+
- Deciders: takaokouji
6+
- Date: 2023-01-02T05:05:45:29+0900
7+
8+
Sorry, this is written in Japanese.
9+
10+
# self.whenからself.を取り除いたRubyの命令を検討する
11+
12+
イベントカテゴリの `フラグが押されたとき` 、 `[スペース▼]キーが押されたとき` などの各種イベントに対応したブロック(以下、イベントブロック)は、`self.when(:flag_clicked) do ~ end` のように Ruby では `Sprite#when` メソッドにマッピングされる。
13+
14+
```ruby
15+
# フラグが押されたとき
16+
self.when(:flag_clicked) do
17+
end
18+
19+
# [スペース▼]キーが押されたとき
20+
self.when(:key_pressed, "space") do
21+
end
22+
23+
# [音量▼] > (10) のとき
24+
self.when(:greater_than, "loudness", 10) do
25+
end
26+
```
27+
28+
`self.when` には次の課題がある。
29+
30+
- Ruby では、publicなメソッドの呼び出しは通常は `self.` を省略するが、`when` は予約語であるため、常に `self.` を記述する必要がある
31+
- Ruby では、予約語をメソッド名に使うことはできるが、それを推奨するといった説明はどこにもない
32+
33+
イベントブロックは多用されるため、これが不自然なものであれば、スモウルビーを通じてRubyの文法を学習するときに問題となることを懸念している。
34+
35+
そこで、イベントブロックから Ruby の命令へのマッピングとして `self.when` ではない別の選択肢を検討する。
36+
37+
## 判断基準や制限
38+
39+
* Rubyの文法を自然に学べること
40+
* Rubyの初学者に受け入れられるように入門書で扱うRubyの文法や仕組みを使うこと
41+
* 現状の「予約語 when を上書きする」というのは中級者以上を想定したものだと認識している
42+
* ブロックとRubyの相互変換処理の実装が簡単であること
43+
* 前後の状態に依存したものは実装が大変
44+
* 文字のタイプ数が少ないこと
45+
* 記号のタイプ数が少ないこと
46+
* ブロックの英語表現に似たRubyの命令であること
47+
48+
## 選択肢
49+
50+
* `when_%event_type%(%args%)`
51+
* `When(:%event_type%, %args%)`
52+
* `_when(:%event_type%, %args%)`
53+
* `on(:%event_type%, %args%)`
54+
55+
## 決定
56+
57+
**採用:** `when_%event_type%(%args%)`
58+
59+
```ruby
60+
# フラグが押されたとき
61+
when_flag_clicked do
62+
end
63+
64+
# [スペース▼]キーが押されたとき
65+
when_key_pressed("space") do
66+
end
67+
68+
# [音量▼] > (10) のとき
69+
when_greater_than("loudness", 10) do # 省略形 when_gt(...)
70+
end
71+
```
72+
73+
* `on(:%event_type%, %args%)` と迷った
74+
* 決め手は「メソッド名がブロックの英語表現と類似している」こと
75+
* スモウルビーは、先生やメンターなどの指導者がいない状況でRubyの文法を学ぶことを想定しているため、ブロックを英語(English)表記にするだけでRubyの文法をほとんど学べている、というのは魅力的
76+
77+
## 各選択肢の良い点と悪い点
78+
79+
### `when_%event_type%(%args%)`
80+
81+
```ruby
82+
# フラグが押されたとき
83+
when_flag_clicked do
84+
end
85+
86+
# [スペース▼]キーが押されたとき
87+
when_key_pressed("space") do
88+
end
89+
90+
# [音量▼] > (10) のとき
91+
when_greater_than("loudness", 10) do # 省略形 when_gt(...)
92+
end
93+
```
94+
95+
* `+` 増えた記号が `_` で減った記号が `:` なので+-0
96+
* `+` `self.`分、タイプ数が減る
97+
* `+` メソッド名がブロックの英語表現と類似している
98+
* ただし、引数まで考慮すると違和感がある。`when [loudness▼] > 10` が `when_greater_than("loudness", 10) do`
99+
* `+` メソッドが分かれるのでRubyからブロックへの変換処理の実装が簡単になる
100+
* `-` メソッドが増える
101+
* `self.when` の場合は `when` メソッドのみだった
102+
103+
### `When(:%event_type%, %args%)`
104+
105+
```ruby
106+
# フラグが押されたとき
107+
When(:flag_clicked) do
108+
end
109+
110+
# [スペース▼]キーが押されたとき
111+
When(:key_pressed, "space") do
112+
end
113+
114+
# [音量▼] > (10) のとき
115+
When(:greater_than, "loudness", 10) do
116+
end
117+
```
118+
119+
* `+` `self.` を記述しなくてよい
120+
* `+` `self.when` からの変更が少ない
121+
* `-` Ruby にはメソッド名を大文字から始める習慣がないため、Rubyの初学者に誤った知識を与える可能性がある
122+
* `-` Rubyの初学者がまったく動作の異なる予約語 `when` をこの When メソッドだと勘違いして覚えてしまう可能性がある
123+
124+
### `_when(:%event_type%, %args%)`
125+
126+
```ruby
127+
# フラグが押されたとき
128+
_when(:flag_clicked) do
129+
end
130+
131+
# [スペース▼]キーが押されたとき
132+
_when(:key_pressed, "space") do
133+
end
134+
135+
# [音量▼] > (10) のとき
136+
_when(:greater_than, "loudness", 10) do
137+
end
138+
```
139+
140+
* `+` `self.` を記述しなくてよい
141+
* `+` `self.when` からの変更が少ない
142+
* `-` ( `When` と同様に ) Ruby にはメソッド名を `_` から始める習慣がないため、Rubyの初学者に誤った知識を与える可能性がある
143+
* `-` ( `When` と同様に ) Rubyの初学者がまったく動作の異なる予約語 `when` をこの When メソッドだと勘違いして覚えてしまう可能性がある
144+
145+
### `on(:%event_type%, %args%)`
146+
147+
```ruby
148+
# フラグが押されたとき
149+
on(:flag_clicked) do
150+
end
151+
152+
# [スペース▼]キーが押されたとき
153+
on(:key_pressed, "space") do
154+
end
155+
156+
# [音量▼] > (10) のとき
157+
on(:greater_than, "loudness", 10) do
158+
end
159+
```
160+
161+
* `+` `self.` を記述しなくてよい
162+
* `+` `self.when` からの変更が少ない
163+
* `+` `on` はイベントハンドラとして違和感がないメソッド名である
164+
- Rubyだけでなく各種言語やライブラリでこのような用途として使われているという実績がある
165+
* `+` タイプ数が少ない
166+
* `-` メソッド名がブロックの英語表現とは異なる
167+
* ブロックの英語表現は、 `when :flags: clicked` 、 `when [loudness▼] > 10` など。

docs/adr/template.ja.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# *[課題と解決案を簡潔に表した英語のタイトル]*
2+
3+
- User Story: *[smalruby/%xxx%#issue-number]* <!-- optional -->
4+
- Status: *[proposed | rejected | accepted | deprecated | superseded by]*
5+
- Deciders: *[Decider's GitHub account names]* <!-- optional -->
6+
- Date: *[YYYY-MM-DD(THH:MM:SSTZ)]*
7+
8+
Sorry, this is written in Japanese.
9+
10+
# *[課題と解決案を簡潔に表した日本語のタイトル]*
11+
12+
*[ここには背景と課題の説明を記述します]*
13+
14+
## 判断基準や制限
15+
16+
*[ここには解決案を判断するための基準や制限を箇条書きで記述します]*
17+
18+
## 選択肢
19+
20+
* *[選択肢1]*
21+
* *[選択肢2]* <!-- 選択肢は1つでも構いません。良い点と悪い点を言語するために使ってください -->
22+
* *[選択肢3]*
23+
* *[...]* <!-- 選択肢は適宜加減してください -->
24+
25+
## 決定
26+
27+
**採用:** *[選択肢1]*
28+
29+
* *[これとそれを迷ったけど、XXXという理由でこっちのほうがよかったとか、際どい選択のときに説明を記述する。そうではなく、自明な場合は説明は不要]*
30+
* *[選択した結果で、解決できていないことがあれば今後の課題とするためにここに記述しておく。]* <!-- optional -->
31+
32+
## 各選択肢の良い点と悪い点
33+
34+
### *[選択肢1]*
35+
36+
* `+` *[良い点1]*
37+
* `+` *[良い点2]*
38+
* `-` *[悪い点1]*
39+
* *[...]* <!-- 良い点と悪い点は適宜加減してください -->
40+
41+
### *[選択肢2]*
42+
43+
* `+` *[良い点1]*
44+
* `+` *[良い点2]*
45+
* `-` *[悪い点1]*
46+
* *[...]* <!-- 良い点と悪い点は適宜加減してください -->
47+
48+
### *[選択肢3]*
49+
50+
* `+` *[良い点1]*
51+
* `+` *[良い点2]*
52+
* `-` *[悪い点1]*
53+
* *[...]* <!-- 良い点と悪い点は適宜加減してください -->

docs/adr/template.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# *[short title of solved problem and solution]*
2+
3+
- User Story: *[smalruby/%xxx%#issue-number]* <!-- optional -->
4+
- Status: *[proposed | rejected | accepted | deprecated | superseded by]*
5+
- Deciders: *[Decider's GitHub account names]* <!-- optional -->
6+
- Date: *[YYYY-MM-DD(THH:MM:SSTZ)]*
7+
8+
*[context and problem statement]*
9+
*[decision drivers | forces]* <!-- optional -->
10+
11+
## Considered Alternatives
12+
13+
* *[alternative 1]*
14+
* *[alternative 2]*
15+
* *[alternative 3]*
16+
* *[...]* <!-- numbers of alternatives can vary -->
17+
18+
## Decision Outcome
19+
20+
* Chosen Alternative: *[alternative 1]*
21+
* *[justification. e.g., only alternative, which meets k.o. criterion decision driver | which resolves force force | ... | comes out best (see below)]*
22+
* *[consequences. e.g., negative impact on quality attribute, follow-up decisions required, ...]* <!-- optional -->
23+
24+
## Pros and Cons of the Alternatives <!-- optional -->
25+
26+
### *[alternative 1]*
27+
28+
* `+` *[argument 1 pro]*
29+
* `+` *[argument 2 pro]*
30+
* `-` *[argument 1 con]*
31+
* *[...]* <!-- numbers of pros and cons can vary -->
32+
33+
### *[alternative 2]*
34+
35+
* `+` *[argument 1 pro]*
36+
* `+` *[argument 2 pro]*
37+
* `-` *[argument 1 con]*
38+
* *[...]* <!-- numbers of pros and cons can vary -->
39+
40+
### *[alternative 3]*
41+
42+
* `+` *[argument 1 pro]*
43+
* `+` *[argument 2 pro]*
44+
* `-` *[argument 1 con]*
45+
* *[...]* <!-- numbers of pros and cons can vary -->

0 commit comments

Comments
 (0)