回答編集履歴

1

汎用性

2017/10/01 09:26

投稿

think49
think49

スコア18162

test CHANGED
@@ -1,3 +1,7 @@
1
+ ### 静的関数
2
+
3
+
4
+
1
5
  また、「リファクタリングを求めているわけではないのでコードを書く必要性を感じません」といわれそうですが、ケースバイケースだと思うので、コードを出してほしいと思います。
2
6
 
3
7
  コードを出せば、前提条件を後出しする事がないからです。
@@ -10,9 +14,9 @@
10
14
 
11
15
  ```JavaScript
12
16
 
13
- function addComma (num) {
17
+ function addComma (numberString) {
14
18
 
15
- return num.split(/(?=(?:\d{3})+$)/).join();
19
+ return numberString.split(/(?=(?:\d{3})+$)/).join();
16
20
 
17
21
  }
18
22
 
@@ -24,4 +28,158 @@
24
28
 
25
29
 
26
30
 
31
+ ### 汎用性
32
+
33
+
34
+
35
+ 2017/10/01 16:21の変更を受けて追記します。
36
+
37
+ 関数名が変更(addComma -> asValueSeparatedByComma) されていますが、そこは重要ではなく、addComma では存在した仮引数 `value` がなくなっています。
38
+
39
+ 変更前の addComma では静的関数を予想させるコードでしたが、`this.value` に依存するメソッドへ変質したことで状況は大きく変わりました。
40
+
41
+
42
+
43
+ 共通処理のメンテナンスコストを下げるには共通処理を外へ追い出す必要があります。
44
+
45
+ 共通処理を外へ追い出すという事は**依存関係が出来る**という事です。
46
+
47
+ どうやっても依存関係が出来るのなら、「汎用性が高い方法」を採用するのがベストだと考えます。
48
+
49
+
50
+
51
+ 一つは、**参照透過性**です。
52
+
53
+ ご質問のコードでは `this.value` に依存している為、参照透過性がないコードですが、`this.foo` でも `this.piyo` でも再利用できるコードが好ましいでしょう。
54
+
55
+
56
+
57
+ ```JavaScript
58
+
59
+ 'use strict';
60
+
61
+ function insertCommaDelimiter (numberString) {
62
+
63
+ return String(numberString).replace(/(\d+)(.\d+)?/, function (subString, capture1, capture2) {
64
+
65
+ capture1 = capture1.split(/(?=(?:\d{3})+$)/).join();
66
+
67
+ return capture2 ? capture1 + capture2.replace(/(\d{3})(?=\d)/, '$1,') : capture1;
68
+
69
+ });
70
+
71
+ }
72
+
73
+
74
+
75
+ class AAA {
76
+
77
+ constructor (value) {
78
+
79
+ this.value = value;
80
+
81
+ }
82
+
83
+
84
+
85
+ asValueSeparatedByComma () {
86
+
87
+ return insertCommaDelimiter(this.value);
88
+
89
+ }
90
+
91
+ }
92
+
93
+
94
+
95
+ class BBB {
96
+
97
+ constructor (foo) {
98
+
99
+ this.foo = foo;
100
+
101
+ }
102
+
103
+
104
+
105
+ asValueSeparatedByComma () {
106
+
107
+ return insertCommaDelimiter(this.foo);
108
+
109
+ }
110
+
111
+ }
112
+
113
+
114
+
115
+ console.log(new AAA(12345678).asValueSeparatedByComma()); // "12,345,678"
116
+
117
+ console.log(new BBB('私の所持金額は43421円です。').asValueSeparatedByComma()); // "私の所持金額は43,421円です。"
118
+
119
+ ```
120
+
121
+
122
+
123
+ 更に汎用性を上げると、挿入されるデリミタはカンマでなくても良く、任意の文字数単位でデリミタを挿入できる設計が考えられます。
124
+
125
+
126
+
127
+ ```JavaScript
128
+
129
+ function insertDelimiterByNumberString (numberString, digit, delimiter) {
130
+
131
+ var digit = Number(digit),
132
+
133
+ integerPart = new RegExp('(?=(?:\d{' + digit + '})+$)'),
134
+
135
+ decimalPart = new RegExp('(\d{' + digit + '})(?=\d)', 'g'),
136
+
137
+ delimiter = arguments.length < 3 ? ',' : String(delimiter);
138
+
139
+
140
+
141
+ return String(numberString).replace(/(\d+)(.\d+)?/g, function (subString, capture1, capture2) {
142
+
143
+ capture1 = capture1.split(integerPart).join(delimiter);
144
+
145
+ return capture2 ? capture1 + capture2.replace(decimalPart, '$1,') : capture1;
146
+
147
+ });
148
+
149
+ }
150
+
151
+
152
+
153
+ console.log(insertDelimiterByNumberString(12345678.42133212, 3)); // "12,345,678.421,332,12"
154
+
155
+ console.log(insertDelimiterByNumberString(180012, 2, ':')); // "18:00:12"
156
+
157
+ ```
158
+
159
+
160
+
161
+ もう一つの方向性としては、汎用的なクラスを作る事です。
162
+
163
+ 例えば、moment.js は `Date` を操る事に特化したライブラリですが、カンマ区切りの数値を作る処理も何らかの汎用性の高いクラスの一部とします。
164
+
165
+ class AAA, class BBB は作った class との間に依存関係が出来ますが、汎用性が高いクラスであれば気にならないかもしれません。
166
+
167
+ ただし、この方法はたった一つの機能が欲しいがために重い class をインポートする事にも繋がるので、設計方針次第では採用しがたいと思います。
168
+
169
+
170
+
171
+ いずれにしても、再利用性を高める為には、可能な限り、**汎用性が高い設計**にする必要があると考えます。
172
+
173
+ 私の書いた例は一例に過ぎず、最終的には「汎用性をどの方向に追求するか」というポリシーの問題になります。
174
+
175
+
176
+
177
+ ### 更新履歴
178
+
179
+
180
+
181
+ - 2017/10/01 18:26 「汎用性」を追記
182
+
183
+
184
+
27
185
  Re: hayatomo さん