Chắc các bạn có để ý thấy, là mỗi khi khởi chạy Android Studio lên, sẽ có một popup nhỏ với tiêu đề là Tip of the Day. Popup này xuất hiện hoài cho đến khi bạn bỏ chọn Show Tips on Startup thì thôi.
Mình đồng ý với bạn là popup này cực kỳ hữu ích, nhưng không phải lúc nào chúng ta cũng đều dừng lại đọc và ghi nhớ tốt mỗi khi popup này hiện lên. Đã có lúc mình note các tip này lại ở đâu đó, nhưng rồi cũng bỏ mất. Chính vì vậy hôm nay mình quyết định một lần nữa tổng hợp tất cả chúng lại vào một bài viết, và mình cũng sẽ lọc ra các tip gần gũi và có thể được sử dụng nhiều nhất với mình và các bạn. Hi vọng bài viết hôm nay sẽ là trợ thủ đắc lực trong công việc lập trình ứng dụng Android hằng ngày của chúng ta.
Một Số Ký Hiệu Phím Đặc Biệt
Trước khi đi vào từng tip, chúng ta phải thống nhất với nhau các ký hiệu phím sẽ được dùng trong bài viết.
⇧Phím Shift
↑ Phím mũi tên hướng lên ⏎ Phím Enter
⌃ Phím Control (máy Mac)
⌥ Phím Option (máy Mac)
⌘ Phím Command (máy Mac) ⌫ Phím Delete (máy Mac)
Chức năng này rất rất cơ bản, mình nghĩ rằng ai cũng biết đến tổ hợp phím này khi tham gia vào lập trình. Đây đơn giản là một chức năng giúp gợi ý các dòng code cho bạn.
Tuy vậy, nếu tìm hiểu kỹ về chức năng cơ bản này, bạn sẽ phát hiện thêm nhiều điều thú vị hơn đấy nhé.
Mình ví dụ như khi nhấn tổ hợp phím⌃Space (máy Mac) khi gõ đến dòng code dưới đây, bạn thấy kết quả gợi ý hoàn thành code của hệ thống như sau. Bạn có thể chọn bất kỳ dòng code nào mà bạn muốn đúng không nào.
Thú vị ở chỗ, nếu ở bước này mình nhấn thêm một lần ⌃Space nữa, hệ thống sẽ cho ra kết quả nhiều hơn, chẳng hạn như sẽ có thêm các biến private.
Nếu bạn đã quen với tổ hợp phím tắt để hoàn thành code như đã nói trên đây, thì để cho hệ thống gợi ý hoàn thành code thông minh hơn bạn chỉ cần nhấn thêm phím⇧ mà thôi.
Khi dùng tính năng này, hệ thống sẽ dự đoán kiểu dữ liệu, hoặc luồng dữ liệu mà bạn sắp dùng, và đưa ra gợi ý phù hợp nhất trong ngữ cảnh đó.
Tương tự nếu bạn nhấn thêm một lần ⌃⇧Space nữa, hệ thống sẽ cho ra kết quả nhiều hơn.
Gợi Ý Các Tham Số Truyền Vào (Parameters)
Phím tắt:
– Mac: ⌘P – Windows/Linux:Ctrl+P
Dùng phím tắt này nếu bạn muốn xem tất cả các tham số truyền vào của một hàm hay một constructor.
Chuyển Đổi Hoa/Thường Một Dòng Code
Phím tắt:
– Mac: ⌘⇧U – Windows/Linux: Ctrl+Shift_U
Nếu bạn lỡ khai báo một hằng số hay một biến nào đó với toàn các ký tự thường như thế này.
Và mong muốn sửa thành in hoa hết như thế này.
Rất đơn giản, chỉ cần đưa trỏ chuột vào dòng muốn thay đổi in thường sang in hoa hoặc ngược lại rồi nhấn tổ hợp phím như trên kia. Xong.
Hoàn Thành Câu Lệnh
Phím tắt:
– Mac:⇧⌘⏎ – Windows/Linux:Ctrl+Shift+Enter
Khi bạn muốn hệ thống kết thúc một câu lệnh giúp bạn, chẳng hạn như hệ thống sẽ tự biết mà điền vào các dấu đóng ngoặc, dấu chấm phẩy,… thì dùng phím tắt này cho nhanh. Bạn hãy tự kiểm chứng nhé.
Sao Chép Một Dòng Code
Phím tắt:
– Mac: ⌘D – Windows/Linux: Ctrl+D
Mình chắc chắn là nhiều bạn sẽ thắc mắc, rằng bộ đôi thần thánh copy/paste cũng đủ dùng rồi, nhớ cái này mần chi? Vâng mình đồng ý, trước đây mình cũng nghĩ vậy, nhưng từ khi quen với tổ hợp phím này, mình như đã nghiện nó hơn là copy và paste truyền thống, vì nó giúp bạn chỉ cần một bước thôi là đã có thể sao chép một dòng lệnh rồi. Và nếu sẵn tiện bạn thử tô khối nhiều dòng lệnh rồi mới nhấn tổ hợp phím xem hiệu quả của nó nhé.
Xóa Một Dòng Code
Phím tắt:
– Mac: ⌘⌫ – Windows/Linux: Ctrl+Y
Thay vì nhấn liên tục phím delete để xóa hết một dòng code dài, bạn dùng chức năng này để xóa hết chỉ một lần nhấn nhé.
Di Chuyển Dòng Code Lên/Xuống
Phím tắt:
– Mac: ⇧⌘↑ hay ⇧⌘↓ – Windows/Linux: Ctrl+Shift+Up hay Ctrl+Shift+Down
Chức năng này giúp bạn di chuyển một dòng code lên/xuống, bạn nên hiểu là nó có hai tác dụng sau.
– Nếu có dòng trống ở trên hay dưới dòng mà con trỏ đang đứng, chức năng này giúp dòng code đang đứng dịch lên hay xuống để chiếm lấy dòng trống đó, y như là xóa luôn dòng trống vậy.
– Nếu có dòng code ở trên hay dưới dòng mà con trỏ đang đứng, chức năng này giúp đổi chỗ dòng code đang đứng với các dòng code đó.
Dùng Hiệu Quả Navigation Bar
Bạn nên biết rằng Navigation Bar cho bạn biết đường dẫn đến file dang mở. Như ở Android bài 3 cũng có nói đến.
Dựa vào Navigation Bar này, nếu bạn click vào một thư mục bất kỳ trên danh sách của nó, bạn sẽ thấy tất cả các thành phần con trong thư mục đó được bung ra, giúp bạn đi đến nơi cần đến một cách nhanh chóng.
Phím tắt để vào Navigation Bar:
– Mac: ⌘↑ – Windows/Linux: Alt+Home
Sử Dụng Distraction Free Mode
Có thể tạm dịch đây là Chế Độ Chống Phân Tâm. Khi bạn có nhu cầu cần chú tâm đến những dòng code của file hiện tại mà thôi, thì bạn hãy thử khởi động chế độ này, nó sẽ ẩn đi hết tất cả các cửa sổ và thành phần râu ria, chỉ chừa có mỗi code (và các menu của Android Studio) cho bạn dễ dàng làm việc.
Vào Distraction Free Mode
Từ menu của Android Studio, chọn View > Enter Distraction Free Mode.
Chế độ Distraction Free Mode sẽ điều chỉnh các cửa sổ code trông như sau.
Thoát khỏi Distraction Free Mode
Từ menu của Android Studio, chọn View > Exit Distraction Free Mode. Mọi thứ sẽ trở về như cũ.
Các bạn đều biết rằng, để có thể code được Java, nhất định cần phải xây dựng một môi trường lập trình cho nó. Với một môi trường lập trình như vậy, bạn sẽ có trong tay đầy đủ các công cụ cần thiết để có thể bắt tay vào xây dựng các dòng code cho riêng mình.
Vậy thì một môi trường lập trình cho Java sẽ phải cần đến những công cụ gì? Xây dựng chúng như thế nào? Chúng ta hãy cùng bắt tay vào tìm hiểu cách xây dựng từng công cụ nhé!
Cài Đặt JDK
Tương tự như phần hướng dẫn cài đặt JDK ở bên bài học Android, nếu bạn nào đã làm theo hướng dẫn đó rồi thì có thể bỏ qua phần này mà đến thẳng việc cài đặt InteliJ bên dưới, vì 2 phần hướng dẫn của 2 bài giống nhau.
Còn nếu chưa cài đặt JDK bao giờ thì bạn hãy vào trang của Oracle để download file cài đặt, bạn có thể vào bằng đường dẫn này đây (bạn cũng có thể search Google với từ khóa JDK Download). Sau khi mở link, bạn sẽ thấy danh sách các gói cài đặt như hình sau (hình ảnh có thể khác với máy của bạn ở thời điểm hiện tại do trang web này luôn được làm mới thường xuyên).
Ứng tuyển các vị trí việc làm Java lương cao trên TopDev
Nhiều gói JDK cho bạn cài đặt
Bạn hãy chọn gói theo hệ điều hành mà bạn đang dùng rồi down về thôi. Sau khi download JDK về thì bạn tiến hành cài đặt nhé.
Nếu bạn cài đặt JDK cho MacOS thì có thể bỏ qua mục này. Nhưng nếu bạn đang cài đặt JDK này trên nền Windows, bạn nên làm tiếp một bước tiếp theo này.
Nghe qua có vẻ xa lạ, nhưng nếu bạn nào đã từng quen thuộc với các dòng lệnh trên Command Line sẽ hiểu việc thiết lập Path & Java Home này là gì. Cơ bản thì việc thiết lập này sẽ giúp hệ điều hành Windows có thể thực thi được các dòng lệnh Java bên trong jdk/bin mà bạn mới cài đặt xong.
Do mình không dùng Windows nên các chỉ dẫn của mình có thể không rõ ràng, các bạn có thể dễ dàng tìm kiếm với từ khóa Path & Java Home Windows sẽ ra các chỉ dẫn rõ ràng hơn nhé. Hoặc bạn có thể để lại bình luận, hoặc chat với mình nếu gặp bất cứ vấn đề nào về việc thiết lập này nhé.
Trước hết bạn hãy vào đường dẫn này để download InteliJ về. Khi mở link lên bạn sẽ nhìn thấy trang download của InteliJ như sau (một lần nữa mình lưu ý là hình ảnh có thể khác với máy của bạn ở thời điểm hiện tại nhé).
Trang download của InteliJ
Khi này bạn hãy nhấn vào nút Download.
Sau khi đã vào trang download, bạn sẽ được lựa chọn các gói download phù hợp với hệ điều hành của bạn.
Các tùy chọn cài đặt InteliJ
Như hình trên bạn có thể thấy, ngoài lựa chọn theo hệ điều hành ra thì còn có thêm 2 phiên bản của InteliJ IDEA cho bạn chọn nữa, bao gồm Ultimate và Community. Như mình có nói ở bài học đầu tiên, chúng ta chỉ cần phiên bản Community miễn phí của InteliJ là đã có thể dùng để học được rồi. Vậy bạn hãy nhấn vào nút Download bên Community nhé.
Sau khi chờ đợi trong ít phút, gói cài đặt đã được down về. Bạn hãy tiến hành cài đặt.
Sau khi cài đặt xong, bạn hãy mở InteliJ lên để làm quen nào. Khi lần đầu tiên mở InteliJ lên bạn sẽ thấy một màn hình như thế này.
Màn hình đầu tiên khi khởi chạy InteliJ
Kết Luận
Xin chúc mừng, bạn đã cài đặt thành công InteliJ cũng như các công cụ cần thiết để phát triển ứng dụng Java rồi đấy.
Chúng ta kết chúc bài học ở đây, bạn có thể tiếp tục mày mò cách sử dụng công cụ InteliJ lúc này. Nhưng đừng lo lắng quá nếu bạn chưa biết cách sử dụng nó. Chúng ta sẽ từng bước tìm hiểu Java cũng như công cụ lập trình InteliJ mạnh mẽ ở những bài học tiếp theo.
Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh
Trong bài này, chúng ta sẽ cùng tìm hiểu về xác thực (authentication) và phân quyền (authorization) trong ứng dụng.
Xác thực (Authentication) là gì?
Theo định nghĩa của wikipedia, Xác thực/ Định danh (authentication) là một hành động nhằm thiết lập hoặc chứng thực một cái gì đó (hoặc một người nào đó) đáng tin cậy, có nghĩa là, những lời khai báo do người đó đưa ra hoặc về vật đó là sự thật.
Như đã biết, RESTful web service sử dụng HTTP protocol như một phương tiện giao tiếp và HTTP request là stateless protocol. Tức là server không lưu giữ bất kỳ thông tin nào của client, server xử lý các request một cách độc lập, không phụ thuộc vào trạng thái hay kết quả của request trước.
Như hình bên dưới, do server không lưu giữ bất kỳ thông tin nào của request trước. Nên mỗi request gửi lên server đều phải phải chứng thực lại, mặc dù là request của cùng một user đã được chứng thực.
Một trong những cách để giải quyết vấn đề này là mỗi request client gửi lên đều gửi kèm thông tin đã chứng thực trước đó.
Một số dấu hiện nhận biết quá trình chứng thực có thể được thực hiện hay không là: ở mỗi request, client sẽ gửi kèm thông tin chứng thực lên server như username/ password, một chuỗi chứa thông tin mã hóa (token, api key), một chuỗi random (session_id). Chúng thường được gửi kèm với trong HTTP request như: query string trong URL, Header (Cookie header, Authorization header, Custom header), Body (Form field, Hidden field,…)
Để có được dấu hiệu nhận dạng phía trên, ta cần có sự thống nhất trước giữa người dùng và ứng dụng để ứng dụng của chúng ta có thể nhận dạng được người dùng.
Về cơ bản thì một quá trình authentication sẽ gồm 2 bước:
Sinh ra dấu hiệu: đây là việc chúng ta quyết định xem dùng dấu hiệu gì, tạo ra dấu hiệu đó như thế nào. Một quá trình authentication có thể có sự xuất hiện của nhiều dấu hiệu, ví dụ username/password, user token, api key,… Các dấu hiệu này sẽ có cách sinh ra khác nhau, quy ước sử dụng khác nhau.
Lưu trữ dấu hiệu: Đây là việc ứng dụng sẽ quyết định lưu trữ dấu hiệu này ở đâu, ở cả server và client, thông qua vị trí nào trên HTTP request,…
Kiểm tra dấu hiệu: Đây là việc ứng dụng của chúng ta kiểm tra lại tính hợp lệ của dấu hiệu, đối chiếu xem dấu hiệu này có hợp lệ hay không và của người dùng nào,…
Phía trên ảnh là ví dụ quá trình authentication, trong đó mỗi request tùy thuộc vào thông tin đầu vào sẽ được xử lý qua 1 hoặc nhiều phần của quá trình authentication.
Cơ chế lưu giữ đăng nhập người dùng
Trong bài viết này, chúng ta sẽ cùng tìm hiểu chủ yếu tới 3 cơ chế lưu giữ đăng nhập người dùng cơ bản là:
Basic Authentication
Session-based Authentication
Token-based Authentication
Basic Authentication
Basic Auth là cơ chế xác thực đơn giản nhất của một ứng dụng web. Cách hoạt động của Basic Auth là gửi chính username + password của người dùng theo mỗi request.
Flow
Dấu hiệu: Chuỗi username:password đã được mã hóa Base64. Ví dụ có username là abc, password là 123 thì ta tạo chuỗi mã hóa: abc:123 –Base64–> YWJjOjEyMw==
Lưu trữ dấu hiệu:
Tại server: Máy chủ web sẽ lưu lại username, password trong database, file (htpasswd),…
Tại client: Sau khi hỏi người dùng nhập username và password lần đầu, browser sẽ lưu lại 2 giá trị này trong bộ nhớ được quản lý bởi mỗi trình duyệt (và chúng ta không thể tiếp cận bộ nhớ này bằng code trên trang) để tránh phải liên tục hỏi chúng ta username, password. Tuy nhiên thời gian lưu thường là có giới hạn.
Truyền tải: chuỗi đã mã hóa base64 phía trên sẽ được truyền trong HTTP request trong Authorization header với từ khóa Basic phía trước: Authorization: Basic YWJjOjEyMw==
Kiểm tra dấu hiệu: Với mỗi request gửi lên kèm thông tin username/password trên, server sẽ so sánh username/password với database, config file,… để kiểm tra tính hợp lệ.
Flow của Basic Auth:
Usecase
Ưu điểm:
Đơn giản, do đó được hầu hết các trình duyệt, webserver (nginx, apache,…) hỗ trợ. Bạn có thể dễ dàng config cho webserver sử dụng Basic Auth với 1 vài dòng config.
Dễ dàng kết hợp với các phương pháp khác. Do đã được xử lý mặc định trên trình duyệt và webserver thông qua truyền tải http header, các bạn có thể dễ dàng kết hợp phương pháp này với các phương pháp sử dụng cookie, session, token,…
Nhược điểm:
Username/password dễ bị lộ. Do mỗi request đều phải truyền username và password nên sẽ tăng khả năng bị lộ qua việc bắt request, log server,…
Không thể logout. Vì việc lưu username, password dưới trình duyệt được thực hiện tự động và không có sự can thiệp của chủ trang web. Do vậy không có cách nào logout được người dùng ngoại trừ việc tự xóa lịch sử duyệt web hoặc hết thời gian lưu của trình duyệt.
Không thân thiện với người dùng. Việc hiển thị hộp thoại đăng nhập cũng như thông báo lỗi của trình duyệt, như các bạn đã biết là vô cùng nhàm chán, không chứa đựng nhiều thông tin cho người dùng.
Vì những đặc điểm trên, Basic Auth thường được sử dụng trong các ứng dụng nội bộ, các thư mục cấm như hệ thống CMS, môi trường development, database admin,… lợi dụng việc chặt chẽ của kiểm tra Basic Auth trên các web server để tránh tiết lộ thông tin hệ thống nội bộ cho người ngoài, phòng chống hack, khai thác lỗ hổng ứng dụng,…
Session-based Authentication
Session-based authentication là cơ chế xác thực người dùng dựa trên việc tạo ra session của người dùng ở phía server. Sau quá trình xác thực người dùng thành công (username/password,…) thì phía server sẽ tạo và lưu ra một Session ID duy nhất để định danh. Session này chứa thông tin của người dùng đang đăng nhập và trả lại cho client session ID để truy cập session cho những request sau.
Phía client có thể lưu Session ID lại dưới dạng cookie và gửi kèm nó trong mọi request. Hệ thống sau đó sẽ dùng Session ID được gửi đi để xác định danh tính của user truy cập, để người dùng không cần phải nhập lại thông tin đăng nhập lần sau.
Khi Session ID được gửi lên, server sẽ xác định được danh tính của người dùng gắn với Session ID đó, đồng thời sẽ kiểm tra quyền của user xem có được truy cập tác vụ đó hay không. Giải pháp session và cookie vẫn có thể sử dụng, tuy nhiên ngày nay chúng ta có nhiều yêu cầu hơn, chẳng hạn như các ứng dụng Hybrid hoặc SPA (Single Page Application) có thể cần truy cập tới nhiều hệ thống backend khác nhau, vì vậy session và cookie lấy từ 1 server có thể không sử dụng được ở server khác.
Flow
Chúng ta hãy điểm qua các khía cạnh cơ bản của cơ chế này:
Dấu hiệu: 1 chuỗi (thường là random) unique gọi là Session ID
Lưu trữ dấu hiệu:
Tại server: Lưu dữ liệu của session trong database, file, ram,… và dùng Session ID để tìm kiếm.
Tại client: Lưu Session ID trong bộ nhớ cookie, hoặc URL trang web, form field ẩn,…
Truyền tải: Session ID sẽ xuất hiện trong các HTTP request tiếp theo trong Cookie (header Cookie: SESSION_ID=abc), URL (/profile?session_id=abc), body (form field ẩn),…
Kiểm tra dấu hiệu: Server dùng Session ID client truyền lên để tìm dữ liệu của session từ các nguồn lưu như database, file, ram,…
Quá trình set Session ID thường được thực hiện một cách tự động bởi server, cho nên session-based authentication thường sử dụng Cookie, vì cookie có thể set được từ phía server và được browser áp dụng tự động cho các request tiếp theo. Do đó cơ chế này thường đi liền với cookie. Tuy nhiên hãy nhớ là có nhiều cách để sử dụng được session ID mà không dùng cookie nữa nhé.
Flow của Session-based Authentication
Usecase
Ưu điểm:
Thông tin được giấu kín: Client chỉ được biết tới Session ID thường là 1 chuỗi random không mang thông tin gì của người dùng, còn mọi thông tin khác của phiên đăng nhập hay người dùng hiện tại đều được lưu phía server nên cơ chế này giữ kín được thông tin của người dùng trong quá trình truyền tải.
Dung lượng truyền tải nhỏ: Bởi vì tự thân Session ID không mang theo thông tin gì, thông thường chỉ là một chuỗi ký tự unique khoảng 20-50 ký tự, do vậy việc gắn Session ID vào mỗi request không làm tăng nhiều độ dài request, do đó việc truyền tải sẽ diễn ra dễ dàng hơn.
Không cần tác động client: Theo mình thì để sử dụng cơ chế session này bạn chủ yếu chỉ cần sửa phía server. Client mà cụ thể là browser hầu như không cần phải xử lý gì thêm bởi đã được tích hợp tự động (đối với cookie), hoặc response trả về của server đã có sẵn (đối với session ID ở URL hoặc hidden form)
Fully-controlled session: Tính chất này có thể cho phép hệ thống quản trị TẤT CẢ các hoạt động liên quan tới phiên đăng nhập của người dùng như thời gian login, force logout,…
Nhược điểm:
Chiếm nhiều bộ nhớ: Với mỗi phiên làm việc của user, server sẽ lại phải tạo ra một session và lưu vào bộ nhớ trên server. Số data này có thể còn lớn hơn cả user database của bạn do mỗi user có thể có vài session khác nhau. Do vậy việc tra cứu đối với các hệ thống lớn nhiều người dùng sẽ là vấn đề.
Khó scale: Vì tính chất stateful của việc lưu session data ở phía server, do đó bạn sẽ khó khăn hơn trong việc scale ngang ứng dụng, tức là nếu bạn chạy ứng dụng của bạn ở 10 máy chủ, hay 10 container, thì 1 là bạn phải dùng chung chỗ lưu session, 2 là nếu không dùng chung bộ nhớ session thì phải có giải pháp để ghi nhớ user đã kết nối tới server nào của bạn. Nếu không rất có thể chỉ cần ấn refresh thôi, user kết nối với server khác khi cân bằng tải là sẽ như chưa hề có cuộc login ngay.
Phụ thuộc domain: Vì thường sử dụng cookie, mà cookie lại phụ thuộc vào domain, do vậy khả năng sử dụng phiên đăng nhập của bạn sẽ bị giới hạn ở đúng domain được set cookie. Điều này không phù hợp với các hệ thống phân tán hoặc tích hợp vào ứng dụng bên thứ 3.
CSRF: Nói nôm na là Session ID thường được lưu vào Cookie, và cookie mới là thứ dễ bị tấn công kiểu này. Vì cookie được tự động gắn vào các request tới domain của bạn. Ví dụ:
User vừa login vào my-bank.com và được set cookie: session_id=123
User vào trang web taolahacker.com xem tut của mình
Trên taolahacker.com mình ngầm gửi 1 request ajax tới domain my-bank.com.
Vì browser tự động thêm cookie session_id=123 vào request ajax trên, do vậy request của mình có thể thao tác mọi thứ như User thật.
Vì những đặc điểm trên, Session-based Authentication thường được dùng trong các website và những ứng dụng web làm việc chủ yếu với browser, những hệ thống monolithic do cần sự tập trung trong việc lưu session data và sự hạn chế về domain.
Token-based Authentication
Token-based Authentication là cơ chế xác thực người dùng dựa trên việc tạo ra token – một chuỗi ký tự (thường được mã hóa) mang thông tin xác định người dùng được server tạo ra và lưu ở client. Server sau đó có thể không lưu lại token này.
Flow
Dấu hiệu: 1 chuỗi chứa thông tin người dùng (thường được mã hóa và signed) gọi là token
Lưu trữ dấu hiệu:
Tại server: Thường là không cần lưu.
Tại client: Ứng dụng client (javascript, mobile,…) phải tự lưu token trong các bộ nhớ ứng dụng, local storage, cookie,…
Truyền tải: Token sẽ xuất hiện trong các HTTP request tiếp theo trong Authorization header (Authorization: Bearer abc), Cookie (header Cookie: token=abc), URL (/profile?token=abc), body (ajax body, field),…
Kiểm tra dấu hiệu: Token thường có tính self-contained (như JWT), tức là có thể tự kiểm tra tính đúng đắn nhờ vào các thuật toán mã hóa và giải mã chỉ dựa vào thông tin trên token và 1 secret key nào đó của server. Do đó server không cần thiết phải lưu lại token, hay truy vấn thông tin user để xác nhận token.
JWT hay Json Web Token là một loại token được chấp nhận và sử dụng rộng rãi như một tiêu chuẩn của các nền tảng web hiện đại (RFC 7519) bởi nó thỏa mãn được tính chất self-contained, được hỗ trợ bởi nhiều ngôn ngữ và nền tảng và hơn hết là cấu trúc JSON đơn giản, nhỏ gọn hơn rất nhiều so với các loại token khác như Simple Web Tokens (SWT) and Security Assertion Markup Language Tokens (SAML). Chi tiết về JWT, chúng ta sẽ cùng tìm hiểu ở một bài viết khác.
Flow của Token-based Authentication:
Usecase
Ưu điểm:
Stateless: Bởi vì token thường có tính chất self-contained, do vậy server không cần lưu thêm thông tin gì về token hay map giữa token và người dùng. Do vậy đây là tính chất quan trọng nhất, phục vụ cho việc scale ứng dụng theo chiều ngang khi không cần quan tâm tới việc bạn sẽ sinh ra token ở đâu và verify token ở đâu.
Phù hợp với nhiều loại client: Nên nhớ, cookie là một concept được các browser áp dụng tự động, còn với các client sử dụng Web API như mobile, IoT device, server,… thì việc sử dụng cookie lại rất hạn chế. Sử dụng token trong header hay URL,… sẽ dễ dàng hơn cho client trong việc lưu lại token và truyền tải token.
Chống CSRF: Do việc sử dụng token phải được client xử lý từ việc lưu tới truyền tải, do vậy sử dụng token (mà không dùng cookie) sẽ phòng chống được các trường hợp tấn công như với trường hợp session/cookie.
Không bị giới hạn bởi domain: Đây là tính chất giúp các hệ thống hiện đại có sự tham gia của bên thứ 3 hoạt động dễ dàng hơn khi không bị giới hạn chỉ ở domain của hệ thống đăng nhập.
Nhược điểm:
Khó quản lý đăng xuất: Bởi vì server không lưu thông tin gì về token hay session của user, do đó điều khó kiểm soát nhất chính là việc đăng xuất. Và vì việc kiểm tra token chỉ dựa vào thông tin trên token, do vậy sẽ khó để ứng dụng của chúng ta vô hiệu hóa một token vẫn còn hiệu lực.
Phức tạp phần client: Cơ chế sử dụng token thường yêu cầu client phải có xử lý liên quan tới lưu token, gửi token, do vậy sẽ không phù hợp với những website kiểu cũ, sử dụng nhiều server render html và phần javascript hạn chế.
Thông tin dễ lộ: Khác với session, thông tin về phiên đăng nhập của người dùng có trên token và được lưu phía client, do vậy sẽ có các nguy cơ liên quan tới lộ thông tin trong token trong quá trình lưu trữ, truyền tải,… Chính vì vậy, thông thường người ta chỉ lưu 1 số thông tin thiết yếu như user_id, username mà không lưu những thông tin nhạy cảm như password vào token.
Dung lượng truyền tải lớn: Thường thì 1 token sẽ dài hơn session ID khá nhiều, mà token lại được gửi với mỗi request, do vậy độ dài request sẽ tăng lên, do đó băng thông truyền tải cũng sẽ cần phải tăng theo. Tuy nhiên, đây chỉ là một điểm hạn chế nhỏ so với những lợi ích nó mang lại.
Vì các đặc điểm trên, Token-based Authentication thường được sử dụng trong các hệ thống Web API, các hệ thống phân tán, micro-services, các hệ thống có sự tham gia của các nền tảng khác như mobile, IoT, server,…, hoặc các website kiểu mới (phân tách rõ UI app và API).
Bảng so sánh
Sau đây là bảng so sánh để các bạn dễ hình dung về 3 cơ chế đăng nhập này:
ĐẶC ĐIỂM
BASIC
SESSION-BASED
TOKEN-BASED
Dấu hiệu
username + password
Chuỗi random (Session ID)
Chuỗi mang thông tin được mã hóa
Truyền tải
Authorization Header
Header (cookie) / URL / Body (form)
Header (Auth, custom) / URL / Body
Lưu Server
Không lưu (vì chính là UserDB)
Có lưu Session Data (memory, database, file,…)
Không lưu (vì token chứa đủ thông tin rồi)
Lưu Client
Browser tự lưu (username + pass)
Cookie (Session ID)
Local storage, Cookie, session storage (browser)
Cách verify
So sánh với User trong database
Dùng Session ID để tìm data trong session storage
Kiểm tra tính toàn vẹn của token qua signature của token
Phù hợp cho
Hệ thống internal
Monolithic website
Web API của hệ thống phân tán, đa nền tảng,…
Phân quyền (Authorization) là gì?
Sau khi đã có định danh và giao thức dùng để giao tiếp, câu hỏi tiếp theo là cần trả lời câu hỏi đối tượng với định danh đó có quyền thực hiện 1 hành động, truy cập 1 tài nguyên nào đó hay không. Quá trình này gọi là phân quyền (Authorization). Authorization xảy ra sau khi hệ thống của bạn được Authentication (xác thực) thành công.
Xác thực (authentication) trả lời câu hỏi “bạn là ai?” và phân quyền (authorization) sẽ trả lời câu hỏi “bạn có thể làm được gì?” Hai câu hỏi này luôn là thành phần không thể thiếu của mọi hệ thống, nhưng mức độ áp dụng thì lại tùy thuộc vào từng giai đoạn. Nếu bạn làm mọi thứ chặt chẽ ngay từ đầu, nó có thể làm tăng độ phức tạp và làm chậm sự phát triển của công ty. Nhưng nếu bạn làm nó quá muộn, thì có thể bạn sẽ hứng chịu nguy cơ bị tấn công và rủi ro từ đó.
So sánh Authentication với Authorization
Authentication
Authorization
Authentication xác nhận danh tính của user để cấp quyền truy cập vào hệ thống.
Authorization xác định xem user có được phép truy cập tài nguyên không.
Đây là quá trình xác nhận thông tin đăng nhập để có quyền truy cập của người dùng.
Đó là quá trình xác minh xem có cho phép truy cập hay không.
Nó quyết định liệu người dùng có phải là những gì anh ta tuyên bố hay không.
Nó xác định những gì người dùng có thể và không thể truy cập.
Authentication thường yêu cầu tên người dùng và mật khẩu.
Các yếu tố xác thực cần thiết để authorization có thể khác nhau, tùy thuộc vào mức độ bảo mật.
Authentication là bước đầu tiên của authorization vì vậy luôn luôn đến trước.
Authorization được thực hiện sau khi authentication thành công.
Ví dụ, sinh viên của một trường đại học cụ thể được yêu cầu tự xác thực trước khi truy cập vào liên kết sinh viên của trang web chính thức của trường đại học. Điều này được gọi là authentication.
Ví dụ, authorization xác định chính xác thông tin nào sinh viên được phép truy cập trên trang web của trường đại học sau khi authentication thành công.
Bài viết được sự cho phép của tác giả Lại Đình Cường
Export và Import dữ liệu trong WordPress là 2 chức năng hữu ích nếu như bạn muốn di chuyển hoặc khôi phục dữ liệu. Nếu trang bạn bị virus, bạn có thể export dữ liệu. Sau đó xóa hết mọi thứ. Cuối cùng là bạn import dữ liệu lại. Chức năng này cũng áp dụng cho trường hợp bạn di chuyển hosting hoặc đổi tên miền,…
Không chỉ hỗ trợ import dữ liệu từ WordPress. Chức năng import còn cho phép bạn chuyển dữ liệu từ các mã nguồn khác sang WordPress, đặc biệt là Blogger.
Hướng dẫn Export và Import dữ liệu trong WordPress
Như mình đề cập đến lợi ích của công cụ import và export dữ liệu bên trên. Ở đây mình không nói thêm nữa mà đi vào vấn đề của bài viết luôn. Trong bài này có 2 phần đó là: Hướng dẫn export (xuất) dữ liệu cho WordPress và hướng dẫn import (nhập) dữ liệu cho WordPress.
Cả 2 cái này là chức năng của WordPress nha các bạn. Không phải là export và import cơ sở dữ liệu trong MySQL nhé.
Để export dữ liệu trong WordPress thì bạn vào Dashboard → Tools → Export. Nội dung trang export sẽ được hiển thị như hình ảnh mình gửi đầu bài. Bên trong này thì bạn có thể export toàn bộ dữ liệu hoặc từng thể loại.
Sau khi chọn xong thì bạn nhấn nút Download Export File. Tập tin dữ liệu được tải về máy tính dưới dạng là .xml nhé. Cái này bạn có thể áp dụng để backup dữ liệu theo khoảng thời gian cho blog WordPress.
Nếu như export là xuất dữ liệu dưới dạng tập tin .xml thì import là bạn nhập dữ liệu vào lại cho blog WordPress. Bạn vào Dashboard → Tools → Import. Một trang sẽ hiển thị lên như hình ảnh bên dưới:
Bên trong trang import này có rất nhiều chức năng. Ngoài chức năng nhập và chuyển đổi dữ liệu thì bạn còn có thể sử dụng để chuyển đổi qua lại giữa thẻ và chuyên mục. Ở đây mình hướng dẫn export và import dữ liệu trong WordPress nên bạn sẽ chọn WordPress Run Importer.
Một trang mới sẽ xuất hiện. Bạn chọn tập tin XML mà bạn đã export lúc trước. Sau khi chọn xong tập tin thì bạn nhấn nút Upload file and import. Màn hình Import WordPress hiển thị lên cho phép bạn gán nội dung bài viết cho tài khoản mới hoặc chọn tài khoản tác giả có sẵn. Mục tùy chọn Download and import file attachments là bạn dùng để chọn có nhập các tập tin đính kèm cùng bài viết hay không.
Cuối cùng là bạn nhấn nút Submit và chờ đợi quá trình import hoàn tất.
Kết luận
Qua bài viết Hướng dẫn Export và Import dữ liệu trong WordPress này bạn đã có thể xử lý dữ liệu cho WordPress một cách dễ dàng. Không chỉ áp dụng cho dữ liệu của WordPress. Trong chức năng Import còn cho phép bạn nhập dữ liệu từ nhiều nguồn khác.
Hy vọng bài viết sẽ giúp ích được bạn. Nếu thấy bài viết hữu ích thì hãy chia sẻ cùng mọi người nhé. Và đừng quên để lại bình luận để trao đổi dù bạn có cần sự trợ giúp hay không. Chúc bạn thành công.
Hệ điều hành Android là một trong những hệ điều hành lớn nhất trên thế giới với thị phần chiếm trên 70%. Với sự phổ biến của hệ điều hành này đã kéo theo nhu cầu tuyển dụng lập trình viên Android Developer tăng cao, trở thành một ngành vô cùng tiềm năng cho những ai muốn theo đuổi. Vậy Android Developer là gì? Làm thế nào để trở thành một Android Developer giỏi? Cùng TopDev tìm hiểu chi tiết về công việc này nhé!
Android Developer là gì?
Android là hệ điều hành được phát triển bởi ông lớn Google dành cho các thiết bị di động thông minh (điện thoại, tivi, máy tính bảng,…). Với đặc điểm là một nền tảng mã nguồn mở nên các nhà phát triển sẽ dễ dàng điều chỉnh, thiết kế các ứng dụng trong hệ điều hành.
Các Android Developer là những lập trình viên sử dụng các ngôn ngữ lập trình để xây dựng, thiết kế ứng dụng chạy trên hệ điều hành Android. Bên cạnh đó, họ còn là người chịu trách nhiệm duy trì, phát triển và cập nhật những tính năng mới cho phần mềm này.
Những nhà phát triển ứng dụng – Android Developer sẽ làm các công việc liên quan đến xây dựng, phát triển phần mềm chạy trên hệ điều hành Android. Cụ thể:
Nghiên cứu yêu cầu của dự án, nhu cầu của người dùng.
Xây dựng khái quát các tính năng trên ứng dụng đó.
Xử lý nguồn dữ liệu bên ngoài và lập trình API hỗ trợ cho các thiết bị tương thích.
Thiết kế giao diện, tối ưu trải nghiệm cho người dùng.
Chạy test phần mềm để phát hiện và sửa các lỗi.
Xuất bản ứng dụng dưới dạng APK trên Google Play.
Nâng cấp và cập nhật các tính năng mới cho ứng dụng qua các bản cập nhật.
Để trở thành một lập trình viên Android bạn có thể học nhiều ngôn ngữ lập trình. Tuy nhiên, việc lựa chọn một ngôn ngữ lập trình chính và hiểu sâu về nó sẽ tốt hơn là việc học tất cả các ngôn ngữ mà không giỏi ngôn ngữ nào. Dưới đây là một số ngôn ngữ lập trình bạn có thể học nếu muốn trở thành Android Developer:
Kotlin: Đây là ngôn ngữ lập trình đa nền tảng do chính Google phát triển nên sẽ được ưu tiên hỗ trợ hàng đầu.
Java: Đây là ngôn ngữ lập trình được các lập trình viên Android sử dụng nhiều nhất. Việc thông thạo nó sẽ giúp bạn hoàn thành tốt công việc, hiệu quả và nhanh chóng.
C++: Ngôn ngữ này sẽ tương thích với phần cứng giúp tiết kiệm tài nguyên phần cứng hơn, nâng cao hiệu suất và tốc độ chạy của chương trình.
Python: Các bước lập trình Python khá đơn giản và bạn không cần phải cài thêm quá nhiều công cụ. Các lập trình viên có thể chạy thử ứng dụng trên thiết bị Android dễ dàng.
Android SDK và Android Studio IDE: Android SDK cung cấp các công cụ để tạo và quản lý tài nguyên, các trình biên dịch và trình giả lập để kiểm tra ứng dụng trước khi triển khai trên thiết bị Android. Bên cạnh đó, Android Studio sẽ cung cấp một giao diện đồ họa và các công cụ để tạo và quản lý các dự án Android, xây dựng giao diện người dùng, lập trình phần mềm, và triển khai ứng dụng trên các thiết bị Android.
Nên học lập trình Web hay lập trình Mobie?
Web Developer và Mobile Developer là hai vai trò khác nhau trong lĩnh vực phát triển phần mềm. Tuy nhiên, với những bạn lập trình viên mới ra trường thì việc tìm hiểu và lựa chọn học nào gặp phải nhiều khó khăn.
Dưới đây là một vài phân tích giúp bạn đưa ra quyết định chính xác khi phân vân giữa 2 công việc này.
Lập trình Web
Lập trình Mobile
Tính chất
Có 3 hướng đi cho sự nghiệp:
Lập trình Frontend
Lập trình Backend
Lập trình FullStack
Có 3 nhóm chính:
Ứng dụng Native
Ứng dụng HTML5
Ứng dụng Hybrid
Ngôn ngữ lập trình
JavaScript, Java, Python, Ruby, PHP,…
Java, Swift, Kotlin,…
Tính linh hoạt
Tính linh hoạt cao, khi bạn thành thạo một ngôn ngữ, bạn có thể sử dụng trong nhiều mục đích công việc khác nhau.
Mobile Developer mang tính đặc thù hơn, bạn sẽ phải sử dụng nhiều ngôn ngữ và công cụ để phát triển app trên các nền tảng khác nhau.
Cơ hội nghề nghiệp và mức lương
Cơ hội nghề nghiệp hấp dẫn với đa dạng vị trí tuyển dụng. Mức lương cũng vô cùng hấp dẫn, dao động từ 10 – 25 triệu đồng/tháng.
Thiết bị di động ngày càng nhiều kéo theo nhu cầu tuyển dụng tăng cao. Kèm theo đó mức lương của Mobile Developer cũng cao hơn Web Developer vì sự phức tạp trong việc phát triển ứng dụng.
Kỹ năng và tố chất cần thiết để trở thành Android Developer
Để trở thành một lập trình viên Android giỏi bạn phải thành thạo một số kỹ năng dưới đây:
Kỹ năng sử dụng ngôn ngữ lập trình: Việc hiểu và thành thạo các ngôn ngữ lập trình (Java, C, C++,…) là điều tất yếu giúp cho bạn làm việc hiệu quả.
Thành thạo Android Studio: Bạn cần có kiến thức về cách sử dụng các công cụ và thư viện của Android để thao tác nhanh chóng và hiệu quả hơn.
Kỹ năng làm việc nhóm: Hợp tác với các thành viên trong team sẽ giúp xây dựng và phát triển ý tưởng tốt hơn.
Kỹ năng phân tích và giải quyết vấn đề: Các vấn đề xảy ra trong quá trình chạy phần mềm là khó tránh khỏi, bạn cần nhạy bén với vấn đề và đưa ra các giải pháp phù hợp để giải quyết nó.
Liên tục cập nhật các kiến thức mới: Các lập trình viên nên update thường xuyên những kiến thức mới trên các trang blog, medium, trên youtube, google,… phát triển phần mềm tốt hơn.
Cơ hội nghề nghiệp và mức lương của Android Developer
Việc phát triển mạnh mẽ của các thiết bị công nghệ cùng nhu cầu giải trí và sử dụng ứng dụng thông minh từ người dùng ngày càng cao, điều này làm tăng nhu cầu tuyển dụng Android Developer. Cơ hội tìm việc làm lập trình Android tại các công ty công nghệ ngày càng rộng mở với mức thu nhập cực hấp dẫn.
Mức lương của vị trí Android Developer khá tốt, dao động khoảng 10 – 12 triệu đồng/tháng với những người từ 1 – 2 năm kinh nghiệm. Lập trình viên làm việc lâu năm mức lương có thể lên đến 30 triệu đồng/tháng. Cần lưu ý, mức lương này có thể thay đổi tùy thuộc vào nhiều yếu tố như kinh nghiệm, công ty, vị trí làm việc,…
Qua bài viết này, mong rằng bạn đã có cái nhìn tổng quan về nghề Android Developer, cũng như có thêm định hướng cho việc chọn ngành trong tương lai. Cơ hội việc làm lập trình Android đang rộng mở tại TopDev, truy cập ngay để biết thêm thông tin về yêu cầu và mức lương bạn nhé!
Với sự phát triển nhanh chóng của công nghệ và Internet đã giúp các thiết bị di động trở thành một phần không thể thiếu trong cuộc sống con người. Điều này tạo ra một cơ hội tuyệt vời cho những Mobile App Developer, họ là những nhà phát triển ứng dụng tên các chiếc smartphone bạn đang sử dụng. Đây là một công việc đầy tiềm năng và rất đáng để các bạn trẻ theo đuổi. Cùng TopDev tìm hiểu một vài thông tin hữu ích về vị trí Mobile App Developer này nhé!
Mobile App Developer là gì?
Mobile App Developer (hay còn gọi là nhà phát triển ứng dụng di động) là người thiết kế, phát triển và triển khai các ứng dụng trên các thiết bị di động như điện thoại thông minh, máy tính bảng và các thiết bị đeo tay. Các ứng dụng di động có thể được phát triển cho các nền tảng khác nhau như iOS (Apple), Android (Google), Windows Phone (Microsoft) hoặc những nền tảng di động khác.
Bên cạnh đó, các Mobile App Developer sẽ không ngừng nâng cấp và cải tiến ứng dụng để mang lại nhiều tính năng mới, nâng cao trải nghiệm người dùng. Có thể thấy, các lập trình viên Mobile không chỉ đơn giản ngồi code, mà họ tham gia vào tất cả các giai đoạn của việc phát triển sản phẩm.
Mobile App Developer có thể chia làm hai loại chính là iOS Developer và Android Developer:
iOS Developer là những người chịu trách nhiệm xây dựng, phát triển, cập nhật các ứng dụng cho các thiết bị chạy hệ điều hành iOS. Các iOS Developer sẽ viết code bằng ngôn ngữ lập trình Swift hoặc Objective-C để phát triển ứng dụng.
Android Developer sẽ đảm nhiệm việc phát triển ứng dụng cho các thiết bị chạy hệ điều hành Android. Để viết được các ứng dụng này bạn cần có kiến thức cơ bản về Java, điều này sẽ giúp ích cho chặng đường sự nghiệp của bạn.
Một Mobile App Developer thực thụ sẽ làm các công việc liên quan đến việc lên kế hoạch, xây dựng ý tưởng và phát triển ứng dụng. Cụ thể, họ phải thực hiện những công việc sau:
Tìm hiểu và phân tích nhu cầu của người dùng.
Đề xuất và đưa ra ý tưởng về sản phẩm, dịch vụ ứng dụng di động.
Viết code lập trình và xây dựng khung tính năng nền tảng cho phần mềm.
Chạy thử và đánh giá chất lượng ứng dụng trên các phần mềm giả lập.
Lên kế hoạch, ý tưởng bổ sung để sửa đổi và nâng cấp ứng dụng theo những tiêu chuẩn chất lượng của hệ điều hành iOS hay Android.
Cần có những kỹ năng gì khi làm Mobile App Developer?
Với nhu cầu sử dụng các thiết bị di động thông minh trong việc học tập, làm việc, giải trí,… đã đưa nghề Mobile App Developer thành một vị trí có mức lương vô cùng hấp dẫn. Tuy nhiên, để thành công trong công việc này bên cạnh việc thành thạo các ngôn ngữ lập trình bạn cần trau dồi thêm nhiều kỹ năng liên quan. Dưới đây là một số kỹ năng cần có của một Mobile App Developer.
Kỹ năng chuyên môn
Kỹ năng thiết kế giao diện người dùng: Xây dựng giao diện người dùng (UI) trực quan, dễ sử dụng, thu hút và mượt mà là nhiệm vụ của Mobile App Developer. Lập trình viên cần nắm được các quy tắc thiết kế để sáng tạo ra những ứng dụng có điểm riêng nhưng vẫn người dùng vẫn dễ dàng sử dụng.
Kỹ năng phát triển đa nền tảng: Một lập trình viên Mobile cần có nhiều kiến thức về các nền tảng di động khác nhau như Android, iOS, Windows Phone. Điều này sẽ giúp bạn có cơ hội tiến xa hơn trên con đường sự nghiệp.
Kỹ năng lập trình các ngôn ngữ mới: Bạn cần có kỹ năng sử dụng thành thạo các ngôn ngữ lập trình thông dụng như Java, C++. Hiểu biết các ngôn ngữ lập trình như CSS, HTML, có khả năng thực hiện bộ di động đa nền tảng như AMP và Anten.
Biết cách phát hành ứng dụng lên store:Mỗi cửa hàng ứng dụng sẽ có chính sách, quy trình deploy ứng dụng khác nhau. Các Mobile App Developer cần nắm được cách upload ứng dụng, setup các nội dung trên ứng dụng,…
Kỹ năng mềm
Kỹ năng giao tiếp: Kỹ năng này sẽ giúp bạn làm việc nhóm hiệu quả hơn, bởi việc phát triển một phần mềm cần sự cộng tác của cả một tập thể.
Kỹ năng giải quyết vấn đề:Các sự cố xảy ra liên quan đến ứng dụng di động cần đều cần lập trình viên phát hiện và giải quyết kịp thời. Do đó, bạn cần có kỹ năng này để tìm ra lỗi và chỉnh sửa để ứng dụng hoạt động ổn định nhất.
Kỹ năng sáng tạo:Một Mobile App Developer nên có kỹ năng này để tạo được sự mới mẻ, giúp người dùng cảm thấy hứng thú khi sử dụng ứng dụng.
Để trở thành một lập trình viên Mobile, bạn có thể học các ngôn ngữ lập trình dưới đây:
Dart (Flutter)
Flutter là một Framework được phát triển bởi Google và Dart, bạn có thể sử dụng để viết code khá đơn giản. Đây là ngôn ngữ lập trình đa nền tảng 1 code – base build cho các hệ điều hành trên điện thoại, tuy nhiên có thể sẽ khó tiếp cận với người mới.
JavaScript/Typescript (React Native)
Đây là 2 ngôn ngữ lập trình sử dụng cho Framework React Native đa nền tảng. Người mới có thể sử dụng JavaScript, người nhiều kinh nghiệm hơn thì dùng Typescript.
Kotlin/Java (Android)
Kotlin và Java là một native-apps dành riêng cho Android nên việc sử dụng sẽ đơn giản và linh hoạt hơn.
Swift (iOS)
Đây là ngôn ngữ lập trình dành cho các lập trình viên iOS với ưu điểm tương đối clean, dễ dùng và có thể tái sử dụng dễ dàng. Tuy nhiên, các Mobile App Developer phải đầu tư thiết bị của Apple để thực hiện ngôn ngữ lập trình này.
Mức lương của lập trình viên Mobile
Với sự phát triển mạnh mẽ của các thiết bị di động kéo theo nhu cầu tuyển dụng lập trình viên Mobile App Developer tăng cao. Vì vậy, mức lương của lập trình viên Mobile khá tốt, dao động từ 8-12 triệu đồng/tháng với những người mới ra trường. Còn với các lập trình viên trên 2 năm kinh nghiệm mức lương có thể trên 20 triệu đồng.
Có thể thấy, thị trường nhân sự ngành IT đang rất khát nhân lực nên việc lựa chọn theo nghề Mobile App Developer sẽ giúp bạn kiếm được nhiều thu nhập trong tương lai.
Hy vọng rằng, qua bài viết này bạn đã hiểu hơn về công việc và những yêu cầu cần có của một Mobile App Developer. Bạn có thể truy cập TopDev để tìm các công việc liên quan đến lập trình Mobile với mức lương và nhiều chính sách đãi ngộ hấp dẫn.
Xin chào các bạn. Bạn đang ở đây và đang đọc các dòng mở đầu cho các bài viết về lập trình Android của mình, chứng tỏ bạn đang quan tâm đến lĩnh vực lập trình cho các thiết bị Android này. Dù cho bạn có đang là một người mới muốn làm quen và thử sức với lập trình Android, hay bạn là người đã có kinh nghiệm nhất định về Android và đang muốn tham khảo thêm các thông tin và ý kiến từ những lập trình viên khác, thì việc bạn chú ý đến các bài viết này, theo mình nghĩ, đều là các quyết định sáng suốt.
Với chuỗi bài viết về lập trình Android này, mình sẽ cố gắng mang đến cho các bạn các thông tin cơ bản và cơ sở nhất, cùng những xây dựng từng bước, giúp các bạn mới làm quen với Android có thể dễ dàng tiếp cận và thực hiện mong ước xây dựng một ứng dụng Android hoàn chỉnh của các bạn. Đồng thời mình sẽ tìm hiểu các bài viết từ các nguồn khác để nói rộng hơn một chút về Android cho các bạn đã hiểu về lĩnh vực này có cơ hội cùng chia sẻ kiến thức.
Tuy cố gắng trong việc xây dựng một bộ kiến thức ổn về Android là vậy, nhưng thực sự với tốc độ phát triển và sự nâng cấp nhiệt tình từ chính Google dành cho hệ điều hành của họ, cũng khiến mình nhiều phen “hụt hơi”, “chới với” (trong việc viết và cập nhật trên blog). Do đó nếu bạn có đang đọc các bài viết trong chuỗi bài này của mình mà thấy kiến thức đã cũ, thì vui lòng giúp mình để lại comment ở mỗi bài viết, đồng thời cũng hãy chủ động tìm kiếm thông tin mới mẻ hơn từ các trang web khác hoặc trang “chính chủ” Google nhé, dĩ nhiên mình luôn để link đến trang web gốc ở các mục liên quan rồi.
Hãy bắt đầu nào. Trước tiên, để có thể yêu thích lập trình Android, thì mình mời bạn tìm hiểu về Android trước.
Vâng, Android là một hệ điều hành, và hệ điều hành này là một hệ điều hành mã nguồn mở.
Biểu tượng hình chú robot của hệ điều hành Android
Ban đầu hệ điều hành này được xây dựng hướng đến việc sử dụng trên các điện thoại di động thông minh, sau này nó tiếp tục được phát triển để sử dụng rộng rãi trên các máy tính bảng, TV, thiết bị đeo được, xe hơi,…
Liệt kê ra như vậy để bạn thấy rằng, tiếp cận vào lập trình Android không chỉ gói gọn trong một lĩnh vực là viết ứng dụng cho các điện thoại thông minh, mà bạn còn có cơ hội mở rộng hơn kiến thức bản thân cho các nền tảng khác, như TV chẳng hạn. Hơn nữa với việc đây là hệ điều hành mã nguồn mở, bạn có thể còn phát triển được các ứng dụng chạy trên rất nhiều thiết bị phần cứng của nhiều hãng sản xuất khác nhau. Về cơ bản tất cả các hệ điều hành liên quan này đều dựa trên nền tảng Android, nhưng mỗi nhà sản xuất lại đưa vào những cập nhật riêng, mang đến các diện mạo khác nhau đôi chút hoặc rất nhiều tùy từng nhà sản xuất (sự đa dạng này vừa là lợi thế nhưng cũng gây ra các vấn đề tương thích khá hóc búa cho các lập trình viên chúng ta, nhưng không sao, hãy cùng nhau trải nghiệm thôi).
Sau khi nhìn “sơ” qua Android là gì, chúng ta đến một bước lựa chọn nữa khi tìm hiểu sâu hơn về Android dưới con mắt của một lập trình viên.
Dễ Tiếp Cận
Có thể nói trở thành một lập trình Android là một quyết định khá dễ dàng, chỉ cần bạn thích và… bùm, bắt tay vào thôi.
Có được điều này thứ nhất phải kể đến Trang thiết bị. Chắc chắn để lập trình thì bạn phải trang bị máy tính rồi, nhưng máy tính nào thì lập trình được Android? Thì có thể nói là, hầu như bạn chẳng cần quá bận tâm về nó.
Dù máy tính bạn có chạy được Windows, Mac, Linux hay thậm chí Chrome OS, bạn đều thoải mái bắt đầu với Android. Còn về một điện thoại di động thông minh để kiểm thử ứng dụng ư? Điều đó cũng không quá khó khi mà các điện thoại Android trên thị trường hiện nay đa số đều có giá khá “mềm”, bạn rất dễ để tìm mua một chiếc nếu chưa có thiết bị này trong tay.
Thêm nữa, các lập trình viên Android được Google trang bị cho một công cụ lập trình có tên Android Studio, bạn sẽ được làm quen công cụ này sau. Công cụ lập trình này phải nói là khá mạnh mẽ, và như mình nói ở trên, tương thích được với nhiều loại hệ điều hành, khiến chúng ta vừa dễ cài đặt, dễ tiếp cận, lại yên tâm code vì rõ ràng ở những bước đầu tiên này chúng ta đã cảm nhận được sự trang bị đầy đủ từ Google như nào rồi ha.
Nhìn giao diện hiện đại này của Android Studio bạn có thấy kích thích không?
Điều tiếp theo dẫn đến lập trình Android trở nên dễ tiếp cận, đó là Ngôn ngữ lập trình. Nếu bạn đã biết Java, điều đó thật tuyệt, bạn sẽ chỉ cần học thêm về cách thức tương tác với hệ điều hành thông qua Java. Nhưng nếu như bạn chưa từng biết đến Java, thì việc học Java cũng không quá khó khăn, đặc biệt nếu bạn đã từng biết đến một ngôn ngữ lập trình Hướng đối tượng nào khác như C++ hay C# (bạn có thể tìm hiểu về Java qua các bài viết của mình ở đây). Hoặc một lựa chọn tuyệt vời hơn, đó là bạn tìm hiểu luôn Kotlin, một ngôn ngữ khá hiện đại và mạnh mẽ. Tóm lại nếu bạn biết Java hay Kotlin đều có thể bắt tay vào lập trình Android ngay được rồi.
Biết Java hay Kotlin đều có thể lập trình Android
Tính Tương Thích
Mục này cũng có thể hiểu với nhiều ý.
Thứ nhất, có thể thấy sự tương thích nằm ở Hệ điều hành. Android là một hệ điều hành mở, lại là một hệ điều hành nổi tiếng số một trên thế giới hiện nay. Việc Android được ứng dụng trên nhiều lĩnh vực khác nhau mang đến cho bạn có cơ hội suy nghĩ đến việc phát triển một ứng dụng trên thiết bị điện thoại thông minh, lại có thể nhanh chóng mở rộng ra để chạy trên các thể loại thiết bị khác, như TV hay các thiết bị giải trí khác.
Sự tương thích cũng nằm ở Ngôn ngữ lập trình cho hệ điều hành này. Không cần phải nói đến việc ngôn ngữ Java được sử dụng rộng rãi cho các lĩnh vực khác nhau như thế nào vì ai cũng biết, điều này cho thấy nếu bạn từng lập trình Android bằng Java, bạn cũng có thể nhanh chóng ứng dụng logic hay nền tảng của ứng dụng này cho các lĩnh vực khác cũng dùng ngôn ngữ Java. Hay nếu bạn biết Kotlin, bạn cũng dễ dàng phát triển ra các ứng dụng cho iOS hay các ứng dụng Web khác cũng bằng ngôn ngữ Kotlin này.
Ứng Dụng Của Bạn Được Đưa Lên Google Play
Chắc hẳn bạn cũng biết cái “chợ” cho các ứng dụng Android này. Nó được gọi là Google Play, hay Google Play store. Không cần phải là một lập trình viên, bạn vẫn thường xuyên sử dụng nó, và bạn cũng nhận ra rằng Google Play là một nơi chứa vô số các ứng dụng khác nhau.
Giao diện Google Play quen thuộc
Đúng vậy, mình đã từng nghe Google Play đã cán mốc 2,6 triệu ứng dụng được đưa lên đây. Và bạn hãy tưởng tượng mà xem, trong số 2,6 triệu ứng dụng này, cũng có vài ứng dụng của bạn trên đó thì sao. Khi đó, có khi có đến hàng trăm, hoặc hàng ngàn, hoặc hơn nữa, người dùng trên khắp thế giới đang sử dụng ứng dụng của bạn hàng ngày thì sao. Nghĩ thôi đã thấy thích rồi.
Ngoài việc dễ dàng tải ứng dụng xuống, thì việc đưa ứng dụng lên Google Play cũng khá dễ dàng. Bạn chỉ cần bỏ ra $25 cho một lần duy nhất trong đời để mua tài khoản trên đây, rồi sau đó thoải mái phát triển các ứng dụng của riêng bạn và xuất bản.
Thêm nữa, bên cạnh có nhiều người dùng trên thế giới biết đến và sử dụng ứng dụng của bạn, bạn còn có khả năng kiếm thêm tiền nhờ vào việc tận dụng hiển thị quảng cáo trong ứng dụng, hoặc xây dựng các chức năng có trả phí, hoặc xây dựng các ứng dụng cần người dùng phải mua mới dùng được. Thật tuyệt đúng không nào.
Chưa hết, khi bạn đã quyết định đưa ứng dụng lên Google Play thì chỉ mất vài giờ để ứng dụng của bạn đến với người dùng trên toàn thế giới (con số này so với Apple App Store là vài ngày, thậm chí có khi đến cả tuần). Việc đưa các bản cập nhật hay sửa lỗi lên Google Play chính vì vậy cũng khá là nhanh chóng và dễ thở hơn nhiều.
Môi Trường Phát Triển Phần Mềm
Chúng ta đã hiểu về Android qua tìm hiểu các ý trên đây rồi. Nhưng bài hôm nay sẽ không dừng lại sớm vậy, hãy cùng xem thêm chút nữa về cái gọi là Môi trường phát triển phần mềm là gì nhé.
Môi trường phát triển phẩm mềm là một môi trường mà ở đó nhà Phát Triển Phần Mềm có được những công cụ cần thiết nhất để viết ra một ứng dụng hoàn chỉnh. Vì bài học liên quan đến Android, do đó chúng ta sẽ tập trung vào tìm hiểu Môi trường phát triển phần mềm Android (Android Development Environment) sẽ bao gồm những công cụ cần thiết gì tiếp theo đây.
Hệ Điều Hành (Operating System)
Như mình có nói trên kia, ứng dụng Android có thể được lập trình trên hầu hết các nền tảng hệ điều hành phổ biến nhất hiện nay như Windows, Mac, Linux hay thậm chí Chrome OS.
Dù bạn có đang dùng hệ điều hành nào thì cũng đừng quá lo lắng
Java Development Kit (JDK)
Bộ Công Cụ Phát Triển Cho Java, chắc chắn rồi, vì ứng dụng Android được viết dựa trên ngôn ngữ Java mà, do đó chúng ta cần phải có bộ JDK này để các công cụ khác có thể dùng nó để biên dịch ra mã Java, rồi từ Java sẽ biên dịch tiếp thành các mã máy. Ngay cả như nếu bạn dùng Kotlin để lập trình Android, thì bạn vẫn cần đến bộ JDK này, vì Kotlin vẫn tận dụng máy ảo JVM bên trong JDK mà thôi.
JDK
Android Software Development Kit (Android SDK)
Tương tự như JDK, Android SDK là Bộ Công Cụ Phát Triển Cho Android. SDK này sẽ cung cấp cho chúng ta một bộ các thư viện và công cụ cần thiết để chúng ta có thể build, kiểm tra và debug cho các ứng dụng Android mà chúng ta sắp lập trình đây.
Android SDK
Android Studio
Cuối cùng chúng ta phải cần công cụ này, như đã nói ở trên, đây là công cụ mà chúng ta sẽ tương tác trực tiếp và dài lâu. Android Studio cung cấp cho chúng ta một giao diện trực quan để chúng ta có thể viết code, chỉnh sửa, biên dịch, debug, quản lý bộ nhớ,… tất cả mọi thứ cần thiết để chúng ta có thể tạo nên một phần mềm trên đó.
Android Studio
Kết Luận
Chúng ta vừa có cái nhìn sơ lược nhất về việc xây dựng ứng dụng trên hệ điều hành Android này. Hi vọng các thông tin căn bản này giúp tạo cho bạn một kiến thức và một động lực nhất định để xây dựng ước mơ lập trình trên nền tảng di động của chính bạn.
Unity là một công cụ phát triển game đa nền tảng được phát triển bởi Unity Technologies từ những năm 2005, hiện nay nó đã dần trở thành một game engine phổ biến nhất trên thế giới. Unity Developer – lập trình viên Unity đang là 1 lựa chọn tiềm năng của các bạn có đam mê với game và muốn sử dụng kĩ năng lập trình của mình để tạo ra được những ứng dụng game sáng tạo và hấp dẫn. Bài viết hôm nay mình sẽ cùng các bạn tìm hiểu sâu hơn về ngành nghề này, và cần học những gì để có thể trở thành 1 lập trình viên Unity nhé.
Unity Engine là gì?
Unity Engine là 1 cross-flatform game engine sử dụng để phát triển game trên nền tảng PC, consoles, websites và các thiết bị di động.
Hầu hết các nền tảng chơi game phổ biến hiện nay đều được Unity hỗ trợ, bao gồm: mobile (Android, iOS, WindowPhone), PC (Window, MacOS), Consoles (Nintendo, PlayStation), Browsers (sử dụng WebGL), … Không chỉ vậy, Unity cũng sẵn có các tính năng công nghệ thực tế ảo VR hay thực tế tăng cường AR có thể chạy tốt trên các thiết bị như Google Cardboard, GearVR, Hololens, Oculus, …
Về mặt đồ họa, Unity hỗ trợ cả 2D và 3D, có thể sử dụng các đồ họa APIs phổ biến như Direct3D, OpenGL, WebGL, … Unity cung cấp cho các lập trình viên những công cụ dựng hình, kết xuất đồ họa, xử lý về cả âm thanh, hình ảnh, đồng thời có sẵn công cụ vật lý (tính toán và phát hiện va chạm).
Unity Developer là những lập trình viên sử dụng nền tảng Unity để phát triển, xây dựng những dự án game theo yêu cầu của khách hàng. Những dự án Unity phổ biến như: trò chơi (game), phim ảnh, hoạt hình, ô tô, kiến trúc, quảng cáo, xây dựng, …
Cũng giống như các lập trình viên ở mảng khác, công việc của 1 Unity Developer bao gồm việc viết code để thực hiện chương trình với ngôn ngữ mà game engine này sử dụng phổ biến là C# – ngôn ngữ kịch bản hướng đối tượng. Tuy nhiên, Unity Developer không chỉ viết code, làm game sẽ có những công việc đặc thù khác với lập trình khác như dưới đây:
Lên ý tưởng và triển khai gameplay trong môi trường phát triển:
Đây là yêu cầu bắt buộc mà Unity Developer cần phải nắm được. Không như các ứng dụng thì game có những logic, kịch bản, gameplay hoạt động độc lập theo logic nhất định là thường xuyên suốt quá trình chơi; vì thế lập trình viên cần nắm được các logic này, đồng thời còn phát huy sự sáng tạo trong quá trình phát triển để tạo ra sản phẩm thu hút được người dùng cuối.
Unity cung cấp cho chúng ta Unity Editor và bạn phải làm việc chính trên công cụ này. Nó giúp bạn tạo ra các Scenes (màn chơi), import và sử dụng các assets (2D, 3D resources, sound, animation, …), tạo ra các đối tượng (GameObject), gắn kịch bản (Scripts) cho đối tượng, … Có thể nói tất cả các công việc của bạn đều thực hiện cùng Unity Editor, vì vậy việc học và sử dụng nó là điều tất yếu mà bạn cần phải làm để tạo ra game của mình.
Làm việc với Unity Asset Store:
Đây là 1 nơi cung cấp cho bạn vô số các resources hữu ích mà có thể sử dụng trong dự án. Bạn có thể tìm được từ các mô hình (model) nhân vật, các hiệu ứng chuyển động (animation) hay cả những đoạn code (script) có sẵn và chính thống đến từ Unity và các nhà phát triển khác phát hành. Ngoài ra, bạn cũng cần tài khoản Unity ID cho việc phát hành game, đồng thời có thể tích hợp các tính năng như quảng cáo, kiếm tiền, phân tích số liệu thông qua các service mà Unity cung cấp.
Phát hành, quảng cáo game:
Đối với game, việc thu hút được số lượng người chơi ngay từ ban đầu lúc phát hành là điều vô cùng quan trọng quyết định đến thành công của sản phẩm. Lập trình viên làm game nói chung hay Unity nói riêng để hỗ trợ phát hành game cũng tham gia tích cực vào giai đoạn này với việc kiểm thử (chơi thử), phát hành các bản demo, dùng thử, tạo các quảng cáo cho game nhằm thu hút người dùng,…
Trước hết nếu muốn làm Unity, theo mình thì các bạn cần có 1 sự đam mê nhất định về game và thích chơi game. Mặc dù Unity có thể làm nhiều thứ khác ngoài game, tuy vậy logic và tư duy lập trình Unity khá là khác so với việc làm Web, làm ứng dụng đơn thuần. Đam mê chơi và tạo ra game bằng chính những dòng code của mình lúc nào cũng tạo ra động lực lớn hơn đúng không nào.
Để lập trình thì bước đầu tiên luôn là học ngôn ngữ lập trình cùng các kiến thức cơ bản, với Unity thì bạn cần học C#, từ cách khai báo biến, cách viết các câu lệnh điều kiện, vòng lặp. Kiến thức và tư duy về thuật toán, giải thuật cũng khá cần thiết trong game, vì vậy hãy đầu tư tìm hiểu và học về nó để sẵn sàng có thể giải quyết các bài toán gặp phải.
Bước tiếp theo, hãy làm quen với Unity Editor, hàng năm đều có phiên bản mới được cập nhật với những cải thiện và tính năng mới được Unity thêm vào.
Cái thành phần cơ bản nhất trong Unity Editor mà bạn cần nắm vững:
Scene View: màn hình thế giới game, nơi chứa tất cả những gì trong game của bạn tạo ra
Game View: màn hình game, hiển thị những gì mà người dùng nhìn thấy khi chơi game.
Hierarchy: hiển thị danh sách các gameObjects mà bạn tạo ra theo phân cấp (dạng cây)
Inspector: hiển thị các thông số, thuộc tính của gameObject như tọa độ, hình ảnh, các script được gắn vào
Project: hiển thị các assets cùng các script mà bạn sử dụng
Có rất nhiều công cụ, tính năng được Unity Editor cung cấp cho bạn. Hãy cố gắng tìm hiểu nhiều nhất có thể.
Sau khi làm quen được với Unity Editor, hãy tập trung tìm hiểu về phần xử lý hình ảnh, âm thanh, animation,… gồm cả 2D và 3D trong Unity. Đây là bước giúp bạn có thể sử dụng resources và tạo ra các gameobject, xây dựng nhân vật, hiệu ứng cho game của mình. Trong Unity, bạn cũng có những component cơ bản như Button, Text, Image, Input, … tương tự trên Web; tuy vậy thì thứ bạn thường xuyên làm việc cùng đấy là Canvas, Materials, 3D Objects, Camera, Light, Particale, Terrains, … và nó cũng là đặc thù của việc làm game.
Bên cạnh đó điều mới mẻ và cũng là khó nhất trong Unity là làm việc với engine vật lý (Physic): Rigidbody, Collider (Box, Capsule, Mesh, Sphere, Wheel,…), Mass, Gravity, … Xử lý vật lý luôn là phần cốt lõi trong việc hình thành ra game, tương tác giữa các nhân vật (characters), giữa nhân vật với chướng ngại vật (obstacle) hay với background xung quanh có trọng lực (gravity) sẽ giúp game giống với thực tế và tạo sự hấp dẫn cho nó. Đây là 1 kiến thức khó, vì thế để làm được Unity, bạn cần nắm được nó thì mới có thể thực sự lập trình được cùng engine này.
Đến bước này, các bạn đã có thể nắm được cơ bản kiến thức về Unity và tự tin làm việc cùng nó trong các dự án game của mình hay của khách hàng. Để phát triển sâu, hãy tìm hướng đi bằng cách chọn những thể loại game phù hợp, tìm hiểu sâu về kiến thức mảng mà mình tìm hiểu. Có 1 số mảng game mà Unity được xem là thế mạnh và bạn có thể lựa chọn:
Game Casual: thể loại game phổ thông, dễ chơi thường chạy trên Web hoặc mobile, nổi bật gần đây là tựa game Untitled Goose phát hành bởi House House
Online MultiPlayer: thể loại game online nhiều người chơi, chạy trên nhiều platform khác nhau từ mobile, web đến PC, consoles. Đại diện ưu tú của dòng game này được phát triển bằng Unity là Amoung Us
VR/AR Game: dòng game thực tế ảo / thực tế tăng cường là 1 thế mạnh của Unity. Nổi bật nhất là Pokemon Go của Niantic
Action/RPG: dòng game hành động nhập vai, đây được xem là dòng game đỉnh cao nhất của các thể loại game với đồ họa, logic, xử lý vô cùng phức tạp. Unity cũng đóng góp những đại diện cho dòng game này nổi bật như Escape from Tarkov
Ngoài ra còn vô số dòng game khác mà các bạn nếu đam mê hãy tìm hiểu thêm nhé.
Kết bài
Nói về Unity thì chỉ trong khuôn khổ một bài viết là không hề đủ, có rất nhiều kiến thức thú vị và hấp dẫn về game engine cũng như cộng đồng lập trình viên Unity. Unity Developer đã, đang và sẽ là 1 nghề hấp dẫn với mức đãi ngộ tốt trong tương lai sắp tới. Hy vọng bài viết đã mang lại cho bạn những thông tin hữu ích về ngành lập trình game bằng Unity. Hẹn gặp lại các bạn trong các bài viết tiếp theo của mình.
Bài viết được sự cho phép của tác giả Trần Văn Dem
Gần đây mọi người hay so sánh REST với RPC nên chọn công nghệ nào để truyền tải dữ liệu qua các server. Với REST chúng ta có thể tìm thấy rất nhiều bài hướng dẫn trên internet. Các bài về tìm hiểu cơ chế chạy, cách truyền dữ liệu thông qua body,… Những bài viết đó khiến chúng ta quá quen thuộc với REST và nó không còn là hộp đen nữa. Trái ngược với điều trên thì RPC lại không nhiều bài viết hướng dẫn mọi người implement, mọi người thường tìm thấy cách sử dụng của một số framework như gRPC, thrift,… và các bài so sánh hiệu năng viết RPC nhanh hơn REST và thích hợp với truyền tải thông tin liên server hơn REST. Tại đây tôi có 1 implement nhỏ đơn giản về RPC hy vọng thông qua bài này mọi người sẽ không còn cảm thấy lạ với loại hình này và có thể giải thích được tại sao nó lại thích hợp giữa các server.
Transport
Cũng như các hệ thống client-server khác để giao tiếp giữa client và server chúng ta cần một network protocol. Các framework về RPC nổi tiếng họ dùng tầng transport sau:
gRPC sử dụng http2 truyền tải dũ liệu dữa client – server. Với Java thì họ dùng netty để dựng server http2. Vì Netty là một Non Blocking IO Framework
thrift sử dụng http1.1 truyền tải dữ liệu giữa client-server
Trong lúc đi làm tôi thường thấy mọi người hay so sánh giữa http và rpc. Hai khái niệm này không thể so sánh với nhau được vì nó thuộc 2 phạm trù khác nhau. Hy vọng sau bài viết này các bạn sẽ tự mình phân biệt được.
Trong bài demo này tôi cũng sẽ sử dụng Netty để xây dựng tầng transport dữ liệu giữa client server cụ thể sẽ dùng Non Blocking Socket của Netty
publicvoidconnectNetty(){
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap(); // (1)
b.group(workerGroup); // (2)
b.channel(NioSocketChannel.class); // (3)
b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
b.option(ChannelOption.TCP_NODELAY,true);
b.handler(new ChannelInitializer<SocketChannel>() {
@OverridepublicvoidinitChannel(SocketChannel ch)throws Exception {
ch.pipeline().addLast(transport = new ClientHandle(SimpleRpcClient.this));
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync(); // (5)// Wait until the connection is closed.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Serialize data
Với REST dữ liệu thường sẽ truyền tải giữa client server sẽ nằm trong body của request và được chuyển sang dưới dạng json. Với dạng Json sẽ dễ dàng đọc hiểu với mọi người nhưng với máy tính thì việc đó không dễ dàng. Nó kiến việc Deserialize và Serialize dữ liệu chậm hơn.
Với RPC dữ liệu truyền tải giữa client và server thì thường sẽ được serialize thành array byte việc này làm tiết kiệm được tài nguyên thực hiện serialize và deserialize
Hẹn các bạn ở bài viết sau sẽ giải thích lý do vì sao dạng byte array lại nhanh hơn so với json. Các bạn có thể tham khảo một bài viết trên medium
Với gRPC họ sử dụng protobuf để serialize dữ liệu thành byte array và ngược lại. Apache thrift cũng sẽ có một bộ serialize và deserialize riêng để biến dữ liệu truyền tải giữa server và client
Tại bài viết này tôi sẽ dùng thư viện kryo một thư viện mạnh mẽ với java về serialize và deserialize dữ liệu. Việc tự xây cho mình một cách serialize dữ liệu cũng hoàn toàn có thể làm được nhưng tôi sẽ để một bài viết khác.
Qua github của Kryo ta sử dụng thư viện này đơn giản nhất như sau:
import com.esotericsoftware.kryo.kryo5.Kryo;
import com.esotericsoftware.kryo.kryo5.io.ByteBufferInput;
import com.esotericsoftware.kryo.kryo5.io.ByteBufferOutput;
import com.esotericsoftware.kryo.kryo5.io.Input;
import com.esotericsoftware.kryo.kryo5.io.Output;
publicclassRPCSerialize{
publicstatic RPCSerialize serialize = new RPCSerialize();
privatefinal Kryo kryo;
publicRPCSerialize(){
this.kryo = new Kryo();
kryo.register(RPCRequest.class);
kryo.register(RPCResponse.class);
kryo.register(Object[].class);
kryo.register(User.class);
}
public <T> T deSerialize(byte[] arr, Class<T> t){
Input input = new ByteBufferInput(arr);
returnthis.kryo.readObject(input, t);
}
public <T> byte[] serialize(T t) {
Output output = new ByteBufferOutput(1024);
kryo.writeObject(output, t);
return output.toBytes();
}
}
Ta chỉ cần đăng ký các object cần giải serialize và deserialize với Kryo sau đó dựa vào reflection thư viện có thể serialize, deserialize dữ liệu.
Simple RPC server
Tại bài này chúng ta sẽ implement một service đơn giản sau :
import blog.rpc.support.User;
publicinterfaceSimpleService{
intadd(int a, int b);
User getUser();
}
import blog.rpc.service.SimpleService;
import blog.rpc.support.User;
publicclassServerImplimplementsSimpleService{
@Overridepublicintadd(int a, int b){
return a+b;
}
@Overridepublic User getUser(){
returnnew User("demtv");
}
}
Một RPC server cần phải lưu được lại các method của các service của mình để khi nhận được request chúng sẽ thực hiện gọi các method này theo cơ chế RPC. Tôi sẽ sử dụng một Map để lưu trữ thông tin này và sử dụng java reflection để gọi method.
IdGenerator chịu trách nhiệm tạo id cho request và response. Vì netty là Non Blocking IO nên cần thiết có id để đánh dấu response này được phản hồi cho request nào.
RPCRequest là object sẽ được truyền từ client lên server
RPCResponse là object sẽ được truyên từ server lên client
XFuture một custom của class Future nhằm đợi kết quả được gửi về server.
XMethod tạo ra signature để đánh dấu method và thực hiện invoke method.
Simple RPC client
Sau khi implement server, chúng ta thực hiện implement client. Client khi implement cần gửi lên server đúng method và param thực hiện method. Ta Override lại các method interface SimpleService đơn giản như sau để gửi lên server và nhận lại kết quả.
@Override
publicintadd(int a, int b) {
int rs = Integer.MAX_VALUE;
try {
RPCRequest request = new RPCRequest();
request.setId(idGenerator.nextId());
Methodmethod = this.getClass().getMethod("add", int.class, int.class);
request.setMethod(XMethod.signature(method));
request.setArgs(newObject[]{a, b});
byte[] x = serialize.serialize(request);
transport.sendMsg(Unpooled.copiedBuffer(x));
XFuture<Integer> future = new XFuture<>();
futures.put(request.getId(), future);
rs = future.get(100, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
return rs;
}
@Override
publicUser getUser() {
try {
RPCRequest request = new RPCRequest();
request.setId(idGenerator.nextId());
Methodmethod = this.getClass().getMethod("getUser");
request.setMethod(XMethod.signature(method));
request.setArgs(null);
byte[] x = serialize.serialize(request);
transport.sendMsg(Unpooled.copiedBuffer(x));
XFuture<User> future = new XFuture<>();
futures.put(request.getId(), future);
return future.get(100, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
returnnull;
}
Kết luận
RPC là một dạng giao tiếp giữa client và server thông tin trao đổi gồm có: method,param của method và kết quả. Nó thường được sử dụng hơn so với REST để truyền tải dữ liệu giữa client và server vì có thể dùng được nhiều loại transport khác nhau. Sử dụng Serialize dữ liệu hiệu quả hơn so với REST
RPC server cần phải có cơ chế lưu lại cái method và gọi đúng method khi nhận được request.
RPC client cần phải gửi lên method và param và đợi kết quả trả về từ server
Hy vọng mọi người cũng có thể hiểu hơn RPC là gì nhưng khi sử dụng thì mọi người nên sử dụng framework cho nó nhàn :)).
Bài viết được sự cho phép của tác giả Phạm Minh Khoa
Trong các hệ thống kiểm soát sửa đổi (Revision Control System), monorepo là một chiến lược phát triển phần mềm trong đó mã cho nhiều dự án được lưu trữ trong cùng một kho. Tính đến năm 2017, các hình thức khác nhau của thực hành kỹ thuật phần mềm này đã được hơn hai thập kỷ, nhưng khái niệm chung mới chỉ được đặt tên gần đây.
THEO WIKIPEDIA
Mono trong tiếng Hy Lạp là một, cô đơn, đơn lẻ và repo ở đây là repository (trong tiếng anh là kho chứa). Trường hợp ở đây là các repository trong các hệ thống kiểm soát phiên bản (Version Control System) như Git hay SVN.
Mono-repo là repository đơn lẻ mà trong đó các module con nằm gói gọn trong 1 repo. Ngoài ra, bên cạnh mono-repo thì còn có Multi-repo (nhiều repository) và Monolith (nguyên khối).
Mỗi kiến trúc Microservice trên đều đem lại một lợi ích nhất định. Với Monolith thì đây là kiến trúc căn nguyên và thường được sử dụng để kiến trúc các mô hình đúng nghĩa “nguyên khối” là không có sự phân chia module. Hiểu nôm na là mã nguồn dành cho giao diện người dùng (front-end) và truy vấn, truy cập vào database (back-end) sẽ nằm chung một repository.
Song các kiến trúc như Multi-repo và Mono-repo được tái kiến trúc từ Monolith để cách thức lưu trữ và quản lý mã nguồn trở nên “dễ thở” hơn.
Không phải mỗi ứng dụng nào cũng được phát triển dưới dạng microservices. Tuy nhiên, dù có phải tái cấu trúc mã nguồn từ một khối nguyên khối hay không, chúng ta đều sẽ phải lựa chọn cách thức lưu trữ và quản lý mã nguồn theo kiểu multiple repositories (multirepo) hay mono repositories (monorepo). Sơ lược của hai kiểu cách thức lưu trữ và quản lý này như sau:
Monorepo là kiểu cấu trúc project trong đó tất cả module (hoặc project con) đều nằm trong cùng 1 git repository.
Multirepo, ngược lại, là kiểu cấu trúc project trong đó mỗi module (hoặc project con) chứa ở những git repository riêng lẻ.
Tổ chức liền mạch: Với mono repo, các dự án có thể được tổ chức và nhóm lại với nhau theo bất kỳ cách nào bạn thấy là nhất quán về mặt logic nhất. Sử dụng một repo duy nhất cũng làm giảm chi phí quản lý các phần dependencies.
Cải thiện văn hóa làm việc chung giữa các nhóm: Với việc áp dụng mono repo, mọi cá nhân trong tổ chức đều nhận thức được các mục tiêu của ứng dụng và điều này làm cho cả tổ chức trở thành một nhóm thống nhất và do đó có thể đóng góp cụ thể hơn cho các mục tiêu và mục tiêu của tổ chức.
Phối hợp tốt hơn giữa các nhà phát triển: Các nhà phát triển có thể dễ dàng chạy toàn bộ nền tảng trên máy của họ và điều này giúp họ hiểu tất cả các dịch vụ và cách chúng làm việc cùng nhau. Điều này đã khiến các nhà phát triển tìm thấy nhiều lỗi cục bộ hơn trước khi gửi một pull request.
Tái cấu trúc dễ dàng: Bất kỳ lúc nào chúng ta muốn đổi tên một cái gì đó, việc tái cấu trúc trở nên vô cùng dễ dàng. Việc tái cấu trúc cũng dễ dàng hơn vì mọi thứ đều gọn gàng ở một nơi và dễ hiểu hơn.
Monorepos không chỉ duy trì được hầu hết các ưu điểm khi triển khai dưới dạng microservices mà còn đơn giản hóa việc chia sẻ mã và tái cấu trúc dự án chéo, chúng giảm đáng kể chi phí tạo libs, microservices và microfrontends. Vì vậy, việc áp dụng monorepo thường cho phép triển khai linh hoạt hơn.
Trong một số tình huống trong phát triển phần mềm, chúng ta có thể cải thiện hiệu suất của ứng dụng với việc sử dụng Cache. Hãy tưởng tượng rất nhiều đối tượng được tạo ra và lãng phí bộ nhớ. Mô hình Flyweight được tạo ra để tránh vấn đề này và tối ưu hóa hiệu suất.
Flyweight Pattern là gì?
Use sharing to support large numbers of fine-grained objects efficiently.
Flyweight Pattern là một trong những Pattern thuộc nhóm cấu trúc (Structural Pattern). Nó cho phép tái sử dụng đối tượng tương tự đã tồn tại bằng cách lưu trữ chúng hoặc tạo đối tượng mới khi không tìm thấy đối tượng phù hợp.
Flyweight Pattern được sử dụng khi chúng ta cần tạo một số lượng lớn các đối tượng của 1 lớp nào đó. Do mỗi đối tượng đều đòi hỏi chiếm giữ một khoảng không gian bộ nhớ, nên với một số lượng lớn đối tượng được tạo ra có thể gây nên vấn đề nghiêm trọng đặc biệt đối với các thiết bị có dung lượng nhớ thấp. Flyweight Pattern có thể được áp dụng để giảm tải cho bộ nhớ thông qua cách chia sẻ các đối tượng. Vì vậy performance của hệ thống được tối ưu.
Flyweight object là immutable, nghĩa là không thể thay đổi khi nó đã được khởi tạo.
Trạng thái của flyweight object là một phần quan trọng trong việc thiết kế Flyweight Pattern. Mục tiêu chính của Flyweight Pattern là giảm bộ nhớ bằng cách chia sẽ các đối tượng. Điều này có thể đạt được bằng cách tách các thuộc tính của đối tượng thành hai trạng thái: độc lập và phụ thuộc. Hay còn gọi là Intrinsic (trạng thái nội tại) và Extrinsic (trạng thái bên ngoài).
Intrinsic State (trạng thái nội tại) : Trạng thái này chứa dữ liệu không thể thay đổi (unchangeable) và không phụ thuộc (independent) vào ngữ cảnh (context) của đối tượng Flyweight . Những dữ liệu đó có thể được lưu trữ vĩnh viễn bên trong đối tượng Flyweight. Vì vậy mà Flyweight object có thể chia sẻ. Dữ liệu nội tại là phi trạng thái (stateless) và thường không thay đổi (unchanged). Tính năng này cho phép khả năng tái tạo các thuộc tính đối tượng Flyweight giữa các đối tượng tương tự khác. Điều quan trọng cần lưu ý là các đối tượng Flyweight chỉ nên nhận trạng thái bên trong của chúng thông qua các tham số của hàm tạo và không cung cấp các phương thức setter hay các biến public.
Extrinsic State (trạng thái bên ngoài) : Trạng thái bên ngoài thể hiện tính chất phụ thuộc ngữ cảnh của đối tượng flyweight. Trạng thái này chứa các thuộc tính và dữ liệu được áp dụng hoặc được tính toán trong thời gian thực thi (runtime). Do đó, những dữ liệu đó không được lưu trữ trong bộ nhớ. Vì trạng thái bên ngoài là phụ thuộc ngữ cảnh và có thể thay đổi nên các đối tượng đó không thể được chia sẻ. Do đó, client chịu trách nhiệm truyền dữ liệu liên quan đến trạng thái bên ngoài cho đối tượng flyweight khi cần thiết, có thể thông qua các tham số (argument).
Tóm lại, tốt nhất là xem xét cách mỗi dữ liệu hoạt động bên trong đối tượng khi tạo đối tượng flyweight. Nghĩa là thành phần nào không được thay đổi, cần lưu trữ, thành phần nào không được thay đổi, không cần lưu trữ. Điều này giúp cho chúng ta tiết kiệm được bộ nhớ và thực thi được hiệu quả.
Flyweight : là một interface/ abstract class, định nghĩa các các thành phần của một đối tượng.
ConcreteFlyweight : triển khai các phương thức đã được định nghĩa trong Flyweight. Việc triển khai này phải thực hiện các khả năng của trạng thái nội tại. Đó là dữ liệu phải không thể thay đổi (unchangeable) và có thể chia sẻ (shareable). Các đối tượng là phi trạng thái (stateless) trong triển khai này. Vì vậy, đối tượng ConcreteFlyweight giống nhau có thể được sử dụng trong các ngữ cảnh khác nhau.
UnsharedFlyweight : mặc dù mẫu thiết kế Flyweight cho phép chia sẻ thông tin, nhưng có thể tạo ra các thể hiện không được chia sẻ (not shared). Trong những trường hợp này, thông tin của các đối tượng có thể là stateful.
FlyweightFactory (Cache): lớp này có thể là một Factory Pattern được sử dụng để giữ tham chiếu đến đối tượng Flyweight đã được tạo ra. Nó cung cấp một phương thức để truy cập đối tượng Flyweight được chia sẽ. FlyweightFactory bao gồm một Pool (có thể là HashMap, không cho phép bên ngoài truy cập vào) để lưu trữ đối tượng Flyweight trong bộ nhớ. Nó sẽ trả về đối tượng Flyweight đã tồn tại khi được yêu cầu từ Client hoặc tạo mới nếu không tồn tại.
Client : sử dụng FlyweightFactory để khởi tạo đối tượng Flyweight.
Ứng tuyển các vị trí việc làm Java lương cao trên TopDev
Ví dụ:
Một ứng dụng game bao gồm rất nhiều Solider (lính), được chia thành các loại: Yuri, Spy, Doctor, … Mỗi Solider sẽ có id và cấp độ khác nhau. Thời gian để tạo một loại Solider là 3 giây.
Chương trình chúng ta được cài đặt với Flyweigth Pattern như sau:
ISoldier : đóng vai trò là một Flyweight. Định nghĩa phương thức promote với tham số là context, giá trị tham số này được quyết định bởi Client.
Context : đóng vai trò là Extrinsic State. Tùy vào ngữ cảnh khác nhau sẽ có giá trị khác nhau.
Soldier : đóng vai trò là ConcreteFlyweight. Triển khai các phương thức đã được định nghĩa trong Flyweight. Nó có một giá trị name (ứng với loại lính – Intrinsic State) không thay đổi, có thể chia sẻ được.
SoldierFactory : đóng vai trò là FlyweightFactory. Nó giữ một private Map để lưu giữ các loại soldier đã được tạo. Một phương thức createSoldier() để tạo soldier ứng với tên loại được truyền vào. Một phương thức getTotalOfSoldiers() để kiểm tra số lượng các loại soldier đã tạo.
GameApp : đóng vai trò là Client. Sử dụng SoldierFactory để tạo các Soldier.
package com.gpcoder.patterns.structural.flyweight;
/**
* Extrinsic State
*/
public class Context {
private String id;
private int star;
public Context(String id, int star) {
this.id = id;
this.star = star;
}
public String getId() {
return this.id;
}
public int getStar() {
return this.star;
}
}
Soldier.java
package com.gpcoder.patterns.structural.flyweight;
/**
* Concrete Flyweight
*/
public class Soldier implements ISoldier {
private final String name; // Intrinsic State
public Soldier(String name) {
this.name = name;
System.out.println("Soldier is created! - " + name);
}
@Override
public void promote(Context context) {
System.out.println(name + " " + context.getId() + " promoted " + context.getStar());
}
}
SoldierFactory.java
package com.gpcoder.patterns.structural.flyweight;
import java.util.HashMap;
import java.util.Map;
/**
* FlyweightFactory
*/
public class SoldierFactory {
private static final Map<String, ISoldier> soldiers = new HashMap<>();
private SoldierFactory() {
throw new IllegalStateException();
}
public static synchronized ISoldier createSoldier(String name) {
ISoldier soldier = soldiers.get(name);
if (soldier == null) {
waitingForCreateASoldier();
soldier = new Soldier(name);
soldiers.put(name, soldier);
}
return soldier;
}
public static synchronized int getTotalOfSoldiers() {
return soldiers.size();
}
private static void waitingForCreateASoldier() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
GameApp.java
package com.gpcoder.patterns.structural.flyweight;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
/**
* Client
*/
public class GameApp {
private static List<ISoldier> soldiers = new ArrayList<>();
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
createSoldier(5, "Yuri", 1);
createSoldier(5, "Spy", 1);
createSoldier(3, "Spy", 3);
createSoldier(2, "Yuri", 2);
long endTime = System.currentTimeMillis();
System.out.println("---");
System.out.println("Total soldiers made : " + soldiers.size());
System.out.println("Total time worked : " + Duration.ofMillis(endTime - startTime).getSeconds() + " seconds");
System.out.println("Total type of soldiers made : " + SoldierFactory.getTotalOfSoldiers());
}
private static void createSoldier(int numberOfSoldier, String soldierName, int numberOfStar) {
for (int i = 1; i <= numberOfSoldier; i++) {
Context star = new Context("Soldier" + (soldiers.size() + 1), numberOfStar);
ISoldier soldier = SoldierFactory.createSoldier(soldierName);
soldier.promote(star);
soldiers.add(soldier);
}
}
}
Output của chương trình trên như sau:
Soldier is created! - Yuri
Yuri Soldier1 promoted 1
Yuri Soldier2 promoted 1
Yuri Soldier3 promoted 1
Yuri Soldier4 promoted 1
Yuri Soldier5 promoted 1
Soldier is created! - Spy
Spy Soldier6 promoted 1
Spy Soldier7 promoted 1
Spy Soldier8 promoted 1
Spy Soldier9 promoted 1
Spy Soldier10 promoted 1
Spy Soldier11 promoted 3
Spy Soldier12 promoted 3
Spy Soldier13 promoted 3
Yuri Soldier14 promoted 2
Yuri Soldier15 promoted 2
---
Total soldiers made : 15
Total time worked : 6 seconds
Total type of soldiers made : 2
Như bạn thấy, chúng ta đã tạo ra 15 soldier chỉ với 6 giây (do chỉ tạo 2 lần ứng với 2 loại Yuri và Spy, mỗi loại mất 3 giây). Nếu không sử dụng Flyweight mà tạo từng soldier riêng lẻ, chúng ta sẽ mất đến 45 giây (do mỗi soldier mất 3 giây và có tất cả 15 soldier).
Lợi ích của Flyweight Pattern là gì?
Giảm số lượng đối tượng được tạo ra bằng cách chia sẻ đối tượng. Vì vậy, tiết kiệm bộ nhớ và các thiết bị lưu trữ cần thiết.
Cãi thiện khả năng cache dữ liệu vì thời gian đáp ứng nhanh.
Tăng performance.
Sử dụng Flyweight Pattern khi nào?
Khi có một số lớn các đối tượng được ứng dụng tạo ra một cách lặp đi lặp lại.
Khi việc tạo ra đối tượng đòi hỏi nhiều bộ nhớ và thời gian.
Khi muốn tái sử dụng đối tượng đã tồn tại thay vì phải tốn thời gian để tạo mới.
Khi nhóm đối tượng chứa nhiều đối tượng tương tự và hai đối tượng trong nhóm không khác nhau nhiều.
Bài viết được sự cho phép của tác giả Võ Quang Huy
1. Có kiến thức cơ bản về lập trình
Kiến thức cơ bản về lập trình là một trong những yếu tố cần thiết để trở thành một lập trình viên giỏi. Để có được kiến thức cơ bản về lập trình, bạn cần phải tập trung vào các khía cạnh của ngôn ngữ lập trình, cách thức lập trình, hoạt động của các công cụ lập trình và các lý thuyết cơ bản.
Bắt đầu bằng cách học các khía cạnh cơ bản của ngôn ngữ lập trình. Bạn cần phải tìm hiểu các cấu trúc cơ bản, biến, hàm, tham số, dữ liệu, và các từ khóa của ngôn ngữ. Bạn cũng cần phải học cách dùng các cấu trúc điều khiển để tạo ra các lệnh điều hành và đảm bảo rằng các lệnh được thực hiện theo cách mong muốn.
Tiếp theo, bạn cần phải học cách thức lập trình. Điều này bao gồm việc hiểu cách làm việc của các quy trình, lời gọi hàm, các phần mềm để giải quyết vấn đề, và để thiết kế các chương trình phức tạp.
Khi bạn hiểu rõ các khía cạnh cơ bản của ngôn ngữ lập trình và cách thức lập trình, bạn cần phải hiểu cách hoạt động của các công cụ lập trình. Việc hiểu cách hoạt động của các công cụ sẽ giúp bạn làm việc nhanh hơn và hiểu rõ cách lập trình của hệ thống hơn.
Cuối cùng, bạn cần phải hiểu các lý thuyết cơ bản của lập trình. Lý thuyết lập trình giúp bạn hiểu rõ cách các chương trình làm việc, các quy trình lập trình, và cách thức sử dụng các công cụ lập trình.
2. Khám phá khả năng của công cụ lập trình
Khi học lập trình, một yếu tố quan trọng là khám phá khả năng của các công cụ lập trình. Khám phá các công cụ là một phần quan trọng trong quá trình học lập trình, bởi nó cung cấp cho bạn những công cụ cần thiết để tiến hành công việc. Các công cụ này bao gồm các ngôn ngữ lập trình, các phần mềm, công cụ thống kê, hệ thống hỗ trợ, mô hình hóa và thiết kế, các ứng dụng hỗ trợ công việc liên quan đến lập trình và các công cụ khác.
Khi sử dụng các công cụ lập trình, bạn cần phải hiểu rõ cách để sử dụng chúng một cách hiệu quả. Điều này có nghĩa là bạn cần phải có kiến thức về các công cụ lập trình, phân tích các yêu cầu, xây dựng các giải pháp và thực hiện các bước để sử dụng công cụ. Bạn cũng cần phải làm quen với các công cụ lập trình mới nhất để duy trì các kỹ năng lập trình của mình.
Bạn cũng cần phải đọc cẩn thận các tài liệu về các công cụ lập trình, cũng như các hướng dẫn sử dụng các công cụ. Nếu có thể, hãy thử sử dụng công cụ trên môi trường thực nghiệm để trải nghiệm cách thức sử dụng các công cụ trong thực tế. Học cách sử dụng các công cụ sẽ giúp bạn hiểu rõ hơn về lập trình và cũng sẽ giúp bạn trong quá trình thực hiện.
Việc tự học các tính năng và công nghệ mới nhất là một trong những yếu tố quan trọng của việc học lập trình giỏi. Để làm được điều này, bạn cần phải thực hành nhiều và nắm bắt những thay đổi của công nghệ. Bạn cần phải tự học các tính năng và công nghệ mới nhất trong lập trình. Bạn có thể bắt đầu bằng cách tìm hiểu các công nghệ mới cũng như các sản phẩm lập trình. Bạn có thể tìm kiếm những nguồn thông tin đáng tin cậy và đọc nhiều nhất có thể. Bạn cũng nên tìm hiểu các ví dụ về tính năng và công nghệ mới để hiểu hơn về chúng.
Bạn cũng cần phải làm nhiều bài tập để thực hành những kiến thức đã học. Bạn có thể tạo ra những dự án nhỏ để làm quen với công nghệ mới. Tìm hiểu cách sử dụng các tính năng mới và công nghệ để tạo ra các dự án lớn hơn. Bạn cũng có thể tham gia những dự án cộng đồng để học hỏi thêm về các công nghệ và tính năng mới.
Bạn cũng nên tìm hiểu về các công cụ lập trình và cách sử dụng chúng để tối ưu công việc của mình. Hãy tự học cách sử dụng các công cụ, công nghệ và tính năng lập trình để có thể làm việc hiệu quả và tối ưu hóa thời gian của bạn.
Bạn cũng nên tìm những nhóm học tập và đối thoại với những người chuyên về lập trình. Điều này sẽ giúp bạn tạo ra một môi trường học tập có ích và hữu ích với những người cùng sở thích. Bạn cũng có thể thảo luận về các vấn đề về công nghệ và lập trình với nhau để có thể học hỏi nhiều hơn.
4. Làm nhiều bài tập để luyện tập.
Việc làm nhiều bài tập là yếu tố rất quan trọng để học lập trình giỏi. Việc làm nhiều bài tập giúp bạn củng cố lại các kiến thức đã học, và đồng thời giúp bạn học những kỹ năng thiết yếu cần thiết như làm việc với các dữ liệu, quản lý các biến, giải quyết vấn đề, v.v. Khi làm bài tập, hãy xem xét và phân tích những vấn đề mà bạn đang gặp phải, và cố gắng tìm ra cách giải quyết nó. Điều này sẽ giúp bạn phát triển kỹ năng tự học, tự động hóa việc giải quyết vấn đề, và cố gắng tìm ra các giải pháp tối ưu nhất.
Hãy thử làm nhiều bài tập khác nhau, và hãy tham gia các cuộc thi lập trình nhằm nâng cao khả năng của bạn. Việc tham gia các cuộc thi lập trình sẽ giúp bạn tăng cường kỹ năng lập trình của mình, và học được rất nhiều kiến thức về lập trình từ những người khác. Bên cạnh đó, việc đặt ra những câu hỏi và trả lời những câu hỏi này cũng sẽ giúp bạn học được nhiều hơn.
Cố gắng tập trung vào việc làm bài tập, và luôn đề cao việc sử dụng các công cụ và các công nghệ mới nhất để giúp bạn cải thiện kỹ năng lập trình của mình. Khi làm bài tập, hãy luôn luôn ghi chép lại các quá trình giải quyết vấn đề của bạn, để có thể tham khảo lại và tìm ra các giải pháp tốt hơn trong tương lai.
Trong tổng thể, việc làm nhiều bài tập là yếu tố thiết yếu để học lập trình giỏi. Việc làm bài tập sẽ giúp bạn đào sâu vào lập trình và luôn đề cao việc sử dụng công nghệ mới nhất.
5. Tham gia nhóm học tập và đối thoại với những người chuyên về lập trình.
Những người chuyên về lập trình luôn là một nguồn thông tin vô cùng có giá trị. Tham gia nhóm học tập cũng như đối thoại với những người này có thể giúp bạn cải thiện những kỹ năng lập trình của bạn rất nhanh. Những nhóm này cũng là nơi bạn có thể được giải đáp những thắc mắc về lập trình của bạn, họ sẽ cung cấp cho bạn những ý tưởng sáng tạo và làm cho bạn cảm thấy bản thân hứa hẹn hơn trong việc học tập và lập trình. Để học lập trình giỏi, những nhóm này cũng là nơi bạn được học thêm những kỹ năng lập trình cần thiết như là lập trình đồ họa, lập trình web, lập trình mạng, v.v. Điều này là rất hữu ích vì bạn sẽ được nhận được những góp ý và tham khảo từ những người có tay nghề và kinh nghiệm trong lĩnh vực này. Họ sẽ giúp bạn hiểu được những câu hỏi cơ bản của lập trình và cách tốt nhất để giải quyết các vấn đề. Ngoài ra, đối thoại với những người chuyên về lập trình cũng giúp bạn có được những ý tưởng sáng tạo trong lập trình và hiểu hơn về các công nghệ hiện đại. Vậy thì tham gia nhóm học tập và đối thoại với những người chuyên về lập trình là một trong những yếu tố quan trọng nhất để học lập trình giỏi.
Tổng kết:
Để trở thành một lập trình viên tốt, bạn cần có kiến thức cơ bản về lập trình, hiểu các tính năng và công nghệ mới nhất, khám phá khả năng của công cụ lập trình, luyện tập thực hành và tham gia nhóm học tập. Những yếu tố này sẽ giúp bạn có được những kiến thức và kỹ năng lập trình tốt hơn.
Frontend là 1 phần của website mà ở đó người dùng có thể tương tác để sử dụng, nói cách khác thì tất cả những gì mà bạn có thể nhìn thấy trên website từ nội dung, font chữ, màu sắc, menu, thanh điều hướng, … đều là frontend, và là thứ mà Frontend Developer tạo ra. Trong bài viết này bạn sẽ biết được Frontend là gì? thế nào là một Frontend developer, những kỹ năng và nền tảng công nghệ mà bạn có thể học hỏi được từ việc trở thành một Frontend, cũng như tương lai nào cho bạn khi bạn trở thành một Frontend.
Frontend là gì?
Trước hết hãy tìm câu trả lời Frontend là gì?
Frontend là phần của trang web mà người dùng trực tiếp tương tác. Nó bao gồm thiết kế, thanh điều hướng, text, hình ảnh, video, và cấu trúc tổng thể của trang. Mục tiêu chính của frontend là đảm bảo tính tương thích và hiệu suất của trang web.
Khi vào một website hay một application, những gì bạn thấy, các nút bấm, những hành động click hay scroll trên trang đó là kết quả của lập trình Front End. Bạn có thể coi Front-End là client-side và Back-End là server-side.
Sự khác biệt giữa Front-End và Back-End là Front-End đề cập đến giao diện của trang web, trong khi Back-end đề cập đến cách trang web hoạt động.
Các ngôn ngữ chính dùng trong phát triển frontend bao gồm HTML, CSS và JavaScript. HTML định dạng cấu trúc nội dung, CSS điều chỉnh kiểu dáng và bố cục, còn JavaScript cung cấp tính năng động và tương tác cho trang web.
Trách nhiệm chính của Lập trình viên Front-End là tạo ra giao diện người dùng.
Lập trình frontend là việc sử dụng các ngôn ngữ HTML, CSS và ngôn ngữ lập trình JavaScript để thiết kế, viết code tạo ra giao diện của các ứng dụng hay trang web dành cho người dùng.
Giao diện mà Frontend Developer tạo ra không chỉ chạy trên 1 loại thiết bị duy nhất mà còn phải đảm bảo nó tương thích với nhiều phần cứng khác nhau từ kích thước màn hình, độ phân giải, hệ điều hành, loại trình duyệt,… giúp mang lại trải nghiệm tốt nhất cho khách hàng. Ngoài việc xử lý các logic ở Client Side, Frontend Developer cũng đảm nhận việc xử lý giao tiếp với phía Backend (Server Side) thông qua việc gửi request API, nhận response dữ liệu và hiển thị kết quả cho người dùng.
HTML và CSS: đây là 2 ngôn ngữ cơ bản nhất để xây dựng nên các building block cơ bản, từ đó tạo ra giao diện của 1 website.
JavaScript: ngôn ngữ lập trình sử dụng để xử lý các sự kiện, tương tác của người dùng với website, đây cũng là 1 phần không thể thiếu khi muốn tạo ra các website động.
Các framework, thư viện: để tiết kiệm thời gian xây dựng thành phần của website, chúng ta có thể tận dụng các framework, thư viện có sẵn hiện nay như ReactJS, AngularJS, jQuery, … Ngoài việc tận dụng các thành phần và xử lý có sẵn thì việc sử dụng các thư viện cũng giúp bạn viết code và quản lý source code dễ dàng hơn theo các cấu trúc rõ ràng.
Responsive: website của bạn không chỉ chạy trên 1 loại màn hình, vì thế cần thiết kế để website hiển thị 1 cách hợp lý và tối ưu trên các loại màn hình khác nhau và cả trên các thiết bị di động.
Cross-Browser: ngoài việc tối ưu hiển thị trên các kích thước màn hình khác nhau, website của bạn cũng cần chạy được trên nhiều trình duyệt khác nhau như Chrome, Firefox, IE, … mỗi trình duyệt có những đặc thù riêng, CSS, JS hỗ trợ cũng khác nhau. Vì thế bạn cần nắm rõ những đặc điểm trên để website có thể chạy tốt trên các nền tảng trình duyệt đó.
Rest API: cách để Frontend giao tiếp với Backend thông qua việc gửi yêu cầu (request) và nhận lại phản hồi (response) và dữ liệu để hiển thị. Việc nắm rõ các phương thức giao tiếp POST, GET, DELETE, …cùng body gửi lên là cần thiết để truyền và nhận dữ liệu 1 cách chính xác.
Lập trình viên Frontend cần sở hữu một loạt các kỹ năng để phát triển và duy trì các giao diện người dùng hiệu quả và hấp dẫn. Dưới đây là những kỹ năng quan trọng mà một lập trình viên Frontend nên có:
1. Ngôn Ngữ Lập Trình Cơ Bản
HTML và CSS: đây là 2 ngôn ngữ cơ bản nhất để xây dựng nên các building block cơ bản, từ đó tạo ra giao diện của 1 website.
JavaScript: ngôn ngữ lập trình sử dụng để xử lý các sự kiện, tương tác của người dùng với website, đây cũng là 1 phần không thể thiếu khi muốn tạo ra các website động.
2. Framework và Thư Viện JavaScript và CSS
Các framework, thư viện: để tiết kiệm thời gian xây dựng thành phần của website, chúng ta có thể tận dụng các framework, thư viện có sẵn hiện nay như ReactJS, AngularJS, jQuery, … Ngoài việc tận dụng các thành phần và xử lý có sẵn thì việc sử dụng các thư viện cũng giúp bạn viết code và quản lý source code dễ dàng hơn theo các cấu trúc rõ ràng:
Bootstrap: Một framework CSS phổ biến giúp tạo giao diện người dùng responsive.
W3.CSS: Một framework CSS đơn giản và dễ sử dụng.
jQuery: Thư viện JavaScript giúp đơn giản hóa việc thao tác với DOM.
Angular: Một framework JavaScript mạnh mẽ để xây dựng các ứng dụng web động.
React: Một thư viện JavaScript của Facebook dùng để xây dựng giao diện người dùng.
Xử Lý API
REST: Giao thức API phổ biến dùng để tương tác với các dịch vụ web.
GraphQL: Một ngôn ngữ truy vấn API giúp lấy dữ liệu hiệu quả hơn.
Responsive
Website của bạn không chỉ chạy trên 1 loại màn hình, vì thế cần thiết kế để website hiển thị 1 cách hợp lý và tối ưu trên các loại màn hình khác nhau và cả trên các thiết bị di động.
Định Dạng Dữ Liệu
JSON: Định dạng dữ liệu nhẹ thường được sử dụng để truyền tải dữ liệu giữa client và server.
XML: Một định dạng dữ liệu khác, thường dùng trong các ứng dụng web truyền thống.
Công Cụ Phát Triển
Git: Hệ thống quản lý phiên bản phân tán, quan trọng để theo dõi và quản lý mã nguồn.
Những kỹ năng này giúp lập trình viên Frontend phát triển các giao diện người dùng hiệu quả, đáp ứng nhu cầu của người dùng và đảm bảo hiệu suất tối ưu cho trang web.
Những nền tảng công nghệ trong lập trình Frontend
Phần tiếp theo của bài viết, chúng ta sẽ lướt qua các nền tảng công nghệ mà khi bạn muốn trở thành frontend developer bạn cần phải biết cũng như có hiểu biết đúng đắn, đầy đủ và thật sâu về nó.
Những nền tảng này không chỉ ảnh hưởng đã từ rất lâu trong quá khứ, mà còn hiện tại cho đến tương lai về sau.
Hệ sinh thái CSS Framework
Ngày nay không khó để điểm mặt chỉ tên các nền tảng về css framework phổ biến như: Bootstrap, Foundation, SemanticUI và hàng loạt các tên tuổi khác có các thế mạnh, triết lý riêng.
Các framework cung cấp hàng loạt các tính năng, đáp ứng gần như là đầy đủ các yêu cầu cơ bản cần có đối với một sản phẩm được thiết kế theo hướng hiện đại: carousel, form, modal, drag/drop, datetime picker… nhằm giúp lập trình viên phát triển nhanh hơn ứng dụng của mình.
Hệ sinh thái jQuery
Sau nhiều năm đứng đầu về sự đóng góp của mình trong lĩnh vực Frontend, JQuery đã tạo cho mình một hệ sinh thái, một vị trí thống lĩnh mà hiếm có thư viện nào có thể sánh kịp. Các plugin của jQuery đã cung cấp hầu hết mọi thứ mà các lập trình viên cần đến, với lại rất dễ dàng để tích hợp vào source code của họ. API jQuery được thiết kế thông minh, dễ sử dụng, hầu hết là tương thích với các trình duyệt phổ biến đã làm giảm đi chi phí phát triển, kiểm lỗi và hạn chế được rất nhiều rủi ro.
Ngay cả khi các nền tảng về frontend lớn hiện tại như Angular, React, Vuejs không còn phụ thuộc vào nó nữa thì tư tưởng và tầm ảnh hưởng của nó sẽ vẫn còn trong rất nhiều năm tới, nếu không muốn nói là khó có thể thay thế được trong tương lai gần.
Và cũng tránh nhầm lẫn trong việc jQuery so sánh với các nền tảng như Angular, Reactjs… thì trong giới hạn của bài viết, bạn đọc có thể hình dung rằng đó là 2 nền tảng tiếp cận theo hai hướng hoàn toàn khác nhau, có thể chúng không phụ thuộc lẫn nhau nhưng không có nghĩa là chúng phủ định lẫn nhau.
Hệ sinh thái Nodejs
Nodejs có một hệ sinh thái đa dạng và rộng lớn, phát triển với tốc độ khủng khiếp chưa từng có, cùng với sự tham gia hỗ trợ của các ông lớn trong ngành bao gồm Microsoft, Google, Facebook v.v…
Với Nodejs bạn có thể tìm thấy mọi thứ mình cần, bao gồm các công cụ để phát triển Frontend, các phương pháp phát triển sản phẩm mới.
Hệ sinh thái Webpack
Webpack là một phần trong hệ sinh thái của Nodejs, nhưng vì tầm vóc và tương lai của nó nên chúng ta cũng nên tách nó ra thành một phần tương xứng. Webpack cung cấp cho chúng ta công cụ quan trọng để hiện thực hoá nhiều thao tác vốn phức tạp nay trở nên dễ dàng.
Các tiện ích mà Webpack cung cấp gần như là bao phủ tất cả, bao gồm giải quyết các vấn đề về tổ chức source code, giải quyết sự phụ thuộc giữa các thư viện, quản lý các resource như image, font, đi kèm với các công cụ để tối ưu source code như tách source nhỏ ra để tăng tốc tải trang…
Lộ trình để trở thành Frontend Developer
Frontend Developer là những lập trình viên tạo ra các website ở phía client side, vì thế bước đầu tiên bạn cần là trang bị kiến thức về Internet:
Cách Internet hoạt động, HTTP là gì?
Trình duyệt (browser) hoạt động thế nào, các trình duyệt thông dụng
Tiếp theo chúng ta cần trang bị kiến thức cơ bản trực tiếp liên quan đến lập trình frontend bao gồm: HTML, CSS và JavaScript:
HTML: các thẻ (tag), form, thẻ media và cách sử dụng. Trang bị kiến thức về HTML5, kỹ thuật SEO cơ bản.
CSS: các thuộc tính CSS của từng thẻ HTML tương ứng. Cách sử dụng thẻ media để xử lý responsive cho các kích thước màn hình khác nhau. Cách xây dựng layout cơ bản. Tìm hiểu thêm về SCSS hay SASS
JavaScript: Cú pháp lập trình, các kiểu dữ liệu cơ bản trong JS. ES6+ và các module cơ bản trong JavaScript. Cách xử lý với API (fetch, xhr). Sau khi nắm vững được cơ bản về JS thì chúng ta có thể tìm hiểu sâu hơn về các thư viện JS thường sử dụng như jQuery, React, Vue,…
Việc chọn 1 framework để sử dụng và tiếp tục tìm hiểu sâu là cần thiết, giúp bạn có thể tối ưu hóa được thời gian và chi phí lập trình; đồng thời đáp ứng được nhu cầu tuyển dụng của các công ty.
Ngoài ra trong quá trình làm việc, các bạn cũng cần có kiến thức liên quan đến trình quản lý package, các tools giúp định dạng hiển thị sourcode và tự động format đúng chuẩn:
Framework và thư viện: React, Angular, Vue.js, Svelte, Solid JS
Đến đây bạn có thể tự tin chinh chiến các dự án được giao trách nhiệm, code các module theo đúng yêu cầu của khách hàng. Tất nhiên việc học không bao giờ là đủ, 1 senior Frontend Developer cần trang bị thêm nhiều kiến thức chuyên sâu hơn nữa, 1 số gạch đầu dòng dưới đây để các bạn có thể tham khảo:
Authentication: JWT, Oauth, Sessio Auth, SSO
SSR, SSG: Server Side Rendering, Static Site Generation
Progressive Web Apps: làm việc với Web Sockets, Service Workers, sử dụng Lighthouse hay Devtools cho việc tối ưu hóa website
GraphQL: cách để phía frontend tương tác trực tiếp với Database mà không cần qua Backend
Tạo ra các ứng dụng dành cho mobile hay desktop: hiện tại với JS chúng ta không chỉ còn tạo ra các ứng dụng web, mà nó còn có thể tạo ra các ứng dụng chạy trên mobile hay desktop. 1 số framework hay thư viện có thể giúp chúng ta làm điều đó: React Native, Flutter, Ionic, NativeScript cho mobile; Electron, Tauri dành cho desktop.
Tương lai của một Frontend Dev
Ngày nay, với phong trào khởi nghiệp, các sản phẩm mới được phát triển không chỉ nhiều về số lượng, mà đa dạng về lĩch vực, các sản phẩm cũ cũng được nâng cấp lên về chất lượng, performance bên trong cũng như UI/UX bên ngoài tạo ra một nguồn cầu rất lớn từ thị trường.
Các ứng dụng giờ không chỉ được xây dựng cho desktop, mà còn phải chạy tốt trên nền tảng di động tạo ra gần như gấp đôi khối lượng công việc để làm. Ngoài ra nền tảng di động đòi hỏi các yêu cầu khắt khe hơn về các tiêu chí kỹ thuật như về performance, network, optimize việc sử dụng tài nguyên của thiết bị sao cho tối ưu nhất.
Một thị trường đa dạng, rộng lớn chắc chắn sẽ mang lại nhiều cơ hội nghề nghiệp hấp dẫn (số lượng), với mức lương cạnh tranh (chất lượng), điều đó làm nên một tương lai tươi sáng cho nghề nghiệp của chúng ta.
Kết bài
Frontend là 1 phần không thể thiếu trong 1 website nói riêng và hệ thống Web nói chung. Lập trình viên Frontend có thể học thêm NodeJS để làm backend cũng khiến cho nghề này trở nên hấp dẫn hơn trong định hướng của bạn. Bài viết này hy vọng đã mang đến cho các bạn cái nhìn tổng quan nhất về frontend developer và lộ trình học để trở thành 1 lập trình viên trong tương lai. Cảm ơn các bạn đã đọc bài và hẹn gặp lại các bạn trong những bài viết tiếp theo của mình.
Theo thống kê từ trang Statista, đầu năm 2023, số lượng người dùng smartphone trên thế giới hiện nay là 6.92 tỷ người, nghĩa là có đến 86.34% dân số thế giới sở hữu smartphone. Thị trường phát triển ứng dụng smartphone ngày càng có nhu cầu lớn hơn, cũng chính vì thế mà lập trình viên ứng dụng di động – Mobile Developer trở thành 1 ngành nghề hot với nhu cầu tuyển dụng rất lớn. Bài viết hôm nay chúng ta cùng tìm hiểu về ngành này cũng như lộ trình để trở thành lập trình viên ứng dụng di động nhé.
Mobile Developer là gì?
Mobile Developer là những lập trình viên phát triển những ứng dụng dành cho các thiết bị di động, phổ biến hiện nay là các ứng dụng trên smartphone với 2 hệ điều hành chính là Android và iOS. Các hệ điều hành chạy trên thiết bị smartphone đều được trang bị các công cụ (SDK, IDE) và ngôn ngữ giúp các nhà phát triển tạo ra ứng dụng của mình, với Android sử dụng Java hay Kotlin; iOS sử dụng Objective-C hay Swift.
Ngoài ra có các thư viện hay framework và ngôn ngữ khác nhau giúp tạo ra ứng dụng đa nền tảng (có thể chạy trên nhiều hệ điều hành) như React Native viết bằng JavaScript, Flutter viết bằng Dart,… Nhiệm vụ của lập trình viên di động là nắm vững các kiến thức về lập trình, trang bị cho mình 1 hoặc nhiều trong số các ngôn ngữ, thư viện hay framework kể trên để có thể tạo ra những ứng dụng theo yêu cầu.
Mô tả về công việc cụ thể của 1 lập trình viên di động như sau:
Tham gia thiết kế xây dựng phần mềm dựa vào ý tưởng, nhu cầu của người dùng và những kinh nghiệm phát triển ứng dụng di động đã có
Viết code lập trình xây dựng giao diện và tính năng cho ứng dụng theo như khách hàng yêu cầu
Tham gia chạy, kiểm thử ứng dụng trên các thiết bị, phần mềm giả lập
Sửa chữa và nâng cấp các lỗi xuất hiện trong quá trình sử dụng ứng dụng
Publish (phát hành) ứng dụng lên các nền tảng chợ (market) như Google Play với Android hay AppStore với iOS
Nghiên cứu các công nghệ mới, cập nhật các bản phát hành của hệ điều hành, công cụ phát triển (SDK, IDE) tương ứng để áp dụng vào công việc, hỗ trợ cập nhật phần mềm khi có phiên bản hệ điều hành mới
Khác với lập trình Web hay Desktop, có 1 số đặc thù mà chỉ riêng ngành lập trình di động mới có và nó tác động khá lớn đến dự định trở thành 1 mobile developer của bạn:
Làm việc với nhiều thiết bị phần cứng khác nhau: hiện nay có vô số các thiết bị smartphone với đủ kích thước màn hình, cấu hình phần cứng khác nhau. Ứng dụng của bạn sẽ phải đối ứng với đủ các kiểu màn hình như tai thỏ, giọt nước, đục lỗ, … khiến cho ứng dụng của bạn có thể gặp nhiều vấn đề mà trên PC sẽ không bao giờ gặp phải.
Tương tác trực tiếp với các thiết bị cảm biến phần cứng: nếu như trên PC hay các ứng dụng Web, việc truy cập và làm việc với các thiết bị ngoại vi như camera, mic, loa mặc dù không quá thường xuyên nhưng có thể khiến bạn đau đầu; thì với smartphone hiện nay, có hàng chục các loại cảm biến khác nhau từ định vị, cảm biến con quay hồi chuyển, cảm biến gia tốc, vân tay, faceid, cảm biến tiệm cận, … với đủ các thứ quyền mà bạn cần xin phép mới có thể sử dụng.
Phát hành ứng dụng lên các chợ: ứng dụng của bạn nếu muốn đến tay người dùng thì không chỉ cần 1 địa chỉ website như ứng dụng Web, cũng không chỉ cần 1 bản cài đặt như ứng dụng trên Desktop; bạn cần phải phát hành chúng trên các chợ như Google Play, Appstore để người dùng tìm kiếm và có thể download về cài đặt. Việc tuân thủ tất cả các chính sách có thể khiến bạn phải đau đầu, chưa kể sự cập nhật thường xuyên về hệ điều hành cũng khiến ứng dụng của bạn cần update để đáp ứng.
Với việc đặc thù là tạo ra ứng dụng chạy trên nhiều nền tảng hệ điều hành di động khác nhau, vì thế có 2 định hướng khá rõ trong lộ trình trở thành 1 lập trình viên di động.
Hướng thứ nhất là tập trung làm mobile trên 1 nền tảng duy nhất (single platfom):
iOS: sử dụng ngôn ngữ Swift, Objective-C trên IDE Xcode sử dụng iOS SDK do Apple cung cấp để viết các ứng dụng dành riêng cho nền tảng iOS, chạy trên các thiết bị iPhone, iPad, Mac, …
Android: sử dụng ngôn ngữ Java, Kotlin trên IDE Android Studio sử dụng Android SDK do Google cung cấp để tạo ra các ứng dụng dành riêng cho nền tảng Android, chạy trên các thiết bị di động sử dụng hệ điều hành Android
Đối với hướng này, các lập trình viên sẽ tìm hiểu sâu vào từng ngôn ngữ, từng thư viện được cung cấp sẵn trong SDK, tương tác sâu và trực tiếp với các thiết bị phần cứng.
Đặc thù của ứng dụng bạn viết ra là sẽ chỉ chạy được trên nền tảng duy nhất, bạn không thể lấy source code ứng dụng Android để tạo ra ứng dụng tương ứng cho iOS. Nhưng cũng chính đó là ưu điểm của hướng phát triển này khi bạn có thể tối ưu hóa 1 cách tốt nhất cho ứng dụng của mình.
Hướng thứ 2 là việc phát triển các ứng dụng đa nền tảng (cross platform), được hiểu là có thể tạo ra ứng dụng chạy được trên nhiều nền tảng hệ điều hành khác nhau. 2 loại kỹ thuật phát triển ứng dụng đa nền tảng là Hybrid và Native:
Hybrid: các ứng dụng hybrid chủ yếu được viết trên nền tảng Web sử dụng HTML, CSS và JS. Bằng việc bao bọc ứng dụng bằng 1 trình duyệt để nó có thể chạy trên nền tảng di động, ứng dụng hybrid tạo ra 1 giao diện duy nhất cho nhiều nền tảng hệ điều hành khác nhau. Có thể kể đến 1 vài framework hay thư viện giúp xây dựng ứng dụng Hybrid như Cordova, Ionic, jQuery Mobile, HTML5, …
Native: khác với Hybrid khi chỉ tạo ra 1 ứng dụng duy nhất, các ứng dụng Native cho phép bạn viết 1 source code duy nhất và tạo ra các ứng dụng dành riêng cho từng hệ điều hành khác nhau bằng các công cụ biên dịch. Lựa chọn này giúp ứng dụng của bạn có thể tối ưu tốt hơn khi tương tác với phần cứng cụ thể của từng hệ điều hành cũng như tối ưu hóa hiệu năng. Có thể kể đến các framework như React Native, Flutter, Xamarin.
Ưu điểm của hướng thứ 2 chính là việc tiết kiệm thời gian, nguồn lực và kinh phí phát triển ứng dụng so với hướng thứ 1. Tuy vậy thì nhược điểm của nó là khả năng tạo ra các ứng dụng với trải nghiệm tốt nhất về giao diện cũng như hiệu năng dành cho người dùng.
Mobile Developer cần xác định trước lộ trình mình mong muốn trở thành ngay từ đầu để có thể lựa chọn học đúng, học đủ và học sâu những kiến thức theo lộ trình. Sau khi thành thạo 1 trong 2 hướng thì có thể chuyển qua học hướng còn lại để nâng cao khả năng lập trình của mình.
Kết bài
Như vậy qua bài viết này, mình đã cùng các bạn tìm hiểu về ngành lập trình ứng dụng di động – Mobile Developer cũng như lộ trình, các kiến thức cần thiết nếu bạn có dự định dấn thân vào ngành này. Đây là 1 ngành nghề hay và thú vị, cùng với nhu cầu lớn của thị trường sẽ là 1 lựa chọn tiềm năng dành cho bạn. Cảm ơn các bạn đã đọc và theo dõi, hẹn gặp lại trong các bài viết tiếp theo của mình.
Laravel tuy một PHP framework mạnh mẽ khi cung cấp rất nhiều tính năng hay ho cho developer. Nhưng thực tế, nhiều bạn developer mới chỉ sử dụng Laravel như một framework MVC đơn thuần mà không biết rằng ngoài cái đó ra, Laravel còn có nhiều tính năng cao cấp khác.
Vì vậy, trong bài viết này mình sẽ chỉ ra một số tính năng hữu ích khác của Laravel (bên cạnh một MVC framework thuần túy). Hy vọng các bạn sẽ có thêm kiến thức để giải quyết các vấn đề trong dự án tốt hơn.
I. Queue
Queue – Hàng đợi trong Laravel là giải pháp để xử lý các request tốn nhiều thời gian thực thi, trong khi bạn lại không muốn user phải đợi quá lâu mới có response.
Để hiểu rõ hơn, chúng ta sẽ cùng làm một tính năng theo 2 cách, cách 1 không sử dụng queue, cách 2 sử dụng queue để xem sự khác nhau như thế nào nhé:
Xét bài toán như sau:
Xây dựng tính năng đăng ký tài khoản, sau khi đăng ký thành công, sẽ gửi tới email của user một thông báo “Chào mừng bạn đến với website … “, đồng thời hiện một thông báo lên màn hình là “Bạn đã đăng ký thành công“.
Cách 1 yêu cầu user phải đợi cho đến khi email được gửi thành công thì mới thực hiện bước 4.
Cách 2 thì tạo ra một “job gửi email” và được đưa vào trong queue, job này sẽ chạy sau, nên user không cần phải đợi mà có thể chuyển sang bước 4 ngay.
Vì cách 2 không yêu cầu phải đợi, nên cách 2 user sẽ sớm nhận được thông báo “Bạn đã đăng ký thành công“, làm user có trải nghiệm tốt hơn.
Job đưa vào trong queue đúng là chạy sau, nhưng nó gần như chạy sau khi user nhận được thông báo “Bạn đã đăng ký thành công hơn“, nên user sẽ vẫn nhận được email ngay sau khi đăng ký.
Laravel là PHP framework, mà ứng dụng PHP sẽ chỉ hoạt động khi có request (tức có user truy cập). Nhưng trong thực tế đôi khi sẽ có những yêu cầu mà ứng dụng PHP phải tự nó chạy mà không cần request nào được gửi đến.
Như việc backup dữ liệu vào 12h đêm mỗi ngày chẳng hạn, không lẽ bạn cứ phải căn đúng 12h đêm để vào website, nhấn nút “backup” sao. Thật ra nếu muốn thì bạn cũng có thể làm như vậy, nhưng có cách khác tiện hơn nhiều, đó chính là Task scheduling.
Task scheduling là tính năng cho phép bạn lập lịch chạy một tác vụ nào đó.
Quay trở lại ví dụ backup database ở trên, mình sẽ tạo ra một task mà cứ đúng 12h đêm nó sẽ tự động được chạy, để rồi sáng hôm sau mình sẽ chỉ việc download file database đã được backup về máy, mà không cần phải thức đêm để nhấn nút “backup”.
Cách sử dụng Laravel task scheduling
Laravel task scheduling hoạt động dựa trên crontab, vì thể để sử dụng được tính năng này bạn cần phải cấu hình một cronjob như sau:
Crontab là chương trình lập lịch chạy trên Linux, mỗi một tác vụ được lập lịch chạy được gọi là một cronjob.
Cronjob trên có ý nghĩa là “Cứ mỗi phút thì thực hiện lệnh cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1 một lần”. Bạn có thể tìm hiểu thêm về cú pháp của Crontab tại đây.
Sau khi cấu hình crontab, giờ bạn có thể cấu hình task scheduling trong file app/Console/Kernel.php.
// app/Console/Kernel.php// ...protectedfunctionschedule(Schedule $schedule){$schedule->call(function() {// Task làm gì sẽ được định nghĩa ở đây})// daily() nghĩa là task này sẽ được chạy mỗi ngày ngày.// ngoài daily() thì còn nhiều phương thức khác nữa// chi tiết tìm hiểu trên docs của Laravel bạn nhé->daily();}
Về cách khai báo task, cũng như lập lịch task (mỗi ngày, mỗi tuần, chạy lúc mấy giờ,…) thì tài liệu Laravel đã viết rất rõ, nên mình lười không muốn viết lại nữa, bạn có thể đọc thêm ở đây.
III. Compiling Assets
Là một PHP framework, nhưng Laravel cũng chú trọng cả frontend, điều này được thể hiện qua tính năng “Compiling assets” (Biên dịch các file assets như scss, js). Ở phiên bản hiện tại (Laravel 8), Laravel thực hiện compiling assets thông qua gói Laravel Mix.
Nếu bạn đã từng sử dụng các tool build frontend như webpack, gulp thì Laravel Mix cũng là cái gì đó tương tự như vậy.
Frontend của các dự án web ngày càng phức tạp, trong khi đó kiểu lập trình web truyền thống thì chưa tập trung nhiều vào tối ưu frontend. Ví dụ, để viết CSS cho website, chúng ta thường tạo một file style.css và nhúng nó vào phần head của trang web. Nhưng khi các trang web ngày càng trở nên phức tạp (ngày càng nhiều trang, ngày càng nhiều css) thì cách làm này dần phát sinh nhiều nhược điểm:
File style.css quá nặng.
Không tối ưu css: do toàn bộ css đều được viết trong một file, và không phải trang nào cũng sử dụng hết các class được khai báo trong đó, thậm chí có những đoạn css đã không còn dùng tới.
Khó quản lý các class: các class mới thì ngày càng được bổ sung, và có thể bị trùng lặp, hoặc xung đột với các class trước đó.
Đứng trước các nhược điểm trên, người ta đã tạo ra các công cụ giúp để tối code frontend, giúp việc code và quản lý các file css, js trở nên đơn giản hơn gấp bội phần. Webpack hiện đang là công cụ được sử dụng nhiều nhất, và Laravel Mix thì được xây dựng dựa trên Webpack.
Về cơ bản Laravel Mix sẽ giúp bạn viết css bằng các css preprocessor, đóng gói (bundle) các file js và minify chúng.
Laravel Mix đã được tích hợp mặc định trong source code Laravel, để sử dụng Laravel Mix, bạn chỉ cần chạy lệnh npm install để cài đặt.
Điểm danh trước 3 tính năng “Premium” trong Laravel mà chưa hẳn ai cũng biết, các tính năng còn lại mình sẽ tổng hợp và chia sẻ với các bạn qua Phần 2, Phần 3, … Phần N nhé.
Khi cần điều khiển truy nhập tới một đối tượng được thực hiện từ quá trình khởi tạo nó cho tới khi thực sự cần sử dụng nó. Hoặc cần bảo vệ quyền truy xuất vào các phương thức của object thực. Trong trường hợp như vậy, ta nên dùng mẫu thiết kế Proxy.
Proxy Pattern là gì?
Provide a surrogate or placeholder for another object to control access to it.
Proxy Pattern là một trong những Pattern thuộc nhóm cấu trúc (Structural Pattern).
Proxy có nghĩa là “ủy quyền” hay “đại diện”. Mục đích xây dựng Proxy pattern cũng chính vì muốn tạo ra một đối tượng sẽ ủy quyền, thay thế cho một đối tượng khác.
Proxy Pattern là mẫu thiết kế mà ở đó tất cả các truy cập trực tiếp đến một đối tượng nào đó sẽ được chuyển hướng vào một đối tượng trung gian (Proxy Class). Mẫu Proxy (người đại diện) đại diện cho một đối tượng khác thực thi các phương thức, phương thức đó có thể được định nghĩa lại cho phù hợp với múc đích sử dụng.
Để đơn giản hơn bạn có thể nghĩ đến khái niệm HTTP proxy trong mạng máy tính, nó là một gateway giữa trình duyệt (client) và máy chủ (server). HTTP proxy giúp nâng cao trải nghiệm người dùng, tăng tốc với lưu đệm các dữ liệu, loại bỏ các trang quảng cáo, giới hạn các vùng thông tin được xem… Proxy Pattern cũng có chung một mục đích như với HTTP proxy.
Proxy Pattern còn được gọi là Surrogate (thay thế) hoặc Placeholder (trình giữ chỗ).
Virtual Proxy : Virtual Proxy tạo ra một đối tượng trung gian mỗi khi có yêu cầu tại thời điểm thực thi ứng dụng, nhờ đó làm tăng hiệu suất của ứng dụng.
Protection Proxy : Phạm vi truy cập của các client khác nhau sẽ khác nhau. Protection proxy sẽ kiểm tra các quyền truy cập của client khi có một dịch vụ được yêu cầu.
Remote Proxy : Client truy cập qua Remote Proxy để chiếu tới một đối tượng được bảo về nằm bên ngoài ứng dụng (trên cùng máy hoặc máy khác).
Monitor Proxy : Monitor Proxy sẽ thiết lập các bảo mật trên đối tượng cần bảo vệ, ngăn không cho client truy cập một số trường quan trọng của đối tượng. Có thể theo dõi, giám sát, ghi log việc truy cập, sử dụng đối tượng.
Firewall Proxy : bảo vệ đối tượng từ chối các yêu cầu xuất xứ từ các client không tín nhiệm.
Cache Proxy : Cung cấp không gian lưu trữ tạm thời cho các kết quả trả về từ đối tượng nào đó, kết quả này sẽ được tái sử dụng cho các client chia sẻ chung một yêu cầu gửi đến. Loại Proxy này hoạt động tương tự như Flyweight Pattern.
Smart Reference Proxy : Là nơi kiểm soát các hoạt động bổ sung mỗi khi đối tượng được tham chiếu.
Synchronization Proxy : Đảm bảo nhiều client có thể truy cập vào cùng một đối tượng mà không gây ra xung đột. Khi một client nào đó chiếm dụng khóa khá lâu khiến cho số lượng các client trong danh sách hàng đợi cứ tăng lên, và do đó hoạt động của hệ thống bị ngừng trệ, có thể dẫn đến hiện tượng “tắc nghẽn”.
Copy-On-Write Proxy : Loại này đảm bảo rằng sẽ không có client nào phải chờ vô thời hạn. Copy-On-Write Proxy là một thiết kế rất phức tạp.
Cung cấp mức truy cập gián tiếp vào một đối tượng.
Tham chiếu vào đối tượng đích và chuyển tiếp các yêu cầu đến đối tượng đó.
Cả Proxy và đối tượng đích đều kế thừa hoặc thực thi chung một lớp giao diện. Mã máy dịch cho lớp giao diện thường “nhẹ” hơn các lớp cụ thể và do đó có thể giảm được thời gian tải dữ liệu giữa server và client.
Các thành phần tham gia vào mẫu Proxy Pattern:
Subject : là một interface định nghĩa các phương thực để giao tiếp với client. Đối tượng này xác định giao diện chung cho RealSubject và Proxy để Proxy có thể được sử dụng bất cứ nơi nào mà RealSubject mong đợi.
Proxy : là một class sẽ thực hiện các bước kiểm tra và gọi tới đối tượng của class service thật để thực hiện các thao tác sau khi kiểm tra. Nó duy trì một tham chiếu đến RealSubject để Proxy có thể truy cập nó. Nó cũng thực hiện các giao diện tương tự như RealSubject để Proxy có thể được sử dụng thay cho RealSubject. Proxy cũng điều khiển truy cập vào RealSubject và có thể tạo hoặc xóa đối tượng này.
RealSubject : là một class service sẽ thực hiện các thao tác thực sự. Đây là đối tượng chính mà proxy đại diện.
Client : Đối tượng cần sử dụng RealSubject nhưng thông qua Proxy.
Ứng tuyển các vị trí việc làm Java lương cao trên TopDev
Ví dụ Virtual Proxy
Trì hoãn việc tạo ra real subject bên trong proxy class. Chỉ đến khi cần, proxy class mới thật sự khởi tạo real class. Loại Proxy này làm việc theo cơ chế Lazy Loading.
Lazy Loading là một khái niệm mà ứng dụng trì hoãn việc tải các đối tượng cho đến thời điểm mà người dùng cần nó. Nói một cách đơn giản là tải theo yêu cầu của người dùng chứ không phải tải đối tượng không cần thiết. Lợi ích của việc này là giảm thiểu số lượng yêu cầu, giảm thiểu số lượng tài nguyên thừa cần tải cho tới khi người dùng cần đến chúng thực sự. Chúng ta đã thấy điều này qua cơ chế Lazy load của Hibernate.
Nó giải quyết vấn đề rất lớn về hiệu suất, lý do là vì proxy class có chi phí khởi tạo rất ít, việc duy trì nó không mất nhiều tài nguyên hệ thống. Trong khi đó Real class thường rất tốn chi phí , vì thế với virtual proxies, chỉ khi nào cần thiết, real class mới được khởi tạo.
Ví dụ một website hiển thị ảnh, có thể có rất nhều ảnh trên một trang hay một ảnh được hiển thị nhiều lần. Trường hợp này chúng ta chỉ cần load ảnh khi nó cần hiển thị (khi ta scroll tới nơi đặt image) hoặc là nó chưa được load (không như các website truyền thống là load hình ngay khi load website, nó rất tốn tài nguyên và đôi khi không cần thiết do người dùng không scroll tới nơi đặt image, có thể load 1 ảnh nhiều lần).
Image.java
package com.gpcoder.patterns.structural.proxy.virtual;
public interface Image {
void showImage();
}
RealImage.java
package com.gpcoder.patterns.structural.proxy.virtual;
public class RealImage implements Image {
private String url;
public RealImage(String url) {
this.url = url;
System.out.println("Image loaded: " + this.url);
}
@Override
public void showImage() {
System.out.println("Image showed: " + this.url);
}
}
ProxyImage.java
package com.gpcoder.patterns.structural.proxy.virtual;
public class ProxyImage implements Image {
private Image realImage;
private String url;
public ProxyImage(String url) {
this.url = url;
System.out.println("Image unloaded: " + this.url);
}
@Override
public void showImage() {
if (realImage == null) {
realImage = new RealImage(this.url);
} else {
System.out.println("Image already existed: " + this.url);
}
realImage.showImage();
}
}
Client.java
package com.gpcoder.patterns.structural.proxy.virtual;
public class Client {
public static void main(String[] args) {
System.out.println("Init proxy image: ");
ProxyImage proxyImage = new ProxyImage("http://gpcoder.com/favicon.ico");
System.out.println("---");
System.out.println("Call real service 1st: ");
proxyImage.showImage();
System.out.println("---");
System.out.println("Call real service 2nd: ");
proxyImage.showImage();
}
}
Output của chương trình:
Init proxy image:
Image unloaded: http://gpcoder.com/favicon.ico
---
Call real service 1st:
Image loaded: http://gpcoder.com/favicon.ico
Image showed: http://gpcoder.com/favicon.ico
---
Call real service 2nd:
Image already existed: http://gpcoder.com/favicon.ico
Image showed: http://gpcoder.com/favicon.ico
Như bạn thấy image chỉ thật sử được load lên khi proxy class gọi hàm.
Ví dụ Protection proxy
Yêu cầu người gọi proxy class phải chứng thực trước khi proxy class truy xuất vào real class. Cái này rất hữu dụng khi bạn bạn viết library cho một bên khác sử dụng và yêu cầu họ xác thực trước khi gọi hàm.
package com.gpcoder.patterns.structural.proxy.protection;
public class UserServiceImpl implements UserService {
private String name;
public UserServiceImpl(String name) {
this.name = name;
}
@Override
public void load() {
System.out.println(name + " loaded");
}
@Override
public void insert() {
System.out.println(name + " inserted");
}
}
UserServiceProxy.java
package com.gpcoder.patterns.structural.proxy.protection;
public class UserServiceProxy implements UserService {
private String role;
private UserService userService;
public UserServiceProxy(String name, String role) {
this.role = role;
userService = new UserServiceImpl(name);
}
@Override
public void load() {
userService.load();
}
@Override
public void insert() {
if (isAdmin()) {
userService.insert();
} else {
throw new IllegalAccessError("Access denied");
}
}
private boolean isAdmin() {
return "admin".equalsIgnoreCase(this.role);
}
}
Client.java
package com.gpcoder.patterns.structural.proxy.protection;
public class Client {
public static void main(String[] args) {
UserService admin = new UserServiceProxy("gpcoder", "admin");
admin.load();
admin.insert();
UserService customer = new UserServiceProxy("customer", "guest");
customer.load();
customer.insert();
}
}
Output của chương trình:
gpcoder loaded
gpcoder inserted
customer loaded
Exception in thread "main"
java.lang.IllegalAccessError: Access denied
at com.gpcoder.patterns.structural.proxy.rotection.UserServiceProxy.insert(UserServiceProxy.java:23)
at com.gpcoder.patterns.structural.proxy.rotection.Client.main(Client.java:11)
Các bạn thấy khi Client muốn gọi hàm insert(), trong Proxy luôn xác thực quyền của user trước khi thực hiện nó.
Ví dụ Remote Proxy
Với Remote Proxy, proxy class và real class nằm ở 2 địa chỉ khác nhau. Thông qua network, proxy class sẽ encode và gửi request tới real class để khởi tạo, truy xuất, …
Chúng ta có thể thấy remote Proxy khi implements Java RMI hoặc thông dụng nhất là ở WebService. Bên phía client sẽ có 1 proxy class, client sẽ khởi tạo proxy class và gọi tới real class nằm ở 1 địa chỉ khác.
Ví dụ Smart Proxy
Proxy Class sẽ thay đổi hoặc thêm 1 số thao tác trước khi gọi tới real class. Một số trường hợp thường thấy là:
Ở lần đâu tiên khởi tạo real class, Proxy class sẽ lưu lại thông tin của real class vào cache và hữu dụng cho lần tái sử dụng sau. Ta có thể thấy việc xuất hiện ở lazy-load ở các connection xuống database.
Trước khi gọi real class, ta có thể lock real class lại và không cho các thread khác phải chờ cho tới khi thread hiện tại release real class.
Đếm số lượng reference tới real class.
Ở Virtual Proxy, mình cũng có lồng 1 ví dụ của Smart Proxy vào. Khi ta khởi tạo RealImage, mình đã lưu cache RealImage lại và lần sau gọi hàm ShowImage(), ta không phải khởi tạo lại RealImage.
Lợi ích của Proxy Pattern là gì?
Cãi thiện Performance thông qua lazy loading, chỉ tải các tài nguyên khi chúng được yêu cầu.
Nó cung cấp sự bảo vệ cho đối tượng thực từ thế giới bên ngoài.
Giảm chi phí khi có nhiều truy cập vào đối tượng có chi phí khởi tạo ban đầu lớn.
Dễ nâng cấp, bảo trì.
Sử dụng Proxy Pattern khi nào?
Khi muốn bảo vệ quyền truy xuất vào các phương thức của object thực.
Khi cần một số thao tác bổ sung trước khi thực hiện phương thức của object thực.
Khi tạo đối tượng ban đầu là theo yêu cầu hoặc hệ thống yêu cầu sự chậm trễ khi tải một số tài nguyên nhất định (lazy loading).
Khi có nhiều truy cập vào đối tượng có chi phí khởi tạo ban đầu lớn.
Khi đối tượng gốc tồn tại trong môi trường từ xa (remote).
Khi đối tượng gốc nằm trong một hệ thống cũ hoặc thư viện của bên thứ ba.
Khi muốn theo dõi trạng thái và vòng đời đối tượng.
So sánh Proxy Pattern với Decorator Pattern
Cấu trúc của Proxy Pattern và Decorator Pattern là tương tự nhau (bạn có thể coi ở class diagram). Hai Pattern này đều Wrap một đối tượng thực bên trong nó. Tuy nhiên, khác nhau thật sự giữa Proxy Pattern và Decorator Pattern nằm ở mục đích sử dụng. Với Decorator Pattern, người sử dụng sẽ nhắm tới mục tiêu là có thể thêm tính năng động vào một đối tượng có trước, trong khi đó Proxy Pattern cho phép ta tạo ra một đại diện cho một đối tượng khác.
Bài viết được sự cho phép của tác giả Trần Văn Dem
Hiện nay việc tìm kiếm các hướng dẫn về sử dụng hibernate, spring jpa là rất dễ. Tuy nhiên các hướng dẫn này thường chỉ giới thiệu cách sử dụng, quản lý Id của Entity thông qua strategy : AUTO,TABLE,SEQUENCE,IDENTITY. Nhưng rất ít hoặc rất khó tìm bài hướng dẫn nào nói cụ thể về các kiểu strategy này và cách sử dụng hiệu trong dự án. Bài viết này tôi sẽ giúp các bạn hiểu rõ hơn về các loại strategy này từ đó có thể tự tin lựa chọn trong project tránh các lỗi không đáng có.
1. sequence vs auto_increment
Trước khi tìm hiểu về các loại strategy thì chúng ta nên phân biệt các loại dữ liệu này. Trước tiên thì 2 loại này sẽ là cách cơ sở dữ liệu của bạn dùng để tạo id cho bảng lưu trữ dữ liệu.
auto increment
Cách sử dụng auto_increment
createtableuser
(
idint auto_increment
primary key,
namevarchar(255) null,
age intnull
);
insertintouser (age, name) values (104, 'mai4')
insertintouser (age, namevalues (103, 'mai3')
SELECT * FROMuser;
+----+------+------+
| id | name | age |
+----+------+------+
| 1 | mai4 | 104 |
| 2 | mai3 | 103 |
+----+------+------+
2 rows in set (0,00 sec)
Kiểu dữ liệu này chắc hầu hết mọi người đều đã biết và sử dụng thường xuyên kiểu này. Các loại database sau hỗ trợ: mysql, mariadb,…
Tạo 1 entity đơn giản như bên dưới lưu ý allocationSize phải đúng với giá trị INCREMENT BY khi tạo sequence. Loại strategy này sẽ hỗ trợ việc batch insert. Ví dụ bên dưới thực hiện với mariadb.
Ta thấy các id được service tạo ra nó có thứ tự liên tiếp khác với những id được chúng ta tạo với 2 câu lệnh insert đầu tiên. Hình ảnh bên dưới mô tả cơ chế GenerationType.SEQUENCE của hibernate.
Đầu tiên hibernate sẽ gọi vào database để lấy nextVal của sequece lưu lại nextVal này và tiếp tự generate id của entity từ nextVal – allocateSize-1 đến nextVal hoạt động tạo id này sẽ không cần truy cập vào database nên sẽ tối ưu về mặt tốc độ. Mặt khác vì kiểu sequence là kiểu đặc biệt nên 2 service cùng gọi để lấy nextVal tại 1 thời điểm thì kết quả trả về cho 2 service là khác nhau cho nên sẽ không có trường hợp bị trùng id giữa các service khác nhau sử dụng cùng một sequence để tạo id.
3. strategy = GenerationType.IDENTITY
Chúng ta sẽ sử dụng loại strategy này với mysql, strategy này ứng với dạng auto_increment. Chỉnh sửa một chút về file config, Entity, thư viện.
Vì trong hibernate khi batch insert chúng ta bắt buộc phải truyền theo Id, nhưng dạng này lại dựa vào cơ chế auto_increment của database nên lúc insert chúng ta chưa biết được id của nó là gì khiến cho dạng này hibernate sẽ không hỗ trợ batch insert mặc dù chúng ta vẫn cấu hình batch insert cho nó. Thực hiện gọi đến route và ta được kết quả.
Bằng các cách tạo id hiện nay, các service của chúng ta không cần phải trọc vào database vẫn có thể tạo ra các id khác nhau (Mình sẽ viết phương pháp này trong bài tiếp) . Ngay cả khi chúng ta thực hiện truyền id này vào trong entity sử dụng strategyGenerationType.IDENTITY hibernate cũng không thực hiện batch insert, thậm trí khi truyền Id chúng ta lại có một hiệu năng còn tệ hơn.
@PutMapping("/multi/user")
String insertMultiUser() {
List<User> savedUser = new ArrayList<>();
for (int i = 1; i < 6; i++) {
Useruser = newUser();
user.setId(1000 * i);
intindex = count.addAndGet(1);
user.setName("demtv" + index);
user.setAge(index);
savedUser.add(user);
}
repository.saveAll(savedUser);
return "done";
}
Thực hiện gọi route ta có kết quả
{"name":"Batch-Insert-Logger", "time":1, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["1000"]]}
Hibernate: insertintouser (age, name) values (?, ?)
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["insert into user (age, name) values (?, ?)"], "params":[["1","demtv1"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["2000"]]}
Hibernate: insertintouser (age, name) values (?, ?)
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["insert into user (age, name) values (?, ?)"], "params":[["2","demtv2"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["3000"]]}
Hibernate: insertintouser (age, name) values (?, ?)
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["insert into user (age, name) values (?, ?)"], "params":[["3","demtv3"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":1, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["4000"]]}
Hibernate: insertintouser (age, name) values (?, ?)
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["insert into user (age, name) values (?, ?)"], "params":[["4","demtv4"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["5000"]]}
Hibernate: insertintouser (age, name) values (?, ?)
{"name":"Batch-Insert-Logger", "time":1, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["insert into user (age, name) values (?, ?)"], "params":[["5","demtv5"]]}
Theo kết quả query của hibernate bên trên thì trước mỗi câu insert chúng ta đều phải có một câu select để kiểm tra id của chúng ta truyền vào đã tồn tại trong bảng hay chưa? Rồi mới đến bước insert vào database. Điều đó khiến hiệu năng giảm xuống. Tiếp theo check kết quả mysql chúng ta mới thấy sự bất ngờ.
Hibernate: select next_val as id_val fromserialforupdate
{"name":"Batch-Insert-Logger", "time":1, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select next_val as id_val from serial for update"], "params":[[]]}
Hibernate: updateserialset next_val= ? where next_val=?
{"name":"Batch-Insert-Logger", "time":1, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["update serial set next_val= ? where next_val=?"], "params":[["11","1"]]}
Hibernate: select next_val as id_val fromserialforupdate
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select next_val as id_val from serial for update"], "params":[[]]}
Hibernate: updateserialset next_val= ? where next_val=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["update serial set next_val= ? where next_val=?"], "params":[["21","11"]]}
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
{"name":"Batch-Insert-Logger", "time":2, "success":true, "type":"Prepared", "batch":true, "querySize":1, "batchSize":5, "query":["insert into user (age, name, id) values (?, ?, ?)"], "params":[["1","demtv1","1"],["2","demtv2","2"],["3","demtv3","3"],["4","demtv4","4"],["5","demtv5","5"]]}
Chúc mừng chúng ta cuối cùng đã thực hiện được batch insert với mysql. Nhưng sự thật có đáng để vui hay không? Theo như log bên trên mỗi lần thực hiện insert hibernate lại vào bảng serial lấy ra id tiếp theo Hibernate: select next_val as id_val from serial for update Cơ chế này sẽ làm giảm hiệu năng chương trình đi rất nhiều. Tiếp đến câu lệnh hibernate dùng để lấy id cũng gây lock table serial lại khiến hiệu năng lại giảm thêm. Cơ chế này không phải cơ chế SEQUENCE mà là cơ chế “TABLE” một trong các cơ chế mọi người nên tránh sử dụng. Chỉ sủ dụng khi loại database của mọi người không hỗ trọ cơ chế “auto_increment” và “sequence”. Với mysql hibernate chỉ sử dụng tốt nhất với strategy = GenerationType.IDENTITY
3.2 Không sử dụng strategy
Giả sử với phương pháp tạo Id, chúng ta không cần thiết phải dựa vào database để tạo id. Chúng ta dùng id tự tạo ra để insert vào database.
@PutMapping("/multi/user")
String insertMultiUser() {
List<User> savedUser = new ArrayList<>();
for (int i = 1; i < 6; i++) {
Useruser = newUser();
user.setId(1000 * (i + 1));
intindex = count.addAndGet(1);
user.setName("demtv" + index);
user.setAge(index);
savedUser.add(user);
}
repository.saveAll(savedUser);
return "done";
}
Chúng ta gọi đến route và check log
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["2000"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["3000"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["4000"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["5000"]]}
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ fromuser user0_ where user0_.id=?
{"name":"Batch-Insert-Logger", "time":0, "success":true, "type":"Prepared", "batch":false, "querySize":1, "batchSize":0, "query":["select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?"], "params":[["6000"]]}
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
Hibernate: insertintouser (age, name, id) values (?, ?, ?)
{"name":"Batch-Insert-Logger", "time":2, "success":true, "type":"Prepared", "batch":true, "querySize":1, "batchSize":5, "query":["insert into user (age, name, id) values (?, ?, ?)"], "params":[["1","demtv1","2000"],["2","demtv2","3000"],["3","demtv3","4000"],["4","demtv4","5000"],["5","demtv5","6000"]]}
Cách này cũng giống như khi sử dụng strategy=IDENTITY cũng gây hiệu năng giảm sút vì cần các câu select trước các câu insert.
4. Bulk insert with mariadb
Các bạn có thể biết cách batch insert không phải là cách insert nhanh nhất khi thực hiện insert dữ liệu vào database. Nó chỉ tiết kiệm được IO truyền qua mạng bằng cách gửi nhiều lệnh insert lên database thực hiện một lần. Kiểu insert nhanh nhất vào database phải là bulk insert rất tiếp hibernate không hỗ trợ kiểu này. Nhưng với mariadb và mysql chúng ta có config rewriteBatchedStatements nếu set config này rewriteBatchedStatements=true thì jdbc sẽ viết lại các câu lệnh batch insert thành bulk insert.
Chú ý phần argument của câu lệnh insert nó đã được viết lại thành bulk insert điều này tăng hiệu năng của chương trình.
5. Kết luận
Sau khi thử nghiệm các loại strategy khác nhau chúng ta có kết luận sau:
Sử dụng SEQUENCE khi database hỗ trợ dạng này. Kể cả hỗ trợ SEQUENCE lẫn IDENTITY thì vẫn chọn dạng SEQUENCE vì hibernate hỗ trợ tốt nhất với dạng này.
Nếu database hỗ trợ IDENTITY thì chỉ nên dùng IDENTITY đùng sử dụng các loại khác
Không sử dụng loại TABLE trừ khi database của bạn không hỗ trợ “auto_increment” hoặc “sequence”
Không nên truyền id khi thực hiện insert trong hibernate nếu không hiệu năng chương trình của bạn sẽ có vấn đề
Sử dụng config “rewriteBatchedStatements” với mariadb, mysql để tăng hiệu năng của chương trình.
Trên môi trường local, chúng ta khởi động queue bằng cách chạy command:
php artisan queue:work
Nhưng trên môi trường production thì không ai rảnh mà lúc nào cũng bật một terminal để chạy command trên cả, mà sẽ có cách khác, và trong bài viết ngắn gọn này mình sẽ chỉ bạn điều đó.
I. Supervisor
1.1 Cấu hình supervisor để chạy queue
Supervisor là một chương trình giám sát tiến trình trên hệ điều hành Linux, mặt khác Laravel thường được deploy trên các server Linux, vì thế mình sẽ sử dụng Supervisor để giám sát việc chạy queue Laravel.
Hiểu nôm na, Supervisor sẽ giúp chúng ta chạy ngầm cái command php artisan queue:work ngay cả khi tắt terminal.
Để sử dụng supervisor làm “giám sát viên” cho queue, ta thực hiện các bước sau:
Bước 1: Cài đặt Supervisor trên Linux (ở đây mình sử dụng Ubuntu)
sudo apt-get install supervisor
Bước 2: Cấu hình supervisor
Mỗi một tiến trình do Supervisor giám sát sẽ được cấu hình ở một file dạng *.conf nằm trong thư mục /etc/supervisor/conf.d. Nên mình sẽ tạo ra một file có tên là laravel-workder.conf để cấu hình tiến trình chạy queue của Laravel.
sudo vim /etc/supervisor/conf.d/laravel-workder.conf
Nội dung của file laravel-workder.conf như sau:
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/your/project/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
# user thực hiện command 'php artisan queue:work'
# nhớ thay bằng user có quyền thực hiện command trên nhé
user=forge
numprocs=8
redirect_stderr=true
# Các vấn đề sẽ được log vào đây
stdout_logfile=/path/to/your/project/worker.log
Nhớ thay các đoạn bôi đỏ thành thông tin phù hợp với dự án của bạn, sau đó lưu file lại.
Khi sử dụng Supervisor để chạy queue Laravel, thường có một số vấn đề (lỗi) kèm hướng khắc phục như sau:
Queue không chạy
Có rất nhiều nguyên nhân dẫn đến queue không chạy, vì thế hãy đọc file log worker.log để biết thêm thông tin (cũng nên kết hợp đọc cả file storage/logs/laravel.log nữa).
Vẫn chạy “job cũ“
Code trong job được update, thế nhưng nó không chạy theo code mới, mà lại chạy theo code cũ. Gặp trường hợp này, hãy thử khởi động lại supervisor:
sudo service supervisor restart
II. Queue Driver
Queue đã tự động chạy với Supervisor, giờ chúng ta tìm hiểu kỹ hơn về các queue driver có trong Laravel.
Queue driver là các “loại queue” có trong Laravel, chúng đều có mục đích là giúp queue có thể hoạt động, nhưng mỗi loại queue lại có các tính chất (hiệu năng, cách cài đặt, cách chạy) khác nhau, và tùy từng dự án mà chúng ta sẽ sử dụng các loại queue khác nhau.
Từ Laravel 6.x, Queue driver được gọi là Queue connection, chỉ là đổi cách gọi tên, còn chúng vẫn là một.
2.1 Sync
Queue sync là queue mà … dùng như không dùng. Các job khi đưa vào queue sẽ được thực hiện ngay lập tức. Cũng có thể hiểu, khi cấu hình queue driver là sync tức là bạn đã tắt queue trong Laravel.
Queue sync chỉ nên sử dụng để dev trên local, không nên để trên production.
Cách cài đặt
Mở file .env, tìm dòng QUEUE_DRIVER=XXX, đổi thành QUEUE_DRIVER=sync.
Lưu ý: với Laravel 6.x trở nên thì QUEUE_DRIVER đổi thành QUEUE_CONNECTION.
2.2 Database
Với queue database, các job sẽ được lưu vào trong database để chạy dần dần. Vì lưu trữ job trong database, nên chúng ta sẽ cần tạo một vài table mới để lưu trữ, nhưng không sao, laravel đã tạo sẵn cho bạn command để cài đặt rồi.
Cách cài đặt
Chạy command sau để tạo bảng lưu trữ các job:
php artisan queue:tablephp artisan migrate
Cấu hình .env
QUEUE_DRIVER=database
Queue database cũng phù hợp để sử dụng trên production.
2.3 Redis
Redis là một dạng database lưu trữ trên RAM, đặc điểm của nó là tốc độ đọc – ghi rất nhanh, rất phù hợp để làm nơi lưu trữ các job của queue. Để sử dụng queue driver là redis, trước tiên bạn cần cấu hình thông tin kết nối tới redis ở config/database.php trước đã:
// config/database.php
// ...
'redis' => [
'client' => 'predis',
// Hãy đảm bảo các thông tin kết nối tới redis là chính xác
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
],
Bạn có thể tìm hiểu thêm về cách cài đặt và cấu hình redis database theo tài liệu của Laravel.
Cách cài đặt
Về cơ bản, bạn chỉ cần cấu hình thông tin kết nối tớ redis ở file config/database.php là đủ, nhưng bạn cũng nên xem qua file config/queue.php
Công nghệ Blockchain mang một tiềm năng to lớn, được xem là “chìa khóa” cho chuyển đổi số và mở ra một xu hướng mới cho nhiều lĩnh vực trong tương lai. Vậy công nghệ blockchain là gì? Các đặc điểm nổi bật của blockchain? Và ứng dụng nó như thế nào?
Công nghệ Blockchain là gì?
Blockchain là công nghệ chuỗi khối, cho phép chia sẻ thông tin một cách minh bạch và an toàn dựa trên hệ thống mã hóa vô cùng phức tạp. Dữ liệu sẽ được lưu trữ trong các khối, liên kết với nhau trong một chuỗi và được mở rộng theo thời gian.
Mỗi khối sẽ chứa đựng các thông tin về dữ liệu giao dịch và liên kết với khối trước đó nên việc can thiệp thay đổi thông tin là điều không thể xảy ra.
Một điều khác biệt của blockchain so với các công nghệ khác là thông tin không nằm tập trung ở một máy chủ nào cả, cũng không ai kiểm soát được nó, mọi thông tin sẽ được sao lưu trên nhiều máy chủ khác nhau. Thiết kế của mạng lưới này giúp chống lại sự thay đổi của dữ liệu và quản lý dưới mạng lưới phi tập trung. Ngay cả khi một phần của hệ thống blockchain sụp đổ thì các nút khác vẫn sẽ tiếp tục lưu trữ và giữ cho mạng lưới hoạt động bình thường.
Các chuỗi blockchain không thể làm giả và phá hủy: Chỉ khi máy Internet trên toàn cầu biến mất blockchain mới bị phá hủy.
Bất biến: Dữ liệu không thể được sửa chữa nếu giao dịch đã xảy ra.
Bảo mật: Các thông tin và dữ liệu về các chuỗi blockchain được phân tán và an toàn tuyệt đối.
Minh bạch: AI sẽ theo dõi đườngđi của blockchain từ địa chỉ này qua địa chỉ khác và ghi lại toàn bộ lịch sử đó.
Hợp đồng thông minh: Đây là một dạng hợp đồng kỹ thuật số được nhúng vào đoạn code if-this-then-that (IFTTT) cho phép chúng tự động thực thi khi đáp ứng các điều kiện đã định sẵn mà không cần can thiệp bởi bên thứ ba.
Công nghệ blockchain và ứng dụng
Blockchain là một công nghệ mới và ngày càng chứng minh được khả năng ứng dụng tuyệt vời của nó vào thực tiễn. Dưới đây là một số ứng dụng điển hình của công nghệ blockchain trong nhiều lĩnh vực.
Truyền thông và viễn thông: Blockchain sẽ giúp các nhà cung cấp dịch vụ truyền thông tối ưu hóa quy trình, tăng cường khả năng bảo mật mạng cũng như quản lý danh tính trong mô hình kinh doanh của mình.
Sản xuất: Công nghệ blockchain mang đến các giải pháp giúp theo dõi quá trình sản xuất, quản lý hàng tồn kho, truy xuất nguồn gốc sản phẩm qua các khâu, theo dõi nguồn cung cấp nguyên liệu sản xuất, ghi nhận thông tin giao dịch,…
Y tế: Blockchain được sử dụng để quản lý tài sản và lưu trữ thông tin sức khỏe bệnh nhân, quản lý chuỗi cung ứng thuốc, thiết bị y tế (nguồn gốc, hạn sử dụng,…), tăng cường tính minh bạch và tự động hóa trong các giao dịch khám chữa bệnh,…
Giáo dục:Công nghệ blockchain giúp lưu trữ các thông tin về quá trình học, các kinh nghiệm thực tế, trình độ học vấn, kỷ luật,… tránh tình trạng ứng viên gian lận trong quá trình xin học bổng, thăng tiến. Blockchain còn giúp thực hiện các khoản nội quy đào tạo của nhà trường, xử lý các trường hợp vi phạm và cải thiện quy trình làm việc.
Tài chính & ngân hàng: Khả năng tạo hợp đồng thông minh của blockchain sẽ giải quyết được các rủi ro khi giao dịch, loại bỏ tình trạng tập trung quyền lực, cho phép giao dịch ngay cả khi không có trung gian xác minh. Người dùng sẽ tiết kiệm được chi phí, tăng tốc độ giao dịch và hạn chế rủi ro trong quá trình thanh toán.
Thương mại điện tử: Công nghệ blockchain sẽ giải quyết các vấn đề liên quan đến nguồn gốc sản phẩm, quá trình vận chuyển bằng các hợp đồng thông minh, tạo điều kiện cho các doanh nghiệp đa quốc gia dễ dàng ký kết.
Nông nghiệp:Blockchain được ứng dụng trong nông nghiệp giúp lưu trữ thông tin giao dịch, tăng tính minh bạch của thông tin trong quá trình vận chuyển sản phẩm từ cơ sở sản xuất đến cơ sở chế biến, nhà phân phối, cửa hàng hay siêu thị. Điều này giúp truy xuất nguồn gốc hiệu quả, nâng cao lòng tin cho người tiêu dùng.
Ngoài ra, công nghệ blockchain còn được ứng dụng ở nhiều lĩnh vực khác như vận tải và logistics, ngành bán lẻ, du lịch, bảo hiểm, năng lượng, xây dựng,…
Thành công lớn nhất của công nghệ blockchain là tạo ra “hợp đồng thông minh”, các giao dịch thỏa thuận trong hợp đồng sẽ được xác nhận mà không cần thông qua bên trung gian. Mọi giao dịch đều an toàn và minh bạch, khó có thể làm giả và nếu có chắc chắn sẽ để lại dấu vết.
Công nghệ blockchain đã mở ra một xu hướng mới cho các lĩnh vực như tài chính ngân hàng, bảo hiểm, kế toán kiểm toán, y tế, game,… Kéo theo cơn khát nhân sự blockchain nóng hơn bao giờ hết.
Trong thời đại công nghệ, nhu cầu bảo mật, kết nối và tiện lợi của khách hàng ngày càng cao, việc nắm bắt xu hướng công nghệ mới sẽ tạo lợi thế khác biệt để thương hiệu vươn lên trước đối thủ cạnh tranh. Hiện nay đã có rất nhiều công ty và tập đoàn lớn bắt tay vào xây dựng blockchain như Facebook, Apple, Alibaba, Ford,… tạo nên một làn sóng công nghệ mới cho tương lai.
Tóm lại, công nghệ blockchain ra đời đã và đang trở thành một điểm sáng trong nền khoa học 4.0 của thế kỷ 21. Đây là thời điểm thích hợp để các công ty/doanh nghiệp khai thác và tận dụng công nghệ mới này một các tối ưu và hiệu quả nhất. Hy vọng bài viết này đã giúp bạn hiểu rõ hơn về công nghệ blockchain, chúc bạn có những định hướng tốt trong trong tương lai.
Vạn sự khởi đầu nan, câu nói này chưa bao giờ sai, kể cả trong việc học lập trình cũng vậy. Bài viết này mình sẽ kể ra những cái “khó” mà mình gặp phải trong những ngày đầu tiên học lập trình, để xem giữa mình và bạn có đặc điểm chung nào không nhé.
I. Nản do phải học nhiều thứ
Trước khi học lập trình, mình có ước mơ là sẽ tạo ra một phần mềm gì đó thật ngầu, làm thay đổi thế giới, và trở nên giàu có nhờ phần mềm đó. Nhưng khi bắt đầu học, thì mới thấy cái ước mơ đầu quá xa vời. Vì để tạo ra một phần mềm vĩ đại như thế, mình cần phải học rất nhiều thứ (cho tới bây giờ cũng chưa học hết). Khi biết được điều này, thật sự mình cảm thấy nản và muốn bỏ cuộc. Nhưng nghĩ kỹ thì lại thấy làm gì có gì dễ dàng đâu, thôi thì giảm mục tiêu xuống vậy.
– Trước khi học lập trình: Mình sẽ tạo ra một con game làm “điên đảo” game thủ thế giới
– Khi học được 1 năm: Mình sẽ tạo ra một cổng thông tin về game lớn nhất Việt Nam
– Khi học được 2 năm: Mình sẽ tạo ra một blog và tự tay viết các tin về game
– Khi học được 3 năm: Mình sẽ dùng một nền tảng blog có sẵn để viết bài thay vì tự code
– Khi học xong: Code gì cũng được, miễn là code
– Khi đi làm: Ai đó fix giúp tôi cái bug này
Nếu bạn có rơi vào trường hợp này giống mình, thì cũng hãy thử giảm mục tiêu xuống xem sao. Giảm mục tiêu không phải là sợ mình không làm được việc lớn, mà là biết lượng sức mình. Hoàn thiện nhiều việc nhỏ giúp mình có kiến thức và kinh nghiệm để sau này làm việc lớn.
Khi học lập trình, mình gặp rất nhiều kiến thức được gắn mác “cơ bản”, nhưng khi học mình lại khó vô cùng (nhất là kiến thức về giải thuật), làm mình có suy nghĩ “có phải mình quá ngu để học lập trình hay không”, và lại bắt đầu chán nản lần 2.
Nhưng một người khác đã nói với mình “cơ bản không có nghĩa là dễ học dù phần lớn kiến thức cơ bản đều dễ học“. Nghĩ thì thấy đúng thật.
kiến thức cơ bản là những kiến thức mang tính cơ sở để học các kiến thức khác, và nó không có “nghĩa vụ” là phải dễ học. Nếu một kiến thức gắn mác “cơ bản”, nghĩa là mình phải học nó, chứ không có nghĩa là mình có thể học nó một cách dễ dàng. Quan điểm này đã giúp mình thay đổi suy nghĩ và tiếp tục học một cách nghiêm túc.
Mình đã bỏ thời gian học hành nghiêm túc, mình đã học hết các kiến thức cơ bản, mình đã có thể tạo ra một giao diện web hoặc một phần mềm giả lập máy tính bỏ túi, và mình cũng tự tin là nắm rõ một vài ngôn ngữ lập trình. Nhưng mình vẫn không thể tạo ra một phần mềm ưng ý. Phần mềm mình tạo ra rất khó sử dụng, thường xuyên gặp lỗi, bố cục lộn xộn, giao diện xấu xí, và mình còn chẳng muốn sử dụng nó chứ đừng nói là cho người khác sử dụng – nói chung là “Học được nhưng làm không được”.
Nhưng mà kệ, đâm lao thì phải theo lao thôi, học được đến đây rồi không lẽ bỏ cuộc.
Mình cũng cho rằng việc “học được nhưng làm không được” là do thiếu kinh nghiệm, nên mình cố gắng code nhiều hơn, cải tiến các dự án cũ cho bớt lỗi và dễ sử dụng hơn, cũng như tham khảo các dự án opensource được tạo ra bởi các developer có kinh nghiệm để học tập.
Mình chẳng nhớ là đã làm bao nhiêu dự án cá nhân (pet project) nữa, chắc phải đến cả trăm cái, qua mỗi dự án như vậy, mình lại rút ra được một chút kinh nghiệm. Lâu dần, tích tiểu thành đại, mình đã nâng cao khả năng code đáng kể.
IV. Một vài khó khăn khác
Một vài khó khăn khác nhỏ hơn, nhưng vẫn đáng nói:
Không quen “mặt bug”: Khi mới học lập trình, có những lỗi rất khó hiểu, mặc dù trình biên dịch hiển thị lỗi rất cụ thể, nhưng đọc vẫn không hiểu. Đành copy lên google xem có ai gặp phải hay chưa rồi xem cách khắc phục của họ. Lâu ngày, bug cũ lặp đi lặp lại thì thành ra “quen mặt”, nên cũng dễ fix hơn.
Không quen “mặt code”: Mỗi ngôn ngữ lập trình lại có cú pháp khác nhau, cái dài cái ngắn, cái có dấu chấm phẩy cái lại không có. Nên thời gian đầu đọc hơi khó hiểu, nên đành phải code nhiều, nhìn nhiều cho quen.
Chọn cách giải nào: Cùng một vấn đề, nhưng có thể có nhiều cách giải, và mình phải tốn khá nhiều thời gian và chất xám để tìm ra cách giải nào là tốt nhất.
V. Lời kết
Bài viết này không chỉ mang tính chất “kể khổ”, mà còn muốn nhắn nhủ tới các bạn newbie rằng “vạn sự khởi đầu nan”. Dù khó khăn của bạn có giống của mình hay không, thì thời gian đầu chắc chắn khó học, nhưng khó ở đây là khó chung chứ không riêng gì bạn, vì thế hãy cố gắng vượt qua nhé. Chúc các bạn thành công.