Câu hỏi bảo vệ
Trang này là bản trả lời nhanh khi thầy hỏi trực tiếp. Cách nói tốt nhất là đi theo 3 lớp: người dùng làm gì, frontend gọi gì, backend/database xử lý gì.
Công thức trả lời 30 giây
| Nếu bị hỏi | Câu trả lời khung | Mở thêm |
|---|---|---|
| Dự án dùng công nghệ gì? | Backend Java 21/Spring Boot, frontend Angular 20, database PostgreSQL/Flyway, deploy Docker/Caddy, media trên R2, video bằng Shaka/HLS/DASH. | Kiến trúc |
| Vì sao chia module? | Tách nghiệp vụ theo domain để dễ test, dễ sửa và không để framework/JPA trộn vào domain. | Backend |
| Database có bao nhiêu bảng? | Theo Flyway hiện tại có 78 application tables, 2 materialized views, 107 migration SQL files. flyway_schema_history không tính là bảng nghiệp vụ LMS. |
SQL schema catalog |
| Learner học từ đâu? | Learner đọc snapshot trong course_publications, không đọc trực tiếp draft teacher đang sửa. |
Publication |
| Wiii/Pointy có tự sửa dữ liệu không? | Không. Pointy chỉ được click safe target, và nội dung AI phải qua preview/diff trước khi apply. | Wiii |
| Muốn sửa UI/logic mở file nào? | UI mở component/template/SCSS trong fe/src/app/features/...; logic backend mở controller -> use case -> repository adapter -> migration nếu đổi schema. |
Vị trí file code |
Dự án dùng công nghệ gì?
Backend dùng Java 21, Spring Boot 3.2, Spring Security, JWT, PostgreSQL 16, Flyway, SpringDoc OpenAPI, AWS S3 SDK cho Cloudflare R2. Frontend dùng Angular 20, TypeScript, RxJS, Signals, Sass, PWA Service Worker, Dexie/IndexedDB. Video dùng Shaka Player, HLS/DASH, object storage và dedicated video worker.
Cách nói ngắn: LMS là web app full-stack theo hướng modular monolith. Backend tập trung nghiệp vụ và dữ liệu; frontend xử lý trải nghiệm học/giảng dạy; storage/video worker tách phần nặng ra khỏi request web thông thường.
Vì sao backend dùng DDD/Clean Architecture?
Mục tiêu là tách nghiệp vụ khỏi framework. Domain model không phụ thuộc JPA. Application use case điều phối nghiệp vụ. Infrastructure chứa REST controller, JPA entity, repository adapter, storage adapter và integration ngoài.
Khi sửa một chức năng backend, đi theo thứ tự:
- Controller nhận request và validate quyền.
- Use case xử lý nghiệp vụ.
- Repository port nói bằng domain model.
- Adapter/JPA entity lo database.
- Migration Flyway thay đổi schema nếu cần.
Điểm cần nhấn mạnh: Spring Data JPA repository phải trỏ tới *JpaEntity, không trỏ trực tiếp domain model, nếu không dễ lỗi Not a managed type.
Auth và phân quyền hoạt động thế nào?
Người dùng đăng nhập qua API auth, backend trả JWT. Frontend giữ session và route guard theo role. Backend vẫn là nơi kiểm quyền cuối cùng bằng security config, annotation và ownership guard.
Role chính:
| Role | Vai trò | Ranh giới |
|---|---|---|
ADMIN |
Quản trị hệ thống | Được quản trị toàn hệ thống, gồm endpoint system-only |
ORG_ADMIN |
Quản lý vận hành | Duyệt course, quản lý teacher/student, analytics; không được nâng quyền admin |
TEACHER |
Giảng viên | Tạo course, lesson, quiz, assignment, grading |
STUDENT |
Học viên | Enroll, học bài, làm quiz/assignment, xem progress |
Teacher tạo khóa học đi qua những gì?
Flow ngắn: teacher mở course editor ở Angular, sửa metadata/chapter/lesson/block, frontend gọi teacher course API, backend lưu draft trong các bảng course authoring như courses, chapters, lessons, sections, lesson_attachments.
Khi teacher submit, hệ thống tạo luồng review. Admin/ORG_ADMIN duyệt thì learner-facing snapshot được ghi vào course_publications. Đây là điểm quan trọng để tránh learner nhìn thấy bản draft đang sửa dở.
Nếu bị hỏi content_blocks: đây là cột JSONB để lưu rich content trong lessons và questions, không phải bảng riêng.
Student học bài đi qua những gì?
Student xem catalog/course detail, enroll hoặc thanh toán nếu course có phí. Khi học, frontend đọc nội dung từ publication snapshot, hiển thị lesson/video/quiz/assignment. Progress được ghi vào các bảng như enrollments, student_lesson_progress, video_progress, quiz_attempts, assignment_submissions.
Nếu offline, app shell và dữ liệu đã tải được lưu local; progress được queue và sync lại khi online.
Quiz, assignment và grading xử lý thế nào?
Quiz dùng quizzes, questions, question_options, quiz_questions, quiz_attempts. Assignment dùng assignments, assignment_submissions, assignment_attachments, assignment_rubrics, grading_audit_log. Backend phải bảo vệ các hành động nhạy cảm: student không được tự grade, Wiii không được tự submit quiz, teacher chỉ grade phạm vi được phép.
Khi nói với thầy: assessment tách rõ quiz tự động và assignment/rubric có chấm điểm, có audit để truy vết grading.
Upload tài liệu/video hoạt động thế nào?
Upload thông thường dùng presigned upload: backend tạo upload session, frontend upload file lên storage, backend confirm và gắn file vào entity phù hợp. Video đi thêm pipeline ingest: video_assets, video_renditions, video_ingest_jobs, worker tạo HLS/DASH/offline profile.
Điểm mạnh là web backend không phải giữ request stream file nặng trong thời gian dài. Với video lớn, xử lý nặng đi qua worker riêng.
Shaka, ABR và offline là gì?
Shaka Player phát manifest HLS/DASH. ABR là adaptive bitrate: player chọn chất lượng theo mạng/thiết bị. Offline/PWA dùng service worker cho app shell và IndexedDB/Dexie cho dữ liệu học, cache, queue sync.
Nếu bị hỏi sửa Shaka/ABR: mở AdaptiveVideoPlayerComponent, các service video/offline trong frontend, và backend video asset/playback endpoint.
Payment và doanh thu xử lý ra sao?
VNPay/SePay tạo giao dịch trong payment_transactions. Callback/IPN/webhook xác nhận trạng thái. Sau khi payment thành công, backend kích hoạt enrollment hoặc quyền truy cập phù hợp. Revenue/payout dùng revenue_splits, teacher_bank_accounts, payout_requests.
Điểm cần cẩn thận: payment là vùng dữ liệu nguy hiểm, không để AI/Wiii tự click, tự confirm, tự refund hoặc tự mutate.
Wiii tích hợp an toàn thế nào?
LMS host cung cấp iframe/embed và DOM target ổn định qua data-wiii-id. Pointy là lớp quan sát/click của Wiii. Chỉ nút điều hướng an toàn mới có data-wiii-click-safe="true". Các action tạo nội dung như lesson draft phải đi qua preview/diff và người dùng xác nhận trước khi apply.
Không cho Wiii tự làm các việc nguy hiểm: submit quiz, delete, publish, enroll, grade, payment, refund, payout hoặc mutate dữ liệu không có preview.
Web chịu tải được bao nhiêu người?
Không nên trả lời bằng một con số tuyệt đối nếu chưa có load test thật. Cách trả lời đúng là: hệ thống đã tách web backend, database, object storage và video worker; video/static media không đi trực tiếp qua backend lâu dài; nhưng giới hạn concurrent thực tế phụ thuộc CPU/RAM VM, DB connection pool, cache, CDN/R2, query/index và traffic mix.
Nếu thầy hỏi 20.000 hay 500.000 người cùng lúc, câu trả lời an toàn là phải có kịch bản load test: login/course list/lesson/video/payment riêng. 500.000 concurrent cần kiến trúc scale ngang, cache/CDN, queue, DB read replica hoặc managed DB mạnh hơn, rate limit và chống DDoS ở edge.
Khi thầy bảo sửa màu hoặc sửa logic
Sửa màu/layout: mở component Angular tương ứng, template .html, style .scss, hoặc global style/design token. Sửa logic UI: mở component/service/store. Sửa logic backend: mở controller để xem API, use case để xem nghiệp vụ, repository adapter để xem DB, migration nếu đổi schema.
Trang cần mở nhanh: Vị trí file code, Source map, Symbol index.
Câu hỏi kết bài
Nếu cần tóm tắt dự án trong một phút:
LMS Hàng Hải là hệ thống học trực tuyến theo domain giáo dục hàng hải. Backend Spring Boot được chia DDD/Clean Architecture, frontend Angular 20 dùng signal và PWA, database PostgreSQL quản lý bằng Flyway. Hệ thống có course authoring, publication approval, learning progress, quiz/assignment, payment/revenue, video adaptive/offline, và tích hợp Wiii theo ranh giới an toàn có preview/diff trước khi apply nội dung AI.