Thiết
kế chương trình hướng đối tượng
Center
of Excellence
Bài
6
Thẻ
Tín Dụng (Credit Card)
Điều
thường hằng duy nhất, đó là sự thay đổi
--
Heraclitus
I.
Bài toán
Để
có thể cấp thẻ tín dụng (credit card) cho khách hàng,
ngân hàng cần kiểm tra hai thông tin: lương hàng năm
(annual salary) và mức độ tín nhiệm (credit rating). Hãy
phát triển code nhận vào từ keyboard annual salary và credit
rating của một khách hàng, trong đó annual salary là một
số dương và credit rating là một số nguyên từ 1 (rất
tệ) đến 10 (rất được tín nhiệm), sau đó code sẽ cho
biết khách hàng có thể được cấp credit card hay không.
Biết rằng khách hàng cần thỏa mãn hai điều kiện:
annual salary tối thiểu là 20.000 USD và credit rating tối
thiểu bằng 7.
Bạn
không phải phát triển phần UI, nhưng để hiểu rõ hơn
yêu cầu bài toán, bạn có thể tham khảo một UI mẫu
dưới đây.
Hình
1
II.
Giải pháp
Tương
tự như bài trước, bài này yêu cầu ta thực hiện việc
nhập data rồi tính toán.
- Nhập annual salary (phải là số nguyên dương)
- Input: từ keyboard
- Output: annual salary
- Nhập credit rating (phải từ 1 đến 10)
- Input: từ keyboard
- Output: credit rating
- Kiểm tra khách hàng có được cấp credit card hay không
- Input: annual salary, credit rating
- Output: có (true) hoặc không (false)
1.
Nhập annual salary
1.1.
Thiết kế sơ bộ
Theo kinh nghiệm thiết kế ở bài trước, ta có thể có ba classes: Input class phục vụ việc nhập data, một class dùng để tính toán (tên class sẽ được quyết định sau, phụ thuộc vào yêu cầu tính toán), và Main class để thực hiện việc tích hợp nhằm tạo ra một chương trình hoàn chỉnh.
Theo kinh nghiệm thiết kế ở bài trước, ta có thể có ba classes: Input class phục vụ việc nhập data, một class dùng để tính toán (tên class sẽ được quyết định sau, phụ thuộc vào yêu cầu tính toán), và Main class để thực hiện việc tích hợp nhằm tạo ra một chương trình hoàn chỉnh.
Hình
2
1.2.
Test cases
readAnnualSalary()
|
||
No
|
input
từ keyboard
|
annualSalary?
|
1
|
30_000
|
30_000
|
2
|
20_000
|
20_000
|
3
|
10_000
|
10_000
|
4
|
0
|
không
chấp nhận
|
1.3.
Phát triển method
- Project: CreditCard
Biết
rằng bài này và bài trước đều có Input class, ta
cần xem xét khả năng tái dụng (reuse) Input class của
bài trước cho bài này được hay không.
Hình
3
Nhận
xét rằng readAnnualSalaryGui() rất giống với
readPlayersGui() (code duplication), vì vậy ta cần
refactor chúng. Hai methods này
có điểm chung là yêu cầu user nhập một số nguyên
dương, vì vậy ta có thể sát nhập chúng thành một
method, gọi là readPositiveIntGui().
Điểm khác biệt của hai methods là nội dung lời
nhắc (prompt), nên ta bổ sung
prompt
parameter cho method mới. Sau khi đã hoàn thành việc
xây dựng và kiểm thử method mới, ta có thể loại bỏ
hai methods cũ ra khỏi class.
Hình
4
Hình
5
2.
Nhập credit rating
2.1.
Thiết kế sơ bộ
Hình
6
Từ
kinh nghiệm của phần trước, ta có thể thử sát nhập
hai methods readPlayersPerTeamGui()
và readCreditRatingGui()
thành readIntGui()
với nhiều hơn một parameter, đó là prompt.
Hình
7
2.2.
Test cases
readIntGui()
|
||||
No
|
lowerBound
|
upperBound
|
input
từ keyboard
|
output?
|
1
|
9
|
15
|
8
|
không
chấp nhận
|
2
|
9
|
15
|
9
|
9
|
3
|
9
|
15
|
10
|
10
|
4
|
9
|
15
|
15
|
15
|
5
|
9
|
15
|
16
|
không
chấp nhận
|
6
|
1
|
10
|
0
|
không
chấp nhận
|
7
|
1
|
10
|
1
|
1
|
8
|
1
|
10
|
5
|
5
|
9
|
1
|
10
|
10
|
10
|
10
|
1
|
10
|
11
|
không
chấp nhận
|
2.3.
Phát triển method
Hình
8
Hình
9
3.
Kiểm tra khách hàng có được cấp credit card hay không
3.1.
Thiết kế sơ bộ
Hình
10
3.2.
Test cases
qualify()
|
|||
No
|
annualSalary
|
creditRating
|
qualify?
|
1
|
10_000
|
1
|
false
|
2
|
10_000
|
3
|
false
|
3
|
10_000
|
7
|
false
|
4
|
10_000
|
8
|
false
|
5
|
10_000
|
10
|
false
|
6
|
20_000
|
1
|
false
|
7
|
20_000
|
3
|
false
|
8
|
20_000
|
7
|
true
|
9
|
20_000
|
8
|
true
|
10
|
20_000
|
10
|
true
|
11
|
30_000
|
1
|
false
|
12
|
30_000
|
3
|
false
|
13
|
30_000
|
7
|
true
|
14
|
30_000
|
8
|
true
|
15
|
30_000
|
10
|
true
|
3.3.
Phát triển method
CreditCardRequestTest.java
package model;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class CreditCardRequestTest {
@Test public void qualify(){
assertFalse(new CreditCardRequest(10_000, 1).qualify());
assertFalse(new CreditCardRequest(10_000, 3).qualify());
assertFalse(new CreditCardRequest(10_000, 7).qualify());
assertFalse(new CreditCardRequest(10_000, 8).qualify());
assertFalse(new CreditCardRequest(10_000, 10).qualify());
assertFalse(new CreditCardRequest(20_000, 1).qualify());
assertFalse(new CreditCardRequest(20_000, 3).qualify());
assertTrue(new CreditCardRequest(20_000, 7).qualify());
assertTrue(new CreditCardRequest(20_000, 8).qualify());
assertTrue(new CreditCardRequest(20_000, 10).qualify());
assertFalse(new CreditCardRequest(30_000, 1).qualify());
assertFalse(new CreditCardRequest(30_000, 3).qualify());
assertTrue(new CreditCardRequest(30_000, 7).qualify());
assertTrue(new CreditCardRequest(30_000, 8).qualify());
assertTrue(new CreditCardRequest(30_000, 10).qualify());
}
}
CreditCardRequest.java
package model;
public class CreditCardRequest {
private final int annualSalary;
private final int creditRating;
public CreditCardRequest(int annualSalary, int creditRating) {
this.annualSalary = annualSalary;
this.creditRating = creditRating;
}
public boolean qualify() {
return annualSalary >= 20_000 && creditRating >= 7;
}
}
4.
Tích hợp
package controller;
import javax.swing.JOptionPane;
import model.CreditCardRequest;
import view.Input;
public class Main {
private Main() {
throw new RuntimeException(this.getClass() +
" is a noninstantiable utility class");
}
public static void main(String[] args) {
int annualSalary = Input.readPositiveIntGui("Annual salary: ");
int creditRating = Input.readIntGui("Credit rating: ", 1, 10);
boolean qualified =
new CreditCardRequest(annualSalary, creditRating).qualify();
if (qualified)
JOptionPane.showMessageDialog(null, "Qualified");
else
JOptionPane.showMessageDialog(null, "Unqualified",
null, JOptionPane.ERROR_MESSAGE);
}
}
III. Tổng kết
Bài này đã trình
bày việc tái dụng code và thiết kế có sẵn. Đứng
trước một vấn đề mới, nếu thấy nó có dáng dấp
tương tự như những vấn đề đã từng gặp trước đây,
ta nên thử tìm cách tái dụng (reuse). Khi reuse, có thể
cần phải đổi tên và thêm bớt tham số cho phù hợp với
tình hình mới.
V.
Tài liệu tham khảo
- Gaddis T. (2010) Starting Out with Java: From Control Structures Through Objects (4th edition), Pearson Education, Boston. Chương 5.
V. Bài tập
- Trong Input class, hãy chuyển readPlayersPerTeam(lowerBound, upperBound) thành readInt(lowerBound, upperBound) và phát triển thêm readPositiveInt(). Hai methods này dùng console để nhập data.
- Hãy thay đổi Main class để dùng hai methods trên.
- Cần đảm bảo rằng cả hai chương trình của bài này và bài trước đều chạy tốt sau khi thực hiện những thay đổi trên.
Không có nhận xét nào:
Đăng nhận xét