Tuyệt chiêu tối ưu code Java khi lập trình Android

2
330

Tuyệt chiêu tối ưu code Java khi lập trình Android

Có thể nói rằng Effective Java là một trong những cuốn sách thật sự nổi danh và còn là một trong những cuốn “bí kíp” quan trọng nhất để các nhà developer hay dùng để gối đầu giường cho mỗi giấc ngủ. Và ngoài ra còn dùng để tham khảo cách viết code Java cho những dự án có khả năng maintaince hiệu quả nhất. Phần lớn hệ điều hành Android sử dụng Java là ngôn ngữ chính để xây dựng và phát triển tầng ứng dụng và Framework. Vì thế đa số các lời khuyên trong cuốn sách này đều phù hợp với các bạn, điều này có phải luôn đúng? Thế nhưng thực tế lại có một số người cho rằng khá nhiều lời khuyên đưa ra trong cuốn sách khó có thể ứng dụng vào lập trình Android. Tuy nhiên điều này chẳng ai công nhận cả 🙂

Vậy nên nghe theo ý kiến nào là đúng đây? Ơn giời!

Kinh nghiệm của mình rút ra khi lập trình Android

Theo kinh nghiệm của bản thân thì một số kiến thức được đưa ra trong cuốn sách này chưa thực sự phù hợp cho lập trình android vì không hẳn hầu hết các tính năng của Java đều được tối ưu nhằm sử dụng cho lập trình android chẳng hạn như Enums, Serialization… hoặc những cơ chế trên các thiết bị di động như máy ảo Davik/ART hoạt động khác so với JVM trên PC. Tuy nhiên phần lớn các mô hình được đưa ra trong sách có thể ứng dụng trong quá trình làm cho mã nguồn “sạch sẽ”và dễ maintaince hơn (thuật ngữ chuyên ngành như chúng ta đã biết là more cleaner and more maintainable)

Mình không có ý định liệt kê toàn bộ những lời khuyên trong cuốn sách mà mình chỉ tập trung vào những gì tinh túy nhất của cuốn sách và hầu hết các lời khuyên này đều có thế ứng dụng rất tốt trong việc phát triển ứng dụng Android. Với các bạn đã từng đọc qua cuốn sách này thì đây chính là cơ hội để mọi người nhớ lại các “bí kíp” văn ôn võ luyện. Còn các bạn nào chưa từng đọc qua sách này thì xin chúc mừng bạn, đây chính là một trong những bí kíp nổi tiếng nhất trong giới võ lâm “Như lai thần chưởng” nhằm mục đích tu thành chánh đạo “Coding thập bát chưởng” đấy nhé.

Force non-instantiability

Nếu bạn không muốn một Object được tạo bằng từ khóa NEW thì hãy sử dụng Private constructor. Việc ứng dụng này đặc biệt hữu ích cho các Class chỉ chứa các hàm static và với các bạn Android Developer rất hay dùng method static trong các Utils class.

class MovieUtils {
    private MovieUtils() {}
    static String titleAndYear(Movie movie) {
    [...]
    }
}

Static Factories

Nhằm mục đích để đóng gói Object và hạn chế việc truy cập từ bên ngoài, lấy một ví dụ cụ thể để bạn dễ hiểu hơn như trong trường hợp chúng ta cố gắng tránh việc cung cấp cách thức truy cập trực tiếp vào Database bởi vì tốn rất nhiều tài nguyên. Do đó, đây chính là thời điểm mà chúng ta cần nghĩ đến việc ứng dụng Static Fatory Method. Trong đó, những hàm Factory Methods này có thể đặt tên khác với các hàm Constructor và tên Class (mặc định tên hàm Constructor chính là tên của Class). Ngoài ra, chúng không bị áp đặt bắt buộc phải trả về một Instance của Object trong mỗi lần gọi. Ngoài ra, bạn có thể bấm trả về một Subtype khác tùy thuộc vào mục đích bạn sử dụng.

class Movie {

    [...]

    public static Movie create(String title) {

    return new Movie(title);

    }

}
Lưu ý: Việc ứng dụng Static Factories Methods có thể gây nhiều trở ngại trong quá trình testing. Nếu chẳng may vướn vào trường hợp này, bạn có thể xem xét sử dụng Non-static Factories Methods hoặc Factory Interface để dễ dàngtạo raMock Test hơn.

Builders

Nếu trường hợp bạn sở hữu một Object nhưng yêu cầu cần đến hơn 3 tham số trong hàm Constructor để tạo một Instance, lúc này bạn nên thử với Builder nhằm khởi tạo Object cũng giống như cách lập trình android thiết kế Dialog, cũng dùng Builder để tạo Dialog. Tuy nhiên, phải công nhận cách viết này cần khá nhiều dòng code nhưng ngược lại phần code sẽ rất dễ đọc và mở rộng hơn.

class Movie {
    static Builder newBuilder() {
        return new Builder();
    }
    static class Builder {
        String title;
        Builder withTitle(String title) {
            this.title = title;
            return this;
        }
        Movie build() {
            return new Movie(title);
        }
    }

    private Movie(String title) {
    [...]    
    }
}
// Use like this:
Movie matrix = Movie.newBuilder().withTitle("The Matrix").build();

Static member classes

Đừng quên khái niệm Static Class nếu như các bạn đang cần define một Inner Class mà không muốn phụ thuộc hay liên quan đến Outer Class. Lý do nào khiến bạn phải làm như thế? Bởi vì nếu không làm như vậy thì rất dễ dẫn đến việc mỗi Instance của Inner class sẽ được references đến Outer Class, điều này thực sự sẽ mang đến nhiều phiền toái và có thể bị Memory Leak.

class Movie {
    [...]
    static class MovieAward {
        [...]
    }
}

Generics (almost) everywhere

Các bạn nên đánh giá cao và biết ơn về việc Java cung cấp một cơ chế gọi là Type-safety. Đây là cơ chế luôn giúp giảm đi tình trạng sử dụng Raw Types hay Object ít nhất có thể. Điều đó sẽ giúp cho phần Code của bạn sẽ được hạn chế bớt lỗi sai khi biên dịch.

// DON'T
List movies = Lists.newArrayList();
movies.add("Hello!");
[...]
String movie = (String) movies.get(0);

// DO
List<String> movies = Lists.newArrayList();
movies.add("Hello!");
[...]
String movie = movies.get(0);

// DON'T
List sort(List input) {
    [...]
}

// DO
<T> List<T> sort(List<T> input) {
    [...]
}

Để Code có thể linh hoạt(flexible) hơn, bạn có thể sử dụng Bounded Wildcards (tạm dịch là“Ký hiệu đại diện”) nhằm mở rộng kiểu trả về mà bạn có thể chấp nhận được.

// Read stuff from collection - use "extends"
void readList(List<? extends Movie> movieList) {
    for (Movie movie : movieList) {
        System.out.print(movie.getTitle());
        [...]
    }
}

// Write stuff to collection - use "super"
void writeList(List<? super Movie> movieList) {
    movieList.add(Movie.create("Se7en"));
    [...]
}

Return empty

Theo kinh nghiệm bản thân, nếu một hàm bắt buộc trả về một List/Collection, tôi khuyên các bạn nên trả về một Collection rỗng thay thế cho việc trả về kết quả NULL. Đây là cách tốt nhất giúp bạn hạn chế việc guide cho người sử dụng lại hàm đó cần phải xử lý NULL ngược lại nếu không làm sẽ dẫn đến NPE(NullPointerException).

List<Movie> latestMovies() {
    if (db.query().isEmpty()) {
        return Collections.emptyList();
    }
    [...]
}

No + String

Trong trường hợp các bạn cần phải ghép nối nhiều String trở thành một String duy nhất thì cách tốt nhất là hạn chế tối đa sử dụng toán tử “+” vì chúng có thể giảm hiệu suất. Thay vì đó, các bạn nên sử dụng StringBuilder.

String latestMovieOneLiner(List<Movie> movies) {
    StringBuilder sb = new StringBuilder();
    for (Movie movie : movies) {
        sb.append(movie);
    }
    return sb.toString();
}

Recoverable exceptions

Nếu trước đây bạn có thói quen xử lý Exception qua loa bằng cách Throw Exceptions, mặc kệ Class “cha ” xử lý thế nào cũng không quan trọng thì chắc chắn ứng dụng của bạn sẽ rất dễ rơi vào trạng thái thông báo error một cách chung chung cho người dùng. Do đó, khá nhiều người dùng thường feedback chỉ biết rằng ứng dụng đã có lỗi nhưng không hiểu rõ được lỗi gì và cách xử lý thế nào. Vì vậy, các bạn nên tập thói quen cụ thể hóa khi nào thì Exception này xảy ra và thông báo lỗi như nào. Tránh việc gây khó chịu cho người dùng mà ngay cả Developer cũng sẽ khó tìm và sửa lỗi ứng dụng.

List<Movie> latestMovies() throws MoviesNotFoundException {
    if (db.query().isEmpty()) {
        throw new MoviesNotFoundException();
    }
    [...]
}

Kết luận

Theo cách nhìn của bản thân, bài viết này đơn thuần là nơi tổng hợp những lời khuyên phù hợp nhất cho lập trình Android và giải thích ngắn gọn nhất có mà cá nhân mình cảm thấy thực sự tâm đắc khi đọc qua cuốn sách Effective Java. Mong rằng bài viết sẽ có thể giúp ích phần nào cho những người anh em trong ngành có thể dễ dàng xử lý công việc và cũng như trong quá trình nghiên cứu học tập. Nếu thông tin trong bài viết còn điểm nào còn thiếu sót, hi vọng các anh em gửi cho mình feedback và thông tin bổ sung để mình có thể cập nhật nhanh chóng kiến thức mới nhất cho các anh em khác nhé.

Chào thân ái các chiến hữu và hẹn gặp lại !!!

 

2
Bình luận. Đặt câu hỏi cũng là một cách học

avatar
2 Bình luận
0 Trả lời
0 Theo dõi
 
Bình luận hay nhất
Bình luận hay nhất
2 Độc giả
TVDTrần Long Độc giả vừa bình luận
  Theo dõi bình luận  
Mới nhất Cũ nhất Nhiều voted nhất
Thông báo
Trần Long
Guest
Trần Long

Hay quá. Cám ơn tác giả nhé

TVD
Guest

Cảm ơn bạn đã chia sẻ!