Thường được kết hợp với phát triển Backend, làm việc với logic phía máy chủ và quản lý dữ liệu, để tạo ra một ứng dụng phần mềm hoặc trang web hoàn chỉnh và chức năng.. Thời kỳ Jav
TỔNG QUAN VỀ FRONTEND
Frontend là gì
Frontend, còn được gọi là client-side đề cập đến phần của ứng dụng phần mềm hoặc trang web mà người dùng tương tác trực tiếp Nó bao gồm các yếu tố giao diện người dùng (UI) và trải nghiệm người dùng (UX) của một hệ thống Phát triển Frontend liên quan đến việc tạo và triển khai các yếu tố trực quan, chẳng hạn như trang web, biểu mẫu, nút, menu và các tính năng tương tác khác mà người dùng thấy và tương tác khi sử dụng một ứng dụng hoặc trang web
Phát triển front-end thường bao gồm sự kết hợp của các công nghệ, bao gồm HTML để cấu trúc nội dung, CSS để thiết kế và bố trí và JavaScript để thêm tính tương tác và chức năng vào các trang web Các nhà phát triển front-end làm việc để đảm bảo rằng giao diện người dùng thân thiện, hấp dẫn mắt và phản hồi trên các thiết bị và kích thước màn hình khác nhau
Phát triển Frontend là một khía cạnh quan trọng của phát triển web và phần mềm, vì nó ảnh hưởng trực tiếp đến cảm nhận của người dùng về chất lượng và khả năng sử dụng của ứng dụng Thường được kết hợp với phát triển Backend, làm việc với logic phía máy chủ và quản lý dữ liệu, để tạo ra một ứng dụng phần mềm hoặc trang web hoàn chỉnh và chức năng
Hình 1.1 HTML, CSS, JavaScript tạo nên trang web
Lịch sử phát triển
Trong khoảng những năm của thập niên 1980 cho tới những năm đầu của thập niên
2000, với việc internet còn chưa thực sự phát triển và sự phổ biến của máy tính cá nhân, desktop app chiếm thế thượng phong trong thị trường ứng dụng với tốc độ tăng chóng mặt Desktop app giúp cho người dùng không phải dựa vào kết nối mạng nghèo nàn thời đó mà chỉ dựa vào sức mạnh phần cứng của máy tính cá nhân để thực hiện các tác vụ hằng ngày như soạn thảo văn bản, chỉnh sửa hình ảnh, v.v…
Vào năm 1995, Bredan Eich phát triển ngôn ngữ JavaScript khi làm việc tại Netscape, được thiết kế ban đầu là một ngôn ngữ nhẹ chạy ở trình duyệt, tương tác với DOM để thêm vào trang web tính tương tác như nhập dữ liệu, xác thực dữ liệu Tuy nhiên lúc này vẫn vẫn là các trang web tĩnh, tương tác với server và chờ đợi một file HTML mới trả về
Vào những năm tiếp theo, Netscape cho ra đời Netscape Navigator 2.0, là trình duyệt đầu tiên hỗ trợ Javascript, trong khi đó Microsoft giới thiệu một phiên bản của chính họ là JScript hoạt động trên trình duyệt IE Điều này khiến cho việc phát triển, thực thi các đoạn mã Javascript trên các trình duyệt khác nhau cũng khác nhau, sự đồng bộ của ngôn ngữ là chưa có khiến cho Javascript chưa được phát triển mạnh mẽ và sử dụng rộng rãi
Tới năm 1997, chuẩn ECMAScript được giới thiệu để chuẩn hoá Javascript và đảm bảo khả năng tương thích giữa các trình duyệt khác nhau Chuẩn ECMAScript định nghĩa những tính năng cốt lõi của Javascript và vẫn được phát triển qua nhiều phiên bản sau
Sau sự ra đời của chuẩn ECMAScript, từ những năm 1990 đến đầu 2000, Javascript được phát triển rộng rãi và mạnh mẽ trong cộng đồng thông qua các tính năng của nó Javascript mang lại một luồng gió mới khi nó có thể được sử dụng ở phía trình duyệt để xác thực form, cập nhật DOM, làm các hiệu ứng
Tới đầu năm 2000, kỹ thuật AJAX (Asynchronous JavaScript and XML), một trong những kĩ thuật quan trọng trong quá trình phát triển web, đã tạo nên một cuộc cách
4 mạng trong quá trình phát triển web application Kỹ thuật này thay thế cách một trang web thông thường lấy dữ liệu từ phía máy chủ đó là phải tải lại cả trang web, hay có thể xem như là đồng bộ bằng phương pháp mới, cho phép thực hiện truyền tải dữ liệu một cách bất đồng bộ Tức là thay vì phải chờ máy chủ trả về file HTML mới, làm cho quá trình tương tác của user bị giáng đoạn thì giờ đây trang web vẫn có thể tương tác được trong khi chờ dữ liệu trả về từ phía server, sau khi nhận dữ liệu, kỹ thuật này cho phép Javascript áp dụng dữ liệu này và thay đổi DOM để hiển thị lên trên trình duyệt, giúp cho trải nghiệp của người dùng mượt mà hơn, không bị giáng đoạn như trước
Hình 1.2 Cách AJAX hoạt động
Tới những năm tiếp theo, nhiều frameworks và thư viện ra đời để đơn giản hoá việc lập trình web bằng Javascript Đặc biệt phải kể đến jQuery được giới thiệu năm
2006 Sau sự ra đời của jQuery, nhiều framework hiện đại khác được ra đời, sớm nhất là Angular của Google giúp cho việc phát triển web càng ngày càng trở nên hiện đại, dễ dàng và nhiều tác vụ nâng cao hơn cũng được hiện thực hoá, làm cho trang web càng ngày càng có tính tương tác cao, bắt mắt với người dùng Lúc này trong cộng đồng lập trình web phân ra hai nhánh gồm Frontend và Backend, Frontend sẽ sử dụng JS để phát triển còn Backend sử dụng các ngôn ngữ server từ trước như C#, Java
Tới năm 2009, với sự ra đời của Node.js, đã đánh dấu bước ngoặt rằng JS là một ngôn ngữ fullstack khi có thể được sử dụng ở phía server Node.js là một môi trường
5 thực thi trên nền V8 engine của Google, hỗ trợ để xây dựng máy chủ có tính mở rộng và có hiệu suất hoạt động cao
Hình 1.3 Các tính năng của NodeJS
1.2.2.2 Sự phát triển của CSS
Vào năm 1966, W3C giới thiệu CSS1 nhằm mục đíach tách phần khung của trang web (HTML) ra khỏi cách trình bày nó trên trang web (CSS)
Vào năm 1998, CSS2 được giới thiệu với nhiều tính năng mở rộng thêm so với CSS1 như thuộc tính position cho các element, cung cấp nhiều css selectors nâng cao hơn Phiên bản này đã đóng một vai trò quan trọng trong việc giúp cho việc hiển thị của trang web
Trong suốt từ cuối thập niên 1990 và đầu thập niên 2000, các lập trình viên web đối diện với vấn đề tương tự với javascript, đó là css hoạt động trên các trình duyệt khác nhau một cách khác nhau
Từ giữa thập niên 2000 cho tới nay, CSS3 ra đời mà giới thiệu nhiều tính năng mới, tính năng nâng cao như bo góc cho viền, màu gradients, cung cấp từ khoá định nghĩa các hoạt hoạ chuyển động trên trang web, cung cấp các từ khoá để định nghĩa các media-query phục vụ cho việc phát triển trang web có thể hiển thị trên nhiều trình duyệt với độ rộng màn hình khác nhau, cũng như giới thiệu grid-layout, flexbox layout
Ngày nay, nhiều CSS frameworks ra đời, ví dụ như Bootstrap, Tailwinds hoặc các thư viện CSS Những framworks và thư viện này cung cấp những phần tử, components sẵn có giúp cho việc phát triển trang web có giao diện bắt mắt ngày càng dễ dàng hơn, mang lại trải nghiệm tốt hơn cho người dùng
Chuẩn ECMAScript chỉ định nghĩa các phương thức cốt lõi của Javascript, các trình duyệt vẫn xử lí những tác vụ như cập nhật DOM, thực hiện AJAX request, xử lí sự kiện một cách riêng biệt theo tiêu chuẩn của nó, vì vậy jQuery đã ra đời để xử lí vấn đề nhức nhối này JQuery cung cấp các phương thức ở mức nâng cao, trừu tượng để lập trình viên xử lí các tác vụ nêu trên, trừu tượng hoá sự khác biệt giữa các trình duyệt, nhờ đó mà các dòng lệnh Javascript giữa các lập trình viên, giữa các mã nguồn trở nên đồng bộ hơn, các lập trình viên cũng không cần quan tâm các trình duyệt xử lí các dòng lệnh theo các cách khác nhau khi mà thư viện jQuery đã hỗ trợ việc đó cho họ Thư viện này còn đơn giản hoá các câu lệnh truy vấn DOM, thực hiện AJAX requets; giúp cho các tác vụ như cập nhật phần tử, thêm sửa xoá CSS và xử lý sự kiện cũng trở nên ngắn gọn Cụ thể hơn, khi viết một câu lệnh jQuery để thực hiện truy vấn DOM, thư viện này sẽ dựa vào trình duyệt đang chạy câu lệnh jQuery mà thực thi câu lệnh JS được hỗ trợ tương ứng JQuery đã tạo nên một cuộc cách mạng thật sự khi mà với jQuery và AJAX, việc lập trình Frontend đã trở nên dễ dàng hơn, lập trình viên với hai công cụ mạnh mẽ này có thể lập trình được hầu hết các tính năng được yêu cầu vào thời gian đó Nhờ vậy mà jQuery ngày càng được sử dụng rộng rãi, cộng đồng sử dụng ngày càng tăng và trở thành một cuộc cách mạng thật sự trong cộng đồng phát triển web
Hình 1.4 Một số phương thức trong jQuery
Mobile applications được định nghĩa là các phần mềm được thiết kế đặc biệt để chạy trên các thiết bị di dộng, máy tính bảng, đồng hồ thông minh, Mobile app có ứng dụng trong nhiều lĩnh vực, hỗ trợ cho trải nghiệm người dùng trong thời kì mà các thiết bị di động đang phát triển mạnh mẽ
Công nghệ Frontend
Ngày nay, công việc lập trình Frontend ngày càng trở nên thuận tiện cho các lập trình viên nhờ vào các công cụ được phát triển nhằm mục đích tiết kiệm thời gian, mang lại cú pháp, cách dùng thân thiện với con người hơn Các công cụ có thể kể đến như IDE như Visual Studio, đóng gói và cung cấp những trình biên dịch hoặc thông dịch các dòng lệnh để chạy ứng dụng, ngoài ra còn có các tính năng khác như trình gỡ lỗi, các trình quản lý đối tượng
Text editor, cung cấp ít tính năng hơn so với IDE và thường cần các extension bên ngoài để chạy ứng dụng Mục đích chính của text editor thường chỉ để soạn thảo các dòng lệnh
Các công cụ quản lý các thư viện bên thứ ba, các module, các nudget đi kèm như NPM, Yarn
Công cụ tối ưu hoá quá trình quản lý các phiên bản của mã nguồn như Git, SVN giúp bảo vệ mã nguồn khỏi các sơ suất làm mất mát dòng lệnh, quản lý các phiên bản của phần mềm được ra mắt với người dùng
Các công cụ để build và bundler mã nguồn như Webpack, Turbopack, Parcel được sử dụng để bunble và build mã nguồn (ví dụ như Javascript, CSS) để tối ưu hoá hiệu suất, tăng tốc độ tải trang, giảm kích thước trang cần tải về trình duyệt
Hình 1.9 IDE và text editor 1.3.2 Các ngôn ngữ lập trình và framework
Các ngôn ngữ lập trình được dùng phổ biến trong việc lập trình Frontend như PHP, Ruby, Java, C# trong thời kì đầu, sau này là sự xuất hiện của Javascript Với sự phát triển của công nghệ, các framework ra đời như Laravel, CakePHP cho ngôn ngữ PHP, Ruby on Rails, Spring cho Java, NET cho C#, Angular, VueJS, NextJS, Svelte, Solid cho Javasript
Các framework được sinh ra nhằm mục đích đơn giản hoá các bước cấu hình cho dự án, các hàm gọi dùng để render giao diện người dùng Việc sử dụng framework giúp cho bộ mã nguồn được cấu trúc theo một mẫu cấu trúc thư mục sẵn có, cung cấp hướng dẫn cho các lập trình nhằm đảm bảo tính thống nhất giữa các thành viên, đảm bảo khả năng bảo trì và nâng cấp của dự án Các framework còn giúp cho ứng dụng chạy mượt
13 mà trên các trình duyệt, hệ điều hành khác nhau thêm vào đó là tài liệu và cộng đồng sử dụng rộng rãi
Hình 1.10 Đa dạng ngôn ngữ lập trình
Responsive web design là kỹ thuật giúp cho ứng dụng có giao diện có thể hiển thị mượt mà trên nhiều ứng dụng có kích thước khác nhau
AJAX là kỹ thuật giúp trang web được cập nhật dữ liệu thông qua việc giao tiếp bất đồng bộ với server, cập nhật dữ liệu mà không phải tải lại trang
Tối ưu hiệu suất thông qua các kỹ thuật hydration, lazy loading, caching để giảm thời gian chờ của người dùng khi sử dụng ứng dụng
Kiểm lỗi và gỡ lỗi thông qua các thư viện như Jest, Mocha hoặc cửa sổ developer của các trình duyệt
Các công nghệ mới như PWA, kiến trúc serverless nhằm giảm công sức tiền bạc của các nhà phát triển ứng dụng, mang đến ứng dụng ổn định cho người dùng, mang lại các tính năng hiện đại như đẩy thông báo, khả năng sử dụng ứng dụng khi không có mạng, caching trang web,
Các Frontend framework
Framework là một tập các dòng lệnh được viết sẵn theo một tiêu chuẩn cụ thể, các thư viện, công cụ dùng để phát triển phần mềm Các framework tập trung vào việc tối ưu quá trình phát triển bằng cách cung cấp nhũng thành phần có thể tái sử dụng, áp dụng design-patern và một tập các luật để lập trình viên dựa theo đó để phát triển phần mềm một cách hiệu quả nhất Frontend framework cung cấp một cấu trúc dựng sẵn để xây
14 dựng giao diện và nâng cao trải nghiệm của người dùng khi sử dụng website hoặc webapp
1.4.2 Các framework Frontend phổ biến a) NextJS: Được phát triển bởi Vercel dựa trên thư viện React, kế thừa cấu trúc component-based, tối ưu và cung cấp tính năng server-rendering để tối ưu hoá cho SEO cũng như giảm thời gian cần thiết để tải trang web b) Angular 2: Được phát triển bởi Google, mà một phiên bản nâng cấp của Angular Cũng sử dụng kiến trúc component-based đồng thời cung cấp nhiều tính năng tối ưu cho trang web như tree-saking, dependency injection và data binding c) VueJS: VueJS là một framework tương tự ReactJS, có điểm khác biệt ở cách sử dụng data binding, thay vì 1-way mà là 2-way Điều này giúp cho việc tiếp cận framework này trở nên dễ dàng d) Bootstrap: Bootstrap là một CSS framework phát triển bởi Twitter hay X Framwork cung cấp một loạt những component được dựng sẵn, các style CSS và layout dựng sẵn giúp xây dựng trang web responsive Bootstrap thường được dùng với React hoặc AngularJS e) TailwindCSS: là một CSS framework cung cấp những class dựng sẵn giúp nhanh chóng xây dựng những component mà lập trình viên có thể tự tuỳ chỉnh hiển thị.
Các xu hướng công nghệ phổ biến
1.5.1 Artificial Intelligence và Machine Learning
Artificial Intelligence (AI) đề cập đến việc mô phỏng trí thông minh của con người trong các máy tính được lập trình để suy nghĩ và mô phỏng hành vi của con người AI bao gồm một loạt các kỹ thuật như giải quyết vấn đề, học tập, nhận diện ngôn ngữ và đưa ra quyết định
Machine Learning (ML) là một nhánh của AI liên quan đến việc phát triển các thuật toán và mô hình thống kê cho phép máy tính học hỏi và cải thiện từ kinh nghiệm, những quá trình học hỏi trước mà không cần được lập trình rõ ràng Thuật toán ML sử dụng dữ liệu để xác định mẫu, đưa ra dự đoán hoặc tối ưu hóa quy trình
AI và ML được áp dụng vào front-end thông qua nhiều tính năng như hệ thống gợi ý, cá nhân hoá dữ liệu người dùng, chat bot, gợi ý dữ liệu nhập vào, tự động tạo nội dung…
SPA là viết tắt của Single Page Application, một loại ứng dụng web hoạt động trong một trang web duy nhất Không giống như các trang web truyền thống nơi mỗi tương tác có thể dẫn đến việc tải một trang mới từ máy chủ, SPA tải một lần ban đầu và cập nhật nội dung động khi người dùng tương tác với ứng dụng
Các đặc điểm chính của SPA bao gồm: a) Dynamic content loading: SPA sử dụng JavaScript để tải nội dung ở phía trình duyệt, mang lại trải nghiệm người dùng mượt mà và phản hồi nhanh hơn mà không cần tải lại toàn trang b) Client-side rendering: Việc hiển thị nội dung và thao tác dữ liệu xảy ra ở phía client) bằng cách sử dụng các thư viện và framework JavaScript như React, Angular hoặc Vue.js, thay vì dựa vào máy chủ để hiển thị HTML c) Routing: SPA thường sử dụng cơ chế định tuyến phía máy khách để quản lý điều hướng trong ứng dụng, cập nhật URL động mà không yêu cầu các trang mới từ máy chủ Điều này cho phép kiểm soát tốt hơn lịch sử duyệt web d) Hiệu suất: SPA có thể cung cấp thời gian tải nhanh hơn sau lần tải đầu tiên vì trang web lấy dữ liệu từ API và cập nhật nội dung một cách linh hoạt mà không cần làm mới toàn bộ trang e) Nâng cao trải nghiệm người dùng: Bằng cách cung cấp trải nghiệm liền mạch, SPA thường phản hồi và tương tác tốt hơn với người dùng, giống như các ứng dụng di động native f) Phát triển với trung tâm là API: SPA thường tương tác với API phía máy chủ để tìm nạp dữ liệu hoặc thực hiện các hoạt động không đồng bộ, cho phép tách rời quá trình phát triển front-end và back-end g) SPA cũng đối diện với nhiều mặt hạn chế như không tối ưu cho SEO khi các máy tìm kiếm không thể chạy code JavaScipt để lấy thông tin của trang web SPA cũng có thời gian load lần đầu cho trang web khá lâu khi trình duyệt cần tải hết mã nguồn về để chạy ứng dụng
PWA là viết tắt của Progressive Web Apps, là một loại ứng dụng web sử dụng công nghệ web để cung cấp cho người dùng trải nghiệm giống như ứng dụng native thông
16 qua trình duyệt web PWA nhằm mục đích kết hợp các tính năng tốt nhất của ứng dụng web và ứng dụng di động, mang lại hiệu suất, độ tin cậy và mức độ tương tác cao hơn Các nhà phát triển thường tận dụng các công nghệ như Service Workers, Manifest JSON và responsive design để xây dựng PWA Các framework và thư viện phổ biến như React, Angular và Vue.js cung cấp các công cụ và tài nguyên để đơn giản hóa việc phát triển PWA
PWA cung cấp cho các doanh nghiệp và nhà phát triển một giải pháp thay thế cho các ứng dụng di động gốc truyền thống, mang lại nhiều lợi thế, bao gồm phân phối dễ dàng hơn (không cần cửa hàng ứng dụng), khả năng tương thích đa nền tảng và giảm chi phí phát triển
Kiến trúc serverless (tối giản server) là mô hình điện toán đám mây cho phép các nhà phát triển xây dựng và chạy các ứng dụng mà không cần quản lý cơ sở hạ tầng Mặc dù tên của kiến trúc là serverless, các server vẫn tham gia vào việc thực thi dòng lệnh, nhưng các lập trình viên không cần phải quản lí, bảo trì và nâng cấp máy chủ mà đưa lên các máy tính điện toán đám mây
Các nền tảng serverless phổ biến bao gồm AWS Lambda, Azure Functions, Google Cloud Functions và các dịch vụ như AWS API Gateway hoặc Azure Event Grid, hỗ trợ các kiến trúc hướng sự kiện và cho phép nhà phát triển xây dựng các ứng dụng serverless
Kiến trúc serverless rất phù hợp cho nhiều trường hợp sử dụng khác nhau, bao gồm ứng dụng web, API, xử lý dữ liệu theo thời gian thực, ứng dụng IoT Tuy nhiên, nó có thể không phù hợp với các ứng dụng yêu cầu kiểm soát chi tiết đối với cơ sở hạ tầng Việc áp dụng kiến trúc serverless mang lại những lợi ích như khả năng mở rộng, giảm chi phí vận hành và chu kỳ phát triển tính năng nhanh hơn, khiến kiến trúc này trở thành lựa chọn hấp dẫn cho nhiều ứng dụng hiện đại và nhiều trường hợp sử dụng
Server-Side Rendering (SSR) là một kỹ thuật được sử dụng trong phát triển web trong đó server sẽ tạo HTML ban đầu cho trang web trước khi gửi nó đến client (trình duyệt) Cách tiếp cận này khác với client-side rendering (CSR), trong đó trình duyệt tải xuống một tệp HTML tối thiểu và sau đó JavaScript ở phía máy khách sẽ hiển thị nội dung
Các khía cạnh và lợi ích chính của Server-Side Rendering bao gồm: a) Cải thiện hiệu suất và SEO: SSR thường giúp tải trang ban đầu nhanh hơn vì máy chủ gửi HTML được hiển thị đầy đủ tới trình duyệt Điều này có lợi cho việc tối ưu hóa công cụ tìm kiếm (SEO) vì trình thu thập thông tin của công cụ tìm kiếm có thể dễ dàng lập chỉ mục nội dung b) First Contentful Paint (FCP): SSR có thể giúp đạt được FCP nhanh hơn vì trình duyệt nhận được nội dung HTML sớm hơn, cho phép người dùng xem và tương tác với trang nhanh hơn c) Tăng khả năng tiếp cận của người dùng: Bằng cách cung cấp HTML, SSR đảm bảo rằng nội dung có sẵn ngay cả khi JavaScript không tải hoặc thực thi đúng cách ở phía máy khách, cải thiện khả năng truy cập và trải nghiệm người dùng, đặc biệt đối với người dùng trên các thiết bị chậm hơn hoặc điều kiện mạng hạn chế d) Hỗ trợ trình thu thập dữ liệu web: SSR cung cấp nội dung chính xác cho các nền tảng truyền thông xã hội và trình thu thập dữ liệu web, cho phép các trang web hiển thị một phần giao diện xem trước tốt hơn khi chia sẻ liên kết và đảm bảo lập chỉ mục nội dung phù hợp e) Bộ nhớ đệm: SSR hiệu quả đói với những phương thức caching, tối ưu hóa việc phân phối nội dung và giảm tải cho máy chủ cho các yêu cầu tiếp theo
SSR thường được triển khai bằng cách sử dụng các công nghệ và framework như Next.js cho React, Nuxt.js cho Vue.js hoặc Angular Universal cho Angular Các framework này tạo điều kiện thuận lợi cho quá trình hiển thị phía máy chủ và xử lý sự phức tạp của việc hiển thị nội dung ở cả phía máy chủ và phía máy khách thông qua công nghệ hydration
Mặc dù SSR mang lại lợi thế về hiệu suất và SEO, nhưng nó có thể có chi phí xử lý máy chủ cao hơn so với CSR Ngoài ra, thời gian tải trang lần đầu có thể bị ảnh hưởng nếu thời gian phản hồi của máy chủ chậm hoặc nếu độ phức tạp của ứng dụng ảnh hưởng đến tốc độ xuất file HTML trên máy chủ
Hình 1.11 Server-side rendering
CÁC KIẾN TRÚC PHỔ BIẾN
MVC
MVC (Model - View - Controller) là một mô hình/thiết kế kiến trúc chia ứng dụng thành ba thành phần logic chính tương: Model (Mô hình), View (Hiển thị), và Controller (Controller) Mỗi thành phần kiến trúc được xây dựng để xử lý các khía cạnh phát triển cụ thể của một ứng dụng Nó cô lập logic kinh doanh và lớp hiển thị với nhau Ban đầu, nó thường được sử dụng cho giao diện người dùng đồ họa(GUIs) trên máy tính cá nhân Ngày nay, MVC là một trong những Framework phổ biến nhất trong ngành phát triển web để tạo ra các dự án có khả năng mở rộng và mở rộng Nó cũng được sử dụng để thiết kế ứng dụng di động
2.1.2 Cấu trúc mô hình MVC
Các thành phần chính trong mô hình MVC bao gồm: a) Mô hình (Model): Model là thành phần chịu trách nhiệm quản lý dữ liệu và logic kinh doanh của ứng dụng Nó bao gồm các lớp và đối tượng biểu diễn cho dữ liệu, và xử lý các thay đổi trạng thái của nó Model không biết đến sự tồn tại của View và Controller b) Hiển thị (View): View là thành phần chịu trách nhiệm hiển thị thông tin cho người dùng Nó nhận dữ liệu từ Model và biểu diễn nó theo cách được định nghĩa View không thay đổi dữ liệu, mà chỉ làm nhiệm vụ hiển thị c) Controller (Controller): Controller là thành phần trung gian giữa Model và View
Nó xử lý sự kiện từ người dùng, tương tác với Model để cập nhật dữ liệu và sau đó cập nhật View để hiển thị thông tin mới Controller là nơi điều phối luồng điều khiển của ứng dụng
2.1.3 Hoạt động của mô hình MVC
Ta có thể khái quát mô tả hoạt động qua các bước như sau: a) Người Dùng (User) tương tác với View:
Sự tương tác bắt đầu khi người dùng tương tác với View, như là bấm một nút hoặc nhập dữ liệu b) View Tương Tác với Controller:
View ghi nhận dữ liệu người dùng và gửi nó đến Controller để xử lý
Controller giải thích dữ liệu người dùng và quyết định cách xử lý nó c) Controller Tương Tác với Model:
Controller tương tác với Model để cập nhật dữ liệu hoặc logic kinh doanh của ứng dụng dựa trên dữ liệu người dùng
Model cập nhật trạng thái nội tại của mình theo hướng dẫn của Controller d) Model Thông Báo View:
Nếu trạng thái của Model thay đổi (do dữ liệu người dùng hoặc các yếu tố khác), nó thông báo cho các View đã đăng ký
Thông báo này thông báo cho View rằng chúng cần cập nhật bản thể để phản ánh những thay đổi trong dữ liệu e) View Truy Xuất Dữ Liệu từ Model:
View, sau khi nhận thông báo, truy xuất dữ liệu đã được cập nhật từ Model
View cập nhật bản thể của mình để phản ánh những thay đổi trong dữ liệu f) Controller Tương Tác với View (Tùy chọn):
Trong một số trường hợp, Controller có thể trực tiếp cập nhật View để phản ánh những thay đổi trong Model mà không đợi thông báo
Ví dụ: một người dùng cuối gửi một yêu cầu đến một máy chủ để nhận danh sách sinh viên đang học trong một lớp Sau đó, máy chủ sẽ gửi yêu cầu đó đến Controller cụ thể quản lý sinh viên Controller đó sau đó sẽ yêu cầu Model quản lý sinh viên trả về một danh sách của tất cả sinh viên đang học trong một lớp
Hình 2.1 Mô phỏng luồng hoạt động của MVC
Model sẽ truy vấn cơ sở dữ liệu để lấy danh sách tất cả sinh viên và sau đó trả lại danh sách đó cho Controller Nếu phản hồi từ Model thành công, Controller sẽ yêu cầu View liên quan đến sinh viên trả lại một bản trình bày về danh sách sinh viên View này sẽ lấy danh sách sinh viên từ Controller và hiển thị danh sách thành HTML có thể được sử dụng bởi trình duyệt
Controller sau đó sẽ lấy bản trình bày đó và trả lại cho người dùng, kết thúc yêu cầu Nếu trước đó Model trả về một lỗi, Controller sẽ xử lý lỗi đó bằng cách yêu cầu View xử lý lỗi tạo một bản trình bày cho lỗi cụ thể đó Bản trình bày lỗi đó sau đó sẽ được trả lại cho người dùng thay vì bản trình bày danh sách sinh viên
Như chúng ta có thể thấy từ ví dụ trên, Model xử lý tất cả dữ liệu View xử lý tất cả bản trình bày và Controller chỉ thông báo cho Model và View về những gì cần làm Đây là kiến trúc cơ bản và cách làm việc của framework MVC
2.1.4 Lợi ích của việc sử dụng mô hình MVC a) Mã nguồn dễ bảo trì và có thể mở rộng một cách dễ dàng b) Các thành phần của mô hình MVC có thể được kiểm thử một cách độc lập c) Các thành phần của MVC có thể được phát triển đồng thời
26 d) Nó giảm độ phức tạp bằng cách chia ứng dụng thành ba đơn vị: Model-View- Controller e) Hỗ trợ Test Driven Development (TDD) f) Hoạt động tốt cho ứng dụng web được hỗ trợ bởi đội ngũ lớn nhà thiết kế và nhà phát triển web g) Kiến trúc này giúp kiểm thử các thành phần độc lập vì tất cả các lớp và đối tượng đều độc lập với nhau h) Thân thiện với Search Engine Optimization (SEO)
2.1.5 Các ngôn ngữ và framework sử dụng mô hình MVC a) Ruby on Rails b) Django c) CherryPy d) Spring MVC e) Catalyst f) Rails g) Zend Framework h) Fuel PHP i) Laravel j) Symphony
Hình 2.2 Các ngôn ngữ và framework sử dụng MVC
Tóm lại, mô hình kiến trúc Model-View-Controller (MVC) cung cấp một cách tiếp cận có cấu trúc trong phát triển phần mềm, chia ứng dụng thành các thành phần Model, View và Controller Việc phân tách rõ ràng giữa các nhiệm vụ khuyến khích việc bảo trì mã nguồn, khả năng mở rộng và kiểm thử độc lập của các thành phần Việc phân rõ trách nhiệm nâng cao sự hợp tác giữa các đội phát triển và hỗ trợ phát triển đồng thời Tính mô-đun của MVC giảm độ phức tạp, làm cho nó phù hợp cho các dự án quy mô lớn, đặc biệt là các ứng dụng web, trong khi sự hỗ trợ cho Test-Driven Development (TDD) đảm bảo sự chắc chắn của phần mềm Tổng cộng, MVC cung cấp một framework giúp tăng cường hiệu suất, khả năng bảo trì và khả năng mở rộng trong phát triển phần mềm.
MVP
MVP (Model-View-Presenter) là một mô hình kiến trúc được sử dụng để tổ chức mã nguồn của một giao diện người dùng Tương tự như mô hình Model-View-Controller (MVC), MVP nhằm vào việc phân chia các tác vụ trong một ứng dụng, tập trung đặc biệt vào tương tác giữa giao diện người dùng (UIs), logic kinh doanh và dữ liệu (Data)
Mô hình MVP vượt qua những thách thức của MVC và cung cấp phương pháp dễ dàng để xây dựng mã nguồn dự án Lý do MVP được chấp nhận rộng rãi là nó mang lại tính mô-đun, khả năng kiểm thử cũng như một mã nguồn sạch sẽ và dễ bảo trì hơn
2.2.2 Cấu trúc của mô hình MVP
Các thành phần chính trong mô hình MVP bao gồm: a) Model (Mô hình): Đại diện cho dữ liệu và logic kinh doanh của ứng dụng Nó chịu trách nhiệm quản lý dữ liệu, truy xuất và lưu trữ thông tin, và thông báo cho Presenter về bất kỳ thay đổi nào b) View (Hiển thị): Hiển thị giao diện người dùng và trình bày dữ liệu cho người dùng Khác với mô hình MVC truyền thống, View trong MVP là một phần động, không xử lý đầu vào người dùng trực tiếp Thay vào đó, nó chuyển quyền xử lý đầu vào người dùng cho Presenter
28 c) Presenter (Bộ trình bày): Là một người trung gian giữa Model và View Nó nhận đầu vào người dùng từ View, xử lý nó (thường liên quan đến tương tác với Model), và cập nhật View tương ứng Presenter chịu trách nhiệm cho logic và hành vi của ứng dụng
2.2.3 Hoạt động của mô hình MVP
Ta có thể khái quát mô tả hoạt động qua các bước như sau: a) Tương Tác Người Dùng:
Người dùng tương tác với thành phần View, thường thông qua các yếu tố giao diện người dùng như nút, hộp văn bản, v.v b) View Thông Báo cho Presenter:
View không xử lý đầu vào người dùng trực tiếp mà thay vào đó thông báo cho Presenter về các hành động hoặc đầu vào của người dùng c) Presenter Xử Lý Đầu Vào Người Dùng:
Presenter nhận thông báo từ View và xử lý đầu vào người dùng Điều này có thể liên quan đến tương tác với Model để lấy hoặc thay đổi dữ liệu d) Presenter Cập Nhật View:
Dựa trên đầu vào đã xử lý và bất kỳ thay đổi nào trong Model, Presenter cập nhật View theo đúng Nó quyết định cách dữ liệu nên được trình bày e) View Phản Ánh Các Thay Đổi:
View phản ánh các thay đổi theo hướng dẫn của Presenter, cập nhật giao diện người dùng để hiển thị dữ liệu đã được sửa đổi hoặc phản ứng với các hành động của người dùng f) Model Quản Lý Dữ Liệu:
Model quản lý dữ liệu và logic kinh doanh của ứng dụng Nó phản hồi cho Presenter, thực hiện các thao tác dữ liệu và thông báo cho Presenter về bất kỳ thay đổi nào
2.2.4 Sự khác biệt giữa MVC và MVP a) MVP:
Trong MVP, Presenter chứa logic kinh doanh của giao diện người dùng cho View Tất cả các lời gọi từ View được đưa trực tiếp đến Presenter Presenter cũng không kết nối trực tiếp với View và giao tiếp với nó thông qua interface Điều này giúp cho việc tạo mô phỏng của View khi kiểm thử Một đặc điểm phổ biến của MVP là phải có nhiều sự chuyển giao hai chiều giữa View và Presenter
Hình 2.3 Mô hình MVP b) MVC:
Trong MVC, Controller chịu trách nhiệm xác định View nào sẽ được hiển thị phản ứng với bất kỳ hành động nào, bao gồm cả khi ứng dụng khởi động Điều này khác biệt so với MVP, nơi các hành động được định tuyến thông qua View đến Presenter Trong MVC, mỗi hành động trong View tương ứng với một cuộc gọi đến Controller cùng với một hành động Trong web, mỗi hành động liên quan đến một cuộc gọi đến một URL ở phía bên kia đó là một Controller đáp ứng Sau khi Controller đã hoàn tất quá trình xử lý, nó sẽ trả về View đúng
Hình 2.4 Mô hình MVC
2.2.5 Lợi ích của việc sử dụng mô hình MVP
Mô hình MVP (Model — View — Presenter) xuất hiện như một sự thay thế cho mô hình kiến trúc truyền thống MVC (Model — View — Controller) Khi sử dụng MVC làm kiến trúc phần mềm, nhà phát triển phải đối mặt với những khó khăn sau:
Hầu hết logic kinh doanh cốt lõi tập trung trong Controller Trong thời gian vận hành của ứng dụng, tệp này trở nên lớn lên và việc duy trì mã nguồn trở nên khó khăn
Do cơ chế giao diện người dùng và truy cập dữ liệu được kết nối chặt (tightly- coupled), cả Controller và lớp View đều nằm trong cùng một hoạt động hoặc đoạn mã Điều này gây khó khăn khi thực hiện các thay đổi trong các tính năng của ứng dụng Việc thực hiện kiểm thử đơn vị (Unit testing) trở nên khó khăn do phần lớn phần đang được kiểm thử cần các thành phần của Android SDK
2.2.6 Các ngôn ngữ và framework sử dụng mô hình MVP a) Laravel b) Ruby on Rails c) GWT (Google Web Toolkit) d) Vaadin e) ASP.NET Web Forms (with Web Forms MVP) f) WinForms (.NET) g) Android (with Mosby, Moxy, or other libraries) h) iOS (with VIPER)
MVVM
Mô hình MVVM (Model-View-ViewModel) phân chia một cách rõ ràng business logic và presentation logic của ứng dụng với giao diện người dùng (UI) Việc duy trì sự phân chia cặn kẽ giữa logic ứng dụng và UI giúp giải quyết nhiều vấn đề khi phát triển và làm cho ứng dụng dễ kiểm thử, bảo trì và phát triển Nó cũng có thể cải thiện đáng kể cơ hội tái sử dụng các thành phần và cho phép nhà phát triển và nhà thiết kế UI hợp tác một cách dễ dàng hơn khi phát triển các phần tương ứng của ứng dụng
2.3.2 Cấu trúc của mô hình MVVM
Có ba thành phần cốt lõi trong mô hình MVVM: a) Model (Mô hình): Model đại diện cho dữ liệu và logic kinh doanh của ứng dụng
Nó chịu trách nhiệm quản lý, truy xuất và lưu trữ dữ liệu Model thông báo cho ViewModel về bất kỳ thay đổi nào trong dữ liệu b) View (Giao diện): View chịu trách nhiệm hiển thị giao diện người dùng (UI) và trình bày dữ liệu cho người dùng Nó quan sát ViewModel và cập nhật UI dựa trên các thay đổi trong ViewModel c) ViewModel (Mô hình Giao diện): ViewModel đóng vai trò là một trung gian giữa Model và View Nó chứa logic trình bày và tiết lộ dữ liệu và lệnh mà View có thể liên kết ViewModel giao tiếp với Model để lấy và thay đổi dữ liệu và cập nhật View khi dữ liệu thay đổi
Hình 2.5 Cấu trúc mô hình MVVM
2.3.3 Hoạt động của mô hình MVVM Ở tầng cao trong mô hình MVVM (Model-View-ViewModel), View biết về ViewModel, và ViewModel biết về Model Tuy nhiên, Model không biết về ViewModel và ViewModel không biết về View Sự tách rời này được thiết kế một cách có chủ đích
32 để đảm bảo rằng ViewModel hoạt động như một trung gian, cô lập View khỏi sự phức tạp của Model Do đó, các thay đổi trong Model có thể xảy ra độc lập với View, tạo điều kiện cho sự linh hoạt và tiến triển trong dữ liệu và logic kinh doanh của ứng dụng Sự tách biệt này cải thiện khả năng bảo trì, khả năng kiểm thử và tổ chức mô-đun tổng thể trong kiến trúc MVVM
2.3.4 Sự khác biệt giữa MVC/MVP và MVVM
Xét tổng quan, sự khác biệt chính giữa MVC và MVVM là vai trò của thành phần trung gian Trong MVC, Model đóng vai trò như trung gian giữa View và Model, trong khi trong MVVM, ViewModel đóng vai trò như trung gian giữa View và Model MVC là một mô hình đơn giản hơn, trong khi MVVM linh hoạt hơn và cho phép phân chia rõ ràng hơn giữa các lớp khác nhau của ứng dụng Mặc dù cả MVC và MVVM đều là các mô hình hữu ích để tổ chức mã nguồn cho một ứng dụng phần mềm, MVVM mang lại nhiều ưu điểm hơn so với MVC, dưới đây là một số điểm: a) Phân chia rõ ràng về trách nhiệm:
Trong MVVM, ViewModel đóng vai trò như một trung gian giữa View và Model, cho phép phân chia rõ ràng hơn về trách nhiệm giữa các lớp khác nhau của ứng dụng Điều này có thể làm cho việc bảo trì và sửa đổi mã nguồn dễ dàng hơn theo thời gian b) Kiểm thử tốt hơn:
Vì ViewModel chịu trách nhiệm về việc tiết lộ dữ liệu và logic của Model cho View, nó có thể dễ dàng kiểm thử ViewModel một cách độc lập từ View Điều này có thể làm cho việc đảm bảo ứng dụng hoạt động đúng và tìm và sửa lỗi trở nên dễ dàng hơn c) Tính linh hoạt cao hơn:
ViewModel trong MVVM linh hoạt hơn Model trong MVC, vì nó có thể tiết lộ dữ liệu và logic từ Model một cách dễ dàng để View tiêu thụ Điều này có thể làm cho việc tạo ra các giao diện khác nhau cho cùng một dữ liệu và logic hoặc tái sử dụng cùng một ViewModel với nhiều View trở nên dễ dàng hơn d) Hỗ trợ tốt hơn cho nhiều nhà phát triển:
Bởi vì mô hình MVVM cho phép phân chia rõ ràng về trách nhiệm giữa các lớp khác nhau của ứng dụng, việc nhiều nhà phát triển làm việc đồng thời trên các phần khác nhau của mã nguồn có thể trở nên dễ dàng hơn Điều này có thể cải thiện hiệu suất của quá trình phát triển và giảm nguy cơ xung đột giữa các phần khác nhau của mã nguồn
2.3.5 Lợi ích của việc sử dụng mô hình MVVM
Một số lợi ích của mô hình MVVM có thể kể đến như: a) Khả năng bảo trì: Có thể duy trì tính linh hoạt và phát hành các phiên bản liên tiếp một cách nhanh chóng b) Khả năng mở rộng: Có khả năng thay thế hoặc thêm mới các phần mã c) Khả năng kiểm thử: Dễ dàng viết các bài kiểm thử đơn vị đối với logic cốt lõi d) Giao tiếp minh bạch: ViewModel cung cấp một giao diện trong suốt cho view controller, mà nó sử dụng để điền dữ liệu cho lớp view và tương tác với lớp model, kết quả là một giao tiếp trong suốt giữa các lớp của ứng dụng của bạn
2.3.6 Các ngôn ngữ và framework sử dụng mô hình MVVM a) MVVM Toolkit b) MVVM Foundation c) WPF Application Framework (WAF) d) Light MVVM e) Caliburn f) Cinch g) Prism h) ReactiveUI
Tóm lại, mô hình kiến trúc MVVM (Model-View-ViewModel) cung cấp một framework mạnh mẽ cho việc phát triển các ứng dụng có khả năng mở rộng và dễ bảo trì Bằng cách thúc đẩy sự phân chia rõ ràng về trách nhiệm giữa Model, View và ViewModel, MVVM cải thiện tổ chức mã nguồn và khả năng đọc mã ViewModel hoạt động như một trung gian, tạo điều kiện cho việc giao tiếp mượt mà giữa View và Model, cho phép tiến triển độc lập của mỗi thành phần Mô hình này không chỉ cải thiện khả năng bảo trì, khả năng mở rộng và khả năng kiểm thử, mà còn khuyến khích giao tiếp trong suốt giữa các lớp khác nhau của ứng dụng Mô hình MVVM đặc biệt hữu ích cho những nhà phát triển đang tìm kiếm một cách tiếp cận có cấu trúc và linh hoạt đối với phát triển phần mềm, giúp tối ưu hóa các phiên bản linh hoạt, sự mở rộng dễ dàng và sự hợp tác hiệu quả giữa các khía cạnh khác nhau của ứng dụng Tổng cộng, MVVM là
34 một mô hình quan trọng, đóng góp vào việc xây dựng các ứng dụng mạnh mẽ, có cấu trúc và thân thiện với người dùng.
Component-based
Component-based Architecture (CBA) là kiến trúc tập trung vào sự phân tách thiết kế của ứng dụng thành từng các chức năng riêng biệt hoặc các thành phần logic Mỗi thành phần đóng gói chức năng có định nghĩa rõ ràng vào một đơn vị nhị phân, và có thể được lưu trữ trong một thư viện và tích hợp vào một ứng dụng mà không cần sửa đổi các thành phần khác
2.4.2 Cấu trúc của mô hình component-based
Themes (Chủ đề): Chủ đề định nghĩa giao diện và cảm nhận của ứng dụng Thông thường, chúng được mô tả bởi các quy tắc bảng kiểu và định nghĩa lưới được sử dụng để định vị và kích thước các thành phần trên màn hình Chúng cung cấp một trải nghiệm nhất quán trên tất cả các nền tảng và kịch bản, tạo ra thương hiệu thống nhất bất kể các yếu tố như các đối tượng cụ thể
Widgets (Tiện ích): Tiện ích tương tự như các thành phần ở nhiều khía cạnh, ngoại trừ việc chúng chưa đến mức đó Tiện ích cung cấp một tính năng bổ sung và có thể tái sử dụng, thường liên quan đến giao diện người dùng, và có thể trở thành thành phần khi chúng bao gồm một tập hợp định nghĩa như tham số và biến
Libraries (Thư viện): Thư viện bao quanh tiện ích hoặc khối cung cấp một giao diện dễ tương tác Ví dụ, thư viện JavaScript thường cung cấp một trải nghiệm front-end xuất sắc
Connectors (Kết nối): Như tên gọi, kết nối cho phép tích hợp mà không cần viết thêm code, giảm thời gian và công sức cần thiết và loại bỏ lỗi Kết nối cho phép bạn tích hợp với các ứng dụng khác như Paypal hoặc Facebook
Plugin (Tiện ích): Các tiện ích như Zapier cho phép tích hợp mà không cần viết thêm code cho ứng dụng của bạn Chúng là bước cần thiết nếu bạn muốn tiết kiệm thời gian và công sức trong khi cho phép người sử dụng xem danh bạ của họ ở những nơi khác nhau, như Slack hoặc Salesforce
2.4.3 Hoạt động của mô hình component-based
Mỗi component được xây dựng để thực hiện một nhiệm vụ theo cách được định rõ bởi kiến trúc Các component được lưu trữ trong một thư viện và được lập trình viên
“lắp ráp” Các component trò chuyện với nhau thông qua các giao diện chương trình ứng dụng (APIs) để đơn giản hóa
Giao tiếp được hỗ trợ bởi một trình điều phối yêu cầu đối tượng(object request broker), đôi khi được gọi là "software bus" vì nó cung cấp một mặt bằng giao tiếp duy nhất mà tất cả các thành phần đều sử dụng Giao tiếp có thể xảy ra theo nhiều cách, chẳng hạn như bất đồng bộ, thông qua broadcast, thông qua hệ thống định hình theo tin nhắn (message-driven system), hoặc như một phần của dòng dữ liệu liên tục
2.4.4 Lợi ích của việc sử dụng mô hình component-based
Khả năng tái sử dụng: Các thành phần được thiết kế để có thể kết nối vào nhiều ứng dụng khác nhau mà không cần sửa đổi hoặc điều chỉnh đặc biệt
Khả năng mở rộng: Một thành phần có thể được kết hợp với các thành phần khác để tạo ra các hành vi mới
Khả năng thay thế: Các thành phần có chức năng tương tự có thể được thay thế lẫn nhau
Tính đóng gói: Các thành phần tự đóng gói và tiếp cận chức năng thông qua các giao diện, trong khi che giấu chi tiết về quy trình nội tại
Tính độc lập: Các thành phần có sự phụ thuộc tối thiểu vào các thành phần khác và có thể hoạt động trong các môi trường và ngữ cảnh khác nhau
2.4.5 Các ngôn ngữ và framework sử dụng mô hình component-based
.NET Windows Presentation Foundation (WPF)
Tóm lại, Component-based Architecture(CBA) là một mô hình quan trọng trong phát triển phần mềm, khuyến khích tính mô-đun, khả năng tái sử dụng và dễ bảo trì Bằng cách phân chia ứng dụng thành các thành phần tự chủ và có thể tái sử dụng, CBA giúp nhà phát triển thiết kế, triển khai và cập nhật hệ thống phức tạp một cách hiệu quả Việc phân chia trách nhiệm trong các thành phần tạo ra một mã nguồn rõ ràng và có tổ chức, làm cho nó dễ hiểu, dễ mở rộng và sửa lỗi Các framework và nền tảng tuân theo nguyên tắc CBA, như Angular, React và Vue.js, giúp nhà phát triển xây dựng ứng dụng có khả năng mở rộng và linh hoạt Sự tập trung vào khả năng tái sử dụng và cô lập của các thành phần trong CBA đóng góp vào quy trình phát triển hiệu quả hơn, giảm thời gian đưa sản phẩm ra thị trường và khả năng thích ứng và mở rộng ứng dụng theo yêu cầu thay đổi.
Micro Frontend
2.5.1 Khái niệm Áp dụng kỹ thuật Microservice vào Frontend, Micro-Frontend (MFE) là mô hình kiến trúc giúp giải quyết những khó khăn của ứng dụng Frontend đơn thể (Frontend Monolith) bằng cách phân tách thành các mô-đun có khả năng triển khai và mở rộng độc lập
2.5.2 Cấu trúc của mô hình micro Frontend
Các thành phần chính của kiến trúc Micro-Frontend: a) Host container: Tất cả các micro Frontend bắt đầu từ một host container Đây là ứng dụng chính chứa tất cả các thành phần bên trong Đây là file JavaScript chính được gửi đến người dùng khi họ truy cập ứng dụng Những thành phần mang tính toàn cục như footer, header và điều hướng trang thường được tích hợp vào host container b) Micro-Frontends: Một host container sẽ có nhiều Micro Frontend - là những mô đun độc lập chịu trách nhiệm cho một tính năng cụ thể hoặc một phần của ứng dụng
2.5.3 Hoạt động của mô hình micro Frontend
Một trang web đơn thể có thể được cắt nhỏ cục bộ ra thành các micro-Frontends Khi người dùng gửi yêu cầu truy cập, hệ thống chỉ gửi code của host container đến người dùng Sau đó, tùy theo quy trình của người dùng, sẽ gửi lời gọi network để tải thêm các
37 tính năng khác cho đến khi kết thúc ứng dụng Mã nguồn có thể ở nhiều server khác khau so với host container và có thể được cập nhật bất kỳ lúc nào
2.5.4 Lợi ích của việc sử dụng mô hình micro Frontend
Scalability: nhiều nhóm có thể làm việc cùng lúc trên một webpage, vì các micro- Frontend vận hành độc lập với nhau
Reusability: nếu các micro-Frontend vận hành theo một tiêu chuẩn chung định trước, chúng có thể được cô lập thành các component và sử dụng lại ở tính năng khác
Technology Agnotism: host container và các micro-Frontend có thể được viết từ nhiều ngôn ngữ lập trình khác nhau miễn là vận hành theo một tiêu chuẩn chung định trước
Isolation of failures (Cô lập sự cố): Vì Micro Frontends hoạt động độc lập, sự cố hoặc vấn đề xảy ra trong một Micro Frontend không nhất thiết phải ảnh hưởng đến toàn bộ ứng dụng Sự cô lập này giúp dễ dàng xác định và giải quyết vấn đề
2.5.5 Các công nghệ và framework sử dụng mô hình micro Frontend
Micro Frontends in Action (Mosaic)
Micro Frontends (MFE) mang lại một phương pháp mang tính mô-đun và có khả năng mở rộng phù hợp với yêu cầu của kiến trúc phần mềm hiện đại Khả năng phát triển, triển khai và cập nhật các tính năng hoặc một phần độc lập của ứng dụng mang lại sự linh hoạt và nhanh chóng chưa từng có MFE cho phép sự đa dạng về công nghệ, framework và ngôn ngữ tồn tại chung trong cùng một ứng dụng, phục vụ cho những nhu cầu chuyên sâu của từng nhóm phát triển cụ thể Các lợi ích từ việc triển khai độc lập, đa dạng công nghệ và sự hợp tác cải thiện đáng kể chu kỳ phát triển và bảo trì Tuy nhiên, để tận dụng đầy đủ tiềm năng của mô hình kiến trúc này, việc xem xét cẩn thận về chiến lược giao tiếp và thiết kế tổng thể của hệ thống là quan trọng Trong bối cảnh
38 các tổ chức tiếp tục phát triển các phương thức phát triển web của họ, Micro Frontends nổi lên như một giải pháp hấp dẫn để đối mặt với thách thức về khả năng mở rộng, bảo trì và triển khai tính năng nhanh chóng trong cảnh động đất của ứng dụng web hiện đại.
Kiến trúc Flux
Flux được giới thiệu bởi Facebook để xây dựng Ứng dụng Đơn Trang (SPAs) Flux là một kiến trúc được sử dụng để xây dựng giao diện người dùng, đặc biệt là trong ứng dụng web, và giải quyết các thách thức của việc quản lý luồng dữ liệu trong các ứng dụng lớn và phức tạp
Flux chia ứng dụng thành các thành phần chính như sau: a) Stores (Kho) b) Dispatcher (Trình Phân Phối) c) Views (Hiển Thị) d) Action/ Action Creators (hành động)
Hình 2.6 Các thành phần của kiến trúc Flux
2.6.2 Cấu trúc của kiến trúc Flux a) Stores (Kho):
Stores quản lý các State (trạng thái) của ứng dụng, cũng như lưu trữ cả Domain State (trạng thái miền) và User Interaction State (trạng thái giao diện người dùng) Mỗi store nên có một trạng thái có thể dự đoán và không thể thay đổi
Store và State là hai khái niệm khác nhau State là một data value Store là một đối tượng có thể quản lý State thông qua các methods (phương thức) Một Store quản lý
39 nhiều đối tượng Nó là nguồn thông tin duy nhất đối với những đối tượng cụ thể đó Không có các phương thức thiết lập trên Store Bạn chỉ có thể yêu cầu thay đổi trạng thái bằng cách truyền một hành động đến dispatcher Stores không phụ thuộc vào các Store khác b) Dispatcher (Trình Phân Phối):
Dispatcher chịu trách nhiệm phân phối các Actions (hành động/sự kiện) đến các stores đã đăng ký Nó hoạt động như một trung tâm tập trung quản lý luồng dữ liệu trong ứng dụng Dispatcher là một đối tượng duy nhất phát sóng Action đến tất cả các store đã đăng ký Stores cần được khai báo đăng ký để nhận Action khi ứng dụng bắt đầu c) View (Hiển Thị):
View là một UI component để xây dựng giao diện người dùng và xử lý tương tác người dùng, được tổ chức theo cấu trúc cây (tree structure) Views có nhiệm vụ lắng nghe sự thay đổi của store và xây dựng lại giao diện dựa trên state mới Views được chia thành 2 loại khác nhau là Presentation View và Container View
Presentation views không kết nối với dispatcher hoặc stores Chúng giao tiếp chỉ thông qua các thuộc tính của chính mình
Container views được kết nối với stores và dispatcher Chúng lắng nghe sự kiện từ stores và cung cấp dữ liệu cho các thành phần trình bày Chúng nhận dữ liệu mới bằng cách sử dụng các phương thức public getter của stores và sau đó chuyển dữ liệu đó xuống cây views (views tree).Container views truyền đi các Actions khi có phản hồi từ người dùng d) Actions (Hành động):
Hành động là một đối tượng chứa tất cả thông tin cần thiết để thực hiện hành động đó, có một thuộc tính type để xác định loại hành động Khi các Action di chuyển trong ứng dụng, Action nên được thiết lập không thể thay đổi (immutable)
Hành động có thể đến từ nhiều nơi khác nhau Chúng có thể đến từ các view như kết quả của tương tác người dùng Chúng có thể đến từ các nơi khác như mã khởi tạo (init code), nơi dữ liệu có thể được lấy từ một Web API và hành động được kích hoạt để cập nhật các view Hành động cũng có thể đến từ một bộ đếm thời gian yêu cầu cập nhật màn hình
2.6.3 Hoạt động của kiến trúc Flux
Luồng dữ liệu trong Flux tuân theo một con đường một chiều: a) Người dùng tương tác với view, kích hoạt một hành động b) Hành động được phân phối bởi Dispatcher c) Các stores nhận hành động và cập nhật trạng thái của mình d) Các views được thông báo về các thay đổi trạng thái trong stores và cập nhật giao diện tương ứng
2.6.4 Lợi ích của việc sử dụng kiến trúc Flux
Kiến trúc Flux là lựa chọn tốt hơn trong một ứng dụng nơi các view không ánh xạ trực tiếp với các stores của miền dữ liệu Nói một cách khác, khi các view có thể tạo ra các hành động sẽ cập nhật nhiều stores và các stores có thể kích hoạt các thay đổi sẽ cập nhật nhiều views
Một trong những ưu điểm của Flux là tính dự đoán và dễ sửa lỗi Vì luồng dữ liệu di chuyển theo một chiều, việc theo dõi cách thay đổi dữ liệu lan truyền qua hệ thống trở nên dễ dàng hơn
Việc phân chia trách nhiệm trong Flux giúp dễ dàng theo dõi trạng thái và hành vi của ứng dụng
Hành động có thể được lưu trữ và sau đó được tái thực hiện
2.6.5 Các công nghệ và framework sử dụng kiến trúc Flux
Tóm lại, Flux là một mô hình kiến trúc mạnh mẽ được Facebook phát triển để giải quyết những thách thức của việc quản lý luồng dữ liệu phức tạp trong các ứng dụng lớn, đặc biệt là những ứng dụng có giao diện người dùng động Nó nhấn mạnh vào việc chuyển dữ liệu theo một hướng duy nhất, phân tách các vấn đề thành hành động, store và views, tạo ra một cấu trúc rõ ràng và dự đoán cho việc xây dựng ứng dụng Mặc dù Flux chính nó không phải là một phần mềm hay framework cụ thể, những nguyên tắc của nó đã ảnh hưởng đến việc phát triển nhiều thư viện và framework khác nhau, như
Redux, Reflux và Fluxible Bằng cách buộc một luồng dữ liệu theo chiều một hướng và cung cấp một dispatcher tập trung để quản lý hành động, Flux nâng cao tính dự đoán, khả năng bảo trì và khả năng gỡ lỗi của ứng dụng, tạo nên một phương pháp quan trọng để xây dựng các ứng dụng web có quy mô lớn và có tổ chức tốt.
Kiến trúc Redux
Một trong những triển khai phổ biến nhất của kiến trúc Flux là Redux, thường được sử dụng với React Redux đơn giản hóa kiến trúc Flux và cung cấp một store duy nhất với cách tiếp cận có tổ chức hơn để quản lý trạng thái trong ứng dụng React
Redux là một thư viện mã nguồn (source code library) mở được sử dụng phổ biến trong lập trình JavaScript, đặc biệt là kết hợp thường xuyên với React để quản lý trạng thái (State Management) của một ứng dụng
2.7.2 Cấu trúc của kiến trúc Redux
Hình 2.7 Cấu trúc của kiến trúc Redux
Cấu trúc của Redux được phát triển dựa theo khuôn mẫu của Flux cùng một số thay đổi như sau: a) Redux Store:
Một cửa hàng trung tâm, duy nhất giữ toàn bộ các trạng thái của ứng dụng Cửa hàng trung tâm này giúp dễ dàng quản lý và duy trì trạng thái một cách dễ dự đoán
State (Trạng thái) được thiết lập Read-only trong Redux và chỉ có thể thay đổi khi phát ra một Action (hành động) mô tả những thay đổi chúng ta muốn thực hiện trong trạng thái
Nó nên được xem xét và duy trì như một nguồn thông tin duy nhất (single source of true) về trạng thái của ứng dụng b) Action:
Actions là các đối tượng JavaScript thông thường đại diện cho sự kiện hoặc tương tác người dùng Chúng có một thuộc tính type xác định loại hành động và có thể mang theo dữ liệu bổ sung
Khi muốn thay đổi trạng thái của ứng dụng, ta cần diễn đạt ý định bằng cách phát ra hoặc phát đi một hành động c) Reducer:
Reducers là các hàm chịu trách nhiệm xử lý hành động và cập nhật trạng thái của ứng dụng Reducers chỉ định cách trạng thái thay đổi dựa trên hành động
Reducers nhận vào hai thứ: trạng thái trước đó (previous state) và Action Sau đó, chúng đọc và trả về một thực thể duy nhất: phiên bản trạng thái mới được cập nhật
2.7.3 Hoạt động của kiến trúc Redux a) Tạo Hành Động (Action):
Một hành động được tạo ra khi có một sự kiện hoặc tương tác người dùng trong ứng dụng Hành động là các đối tượng JavaScript thông thường với thuộc tính type mô tả hành động và dữ liệu bổ sung nếu cần b) Phát Hành Động (Dispatch):
Hành động được phát ra bằng cách sử dụng hàm dispatch Hàm này được cung cấp bởi cửa hàng Redux Việc phát hành hành động là quá trình gửi một hành động đến cửa hàng c) Reducers Xử Lý Hành Động:
Reducers là các hàm thuần túy nhận vào trạng thái hiện tại và một hành động làm tham số, chúng chỉ định cách trạng thái sẽ thay đổi dựa trên hành động Reducers trả về một trạng thái mới và chúng không nên sửa đổi trạng thái hiện tại trực tiếp d) Cập Nhật Trạng Thái:
Trạng thái mới được trả về bởi reducer trở thành trạng thái hiện tại của ứng dụng Redux đảm bảo rằng trạng thái được xem xét như một đối tượng không thay đổi, có nghĩa là tạo ra một đối tượng trạng thái mới cho mỗi cập nhật e) Đăng Ký và Cập Nhật Giao Diện:
Các thành phần hoặc view quan tâm đến sự thay đổi trạng thái đăng ký theo dõi cửa hàng Redux Khi trạng thái thay đổi, các thành phần đã đăng ký được thông báo, kích thích việc vẽ lại giao diện với trạng thái đã cập nhật
2.7.4 So sánh kiến trúc Redux so với kiến trúc Flux
Redux được phát triển từ Flux và đều là các kiến trúc để quản lý trạng thái của ứng dụng, đặc biệt trong ngữ cảnh của giao diện người dùng
Flux có thể trở nên phức tạp hơn khi ứng dụng mở rộng do khả năng xuất hiện nhiều stores Redux có cách tiếp cận chỉ một store trung tâm, duy nhất, đơn giản hóa cấu trúc tổng thể
Cả Flux và Redux đều được sử dụng rộng rãi, nhưng Redux đã có sự phổ biến hơn, đặc biệt là trong hệ sinh thái React
Redux cần nhiều thời gian hơn để bắt đầu và phát triển ứng dụng, đặc biệt đối với những nhà phát triển mới với khái niệm về Immutable State (trạng thái bất biến) và luồng dữ liệu một chiều (unidirectional data flow)
2.7.5 Các công nghệ và framework sử dụng kiến trúc Redux
CÁC VẤN ĐỀ CƠ BẢN CỦA FRONTEND
Tương tác UI
Khi thiết kế UI, nhà phát triển cần phải quan tâm và giải quyết những vấn đề gây ảnh hưởng đến trải nghiệm người dùng như: a) Tương tác người dùng quá phức tạp b) Trình bày quá nhiều thông tin trong một thời điểm c) Thiếu sự nhất quán giữa các thành phần như bố cục, chủ đề, d) Thời gian phản hồi chậm
49 e) Phản hồi tối ý f) Cách tương tác khó hiểu g) Thông báo lỗi mơ hồ h) Xử lý lỗi kém
Do đó, đòi hỏi các thư viện front-end của cung cấp nhà phát triển những công cụ hửu hiệu, hỗ trợ kiểm tra và giải quyết những vấn đề hoặc sai sót phát sinh khi phát triển ứng dụng
React cung cấp kiến trúc hướng thành phần (Component-based architecture) để giúp giải quyết những vấn đề UI thường thấy: a) Giao diện quá phức tạp và mẫu thiết kế không đồng nhất: React khuyến khích kiến trúc đơn mô-đun, hướng thành phần Mỗi thành phần đóng gói logic và giao diện của nó, giúp quản lý và giải thích giao diện dễ dàng hơn Các thành phần có thể tái sử dụng cũng giúp duy trì một thiết kế đồng nhất b) Hiệu suất chậm và độ trễ trong phản ứng của giao diện người dùng: React sử dụng một virtual DOM để cập nhật DOM thật một cách hiệu quả Bằng cách giảm thiểu việc thay đổi trực tiếp của DOM và gom nhóm các cập nhật, React cải thiện hiệu suất và đảm bảo giao diện người dùng phản ứng nhanh hơn c) Mã lệnh phức tạp và dễ gây lỗi cho việc tương tác với giao diện người dùng: React sử dụng lập trình khai báo, mô tả giao diện dựa trên trạng thái của ứng dụng Tiếp cận này giúp đơn giản hóa mã lệnh, giảm lỗi và dễ hiểu và duy trì logic của giao diện d) Dòng dữ liệu không đồng nhất hoặc không ngờ dẫn đến vấn đề với giao diện người dùng: React áp dụng mô hình dòng dữ liệu một chiều, có nghĩa là thay đổi dữ liệu chỉ di chuyển theo một hướng, giúp dễ theo dõi và quản lý sự thay đổi Điều này giúp ngăn chặn các tác động phụ không mong muốn và đảm bảo trạng thái giao diện dự đoán được hơn e) Cấu trúc điều hướng (navigation) không rõ ràng hoặc mơ hồ: React Router là một thư viện phổ biến để xử lý điều hướng trong ứng dụng React Nó cho phép nhà phát triển định nghĩa một cấu trúc điều hướng rõ ràng và có tổ chức, giúp người dùng dễ dàng hiểu và điều hướng trong ứng dụng
50 f) Hiển thị quá nhiều thông tin hoặc nội dung không liên quan: React hỗ trợ việc hiển thị có điều kiện, cho phép nhà phát triển hiển thị hoặc ẩn các thành phần dựa trên điều kiện cụ thể Điều này giúp quản lý hiển thị thông tin và kiểm soát điều người dùng nhìn thấy, giảm bớt quá tải thông tin g) Thông báo lỗi mơ hồ hoặc xử lý lỗi kém: React giới thiệu khái niệm về "error boundaries", cho phép nhà phát triển bắt lỗi JavaScript xảy ra trong quá trình render Điều này giúp hiển thị thông báo lỗi có ý nghĩa cho người dùng và ngăn chặn ứng dụng từ việc bị crash toàn bộ h) Thiếu khả năng đáp ứng thông tin trên nhiều thiết bị: React hỗ trợ thiết kế đáp ứng bằng cách cho phép nhà phát triển tạo ra các thành phần thích ứng với các kích thước màn hình khác nhau Các thư viện như React-Responsive có thể được sử dụng để xử lý tính năng đáp ứng một cách hiệu quả hơn
Flutter được thiết kế để giải quyết nhiều thách thức với giao diện người dùng và cung cấp một khung làm việc nhất quán: a) Giao diện quá phức tạp và mẫu thiết kế không đồng nhất: Flutter sử dụng một kiến trúc dựa trên các Widget, trong đó mọi thứ trong UI là một Widget Điều này khuyến khích một cách tiếp cận modul và có thể tái sử dụng để xây dựng các phần giao diện, đóng góp vào việc duy trì một thiết kế đồng nhất trên toàn ứng dụng b) Hiệu suất chậm và độ trễ trong phản ứng của giao diện người dùng: Flutter có bộ kỹ thuật render riêng của mình vẽ các Widget trực tiếp lên màn hình Điều này loại bỏ cần thiết của một cầu nối giữa ứng dụng và nền tảng native, kết quả là giao diện người dùng với hiệu suất cao, có các hiệu ứng mượt mà và chuyển động c) Mã lệnh phức tạp và dễ gây lỗi cho việc tương tác với giao diện người dùng: Flutter sử dụng phương pháp lập trình khai báo (declarative syntax) để phát triển giao diện người dùng Nhà phát triển xây dựng giao diện bằng cách đặc tả, và Flutter cập nhật giao diện người dùng sao cho phản ánh trạng thái mong muốn Điều này làm cho mã lệnh trở nên dễ đọc hơn và ít gặp lỗi hơn d) Chu kỳ phát triển chậm và thời gian gỡ lỗi dài: Tính năng Hot Reload của Flutter cho phép nhà phát triển thấy ngay tác động của các thay đổi mã lệnh lên ứng dụng đang chạy, làm cho quá trình phát triển trở nên nhanh chóng và có thể lặp lại
51 e) Cấu trúc điều hướng không rõ ràng hoặc mơ hồ: Flutter cung cấp một hệ thống điều hướng tích hợp với một Widget Navigator Điều này giúp đơn giản hóa việc xác định một cấu trúc điều hướng rõ ràng, quản lý các route, và chuyển đổi giữa các màn hình một cách có tổ chức f) Thiếu tính đáp ứng trên nhiều thiết bị: Flutter được thiết kế để có độ đáp ứng mặc định Các Widget tự động thích ứng với các kích thước màn hình khác nhau, và framework cung cấp các công cụ để tạo ra bố cục hoạt động tốt trên nhiều thiết bị g) Quá tải thông tin hoặc hiển thị nội dung không liên quan: Flutter khuyến khích việc sử dụng cây Widget, trong đó mỗi Widget đại diện cho một phần của UI Nhà phát triển có thể dễ dàng hợp nhất và cấu trúc các Widget để quản lý việc hiển thị thông tin và kiểm soát những gì người dùng nhìn thấy h) Thiếu phản hồi và trạng thái ứng dụng không rõ ràng: Flutter cung cấp nhiều lựa chọn cho quản lý trạng thái, bao gồm trạng thái của Widget, inherited Widgets, và các giải pháp quản lý trạng thái bên ngoài như Redux Điều này cho phép nhà phát triển quản lý trạng thái ứng dụng hiệu quả và cung cấp phản hồi rõ ràng cho người dùng i) Thông báo lỗi mơ hồ và xử lý lỗi kém: Flutter bao gồm một cơ chế xử lý lỗi mạnh mẽ Nhà phát triển có thể sử dụng khối try-catch để bắt lỗi và hiển thị thông báo lỗi có ý nghĩa cho người dùng Flutter cũng cung cấp các Widget xử lý lỗi để xử lý lỗi một cách êm dịu và ngăn chặn ứng dụng từ việc bị crash toàn bộ k) Thiếu các tính năng hoặc chức năng cụ thể: Flutter có một hệ sinh thái phong phú của các gói hỗ trợ, mà nhà phát triển có thể sử dụng để thêm các tính năng hoặc chức năng cụ thể vào ứng dụng của mình Các gói này bao gồm nhiều trường hợp sử dụng và giúp giải quyết các thách thức cụ thể với giao diện người dùng.
Form Validation
Trước khi gửi dữ liệu cho server, cần phải có phương pháp kiểm tra tính đúng đắn của dữ liệu, nhằm hạn chế lỗi trả về từ server nhằm tăng hiệu suất hoạt động của ứng dụng
Form validation là quá trình kiểm tra và xác minh tính hợp lệ của dữ liệu nhập vào trong một biểu mẫu (form) Quá trình này thường được sử dụng để đảm bảo rằng người
52 dùng đã nhập thông tin đúng cách và đầy đủ trước khi dữ liệu được gửi đến máy chủ hoặc xử lý trong ứng dụng
Tùy vào điều kiện, yêu cầu, độ phức tạp, của ứng dụng mà ta có nhiều phương thức form validation khác nhau: a) Form Validation bằng State và Events:
React có tích hợp hàm useState() để nhận biết sự thay đổi của trang thái form Và qua những eventHanler() (hàm xử lí sự kiện) để quản lí trạng thái của form, cũng như xử lý các sự kiện của form bằng các thuật toán logic tự quy định, cũng như báo lỗi khi cần thiết b) Thư viện Formik và thư viện Yup:
Yup là một thư viện JavaScript giúp thực hiện việc kiểm tra dữ liệu (form validation) theo các quy tắc định nghĩa trước Nó thường được sử dụng để kiểm tra tính hợp lệ của dữ liệu trong các ứng dụng React
Hình 3.4 Mẫu mã lệnh sử dụng thư viện yup và react-hook-form
Formik là một thư viện quản lý form trong React, giúp đơn giản hóa quá trình quản lý trạng thái form, xử lý sự kiện, và thực hiện kiểm tra tính hợp lệ của dữ liệu
Hình 3.5 Mẫu mã lệnh sử dụng formik
Sử dụng Yup và Formik cùng nhau là một phương pháp phổ biến để kiểm tra tính hợp lệ trong ứng dụng React Yup được sử dụng để định nghĩa các schema kiểm tra, và Formik được sử dụng để quản lý trạng thái form và xử lý việc submit form c) React Hook Form:
React Hook Form là một thư viện React được thiết kế để quản lý và xử lý các form trong ứng dụng React bằng cách sử dụng React hooks Thư viện này cung cấp một cách đơn giản và hiệu quả để quản lý trạng thái form, kiểm tra tính hợp lệ, và xử lý sự kiện của form
Hình 3.6 Mẫu mã lệnh sử dụng react-hook-form
3.3.4 Form Validation với Flutter a) TextFormField Widget và Form Widget:
TextFormField của Flutter thường được sử dụng kết hợp với Widget Form để thực hiện các kiểm tra hợp lệ cơ bản thông qua thuộc tính validator của TextFormField để định nghĩa một hàm kiểm tra
Hình 3.7 Mẫu mã lệnh sử dụng TextFormField b) Kiểm tra dựa trên Controllers:
Tạo Frontend động (dynamic form)
Bạn có thể sử dụng TextEditingController với các form và kiểm tra input một cách thủ công Ví dụ, việc chạy một hàm gọi lại (callback function) mỗi khi textfield thay đổi c) Các Gói (Package) có sẵn cho Form Validation:
Có các gói có sẵn trong hệ sinh thái Flutter có thể hỗ trợ việc kiểm tra form Ví dụ, gói flutter_form_bloc hoặc provider có thể được sử dụng để quản lý trạng thái form và kiểm tra
Hình 3.8 Gói form_bloc hỗ trợ cho Flutter
3.4 Tạo Frontend động (dynamic form)
Dynamic form (trang động) là một web form có thể thay đổi cấu trúc hoặc giao diện của mình dựa trên tương tác của người dùng hoặc các yếu tố bên ngoài Khác với biểu mẫu tĩnh, cấu trúc và các trường là cố định, Frontend động mang lại tính linh hoạt và thích nghi với thay đổi của người dùng Các công nghệ như React, Angular hoặc Vue.js thường được sử dụng để triển khai biểu mẫu động trong các ứng dụng web
BEEKAI là công nghệ xây dựng ứng dụng trang web (form application builder) bằng phương pháp drag-and-drop BEEKAI có thể xây dựng các trang khảo sát, giải đố và thậm chí các ứng dụng trang web hoàn thiện mà không cần kĩ năng lập trình
Hình 3.10 Tổ chức cấu trúc trang và các form câu hỏi bằng bảng điều khiển (control panel) và phương thức drag-and-drop
Hình 3.11 Lọc đầu vào (Input Sanitization)
Hình 3.12 Thiết kế chủ đề
Hình 3.13 Tự tạo code (Code Generation): Tự động xây dựng ứng dụng bằng ngôn ngữ HTML hoặc React Hook Form
3.4.2.2 Xây dựng form với nhiều bước (multi-step form builder) a) Flow Control: BEEKAI có khả năng thiết kế và phân bước nhanh chóng ứng dụng biểu mẫu thông qua các biểu đồ minh họa từ đó có thể nhanh chóng sửa đổi thiết kế và bảo trì, cũng như cho pháp tích hợp logic doanh nghiệp (business logic) khi cần thiết một cách tiện lợi
Hình 3.14 Flow control của BEEKAI b) Tích hợp đa nền tảng:
Hình 3.15 BEEKAI có khả năng duy trì khả năng đáp ứng người dùng trên mọi nền tảng
60 c) Thống kê ứng dụng (Application Analytics): BEEKAI có khả năng phân tích sâu hệ thống ứng dụng BEEKAI Analytics theo dõi và phân tích các tương tác của người dùng với ứng dụng, qua đó cho phép nhà phát triển đưa ra những quyết định chính xác trong tương lai
Hình 3.16 Kết quả phân tích của BEEKAI
3.4.2.3 Theo dõi hồ sơ (Submission) a) Submission Tracker: Hệ thống đơn nhất giúp theo dõi thông tin người dùng, xem bảng tin và tìm kiếm lịch sử hồ sơ
Hình 3.17 Giao diện theo dõi hồ sơ của BEEKAI
61 b) Xuất bản dữ liệu: Hỗ trợ tổng hợp và chuyển đổi dữ liệu thành dạng CSV cho phân tích thống kê
Hình 3.18 Xuất bản dữ liệu theo dõi người dùng
React Hooks là các hàm cho phép người lập trình React sử dụng State (trạng thái) và các tính năng khác của React trong các thành phần hàm
Chúng được giới thiệu trong phiên bản React 16.8 để cung cấp một cách làm tường minh và ngắn gọn hơn khi làm việc với logic có trạng thái và các hiệu ứng phụ trong các thành phần hàm Các “hooks” có thể được kết hợp lẫn nhau để tạo ra các hooks mới
3.4.3.2 Các loại React Hooks a) State Hook (Hook Trạng Thái):
State giúp có thành phần React “nhớ” các thông tin như thông tin đầu vào của người dùng Để thêm State vào thành phần, ta có thể gọi 2 hook:
UseState() khai báo một biến State cập nhật trực tiếp vào thành phần
UseReducer() khai báo một biến State với logic cập nhật nằm trong hàm Reducer b) Context hook (hook Ngữ Cảnh):
Context giúp 1 thành phần có thể truy cập thông tin từ một thành phần cha nào đó mà không cần truyền vào Props
Hook UseContext() đọc và theo dõi ngữ cảnh của 1 thành phần cha nào đó c) Ref Hook (Hook Tham Chiếu):
Ref cho phép các thành phần có thể lưu các thông tin không dùng để render, như là một mối thành phần trong DOM Khác với State, cập nhật một Ref không kích hoạt
62 chức năng render của thành phần Ref rất hữu dụng khi cần phải làm việc với các hệ thống ngoài React, nhưng các trình duyệt API có sẵn useRef() khai bái một ref Nó có thể được dùng để lưu bất kì giá trị nào, nhưng thường xuyên được dùng để lưu các nút của DOM useImperativeHandle() cho phép bạn tùy chỉnh các ref lưu trong thành phần Hàm này hiếm khi được sử dụng d) Effect Hooks (Hook Hiệu Ứng):
Effect cho phép thành phần kết nối và đồng bộ đến hệ thống ngoại vi, bao gồm xử lí hệ thống mạng, DOM của trình duyệt, hình động, và các component được xây dựng bằng các thư viện UI khác, useEffect() kết nối thành phần tới hệ thống ngoại vi
Effect là “lối thoát” của hệ thống React Không sử dụng Effect để quản lí luồng dữ liệu bên trong ứng dụng e) Performance Hooks (Hook Năng Suất):
Một cách thường được sử dụng để tăng năng suất tái render là lược bỏ những tác vụ không cần thiết useMemo() cho khả năng ghi nhớ kết quả của 1 phép tính lớn useCallback() cho khả năng ghi nhớ một định nghĩa hàm trước khi truyền nó xuống một thành phần đã được tối ưu f) Resource Hook (Hook Tài Nguyên):
Resource có thể được truy cập bởi một thành phần mà không cần phải khai báo Resource nằm trong State của nó use() được sử dụng để đọc giá trị của một resource nào đó như Promise hoặc
Context g) Các loại Hook khác:
Có một số loại Hook khác, nhưng chỉ thường được dùng bởi nhà phát triển thư viện, và hiếm khi được dùng bởi người phát triển ứng dụng.
KHÁI QUÁT VỀ FLUTTER
Khái niệm
Theo giới thiệu tại trang FAQ của Flutter, Flutter được giới thiệu như một bộ công cụ giao diện người dùng di động của Google để tạo nên các ứng dụng hoàn thiện, được biên dịch thành các ứng dụng native cho thiết bị di động, web và máy tính để bàn từ một bộ mã nguồn duy nhất Flutter là bộ mã nguồn mở và miễn phí được các nhà phát triển và tổ chức trên khắp thế giới sử dụng
Dart là một ngôn ngữ lập trình mới, hiện đại và là ngôn ngữ hướng đối tượng được phát triển bởi Google Nó được biết đến rộng rãi thông qua việc là ngôn ngữ chính của framework Flutter Dart hỗ trợ kiểu dữ liệu tĩnh, lập trình bất đồng bộ và cung cấp trình biên dịch Just-In-Time (JIT) cho tính năng hot-reload lúc phát triển và Ahead-Of-Time (AOT) dành cho sản phẩm thực tế nhằm tối ưu hoá thời gian thực thi mã nguồn
Hình 4.1 Ngôn ngữ Dart.
Lịch sử phát triển
Vào những nằm đầu, vào năm 2015, Goolgle giới thiệu phiên bản thử nghiệm của dự án xây dựng ứng dụng di động tương tự ứng dụng gốc Trong những nằm tiếp theo, thông qua quá trình thử nghiệm và phát triển, Google đã cho ra mắt chính thức phiên bản 1.0 của Flutter vào năm 2018
Phiên bản 1.12 ra mắt năm 2019 hỗ trợ iOS darkmode cho iOS 13, thêm nhiều tính năng, Widget, nhiều thay đổi về API của framework
Phiên bản 1.17 năm 2020 tối ưu về hiệu năng, giới thiệu những component mới theo Material design và công cụ theo dõi các tương tác mạng
Phiên bản 2.0 đánh dấu khả năng sử dụng Flutter để phát triển các ứng dụng web một cách ổn định, công bố bản thử nghiệm beta của tính năng Flutter desktop, cung cấp thêm
64 nhiều Widget cải tiến hỗ trợ các hệ điều hành mới lúc bấy giờ Phiên bản 2.2 sau đó cập nhật service-worker cho Flutter web, tối ưu về hiệu suất cho các hệ điều hành
Phiên bản 2.5 (2021) tối ưu performance trong quá trình shader warmup, thực hiện các nhiệm vụ bất đồng bộ, tối ưu tác vụ dọn dẹp bộ nhớ rác Hỗ trợ chế độ toàn màn hình cho ứng dụng Android và cập nhật Material You Đến phiên bản 2.10, Flutter đã hỗ trợ ổn định cho các ứng dụng Window, hỗ trợ Material 3 và các tính năng cập nhật cho iOS, Android và Web
Flutter 3 được ra mắt vào 2022 đánh dấu Flutter có thể được sử dụng đa nền tảng với việc chính thức hỗ trợ macOS và Linux, sẵn sàng cho các ứng dụng production đồng thời tiếp tục các cập nhật cho Web, iOS, Android Phiên bản 3.7 hỗ trợ thêm nhiều component của Material Design, đồng thời cung cấp cho các nhà phát triển tính năng kiểm tra các cài đặt của ứng dụng iOS để xem ứng dụng có đạt yêu cầu của App store hay không Quá trình kiểm tra sẽ được thực hiện lúc sử dụng lệnh flutter build ipa Bên cạnh các tính năng chính, Flutter 3.3 còn tối ưu hiệu năng và quản lý bộ nhớ tốt hơn, đồng thời là những hỗ trợ mới về UI
Phiên bản 3.10 đánh dấu nhiều thay đổi, trong đó việc thay đổi engine của Flutter sang Impeller cho các ứng dụng xây dưng trên nền iOS, giúp giảm dung lượng bộ nhớ mà ứng dụng sử dụng từ đó giảm được thời gian tải trên CPU và GPU Phiên bản này của Flutter còn áp dụng SLSA cấp 1 nhằm đảm bảo sự bảo mật trong chuỗi cung ứng gồm một số tính năng như bảo mật quá trình build, cho phép nhiều bên cùng tham gia để chấp thuận vào quá trình phát hành của Flutter app và các lần thực thi đều tạo ra một bản ghi để không ai có thể xen vào và đưa ra những thay đổi giữa mã nguồn và sản phẩm Ngoài ra còn là nhiều cải tiến về hiệu suất và trải nghiệm người dùng Đến hiện tại, phiên bản mới nhất của Flutter là 3.16, giới thiệu engine Impleller dành cho Android, sẵn sàng nhận phản hồi từ các nhà phát triển Cung cấp các component với style mặc định được cập nhật sát với Material Design 3 cùng với giới thiệu hệ sinh thái mới gồm những gói hỗ trợ mà Flutter khuyên dùng Devtools cũng có nhiều cải tiến hỗ trợ cho lập trình viên trong qua trình quan sát, thử nghiệm sản phẩm
Hình 4.2 Tóm tắt lịch sử Flutter.
Kiến trúc hệ thống Flutter
Flutter là bộ công cụ giao diện người dùng đa nền tảng được thiết kế để cho phép tái sử dụng mã nguồn trên các hệ điều hành khác nhau như iOS và Android, đồng thời cho phép các ứng dụng giao tiếp trực tiếp với các dịch vụ của nền tảng hệ thống mà ứng dụng chạy trên đó Mục tiêu của Flutter là cho phép các nhà phát triển cung cấp các ứng dụng hiệu suất cao trên các nền tảng khác nhau, tổng hợp những khác biệt tồn tại giữa các hệ điều hành trong khi chia sẻ nhiều mã nguồn nhất có thể
Trong quá trình phát triển, các ứng dụng Flutter chạy trong VM (virtual machine - máy ảo) cung cấp khả năng làm mới các thay đổi tức thì, những thay đổi với trạng thái của ứng dụng mà không cần biên dịch lại cả ứng dụng Đối với quá trình phát hành ứng dụng, các ứng dụng Flutter được biên dịch trực tiếp sang mã máy, cho dù là kiến trúc Intel x64 hay ARM hoặc sang JavaScript nếu môi trường được nhắm đến là web Flutter được thiết kế theo hướng hệ thống gồm nhiều lớp, framework tồn tại một loạt những thư viện độc lập với nhau, mỗi thư viện phụ thuộc vào các lớp bên dưới Không một lớp nào có quyền truy cập những lớp bên dưới và các phần của Flutter được thiết kế để có thể dễ dàng thay thế trong quá trình cập nhật và nâng cấp
Hình 4.3 Kiến trúc Flutter Đối với hệ điều hành cơ bản, ứng dụng Flutter được đóng gói giống với cách những ứng dụng gốc khác được đóng gói Trình nhúng (embedder) dành riêng cho các nền tàng cung cấp một điểm kết nối với hệ điều hành bên dưới dành cho các thao tác kết nối với những dịch vụ mà hệ điều hành cung cấp như render hình ảnh, khả năng tuỳ chỉnh các cài đặt, tương tác với thao tác nhập xuất; quản lý event loop Flutter cung cấp những trình nhúng coh một số hệ điều hành phổ biến như macOS, iOS, Android, Window, Ngoài ra các nhà phát triển cũng có thể xây dựng một trình nhúng dành cho hệ điều hành mà nhà phát triển nhắm đến
Lõi của framework Flutter là Flutter engine Engine chịu trách nhiệm cho quá trình rasterizing các khung hình khi một frame mới cần được vẽ lên màn hình Engine cung cấp khả năng triển khai các API chính của Flutter, gồm các API về đồ hoạ (thông qua engine kết xuất hình ảnh Impeller đang được dùng trên iOS và đang được nghiên cứu áp dụng trên Adnroid, và Sika cho những nền tảng khác), đọc và ghi file, các thao tác trên tầng network, kiến trúc hỗ trợ cho các plugin, runtime cho ngôn ngữ Dart và công
67 cũ hỗ trợ biên dịch mã nguồn Vì thiết kế của kiến trúc, để tầng framework có thể kết nối với engine, engine cung cấp dart:ui đóng gói những dòng mã C++ bên trong các lớp Thư viện dart:ui cung cấp những lớp nguyên thuỷ nhất, trừu tượng và gần với mã nguồn nhất như nhập xuất, đồ hoạ và các hệ thống nhỏ hơn để xuất chữ viết
Thông thường, lập trình viên chỉ tương tác với Flutter framework cung cấp giao diện hiện đại và thân thiện với lập trình viên thông qua ngôn ngữ Dart Framework bao gồm nhiều platform, thư viện thể hiện thông qua kiến trúc lớp: a) Các lớp foundational, dịch vụ như animation, paiting và gestures cung cấp những các dùng trừu tượng đối với các lớp bên dưới b) Lớp rendering cung cấp các phương thức trừu tượng để xử lý giao diện Với lớp này, lập trình viên có thể xây dựng một cấu trúc cây bao gồm các object có thể được render ra giao diện Lập trình viên có thể thay đổi các object này (thông qua thay đổi trạng thái của object chẳng hạn) và cây object sẽ tự động cập nhật giao diện để ánh xạ thay đổi c) Lớp Widget là một lớp gồm những thành phần trừu tượng, cụ thể hơn là mỗi object trong lớp rendering sẽ có một lớp (class) trong lớp (layer) Widgets Ngoài ra, lớp này giúp lập trình viên có thể định nghĩa các kết hợp của các lớp (class) để có thể được tái sử dụng d) Material và Cuperino là các thư viện cung cấp một tập các quản lý toàn diện dùng các thành phần nguyên thuỷ của lớp Widget để thực hiện các ngôn ngữ thiết kế của Material hoặc iOS.
Ưu nhược điểm
4.4.1 Ưu điểm a) Flutter là một framework được xây dưng cho việc phát triển ứng dụng đa nền tảng dựa trên một mã nguồn duy nhất, từ đó cho ra thời gian phát triển ứng dụng nhanh chóng, tối ưu thời gian và chi phí b) Tính năng hot-reload (cập nhật tức thì) các thay đổi trạng thái của ứng dụng giúp lập trình viên thấy được các thay đổi tức thì từ mã nguồn lên ứng dụng Tính năng này tăng tốc quá trình phát triển và gỡ lỗi c) Cộng đòng cũng như nhóm phát triển Flutter cung cấp sẵn nhiều Widgets và thư viện hỗ trợ, giúp cho quá trình phát triển tập trung vào logic nghiệp vụ, lõi ứng dụng, các domain thay vì những thành phần phụ như UI cơ bản
68 d) Flutter với mục đích sinh ra của nó giúp cho các ứng dụng khi được biên dích, xây dựng (build) và phát hành cung cấp cho người dùng cảm giác như đang sử dụng ứng dụng được xây riêng cho nền tảng, hệ điều hành riêng Ứng dụng có thể tương tác với những API cụ thể và khác biệt đối với các nền tảng khác nhau Ngoài ra Flutter còn sử dụng những engine đồ hoạ được hỗ trợ bởi những nhà phát hành lớn, những ứng dụng phổ biến như Skia, Impeller, đảm bảo sự mượt mà của ứng dụng khi vẽ các Widget lên màn hình thiết bị e) Flutter Widget có tính đa dụng và tuỳ biến cao, hỗ trợ cho các lập trình viên áp dụng và các yêu cầu cụ thể riêng biệt f) Flutter cũng đồng thời cung cấp hệ thống quản lý trạng thái riêng, mạnh mẽ giúp cho việc phát triển, bảo trì các ứng dụng lớn, phức tạp trở nên rõ ràng, dễ dàng hơn
4.4.2 Nhược điểm a) Với việc sử dụng một ngôn ngữ mới là Dart, việc tiếp cận với Flutter có thể là một thác thức với những nhà phát triển không quen thuộc với ngôn ngữ này b) Ứng dụng Flutter có thể sẽ có kích thước lớn hơn những ứng dụng gốc do phải bao gồm Flutter framework, từ đó dẫn đến việc dung lượng của ứng dụng tăng lên, và người dùng phải tốn nhiều dung lượng và băng thông hơn để tải và cài đặt ứng dụng được xây dựng bằng Flutter c) Một số API của các ứng dụng gốc chưa được hỗ trợ bởi Flutter d) Là một framework mới được phát triển, vẫn còn một số lỗi tiềm ẩn khi xây dựng ứng dụng, đi kèm với đó là cộng động chưa phát triển lớn mạnh như những framework khác hoặc ngôn ngữ khác e) Flutter chỉ mới hỗ trợ những hệ điều hành phổ biến, một số hệ điều hành và thiết bị chưa có đông đảo người dùng như Smart TV, smartwatch chưa được hỗ trợ.
Hiện trạng, tiềm năng
Hiện này, Flutter đã trở thành một trong những framework nổi tiếng và phổ biến nhất hiện nay trong việc phát triển ứng dụng đa nền tảng Nhiều công ty lớn như Google, Alibaba, BMW đã sử dụng Flutter cho các ứng dụng mobile Nhờ vào sự phát triển rộng rãi này mà cộng đồng sử dụng Flutter đã trở nên to lớn gồm nhiều nhà phát triển trên khắp nơi trên thế giới Cộng đồng này đóng một vai trò quan trọng trong việc hỗ trợ và
69 đóng góp vào quá trình phát triển, nâng cao và tối ưu framework; đồng thời hệ sinh thái đa dạng gồm nhiều các plugins, gói hỗ trợ (package) kế thừa các tính năng có sẵn của Flutter và phục vụ nhiều nhu cầu đa dạng
Flutter tự bản thân framework cung cấp một bộ công cụ phát triển đầy đủ bao gồm Dart DevTools, Flutter Inspector và tính năng thay đổi tức thì (hot-reload) giúp tăng trải nghiệm phát triển Đồng thời nhiều tài liệu hướng dẫn bao gồm tài liệu chữ viết và video giúp những lập trình viên mới dễ học và tiếp cận với framework một cách hiệu quả Framework Flutter cũng đảm bảo hiệu suất và khả năng tương thích, mở rộng của ứng dụng thông qua kiến trúc thiết kế theo từng lớp (layer), giúp cho giao diện lập trình tổng quan hoá cho nhiều hệ điều hành trong khi framework sẽ tự động lo việc kết nối và giao tiếp với các nền tảng, hệ điều hành khác nhau, tạo ra trải nghiệm sử dụng mượt mà như những ứng dụng gốc thông thường Các engine đồ hoạ như Skia và Impeller cũng giúp cho quá trình render các Widget lên màn hình của người dùng trở nên mượt mà trên mọi nền tảng Không thể không kể đến việc sử dụng cấu trúc cây để thể hiện các Widget thành các object có thể được render nhằm giúp ứng dụng tối ưu chi phí khi chỉ cần render lại những phần của ứng dụng mà có trạng thái được thay đổi
Flutter đang ngày càng tối ưu cho việc render hoạt ảnh nhờ vào việc sử dụng engine mới là Impeller được hứa hẹn là sẽ tối ưu hơn Skia Flutter đã chính thức đưa Imepller vào sử dụng cho các ứng dụng iOS và đang dần mang lên nền tảng Android, hứa hẹn một sự cải thiện về mặt hiệu suất
Các nền tảng được hỗ trợ bởi Flutter dần được mở rộng, không chỉ tập trong vào việc xây dưng các ứng dụng gốc đa nền tảng, Flutter còn hỗ trợ xây dựng ứng dụng web và cả game, đồng thời là những nền tảng khác đang được nghiên cứu
Trong nhiều bản cập nhật mới, Flutter luôn chú ý tới việc nâng cao trải nghiệp phát triển bằng cải tiến DevTools cũng như Inspector Bên cạnh đó, nhà phát triển cũng lưu tâm đến việc hỗ trợ tích hợp những plugin cần dùng để phát triển Flutter vào các IDE và text editor phổ biến
Với định hướng phát triển như hiện tại, Flutter đang đóng một vai trò thiết thực trong quá trình phát triển của những công nghệ mới nổi như AR, VR, IoT, những ứng dụng
70 cần sự tương thích đa nền tảng cũng như là khả năng phát triển từ ứng dụng sẵn có để hỗ trợ những công nghệ mới này.
Roadmap
Từng bước học để sử dụng Flutter bao gồm: a) Đầu tiên cả, chúng ta cần học ngôn ngữ được sử dụng chính trong Flutter là Dart Cần học cơ bản những khái niệm và cách dùng của ngôn ngữ này như các kiểu dữ liệu có sẵn, cách để tạo kiểu dữ liệu mới, hàm, toán tử, luồng chạy của một mã nguồn Dart b) Bước 2, cần xem qua tài liệu giới thiệu của Flutter để cài đặt và thiết lập CLI cũng như những bộ công cụ cần thiết, ví dụ như Android Studio Đồng thời là thiết lập công cụ hỗ trợ trong việc gõ lệnh, có thể là một IDE như Visual Studio hoặc là text editor như VScode, Vim, … c) Tiếp theo là tìm hiểu một trong những thành phần cốt lõi, tồn tại xuyên suốt ứng dụng là những Widgets Cần hiểu rõ Widgets là gì, có những kiểu Widget nào ví dụ như Stateless Widgets để chỉ những Widgets không cần quản lý trạng thái hoặc không có trạng thái ví dụ như một đoạn văn bản tĩnh, một hình ảnh đơn thuần; hoặc là Stateful Widgets để khởi tạo một Widgets có những trạng thái đi kèm như input, checkbox, navigations, ; hoặc Inherited Widgets để giải quyết bài toán về việc truyền dữ liệu qua quá nhiều Widget lồng nhau d) Đồng thời ở bước trên, chúng ta cũng có thể học cách để làm việc, tức cách để truy cập tới các tài nguyên khác như Fonts, Images e) Tiếp đến là làm quen với các trình quản lý gói cho Flutter như pub Học cách sử dụng trình quản lý gói sẽ giúp cho quá trình phát triển, tích hợp những thư viện hỗ trợ trở nên dễ dàng hơn f) Flutter là framework hỗ trợ xây dựng ứng dụng cho người dùng, không phải là một máy chủ lưu trữ dữ liệu, vì vậy chúng ta cần học cách để Flutter app có thể kết nối với máy chủ dữ liệu thông qua API g) Trong quá trình xây dựng, kết nối, nhiều khi ứng dụng sẽ gặp những lỗi khó mà phát hiện chỉ bằng việc quan sát mã nguồn và giao diện Vì vậy tiếp theo chúng ta cần làm quen và học cách sử dụng Flutter Inspector để theo dõi gian diện, Flutter DevTools để theo dõi các thao tác mạng, các dòng log của ứng dụng cũng như quản lý bộ nhớ mà ứng dụng sử dụng khi được khởi chạy
71 h) Tiếp đến, sau khi làm quen với những kiến thức cơ bản thì cũng ta sẽ đọc qua những kiến thức nâng cao của Flutter như kiến trúc ứng dụng như các thư viện chính, 3 cấu trúc cây chính của Flutter gồm Widget Tree, Element Tree và RenderObject Tree, hiểu được cách mà từ một mã Widget, Flutter có thể biến nó thành giao diện người dùng Bên cạnh đó còn là những khái niệm nâng cao của ngôn ngữ Dart như Higher-Order Functions, dữ liệu toàn vẹn không bị thay đổi, lambdas, closure, các kiểu dữ liệu nâng cao như Collections (stack, queue, ) i) Cuối cùng trong quá trình phát triển là phát hành ứng dụng, cần biết được cách từ mã nguồn, xử dựng các câu lệnh để phát hành ra ứng dụng dành cho các hệ điều hành khác nhau
Hình 4.4 Mô tả roadmap của Flutter.
Best Practices
4.7.1 Refactor mã thành Widget thay vì phương thức
Thay vì để những Widget vào trong phương thức build của một Widget thì chúng ta nên tách thành nhiều Widget con Điều này giống như một nguyên tắc trong React khi tách các thành phần UI thành nhiều Widget con, điều này giúp tăng khả năng bảo trì, tái sử dụng mã nguồn Đồng thời viết tách thành các Widget nhỏ hơn còn giúp tăng hiệu suất ứng dụng như đưa các state xuống những Widget cần nó, tránh việc phải vẽ lại những Widget không liên quan
4.7.2 Kiểm soát chi phí phương thức build
Phương thức build của Widget có thể khiến cho ứng dụng bị trì trệ nếu chúng ta không kiểm soát được tài nguyên tiêu tốn bởi phương thức này Phương thức Build luôn được gọi mỗi lần Widget cần được build lại để được render thành giao diện mới, cập nhật với trạng thái của Widget Vì vậy nếu phương thức này tốn quá nhiều tài nguyên có thể khiến ứng dụng bị lỗi và sập bất ngờ
Khi ứng dụng trở nên lớn, các Widget lồng nhau thì chúng ta nên cân nhắc sử dụng các state management ví dụ như StreamProvider để chia sẻ trạng thái giữa các Widget với nhau, tránh việc phải truyền các trạng thái xuống Widget con thông qua hàm khởi tạo thông qua quá nhiều Widget trung gian khiến cho mã nguồn ứng dụng trở nên xấu và khó bảo trì, dò tìm và sửa lỗi
4.7.4 Xác định rõ ràng kiến trúc
Việc chọn mẫu kiến trúc phù hợp cho ứng dụng Flutter rất quan trọng cho sự thành công của ứng dụng Với nhiều mẫu kiến trúc có sẵn, điều quan trọng là phải đánh giá cẩn thận nhu cầu của ứng dụng và chọn kiến trúc sẽ hỗ trợ tốt nhất chức năng và khả năng mở rộng của ứng dụng Quyết định phải được dựa trên quy mô, độ phức tạp và cấu trúc nhóm phát triển của ứng dụng Các mẫu được sử dụng phổ biến nhất cho ứng dụng Flutter bao gồm các kiến trúc Lifting State Up, Provider, BLOC, MVI,… Mỗi mô hình này đều có những lợi ích và hạn chế riêng và điều quan trọng là phải hiểu những điều này khi đưa ra quyết định Bằng cách chọn kiến trúc phù hợp, nhà phát triển có thể đảm bảo rằng ứng dụng của họ được tổ chức tốt, có thể bảo trì và có thể mở rộng, đồng thời cơ sở mã dễ quản lý và hoạt động theo thời gian
Kiến trúc BLOC là một mẫu kiến trúc phổ biến trong Flutter sử dụng streams để xử lý việc quản lý trạng thái Trong Bloc, mã của ứng dụng được chia thành ba phần: view, bloc và repository View chịu trách nhiệm hiển thị giao diện người dùng, bloc quản lý trạng thái của ứng dụng bằng cách sử dụng luồng và repository chịu trách nhiệm tìm nạp và lưu trữ dữ liệu Một trong những lợi ích của Bloc là nó có thể giúp xử lý việc quản lý trạng thái phức tạp dễ dàng hơn
Hình 4.5 Kiến trúc BLOC
Provider là một mẫu kiến trúc quản lý trạng thái phổ biến khác trong Flutter Nó tương tự như Bloc ở chỗ nó tách quản lý trạng thái khỏi UI, nhưng thay vì sử dụng các streams, nó sử dụng các Widget InheritedWidget và ChangeNotifier để quản lý trạng thái Một trong những lợi ích của Provider là nó có thể giúp quản lý trạng thái dễ dàng hơn trong các ứng dụng vừa và nhỏ Nó cũng có thể giúp việc chia sẻ trạng thái giữa các phần khác nhau, các Widget của ứng dụng trở nên dễ dàng hơn
Hình 4.6 Kiến trúc Provider sử dụng ChangeNotifier
4.7.5 Tuân theo Dart style guide
Tuân thủ theo gói hỗ trợ flutter_lintst dùng để kiểm tra mã nguồn đã tuân thủ theo style guide của Dart chưa như dùng const, final ở các hằng, const ở các hằng có thể biết giá trị trong quá trình build-time, final ở các hằng chỉ biết trong thời gian run-time Hoặc là quy định về cách viết các hàm khởi tạo của một lớp
4.7.6 Lựa chọn Package kỹ càng
Lựa chọn các gói hỗ trợ kỹ càng, không nên cài đặt dư thừa các gói để tránh cho kích thước của ứng dụng trở nên lớn quá mức cần thiết khi được phổ biến cho cộng động sử dụng Ngoài ra còn để tối ưu hiệu suất của ứng dụng khi không cần cài đặt những package không cần thiết, giảm thiểu thời gian tải của ứng dụng, cũng như là hạn chế những gói không được tối ưu tốt, làm cho ứng dụng trở nên chậm chạp
4.7.7 Hạn chế sử dụng MediaQuery/LayoutBuilder
MediaQuery rất hữu dụng khi sử dụng để xây dựng một ứng dụng có tính responsive cao, tức có thể hiển thị trên nhiều màn hình có kích thước khác nhau LayoutBuilder thì lại có giá trị khi nhu cầu của chúng ta là xây dựng Widget có thể điều chỉnh layout của chính nó dựa vào các Widget cha Tuy vậy, việc sử dụng bừa bãi 2 Widget này có thể dẫn đến việc mã nguồn trở nên rối rắm quá mức, khiến cho việc bảo trì, sửa lỗi và phát triển trở nên mất thời gian hơn Đồng thời cũng có nhiều ảnh hưởng về mặt hiệu suất khi các Widget được build lại nhiều lần khi ví dụ khi người dùng xoay màn hình hoặc Widget cha thay đổi kích thước liên tục
4.7.8 Chỉ sử dụng Streams khi cần thiết
Stream là tính năng của Dart và Flutter kế thừa lại nó Trong Flutter có 2 loại stream là Single - Subscription Stream và Broadcast Streams Việc sử dụng các stream này dùng để lắng nghe các sự kiện làm thay đổi dữ liệu của stream và build giao diện dựa vào các dữ liệu này Tuy nhiên việc làm dụng Streams là điều không nên khi mà nó có thể khiến cho ứng dụng sử dụng nhiều bộ nhớ, hoặc khiến cho các Widget bị build lại nhiều lần vì sự thay đổi của các tác vụ bất đồng bộ, đặc biệt trong quá trình giao tiếp với Backend Thêm vào đó việc sử dụng Streams khiến cho đoạn mã khó đọc hơn, khó để bảo trì và kiểm soát lỗi và nếu không kiểm soát được các tác vụ bất đồng bộ có thể gây lãng phí bộ nhớ, sử dụng bộ nhớ cho những tác vụ không còn cần đến nữa
4.7.9 Sử dụng từ khóa const khi có thể
Sử dụng hàm khởi tạo được khai báo là hằng (const) vì Flutter sẽ tự động nhận biết, và giúp Flutter tối ưu quá trình xây dựng các Widget Ngoài ra trong ngôn ngữ Dart, const đánh dấu những biến có thể biết được giá trị trong quá trình build-time từ đó giúp tối ưu cho quá trình biên dịch, vì đã biết được giá trị của những biến này rồi nên bộ nhớ sử dụng trong quá trình biên dịch được giảm bớt Đồng thời sử dụng const còn giúp đánh dấu những biến không được thay đổi trong quá trình phát triển, giúp cho quá trình phát triển và bảo trì trong tương lai
4.7.10 Giảm thiểu các hoạt động tốn kém
Hạn chế những công việc tốn nhiều tài nguyên, có độ phực tạp lớn (ví dụ như các vòng lặp lồng nhau) được đặt trong phương thức build Vì khi các Widget được xây lại (re-build), nhất là đối với những Widget người dùng tương tác nhiều như trường nhập thông tin,… thì các công việc tốn tài nguyên sẽ chạy với một tần suất lớn, khiến ứng dụng bị trì trệ
Khi phải build một danh sách dài các Widget, điều hiển nhiên sẽ có một số Widget sẽ không cần hiển thị ngay vì đang nằm ngoài tầm nhìn của người dùng (bên ngoài viewport) Khi đó, việc sử dụng lazy builder có thể giảm thiểu chi phí build của ứng dụng, tăng hiệu suất và giảm bộ nhớ sử dụng của ứng dụng Một Widget sẵn có để áp dụng kỹ thuật này là ListView, sử dụng phương thức builder
Hình 4.7 Ví dụ sử dụng lazy builder
Hạn chế việc Flutter phải thực hiện intrinsic pass, thực hiện các intrinsic operations từ đó dẫn đến việc ứng dụng tốn thêm 1 lần tài nguyên để vẽ các Widget thành UI
Ví dụ về intrinsic pass có thể được xem xét trong ví dụ về việc vẽ một lưới các ô, và muốn tất cả các ô có kích thước bằng với ô lớn nhất Để làm được việc này, Flutter phải lặp qua tất cả các ô, lấy được kích thước nguyên bản (intrinsic size) rồi sau đó Flutter thực hiện lặp qua các ô lần thứ 2 để quyết định kích thước các ô
Use cases
4.8.1 Trường hợp nên sử dụng
4.8.1.1 Phát triển ứng dụng di động đa nền tảng Đối với những nhóm phát triển, doanh nghiệp cần xây dựng ứng dụng đa nền tảng, không yêu cầu những tính năng nâng cao mà chỉ những nền tảng cụ thể hỗ trợ, Flutter có thể sẽ là sự lựa chọn phù hợp giúp tối ưu thời gian phát triển, bảo trì, nâng cấp vì ứng dụng giờ đây chỉ bắt nguồn từ một bộ mã nguồn duy nhất đồng thời giúp tiếp kiệm chi phí
Với những sản phẩm được nhắm tới nền tảng web ngay từ đầu, Flutter sẽ không quá phù hợp, tuy nhiên với những ứng dụng gốc cho các nền tảng di dộng hoặc máy tính, Flutter có thể là lựa chọn tốt để chuyển đổi từ ứng dụng gốc sang ứng dụng web Ngoài ra Flutter có thể sử dụng để xây dựng các ứng dụng web tích hợp PWA
4.8.1.3 Phát triển ứng dụng yêu cầu ổn định cao
Flutter là một lựa chọn phù hợp cho các ứng dụng yêu cầu sự ổn định vì một số những lý do sau: a) Các API của Flutter được hỗ trợ xuyên suốt qua nhiều phiên bản, tức những API của các phiên bản trước vẫn được cập nhật và hỗ trợ trong những phiên bản mới cho tới khi những API này thật sự bị lỗi thời b) Các đoạn mã Flutter được biên dịch sang mã máy, giúp cho ứng dụng đa nền tảng có thể chạy hiệu quả như ứng dụng gốc giúp giảm khả năng ứng dụng bị lỗi, tắt đột ngột c) Render engine Skia và Impeller giúp cho hiệu ứng hình ảnh được render mượt mà, tăng sự ổn định của ứng dụng
Với những doanh nghiệp cần phát triển ứng dụng MVP, Flutter giúp doanh nghiệp đạt được điều này dễ dàng hơn, tiết kiệm thời gian phát triển khi một bộ mã nguồn có thể được xây dựng thành ứng dụng chạy được trên đa số các nền tảng phổ biến hiện nay
4.8.2 Trường hợp không nên sử dụng
4.8.2.1 Ứng dụng có chức năng phụ thuộc cao đến hệ điều hành
Với những ứng dụng có chức năng phụ thuốc đến những API cụ thể mà chỉ có một số hệ điều hành có, Embeder của Flutter chưa hỗ trợ đến những API này, điều này khiến cho các tính năng này của ứng dụng không thể hiện thực hoá được Hoặc phải chờ những phiên bản tiếp theo, hoặc phải tự viết các custom plugin để hỗ trợ những API này
4.8.2.2 Áp dụng thực tế tăng cường (Augmented Reality)
Dù cho Flutter đã hỗ trợ việc áp dụng AR vào ứng dụng, tuỳ nhiên khả năng hỗ trợ cũng như hệ sinh thái plugin dành cho AR vẫn còn hạn chế, chưa thật sự đầy đủ để phục vụ cho những yêu cầu của ứng dụng Bên cạnh đó còn là hạn chế vầ mặt hiệu năng khi những tác vụ AR nặng có thể sẽ khiến cho ứng dụng bị lỗi
4.8.2.3 Khả năng Web hạn chế
Flutter cho web bị hạn chế về mặt SEO khi chưa hỗ trợ cho SSR, bên cạnh đó web application được phát triển bằng Flutter sẽ khiến cho ứng dụng có kích thước lớn hơn thông thường vì phải bao gồm cả Flutter engine Ngoài ra, có những API của trình duyệt chưa được hỗ trợ bởi Flutter, điều này là một hạn chế đối với quá trình phát triển phần mềm
Hình 4.9 Hạn chế của Flutter cho Web.
Study cases
Tencent Cloud Chat là một Chat SDK giúp cho khách hàng có thể nhanh chóng xây dựng module trò chuyện in-app hiện đang được đánh giá số 1 trong thị trường úng dụng
80 dịch vụ chat Với việc sử dụng Flutter, Tencent Cloud giúp tăng doanh thu lên tới 34%, giảm thời gian phát triển và triển khai dịch vụ nhanh hơn trước Flutter còn mang lại lợi ích cho khách hàng của Tencent Cloud như giúp giảm tài nguyên cần thiết tới 38%, giảm các lỗi xuất hiện tới 30%
Hình 4.10 Tencent Cloud Chat sử dụng Flutter
Hình 4.11 Chỉ số thành công của nhóm phát triển khi sử dụng Flutter
4.9.2 Ecommerce platforms a) Alibaba, một trong những chợ thương mại trực tuyến lớn nhất thế giới hiện nay đã dùng Flutter xây dựng ứng dụng Xianyu cho hàng chục triệu người dùng trên khắp thế giới với mục đích bán lại hàng đã qua sử dụng giả rẻ Thách thức đưa ra với nhóm phát triển của Alibaba là phải xây dựng ứng dụng mượt mà, mang lại trải nghiệm tốt nhất cho người dùng nhưng phải tối ưu về thời gian và chi phí Từ đó, nhóm đã lựa chọn Flutter để sử dụng làm nền tảng phát triển cho cả ứng dụng iOS và Android nhằm mục đích tiếp cận với nhiều người dùng nhất có thể Bằng việc sử dụng Flutter, nhóm đã tiết kiệm một lượng lớn thời gian để phát triển cũng như khi thêm tính năng mới cho ứng dụng
Hình 4.12 Ứng dụng Xianyu sử dụng Flutter b) Nhóm phát triển eBay Motors được yêu cầu xây dựng ứng dụng gốc cho Android và iOS, với bộ tính năng đầy đủ cũng như giao diện giống như ứng dụng chính của eBay trong thời gian 1 năm Nhóm đã chọn Flutter khi nghe qua về framework này vì cảm thấy đây là một công nghệ đầy hứa hẹn và có thể giúp nhóm tối ưu thời gian phát triển và thiết kế Ứng dụng được hoàn thành rất nhanh chóng, trong vòng 3 tháng phiên bản beta đã được ra mắt và vài tháng sau ứng dụng đã được ra mặt với người dùng với nhiều phản hồi tích cực về giao diện đẹp, trải nghiệm mượt mà Bên cạnh đó, các thành viên trong nhóm phát triển cũng phản hồi tích cực với Flutter khi đã giúp cho nhóm tăng tốc độ phát triển gần như gấp 2 lần chỉ với một bộ mã nguồn duy nhất Flutter giúp cho nhóm phát triển chia sẻ gần như tất cả mọi thứ cho cả nền tảng iOS và Android: giao diện, logic nghiệp vụ, domain models,
Hình 4.13 Chỉ số thành công của nhóm phát triển eBay
Hình 4.14 Ứng dụng eBay Motors
Nubank là ngân hàng số độc lập lớn nhất bên ngoài châu Á, với số lượng người dùng lên tới 48 triệu người dùng Trong quá trình phát triển nhanh chóng, họ cần một giải pháp để xây dựng một ứng dụng cho người dùng một cách nhanh chóng nhưng không được để mất chất lượng ứng dụng Nubank gặp khó khăn khi phát triển các ứng dụng gốc khi mà ứng dụng iOS và Andoird thường không tung ra tính năng song song với nhau, đồng thời viết phát triển một tính năng cho 2 nền tảng riêng biệt làm lãng phí thời gian Qua quá trình tìm hiểu, thẩm định, đánh giá, Nubank đã chọn Flutter để phát triển ứng dụng cho cả nền tảng iOS và Android Flutter đã giúp doanh nghiệp này tiếp tục mở rộng các tính năng của họ nhưng không phải đánh đổi với chất lượng của ứng dụng, đồng thời Flutter còn giúp rút ngắn thời gian onboard của nhân sự Thực tế cho thấy, Flutter đã tăng hiệu suất của Nubank lên rất nhiều, tỉ lệ được gộp của mã nguồn tặng 30% và trung bình chỉ mất 9.9 phút để yêu cầu gộp được thực thi Giờ đây, nhờ việc tập trung lại một bộ mã nguồn duy nhất, Nubank có thể tạo cho riêng họ một design-system riêng, mang đến cho người dùng trải nghiệm độc nhất đồng thời tối ưu quá trình thiết kế và phát triển cho ứng dụng
Hình 4.15 Chỉ số thành công của nhóm phát triển Nubank
Hình 4.16 Ứng dụng Nubank liên kết với thẻ vật lý
SO SÁNH FLUTTER VỚI REACT NATIVE
Ngôn ngữ lập trình
Flutter sử dụng Dart là ngôn ngữ lập trình chính Dart là ngôn ngữ hướng đối tượng, xoay quan các class và được phát triển bởi Google, được thiết kế để xây dựng website, server và các ứng dụng di động
Dart được tối ưu để lập trình đa nền tảng với khả năng biên dịch just-in-time cũng như ahead-of-time và có cú pháp gần giống với TypeScript
React Native sử dụng JavaScript làm ngôn ngữ chính để xây dựng ứng dụng di động Được tích hợp React, là thư viện phổ biến để xây dựng giao diện người dùng web Có thể tích hợp TypeScript theo ý muốn
Sự khác biệt chính về ngôn ngữ nằm ở việc React Native sử dụng JavaScript (hoặc TypeScript), trong khi Flutter sử dụng Dart Sự lựa chọn giữa hai công cụ này có thể phụ thuộc vào sự quen thuộc của nhà phát triển với ngôn ngữ, kỹ năng hiện có của đội phát triển, và yêu cầu cụ thể của dự án Cả hai framework đều nhằm cung cấp một cách để xây dựng ứng dụng di động đa nền tảng với một mã nguồn duy nhất, và mỗi cái đều có nhược điểm và ưu điểm riêng
Kiến trúc kỹ thuật
Hình 5.1 Skia – Flutter high performance rendering engine
Thay vì sử dụng các thành phần native như React Native, Flutter xây dựng đồ họa ứng dụng bằng Engine của riêng mình
Phát triển sử dụng C++ và Skia, Flutter Rendering Engine xây dựng thành phần của riêng mình rồi biên dịch thành ngôn ngữ native của nền tảng Do đó, nhà phát triển
85 có thể xây dựng thành phần phù hợp với mọi nền tảng, cũng như tùy chỉnh theo ý mình
Kiến trúc của React Native bao gồm 2 luồng (Thread) chạy bằng JavaScript:
Hình 5.2 Mô tả kiến trúc 2 luồng của React Native a) Main Thread : Sử dụng để chạy ứng dụng trên nền tảng native b) JavaScript Thread : Sử dụng để chạy các logic doanh nghiệp của ứng dụng c) Bridge : 2 threads này chạy song song và độc lập với nhau, nhưng đôi khi chúng cần phải tương tác Bridge là cầu nối để chúng trao đổi các thông tin dưới dạng chuỗi Thiết kế 2 Threads dẫn đến khả năng chậm trễ do thời gian giao tiếp giữa JavaScript và ngôn ngữ native
Hình 5.3 React Native giao tiếp với nền tảng native thông qua cơ chế cầu nối Bridge
Khác với React, khi ứng dụng web bị đóng gói thành ứng dụng di động, React Native có khả năng giao tiếp với nền tảng native và hiển thị các thành phần native của nền tảng đó Do đó, ứng dụng React Native luôn nhìn giống với các ứng dụng native của nền tảng đó
Mặc dù trên lý thuyết, React Native có hiệu suất thấp hơn so với Flutter trên hầu hết các phép so sánh, cả hai công cụ đều đã được sử dụng thành công để phát triển nhiều
86 ứng dụng di động phổ biến với độ tối ưu tốt cho nhiều thiết bị Nhà phát triển nên lựa chọn giữa hai công cụ dựa trên yêu cầu của dự án, kĩ năng của tổ đội cũng như yếu tố căn bằng giữa hiệu suất và cường độ làm việc.
UI component và development API
Flutter sử dụng Widget là thành phần cơ bản nhất của ứng dụng, và các Widget được ghép lại để xây dựng các giao diện phức tạp
Hình 5.4 Mô tả Widget thông qua Widget tree của Flutter inspector
Widget được phân loại thành hai loại: StatelessWidgets (không thay đổi) và StatefulWidgets (thay đổi) Flutter cung cấp một bộ Widget tích hợp đa dạng cho các yếu tố giao diện khác nhau, bao gồm nút, văn bản, hình ảnh, container, hàng, cột, và nhiều hơn nữa
Flutter có các Widget tuân thủ theo hướng dẫn thiết kế Material Design cho ứng dụng Android, mang lại một trải nghiệm có cảm giác nhất quán
Ngoài ra, Flutter cung cấp các Widget Cupertino mô phỏng nguyên tắc thiết kế của iOS để có trải nghiệm tự nhiên trên thiết bị iOS
Flutter cho phép nhà phát triển tạo ra và đóng gói các Widget tuỳ chỉnh, làm cho nó có tính tuỳ chỉnh cao
React Native sử dụng một kiến trúc dựa trên thành phần lấy cảm hứng từ React trên web Thành phần được viết bằng JavaScript hoặc TypeScript và được chia thành thành phần chức năng (không thay đổi trạng thái) và thành phần lớp (thay đổi trạng thái)
Hình 5.5 React Native lấy cảm hứng component từ React, chỉ khác môi trường chạy ứng dụng
React Native bao gồm một tập hợp các thành phần cốt lõi tương ứng với các yếu tố giao diện người dùng native trên cả iOS và Android Ví dụ như View, Text, Image, ScrollView, và nhiều hơn nữa
Hình 5.6 Ví dụ ứng dụng React Native
React Native cho phép nhà phát triển sử dụng các module native viết bằng Java, Swift, hoặc Objective-C để thực hiện các chức năng không được bao gồm trong các thành phần cốt lõi Do đó, Nhà phát triển có thể tạo ra các module native tùy chỉnh để truy cập các tính năng thiết bị cụ thể hoặc tích hợp với các API native
Bảng 5.1 So sánh hiệu suất của Flutter và React Native
Tiêu chí đánh giá hiệu năng
Flutter có hiệu suất cao vì nó biên dịch thành mã ARM native, loại bỏ sự phụ thuộc vào bridge của JavaScript
React Native phải dựa vào bridge JavaScript để giao tiếp giữa luồng JavaScript và các module native, điều này có thể tạo ra một số chi phí hiệu suất
Thời gian khởi động
Biên dịch trước (AOT) giúp ứng dụng Flutter bắt đầu nhanh chóng và giảm thời Ứng dụng React Native có thể trải qua thời gian khởi động lâu hơn
89 gian cần thiết cho việc vẽ đầu tiên của giao diện người dùng do bridge JavaScript và tính chất dịch mã của mã nguồn JavaScript Độ phản hồi
Flutter cung cấp một hiệu suất ổn định 60 khung hình mỗi giây (FPS) cho hoạt ảnh và tương tác giao diện mượt mà
Mặc dù React Native có thể đạt được hiệu suất tốt, đặc biệt là với việc sử dụng các module native và các tối ưu hóa, cầu nối JavaScript có thể tạo ra những trục trặc hiệu suất đôi khi trong các hoạt ảnh phức tạp Độ tích hợp
Mô-đun native Ứng dụng Flutter có thể tích hợp với các tính năng native, nhưng nhu cầu sử dụng module native giảm do sự tiếp cận biên dịch thành mã native của Flutter
React Native dựa vào các module native được viết bằng ngôn ngữ native để thực hiện một số tính năng cụ thể của thiết bị Việc tích hợp này đôi khi có thể tạo ra chi phí hiệu suất.
Năng suất của nhà phát triển
Flutter hỗ trợ một lượng lớn tính năng giúp nâng cao năng suất của nhà phát triển: a) Hot Reload:
Cho nhà phát triển khả năng nhận thấy tác dụng tức thì của các thay đổi trong code mà không cần phải khởi động lại ứng dụng Khả năng này nâng cao nhanh chóng tiến trình phát triển ứng dụng b) API nhất quán:
Flutter có API nhất quán giữa phát triển trên ứng dụng Android lẫn IOS Do đó, nhà phát triển chỉ cần 1 mã nguồn cho cả hai nền tảng c) Dart:
Là ngôn ngữ kiểu dữ liệu chặt chẽ (strongly-typed-language), Dart dò và ném lỗi trong thời gian biên dịch, giúp tăng chất lượng mã nguồn và giảm lỗi trong quá trình runtime
Flutter có một lượng lớn Widget được xây dựng sẵn cho nhiều yếu tố UI khác nhau, giảm lượng công việc phải thực hiện Widget giúp dễ dàng xây dựng các hệ thống phức tạp
Giống với Flutter, React Native cũng tích hợp nhiều chức năng hỗ trợ nâng cao năng suất của nhà phát triển: a) Hot Reload:
React Native cũng hỗ trợ Hot Reload như Flutter, nhưng có thể xảy ra biến động khi xử lý một hệ thống phức tạp b) Độ phổ biến của JavaScript/TypeScript:
React Native sử dụng JavaScript và TypeScript, rất phổ biến với hầu hết người lập trình web Các nhà phát triển đã có sẵn kiến thức phát triển web, đặc biệt là React, có thể chuyển giao dễ dàng sang React Native c) Môi trường sinh thái phổ biến và đa dạng:
React Native có môi trường sinh thái rộng lớn với nhiều thư viện, mô-đun và hỗ trợ cộng đồng Các nhà phát triển có thể tái sử dụng các kỹ năng và thư viện có sẵn, tăng năng suất phát triển d) Tích hợp mô-đun native:
React Native cho phép khả năng tích hợp với các mô-đun native, viết bằng Java, Swift hoặc Objective-C, để truy cập các chức năng native React Native rất thích hợp cho các dự án đòi hỏi tích hợp chặt chẽ với các chức năng native
Hiệu suất của nhà phát triển trên Flutter và React Native phụ thuộc vào các yếu tố như kinh nghiệm của nhà phát triển, sự quen thuộc với ngôn ngữ và framework, và yêu cầu của dự án Cả hai công cụ đều cung cấp các tính năng như Hot Reload để tăng tốc độ phát triển, và sự lựa chọn giữa chúng thường phụ thuộc vào kĩ năng cá nhân và đặc điểm cụ thể của từng dự án
Flutter cung cấp tài liệu chính thức toàn diện và được duy trì tốt Tài liệu bao gồm hướng dẫn, bài giảng và tài nguyên API, là nguồn thông tin quý giá cho các nhà phát triển
Flutter tổ chức Flutter Interact hàng năm, bao gồm các buổi công bố, các phiên hội thảo và thông báo Nó là một nền tảng cho các nhà phát triển để tìm hiểu về những cập nhật mới nhất và các thực hành tốt nhất
Kho GitHub Cộng Đồng Flutter là một trung tâm cho các dự án, plugin và tài nguyên do cộng đồng tạo ra Nhà phát triển có thể đóng góp và khám phá các phần mở rộng hữu ích
Flutter có một hệ sinh thái phong phú với nhiều gói và plugin do cộng đồng đóng góp, có sẵn thông qua pub.dev Nhà phát triển có thể tìm kiếm và chia sẻ gói để nâng cao dự án của họ
Ngoài tài liệu chính thức, có nhiều hướng dẫn, bài viết blog và nội dung video được tạo bởi cả nhóm Flutter và các thành viên cộng đồng Điều này giúp nhà phát triển học hỏi và cập nhật về phát triển Flutter
Những sáng kiến do cộng đồng đề xuất, như Flutter Study Jams và các buổi họp cộng đồng Flutter địa phương, tạo cơ hội cho nhà phát triển hợp tác, học hỏi và giao lưu Nhóm Flutter duy trì các kênh giao tiếp mở với cộng đồng qua thông báo, bài đăng trên blog và sự tham gia trong các diễn đàn và sự kiện
Hỗ trợ Testing
Nhà phát triển có thể thực hành phát triển dựa trên kiểm thử (Testing Driven Design) trong Flutter bằng cách viết kiểm thử trước và sau đó triển khai chức năng tương ứng a) Widget Testing: là framework kiểm thử tích hợp cho việc kiểm thử Widget, cho phép nhà phát triển kiểm thử các thành phần giao diện người dùng (UI) một cách độc lập Kiểm thử Widget trong Flutter nhanh chóng và hiệu quả, giúp nhà phát triển xác minh hành vi UI một cách dễ dàng b) Unit Testing: Flutter hỗ trợ kiểm thử đơn vị để kiểm thử các hàm hoặc phương thức cá nhân độc lập Dart, ngôn ngữ lập trình được sử dụng với Flutter, có một thư viện kiểm thử đơn vị đáng tin cậy và được hỗ trợ tốt c) Integration Testing: Flutter cung cấp các công cụ cho kiểm thử tích hợp, cho phép nhà phát triển kiểm thử tương tác giữa nhiều thành phần trong ứng dụng Kiểm thử tích hợp trong Flutter có thể mô phỏng tương tác người dùng thực tế và hữu ích cho việc kiểm thử kịch bản end-to-end
Flutter hỗ trợ Golden Testing, được sử dụng để xác minh một cách trực quan rằng đầu ra của một Widget không thay đổi qua thời gian
5.6.2 React Native Testing a) Jest Testing: React Native sử dụng Jest như là framework kiểm thử mặc định Jest là một framework kiểm thử JavaScript phổ biến hỗ trợ nhiều loại kiểm thử b) Snapshot Testing: Jest trong React Native hỗ trợ kiểm thử snapshot, nơi đầu ra của một thành phần được so sánh với một snapshot được lưu lại để xác định những sự thay đổi ngoài mong muốn c) Unit Testing: React Native hỗ trợ kiểm thử đơn vị bằng Jest để kiểm thử các hàm hoặc module độc lập Các thư viện và tiện ích JavaScript để kiểm thử có thể được sử dụng cho kiểm thử đơn vị trong React Native.
Hỗ trợ tự động hóa Build và Release
d) End-to-End Testing: Đối với kiểm thử end-to-end trong React Native, các công cụ như Detox có thể được sử dụng để mô phỏng tương tác người dùng và kiểm thử hành vi của ứng dụng trong một môi trường thực tế
Kiểm thử Widget trong Flutter tập trung vào việc kiểm thử các thành phần giao diện người dùng một cách độc lập, trong khi kiểm thử snapshot của React Native ghi lại đầu ra được hiển thị của một thành phần để so sánh
React Native hưởng lợi từ cộng đồng JavaScript và React lớn, đóng góp vào một hệ sinh thái phong phú về công cụ và thư viện kiểm thử còn Dart, ngôn ngữ của Flutter, có một cộng đồng ngày càng phát triển, và hệ sinh thái kiểm thử của Flutter được hỗ trợ chặt chẽ bởi nhóm Flutter
Kiểm thử Widget của Flutter nổi tiếng về tốc độ và hiệu quả của chúng, trong khi kiểm thử của React Native, đặc biệt là kiểm thử end-to-end, có thể mất thời gian thực hiện lâu hơn
Cả Flutter và React Native đều cung cấp công cụ cho kiểm thử tích hợp, cho phép nhà phát triển xác nhận tương tác giữa các phần khác nhau trong ứng dụng của họ
5.7 Hỗ trợ tự động hóa Build và Release
5.7.1 Flutter Build and Release Ứng dụng Flutter được biên dịch trực tiếp thành mã máy native cho nền tảng native (iOS hoặc Android) Quy trình xây dựng bao gồm việc chạy lệnh ’flutter build’, tạo ra các sản phẩm đặc trưng cho từng nền tảng
Giao diện dòng lệnh Flutter (CLI) cung cấp các lệnh để xây dựng và đóng gói ứng dụng Nhà phát triển có thể sử dụng các lệnh như flutter build apk hoặc flutter build ios để tạo ra các APK cho Android hoặc dự án Xcode cho iOS
Flutter hỗ trợ các chế độ xây dựng khác nhau, như ‘debug’ và ‘release’ Chế độ
‘release’ bao gồm các tối ưu hóa về hiệu suất và kích thước Đối với iOS, Flutter sử dụng quy trình chữ ký mã của Xcode Nhà phát triển cấu hình chữ ký mã trong dự án Xcode Đối với Android, Flutter dựa vào quy trình chính thức chữ ký mã Android
Lệnh flutter pub được sử dụng để quản lý các phụ thuộc và có thể được tích hợp vào quy trình xây dựng để đảm bảo các gói mới nhất được lấy
Flutter có thể tích hợp vào nhiều hệ thống CI/CD khác nhau, chẳng hạn như Jenkins, Travis CI, hoặc GitHub Actions, để tự động hóa quá trình xây dựng khi có thay đổi mã nguồn
5.7.2 React Native Build and Release Ứng dụng React Native được xây dựng bằng cách sử dụng các công cụ xây dựng native cho từng nền tảng (Xcode cho iOS và Gradle cho Android) Quy trình xây dựng bao gồm việc chạy các lệnh xây dựng native (react-native run-android hoặc react-native run-ios)
Giao diện dòng lệnh React Native (CLI) cung cấp các lệnh để xây dựng và chạy ứng dụng trên cả hai nền tảng iOS và Android Nhà phát triển sử dụng các lệnh như react- native run-android hoặc react-native run-ios để bắt đầu quy trình xây dựng
React Native hỗ trợ việc xây dựng các phiên bản cho cả iOS và Android Đối với Android, nhà phát triển thường sử dụng Gradle, và đối với iOS, quy trình lưu trữ của Xcode được sử dụng để tạo ra các phiên bản
Tương tự như Flutter, React Native phụ thuộc vào quy trình chữ ký mã tiêu chuẩn cho cả iOS và Android Ứng dụng React Native sử dụng một bản tổng hợp JavaScript để thực thi tại runtime Bản tổng hợp được tạo và được tối ưu hóa trong quy trình xây dựng Đối với phiên bản release, nhà phát triển thường sử dụng các lệnh như react-native bundle để tạo ra các bản tổng hợp JavaScript được tối ưu hóa
React Native cũng có thể tích hợp vào nhiều hệ thống CI/CD khác nhau, cho phép tự động hóa quá trình xây dựng và kiểm thử khi có thay đổi mã nguồn
PHÂN TÍCH THIẾT KẾ ỨNG DỤNG
Hiện trạng vấn đề
Với sự phát triển của công nghệ, nhu cầu và khả năng kết nối từ xa của con người ngày càng tăng Giờ đây người ta mong muốn dù ở cách nhau nửa bán cầu vẫn có thể chia sẻ những khoảng khắc cuộc sống dến với bạn bè và rộng hơn là cả thế giới
Tuy nhiên có nhiều nền tảng mạng xã hội lại chỉ có ứng dụng trên một nền tảng nhất định như web, android, iOS,… Điều này dẫn đến vấn đề rằng người dùng gặp khó khăn trong quá trình sử dụng nếu có chuyển đổi thiết bị có hệ điều hành khác nhau Điều này xảy ra vì trên các hệ điều hành khác nhau thì kernel cũng khác nhau, dẫn đến việc khởi chạy ứng dụng cũng yêu cầu những dòng lệnh riêng biệt Việc xây dựng và bảo trì nhiều bộ mã nguồn khác nhau là một vấn đề khá lớn với nhiều nhóm phát triển phần mềm khi tiêu tốn nhân lực, tiền bạc và thời gian rất lớn
Tính đến hiện tại, đã có nhiều giải pháp đa nền tảng được giới thiệu để giải quyết vấn đề trên, điển hình như framework Flutter được phát triển bời Google Nhờ sự trợ giúp của Flutter mà việc phát triển ứng dụng đa nền tảng dựa trên một bộ mã nguồn duy nhất giờ đây đã trở nên dễ dàng hơn trong khi vẫn đảm bảo được hiệu năng của ứng dụng cũng như khả năng tích hợp với các dịch vụ bên thứ 3 cho mục đích lưu trữ, AI,… Việc sử dụng Flutter đòi hỏi lập trình viên phải học ngôn ngữ mới là Dart và học các phương thức, khái niệm mà Flutter cung cấp Tuy vậy, đây không phải là một việc gì đó quá khó khăn khi mà Dart được tạo cảm hứng từ nhiều ngôn ngữ phổ biến hiện nay như C#, Javascript,… đồng thời là kiến trúc được ứng dụng rộng rãi trong thực tế như kiến trúc component-based của React Điều này giúp cho lập trình viên nhanh chóng tiếp cận công nghệ mới và có thể bắt tay vào xây dựng dự án trong thời gian sớm nhất có thể Ứng dụng được xây dựng sau đây sẽ sử dụng framework Flutter để xây dựng một ứng dụng mạng xã hội đơn giản
6.2 Phân tích yêu cầu ứng dụng
Yêu cầu của ứng dụng là một nền tảng mạng xã hội với những chức năng chính bao gồm đăng nhập, đăng kí, đăng bài viết, xoá bài viết, yêu thích bài viết, bình luận vào bài viết,
97 xoá bình luận, chỉnh sửa thông tin cá nhân Đồng thời với giao diện thân thiện dễ sử dụng
6.3 Phân tích thiết kế hệ thống
Hình 6.1 Sơ đồ Use Case tổng quát
Hình 6.2 Sơ đồ Use Case cho module bài đăng
Hình 6.3 Sơ đồ Use Case cho module bình luận
1 User Người dùng mạng xã hội
Bảng 6.2 Danh sách Use Case
STT Tên Use Case Ý nghĩa
1 Đăng ký User đăng ký tài khoản bằng email và password
2 Đăng nhập User đăng nhập với tài khoản bằng email và password
3 Đăng xuất User đăng xuất tài khoản khỏi hệ thống
User đăng nhập bằng tài khoản Google có sẵn
5 Xem danh sách bài đăng
User xem các bài đăng có trong cơ sở dữ liệu của mạng xã hội
6 Thêm bài đăng User tạo bài đăng mới
7 Yêu thích bài đăng User yêu thích một bài đăng, thể hiện cảm xúc
8 Xoá bài đăng User xoá bài đăng của chính mình,
9 Xem danh sách bình luận
User xem danh sách bình luận của một bài đăng
10 Thêm bình luận User thêm bình luận vào một bài đăng
11 Xoá bình luận User xoá bình luận của chính mình hoặc xoá bình luận ở bài dăng của mình
11 Chỉnh sửa thông tin tài khoản
User vào trang thông tin cá nhân để chỉnh sửa thông tin theo ý muốn
6.3.2.1 Đặc tả Use Case đăng ký
Bảng 6.3 Đặc tả Use Case đăng ký
Tên Use Case Đăng ký
Mô tả Use Case User đăng ký tài khoản bằng email và password
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Người dùng nhấn vào nút “sign up” ở trang đăng nhập
Tiền điều kiện Không có
Hậu điều kiện a) Người dùng đăng nhập vào hệ thống với tài khoản tạo thành công b) Hệ thống ghi nhận chính xác thông tin người dùng vừa tạo
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Người dùng nhấn vào nút ‘sign up’ c) Người dùng điền thông tin tài khoản như email và password phù hợp với luật lệ của hệ thống d) Người dùng nhận được phản hồi tạo tài khoản thành công e) Tự động đăng nhập vào ứng dụng bằng tài khoản mới tạo
Luồng sự kiện phụ a) Người dùng truy cập vào ứng dụng b) Người dùng nhấn vào nút ‘sign up’ c) Người dùng điền thông tin tài khoản như email và password
101 d) Hệ thống thông báo email hoặc password của người dùng không phù hợp với luật lệ của hệ thống e) Người dùng điền lại thông tin tài khoản như email và password phù hợp với luật lệ của hệ thống f) Người dùng nhận được phản hồi tạo tài khoản thành công g) Tự động đăng nhập vào ứng dụng bằng tài khoản mới tạo
Luồng sự kiện ngoại lệ Không có
Yêu cầu phi chức năng
6.3.2.2 Đặc tả Use Case đăng nhập
Bảng 6.4 Đặc tả Use Case đăng nhập
Tên Use Case Đăng nhập
User đăng nhập vào hệ thống bằng email và password của tài khoản đã đăng ký từ trước
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Ngưởi dùng truy cập vào ứng dụng
Tiền điều kiện Người dùng đã đăng ký tài khoản thành công
Hậu điều kiện người dùng đăng nhập vào hệ thống thành công với tài khoản tương ứng
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Người dùng đăng nhập bằng email và password của tài khoản đã khởi tạo
102 c) Người dùng nhận thông báo đăng nhập thành công d) Người dùng được chuyển đến trang chính của ứng dụng
Luồng sự kiện phụ a) Người dùng truy cập vào ứng dụng b) Người dùng đăng nhập bằng email và password của tài khoản đã khởi tạo c) Hệ thống thông báo người dùng đã nhập sai thông tin đăng nhập d) Người dùng đăng nhập bằng email và password của tài khoản đã khởi tạo e) Người dùng nhận thông báo đăng nhập thành công f) Người dùng được chuyển đến trang chính của ứng dụng
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.3 Đặc tả Use Case đăng xuất
Bảng 6.5 Đặc tả Use Case đăng xuất
Tên Use Case Đăng xuất
Mô tả Use Case User đăng xuất khỏi hệ thống sau khi đã đăng nhập
103 Độ ưu tiên Phải có
Kích hoạt (trigger) - Ngưởi dùng nhấn vào nút ‘Sign out’ ở trang chính
Tiền điều kiện Người dùng đã đăng nhập vào ứng dụng thành công
Hậu điều kiện Tài khoản của người dùng được ghi nhận đã đăng xuất khỏi hệ thống
Luồng sự kiện cơ bản a) Người dùng nhấn vào nút ‘sign out’ ở trang chính b) Người dùng nhận thông báo đã đăng xuất khỏi ứng dụng c) Người dùng được đưa đến trang đăng nhập
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.4 Đặc tả Use Case đăng nhập với Google
Bảng 6.6 Đặc tả Use Case đăng nhập với Google
Tên Use Case Đăng nhập với Google
Mô tả Use Case User đăng nhập vào hệ thống bằng tài khoản Google
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Ngưởi dùng nhấn vào nút ‘Sign in with
Tiền điều kiện Người dùng đã tạo tài khoản thành công với Google
Hậu điều kiện Tài khoản Google của người dùng được liên kết với hệ thống
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Người nhấn vào nút ‘Sign in with Google’ c) Người dùng được chuyển đến trang d) đăng nhập với Google e) Google trả về tài khoản đã đăng nhập thành công f) Hệ thống ghi nhận thông tin tài khoản Google của người dùng và đăng nhập người dùng g) Người dùng được chuyển đến trang chính của ứng dụng
Luồng sự kiện phụ a) Người dùng truy cập vào ứng dụng b) Người nhấn vào nút ‘Sign in with Google’ c) Người dùng được chuyển đến trang đăng nhập với Google d) Google trả về tài khoản đã đăng nhập thất bại e) Người dùng được chuyển về trang đăng nhập của ứng dụng
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng
105 b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.5 Đặc tả Use Case xem danh sách bài đăng
Bảng 6.7 Đặc tả Use Case xem danh sách bài đăng
Tên Use Case Xem danh sách bài đăng
Mô tả Use Case Là người dùng, tôi muốn xem các bài đăng có trên mạng xã hội
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) a) Người dùng mở ứng dụng b) Nhấn vào nút đầu tiên ở thanh điều hướng ở cạnh dưới màn hình
Tiền điều kiện Người dùng đã đăng nhập thành công và có thông tin cá nhân trên mạng xã hội
Hậu điều kiện Người dùng nhìn thấy danh sách các bài đăng có trên mạng xã hội
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Tầng Frontend đưa người dùng đến trang chủ c) Tầng Frontend tải dữ liệu bài đăng từ cơ sở dữ liệu Firebase và hiển thị lên màn hình d) Với từng bài đăng, tầng Frontend tải dữ liệu về người dùng là chủ sở hữu của bài đăng và hiện thị lên phía trên của nội dung bài đăng Đồng thời tải dữ liệu về
106 số lượng bình luận và hiện thị ở phía dưới nội dung bài đăng
Luồng sự kiện phụ a) Người dùng nhấn vào nút đầu tiên ở thanh điều hướng ở cạnh dưới màn hình b) Thực hiện luồng sự kiện cơ bản từ bước b)
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.6 Đặc tả Use Case thêm bài đăng
Bảng 6.8 Đặc tả Use Case thêm bài đăng
Tên Use Case Thêm bài đăng
Mô tả Use Case Là người dùng, tôi muốn đăng tải bài đăng mới lên mạng xã hội
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Người dùng nhấn vào nút thứ 2 ở thanh điều hướng ở cạnh dưới màn hình
Tiền điều kiện Người dùng đã đăng nhập thành công và có thông tin cá nhân trên mạng xã hội
Hậu điều kiện Người dùng nhìn thấy bài đăng của mình hiển thị trên mạng xã hội
Phân tích thiết kế hệ thống
Hình 6.1 Sơ đồ Use Case tổng quát
Hình 6.2 Sơ đồ Use Case cho module bài đăng
Hình 6.3 Sơ đồ Use Case cho module bình luận
1 User Người dùng mạng xã hội
Bảng 6.2 Danh sách Use Case
STT Tên Use Case Ý nghĩa
1 Đăng ký User đăng ký tài khoản bằng email và password
2 Đăng nhập User đăng nhập với tài khoản bằng email và password
3 Đăng xuất User đăng xuất tài khoản khỏi hệ thống
User đăng nhập bằng tài khoản Google có sẵn
5 Xem danh sách bài đăng
User xem các bài đăng có trong cơ sở dữ liệu của mạng xã hội
6 Thêm bài đăng User tạo bài đăng mới
7 Yêu thích bài đăng User yêu thích một bài đăng, thể hiện cảm xúc
8 Xoá bài đăng User xoá bài đăng của chính mình,
9 Xem danh sách bình luận
User xem danh sách bình luận của một bài đăng
10 Thêm bình luận User thêm bình luận vào một bài đăng
11 Xoá bình luận User xoá bình luận của chính mình hoặc xoá bình luận ở bài dăng của mình
11 Chỉnh sửa thông tin tài khoản
User vào trang thông tin cá nhân để chỉnh sửa thông tin theo ý muốn
6.3.2.1 Đặc tả Use Case đăng ký
Bảng 6.3 Đặc tả Use Case đăng ký
Tên Use Case Đăng ký
Mô tả Use Case User đăng ký tài khoản bằng email và password
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Người dùng nhấn vào nút “sign up” ở trang đăng nhập
Tiền điều kiện Không có
Hậu điều kiện a) Người dùng đăng nhập vào hệ thống với tài khoản tạo thành công b) Hệ thống ghi nhận chính xác thông tin người dùng vừa tạo
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Người dùng nhấn vào nút ‘sign up’ c) Người dùng điền thông tin tài khoản như email và password phù hợp với luật lệ của hệ thống d) Người dùng nhận được phản hồi tạo tài khoản thành công e) Tự động đăng nhập vào ứng dụng bằng tài khoản mới tạo
Luồng sự kiện phụ a) Người dùng truy cập vào ứng dụng b) Người dùng nhấn vào nút ‘sign up’ c) Người dùng điền thông tin tài khoản như email và password
101 d) Hệ thống thông báo email hoặc password của người dùng không phù hợp với luật lệ của hệ thống e) Người dùng điền lại thông tin tài khoản như email và password phù hợp với luật lệ của hệ thống f) Người dùng nhận được phản hồi tạo tài khoản thành công g) Tự động đăng nhập vào ứng dụng bằng tài khoản mới tạo
Luồng sự kiện ngoại lệ Không có
Yêu cầu phi chức năng
6.3.2.2 Đặc tả Use Case đăng nhập
Bảng 6.4 Đặc tả Use Case đăng nhập
Tên Use Case Đăng nhập
User đăng nhập vào hệ thống bằng email và password của tài khoản đã đăng ký từ trước
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Ngưởi dùng truy cập vào ứng dụng
Tiền điều kiện Người dùng đã đăng ký tài khoản thành công
Hậu điều kiện người dùng đăng nhập vào hệ thống thành công với tài khoản tương ứng
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Người dùng đăng nhập bằng email và password của tài khoản đã khởi tạo
102 c) Người dùng nhận thông báo đăng nhập thành công d) Người dùng được chuyển đến trang chính của ứng dụng
Luồng sự kiện phụ a) Người dùng truy cập vào ứng dụng b) Người dùng đăng nhập bằng email và password của tài khoản đã khởi tạo c) Hệ thống thông báo người dùng đã nhập sai thông tin đăng nhập d) Người dùng đăng nhập bằng email và password của tài khoản đã khởi tạo e) Người dùng nhận thông báo đăng nhập thành công f) Người dùng được chuyển đến trang chính của ứng dụng
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.3 Đặc tả Use Case đăng xuất
Bảng 6.5 Đặc tả Use Case đăng xuất
Tên Use Case Đăng xuất
Mô tả Use Case User đăng xuất khỏi hệ thống sau khi đã đăng nhập
103 Độ ưu tiên Phải có
Kích hoạt (trigger) - Ngưởi dùng nhấn vào nút ‘Sign out’ ở trang chính
Tiền điều kiện Người dùng đã đăng nhập vào ứng dụng thành công
Hậu điều kiện Tài khoản của người dùng được ghi nhận đã đăng xuất khỏi hệ thống
Luồng sự kiện cơ bản a) Người dùng nhấn vào nút ‘sign out’ ở trang chính b) Người dùng nhận thông báo đã đăng xuất khỏi ứng dụng c) Người dùng được đưa đến trang đăng nhập
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.4 Đặc tả Use Case đăng nhập với Google
Bảng 6.6 Đặc tả Use Case đăng nhập với Google
Tên Use Case Đăng nhập với Google
Mô tả Use Case User đăng nhập vào hệ thống bằng tài khoản Google
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Ngưởi dùng nhấn vào nút ‘Sign in with
Tiền điều kiện Người dùng đã tạo tài khoản thành công với Google
Hậu điều kiện Tài khoản Google của người dùng được liên kết với hệ thống
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Người nhấn vào nút ‘Sign in with Google’ c) Người dùng được chuyển đến trang d) đăng nhập với Google e) Google trả về tài khoản đã đăng nhập thành công f) Hệ thống ghi nhận thông tin tài khoản Google của người dùng và đăng nhập người dùng g) Người dùng được chuyển đến trang chính của ứng dụng
Luồng sự kiện phụ a) Người dùng truy cập vào ứng dụng b) Người nhấn vào nút ‘Sign in with Google’ c) Người dùng được chuyển đến trang đăng nhập với Google d) Google trả về tài khoản đã đăng nhập thất bại e) Người dùng được chuyển về trang đăng nhập của ứng dụng
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng
105 b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.5 Đặc tả Use Case xem danh sách bài đăng
Bảng 6.7 Đặc tả Use Case xem danh sách bài đăng
Tên Use Case Xem danh sách bài đăng
Mô tả Use Case Là người dùng, tôi muốn xem các bài đăng có trên mạng xã hội
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) a) Người dùng mở ứng dụng b) Nhấn vào nút đầu tiên ở thanh điều hướng ở cạnh dưới màn hình
Tiền điều kiện Người dùng đã đăng nhập thành công và có thông tin cá nhân trên mạng xã hội
Hậu điều kiện Người dùng nhìn thấy danh sách các bài đăng có trên mạng xã hội
Luồng sự kiện cơ bản a) Người dùng truy cập vào ứng dụng b) Tầng Frontend đưa người dùng đến trang chủ c) Tầng Frontend tải dữ liệu bài đăng từ cơ sở dữ liệu Firebase và hiển thị lên màn hình d) Với từng bài đăng, tầng Frontend tải dữ liệu về người dùng là chủ sở hữu của bài đăng và hiện thị lên phía trên của nội dung bài đăng Đồng thời tải dữ liệu về
106 số lượng bình luận và hiện thị ở phía dưới nội dung bài đăng
Luồng sự kiện phụ a) Người dùng nhấn vào nút đầu tiên ở thanh điều hướng ở cạnh dưới màn hình b) Thực hiện luồng sự kiện cơ bản từ bước b)
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng b) Nếu hệ thống gặp lỗi trong quá trình lấy dữ liệu từ Firebase, thông báo cho người dùng thông qua snackbar
Yêu cầu phi chức năng
6.3.2.6 Đặc tả Use Case thêm bài đăng
Bảng 6.8 Đặc tả Use Case thêm bài đăng
Tên Use Case Thêm bài đăng
Mô tả Use Case Là người dùng, tôi muốn đăng tải bài đăng mới lên mạng xã hội
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Người dùng nhấn vào nút thứ 2 ở thanh điều hướng ở cạnh dưới màn hình
Tiền điều kiện Người dùng đã đăng nhập thành công và có thông tin cá nhân trên mạng xã hội
Hậu điều kiện Người dùng nhìn thấy bài đăng của mình hiển thị trên mạng xã hội
Luồng sự kiện cơ bản a) Người dùng nhấn vào nút thứ 2 ở thanh điều hướng ở cạnh dưới màn hình b) Hiển thị giao diện đăng bài, c) User điền thông tin bài đăng và nhấn nút đăng bài ở góc trên d) Hệ thống ghi nhận bài đăng mới Luồng sự kiện phụ
Luồng sự kiện ngoại lệ a) Nếu hệ thông gặp lỗi trong quá trình xử lí logic ở tầng Frontend, thông báo lỗi cho người dùng b) Nếu hệ thống gặp lỗi trong quá trình lưu dữ liệu xuống Firebase, thông báo cho người dùng thông qua snackbar Quy tắc nghiệp vụ
Yêu cầu phi chức năng
6.3.2.7 Đặc tả Use Case yêu thích bài đăng
Bảng 6.9 Đặc tả Use Case yêu thích bài đăng
Tên Use Case Yêu thích bài đăng
Là người dùng, tôi muốn thể hiện sự yêu thích hoặc thu hồi thể hiện này với một bài đăng trên mạng xã hội
Actor User Độ ưu tiên Phải có
Kích hoạt (trigger) Người dùng nhấn vào nút yêu thích hoặc nhấn đúp vào bài đăng Tiền điều kiện a) Người dùng đã đăng nhập thành công và có thông tin cá nhân trên mạng xã hội b) Tồn tại ít nhất một bài đăng
Người dùng nhìn nút yêu thích được tô màu đỏ nếu trước đó chưa được tô và ngược lại
Luồng sự kiện cơ bản a) Người dùng nhấn vào nút yêu thích ở dưới nội dung bài đăng b) Hệ thống ghi nhận sự kiện, kiểm tra nếu người dùng đã yêu thích bài đăng thì thu hồi yêu thích của người dùng và ngược lại c) Hệ thống lưu lại kết quả xuống cơ sở dữ liệu
Mô tả giao diện ứng dụng
Hình 6.4 Giao diện đăng ký Bảng 6.19 Mô tả giao diện đăng ký
1 Nút quay lại trang trước
2 Trường nhập thông tin email
4 Trường nhập xác nhận mật khẩu
5 Nút đăng ký tài khoản
6 Dòng chữ gợi ý có nghĩa: “Nếu đã có tài khoản” và chữ “Sign in” chuyển hướng người dùng sang trang đăng nhập nếu nhấn vào
Hình 6.5 Giao diện đăng nhập
Bảng 6.20 Mô tả giao diện đăng nhập
1 Trường nhập thông tin email
4 Dòng chữ gợi ý có nghĩa: “Nếu chưa có tài khoản” và chữ “Sign up” chuyển hướng người dùng sang trang đăng kí nếu nhấn vào
5 Nút đăng nhập với Google
Hình 6.6 Giao diện trang chủ
Hình 6.7 Giao diện trang chủ khi mở menu mở rộng của bài đăng
Bảng 6.21 Mô tả giao diện trang chủ
2 Thông tin người sở hữu bài đăng, gồm các thông tin từ trái sang phải: ảnh đại diện, tên người dùng
3 Ảnh của bài đăng nếu có
4 Nút yêu thích bài đăng
5 Nút xem danh sách bình luận của bài dăng
6 Số lượt yêu thích bài đăng
8 Dòng chữ có ý nghĩa: “Xem tất cả {x} bình luận” với x là tổng số bình luận
10 Nút mở menu mở rộng, chỉ xuất hiện với những bài đăng mà tải khoản đang đăng nhập sỡ hữu
11 Thanh điều hướng ứng dụng, gồm các nút từ trái sang phải: Trang chủ, Thêm bài đăng mới, Quản lý thông người dùng
12 Menu mở rộng của bài đăng, có lựa chọn xoá bài đăng
6.4.4 Giao diện danh sách bình luận
Hình 6.8 Giao diện danh sách bình luận
Hình 6.9 Giao diện danh sách bình luận khi mở menu mở rộng của bình luận Bảng 6.22 Mô tả giao diện danh sách bình luận
1 Nút quay lại trang chủ
2 Ảnh đại diện của người đăng bình luận
3 Thông tin của bình luận từ trên xuống dưới bao gồm: tên người bình luận, nội dung bình luận, thời gian bình luận
Nút mở menu mở rộng của bình luận Chỉ xuất hiện khi tài khoản đang đăng nhập là tài khoản đăng bình luận hoặc là tài khoản sỡ hữu bài đăng mà bình luận này thuộc về
5 Ảnh đại diện của tài khoản đang đăng nhập
6 Trường nhập nội dung bình luận
7 Nút đăng tải bình luận
8 Menu mở rộng của bình luận, có lựa chọn xoá bình luận
6.4.5 Giao diện thêm bài đăng
Hình 6.10 Giao diện thêm bài đăng
Hình 6.11 Giao diện thêm bài đăng khi mở menu mở rộng chọn ảnh
Bảng 6.23 Mô tả giao diện thêm bài đăng
1 Ảnh đại diện của tài khoản đang đăng nhập
2 Trường nhập nội dung bài đăng
3 Nút đăng tải bài đăng, chỉ có thể nhấn được khi hoặc có nội dung bài đăng hoặc có ảnh đính kèm bài đăng
4 Nút mở menu để chọn hình ảnh cho bài đăng,
5 Khu vực hiện ảnh đính kèm bài đăng nếu có
6 Menu mở rộng để chọn ảnh đính kèm cho bài đăng gồm các lựa chọn từ trên xuống dưới: chụp ảnh, chọn ảnh từ thư viện và huỷ
6.4.6 Giao diện quản lý thông tin tài khoản
Hình 6.12 Giao diện quản lý thông tin tài khoản
Hình 6.13 Giao diện quản lý thông tin tài khoản khi mở menu mở rộng chọn ảnh
Bảng 6.24 Mô tả giao diện quản lý thông tin tài khoản
1 Ảnh đại diện của tài khoản đang đăng nhập
2 Nút mở menu mở rộng để chọn ảnh đại diện
3 Trường nhập thông tin tên người dùng
4 Nút lưu thông tin người dùng,
5 Menu mở rộng để chọn ảnh đính kèm cho bài đăng gồm các lựa chọn từ trên xuống dưới: chụp ảnh, chọn ảnh từ thư viện và huỷ.
Cài đặt ứng dụng
Ứng dụng cú thờ̉ được tải về ở url: Release Release web and android ã code- plet/socialnetworkapp (github.com) Trong đó: a) Tệp tin socialnetwork_web.zip là tệp tin nén chứa các tệp tin cần thiết để triển khai ứng dụng web lên domain b) Tệp tin socialnetwork_android_app.apk là tệp tin cài đặt ứng dụng trên nền tảng Android
KẾT LUẬN
Đánh giá
Trong quá trình tìm hiểu, nhóm dễ dàng tìm kiếm các thông tin liên quan nhờ vào nguồn tài liệu được viết rõ ràng từ các framework cũng như là từ các nguồn tài liệu khác Thành viên trong nhóm cũng có kinh nghiệm với Javascript, C++, Firebase nên từ đó việc học ngôn ngữ mới là Dart không gặp quá nhiều khó khăn cũng như việc xây dựng ứng dụng mẫu cũng dễ dàng hơn khi dựa vào tài liệu Flutter được viết bởi chính nhà phát triển
Mặc dù việc phát triển ứng dụng ở phía nhà phát triển có thể dễ dàng, việc đưa ứng dụng trở nên có thể cài đặt được trên các thiết bị thật để chứng minh khả năng chạy đa nền tảng còn hạn chế vì thiết thiết bị, điển hình là thiết bị chạy macOS Ứng dụng hiện chỉ có thể chạy được trên nền tảng web và điện thoại Android.
Kết quả đạt được
Nhóm đã cung cấp được một cái nhìn cụ thể về lịch sử phát triển của Frontend, những thành phần kiến tạo nên Frontend của ứng dụng, những công nghệ phổ biến và những xu hướng công nghệ trong thời gian gần đây Tiếp đó, nhóm đã cung cấp cái nhìn cụ thể về framework Flutter dùng để phát triển ứng dụng đa nền tảng, những khái niệm, những best practices để tối ưu ứng dụng và kiến trúc của Flutter để người đọc hiểu rõ cách mà Flutter hoạt động; đồng thời so sánh với một framework khác tương tự như React Native để người đọc có thể xem xét lợi và hại khi đặt 2 framework này lên bàn cân.
Hướng phát triển
Nhóm sẽ tiếp tục phát triển ứng dụng mạng xã hội có thêm nhiều tính năng nâng cao hơn, giao diện hiện đại và hợp lý hơn, tốt cho UI và UX, đồng thời áp dụng triệt để các best-practices để mang lại một ứng dụng mẫu được tối ưu tốt nhất có thể, mạng lại một ứng dụng mượt mà Đồng thời nhóm sẽ tìm kiếm phương án để đưa ứng dụng lên nền tảng iOS, macOS và Windows
[1] O 1Training, “How HTML, CSS and JavaScript are used for web development?,” 1Training, https://www.1training.org/blog/html-css-javascript-web-development/ (accessed Oct 12, 2023)
[2] Mike ShannonMike is the creator of Go With Code and a coder at heart ?, “21 most popular programming languages in the world (and where to learn them),” //Go With Code/, https://gowithcode.com/top-programming-languages (accessed Nov 16, 2023)
[3] DungVu, “Ide LÀ GÌ? Tổng Quan Ide Cho người mới bắt đầu,” BKHOST, https://bkhost.vn/blog/ide/ (accessed Nov 20, 2023)
[4] Z Khotov, “Top 15 best javascript frameworks,” LinkedIn, https://www.linkedin.com/pulse/top-15-best-javascript-frameworks-zamir-khotov (accessed Nov 20, 2023)
[5] React Native Team, “Introduction ã REACT NATIVE,” React Native RSS, https://reactnative.dev/docs/getting-started (accessed Dec 5, 2023)
[6] F Team, “Flutter documentation,” Flutter, https://docs.flutter.dev/ (accessed Nov 23, 2023)
[7] S Morris, “What is jQuery?,” Skillcrush, https://skillcrush.com/blog/what-is-jquery-used- for/ (accessed Oct 10, 2023)
[8] T Sufiyan, “What is node.js: A comprehensive guide,” Simplilearn.com, https://www.simplilearn.com/tutorials/nodejs-tutorial/what-is-nodejs (accessed Dec 10, 2023) [9] Quantri, “Ajax là gì? 3 phương Thức Trong Ajax - Accesstrade việt nam,” Access Trade, https://accesstrade.vn/ajax-la-gi/ (accessed Nov 15, 2023)
[10] S E Training, “Flutter vs react native: Lựa Chọn Nào Tốt Nhất Hiện Nay,” Viblo, https://viblo.asia/p/flutter-vs-react-native-lua-chon-nao-tot-nhat-hien-nay-E375zLM6ZGW (accessed Nov 29, 2023)
[11] Y Alemayehu, “Demystifying ‘final’ and ‘const’ in flutter and Dart:,” Medium, https://medium.com/@yetesfadev/demystifying-final-and-const-in-flutter-and-dart- 4d6dbc4cbbb8#:~:text=%2D%20Code%20Optimization%3A%20Using%20%E2%80
%9Cconst,expressions%20involving%20only%20other%20constants (accessed Dec
[12] A AlHamali, “Flutter: Creating a listview that loads one page at a time,” Medium, https://medium.com/saugo360/flutter-creating-a-listview-that-loads-one-page-at-a- time-c5c91b6fabd3 (accessed Nov 21, 2023).