So sánh chi tiết Golang vs NodeJS
Bài đăng này đã không được cập nhật trong 3 năm
Cuộc chiến giữa Golang vs NodeJS đã diễn ra từ lâu. Trong đó, NodeJS đã chiếm ưu thế trong một khoảng thời gian dài. Tuy nhiên, với sự thay đổi của công nghệ, những nhu cầu mới xuất hiện thì liệu rằng NodeJS có còn chiếm thế thượng phong nữa không? Hay Golang có thực sự nổi trội hơn? Theo dõi bài viết so sánh giữa NodeJS với Golang dưới đây để đưa ra lựa chọn tốt nhất cho dự án tiếp theo của bạn.
Bạn có thể xem bài viết đầy đủ tại 200Lab Education
1. NodeJS: Giới thiệu
Ryan Dahl đã tạo ra NodeJSvà bản phát hành đầu tiên vào năm 2009. Dahl đã xây dựng cross-platform runtime environment này trên Javascript engine V8 của chrome.
Node.js là dynamically-typed vì được xây dựng trên Javascript. Kiểu Runtime environment này giúp đảm nhận toàn bộ một dự án phát triển ứng dụng web với một ngôn ngữ lập trình duy nhất.
NodeJS cũng cung cấp khả năng mở rộng và throughput cao. Kiến trúc event-driven và asynchronous I/O giúp bạn tạo những ứng dụng web real-time một cách dễ dàng.
Kể từ bản ra mắt đầu tiên nhiều sự phát triển đã diễn ra xung quanh NodeJS. Tại thời điểm của bài viết này bản phát hành ổn định mới nhất của nó là 14.7.1.
Javascript là một ngôn ngữ rất phổ biến và điều này có thể ảnh hưởng đến sự phổ biến của NodeJS, nhưng nó không phải là yếu tố duy nhất.
2. NodeJS dùng cho việc gì?
Khi nói về ứng dụng của NodeJS thì không thể bỏ qua việc NodeJS có thể tạo ra những ứng dụng network nhanh một cách dễ dàng. Những ứng dụng NodeJS có thể mở rộng với quy mô đủ tốt. Nó cũng có thể giúp tạo server-side cũng như những ứng dụng networking.
Nếu bạn dự định tạo ra một ứng dụng web real-time với kết nối two-way thì NodeJS là một sự lựa chọn hoàn hảo. Với loại ứng dụng này bạn sẽ cần một server không đợi API trả về dữ liệu.
Những server NodeJS-based có thể đáp ứng được những yêu cầu này. Vì Node.JS cho phép lập trình bất đồng bộ nên các API của NodeJS thì non-blocking. Một NodeJS server sẽ gọi một API và sau đó nó sẽ gọi một API khác thay vì đợi kết quả của cuộc gọi lần trước. Vì NodeJS giúp lập trình event-driven, cơ chế event sẽ cho phép server nhận phản hồi từ lệnh gọi API đầu tiên. Cơ chế event này giúp NodeJS phản hồi các yêu cầu bằng cách sử dụng phương pháp non-blocking, giúp tạo các ứng dụng có thể mở rộng.
Hơn nữa, NodeJS không đệm bất kỳ dữ liệu nào. Điều này làm cho nó trở thành một lựa chọn tốt cho các ứng dụng streaming.
NodeJS giúp bạn tạo các ứng dụng nhanh chóng vì được xây dựng trên JavaScript V8 engine của Chrome.
Các tổ chức sau đây đã sử dụng NodeJS:
- Netflix
- Walmart
- Trello
- Uber
- PayPal
- Medium
- eBay
- NASA
Một số framework nổi tiếng của NodeJS:
- Express.js
- Koa.js
- Sails.js
- Meteor.js
- Derby.js
- Total.js
- Adonis.js
- Nest.js
- Socketio
3. NodeJS: Ưu điểm và nhược điểm
3.1 Ưu điểm của NodeJS:
- Từ quan điểm của một nhà đầu tư, việc lựa chọn runtime environment mã nguồn mở này có thể là một cách để tăng hiệu quả và nhịp độ công việc của nhóm. Các nhà phát triển đánh giá cao khả năng mở rộng, độ nhẹ cũng như sự phong phú của hệ sinh thái đã được đóng gói.
- NodeJS dựa trên JavaScript mà nhiều nhà phát triển đã biết. Đối với một số lượng lớn các nhà phát triển, việc học NodeJS khá dễ dàng.
- Với NodeJS, bạn chỉ sử dụng một runtime environment để viết mã cả front-end và back-end cho ứng dụng web được đề xuất. Đồng nghĩa với việc các dev dễ dàng đồng bộ hóa giữa backend và frontend. Chỉ cần thuê các dev NodeJS là bạn cũng có cả dev Full-stack.
- NodeJS giúp bạn tạo các ứng dụng có hiệu suất cao, như chúng tôi đã đề cập trước đó.
- NodeJS giúp caching các module riêng lẻ dễ dàng hơn
- NodeJS là một lựa chọn tốt để tạo ra các app streaming
- Ngoài khả năng mở rộng cao, NodeJS hoạt động rất tốt với MongoDB, database NoSQL phổ biến.
- NodeJS có một cộng đồng sôi động và ngày càng phát triển để hỗ trợ. Điều này mang lại cho bạn hai lợi thế. Đầu tiên là bạn nhận được sự hỗ trợ nhiệt tình. Thứ hai là cộng đồng này đã tạo ra nhiều công cụ và framework mã nguồn mở tuyệt vời cho NodeJS. Bạn sẽ nhận được năng suất tăng đáng kể khi làm việc với NodeJS.
3.2 Nhược điểm của NodeJS:
- Là một cross-platform đơn luồng (single thread), NodeJS là một lựa chọn hoàn hảo cho các ứng dụng IO chuyên sâu và các ứng dụng non-blocking như web và real-time server hoặc các tiện ích command-line. Tính không đồng bộ của nó loại trừ việc đợi phản hồi từ server - bạn có thể chuyển sang lệnh tiếp theo. Tuy nhiên, khái niệm về vòng lặp sự kiện mà nó sử dụng có thể trở nên khá rắc rối. Khi mọi sự kiện mới được gửi đến cuối hàng đợi, quá trình xử lý trở nên chậm hơn. Điều đó giải thích tại sao NodeJS sẽ không thực sự là ứng dụng phù hợp nhất cho các hoạt động chuyên sâu của bộ xử lý. Điều đó có thể đặt ra một thách thức đối với các nhà phát triển không quen thuộc với lập trình bất đồng bộ. Bạn cần thuê các nhà phát triển có chuyên môn phù hợp.
- NodeJS dựa trên JavaScript là dynamically typed. Nó cũng là weakly typed. Việc mắc lỗi mã hóa liên quan đến variable types là điều thường gặp khi bạn sử dụng loại ngôn ngữ này. Nếu bạn có các lập trình viên tương đối thiếu kinh nghiệm, họ có thể gặp khó khăn để gỡ lỗi các lỗi như vậy. Bạn cần thuê các lập trình viên đủ kinh nghiệm biết họ đang làm gì liên quan đến variable types.
- Nhiều API được sử dụng trong NodeJS thường xuyên thay đổi, điều này có thể gây khó khăn cho nhiều nhà phát triển.
4. Golang: giới thiệu
Một nhóm kỹ sư phần mềm tại Google đã phát triển Go và ngôn ngữ lập trình này còn được gọi là Golang. Robert Griesemer, Rob Pike và Ken Thompson đóng vai trò quan trọng trong việc thiết kế ngôn ngữ lập trình mã nguồn mở này. Đội này đã phát hành Golang lần đầu tiên vào năm 2009.
Có thể bạn quan tâm: Tìm hiểu ngôn ngữ lập trình Golang. Tại sao bạn nên học Golang vào bây giờ?
Nhóm thiết kế và phát triển Go đã nghiên cứu rất kỹ ngôn ngữ C. Họ muốn giữ lại một số điểm mạnh của C trong ngôn ngữ lập trình mới mà họ đang thiết kế. Go có nhiều điểm tương đồng với C về mặt cú pháp. Golang là một ngôn ngữ lập trình statically-typed và compiled.
Ngôn ngữ lập trình này giúp các nhà phát triển sử dụng bộ nhớ một cách an toàn. Quản lý đối tượng, thu gom garbage và hỗ trợ concurrency là một số tính năng chính khác của nó.
Golang đã trải qua rất nhiều cải tiến, nhờ vào cộng đồng các nhà phát triển sôi động. Tại thời điểm viết bài, bản phát hành ổn định mới nhất của Go là 1.16.5.
Golang rất được yêu thích và ngôn ngữ này đang dần trở nên phổ biến.
Nhờ các tính năng mạnh mẽ của Go, bạn có thể sử dụng Go trong một loạt các dự án phát triển khác nhau. Hiệu năng là một trong những điểm mạnh khi bạn nghĩ đến lý do sử dụng Golang. Đó là một ngôn ngữ compiled và việc không có interpreter giúp Go mang lại hiệu năng cực kỳ mạnh mẽ. Go sử dụng tài nguyên bộ xử lý của hệ thống một cách rất hiệu quả, đó là một lợi thế khác liên quan đến hiệu năng.
Vì Golang có thể quản lý bộ nhớ được cấp phát một cách hiệu quả, nên nó giúp bạn viết các ứng dụng đáng tin cậy hơn. Nhiều tổ chức sử dụng Go để phát triển các ứng dụng web. Bạn có thể sử dụng Go để viết các API và các dịch vụ web. Go đã chứng minh được tiện ích của nó trong lập trình hệ thống, lập trình mạng, phát triển big data và phát triển machine learning.
Một số công ty sử dụng Go:
- Uber
- Twitch
- Dailymotion
- SendGrid
- Dropbox
- SoundCloud
Một vài framework quan trọng trong lập trình ngôn ngữ Go;
- Gin
- Beego
- Iris
- Echo
- Revel
- Martini
- Buffalo
5. Golang: Ưu điểm và nhược điểm
5.1 Ưu điểm của Golang:
- Golang giới hạn số lượng các hành động và quyết định cần thiết. Do đó, các nhà phát triển nhận thấy Go rất dễ sử dụng vì ngôn ngữ này có syntax gọn gàng và rõ ràng. Điều này làm cho nó đơn giản hơn các ngôn ngữ khác.
- Vì Go đang trở nên phổ biến, nên sẽ có nhiều nhà phát triển học nó hơn. Điều này sẽ giúp việc thuê các nhà phát triển Go trở nên dễ dàng hơn trong tương lai.
- Bạn sẽ thấy dễ dàng hơn để duy trì các ứng dụng được viết bằng Go vì mã được viết bằng Go rất dễ đọc.
- Go có nhiều điểm tương đồng với C. Vì nhiều lập trình viên biết C, C # hoặc C ++, họ sẽ thấy dễ dàng học Go. Ngay cả với những người mới bắt đầu cũng không quá khó khăn để nắm bắt được ngôn ngữ này bởi vì Go rất đơn giản và trực quan.
- Go cung cấp một thư viện tiêu chuẩn tinh vi, hơn nữa, thư viện này rất dễ sử dụng. Lập trình viên không cần phải nhập các thư viện phức tạp bên ngoài hoặc phải tìm hiểu thêm các kiểu thư viện như vậy. Thư viện chuẩn Go hỗ trợ nhiều chức năng. Bạn có thể sử dụng chúng để hoàn thành nhiều nhiệm vụ và không cần phải viết những đoạn mã phức tạp.
- Go giúp các nhà phát triển viết mã không có lỗi. Vì đó là ngôn ngữ statically-typed, bạn sẽ không mắc phải những lỗi phức tạp liên quan đến variable types. Go có tính năng thu gom garbage hiệu quả và hỗ trợ quản lý bộ nhớ an toàn. Tất cả những yếu tố này làm giảm khả năng xuất hiện lỗi.
- Go giúp viết các ứng dụng an toàn và lợi thế này liên quan nhiều đến cách giúp viết mã không có lỗi. Trong thế giới ngày nay, tội phạm mạng không ngừng tìm kiếm những kẽ hở để khám phá trong các ứng dụng phần mềm. Một ngôn ngữ lập trình làm giảm khả năng xảy ra lỗi sẽ mang lại những lợi thế nhất định.
- Google tích cực hỗ trợ sự phát triển của Go và các công ty thúc đẩy nó. Gã khổng lồ công nghệ sử dụng Go rất nhiều trong các dự án của mình. Bạn có thể chắc chắn rằng Golang sẽ nhận được sự hỗ trợ phát triển mà nó cần.
- Các lập trình viên có thể tận dụng các tài liệu tuyệt vời có sẵn cho Go. Khi bạn viết một chương trình trong Go và bạn quên tạo đủ tài liệu, ngôn ngữ sẽ cảnh báo bạn.
- Go không cần interpreter vì nó là một ngôn ngữ compiled. Điều này giúp nó mang lại hiệu năng cao.
- Go hỗ trợ concurrency, giúp lập trình viên xây dựng hệ thống với mức độ xử lý song song cao.
- Go giúp các lập trình viên xây dựng các ứng dụng có khả năng mở rộng. Ngôn ngữ lập trình này giúp các nhà phát triển nhanh chóng xác định các bottleneck có thể ảnh hưởng xấu đến khả năng mở rộng của ứng dụng. Điều này cung cấp cho họ đủ thời gian để tối ưu hóa ứng dụng.
- Các nhà phát triển Go có thể dễ dàng thực hiện phân tích static code bằng GoMetaLinter, đây là một công cụ khá hữu ích.
- Go cung cấp một API giúp các nhà phát triển kiểm tra code của họ. Các lập trình viên có thể sử dụng nó để bắt đầu hoặc bỏ qua một bài kiểm tra, cách khác, họ có thể sử dụng nó để chạy các bài kiểm tra song song.
5.2 Nhược điểm của Golang:
- Các nhà phát triển cần code nhiều hơn để triển khai các chức năng phức tạp trong Go so với một số ngôn ngữ hàng đầu khác. Ngôn ngữ này không cung cấp complex abstractions như một số ngôn ngữ lập trình phổ biến khác. Mặc dù điều đó làm cho Go trở thành một ngôn ngữ đơn giản để sử dụng, nhưng nó lại hạn chế tính linh hoạt của nó.
- Các chương trình phức tạp được viết bằng Go có thể tiêu tốn nhiều tài nguyên máy tính hơn. Các chương trình như vậy có kích thước tệp rất lớn vì Go không có máy ảo (virtual machine)
- Go không cung cấp thư viện GUI của riêng mình. Điều này có nghĩa là bạn sẽ cần phải dành nhiều nỗ lực để kết nối thư viện với dự án của mình.
- Bạn sẽ thấy khó sử dụng lại mã trong Go hơn các ngôn ngữ khác vì Go không hỗ trợ đa nền tảng.
- Cộng đồng những lập trình viên sử dụng Go đang hoạt động ít sôi nổi hơn những cộng đồng ngôn ngữ lập trình khác (nếu so sánh với Javascript)
6. So sánh Golang vs NodeJS
Một số tiêu chí để so sánh Golang vs NodeJS
1. Việc tìm kiếm nhà phát triển
Vì NodeJS dựa trên JavaScript và nhiều nhà phát triển đã biết về nó, bạn có thể tìm nhà phát triển khá dễ dàng. Bạn sẽ cần nhiều thời gian và nỗ lực hơn để tìm các nhà phát triển Golang.
2. Learning curve
Learning curve của NodeJS ít khó khăn hơn vì JavaScript đã được phổ biến rộng rãi. Learning curve của Golang thì khó khăn hơn nhiều. Trong so sánh NodeJS và Golang, NodeJS là một lựa chọn tốt hơn xét về Learning curve.
3. Sự hoàn thiện
Go trải qua những phát triển và cải tiến, tuy nhiên, chúng tuân theo một mô hình có hệ thống. Mặt khác, một số API NodeJS trải qua những thay đổi thường xuyên. Điều này cho thấy sự thiếu hoàn thiện của NodeJS. Golang đã đạt được mức độ hoàn thiện hơn.
4. Hiệu năng
Như đã được đề cập ở trên, khi nói về hiệu năng thì phải nhắc đến Golang. Cho nên ở khía cạnh này mang lại hiệu năng cao hơn NodeJS.
5. Khả năng mở rộng
Trong khi cả NodeJS và Golang đều giúp bạn tạo các ứng dụng có khả năng mở rộng, thì Golang hỗ trợ concurrency tốt hơn. Điều này làm cho nó trở thành một lựa chọn tốt hơn để viết mã các ứng dụng có thể mở rộng.
6. Tính sẵn có của các công cụ và framework
Cộng đồng các nhà phát triển NodeJS đã tạo ra một loạt các công cụ và framework mã nguồn mở. Yếu tố này giúp người lập trình đạt năng suất cao hơn. Để so sánh, bạn sẽ tìm thấy ít công cụ và framework hơn cho Golang.
7. Tránh lỗi mã hóa
Go là một ngôn ngữ statically-typed, giúp loại bỏ phạm vi các lỗi liên quan đến variable types. NodeJS dựa trên JavaScript là dynamically-typed. Bạn có thể tìm thấy các lỗi liên quan đến variable types khó gỡ lỗi hơn.
8. Xử lý lỗi
Golang yêu cầu xử lý lỗi rõ ràng. Điều này đòi hỏi một cách tiếp cận có kỷ luật và có hệ thống để mã hóa, giúp cải thiện khả năng bảo trì. Về khía cạnh này, Golang thích hơn NodeJS.
9. Triển khai
Việc triển khai các ứng dụng được viết bằng Go dễ dàng hơn so với các ứng dụng được viết bằng NodeJS.
10. Hỗ trợ cộng đồng
Cộng đồng các nhà phát triển NodeJS rộng hơn và sôi động hơn cộng đồng các nhà phát triển Golang.
11. Maps trong Go và NodeJS
Map trong Go là hashmap, rất giống với map được sử dụng trong Python hay NodeJS. Là một cấu trúc dữ liệu, một map trong Golang là một tập hợp không có thứ tự của cặp key-value với mỗi giá trị duy nhất cho mỗi cặp. Nó khá là hữu ích cho việc lưu trữ thông tin và tìm kiếm. Cơ chế lưu trữ tương tự với NodeJS.
12. Machine learning với Golang và NodeJS
Với Golang, TensorFlow đáng được xem xét. Đó là một thư viện mã nguồn mở cho phép tính toán số. Tuy nhiên, API được cung cấp cho Go sẽ không cho phép các model training. Mà người dùng Go chỉ có thể sử dụng các model đã được train. Cho nên để xác định và đào tạo các model, hầu hết các dev của Go phải sử dụng Python, tải chúng lên Go sau.
Còn với NodeJS, bạn có thể tạo các model và train chúng ngay từ đầu nhưng cũng có thể sử dụng lại các model đã được train. Trong trường hợp đó, TensorFlow cũng sẽ là một sự lựa chọn hoàn hảo. Vì NodeJS cung cấp nguồn thư viện tốt hơn nên trong khía cạnh Machine learning NodeJS có lợi thế hơn Golang. Tuy vậy, cả JavaScript và Go đều không phải là lựa chọn đầu tiên với machine learning. Có rất nhiều thư viện được tạo sẵn cho Python và các ngôn ngữ khác, trong khi Go và JS yêu cầu nhiều công việc hơn.
13. Benchmark
Rất khó để đưa ra thời gian chính xác về việc chuyển đổi context liên quan đến các various model này. Vì vậy, thay vào đó, bài viết sẽ cung cấp cho bạn một số điểm benchmark cơ bản so sánh hiệu năng server HTTP tổng thể của các môi trường server này. Hãy nhớ rằng rất nhiều yếu tố liên quan đến hiệu năng của toàn bộ đường dẫn phản hồi HTTP end-to-end và những con số được trình bày ở đây chỉ là một số mẫu tập hợp lại để đưa ra so sánh cơ bản.
Đối với mỗi môi trường, tôi đã viết mã thích hợp để đọc trong tệp 64k với các byte ngẫu nhiên, chạy hàm SHA-256 hash trên đó N số lần (N được chỉ định trong chuỗi truy vấn của URL, ví dụ: .../test.php?n=100 và in kết quả hash trong hex. Tôi chọn điều này vì đây là một cách rất đơn giản để chạy các điểm benchmark giống nhau với một số I / O nhất quán và một cách có kiểm soát để tăng mức sử dụng CPU.
Đầu tiên, chúng ta hãy xem xét một số ví dụ về concurrency thấp. Chạy 2000 lần lặp với 300 yêu cầu đồng thời và chỉ một hàm hash cho mỗi yêu cầu (N = 1) cho chúng ta điều này:
Thật khó để đưa ra kết luận chỉ từ một biểu đồ này, với khối lượng kết nối và tính toán này, chúng ta đang thấy nhiều việc phải làm hơn với việc thực thi chung các ngôn ngữ, nhiều hơn thế nữa để I/O. Lưu ý rằng các ngôn ngữ được coi là "scripting languages" (loose typing, dynamic interpretation) hoạt động chậm nhất.
Nhưng điều gì sẽ xảy ra nếu chúng ta tăng N lên 1000, vẫn với 300 yêu cầu đồng thời - tải như nhau nhưng số lần lặp hash nhiều hơn 100 lần (tải CPU nhiều hơn đáng kể):
Đột nhiên, hiệu suất Node giảm đáng kể, vì các hoạt động đòi hỏi nhiều CPU trong mỗi yêu cầu đang chặn lẫn nhau.
Bây giờ chúng ta hãy thử 5000 kết nối đồng thời (với N = 1). Thật không may, đối với hầu hết các môi trường này, tỷ lệ thất bại không phải là không đáng kể. Đối với biểu đồ này, chúng tôi sẽ xem xét tổng số yêu cầu mỗi giây. Càng cao càng tốt:
Và bức tranh trông khá khác biệt.. Rõ ràng, Go là người chiến thắng ở đây.
Mặc dù có rất nhiều yếu tố liên quan đến throughput tổng thể và cũng rất khác nhau giữa các ứng dụng, nhưng bạn càng hiểu rõ về những gì đang diễn ra và những đánh đổi liên quan, bạn sẽ càng có lợi thế.
7. Golang vs NodeJS: Nên sử dụng cái nào?
Làm cách nào để bạn quyết định có sử dụng Go vs NodeJS không? Hãy sử dụng các yếu tố sau:
- Thời gian chờ đợi để tuyển dụng các nhà phát triển ứng dụng Go vs NodeJS: Nếu bạn không có nhiều thời gian để tuyển dụng các nhà phát triển, thì bạn nên chọn NodeJS. Bạn sẽ thấy việc tuyển dụng các nhà phát triển NodeJS dễ dàng hơn các nhà lập trình Golang.
- Bạn chỉ muốn sử dụng một ngôn ngữ: Việc phát triển NodeJS có nghĩa là sử dụng JavaScript cho cả front-end và backend. NodeJS cung cấp đầy đủ các công cụ và framework để phát triển cả front-end và back-end. Để so sánh, Go không có thư viện GUI (giao diện người dùng) và bạn cần sử dụng thư viện của bên thứ ba. Nếu bạn muốn một bộ ngôn ngữ và framework chỉ dành cho toàn bộ quá trình phát triển ứng dụng web của mình, thì bạn nên sử dụng NodeJS.
- Bạn muốn một ứng dụng có hiệu năng cao và có khả năng mở rộng: Khi bạn xem xét Golang bạn sẽ nghĩ đến khả năng mở rộng và hiệu năng của nó. Trong bài so sánh Go vs NodeJS này, Go làm tốt hơn mặt này so với NodeJS.
- Bạn có các yêu cầu nghiêm ngặt về bảo mật: Go loại bỏ nhiều lỗi lập trình phổ biến, do đó, nó làm giảm các lỗ hổng bảo mật của ứng dụng. Khả năng quản lý bộ nhớ và thu gom rác mạnh mẽ của nó khiến nó trở thành lựa chọn tốt hơn NodeJS.
- Bạn cần real-time data streaming: NodeJS làm tốt hơn Golang về mặt này (dễ phát triển hơn).
- Bạn thích một tập hợp các quy trình phát triển, xem xét, thử nghiệm và triển khai được sắp xếp hợp lý: Bạn nên sử dụng Golang do hỗ trợ công cụ của nó để phân tích, thử nghiệm và triển khai static code. Trong so sánh Go vs NodeJS, Go đại diện cho một sự lựa chọn tốt hơn ở khía cạnh này.
Tóm lại, bài viết trên đã phân tích rất kỹ các đặc điểm của cả NodeJS vs Golang. Cả hai đều có những ưu điểm và hạn chế riêng. Bài viết cũng đã thảo luận về các trường hợp khác nhau mà bạn nên sử dụng cái này hay cái kia. Công việc tiếp theo là tùy thuộc vào bạn. Hãy phân tích các yêu cầu kinh doanh và dự án của bạn một cách cẩn thận trước khi bạn đưa ra lựa chọn giữa Go vs NodeJS.
Bài viết được tham khảo từ các nguồn: toptal; devathon; miquido.
All rights reserved