Home Blog Page 49

Top 10 câu hỏi phỏng vấn Web Developer và cách trả lời hay nhất

Top 10 câu hỏi phỏng vấn Web Developer và cách trả lời hay nhất

Web Developer hay lập trình viên Web là những người tạo ra các ứng dụng web để chạy trên các trình duyệt Web. Ứng dụng Web có thể được tạo ra bằng nhiều ngôn ngữ lập trình, thư viện hay framework khác nhau. Cơ hội việc làm cho các Web Developer vô cùng lớn do nhu cầu phát triển Web hiện nay, trong bài viết này, chúng ta cùng tìm hiểu top 10 câu hỏi phỏng vấn Web Developer thường gặp nhất nhé.

Câu 1: Website cơ bản bao gồm những gì?

Để xây dựng nên một website và đưa nó đến được với người dùng thì chúng ta cần những thành phần cơ bản sau:

  • Tên miền (domain): là địa chỉ của website đó trên Internet. Để người dùng truy cập được vào nội dung của website thì họ cần gõ đúng địa chỉ website vào thanh địa chỉ của trình duyệt web.
  • Hosting: máy chủ chạy trên Internet, có vai trò lưu trữ dữ liệu và chạy ứng dụng của bạn.
  • Source code: chính là mã nguồn của ứng dụng web. Khi người dùng truy cập vào website, ứng dụng web sẽ trả về những nội dung để hiển thị lên cho người dùng tương tác, đồng thời cập nhật dữ liệu lưu trữ nếu cần.

  [Updated] Bộ câu hỏi phỏng vấn Fullstack Developer hay và khó năm 2024

  Phân biệt Front End và Back End, điểm khác nhau là gì?

Câu 2: Công việc của một Web Developer

Web Developer thường sẽ được chia thành 2 hướng khác nhau:

  • FrontEnd Developer: xây dựng phần giao diện hiển thị lên phía người dùng (client-side). Thông thường sẽ sử dụng HTML, CSS và JavaScript cho việc thiết kế, xây dựng ứng dụng xử lý tương tác trực tiếp với người dùng.
  • Backend Developer: xây dựng ứng dụng chạy trên máy chủ phía server (server-side). Công việc của Backend là xử lý tiếp nhận yêu cầu từ phía client, thực hiện logic, cập nhật dữ liệu vào database nếu cần và trả về phản hồi cho client.

Trong một dự án, nếu bạn đảm nhiệm cả 2 vai trò trên thì được gọi là Fullstack Developer, có khả năng xây dựng Web Application đầy đủ bằng cách sử dụng cùng lúc nhiều ngôn ngữ lập trình khác nhau.

Công việc của một Web Developer
Nguồn: https://www.liveabout.com/web-developer-job-description-salary-and-skills-2061841

Câu 3: DOM, HTML DOM là gì?

DOM – viết tắt của Document Object Model hay mô hình đối tượng tài liệu, là một giao diện lập trình ứng dụng (API) dùng để truy xuất các tài liệu dạng HTML và XML. DOM có cấu trúc dữ liệu dạng cây (Tree), chứa các nút (Node), mỗi nút sẽ có những thuộc tính riêng cho việc hiển thị giá trị hay truy xuất dữ liệu.

HTML DOM là chuẩn mô hình object và giao diện lập trình cho HTML, trong đó định nghĩa:

  • HTML elements (phần tử) là các objects
  • Thuộc tính (properties) và các sự kiện (events) cho tất cả HTML elements
  • Phương thức (methods) truy cập đến các HTML elements

HTML DOM giúp bạn thực hiện các thao tác với các trang web, thay đổi nội dung hiển thị và nhận lại kết quả từ hành động.

Tham khảo việc làm Web Developer hấp dẫn trên TopDev

Câu 4: CORS là gì?

CORS hay Cross-Origin Resource Sharing là một cơ chế trình duyệt cho phép truy cập và kiểm soát các tài nguyên nằm bên ngoài một tên miền nhất định nào đó. CORS sinh ra vì chính sách same-origin liên quan đến bảo mật được cài đặt vào toàn bộ các trình duyệt hiện nay.

Cụ thể là một website không thể truy cập và sử dụng các thông tin, tài nguyên của người dùng trên các website khác nếu không được phép.

Với ứng dụng Web thông thường, các lập trình viên thường sẽ truy vấn đến các domain khác thông qua việc gọi API, và để phù hợp với chính sách same-origin thì CORS được sử dụng để thông báo cho trình duyệt bằng ứng dụng chạy trên domain này được phép truy cập vào tài nguyên ở domain được chỉ định.

Câu 5: RESTfull API là gì?

API (Application Programming Interface) hay giao diện lập trình ứng dụng là một trung gian phần mềm cho phép 2 ứng dụng giao tiếp với nhau. Thông thường trong một ứng dụng Web, API sử dụng để giao tiếp giữa ứng dụng phía frontend client và ứng dụng phía backend server. RESTfull API là một chuẩn dùng trong việc thiết kế API cho các ứng dụng Web, nó chú trọng vào việc quản lý các resource hệ thống (file, ảnh, âm thanh, video, dữ liệu động, …) được truyền tải qua HTTP. 

RESTfull API được thiết kế để hoạt động chủ yếu trên phương thức CRUD (Create, Read, Update, Delete) tương đương với 4 giao thức HTTP là POST, GET, PUT và DELETE. 

RESTfull API là gì?

Câu 6: Có bao nhiêu loại method trong HTTP request?

Có 9 loại tất cả, trong đó gồm:

  • GET: sử dụng để lấy thông tin từ server
  • HEAD: giống với GET nhưng response chỉ trả về header, không có body
  • POST: gửi thông tin tới server thông qua các parameters của HTTP
  • PUT: ghi đè tất cả thông tin của đối tượng bằng những gì được gửi lên
  • PATCH: ghi đè những thông tin được thay đổi của đối tượng
  • DELETE: xóa resource trên server
  • CONNECT: thiết lập kết nối đến server
  • OPTIONS: mô tả tùy chọn giao tiếp cho resource
  • TRACE: thực hiện test loop-back đến resource

Câu 7: Database là gì? Hệ quản trị cơ sở dữ liệu là gì?

Database hay cơ sở dữ liệu là một tập hợp có tổ chức các thông tin có cấu trúc hoặc dữ liệu, thường được lưu trữ trực tuyến trong một hệ thống máy tính. Hệ quản trị cơ sở dữ liệu (DBMS) là một chương trình phần mềm cơ sở dữ liệu toàn diện đóng vai trò như một giao diện giữa các cơ sở dữ liệu và người dùng đầu cuối hoặc các chương trình để cho phép người dùng lấy, cập nhật và quản lý các thông tin được tổ chức và được tối ưu hóa. 

Một số loại database phổ biến:

  • CSDL quan hệ: tổ chức dưới dạng tập hợp các cột và hàng
  • CSDL hướng đối tượng: biểu diễn thông tin dưới dạng đối tượng
  • CSDL phân tán: tổ chức các file nằm ở các hệ thống máy tính, mạng khác nhau
  • CSDL NoQuery: lưu trữ và thao tác với dạng dữ liệu không có cấu trúc

Câu 8: Phân biệt Cookies, Session, Session Storage và Local Storage

Cookie là một đoạn văn bản ghi thông tin được tạo ra và lưu trên trình duyệt của máy người dùng (client) thường được tạo ra khi người dùng truy cập vào một website, nó sẽ ghi nhớ các thông tin như tên đăng nhập, mật khẩu hoặc các tùy chọn do người dùng lựa chọn đi kèm. Session (phiên làm việc) là một cách lưu lại dữ liệu của người dùng sử dụng website dưới dạng một tập tin trên máy chủ (server), nó chứa thông tin của người dùng cùng phiên làm việc giúp xác thực thông tin của tài khoản đang làm việc. Khi kết thúc phiên làm việc (đóng trình duyệt) thì thông tin session sẽ bị mất.

Local Storage là bộ nhớ của trình duyệt, có khả năng lưu trữ các thông tin cần thiết với dung lượng đến 10MB, giúp ứng dụng web ở phía client có thể đọc ghi nhanh chóng dữ liệu dùng chung, giảm thiểu thời gian request.

Câu 9: SEO là gì? Thế nào là một website chuẩn SEO

SEO là gì?

SEO – Search Engine Optimization là khái niệm chỉ việc tối ưu hóa vị trí tìm kiếm cho website trên các công cụ tìm kiếm phổ biến như Google, Facebook,… Ví dụ khi người dùng tìm kiếm một từ khóa liên quan đến ngành nghề, sản phẩm mà website của bạn cung cấp vì việc kết quả tìm kiếm hiển thị website của bạn lên đầu là một cách để thu hút người dùng, đồng thời cũng được các search engine đánh giá cao trong xếp hạng ưu tiên. Một website chuẩn SEO là website được thiết kế tương thích với bộ tìm kiếm (search engine) của Google hay Facebook,… mỗi search engine có một thuật toán tìm kiếm khác nhau, vì vậy cũng có những cách SEO khác nhau dành riêng. Dù vậy để đánh giá một website chuẩn SEO thì khi lập trình xây dựng website, có một số kỹ thuật cụ thể như gắn các thẻ meta, tối ưu layout bằng CSS, đặt các deep link,…

Câu 10: Nêu một số framework phổ biến phát triển web hiện nay

Có nhiều lựa chọn cho việc phát triển web hiện nay, cụ thể:

Dành cho phía Frontend:

Cả 5 thư viện / framework trên đều được viết bằng JavaScript (hoặc TypeScript), ngôn ngữ bạn gần như phải biết để làm frontend.

Dành cho phía Backend:

Kết bài

Như vậy chúng ta đã đi qua top 10 câu hỏi dành cho vị trí Web Developer phổ biến nhất mà bạn có thể gặp phải trong buổi phỏng vấn của mình. Hy vọng bài viết này giúp bạn tự tin hơn để sẵn sàng trả lời các câu hỏi mà người phỏng vấn đưa ra. Hẹn gặp lại các bạn trong các bài viết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

Xem thêm tuyển dụng nhân viên IT hấp dẫn trên TopDev

Cấu trúc rẽ nhánh trong swift – Decision Making

Cấu trúc rẻ nhánh trong swift – Decision Making

Bài viết được sự cho phép của tác giả Lê Hồng Kỳ

Cấu trúc rẻ nhánh trong swift yêu cầu lập trình viên chỉ định một hoặc nhiều điều kiện. Một hoặc nhiều câu lệnh sẽ được thực thi nếu điều kiện được xác định là đúng (true) và ngược lại những câu lệnh khác sẽ được thực thi nếu điều kiện được xác định là sai (xử lý ngược lại là không bắt buộc – optionally).

Sau đây là sơ đồ (flow chart) biểu diễn cấu trúc rẻ nhánh trong swift

Cấu trúc rẻ nhánh trong swift – Câu lệnh if (If Statement)

Một câu lệnh if bao gồm một biểu thức luận lý (boolean expression) theo sau là một hoặc nhiều câu lệnh.

Cú pháp

if boolean_expression {
   /* Câu lệnh sẽ thực hiện nếu biểu thức boolean là đúng */
}

Nếu biểu thức điều kiện (boolean expression) được xác định là đúng (true) thì khối lệnh bên trong câu lệnh if sẽ được thực thi

Ví dụ

var age:Int = 10;
/* Kiểm tra các điều kiện boolean sử dụng câu lệnh if */
if age < 20 {
   /* Nếu điều kiện là đúng thì in thông báo sau */
   print("Tuổi nhỏ hơn 20");
}
print("Tuổi của bạn là \(age)");

Khi chạy chương trình trên sử dụng playground, chúng ta sẽ nhận được kết quả

Tuổi nhỏ hơn 20 
Tuổi của bạn là 10

  Tạo thư viện bằng Swift Package Manager trong Xcode

  Nghệ thuật viết chương trình Hello World bằng Swift

Cấu trúc rẻ nhánh trong swift – Câu lệnh if…else (If…Else Statement)

Một câu lệnh if có thể theo sau nó là câu lệnh else (điều này không bắt buộc) và khối lệnh trong câu lệnh else sẽ được thực thi khi biểu thức điều kiện là sai (false)

Cú pháp

if boolean_expression {
   /* Câu lệnh sẽ thực hiện nếu biểu thức boolean là đúng */
} else {
   /* Câu lệnh sẽ thực hiện nếu biểu thức boolean là sai */
}

Sơ đồ biểu diễn câu lệnh if…else

cấu trúc rẽ nhánh

Ví dụ

var age:Int = 100;
if age < 20 {
   print("Tuổi nhỏ hơn 20");
} else {   
   print("Tuổi lớn hơn 20");
}
print("Tuổi của bản là \(age)");

Khi chạy chương trình trên sử dụng playground, chúng ta sẽ nhận được kết quả

Tuổi lớn hơn 20 
Tuổi của bạn là 100

Swift Developer Jobs hấp dẫn đang chờ bạn tại TopDev

Cấu trúc rẻ nhánh trong swift – Câu lệnh if…else if…else (if…else if…else Statement)

Một câu lệnh if có thể theo sau một câu lệnh else if…else (điều này không bắt buộc), điều này được sử dụng để test nhiều trường hợp.

Cú pháp

if boolean_expression_1 {
   /* Thực thi khi expression 1 đúng */
} else if boolean_expression_2 {
   /* Thực thi khi expression 2 đúng */
} else if boolean_expression_3 {
   /* Thực thi khi expression 3 đúng */
} else {
   /* Thực thi nếu không có điều kiện nào bên trên đúng */
}

Ví dụ

var age:Int = 100;
if age == 20 {
   print("Tuổi bằng 20");
} else if age == 50 {   
   print("Tuổi bằng 50");
} else {   
   print("Không thoả");
}
print("Tuổi của bạn là \(age)");

Khi chạy chương trình trên sử dụng playground, chúng ta sẽ nhận được kết quả

Không thoả 
Tuổi của bạn là 100

Cấu trúc rẻ nhánh trong swift – Câu lệnh if lồng nhau (Nested If Statements)

Có nghĩa là bạn có thể sử dụng một câu lệnh if hoặc câu lệnh else if và bên trong chứa một hoặc nhiều câu lệnh if hoặc else if khác.

Cú pháp

if boolean_expression_1 {
   /* Thực thi nếu expression 1 đúng */
   if boolean_expression_2 {
      /* Thực thi nếu expression 2 đúng */
   }
}

Ví dụ

var n1:Int = 100;
var n2:Int = 200;
if n1 == 100 {
   print("Điều kiện đầu tiên thoả");
   if n2 == 200 {
      print("Điều kiện thứ 2 cũng thoả");
   }
}
print("Giá trị của n1 là \(n1)");
print("Giá trị của n2 là \(n2)");

Khi chạy chương trình trên sử dụng playground, chúng ta sẽ nhận được kết quả

Điều kiện đầu tiên thoả
Điều kiện thứ 2 cũng thoả
Giá trị của n1 là 100
Giá trị của n2 là 200

Cấu trúc rẻ nhánh trong swift – Toán tử ? (The ? : Operator)

Chúng ta có thể sử dụng toán tử ? để thay cho câu lệnh if…else, sau đây là cú pháp

variableName = Exp1 ? Exp2 : Exp3;

Trong đó Exp1, Exp2 và Exp3 là các biểu thức. Nếu biểu thức 1 (Exp1) được xác định là true thì giá trị của variableName là giá trị của biểu thức 2 (Exp2). Nếu biểu thức 1 (Exp1) được xác định là false thì giá trị của variableName là giá trị của biểu thức 3 (Exp3).

Ví dụ tìm số lớn nhất trong 2 số

var n1:Int = 100;
var n2:Int = 200;
var max:Int;
max = n1 >= n2 ? n1 : n2;
print("Giá trị lớn nhất là \(max)");

Khi chạy chương trình trên sử dụng playground, chúng ta sẽ nhận được kết quả

Giá trị lớn nhất là 200

Cấu trúc rẻ nhánh trong swift – câu lện switch (Switch Statement)

switch expression {
   case expression1 :
      statement(s)
      fallthrough /* optional */
   case expression2, expression3 :
      statement(s)
      fallthrough /* optional */
   default: /* Optional */
      statement(s);
}

Ví dụ 1 (Không sử dụng fallthrough)

var index = 10
switch index {
   case 100, 200 :
      print("Giá trị của index bằng 100 hoặc 200")
   case 10 :
      print("Giá trị của index là 10")
   case 5 :
      print("Giá trị của index là 5")
   default :
      print("Không xác định")
}

Khi chạy chương trình trên sử dụng playground, chúng ta sẽ nhận được kết quả

Giá trị của index là 10

Ví dụ 2 (Sử dụng fallthrough)

var index = 10
switch index {
   case 100, 200 :
      print("Giá trị của index bằng 100 hoặc 200")
      fallthrough
   case 10 :
      print("Giá trị của index bằng 10")
      fallthrough
   case 5 :
      print("Giá trị của index bằng 5")
   default :
      println("Không xác định")
}

Khi chạy chương trình trên sử dụng playground, chúng ta sẽ nhận được kết quả

Giá trị của index bằng 10 
Giá trị của index bằng 5

Tổng kết cấu trúc rẻ nhánh trong swift

  • Câu lệnh if
  • Câu lệnh if…else
  • Câu lệnh if…else if…else
  • Câu lệnh if lồng nhau
  • Toán tử ?
  • Câu lệnh switch

Cấu trúc rẻ nhánh trong swift – Bài tập thực hành

Bài thực hành số 1: Tìm số lớn nhất trong 3 số thực Bài thực hành số 2: Giải phương trình bậc nhất ax + b = 0 Bài thực hành số 3: Tính điểm trung bình từ điểm toán, điểm lý, điểm hoá. Dựa vào điểm trung bình và xếp loại

  • Nếu điểm trung bình (sau đây gọi là dtb) nhỏ hơn 5, xếp loại “Yếu”
  • Nếu dtb lớn hơn hoặc bằng 5 và nhỏ hơn 6.5, xếp loại “Trung bình”
  • Nếu dtb lớn hơn hoặc bằng 6.5 và nhỏ hơn 8, xếp loại “Khá”
  • Nếu dtb lớn hơn hoặc bằng 8 và nhỏ hơn 10, xếp loại “Giỏi”
  • Nếu dtb bằng 10, xếp loại “Xuất sắc”

Bài thực hành số 4: Hiển thị số ngày của tháng. Với tháng 2 có 29 ngày nếu là năm nhuần, 28 ngày nếu là năm không nhuần.

Bài thực hành số 5: Giải phương trình bậc 2: ax2 + bx = c

Lưu ý: Ngoài việc sử dụng Xcode, chúng ta có thể sử dụng Swift IDE Online để chạy các đoạn code bằng Swift trực tiếp trên website. Đây là một sự lựa chọn thú vị.

Top 5 câu hỏi phỏng vấn SQL Developer – Phần 1

Top 5 câu hỏi phỏng vấn SQL Developer

Liệu rằng phỏng vấn SQL Developer đơn giản chỉ xoay quanh SQL (Structure Query Language)? Xin thưa là không, SQL Developer ngoài hiểu biết sâu rộng về SQL cũng cần có kiến thức về bảo mật, về tổng quan hệ cơ sở dữ liệu và nhiều yếu tố, thành phần khác liên quan tới DB.

Phần 1 bài viết này sẽ chia sẻ 5 câu hỏi liên quan tới SQL, mỗi câu hỏi là một phần kiến thức anh em có thể tham khảo. Vừa đánh giá kiến thức, vừa bổ sung nếu như đang còn hổng.

phỏng vấn SQL Developer
Dễ nhớ nhưng không có nghĩa anh em SQL Developer nào cũng nhìn nghiêm trọng vậy đâu nha

Chúc anh em SQL Developer thu thập được nhiều các kiến thức bổ ích thông qua bài viết này!

Ô sờ kê, gét gô thôi anh em.

1. Union là gì? Union khác gì so với Union All

Gòi, mồm to chứ câu đầu tiên phỏng vấn SQL Developer không thể không nhắc tới kiến thức cơ bản về SQL. Mà nhắc tới SQL không thể không nhắc tới từ khoá.

Từ khoá được nêu danh trong phần 1 này là union và union all.

Đầu tiên là union là cách thức hợp nhất nội dung của hai bảng có cùng cấu trúc. Hoặc sự thống nhất về cột trong 2 câu queries. Sự khác biệt giữa Union và union all là union sẽ tự động loại bỏ trùng lặp.

Trong anh có em, trong em có anh nhưng cái nào lặp thì ta bỏ đi. Còn không muốn bỏ thì ta có UNION ALL. À có một lưu ý nho nhỏ là UNION ALL sẽ tốt hơn về mặt performance do UNION phải tốn thêm xử lý để loại bỏ các dòng trùng lặp. Trong trường hợp anh em chắc chắn không thể có trùng lặp, UNION ALL nên được ưu tiên sử dụng.

  Oracle SQL developer - Top 5 cách dùng thông minh

phỏng vấn SQL Developer

2. Cluster và non clustered index khác gì nhau?

Cluster và non clustered là câu hỏi đánh giá mức độ hiểu biết của anh em về các loại index. Tuy chỉ là câu hỏi tổng quan về phân loại. Nhưng nếu anh em có thể phân biệt rõ sự khác biệt giữa hai loại index này, tin rằng anh em đã có kiến thức khá ổn về index.

Đầu tiên thì clustered index là loại index xác định sự sắp xếp vật lý (physical arrangement) của các dòng dữ liệu. Mỗi một bảng chỉ có một clustered index vì chỉ có một cách duy nhất duy trì về mặt vật lý cho các records trên một bảng.

Ngược lại, non clustered index là index không xác định sắp xếp vật lý (doesn’t specify the physical arrangement). Với non clustered thì dữ liệu có thể được lưu ở các bảng khác. Chính vì vậy, mỗi bảng có thể có nhiều non clustered index.

phỏng vấn SQL Developer

Câu hỏi về index là câu hỏi số hai phỏng vấn SQL Developer. Mục đích giúp anh em phân biệt hai loại index này. Anh em cũng có thể quay lại xem qua các loại index cho chắc nha.

Tham khảo SQL Developer Jobs hấp dẫn trên TopDev

3. Tìm kiếm các records bị trùng lặp như thế nào?

Chuyện dữ liệu bị trùng lặp giữa các bảng, các views là chuyện bình thường như cơm bữa. Câu hỏi số 3 trong bộ câu hỏi phỏng vấn SQL Developer muốn kiểm tra cách anh em xử lý vấn đề thực tế với SQL.

Từ vấn đề đó kiểm tra xem anh em có dùng đúng keywords không. Có hiểu và nhớ về các từ khoá, sử dụng với mục đích gì hay không?.

Trùng lặp records chia thành 2 trường hợp. Một là 1 field, hai là nhiều field trong một table. Nếu chỉ trùng 1 field anh em có thể sử dụng GROUP BY với HAVING COUNT để tìm ra field trùng trong bảng, trong views

 SELECT name, COUNT(email) 
 FROM users
 GROUP BY email
 HAVING COUNT(email) > 1 

Trường hợp có nhiều hơn 1 field, anh em có thể sử dụng COUNT *

 SELECT name, email, COUNT(*)
 FROM users
 GROUP BY name, email
 HAVING COUNT(*) > 1

Tất nhiên sử dụng các từ khoá, ghi nhớ từ khoá anh em không thể học tủ đâu nha, phải nhớ hết. Đây chỉ là một câu hỏi ví dụ.

phỏng vấn SQL Developer
Bộ keywords anh em phải thuộc như nằm lòng nha

  Hướng dẫn kết nối PHP với SQL Server

4. Làm sao để xử lý các vấn đề liên quan tới SQL?

Đây là câu hỏi thường gặp trong các buổi phỏng vấn SQL Developer. Nguyên nhân là nó đánh giá được kinh nghiệm thực tế anh SQL Developer được gặp.

Câu hỏi này cũng phân loại ra những anh em backend thông thường chỉ sử dụng SQL theo kiểu Queries đã viết sẵn hoặc những câu đơn giản không có vấn đề về performance. Câu hỏi này khuyến nghị anh em nêu ra từ khoá, các thức xử lý vấn đề với các câu SQL. Hai nữa là nêu ra kinh nghiệm thực tế đã optimize như thế nào. Được như vậy sẽ thuyết phục hơn.

Quay lại với câu hỏi, câu trả lời anh em có thể nêu ra liên quan tới một số vấn đề của SQL Queries:

  • Nếu SQL chậm, có vấn đề về performance, giải pháp là đánh index cho các column thường được tìm kiếm và thường được sort. Cụ thể index như thế nào, loại nào anh em có thể nêu ra. Một số loại index anh em có thể tham khảo ở đây.
  • Cũng trong SQL performance, anh em có thể nêu ra các cách thức, kĩ thuật sử dụng để phân tích câu SQL. Tìm ra chỗ gây chậm hoặc không hiệu quả. Câu SQL có vấn đề thường là rất dài nên phải tìm từng phần trong đó
  • Từ khoá thì anh em có thể nêu rõ ràng ra dùng EXPLAIN, EXPLAIN ANALYZE. Tuỳ thuộc vào DB mà anh em thường sử dụng.

Về kinh nghiêm thực tế anh em còn có thể nêu ra cụ thể tên một số tools, các thức anh em đã dùng để tối ưu:

  • Sử dụng công cụ như pgAdmin, MySQL Workbench hoặc SQL Server Management Studio để tìm hiểu sâu hơn về SQL như CPU, Ram.
  • Với một số câu SQL, nguyên nhân chậm có thể do các tham số (argument), có thể nêu ra các lần anh em đã thử thay đổi tham số để điều tra nguyên nhân chậm của SQL.

phỏng vấn SQL Developer
Như SQL Server, nó cho biết kích thước dữ liệu trả về là bao nhiêu, dùng hết bao nhiêu CPU cho từng actions

5. Những cách nào được sử dụng để đảm bảo security cho SQL?

Câu hỏi về security là câu hỏi được đánh giá ở mức độ cao hơn trong danh sách các câu hỏi phỏng vấn SQL Developer nha. Những anh em nào có kinh nghiệm hoặc apply vị trí SQL Developer thường sẽ gặp câu này.

Thời đại mà làm cái gì kể cả là Frontend, Backend, Network,… người ta đều chú ý tới security thì SQL cũng không phải là ngoại lệ.

Nếu anh em còn chưa biết nhiều về SQL Security thì có thể tham khảo thêm nha. Đọc để biết thêm về thứ mà chắc chắn là ở level cao anh em nào cũng cần có kiến thức. Rồi, quay lại câu trả lời, anh em có thể liệt kê ra một số kỹ thuật để đảm bảo security cho SQL.

  • Access control: cái này là cơ bản nhất ha, dựa trên quyền truy cập ta có thể chặn hoặc giới hạn quyền truy cập vào hệ cơ sở dữ liệu.
  • Encryption: Mã hoá là xương sống của bảo mật, mật khẩu, thẻ tín dụng, … Tất cả đều được mã hoá để đảm bảo tính bảo mật. Anh em có thể nhấn nhá qua tí về các thức lưu dữ liệu trong các cột.
  • Auditing: Kiểm tra là kỹ thuật lưu lại tất cả hành động được thực hiện trên DB, ai đã log vào DB, đã xem bảng nào, truy cập bảng nào.
  • SQL Injection: Cái này cần phải kiểm tra kĩ input parameter. Anh em lưu ý đây là kiến thức bảo mật cơ bản cần phải có nha.

phỏng vấn SQL Developer
SQL Injection là kiến thức cơ bản cần nhớ nha anh em

6. Tham khảo thêm về phỏng vấn SQL Developer

Cảm ơn anh em đã đọc bài – Thank you for your time – Happy interview!

Tác giả: Kiên Nguyễn

Xem thêm:

Xem thêm tuyển dụng nhân viên it hấp dẫn trên TopDev

Selenium Webdriver – Xử lý thao tác Drag-Drop

Selenium Webdriver – Xử lý thao tác Drag-Drop

Bài viết được sự cho phép của tác giả To Thi Van Anh

Việc xử lý drag và drop trong thực tế thì đôi khi ta có gặp nhưng mà không nhiều lắm, tại vì đang hơi rảnh nên cứ note lại vào đây, biết đâu có một ngày không đẹp trời nào đó lại va vào nhau như kiểu tình yêu sét đánh thì sao, nhề!!!

Selenium Webdriver

Thường thì đối với drag và drop thì trình tự thao tác sẽ là bạn kéo một lable từ group này sang một group khác, hoặc là bạn có thể gặp khi mà trong danh sách một group nào đó có nhiều item và bạn cần sắp xếp lại vị trí của các item đó bằng cách là kéo lên hoặc kéo xuống item cần thay đổi vị trí.

Đơn giản nhất, nếu như đã dùng qua Trello thì thao tác kéo thả thể hiện trực quan nhất là kéo task từ list “Doing” sang list “Done” chẳng hạn.

Vậy thì nếu sử dụng Selenium thì nó sẽ xử lý như thế nào?

  Thao tác Mouse hover trong Selenium Webdriver

Selenium Webdriver

Selenium có cung cấp class với các method giúp bạn xử lý bài toán này, và nó có cú pháp như sau:

Actions builder = new Actions(driver);
Action dragAndDrop = builder.clickAndHold(sourceLocator)
 .moveToElement(destinationLocator)
 .release(destinationLocator)
 .build();
dragAndDrop.perform();

Ở đây, class Actions có một method là dragAndDrop( WebElement source, WebElement  target), method này với mục đích là thực hiện lick và giữ phần tử từ vị trí nguồn (source), rồi di chuyển phần tử đó đến vị trí đích muốn kéo đến (target). Sau đó thực hiện build method dragAndDrop cùng với các giá trị đầu vào là source element và target element bằng method build() và cuối cùng tiến hành thực hiện tiến trình này bằng method perform().

Hoặc bạn cũng có thể sử dụng cú pháp này để giả lập thao tác drag và drop:

(new Actions(driver)).dragAndDrop(element, target).perform();

Với cú pháp này thì ta bỏ qua bước build method và thực hiện luôn thao tác với perform() luôn.

Bên cạnh đó, ta cũng có nhiều cú pháp và cách khác mà bạn có thể sử dụng, các bạn có thể Google để tìm thêm nhé! Hehe, cách này đối với mình thì tương đối là dễ hiểu và cũng dễ dùng nữa. Àh điều này không có nghĩa là các cách khác nó khó dùng khó hiểu đâu nhé!

  VisGrid – Thiết lập Selenium-Grid qua giao diện

Ngoài ra, để tránh các trường hợp exception hoặc bug không mong muốn do việc load dữ liệu, vì trong nhiều trường hợp các drag và drop này được nằm trong thẻ frame, nên khi truy cập vào trang thì dữ liệu chưa thể load lên ngay lập tức được. Và sau khi ta thực hiện kéo thả dữ liệu, cũng cần phải verify xem có đúng là nó đã drop hoàn thành và đúng hay chưa (cái này thì tùy vào yêu cầu và output của từng bài toán).

Vì thế, trước khi thực hiện action này, thì ta cần kiểm tra việc available location của nguồn và đích. Và sau khi thực hiện action thì cần kiểm tra tính đúng của nó có thể bằng cách assert dữ liệu hiển thị hoặc thông báo thành công khi kết thúc thao tác.

Về mặt lý thuyết thì cơ bản là bạn cần nắm được cái cú pháp để thực hiện như phía trên.

Và dưới đây là code example của mình cho bài toán này, các bạn có thể tham thảo và hi vọng là sẽ cùng các bạn hiểu hơn về cách dùng của nó.

package basic;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.interactions.Action;
import org.openqa.selenium.interactions.Actions;

public class DragAndDrop {

public static void main(String[] args) {
 System.setProperty("webdriver.gecko.driver","E:\\Program\\Firefox\\geckodriver.exe");
 FirefoxOptions options = new FirefoxOptions();
 options.setBinary("C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe"); 
 FirefoxDriver driver = new FirefoxDriver(options);
 driver.get("http://www.testingbar.com/drag-and-drop/");

 //Vị trí của phần tử nguồn sẽ drop
 WebElement sourceLocator = driver.findElement(By.id("draggable"));
 
 //Vị trí của đích mà phần tử nguồn sẽ thả vào
 WebElement destinationLocator = driver.findElement(By.id("droppable"));
 
//Thực hiện kéo - thả
 Actions builder = new Actions(driver);
 Action dragAndDrop = builder.clickAndHold(sourceLocator)
 .moveToElement(destinationLocator)
 .release(destinationLocator)
 .build();
 dragAndDrop.perform();
}
}

Bài viết gốc được đăng tải tại vananhtooo.wordpress.com

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

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

Top 10 câu hỏi phỏng vấn AngularJS Developer có đáp án chi tiết

Top 10 câu hỏi phỏng vấn AngularJS Developer có đán án chi tiết

AngularJS là một framework viết bằng JavaScript dành cho Web được phát triển bởi Google từ những năm 2010. Nhờ sự hỗ trợ từ Google mà Angular luôn có chỗ đứng trong top những framework phổ biến dành cho lập trình viên Frontend; và vì thế nhu cầu tuyển dụng lập trình viên AngularJS cũng luôn ở mức cao. Trong bài viết hôm nay chúng ta cùng tìm hiểu top 10 câu hỏi phỏng vấn thường gặp cho vị trí AngularJS Developer nhé.

Câu 1: AngularJS có đặc điểm gì nổi bật?

câu hỏi phỏng vấn AngularJS Developer

AngularJS có thể xem là một trong những framework / thư viện JavaScript dành cho Frontend đầu tiên hỗ trợ double-binding dữ liệu giúp công việc lập trình Web trở nên nhanh chóng và hiệu quả. Sự tăng trưởng nhanh chóng của AngularJS vào giai đoạn 2013-2015 khiến người người nhà nhà học và làm AngularJS.

AngularJS có những ưu điểm như sau:

  • Chứa khung MVC JavaScript mã nguồn mở giúp bạn dễ dàng triển khai, mở rộng dự án mà không phải lo vấn đề quản lý source code
  • AngularJS được viết bằng JS và HTML, bạn không cần học thêm ngôn ngữ mới. Việc sử dụng HTML cũng giúp code trở nên dễ hiểu, dễ chuyển đổi từ source code cũ sang.
  • Hỗ trợ double-binding dữ liệu, sử dụng Injection Dependency, hỗ trợ đầy đủ REST API
  • Với AngularJS chúng ta sẽ viết ít code hơn, phát triển ứng dụng nhanh hơn; chưa kể với sự hậu thuẫn của Google nên cộng đồng support cho framework này rất lớn.

Câu 2: Data-binding là gì?

Data binding là tính năng có sẵn trong AngularJS. 

Data binding giúp gắn một biến với một vị trí nào đó trong view, cụ thể là gắn trực tiếp với một node trên HTML DOM. AngularJS hỗ trợ 2 chiều binding, nghĩa là nếu data thay đổi thì giá trị hiển thị trên View cũng được cập nhật và ngược lại, khi giá trị trên View thay đổi thì giá trị biến cũng được cập nhật.

Data-binding là một trong những tính năng cốt lõi của AngularJS giúp tự động đồng bộ hóa dữ liệu giữa thành phần model và view trong mô hình MVC.

  Top 10 câu hỏi phỏng vấn JavaScript cực chi tiết

  Top 5 tips and tricks hot nhất của JavaScript năm 2024

Câu 3: Phân biệt Angular và AngularJS

phân biệt Angular và AngularJS
Nguồn: https://flexisourceit.com.au/wp-content/uploads/2021/10/comparison-between-Angular-and-AngularJS.jpg

Angular và AngularJS là 2 version của Angular nhưng lại khác nhau khá nhiều. AngularJS hay còn gọi là AngularJS 1.x, ngược lại thì Angular dùng để chỉ Angular 2+ version. AngularJS viết bằng JavaScript, còn Angular (phiên bản 2 trở lên) được viết bằng TypeScript, một phiên bản nâng cao hơn của JS ra đời năm 2016 và là 1 phần của ES6. 

Sự khác nhau ngay từ ngôn ngữ sử dụng khiến 2 version Angular này có sự khác biệt về thành phần, bộ điều khiển cũng như các công cụ mẫu. Angular là phiên bản mới hơn và vẫn đang được Google phát triển, cập nhật phiên bản mới. So với AngularJS thì Angular nhanh hơn, hỗ trợ trên các trình duyệt di động tốt hơn. Mặc dù vậy vẫn rất nhiều website, ứng dụng Web vẫn sử dụng và được phát triển bằng AngularJS nhờ nó được viết bằng JavaScript, ngôn ngữ dễ đọc hơn TypeScript.

Tham khảo việc làm AngularJS mới nhất trên TopDev!

Câu 4: Directive trong AngularJS là gì?

Directive được AngularJS định nghĩa cho việc thao tác, cập nhật, thêm ,xóa các thành phần giao diện HTML trên Web. Một vài directive cơ bản trong AngularJS như sau:

  • ng-app: dùng để xác định một ứng dụng AngularJS
  • ng-init: khai báo biến trong ứng dụng
  • ng-model: dùng để liên kết các giá trị trong các thẻ HTML (input, select, textarea,…) với biến (variables) trong ứng dụng
  • ng-bind: sử dụng để kết nối dữ liệu ứng dụng với HTML views
  • ng-repeat: sử dụng như vòng lặp để hiển thị HTML views theo biến dữ liệu

Câu 5: Cách khai báo và sử dụng Controller?

Controller trong AngularJS là nơi chúng ta định nghĩa các hành vi và xử lý dữ liệu của ứng dụng. Chúng ta sử dụng directive ng-controller để định nghĩa controller cho ứng dụng. Một controller trong AngularJS là một JavaScript object (đối tượng), trong đó khai báo các thuộc tính và phương thức (function) để sử dụng trong ứng dụng.

Ở phần view HTML, khi controller được định nghĩa, chúng ta sử dụng directive ng-model để lấy ra các thuộc tính được khai báo trong controller cho việc hiển thị dữ liệu; hoặc call trực tiếp function đã khai báo bên trong vùng định nghĩa của ng-controller.

Câu 6: Hãy giải thích biến $scope trong AngularJS

$scope là đối tượng đặc biệt của Controller chứa các biến và hàm xử lý, sau đó dữ liệu được đồng bộ lên giao diện thông qua cơ chế data-binding của AngularJS. Khi một controller được gán vào tag HTML thì AngularJS sẽ tạo ra một đối tượng $scope dành riêng cho controller làm việc với phạm vi của tag đó. Một ứng dụng AngularJS có thể có nhiều Controller, vì thế cũng sẽ có nhiều $scope tương ứng, các biến trong mỗi $scope là tách biệt và không thể truy xuất dữ liệu qua lại giữa các $scope.

Đối với trường hợp $scope lồng nhau (hay $scope cha và $scope con) thì lúc này AngularJS cho phép truy xuất biến giữa 2 scope trên thông qua từ khóa $parent. Ngoài ra Angular còn cung cấp biến $rootScope có thể truy xuất trực tiếp trong phạm vi ng-app.

Câu 7: Mô hình MVC áp dụng trong AngularJS như thế nào?

Mô hình MVC

MVC hay Model View Controller là mô hình thiết kế phần mềm phổ biến cho các ứng dụng trên nền tảng Web. AngularJS cũng sử dụng mô hình này trong việc phát triển ứng dụng, trong đó:

  • Model: thành phần có nhiệm vụ quản lý dữ liệu. Model phản hồi các yêu cầu từ phần view và thực hiện những phần lệnh từ controller.
  • View: thành phần hiển thị dữ liệu, trong AngularJS chính ra phần HTML view và được trigger bởi controller khi dữ liệu thay đổi hoặc có tương tác với người dùng
  • Controller: khai báo controller trong các module JS sử dụng ng-controller để liên kết với View. Controller có thể thay đổi trạng thái dữ liệu trong model và cập nhật dữ liệu mới lên View.

Câu 8: Làm thế nào để nhúng một trang html vào trong trang html khác?

AngularJS cung cấp directive ng-include để nhúng các hành phần html (hoặc một trang html) vào HTML View hiện tại. Khi thực hiện import, nếu có khai báo xử lý data hiển thị trên View trong các template thì biến $scope vẫn xử lý được các giá trị đó bình thường. Hay nói cách khác, về bản chất thì directive ng-include trong AngularJS sẽ thực hiện việc nhúng template HTML vào phần HTML View trước, sau đó mới xử lý logic hiển thị dữ liệu cùng các action trên trang.

Câu 9: Service là gì? Làm sao để tạo một custom service trong AngularJS

Service là các hàm JavaScript có nhiệm vụ trên những task nhất định. AngularJS cung cấp nhiều services định nghĩa sẵn như $http, $scope, $route $window, $location, … mỗi service có một nhiệm vụ nhất định (service mặc định của AngularJS được bắt đầu bởi ký tự $).

Để tạo một custom service chúng ta có thể sử dụng phương thức fatory hoặc service, 2 cách khai báo tương tự và cho kết quả tương đương.

  • module. fatory([“tên service”], function())
  • module.service([“tên service”], function())

Câu 10: Đánh giá AngularJS với các framework JS khác

Hiện tại phiên bản AnguarJS (Angular 1.x) không còn được Google hỗ trợ cập nhật và khuyến khích sử dụng thay thế bằng Angular 2+. Mặc dù vậy với ưu điểm viết bằng JavaScript và sự quen thuộc với hầu hết các lập trình viên nhờ tính đơn giản, dễ đọc hiểu nên AngularJS vẫn được ưa chuộng. So với các framework JS khác thì hiện nay AngularJS không có nhiều tính năng hiện tại được bổ sung; mặc dù vậy thì nó vẫn được đánh giá là một lựa chọn tốt khi kết hợp sử dụng với một số ngôn ngữ backend khác như PHP giúp thời gian phát triển dự án nhanh chóng và hiệu quả.

Kết bài

Trên đây là top 10 câu hỏi phổ biến nhất mà bạn có thể thường xuyên gặp khi đi phỏng vấn vị trí AngularJS Developer. Hy vọng bài viết giúp bạn tự tin hơn để chuẩn bị tốt cho buổi phỏng vấn của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

Tìm việc làm IT mới nhất trên TopDev

Golang là gì? Top 07 Framework tối ưu “cực căng” cho Golang

Golang là gì? 9 Framework tối ưu “cực căng” cho Golang

Golang là một trong những ngôn ngữ lập trình phổ biến nhất trên thế giới, đứng sau thành công của nhiều phần mềm nổi tiếng như Docker hay Kubernetes. Độ “nóng” của ngôn ngữ ngữ này giúp cho việc phát triển nguồn mở của dân dev ngày càng trở nên dễ dàng hơn. Bài viết này sẽ giúp bạn hiểu hơn về Golang và cung cấp danh sách top framework hàng đầu giúp bạn đi xa hơn trong lĩnh vực GO. Hãy lưu lại lại để dùng dần nha!

Giới thiệu về ngôn ngữ Golang

golang là gì

Golang (hay còn gọi là Go) là một ngôn ngữ lập trình được phát triển bởi Google vào năm 2007 và ra mắt chính thức vào năm 2009. Golang được thiết kế để có thể xử lý các công việc đa nhiệm và đa luồng một cách hiệu quả, đồng thời hỗ trợ tốt việc lập trình hệ thống.

Điểm khác biệt của Golang so với các ngôn ngữ lâp trình khác là cú pháp đơn giản và dễ đọc, hỗ trợ nhiều tính năng, bao gồm cả hỗ trợ đa nền tảng, tốc độ thực thi nhanh và khả năng quản lý bộ nhớ tự động. Nó được sử dụng rộng rãi trong các ứng dụng đòi hỏi tốc độ cao, bao gồm các hệ thống web, game, máy chủ, các ứng dụng về đám mây và các dịch vụ liên quan.

  Thủ thuật xử lý lỗi trong Golang

  Flutter cơ bản - Framework di động được yêu thích nhất hiện nay?

7 Framework tốt nhất cho Golang bạn cần biết

Gin/Gin-Gonic

Gin là một framework được xây dựng trên nền tảng HTTP router và middleware, cung cấp các tính năng giúp đơn giản hóa việc phát triển các ứng dụng web với Golang. Gin có API giống như Martini nhưng cung cấp hiệu suất lên đến 40 lần so với Martini.

Gin-gonic được thiết kế để tạo ra các ứng dụng web có hiệu suất cao, đồng thời hỗ trợ nhiều tính năng như xử lý request và response, routing, middleware, validation, logging, và nhiều tính năng khác. Nó cũng có cú pháp đơn giản và dễ sử dụng, cho phép các lập trình viên nhanh chóng tạo ra các ứng dụng web phức tạp với Golang.

Beego

Beego là một framework MVC hoàn chỉnh với đầy đủ với các thư viện tích hợp sẵn như xử lý context, hỗ trợ ORM để truy cập dữ liệu, cơ chế ghi nhật ký và thư viện cho các operation với những đối tượng HTTP. Beego được chia thành tám module để sử dụng theo nhu cầu của người dùng.

Echo

Echo là một framework tập trung vào hiệu suất, tính mở rộng và đơn giản. Echo hỗ trợ cho việc thiết kế API RESTful, bạn có thể sử dụng nó như một framework độc lập hoặc kết hợp với các thư viện khác như Gin. Echo cung cấp nhiều tính năng như ràng buộc và hiển thị dữ liệu, hỗ trợ TLS tự động, tính mở rộng, hỗ trợ HTTP/2, middlewares, tối ưu hóa router, và các tính năng khác.

Tham khảo việc làm Golang hấp dẫn trên TopDev!!

Iris

Iris là một framework Golang nhanh, đơn giản và nhẹ nhàng, phù hợp cho những ai quen thuộc với framework Node.js. Iris cũng có nhiều thư viện như passport, express-session, body-parser, Morgan,… Nó cho phép tích hợp các thư viện bên thứ ba vào dự án một cách hiệu quả. Tương tự như Beego, Iris cũng cung cấp hỗ trợ MVC cơ bản, hỗ trợ tích hợp cho phần mềm trung gian sessions, routing, và caching.

Gorilla

Gorilla là framework được xem như một “web toolkit” dùng để giải quyết các khía cạnh khác nhau của việc viết một dịch vụ web: context, mux và các thư viện khác để thực hiện cookie, session, websockets và RPC qua HTTP.

Nhiều tên tuổi lớn, bao gồm Netflix, sử dụng Gorilla cho phát triển ứng dụng web của họ. Nó cũng sở hữu một loạt tính năng hữu ích và sử dụng hoàn toàn miễn phí. Gorilla khá dễ sử dụng, với tài liệu hướng dẫn được cung cấp bằng nhiều ngôn ngữ.

Revel

Revel framework

Revel là một trong những framework tốt nhất của Golang, nó không cần yêu cầu về thiết lập và cấu hình, điều này hoàn toàn khác biệt so với tất cả các framework Go khác. Ngoài ra, Revel hoàn toàn không bị ràng buộc bởi middleware và cũng như các plugin của bên thứ ba.

Công cụ Hot Code Reload trên Revel sẽ cho phép bạn xây dựng lại dự án của mình trên mỗi thay đổi tệp. Revel còn cho phép bạn sử dụng component một cách tự do để đáp ứng các nhu cầu khác.

Gocraft

Gocraft là một framework tối giản nhưng mạnh mẽ, cung cấp nhiều tính năng linh hoạt và có khả năng mở rộng. Gocraft nổi tiếng với middleware tích hợp sẵn giúp các nhà phát triển viết và thêm các tính năng bổ sung vào các ứng dụng web. Nó rất dễ sử dụng và là lựa chọn lý tưởng cho việc phát triển các ứng dụng web có hiệu suất cao.

Xem thêm:

Xem thêm các việc làm Developer hấp dẫn tại TopDev

Top 10 câu hỏi phỏng vấn iOS Developer và cách trả lời hay nhất

Top 10 câu hỏi phỏng vấn iOS Developer và cách trả lời hay nhất

Hệ điều hành iOS ra đời và phát triển cùng với hệ sinh thái iPhone, iPad của Apple từ những năm 2007 đến nay đã trở thành 1 trong những hệ điều hành phổ biến nhất trên thế giới. iOS Developer là người xây dựng, phát triển các ứng dụng cho các thiết bị di động và tương thích với hệ điều hành iOS. Với sự lớn mạnh của Apple hiện nay ,nhu cầu tuyển dụng iOS Developer trở nên lớn hơn bao giờ hết. Để chuẩn bị cho một buổi phỏng vấn vị trí này, hôm nay chúng ta cùng tìm hiểu top 10 câu hỏi phỏng vấn iOS Developer nhé.

Câu 1: Lập trình iOS là gì? Ngôn ngữ, công cụ sử dụng

lập trình ios

Lập trình iOS là việc xây dựng và phát triển các ứng dụng có thể chạy trên các thiết bị sử dụng hệ điều hành iOS, cụ thể là iPhone, iPad, iPod. Apple cung cấp IDE Xcode và iOS SDK cho việc lập trình iOS bằng ngôn ngữ Objective-C hay Swift; ngoài ra chúng ta cũng có thể phát triển ứng dụng iOS bằng các nền tảng cross-platform khác như React Native hay Flutter. iOS SDK được Apple phát hành miễn phí cho lập trình viên, mặc dù vậy nó chỉ hỗ trợ chạy trên nền MacOS cũng thuộc hệ sinh thái Apple.

Để ứng dụng iOS đến được với người dùng, các nhà phát hành cần đăng ký tài khoản Apple Developer và publish nó lên kho chợ ứng dụng AppStore. Tính đến nay có khoảng 2 triệu ứng dụng được phát hành trên nền tảng chợ ứng dụng này.

Câu 2: Mô tả vòng đời View Controller trong ứng dụng iOS

View Controller có nhiệm vụ tương tác với View và hệ thống, quản lý thay đổi từ View và thực hiện các cập nhật lên View.

Vòng đời của View Controller bao gồm:

  • Load View: gọi khi khởi tạo 1 view controller
  • viewDidLoad: Sau khi view controller được tạo và nạp vào bộ nhớ xong thì hàm này sẽ được gọi. Trong hàm này sẽ xử lý việc chuẩn bị data hay khởi tạo các giá trị trên màn hình
  • viewDidAppear: được gọi khi view đã được hiển thị lên màn hình
  • viewDidDisappear: gọi khi view được ẩn khỏi màn hình, chuyển sang màn hình khác

  Quản lý realm database theo hướng micro-service trong iOS

  Giới thiệu View Controller và vòng đời view controller trong lập trình IOS

Câu 3: Các trạng thái thông thường của một ứng dụng iOS

Thông thường có 5 trạng thái mà một ứng dụng iOS có thể có:

  • Not Running: ứng dụng đang hoàn toàn không được chạy
  • Inactive: ứng dụng đang ở trạng thái mở nhưng có 1 ứng dụng khác đang chạy ưu tiên active bên trên như cuộc gọi, tin nhắn, ….
  • Active: ứng dụng đang mở hoạt động và người dùng có thể tương tác
  • Background: ứng dụng đang ở trạng thái chạy nền, thông thường là ứng dụng được mở từ trước đó, người dùng thoát ra sử dụng ứng dụng khác nhưng không tắt ứng dụng đi
  • Suspended: ứng dụng khi ở trạng thái nền một thời gian nếu bộ nhớ của thiết bị không đủ để duy trì việc chạy nền thì sẽ không thể xử lý thêm tác vụ nào từ ứng dụng và đưa nó về trạng thái treo

Xem thêm việc làm iOS Developer hấp dẫn tại TopDev 

Câu 4: Swift là gì? Ưu điểm của nó với Objective-C

Swift là gì?

Swift là một ngôn ngữ lập trình hướng đối tượng được Apple phát triển cho iOS, macOS và một số nền tảng khác. Swift được phát hành từ năm 2014, nó có nhiều tính năng ưu việt hơn các ngôn ngữ khác nhờ việc chọn ra những ý tưởng nổi bật của các ngôn ngữ đã phát triển trước đó.

So với Objective-C (ngôn ngữ ban đầu được Apple sử dụng cho lập trình iOS) thì:

  • Code trong Swift ngắn gọn và dễ đọc, dễ viết, dễ bảo trì hơn
  • Rút ngắn được thời gian phát triển
  • Có khả năng tương thích với Objective-C
  • Có các tính năng hiện đại hơn như kiểm tra kiểu dữ liệu, quản lý bộ nhớ tự động
  • Hỗ trợ lập trình hàm

Câu 5: Mô hình MVC trong ứng dụng iOS được thể hiện như thế nào?

MVC là mẫu thiết kế phần mềm gồm 3 thành phần Model View Controller, iOS sử dụng MVC làm phương pháp chính để phát triển ứng dụng, trong đó:

  • View: UIView và các lớp con của nó
  • Controller: UIViewController và các lớp con của nó
  • Model: các đối tượng dữ liệu, lớp NSManagedObject và các lớp con

Apple khuyến khích lập trình viên sử dụng mô hình MVC để phát triển ứng dụng iOS. Ngoài MVC thì có một vài mẫu thiết kế khác cũng được áp dụng trong lập trình iOS như MVVM, MVP, VIPER, …

Câu 6: Phân biệt Strong pointer và Weak pointer

Pointer hay con trỏ là một cách truy cập trực tiếp vào memory (bộ nhớ) để tương tác với dữ liệu; trong Objective-C hay Swift đều hỗ trợ các phương thức làm việc với con trỏ.

Strong pointer là một con trỏ được sử dụng để trỏ đến một đối tượng và đồng thời sở hữu đối tượng đó; ngược lại thì Weak pointer không sở hữu đối tượng đó. Hay nói cách khác thì Strong pointer sẽ quyết định đến sự tồn tại của đối tượng.

Trong iOS, có 1 khái niệm là retainCount thể hiện số lượng con trỏ sở hữu đối tượng đó. Nếu một đối tượng không thuộc sở hữu của con trỏ nào thì đối tượng đó sẽ bị hủy (giải phóng bộ nhớ). Strong pointer khi trỏ đến 1 đối tượng sẽ làm tăng retainCount lên 1 đơn vị, ngược lại thì Weak pointer sẽ không làm tăng retainCount. Khi đối tượng mà weak pointer trỏ đến bị hủy, lúc này giá trị của weak pointer sẽ bị set về null.

Câu 7: So sánh các collection Array, Set và Dictionary trong Swift

Collection là những kiểu dữ liệu tập hợp, trong Swift có 3 dạng chính là Arrays, Sets và Dictionary. 

  • Array (Mảng) : sử dụng để lưu trữ dữ liệu cùng kiểu và sắp xếp có thứ tự. Do cần có thứ tự nên các phần tử trong mảng có thể trùng lặp nhau.
  • Set (Bộ): cũng được sử dụng để lưu trữ các dữ liệu có cùng kiểu nhưng không quan tâm đến thứ tự sắp xếp trong đó. Khác với Array, các phần tử trong Set không được phép trùng lặp
  • Dictionary (Từ điển): lưu trữ dữ liệu bằng cặp key – value, các key bắt buộc không trùng lặp nhau, tuy nhiên value thì có thể trùng lặp.

Câu 8: App Bundle trong iOS là gì?

Khái niệm App Bundle được sử dụng cho cả iOS và Android, đây là thư mục chứa toàn bộ source code và resource của ứng dụng được tự động tạo ra khi bạn thực hiện việc đóng gói để chuẩn bị upload ứng dụng lên store. 

Với iOS, Apple tổ chức thư mục bundle chứa trong đó các thư mục con được xác định rõ cấu trúc theo nền tảng và loại gói. Để đọc được nội dung bundle theo cấu trúc thì các tệp thực thi cần sử dụng đối tượng gói (bundle object) để xác định vị trí tài nguyên bên trong gói của ứng dụng hoặc cũng có thể đọc từ các gói khác (thường được Apple cung cấp sẵn trong các framework, plugins của mình).

Câu 9: So sánh việc phát triển ứng dụng iOS bằng Objective-C/Swift và các cross platform mobile

Phát triển ứng dụng iOS bằng Objective-C hay Swift (là những ngôn ngữ được Apple giới thiệu dành riêng cho iOS) được gọi là Native- hay phát triển bằng chính ngôn ngữ gốc. Ngược lại với nó là sử dụng các cross platform (đa nền tảng) như React Native, Flutter, Xamarin, … để viết source code bằng các ngôn ngữ khác như JavaScript, Dart, C#, … và build thành các ứng dụng có thể chạy được trên nhiều nền tảng mobile khác nhau trong đó có cả iOS. 

Việc phát triển ứng dụng iOS bằng native đương nhiên được hỗ trợ tốt nhất từ Apple và iOS SDK, luôn được cập nhật tính năng trong phiên bản hệ điều hành sớm hơn cùng tài liệu đầy đủ. Ứng dụng build ra từ Native luôn được đánh giá cao hơn về hiệu năng, khả năng tương thích cũng như thiết kế đồng bộ với phiên bản iOS mới nhất. Tuy vậy thì việc phát triển ứng dụng cross platform đem lại cho chúng ta lợi ích về mặt thời gian phát triển, chi phí xây dựng ứng dụng cũng như sự đồng bộ về giao diện của ứng dụng trên nhiều nền tảng. Vì vậy lựa chọn phát triển ứng dụng iOS bằng hướng nào thường phụ thuộc vào định hướng sản phẩm của nhà phát triển cũng như các ràng buộc về thời gian và chi phí dự án.

Câu 10: Các bước để phát hành ứng dụng iOS trên AppStore

Bước đầu tiên, bạn cần đăng ký chương trình nhà phát triển của Apple (Apple Developer Program) để có thể phát hành ứng dụng lên chợ Appstore

Sau khi có tài khoản, bạn cần tạo các file và thiết lập cho tài khoản và ứng dụng của mình, bao gồm:

  • AppID: xác minh ứng dụng của bạn, nó là duy nhất
  • Các thông tin cơ bản về ứng dụng: từ tên, mô tả, các ảnh chụp màn hình, các thông tin để phía Apple kiểm duyệt, … bạn cần cung cấp để mọi người biết đến ứng dụng của bạn
  • Certificate: chứng chỉ được cấp bởi Apple đảm bảo việc ứng dụng của bạn được chấp nhận bởi các thiết bị sử dụng iOS
  • Provisioning: như một hồ sơ đăng ký giúp ứng dụng của bạn xác định danh tính, bảo mật thông tin và giúp bạn có thể build được ứng dụng lên Appstore

Sau khi chuẩn bị hết các thứ ở trên, chúng ta tiến hành build và phát hành ứng dụng thông qua AppStore. Apple cũng cung cấp sẵn các tính năng giúp nhà phát hành kiểm thử ứng dụng nội bộ (trên một nhóm các testers được chỉ định) hoặc phát hành các bản dùng thử alpha, beta,…

Kết bài

Trên đây là top 10 câu hỏi cho vị trí iOS Developer mà các bạn sẽ có thể gặp trong buổi phỏng vấn của mình. Hãy chuẩn bị kiến thức về iOS, về ngôn ngữ Swift hay các công cụ lập trình như Xcode để có thể trả lời một cách tốt nhất các câu hỏi liên quan đến mảng kiến thức này. Chúc các bạn có một buổi phỏng vấn thành công và hẹn gặp lại trong các bài viết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

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

Thao tác Mouse hover trong Selenium Webdriver

Thao tác Mouse hover trong Selenium Webdriver

Bài viết được sự cho phép của vntesters.com

Sự xuất hiện của class Action cũng như là các method mà nó cung cấp, được sử dụng để giúp bạn xử lý một số các thao tác hơi đặc biệt một chút liên quan đến mouse, keyboard… mà ta vẫn gặp trong các ứng dụng web. Ở các bài viết trước đây như xử lý Drag- drop, right-click, double-click… các bạn cũng đã biết được chức năng và cách sử dụng của nó rồi. Và hôm nay mình sẽ bổ sung thêm trong list kia một method khác mà đôi khi ta cũng có thể gặp phải, đó chính là mouse hover (các bạn cũng có thể search google với tên khác là mouseover).

Thao tác Mouse hover trong Selenium Webdriver

Trong thực tế, cũng có không ít những tình huống ta gặp phải những trường hợp như này, đó là thực hiện đưa con trỏ chuột vào một menu hay button nào đó, từ menu hay button ấy sẽ hiển thị ra thông tin nào đó hoặc là lại tiếp tục hiển thị ra các submenu nhỏ hơn để ta có những lựa chọn tương ứng phù hợp. Công việc của chúng ta bây giờ là dùng Selenium để automate thao tác này.

  Đợi đối tượng UI hoặc sự kiện với Selenium WebDriver

  Sử dụng các câu lệnh điều khiển trên Selenium IDE

Xem thêm tuyển dụng ReactJS hấp dẫn trên TopDev

Thao tác Mouse hover trong Selenium Webdriver

Dạo quanh các trang web, diễn đàn hay blog tìm hiểu về cái này thì hầu hết đều đi đến một mẫu số chung cho bài toán này đó là sử dụng class Action, với method moveToElement(toElement). Ta có cú pháp như sau:

Hover:

public static void Hover(WebDriver driver, WebElement element) {
               Actions action = new Actions(driver);
               action.moveToElement(element).perform();
}

Hover kết hợp click:

public static void hoverAndClick(WebDriver driver,WebElement elementToHover, 
                                 WebElement elementToClick) {
      Actions action = new Actions(driver);
      action.moveToElement(elementToHover).click(elementToClick)
            .build().perform();
}

Hoặc :

public static void Hover(WebDriver driver, WebElement elementToHover, 
                         WebElement elementToClick) {
              Actions action = new Actions(driver);
              action.moveToElement(elementToHover).build().perform();
              elementToClick.click();
}

Đối với một số trình duyệt, có thể xảy ra trường hợp là khi hover vào một menu, submenu hiển thị ra nhưng Selenium chưa kịp thực hiện thao tác nào lên submenu ấy thì cái menu đã bị biến mất, nên không thể thao tác tiếp với submenu được. Do đó gợi ý cho bạn trong trường hợp này đó là ta sẽ sử dụng action perform() trên menu chính, cho đến khi Selenium có thể xác định và thao tác được đến submenu đích muốn thực hiện, chỉ với cú pháp đơn giản như sau:

public static void Hover(WebDriver driver, WebElement menuToHover, 
                         WebElement submenuToClick) {
               Actions action = new Actions(driver);
               action.moveToElement(menu).perform();
               action.moveToElement(submenu);
               action.click();
               action.perform();
}

Đó, vậy thôi. Cũng không quá khó đúng không nào. Hi vọng bài viết đã tổng hợp được những hữu ích nhất định cho các bạn.

Các bạn có thể tham khảo đoạn code ngắn ví dụ này của mình cho dễ hình dung nhé!

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.interactions.Actions;
public class MouseHover {
      public static void main(String[] args) {
            System.setProperty("webdriver.gecko.driver", "E:\\Program\\Firefox\\geckodriver.exe");
            FirefoxOptions options = new FirefoxOptions();
            options.setBinary("C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe");
            FirefoxDriver driver = new FirefoxDriver(options);
            driver.get("http://www.myntra.com");
            WebElement women = driver.findElement(By.linkText("Women"));           
            Actions action = new Actions(driver);
            action.moveToElement(women).build().perform();       
            WebElement type = driver.findElement(By.linkText("Kurtis, Tunics & Tops"));        
            type.click();
      }
}

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

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

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

Hướng dẫn tạo Let’s Encrypt Certificates dưới local và import vào AWS Certificate Manage

Hướng dẫn tạo Let’s Encrypt Certificates dưới local và import vào AWS Certificate Manage

Bài viết được sự cho phép của tác giả Lê Chí Dũng

SSL/TLS certificates thì được dùng phổ biến trong hệ thống nhằm tăng cường security. Và việc load balancer, Gateway,… thì cấu hình này khá phức tạp và AWS Certificate Manage (ACM) sẽ giúp cho việc này dễ dàng quản lý hơn. Trong bài này mình sẽ share cách tích hợp Let’s Encrypt Certificates (miễn phí) trên ACM.

1. Cài đặt Certbot của Let’s Encrypt Certificates

Tài liệu tham khảo: https://certbot.eff.org/

Nếu dùng MacOS thì cài từ brew cho lẹ https://formulae.brew.sh/formula/certbot

brew install certbot

2. Execute certbot và cấu hình DNS để tạo Certificate cho domain dưới local

sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns -d 'domain.com'

Sau khi execute command ở trên sẽ xuất hiện thông tin set up DNS trên domain.

  • Type: TXT
  • Name: _acme-challenge
  • Value: 3qFPwRcxEd…

Sau khi add xong TXT trên DNS thì chờ vài giây hoặc vài phút mới apply. Trong lúc chờ có thể confirm bằng cách access vào URL Toolbox của google check https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challen…

  Đồng bộ dữ liệu giữa MongoDB với Elasticsearch bằng Transporter

Hướng dẫn tạo Let’s Encrypt Certificates

Xem thêm Front-End Developer Jobs tại TopDev!!

3. Import Certificate vào ACM (AWS Certificate Manage)

Sau khi generate certificate ta sẽ có 4 files:

  • /etc/letsencrypt/live/domain.com/cert.pem
  • /etc/letsencrypt/live/domain.com/privkey.pem
  • /etc/letsencrypt/live/domain.com/chain.pem
  • /etc/letsencrypt/live/domain.com/fullchain.pem

Sau khi access AWS Certificate Manage, chọn import.

Hướng dẫn tạo Let’s Encrypt Certificates

  Giới thiệu Abstract Factory Pattern

Lúc này nhập thông tin tương ứng các field sau:

  • Certificate Body, sử dụng cert.pem
  • Certificate Private Key, sử dụng privkey.pem
  • Certificate Chain, sử dụng fullchain.pem
Hướng dẫn tạo Let’s Encrypt Certificates

Sau khi nhập đúng thông tin thì Next tới màn hình review thông tin Certificate rồi Import thôi.

Sau khi import xong thì giờ có thể tích ACM này vào Gateway,… cần certifcate.

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

Test REST Web Service đơn giản hơn với REST Assured

Test REST Web Service đơn giản hơn với REST Assured

Bài viết được sự cho phép của tác giả Giang Phan 

Ở bài viết trước, tôi đã giới thiệu với các bạn cách test REST API trong Jersey project. Giả sử bây giờ chúng ta cần sử dụng API của bên thứ 3 (không phải source code trong jersey project của chúng ta), khi đó ta không thể sử dụng Jersey Test. Khi đó, chúng ta cần một thư viện khác có thể giúp chúng ta gửi một request thật để verfiy kết quả trả về.

Trong bài này tôi sẽ giới thiệu với các bạn một thư viện rất mạnh mẽ để test web service, đó chính là REST Assured. Nó cho phép chúng ta gửi một HTTP request thật và verify trên kết quả trả về một cách dễ dàng. Chẳng hạn chúng ta có một request http://localhost:8080/lotto/{id} và server trả về response JSON như sau:

Test REST Web Service
Test REST Web Service

Khi đó chúng ta dễ dàng sử dụng REST Assured để verify mọi thứ từ response trên như sau:

Test REST Web Service
Test REST Web Service

Mọi thứ trông thật đơn giản phải không nào? Bây giờ, chúng ta hãy bắt đầu cài đặt thư viện cần thiết và viết một vài test case cho REST API sử dụng REST Assured.

Cài đặt REST Assured

Để sử dụng REST Assured chúng ta đơn giản chỉ việc thêm dependency sau trong file pom.xml.

<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>4.0.0</version>
</dependency>

  API là gì? Các nguyên tắc xây dựng Rest API

  Dùng Vim làm REST API client

Xây dựng Jersey Rest API

Bước này chỉ là giả định bên thứ ba cung cấp cho chúng ta các API để sử dụng, nếu các bạn đã có sẵn REST API, các bạn có thể đi đến bước kế tiếp “Test REST API sử dụng REST Assured”.

Để dễ hiểu, tôi sử dụng lại service đã tạo ở bài trước để hướng dẫn các bạn viết JUnit Test cho REST API với REST Assured.

Chúng ta có các API sau:

Test REST Web Service
Test REST Web Service

Giả sử tất cả các API này user cần phải được chứng thực trước. Tôi sẽ sử dụng Basic Authentication với JWT. Chi tiết các bạn xem lại bài viết “JWT – Token-based Authentication trong Jersey 2.x“.

Chúng ta có class AuthService như sau:

package com.gpcoder.api;

import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.gpcoder.helper.JwTokenHelper;
import com.gpcoder.model.User;
import com.gpcoder.service.UserService;

@Path("/auth")
public class AuthService {

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response authenticateUser(@FormParam("username") String username, @FormParam("password") String password) {

        // Authenticate the user using the credentials provided
        UserService userService = new UserService();
        User user = userService.getUser(username);
        if (user == null || !user.getPassword().equals(password)) {
            return Response.status(Response.Status.FORBIDDEN) // 403 Forbidden
                    .entity("Wrong username or password") // the response entity
                    .build();
        }

        // Issue a token for the user
        String token = JwTokenHelper.createJWT(user);

        // Return the token on the response
        return Response.ok(token).build();
    }
}

Class OrderService cần thêm Annotation Authorized của Jersey @RolesAllowed(Role.ROLE_ADMIN)

package com.gpcoder.api;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.SecurityContext;

import com.gpcoder.model.Order;
import com.gpcoder.model.Role;

// URI:
// http(s)://<domain>:(port)/<YourApplicationName>/<UrlPattern in web.xml>/<path>
// http://localhost:8080/api/orders
@Path("/orders")
@RolesAllowed(Role.ROLE_ADMIN)
public class OrderService {

    @GET
    @Path("/{id}")
    public Response get(@PathParam("id") int id) {
        Order order = new Order();
        order.setId(1);
        order.setName("gpcoder");
        return Response.ok(order).build();
    }

    @POST
    public Response insert(Order order, @Context SecurityContext securityContext) {
        int newOrderId = 999;
        return Response.status(Status.CREATED).entity(newOrderId).build();
    }

    @PUT
    @Path("/{id}")
    public Response update(@PathParam("id") int id, Order order) {
        return Response.ok().build();
    }

    @DELETE
    @Path("/{id}")
    public Response delete(@PathParam("id") int id) {
        return Response.status(Status.NO_CONTENT).build();
    }
}

Test REST API sử dụng REST Assured

Do các API cần phải được chứng thực user trước khi sử dụng, nên chúng ta cần chứng thực trước để nhận một Token (JWT), sau đó gửi chúng vào header ở mỗi request.

  • getBearerToken() : gửi request authentication để lấy token (JWT).
  • testGetById_Way1() : sử dụng để test GET /api/orders/{id}, trong ví dụ này tôi sẽ verify trực tiếp response thông qua phương thức body của REST Assured.
  • testGetById_Way2() : sử dụng để test GET /api/orders/{id}, trong ví dụ này tôi sẽ tạo một POJO object để nhận response và verify kết quả thông qua các phương thức của JUnit.
  • testCreate() : sử dụng để test POST /api/orders
  • testUpdate() : sử dụng để test PUT /api/orders/{id}
  • testDelete() : sử dụng để test DELETE /api/orders/{id}

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

OrderServiceRestAssuredTest.java

package com.gpcoder.api;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;

import javax.ws.rs.core.Response.Status;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import com.gpcoder.model.Order;

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.response.Response;

public class OrderServiceRestAssuredTest {

    private static String BEARER_TOKEN = "";

    @BeforeClass
    public static void setUp() {
        RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
        RestAssured.baseURI = "http://localhost";
        RestAssured.port = 8080;
        BEARER_TOKEN = getBearerToken();
    }

    public static String getBearerToken() {
        Response response = 
            given()
                .header("Content-Type", "application/x-www-form-urlencoded")
                .formParam("username", "gpcoder")
                .formParam("password", "gpcoder")
                .request()
            .when()
                .post("/api/auth")
            .then()
                .assertThat()
                .statusCode(Status.OK.getStatusCode())
                .extract()
                .response();
        return response.asString();

    }

    @Test
    public void testGetById_Way1() {
        given()
             .headers("Authorization", "Bearer " + BEARER_TOKEN)
             .accept(ContentType.JSON)
        .when()
             .get("/api/orders/1")
        .then()
             .statusCode(Status.OK.getStatusCode())
             .contentType(ContentType.JSON)
             .body("id", equalTo(1)) // Verify JSON Path
             .body("name", equalTo("gpcoder"));
    }

    @Test
    public void testGetById_Way2() {
        Order order = 
            given()
                .headers("Authorization", "Bearer " + BEARER_TOKEN)
                .accept(ContentType.JSON)
            .when()
                .get("/api/orders/1")
            .then()
               .statusCode(Status.OK.getStatusCode())
               .contentType(ContentType.JSON)
               .extract().as(Order.class); // Use POJOs and Object Mapping

        Assert.assertEquals(1, order.getId().intValue());
        Assert.assertEquals("gpcoder", order.getName());
    }

    @Test
    public void testCreate() {
        Order order = new Order(1, "gpcoder");

        Integer newOrderId =
            given()
                .headers("Authorization", "Bearer " + BEARER_TOKEN)
                .contentType(ContentType.JSON)
                .accept(ContentType.JSON)
                .body(order)
           .when()
                .post("/api/orders")
           .then()
               .assertThat()
               .statusCode(Status.CREATED.getStatusCode())
               .extract().as(Integer.class);

        Assert.assertEquals(999, newOrderId.intValue());
    }

    @Test
    public void testUpdate() {
        Order order = new Order(1, "gpcoder edited");
        given()
            .headers("Authorization", "Bearer " + BEARER_TOKEN)
            .contentType(ContentType.JSON)
            .body(order)
        .when()
            .put("/api/orders/{id}/", order.getId())
        .then()
            .assertThat()
            .statusCode(Status.OK.getStatusCode());
    }

    @Test
    public void testDelete() {
        given()
            .headers("Authorization", "Bearer " + BEARER_TOKEN)
        .when()
            .delete("/api/orders/{id}/", 1)
        .then()
           .assertThat()
           .statusCode(Status.NO_CONTENT.getStatusCode());
    }
}

Các bạn có thể chạy thử để xem kết quả.

Lưu ý: Phải start server REST API lên trước khi chạy Unit Test.

Như bạn thấy, REST Assured hỗ trợ cú pháp rất quen thuộc từ Behavior-Driven Development (BDD) khi viết Unit Test là Given/ When/ Then. Nhờ vậy mà Unit test của chúng ta rất dễ đọc và dễ kiểm tra tất cả mọi thứ (setup, execution, and verification) với chỉ vài dòng code.

  • Given: Thiết lập các điều kiện cần thiết: khởi tạo các đối tượng, xác định tài nguyên cần thiết, xây dựng các dữ liệu giả, …
  • When: Triệu gọi các phương thức cần kiểm tra.
  • Then: Kiểm tra sự hoạt động đúng đắn của các phương thức.

Test REST Web Service

Trên đây là một số ví dụ cơ bản về viết Unit Test cho REST web server sử dụng thư viện REST Assured, còn rất nhiều phương thức khác hỗ trợ chúng ta viết test dễ dàng hơn và nhanh chóng hơn, các bạn hãy tham khảo thêm trên document của REST Assured.

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

MD5 là gì? Công cụ mã hóa MD5 online

MD5 là gì? Công cụ mã hóa MD5 online

Bài viết được sự cho phép của tác giả Phạm Bình

Bạn có từng thấy qua biểu tượng MD5 khi tải file hay phần mềm trên máy tính? MD5 được sử dụng khá phổ biến nhưng không chắc nhiều bạn đã biết MD5 là gì. Cùng TopDev tìm hiểu về MD5 thật chi tiết thông qua bài viết dưới đây nhé!

MD5 là gì? Công cụ mã hóa MD5 online

Công nghệ mã hóa MD5 là gì?

MD5 (Message Digest Algorithm 5) là một thuật toán băm mật mã học (hash algorithms) được phát triển bởi Ronald Rivest vào năm 1991. MD5 được sử dụng để tạo ra một giá trị băm (hash value) cố định từ một thông điệp hoặc một đoạn dữ liệu đầu vào. Giá trị băm này thường được gọi là “message digest” và có độ dài 128 bit (16 byte), thường được biểu diễn dưới dạng một chuỗi 32 ký tự hex.

Công nghệ mã hóa MD5 là gì?

Sau khi mã hóa, MD5 luôn cho ra kết quả là một chuỗi có độ dài cố định 32 ký tự cho dù đầu vào là gì đi nữa, và kết quả này không thể dịch ngược (không thể giải mã) lại được.

<?php

// Ví dụ sử dụng mã hóa md5 trong lập trình PHP

$string1 = "Hello world";
echo md5($string1); // f690e937880ebd98086689b871744a84

$string2 = "Xin chao cac ban nha";
echo md5($string2); // f514d5e5d14553003120806ddadffafe

Trên lý thuyết, mỗi đầu vào của thuật toán mã hóa md5 sẽ tương ứng với một đầu ra duy nhất. Nhưng thực tế, người ta cũng đã tìm ra một vài lỗ hổng cho thấy rằng mặc dù đầu vào là 2 mẫu khác nhau, nhưng sau khi mã hóa lại cho ra kết quả giống nhau. Tuy nhiên, sự “đụng độ” về đầu ra của thuật toán mã hóa md5 chỉ xảy ra ở một số trường hợp đặc biệt, và nó không đủ để làm người ta thôi sử dụng thuật toán mã hóa này, ngoài ra bạn cũng có thể thêm “muối” để giảm khả năng xảy ra đụng độ (chi tiết sẽ trình bày ở mục 3).

Cụm từ “đụng độ kết quả” ám chỉ với các đầu vào khác nhau nhưng lại cho ra các kết quả giống nhau.

  Mã hóa mật khẩu trong Selenium Webdriver

Mã hóa MD5 thường dùng để làm gì?

Về cơ bản, MD5 là một hàm băm, vì vậy các ứng dụng của nó thường là để:

Mã hóa mật khẩu

Do có tính chất không thể dịch ngược, nên MD5 được sử dụng phổ biến để mã hóa mật khẩu.

Kiểm tra tính toàn vẹn của dữ liệu

Bạn sẽ hiểu hơn khi tham khảo ví dụ sau:

Anh A download một phần mềm X trên internet, nhưng vì một lý do nào đó mà anh A phải download ở một nguồn KHÔNG CHÍNH CHỦ. Anh A lo sợ phần mềm X này đã bị hacker chèn virus. Nhưng may mắn, trên trang chủ của phần mềm X có cung cấp một mã md5 – là kết quả của việc mã hóa toàn bộ phần mềm. Giả sử mã md5 đó là f690e937880ebd98086689b871744a84.

Để đảm bảo phần mềm X download ở nguồn không chính chủ kia chưa bị chỉnh sửa gì, hay nói cách khác là giống hệt so với việc download từ nguồn chính chủ. Anh A đã mã hóa phần mềm X vừa download bằng thuật toán md5, sau đó so sánh kết quả với mã md5 của nhà phát hành. Nếu 2 mã giống nhau, anh A có thể tin tưởng rằng phần mềm X này chưa bị chỉnh sửa, bởi trên lý thuyết mỗi đầu vào của md5 sẽ chỉ cho ra 1 kết quả duy nhất. Ngược lại, nếu 2 kết quả khác nhau, thì có nghĩa là phần mềm anh A download đã bị chỉnh sửa khác với phiên bản của nhà phát hành.

Trên là một ví dụ điển hình của việc sử dụng md5 để kiểm tra tính toàn vẹn của dữ liệu.

Với nhưng tập dữ liệu lớn hoặc các tệp tin không phải dạng văn bản thuần túy, thì rất khó để nhận biết liệu có sự thay đổi nào giữa 2 phiên bản hay không. Để làm đơn giản việc so sánh này, người ta sẽ dùng một hàm băm (như VD trên là sử dụng md5) để mã hóa các dữ liệu cần so sánh, sau đó nhận biết sự khác nhau dựa vào việc so sánh các kết quả của hàm băm này. Nếu các kết quả giống nhau, đồng nghĩa là các tệp dữ liệu ban đầu cũng giống nhau và ngược lại.

Các thao tác tương tự như trên còn được gọi là checksum.

Tham khảo việc làm JavaScript Developer trên TopDev!

Đặc điểm của thuật toán Message-digest

Các hàm băm, còn được gọi là thuật toán message-digest, là các hàm một chiều; chúng chấp nhận một thông điệp có kích thước bất kỳ làm đầu vào và tạo ra một thông điệp băm có độ dài cố định.

MD5 là thuật toán message-digest thứ ba được tạo ra bởi Ronald Rivest. Các thuật toán MD2, MD4 và MD5 có cấu trúc tương tự nhau, nhưng MD2 được tối ưu hóa cho các máy 8-bit, trong khi hai thuật toán sau được thiết kế cho các máy 32-bit. Thuật toán MD5 là một phần mở rộng của MD4, mặc dù MD4 được đánh giá là nhanh nhưng tiềm ẩn nguy cơ bảo mật. Ngược lại, MD5 không nhanh bằng MD4 nhưng cung cấp mức độ đảm bảo bảo mật dữ liệu cao hơn nhiều.

MD5 hoạt động như thế nào?

Thuật toán băm message-digest MD5 xử lý dữ liệu dưới dạng các chuỗi 512-bit, được chia nhỏ thành 16 từ, mỗi từ gồm 32 bit. Đầu ra từ MD5 là một giá trị message-digest có độ dài 128-bit.

Việc tính toán giá trị băm MD5 được thực hiện qua các giai đoạn riêng biệt, xử lý từng khối dữ liệu 512-bit cùng với giá trị được tính toán ở giai đoạn trước đó. Giai đoạn đầu tiên bắt đầu với các giá trị message-digest được khởi tạo bằng các giá trị số thập lục phân liên tiếp. Mỗi giai đoạn bao gồm bốn lượt xử lý message-digest, chúng thao tác các giá trị trong khối dữ liệu hiện tại và các giá trị được xử lý từ khối trước đó. Giá trị cuối cùng được tính toán từ khối cuối cùng trở thành giá trị băm MD5 cho khối đó.

Nguyên lý hoạt động chung của MD5

Nguyên lý hoạt động chung của MD5

Chuẩn bị dữ liệu đầu vào

  1. Bổ sung bit (Padding Bits):
    • Đầu vào ban đầu được bổ sung thêm một bit 1 và sau đó là một chuỗi các bit 0 để độ dài của thông điệp sao cho nó thỏa mãn yêu cầu: độ dài thông điệp sau bổ sung bit chia hết cho 512 (cụ thể là 448 bit + 64 bit cho chiều dài gốc của thông điệp).
  2. Bổ sung chiều dài (Padding Length):
    • Đoạn dữ liệu gốc được bổ sung thêm một đoạn 64 bit để biểu diễn chiều dài của thông điệp ban đầu (trước khi bổ sung bit) dưới dạng nhị phân, sau đó được thêm vào cuối thông điệp. Bước này đảm bảo rằng chiều dài của thông điệp sau bổ sung chia hết cho 512 bit.

Khởi tạo các biến

MD5 sử dụng bốn bộ đệm 32 bit được khởi tạo với các giá trị hằng số nhất định:

  • A = 0x67452301
  • B = 0xEFCDAB89
  • C = 0x98BADCFE
  • D = 0x10325476

Xử lý từng khối

  1. Chia nhỏ thông điệp:
    • Thông điệp đã được bổ sung và chia thành các khối 512 bit.
  2. Xử lý mỗi khối 512 bit:Mỗi khối 512 bit được xử lý qua bốn vòng lặp, mỗi vòng lặp có 16 bước. Trong mỗi bước, một hàm phi tuyến tính được áp dụng lên ba trong số bốn bộ đệm, bộ đệm còn lại được cộng thêm một giá trị từ thông điệp và một giá trị hằng số. Các hàm phi tuyến tính được sử dụng trong các vòng lặp:
    • F (B, C, D) = (B AND C) OR (NOT B AND D)
    • G (B, C, D) = (B AND D) OR (C AND NOT D)
    • H (B, C, D) = B XOR C XOR D
    • I (B, C, D) = C XOR (B OR NOT D)
  3. Cập nhật bộ đệm:
    • Sau mỗi khối 512 bit được xử lý, giá trị của các bộ đệm A, B, C, D được cập nhật. Các giá trị mới này sẽ được sử dụng để xử lý khối tiếp theo.

Tạo giá trị băm cuối cùng

Sau khi tất cả các khối 512 bit được xử lý, bốn bộ đệm A, B, C, D sẽ chứa giá trị băm cuối cùng. Các bộ đệm này được nối lại để tạo ra giá trị băm 128 bit (16 byte).

MD5 có an toàn không?

MD5 (Message Digest Algorithm 5) hiện không còn được coi là an toàn về mặt mật mã học. Mục tiêu của bất kỳ hàm băm mật mã học nào là tạo ra các giá trị băm trông như ngẫu nhiên và đáp ứng hai yêu cầu quan trọng:

  1. Không thể tạo ra một thông điệp khớp với một giá trị băm cụ thể: Đảm bảo rằng không ai có thể tạo ra một thông điệp cụ thể mà khi băm lại cho ra giá trị băm đã biết trước.
  2. Không thể tạo ra hai thông điệp khác nhau cho ra cùng một giá trị băm: Đảm bảo rằng không ai có thể tìm ra hai thông điệp khác nhau nhưng lại có cùng giá trị băm (va chạm).

Theo Internet Engineering Task Force (IETF), hàm băm MD5 không còn đáp ứng được các yêu cầu này và do đó không nên được sử dụng cho mục đích xác thực mật mã học.

Các vấn đề bảo mật của MD5

Các vấn đề bảo mật của MD5
Các vấn đề bảo mật của MD5

Vào năm 2011, IETF đã công bố RFC 6151, “Cập nhật các xem xét về bảo mật cho thuật toán MD5 và HMAC-MD5,” trong đó trình bày nhiều cuộc tấn công gần đây vào hàm băm MD5. Báo cáo này chỉ ra rằng:

  • Có một cuộc tấn công có thể tạo ra va chạm băm trong vòng chưa đầy một phút trên máy tính xách tay tiêu chuẩn.
  • Một cuộc tấn công khác có thể tạo ra va chạm chỉ trong 10 giây trên hệ thống Pentium 4 tốc độ 2.6 GHz.

Do những lỗ hổng này, IETF khuyến nghị rằng các thiết kế giao thức mới không nên sử dụng MD5 và cho rằng các cuộc tấn công gần đây vào thuật toán này đã cung cấp đủ lý do để loại bỏ việc sử dụng MD5 trong các ứng dụng yêu cầu khả năng chống va chạm, chẳng hạn như chữ ký số.

Thay vào đó, các thuật toán băm mạnh hơn như SHA-256 hoặc SHA-3 được khuyến khích sử dụng để đảm bảo tính toàn vẹn và bảo mật của dữ liệu.

Sử dụng MD5 với “muối” để tăng độ an toàn

Giảm sự đụng độ

Như đã trình bày, kết quả của thuật toán mã hóa MD5 có thể bị đụng độ. Để giảm thiểu khả năng này, người ta thường kèm theo “muối” ở đầu vào của thuật toán. Bạn có thể xem ví dụ sau để dễ hiểu hơn:

<?php

// Ví dụ mã hóa md5 trong PHP có kèm theo "muối"

// Đây chính là "muối", một string bí mật mà chỉ có bạn mới biết
$salt = "$%&$#@^akdmrKDLDGK115";

// String cần mã hóa
$string = "Hello world";

// Output được mã hóa kèm theo "muối"
$output = md5($string . $salt);

echo $output; // d26e50b575ca5d47808442412410afe6

// Hoặc bạn có thể đóng gói thành hàm để dùng cho tiện
function my_md5($string) {
    $salt = "$%&$#@^akdmrKDLDGK115";
    return md5($string . $salt);
}

echo my_md5($string); // d26e50b575ca5d47808442412410afe6

Với thủ thuật trên, output sẽ giảm tỉ lệ bị đụng độ (giảm tới múc nào thì mình không rõ).

Giảm khả năng bị “vét cạn”

Việc thêm muối khi mã hóa, ngoài việc làm giảm lỗi đụng độ kết quả, còn làm giảm nguy cơ output của bạn bị “vét cạn” – brute force.

Mặc dù md5 là một hàm mã hóa không thể dịch ngược, nhưng vì dạng mã hóa này được sử dụng quá phổ biến, mà người ta có thể xây dựng nên một bộ từ điển chứa kết quả mã hóa của các bộ đầu vào phổ biến như 123123anhyeuemiloveyou,… Dựa vào từ điển này, mà một số mã md5 có thể bị dịch ngược. Bạn có thể dễ dàng tìm được các công cụ “dịch ngược md5” bằng cách tìm kiếm từ khóa “crack md5” trên google.

Tuy nhiên khi bạn mã hóa kèm theo muối, thì cho dù là các chuỗi có vẻ phổ biến như 123456abcdef cũng sẽ trở nên vô cùng phức tạp và khó đoán, và điều quan trọng nhất – tỉ lệ nó nằm trong bộ từ điển crack md5 là rất thấp (trừ khi bạn sử dụng “muối” quá đơn giản).

Một vài lưu ý với thủ thuật này:

  • Muối của bạn phải đủ phức tạp.
  • Chỉ có bạn mới biết muối là gì.

Qua bài viết trên của TopDev, chắc hẳn bạn đã hiểu MD5 là gì và cách thuật toán hash này hoạt động. Tuy còn nhiều lổ hổng bảo mật, nhưng đây cũng là một thuật toán mã hóa thú vị bạn nên biết, bạn có thể kết hợp với một số cách mà chúng tôi đề xuất để sử dụng MD5 an toàn và hiệu quả hơn.

Bài viết được TopDev cập nhật và chỉnh sửa từ bài gốc tại phambinh.net

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

Xem thêm các việc làm Developer hấp dẫn tại TopDev

Doc Comment Và Javadoc Trong Java

Doc Comment Và Javadoc Trong Java

Bài viết được sự cho phép của tác giả Nhựt Danh

Nhắc Lại Kiểu Documentation Comment

Từ bây giờ chúng ta hãy gọi chức năng này bằng một tên chuẩn tiếng Anh cho thống nhất, hãy gọi chức năng này là Documentation Comment, hay gọi tắt là Doc Comment cũng được. Chúng ta đều hiểu nó là cách comment code theo kiểu document vậy.

Vậy thì đây là một kiểu comment đặc biệt. Khác với kiểu // Text là comment trên một dòng hay /* Text */ là comment trên nhiều dòng code. Kiểu Doc Comment được ghi theo format /** Document */.

Tất cả các kiểu comment đều có một điểm giống nhau là khi build, trình biên dịch sẽ bỏ qua chúng, không build comment vào file build cuối cùng. Nhưng, khác với anh em trong họ comment, Doc Comment không đơn thuần chỉ là để comment, chúng được dùng trong một chuyện khác. Công dụng cụ thể của Doc Comment là gì thì mời bạn xem qua mục sau. Dưới đây là một ví dụ sử dụng comment theo kiểu Doc Comment.

/**
 * The MainClass is the class that help to print out the "Hello World!" text
 * 
 * @author yellowcode
 * @version 1.0
 * @since 2021-05-04
 *
 */
public class MainClass {

    /**
     * The main function, entry point of this app
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

Công Dụng Của Doc Comment

Về phía kinh nghiệm code bao lâu nay của mình, mình vẫn rất thích kiểu Doc Comment này hơn các kiểu comment khác, là vì có các lợi ích sau đây.

Thứ nhất, về mặt giải thích cho các dòng code bạn đang làm, thì Doc Comment sẽ luôn rõ ràng hơn do chúng có được sự hỗ trợ về mặt định dạng nổi bật hơn cho các tham số.

Doc-Comment -Javadoc-Trong-Java
Định dạng tham số bắt mắt (hiển thị trên InteliJ)

 

Thứ hai, là lợi ích về mặt sử dụng các dòng code có comment theo kiểu Doc Comment này. Thì khi sử dụng các thành phần được comment “chuẩn”, bạn sẽ thấy comment, hay document sẽ xuất hiện ở thanh ngữ cảnh của Eclipse hay InteiJ (bạn dễ dàng nhìn thấy các document này khi đưa chuột vào lớp hay hàm có Doc Comment).

Hiển thị Doc trên Eclipse

Thứ ba, về mặt xuất xưởng các thư viện. Doc Comment sẽ được một công cụ có tên Javadoc build ra một trang mô tả theo kiểu HTML. Nó là một trang Web được xây dựng hoàn chỉnh và bạn có thể dùng để publish hay nhúng vào trang Web khác. Rất thích hợp để bạn tạo ra các thư viện Java và gửi đến người dùng thư viện của bạn với đầy đủ các hướng dẫn sử dụng các Java code mà bạn xây dựng. Với lợi ích thứ ba này thì mình mời các bạn đến với mục tiếp theo để trải nghiệm nhé.

Sẽ thật thiếu sót nếu như nói về Doc Comment mà quên nói sơ về Javadoc.

Javadoc là một công cụ có sẵn đi kèm với JDKJavadoc dùng để xuất xưởng ra một document theo định dạng HTML, để giúp bạn mô tả rõ hơn về các source code Java của bạn hay của tổ chức của bạn. Nhưng để Javadoc có thể tạo ra một document, thì bạn nên tuân thủ theo những định dạng mà công cụ này cung cấp. Ở phần sau đây chúng ta sẽ đi sâu hơn về cách vận dụng các nguyên tắc và định dạng của Javadoc.

Nói sơ tí về Javadoc

  Ép Kiểu & Comment Source Code trong Java

  Functional Interface là gì? Functional Interface API trong Java 8

Thử Tạo Một HTML Document

Bước này chúng ta hãy cũng trải nghiệm việc sử dụng công cụ Javadoc để tạo ra một HTML document xịn xò.

Thật may là Eclipse hay InteliJ đều hỗ trợ các tương tác đến công cụ Javadoc một cách dễ dàng. Bạn hãy chọn một trong hai công cụ này để thực hành theo các chỉ dẫn sau.

Tạo HTML Document trên Eclipse

Với Eclipse. Với project đang mở. Và dĩ nhiên phải có một vài Doc Comment đã được bạn định nghĩa trong source code. Bạn hãy chọn theo menu Project > Generate Javadoc….

Doc-Comment -Javadoc-Trong-Java-1
Chọn Generate Javadoc từ menu

 

Một cửa sổ xuất hiện, bạn hãy để nguyên như mặc định. Chúng là các thiết lập đường dẫn đến file thực thi Javadoc, project cần tạo Javadoc, cũng như nơi mà thành phẩm HTML document được trích xuất ra (đó chính là thư mục /doc bên trong project của bạn).

Doc-Comment -Javadoc-Trong-Java-2
Tùy chọn cho việc tạo Javadoc

 

Hãy đảm bảo các chọn lựa của bạn giống như hình trên. Sau đó nhấn Next. Một cửa sổ chọn lựa khác xuất hiện như sau.

Doc-Comment -Javadoc-Trong-Java-3
Tùy chọn tiếp theo cho việc tạo Javadoc

 

Ở bước trên, bạn hãy nhập vào tiêu đề cho document (mục Document title). Khi này bạn có thể nhấn Finish vì thực chất bước sau nữa cũng không có gì đáng chú ý cả.

Sau một lúc, bạn sẽ thấy xuất hiện thêm một thư mục /doc bên trong project của bạn ở của sổ Package Explorer. Hãy xổ thư mục này ra và tìm đến file index.html và click đúp vào đó, bạn sẽ thấy nội dung document đã được tạo ra tự động y như một trang Web thực thụ vậy. Và đây là những gì chúng ta đã comment vào source code theo dạng Doc Comment.

Doc-Comment -Javadoc-Trong-Java-4
Kết quả tạo ra Document cho các lớp chúng ta đã tạo

 

Bạn hãy thử trải nghiệm bằng cách click chuột đi tới đi lui trong trang Web này để xem Javadoc giúp tạo các hướng dẫn cho code của chúng ta như thế nào.

Ở mục sau chúng ta sẽ tìm hiểu sâu hơn việc tạo document một cách chỉn chu hơn, đầy đủ và chuyên nghiệp hơn như thế nào nhé.

Tham khảo việc làm Java hấp dẫn trên TopDev

Tạo HTML Document Trên InteliJ

Với InteliJ. Với project đang mở. Và dĩ nhiên phải có một vài Doc Comment đã được bạn định nghĩa trong source code. Bạn hãy chọn theo menu Tools > Generate JavaDoc….

Doc-Comment -Javadoc-Trong-Java-5
Chọn Generate Javadoc từ menu

 

Một cửa sổ xuất hiện, bạn hãy để nguyên như mặc định. Chúng là các thiết lập phạm vi áp dụng để tạo HTML document (scope), cấp độ chia sẻ private/package/protected/public. Và thiết lập nơi mà thành phẩm HTML document được trích xuất ra, bạn có thể chỉ định xuất vào thư mục /doc bên trong project của bạn như dưới đây.

Tùy chọn cho việc tạo Javadoc
Tùy chọn cho việc tạo Javadoc

 

Sau khi nhấn OK ở cửa sổ trên, bạn sẽ thấy ngay lập tức Web Browser mặc định trên máy bạn được mở ra với nội dung chính là giới thiệu về project của bạn kèm với các Doc Comment trong đó.

Doc-Comment -Javadoc-Trong-Java-7
Kết quả tạo ra Document cho các lớp chúng ta đã tạo

 

Bạn hãy thử trải nghiệm bằng cách click chuột đi tới đi lui trong trang Web này để xem Javadoc giúp tạo các hướng dẫn cho code của chúng ta như thế nào.

Ở mục sau chúng ta sẽ tìm hiểu sâu hơn việc tạo document một cách chỉn chu hơn, đầy đủ và chuyên nghiệp hơn như thế nào nhé.

Định Dạng Java Doc Thông Qua Sử Dụng Tag

Ở các ví dụ trên đây, bạn đã nhìn thấy một số Tag được dùng trong Javadoc như @author@version@since@param. Và bạn đã hiểu các Tag này giống như các tham số giúp cho Javadoc có thể tạo ra các HTML và truyền các định nghĩa của từng Tag vào HTML như thế nào rồi đúng không nào. Các Tag trong Javadoc thường không ràng buộc một công thức nào kèm theo cả, bạn chỉ cần vận dụng Tag ở những nơi bạn cần HTML làm nổi bật thông tin đó lên thôi, vì dù sao Doc Comment cũng chỉ là một kiểu comment, nên bạn cứ thoải mái sử dụng đi nhé.

Mình sẽ không giải thích dài dòng về Tag nữa mà vào cụ thể việc sử dụng Tag trong Javadoc như thế nào luôn.

@author, @version, @since

  • @author: dùng để hiển thị thông tin tác giả.
  • @version: dùng để hiển thị version của document.
  • @since: dùng hiển thị ngày hoặc version tạo ra document.

Mời bạn xem ví dụ sử dụng Tag và kết quả xuất ra dưới dạng HTML document.

Doc-Comment -Javadoc-Trong-Java-8
Ví dụ sử dụng các tag @author, @version, @since

 

{@code}, @param

  • {@code}: giúp hiển thị code bên trong HTML. Các code này được hiển thị với font chữ khác các font chữ còn lại, và bạn cũng không cần lo lắng nếu có các dòng code xung đột với các tag của HTML khi này.
  • @param: theo sau tag này sẽ là tên tham số của hàm, theo sau nữa sẽ là lời giải thích cho tham số đó.

Chi tiết về cách sử dụng 2 Tag này được thể hiện qua ví dụ dưới đây.

Doc-Comment -Javadoc-Trong-Java-9
Ví dụ sử dụng các tag {@code}, @param

 

@deprecated, {@link}

  • @deprecated: giúp đánh dấu rằng thành phần này sẽ bị gỡ bỏ khỏi API trong nay mai.
  • {@link}: link dẫn đến một thành phần khác trong source code.

“Hiệu ứng” của các Tag này được minh họa bằng các ví dụ dưới.

Doc-Comment -Javadoc-Trong-Java-10
Ví dụ sử dụng các tag @deprecated, {@link}

 

@exception, @throws

Hai Tag này có công dụng như nhau. Giúp thêm một thông tin Throws trong document báo hiệu phương thức này sẽ tung ra một exception.

Doc-Comment -Javadoc-Trong-Java-11
Ví dụ sử dụng tag @exception

 

@return, @see

  • @return: giải thích cho return của hàm.
  • @see: đưa ra các tham khảo đến các class khác.

Doc-Comment -Javadoc-Trong-Java-12
Ví dụ sử dụng các tag @return, @see

 

{@value}

Giúp hiển thị giá trị của các static field.

Doc-Comment -Javadoc-Trong-Java-13
Ví dụ sử dụng tag {@value}

 

Tham Khảo Thêm Các Định Dạng Khác

Trên đây mình có trình bày qua các định dạng Tag phổ biến trong Javadoc. Tuy nhiên vẫn còn một số định dạng khác, chẳng hạn như vận dụng thêm các thẻ HTML vào Doc Comment, thì bạn có thể làm quen thông qua việc tìm hiểu chính source code của “chính chủ” Oracle, hoặc bạn hãy để ý các Doc Comment từ các source code của các thư viện khác. Đảm bảo bạn sẽ thấy thích và ngộ ra được nhiều phong cách Doc Comment từ các nguồn này, bạn sẽ nhanh “lên tay” hơn cho việc comment cho source code của chính bạn thôi.

Để xem source code của JDK, đơn giản, khi Eclipse hoặc InteliJ đang mở, hãy nhấn giữ phím Ctrl (Windows) hoặc Command (Mac) và click vào lớp được xây dựng sẵn từ JDK. Như ví dụ dưới đây mình mở ra lớp String, bạn sẽ nhanh chóng nhìn thấy source code của lớp này trên chính IDE của bạn.

Doc-Comment -Javadoc-Trong-Java-14
Xem source code của file String

 

Hoặc bạn có thể xem ở một số link online cũng được. Như một vài link mình liệt kê sau.

Kết Luận

Chúng ta vừa xem qua các cách sử dụng Doc Comment trong lập trình Java như thế nào. Hi vọng thông qua bài viết này, các bạn sẽ nâng cao hơn tính “thẩm mỹ” và tính dễ đọc đối với các source code của các bạn thông qua việc nâng cao kỹ năng comment. Cũng như hiểu rõ các document được tạo ra như thế nào ở các thư viện mà các bạn đang dùng.

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

Xem thêm:

Tìm việc làm IT mọi cấp độ tại TopDev

Phương pháp kiểm thử ứng dụng Web phổ biến

Bài viết được sự cho phép của vntesters.com

Xin chào các bạn! Để tiếp nối chủ đề “Kiểm thử web“, trong khuôn khổ bài viết này, mình xin hệ thống một số loại test cơ bản mà bạn cần lưu ý khi kiểm thử một ứng dụng web (web app) để các bạn có những hình dung cụ thể hơn công việc mình cần làm.

Functionality test: cũng như bất kỳ một ứng dụng nào khác, việc kiểm thử xem ứng dụng web có được xây dựng đúng với yêu cầu (requirements) của nhà cung cấp hay không là điều tiên quyết và quan trọng nhất.

Cụ thể hơn, bạn cần xem xét từng ngóc ngách, từng câu chữ trong phần mô tả requirement, sitemap cũng như từng business rule của dịch vụ web được phát triển để bảo đảm là mọi thứ chạy đúng bản thiết kế và ý muốn khách hàng. Thêm vào đó, bạn cũng cần kiểm tra thiết kế có hướng theo các chuẩn thông dụng (web standards) về màu sắc, bố cục và bài trí hay không, có bảo đảm tiện dụng cho người dùng cuối (end-user) khi sử dụng không. Chúng ta có nhiều thứ phải làm ở phần này trên cả 2 mảng front-end và back-end.

Kiểm tra nội dung trình diễn trên trang web: Mỗi thành phần button, textbox, image, link trên page và bố cục page cần tuân theo chính xác kích thước và vị trí mà bản thiết kế UI quy định. Đa số các bản thiết kế đều kèm theo mockup/wireframe để chỉ rõ kích thước và vị trí, màu sắc, cỡ chữ và bố cục từng trang web. Bạn cần so sánh đối chiếu giữa mockup và nội dung thực sự hiển thị trên browser. Vì sao chúng ta cần quan trọng hóa vấn đề xăm soi này như vậy? Vì những ứng dụng web được đầu tư thỏa đáng thường có cả một đội ngũ các UX designers đầu tư nhiều công sức, nhằm tạo ra 1 thiết kế bố cục hài hòa và tiện dụng nhất. Vì vậy, đôi lúc một xê dịch nhỏ giữa các button cũng có thể làm mất đi ý tưởng thiết kế thân thiện ban đầu. Tôi biết vẫn còn rất nhiều coder có xu hướng dễ dãi trong việc canh chỉnh UI 

  Kiểm thử ứng dụng Web – Ứng dụng Web là gì?

Phương pháp kiểm thử ứng dụng Web phổ biến
UX, một nghề mới trong xây dựng web

  • Kiểm tra các link & menu: Kiểm tra tất cả link nội bộ (internal link) và link ngoại bộ (external link) xem chúng có hoạt động không, có trỏ đến đúng địa chỉ mong muốn không. Bạn cần bảo đảm các link email sẽ mở ra trình soạn email mặc định khi user click vào. Ngoài ra, các link không được tự trỏ đến vị trí của chính nó và không tồn tại các orphan page.
  • Kiểm tra các form nhập dữ liệu: Form nhập liệu là nơi browser tiếp nhận thông tin user nhập vào để chuyển đến server. Bạn cần bảo đảm các trường (field) dữ liệu được thiết kế đúng dạng, luôn có giá trị mặc định, luôn có bộ lọc kiểm tra (validation) những thông tin user nhập vào xem có hợp lệ không trước khi submit. Ngoài ra, quá trình chuyển tải thông tin từ browser đến server cũng cần bảo đảm là thông tin gửi đi khớp với những gì user nhập vào, không thất lạc và bị sai lệch. Một trong các lỗi thường gặp về nhập liệu là việc chuyển đổi các dạng dữ liệu (data type parsing) trong quá trình xử lý ở browser đôi lúc tạo ra sự không chính xác. Một vd điển hình là khi người coder vô tình làm tròn giá trị tiền tệ user nhập vào, hay khi định dạng số điện thoại không đúng cách thì số 0 đầu tiên thường bị cắt mất.
  • Kiểm tra lỗi cú pháp html/css: Chúng ta biết nội dung web được browser trình diễn dựa vào chuẩn ngôn ngữ html và css. Tất cả nội dung 1 trang web nhận được từ server chỉ bao gồm các html tag và css format, và chúng được browser biên dịch dựa vào các chuẩn trình diễn html. Các browser thế hệ mới đủ thông minh để nhận diện các đoạn html tag và css bị lỗi cú pháp và loại bỏ chúng khỏi web page. Điều này bảo đảm tính thẩm mỹ và tương tác cho người dùng nhưng lại là 1 con dao 2 lưỡi nếu vô tình mẫu thông tin bị mất lại là thông tin quan trọng user cần. Vì vậy bạn cần kiểm tra nội dung html và bảo đảm là ko có lỗi cú pháp xảy ra khi biên dịch. Bạn cần học cách chạy debug browser để tìm được lỗi cú pháp này vì đôi lúc lỗi đó không thể hiện lên trang web.
  • Kiểm tra cookie (browser) & session (server): Với các trang web hỗ trợ phiên đăng nhập (session), cookie sẽ là 1 thành phần cần kiểm tra để bảo đảm hệ thống xử lý tốt các trường hợp cấu hình bất thường từ máy client. Ví dụ như khi user tắt hỗ trợ cookie trên browser thì trang web của bạn sẽ phản ứng thế nào? Bạn cũng cần kiểm tra xem thông tin session được lưu đúng và cookie được xóa khi user đăng xuất (logout). Đồng thời cookie cũng cần được mã hóa nếu chứa đựng thông tin nhạy cảm của người dùng. Cùng chức năng với cookie, nhưng session được sử dụng ở phía server với độ bảo mật tốt hơn. Hãy kiểm tra session cho mỗi địa chỉ / tài khoản đăng nhập được server lưu trữ đúng, thời gian timeout cho mỗi lượt truy cập hay giới hạn truy cập cho mỗi tài khoản ở cùng 1 thời điểm (một số ứng dụng web đặc thù không cho phép đăng nhập cùng 1 tài khoản trên nhiều ip và browser khác nhau).
  • Kiểm tra bản dịch (localization): Nếu ứng dụng của bạn hỗ trợ đa ngôn ngữ, test bản dịch từng ngôn ngữ là cần thiết để bảo đảm quá trình dịch và gắn ráp không có sự cố “râu ông này cắm cằm bà kia”, hoặc bản dịch không sát nghĩa, bị tràn dòng khi dịch, v…v..
  • Kiểm tra dữ liệu gửi về server được xử lý đúng: Bạn cần bảo đảm các hoạt động của ứng dụng web trên máy server có tuân thủ business rule và bản thiết kế hay không. Kiểm tra bộ nhớ có bị rò rỉ hoặc cache server có được thu dọn đều đặn với mỗi phiên xử lý hay không.
  • Kiểm tra database: Kiểm tra dữ liệu truy xuất ra có khớp với giá trị lưu trữ, kiểm tra dữ liệu ghi xuống có đúng với những gì server nhận được hay không. Đây cũng là 1 vị trí dễ xảy ra hiện tượng dữ liệu không chính xác khi chuyển đổi (parsing) qua lại giữa các dạng dữ liệu thô. Điều này xuất phát từ nguyên nhân phần lớn các developer thường chủ quan trong việc thắt chặt ràng buộc dữ liệu ở cấp độ database vì họ đinh ninh dữ liệu đã được xử lý hợp lệ ở giai đoạn front-end từ browser.
  • Kiểm tra việc log dữ liệu trên server: Việc log lại tất cả dữ liệu trao đổi, ngày giờ, nội dung truy cập, thông tin client và thông số server là cần thiết để truy lại và tìm ra nguyên nhân các sự cố, cũng như để bảo lưu và hồi phục dữ liệu trong trường hợp mất, hao hụt hoặc truy tìm danh tính 1 kẻ truy cập xấu. Hãy lên danh sách các thông tin cần log, kiểm thử việc log và bảo đảm thông tin log chính xác và được lưu trữ hợp lý.

Xem thêm tuyển Web Developer hấp dẫn trên TopDev

Usability test: đây là một trong những thiết yếu trong việc bảo đảm chất lượng một web app. Ta biết đặc thù của mọi web app là có đa dạng đối tượng sử dụng. Họ có thể là một chuyên gia máy tính, cũng có thể là một người không rành cả gõ văn bản, một học sinh táy máy hoặc một cụ già mắt yếu. Việc bảo đảm web app được thiết kế thân thiện cho người dùng và dễ sử dụng là yếu tố quan trọng bảo đảm sự thành công của hệ thống.

  NUnit – Thực thi kiểm thử tự động với mã từ Selenium IDE

  • Kiểm tra nội dung: Hãy đọc nội dung web tương tự như cách bạn đọc một tờ tạp chí. Bạn sẽ thích một bài báo toàn lỗi chính tả? Hoặc bạn đọc xong và nhận ra bạn chẳng hiểu gì vì bố cục loạn xạ và câu cú lủng củng, thậm chí sai văn phạm. Có một số ý kiến cho rằng nội dung là phần quản trị web phải quản lý và tester chỉ có nhiệm vụ kiểm tra các vấn đề về thiết kế. Thực sự không hoàn toàn như vậy, tester thường là người cuối cùng trong đội phát triển nhìn lại sản phẩm trước khi ra lò. Vì vậy ngay cả khi bạn được yêu cầu không test nội dung, hãy luôn chắc rằng mọi vấn đề mà bạn tìm thấy được báo cáo và lưu lại ở đâu đó cho người có trách nhiệm xử lý.
  • Kiểm tra các logic liên kết và hướng dẫn: Bạn đã bao giờ thấy khó chịu khi chợt nhận ra bạn đang ở cuối một con hẻm cụt và phải lùi ngược xe để trở ra? Cảm giác tương tự cũng xảy ra với người dùng khi trót lướt qua hàng tá trang web và phải bấm Back từng trang một để về trang mình muốn. Hoặc khi người dùng bị ném cho một thông báo rằng họ chưa đăng ký và không thể truy cập chức năng abc nhưng lại chẳng tìm thấy hướng dẫn nào cho việc đăng ký. Người dùng luôn cần hướng dẫn và liên kết ở mọi nơi, mọi lúc và càng súc tích cô đọng càng tốt. Hãy bảo đảm mọi thao tác trên trang web đều được hướng dẫn và gợi ý thông qua các tooltip, các thông báo, sitemap, các liên kết và hình ảnh nếu cần.

Phương pháp kiểm thử ứng dụng Web phổ biến
Tooltip luôn là một công cụ hướng dẫn đắc lực cho end-user

Có một điều thú vị là mình luôn gặp đâu đó một số tester quan niệm rằng những điểm nêu trên không đáng bắt bug, quá mất thời gian và developer sẽ không thích sửa chữa những vấn đề mơ hồ như thế khi họ chỉ biết làm theo thiết kế.  Thực sự thì tất cả chúng đều là bug ở dạng usability. Nên ngay cả khi chúng không được đặt nặng độ ưu tiên, hãy cố gắng để những người có trách nhiệm hiểu tầm ảnh hưởng của chúng đến chất lượng chung và tìm cho ra một ai đó có khả năng giải quyết.

  • Kiểm tra văn hóa khu vực và đối tượng sử dụng: bạn đã bao giờ lướt web và nhận ra rằng một số trang web thuộc lĩnh vực nào đó có tông màu lạnh và bố cục đơn giản trong khi một số khác lại xen kẽ tông màu nóng và kiểu cách cầu kỳ hơn? Điều này bắt nguồn từ đặc điểm riêng của từng lĩnh vực (vd y khoa thường dùng màu sáng để thể hiện sự sạch sẽ), hoặc văn hóa riêng từng khu vực (người châu á thường chuộng tông màu nóng và cầu kỳ hơn châu âu). Nếu bạn đã có những kinh nghiệm đó, hãy tận dụng trong quá trình test của mình. Nếu bạn chưa có sẵn? Hãy bắt đầu quan sát và thu thập chúng.

Thêm vào đó, trong quá trình test, bạn hãy luôn bảo đảm rằng chuẩn thiết kế web app của bạn có thể được tìm thấy phổ biến ở nhiều web app khác. Vd như button login, logout thường nằm ở góc trên bên phải và menu chính luôn nằm ở trên cho tất cả trang web con. Nếu bạn thấy một trang web khoa học trình bày bằng font chữ cách điệu lòe loẹt, tiêu đề chạy ngang dọc, hoặc một trang web dành cho trẻ em lại chỉ dùng 2 tông màu đen trắng buồn tẻ, hãy góp ý với bộ phận thiết kế. Và đó là một số trong hàng tá vấn đề bạn cần phản ánh nếu bộ phận thiết kế không nhìn ra.

Hệ thống của bạn có thể khác biệt và đột phá trong thiết kế? Có thể, nhưng hãy cân nhắc việc người dùng có thấy thân thiện khi sử dụng sự đột phá đó không.

  1. Compability test: Với đặc điểm hỗ trợ trên nhiều thiết bị, nhiều môi trường và công nghệ thay đổi chóng mặt, kiểm thử độ tương thích với web app là một thử thách không nhỏ vì trải dài và tốn nhiều công sức (lại có rủi ro cao). Việc lập ra các bảng kết hợp độ bao phủ (test coverage matrix) giữa các thiết bị, môi trường và các function cần test là một ý tưởng tốt để chắc rằng bạn ko bỏ sót kịch bản nào.
  • Kiểm thử tương thích theo thiết bị & hệ điều hành: ngày nay, các browser được ứng dụng rộng rãi trên máy tính cá nhân, máy tính xách tay, máy tính bảng, smartphone và nhiều loại thiết bị ngoại vi hỗ trợ hệ điều hành. Có vô số dòng và mẫu thiết bị đang được lưu hành nên trước khi bắt tay vào kiểm thử hãy chắc chắn bạn có danh sách các thiết bị mà nhà cung cấp muốn web app của họ hỗ trợ. Không có phần mềm nào chạy hoàn hảo trên tất cả môi trường nên hãy đặt ưu tiên cho những môi trường cần hỗ trợ. Bạn cần nắm rõ về cấu hình, hệ điều hành và thiết lập của từng thiết bị để biết sự khác biệt của chúng khi trình diễn nội dung web.

Hai điều cần lưu tâm nhất khi kiểm thử web với thiết bị là khung hình và khả năng hỗ trợ của thiết bị với các phiên bản html. Hãy truy cập tất cả nội dung web bạn có thể trên từng loại thiết bị và thay đổi zoom hình, quay ngang dọc để xem nội dung web thay đổi thế nào. Hãy chạy thử từng function trên trang web để bảo đảm chúng chạy đúng (functionality test)

  • Kiểm thử tương thích theo browser và thư viện hỗ trợ: Cũng như việc kiểm thử theo thiết bị, chúng ta không thể bảo đảm một nội dung web sẽ hiển thị tốt trên tất cả browser vì mỗi browser tương đối khác nhau ở cách biên dịch html và thư viện hỗ trợ. Nếu trang web của bạn xây dựng trên nền .Net thì có khả năng cao một số control sẽ hoạt động ko tốt trên môi trường không cài đặt đầy đủ thư viện .Net hoặc thư viện quá cũ (tương tự cho các thư viện khác). Ngoài ra, mỗi loại browser và phiên bản browser sẽ có sự hỗ trợ khác nhau về phiên bản html, css và flash. Trong quá trình chạy kịch bản kiểm thử (run test case) cho functionality test, bạn cần kết hợp so sánh tính năng và nội dung trình diễn web trên tất cả những loại browser được yêu cầu hỗ trợ.
  1. Performance testKiểm thử hiệu suất là một phương pháp khá khó và đòi hỏi nhiều kiến thức chuyên môn sâu rộng của tester. Ngay cả với những tester có thâm niên kinh nghiệm thì đây cũng là một thử thách và đòi hỏi họ phải chuyên hóa trong phương pháp kiểm thử này. Trong khuôn khổ bài viết này mình chỉ có thể tóm tắt một số khái niệm cơ bản về hiệu suất để các bạn có hướng tìm hiểu khi đạt những cấp độ cao hơn về test web.
  • Kiểm thử trọng tải (load test): mỗi web app khi xây dựng, dựa vào nhu cầu và khả năng đáp ứng cấu hình host server sẽ có một yêu cầu tối thiểu cho web app về các thông số sau: lượng xử lý truy cập cho phép trong cùng 1 lúc (Throughput), thời gian tối thiểu cho mỗi request/response (response time), lưu lượng tối đa truy cập (query) vào server, đường truyền (bandwidth, lag latency) và hiệu suất xử lý back-end (Resource utilization). Để thực hiện load test, bạn cần thu thập yêu cầu tải trọng cho web app từ nhà cung cấp và cấu hình host server. Bạn cần giả lập môi trường cài đặt web app và học cách dùng performance tool để giả lập các lưu lượng truy cập (Vd: LoadRunner, Jmeter). Để vượt qua loại test này, web app cần chạy đúng và không xảy ra lỗi trong tất cả function được test với giả lập trọng tải bằng hoặc dưới yêu cầu tối thiểu
  • Kiểm thử sức chịu đựng (stress test): tương tự như load test nhưng bạn cần tăng lưu lượng giả lập vượt quá mức yêu cầu tối thiểu và tiến hành đo đạc thời gian hệ thống có thể chịu được trước khi xảy ra sự cố nghiêm trọng. Thông thường, server sẽ gia tăng lượng response lỗi (request timeout), xử lý chậm chạp dần tỷ lệ thuận với lượng truy cập quá tải trước khi thực sự xảy ra chết hệ thống (downtime). Kết quả đo đạc sẽ là thông tin quý giá để đội ngũ hỗ trợ có kế hoạch hồi phục tốt khi thực tế xảy ra.

Phương pháp kiểm thử ứng dụng Web phổ biến
Web stress test

  1. Security test
  • Kiểm tra Captcha: Sẽ thế nào nếu một buổi sáng đẹp trời, database của bạn bị sập vì quá tải với hàng trăm ngàn tài khoản ảo được tạo? Đó là điều bạn sẽ thấy khi người ta dùng một công cụ tự động truy cập web app của bạn và lặp đi lặp lại việc đăng ký tài khoản. Mã Captcha ra đời để giúp phòng tránh việc này. Hãy bảo đảm hệ thống của bạn được cài đặt Captcha hợp lý để hạn chế việc spam những request nhạy cảm khả dĩ có thể làm hỏng hệ thống (đăng ký tài khoản, đăng nhập…). Tuy nhiên, việc cài đặt nên hạn chế tùy tiện vì chúng sẽ gây phiền phức cho user. Hãy thông báo nếu bạn thấy một function nào đó không được cài đặt Captcha hợp lý.
  • Kiểm tra việc mã hóa dữ liệu trao đổi: điều này là tối cần thiết nếu web app của bạn có hệ thống tài khoản, thanh toán online hoặc có nhu cầu trao đổi thông tin nhạy cảm với user. Bạn hãy xem gói dữ liệu request/response và đọc chúng để chắc rằng mọi thông tin quan trọng được giấu đi hoặc được mã hóa. Người ngoài không nên dễ dàng xem được hoặc tìm được cách giải mã chúng. Hệ thống có thông tin càng giá trị thì càng cần các biện pháp mã hóa tối tân. Hãy lên danh sách các trường dữ liệu được trao đổi qua hệ thống của bạn, đánh dấu những loại thông tin nhạy cảm và giả lập các tình huống test mà 1 guest (một truy cập lạ) có thể đọc được những thông tin đó. Thêm vào đó hãy liên hệ với đội ngũ developer để hiểu rõ cách web app tổ chức mã hóa dữ liệu thế nào và suy nghĩ các điểm yếu có thể. Nếu bạn chỉ mất vài tiếng để tìm ra cách trộm được thông tin, chắc chắn những kẻ xấu cũng vậy.
  • Kiểm tra SSL và Certificates: Hệ thống SSL (Secure Socket Layer) và Certificate là một biện pháp bảo mật phổ biến nhằm bảo đảm độ tin cậy của web app và kênh trao đổi với user. Ta hiểu nôm na chúng như 1 loại chữ ký điện tử để người dùng nhận biết rằng họ đang truy cập một trang web “chính chủ”. Tất cả các website khi đăng ký tên miền thường luôn kèm một Digital Certificate bao gồm 1 số serial và các thông tin cá nhân về tổ chức/doanh nghiệp của họ được đăng ký pháp lý trên hệ thống DNS. Khi một user truy cập vào tên miền đó, thông qua certificate user được bảo đảm rằng họ đã truy cập vào đúng địa chỉ mình cần thay vì một phishing site (những web giả mạo được lập ra với tên miền và giao diện tương đồng với một trang web nào đó nhằm lừa user gửi thông tin của họ đến server giả với mục đích trục lợi).

Bạn hãy thu thập các thông tin về Certificate của hệ thống đang test và bảo đảm rằng khi lên live, web app của bạn và máy client được thiết lập Trust Certificate đúng và các thông tin được đăng ký chính xác. Hãy thử truy cập vào tên miền với tiếp đầu ngữ “https://…” và “http://…” và xem xét. Một thiết lập đúng sẽ hiện thông điệp về certificate khi bạn dùng “https”.

Phương pháp kiểm thử ứng dụng Web phổ biến
https protocol

  • Kiểm tra việc truy cập tài nguyên thông qua tên miền: mỗi webpage và tài nguyên trên server (file download, hình ảnh, video…) đều cần được định danh và có thể được truy cập từ client thông qua đường địa chỉ URL (phần ký tự loằng ngoằng phía sau tên miền). Bạn cần bảo đảm user bị chặn truy cập vào tất cả những webpage, những file và thư mục mà họ không được phép truy cập. Vd, giả sử ta có “http://abc.com/lineA/pageA.aspx” là trang web mà hệ thống bạn chỉ dành cho user đã đăng nhập. Bạn hãy thử gõ trực tiếp URL “http://abc.com/lineA/pageA.aspx” vào browser với tư cách một guest (user lạ chưa đăng nhập). Nếu browser truy cập thành công pageA với đầy đủ tính năng, hẳn bạn có 1 bug. Ngoài ra, bạn hãy kiểm tra tất cả các tên định danh của webpage và đường dẫn URL đến các tài nguyên nhạy cảm trên server để bảo đảm chúng không quá phổ thông và dễ đoán. Hãy thử truy cập tài nguyên thông qua 1 số giao thức khác ngoài http (vd ftp,…) và bảo đảm tất cả giao thức không cần thiết đều được tắt để hạn chế truy cập ngoài ý muốn. Nếu có điều kiện, bạn hãy tìm hiểu về SQL Injection và áp dụng chúng vào việc kiểm thử xem hệ thống có dễ bị tấn công thông qua việc dùng parameter trên URL hay không.

Kết luận

Qua những nội dung trên, chúng ta có thể thấy rằng test web thực sự không khó nhưng đòi hỏi ở các bạn sự nghiêm túc trong việc nghiên cứu và tích lũy kinh nghiệm qua từng giai đoạn làm việc. Test web không cần nhiều kiến thức sâu rộng về mạng (network), tuy nhiên thay vào đó bạn cần có những hiểu biết nhất định về nguyên tắc giao tiếp dữ liệu và các loại ngôn ngữ trình diễn web. Bạn cũng cần tập luyện thói quen tìm hiểu các công nghệ phát triển web và phong cách trình diễn web mới (vốn thay đổi liên tục theo thời gian). Hi vọng với bài viết này, các bạn có thể dễ dàng hơn trong việc làm quen với kiểm thử web.

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

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

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

Functional Interface là gì? Functional Interface API trong Java 8

Functional Interface là gì? Functional Interface API trong Java 8

Bài viết được sự cho phép của tác giả Trần Hữu Cương

1.  Functional Interface là gì?

Functional Interface là interface có duy nhất 1 method trừu tượng (có thể có thêm các method không trừu tượng bằng từ khóa default trong Java 8)
Ví dụ: Comparable  là 1 Functional Interface với method trừu tượng duy nhấtcompareToRunnable là 1 Functional Interface với method trừu tượng duy nhất run

Về annotation @FunctionalInterface: nó được dùng ở trước mỗi interface để khai báo đây là 1 functional interface.

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

Việc dùng annotation @FunctionalInterface là không bắt buộc nhưng nó giúp đảm bảo cho quá trình compile. Ví dụ bạn khai báo @FunctionalInterface nhưng trong interface lại có nhiều hơn 2 method trừu tượng thì nó sẽ báo lỗi.

  Giới thiệu về GraphQL. Cách giải quyết những hạn chế của RESTful API

  Refactoring Design Pattern với tính năng mới trong Java 8

2. Functional Interface API trong Java 8

Java 8 xây dựng sẵn một số functional interface và nó được dùng nhiều trong các biểu thức lambda:

2.1. java.util.function.Consumer

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Consumer<T> {

    // Phương thức chấp nhận một tham số đầu vào
    // và không trả về gì cả.
    void accept(T t);

}

consumer thường được dùng với list, stream để xử lý với các phần tử bên trong.

Ví dụ: đoạn code dưới đây in ra tất cả các giá trị của 1 list

List<String> list = Arrays.asList("stack", "java", "stackjava.com");

// Sử dụng List.forEach(Consumer) để in ra giá trị của các phần tử trong list
list.forEach(new Consumer<String>() {
  @Override
  public void accept(String t) {
    System.out.println(t);
  }
});
System.out.println("----------------");

// Sử dụng List.forEach(Consumer) với cú pháp lambda expression:
list.forEach(t -> System.out.println(t));

Kết quả:

stack
java
stackjava.com
----------------
stack
java
stackjava.com

Xem thêm nhiều việc làm Java lương cao trên TopDev

2.2. java.util.function.Predicate

package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Predicate<T> {

    // Kiểm tra một tham số đầu vào và trả về true hoặc false.
    boolean test(T t);

}

predicate thường được dùng với list, stream để kiểm tra từng phần tử lúc xóa, lọc…

Ví dụ: đoạn code dưới đây xóa bỏ tất cả các số âm khỏi 1 ArrayList<Integer>

List<Integer> list = new ArrayList<>();
list.add(-1);
list.add(1);
list.add(0);
list.add(-2);
list.add(3);

// lệnh removeIf sẽ thực hiện duyệt từng phần tử,
// nếu method test của Predicate trả về true thì sẽ remove phần tử đó khỏi list
list.removeIf(new Predicate<Integer>() {
  @Override
  public boolean test(Integer t) {
    return t < 0;
  }
});
list.forEach(t -> System.out.println(t));
System.out.println("-----------------------------");

// Sử dụng Predicate với cú pháp Lambda Expression
// loại bỏ các phần tử lớn hơn 1
list.removeIf(t -> t > 1);
list.forEach(t -> System.out.println(t));
Kết quả:
1
0
3
-----------------------------
1
0

2.3. java.util.function.Function

package java.util.function;

import java.util.Objects;


@FunctionalInterface
public interface Function<T, R> {

    // Method này nhận đầu vào là 1 tham số và trả về một giá trị.
    R apply(T t);

}

Function thường dùng với Stream khi muốn thay đổi giá trị cho từng phần tử trong stream.

Ví dụ: đoạn code dưới đây thực hiện chuyển các phần phần tử kiểu string trong 1 stream thành chữ in hoa/thường:

List<String> list = Arrays.asList("stack", "JAVA", "demo", "Function");
Stream<String> stream = list.stream();

// chuyển tất cả các phần tử của stream thành chữ in hoa

stream.map(new Function<String, String>() {
  @Override
  public String apply(String t) {
    return t.toUpperCase();
  }
}).forEach(t -> System.out.println(t));
System.out.println("---------------");
// Function với cú pháp Lambda Expression
// chuyển tất cả các phần tử của stream thành chữ thường

stream = list.stream();// lưu ý là stream ko thể dùng lại nên phải khởi tạo lại
stream.map(t -> t.toLowerCase()).forEach(t -> System.out.println(t));

Kết quả:

STACK
JAVA
DEMO
FUNCTION
---------------
stack
java
demo
function

Một số Function interface tương tự:

  • java.util.function.IntFunction<R>: dữ liệu chuyển về kiểu Integer
  • java.util.function.DoubleFunction<R>: dữ liệu chuyển về kiểu Double
  • java.util.function.LongFunction<R>: dữ liệu chuyển về kiểu Long

2.4. java.util.function.Supplier

package java.util.function;

@FunctionalInterface
public interface Supplier<T> {

    // method này không có tham số nhưng trả về một kết quả.
    T get();

}

Ví dụ: đoạn code dưới đây tạo ra 1 list gồm 10 số 1 cách random:

Random random = new Random();
Stream<Integer> stream = Stream.generate(new Supplier<Integer>() {
  @Override
  public Integer get() {
    return random.nextInt(10);
  }
}).limit(5);

stream.forEach(t -> System.out.print(t +" "));
System.out.println("\n--------------------");

// Sử dụng Supplier với cú pháp Lambda Expression:
stream = Stream.generate(() -> random.nextInt(10)).limit(5);
stream.forEach(t -> System.out.print(t +" "));

Kết quả:

4 9 8 5 8
--------------------
2 2 9 9 6

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

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

Tuyển dụng IT lương cao, đãi ngộ hấp dẫn. Ứng tuyển ngay!

Làm thế nào tạo instance của một class mà không gọi từ khóa new?

Làm thế nào tạo instance của một class mà không gọi từ khóa new?

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

Như đã biết, trong Java để khởi tạo một instance của một class chúng ta sẽ sử dụng từ khóa new. Tuy nhiên, trong một số trường hợp chúng ta cần tạo một instance khi chỉ biết tên class hoặc private constructor hoặc không biết được số lượng tham số của constructor,… Với những trường hợp như vậy, chúng ta không thể gọi từ khóa new một cách trực tiếp mà sẽ sử dụng một số cách đặc biệt và chúng ta sẽ cùng tìm hiểu các cách giải quyết vấn đề này trong phần tiếp theo của bài viết.

Sử dụng Reflection khi biết tên class

Một trong những cách đơn giản và thường được sử dụng để tạo instance của một class là sử dụng kỹ thuật Reflection. Nếu bạn chưa biết về Reflection, hãy dành chút thời gian xem lại bài viết Hướng dẫn sử dụng Java Reflection.

Sử dụng newInstance() khi class có constructor không có tham số và phạm vi truy cập không phải private

package com.gpcoder.instance;

public class Employee {

    private int id;

    private String name;

    public Employee() {
        super();
    }

    public Employee(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + "]";
    }
}

Tạo instance sử dụng newInstance():

package com.gpcoder.instance;

import java.lang.reflect.InvocationTargetException;

public class NewInstanceExample {

    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException {

        // Get class based on the given class name
        Class<?> clazz = Class.forName("com.gpcoder.instance.Employee");

        // Create a new instance with empty argument of constructor of a class
        Employee employee = (Employee) clazz.newInstance();
        employee.setId(1);
        employee.setName("gpcoder");
        System.out.println("employee: " + employee);
    }
}

Lưu ý:

  • Nếu không tồn tại constructor không có tham số, chương trình sẽ throw ra một exception như sau:
Exception in thread "main" java.lang.InstantiationException: com.gpcoder.instance.Employee
    at java.lang.Class.newInstance(Class.java:427)
    at com.gpcoder.instance.NewInstanceExample.main(NewInstanceExample.java:15)
Caused by: java.lang.NoSuchMethodException: com.gpcoder.instance.Employee.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.newInstance(Class.java:412)
    ... 1 more
  • Nếu constructor không tham số có phạm vi truy cập là private, chương trình sẽ throw ra exception sau:
Exception in thread "main" java.lang.IllegalAccessException: Class com.gpcoder.instance.NewInstanceExample can not access a member of class com.gpcoder.instance.Employee with modifiers "private"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
    at java.lang.Class.newInstance(Class.java:436)
    at com.gpcoder.instance.NewInstanceExample.main(NewInstanceExample.java:15)

  Ngắm và bắn với thuộc tính watch trong Vue instance

  Toán tử instanceof trong Java

Sử dụng getConstructor() khi constructor của class là public

Chúng ta sẽ tạo instance của class Employee sử dụng phương thức getConstructor():

package com.gpcoder.instance;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ConstructorNewInstanceExample {

    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException {

        // Get class based on the given class name
        Class<?> clazz = Class.forName("com.gpcoder.instance.Employee");

        // Get all constructor of the class
        Constructor<?>[] allConstructors = clazz.getConstructors();
        for (Constructor<?> constructor : allConstructors) {
            Class<?>[] parameters = constructor.getParameterTypes();
            if (parameters.length == 0) {
               // Create a new instance without parameter
               Employee employee1 = (Employee) constructor.newInstance();
               employee1.setId(1);
               employee1.setName("gpcoder 1");
               System.out.println("employee1: " + employee1);
            } else if (parameters.length == 2) {
               // Create a new instance with two parameters
               Employee employee2 = (Employee) constructor.newInstance(2, "gpcoder 2");
               System.out.println("employee2: " + employee2);
            }
        }

        // Create a new instance with specific constructor of class
        Constructor<?> constructor = clazz.getConstructor(int.class, String.class);
        Employee employee3 = (Employee) constructor.newInstance(3, "gpcoder 3");
        System.out.println("employee3: " + employee3);
    }
}

Output của chương trình:

employee1: Employee [id=1, name=gpcoder 1]
employee2: Employee [id=2, name=gpcoder 2]
employee3: Employee [id=3, name=gpcoder 3]

Cập nhật việc làm Java đãi ngộ hấp dẫn trên TopDev

Sử dụng getDeclaredConstructor() khi constructor của class là private

Ví dụ:

package com.gpcoder.instance;

public class PrivateEmployee {

    private int id;

    private String name;

    private PrivateEmployee(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "PrivateEmployee [id=" + id + ", name=" + name + "]";
    }
}

Sử dụng getDeclaredConstructor() khi các constructor của class là private:

package com.gpcoder.instance;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class PrivateConstructorNewInstanceExample {

    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException, NoSuchMethodException, SecurityException {

        // Get class based on the given class name
        Class<?> clazz = Class.forName("com.gpcoder.instance.PrivateEmployee");

        // Get the private constructor.
        Constructor<?> constructor = clazz.getDeclaredConstructor(int.class, String.class);

        // Since it is private, make it accessible.
        constructor.setAccessible(true);

        // Create a new instance with specific constructor of class
        PrivateEmployee employee = (PrivateEmployee) constructor.newInstance(1, "gpcoder");
        System.out.println("employee: " + employee);
    }
}

Output của chương trình:

employee: PrivateEmployee [id=1, name=gpcoder]

Sử dụng Object.clone() để tạo một instance từ một instance khác

Để sử dụng phương thức clone(), class cần implement interface java.lang.Cloneable và override phương thức clone(). Chi tiết các bạn xem lại bài viết Object cloning trong java.

package com.gpcoder.instance;

public class Programer implements Cloneable {

    private int id;

    private String name;

    public Programer(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    protected Programer clone() throws CloneNotSupportedException {
        return (Programer) super.clone();
    }

    @Override
    public String toString() {
        return "Programer [id=" + id + ", name=" + name + "]";
    }
}

Tạo new instance từ clone()

package com.gpcoder.instance;

public class CloneExample {

    public static void main(String[] args) throws CloneNotSupportedException {
        Programer obj1 = new Programer(1, "gpcoder");
        Programer obj2 = obj1.clone();
        obj2.setName(obj2.getName().toUpperCase());

        System.out.println(obj1);
        System.out.println(obj2);
    }
}

Output chương trình:

Programer [id=1, name=gpcoder]
Programer [id=1, name=GPCODER]

Tạo new instance sử dụng serialization và deserialization

Chúng ta có thể tạo một instance cho một class bằng cách sử dụng Deserialization từ một data object đã được Serialization. Khi sử dụng deserialization, JVM sẽ không sử dụng bất kỳ constructor nào để tạo instance. Chi tiết các bạn xem lại bài viết Serialization và Deserialization trong java.

Giả sử chúng ta cần tạo instance cho class sau:

package com.gpcoder.instance;

import java.io.Serializable;

public class StudentSerializable implements Serializable {

    private static final long serialVersionUID = 1427461703707854023L;

    private int id;
    private String name;

    public StudentSerializable(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "StudentSerializable [id=" + id + ", name=" + name + "]";
    }
}

Bây giờ chúng ta sẽ tạo một đối tượng đã được Serialize và lưu vào một nơi nào đó (có thể lưu trữ ở một nơi nào đó tách biệt hoặc nhận từ một service khác). Sau đó, chúng ta đọc file này và tạo instance sử dụng Deserialize.

package com.gpcoder.instance;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class DeserializationNewInstanceExample {

    public static void main(String[] args) throws FileNotFoundException, ClassNotFoundException, IOException {
        File file = File.createTempFile("student", "txt");
        serialize(file);
        deserialize(file);
    }

    private static void serialize(File file) throws FileNotFoundException, IOException, ClassNotFoundException {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
            StudentSerializable student = new StudentSerializable(1, "gpcoder");
            oos.writeObject(student);
            oos.flush();
            System.out.println("Serialized");
        }
    }

    private static void deserialize(File file) throws FileNotFoundException, IOException, ClassNotFoundException {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
            StudentSerializable student = (StudentSerializable) ois.readObject();
            System.out.println(student);
            System.out.println("Deserialized");
        }
    }
}

Output chương trình:

Serialized
StudentSerializable [id=1, name=gpcoder]
Deserialized

Sử dụng thư viện Objenesis

Objenesis là gì?

Một số hạn chế của các cách ở trên:

  • Với phương thức Class.newInstance(), class của chúng ta bắt buộc phải có constructor không có tham số.
  • Với Class.getDeclaredConstructor() hoặc Class.getConstructor(), chúng ta phải xác định chính xác số lượng tham số và kiểu dữ liệu của từng tham số.
  • Với Object.clone(), class của chúng ta phải implement một interface Clonable.
  • Với serialization và deserialization, class của chúng ta phải implement một interface Serializable.

Ngoài ra, một số trường hợp chúng ta có thể gặp phải khi tạo instance thông qua constructor như:

  • Trong constructor có throw exception, chẳng hạn private constructor của singleton hay util class có thể throw exception trực tiếp trong constructor.
  • Trong constructor gọi rất nhiều xử lý khác, nó làm chậm quá trình khởi tạo instance và chúng ta cũng không cần dữ liệu khởi tạo đó.

Để có thể tạo một instance cho một class mà không gặp bất kỳ hạn chế trên, chúng ta có thể sử dụng thư viện Objenesis.

Objenesis là một thư viện mã nguồn mở của Java, nó được sử dụng để tạo instance của một class đặc biệt mà không thông qua constructor.

Cài đặt Objenesis

Thêm thư viện Objenesis vào project vào project maven:

<!-- https://mvnrepository.com/artifact/org.objenesis/objenesis -->
        <dependency>
            <groupId>org.objenesis</groupId>
            <artifactId>objenesis</artifactId>
            <version>3.0.1</version>
        </dependency>

Ví dụ sử dụng Objenesis

Giả sử chúng ta có một class có constructor là private và trong constructor này có throw một exception.

package com.gpcoder.instance;

public class ProductFactory {

    private ProductFactory() {
        throw new UnsupportedOperationException("Cannot call the contructor directly");
    }

    public void doSomething(String factory) {
        System.out.println("Working on " + factory);
    }
}

Như bạn thấy, với những cách đã giới thiệu ở trên chúng ta không thể khởi tạo được instance của class này. Bây giờ hãy xem cách sử dụng Objenesis:

package com.gpcoder.instance;

import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import org.objenesis.instantiator.ObjectInstantiator;

public class ObjenesisExample {

    public static void main(String[] args) {
        // Step 1: Create objenesis
        Objenesis objenesis = new ObjenesisStd(); // or ObjenesisSerializer

        // Step 2: Create instantiator with the specific ProductFactory type
        // Try to reuse the ObjectInstantiator objects as much as possible to improve performance
        // It can be shared between multiple threads and used concurrently
        ObjectInstantiator<?> instantiator = objenesis.getInstantiatorOf(ProductFactory.class);

        // Step 3: Create new instance of the ProductFactory type
        ProductFactory productFactory1 = (ProductFactory) instantiator.newInstance();
        ProductFactory productFactory2 = (ProductFactory) instantiator.newInstance();
        ProductFactory productFactory3 = (ProductFactory) instantiator.newInstance();

        // Step 4: Use the instances
        System.out.println("productFactory1: " + productFactory1);
        System.out.println("productFactory2: " + productFactory2);
        System.out.println("productFactory3: " + productFactory3);

        productFactory1.doSomething("factory1");
        productFactory2.doSomething("factory2");
        productFactory3.doSomething("factory3");
    }
}

Output của chương trình:

productFactory1: com.gpcoder.instance.ProductFactory@5cad8086
productFactory2: com.gpcoder.instance.ProductFactory@6e0be858
productFactory3: com.gpcoder.instance.ProductFactory@61bbe9ba
Working on factory1
Working on factory2
Working on factory3

Lưu ý: Do Objenesis khởi tạo đối tượng không thông qua constructor nên các giá trị khởi tạo trong constructor sẽ không tồn tại. Do đó, chúng ta cần gán lại các giá trị cho đối tượng trước khi gọi các phương thức của nó.

Ví dụ chúng ta có một class Document. Class này ban đầu chỉ chứa thông tin về document. Sau đó, hệ thống cần xuất dữ liệu document ra file và mỗi loại document có cách xuất dữ liệu/ biểu mẫu khác nhau. Do đó, chúng ta thêm một field className để lưu thông tin tên concrete class. Chúng ta có cấu trúc như sau:

objenesis-example

Code chương trình:

Document.java

package com.gpcoder.instance.objenesis;

public class Document {

    private String title;
    private String author;
    private String className;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }
}

SelfDocumentGenerable.java

package com.gpcoder.instance.objenesis;

public abstract class SelfDocumentGenerable extends Document {

    public abstract void generateFile();
}

Concrete1SelfDocumentGenerable.java

package com.gpcoder.instance.objenesis;

import java.util.Date;

public class Concrete1SelfDocumentGenerable extends SelfDocumentGenerable {

    private Date createdDate;

    public Concrete1SelfDocumentGenerable(String title, String author, Date createdDate) {
        setTitle(title);
        setAuthor(author);
        this.createdDate = createdDate;
    }

    @Override
    public void generateFile() {
        System.out.printf("Concrete1: %s - %s\n", getTitle(), getAuthor());
    }
}

Concrete2SelfDocumentGenerable.java

package com.gpcoder.instance.objenesis;

public class Concrete2SelfDocumentGenerable extends SelfDocumentGenerable {

    public Concrete2SelfDocumentGenerable(String title, String author) {
        setTitle(title);
        setAuthor(author);
    }

    @Override
    public void generateFile() {
        System.out.printf("Concrete2: %s - %s\n", getTitle(), getAuthor());
    }
}

Như bạn thấy, mỗi concrete class có constructor với các tham số khác nhau, chúng ta không thể gọi từ khóa new một cách trực tiếp, không thể gọi phương thức newInstance() do không chắc chắn các concrete class có constructor không tham số hay không và cũng không thể xác định chính xác các tham số của constructor nên không thể sử dụng getConstructor(). Trường hợp này, chúng ta sẽ sử dụng Objenesis để tạo instance.

Do Objenesis tạo instance không thông qua constructor nên chúng ta phải gán lại các giá trị title và author cho phương thức generateFile() sử dụng.

DocumentGenerator.java

package com.gpcoder.instance.objenesis;

import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import org.objenesis.instantiator.ObjectInstantiator;

public class DocumentGenerator {

    public static void generate(Document document) throws ClassNotFoundException {
        Objenesis objenesis = new ObjenesisStd();
        Class<?> clazz = Class.forName(document.getClassName());
        ObjectInstantiator<?> instantiator = objenesis.getInstantiatorOf(clazz);
        SelfDocumentGenerable selfDocumentGenerable = (SelfDocumentGenerable) instantiator.newInstance();
        copyProperties(document, selfDocumentGenerable);
        selfDocumentGenerable.generateFile();
    }

    private static void copyProperties(Document src, Document target) {
        target.setTitle(src.getTitle());
        target.setAuthor(src.getAuthor());
    }
}

ObjenesisDocumentGeneratorExample.java

package com.gpcoder.instance.objenesis;

public class ObjenesisDocumentGeneratorExample {

    public static void main(String[] args) throws ClassNotFoundException {
        Document document = new Document();
        document.setTitle("Doc1");
        document.setAuthor("gpcoder1");
        document.setClassName(Concrete1SelfDocumentGenerable.class.getCanonicalName());
        DocumentGenerator.generate(document);

        document = new Document();
        document.setTitle("Doc2");
        document.setAuthor("gpcoder2");
        document.setClassName(Concrete2SelfDocumentGenerable.class.getCanonicalName());
        DocumentGenerator.generate(document);
    }
}

Output của chương trình:

Concrete1: Doc1 - gpcoder1
Concrete2: Doc2 - gpcoder2

Session, Cookie, Storage đơn giản mà dễ hiểu

Session, Cookie, Storage đơn giản mà dễ hiểu

Bài viết được sự cho phép của tác giả Phạm Minh Khoa

Session, Cookie, Storage

Nhìn cái ảnh trên là thấy đơn giản mà dễ hiểu rồi đúng ko?

Tất nhiên không thể kết thúc bài viết ở đây được rồi. Giải thích chi tiết 1 chút nhé các bạn.

Thấy cái dòng đỏ đỏ ở giữa hình trên ko? Http is stateless – dịch ra nghĩa là “như lần đầu gặp gỡ” (hình như tên phim bộ của Tung Của), http vốn dĩ được mở khi client yêu cầu (request) gì đó đối với server, xong xuôi là ổng đóng luôn khi trả về response. Server thì cùng lúc phục vụ cả trăm nghìn thằng client => thế cho nên không thể trông cậy được vào thằng http để biết được client là thằng nào. Ví dụ ông vừa login vào Facebook => ông tiếp tục yêu cầu đăng bài post mới thì sao tôi biết được ông là thằng nào, chả nhẽ lại gửi tiếp username/password lên lần nữa. Méo ổn đúng không.

Vì đó session và cookie ra đời.

Session là phiên làm việc, được mở đầu khi bạn bắt đầu vào trang web đó, kéo dài trong suốt quá trình sử dụng đến khi bạn tắt web, tắt trình duyệt hoặc mất điện (tất nhiên là session còn phụ thuộc vào logic của dev làm ra cái web đó quy định, nhưng cơ bản là vậy).

Trên server để ông ý biết được request gửi từ client đến là của bà client nào thì trong cái request đầu tiên (dễ hình dung thì là lúc đăng nhập), ông ý sẽ tạo ra 1 cái gọi là session id (đoạn mã dài dài trên hình ấy), lưu vào phía server; rồi ổng sẽ tạo cookie lưu ở phía client chứa thông tin về cái bà client kia. Từ lần gửi request sau, bà client sẽ gửi cái session id ấy lên cho ông server biết bà ý là bà nào, cứ thế mà phục vụ cho tử tế nhé.

  Session là gì? Cookie là gì?

Trên lý thuyết mà nói thì chỉ cần ông server biết bà client là ai thôi, chứ bà client thì bà cần gì lưu lại thông tin; nên cần gì Cookie đúng ko? Thật ra thì bài toán không đơn giản như vậy. Ông server phục vụ 1 lúc trả chục, cả trăm, có khi có nghìn bà, nên ông ý không thể cứ đi mò trong đống sổ sách giấy tờ (database) để lấy thông tin cơ bản về tên tuổi địa chỉ của từng bà khi có yêu cầu được. Nên là những thông tin dùng đi dùng lại nhiều, hoặc là lịch sử bà ý đã xem gì, ăn gì, uống gì, bấm nút nào cũng sẽ được lưu vào cookie; giảm bớt cho ông server đi.

Tham khảo việc làm Java hấp dẫn trên TopDev

Cookie không chỉ sinh ra bởi server của website mà bạn truy cập, nó còn từ 1 thư viện bên thứ 3 mà server đó sử dụng.

Ví dụ bạn vào shopee tìm đồng hồ, ông google quảng cáo trong shopee lưu lại thông tin vào cookie là: “thằng này nó kiếm đồng hồ nè”, xong đó bạn tắt shopee đi rồi vào facebook. Ông facebook lại cũng sử dụng quảng cáo của google, lúc đó thằng google nó lại đọc được từ cookie đã lưu trước đó thì biết là thằng này vừa kiếm đồng hồ, thế là nó lại hiển thị quảng cáo đồng hồ. Lưu ý ở đây google quảng cáo là 1 bên thứ 3 chứ không phải là server của website bạn vừa vào. Vì vậy đừng ngạc nhiên nhé!

Tại sao giờ session lại ít được nói đến hơn.

Thật ra cũng không hẳn là ít hơn, mà do xu thế sử dụng token JWT React Single Application Web App, … và nhiều phương thức khác nên Session ít dùng hơn (nhất là với JS). Cookie thì vẫn được dùng để lưu thông tin phía client, hoặc lưu access token, refresh token. Bạn cũng có thể sử dụng localstorage để lưu. Cũng nên phân biết khái niệm session storage và session, vì session storage là lưu ở client nhé, méo liên quan gì phía server đâu.

  Đánh cắp Cookie bằng cách lợi dụng lỗi bảo mật XSS

3 thằng này đều phía client nhé, dùng để lưu các thông tin của bà client như đã nói ở trên. Phân biệt cũng đơn giản thôi.

Localstorage chả liên quan gì đến session cả, nên không có tự xóa được.

Cookie thì được cái là cả phía client và phía server đều đọc được, và nó có thể được thiết lập ở phía browser thời gian lưu trữ

Sessionstorage kết hợp 2 thằng trên lại, chỉ dùng trong phiên làm việc nhưng cũng chỉ đọc ở phía client.

Ngoài các ý trên thì còn 1 số yếu tố liên quan đến bộ nhớ, bảo mật nữa. Cụ thể mọi người có thể xem thêm dưới ảnh

LocalStorage, Session Storage và Cookie

Tài liệu về Session và Cookie thì nhiều lắm, nhưng trên là những ý mà mình hiểu. Bản thân trong các dự án mình tham gia không sử dụng nhiều với session và cookie lắm, hoặc có thì chỉ setup đơn giản, mọi người có thấy sai sót gì thì thông báo nhé.

Cảm ơn mọi người!

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

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

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

Hướng dẫn Java Design Pattern – Intercepting Filter

Hướng dẫn Java Design Pattern – Intercepting Filter

Intercepting Filter Pattern là gì?

Intercepting filter pattern là một Java EE pattern, được sử dụng khi muốn thực hiện một vài xử lý trước (pre-processing) khi request được ứng dụng đích (target) xử lý hoặc sau (post-processing) khi response được trả về từ target.

Các Filter được định nghĩa và áp dụng trên yêu cầu (request) khi chuyển request đến ứng dụng đích thực tế (target). Các Filter có thể thực hiện xác thực (authentication), ủy quyền (authorization), nén dữ liệu (compressing), ghi nhật ký (logging) hoặc theo dõi yêu cầu (tracking) và sau đó chuyển yêu cầu đến các trình xử lý tương ứng.

Các Filter được thực thi một cách trong suốt, phía client và target không hề biết sự tồn tại của nó.

Tìm Java job lương cao trên TopDev ngay!

Cài đặt Intercepting Filter Pattern như thế nào?

Intercepting Filter Pattern

Các thành phần tham gia mẫu Intercepting filter pattern:

  • Filter : chịu trách nhiệm thực hiện một vài xử lý trước khi request được target xử lý hoặc sau khi response được trả về từ target.
  • Target : là một đối tượng xử lý lý chính, một trình xử lý yêu cầu.
  • Filter chain : chứa một chuỗi các Filter sẽ được thực hiện trên target theo thứ tự được xác định.
  • Filter manager : quản lý các Filter và Filter Chain.
  • Client : đối tượng gửi request đến target hoặc nhận response từ target.

  Hướng dẫn Java Design Pattern – Memento

  Một số Patterns hay sử dụng trong React

Ví dụ sử dụng Intercepting Filter Pattern

Giả sử chúng ta có một ứng dụng cần ghi log, xác thực tất cả request đến hệ thống trước khi target xử lý. Chương trình của chúng ta như sau:

Intercepting Filter Pattern

HttpRequest.java

package com.gpcoder.patterns.other.filter;

import lombok.Data;

@Data
public class HttpRequest {

    private String clientIp;
    private String targetUrl;
}

Filter.java

package com.gpcoder.patterns.other.filter;

public interface Filter {
    void doFilter(HttpRequest request);
}

TrackingFilter.java

package com.gpcoder.patterns.other.filter;

public class TrackingFilter implements Filter {

    @Override
    public void doFilter(HttpRequest request) {
        System.out.println("Tracking request: " + request);
    }
}

AuthenticationFilter.java

package com.gpcoder.patterns.other.filter;

public class AuthenticationFilter implements Filter {

    @Override
    public void doFilter(HttpRequest request) {
        System.out.println("Authenticating request: " + request);
    }
}

Target.java

package com.gpcoder.patterns.other.filter;

public class Target {

    public void execute(HttpRequest request) {
        System.out.println("Executing request: " + request);
    }
}

FilterChain.java

package com.gpcoder.patterns.other.filter;

import java.util.ArrayList;
import java.util.List;

public class FilterChain {

    private List<Filter> filters = new ArrayList<>();

    private Target target;

    public void addFilter(Filter filter) {
        filters.add(filter);
    }

    public void doFilter(HttpRequest request) {
        // Do some pre-processing
        for (Filter filter : filters) {
            filter.doFilter(request);
        }

        // Execute actual processing by target
        target.execute(request);

        // Do some pos-processing
    }

    public void setTarget(Target target) {
        this.target = target;
    }
}

FilterManager.java

package com.gpcoder.patterns.other.filter;

public class FilterManager {

    private FilterChain filterChain;

    public FilterManager(Target target) {
        filterChain = new FilterChain();
        filterChain.setTarget(target);
    }

    public void addFilter(Filter filter) {
        filterChain.addFilter(filter);
    }

    public void filterRequest(HttpRequest request) {
        filterChain.doFilter(request);
    }
}

Client.java

package com.gpcoder.patterns.other.filter;

public class Client {

    private FilterManager filterManager;

    public Client(FilterManager filterManager) {
        this.filterManager = filterManager;
    }

    public void sendRequest(HttpRequest request) {
        filterManager.filterRequest(request);
    }
}

InterceptingFilterPatternExample.java

package com.gpcoder.patterns.other.filter;

public class InterceptingFilterPatternExample {

    public static void main(String[] args) {
        FilterManager filterManager = new FilterManager(new Target());
        filterManager.addFilter(new TrackingFilter());
        filterManager.addFilter(new AuthenticationFilter());

        HttpRequest request = new HttpRequest();
        request.setClientIp("127.0.0.1");
        request.setTargetUrl("/home");

        Client client = new Client(filterManager);
        client.sendRequest(request);
    }
}

Output của chương trình:

Tracking request: HttpRequest(clientIp=127.0.0.1, targetUrl=/home)
Authenticating request: HttpRequest(clientIp=127.0.0.1, targetUrl=/home)
Executing request: HttpRequest(clientIp=127.0.0.1, targetUrl=/home)

Lợi ích của Intercepting Filter Pattern là gì?

  • Có thể thêm một vài xử lý trước hoặc sau khi request, response được target xử lý thực sự.
  • Giảm kết dính giữa các thành phần trong ứng dụng, mỗi filter chịu trách nhiệm một phần riêng.
  • Tăng khả năng tái sử dụng lại.
  • Dễ dàng thêm/ bớt filter mà không ảnh hưởng đến Business Logic.

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

Xem thêm:

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

Kỹ thuật tăng Database Performance, Availability và Scalability

Kỹ thuật tăng Database Performance, Availability và Scalability

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

Quay lại với chủ đề Database Performance, chủ đề không mới nhưng các kĩ thuật để cải thiện Performance thì luôn mới theo từng ngày.

Performance ở đây không chỉ nói về tốc độ, bản thân nó còn bao gồm khả năng mở rộng (Scalability) và tính sẵn sàng (Availability) của hệ cơ sở dữ liệu nữa.

Bài viết này tui hân hạnh giới thiệu với anh em 3 kĩ thuật giúp cải thiện Performance. Anh em đọc xong có góp ý gì thì comment cho tui với nhé.

1. Database Performance với Indexing

Database Indexing là một kĩ thuật không còn quá xa lạ với anh em. Với indexing, performance các câu truy vấn tăng lên rõ rệt. Mục này xin được phân tích kĩ hơn bằng cách nào mà Indexing lại có thể làm tăng Database Performance.

1.1 Movitation

Đầu tiên, với Indexing:

  • Speed up retrieval operations
  • Locate the desired records in a sublinear time

Chính vì vậy, nếu không có Indexing và khi table có một lượng data cực kì lớn, ta sẽ gặp phải vấn đề về Database Performance (cụ thể là Query Performance)

  • Require a “Full Table Scan” (Scan toàn bộ table để tìm record match)
  • Take a long time for large tables (Cần thời gian nhiều hơn đối với table có lượng data khủng)

Ví dụ dưới đây ta cần tìm kiếm cho các records có city là “Los Angeles”. Không có indexing, ta cần scan toàn bộ table từ trên xuống dưới để tìm ra được các records thoả mãn yêu cầu.

Database Performance

Hoặc với một trường hợp khác là vừa Scan vừa Sort theo Age. Số lần sort tối thiểu cần là 1 và vẫn scan toàn bộ table.

Database Performance

Nếu scan toàn bộ table và với một lượng data lớn. Việc full scan table có thể gây ra 2 vấn đề:

  • Become a performance bottleneck (trở thành một điểm chết về performance)
  • Impact our users’ experience (ảnh hưởng tới trải nghiệm người dùng)

  Công cụ performance test Jmeter
  Quản lý realm database theo hướng micro-service trong iOS

1.2 Index Table

Tới với giải pháp đầu tiên là Index Table. Vậy index table là gì?

Index Table is helper table, created from a particular columns/ group columns Index Table thực chất là một bảng hỗ trợ được tạo từ một cột hoặc một nhóm cột cụ thể

Ví dụ phía trên cho thấy Index Table bao gồm City và Row, row là thứ tự của dòng có giá trị City mà nó lưu.

1.3 Data Structures

Index Table cũng có Data Structures của riêng nó theo từng loại index. Mỗi loại index lại sử dụng một loại Data Structures riêng, từ đó improve được Database Performance.

  • HashMap
  • Self-balanced tree (B-Tree)

Ví dụ dưới đây là Index Hash Table và sử dụng HashMap, phía bên row là index của các row có giá trị của City là Los Angeles. Chính cái này làm tăng performance. Khi cần query thì chỉ cần lấy ở row số 1 và row số 3

Database Performance

Chi tiết hteme về database index anh em có thể tham khảo ở bài viết Database indexes : advantages and disadvantages.

Tham khảo việc làm Database hấp dẫn tại TopDev!

2. Database Replication

Database Replication cũng là một kĩ thuật giúp cải thiện Database Performance. Bản thân từ Replication có nghĩa là nhân rộng. Cũng là bản chất của kĩ thuật này và tại sao áp dụng nó lại làm tăng tính Scalability của Database nói riêng và hệ thống nói chung.

Database Performance

Ví dụ như hình trên đây là mình hoạ cho một ứng dụng chỉ có duy nhất một Replica của Database. Ta có rất nhiều services và nhiều Server để thao tác với database.

Chỉ một database kiểu này biến nó trở thành (Single point of failure – một điểm chết). Trường hợp database này có vấn đề, toàn bộ hệ thống sẽ down.

Replication lúc này trở thành cứu cánh, giải pháp là Replication tạo ra nhiều hơn một các Database.

Database Performance

Khi một Replication down, request từ services lúc này sẽ chuyển hướng tới các Replica khác

Chính việc áp dụng Replication giúp làm tăng tính sẵn sáng của hệ thống (Availability).

3. Database Sharding

Database Sharding hay còn có cái tên khác à Databse Partitioning là một giải pháp khác giúp làm tăng Database Performance. Chủ yếu là ở phương diện Scalability (mở rộng).

Về cơ bản thì kĩ thuật này thay vì clone các Database thành các Replica khác nhau (bao gồm toàn bộ data) như hình dưới.

Database Performance

Thay vì clone ra như giải pháp Replication, Sharding là kĩ thuật chia toàn bộ Database thành các Shard nhỏ hơn. Khái niệm về Shard không dễ đâu nha anh em. Anh em có thể tìm hiểu thêm qua bài viết Dynamic Sharding – Nghệ thuật của locator.

Database Performance

Về adavantages thì Database Sharding cho phép ta:

  • Scale our database to store more data (lưu được nhiều dữ liệu hơn)
  • Different queries can be performed completely in parallel
  • Better Performance
  • Higher Scalability

Sharding cũng là giải pháp cho hệ cơ sở dữ liệu phân tán (Distributed Database). Vấn đề muôn thưở là Shard nào sẽ lưu đúng data mà ta cần. Request tới, nhưng lấy dữ liệu từ đâu?

Database Performance

Mé, cái này là câu hỏi lớn và cần một bài viết riêng mới giải thích cụ thể hơn cho anh em là làm như thế nào có thể “tìm được đúng tình yêu Shard của đời mình”?.

4. Tổng kết

Bài viết này tui đã giới thiệu cho anh em 3 kĩ thuật giúp tăng Database Performance bao gồm:

  • Một là Indexing
  • Hai là Replication
  • Ba là Partitioning

Có kĩ thuật nào khác nhờ anh em chỉ giáo giúp nghe.

5. Tham khảo

Today is great day for me when I learned a new thing – Thank you for your time – Happy coding!

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

Làm thế nào để viết bug dễ hiểu và hiệu quả

Làm thế nào để viết bug dễ hiểu và hiệu quả

Bài viết được sự cho phép của tác giả To Thi Van Anh

Log bug là một công việc quan trọng và không thể tránh được trong kiểm thử phần mềm, một bug được log tốt, giúp cho người đọc có thể dễ dàng nhìn ra được vấn đề, không phải mất nhiều thời gian để tìm hiểu và trao đổi qua lại quá nhiều lần, bên cạnh đó cũng là để phòng ngừa và phát hiện những vấn đề nghiêm trọng xảy ra, liên quan và ảnh hưởng trực tiếp đến chất lượng sản phẩm phần mềm.

Về mặt lý thuyết, có lẽ các bạn đều biết được rằng bug đưa lên thì cần phải ngắn gọn súc tích nhưng vẫn phải đảm bảo cung cấp đủ các thông tin cần thiết. Ô mà như thế nào là ngắn gọn mà vẫn đầy đủ thông tin? Haha, mời các bạn bớt chút thời gian đọc tiếp nha!

Hình ảnh có liên quan

Yếu tố tâm lý: Đóng góp – đừng ra lệnh

Khi test mà bắt được con bug nào, tester vui mừng bao nhiêu thì Dev buồn bấy nhiêu. :)) Vì thế hãy luôn mang một tinh thần và mục tiêu là cùng đóng góp để xây dựng một sản phẩm chất lượng, đừng gay gắt ra lệnh, nó dễ làm ảnh hưởng đến tâm lý người nhận và dễ gây căng thẳng giữa hai bên.

  Các câu hỏi thú vị phỏng vấn kỹ sư kiểm thử phần mềm – Phần 1

  Làm thế nào để cải thiện kỹ năng debug?

Đừng log trùng bug

Một vấn đề khác, đó là việc log bug bị trùng, nguyên nhân thì do chủ quan hay khách quan đều có, nhưng dù là gì đi nữa thì bạn cũng nên hạn chế thấp nhất vấn đề này, một vài lần xảy ra sẽ khiến dev “mất niềm tin” ở bạn ngay. Vì vậy, cần kiểm tra và lọc kỹ thông tin trước khi log bug, một vài chục bug ta có thể nhớ được chứ khi đã lên đến hàng trăm thì không thể chủ quan được!

Xem thêm các việc làm tuyển dụng Tester hấp dẫn tại TopDev

Cung cấp thông tin chi tiết, đầy đủ: What, How, When.

Điểm quan trọng nữa đối với việc log bug, đó là bạn phải cung cấp được thông tin liên quan đến bug đó như là điều gì đã xảy ra, nó đã xảy ra như thế nào nào? ở đâu, khi nào?

Ví dụ: bug này xảy ra khi bạn đã thực hiện các bước với test data như thế nào, và bạn đã thực hiện nó ở phần chức năng nào của hệ thống. Để từ đó người đọc sẽ hình dung, dễ dàng tái hiện và tìm bug theo mô tả này của bạn hơn.

Mỗi bug nên tập trung vào một vấn đề thôi

Trong một bug bạn chỉ nên tập trung vào một vấn đề cụ thể mà bạn gặp đó thôi, đừng nghĩ là mất công log một bug này nên là tranh thủ gom vài vấn đề vào chung luôn cho đỡ phải log tiếp, như vậy làm cho các vấn đề trở nên rắc rối, khó nắm bắt, nhiều khi bị lan man mất nhiều thời gian để có thể giải quyết và close được bug.

Một vài lưu ý lớn

Mỗi công ty/đội dự án lại có các cách quản lý bug khác nhau, các biểu mẫu và cách báo cáo khác nhau. Nhưng nhìn chung thì log bug chúng ta cũng đều phải đảm bảo và lưu ý một số yếu tố dưới đây:

1. Bug id: Yếu tố này giúp việc quản lý, tìm kiếm dễ dàng và nhanh chóng hơn. Đặc biệt đối với project mà số lượng bug trở nên quá lớn qua các build version.

2. Tiêu đề của bug: Đây sẽ là phần mà thường là ta sẽ đọc đầu tiên trước khi mở bug đó ra và đọc tiếp các mô tả bên trong, do đó phần này nên mô tả một cách khái quát nhất, đủ để người đọc có thể hình dung ra được vấn đề nhanh nhất có thể. Giúp người đọc có thể hiểu được và biết được là bug đã được fix hay đã gặp lần nào bao giờ chưa.

3. Mức độ nghiêm trọng của bug: Khi bug xảy ra, bạn có thể đánh giá độ nghiêm trọng của lỗi để gán cho nó trạng thái tương ứng, các trạng thái này có thể là Critical, Major, Minor, … tùy từng hệ thống, thường thì sẽ dựa vào chỉ số này để ưu tiên các bug nào sẽ phải được/nên được fix trước.

4. Môi trường/Nền tảng/Device test: Ở đây ta cần phải đưa ra thông tin cụ thể việc xảy ra bug đó khi bạn test trên môi trường nào, sử dụng device test nào: ví dụ như test trên Window 7, Chrome latest version…. Hay iPhone 7, iOS 9…., vì đôi khi thì bug đó chỉ xảy ra ở một số môi trường đặc biệt nào đó thôi, việc cung cấp các thông tin này cũng giúp cho đội Dev có thêm thông tin để tìm được ra được các vấn đề.

5. Mô tả lỗi: Phần này cung cấp thông tin đầy đủ và chi tiết về lỗi đã xảy ra, giúp cho Dev hiểu hơn về vấn đề. Đưa ra các bước theo đúng tuần tự thực hiện để có thể tái hiện lỗi:

  • Điều kiện đầu vào: Bao gồm các bước chuẩn bị, test data…
  • Test steps: Các bước thực hiện, nên đánh số 1, 2, 3, …
  • Kết quả mong đợi: Kết quả đúng cho case này là gì?
  • Kết quả thực tế: Thực tế nó đã xảy ra như thế nào, cần mô tả rõ ràng và đầy đủ kết quả thực tế đã xảy ra nhé!

Bạn có thể sử dụng dấu ngoặc vuông [ ] để chỉ tên chức năng thực tế trên hệ thống để dễ Dev dễ hình dung nhé!

6. Tài kiệu đính kèm: “Một hình ảnh bằng hàng nghìn lời nói”, do đó bạn nên đính kèm theo mỗi bug các hình ảnh liên quan trực tiếp đến nó, có thể highlight vùng lỗi lên để người đọc dễ quan sát hơn, hoặc bạn cũng có thể quay một video các bước đã thực hiện, cách này sẽ giúp ích rất nhiều trong việc tái hiện và hiểu bug. Ngoài ra nếu bạn có thể lấy được các log file thì cũng có thể đính kèm lên cùng với bug, rồi các tài liệu tham khảo liên quan khác, nếu cần thiết.

Một lưu ý nữa là bạn cần đảm bảo là đã sử dụng bản build test và điều kiện phù hợp tương ứng với test cycle. Và nhớ đọc kỹ lại một lượt bug để đảm bảo không mắc các lỗi về diễn đạt hay chính tả nữa nha.

Kiểm tra kỹ hơn trên các máy test khác để đảm bảo là nó không phải chỉ gặp vấn đề ở mỗi máy của bạn thôi, còn trên máy của người khác vẫn không vấn đề gì. Rồi cũng phải đảm bảo là bug này có thể tái hiện lại được.

Viết bug dễ hiểu và hiệu quả
Hehe, Chuyện tình lãng mạn chưa nè, nhớ đọc kỹ nhaaa!

Khi log một bug cần luôn phải nhớ rằng mô tả cần ngắn gọn, rõ ràng, dễ hiểu, cung cấp đầy đủ thông tin cần thiết, để có thể dễ dàng tái hiện bug, tránh mất thời gian để trao đổi quá nhiều lần. Điều này giúp bạn có ấn tượng tốt trong mắt các bạn Dev, mặc dù biết là bạn log bug thì họ cũng không hề vui vẻ gì! Hehe

Bài viết gốc được đăng tải tại vananhtooo.wordpress.com

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

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

Phân biệt Front End và Back End, điểm khác nhau là gì?

Phân biệt Front End và Back End, điểm khác nhau là gì?

Nếu bạn là một lập trình viên newbie, có thể bạn sẽ bối rối với các thuật ngữ như Front EndBack End. Đây là 2 thuật ngữ quan trọng trong một website bất cứ ai theo học lập trình web đều phải biết. Tuy nhiên, nhiều người vẫn chưa thực sự hiểu rõ sự khác biệt giữa chúng là gì và nhiệm vụ của từng phần là gì. Trong bài viết này, chúng ta sẽ tìm hiểu sâu hơn về Front End và Back End, cách phân biệt Front End và Back End chi tiết nhất. Cùng theo dõi nhé!

Phân biệt khái niệm Front End và Back End

Front End và Back End

Front End là gì?

Front-end là phần giao diện của website nơi mà người dùng cuối có thể nhìn thấy và tương tác trực tiếp. Tất cả những gì bạn có thể nhìn thấy trên website bao gồm: màu sắc, hình ảnh, văn bản, đồ thị, bảng biểu,… được gọi là phần front-end của trang web.

Những người chịu trách nhiệm xây dựng, phát triển những thành phần này được gọi là Front End Developer. Họ sẽ sử dụng các công cụ và ngôn ngữ lập trình như HTML, CSS, JavaScript để tạo ra giao diện người dùng trực quan và hấp dẫn, tương thích trên nhiều trình duyệt và thiết bị khác nhau.

Back End là gì?

Back End là phần người dùng không thể nhìn thấy được, có nhiệm vụ xử lý các nghiệp vụ phức tạp ở phía sau giúp phần front end hoạt động trơn tru. Thông thường, các phần này bao gồm cơ sở dữ liệu, máy chủ, và các tập lệnh khác được sử dụng để xử lý và lưu trữ dữ liệu. Mặc dù người dùng không tương tác trực tiếp với back-end nhưng họ sẽ tương tác gián tiếp thông qua front-end.

Các Back End Developer sẽ tập trung vào phía máy chủ trang web bao gồm: Databases, quản lý service,… Sử dụng các ngôn ngữ lập trình như Java, Python, Ruby, PHP và các framework như Node.js, Ruby on Rails và Django để phát triển các hệ thống website. Vai trò của một Back End Developer là cực kỳ quan trọng trong việc xây dựng một trang web, bởi vì họ đảm bảo rằng các ứng dụng phải hoạt động chính xác và đáp ứng được nhu cầu của người dùng.

  Những Câu Hỏi Phỏng Vấn Front End Thường Xuất Hiện Trong Các Buổi Phỏng Vấn

  Top 7 câu hỏi phỏng vấn Backend Developer

Kỹ năng của Front End Developer và Back End Developer

Front End DeveloperBack End Developer là hai vai trò quan trọng trong quá trình phát triển website. Mỗi vai trò đều có những kỹ năng đặc trưng riêng, dưới đây là một số sự khác biệt về kỹ năng giữa Front End Developer và Back End Developer:

Front End Developer

  • Thành thạo HTML, CSS và JavaScript để xây dựng giao diện người dùng tốt nhất có thể.
  • Sử dụng các framework như Angular, React, Vue.js, Ember để tăng tốc độ phát triển web.
  • Kỹ năng sử dụng JavaScript/jQuery để thêm các chức năng cần thiết và các plugin, extension  giúp việc phát triển trang web nhanh chóng và dễ dàng hơn.
  • Kỹ năng quản lý các Git và Version để theo dõi các thay đổi được tạo ra trong quá trình code hoặc kiểm soát các version.
  • Hiểu biết về UI/UX design và các nguyên tắc thiết kế.
  • Có khả năng sửa lỗi, tối ưu hóa tốc độ tải trang web.
  • Có kiến ​​thức về responsive designcross-browser compatibility.

front end developer

Tham khảo việc làm Back-end Developer Hồ Chí Minh hấp dẫn trên TopDev

Back End Developer

  • Thành thạo các ngôn ngữ lập trình như Java, Python, Ruby, PHP, C# để xử lý các yêu cầu phức tạp từ phía người dùng.
  • Có kiến thức về cơ sở dữ liệu và truy vấn dữ liệu, hiện nay SQL và NoSQL là hai loại cơ sở dữ liệu được sử dụng phổ biến nhất.  
  • Hiểu biết về mạng và máy chủ, bao gồm các giao thức web, lưu lượng truy cập, bảo mật và quản lý máy chủ.
  • Có kiến thức về một số thuật toán như: Depth First Search và Breadth-First Search, bubble sort, selection sort, insertion sort, merge sort, quick sort, thuật toán đệ quy và lặp,…
  • Có khả năng sửa lỗi và cải thiện hiệu suất website.
  • Nắm được một số kỹ năng khác như: Quản lý môi trường lưu trữ với CSDL, kiến thức về kiểm soát Git và,…

back end developer

Link ảnh tham khảo: https://www.liveabout.com/the-skills-you-need-to-be-a-backend-developer-2071184

Ngoài ra, cả Front End Developer và Back End Developer đều cần có kỹ năng tốt về giao tiếp để tương tác với các thành viên khác trong đội ngũ phát triển, kỹ năng giải quyết vấn đề, tư duy logic và sáng tạo.

Bảng tóm tắt so sánh Back End và Front End

Yếu tố

Backend Developer

Frontend Developer

Tính chất công việc Tập trung vào phát triển giao diện website để mang đến những trải nghiệm tốt nhất cho người dùng. Phát triển cấu trúc và chức năng của hệ thống, xử lý logic và dữ liệu từ phía máy chủ.
Ngôn ngữ lập trình Java, Python, Ruby, PHP, Node.js HTML, CSS, JavaScript, TypeScript
Nhiệm vụ Tạo và duy trì hệ thống sau đó cung cấp dữ liệu cho Frontend Developer Xây dựng giao diện người dùng và các tính năng tương tác
Mức lương Trung bình khoảng $81,000 USD/năm Trung bình khoảng $75,000 USD/năm
Thư viện Django, Laravel, Node.js, Ruby on Rails, Flaskkkk React, Angular, Vue.js, Ember.js, jQuery

Kết luận

Hy vọng bài viết này đã giúp bạn phân biệt được Front End và Back End, cũng như nhiệm vụ và vai trò của 2 vị trí Front End Developer và Back End Developer. Dù là Frontend hay Backend Developer, cả hai đều có vai trò quan trọng trong việc phát triển website.

Nếu bạn muốn trở thành một lập trình viên thành thạo, cần phải nắm vững những kỹ năng và công nghệ cần thiết cho từng vai trò. Với sự phát triển nhanh chóng của ngành công nghệ thông tin hiện nay, việc học tập và cập nhật kiến thức mới liên tục sẽ giúp bạn trở thành một chuyên gia trong lĩnh vực của mình. Chúc bạn thành công!

Bạn có thể quan tâm:

Tìm việc làm IT lương cao, đãi ngộ hấp dẫn trên TopDev!