Tại sao chúng ta không thích các lớp dạy tiếng Anh

Nguồn: http://vinacode.net/2014/08/27/cac-lop-day-tieng-anh/

Tới các trung tâm Anh ngữ là cách phổ biến nhất khi mà mọi người muốn học tiếng Anh. Một điều cũng phổ biến đến mức kinh ngạc là hầu hết mọi người thậm chí không nghĩ về cách làm thế nào để học giỏi tiếng Anh. Quy trình này thì hết sức tự động: tôi muốn học tiếng Anh, vì thế tôi đăng ký vào một khóa học tiếng Anh. Tôi sẽ trả một ít tiền, ngồi trong lớp trong một ít giờ mỗi tuần, và tôi sẽ trở nên giỏi tiếng Anh.

Điều này thì rất đáng ngạc nhiên, bởi vì tham gia các lớp dạy tiếng Anh là một cách rất tồi để học tiếng Anh. Chúng ta đã dành một phần lớn của cuộc đời mình trong các lớp dạy tiếng Anh (ở trường trung học, đại học, và tại các trung tâm ngoại ngữ), và chúng ta biết rằng các lớp học này giống nhau như thế nào. Với tất cả kiến thức mà chúng ta nhận được tại các lớp và khóa học tiếng Anh đó, ta sẽ vô cùng ngạc nhiên nếu tình cờ gặp một ai đó nói tiếng Anh rất giỏi bằng cách tham gia vào các lớp học tiếng Anh.

Tham gia các lớp dạy tiếng Anh chỉ tốn thời gian và tiền bạc của bạn mà không thu được nhiều kết quả.Tham gia các lớp dạy tiếng Anh chỉ tốn thời gian và tiền bạc của bạn mà không thu được nhiều kết quả.


Nếu bạn tham dự các lớp dạy tiếng Anh, bạn sẽ phải dành nhiều thời gian mỗi tuần cho nó. Thường thì, bạn cũng phải chi ra rất nhiều tiền bạc. Và bạn sẽ nhận lại được điều gì cho số tiền và thời gian mà mình đã bỏ ra đó? Sau đây là danh sách những điều mà bạn có thể làm tại một lớp dạy tiếng Anh:

  • Nghe một thứ tiếng Anh rất dở. Cách phát âm, ngữ pháp, và từ vựng của những học viên khác (và đôi khi cả của giáo viên nữa) thì rất dở. Chắc chắn là bằng cách lắng nghe những người này sẽ không làm cho tiếng Anh của bạn trở nên tốt hơn.
  • Nói được dăm ba câu tiếng Anh. Thường có khoảng từ 10 đến 20 học viên trong mỗi lớp học, vì thế có rất ít thời gian cho bạn để nói tiếng Anh. Các lớp dạy tiếng Anh thông thường thì rất nghèo nàn trong việc luyện nói. (Các lớp đàm thoại thì khá hơn chút ít).
  • Đọc một cuốn giáo trình tẻ nhạt. Hầu hết tất cả các giáo viên dạy tiếng Anh đều sử dụng các cuốn giáo trình. Bạn có muốn biết lý do tại sao không? Bởi vì nó làm cho công việc của họ trở nên dễ dàng hơn. Họ không phải chuẩn bị bài giảng cho mỗi lớp học riêng lẻ. Họ chỉ việc dạy bài học tiếp theo ở trong cuốn sách đó. Các cuốn giáo trình làm cho việc dạy học dễ dàng hơn. Và chúng khiến cho việc học trở nên nhàm chán và kém hiệu quả. Bạn phải đọc những câu chuyện ngớ ngẩn về Michael Jackson hoặc về một người phụ nữ nào đó sống trong rừng rậm Phi Châu trong hai năm trời. Sau đó bạn phải trả lời những câu hỏi về họ và nói về họ với những học viên khác. Điều này thật là điên rồ! Bạn không hề quan tâm đến những hành động ngu ngốc đó. Nó khiến cho bạn nghĩ rằng học tiếng Anh thật là tẻ nhạt.
  • Lắng nghe một số quy tắc ngữ pháp, như là “thì hiện tại tiếp diễn diễn tả một sự việc đang diễn ra ở thời điểm hiện tại”. Việc học các quy tắc ngữ pháp là một điều ngu xuẩn nhất mà bạn có thể làm. Có hai lý do chính để nói như vậy: 1) Dù thế nào chúng ta cũng không thể nhớ tất cả hàng trăm quy tắc ngữ pháp như vậy, 2) Khi nói tiếng Anh, chúng ta không có thời gian để nghĩ: “Tôi nên sử dụng thì nào nhỉ? Xem nào… Tôi muốn trình bày ý tưởng của một hành động tiếp diễn đến thời điểm hiện tại, vì thế tôi nên sử dụng thì hiện tại hoàn thành.” Bạn muốn sử dụng tiếng Anh của mình một cách tự nhiên. Các quy tắc ngữ pháp có thể làm tăng điểm số của bạn trong các kỳ kiểm tra, nhưng chúng không làm tăng trình độ tiếng Anh của bạn.
  • Làm một số bài tập về ngữ pháp. Sau khi nói về các quy tắc ngữ pháp, các giáo viên thường đưa cho bạn một số bài tập, như là bài trắc nghiệm hoặc điền vào ô trống. Các bài tập về ngữ pháp có hai chức năng: 1) chúng giúp bạn ôn lại các quy tắc ngữ pháp, 2) chúng kiểm tra trình độ tiếng Anh của bạn. Chức năng đầu tiên thì vô ích bởi vì các quy tắc ngữ pháp thì không có ý nghĩa gì cả (bạn hãy xem lại phần trên). Chức năng thứ hai, kiểm tra, thì chỉ có ích khi bạn muốn so sánh kiến thức của mình với một người khác. Nhưng kiểm tra không dạy bạn bất kỳ chút tiếng Anh nào.
  • Nhận một số bài tập về nhà. Bài tập về nhà thì thường là các bài tập về ngữ pháp (xem lại phần trước) hoặc một bài luận. Chủ đề của bài luận đó thì sẽ thường là một cái gì đó mà bạn chẳng hề quan tâm. Ví dụ: Nêu quan điểm của bạn về câu tục ngữ “Một giọt máu đào hơn ao nước lã”, Việc trở nên nổi tiếng liệu có tốt hay không?. Thật vô nghĩa làm sao. Làm những thứ nhàm chán thì sẽ không giúp cho tiếng Anh của bạn một chút nào. Nó sẽ chỉ làm giảm động lực của bạn mà thôi.

Các lớp tiếng Anh sẽ không dạy bạn cách phát âm chuẩn (điều này thì đơn giản là cần thiết cho sự giao tiếp!). Hầu hết các giáo viên đều lờ nó đi, đôi khi bởi vì sự phát âm của chính họ cũng rất dở. Một số giáo viên sẽ sửa những lỗi của bạn khi bạn nói. Nhưng rất ít giáo viên sẽ nói với bạn làm thế nào để tránh phạm phải những lỗi tương tự trong tương lai. Rất ít giáo viên sẽ nói với bạn về giọng trong tiếng Anh và làm thế nào để sử dụng một cuốn từ điển để học cách phát âm các từ.

Hầu hết các giáo viên sẽ không khuyến khích bạn đọc trong tiếng Anh, cách mua một cuốn từ điển Anh-Anh tốt, lắng nghe những đoạn ghi âm chính giọng nói của bạn bằng ngôn ngữ tiếng Anh. Họ sẽ chỉ dạy trong cuốn giáo trình và làm bài tập ở trong đó. Nếu giáo viên của bạn khác với những mô tả phía trên thì bạn là người may mắn đấy.

Đây là tình trạng chung của hầu hết tất cả các lớp dạy tiếng Anh. Bạn hãy nghĩ về lớp học tiếng Anh của mình. Nếu chúng giống như vậy — tẻ nhạt và kém hiệu quả — thì bạn đơn giản là bạn đang lãng phí thời gian của chính mình. (Nhưng đừng lo lắng: bạn không đơn độc. Hàng triệu người khắp nơi trên thế giới này đã lãng phí thời gian của họ bởi việc tham gia các lớp dạy tiếng Anh, tuy nhiên họ lại không cải thiện được trình độ tiếng Anh của mình).

Bạn có thể thay thế những lớp học nhàm chán và thiếu hiệu quả bằng những thứ thú vị và chúng sẽ thực sự nâng cao khả năng tiếng Anh của bạn:

  • Thay vì phải nghe thứ tiếng Anh tồi trong các lớp học, thì hãy bật TV nhà bạn lên và xem kênh CNN International hoặc những kênh phát bằng ngôn ngữ tiếng Anh khác. Bạn sẽ nhận được rất nhiều câu hoàn hảo trong tiếng Anh chuẩn.
     
  • Thay vì phải ngồi hai giờ trong lớp để nói dăm ba câu tiếng Anh, hãy tham gia một lớp học hội thoại với một người bản xứ. Hoặc bắt đầu nói chuyện bằng tiếng Anh với người bạn giỏi nhất của mình.
     
  • Thay vì phải làm việc với một cuốn giáo trình tẻ nhạt, hãy đọc một cái gì đó thú vị. Có rất nhiều thứ thú vị bằng văn bản trong tiếng Anh! Hãy lướt qua các trang web bằng tiếng Anh. Đọc những cuốn sách hay bằng tiếng Anh. Đơn giản là tìm đọc một cái gì đó làm bạn cảm thấy hứng thú. Một cái gì đó mà bạn không thấy nhàm chán muốn chết.
     
  • Thay vì phải ngồi nhớ các quy tắc ngữ pháp và làm các bài tập ngữ pháp, hãy đọc và lắng nghe tiếng Anh thật nhiều. Nhập vào đầu càng nhiều thì là cách duy nhất để học thứ tiếng Anh ấn tượng và tự nhiên nhất.
     
  • Thay vì ngồi viết các bài luận về các chủ đề mà giáo viên dạy tiếng Anh đưa cho bạn, hãy viết về một điều gì đó mà bạn cảm thấy quan tâm. Ví dụ, viết một bức thư bằng tiếng Anh. Đừng viết cho giáo viên của bạn — mà hãy viết cho chính bạn!

Lời bàn của Vinacode:

Khoảng năm 2002 khi xem một phóng sự World Cup phát trên truyền hình, lúc đội Senegal ghi bàn thắng, các cổ động viên đội nhà đã lao ra ngoài từ những túp lều trên sa mạc và xổ ra một tràng tiếng… Pháp để trả lời phỏng vấn của cánh báo chí. Lúc đó mình cũng khá sốc, vì dù đã biết rất nhiều các nước Châu Phi trước đây là thuộc địa của Pháp, nhưng không nghĩ rằng tiếng Pháp đã trở thành ngôn ngữ chính của họ. Một số nước khác như Ấn Độ (thuộc địa của Anh), Philippines (thuộc địa của Mỹ) cũng sử dụng tiếng Anh như là một ngôn ngữ quốc gia. Chẳng bù với Việt Nam ta, hơn 1000 năm bị đô hộ bởi phương Bắc, gần 100 năm là thuộc địa của Pháp, nhưng phần lớn người dân chúng ta đều không biết tiếng Hán và cũng chẳng biết tiếng Pháp. Có phải là do người Việt có lòng tự hào dân tộc quá cao nên không thể bị đồng hóa? hay là do tố chất học ngoại ngữ của người Việt không được tốt lắm nhỉ?

Mình đọc báo thấy nhiều bậc phụ huynh thường than rằng, họ cho con em đi học tiếng Anh từ bé, nhưng kết quả là học hàng chục năm tại các trung tâm lớn mà cuối cùng vẫn không nghe nói được cho ra hồn. Có lẽ lý do một phần là do việc học đó không có mục tiêu, bố mẹ bắt học thì đi vậy chứ không phải là sở thích của các em. Gần đây MC Quốc Khánh cũng đã nói đến vấn đề này trong một bài viết của anh:

“Bạn thắc mắc vì sao mình vẫn cứ loay hoay hoài không tiến bộ? Đã đi học bao nhiêu trung tâm, luyện với bao nhiều thầy bản xứ mà vẫn vậy? Tốn kém thời gian và tiền bạc mà vẫn không thấy hiệu quả? Đó là vì: bạn học mà không có mục đích cụ thể. Và có thể tiếng Anh đối với bạn chưa thật sự cần thiết. Do đó bạn không có áp lực phải luyện tập nhiều, phải nghe nói cho bằng được…Nếu chỉ học tiếng Anh với lý do là “phải giỏi tiếng Anh” thì sẽ không bao giờ bạn tiến bộ được. Vì thiếu mục đích và mục tiêu cụ thể, bạn sẽ chẳng bao giờ ép mình vào khuôn khổ để luyện tập. Cứ học xong rồi để đó, luyện tập qua loa rồi thôi. Rồi lại thắc mắc ‘Sao mình học hoài mà không giỏi?’”

Trong bài viết đó Khánh cũng đưa ra ví dụ về một số mục tiêu dành cho các bạn trẻ; nhưng việc học tiếng Anh đối với các em nhỏ thì mục tiêu của các em sẽ không thể giống như người lớn chúng ta được. Bởi vậy mình nghĩ cách tốt nhất là nên xây dựng một “thần tượng” đúng nghĩa cho các em. Mới đây cộng đồng mạng truyền tay nhau video về thần đồng Đỗ Nhật Nam vì khả năng nói tiếng Anh của em trong một cuộc thi English Champion 2014. Cũng như bé Xuân Mai trước đây đã trở thành “thần tượng” của nhiều em nhỏ tại Việt Nam hiện tại (nhiều khi người lớn phải bật mấy bài “Con cò bé bé” của Xuân Mai lên thì chúng mới chịu ăn cơm). Mình chợt nghĩ nếu đối với trường hợp của Đỗ Nhật Nam, người ta cũng ghi lại thật nhiều video về cậu bé này thì có thể biết đâu những hình ảnh đó sẽ truyền động lực về việc học tiếng Anh cho rất nhiều em nhỏ hiện tại và sau này:

Quay trở lại chủ đề chính của bài viết mình xin hỏi bạn vài câu hỏi. Bạn có đã/đang tham gia học tại các trung tâm dạy tiếng Anh không? Bạn thấy tính hiệu quả của việc học đó như thế nào?Bạn có đặt những mục tiêu của mình khi học ngoại ngữ không?Hãy dành chút thời gian chia sẻ với mọi người ở phần bình luận phía dưới nhé!

Tản mạn về Dependency Injection

Tản mạn về Dependency Injection

Như thường lệ, blog của mình sẽ rất ít các định nghĩa, rất nhiều code, hình ảnh minh họa và những câu nói dí dỏm. OK, hãy bắt đầu với định nghĩa về Dependency

Dependency

Khi trong class A có sự tồn tại của lớp B, dùng lớp B để làm 1 công việc gì đó, ta nói lớp A đang phụ thuộc vào lớp B. Ví dụ: CustomerRepository.java

package com.edward.tutorial.di.repository;

import java.util.Collection;

import com.edward.tutorial.di.model.Customer;

public class CustomerRepository {
	public Customer findOne(String customerId) {
		// Code stuff
	}

	public Collection<Customer> findAll() {
		// Code stuff
	}

	public void create(Customer customer) {
		// Code stuff
	}

	public boolean update(Customer customer) {
		// Code stuff
	}

	public void delete(Customer customer) {
		// Code stuff
	}
}

CustomerService.java

package com.edward.tutorial.di.service;

import java.util.Collection;

import com.edward.tutorial.di.model.Customer;
import com.edward.tutorial.di.repository.CustomerRepository;

public class CustomerService {
	
	CustomerRepository customerRepository;
	
	Collection<Customer> findAll() {
		return customerRepository.findAll();
	}

	Customer create(Customer customer) {
		customerRepository.create(customer);
		return customer;
	}
	
	Customer update(Customer customer) {
		customerRepository.update(customer);
		return customer;
	}

	void delete(String customerId) {
		Customer customer = findOne(customerId);
		customerRepository.delete(customer);
	}
	
	public Customer findOne(String customerId) {
		return customerRepository.findOne(customerId);
	}
}

Như ví dụ ở trên, lớp CustomerService đang phụ thuộc vào lớp CustomerRepository, vì CustomerService đang sử dụng 1 instance của CustomerRepository để thực hiện việc lưu trữ dữ liệu xuống database, cụ thể ở đây là customerRepository. Dependency1 Vậy: customerRepository được khởi tạo ở đâu? Vì nếu không được khởi tạo, thì khi sử dụng chúng ta sẽ nhận được NullPointerException. Câu trả lời là: để sử dụng được đối tượng customerRepository trong CustomerService, chúng ta sẽ có 2 cách:

  1. Khởi tạo đối tượng customerRepository trong lớp CustomerService.
  2. Truyền (Inject) đối tượng customerRepository đã được khởi tạo sẵn từ bên ngoài vào lớp CustomerService.

Dependency2

Injection

CHÚNG TA VỪA NHẮC ĐẾN INJECT. ĐÚNG VẬY, KHI LÀM THEO CÁCH 2, NGHĨA LÀ CHÚNG TA ĐANG THỰC HIỆN DEPENDENCY INJECTION. MỘT LƯU Ý KHÁC: Nếu chỉ muốn hiểu Dependency Injection là gì thì xin chúc mừng, chúng ta đã hoàn thành mục tiêu ở đây. Tuy nhiên chắc sẽ chẳng ai muốn dừng lại tại đây. Cho nên chúng ta sẽ đi tiếp phần demo và những chủ đề liên quan đến Dependency Injection Tiếp tục với việc demo cho 2 cách trên. Dependency3 Vậy các bạn sẽ tự hỏi: cách nào là tốt nhất, lúc nào nên dùng cách nào? Câu trả lời vẫn như mọi khi: không cách nào là hoàn hảo.

Tightly coupling và Loosely coupling

Trước khi đi vào phân tích ưu nhược của các cách làm, chúng ta cần làm rõ 2 khái niệm: tightly coupling và loosely coupling.

Tightly coupling:

Ở cách 1, khi khởi tạo đối tượng customerRepository ngay trong lớp CustomerService, ta nói lớp CustomerService đang phụ thuộc hoàn toàn vào lớp CustomerRepository. Trong suốt quá trình chương trình được thực thi (runtime), lớp CustomerService sẽ chỉ làm việc với duy nhất thể hiện của lớp CustomerRepository. Ở cách 2, mặc dù chúng ta không khởi tạo trực tiếp đối tượng customerRepository trong lớp CustomerService mà inject từ ngoài vào, nhưng lớp CustomerService vẫn chỉ làm việc được đối tượng customerRepository, do đó, cách 2 vẫn là Tightly coupling. Vậy, tightly coupling là việc một lớp TRỰC TIẾP sử dụng (phụ thuộc) trực tiếp vào thể hiện cụ thể của 1 lớp khác. TightlyCoupling

Loosely coupling:

Trái với tightly coupling, dễ dàng suy ra loosely coupling là việc một lớp KHÔNG TRỰC TIẾP sử dụng (phụ thuộc) vào thể hiện cụ thể của bất cứ 1 lớp cụ thể nào. Cho đến bây giờ vẫn chưa có 1 ví dụ nào để cho thấy loosely coupling như thế nào. Trong Java (hoặc các ngôn ngữ lập trình hướng đối tượng khác), để đạt được loosely coupling trong thiết kế, chúng ta cần sử dụng khái niệm “đa hình” (polymorphism). Tính đa hình trong lập trình hướng đối tượng là việc định nghĩa những đối tượng trừu tượng (abstraction) như abstract class hoặc interface. Những đối tượng abstraction này khai báo hoặc đưa ra quy ước (contract) và cho phép nhiều lớp đối tượng cụ thể kế thừa và định nghĩa lại hành vi cho riêng chúng.

Ví dụ về tính đa hình

Một tổ chức tiêu chuẩn ISO nào đó đưa ra định nghĩa về chiếc điện thoại: điện thoại là vật có khả năng nghe và nhận cuộc gọi. Lúc này ISO chưa hề cho ra đời 1 chiếc điện thoại nào có thể cầm nắm được, túm lại, nó chỉ là định nghĩa, để khi có người đang cầm trên tay 1 chiếc điện thoại thực sự thì họ có thể gọi hoặc nhận cuộc gọi. Sau khi đã có định nghĩa thế nào là điện thoại, các nhà sản xuất điện thoại hàng đầu thế giới mới bắt tay vào việc sản xuất ra những chiếc điện thoại theo tiêu chuẩn đã đặt ra bởi ISO. Hiện tại có 2 nhà sản xuất là Nokia và Samsung. Mục đích của họ là phải sản xuất ra những chiếc điện thoại có thể nghe và gọi được theo tiêu chuẩn ISO. Khi những chiếc điện thoại được tung ra thị trường, người sử dụng sau đó mua về và thực hiện chức năng nghe gọi mà họ đã từng được nghe ISO công bố trước đó. Tuy nhiên khi thực hiện cuộc gọi từ điện thoại Nokia thì sẽ nghe câu “Hello Microsoft” đầu tiên, còn với Samsung sẽ là câu “Lee Yong-dae” chẳng hạn. (I love Badminton). Có một nhà sản xuất nghiệp dư (giấu tên) cũng tập tành sản xuất điện thoại nhưng không tuân theo tiêu chuẩn của ISO, vậy nên khi cho ra thị trường, người ta không thể thực hiện nghe gọi, mà chỉ có thể… nghe nhạc. Vậy nên có thể gọi đây là cái máy nghe nhạc (tuân theo tiêu chuẩn của một tổ chức nào đó dành cho máy nghe nhạc), chứ không phải cái điện thoại. Phần mô tả cho đa hình đến đây là hết. Cười chút đã. =)) Do vậy, một lớp được gợi là loosely couling khi nó chỉ phụ thuộc vào các đối tượng high level (Abstract class hoặc Interface) thay vì phụ thuộc vào các lớp đối tượng cụ thể (concrete class). (Giống như việc một người tuyên bố, tui biết sử dụng tất cả điện thoại, miễn là nó có thể gọi và nghe, chứ không riêng gì cái điện thoại mà cứ phát ra câu “Lee Yong-dae”.) Ví dụ với bài Điện thoại theo chuẩn ISO ở trên

package com.edward.tutorial.di.phone;

public abstract class Phone {
	public abstract void call(String number);
	public abstract void answer(String number);
}

package com.edward.tutorial.di.phone;

public class NokiaPhone extends Phone {

	@Override
	public void call(String number) {
		System.out.println("Microsoft... " + number);
	}

	@Override
	public void answer(String number) {
		System.out.println(number + " Buy me...");
	}
}

package com.edward.tutorial.di.phone;

public class SamsungPhone extends Phone {

	@Override
	public void call(String number) {
		System.out.println("Kpop Kpop Kpop... " + number);
	}

	@Override
	public void answer(String number) {
		System.out.println(number + " I wanna cry...");
	}
}

package com.edward.tutorial.di.phone;

public class User {
	Phone phone;
	
	public User(Phone phone) {
		this.phone = phone;
	}
	
	public void bringMePhone(Phone phone) {
		this.phone = phone;
	}
	
	public void call(String number) {
		phone.call(number);
	}
	
	public void answer(String number) {
		phone.answer(number);
	}
}

package com.edward.tutorial.di.phone;

public class Main {

	public static void main(String[] args) {
		User bill = new User(new SamsungPhone());
		bill.call("0123");
		bill.bringMePhone(new NokiaPhone());
		bill.answer("0124");
	}
}

Quay lại ví dụ của chúng ta Extract CustomerRepository class thành CustomerRepository interface

package com.edward.tutorial.di.repository;

import java.util.Collection;

import com.edward.tutorial.di.model.Customer;

public interface CustomerRepository {

	public abstract Customer findOne(String customerId);

	public abstract Collection<Customer> findAll();

	public abstract void create(Customer customer);

	public abstract boolean update(Customer customer);

	public abstract void delete(Customer customer);

}

CustomerRepositoryImpl sẽ implement CustomerRepository interface

package com.edward.tutorial.di.repository;

import java.util.Collection;

import com.edward.tutorial.di.model.Customer;

public class CustomerRepositoryImpl implements CustomerRepository {
	@Override
	public Customer findOne(String customerId) {
		// Code stuff
	}

	@Override
	public Collection<Customer> findAll() {
		// Code stuff
	}

	@Override
	public void create(Customer customer) {
		// Code stuff
	}

	@Override
	public boolean update(Customer customer) {
		// Code stuff
	}

	@Override
	public void delete(Customer customer) {
		// Code stuff
	}
}

Và inject CustomerRepository interface thay vì CustomerRepositoryImpl

package com.edward.tutorial.di.service;

import java.util.Collection;

import com.edward.tutorial.di.model.Customer;
import com.edward.tutorial.di.repository.CustomerRepository;

public class CustomerService {
	
	CustomerRepository customerRepository;
	
	public CustomerService(CustomerRepository customerRepository) {
		this.customerRepository = customerRepository;
	}
	
	Collection<Customer> findAll() {
		return customerRepository.findAll();
	}

	Customer create(Customer customer) {
		customerRepository.create(customer);
		return customer;
	}
	
	Customer update(Customer customer) {
		customerRepository.update(customer);
		return customer;
	}

	void delete(String customerId) {
		Customer customer = findOne(customerId);
		customerRepository.delete(customer);
	}
	
	public Customer findOne(String customerId) {
		return customerRepository.findOne(customerId);
	}
}

LooselyCoupling

Nên design theo Tightly coupling hay Loosely coupling

Câu trả lời là Loosely coupling. Vì sao? Đọc tiếp…

Loosely coupling = Dependency Injection + Abstraction

Dependency Injection không giúp chúng ta cải thiện tính flexibility trong thiết kế. Tuy nhiên khi chúng ta kết hợp với Abstraction bằng cách inject các đối tượng abtract, thì chúng ta đã có một bản thiết kế loosely coupling và flexibility.

Dependency inversion principle

Dependency inversion principle là 1 trong 5 nguyên lý thiết kế hướng đối tượng (S.O.L.I.D). Xem thêm tại (https://edwardthienhoang.wordpress.com/2013/11/27/the-dependency-inversion-principle/) Nói đơn giản, Dependency inversion principle giúp chúng ta có được 1 thiết kế loosely coupling Dependency inversion principle = Loosely coupling = Dependency Injection + Abstraction

Inversion of Control (IoC)

Nếu như Dependency inversion là principle thì Inversion of Control là pattern tuân theo principle này. Trong Java, IoC pattern xuất hiện khá nhiều. Lấy 1 ví dụ rất quen thuộc, đó là hàm public static void main(String[] args)

package com.edward.tutorial.di;

public class Main {

    public static void main(String[] args) {
        System.out.println("Developer's dream starts from here");
        doMyWish();
    }

    private static void doMyWish() {
        System.out.println("I wish this app would be the most favourite one in the world");
    }
}

Tất cả các lập trình viên Java đều quá quen thuộc với hàm main này – entry point của 1 chương trình Java truyền thống. Lần này chúng ta sẽ không bàn đến cú pháp, mà bàn đến một việc mà được cho là “chẳng ai quan tâm là mấy”. Câu hỏi là: hàm doMyWish() được gọi bởi hàm main(), vậy hàm main() được gọi bởi hàm nào? Câu trả lời là: Java sẽ gọi hàm main() của chúng ta. Vậy làm thế nào mà Java (chính xác hơn là javac.exe hay đại loại là một cái cao siêu gì đó) có thể gọi được hàm main của chúng ta?

Hollywood principle: “Don’t call us, we’ll call you.”

Dịch nôm na: “Đừng có gọi cho tui, để lại số điện thoại, tui sẽ gọi bạn.” Ngôi sao mà, có quyền chảnh. Nếu nói Java là 1 ngôi sao Hollywood, và hàm main là 1 ai đó, thì việc chúng ta cần làm là nói với ngôi sao đó: “Đây! Địa chỉ của tui đây”. Cung cấp cho Java đường dẫn tới class com.edward.tutorial.di.Main chứa hàm main. Việc còn lại cứ để Java lo, Java sẽ gọi hàm main trong class com.edward.tutorial.di.Main và “Developer’s dream” will be started. LƯU Ý: Hollywood principle chỉ là cách gọi khác của Dependency inversion principle. Thêm 1 ví dụ dễ thấy.

JButton helloButton = new JButton("Hello");
helloButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("I would say Hello to everyone!");
    }
});

Chúng ta không hề gọi hàm actionPerformed(ActionEvent e), mà chỉ khai báo như vậy, và nói: “Hey! Java Swing or EventDispatchThread or something like that, call me when someone click the helloButton”. Một lần nữa, Java sẽ lo việc đó.

Inversion of Control Container (IoC Container)

Chúng ta đã thấy sự tuyệt vời với những đoạn code ở trên, Inversion of Control Container chính là những ngôi sao Hollywood thực thụ, họ định nghĩa ra Hollywood principle, công việc của lập trình viên là: viết ra những đoạn code và nhờ IoC Container đâu là điểm entry point Trong Eclipse, chúng ta dễ dàng config entry point cho 1 chương trình Java tại: Config_Main

Inversion of Control Container Framework (IoC Container Framework)

Trong ứng dụng Java truyền thống, IoC Container có thể được hiểu như những ví dụ ở trên. Tuy nhiên, trong những ứng dụng Java Enterprise, IoC Container mới có nhiều đất diễn, có khá nhiều Framework hỗ trợ IoC Container tạm gọi là IoC Container Framework như: JEE Framework hoặc Spring Framework. Nơi mà những khái niệm về: Dependency Injection, Inversion of Control hay Inversion of Control Container sẽ được nhắc đến như là những Core Feature. Tất cả đều hướng đến một mục đích duy nhất: tạo ra ứng dụng loosely coupling, flexibility cũng như giúp lập trình viên tập trung 99% vào công việc cho business flow.

Loosely coupling và Testing

Một lợi ích không thể nhắc đến khi thiết kế chương trình theo loosely coupling style chính là Testing. Thay vì phải inject những đối tượng thực vào trong SUT (System under test, hay nôm na là class cần test), chúng ta có thể inject các stub đã implement interface vào trong SUT. Chi tiết sẽ được bàn trong bài viết về UnitTesting. :)

Learn from Question&Answer

Có một bạn hỏi như sau:
Nói về chủ đề này, với DI thì ok. Bài viết này của anh khá sâu, tuy nhiên phần ioc lại chưa đc rõ rằng lắm. Vẫn còn khá chung chung. A có thể giải thích cho em vài vấn đề sau. Giữa DI và ioc
1. Thằng nào là con thằng nào?. Quan điểm con của nhau có đúng ko?.
2. Theo em đc biết, DI là 1 design pattern xây dựng lên để đáp ứng cho tính lỏng lẻo, giảm sự liên kết phụ thuộc và khi đó IoC chính là thằng thực hiện theo cái DI đó, nó sẽ sử dụng BeanFactory và ApplicationContext để thao tác lấy thông tin từ XML xử lý, tạo đối tượng. Khi đó, với quan điểm của em thì em nghĩ chẳng thằng nào là con thằng nào cả.

Answer:
Một câu hỏi khá hay. Trong cái thắc mắc của em đã trả lời luôn rồi.
Đúng như em nói: DI là 1 Design Pattern “để đáp ứng cho tính lỏng lẻo, giảm sự liên kết phụ thuộc”. IoC thì rộng hơn, và thường đi liền với Framework. Framework sẽ invert và control phần xương sống của application được develop bên trên, và “chừa”, “cung cấp” 1 số “cổng” để developer có thể inject phần implement của mình vào application. (Inject ở đây có 2 cách hiểu như 2 ví dụ dưới đây.

1. BeanFactory và ApplicationContext: em đang nói đến Spring Framework, vậy đó, Spring cho phép em inject các implementation của mình vào application qua ApplicationContext và 1 số Bean XML. Rõ ràng, DI được dùng để làm chuyện này thông qua @Autowired hay @Inject (CDI)

2. Tuy nhiên, trong bài viết của anh còn đề cập đến một chuyện đơn giản hơn. Đó là Java Swing Framework. Swing cho phép chúng ta định nghĩa ra “những action to be peformed” khi 1 event cụ thể được fired. Còn việc fire đó sẽ do Swing chứ ko phải do mình. DI không được dùng trong đây, nghĩa là Swing không cần đến pattern DI mà vẫn làm được việc Invertion of Control.
Từ 2 ví dụ trên có thể cho em hiểu Invertion Of Control là gì và mối quan hệ với DI rồi nhé.

Kết thúc bài tại đây, hi vọng trong giới hạn hiểu biết cùng với cách giải thích của mình sẽ giúp các bạn có thêm 1 cái nhìn khác về các khái niệm: Dependency Injection, Dependency Inversion Principle, IoC.. Trong những bài sau, chúng ta sẽ bàn luận về IoC Container trong Spring Framework. Happy learning

NGUỒN: HTTP://EDWARDTHIENHOANG.WORDPRESS.COM/ EMAIL: EDWARDTHIENHOANG@GMAIL.COM

Đôi nét về Internet of Thing

Khi mà cuộc sống của con người chúng ta ngày càng có những mối quan hệ chặt chẽ với Internet thì sự phát triển của nó rất được quan tâm. Hãy cùng tìm hiểu đôi nét về một trong những xu hướng phát triển của công nghệ hiện nay mang tên Internet of Thing

Các bạn đã từng đọc, từng nghe những câu chuyện về ngôi nhà thông minh, nơi các máy nướng bánh có thể “giao tiếp” với máy hút khói. Nhưng chúng kết nối với nhau bằng cách nào? Khi nào nó sẽ trở thành xu hướng chủ đạo trong cuộc sống và thực sự trở nên hữu ích? Những câu hỏi thường gặp mà chúng tôi giải thích dưới đây sẽ giúp bạn có cái nhìn tổng quát nhất về khái niệm này.

Internet of Things là gì?Internet of Thing

Cho đến nay, vẫn chưa có một định nghĩa chính xác nào về cụm từ Internet of Things (IoT) – Vật dụng kết nối Internet. Nhưng thật ra, vẫn có những cách để xác định liệu một thứ gì đó có phải là một phần của IoT hay không Hãy đặt ra những câu hỏi sau: Liệu một sản phẩm của một nhà sản xuất nào đó có hoạt động tương thích với sản phẩm của một nhà cung cấp khác không? Liệu một bộ khóa cửa thông minh của hãng này có thể giao tiếp với công tắc đèn thông minh của hãng khác, hoặc tất cả những thứ đó có thể kết nối với bộ cảm biến nhiệt đến từ một hãng sản xuất khác nữa?

Để dễ hiểu hơn, hãy thử tưởng tượng về hệ thống sau: Khi bạn đến gần cửa trước của ngôi nhà, một bộ điều khiển từ xa được tích hợp vào chìa khóa sẽ mở cửa. Thông điệp phát ra từ ổ khóa sẽ khiến đèn hành lang bật sáng. Hệ thống điều khiển nhiệt trong nhà vốn đang hoạt động ở chế độ tiết kiệm điện (hoặc tắt hẳn), sẽ điều chỉnh nhiệt độ ở mức thoải mái nhất. Tất cả mọi thứ đều hoạt động nhịp nhàng như một buổi hòa nhạc. Theo đó, định nghĩa này hoàn toàn giống với mô tả của Paul Williamson, Giám đốc về công nghệ dây công suất thấp của nhà sản xuất chíp bán dẫn CSR: “Internet of Things thực sự là sự phối hợp nhịp nhàng giữa nhiều thiết bị với nhau”.

Điều gì có thể làm cho Internet of Thing có thể biến đổi theo hoàn cảnh?

Chỉ trong một từ: Cảm biến. Nhiều thiết bị IoT có các loại cảm biến có thể ghi nhận sự thay đổi nhiệt độ, ánh sáng, áp lực, âm thanh và chuyển động. Những thứ đó cũng tương tự như đôi mắt và đôi tai của bạn với những gì đang xảy ra trên thế giới.

Trước khi nói về những gì các cảm biến này làm được, chúng ta hãy mô tả chúng. Các cảm biến này là thuộc danh mục các thiết bị hệ thống vi cơ điện tử (Microelectromechanical System – MEMS) và được sản xuất tương tự như việc làm ra các bộ vi xử lý, thông qua một quá trình in thạch bản. Các cảm biến này có thể kết hợp với một mạch ứng dụng tích hợp cụ thể hoặc một ASIC. Đây là một mạch với khả năng lập trình hạn chế về và được điều khiển để làm một thứ gì đó cụ thể. Nó cũng có thể được kết hợp với bộ vi xử lý và có thể gắn liền với radio không dây cho truyền thông.

Một ví dụ về cách mà IoT làm việc?

Hãy tưởng tượng: Bạn đang đi nghỉ và để nhà trống. Một cảm biến độ ẩm sẽ phát hiện nước trên sàn tầng hầm. Cảm biến đó được xử lý bởi một ứng dụng – vốn cũng nhận được báo cáo khác từ cảm biến nhiệt độ phát hiện dòng chảy của nước trong đường ống nước chính (khi nước chảy, nó mất đi nhiệt và làm giảm nhiệt độ).

Cả 2 cảm biến đó đều phát hiện ra những dấu hiệu bất thường đáng quan tâm. Tỉ lệ nước rò rỉ cao có thể là dấu hiệu của việc hư hại ống dẫn, sẽ khiến các van nước tự độn ngắt. Lưu lượng nước nhỏ có thể do nhà vệ sinh bị rò rỉ, hoặc do nhà bạn vừa trải qua trận mưa lớn. Trong cả hai trường hợp, bạn đều nhận được tin nhắn tự động mô tả lại những phát hiện đó.

Và đây là cách bạn điều tra về những trường hợp đó. Thông qua một ứng dụng di động, bạn sẽ có hai mã khóa dùng một lần để mở khóa cửa trước, một cho hàng xóm và một cho một thợ sửa ống nước. Khi cánh cửa được mở khóa, một cảnh báo văn bản sẽ được gởi đến bạn về những người vừa sử dụng mã để vào nhà. Việc luôn luôn theo dõi và thấu hiểu chính căn nhà của bạn chính là lợi ích lớn nhất của IoT.

Cảm biến của IoT hoạt động thế nào ở không gian công cộng?

Ở những bãi đậu xe công cộng của những nước phát triển. Công nghệ được thực hiện bởi hãng Streetline có thể phát hiện và thông báo cho tài xế biết vị trí đậu gần đó. Tài xế đang tìm kiếm chỗ đậu xe có thể sử dụng ứng dụng trên smartphone của hãng này để dò các điểm đậu xe đang trống, hoặc được thông báo khi nào xuất hiện chỗ trống gần đó.

Ở các khu vực công cộng, một chiếc smartphone có thể sẽ rất hữu ích. Ở Boston, khi người ta lái xe xuống đường, cảm biến gia tốc của điện thoại sẽ bắt đầu theo dõi. Cám biến này sẽ theo dõi chính xác các hoạt động tăng – giảm tốc độ khi lái xe của chủ nhân, và trở thành một công cụ giám sát hành trình. Đó là một cách rất mới để sử dụng chiếc smartphone của bạn.

Bạn có muốn phòng tắm “nói chuyện” được với chiếc tủ lạnh?

IoT mở ra rất nhiều cơ hội cho các nhà lập trình ứng dụng. Hãy bắt đầu với một chiếc tủ lạnh thông minh. Bạn mua từ cửa hàng tạp hóa trực tuyến và họ đã gửi hàng đến tận nhà bạn. Một lợi thế rất lớn của lĩnh vực này là các cửa hàng thực phẩm và các nhà sản xuất thực phẩm có thể thêm các thẻ RFID vào những sản phẩm được bán ra của họ. Tủ lạnh thông minh sẽ biết những gì đang có bên trong nó thông qua các kệ chứa có cảm biến cân nặng và giao tiếp với các thẻ RFID đó để biết ngày hết hạn của thực phẩm. Nó cũng có thể giúp bạn giữ một danh sách mua hàng, tự động đặt hàng và cung cấp thông tin dinh dưỡng.

Ví dụ, giả sử khi bạn quyết định lấy một que kem ngon lành ra khỏi tủ đông. Khi điều đó xảy ra, một loa không dây kết nối với tủ lạnh sẽ thông báo lớn: “Hãy xem xét lại lựa chọn này. Theo yêu cầu của bạn, đây là thứ có thể ảnh hưởng đến trọng lượng và chỉ số đo hình thể của bạn”. Loa không dây này sẽ có kết nối với cái cân thông minh mà bạn đặt trong phòng tắm. Tất nhiên, cái cân đó ko kết nối trực tiếp với tủ lạnh, mà giao tiếp với ứng dụng trung gian có nhiệm vụ thu thập, liên kết và đánh giá dữ liệu. Kết hợp cái cân với tủ lạnh nghe có vẻ ngớ ngẩn, nhưng lại là đặc điểm lớn của IoT: Mọi thứ đều có thể kết nối và tạo ra những chức năng mới.

Các thiết bị IoT giao tiếp với nhau như thế nào?

Một thiết bị IoT sẽ có bộ phận phát sóng không dây để có thể gửi và nhận thông tin liên lạc. Giao thức không dây IoT được thiết kế để thực hiện một số dịch vụ cơ bản: vận hành trên điện năng thấp, sử dụng băng thông thấp và làm việc trên một mạng lưới. Một số thứ được thực hiện trên băng tần 2,4 GHz hoặc Wi-Fi và Bluetooth, và các tần số phụ GHz. Các tần số phụ GHz bao gồm 868 và 915 MHz, có thể có lợi thế ít can thiệp.

Vì sao điện năng và băng thông thấp lại quan trọng với IoT?

Một số thiết bị IoT sẽ phải sử dụng hệ thống điện, chẳng hạn như ổ khóa cửa, trong khi các cảm biến độc lập sẽ sử dụng pin. Các thiết bị này gửi và nhận lượng nhỏ thông tin liên tục hoặc định kỳ. Do đó, tuổi thọ pin của một thiết bị IoT có thể dao động từ 1,5 năm đến một thập kỷ. Một nhà sản xuất thiết bị IoT, Insteon, sử dụng cả 2 cách thức giao tiếp là radio và hệ thống điện. Việc sử dụng cả 2 cách thức giao tiếp này sẽ giúp thiết bị IoT gia tăng độ tin cậy.

Vai trò của Bluetooth trong IoT?

Công nghệ Bluetooth Low Energy thích hợp với công nghệ thiết bị đeo người, bởi sự giới hạn kết nối khiến nó không phù hợp với diện rộng của các vật dụng IoT. Nhưng vào đầu năm 2014, CSR, một hãng sản xuất chất bán dẫn, đã công bố một giao thức kết nối Bluetooth mới có thể kết nối với hàng ngàn thứ.

Việc Bluetooth có mặt khắp trong các thiết bị di động, kết hợp với công nghệ Bluetooth mới sẽ tạo ra một nền tảng vô cùng có lợi cho IoT. Nếu trong phạm vi của căn nhà, Bluetooth sẽ biến chiếc smartphone thành một trung tâm điều khiển. Mặt khác, nếu bạn rời xa nhà, như đi làm chẳng hạn, thì công nghệ này là hoàn toàn vô dụng.

Theo Computerworld

We Are Complicating Things a Bit too Much (TDD & DDD)

The other day, I saw something that really encompasses one of the biggest hurdles for younger developers to get through. That hurdle is terminology. These days, there is all sorts of “___ driven development”. In our team, we even joke about “assumption driven development”.

Naming things is one of the hardest things to deal with in programming. It gets worse when we are doing something that is uncomfortable. Make it worse, before we ever started programming there are tons of people who have already named things (and naming things was hard for them too).

And see, this is where we as a community come in and can help people understand things a lot easier. Of course it doesn’t hurt if we don’t muck up some serious patterns and terminology even more (no I’m not talking about Facades, the argument over that hurt the community more).

All The Driven Development

One of the big things that bothered me the other day was hearing someone say “you thought TDD was hard, wait until you change over to using DDD”. Maybe it was out of context, but I think that at heart, a lot of young developers (especially those that are freelancing or the most senior on a small young team) get confused. It used to be information on software patterns was a bit more limited: you hear something from a close coworker, that one message board you subscribe to, a professor, a senior dev, etc then you use it. Now, we face massively social communities where everyone spouts their ideas on Twitter, G+, SO, and more. A developer that would have been slowly introduced to design patterns, Extreme Programming/Agile Development, and best practices are instead bombarded with everything at once.

So I hope to clarify some confusion of thinking that TDD (Test Driven Development) and DDD (Domain Driven Development) are somehow in competition or mutually exclusive. They aren’t in fact! So I’ll dig in to what I’ve taken out of the two methods and where they fit together.

What Is TDD

TDD is the process of writing tests based on a particular desired pieced of functionality, letting them fail. Then you write the least amount of code possible to make the test pass, then write another test. Cycle this over and over until you have finished a feature and then go back and refactor. It’s a bit simplified, I know, but this is the heart of TDD. Don’t get stuck in the mud about it! Don’t worry about techniques, code structure, etc.

Don’t let people fool you!

TDD is just the process of testing code before writing it!

What Is DDD

DDD takes a bit more explaining. You see, a Domain is a set of functionality that you are attempting to mimic that lies outside of your application. Maybe this is a physical event like an election, maybe it’s something a bit more arbitrary such as a source code project initializer. You will want to assign a Domain Expert, this could be your project manager, yourself when you put on your spec writing hat for a new side project (that is really dangerous though), but most likely, your Domain Expert will be your client. The point is, to create something, you must first understand what it is you are trying to create! DDD describes the process of consulting and deciding on explicit definitions of each piece of the domain that you are trying to mimic. And you make sure that these definitions are written before ever writing code. Then these definitions and naming structures from your domain study are used to create a more informed code base. Then when you pick your head up for the next change, error, fix, whatever: you consult with the Domain Expert and turn programming talk back into the Domain terminology.

Don’t let people fool you!

DDD is the process of being informed about the Domain before each cycle of touching code!

Mixing the Two Together

Alright, so now lets see WILL IT BLEND!? That is the question. DDD lives mostly in how you research before coding, how you name things, and how you interact with the client. On the other hand, TDD is the process of actually writing your code. So, as you can see, there is no conflict of interest between the two strategies and they fit together quite well.

Ok, I Lied… A Bit…

If you read Eric Evan’s book on Domain Driven Development and Martin Fowler’s Blog, you will see that their process of Domain Driven Development goes beyond just getting an informed view of the domain and describing it with “ubiquitous language”. They include code coverage, continuous integration, a testing strategy, and code organization as part of the DDD life cycle. While these things do happen between getting domain information from a client before coding and then translating things back to the domain expert, I’m not so sure that these are really part of DDD. Let me explain.

If as good programmers (and good DDD programmers at that), we decide to break things down into their unique single role parts we’d see a few things when examining the formation of the DDD mindset. First, is that it borrows heavily from Extreme Programming. EP was a multi pronged approach to developing software in a more iterative and maintainable fashion. It included planning phases, writing tests, using continuous integration, and more. EP claimed that code was the most important thing in a software project, and developers should be prepared to code efficiently.

Evan’s came in and took a lot from the toolbelt in front of him and created his own method to attacking software problems and he put understanding the domain first. This meant that while code was still really important, the best code in the world is only as good as the understanding of the problem you are trying to solve. At the end of the day, what makes Evan’s process unique was the communication with a Domain Expert. It’s this communication that I would argue IS DDD. Everything else was slight modifications on existing techniques.

A Word On Code Structure

I made a point that TDD as a philosophy doesn’t care how you structure your code. There are those that would probably think that this transfers to DDD as well. Unfortunately it’s a bit stranger than that. While the simplified view of DDD makes me want to say that code structure isn’t part of DDD, I can’t really tell you that. With a deep understanding of the domain and wanting to mimic the domain within the code base, your code structure will and should be influenced. Also on the other side of things, it makes the translation of software output to the domain expert much easier for you: if you are stuck remembering how this SuperDuperSoftwarePatternThing relates back to your domain, you aren’t doing yourself any favors. Stick with efficiency and mimic the language you set up when talking with the client. If things are hard to structure, that’s a sign that you may not understand the specifications for the different actors in the domain.

A Word On BDD

BDD is an implementation of TDD which brings in some aspects of DDD. BDD focuses on how to name tests and instructs that tests should start from outside interaction in. For instance if you want to go to a page and see some blog posts you’d write the test for the route, say “hey I want to see some posts”, then you’ll say “I need to get some posts from somewhere”, then keep going until collide with unit tests at the low level.

BDD also goes to the effort of giving a more conversational way of writing tests. Since many tests start from the outside of a system and work their way in, BDD lends itself well to testing a pass or fail condition for a user story or feature. This means that you describe what actors are setting up a feature to be tested and then what result is to be expected. If you caught that, you may see that BDD lends itself as a TDD strategy for teams that have a solid domain definition from DDD. BDD is also often heralded because BDD testing tools can be arguably more human readable to non-developers such as Domain Experts.

http://ryantablada.com/post/we-are-complicating-things-a-bit-too-much-(tdd-and-ddd)

Working Effectively with Legacy Code (Robert C. Martin Series)

Thêm 1 cuốn sách gối đầu cho lập trình viên, đặc biệt với những ai đang làm trên legacy system. Mọi câu hỏi, khó khăn hay những cách làm việc ưu việt với legacy code sẽ được tác giả giải đáp trong suốt 25 chương của cuốn sách này. :)

LegacyCode

From Amazon

Get more out of your legacy systems: more performance, functionality, reliability, and manageability

Is your code easy to change? Can you get nearly instantaneous feedback when you do change it? Do you understand it? If the answer to any of these questions is no, you have legacy code, and it is draining time and money away from your development efforts.

In this book, Michael Feathers offers start-to-finish strategies for working more effectively with large, untested legacy code bases. This book draws on material Michael created for his renowned Object Mentor seminars: techniques Michael has used in mentoring to help hundreds of developers, technical managers, and testers bring their legacy systems under control.

The topics covered include

  • Understanding the mechanics of software change: adding features, fixing bugs, improving design, optimizing performance
  • Getting legacy code into a test harness
  • Writing tests that protect you against introducing new problems
  • Techniques that can be used with any language or platform—with examples in Java, C++, C, and C#
  • Accurately identifying where code changes need to be made
  • Coping with legacy systems that aren’t object-oriented
  • Handling applications that don’t seem to have any structure

This book also includes a catalog of twenty-four dependency-breaking techniques that help you work with program elements in isolation and make safer changes.

 

Link download ePub:

https://drive.google.com/file/d/0BxrbqNV1YSlmckpLZW9Wc0tKNVk/view?usp=sharing

I Don’t Write Unit Tests Because…. : The Excuses

Print

As someone who’s seen the benefits of the approach, I’m a huge believer in test driven development. It adds a level of quality and maturity to the field of software development, yet it’s still not a widespread practice across development projects. When it comes to a choice between the features, time and quality, it’s always the quality that suffers. We don’t want to add extra time for testing and we don’t want to compromise on the feature set of the delivery. If you haven’t set out to do test driven development at the start of the phase, then it’s difficult to fit in.

We’ve all heard excuses for not taking the test driven approach, but nowhere compiles them better than “Pragmatic Unit Testing in Java With JUnit“, from the Pragmatic Bookshelf.  I read the book a few years ago, and afterward I thought there was no way that any responsible developer could read the book without truly believing that unit tests were one of the most important aspects of the development activity.

The most worrying excuse I’ve heard is that it’s too difficult to test my code. This can be for one of two reasons. One is that your code is mainly UI related, and automating the UI tests is too difficult. I’ll concede that UI automation is a tricky area (but not impossible, as we’ll see in a later article), but every effort should be made to automate it if possible: think about regression tests. If you have a fully automated test suite, including the UI behaviour, you can make a change to your code, and have full confidence that you haven’t broken anything if you have tests to re-run.

The second reason that your code is too difficult to test is that you’ve messed up your design. Maybe your logic and UI code are too tightly coupled, and without that automated UI layer existing, the dependency between the logic and the UI will cause a problem. This is where test driven development helps to ensure a clean design, following best practices. Using JUnit is simple, so if I can just point my test at a clean logic layer, I can test all logic that the UI will ever touch.  What’s that? You’re missing your data model? Well then just use mock objects – there are many frameworks for that!

For those who haven’t read the book yet, I’ll give a quick summary of the excuses for not testing as outlined in the introduction chapter:

I don’t have time to unit test.
Really? But you have to time to fix your mistakes later?  The simple fact is that nobody, not even you, can write bug free code.  Unit tests greatly speed up the time it takes to identify a bug because they narrow the suspect code down to a very specific unit.  Other types of testing, such as Quality Assurance or User Acceptance Testing, identify problems at a much higher level, forcing the developer to spend extra time plodding through the various units looking for the root cause. Unit tests can also serve as verification that the bug is corrected without having to go through the hassle of creating a new application build and deploying it for further testing.  Simply put, unit tests speed up overall development.  It might take slightly longer to create each new feature, but the development time for the entire application, from inception to delivery, is considerable shorter.
The client pays me to develop code, not write unit test.
News Flash – Unit tests are code.  They are as integral to the application as any other piece of code you are writing, and should be included in the original estimate and statement of work.  It might also help to mention to the client that unit tests lower both development cost (see previous excuse) as well as maintenance cost.  If you are not writing unit tests, then you are doing your client an injustice by forcing them to incur extra expense.
I am supporting a legacy application without unit tests.
That still doesn’t preclude you from writing your own.  Granted, you are not going to be able to go in and write tests to bring the entire code base up to an acceptable level of coverage.  You most likely don’t have the time or resources to do that.  But as support issues are raised, write the unit tests for any code that you modify.  When I am working on a support task, one of the very first things I do is write a unit test to recreate the bug.  When the unit test starts passing, I know that I have fixed the problem.  Now, not only have I resolved a bug, but I have added some unit test coverage to the code base.  Over time, this coverage will become more and more robust, and actually reduce future maintenance costs by preventing the introduction of regression bugs.
QA and User Acceptance Testing is far more effective in finding bugs.
No arguments there.  But Unit Testing is far more effective at preventing bugs.  Just because my smoke alarm is better at detecting potential fires doesn’t mean that it is safe to leave the stove on all the time.  QA and UAT are smoke alarms – they alert you to potential existing trouble.  Unit testing is turning off the stove when you are done – it helps you prevent trouble.  Unit testing, QA, and UAT are all important parts of the testing process, and they each play very different roles.  Trying to replace one with another doesn’t work.  I wouldn’t release a project that was well unit tested without QA, and I wouldn’t release a project that was thoroughly QA’ed without unit testing.
I don’t know how to unit test, or I don’t know how to write good unit tests.
Well, this is probably the most valid excuse that is out there.  The sad truth is that a great many number of developers and engineers do not know how to unit test.  I didn’t when I started.  And nothing discourages a developer more than struggling to write bad unit tests.  Luckily there are resources out there.  There are so many books, webinars, conference presentations, blogs, etc on writing good unit tests that the inability to write them simply isn’t going to cut it as an excuse any more.  When someone offers me this excuse, I don’t look at it as a roadblock, but rather as a teachable moment.  It usually only takes a time or two of seeing how well written unit tests can help one develop code to turn them from the dark side…

Are there other excuses out there?  Absolutely.  But they are just that – excuses.  I have yet to encounter a valid reason to skip unit testing.  If you think you have one, post it here.  I look forward to the challenge of changing your mind! :)

http://www.sundoginteractive.com/sunblog/posts/top-five-excuses-for-not-unit-testing