[Notice] Announcing the End of Demo Server [Read me]

milestone: Calculate numbers just in time.
Milestone has stored many calcaulted values (e.g. number of open issues) persistently in database and it causes many problems. They should be calcultaed just in time. Also remove many lines of codes because this fix eliminates the needs.
@57b8cc7b98a8eb4d620bdcc1ff41442cecd63e7a
--- app/controllers/MilestoneApp.java
+++ app/controllers/MilestoneApp.java
... | ... | @@ -38,9 +38,6 @@ |
38 | 38 |
mCondition.sort, |
39 | 39 |
Direction.getValue(mCondition.direction)); |
40 | 40 |
|
41 |
- for(Milestone milestone: milestones) { |
|
42 |
- milestone.updateIssueInfo(); |
|
43 |
- } |
|
44 | 41 |
return ok(list.render("title.milestoneList", milestones, project, mCondition)); |
45 | 42 |
} |
46 | 43 |
|
... | ... | @@ -105,7 +102,6 @@ |
105 | 102 |
} else { |
106 | 103 |
Milestone existingMilestone = Milestone.findById(milestoneId); |
107 | 104 |
existingMilestone.updateWith(milestoneForm.get()); |
108 |
- Milestone.update(existingMilestone, milestoneId); |
|
109 | 105 |
return redirect(routes.MilestoneApp.manageMilestones(userName, projectName)); |
110 | 106 |
} |
111 | 107 |
} |
--- app/models/Issue.java
+++ app/models/Issue.java
... | ... | @@ -196,10 +196,6 @@ |
196 | 196 |
*/ |
197 | 197 |
public static Long create(Issue issue) { |
198 | 198 |
issue.save(); |
199 |
- if (issue.milestoneId != null) { |
|
200 |
- Milestone milestone = Milestone.findById(issue.milestoneId); |
|
201 |
- milestone.add(issue); |
|
202 |
- } |
|
203 | 199 |
return issue.id; |
204 | 200 |
} |
205 | 201 |
|
... | ... | @@ -210,10 +206,6 @@ |
210 | 206 |
*/ |
211 | 207 |
public static void delete(Long id) { |
212 | 208 |
Issue issue = finder.byId(id); |
213 |
- if (issue.milestoneId != null && !issue.milestoneId.equals(0l)) { |
|
214 |
- Milestone milestone = Milestone.findById(issue.milestoneId); |
|
215 |
- milestone.delete(issue); |
|
216 |
- } |
|
217 | 209 |
issue.delete(); |
218 | 210 |
} |
219 | 211 |
|
--- app/models/Milestone.java
+++ app/models/Milestone.java
... | ... | @@ -35,11 +35,6 @@ |
35 | 35 |
@Constraints.Required |
36 | 36 |
public State state; |
37 | 37 |
|
38 |
- public int numClosedIssues; |
|
39 |
- public int numOpenIssues; |
|
40 |
- public int numTotalIssues; |
|
41 |
- public int completionRate; |
|
42 |
- |
|
43 | 38 |
@ManyToOne |
44 | 39 |
public Project project; |
45 | 40 |
|
... | ... | @@ -47,18 +42,20 @@ |
47 | 42 |
milestone.save(); |
48 | 43 |
} |
49 | 44 |
|
50 |
- public static void update(Milestone milestone, Long id) { |
|
51 |
- int completionRate = 0; |
|
52 |
- if (milestone.numTotalIssues != 0) { |
|
53 |
- completionRate = |
|
54 |
- calculateCompletionRate(milestone.numTotalIssues, milestone.numClosedIssues); |
|
55 |
- } |
|
56 |
- milestone.completionRate = completionRate; |
|
57 |
- milestone.update(id); |
|
45 |
+ public int getNumClosedIssues() { |
|
46 |
+ return Issue.finder.where().eq("milestoneId", this.id).eq("state", State.CLOSED).findRowCount(); |
|
58 | 47 |
} |
59 | 48 |
|
60 |
- private static int calculateCompletionRate(int numTotalIssues, int numClosedIssues) { |
|
61 |
- return new Double(((double) numClosedIssues / (double) numTotalIssues) * 100).intValue(); |
|
49 |
+ public int getNumOpenIssues() { |
|
50 |
+ return Issue.finder.where().eq("milestoneId", this.id).eq("state", State.OPEN).findRowCount(); |
|
51 |
+ } |
|
52 |
+ |
|
53 |
+ public int getNumTotalIssues() { |
|
54 |
+ return Issue.findByMilestoneId(this.id).size(); |
|
55 |
+ } |
|
56 |
+ |
|
57 |
+ public int getCompletionRate() { |
|
58 |
+ return new Double(((double) getNumClosedIssues() / (double) getNumTotalIssues()) * 100).intValue(); |
|
62 | 59 |
} |
63 | 60 |
|
64 | 61 |
public static void delete(Milestone milestone) { |
... | ... | @@ -162,55 +159,5 @@ |
162 | 159 |
options.put(milestone.id.toString(), milestone.title); |
163 | 160 |
} |
164 | 161 |
return options; |
165 |
- } |
|
166 |
- |
|
167 |
- public void add(Issue issue) { |
|
168 |
- findIssuesNUpdateTotalCount(); |
|
169 |
- checkIssueState(issue, 1); |
|
170 |
- this._save(); |
|
171 |
- } |
|
172 |
- |
|
173 |
- public void updateIssueInfo() { |
|
174 |
- List<Issue> issues = findIssuesNUpdateTotalCount(); |
|
175 |
- |
|
176 |
- this.numOpenIssues = 0; |
|
177 |
- this.numClosedIssues = 0; |
|
178 |
- |
|
179 |
- for (Issue issue : issues) { |
|
180 |
- checkIssueState(issue, 1); |
|
181 |
- } |
|
182 |
- |
|
183 |
- this.completionRate = calculateCompletionRate(this.numTotalIssues, this.numClosedIssues); |
|
184 |
- update(this.id); |
|
185 |
- } |
|
186 |
- |
|
187 |
- public void delete(Issue issue) { |
|
188 |
- this.numTotalIssues -= 1; |
|
189 |
- checkIssueState(issue, -1); |
|
190 |
- this._save(); |
|
191 |
- } |
|
192 |
- |
|
193 |
- private void checkIssueState(Issue issue, int count) { |
|
194 |
- if (issue.isOpen()) { |
|
195 |
- this.numOpenIssues += count; |
|
196 |
- } else { |
|
197 |
- this.numClosedIssues += count; |
|
198 |
- } |
|
199 |
- } |
|
200 |
- |
|
201 |
- private void _save() { |
|
202 |
- this.completionRate = calculateCompletionRate(this.numTotalIssues, this.numClosedIssues); |
|
203 |
- this.save(); |
|
204 |
- } |
|
205 |
- |
|
206 |
- /** |
|
207 |
- * 마일스톤에 연결된 이슈들을 찾아주며 해당 마일스톤에 할당된 이슈의 총 갯수를 update 해준다. |
|
208 |
- * |
|
209 |
- * @return |
|
210 |
- */ |
|
211 |
- private List<Issue> findIssuesNUpdateTotalCount() { |
|
212 |
- List<Issue> issues = Issue.findByMilestoneId(this.id); |
|
213 |
- this.numTotalIssues = issues.size(); |
|
214 |
- return issues; |
|
215 | 162 |
} |
216 | 163 |
} |
--- app/views/milestone/list.scala.html
+++ app/views/milestone/list.scala.html
... | ... | @@ -84,20 +84,20 @@ |
84 | 84 |
</div> |
85 | 85 |
<div class="progress-wrap"> |
86 | 86 |
<div class="progress"> |
87 |
- <div class="bar orange" style="width: @milestone.completionRate%;"></div> |
|
87 |
+ <div class="bar orange" style="width: @milestone.getCompletionRate%;"></div> |
|
88 | 88 |
</div> |
89 | 89 |
<div class="pull-left"> |
90 |
- <a href="@makeIssuesLink(milestone.id,"closed")">완료 @milestone.numClosedIssues (@milestone.completionRate%)</a> |
|
90 |
+ <a href="@makeIssuesLink(milestone.id,"closed")">완료 @milestone.getNumClosedIssues (@milestone.getCompletionRate%)</a> |
|
91 | 91 |
</div> |
92 | 92 |
<div class="pull-right"> |
93 |
- <a href="@makeIssuesLink(milestone.id,"open")">미완료 @milestone.numOpenIssues (@{100 - milestone.completionRate}%)</a> |
|
93 |
+ <a href="@makeIssuesLink(milestone.id,"open")">미완료 @milestone.getNumOpenIssues (@{100 - milestone.getCompletionRate}%)</a> |
|
94 | 94 |
</div> |
95 | 95 |
</div> |
96 | 96 |
<div class="desc"> |
97 | 97 |
@milestone.contents |
98 | 98 |
</div> |
99 | 99 |
</div> |
100 |
- <div class="completion-rate @if(milestone.completionRate == 100){done}">@milestone.completionRate%</div> |
|
100 |
+ <div class="completion-rate @if(milestone.getCompletionRate == 100){done}">@milestone.getCompletionRate%</div> |
|
101 | 101 |
</li> |
102 | 102 |
} |
103 | 103 |
</ul> |
--- conf/initial-data.yml
+++ conf/initial-data.yml
... | ... | @@ -293,10 +293,6 @@ |
293 | 293 |
dueDate: 2012-07-12 10:59:59 |
294 | 294 |
contents: nFORGE 첫번째 버전. |
295 | 295 |
state: OPEN |
296 |
- numClosedIssues: 2 |
|
297 |
- numOpenIssues: 2 |
|
298 |
- numTotalIssues: 4 |
|
299 |
- completionRate: 50 |
|
300 | 296 |
project: !!models.Project |
301 | 297 |
id: 1 |
302 | 298 |
- !!models.Milestone |
... | ... | @@ -304,10 +300,6 @@ |
304 | 300 |
dueDate: 2012-07-19 10:59:59 |
305 | 301 |
contents: nFORGE 두번째 버전 (Stable). |
306 | 302 |
state: OPEN |
307 |
- numClosedIssues: 2 |
|
308 |
- numOpenIssues: 1 |
|
309 |
- numTotalIssues: 3 |
|
310 |
- completionRate: 66 |
|
311 | 303 |
project: !!models.Project |
312 | 304 |
id: 1 |
313 | 305 |
- !!models.Milestone |
... | ... | @@ -315,10 +307,6 @@ |
315 | 307 |
dueDate: 2011-08-10 10:59:59 |
316 | 308 |
contents: Jindo 안정화 버전 |
317 | 309 |
state: CLOSED |
318 |
- numClosedIssues: 2 |
|
319 |
- numOpenIssues: 0 |
|
320 |
- numTotalIssues: 2 |
|
321 |
- completionRate: 100 |
|
322 | 310 |
project: !!models.Project |
323 | 311 |
id: 2 |
324 | 312 |
- !!models.Milestone |
... | ... | @@ -326,10 +314,6 @@ |
326 | 314 |
dueDate: 2012-04-11 10:59:59 |
327 | 315 |
contents: Jindo2 |
328 | 316 |
state: OPEN |
329 |
- numClosedIssues: 0 |
|
330 |
- numOpenIssues: 3 |
|
331 |
- numTotalIssues: 3 |
|
332 |
- completionRate: 0 |
|
333 | 317 |
project: !!models.Project |
334 | 318 |
id: 2 |
335 | 319 |
- !!models.Milestone |
... | ... | @@ -337,10 +321,6 @@ |
337 | 321 |
dueDate: 2012-12-31 10:59:59 |
338 | 322 |
contents: CUBRID v.0.1 |
339 | 323 |
state: OPEN |
340 |
- numClosedIssues: 1 |
|
341 |
- numOpenIssues: 1 |
|
342 |
- numTotalIssues: 2 |
|
343 |
- completionRate: 50 |
|
344 | 324 |
project: !!models.Project |
345 | 325 |
id: 3 |
346 | 326 |
- !!models.Milestone |
... | ... | @@ -348,10 +328,6 @@ |
348 | 328 |
dueDate: 2013-11-09 10:59:59 |
349 | 329 |
contents: CUBRID v.0.2 |
350 | 330 |
state: CLOSED |
351 |
- numClosedIssues: 1 |
|
352 |
- numOpenIssues: 0 |
|
353 |
- numTotalIssues: 1 |
|
354 |
- completionRate: 100 |
|
355 | 331 |
project: !!models.Project |
356 | 332 |
id: 3 |
357 | 333 |
|
--- test/models/MilestoneTest.java
+++ test/models/MilestoneTest.java
... | ... | @@ -18,13 +18,11 @@ |
18 | 18 |
newMilestone.dueDate = new Date(); |
19 | 19 |
newMilestone.contents = "테스트 마일스톤"; |
20 | 20 |
newMilestone.project = Project.find.byId(1l); |
21 |
- newMilestone.numClosedIssues = 0; |
|
22 |
- newMilestone.numOpenIssues = 0; |
|
23 |
- newMilestone.numTotalIssues = 0; |
|
24 | 21 |
newMilestone.title = "0.1"; |
25 |
- newMilestone.completionRate = 0; |
|
22 |
+ |
|
26 | 23 |
// When |
27 | 24 |
Milestone.create(newMilestone); |
25 |
+ |
|
28 | 26 |
// Then |
29 | 27 |
assertThat(newMilestone.id).isNotNull(); |
30 | 28 |
} |
... | ... | @@ -51,11 +49,11 @@ |
51 | 49 |
assertThat(expactDueDate.get(Calendar.DAY_OF_MONTH)).isEqualTo( |
52 | 50 |
dueDate.get(Calendar.DAY_OF_MONTH)); |
53 | 51 |
|
54 |
- assertThat(firstMilestone.numClosedIssues).isEqualTo(2); |
|
55 |
- assertThat(firstMilestone.numOpenIssues).isEqualTo(2); |
|
56 |
- assertThat(firstMilestone.numTotalIssues).isEqualTo(4); |
|
52 |
+ assertThat(firstMilestone.getNumClosedIssues()).isEqualTo(2); |
|
53 |
+ assertThat(firstMilestone.getNumOpenIssues()).isEqualTo(2); |
|
54 |
+ assertThat(firstMilestone.getNumTotalIssues()).isEqualTo(4); |
|
57 | 55 |
assertThat(firstMilestone.project).isEqualTo(Project.find.byId(1l)); |
58 |
- assertThat(firstMilestone.completionRate).isEqualTo(50); |
|
56 |
+ assertThat(firstMilestone.getCompletionRate()).isEqualTo(50); |
|
59 | 57 |
} |
60 | 58 |
|
61 | 59 |
@Test |
... | ... | @@ -63,6 +61,7 @@ |
63 | 61 |
// Given |
64 | 62 |
Milestone firstMilestone = Milestone.findById(1l); |
65 | 63 |
assertThat(firstMilestone).isNotNull(); |
64 |
+ |
|
66 | 65 |
// When |
67 | 66 |
Milestone.delete(firstMilestone); |
68 | 67 |
flush(); |
... | ... | @@ -70,29 +69,6 @@ |
70 | 69 |
//Then |
71 | 70 |
firstMilestone = Milestone.findById(1l); |
72 | 71 |
assertThat(firstMilestone).isNull(); |
73 |
- } |
|
74 |
- |
|
75 |
- @Test |
|
76 |
- public void update() throws Exception { |
|
77 |
- // Given |
|
78 |
- Milestone updateMilestone = new Milestone(); |
|
79 |
- updateMilestone.contents = "엔포지 첫번째 버전."; |
|
80 |
- updateMilestone.title = "1.0.0-SNAPSHOT"; |
|
81 |
- updateMilestone.numClosedIssues = 10; |
|
82 |
- updateMilestone.numOpenIssues = 1; |
|
83 |
- updateMilestone.numTotalIssues = 11; |
|
84 |
- |
|
85 |
- // When |
|
86 |
- Milestone.update(updateMilestone, 2l); |
|
87 |
- // Then |
|
88 |
- Milestone actualMilestone = Milestone.findById(2l); |
|
89 |
- assertThat(actualMilestone.contents) |
|
90 |
- .isEqualTo(updateMilestone.contents); |
|
91 |
- assertThat(actualMilestone.title).isEqualTo(updateMilestone.title); |
|
92 |
- assertThat(actualMilestone.numClosedIssues).isEqualTo(10); |
|
93 |
- assertThat(actualMilestone.numOpenIssues).isEqualTo(1); |
|
94 |
- assertThat(actualMilestone.numTotalIssues).isEqualTo(11); |
|
95 |
- assertThat(actualMilestone.completionRate).isEqualTo(90); |
|
96 | 72 |
} |
97 | 73 |
|
98 | 74 |
@Test |
... | ... | @@ -174,21 +150,6 @@ |
174 | 150 |
State.ALL); |
175 | 151 |
// Then |
176 | 152 |
assertThat(p2Milestones.size()).isEqualTo(2); |
177 |
- |
|
178 |
- // Given |
|
179 |
- // When |
|
180 |
- List<Milestone> p1MilestonesASCDirection = Milestone.findMilestones(1l, |
|
181 |
- State.ALL, "completionRate", Direction.ASC); |
|
182 |
- // Then |
|
183 |
- assertThat(p1MilestonesASCDirection.get(0).completionRate).isEqualTo(50); |
|
184 |
- |
|
185 |
- // Given |
|
186 |
- // When |
|
187 |
- List<Milestone> p2MilestonesDESCDirection = Milestone.findMilestones( |
|
188 |
- 2l, State.ALL, "completionRate", Direction.DESC); |
|
189 |
- // Then |
|
190 |
- assertThat(p2MilestonesDESCDirection.get(0).completionRate).isEqualTo( |
|
191 |
- 100); |
|
192 | 153 |
} |
193 | 154 |
|
194 | 155 |
@Test |
... | ... | @@ -221,8 +182,8 @@ |
221 | 182 |
public void addIssue() throws Exception { |
222 | 183 |
// GIVEN |
223 | 184 |
Milestone m5 = Milestone.findById(5l); |
224 |
- int totalNumber = m5.numTotalIssues; |
|
225 |
- int openNumber = m5.numOpenIssues; |
|
185 |
+ int totalNumber = m5.getNumTotalIssues(); |
|
186 |
+ int openNumber = m5.getNumOpenIssues(); |
|
226 | 187 |
Issue issue = new Issue("불필요한 로그 출력 코드 제거test"); |
227 | 188 |
issue.date = JodaDateUtil.today(); |
228 | 189 |
issue.state = State.OPEN; |
... | ... | @@ -234,8 +195,8 @@ |
234 | 195 |
|
235 | 196 |
// THEN |
236 | 197 |
m5 = Milestone.findById(5l); |
237 |
- assertThat(m5.numTotalIssues).isEqualTo(totalNumber + 1); |
|
238 |
- assertThat(m5.numOpenIssues).isEqualTo(openNumber + 1); |
|
198 |
+ assertThat(m5.getNumTotalIssues()).isEqualTo(totalNumber + 1); |
|
199 |
+ assertThat(m5.getNumOpenIssues()).isEqualTo(openNumber + 1); |
|
239 | 200 |
} |
240 | 201 |
|
241 | 202 |
@Test |
... | ... | @@ -243,25 +204,23 @@ |
243 | 204 |
//Given |
244 | 205 |
Issue issue = new Issue("불필요한 로그 출력 코드 제거test"); |
245 | 206 |
issue.milestoneId = 6l; |
246 |
- issue.update(5l); |
|
247 |
- |
|
248 | 207 |
Long milestoneId = issue.milestoneId; |
249 | 208 |
Milestone m6 = Milestone.findById(milestoneId); |
250 |
- assertThat(m6.numOpenIssues).isEqualTo(0); |
|
251 |
- assertThat(m6.numClosedIssues).isEqualTo(1); |
|
252 |
- assertThat(m6.numTotalIssues).isEqualTo(1); |
|
253 |
- assertThat(m6.completionRate).isEqualTo(100); |
|
209 |
+ assertThat(m6.getNumOpenIssues()).isEqualTo(0); |
|
210 |
+ assertThat(m6.getNumClosedIssues()).isEqualTo(1); |
|
211 |
+ assertThat(m6.getNumTotalIssues()).isEqualTo(1); |
|
212 |
+ assertThat(m6.getCompletionRate()).isEqualTo(100); |
|
254 | 213 |
|
255 | 214 |
//When |
256 |
- m6.updateIssueInfo(); |
|
215 |
+ issue.update(5l); |
|
257 | 216 |
flush(); |
258 | 217 |
|
259 | 218 |
//Then |
260 | 219 |
m6 = Milestone.findById(milestoneId); |
261 |
- assertThat(m6.numOpenIssues).isEqualTo(1); |
|
262 |
- assertThat(m6.numClosedIssues).isEqualTo(1); |
|
263 |
- assertThat(m6.numTotalIssues).isEqualTo(2); |
|
264 |
- assertThat(m6.completionRate).isEqualTo(50); |
|
220 |
+ assertThat(m6.getNumOpenIssues()).isEqualTo(1); |
|
221 |
+ assertThat(m6.getNumClosedIssues()).isEqualTo(1); |
|
222 |
+ assertThat(m6.getNumTotalIssues()).isEqualTo(2); |
|
223 |
+ assertThat(m6.getCompletionRate()).isEqualTo(50); |
|
265 | 224 |
} |
266 | 225 |
|
267 | 226 |
@Test |
... | ... | @@ -269,19 +228,18 @@ |
269 | 228 |
//Given |
270 | 229 |
Issue issue = Issue.findById(7l); |
271 | 230 |
Milestone m5 = Milestone.findById(issue.milestoneId); |
272 |
- assertThat(m5.numOpenIssues).isEqualTo(1); |
|
273 |
- assertThat(m5.numClosedIssues).isEqualTo(1); |
|
274 |
- assertThat(m5.numTotalIssues).isEqualTo(2); |
|
275 |
- assertThat(m5.completionRate).isEqualTo(50); |
|
231 |
+ assertThat(m5.getNumOpenIssues()).isEqualTo(1); |
|
232 |
+ assertThat(m5.getNumClosedIssues()).isEqualTo(1); |
|
233 |
+ assertThat(m5.getNumTotalIssues()).isEqualTo(2); |
|
234 |
+ assertThat(m5.getCompletionRate()).isEqualTo(50); |
|
276 | 235 |
|
277 | 236 |
//When |
278 | 237 |
issue.delete(); |
279 |
- m5.delete(issue); |
|
280 | 238 |
|
281 | 239 |
//Then |
282 |
- assertThat(m5.numOpenIssues).isEqualTo(0); |
|
283 |
- assertThat(m5.numClosedIssues).isEqualTo(1); |
|
284 |
- assertThat(m5.numTotalIssues).isEqualTo(1); |
|
285 |
- assertThat(m5.completionRate).isEqualTo(100); |
|
240 |
+ assertThat(m5.getNumOpenIssues()).isEqualTo(0); |
|
241 |
+ assertThat(m5.getNumClosedIssues()).isEqualTo(1); |
|
242 |
+ assertThat(m5.getNumTotalIssues()).isEqualTo(1); |
|
243 |
+ assertThat(m5.getCompletionRate()).isEqualTo(100); |
|
286 | 244 |
} |
287 |
-} |
|
245 |
+}(No newline at end of file) |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?