Home Blog Page 49

Top 10 câu hỏi phỏng vấn Golang Developer thường gặp

Top 10 câu hỏi phỏng vấn Golang Developer thường gặp

Go hay Golang là ngôn ngữ lập trình do Google thiết kế và phát triển từ năm 2009, ra đời với mục đích khai thác tối đa nền tảng đa lõi của bộ vi xử lý và hoạt động đa nhiệm tốt hơn. Với sức mạnh của Golang, hiện nay có khá nhiều dự án đang lựa chọn ngôn ngữ lập trình này để phát triển, và vì thế nhu cầu tuyển dụng Golang ngày càng lớn hơn. Trong bài viết này chúng ta cùng nhau tìm hiểu top 10 câu hỏi phỏng vấn Golang Developer để cùng có sự chuẩn bị tốt nhất trước cơ hội việc làm này nhé.

Câu 1: Bạn có thể nói gì về ngôn ngữ lập trình Golang

Golang

Go hay Golang là một ngôn ngữ lập trình mã nguồn mở giúp xây dựng phần mềm một cách dễ dàng, tin cậy và hiệu quả do các kỹ sư hàng đầu của Google phát triển. Golang được khởi nguồn từ năm 2007 và được chính thức công bố dưới dạng mã nguồn mở năm 2009. Phiên bản ổn định 1.0 được Google giới thiệu vào tháng 3/2012. Năm 2018, Google có thông báo về Golang 2 với sự chung tay phát triển của cộng đồng, mặc dù vậy đến hiện nay thì Golang 2 vẫn chưa có kế hoạch về ngày ra mắt.

Sứ mệnh của Golang là giúp tăng năng suất phần mềm, đặc biệt là ở lĩnh vực multicore processing (xử lý đa nhân), network (mạng) và những dự án có source code rất lớn. 

Câu 2: Nêu những đặc tính của Golang

Golang là một ngôn ngữ kiểu tĩnh (static typed) tức là mọi thứ trong nó đều phải được khai báo kiểu. Ban đầu ngôn ngữ này sử dụng trình biên dịch thông qua ngôn ngữ C, từ phiên bản 1.5 thì tác giả đã tự viết luôn một trình compiler dành riêng cho ngôn ngữ. Ưu điểm của trình compiler này là thời gian build rất nhanh so với các trình biên dịch của các ngôn ngữ kiểu tĩnh khác.

Golang hỗ trợ kiến trúc 64 bits, nó cũng có một trình thu dọn rác tự động (Garbage Collector), ngoài ra nó còn hỗ trợ cả Web Assembly. Golang hỗ trợ lập trình đồng thời (concurrent) với từ khóa go đặt ngay trước nơi gọi hàm, kỹ thuật này gọi là Goroutine.

Với những đặc tính trên, Go là một ngôn ngữ phù hợp với việc phát triển các dự án về system như Network, Proxy, Distributed Computing, Cloud Native,…

  So sánh giữa C++ và Golang 

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

Câu 3: Những kiểu dữ liệu trong Golang

Trong Go, có 3 loại dữ liệu cơ bản bao gồm:

  • Kiểu bool (true/false)
  • Kiểu dữ liệu số: int, float, byte, complex, ..
  • Kiểu chuỗi (string)

Kiểu dữ liệu dẫn xuất (derived types) xây dựng từ những kiểu dữ liệu cơ bản và tích hợp sẵn trong Golang bao gồm Pointer (con trỏ), Array (mảng), Structure, Union, Function (hàm), Slice, Interface, Map và Channel.

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

Câu 4: Methods trong Golang khác gì với function

Methods tron Golang

Golang không phải là một ngôn ngữ lập trình hướng đối tượng nên nó không hỗ trợ các lớp (class), mặc dù vậy chúng ta có thể sử dụng struct trong Golang nhằm thay thế cho class. Để có được hành vi tương tự như các lớp (class) trong các ngôn ngữ lập trình khác, Golang hỗ trợ các methods (phương thức) – nó là một hàm(function) được khai báo cho riêng một kiểu dữ liệu đặc biệt được gọi là receiver. Cú pháp để tạo một Method như sau: “func (t Type) methodName(parameter list)”.

Điểm khác cơ bản của methods so với function là việc khai báo receiver, từ đó cho phép khai báo trùng tên và chỉ cần khác kiểu dữ liệu nhận (receiver).

Câu 5: Interface trong Golang là gì?

Interface trong OOP giúp chúng ta xác định các hành vi sẽ có của một đối tượng (chưa cần khai báo nội dung bên trong). Interface trong Golang cũng là tập hợp những khai báo phương thức mà cho phép chúng ta có thể định nghĩa hoạt động cho nó được. Khi một kiểu dữ liệu định nghĩa tất cả các phương thức trong một interface thì nó được gọi là implement của interface đó. Hay nói cách khác thì trong Golang, Interface được implement một cách ngầm định (implicitly) mà không cần khai báo tường minh bằng từ khóa nào.

Một tính năng thú vị khác của interface là dùng để khai báo kiểu dữ liệu any (đại diện cho bất kỳ kiểu dữ liệu nào). Cú pháp interface{} gọi là Empty Interface giúp bạn không cần xác định rõ kiểu dữ liệu của biến, rất hay được sử dụng khi làm value cho kiểu dữ liệu map trong Golang.

Câu 6: Phân biệt Array, Slice và Map trong Golang

Array hay mảng là một tập hợp các phần tử có cùng kiểu dữ liệu nằm liên tiếp nhau, hay nói cách khác thì Array là một tập hợp có thứ tự, vì thế chúng ta có thể truy cập Array bằng chỉ số (index) của phần tử đó trong mảng.

Slice về bản chất là các tham chiếu đến mảng hiện có, nó mô tả một phần hoặc toàn bộ Array, vì thế nó có kích thước động (thay đổi được). Thông thường Slice sẽ được tạo từ 1 Array bằng cách lấy từ vị trí phần tử bắt đầu và kết thúc trên Array đó.

Map cũng là một kiểu dữ liệu tập hợp, tuy nhiên các phần tử trong nó không có thứ tự, tức là chúng ta không thể truy xuất đến phần tử trong Map bằng chỉ số như Slice hay Array. Map sẽ chứa các phần tử dạng key-value, từ đó việc truy xuất sẽ thực hiện qua các key.

Câu 7: Giải thích về Concurrency trong Golang

Concurrency là tính năng xử lý song song nhiều tác vụ cùng một lúc, giúp tận dụng năng lực xử lý của CPU. Trong Golang, một luồng được quản lý bởi Go runtime gọi là Goroutine, cú pháp khai báo của Goroutine đơn giản chỉ cần thêm từ khóa “go” vào trước mỗi hàm cần gọi.

Các Goroutine có khả năng chạy song song cùng lúc, ngoài ra chúng có thể trao đổi dữ liệu với nhau trong qua Channel (kênh). Việc sử dụng Channel cho phép đồng bộ hóa dữ liệu giữa các Goroutine; khi một Goroutine truyền dữ liệu vào Channel thì nó sẽ dừng lại để đợi một Goroutine khác lấy dữ liệu ra thì mới tiếp tục thực hiện tiếp.

Câu 8: Phương pháp xử lý lỗi trong Golang

Xử lý lỗi (error handling) trong Golang không giống với xử lý try/catch như các ngôn ngữ khác; lỗi trong Go sẽ được trả về như 1 giá trị của hàm nếu có điều gì không mong đợi (errors hoặc exceptions) xảy ra. 

Kiểu error trong Go có một phương thức Error() trả về thông báo lỗi dưới dạng string. Go cũng cung cấp cho chúng ta một package error tích hợp sẵn và public với hàm gọi New. Để đưa ra những Exception thì Go cung cấp cho chúng ta cơ chế Panic. Khi một hàm gặp Panic, nó lập tức dừng xử lý, chấm dứt chương trình và giải phóng stack gọi; thông báo lỗi sẽ được trả về khi chương trình kết thúc.

Câu 9: Kể tên một số thư viện, framework phổ biến của Golang

framework golang

  • Beego: web framework với các module chứa các tính năng phổ biến cho ứng dụng web, nó cũng bao gồm 1 ORM (object relationship map) để truy cập dữ liệu và thư viện cho các operation với những đối tượng HTTP
  • Iris: cũng là một web framework, ưu điểm của Iris là khả năng xây dựng các ứng dụng web và API hiệu suất cao
  • Viper: thư viện giúp viết và đọc các nội dung liên quan tới thông số cấu hình trong Golang, hỗ trợ các định dạng như TOML, JSON, YAML,…
  • Cobra: một thư viện giúp bạn xây dựng một CLI (command line interface: giao diện dòng lệnh) trong Golang
  • Colly: công cụ thu thập dữ liệu tùy chỉnh từ các trang web của Golang

Câu 10: Kể tên những dự án nổi tiếng viết bằng Go

  • Docker: nền tảng cung cấp cách dựng, kiểm thử và triển khai ứng dụng nhanh chóng thông qua các container
  • Kubernetes: một hệ thống mã nguồn mở giúp việc triển khai, nhân rộng dễ dàng và tự động thông qua việc sử dụng các container Docker
  • NATS: một Message System, là thành phần quan trọng trong các hệ thống pub/sub, event-driven
  • Consul: một service dành cho việc thiết lập mạng (network) trong microservices một cách dễ dàng 

Kết bài

Như vậy chúng ta đã đi qua được top 10 câu hỏi phỏng vấn thường gặp nhất cho vị trí Golang Developer. Hy vọng bài viết này mang lại thêm sự tự tin cho bạn để chinh phục được nhà tuyển dụng. Hẹn gặp lại các bạn trong bài viết tiếp theo của mình.

Tác giả: Phạm Minh Khoa

Xem thêm:

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

Immutable là gì? Sự khác nhau giữa Immutable với Mutable

Immutable là gì? Sự khác nhau giữa Immutable với Mutable

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

1. Immutable là gì? Sự khác nhau giữa Immutable với mutable.

Immutable hiểu nôm na là không thể thay đổi còn mutable là có thể thay đổi. hai khái niệm Immutable và mutable thường được dùng class, object (Immutable đôi khi còn dùng với Collection nhưng mình sẽ không để cập ở bài này).

Ví dụ: Trong Java String là Immutable còn StringBuffer và StringBuilder là mutable.

1 Class/Đối tượng được coi là immutable nếu các thuộc tính của nó không bao giờ bị thay đổi và chỉ có thể thiết lập lúc khởi tạo.

  • Ví dụ Immutable với String

Immutable với String

  Bí quyết sử dụng "Immutability" để code gọn và sạch hơn

  Giới thiệu về Spring Integration

// Khởi tạo str1 = "first"
String str1 = new String("first");

// Khởi tạo str2 tham chiếu tới str1
String str2 = str1;

// String là immutable, bất kì thao tác nào trên String đều tạo ra 1 đối tượng mới
// str1.concat("-second") sẽ trả về 1 đối tượng String mới có giá trị là "first-second"
str1 = str1.concat("-second");

System.out.println("str1: "+str1);
System.out.println("str2: "+str2);

Kết quả

str1: first-second
str2: first
  • Ví dụ Mutable với StringBuffer

Immutable với String

// Khởi tạo str1 = "first"
StringBuffer str1 = new StringBuffer("first");

// Khởi tạo str2 tham chiếu tới str1
StringBuffer str2 = str1;

// StringBuffer là mutable, do đó khi append thì giá trị của nó sẽ thay đổi trên chính vùng nhớ ban dầu
str1.append("-second");

System.out.println("str1: "+str1);
System.out.println("str2: "+str2);

Kết quả:

str1: first-second
str2: first-second

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

2. Tại sao lại dùng Immutable

Giống như ví dụ với String bên trên, ta thấy được sử dụng immutable sẽ tránh được sự thay đổi lẫn nhau khi đa tham chiếu (str1 và str2 cùng tham chiếu tới 1 vùng nhớ nhưng khi str1 thay đổi thì str2 sẽ không thay đổi)

  • Thread Safe: Khi sử dụng immutable object ta sẽ không cần phải lo tới việc nhiều thread cùng làm thay đổi giá trị của 1 object
  • Sử dụng các immutable object làm tham số của method sẽ không sợ nó bị thay đổi sau khi method kết thúc
  • Sử dụng immutable object để làm key trong HashMap hoặc đẩy vào HashTable mà không gặp vấn đề gì khi lấy ra.

3. Cách tạo 1 Class Immutable

  • Phải là final class (không thể thừa kế bởi class khác)
  • Các field phải là private final
  • Không có các method làm thay đổi trạng thái của các field (Ví dụ: chỉ có hàm get, không có các hàm set)
  • Nếu có field nào là Object thì field đó cũng phải là 1 immutable Object hoặc khi khởi tạo/lấy ra field đó ta phải clone ra 1 bản khác.

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

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

Tìm việc làm IT mới nhất tại TopDev ngay!

Top 10 câu hỏi phỏng vấn Linux hàng đầu dành cho ứng viên

Top 10 câu hỏi phỏng vấn Linux hàng đầu dành cho ứng viên

Linux là một hệ điều hành không xa lạ gì với các lập trình viên, nhất là các vị trí thường xuyên thao tác với hệ thống (System). Thành thạo Linux là một yêu cầu mà nhiều nhà tuyển dụng bắt buộc khi phỏng vấn lập trình viên, vì thế để chuẩn bị tốt cho buổi phỏng vấn của mình, chúng ta cùng nhau tìm hiểu top 10 câu hỏi thường gặp liên quan đến hệ điều hành Linux này nhé.

Câu 1: Hệ điều hành mã nguồn mở là gì?

Mã nguồn mở (open-source) là thuật ngữ chung đề cập đến các phần mềm và ứng dụng chạy trên thiết bị máy tính mà cho phép người dùng có thể sử dụng, xem và tùy chọn sửa đổi các mã nguồn (source code). Hệ điều hành mã nguồn mở (Open-Source Operating System) là những hệ điều hành cho phép cá nhân hay tổ chức được phép can thiệp vào sâu bên trong để tùy biến và sử dụng với các mục đích khác nhau mà không thu phí.

Một số hệ điều hành mã nguồn mở hiện nay như Linux (cha đẻ của những Ubuntu, Fedora, Android,…) Open Solaris, Free BSD. Ngược lại với hệ điều hành mã nguồn mở là hệ điều hành đóng như iOS, macOS của Apple hay Windows của Microsoft.

Câu 2: Linux là gì?

Linux là gì?

Linux là một họ các hệ điều hành tự do mã nguồn mở dựa trên Linux kernel (hạt nhân Linux). Linux được phát hành lần đầu vào năm 1991, bản phát hành bao gồm nhân Linux (kernel), các thư viện và phần mềm hệ thống hỗ trợ.

Từ bản phát hành của Linux, nhiều hệ điều hành dựa trên Linux ra đời và trở nên phổ biến như Ubuntu, Debian hay Fedora. Android – hệ điều hành phổ biến chạy trên các smartphone hiện nay cũng là một hệ điều hành dựa trên nền tảng Linux. Ngoài ra Linux cũng chạy được trên các hệ thống nhúng, từ đó mà các thiết bị điện tử khác như Tivi, máy quay, các thiết bị điện trong smarphone,… cũng đang được chạy phần mềm hoạt động trên nền tảng Linux.

  Cài đặt Rust trên Arch Linux

  6 câu lệnh linux hay dùng trong phân tích log

Câu 3: Nêu những ưu điểm của Linux

Ngoài việc là một hệ điều hành mã nguồn mở, hoàn toàn miễn phí thì Linux còn nhiều ưu điểm đáng để sử dụng:

  • Tính tùy biến cao: bạn có thể dễ dàng thay đổi, tùy biến Linux theo nhu cầu và mục đích sử dụng của mình hay thậm chí tạo ra một hệ điều hành mới của riêng bạn bằng cách sử dụng Linux.
  • Tính tương thích cao: Linux có thể chạy trên hầu hết các thiết bị phần cứng đến từ Intel, IBM,… Các trình điều khiển thiết bị (driver) cũng được cộng đồng hỗ trợ phát triển để có thể sử dụng tốt trên nền tảng Linux.
  • Hiệu suất cao: Hệ điều hành Linux được tối giản giúp nó nhẹ, ít các ứng dụng đi kèm, nhờ vậy mang lại hiệu năng sử dụng cao. Việc cài đặt Linux cũng đòi hỏi cấu hình phần cứng thấp, nhờ vậy các máy tính cũ, cấu hình yếu vẫn có thể chạy tốt khi dùng hệ điều hành này.
  • Tính bảo mật cao: Linux mã nguồn mở nên bất cứ ai cũng có thể đào sâu vào hệ điều hành để đảm bảo rằng nó không có lỗi hay các back door. Nhờ cộng đồng hỗ trợ mà Linux có ít lỗ hổng hơn so với các hệ điều hành đóng khác.
  • Xem thêm tuyển dụng Linux lương cao trên TopDev

Câu 4: Các thành phần cơ bản của Linux

Linux có 4 thành phần cơ bản sau:

  • Kernel: phần nhân – là phần cốt lõi của hệ điều hành, chịu trách nhiệm cho tất cả các hoạt động từ quản lý thiết bị, bộ nhớ, quy trình và xử lý các lệnh gọi hệ thống.
  • Thư viện hệ thống: System Libraries là các chương trình giúp truy cập các tính năng của Kernel
  • Công cụ hệ thống: System Tools là tập hợp các công cụ tiện ích, thường là các lệnh đơn giản giúp người dùng truy cập file, thao tác với thư mục, với dữ liệu,…
  • Công cụ phát triển: Development Tools là những công cụ và thư viện bổ sung giúp các lập trình viên tạo ra các ứng dụng hoạt động trên Linux.

Câu 5: Linux Shell là gì?

Linux Shell là một chương trình cung cấp giao diện dành cho người dùng để sử dụng các dịch vụ hệ điều hành. Shell nhận các lệnh mà người dùng nhập vào, đọc và thực hiện chuyển đổi chúng thành thứ mà Kernel (nhân Linux) có thể hiểu được.

Để làm được điều này thì Shell được trang bị một trình thông dịch để thực thi các lệnh mà người dùng nhập vào. Shell được chia thành 2 loại:

  • Command Line Shell: người dùng sử dụng Terminal để thực hiện việc nhập lệnh để shell thực thi, kết quả cũng trả về trực tiếp trên Terminal. Các lệnh được quy định sẵn trong Shell và người dùng bắt buộc phải nhớ chúng
  • Graphical Shells: Linux cung cấp một số Shell thao tác trên GUI (graphical user interface) như đóng mở cửa sổ, hiển thị thông số dưới dạng biểu đồ,…

Câu 6: Root là gì? Có các loại chủ sở hữu nào trong Linux?

Root là tên người sử dụng (tài khoản) mặc định có quyền truy cập vào tất cả các lệnh và file trên Linux. Quyền Root dùng để chỉ quyền hạn mà tài khoản root có trên hệ thống, đây là đặc quyền lớn nhất trên hệ thống, có quyền tuyệt đối thao tác với dữ liệu, file, thư mục; ngoài ra còn có quyền cấp và thu hồi quyền truy cập đối với các tài khoản user khác trên hệ thống.

Trong Linux, có 3 loại chủ sở hữu (ownership) được gắn lên mỗi file và thư mục bao gồm:

  • User: Khi người dùng tạo ra file hay folder thì sẽ trở thành chủ sở hữu của file, folder đó
  • Group: một group bao gồm nhiều User có cùng quyền truy cập vào một file hay thư mục. Group sử dụng khi bạn muốn chia sẻ dữ liệu cho một nhóm những người dùng chung và cùng muốn set giá trị quyền truy cập, thao tác, chỉnh sửa lên dữ liệu
  • Other: dùng để chỉ bất kỳ người dùng nào không thuộc 2 đối tượng trên.

Linux quy định 3 chủ sở hữu trên để phân quyền và kiểm soát hành vi của người dùng.

Câu 7: Permissions trong Linux. Làm sao để thay đổi quyền của file hay thư mục trong Linux?

Permissions hay quyền giúp kiểm soát hành vi của người dùng trong Linux. Mỗi file hay thư mục trong Linux đều có 3 quyền: đọc, ghi và thực thi. Cụ thể là:

  • Quyền đọc: ký hiệu là r – Read cho phép mở file, đọc file; xem danh sách thư mục và file chứa trong 1 thư mục
  • Quyền ghi: ký hiệu là w – Write cho phép sửa nội dung file; thêm, xóa hay đổi tên các file trong thư mục
  • Quyền thực thi: ký hiệu là x – Execute cho phép chạy file
  • Trường hợp không có quyền nào thì Linux sẽ hiển thị ký hiệu –

Để xem được quyền của file hay thư mục, chúng ta sử dụng lệnh: “ls – l”

Để thay đổi quyền truy cập vào 1 file hay folder chúng ta sử dụng lệnh: “chmod <permissions-number> <filename>”. Trong đó permissions-number sẽ có 3 chữ số với ý nghĩa lần lượt từ trái sang phải là quyền của user, quyền của group và quyền của others.

Câu 8: Trình soạn thảo Vi trong Linux

Trình soạn thảo Vi là một trong những cách phổ biến nhất để người dùng thao tác chỉnh sửa nội dung file trong Linux, nó được ưu chuộng bởi việc nhẹ, chiếm ít tài nguyên và mặc định có sẵn trong các hệ điều hành Linux. Phiên bản nâng cấp của Vi là Vim – Vi Improved. Một số lệnh cơ bản khi thao tác với Vi

  • Chế độ soạn thảo: Vi cung cấp 2 chế độ, chạy command để người dùng thao tác các lệnh tìm kiếm, thay thế, xóa,… và chế độ nhập văn bản (insert mode) thao tác trực tiếp với nội dung file. Để chuyển đổi giữa 2 chế độ chúng ta sử dụng phím i, a, o hoặc Insert để nhập văn bản và Esc để về chế độ command
  • vi <filename> cho việc mở file nếu đã tồn tại, hoặc tạo mới nếu file chưa tồn tại và mở nó lên
  • :q cho việc thoát chế độ văn bản, nếu muốn thoát mà không lưu chúng ta thêm !
  • :w cho việc lưu file. Để lưu và thoát chúng ta kết hợp :wq
  • yy cho việc sao chép dòng hiện tại, p cho việc dán bản sao vào vị trí con trỏ, dd thực hiện việc xóa dòng

Câu 9: stdin, stdout, stderr là gì?

Stdin, stdout và stderr là ba luồng dữ liệu được tạo khi bạn khởi chạy một lệnh trong Linux, trong đó:

  • stdin là dòng đầu vào tiêu chuẩn
  • stdout là dòng đầu ra tiêu chuẩn
  • stderr là dòng báo lỗi tiêu chuẩn

Nói cách khác chúng ta có 1 luồng đầu vào và 2 luồng đầu ra. Mặc định khi chạy chương trình thì kết quả sẽ được hiện ra ở 2 nơi stdout và stderr; để có thể dễ dàng kiểm tra cũng như xử lý các tiến trình tiếp theo thì chúng ta thường sử dụng kỹ thuật trong bash Linux để gửi 2 kết quả đầu ra trên về cùng 1 nơi nào đó, ví dụ như lưu vào 1 file. Kỹ thuật này gọi là sự chuyển hướng câu lệnh.

Câu 10: Những phiên bản phổ biến nhất của hệ điều hành Linux

  1. Red Hat Enterprise Linux: được sử dụng chủ yếu bởi các tổ chức có yêu cầu tính bảo mật cao như cơ quan, tổ chức nhà nước
  2. CentOS: hệ điều hành cho các server và hoàn toàn miễn phí, đây cũng là 1 bản phân phối miễn phí của Red Hat, vì thế nó được đánh giá cao nhờ mức độ bảo mật
  3. Fedora: cũng là một phiên bản được tài trợ bởi Red Hat, nó được dùng để kiểm tra các tính năng mới trước khi được thương mại hóa của Red Hat Enterprise Linux
  4. Debian Linux: bản phân phối miễn phí của Linux, chúng ta có thể dùng để tham khảo source code hay tùy biến để thương mại hóa hoàn toàn hợp pháp
  5. Ubuntu: được xem là Windows của Linux, dễ sử dụng, tương đối đầy đủ các phần mềm và công cụ với hiệu năng ổn đáp ứng nhu cầu của người dùng.

Kết bài

Trên đây là top 10 câu hỏi liên quan đến hệ điều hành Linux mà bạn có thể bắt gặp trong buổi phỏng vấn của mình. Nếu đi sâu vào hệ điều hành Linux, sẽ có rất nhiều kiến thức chuyên sâu mà bạn cần chuẩn bị thêm, liên quan đến phần nhân và cách hệ điều hành hoạt động. Hy vọng bài viết này hữu ích dành cho các bạn có cái nhìn tổng quan về Linux và chuẩn bị thật tốt cho buổi phỏng vấn sắp tới. 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

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

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

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

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

Các hàm xây dựng (constructor) trong Java được sử dụng để tạo đối tượng và có thể lấy các tham số cần thiết để tạo đối tượng. Vấn đề khi một đối tượng có thể được tạo ra với nhiều tham số (param), một số có thể là bắt buộc và một số khác có thể là tùy chọn tuỳ theo từng yêu cầu của người dùng, tuỳ vào hoàn cảnh của ứng dụng. Chúng ta, có thể tạo ra nhiều constructor theo từng nhu cầu hoặc gán giá trị null cho các param không cần thiết. Tuy nhiên, code rất khó đọc, khó bảo trì, người sử dụng có thể gán nhầm giá trị nếu một loạt các tham số có cùng kiểu. Chúng ta cũng có thể sử dụng một giải pháp khác là sử dụng setter() để thay thế cho constructor. Tuy nhiên, nếu muốn đối tượng này là immutable thì không thể.

Do vậy, người ta mong muốn giao công việc này cho một đối tượng chịu trách nhiêm khởi tạo và chia việc khởi tạo đối tượng riêng lẽ, từng bước, để có thể tiến hành khởi tạo riêng biệt ở các hoàn cảnh khác nhau. Và giải pháp được đưa ra là sử dụng Builder Pattern như một người xây dựng.

Builder Pattern là gì?

Builder is a creational design pattern that separate the construction of a complex object from its representation so that the same construction process can create different representations.

Builder pattern là một trong những Creational pattern. Builder pattern là mẫu thiết kế đối tượng được tạo ra để xây dựng một đối tượng phức tạp bằng cách sử dụng các đối tượng đơn giản và sử dụng tiếp cận từng bước, việc xây dựng các đối tượng đôc lập với các đối tượng khác.

Builder Pattern được xây dựng để khắc phục một số nhược điểm của Factory Pattern và Abstract Factory Pattern khi mà Object có nhiều thuộc tính.

Có ba vấn đề chính với  Factory Pattern và Abstract Factory Pattern khi Object có nhiều thuộc tính:

  • Quá nhiều tham số phải truyền vào từ phía client tới Factory Class.
  • Một số tham số có thể là tùy chọn nhưng trong Factory Pattern, chúng ta phải gửi tất cả tham số, với tham số tùy chọn nếu không nhập gì thì sẽ truyền là null.
  • Nếu một Object có quá nhiều thuộc tính thì việc tạo sẽ phức tạp.

Chúng ta có thể xử lý những vấn đề này với một số lượng lớn các tham số bằng việc cung cấp một hàm khởi tạo với những tham số bắt buộc và các method getter/ setter để cài đặt các tham số tùy chọn. Vấn đề với hướng tiếp cận này là trạng thái của Object sẽ không nhất quán cho tới khi tất cả các thuộc tính được cài đặt một cách rõ ràng. Nếu cần xây dựng một đối tượng Immutable thì cách này cũng không thể thực hiện được.

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

  Hướng dẫn Java Design Pattern – Object Pool

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

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

Một builder gồm các thành phần cơ bản sau:

  • Product : đại diện cho đối tượng cần tạo, đối tượng này phức tạp, có nhiều thuộc tính.
  • Builder : là abstract class hoặc interface khai báo phương thức tạo đối tượng.
  • ConcreteBuilder : kế thừa Builder và cài đặt chi tiết cách tạo ra đối tượng. Nó sẽ xác định và nắm giữ các thể hiện mà nó tạo ra, đồng thời nó cũng cung cấp phương thức để trả các các thể hiện mà nó đã tạo ra trước đó.
  • Director/ Client: là nơi sẽ gọi tới Builder để tạo ra đối tượng.

Trường hợp đơn giản, chúng ta có thể gộp Builder và ConcreteBuilder thành static nested class bên trong Product.

Ví dụ sử dụng Builder

Ví dụ: sử dụng Builder cho việc gọi món tại một cửa hàng thức ăn nhanh.

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

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

Product:

public class Order {

    private OrderType orderType;
    private BreadType breadType;
    private SauceType sauceType;
    private VegetableType vegetableType;

    public Order(OrderType orderType, BreadType breadType, SauceType sauceType, VegetableType vegetableType) {
        super();
        this.orderType = orderType;
        this.breadType = breadType;
        this.sauceType = sauceType;
        this.vegetableType = vegetableType;
    }

    @Override
    public String toString() {
        return "Order [orderType=" + orderType + ", breadType=" + breadType + ", sauceType=" + sauceType
                + ", vegetableType=" + vegetableType + "]";
    }

    public OrderType getOrderType() {
        return orderType;
    }

    public BreadType getBreadType() {
        return breadType;
    }

    public SauceType getSauceType() {
        return sauceType;
    }

    public VegetableType getVegetableType() {
        return vegetableType;
    }

}

public enum BreadType {
    SIMPLE, OMELETTE, FRIED_EGG, GRILLED_FISH, PORK, BEEF,
}

public enum OrderType {
    ON_SITE, TAKE_AWAY;
}

public enum SauceType {
    SOY_SAUCE, FISH_SAUCE, OLIVE_OIL, KETCHUP, MUSTARD;
}

public enum VegetableType {
    SALAD, CUCUMBER, TOMATO
}

Builder:

package com.gpcoder.patterns.creational.builder.food.builder;

import com.gpcoder.patterns.creational.builder.food.product.order.Order;
import com.gpcoder.patterns.creational.builder.food.product.type.BreadType;
import com.gpcoder.patterns.creational.builder.food.product.type.OrderType;
import com.gpcoder.patterns.creational.builder.food.product.type.SauceType;
import com.gpcoder.patterns.creational.builder.food.product.type.VegetableType;

public interface OrderBuilder {

    OrderBuilder orderType(OrderType orderType);

    OrderBuilder orderBread(BreadType breadType);

    OrderBuilder orderSauce(SauceType sauceType);

    OrderBuilder orderVegetable(VegetableType vegetableType);

    Order build();

}

ConcreteBuilder:

package com.gpcoder.patterns.creational.builder.food.concretebuilder;

import com.gpcoder.patterns.creational.builder.food.builder.OrderBuilder;
import com.gpcoder.patterns.creational.builder.food.product.order.Order;
import com.gpcoder.patterns.creational.builder.food.product.type.BreadType;
import com.gpcoder.patterns.creational.builder.food.product.type.OrderType;
import com.gpcoder.patterns.creational.builder.food.product.type.SauceType;
import com.gpcoder.patterns.creational.builder.food.product.type.VegetableType;

public class FastFoodOrderBuilder implements OrderBuilder {

    private OrderType orderType;
    private BreadType breadType;
    private SauceType sauceType;
    private VegetableType vegetableType;

    @Override
    public OrderBuilder orderType(OrderType orderType) {
        this.orderType = orderType;
        return this;
    }

    @Override
    public OrderBuilder orderBread(BreadType breadType) {
        this.breadType = breadType;
        return this;
    }

    @Override
    public OrderBuilder orderSauce(SauceType sauceType) {
        this.sauceType = sauceType;
        return this;
    }

    @Override
    public OrderBuilder orderVegetable(VegetableType vegetableType) {
        this.vegetableType = vegetableType;
        return this;
    }

    @Override
    public Order build() {
        return new Order(orderType, breadType, sauceType, vegetableType);
    }

}

Director:

package com.gpcoder.patterns.creational.builder.food.director;

import com.gpcoder.patterns.creational.builder.food.concretebuilder.FastFoodOrderBuilder;
import com.gpcoder.patterns.creational.builder.food.product.order.Order;
import com.gpcoder.patterns.creational.builder.food.product.type.BreadType;
import com.gpcoder.patterns.creational.builder.food.product.type.OrderType;
import com.gpcoder.patterns.creational.builder.food.product.type.SauceType;

public class Client {

    public static void main(String[] args) {
        Order order = new FastFoodOrderBuilder()
                .orderType(OrderType.ON_SITE).orderBread(BreadType.OMELETTE)
                .orderSauce(SauceType.SOY_SAUCE).build();
        System.out.println(order);
    }
}

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

Order [orderType=ON_SITE, breadType=OMELETTE, sauceType=SOY_SAUCE, vegetableType=null]

Ví dụ sử dụng Builder để tạo đối tượng Immutable

Một vài điểm quan trọng về implement class Product:

  • Constructor là private, điều này có nghĩa là class này không thể gọi khởi tạo trực tiếp từ bên ngoài.
  • Tất cả các thuộc tính đều là private final, vì vậy nó chỉ được gán giá trị trong constructor và nó chỉ có thể được cung cấp các phương thức getter().
  • Việc khởi tạo đối tượng chỉ có thể thông qua Builder.

Một vài điểm quan trọng về implement class Builder:

  • Tạo một static nested class (đây được gọi là builder class) và copy tất cả các tham số từ class bên ngoài vào. Chúng ta nên đặt tên class này theo định dạng: [tên class] + Builder. Ví dụ class là BankAccount thì builder class sẽ là BankAccountBuilder.
  • Class Builder có một hàm khởi tạo public với tất cả các thuộc tính bắt buộc.
  • Class Builder có các method setter() cho các tham số tùy chọn.
  • Cung cấp method build() trong Class Builder để trả về đối tượng mà client cần.

Ví dụ: Một tài khoản ngân hàng bao gồm các thông tin: Tên chủ tài khoản, số tài khoản, địa chỉ email, nhận thông báo, sử dụng mobile banking. Một tài khoản được tạo phải có tên chủ tài khoản và số tài khoản. Các thông tin khác tùy theo nhu cầu của khách hàng có thể đăng ký sử dụng.

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

BankAccount:

package com.gpcoder.patterns.creational.builder.bank;

public class BankAccount {

    private final String name; // required
    private final String accountNumber; // required
    private final String address;
    private final String email;
    private final boolean newsletter;
    private final boolean mobileBanking;

    public BankAccount(String name, String accountNumber, String address, String email, boolean newsletter,
            boolean mobileBanking) {
        super();
        this.name = name;
        this.accountNumber = accountNumber;
        this.address = address;
        this.email = email;
        this.newsletter = newsletter;
        this.mobileBanking = mobileBanking;
   }

   // Builder class
   public static class BankAccountBuilder {

       private String name; // required
       private String accountNumber; // required
       private String address;
       private String email;
       private boolean newsletter;
       private boolean mobileBanking;

       public BankAccountBuilder(String name, String accountNumber) {
           this.name = name;
           this.accountNumber = accountNumber;
       }

       public BankAccountBuilder withAddress(String address) {
           this.address = address;
           return this;
       }

       public BankAccountBuilder withEmail(String email) {
           this.email = email;
           return this;
       }

       public BankAccountBuilder wantNewsletter(boolean newsletter) {
           this.newsletter = newsletter;
           return this;
       }

       public BankAccountBuilder wantMobileBanking(boolean mobileBanking) {
           this.mobileBanking = mobileBanking;
           return this;
       }

       public BankAccount build() { 
           validateUserObject();

           BankAccount bankAccount = new BankAccount(
                   this.name, this.accountNumber, 
                   this.address, this.email,
                   this.newsletter, this.mobileBanking);

          return bankAccount;
      }

      private void validateUserObject() {
          // Do some basic validations to check
          if (this.newsletter && email == null) {
              throw new IllegalArgumentException("Email can't be null when client want to receive the new letter");
          }
      }
  }

  @Override
  public String toString() {
      return "BankAccount [name=" + name + ", accountNumber=" + accountNumber + ", address=" + address + ", email="
              + email + ", newsletter=" + newsletter + ", mobileBanking=" + mobileBanking + "]";
  }

}

Client:

package com.gpcoder.patterns.creational.builder.bank;

public class Client {

    public static void main(String[] args) {
        BankAccount newAccount = new BankAccount
                  .BankAccountBuilder("GP Coder", "0123456789")
                  .withEmail("contact@gpcoder.com")
                  .wantNewsletter(true)
                  .build();
        System.out.println(newAccount);
    }
}

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

BankAccount [name=GP Coder, accountNumber=0123456789, address=null, email=contact@gpcoder.com, newsletter=true, mobileBanking=false]

Lưu ý: class BankAccount có hàm khởi tạo là private, nên chỉ có một cách duy nhất để lấy một đối tượng BankAccount là thông qua class BankAccountBuilder.

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

  • Hỗ trợ, loại bớt việc phải viết nhiều constructor.
  • Code dễ đọc, dễ bảo trì hơn khi số lượng thuộc tính (propery) bắt buộc để tạo một object từ 4 hoặc 5 propery.
  • Giảm bớt số lượng constructor, không cần truyền giá trị null cho các tham số không sử dụng.
  • Ít bị lỗi do việc gán sai tham số khi mà có nhiều tham số trong constructor: bởi vì người dùng đã biết được chính xác giá trị gì khi gọi phương thức tương ứng.
  • Đối tượng được xây dựng an toàn hơn: bởi vì nó đã được tạo hoàn chỉnh trước khi sử dụng.
  • Cung cấp cho bạn kiểm soát tốt hơn quá trình xây dựng: chúng ta có thể thêm xử lý kiểm tra ràng buộc trước khi đối tượng được trả về người dùng.
  • Có thể tạo đối tượng immutable.

Một số ví dụ sử dụng Builder Pattern trong JDK:

Nhược điểm của Builder Pattern là gì?

Builder Pattern có nhược điểm là duplicate code khá nhiều: do cần phải copy tất cả các thuộc tính từ class Product sang class Builder.

Tăng độ phức tạp của code (tổng thể) do số lượng class tăng lên.

Sử dụng Builder Pattern khi nào?

  • Tạo một đối tượng phức tạp: có nhiều thuộc tính (nhiều hơn 4) và một số bắt buộc (requried), một số không bắt buộc (optional).
  • Khi có quá nhiều hàm constructor, bạn nên nghĩ đến Builder.
  • Muốn tách rời quá trình xây dựng một đối tượng phức tạp từ các phần tạo nên đối tượng.
  • Muốn kiểm soát quá trình xây dựng.
  • Khi người dùng (client) mong đợi nhiều cách khác nhau cho đối tượng được xây dựng.

So sánh Builder Pattern với Factory/ Abstract Factory Pattern

Factory Pattern cũng có thể được sử dụng để xây dựng một đối tượng phức tạp, vậy sự khác biệt của nó với mô hình Builder Pattern là gì?

Sự khác biệt lớn duy nhất giữa Builder Pattern và Factory Pattern cung cấp cho bạn nhiều quyền kiểm soát hơn đối với quá trình tạo đối tượng.

Factory/ Abstract Factory Pattern là câu trả lời cho “WHAT” và Builder Pattern là câu trả lời cho “HOW“.

Trong Builder Pattern, đối tượng được xây dựng từng bước (step by step). Builder Pattern có nhiều bước nhỏ, mỗi bước sẽ có các đơn vị logic nhỏ kèm theo trong đó. Cũng sẽ có một chuỗi (sequence) liên quan. Nó sẽ bắt đầu từ bước 1 và sẽ đi lên tối đa bước n và bước cuối cùng là trả về đối tượng. Nhưng trong Factory Pattern, bạn sẽ không thấy được đối tượng phức tạp được tạo như thế nào, nó không có từng bước xây dựng đối tượng.

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

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

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

Sử dụng Sqlite trong Android như thế nào hiệu quả nhất?

Sử dụng Sqlite trong Android như thế nào hiệu quả nhất?

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

Thông qua bài Sqlite trong android chúng tôi muốn giới thiệu SQLite là một cơ sở dữ liệu mã nguồn mở được sử dụng để lưu trữ dữ liệu dạng văn bản (text) trên thiết bị di động.

SQLite hỗ trợ tất cả các tính năng của cơ sở dữ liệu quan hệ. Để truy cập cơ sở dữ liệu SQLite, bạn không cần phải thiết lập bất kỳ một loại kết nối đến SQLite như JDBC, ODBC,…

SQLite là hệ quản trị cơ sở dữ liệu cho nền tảng mobile như Android, IOS, Windows Phone. SQLite được sử dụng để quản lý thông tin bao gồm các chức năng như lưu trữ và truy xuất thông tin.

Sqlite trong android

SQLite trong Android – Các bước thực hiện

Bước 1: Tạo một lớp kế thừa lớp SQLiteOpenHelper dùng để thao tác với cơ sở dữ liệu. Trong đó ClassName là tên lớp.

public class ClassName extends SQLiteOpenHelper {
 //Tạo phương thức khởi tạo
 //Override phương thức onCreate
 public void onCreate(SQLiteDatabase db) {
   String sql = "câu lệnh tạo bảng";
   db.execSQL(sql);
 }
 /*Các phương thức:
  thêm dữ liệu, cập nhật dữ liệu,
  xóa dữ liệu và truy vấn dữ liệu*/
}

Xây dựng phương thức thêm dữ liệu

public void methodName([parameter]) {
  SQLiteDatabase db = this.getWritableDatabase();
  ContentValues cv = new ContentValues();
  cv.put(columnName1, value);
  cv.put(columnName2, value);
  ...
  db.insert(tableName, null, cv);
}

Xây dựng phương thức cập nhật dữ liệu

public void methodName([parameter]) {
 SQLiteDatabase db = this.getWritableDatabase();
 ContentValues cv = new ContentValues();
 cv.put(columnName1, value);
 cv.put(columnName2, value);
 …
 String whereClause = "columnName1 = ? …";
 String whereArgs[] = {value1,…};
 db.update(tableName, cv, whereClause, whereArgs);
}

Xây dựng phương thức xoá dữ liệu

public void methodName([parameter]) {
 SQLiteDatabase db = this.getWritableDatabase();
 String whereClause = "columnName1 = ? …";
 String whereArgs[] = {value1,…};
 db.delete(tableName, whereClause, whereArgs);
}

Xây dựng phương thức truy vấn dữ liệu không có điều kiện

public void methodName([parameter]) {
 String sql = "select * [or column1,…] from tableName";
 SQLiteDatabase db = this.getReadableDatabase();
 Cursor c = db.rawQuery(sql, null);
 if(c != null){
    c.moveToFirst(); //Về đầu danh sách
    do {
      Truy vấn dữ liệu sử dụng c.getString(columnIndex);
    }while(c.moveToNext());
 }
}

Xây dựng phương thức truy vấn dữ liệu có điều kiện

public void methodName([parameter]) {
 SQLiteDatabase db = this.getReadableDatabase();
 String[] columns = {"column1", "colum2",…};
 String selection = "column1 = ? …";
 String []selectionArgs = {value1,…};
 String groupBy = null;
 String having = null;
 String orderBy = null;
 Cursor c = db.query(tableName, columns, selection, selectionArgs, groupBy, having, orderBy);
 if(c!=null){
   c.moveToFirst(); //Về đầu danh sách
   do {
     Truy vấn dữ liệu sử dụng c.getString(columnIndex);
   }while(c.moveToNext());
 }
}

Bước 2: Sử dụng lớp đã tạo ở bước 1 trong activity

protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_qlsv);
 //Khai báo đối tượng
 ClassName objectName = new ClassName();
}

Trong đó:

  • ClassName là tên lớp đã xây dựng ở bước 1
  • objectName là tên đối tượng. Sử dụng đối tượng này để truy xuất các phương thức thêm, cập nhật, xoá hoặc truy vấn dữ liệu

  Cách Thiết Lập Máy Ảo, Máy Thật & Khởi Chạy Ứng Dụng Trong Android

  Tạo Splash Screen cho Android như thế nào là "chuẩn" nhất?

SQLite trong android – Ví dụ mẫu xây dựng ứng dụng quản lý danh sách khách hàng

Sqlite trong android

Màn hình thêm mới khi người dùng chạm vào “Add New”

Sqlite trong android

Khi người dùng chạm vào “SAVE CONTACT“, quay về màn hình chính

Sqlite trong android

Để chỉnh sửa hoặc xoá thông tin khách hàng, người dùng chạm vào khách hàng sau đó chọn thao tác Edit Contact hoặc Delete Contact từ menu

Sqlite trong android

Tham khảo việc làm Android Developer Hồ Chí Minh tại TopDev

SQLite trong android – Các bước thực hiện

Bước 1: Tạo java class tên DBHelper. Code đầy đủ của DBHelper

Bước 2: Tạo activity DisplayContactActivity

Thiết kế layout

Sqlite trong android

Thiết kế menu display_contact: Chuột phải menu -> chọn New -> chọn Menu resource file

Sqlite trong android

Bổ sung đoạn code sau vào display_contact.xml

<item
    android:id="@+id/Edit_Contact"
    android:orderInCategory="100"
    android:title="@string/edit"/>
<item
    android:id="@+id/Delete_Contact"
    android:orderInCategory="100"
    android:title="@string/delete"/>

Thiết kế menu menu_sqlite_sample: Chuột phải menu -> chọn New -> chọn Menu resource file. Bổ sung đoạn code sau vào menu_sqlite_sample.xml

<item android:id="@+id/item1"
    android:title="@string/Add_New" >
</item>

Bổ sung đoạn code sau vào string.xml

Sqlite trong android
<string name="Add_New">Thêm</string>
<string name="edit">Cập nhật Contact</string>
<string name="delete">Xoá Contact</string>
<string name="title_activity_display_contact">DisplayContact</string>
<string name="name">Name</string>
<string name="phone">Phone</string>
<string name="email">Email</string>
<string name="street">Street</string>
<string name="country">City/State/Zip</string>
<string name="save">Lưu Contact</string>
<string name="deleteContact">Bạn có chắc không?</string>
<string name="yes">Đồng ý</string>
<string name="no">Không</string>

Viết xử lý cho DisplayContactActivity. Code đầy đủ của DisplayContactActivity

Bước 3: Tạo activity SqliteSampleActivity

Thiết kế layout

Sqlite trong android

Viết xử lý cho SqliteSampleActivity. Code đầy đủ của SqliteSampleActivity

Sqlite trong android – Bài tập thực hành 

Xây dựng ứng dụng ToDoList (Danh sách công việc cần thực hiện)

  • Tên cơ sở dữ liệu là todolistdb
  • Tên bảng dữ liệu todolisttbl, có cấu trúc như sau
FieldName Type Description
id Integer Khóa chính (Primary Key), kiểu số nguyên tự tăng (AutoIncrement)
job Text Nội dung công việc cần nhớ
date Text Thời gian công việc cần phải thực hiện

Thiết kế giao diện cho ứng

Sqlite trong android

Khi chọn nút lệnh “Thêm”, chuyển sang màn hình cho phép nhập nội dung và thời gian thực hiện công việc (Hình 2). Khi người dùng chọn nút lệnh “Lưu và trở về”, thực hiện lưu nội dung công việc vào cơ sở dữ liệu, quay về màn hình 1 và hiển thị tất cả nội dung công việc đã tạo.

Sqlite trong android

Trường hợp muốn xóa 1 công việc dự định trong danh sách hay tất cả công việc trong danh sách, người dùng chọn và giữ trên mục công việc để hiện lên context menu và chọn chức năng cần thiết. Lưu ý, bổ sung thêm chức năng cho phép người dùng cập nhật lại nội dung và thời gian thực hiện trong context menu.

Sqlite trong android

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

Bạn có thể xem thêm:

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

Top 5 câu hỏi phỏng vấn MySQL hay gặp và câu trả lời

Top 5 câu hỏi phỏng vấn MySQL hay gặp và câu trả lời

Lại là chuỗi bài series phỏng vấn, SQL có rồi, các hệ cơ sở dữ liệu (RDBMS) khác có rồi, giờ tới lượt MySQL. DB phổ biến hàng đầu thế giới liệu phỏng vấn có gì khác biệt?

Tất cả sẽ tới trong 3 phần của chuỗi bài viết phỏng vấn MySQL.

Bắt đầu thôi nào anh em. Meme cuối cùng cũng chỉ là meme chứ không ý gì là dìm hàng MongoDB. Coi chứ nhiều khi đâu phải MySQL là ngon nhất, nhưng thôi cứ cập nhật kiến thức phỏng vấn đã.

1. VARCHAR và CHAR khác nhau thế nào? Lúc nào thì sử dụng cái nào?

Câu hỏi phỏng vấn MySQL này là câu hỏi cơ bản ha anh em. Đánh giá ở mức độ Junior, nắm chắc kiến thức về các kiểu dữ liệu.

Đầu tiên thì CHAR và VARCHAR chắc chắn là kiểu dữ liệu dạng chuỗi ha. Độ dài các kí tự là cần được quy định.

  • CHAR lưu trữ các kí tự có độ dài cố định, trong khi VARCHAR lưu trữ các ký tự có độ dài không cố định (có thể thay đổi được)
  • Với kiểu CHAR, khi đã khai báo độ dài cố định, nếu chuỗi input vào có độ dài nhỏ hơn, các kí tự phía sau sẽ được tự động thêm vào bằng khoảng trắng.
  • Về hiệu suất thì CHAR tốt hơn VARCHAR một chút.
  • Chính vì độ dài CHAR cấp là cố định từ trước nên bộ nhớ cấp phát cũng có giới hạn, VARCHAR thì ngược lại, bộ nhớ của VARCHAR chưa giới hạn trước mà có thể thay đổi.

Phỏng vấn MySQL

Các kiến thức có thể bổ sung thêm ở phần này:

  • Khác nhau giữa TRUNCATE và DELETE
  • GRANT command trong MySQL
  • Kiểu Blob trong MySQL
  • Khác nhau giữa Foregin Key và Primary Key
  • ENUM trong MySQL

  Lộ trình học MySQL từ A đến Z
 

2. MySQL có bao nhiêu stored objects (đối tượng lưu trữ)?

Làm việc nhiều với MySQL tất nhiên anh em ít nhất đã từng một lần nghe hoặc dùng tới VIEW, STORED PROCEDURE, STORED FUNCTION.

Câu hỏi phỏng vấn MySQL này được phân loại ở mức độ Middle. Có 5 đối tượng dùng để lưu trữ trong MySQL nha anh em, bao gồm VIEW, STORED PROCEDURE, STORED FUNCTION, TRIGGER, EVENT.

Liệt kê từng loại:

  • VIEW – View được xem như một bảng ảo dưa trên kết quả truy vấn dữ liệu. Gom 3 field này ở bảng A, 2 field kia ở query B gom gom xếp xếp lại đem đặt vào VIEW.
  • STORED PROCEDURE – Là stored objects, được gọi tới về lệnh call. Có cái đặc biệt là procedure không trả về giá trị. Chỉ thực hiện làm một việc gì đó nha
  • STORED FUNCTION – Function thì ngược với PROCEDURE, nó có thể trả về một giá trị duy nhất. Có thể được gọi từ một câu lệnh khác.
  • TRIGGER – Trigger là một chương trình được liên kết với bảng. Cái này có thể gọi trước hoặc gọi sau các thao tác anh em thực hiện với table (insert, update, delete)
  • EVENT – Cái này anh em thường ít dùng, Event dùng để chạy một chương trình hoặc một tập các lệnh theo lịch trình đã lên từ trước đó.

Tham khảo việc làm MySQL Hồ Chí Minh hấp dẫn

Phỏng vấn MySQLChú ý là bài viết này chỉ đang đề cập tới MySQL nha anh em. SQL Server và MariaDB thì procedure có thể khác đấy.

3. Khác biệt giữa Heap Table và Temporary Table?

Anh em xài nhiều MySQL và thực hiện nhiều truy vấn hoặc có kinh nghiệm tối ưu performance có thể tự tin trả lời câu hỏi phỏng vấn MySQL này. Cũng không khó để trả lời câu này nếu nhìn vào từ khoá (Heap và Temporary).

Temporary tất nhiên là tạm, nên một số điểm khác biệt cốt lõi có thể nêu ra như sau:

  • Heap thì tồn tại trên memory, nếu anh em restart DB hay gì đó thì mất ha. Temporary thì ngược lại, do tính chất tạm bợ nên temporary chỉ tồn tại theo sessions. Session mất nghĩa là ta cũng mất.
  • Cũng phân biệt đối xử như vậy thì heap có thể chia sẻ giữa một vài client khi query tới DB, trong khi temporary table không chia sẻ giữa các clients.
  • Có cái hơn là để tạo được bảng tạm (temporary) anh em cần được cấp quyền, còn Heap thì không, cứ tạo thoải mái.

Thông tin thêm là MySQL heap table sẽ dử dụng hash index và rất nhanh nha anh em.

  MySQL so găng MariaDB, điểm khác biệt chính, ưu và nhược điểm

4. Sự khác biệt giữa MySQL và MongoDB

Câu hỏi phỏng vấn MySQL này chỉ nêu ví dụ là sự khác biệt với MongoDB. Tuy nhiên anh em nếu có hiểu biết thêm về các hệ cơ sở dữ liệu khác thì càng tốt ha.

Về khác biệt thì có nhiều nhưng anh em có thể liệt kê một số khác biệt chính như sau:

MongoDB MySQL
Là hệ cơ sở dữ liệu mã nguồn mở lưu trữ dạng JSON Là hệ cơ sở dữ liệu mã nguồn mở nhưng lưu trữ theo kiểu dữ liệu dạng quan hệ (relation)
Mỗi dòng dữ liệu khác nhau được lưu trữ theo kiểu document (tài liệu) Mỗi dòng dữ liệu được lưu trữ dưới dạng các hàng trong bảng
Tài liệu một nhóm các Documents sẽ được lưu trữ trong Collection. Một nhóm các records sẽ được lưu trữ trong một bảng

Anh em cũng có thể nói thêm về kiến trúc, sự khác biệt về hiệu năng, lúc nào nên sử dụng MongoDB, lúc nào nên sử dụng MySQL.

5. Kiểu timestamp và đôi điều đặc biệt trong MySQL

Câu này bảo là trick thì cũng đúng, nhưng nếu anh em biết thêm thì cũng hay. Đầu tiên cho 1 statement tạo bảng. Bảng này có 2 cột kiểu TIMESTAMP là start và end

CREATE TABLE phongvan (cau1 VARCHAR(32), cau2 VARCHAR(32), batdau TIMESTAMP, kethuc TIMESTAMP);
INSERT INTO game VALUES ("laptrinh", "cautrucvagiaithuat", now(), now());

Sau khi chạy xong câu này dữ liệu trong bảng như sau:

+-----------+--------+---------------------+---------------------+
| cau1     | cau2  | batdau               | kethuc                 |
+-----------+--------+---------------------+---------------------+
| laptrinh | cautrucvagiaithuat | 2014-07-17 20:44:35 | 2014-07-17 20:44:35 |
+-----------+--------+---------------------+---------------------+

Câu hỏi là khi thực hiện câu SQL dưới đây, những dữ liệu nào sẽ thay đổi?

UPDATE phongvan SET cau1 = "cautrucvagiaithuat" WHERE cau1 = "laptrinh";

Hầu hết anh em đều cho rằng chỉ có cột cau1 là cập nhật. Nhưng kết quả lại là cả cột batdau cũng cập nhật theo, mặc dù ta không thực hiện chạy update. Nguyên nhân là do batdau và ketthuc thuộc kiểu TIMESTAMP. Trong MySQL kiểu timestamp sẽ tự động cập nhật khi thực hiện câu UPDATE. Nhưng chỉ duy nhất cột đầu tiên thực hiện cập nhật đó. Trớ trêu cuộc tình ghê.

Câu này trong bộ câu hỏi phỏng vấn MySQL thì liệt vào dạng trick ha. Nếu anh em có biết trả lời được thì tốt, nếu không cũng không thể đánh giá gì vì nó thuộc dạng trick người thì biết, người không.

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

Cảm ơn anh em đã đón đọc – Phỏng vấn vui vẻ nha anh em – Happy interview

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

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

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

Ăn “bề bề” và cách phát triển phần mềm theo nguyên lý 80/20

Ăn “bề bề” và cách phát triển phần mềm theo nguyên lý 80/20

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

1. Ăn bề bề

Chào các bạn,

Bữa trước mình có đi ăn búp phê với người yêu, trong thực đơn có món “bề bề hấp”. Mình quê ở Quảng Ninh, vốn gần biển nên món này chẳng có gì lạ lẫm cả, nhưng người yêu quê lại ở Thái Nguyên, ít được ăn đồ biển nên khá thích món này. Biết thế nên mình lấy mấy con rồi mang vào bàn ăn. Cái giống bề bề này tuy ngon, nhưng bóc lại cực kỳ khó và mất thời gian, do vỏ với thịt của nó gắn khá chặt với nhau. Nói không đùa, chứ bóc vỏ bề bề là cả một nghệ thuật đấy.

ĂN BỀ BỀ
Con bề bề trong như thế này

 

Oh vậy việc ăn bề bề thì có gì liên quan tới làm phần mềm ở đây?

Trước khi trả lời câu hỏi trên, thì dưới đây là cách bóc bề bề vừa nhanh, vừa dễ mà mình đã đúc kết ra được sau gần 20 năm sống ở Quảng Ninh:

  • Bước 1: Cắt bỏ phần đầu.
  • Bước 2: Cắt bỏ phần đuôi.
  • Bước 3: Cắt bỏ hai bên sườn, khi cắt thì cắt sâu một chút.
  • Bước 4: Lột vỏ trên lưng và dưới bụng.

Thực hiện 4 bước trên, bạn sẽ có một miếng bề bề ngon lành, công đoạn tiếp theo chỉ là cho vào miệng và thưởng thức thôi.

Nhưng khoan đã, hình như có điều gì không ổn trong 4 bước trên … Đúng rồi, có vẻ như mình đã “cắt bỏ” quá nhiều thì phải, bạn có thấy thế không? Hết cắt đầu, cắt đuôi rồi lại cắt hai bên sườn. Vậy sau cùng thì chỉ còn có một mẩu ở giữa thôi à?

Đúng vậy, nếu thực hiện 4 bước trên, bạn sẽ chỉ còn phần thịt ở giữa, nhưng đó là phần nhiều thịt nhất và cũng là phần có thịt ngon nhất. Nói thẳng ra, có một sự đánh đổi ở đây, để bóc bề bề nhanh và dễ, mình đã phải hi sinh phần thịt ở đầu, đuôi và hai bên sườn. Nhưng đây là một cuộc đánh đổi hợp lý và có lợi cho mình:

  • Nếu bỏ đi các phần có ít thịt (đầu đuôi và hai bên sườn), mình chỉ mất 30 giây để bóc, đổi lại mình vẫn giữ được phần thịt ở phần thân ngon lành.
  • Nếu mình chọn cách bóc cẩn thận, tỷ mỉ để lấy được thịt cả ở phần đầu và đuôi, mình sẽ mất tới 2 phút (gấp 4 lần cách trên) hoặc thậm chí hơn, nhưng số lượng thịt lấy được không đáng so với thời gian mình bỏ ra.

  Unit Testing trong phát triển phần mềm hiện đại

2. Nguyên lý 80/20

Với cách phân tích như trên, khiến mình nhớ tới một nguyên lý trong cuộc sống, đó là nguyên lý 80/20, hay còn được gọi là nguyên lý Pareto.

Nguyên lý 80/20: 80% các vấn đề là do 20% nguyên nhân gây ra.

Để ý trong cuộc sống bạn sẽ thấy nguyên lý này rất đúng:

  • 80% lợi nhuận của công ty đến từ 20% khách hàng trả tiền.
  • Bạn giành 80% thời gian cho 20% các mối quan hệ mà bạn có.
  • 80% tài sản trên thế giới được nắm giữ bởi 20% dân số.
  • 80% số thịt trên con bề bề có thể được bóc với 20% công sức.
  • Để hiểu được 80% nội dung của bài viết này, bạn chỉ cần đọc 20% số từ.

Con số 80/20 có thể du di, không nhất thiết phải chính xác tỷ lệ là 80/20. 80 ở đây ám chỉ phần đa số, còn 20 ám chỉ phần thiểu số.

Tham khảo Job FrontEnd HOT trên TopDev!

3. Nguyên lý 80/20 trong phát triển phần mềm

Nguyên lý 80/20 được áp dụng trong cả lĩnh vực phát triển phần mềm, nó giúp các nhà phát triển đưa sản phẩm của họ đến với khách hàng sớm hơn, cũng như tối ưu được các tính năng cần thiết khi tới tay người dùng. Cụ thể quy tắc này được áp dụng như thế nào, mình sẽ trình bày trong phần dưới đây.

3.1 80% tính năng của sản phẩm có thể được hoàn thiện với 20% thời gian

Viết đầy đủ luận điểm trên phải là: 80% tính năng của sản phẩm có thể được hoàn thiện với 20% thời gian, nhưng để hoàn thiện nốt 20% tính năng còn lại, bạn cần bỏ ra 80% thời gian.

Lấy ví dụ với dự án website thương mại điện tử cho gần gũi, thì để tạo ra nơi cho phép “người bán có thể bán hàng và người mua có thể mua hàng” thì thời gian code khá nhanh. Bạn chỉ cần code sao để sản phẩm hiển thị được lên website, khách hàng vào đặt hàng, và thông tin đơn hàng được gửi tới người bán là chấm hết. Code sẽ chỉ mất thời gian khi chúng ta làm thêm các tính năng phụ, giúp việc mua, bán, quản lý sản phẩm diễn ra dễ dàng hơn, hoặc để tối ưu trải nghiệm người dùng như:

  • Website có giao diện responsive.
  • Tính năng chat giữa người mua và người bán.
  • Có thông báo thời gian thực tới người bán khi có đơn hàng.
  • Có hiệu ứng animation khi tải trang web.
  • Thuật toán tìm kiếm tối ưu và nhanh chóng.
  • Lưu lại lịch sử mua hàng của khách hàng.
  • Gợi ý sản phẩm phù hợp với khách hàng.

  Các vai trò trong một team phát triển phần mềm

Mặc dù có thể thấy rằng các tính năng trên đều rất điển hình với một dự án thương mại điển tử hiện nay, nhưng suy cho cùng chúng đều là các tính năng phụ. Bởi cho dù có hay không, thì quy trình mua và bán trên hệ thống vẫn có thể diễn ra bình thường. Nếu không nhất thiết phải làm, bạn có thể bỏ qua cho nhẹ đầu, hoặc làm trong các phiên bản tiếp theo.

Việc lược bỏ các tính năng không cần thiết, hoặc chưa cần thiết trong giai đoạn hiện tại giúp bạn tiết kiệm được rất nhiều thứ, đặc biệt là thời gian.

Kể thêm một trường hợp mà chính mình từng trải qua. Hồi đó mới đi làm, mình nhận task làm tính năng quản lý user trên thống, yêu cầu task như sau:

  • Hiển thị danh sách user có phân trang với 20 user mỗi trang.
  • Có bộ lọc user.
  • Có tính năng ban/unban user.

Thật sự task này chẳng có gì khó, nếu chọn phương án làm đơn giản chắc mình chỉ mất 2 giờ, thế nhưng mình đã mất tới … 8 giờ vì cách làm quá “cồng kềnh”:

  • Danh sách user mình load từ một enpoint, sau đó dùng vuejs để xử lý thay vì dùng dữ liệu trực tiếp từ controller, kết hợp nhanh với một vài vòng lặp để tạo danh sách.
  • Bộ lọc user thông minh, tất cả bộ lọc chỉ có một ô tìm kiếm, khi nhập email, nó sẽ tự tìm kiếm user theo email, khi nhập số điện thoại, nó sẽ tự tìm kiếm user theo số điện thoại. Trong khi đó mình có thể làm cách đơn giản và tiết kiệm thời gian hơn là tạo 2 ô tìm kiếm, 1 ô tìm theo email và 1 ô tìm theo số điện thoại, khi muốn tìm theo tiêu chí nào thì điền vào ô tương tứng.
  • Trước khi ban/unban user mình hiển thị alert bằng thư viện sweetalert nhìn “ngầu lòi” thay vì dùng hàm alert() mặc định của javascript. Mình cũng mạnh dạn code thêm tính năng ban/unban nhiều user cùng lúc trong khi task không yêu cầu tính năng này.

Cuối cùng mình nhận ra rằng bản thân đã tốn quá nhiều thời gian cho một task đơn giản, mà nguyên nhân gây mất thời gian chính là quá tập trung vào các tiểu tiết trong khi giá trị nó đem lại là không cao. Giống như việc cố gắng bóc vỏ ở phần đầu và đuôi của con bề bề chỉ để lấy một chút thịt.

3.2 80% user chỉ sử dụng 20% tính năng sản phẩm.

Có bao nhiêu người mua một chiếc Iphone X và sử dụng hết các tính năng của nó, hay mọi người chỉ dùng mấy tính năng cơ bản như chụp hình, nghe – gọi, nhắn tin, lướt facebook, xem youtube, call facetime? Hay chính bạn đấy, bạn cài bao nhiêu app trên smartphone của mình, và trong số đó có bao nhiêu app được bạn sử dụng thường xuyên.

Đây là một sự thật khá “phũ phàng” với những người làm phần mềm như chúng ta. Vì có nhiều tính năng mà bạn tâm huyết, tốn nhiều ngày để code, rồi lại nhiều đêm đóng vai dũng sĩ diệt bug, vất vả lắm mới kịp deadline nhưng kết quả lại … chẳng có ai sử dụng. Thật đáng buồn phải không?

Lại tiếp tục kể một câu chuyện, ngày trước mình có làm một sản phẩm quản lý học viên cho một trung tâm Tiếng Anh. Các tính năng chia làm 2 giai đoạn, giai đoạn 1 làm các tính năng cơ bản như quản lý lớp học, quản lý học sinh trong lớp, sắp xếp thời khóa biểu,… Giai đoạn 2 làm các tính năng như xin nghỉ học, điểm danh học viên, thu chi,… Giai đoạn 1 làm trong 2 tháng thì xong, giai đoạn 2 làm trong 1 tháng tiếp theo. Nhưng kết quả là các tính năng ở giai đoạn 2 chẳng mấy ai sử dụng cả. Xin nghỉ thì học viên toàn nhắn tin trực tiếp cho giáo viên chứ chẳng thèm lên hệ thống tạo đơn; Học viên mỗi lớp quá ít để diểm danh, giáo viên chỉ cần nhìn là nhận biết được ai đi học, ai nghỉ học; Có tính năng thu chi thì lúc dùng, lúc không dùng, nói chung cũng không cần thiết. Vậy rõ ràng, chỉ với các tính năng ở giai đoạn 1 là sản phẩm đã có thể đáp ứng được các nhu cầu của người dùng mà không cần tới các tính năng ở giai đoạn 2.

80% user chỉ sử dụng 20% tính năng sản phẩm – luận điểm này giúp chúng ta hạn chế việc “vẽ hươu vẽ vượn” các tính năng trên phần mềm. Vì chỉ có 20% tính năng được sử dụng bởi phần lớn khách hàng. Thế nên bạn đừng có “tự đẻ” thêm các tính năng nếu không có căn cứ rõ ràng nhé.

4. Lời kết

Làm phần mềm cũng giống như cách bóc bề bề, nhiều khi bạn phải loại bỏ các tính năng ít giá trị để đối lấy thời gian phát triển nhanh. Và điều này được áp dụng rất nhiều trong các startup công nghệ hiện nay.

Hồi mới vào làm ở công ty, mình thấy mấy tool nội bộ của công ty cùi vãi, cứ thắc sao không áp dụng công nghệ A B C tiên tiến này, sao không làm hiệu ứng loading đẹp chút này, không tối ưu trải nghiệm này,… Cứ nghĩ mấy ông dev trước không biết gì nên mới làm thế, nhưng hóa ra là họ “không thèm làm” vì nó không cần thiết. Và đó cũng là dịp mình được nghe giải thích về nguyên lý 80/20 này, thật sự mình cảm thấy rất tâm đắc. Hôm nay được dịp chia sẻ lại với các bạn, hy vọng giúp các bạn có cái nhìn khách quan về công việc phát triển sản phẩm.

Xin chào, hẹn gặp lại trong các bài viết tiếp theo.

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

Những bài viết liên quan:

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

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