Kỹ năng là hành vi quan sát được
“Biết cloud”, “biết AI” hay “giao tiếp tốt” quá rộng để lập kế hoạch. Một kỹ năng có giá trị phải chuyển thành việc bạn làm được và bằng chứng người khác kiểm được: thiết kế API có idempotency, điều tra latency bằng trace, review diff AI tạo, viết ADR, hoặc dẫn một postmortem không đổ lỗi.
Danh sách dưới đây không xếp hạng tuyệt đối. Backend, mobile, embedded và data cần độ sâu khác nhau. Hãy chọn nền chung, rồi đào sâu theo vai trò mục tiêu. Mỗi quý chỉ nên có hai kỹ năng ưu tiên để đủ thời gian tạo sản phẩm thật.
Đừng học mười kỹ năng bằng mười chứng chỉ. Hãy dùng một dự án đủ thật để buộc chúng phối hợp: yêu cầu, code, test, dữ liệu, deploy, quan sát, bảo mật, tài liệu và phản hồi người dùng.
1. Giải quyết vấn đề và thuật toán
Bạn cần biến yêu cầu thành mô hình, nhận ràng buộc, chọn cấu trúc và chứng minh chi phí. Không phải ngày nào cũng viết Dijkstra, nhưng tư duy bất biến giúp tránh vòng lặp thừa, race logic và truy vấn đắt. Luyện bằng bài thuật toán lẫn tình huống hệ thống: cache key, batching, rate limit.
Bằng chứng tốt: bạn giải thích được từ vét cạn đến phương án, viết ca phá và nêu khi giải pháp không dùng được. “Đã giải 500 bài” chỉ là tín hiệu phụ nếu không tái dựng được.
2. Thành thạo một ngôn ngữ chính
Biết syntax chưa đủ. Hãy hiểu model bộ nhớ, exception, concurrency, package, profiling, công cụ build và thư viện chuẩn. Với Java cần biết collection và GC ở mức vai trò; với Python hiểu mutability, iterator, environment; với C++ hiểu ownership, lifetime và undefined behavior.
Tạo một service hoặc CLI được đóng gói, lint, test, benchmark. Khả năng đọc code người khác và sửa lỗi production quan trọng hơn trình diễn nhiều ngôn ngữ nông.
3. Dữ liệu và database
Mô hình quan hệ, index, transaction, isolation, migration và backup là nền của phần lớn sản phẩm. Biết một truy vấn chạy không đồng nghĩa biết nó an toàn ở tải thật. Hãy dùng EXPLAIN, đo cardinality, hiểu N+1, khóa và kế hoạch rollback schema.
NoSQL không thay SQL theo mốt. Chọn theo access pattern, nhất quán, kích thước và vận hành. Viết trade-off thành tài liệu giúp đội hiểu vì sao quyết định tồn tại.
4. Kiểm thử và chất lượng
Phân biệt unit, integration, contract, end-to-end và property test. Test tốt có oracle độc lập và đánh vào rủi ro, không chỉ tăng coverage. Biết static analysis, type checking, fuzzing và review. Khi lỗi lọt production, bổ sung lớp phòng vệ phù hợp thay vì chỉ thêm một test giống sự cố.
Một portfolio đáng tin có CI chạy tự động, test failure dễ đọc, fixture gọn và quy tắc không flaky. Người khác phải chạy được dự án mà không hỏi tác giả từng bước.
5. Hệ thống, mạng và vận hành
Hiểu process, thread, TCP/HTTP, DNS, timeout, retry, queue, cache và consistency. Lỗi phân tán thường đến từ partial failure, không phải mọi thành phần cùng chết. Retry thiếu idempotency có thể nhân đôi thanh toán; timeout thiếu budget tạo thác chờ.
Học observability bằng logs có cấu trúc, metrics và traces. Đặt SLI/SLO đơn giản, tạo alert theo tác động người dùng, và luyện rollback. “Chạy trên máy em” chưa phải hoàn thành.
6. Bảo mật và quyền riêng tư
Biết xác thực khác phân quyền, secret không nằm trong repo, input cần validation, dependency cần quản lý. Học OWASP cơ bản, threat modeling và least privilege. Khi dùng AI, không gửi dữ liệu hoặc code vượt chính sách; kiểm nguồn, license và lỗ hổng.
Bảo mật không phải bước cuối của chuyên gia khác. Developer tạo API và schema đang quyết định bề mặt tấn công hằng ngày.
7. Dùng AI như công cụ có kiểm chứng
Giao mục tiêu, ràng buộc và context tối thiểu; yêu cầu phương án trước code; review diff nhỏ; chạy test độc lập. Theo dõi tổng thời gian gồm sửa lại. Khảo sát Stack Overflow Developer Survey 2025 (mục AI, công bố năm 2025) cho thấy 84% người trả lời đang dùng hoặc dự định dùng công cụ AI trong quy trình phát triển, nhưng 66% gặp khó chịu lớn vì lời giải AI “gần đúng nhưng chưa đúng” và 45,2% thấy gỡ lỗi code do AI tạo tốn thời gian hơn (Stack Overflow 2025), nên kỹ năng xác minh quan trọng hơn prompt hoa mỹ.
Hãy duy trì năng lực không công cụ: tự phân tích một phần, đọc tài liệu gốc và debug. AI là đòn bẩy cho người có mô hình đúng; nó cũng khuếch đại giả định sai.
8. Giao tiếp viết và nói
Viết issue có expected/actual, RFC có trade-off, review giải thích rủi ro, status không che blocker. Nói ngắn gọn theo người nghe: PM cần tác động và lựa chọn; engineer cần hợp đồng và chi tiết; lãnh đạo cần rủi ro, thời gian và quyết định.
Google khuyên ứng viên chuẩn bị ví dụ cụ thể và luyện câu trả lời. Trong công việc, cùng nguyên tắc áp dụng cho demo, incident và đề xuất kỹ thuật. Giao tiếp tốt giảm rework.
9. Hợp tác, phản hồi và ownership
Ownership không có nghĩa làm hết một mình. Nó là làm rõ người chịu trách nhiệm, kéo đúng bên liên quan, báo rủi ro sớm và theo việc đến kết quả. Nhận feedback bằng cách hỏi ví dụ, tách ý khỏi bản ngã và thử một thay đổi đo được.
Khi bất đồng, viết tiêu chí quyết định và dữ liệu cần thu. Sau quyết định, commit vào hướng chung trừ khi có rủi ro đạo đức hoặc an toàn cần escalation.
10. Hiểu sản phẩm và học có chiến lược
Code chỉ có giá trị khi thay đổi kết quả người dùng. Hỏi ai dùng, pain nào, chỉ số nào, hành vi ngoài dự kiến nào. Một tối ưu kỹ thuật không chạm bottleneck sản phẩm có thể là lãng phí. Học theo vấn đề thật giúp kiến thức bám lâu hơn học danh sách xu hướng.
Mỗi tháng làm review: kỹ năng nào tạo tác động, lỗi nào lặp, công việc sắp tới đòi gì. Chọn tài liệu gốc và dự án, không gom khóa học. Phát triển nghề nghiệp là một vòng lặp: có bằng chứng, nhận phản hồi, rồi được giao phạm vi việc lớn hơn.
Bài thực hành: BFS và khả năng mô hình hóa
Trong lưới có S, T, tường #, mỗi bước đi bốn hướng cùng chi phí. BFS phù hợp vì mọi cạnh trọng số 1. Bất biến: khi một ô được lấy khỏi queue, khoảng cách đã là ngắn nhất; đánh dấu ngay lúc đưa vào để không xếp trùng.
Với lưới S..# / .#.T / ...., hãy ghi từng lớp khoảng cách. Nếu T bị tường cô lập, trả -1; nếu S cạnh T, trả 1; nếu thiếu T theo hợp đồng mẫu, trả -1. Bài nhỏ này cùng lúc luyện mô hình, code đa ngôn ngữ, test và giải thích.
#include <iostream>
#include <queue>
#include <string>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int h, w;
if (!(cin >> h >> w)) return 0;
vector<string> g(h);
for (auto& s : g) cin >> s;
queue<pair<int, int>> q;
vector<vector<int>> dist(h, vector<int>(w, -1));
pair<int, int> target{-1, -1};
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
if (g[i][j] == 'S') {
q.push({i, j});
dist[i][j] = 0;
}
if (g[i][j] == 'T') {
target = {i, j};
}
}
}
const int di[4] = {1, -1, 0, 0};
const int dj[4] = {0, 0, 1, -1};
while (!q.empty()) {
auto [i, j] = q.front();
q.pop();
for (int k = 0; k < 4; k++) {
int x = i + di[k], y = j + dj[k];
if (x >= 0 && x < h && y >= 0 && y < w &&
g[x][y] != '#' && dist[x][y] < 0) {
dist[x][y] = dist[i][j] + 1;
q.push({x, y});
}
}
}
if (target.first < 0) {
cout << -1 << '\n';
} else {
cout << dist[target.first][target.second] << '\n';
}
return 0;
}
import collections
import sys
def main() -> None:
lines = sys.stdin.read().splitlines()
if not lines:
return
it = iter(lines)
h, w = map(int, next(it).split())
grid = [next(it) for _ in range(h)]
q: collections.deque[tuple[int, int]] = collections.deque()
dist = [[-1] * w for _ in range(h)]
target = (-1, -1)
for i in range(h):
for j in range(w):
if grid[i][j] == "S":
q.append((i, j))
dist[i][j] = 0
if grid[i][j] == "T":
target = (i, j)
while q:
i, j = q.popleft()
for x, y in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if 0 <= x < h and 0 <= y < w and grid[x][y] != "#" and dist[x][y] < 0:
dist[x][y] = dist[i][j] + 1
q.append((x, y))
print(-1 if target == (-1, -1) else dist[target[0]][target[1]])
if __name__ == "__main__":
main()
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
if (!sc.hasNextInt()) return;
int h = sc.nextInt();
int w = sc.nextInt();
String[] g = new String[h];
int[][] dist = new int[h][w];
for (int[] row : dist) {
Arrays.fill(row, -1);
}
ArrayDeque<int[]> q = new ArrayDeque<>();
int[] target = {-1, -1};
for (int i = 0; i < h; i++) {
g[i] = sc.next();
for (int j = 0; j < w; j++) {
if (g[i].charAt(j) == 'S') {
q.add(new int[]{i, j});
dist[i][j] = 0;
}
if (g[i].charAt(j) == 'T') {
target = new int[]{i, j};
}
}
}
int[] di = {1, -1, 0, 0};
int[] dj = {0, 0, 1, -1};
while (!q.isEmpty()) {
int[] cur = q.remove();
for (int k = 0; k < 4; k++) {
int x = cur[0] + di[k];
int y = cur[1] + dj[k];
if (x >= 0 && x < h && y >= 0 && y < w &&
g[x].charAt(y) != '#' && dist[x][y] < 0) {
dist[x][y] = dist[cur[0]][cur[1]] + 1;
q.add(new int[]{x, y});
}
}
}
System.out.println(target[0] < 0 ? -1 : dist[target[0]][target[1]]);
}
}
| Kỹ năng | Bằng chứng trong bài BFS |
|---|---|
| mô hình hóa | lưới thành đồ thị cạnh trọng số 1 |
| độ đúng | lớp BFS tăng dần khoảng cách |
| chất lượng | ca không tới, thiếu T, S cạnh T |
| giao tiếp | nêu hợp đồng ký tự và chi phí O(hw) |
Kế hoạch 90 ngày
Ngày 1–30: chọn dự án, viết yêu cầu, schema, API, test nền và CI. Ngày 31–60: deploy, thêm auth, logging, metrics, xử lý lỗi; dùng AI với nhật ký lỗi. Ngày 61–90: đo bottleneck, threat model, viết ADR và nhờ một người review như dự án thật.
Mỗi tuần xuất một bằng chứng: benchmark, postmortem, tài liệu, PR đã review, demo hoặc phản hồi người dùng. Cuối kỳ, viết rõ quyết định nào bạn thay đổi sau dữ liệu. Đây là tín hiệu nghề nghiệp mạnh hơn danh sách công nghệ trên CV.
Lỗi phát triển nghề nghiệp thường gặp
- Học mọi framework mới nhưng không thành thạo toolchain nào.
- Chỉ luyện thuật toán, không build và vận hành sản phẩm.
- Chỉ build CRUD, không luyện phân tích và độ phức tạp.
- Dùng AI để hoàn thành nhưng không giữ bằng chứng hiểu code.
- Tránh viết tài liệu vì nghĩ code “tự giải thích”.
- Đợi chức danh mới rồi mới ownership, thay vì mở rộng phạm vi có kiểm soát.
Luyện ngay trên Big-O Coding
Luyện BFS trên ma trận rồi đi tiếp qua các cấu trúc nền trong Coding Interview 150.
Câu hỏi thường gặp
Junior nên ưu tiên kỹ năng nào trước?
Một ngôn ngữ, Git, debug, test, cấu trúc dữ liệu và giao tiếp công việc. Sau đó build một dự án chạy thật để lộ lỗ hổng tiếp theo.
Có cần học tất cả cloud provider?
Không. Hiểu khái niệm compute, network, storage, identity, observability trên một nền tảng rồi học cách chuyển, thay vì thuộc tên dịch vụ của ba nơi.
Kỹ năng mềm có đo được không?
Có thể quan sát qua chất lượng issue, review, quyết định, phản hồi và cách đội giảm rework. Hãy lưu ví dụ tác động thay vì tự ghi “giao tiếp tốt”.
Luyện LeetCode thực chiến theo pattern, giải bài trong 45 phút và mock interview cùng AI. 16 buổi online, lớp 7–12 học viên, chọn C++, Java hoặc Python.


