Khóa học
Chào mừng bạn quay lại! Trong hướng dẫn đầu tiên của loạt bài này, Devin đã “phủi bụi” repo fp-ts-exercises cũ của tôi và mở một PR nâng cấp phụ thuộc rất gọn. Ở phần hai này, chúng ta sẽ tăng độ khó và xây dựng các tính năng full-stack.
Bạn có thể truy cập tất cả các hướng dẫn trong loạt Devin tại đây:
- Thiết lập và Pull Request đầu tiên (Phần 1)
- Giao một Vertical Slice với Devin (Phần 2)
- Tích hợp, Kiểm thử và CI/CD (Phần 3)
- Bảo mật, Triển khai, Vận hành (Phần 4)
Khi cuộn đến cuối phần hai này, bạn sẽ có:
- Một playground Next.js 14, nơi người học chỉnh sửa mã ngay trong trình duyệt;
- Các bài kiểm thử Vitest trực tiếp chuyển xanh (hoặc đỏ) theo thời gian thực; và
- Một backend NestJS với cơ sở dữ liệu SQL lưu tiến độ chỉ bằng một UUID ẩn danh trong localStorage.
Trong quá trình này, chúng ta sẽ để Devin tự tạo danh sách công việc, xem nó xử lý song song các ticket front-end và back-end, và can thiệp khi nó vướng cấu hình. Tôi sẽ chỉ bạn tôi đã tiêu (và tiết kiệm) ACU ở đâu, tự sửa gì bằng tay, và cách giữ cho phiên làm việc hiệu quả.
Tóm tắt và Điều kiện tiên quyết
Xuyên suốt loạt hướng dẫn này, chúng ta làm việc trên repo bài tập fp-ts (trước đây) bị bỏ quên của tôi.
Dự án là bộ sưu tập các thử thách nhỏ nhằm dạy các khái niệm lập trình hàm (như Option, Either, v.v.) bằng TypeScript. Hiện tại, đây là repo clone-and-run: người học kéo về, chỉnh sửa tệp cục bộ và chạy test trong terminal của họ.
Mục tiêu là biến những bài tập đó thành một playground tương tác trên trình duyệt, nơi mọi người có thể đọc giải thích, chỉnh sửa mã trong trình soạn thảo trên trang và thấy test đỗ (hoặc trượt) ngay lập tức. Người học cũng có thể đăng nhập để lưu tiến độ.
Những gì chúng ta đã làm ở phần đầu
Nhắc lại, trong hướng dẫn đầu tiên, chúng ta đã:
- Hiện đại hóa repo fp-ts cũ: cập nhật phụ thuộc, linting, kiểm tra kiểu.
- Kết nối Devin với GitHub và chứng minh nó có thể mở pull request sạch.
Công cụ cục bộ bạn cần cho phần hai
Cho hướng dẫn này, chúng ta cần:
- Node 20+ và npm 10 (hỗ trợ workspaces sẵn).
- Docker chạy container PostgreSQL (hoặc một PostgreSQL cục bộ).
Thiết lập Devin khuyên dùng
Tôi khuyến nghị các thiết lập sau cho Devin:
- Đặt giới hạn mềm 5 ACU mỗi phiên trong Settings > Usage & limits; chúng ta sẽ mở phiên mới cho mỗi giai đoạn.
- Giữ tab timelapse hiển thị để tạm dừng hoặc nhắc Devin nếu nó đứng yên.
Để Devin Viết Kế Hoạch
Tôi nghĩ sẽ thú vị nếu bắt đầu bằng việc kiểm tra khả năng lập kế hoạch của Devin. Tôi tạo một prompt và nhờ Devin, dùng tính năng “Ask” (hiện miễn phí bản Beta), giúp tôi lên kế hoạch cho công việc hôm nay.
Prompt:
Tôi muốn chuyển repo Node + TypeScript fp-ts-exercises hiện có (đang là bài tập CLI clone-and-run) thành một nền tảng học trên trình duyệt có theo dõi tiến độ.
Trải nghiệm mục tiêu:
- Người học mở ứng dụng web Next.js, chọn một bài tập, chỉnh mã trong trình duyệt, và thấy bài kiểm thử Vitest đỗ hoặc trượt ngay lập tức.
- Tiến độ (các slug đã hoàn thành) được lưu phía máy chủ và tải lại khi truy cập sau, nhưng chúng ta chưa thêm tài khoản người dùng (dùng UUID ẩn danh lưu trong trình duyệt).
Lựa chọn công nghệ tôi đang nghiêng về:
- Frontend: Next.js 14 (React 18, App Router)
- Trình soạn mã & chạy mã: Sandpack + @vitest/browser
- API: NestJS 13 với @nestjs/graphql (Apollo Driver)
- Cơ sở dữ liệu: Prisma 5 với PostgreSQL
- Workspace: npm workspaces thuần (apps/web, apps/api, packages/exercises)
Đề xuất kế hoạch triển khai từng bước (danh sách task) để hiện thực hóa vertical slice này. Ước lượng chi phí ACU tương đối cho mỗi task và đánh dấu các bước chạy lâu (ví dụ: di chuyển dữ liệu lớn hoặc cài đặt phụ thuộc nặng).
Devin đã trả về một danh sách công việc gồm sáu giai đoạn với ước tính ACU cho từng phần, và đánh dấu các bước “cài đặt phụ thuộc nặng”.
Câu trả lời của Devin:
Giai đoạn 1: Thiết lập Workspace (2–3 ACU)
- Khởi tạo cấu trúc npm workspace (1 ACU)
- Tạo thư mục apps/web, apps/api và packages/exercises
- Cấu hình package.json gốc với định nghĩa workspace
- Di chuyển các tệp bài tập hiện có sang packages/exercises/src/
- Thiết lập frontend Next.js 14 (1–2 ACU — Chạy lâu: cài đặt phụ thuộc)Khởi tạo Next.js với App Router trong apps/webCấu hình TypeScript và Tailwind CSSThiết lập cấu trúc routing cơ bản
Giai đoạn 2: Di trú gói bài tập (3–4 ACU)
- Tách nội dung bài tập vào gói dùng chung (2 ACU)
- Tạo packages/exercises với chức năng trích xuất metadata bài tập
- Phân tích các tệp bài tập hiện có để trích xuất:
- Hướng dẫn
- Mã khởi đầu
- Lời giải
- Định nghĩa các interface TypeScript cho cấu trúc bài tập
- Triển khai hệ thống khám phá bài tập (1–2 ACU)
- Xây bộ quét hệ thống tệp (tương tự logic fs.readdirSync trong exercise.js:17–28)
- Xuất metadata bài tập: title, description, difficulty, tests
Giai đoạn 3: Backend API (4–5 ACU)
- Thiết lập NestJS API với GraphQL (2 ACU — Chạy lâu: cài đặt phụ thuộc)
- Khởi tạo dự án NestJS trong apps/api
- Cấu hình máy chủ Apollo GraphQL
- Thiết lập endpoint kiểm tra sức khỏe cơ bản
- Triển khai Prisma + PostgreSQL (2 ACU — Chạy lâu: thiết lập DB)
- Thiết kế schema cho:
- Phiên người dùng
- Bài tập đã hoàn thành
- Thiết lập Prisma client và migrations
- Tạo resolver theo dõi tiến độ
- Quản lý phiên người dùng ẩn danh (1 ACU)
- Tạo UUID và lưu trong localStorage trên trình duyệt
- Bật lưu bền tiến độ theo phiên mà không cần xác thực
Giai đoạn 4: Tính năng lõi Frontend (5–6 ACU)
- Giao diện duyệt bài tập (2 ACU)
- Liệt kê bài tập theo danh mục (option, either, task, v.v.)
- Hiển thị chỉ báo tiến độ và trạng thái hoàn thành
- Bật chọn bài tập và điều hướng
- Tích hợp trình soạn thảo Sandpack (2–3 ACU — Chạy lâu: thiết lập Sandpack)
- Cấu hình Sandpack với hỗ trợ TypeScript
- Tải mã khởi đầu và phụ thuộc fp-ts
- Thiết lập hệ thống tệp cho tệp bài tập + test
- Tích hợp Vitest trong trình duyệt (1 ACU)
- Thay thế các lệnh gọi Vitest bằng execSync (exercise.js:45–47) bằng @vitest/browser
- Bật chạy test theo thời gian thực và hiển thị kết quả
Giai đoạn 5: Theo dõi tiến độ (2–3 ACU)
- Quản lý tiến độ phía client (1 ACU)
- Thiết lập Apollo Client cho GraphQL
- Đồng bộ tiến độ với backend
- Phát hiện hoàn thành bài tập (1–2 ACU)
- Điều chỉnh logic phát hiện thành công hiện có (exercise.js:48–49)
- Gửi cập nhật tiến độ lên backend khi test đỗ
Giai đoạn 6: Hoàn thiện & Triển khai (2–3 ACU)
- Cải thiện UI/UX (1–2 ACU)
- Đảm bảo thiết kế responsive
- Thêm trạng thái tải và xử lý lỗi
- Cải thiện hiển thị hướng dẫn bài tập
- Thiết lập triển khai Production (1 ACU)
- Cấu hình Docker cho cả hai ứng dụng
- Quản lý biến môi trường
- Thiết lập triển khai cơ sở dữ liệu
Tổng chi phí ước tính: 18–24 ACU
Kế hoạch nhìn chung khá ổn. Tôi đã thay đổi một số thứ, đặc biệt ở giai đoạn sáu, vì chúng ta sẽ xử lý triển khai ở hướng dẫn thứ tư.
Giai đoạn 1: Workspace & Khung Front-End
Mục tiêu: Khởi tạo npm workspaces, di chuyển tệp cũ và dựng vỏ Next.js 14 trống.Tiêu hao ACU: 3,66 (kế hoạch 1–2).Kết quả: Repo giờ có /apps/web, gói chia sẻ packages/exercises và ứng dụng Next.js hỗ trợ Tailwind chạy trên localhost:3000.
Prompt
Tôi yêu cầu Devin xây dựng theo kế hoạch mà nó đã đề xuất cho giai đoạn đầu. Devin ở chế độ agent không có ngữ cảnh về những gì bạn đã hỏi trong tính năng “Ask Devin” trước đó, vì vậy bạn phải tạo prompt riêng và cung cấp ngữ cảnh.
Tôi sẽ không dán tất cả các prompt vào bài viết này, nhưng đây là prompt đầu tiên:
Prompt:
Nhiệm vụ: Khởi tạo cấu trúc npm workspace và frontend Next.js cho nền tảng fp-ts-exercises trên trình duyệtNgữ cảnh:
Tôi đang chuyển hệ thống học dựa trên CLI fp-ts-exercises hiện có thành nền tảng trên trình duyệt. Hệ thống hiện tại có các bài tập được tổ chức trong 10-from-either.exercise.ts:1-3 với cấu hình TypeScript ở tsconfig.json:88 và thiết lập Vitest trong vitest.config.ts:7.
Yêu cầu:
- Tạo cấu trúc npm workspace:
- package.json gốc với cấu hình workspace cho apps/web, apps/api, packages/exercises
- Di chuyển các tệp bài tập hiện có từ src/ hiện tại sang packages/exercises/src/
- Giữ nguyên quy ước đặt tên tệp bài tập (.exercise.ts và .solution.ts)
- Khởi tạo frontend Next.js 14 trong apps/web:
- Dùng App Router (không dùng Pages Router)
- Cấu hình TypeScript với các thiết lập nghiêm tương tự tsconfig.json:88 hiện tại
- Thêm Tailwind CSS để tạo kiểu
- Tạo cấu trúc routing cơ bản cho duyệt bài tập
- Duy trì tương thích:
- Đảm bảo cấu trúc bài tập và import hiện tại vẫn hoạt động
- Giữ fp-ts khả dụng trên toàn workspace
- Giữ nguyên mẫu cấu hình Vitest hiện tại
Sản phẩm bàn giao:
- package.json cấu hình workspace ở thư mục gốc
- Ứng dụng Next.js trong apps/web/ với TypeScript và Tailwind
- Các bài tập đã di trú ở packages/exercises/
- Cấu trúc routing cơ bản (/exercises, /exercises/[category], /exercises/[category]/[slug])
Ngăn xếp công nghệ:
- Next.js 14 với App Router
- TypeScript (strict mode)
- Tailwind CSS
- npm workspaces (không dùng yarn/pnpm)
Nộp bài:
- Đảm bảo script lint và typecheck pass
- Tạo PR với các thay đổi của bạn
Tất cả các prompt sau đó tôi viết đều theo cùng một mẫu: nêu nhiệm vụ, ngữ cảnh, yêu cầu, bàn giao, ngăn xếp công nghệ và chi tiết nộp.
Devin thực sự đã làm gì
Nó mất khá lâu để quyết định hướng hành động (khoảng bốn phút), nhưng đã:
- Tạo khung xương workspace
- Di chuyển toàn bộ thư mục bài tập vào
packages/exercises/src. - Dựng Next.js 14 với App Router, TypeScript và Tailwind.
- Thêm script lint & type-check cho ứng dụng frontend (sau khi tôi nhắc).
Vì sao chi phí ACU tăng vọt
Chi phí ACU tăng là vì:
- Devin mất nguyên một phút lặp lại
npm installsau khi mirror timeout. - Nó cố dừng server dev và tiến trình bằng
qtrong Vim, rồiCtrl-C, cả hai đều thất bại. Tôi cho nó chút thời gian tự sửa nhưng cuối cùng phải can thiệp thủ công và thoát tiến trình cả hai lần. Mỗi phút thêm là thêm ACU, và tôi sẽ không nhận ra nhanh nếu không theo dõi sát hành động của Devin.
Can thiệp của con người và bài học rút ra
Đây là tóm tắt các sửa lỗi tôi cần làm:
|
Sửa |
Thời gian |
Tôi đã làm thế nào |
|
Diệt tác vụ node watch treo |
15 s |
Diệt tiến trình trong shell VM. |
|
Cài lại Tailwind |
90 s |
npm install tailwindcss postcss autoprefixer --workspace=apps/web và chạy lại tailwind init. |
|
Thêm .next/ vào .gitignore |
10 s |
Commit thủ công để tránh PR phình to. |
Di chuyển cây tệp lớn bằng tay thì nhanh hơn và rẻ hơn nhiều vì Devin tính phí theo thời gian/tác vụ. Tôi kéo thả thư mục, commit, và để agent nhận cấu trúc mới. Nó có thể kéo thay đổi của tôi và tự merge rất ổn!
Tuy nhiên, tôi phải nhắc nó chạy script lint và typecheck, dù tôi đã nêu trong prompt ban đầu. Cuối cùng nó chạy cả hai, nhưng thất bại. Devin vẫn coi là thành công và mở PR.
Tôi đã sửa cả hai vấn đề cục bộ, tự chạy script và chạy server phát triển web mới để đảm bảo nó khởi động như mong đợi, rồi đẩy commit.
Giai đoạn 2: Đóng gói Bài tập
Mục tiêu: Trích xuất tất cả tệp thử thách vào gói dùng lại packages/exercises và tạo metadata cho từng bài tập.Tiêu hao ACU: 0,6 (kế hoạch 2+).Kết quả: Gói dùng chung xuất metadata có kiểu mà ứng dụng web và API tương lai có thể import bằng import { exercises } from '@exercises/registry'.
Devin thực sự đã làm gì
Devin đã tạo:
- Các interface TypeScript có cấu trúc cho bài tập, metadata, danh mục và toàn bộ danh mục bài tập.
- Bộ phân tích bài tập mà:
- Trích metadata từ comment mã và chữ ký hàm
- Phân tích mã khởi đầu, mã lời giải và test case Vitest
- Tự động tạo thẻ từ cách dùng
fp-ts - Chuyển tên camelCase thành tiêu đề dễ đọc
- Hệ thống khám phá bài tập mà:
- Quét hệ thống tệp để tìm cặp
.exercise.tsvà.solution.ts - Xây dựng danh mục dựa trên slug (ví dụ,
option-01) - Tổ chức bài tập theo danh mục với cache để tăng hiệu năng
- Các export tiện dụng để truy vấn bài tập và danh mục:
getExercises(),getExerciseBySlug(),getExercisesByCategory(),getCategories(),getCategoryBySlug()
Vì sao Devin hoàn thành dưới ngân sách
Devin đã giữ chi phí ACU thấp—đây là cách nó làm:
- Không có cài đặt nặng hoặc gọi mạng
- Di chuyển tệp đơn giản; Devin dùng
git mv(rẻ) thay vì copy-paste rồi diff - Tạo metadata thuần TypeScript, nhanh để lập kế hoạch và thực thi
Can thiệp của con người
Lần này không có!
Rút kinh nghiệm lần trước, tôi checkout nhánh của Devin và chạy script cục bộ. Mọi thứ biên dịch được và registry xuất các định nghĩa kiểu sạch, rất phù hợp để làm đầu vào cho UI và API chúng ta sẽ xây tiếp.
Giai đoạn 3: NestJS + GraphQL API
Mục tiêu: Dựng dịch vụ NestJS 13 phơi bày tiến độ bài tập qua GraphQL và lưu dữ liệu vào PostgreSQL với Prisma.Tiêu hao ACU: 4,2 (kế hoạch 4).Kết quả: apps/api khởi chạy tại localhost:4000/graphql. Bạn có thể query và mutate bản ghi tiến độ theo ID phiên ẩn danh.
Devin thực sự đã làm gì
Ở giai đoạn ba, Devin:
- Tạo đầy đủ API NestJS trong
apps/apivới TypeScript và Apollo GraphQL - Tích hợp PostgreSQL với Prisma ORM và thiết lập schema với model
SessionvàCompletedExercise - Triển khai quản lý phiên ẩn danh bằng UUID (không cần xác thực)
- Xây các resolver GraphQL cho tạo/xác thực phiên, truy vấn bài tập và theo dõi tiến độ
- Kết nối backend với gói bài tập dùng chung (
packages/exercises) để khám phá dữ liệu - Cấu hình CORS để hỗ trợ giao tiếp với frontend Next.js
- Đảm bảo tương thích kiểu giữa schema GraphQL và các interface TypeScript hiện có
- Thiết lập script phát triển, quy trình migration DB và tích hợp Prisma Studio
Devin vấp ở đâu
Đây là các vấn đề tôi gặp ở giai đoạn ba và cách khắc phục:
|
Vấn đề |
Cách khắc phục |
Thời gian |
|
Quên import |
Nhắc Devin: “Tôi gặp lỗi này khi chạy The 'import.meta' meta-property is only allowed when the |
1 ACU, 5 phút |
|
Thiếu script lint |
Nhắc Devin: “Thêm script lint vào gói api và đảm bảo nó pass.” |
1 ACU, 4 phút |
|
Lỡ commit |
|
20 s |
Bài học rút ra
Đây là những điều tôi rút ra:
- Cấu hình vs. mã: Devin làm rất tốt khi đã có boilerplate framework, nhưng chẩn đoán vấn đề phụ thuộc vẫn cần con mắt con người.
- Luôn chạy cục bộ: Tôi đã tạo sẵn cơ sở dữ liệu PostgreSQL cục bộ trên máy, và hướng dẫn trong PR để chạy migration Prisma và khởi động môi trường dev rất rõ ràng, dễ theo (xem ảnh dưới). Devin bình luận là đã chạy API cục bộ thành công, nhưng
npm run devvẫn crash cho đến khi thêmreflect-metadata.

- Devin xử lý bình luận PR tốt. Tôi bình luận trên PR, giải thích rằng tôi cố chạy API cục bộ và gặp lỗi. Nó lập tức để emoji mắt, phiên làm việc tự nối lại để sửa lỗi, và một bản vá được đẩy vài phút sau.


- Luôn kiểm tra tệp bí mật: Devin đã commit tệp
.envvới biếnDATABASE_URL, chứa username và password giả. Sau khi kéo về cục bộ, tôi đổi username và password thành thông tin của DB cục bộ và đảm bảo gỡ tệp khỏi theo dõi git và thêm vào.gitignore. Chúng ta sẽ xem ở các hướng dẫn sau cách xử lý secrets an toàn.
Giai đoạn 4: Sandpack Playground & Live Tests
Mục tiêu: Mang đến cho người học trình soạn thảo trên trình duyệt chạy lời giải fp-ts và kiểm thử Vitest theo thời gian thực.Tiêu hao ACU: 7,2 (kế hoạch 3–4).Kết quả: Truy cập /exercises/option-01 mở chế độ chia đôi: Trình soạn Sandpack bên trái, kênh test bên phải, và thông báo thành công bật lên ngay khi tất cả spec pass.
Devin thực sự đã làm gì
Đây là những gì Devin làm ở giai đoạn bốn:
- Xây trang liệt kê bài tập và điều hướng với hỗ trợ danh mục và slug động
- Tích hợp trình soạn Sandpack với TypeScript, fp-ts và hỗ trợ hệ thống tệp theo thời gian thực
- Thay runner CLI bằng Vitest trong trình duyệt với phản hồi trực tiếp
- Kết nối frontend với backend qua Apollo Client để theo dõi tiến độ theo phiên
- Triển khai UI responsive với trạng thái tải và xử lý lỗi
Devin đã “đốt” thêm ACU ở đâu
Devin dùng nhiều ACU hơn dự kiến ở giai đoạn này—lý do là:
|
Nguyên nhân |
Tôi đã sửa/giảm nhẹ thế nào |
|
Để sót mã runner CLI cũ trong |
Xóa |
|
Đợi phản hồi nhưng không hỏi rõ ràng → vòng lặp nhàn rỗi. |
Gõ “Ổn rồi, tiếp tục.” trong chat sau ba phút im lặng. |
Bài học rút ra
Những điều rút ra lần này:
- Ngồi xem im lặng = tốn tiền. Giữ tab Timelapse mở, nếu Devin lặp, hãy nhắc hoặc tạm dừng.
- Xóa mã chết sớm. Devin hiếm khi tự xóa mã cũ, trừ khi bạn bảo rõ. Tôi từng yêu cầu nó di chuyển tệp mà không nói rõ phải xóa, nên ta có nhiều entry point khiến Devin rất bối rối ở giai đoạn này.
Devin đã tốn thời gian ở đây. Nó lặp đi lặp lại, cố sửa cùng vấn đề, chưa kết nối backend và frontend đúng, thay đổi, khởi động lại server, kiểm tra trên trình duyệt xem đã chạy chưa, v.v. Chắc cũng giống công việc phát triển thông thường thôi…
Hiện chúng ta đã có app hoạt động. Tôi có thể chạy cả API và server web, truy cập localhost, chỉnh hàm stub, bấm Lưu, và thấy khung test chuyển từ đỏ sang xanh. Rồi tôi nhận ra nó mới làm được nửa chừng và hardcode test và lời giải của bài đầu tiên cho mọi trang bài tập. Tôi chỉ ra điều đó, và sau thêm vài vòng lặp, nó đã sửa và đẩy cập nhật.
Giai đoạn 5: Đồng bộ Tiến độ bằng UUID
Mục tiêu: Lưu trạng thái hoàn thành của mỗi người học và tô lại thanh bên khi tải lại, tất cả mà không cần tài khoản người dùng.Tiêu hao ACU: 2,7 (kế hoạch 2–3).Kết quả: Một hook React nhỏ giờ lưu UUID sinh trên trình duyệt, gọi GraphQL API mỗi khi test pass và tải trước tiến độ khi playground mount.
Devin thực sự đã làm gì
Ở giai đoạn năm, Devin:
- Tích hợp Apollo Client để giao tiếp GraphQL giữa frontend và backend
- Triển khai quản lý phiên ẩn danh với UUID lưu trong localStorage
- Đồng bộ dữ liệu tiến độ theo thời gian thực và chỉ báo trực quan ở cả cấp danh mục và bài tập
- Phát hiện hoàn thành bài tập bằng cách móc vào runner Vitest trong trình duyệt
- Thêm hỗ trợ offline, cập nhật lạc quan và xử lý lỗi mạnh mẽ với logic retry (mà tôi không yêu cầu).
Một điểm cộng là Devin thêm cập nhật UI lạc quan nên huy hiệu chuyển sang ✅ ngay lập tức. Điều này quan trọng vì giúp giao diện mượt trên kết nối độ trễ cao.
Bài học rút ra
Những điều tôi rút ra là:
- Phạm vi nhỏ thì ít lỗi: Đây là nhiệm vụ khá nhỏ và phạm vi chặt, nên Devin thực hiện tốt và trong thời gian hợp lý.
- Hãy nói điều bạn muốn, và cả điều bạn không muốn: Tôi nhận thấy Devin có xu hướng mở rộng phạm vi, và lại làm nhiều hơn tôi yêu cầu. Lần này tôi không phiền, nhưng nếu có điều bạn thực sự không muốn nó làm, hãy nói rõ. Ví dụ, trong mọi prompt, tôi đều ghi “không có chức năng đăng nhập” vì đoán nó sẽ thử làm.
Giờ ta đã có bằng chứng đường ống phiên ẩn danh hoạt động end-to-end. Đến lúc làm cho nó trông đẹp ở giai đoạn đánh bóng cuối.
Giai đoạn 6: Đánh bóng UI & Bảng điều khiển Tiến độ
Mục tiêu: Biến giao diện “tiện dụng” thành trải nghiệm màu pastel “thoáng đãng” và thêm dashboard trực quan hóa streak, bậc độ khó và hoạt động hàng tuần của mỗi người học.Tiêu hao ACU: 11 (kế hoạch ≈ 3).Kết quả: Chủ đề pastel sáng/tối, thẻ bài tập được thiết kế lại, và dashboard trực tiếp hiển thị vòng tròn, cột và bộ đếm streak. Devin đạt những nét chính, nhưng tôi phải can thiệp để cứu các lệch đặt tên và việc thay phụ thuộc tùy tiện.
Ở giai đoạn này, tôi cố tình mở rộng phạm vi để xem Devin xử lý bộ yêu cầu lớn hơn thế nào. Tôi nghĩ nó sẽ dễ hơn nhiều so với giai đoạn 3 với tất cả phần backend. Spoiler: Tôi đã nhầm.
Devin đã xử lý gì từ prompt
Đây là phân rã yêu cầu của tôi và đầu ra của Devin:
|
Yêu cầu |
Đầu ra của Devin |
|
Hệ thống thiết kế pastel |
Thêm biến Tailwind CSS cho màu chủ đạo xanh lam nhạt, màu thành công mint, điểm nhấn lavender. Đặt góc bo |
|
Chữ và khoảng cách |
Giới thiệu lớp |
|
Bảng điều khiển tiến độ |
Route mới
|
|
Thẻ nâng cao |
Thay |
|
Mở rộng danh mục |
Tạo thêm 10 bài tập khung với tên mang tính kể chuyện và mẫu placeholder. Metadata gồm độ khó, thời gian ước tính và danh mục. |
Devin sai ở đâu
Mọi thứ không hoàn hảo—Devin đã:
- Thay đổi tên tệp gói bài tập mà không cập nhật wrapper hoặc resolver → lỗi runtime 500; vá +1 ACU.
- Âm thầm thay Postgres bằng SQLite “để dev cục bộ dễ hơn” mà không xin phép. Tôi sẽ không biết nếu không theo dõi.
- Để hàng chục câu lệnh
console.logtrong các component React, và lint cứ thử lại liên tục.
Bài học rút ra
Những điều rút ra của tôi:
- Logic dashboard vẫn cần hoàn thiện: Devin đấu nối bộ đếm streak và thời gian nhưng để chúng không hoạt động. Các chỉ số backend nên có ít nhất một bài test tích hợp để UI “đường hạnh phúc” không bị merge sớm.
- Tốc độ dùng ACU tăng trong phiên dài: Sau ~8 ACU, phiên chậm thấy rõ. Phiên ngắn, giới hạn (< 5 ACU) giữ ngữ cảnh chặt và agent phản hồi nhanh.
- Devin sẽ “giúp” thay phụ thuộc: Nó thay Postgres bằng SQLite mà không hỏi. Hãy ghim các dịch vụ quan trọng trong prompt: “Không thay đổi hệ cơ sở dữ liệu; giữ Postgres.”
- Công việc thiết kế gây churn hot-reload: Mỗi lần Tailwind/Vite refresh đều tính thời gian agent. Có lẽ nên tạm dừng phiên trước khi sửa style hàng loạt, rồi đánh thức Devin khi dự án biên dịch sạch.
Nhiệm vụ đó dài và tốn kém hơn so với phần còn lại. Ít nhất Devin cũng biết mình sai ở đâu:

Chúng ta có một thứ khá đẹp, nhưng tốn thời gian và chưa hoàn chỉnh. Một số chỉ số dashboard bị hardcode—hai bài tập trong danh mục option? Ta có 10. Các chỉ số streak và thời gian cũng chưa nối với gì, và UI trên trang bài tập riêng lẻ khá tệ.
Hồi cứu Chi phí & Thời gian
Kết quả con số
Đây là tóm tắt mọi thứ diễn ra thế nào:
|
Giai đoạn |
ACU kế hoạch |
ACU thực tế |
Chênh lệch |
Ghi chú |
|
1 – Workspace & scaffold |
1 – 2 |
3,66 |
▲ ≈ 1,7 |
Vòng lặp thêm trên |
|
2 – Gói bài tập |
2 |
0,60 |
▼ 1,4 |
Di chuyển tệp đơn giản; không có cài đặt nặng |
|
3 – API & Prisma |
4 |
4,20 |
▲ 0,2 |
Vấn đề cấu hình (thiếu |
|
4 – Playground & test |
3 – 4 |
7,20 |
▲ ≈ 3,5 |
Chu kỳ hot-reload, kẹt merge-editor |
|
5 – Đồng bộ tiến độ |
2 – 3 |
2,70 |
▼ ≈ 0,3 |
Hook + truy vấn đơn giản |
|
6 – Đánh bóng UI & dashboard |
2 – 3 |
11,00 |
▲ ≈ 8 |
Cài lại, thay DB âm thầm, tải lại CSS lớn |
|
Tổng |
18 – 24 |
29,36 |
▲ ≈ 6 – 11 |
Vượt khoảng 35% so với ước tính ban đầu |
|
Chi phí: 29,36 ACU × $2,25 ≈ $66 |
||||
Thời gian tiết kiệm so với làm thủ công
Đây là ước tính thời gian tiết kiệm của tôi:
|
Nhiệm vụ |
Ước tính của người |
Devin (+ sửa lỗi) |
Chênh |
|
Dựng NestJS + GraphQL + Prisma |
4 giờ |
1 giờ (gồm sửa lỗi) |
−3 giờ |
|
Kết nối Sandpack + Vitest trong trình duyệt |
3 giờ |
1 giờ 20 phút |
−1 giờ 40 phút |
|
Thiết kế lại pastel & dashboard đầy đủ |
6 giờ |
2 giờ (nhưng vẫn chưa hoạt động đầy đủ) |
−4 giờ |
|
Tổng thời gian |
~13 giờ |
~4 giờ 20 phút |
-8 giờ 40 phút |
Điểm mấu chốt
Đây là những điều tôi khuyến nghị:
|
Chủ đề |
Nên làm gì |
Vì sao quan trọng |
|
Giữ phiên ngắn |
• Giới hạn mỗi lần chạy ở ≤ 5 ACU. • Chia nhỏ mục tiêu lớn thành ticket ngắn. |
Phiên > 8 ACU trở nên chậm, và tỷ lệ lỗi tăng ở ≈35%. Nhịp ngắn giúp phản hồi nhanh và rẻ hơn. |
|
Nhắc sớm, tạm dừng thường xuyên |
• Xem tab Timelapse; nếu Devin lặp, gõ “Tiếp tục” hoặc “Ngủ”. • Tạm dừng khi bạn sửa CSS/tài liệu hàng loạt, rồi đánh thức Devin khi mã biên dịch. |
Vòng lặp nhàn rỗi vẫn tính tiền; khối lượng hot-reload trong công việc thiết kế là tiêu hao ACU thuần túy. |
|
Xem cấu hình là việc thủ công |
• Tự di chuyển/đổi tên cây tệp lớn (kéo-thả tốt hơn script 0,8 ACU). • Sửa lỗi package lần đầu thủ công, retry là “hố” ACU. |
I/O tệp và cài đặt lặp lại chiếm ~30% credit lãng phí. |
|
Lint & type-check cục bộ |
• Luôn chạy script kiểm thử (trong trường hợp của chúng ta, lint và typecheck) trước khi merge. • Thêm các lệnh này vào CI (sẽ bàn trong hướng dẫn tới!). |
Devin sẽ tuyên bố thành công dù pipeline thất bại. |
|
Ghim công nghệ trọng yếu |
• Nêu rõ những gì không được thay: “Giữ Postgres, không đăng nhập, giữ Tailwind.” • Liệt kê biến môi trường bắt buộc trong |
Devin sẽ “giúp” đổi Postgres sang SQLite hoặc thêm runner test mới nếu không bị cấm. |
|
Tự xử lý secrets |
• Loại tệp • Lên kế hoạch bước secret-manager cho các hướng dẫn sau. |
Devin không nhất thiết phân biệt được thông tin giả với thật. |
|
Xử lý kẹt merge-editor |
• Nhảy vào hỗ trợ các merge commit và thoát tiến trình. |
Kẹt Vim lãng phí phút và ACU. |
|
Xóa mã chết sớm |
• Sau khi di chuyển, |
Tệp dư khiến agent bối rối và tăng thời gian build. |
|
Thêm unit test cho logic mới |
• Bộ đếm streak, hẹn giờ hay chỉ số cần test backend; đừng chỉ tin UI. Cứ bình tĩnh, ta sẽ bàn ở hướng dẫn tiếp theo. |
Devin đấu nối dashboard nhưng để bộ đếm không hoạt động cho đến khi test bộc lộ lỗ hổng. |
|
Nói điều bạn muốn và điều bạn không muốn |
• Phủ định rõ ràng (“Chưa cần auth”) để tránh nới phạm vi. • Rà soát kế hoạch Devin đề xuất và lược bớt phần thừa. |
Agent thích “vượt chỉ tiêu”, tốt cho demo, không tốt cho ngân sách. |
Tiếp theo là gì?
Giờ ta đã có:
- Playground màu pastel chạy test fp-ts ngay trong trình duyệt
- API NestJS + PostgreSQL ghi nhớ tiến độ chỉ với UUID
- Dashboard tiến độ tạo cảm giác thú vị
Trong hướng dẫn tiếp theo, chúng ta sẽ chuyển trọng tâm từ tính năng sang quy trình và cộng tác với:
- Kiểm thử liên tục: Thêm bộ Jest và Playwright, rồi để Devin giữ cả hai “xanh” với mỗi PR.
- Pipeline CI/CD: Tạo GitHub Actions build ứng dụng web và API và chạy test trong Chrome headless.
- Tích hợp nhóm: Kết nối Devin với Jira để cập nhật ticket, đẩy tóm tắt build lên Slack, và thử tính năng Wiki mới trong sản phẩm của Devin cho tài liệu nhẹ.
Nếu bạn sẵn sàng tiếp tục, bấm vào mục thứ ba dưới đây để đến hướng dẫn tiếp theo:
- Thiết lập và Pull Request đầu tiên (Phần 1)
- Giao một Vertical Slice với Devin (Phần 2)
- Tích hợp, Kiểm thử và CI/CD (Phần 3)
- Bảo mật, Triển khai, Vận hành (Phần 4)

Tôi là một trưởng nhóm kỹ thuật định hướng sản phẩm, chuyên giúp các startup giai đoạn đầu phát triển từ nguyên mẫu đầu tiên đến khi đạt được sự phù hợp sản phẩm - thị trường và xa hơn nữa. Tôi luôn tò mò về cách con người sử dụng công nghệ, và tôi thích làm việc sát sao với nhà sáng lập và các nhóm liên chức năng để biến những ý tưởng táo bạo thành hiện thực. Khi không xây dựng sản phẩm, tôi tìm cảm hứng ở những miền đất mới hoặc xả căng thẳng tại phòng tập yoga.