Dan Tech Academy
Sau bài này bạn sẽ
  • Clone repo TicTac, build và chơi được một ván trên Android
  • Làm việc trên branch cá nhân với checkpoint Git, và viết rules file pin đúng stack cho AI pair
Thời lượng16 phút
Độ khóBeginner

Clone TicTac, Git checkpoint và rules file cho AI

Clone repo TicTac, chạy nó trên Android, tạo branch cá nhân, và viết rules file pin đúng stack để AI không gợi ý code Android thuần.

Từ bài này trở đi bạn làm việc trên một app có thật: TicTac - game cờ ca-rô chạy trên Android và iOS, cùng một codebase Kotlin.

Bạn không gõ lại nó. Bạn mở nó ra, đọc đúng phần đang học, rồi sửa. Cách học đó gần với công việc thật hơn nhiều so với gõ lại từng dòng của một app đồ chơi.

Bài này lo ba việc để phần còn lại của khóa chạy trơn: lấy repo về, dựng lưới an toàn bằng Git, và đặt luật cho AI.

Lấy Repo Về Và Chạy Thử

Repo là private, mở cho bạn ngay sau khi mua khóa. Lời mời gửi tới email đăng ký GitHub của bạn.

bash
git clone https://github.com/dan-tech-academy/kotlin-tictac-101.git
cd kotlin-tictac-101

Chưa clone được? Lời mời có thể đang nằm trong hộp thư rác, hoặc chờ ở github.com/notifications. Kiểm hai chỗ đó trước. Quá 30 phút sau khi mua mà vẫn chưa thấy, liên hệ hỗ trợ kèm tên tài khoản GitHub của bạn.

Mở thư mục vừa clone bằng Android Studio, đợi Gradle sync xong, rồi build:

bash
./gradlew :androidApp:assembleDebug

Lần đầu mất vài phút. Kết thúc bằng BUILD SUCCESSFUL là máy bạn dựng được toàn bộ stack của khóa.

Cắm máy hoặc mở emulator, chọn run configuration androidApp trong IDE, nhấn Run. Chơi hết một ván - chọn cỡ bàn, chọn độ khó, đánh tới khi ra kết quả. Bạn vừa thấy đích đến của khóa học.

Có macOS thì mở thêm thư mục iosApp bằng Xcode và nhấn Run. Build phase của Xcode tự gọi Gradle để sinh framework từ code Kotlin chung. Không có macOS thì bỏ qua, mọi thứ còn lại y hệt.

Branch Cá Nhân, Không Đụng master

Mọi thay đổi của bạn nằm trên branch riêng. master giữ nguyên làm bản gốc để đối chiếu khi bạn sửa hỏng thứ gì đó.

bash
git switch -c hoc-tictac

Kiểm tra đang đứng đúng chỗ:

bash
git branch --show-current
# hoc-tictac

Đây là branch local trên máy bạn. Không push lên repo gốc - bạn không có quyền ghi, và không cần. Muốn có bản sao trên GitHub của riêng mình thì bấm Fork trên trang repo rồi thêm remote trỏ về fork đó.

Bốn Lệnh Git Cho Checkpoint

Git có hàng trăm lệnh. Trong khóa này bạn cần đúng bốn.

bash
git status                    # đang thay đổi những file nào
git add .                     # đánh dấu tất cả thay đổi để lưu
git commit -m "mô tả"         # lưu lại thành một checkpoint
git log --oneline             # xem danh sách checkpoint đã có

Tạo checkpoint đầu tiên ngay bây giờ, khi app còn chạy đúng:

bash
git commit --allow-empty -m "chore: mốc xuất phát, app chạy được"

Từ giờ, cứ mỗi lần app chạy đúng như bạn muốn, chạy hai dòng:

bash
git add .
git commit -m "feat: đổi màu ô đã đánh"

Một commit là một điểm quay về. Cứ 15-30 phút mà app còn chạy được thì commit. Lỗi thì sửa nhanh. Thứ ngốn thời gian là không biết nó xuất hiện từ lúc nào.

Khi mọi thứ hỏng

Đây là lệnh cứu mạng. Nó vứt bỏ mọi thay đổi chưa commit và đưa code về đúng checkpoint gần nhất:

bash
git restore .

Muốn quay về xa hơn, xem danh sách rồi chọn:

bash
git log --oneline
# a1b2c3d feat: đổi màu ô đã đánh
# e4f5g6h chore: mốc xuất phát, app chạy được

git restore --source e4f5g6h .

Cảnh báo: git restore . xóa hẳn phần code chưa commit. Chắc chắn bạn không vứt đi thứ mình cần.

Repo đã có sẵn .gitignore đúng cho KMP, nên git status của bạn sẽ chỉ hiện những file bạn thật sự sửa. Nếu nó hiện build/, .gradle/ hay local.properties, nghĩa là có gì đó bị thêm nhầm - chạy git rm -r --cached . rồi git add . để áp lại.

AI Pair: Đặt Luật Trước Khi Nhờ Vả

Bạn sẽ dùng AI trong khóa này - để giải thích code, để đọc thông báo lỗi, để sinh phần code lặp đi lặp lại. Nhưng có một vấn đề rất cụ thể với KMP:

Phần lớn dữ liệu huấn luyện của AI là code Android thuần. Hỏi "viết cho tôi một ViewModel", nó rất dễ trả về import android.content.Context, androidx.compose.ui.platform.LocalContext, hoặc AndroidViewModel. Những thứ đó không biên dịch được trong commonMain.

Nó cũng hay gợi ý những thư viện phổ biến mà repo này cố tình không dùng. Gợi ý sai loại đó tốn của bạn cả buổi, vì code trông rất hợp lý cho tới lúc build đỏ.

Cách chữa: viết luật ra file, đặt ở gốc repo, để công cụ AI đọc trước mỗi lần trả lời.

Tạo file AGENTS.md (hoặc CLAUDE.md, tùy công cụ bạn dùng - nhiều công cụ đọc cả hai) ở thư mục gốc:

markdown
# Luật của project

## Ngữ cảnh

Project Kotlin Multiplatform dùng Compose Multiplatform, chạy trên Android và iOS.
KHÔNG phải project Android thuần. Module chứa code là `:shared`.
Package gốc: `com.dantech.academy.tictac`.

## Phiên bản đã pin - không đề xuất bản khác

```
Kotlin                        2.4.10
Compose Multiplatform         1.11.1
Koin                          4.2.2
androidx-lifecycle            2.11.0-beta01
multiplatform-settings        1.3.0
kotlinx-serialization         1.11.0
kotlinx-collections-immutable 0.5.2
```

## Cấm dùng

- Room, SQLDelight, hay bất kỳ SQL nào. Project lưu dữ liệu bằng key-value.
- Navigation 3 hay bất kỳ thư viện điều hướng nào. Project tự quản màn hình.
- `androidContext()` của Koin. Không có Android Context trong `commonMain`.
- `android.*` trong `commonMain`.

## Bắt buộc

- Mặc định viết vào `shared/src/commonMain/kotlin/`.
- Giao diện: Compose Multiplatform + Material 3.
- Kiến trúc: MVVM. Model không biết ViewModel, ViewModel không biết Composable.
- Bất đồng bộ: coroutines và Flow. Không dùng callback.

## Khi trả lời

- Chỉ ra rõ đoạn code thuộc source set nào.
- Nếu buộc phải viết code riêng cho từng nền tảng, dùng expect/actual và nói rõ vì sao.
- Giải thích ngắn gọn trước khi đưa code, không viết lại cả file nếu chỉ đổi vài dòng.

Commit file này. Nó là một phần của project.

Ba câu hỏi tốt và một câu hỏi tệ

Câu hỏi tệ:

"Viết game cờ ca-rô cho tôi."

Bạn nhận về vài trăm dòng không đọc nổi, không biết sai chỗ nào khi nó không chạy.

Ba câu hỏi tốt:

"Giải thích dòng var count by remember { mutableStateOf(0) } này, từng phần một."

"Đoạn code này báo lỗi Unresolved reference: Context trong commonMain. Vì sao và sửa thế nào theo hướng multiplatform?"

"Đọc file shared/src/commonMain/kotlin/com/dantech/academy/tictac/game/Mark.kt và giải thích enum này dùng để làm gì."

Điểm chung: nhỏ, cụ thể, và bạn kiểm tra được kết quả. Nguyên tắc suốt khóa - không commit code mà bạn không giải thích được. Không hiểu thì hỏi tiếp cho đến khi hiểu, hoặc bỏ đoạn đó đi.

Key takeaway: commit là điểm quay về. Commit sớm, commit thường xuyên.

Đăng nhập