Senior & Junior Java Dev – điều gì làm nên sự khác biệt

Bài viết được sự cho phép của tác giả Kiên Nguyễn

Đối với nghề lập trình viên, kinh nghiệm code là cực kì quan trọng. Nhìn vào một đoạn code, người làm lâu năm có thể nhìn ra đó là đoạn code của Senior Java hay Junior Java. Cũng chẳng phải ngẫu nhiên lại có sự chênh lệch mức lương giữa 2 rank này. =)))

  10 Java Web Framework tốt nhất
  10 lý do cho thấy tại sao bạn nên theo học ngôn ngữ lập trình Java

Xem thêm các việc làm Java hấp dẫn trên TopDev

Đơn giản thôi: Have no idea.

Để cố gắng trở thành Senior, bản thân chúng ta phải luôn luôn học hỏitrau dồi kiến thức. May mắn thay, ngay từ những ngày đầu lọ mọ code từng dòng code, mình đã được sư phụ chỉ cho vài đường cơ bản, tiện đây muốn chia sẻ với các bạn.

Bài viết này mình được sư phụ đầu tiên của mình viết cho. Anh Lương Nguyễn Trung (Senior Java Developer).

1. Kiểm tra NULL (CHECK NULL).

Java NULL, vấn đề muôn thủa. Một Senior với kinh nghiệm code dồi dào sẽ biết cách phòng tránh, hạn chế các trường hợp dẫn tới NullPointerException.

Senior sẽ luôn biết cách phòng tránh Java NullPointerException.But when i do. So funny!.

Một trong những lỗi thường gặp nhất của những bạn mới đó là thiếu kiểm tra Object có phải là NULL hay không.

Thay vì sử dụng những Object này một cách trực tiếp để thực hiện xử lý (cộng trừ nhân chia, cắt chuỗi, nối chuỗi, getLength size…)

Hãy tạo ra những hàm common, trong những hàm này sẽ thực hiện việc kiểm tra giá trị NULL, và thực hiện sử lý tương ứng.

BAD CODE:

public String StringUtil.nullToEmpty(String str) { 
if (str == null) { 
return ""; 
} 
return str; 
}

GOOD CODE:

public String StringUtil.substring(String str, int start, int len) { 
str = nullToEmpty(str); 
// Luôn thực hiện kiểm tra độ dài trước khi substring. 
if (str.length() > len) { 
return str.substring(start, len); 
} 
return str.substring(start); 
}

Mặc dù là nỗi sợ hãi thường trực của các Java Dev, null cũng có đôi điều thú vị. Các bạn có thể đọc thêm ở bài viết này.

2. Sử dụng toán tử cộng trừ nhân chia.

Khi thực hiện cộng trừ nhân chia, trường hợp nếu sử dụng kiểu dữ liệu là Long, Double,… sẽ có trường hợp giá trị trả về bị sai

Decimal dec1 = 4; 
Decimal dec2 = 2; 
Decimal dec3 = dec1 / dec2;

-> Đúng ra, giá dec3 sẽ có giá trị là 2 
Tuy nhiên, trong một vài trường hợp dec3 sẽ có giá trị là 2.0000…1 hoặc 1.99999…9 
Do đó, nếu ta dùng giá trị dec3 để đi so sánh với 2, giá trị sẽ trả về là FALSE

Trường hợp này, nên sử dụng để tính toán. Kì công hơn, hãy tạo class NumberUtil để sử lý việc cộng trừ nhân chia, làm tròn, compare giá trị, format kiểu số…

3. Khai báo biến bên ngoài IF FOR WHILE.

String str; 
for (int i = 0; i < strList.size(); i++) { 
str = strList.get(i); 
… 
} 
// Biến str chỉ được sử dụng bên trong FOR
// Nhưng lại được khai báo bên ngoài.

Source vẫn sẽ chạy đúng, không sai.

Tuy nhiên, sẽ có một vài vấn đề sau:

  • Trường hợp xử lý phức tạp, sẽ khó để một người khác đọc và hiểu ý nghĩa của biến này là gì.
  • Nếu str không phải là String, Number, Date… mà là một kiểu Object có kích thước lớn, thì mặc dù đã ra khỏi IF, FOR, WHILE (biến không còn được sử dụng nữa), nhưng biến này vẫn sẽ giữ giá trị và gây tốn memory.

Xử lí như thế nào?.

  • Khai báo biến bên trong IF FOR WHILE
  • Sử dụng for each (for (String str : strList) {)

4. Danh sách chứa rất nhiều giá trị, không nên sử dụng list.get(i).

Khi danh sách chứa rất nhiều giá trị, không nên sử dụng hàm get tại vị trí thứ i để lấy giá trị này ra.

Nguyên nhân là do hàm get sẽ thực hiện duyệt từng phần tử từ 0 -> i để lấy giá trị của vị trí thứ i này ra, việc này sẽ tốn rất nhiều thời gian nếu vị trí cần lấy là càng về cuối của danh sách.

Ví dụ:

  • get(0)-> Danh sách duyệt 1 lần để trả về giá trị tại vị trí thứ 0.
  • get(10)-> Danh sách duyệt 11 lần để trả về giá trị tại vị trí thứ 10.
  • get(100)-> Danh sách duyệt 101 lần để trả về giá trị tại vị trí thứ 100
// Trường hợp giá trị của danh sách là kiểu Object, 
// Object này có một hạng mục là key để phân biệt với các phần tử khác trong danh sách. 
-> Sử dụng map<key, object> 

// Trường hợp cần loop trên từng phần tử của danh sách 
-> Sử dụng for each 
for (Object dto : dtoList) { 

-> Sử dụng iterator 
Iterator ite = dtoList.iterator(); 
while (ite.hasNext()) { 
Object obj = ite.next(); 
}

5. So sánh String trong Java.

Khi thực hiện so sánh String, không nên sử dụng ==.

if (str == "1") 
// Trường hợp str là NULL, sẽ phát sinh NullPoiterException

Nên:

  • Sử dụng equals
  • Để giá trị cố định đằng trước.
if ("1".equals(str)) 
// Trường hợp str là NULL, 
// Giá trị sẽ trả về là FALSE mà không phát sinh NullPoiterException
Tất nhiên, trong Java, không phải khi nào sử dụng equals cũng là tốt.Tất nhiên, không phải lúc nào sử dụng equals cũng tốt!.

6. Hạn chế thiết lập cứng giá trị trong source code.

Nhiều bạn thường hay thiết lập giá trị cố định vào đoạn source của mình. Tuy nhiên, giá trị này có khi được sử dụng ở nhiều nơi khác nhau trong source.

Như thế, trường hợp có thay đổi tài liệu, hoặc do mình thiết lập giá trị sai, ta phải sửa lại giá trị này ở tất cả mọi nơi đang sử dụng nó, trong lúc sửa, có thể ta cũng sẽ sửa sót, không hết những chỗ cần sửa.

String projectNameHasVersion = "Project AAA" + "1.0.0"; 
if (str == "ABCDE") {

Nên:

Hãy khai báo Constants ở đầu file, hoặc trong constants.java

public static String PROJECT_NAME = "Project AAA"; 
public static String VERSION = "1.0.0"; 

public void Function_1() { 
String projectNameHasVersion = PROJECT_NAME + VERSION; 
} 

public void Function_2() { 
if (VERSION > …) 
}

7. Luôn sử dụng ENUM khi có thể.

Trường hợp cần phải thiết lập nhiều giá trị Constants mà lại phụ thuộc vào một Key nào đó, nếu ta chỉ khai báo constant thì khi sử dụng có khả năng ta sẽ sử dụng sai giá trị constants của key tương ứng này.

public static String TYPE_A_NAME = "..."; 
public static String TYPE_A_WIDTH = "..."; 
public static String TYPE_A_LENGTH = "..."; 

public static String TYPE_B_NAME = "..."; 
public static String TYPE_B_WIDTH = "..."; 
public static String TYPE_B_LENGTH = "..."; 

public void getInfo(String typeName) { 
if (TYPE_A_NAME.equals(typeName) { 
return TYPE_A_WIDTH + TYPE_A_LENGTH; 
} else if (TYPE_B_NAME.equals(typeName) { 
// -> Ở đây đúng ra cần trả về thông tin của TYPE_B,
// Nhưng có thể do bất cẩn hoặc do lỗi copy
// lại đang trả về giá trị của TYPE_A

return TYPE_B_WIDTH + TYPE_A_LENGTH; 
} 
}

Nên:

Tạo enum để lưu các giá trị thuộc về cùng một key vào 1 giá trị duy nhất

public enum MyType { 
TYPE_A("Type A", "Width of A", "Length of A"), -> Mô tả các giá trị của TYPE_A
TYPE_B("Type B", "Width of B", "Length of B"), -> Mô tả các giá trị của TYPE_B
; 

private String name; 
private String width; 
private String length; 

MyType(String name, String width, String length) { 
this.name = name; 
this.width = width; 
this.length = length; 
} 

public String getName() { 
return name; 
} 

public String getWidth() { 
return width; 
} 

public String getLength() { 
return length; 
} 
}
public void getInfo(String typeName) { 
if (MyType.TYPE_A.getName().equals(typeName) { 
return MyType.TYPE_A.getWidth() + MyType.TYPE_A.getLength(); 
if (MyType.TYPE_B.getName().equals(typeName) { 
return MyType.TYPE_B.getWidth() + MyType.TYPE_B.getLength(); 
} 
} 

public void getInfo(MyType myType) { 
return myType.getWidth() + myType.getLength(); 
}
Hãy luôn sử dụng enum khi có thể.If you know, what i mean.

Tại sao Enum lại luôn được ưu tiên sử dụng?. Để tìm hiểu sâu hơn, các bạn có thể đọc thêm bài viết này.

8. Tìm hiểu thêm về Stream, forEach, Lambda.

Từ phiên bản 1.8 trở đi, java có hỗ trợ thêm các feature mới là Stream, forEach, Lambda nếu có thời gian, nên tìm hiểu thêm phần này. Các bạn cũng có thể đọc thêm ở bài viết về stream trên blog này. Muốn trở thành Senior tất nhiên phải bỏ công học hỏi. kkk

Nó sẽ giúp việc lập trình trở nên đơn giản và tiết kiệm thời gian hơn!.

Again, thanks for reading, love u so much!

Bài viết gốc được đăng tải tại kieblog.vn

Có thể bạn quan tâm:

Xem thêm Việc làm IT hấp dẫn trên TopDev