FDE PulseViệc làm FDE đang mở 432Mới trong 7 ngày 28Công ty đang tuyển 42Nhận làm từ xa 24%Lương trung vị (Mỹ) $216kTuyển nhiều nhất Databricks 125
EN

Tờ báo của nghề Forward Deployed Engineer

Bách khoa

Phỏng vấn FDSE ở Palantir: tự luyện vòng re-engineering và vòng learning

Hai vòng này không chấm việc bạn tìm ra lỗi nhanh đến đâu. Chúng chấm cách bạn lần ra lỗi và cách bạn học một thứ mới trong khi có người đang quan sát.

Kỹ sư ngồi trước laptop hiển thị mã nguồn, tập trung đọc và gỡ lỗi trong một văn phòng sáng sủa.
Ảnh: Compagnons / Unsplash

Tóm tắt nhanh

  • Vòng re-engineering thường là một codebase dài 200–1.000 dòng cho ra kết quả sai. Lỗi nằm ở logic chứ không phải cú pháp, và người chấm nhìn vào việc bạn debug có hệ thống hay không.
  • Ứng viên mạnh xuất phát từ output sai rồi lần ngược về input. Đoán một chỗ, sửa thử, chạy lại là kiểu làm hay khiến người ta trượt.
  • Ở vòng learning, hãy đọc tài liệu cho kỹ, nói ra điều mình đang hiểu và đặt câu hỏi ở mức cao. Im lặng lâu dễ bị coi là đang bí.
Chia sẻLinkedInFacebookX
Đồ hoạDebug có hệ thống trong 60 phút
  1. 1Ghi output sai và output đúngVí dụ: B ra 180 trong khi đúng phải là 50, A ra 130 trong khi đúng phải là 70
  2. 2Đọc trọn khối codeĐọc từ trên xuống dưới trước khi sửa, vì lỗi dễ thấy chưa chắc đã là lỗi thật
  3. 3Lần ngược dòng dữ liệuĐi từ con số sai về input; độ lệch gấp đôi một giá trị gợi ý lỗi đảo dấu
  4. 4Nói ra giả thuyếtNói rõ chỗ sai, lý do nghi ngờ và cách kiểm tra trước khi động vào code
  5. 5Mỗi lần sửa một chỗ rồi chạy lạiĐể biết chắc thay đổi nào đã làm con số nào trở về đúng

Bạn được chấm ở việc đi đúng trình tự này, không phải ở việc tìm ra lỗi đầu tiên nhanh đến đâu.

Đồ hoạ: FDE Times

Bạn nhận một codebase dài từ 200 đến 1.000 dòng mà mình chưa đọc bao giờ. Nó đang cho ra kết quả sai và bạn có 60 phút trong CodePair để sửa. Lỗi có thể chỉ là một dấu trừ bị đảo thành dấu cộng.

Đó là bài re-engineering trong buổi onsite tuyển Forward Deployed Software Engineer ở Palantir. Buổi onsite chọn tối đa bốn vòng trong năm loại: Decomposition, Re-engineering, Coding, Learning và System Design. Hướng dẫn này dành cho hai vòng re-engineering và learning.

Hai vòng này đáng luyện kỹ vì chúng rất gần với công việc thật. Re-engineering là làm việc với một hệ thống có sẵn: hiểu nó, phê bình nó, rồi mở rộng hoặc sửa nó, tức là mô phỏng khá sát việc FDE phải làm với hệ thống legacy của khách hàng.

Còn vòng learning đưa cho bạn một công cụ hay API lạ và yêu cầu dùng được ngay. Đó cũng là tình huống quen thuộc khi bạn phải làm việc với công cụ mà khách hàng đang dùng.

Chấm quá trình, không chấm tốc độ

Hướng dẫn của Aced/Exponent nói rõ người chấm tập trung vào việc quá trình debug của bạn có hệ thống hay không, chứ không phải bạn phát hiện lỗi đầu tiên nhanh đến đâu. Theo TechPrep, vòng này còn đo xem bạn cần bao lâu để nắm được một repository lộn xộn và bắt đầu làm ra việc có ích.

Vì thế, luyện bằng cách giải thật nhiều đề sẽ không đủ. Bạn cần luyện một quy trình và biến nó thành phản xạ. Phần dưới hướng dẫn bạn dựng một bộ bài tập nhỏ trên laptop để làm việc đó.

Chuẩn bị: Python 3, một trình soạn thảo, đồng hồ bấm giờ và một cách để ghi âm chính mình. Nếu có bạn đóng vai người phỏng vấn thì càng tốt.

Bước 1: Tự cài lỗi vào một đoạn code

Lỗi trong đề của Palantir là lỗi logic, ví dụ một dấu bị đảo, một giả định sai về thứ tự sắp xếp, hoặc một biến không được reset giữa các vòng lặp. Đoạn code dưới đây được dựng riêng để luyện tập, không phải đề thật. Nó cố ý chứa hai trong ba loại lỗi đó.

# ledger.py — bài tập tự dựng, có cài sẵn lỗi
def net_by_customer(txns):
    result = {}
    total = 0
    current = None
    for cust, kind, amount in sorted(txns):
        if cust != current:
            if current is not None:
                result[current] = total
            current = cust
        if kind == "refund":
            total += amount
        else:
            total += amount
    result[current] = total
    return result

txns = [("A", "sale", 100), ("A", "refund", 30), ("B", "sale", 50)]
print(net_by_customer(txns))

Chạy python3 ledger.py. Kết quả đúng phải là A bằng 70 và B bằng 50. Thực tế nó in ra {'A': 130, 'B': 180}. Kiểm tra: nếu bạn thấy đúng hai con số này thì bài tập đã sẵn sàng.

Bước 2: Đi ngược từ output sai về input

Ứng viên mạnh lần theo dòng dữ liệu từ output ngược về input, còn đoán rồi thử là kiểu làm dẫn đến trượt. Hãy làm điều đó với con số sai rõ nhất trước.

B ra 180, trong khi khách B chỉ có đúng một giao dịch 50. Như vậy 130 thừa ra phải đến từ một nơi khác, và 130 lại chính là giá trị của A. Đi ngược lên, bạn thấy total mang nguyên số dư của A sang B vì không được reset về 0 khi đổi khách hàng.

Tiếp theo là A. A ra 130 thay vì 70, lệch 60, tức gấp đôi khoản refund 30. Độ lệch đúng bằng hai lần một giá trị là dấu hiệu quen thuộc của lỗi đảo dấu: đáng lẽ phải trừ 30 thì code lại cộng 30. Bạn có hai giả thuyết, cả hai đều được suy ra từ con số chứ không phải từ cảm giác.

Kiểm tra: sau khi sửa từng lỗi, chạy lại và xem con số nào đã đúng. Mỗi lần chỉ sửa một chỗ, để bạn biết chắc thay đổi nào gây ra kết quả nào.

Bước 3: Đọc hết khối code trước khi sửa

Aced/Exponent khuyên đọc trọn khối code từ trên xuống dưới trước khi chốt cách sửa, vì lỗi dễ thấy nhất chưa chắc là lỗi thật. Trong ledger.py, nhiều người nhìn thấy sorted(txns) liền nghi ngay phần sắp xếp. Thật ra ở đây sắp xếp theo khách hàng lại là điều kiện cần để vòng lặp gom nhóm đúng.

Để luyện riêng loại lỗi giả định thứ tự, hãy viết thêm một hàm lấy txns[0] làm giao dịch đầu tiên của khách, rồi đưa vào dữ liệu không theo thứ tự thời gian. Sau đó tự hỏi: code này đang giả định dữ liệu đầu vào trông như thế nào, và ai đảm bảo giả định đó đúng?

Bước 4: Nói ra từng giả thuyết

Trong lúc làm, hãy nói thành lời theo khuôn: “Output sai ở đâu. Mình nghi vì sao. Mình sẽ kiểm tra bằng cách nào.” Ghi âm lại cả 60 phút. Khi nghe lại, đếm xem có bao nhiêu lần bạn sửa code mà chưa nói ra được giả thuyết nào. Mỗi lần như thế là một lần bạn đang đoán.

Vòng learning: đọc tài liệu kỹ hơn bạn tưởng

Vòng learning đưa cho bạn một khái niệm hoặc một API nhỏ chưa quen và yêu cầu dựng được gì đó với nó. Lý do trượt phổ biến nhất ở vòng này, theo Leonstaff, là đọc lướt tài liệu rồi đoán hành vi của API.

Cách luyện: chọn một module trong thư viện chuẩn của ngôn ngữ bạn dùng mà bạn chưa động tới bao giờ. Cho mình 20 phút chỉ để đọc tài liệu, sau đó viết một script nhỏ có mục đích rõ ràng. Trước mỗi lần gọi hàm, hãy nói to kết quả bạn dự đoán, rồi chạy để kiểm chứng.

Dự đoán trước, chạy sau: thử với groupby

Đây là một lượt luyện mẫu với itertools.groupby của Python, giả sử bạn chưa dùng nó bao giờ. Nhiệm vụ tự đặt: đếm số giao dịch của mỗi khách.

from itertools import groupby
custs = ["A", "B", "A"]
print([(k, len(list(g))) for k, g in groupby(custs)])

Người đọc lướt chỉ thấy cái tên “group by” và sẽ nói to dự đoán kiểu SQL: [('A', 2), ('B', 1)]. Chạy thử, bạn nhận được [('A', 1), ('B', 1), ('A', 1)]. Dự đoán sai, và đó chính là lúc mô hình tư duy của bạn cần được sửa.

Quay lại tài liệu, bạn sẽ thấy groupby chỉ gom những phần tử liên tiếp có cùng khóa, nên phải sắp xếp trước. Đổi thành groupby(sorted(custs)) thì ra [('A', 2), ('B', 1)]. Đây cũng chính là lý do sorted(txns) trong ledger.py không phải là lỗi.

Kiểm tra sau lượt luyện: bạn ghi lại được ít nhất một chỗ mà dự đoán của mình lệch với tài liệu, và giải thích được vì sao. Trong phòng phỏng vấn, chỉ cần nói một câu như “Mình tưởng nó gom toàn bộ, hóa ra chỉ gom phần tử liền kề” là người phỏng vấn đã thấy được bạn học như thế nào.

Hỏi ít, nhưng hỏi đúng tầm

Hãy kể lại cách bạn đang hiểu vấn đề để người phỏng vấn có thể chỉnh lại mô hình tư duy của bạn trước khi bạn chọn hướng làm. Nhưng hỏi quá nhiều câu chi tiết lại dễ khiến bạn trông như cần được cầm tay chỉ việc.

Hãy so sánh hai câu sau. “Hàm này trả về list hay dict?” là câu bạn tự tra được. “Mình hiểu API này xử lý theo lô, nếu sai thì mình sẽ đổi cách thiết kế” là câu cho người phỏng vấn thấy bạn đang suy nghĩ ở mức nào.

Những lúc im lặng lâu dễ bị hiểu là bạn đang bí, kể cả khi thực ra bạn đang suy nghĩ. Nếu cần im lặng để đọc, hãy báo trước: “Cho mình hai phút đọc phần mô tả xác thực.”

Những lỗi hay gặp

Lỗi đầu tiên là sửa luôn chỗ đầu tiên trông có vẻ sai rồi chạy lại để xem sao. Lỗi thứ hai là sửa nhiều chỗ cùng lúc, nên khi kết quả đúng bạn cũng không giải thích được vì sao.

Lỗi thứ ba, ở vòng learning, là tự lấp chỗ trống trong tài liệu bằng trí nhớ về một thư viện khác trông na ná, đúng như cái bẫy SQL với groupby.

Kỹ năng này dùng ở đâu tại site khách hàng

Thử hình dung bạn mới đến chỗ khách hàng và họ báo một bảng tổng hợp đang lệch số. Pipeline do người khác viết từ nhiều năm trước, còn bạn chưa có ai để hỏi. Cách làm vẫn y như với ledger.py: lấy một bản ghi sai cụ thể, đo độ lệch, lần ngược từng bước biến đổi, và nói rõ giả thuyết với khách trước khi sửa.

Khi viết CV, đừng chỉ ghi “debug hệ thống legacy”. Hãy viết theo cấu trúc: output sai trông ra sao, bạn khoanh vùng nó bằng cách nào, và đã sửa gì. Khi đọc mô tả công việc, những cụm như “existing systems” hay “unfamiliar tools” cho biết vị trí đó cần đúng hai kỹ năng mà bài này luyện.

Người chấm ở Palantir không cho điểm việc bạn bắt được lỗi đầu tiên nhanh đến đâu, mà cho điểm cách bạn đi tìm nó. Cách tìm lỗi có hệ thống ấy cũng chính là thứ bạn cần mang theo khi đứng trước hệ thống của khách hàng.

Bài này có hữu ích không?

Dùng cùng trợ lý AIHỏi Claude ↗Hỏi ChatGPT ↗
5 nguồn
Đọc tiếp trên lộ trình · Chặng 7: Dẫn dắtAi đã đồng ý cho agent làm vậy? Lập RAID log và decision log có cột người duyệtKhi agent làm điều không ai mong muốn, phòng họp sẽ không hỏi về model, mà hỏi tên người đã gật đầu.