Skip to content
DevRecall
← Roadmap
29

Engineering Practices & Leadership

drafted

Git workflow, code review, tech debt, estimation, design doc/RFC/ADR, mentoring, làm việc với PO/QA/Design trong team phân tán, on-call và deprecation.

0/45 rated · mastery 0%

Bài học

12 bài · ~180 phút đọc. Học theo thứ tự, rồi làm câu hỏi.
  1. 01~17 phút· 3 câuverify

    Lịch sử Git: merge, rebase, squash và commit message

    Commit, ref và DAG; merge vs rebase và golden rule; ba cách merge PR (squash, rebase, merge commit) ảnh hưởng bisect/revert ra sao; interactive rebase với fixup/autosquash; Conventional Commits và cách đọc một lịch sử bẩn.

  2. 02~16 phút· 4 câuverify

    Cứu hộ Git: reflog, reset, force push và bisect

    reset --soft/--mixed/--hard làm gì với con trỏ và working tree, reflog cứu commit 'đã mất' ra sao, --force vs --force-with-lease (và vì sao cần --force-if-includes), khôi phục main bị force push, và git bisect run với exit 125, --first-parent trên 400 commit.

  3. 03~14 phút· 3 câuverify

    Branching strategy: trunk-based, GitFlow và hotfix

    Continuous integration thật sự là gì; trunk-based vs GitHub flow vs GitFlow và khi nào mỗi cái hợp; release branch và hotfix từ tag với cherry-pick -x về main; lộ trình chuyển team sang trunk-based; đo bằng bốn DORA metrics với script chạy trên git log.

  4. 04~14 phút· 4 câuverify

    Feature flags: tách deploy khỏi release

    Deploy vs release; bốn loại toggle (release, experiment, ops, permission) và tuổi thọ của chúng; cách đánh giá flag với targeting và % rollout sticky bằng hash; cache, last-known-good và độ trễ của kill switch; flag debt, linter hết hạn và các failure mode hay gặp trong production.

  5. 05~13 phút· 4 câuverify

    Pull request và code review

    Code review để làm gì; PR nhỏ và description tốt (what/why/how tested/risk); thứ tự review từ design tới style; review một diff thật với comment blocking vs nit (chạy đoạn code trên SQLite để chứng minh); đo và sửa tình trạng review mất ba ngày.

  6. 06~17 phút· 4 câuverify

    Feedback và bất đồng kỹ thuật

    Viết review feedback thẳng mà không làm nản (kể cả khác văn hoá) với Conventional Comments; gỡ một thread PR kéo dài 15 comment; review PR của người senior hơn khi thấy lỗi thiết kế; và disagree-and-commit với một quyết định kiến trúc đã công bố, kể cả khi nó sai sáu tháng sau.

  7. 07~16 phút· 5 câuverify

    Tech debt và refactor legacy an toàn

    Tech debt là gì (gốc, lãi), quadrant của Fowler, khi nào nhận nợ là đúng; hữu hình hoá và ưu tiên theo lãi suất bằng hotspot analysis trên git log; cơ chế trả nợ dưới áp lực feature; refactor module legacy không test bằng characterization test, strangler fig, branch by abstraction và dual-run.

  8. 08~14 phút· 3 câuverify

    Breakdown và estimation

    Chia một feature lớn theo vertical slice và spike có timebox; vì sao estimate luôn lệch (cone of uncertainty, planning fallacy, phân phối lệch phải); three-point, PERT và Monte Carlo chạy thật; nói estimate với PO bằng range + độ tự tin; và làm gì khi đi được nửa đường thì phát hiện việc sẽ dài gấp đôi.

  9. 09~14 phút· 4 câuverify

    Design doc, RFC và ADR

    Khi nào một quyết định cần viết ra; design doc/RFC (đề xuất trước khi build) khác ADR (bản ghi sau khi chốt) thế nào; template từng loại; quy trình review async có timebox và decision owner; vòng đời ADR (proposed → accepted → superseded) với tool chạy thật; đưa ADR vào team đang quyết trong chat; và ảnh hưởng hướng kỹ thuật khi không có quyền chính thức.

  10. 10~15 phút· 7 câuverify

    Làm việc với PO, QA, Design trong team phân tán

    Ai quyết cái gì giữa PO, dev, QA, designer; trình bày bug và ràng buộc kỹ thuật bằng impact có dữ liệu; three amigos và shift-left với QA; thương lượng với designer quanh mục tiêu UX và accessibility; async-first, decision log, handoff và overlap hours giữa các timezone (tính bằng script có DST); và khung STAR cho câu hỏi ownership end-to-end và làm việc phân tán.

  11. 11~14 phút· 3 câuverify

    On-call, postmortem và deprecation

    Vận hành on-call từ góc nhìn engineer: alert actionable (phân tích lịch sử page), runbook, severity, vai trò trong incident, mitigate trước root cause sau; 15 phút đầu của một page lúc 3 giờ sáng; blameless postmortem có action item được làm thật; và deprecate một API nội bộ với đo lường consumer, header Deprecation/Sunset, brownout chạy thật.

  12. 12~14 phút· 4 câuverify

    Mentoring, process và Definition of Done

    Mentor một mid-level lên senior bằng ownership tăng dần, review tư duy và sponsorship; mentoring vs coaching vs sponsorship; triết lý 'process vừa đủ' (chi phí, tự động hoá trước quy định, bỏ ceremony); Definition of Done khác acceptance criteria ra sao, DoD cho SaaS multi-tenant và một checker chạy trong CI; ảnh hưởng không cần chức danh.

Tóm tắt & cheat sheet của track

TL;DR

  • Ở level senior, interviewer đánh giá cách bạn làm việc với người và hệ thống, không chỉ code: bạn chia task thế nào, review ra sao, xử lý bất đồng, quản lý tech debt, viết design doc.
  • Git: hiểu trunk-based vs GitFlow, rebase vs merge, và công cụ cứu hộ (reflog, bisect, revert) — đủ để nói "tại sao team chọn cách này".
  • Code review là cơ chế chia sẻ kiến thức và giảm rủi ro, không phải gatekeeping; PR nhỏ, review nhanh, comment có mức độ (blocking vs nit).
  • Estimation là giao tiếp về bất định: chia nhỏ, nêu giả định và rủi ro, cập nhật sớm khi sai — không phải hứa một con số.
  • Quyết định kỹ thuật quan trọng → design doc/RFC trước khi làm, ADR ghi lại sau khi chốt; "disagree and commit" khi đã quyết.

Khái niệm cốt lõi

Khái niệmMột câuVí dụ ngắn
Trunk-based developmentMọi người merge vào main thường xuyên (≤1–2 ngày), branch ngắn, feature flag che phần chưa xongCheckout mới sau flag checkout_v2
GitFlowNhánh develop, release/*, hotfix/*, feature/* dài hơn; hợp với release theo đợtApp mobile phát hành 2 tuần một lần
Rebase vs mergeRebase viết lại lịch sử cho thẳng; merge giữ lịch sử thật với merge commitgit rebase main trên branch cá nhân trước khi mở PR
git bisectBinary search qua commit để tìm commit gây lỗi1.000 commit → ~10 bước
Feature flagTách deploy khỏi releaseBật cho 5% tenant trước
Tech debtChi phí tương lai do lựa chọn hiện tại; có loại cố ý và vô ýHard-code tỷ giá để kịp demo
Design doc / RFCTài liệu đề xuất trước khi build: vấn đề, phương án, trade-offRFC "Chuyển search sang Elasticsearch"
ADRBản ghi ngắn một quyết định kiến trúc: context, decision, consequencesADR-012: Dùng outbox cho event đơn hàng
Definition of DoneTiêu chí chung để coi một task là xongCode + test + review + docs + deployed + monitored
Blameless postmortemPhân tích sự cố tập trung vào hệ thống, không đổ lỗi cá nhân"Tại sao hệ thống cho phép deploy migration chưa test?"

Cơ chế hoạt động

Vòng đời một thay đổi (trunk-based)

Code review flow

Quyết định kỹ thuật

Trade-offs

Chủ đềLựa chọn ALựa chọn BKhi nào chọn
BranchingTrunk-based: integrate liên tục, ít merge conflict, cần CI + flag tốtGitFlow: kiểm soát release, nhiều nhánh sống lâu, merge hellWeb/SaaS deploy liên tục → trunk; release theo version/cần hỗ trợ nhiều version → GitFlow-ish
IntegrateRebase: lịch sử thẳng, dễ bisectMerge: giữ lịch sử thật, an toàn với branch chungRebase branch cá nhân; không rebase branch người khác đang dùng
Merge PRSquash: 1 commit/PR, main sạchMerge commit: giữ từng commitSquash cho PR nhỏ; giữ commit khi mỗi commit có ý nghĩa riêng
EstimationStory points: tương đối, team-levelTime-based: dễ hiểu với businessNói bằng range + độ tự tin, không một con số
Tech debtTrả dần (boy-scout, % capacity mỗi sprint)Dự án trả nợ riêngNợ lan tỏa → trả dần; nợ tập trung, rủi ro cao → dự án riêng có mục tiêu đo được
DocsDesign doc dài, review kỹADR ngắnQuyết định khó đảo ngược → doc; mọi quyết định đáng nhớ → ADR

Pitfalls

  • PR 1.500 dòng, description trống, "please review ASAP".
  • Review chỉ soi style (việc của linter) mà bỏ qua design/correctness; hoặc ngược lại dùng review để áp đặt sở thích cá nhân.
  • git push --force lên branch chung; rebase branch đã share.
  • Estimate một con số rồi im lặng tới deadline mới báo trễ.
  • Gọi mọi thứ là "tech debt" để xin viết lại — không nêu được tác động kinh doanh.
  • Bất đồng kéo dài trong comment PR thay vì gọi 15 phút.
  • Trong team phân tán: quyết định trong call không ghi lại; người ở timezone khác bị loại khỏi quyết định.
  • Deprecate API mà không có timeline, không đo ai còn dùng.

Cheat sheet

  • Git cứu hộ: git reflog (tìm lại commit mất) · git revert <sha> (undo trên branch chung) · git bisect start/bad/good/run · git push --force-with-lease thay --force.
  • PR tốt: < ~400 dòng thay đổi logic, một mục đích, description = what/why/how tested/risk, screenshots cho UI.
  • Comment tốt: nêu mức độ (blocking:, nit:, question:), giải thích why, đề xuất cụ thể.
  • Estimate: breakdown → spike cho phần chưa rõ → range (best/likely/worst) → nêu giả định → cập nhật sớm.
  • Tech debt: ghi vào backlog với tác động (thời gian mất/incident/rủi ro), ưu tiên theo "lãi suất".
  • Design doc: context, goals/non-goals, options + trade-offs, decision, rollout, rollback, open questions.
  • Bất đồng: data > opinion, hiểu lý do bên kia, đề xuất thử nghiệm nhỏ, escalate có văn bản, disagree & commit.
  • Distributed team: async-first, viết quyết định, overlap hours, demo/record, rõ owner.

Interview Questions

Showing 45 / 45

git bisect start
git bisect bad HEAD
git bisect good v2.3.0
git bisect run npx vitest run tests/checkout-total.test.ts
git bisect reset
Feature: Address Management
1. Spike: provider validate địa chỉ (timebox 1 ngày)
2. Migration: bảng addresses (expand) + index (tenant_id, user_id)
3. API: CRUD + default address, tenant-scoped, test cross-tenant
4. FE: list + form (flag address_v2)
5. Checkout đọc default address
6. Rollout theo tenant, monitor, dọn flag
*   a91f2c3 Merge branch 'main' into feature/checkout
|\
| * 77be0d1 fix
| * 4c1e9aa fix again
* | 2d0b8f1 Merge branch 'main' into feature/checkout
|\|
| * 9e3a712 wip
| * 18fd4c0 asdf
* | c0ffee1 Merge pull request #412 from feature/checkout-v2-final-FINAL
* | 5b6d2e9 revert "revert 'add voucher logic'"
git checkout feature/shift-management
git fetch origin
git reset --hard origin/feature/shift-management
# "the remote had the latest version, I just wanted to sync"
+ // TODO: temporary, remove after demo
+ const DISCOUNT_RATE = 0.15;
+
+ export async function applyDiscount(orderId) {
+   const order = await db.query(`SELECT * FROM orders WHERE id = ${orderId}`);
+   order.total = order.total - order.total * DISCOUNT_RATE;
+   await db.query(`UPDATE orders SET total = ${order.total} WHERE id = ${orderId}`);
+   return order
+ }