- Ghi lại các công nghệ đã chọn cách đây 2 năm để xây dựng mobile/web/backend và những nhìn lại về chúng
- Đây là một SaaS rất đơn giản, phổ thông nên mục tiêu là bootstrap thật nhanh với ít công sức và tài nguyên nhất
Do năng lực thiết kế có hạn, tôi không tự phát triển ứng dụng di động mà thuê ngoài, còn chỉ phát triển backend và web
Các lựa chọn công nghệ
Ứng dụng di động
- Dù đã là lập trình viên .NET lâu năm, tôi không muốn phát triển bằng Xamarin
- Để hỗ trợ đồng thời iOS/Android, tôi chọn Flutter
- Chỉ trong vài tuần đã có ứng dụng chạy trên cả hai nền tảng, nên xét về Time to Market thì rất tuyệt vời
- UI có hơi một vài lỗi, nhưng với use case B2B như của chúng tôi thì có thể bỏ qua
- Bản thân Flutter có khá nhiều bug và vấn đề, nhưng chưa đến mức chặn đứng mọi thứ
- Dart với tư cách một ngôn ngữ thì không hợp gu lắm, nhưng đó không phải vấn đề. (Dù sao tôi cũng không trực tiếp phát triển)
- Có lẽ cứ kiên trì với Xamarin hoặc chọn React Native còn tốt hơn
API
- Scale không phải điều quan trọng. Chỉ cần cung cấp cho một vài khách hàng đầu tiên là được
- Vì vậy bỏ qua hết Kubernetes/serverless các kiểu và cứ phát triển theo kiểu monolith
- Đó là một ứng dụng .NET đơn khối nhưng được module hóa, viết bằng F# và theo kiến trúc Onion (mẫu Ports & Adapters)
- Cũng bỏ qua cả GraphQL và chỉ dùng kiểu REST cổ điển
- Kết quả
- API rất vững và nhanh. Gần như không phát sinh vấn đề trong quá trình triển khai
- Không thể chứng minh được, nhưng tôi nghĩ phần lớn thành công này đến từ cách tiếp cận "Applied Functional Programming" mà tôi đã dùng
- Ngoài ra, mã F# rất đẹp, dễ đọc và dễ hiểu
- Vì chỉ phụ thuộc vào rất ít thư viện mã nguồn mở, nên việc hệ sinh thái F# tương đối nhỏ và phát triển chậm không thành vấn đề
Lưu trữ dữ liệu
- Tôi đã dùng SQL Server lâu năm nhưng không muốn tốn chi phí giấy phép cho DB
- Vì vậy tôi chọn PostgreSQL, và API dùng một máy chủ DB đơn. Có kèm một chút cơ chế queue
- Sản phẩm cần có BLOB storage, nên tôi quyết định đơn giản là dùng hệ thống tệp của máy chủ
- Kết quả
- Cứ thế mà chạy ổn (
It just works). Làm việc với Postgres rất dễ chịu
- Kiểu dữ liệu JSONB cho phép kết hợp kỹ thuật Relational và NoSQL. Theo một cách rất ổn định và thoải mái
- Có lẽ không cần phải học thuộc cú pháp truy vấn JSON
- Lưu BLOB trực tiếp lên đĩa là một quyết định lớn, nhưng dùng thứ như AWS S3 có lẽ cũng không giúp ích nhiều với số lượng người dùng ít
Ứng dụng web
- Quyết định công nghệ cho web app mất khá nhiều thời gian
- Trực giác mách bảo tôi chọn Fable và F#, nhưng cuối cùng tôi quyết định dùng React và TypeScript để xây dựng SPA
- Một trong những quyết định quan trọng ở giai đoạn đầu là áp dụng Tailwind CSS
- Kết quả
- React cứ thế mà chạy ổn, TypeScript cũng vậy
- Cũng giống Dart, tôi không thích viết TypeScript lắm, mà đọc cũng không quá thích
- Tuy vậy TS vẫn có những tính năng rất hay. Những thứ như discriminated unions là tính năng tôi ước F# cũng có
- Nhìn chung trải nghiệm phát triển rất tuyệt. Thời gian build cực ngắn (so với F#), và với hầu hết các vấn đề UI phức tạp thì đã có sẵn package
- Ngay cả xét từ góc độ lập trình hàm, mô hình ứng dụng tổng thể của React vẫn có thể hiểu được
- Tailwind CSS giúp giảm tải rất nhiều
Hạ tầng
- Khi đã quyết định đi theo monolith thì việc lựa chọn trở nên dễ dàng hơn
- Tôi thuê máy Linux ở Hetzner và chạy 3 container Docker: Postgres, DotNet API, Nginx
- Mọi thứ đều được build bằng GitHub Actions và tự động deploy
- Kết quả
- Nếu triển khai đồng thời client và backend thì có downtime, nhưng hiện tại nó ngắn và có thể bỏ qua
- Toàn bộ quy trình gọn nhẹ, ổn định, và cấu trúc chi phí cũng vậy. Hetzner thực sự rất rẻ
Tổng kết
- Tôi rất hài lòng với các quyết định hiện tại
- Tôi đã đầu tư vào F# và lập trình hàm ở quy mô rộng hơn so với các dự án trước
- Ba ngôn ngữ F#, TypeScript, Dart trong một dự án thì hơi nhiều.
Dotnet MAUI chưa trưởng thành bằng Flutter, nhưng có vẻ vẫn là một lựa chọn để thay cho một ngôn ngữ khác ít dùng hơn
3 bình luận
Về dài hạn, việc tuyển dụng nhân lực có suôn sẻ không?
Có lẽ đó là một dịch vụ do một người tự vận hành. Có vẻ họ đã nghĩ theo hướng thuận tiện hơn cho chính mình trong việc bảo trì, hơn là dựa vào nhân lực.
Dù cũng có vài điểm không hợp với tôi, nhưng có vẻ đây là những lựa chọn khá thực tế và phù hợp với người này.