"Công nghệ thông tin là rất hữu dụng nhưng nếu chúng được dùng mà không có lương tâm, nó có thể lôi chúng ta lên con đường của phá huỷ và suy tàn. Chúng ta nên học cách dùng chúng cho phúc lợi xã hội của nhân loại và tiến bộ của nền văn minh của chúng ta bằng việc có bộ luật ứng xử đạo đức tốt. Kẻ tội phạm nguy hiểm có thể là người có năng khiếu lập luận logic, nhưng không có đạo đức. Thông minh là không đủ. Thông minh cộng với nhân cách đạo đức là mục đích của giáo dục. Giáo dục đầy đủ cho con người không chỉ tri thức, mà còn nhân cách đạo đức. Giáo dục tốt nhất phải hội tụ không chỉ vào việc thu nhận tri thức mà còn tích luỹ kinh nghiệm sống xã hội bởi vì mục đích của giáo dục là tạo ra công dân tốt cho đất nước."
Ứng xử trong gia đình
- OOP
- JSF
- Essays
- Thuật ngữ Anh-Việt
- Kỹ năng mềm
- Đường thành công
- Hướng nghiệp
- 50 Phép Lịch Sự Cho Nam
- 50 Phép Lịch Sự Cho Nữ
- Phép lịch sự trong gia đình
- Phép lịch sự nơi công cộng
- Phép lịch sự khi làm khách
- Kiến Thức Phổ Thông
- Kinh tế học căn bản
- Toán học trong vài phút
- Nhân liệu (Peopleware)
- Phát triển HTTT kế toán bằng MS Access
- Lập trình viên hạnh phúc
Thứ Năm, 16 tháng 2, 2012
Chủ Nhật, 5 tháng 2, 2012
Hãy lập trình với tinh thần phải bảo trì cho đến chết
Hãy
lập trình với tinh thần phải bảo trì cho đến chết
Yuriy
Zubarev
Khi hỏi
97 người rằng mọi lập trình viên phải học
những gì và cần làm gì, bạn có thể nhận được 97
lời khuyên khác nhau. Kết quả này có thể khiến bạn
cảm thấy quá sức và lo sợ. Lời khuyên nào cũng hay,
nguyên tắc nào cũng hợp lý, và câu chuyện nào cũng đầy
thuyết phục, song phải bắt đầu từ đâu? Quan trọng
hơn, một khi đã bắt đầu, làm thế nào duy trì được
tất cả các thực hành tốt mà bạn đã học, và làm thế
nào tích hợp được chúng vào kỹ năng lập trình của
mình?
Tôi
nghĩ rằng câu trả lời nằm trong tâm, cụ thể hơn là ở
thái độ của bạn. Chẳng hạn, nếu chẳng màng đến
đồng nghiệp lập trình, kiểm thử, quản lý, bán hàng,
tiếp thị, và người sử dụng, bạn sẽ không bị thôi
thúc áp dụng phương pháp phát triển phần mềm dựa trên
kiểm thử (test-driven development), hoặc không muốn chú
thích rõ ràng trong chương trình. Tôi nghĩ rằng có một
cách đơn giản để điều chỉnh thái độ của bạn và
luôn thôi thúc bạn xuất xưởng những sản phẩm có chất
lượng tuyệt hảo, đó là
Hãy
lập trình với tinh thần phải bảo trì cho đến chết
Chỉ
vậy thôi. Nếu bạn thừa nhận quan điểm này, nhiều
điều kỳ diệu sẽ xảy đến. Nếu phải chấp nhận để
nhà tuyển dụng trong quá khứ hay ở hiện tại có quyền
nửa đêm dựng bạn dậy, yêu cầu giải thích vì sao bạn
lại viết phương thức (method) fooBar như thế, bạn
sẽ cải thiện từng bước để trở thành một chuyên
gia lập trình. Tự nhiên bạn muốn đặt tên biến và tên
method cho tốt hơn. Bạn sẽ tránh xa những khối lệnh
chứa hàng trăm dòng. Bạn sẽ tìm học và áp dụng các
công thức thiết kế (design patterns). Bạn sẽ chú thích,
kiểm thử, và liên tục tái cấu trúc (refactor) chương
trình. Tinh thần bảo trì mã (code) do bạn viết ra cho đến
chết còn là một nỗ lực hoàn thiện. Qua đó bạn chẳng
còn chọn lựa nào khác ngoài việc trở nên tốt hơn,
chín chắn hơn, và hiệu quả hơn.
Nếu
suy niệm sâu sắc, bạn nhận thấy rằng chương trình do
mình viết ra nhiều năm trước vẫn tiếp tục tác động
đến nghề nghiệp, bất chấp mình có thích điều đó
hay không. Bạn sẽ để lại di tích về kiến thức, thái
độ, lòng kiên trì, tính chuyên nghiệp, tinh thần tận
tụy, và cảm hứng của mình trong từng method, lớp
(class), và bộ phận (module) mà bạn đã thiết kế và thi
công. Người khác sẽ đánh giá bạn qua code của bạn.
Nếu những đánh giá đó thường xuyên là tiêu cực, bạn
sẽ thu nhận từ nghề nghiệp ít hơn điều mà mình mong
ước. Hãy chăm sóc nghề nghiệp, khách hàng, và người
sử dụng qua từng dòng code – hãy lập trình với tinh
thần phải bảo trì cho đến chết.
Nguồn
Zubarev
Y. (2010) Write
Code As If You Had to Support It for the Rest of Your Life,
97 Things Every Programmer Should Know, Henney K. (ed), O'Reilly,
Sebastopol, CA.
OOP - Bài 7: Doanh thu trong tuần
Center of Excellence
Bài
7
Doanh
thu trong tuần
Vạn vật được
tạo tác từ không
Everything is from
nothing
-- Jessie Fairweather
I. Bài toán
Hãy phát triển chương
trình tính tổng doanh thu trong tuần, doanh thu bình quân
ngày, doanh thu ngày cao nhất, và doanh thu ngày thấp nhất.
Sau đây là ví dụ về doanh thu của một tuần:
1000.00, 500.00, 3000.00,
4000.00, 9000.00, 6000.00, 7000.00
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
Ta cần giải quyết
các yêu cầu sau
- Tính tổng doanh thu tuần (total weekly sales)
- Input: doanh thu hàng ngày trong tuần (daily sales figures)
- Output: total weekly sales
- Tính doanh thu bình quân ngày (average daily sales)
- Input: daily sales figures
- Output: average daily sales
- Tính doanh thu ngày cao nhất (highest daily sales)
- Input: daily sales figures
- Output: highest daily sales
- Tính doanh thu ngày thấp nhất (lowest daily sales)
- Input: daily sales figures
- Output: lowest daily sales
1.1. Thiết kế sơ
bộ
Xác định tên
methods và parameters
Thử chuyển
parameter thành field
Xác định data
type cho field
Do
dailySalesFigures là
một tập hợp doanh thu của bảy ngày trong tuần, ta không
thể sử dụng double
cho field này, mà phải là một mảng (array)
gồm nhiều double.
Để chỉ định một array, ta bổ sung cặp ngoặc vuông.
Xác định tên
class dựa vào field và method
Ta
cần trả lời câu hỏi: Đối tượng nào chứa doanh
thu của bảy ngày trong tuần, rồi từ đó tính được
doanh thu tổng? Đó chính là doanh thu của một tuần
(weekly sales).
Do đã
xác định được tên class, giờ đây ta có thể đơn giản
hóa tên method và field.
sum()
|
||
No
|
figures
|
sum?
|
1
|
1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0,
7_000.0
|
30_500.0
|
1.3.
Phát triển method
Project: WeeklySales
package weeklysales;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class WeeklySalesTest {
@Test public void sum() {
assertEquals(30_500.0, new WeeklySales(???).sum(), 0.0);
}
}
Để
thay thế cụm ??? bằng giá trị cụ thể, ta đặt doanh
thu của bảy ngày trong tuần vào một array. Lưu ý là tất
cả các giá trị này đều nằm trong cặp ngoặc nhọn, và
chúng cách nhau bằng dấu phẩy.
public class WeeklySalesTest {
@Test public void sum() {
double[] figures = { 1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0 };
assertEquals(30_500.0, new WeeklySales(figures).sum(), 0.0);
}
}
Từ
WeeklySalesTest, ta tạo ra WeeklySales class.
package weeklysales;
public class WeeklySales {
private double[] figures;
public WeeklySales(double[] figures) {
this.figures = figures;
}
public double sum() {
return ???;
}
}
Để
tính tổng, ta sử dụng một bộ tích lũy (accumulator) lấy
tên là acc. Ban đầu acc chưa tích lũy được
gì nên bằng 0.0.
public class WeeklySales {
private double[] figures;
public WeeklySales(double[] figures) {
this.figures = figures;
}
public double sum() {
double acc = 0.0;
???
return acc;
}
}
Sau
đó ta dùng vòng lặp for-each, lấy ra từng giá trị
doanh thu (figure) bên trong figures,
rồi tích lũy figure vào acc thông qua toán tử
cộng dồn +=. (Ngoài +=, ta còn có -=, *=, /=, %=)
public class WeeklySales {
private double[] figures;
public WeeklySales(double[] figures) {
this.figures = figures;
}
public double sum() {
double acc = 0.0;
for (double figure : this.figures)
acc += figure;
return acc;
}
}
2.1.
Thiết kế sơ bộ
Do
yêu cầu này dùng chung input với yêu cầu trước nên ta
đặt chúng vào cùng một class.
average()
|
||
No
|
figures
|
average?
|
1
|
1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0,
7_000.0
|
4_357.14
(làm tròn về hai chữ số sau dấu thập phân từ kết
quả 4_357.1428...)
|
2.3.
Phát triển method
public class WeeklySalesTest {
@Test public void sum() {
double[] figures = { 1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0 };
assertEquals(30_500.0, new WeeklySales(figures).sum(), 0.0);
}
@Test public void average() {
double[] figures = { 1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0 };
assertEquals(4_357.14, new WeeklySales(figures).average(), 0.0);
}
}
Xét
thấy có tình trạng code duplication trong hai test methods
sum() và average(),
nhưng ta cần hoàn thành nhiệm vụ trước mắt, đó là
phát triển average(). Doanh
thu bình quân ngày sẽ bằng tổng doanh thu chia cho tổng số
ngày, ta viết
package weeklysales;
public class WeeklySales {
private double[] figures;
public WeeklySales(double[] figures) {
this.figures = figures;
}
public double sum() {
double acc = 0.0;
for (double figure : this.figures)
acc += figure;
return acc;
}
public double average() {
return this.sum() / this.figures.length;
}
}
Ở
trên, bên trong average(),
ta đã tận dụng method tính tổng sum()
đã được phát triển từ trước. Thêm vào đó, ta còn
dùng length field của
figures array để
xác định tổng số ngày. Dĩ nhiên có thể biết trước
tổng số ngày là 7. Tuy vậy, việc sử dụng length
sẽ làm giải pháp trở nên tổng quát hơn. Chẳng hạn,
nếu cửa hàng đóng cửa ngày Chủ nhật, tức doanh số
trong tuần chỉ gồm 6 ngày, thì code của ta không cần
phải thay đổi.
Đến
đây nếu thi hành WeeklySalesTest
class, ta gặp tín hiệu đỏ với thông báo lỗi:
expected:<4357.14> but was:<4357.14857142857>,
tức kết quả của chương trình là 4357.14857142857,
chứ không phải giá trị 4357.14
mà ta đã kỳ vọng. Lý do là ta đã chủ động làm tròn
kết quả về hai chữ số sau dấu chấm thập phân. Để
được tín hiệu xanh, ta cần xác định lại độ lệch
cho phép giữa hai giá trị bên trong lệnh assertEquals().
Trước tiên, ta lấy giá trị lớn hơn trừ giá trị nhỏ
hơn, 4357.14857142857
- 4357.14
= 0.00857142857.
Từ đó độ lệch được xác định bằng cách giữ lại
giá trị chỉ chứa chữ số khác 0
đầu tiên tính từ bên trái (tức 0.008), rồi tăng 1
vào chữ số đó, tức 0.009.
Trường hợp vẫn gặp tín hiệu đỏ thì ta lại tiếp
tục tăng 1
vào chữ số khác 0
cho đến khi gặp tín hiệu xanh.
@Test public void average() {
double[] figures = { 1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0 };
assertEquals(4_357.14, new WeeklySales(figures).average(), 0.009);
}
Loại
bỏ code duplication
Ta
tiến hành loại bỏ tình trạng code duplication bằng cách
khai báo figures là
một field.
public class WeeklySalesTest {
private double[] figures = { 1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0 };
@Test public void sum() {
assertEquals(30_500.0, new WeeklySales(this.figures).sum(), 0.0);
}
@Test public void average() {
assertEquals(4_357.14, new WeeklySales(this.figures).average(), 0.009);
}
}
Hơn
nữa, cả hai methods đều gọi new
WeeklySales(this.figures), nên
ta tiếp tục chuyển object này thành field và đặt tên là
weeklySales.
public class WeeklySalesTest {
private double[] figures = { 1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0 };
private WeeklySales weeklySales = new WeeklySales(this.figures);
@Test public void sum() {
assertEquals(30_500.0, this.weeklySales.sum(), 0.0);
}
@Test public void average() {
assertEquals(4_357.14, this.weeklySales.average(), 0.009);
}
}
Ta
còn có thể cải tiến code thêm một chút thông qua việc
vận dụng khái niệm varargs,
tức variable-length argument list (danh sách đối số có chiều
dài biến động). Trong đoạn code trên, thay vì phải định
nghĩa một array lấy tên là figures,
rồi truyền array đó vào lệnh new
WeeklySales(figures), ta có thể
viết trực tiếp như sau
public class WeeklySalesTest {
private WeeklySales weeklySales = new WeeklySales(
1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0);
@Test public void sum() {
assertEquals(30_500.0, this.weeklySales.sum(), 0.0);
}
@Test public void average() {
assertEquals(4_357.14, this.weeklySales.average(), 0.009);
}
}
Khi đó WeeklySales class cần phải được viết dưới đây, ở đó bên trong parameter của constructor, ta đã thay cặp ngoặc vuông bằng ba dấu chấm.
public class WeeklySales {
private double[] figures;
public WeeklySales(double... figures) {
this.figures = figures;
}
public double sum() {
double acc = 0.0;
for (double figure : this.figures)
acc += figure;
return acc;
}
public double average() {
return this.sum() / this.figures.length;
}
}
3.1.
Thiết kế sơ bộ
max()
|
||
No
|
figures
|
max?
|
1
|
1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0,
7_000.0
|
9_000.0
|
3.3.
Phát triển method
WeeklySalesTest.java
public class WeeklySalesTest {
private WeeklySales weeklySales = new WeeklySales(
1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0);
@Test public void sum() {
assertEquals(30_500.0, this.weeklySales.sum(), 0.0);
}
@Test public void average() {
assertEquals(4_357.14, this.weeklySales.average(), 0.009);
}
@Test public void max() {
assertEquals(9_000.0, this.weeklySales.max(), 0.0);
}
}
WeeklySales.java
public class WeeklySales {
private double[] figures;
public WeeklySales(double... figures) {
this.figures = figures;
}
public double sum() {
double acc = 0.0;
for (double figure : this.figures)
acc += figure;
return acc;
}
public double average() {
return this.sum() / this.figures.length;
}
public double max() {
return ???;
}
}
Để
tìm được doanh thu cao nhất, ta áp dụng thuật toán
(algorithm) sau: đầu tiên giả định rằng doanh thu cao nhất
hiện thời (current max) là hằng số âm vô cực
(negative infinity).
public double getMax() {
double currentMax = Double.NEGATIVE_INFINITY;
???
return currentMax;
}
Sau
đó ta dùng vòng lặp for-each để lấy ra từng giá
trị (figure) bên trong figures array,
public double max() {
double currentMax = Double.NEGATIVE_INFINITY;
for (double figure : this.figures)
???
return currentMax;
}
Mỗi
lần lấy được figure nào ra, ta so sánh nó với
currentMax, nếu lớn hơn currentMax, thì
figure đó sẽ trở thành currentMax.
public double max() {
double currentMax = Double.NEGATIVE_INFINITY;
for (double figure : this.figures)
if (figure > currentMax)
currentMax = figure;
return currentMax;
}
Sau
khi đã so sánh currentMax với toàn bộ sales
trong dailySales, currentMax chính là doanh số
cao nhất.
Phần
này dành làm bài tập. Lưu ý hằng số dương vô cực sẽ
là Double.POSITIVE_INFINITY.
III.
Tổng kết
Bài viết đã vận dụng cấu trúc dữ liệu array, vòng
lặp for-each, bộ tích lũy (accumulator), và toán tử
cộng dồn +=, để thực hiện những tính toán trên tập
hợp các số double.
Khái niệm về danh sách đối số có chiều dài biến động
(varargs) cũng đã được đề cập. Ngoài ra, bài còn trình
bày một phương pháp xác định độ lệch cho phép giữa
hai giá trị double
trong quá trình kiểm thử.
IV.
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 8.
Thứ Bảy, 4 tháng 2, 2012
JSF - Bài 7: Doanh thu trong tuần
Center of Excellence
Bài
7
Doanh
thu trong tuần
I. Bài toán
Hãy phát triển một
web application để tính tổng doanh thu trong tuần, doanh thu
bình quân ngày, doanh thu ngày cao nhất, và doanh thu ngày
thấp nhất. Ví dụ về doanh thu của một tuần như sau:
1000.00, 500.00, 3000.00,
4000.00, 9000.00, 6000.00, 7000.00
Dưới đây là một
UI mẫu.
Hình 1
II. Giải
pháp
Project: WeeklySalesJSF
1.
Thiết kế UI screen
index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<title>Weekly Sales</title>
<script src="resources/clearForm.js"/>
<style>
table input,
fieldset input {
width: 100px;
}
fieldset {
margin: 0 60% 0 0;
}
fieldset label {
width: 140px;
float: left;
text-align: right;
}
</style>
</head>
<body>
<h2>Weekly Sales</h2>
<table>
<thead>
<tr>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
<th>Sunday</th>
</tr>
</thead>
<tbody>
<tr>
<td><input/></td>
<td><input/></td>
<td><input/></td>
<td><input/></td>
<td><input/></td>
<td><input/></td>
<td><input/></td>
</tr>
</tbody>
</table>
<fieldset>
<legend>Statistics</legend>
<label>Total weekly sales $</label>
<input disabled="true"/><br/>
<label>Average daily sales $</label>
<input disabled="true"/><br/>
<label>Highest daily sales $</label>
<input disabled="true"/><br/>
<label>Lowest daily sales $</label>
<input disabled="true"/>
</fieldset>
<div>
<input type="submit" value="Compute Statistics"/>
<input type="button" value="Clear" onclick="clearForm(this.form)"/>
</div>
</body>
</html>
2. Bổ sung phần động cho UI screen
2.1. Thiết kế
managed bean
Thay vì phải dùng bảy
fields trong managed bean để lưu trữ bảy doanh số (sales)
nhập vào từ user, ta tập hợp chúng vào một array, gọi
là salesFigures.
Tuy
nhiên, data type của salesFigures không thể là Double[],
bởi vì đây là input component, ta phải có setter cho từng
thành phần của Double[], tức phải có setter cho từng
Double, nhưng Double đã được qui định sẵn
là không có setter. Để giải quyết vấn đề này, ta có
thể dùng wrapper class, lấy tên là SalesFigure, để bọc
một Double lại, rồi bổ sung getter và setter cho
wrapper đó.
2.2.
Tạo fields và methods cho managed bean
Tạo SalesFigure class
package controller;
public class SalesFigure {
private Double value;
public SalesFigure() {
}
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
}
Tạo managed bean
Lưu
ý rằng ta cần khởi tạo SalesFigure[]. Dưới đây, ta
đặt code khởi tạo bên trong makeSalesFigures() method, và
method này được gọi thi hành bên trong constructor.
package controller; import javax.enterprise.context.RequestScoped; import javax.inject.Named; @Named(value = "index") @RequestScoped public class Index { private SalesFigure[] salesFigures; private Double sum; private Double average; private Double max; private Double min; public Index() { salesFigures = makeSalesFigures();
} private SalesFigure[] makeSalesFigures() {
SalesFigure[] figures = new SalesFigure[7];
for (int i = 0; i < figures.length; i++)
figures[i] = new Figure();
return figures;
}
public void computeStatistics() {
// TODO
}
public SalesFigure[] getSalesFigures() {
return salesFigures;
}
public Double getAverage() {
return average;
}
public Double getMax() {
return max;
}
public Double getMin() {
return min;
}
public Double getSum() {
return sum;
}
}
2.3.
Ràng buộc UI screen với managed bean
Khi
ràng buộc <table> ở UI screen với salesFigures[]
trong managed bean, ta dùng một cấu trúc lặp của JSF, tương
tự như for-each, đó là <ui:repeat>. Cần
lưu ý value attribute trong <h:inputText> là
#{figure.value}.
Đối
với các components khác, ta thực hiện việc ràng buộc như
đã làm trong những bài trước.
3. Phát triển model
3.1.
Design
Lưu ý là ta không
cần dùng wrapper class cho salesFigures bên trong model. Tất
nhiên là sau này, khi kết nối giữa managed bean và model,
ta cần phải chuyển đổi từ SalesFigure[] về double[].
3.2.
Test class
package model;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class WeeklySalesTest {
private WeeklySales weeklySales = new WeeklySales(
1_000.0, 500.0, 3_000.0, 4_000.0, 9_000.0, 6_000.0, 7_000.0);
@Test public void sum() {
assertEquals(30_500.0, weeklySales.sum(), 0.0);
}
@Test public void average() {
assertEquals(4_357.14, weeklySales.average(), 0.009);
}
@Test public void max() {
assertEquals(9_000.0, weeklySales.max(), 0.0);
}
@Test public void min() {
assertEquals(500.0, weeklySales.min(), 0.0);
}
}
3.3.
Main class
package model;
public class WeeklySales {
private final double[] salesFigures;
public WeeklySales(double... salesFigures) {
this.salesFigures = salesFigures;
}
public double sum() {
double acc = 0.0;
for (double saleFigure : this.salesFigures)
acc += salesFigure;
return acc;
}
public double average() {
return sum() / salesFigures.length;
}
public double max() {
double currentMax = Double.NEGATIVE_INFINITY;
for (double salesFigure : this.salesFigures)
if (salesFigure > currentMax)
currentMax = salesFigure;
return currentMax;
}
public double min() {
double currentMin = Double.POSITIVE_INFINITY;
for (double salesFigure : this.salesFigures)
if (salesFigure < currentMin)
currentMin = salesFigure;
return currentMin;
}
}
4.
Kết nối managed bean với model
Như đã đề cập ở
trên, trước khi gọi model từ
managed bean, ta cần chuyển đổi Figure[]
về double[].
Điều này thể hiện trong toDoubleArrayOfFigures().
5. Định dạng số
public void computeStatistics() {
WeeklySales weeklySales = new WeeklySales(salesFiguresToDoubles());
sum = weeklySales.sum();
average = weeklySales.average();
max = weeklySales.max();
min = weeklySales.min();
}
private double[] salesFiguresToDoubles() {
double[] a = new double[figures.length];
for (int i = 0; i < a.length; i++)
a[i] = figures[i].getValue();
return a;
}
Bây
giờ ta muốn hiển thị kết quả tính toán theo các điều
kiện sau
- Áp dụng dấu phân cách hàng ngàn (thousands separator) cho những số lớn
- Nếu không có chữ số khác 0 nào đứng trước dấu chấm thập phân (decimal point) thì sẽ hiển thị số 0 trước decimal point
- Có hai chữ số sau decimal point
Ta điều chỉnh lại index.xhtml như sau
<fieldset>
<legend>Statistics</legend>
<label>Total weekly sales: $</label>
<h:inputText disabled="true" value="#{index.sum}">
<f:convertNumber pattern="#,##0.00"/>
</h:inputText><br/>
<label>Average daily sales: $</label>
<h:inputText disabled="true" value="#{index.average}">
<f:convertNumber pattern="#,##0.00"/>
</h:inputText><br/>
<label>Highest daily sales: $</label>
<h:inputText disabled="true" value="#{index.max}">
<f:convertNumber pattern="#,##0.00"/>
</h:inputText><br/>
<label>Lowest daily sales: $</label>
<h:inputText disabled="true" value="#{index.min}">
<f:convertNumber pattern="#,##0.00"/>
</h:inputText>
</fieldset>
6.
Kiểm tra tính hợp lệ của input
III.
Tổng kết
Bài
viết đã đề cập các khái niệm và kỹ thuật sau
- Cấu trúc bảng với <table>
- Wrapper class cùng getter và setter để ràng buộc web page với managed bean
- Định dạng với <f:convertNumber>
IV.
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 8.
- Ed Burns, Chris Schalk (2010) JavaServer Faces 2.0: The Complete Reference, McGraw-Hill.
V. Bài
tập
Hãy điều
chỉnh để application có thể tiếp nhận input từ user
theo các điều kiện đã được đề cập trong phần định
dạng output. Ví dụ, application có thể tiếp nhận input có
giá trị là 1,234.56.
Đăng ký:
Bài đăng (Atom)