English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

khách
1 / ?
trở lại bài học

Đặt Tên Không Phải Là Tìm Kiếm

Bây giờ bạn biết bảy mô hình MOAD. Biết tên là quan trọng: nó cho phép bạn nhận ra một mô hình khi thấy nó. Nhưng nhận ra trong một bài học có kiểm soát khác với việc phát hiện trong một cơ sở mã bạn chưa bao giờ mở.

Một cơ sở mã không gắn nhãn các lỗi của nó. Một MOAD lắng đọng không đi kèm với nhận xét nói // O(N²) — fix this. Một đàn lạc không tuyên bố bản thân nó là cuộc đổ xô bỏ lỡ bộ đệm. Bạn tìm thấy chúng bằng cách đọc mã với một câu hỏi cụ thể trong đầu: cấu trúc dữ liệu nào nắm giữ các giá trị này, và những hoạt động nào chạy dựa trên nó bên trong một vòng lặp?

Phát hiện là một kỹ năng khác biệt với nhận ra. Nhận ra nói: vâng, mô hình đó là MOAD-0001. Phát hiện nói: hãy để tôi tìm tất cả các nơi trong cơ sở mã này nơi mô hình đó có thể tồn tại, cho dù tôi có thể thấy toàn bộ mã hay chỉ tên biểu tượng.

Seven MOADs: substrates, signatures, fixes

Lần Quét Đầu Tiên

Một lần quét đầu tiên sử dụng grep. Mỗi MOAD có một chất nền: một cấu trúc dữ liệu hoặc API mà sự hiện diện của nó, gần các hoạt động nhất định, là một tín hiệu đáng điều tra.

MOAD-0001 (Lắng đọng): List.contains trong một vòng lặp

# Signal: membership test on a list variable inside a loop
grep -rn '.contains(' src/ | grep -v HashSet | grep -v TreeSet
grep -rn 'visited =' src/ | grep -v set | grep -v Set

MOAD-0002 (Liên kết): cờ có thể thay đổi được chia sẻ trên các giai đoạn

# Signal: static mutable field written by one subsystem, read by another
grep -rn 'static ' src/ | grep -v final | grep -v class | grep -v void

MOAD-0003 (Bối cảnh bị rò rỉ): ThreadLocal trong một thực thi được ghi lại

# Signal: ThreadLocal.set() without guaranteed ThreadLocal.remove()
grep -rn 'ThreadLocal' src/
grep -rn 'ThreadLocal.set' src/ -l

MOAD-0004 (Bí mật được ghi lại): tiêu đề HTTP trong đầu ra nhật ký

# Signal: log call with headers variable near auth endpoints
grep -rn 'log.*header' src/
grep -rn 'Authorization' src/ --include='*.log'

MOAD-0005 (Đàn lạc): bỏ lỡ bộ đệm mà không có đồng bộ hóa

# Signal: cache.get() + null check + cache.put() without lock
grep -rn 'cache.get' src/ -A4 | grep 'cache.put'

Những mô hình này tạo ra ứng cử viên, không phải những lỗi được xác nhận. Mỗi ứng cử viên cần phân loại: đọc mã xung quanh, xác minh loại cấu trúc dữ liệu, xác nhận hoạt động chạy theo quy mô.

Chọn một MOAD từ MOAD-0001 đến MOAD-0005. Mô tả một bước phát hiện cụ thể mà bạn sẽ thực hiện trong một cơ sở mã bạn chưa bao giờ đọc trước đây: những gì bạn tìm kiếm, một kết quả tích cực trông như thế nào, & điều gì phân biệt một lỗi được xác nhận khỏi một dương tính giả.

Đọc Mã để Tìm Độ Phức Tạp

Grep tìm thấy ứng cử viên. Đọc xác nhận chúng. Khi bạn mở một tệp ứng cử viên, bạn đọc với một câu hỏi: chi phí của hoạt động này có tăng lên theo kích thước đầu vào không?

Đối với MOAD-0001, giao thức xác nhận:

1. Tìm vòng lặp bên ngoài. Điều gì ràng buộc số lần lặp của nó?
2. Tìm hoạt động bên trong (.contains, .indexOf, 'in'). Cấu trúc dữ liệu nào nó chạy dựa trên?
3. Cấu trúc dữ liệu đó có phát triển với cùng một đầu vào mà chạy vòng lặp bên ngoài không?
4. Nếu có: chi phí là O(N²) trong đó N = kích thước đầu vào. Lỗi được xác nhận.
5. Nếu không: cấu trúc bên trong bị giới hạn (cấu hình, enum, hằng số nhỏ). Dương tính giả.

Một phép duyệt đồ thị truy cập N nút, kiểm tra danh sách visited ở mỗi bước: cả vòng lặp và cấu trúc dữ liệu bên trong đều phát triển với N. Được xác nhận.

Một trình xử lý yêu cầu kiểm tra danh sách cho phép 5 IP quản trị viên: danh sách cho phép không bao giờ phát triển với khối lượng yêu cầu. Dương tính giả.

Giao thức tương tự áp dụng cho mỗi MOAD: xác định trình điều khiển bên ngoài, xác định cấu trúc bên trong, hỏi liệu cả hai có tỷ lệ lên với nhau không.

Điểm Tăng Đột Ngột: Ưu Tiên Những Phát Hiện Của Bạn

Không phải tất cả các lỗi được xác nhận đều đáng bổ sung ngay lập tức. Một MOAD trong một thư viện có 10.000 phụ thuộc thượng nguồn có điểm tăng đột ngột cao hơn MOAD tương tự trong một công cụ nội bộ riêng.

Điểm tăng đột ngột = tăng tốc × bức vào. Tăng tốc: mã chạy nhanh hơn bao nhiêu với bước độ phức tạp điển hình? Bức vào: có bao nhiêu gói hoặc dịch vụ thượng nguồn sẽ kế thừa bản sửa một cách tự động khi thượng nguồn hợp nhất?

Một MOAD-0001 được xác nhận trong trình phân giải phụ thuộc Apache Maven, chạy trên đồ thị của 50.000 nút, với 1.000+ plugin Maven thượng nguồn kế thừa các thay đổi tự động: điểm tăng đột ngột rất cao. Bản sửa này thuộc về phía trước hàng đợi của bạn.

Một MOAD-0001 được xác nhận trong một công cụ CLI của một người dùng với không có phụ thuộc: điểm tăng đột ngột gần bằng không. Đáng sửa, nhưng không khẩn cấp.

Nút anh chăm sóc so với nút tham lam. Một nút có độ giữa cao & tăng tốc cao là anh chăm sóc: nó xử lý luồng quan trọng & sẽ làm sạch các hàng đợi thượng nguồn khi được bỏ chặn. Chỉ bổ sung nó sau khi xác nhận dung lượng thượng nguồn. Một nút có mức độ ngoài cao & tăng tốc thấp là tham lam: nó tiêu thụ tất cả những gì được cung cấp cho nó và cảm thấy không đau đớn. Bổ sung một anh chăm sóc mà không chuẩn bị dung lượng thượng nguồn tạo ra MOAD-0005 (đàn lạc) ở quy mô cơ sở hạ tầng.

Factory DAG: workaholic & glutton node patterns

Bạn đã xác nhận MOAD-0001 ở hai nơi: (A) một trình phân giải phụ thuộc trong một công cụ xây dựng với 200.000 dự án hoạt động phụ thuộc vào nó, chạy trên đồ thị của cây phụ thuộc 10.000 nút; (B) một tiện ích đồ thị trong một đường ống dữ liệu nội bộ tại một công ty duy nhất, chạy trên đồ thị của 50 nút. So sánh điểm tăng đột ngột của chúng. Bạn sửa cái nào trước, và bạn thực hiện những bước nào trước khi tiết lộ?

Quét để Hợp Nhất: Một Quy Trình MOAD

Một lỗi được xác nhận với điểm tăng đột ngột cao di chuyển qua một quy trình. Mỗi giai đoạn tạo ra một tạo tác. Không có giai đoạn nào là tùy chọn.

scan    → candidate list (grep output, static analysis results)
ticket  → defect description (MOAD number, location, complexity analysis)
patch   → code change (data structure swap, primitive adoption)
test    → unit test (O(1) proof: time the fix at N=100 and N=10,000)
UNDF    → public disclosure post (undefect.com, public domain)
disclose → CVE or CWE reference if security-relevant
PR      → upstream pull request with patch + test + UNDF link
merge   → maintainer acceptance; fix propagates via version bump

Mỗi tạo tác cung cấp cho giai đoạn tiếp theo. Một bản vá mà không có bài kiểm tra không thể được xác minh. Một bài kiểm tra mà không có tiết lộ không thể lan truyền đến các trường hợp khác của cùng một mô hình. Một tiết lộ mà không có PR thượng nguồn làm stranded bản sửa trong một fork.

Một bài MOAD (UNDF) là giai đoạn mà hầu hết các kỹ sư bỏ qua. Họ sửa lỗi, gửi PR, và xem xét bản thân họ đã hoàn thành. Nhưng một bản sửa mà không có bài viết được đặt tên có nghĩa là mỗi kỹ sư tương lai gặp phải cùng một mô hình phải khám phá lại vấn đề và bản sửa một cách độc lập. Một bài MOAD đóng vòng lặp kiến thức: nó đặt tên cho mô hình, cho thấy phương pháp phát hiện, & liên kết đến bản vá. Các nhà nghiên cứu tương lai tìm thấy bản sửa bằng cách tìm kiếm tên mô hình.

Bổ sung hành tinh theo quy mô. Một bản sửa MOAD-0001 trong một thư viện được sử dụng rộng rãi lan truyền đến mỗi dự án nhập nó. Một bài MOAD đảm bảo rằng các kỹ sư trong các dự án sẽ không bao giờ nâng cấp thư viện đó vẫn học bản sửa. Cả hai đường dẫn chạy song song.

Viết Một Vé Lỗi

Một vé lỗi tốt trả lời năm câu hỏi:

1. Ở đâu: tệp chính xác, lớp, hàm, và phạm vi dòng
2. Cái gì: loại cấu trúc dữ liệu và hoạt động dựa trên nó
3. Tại sao: phân tích độ phức tạp (O(N²) hoặc tệ hơn, với N được định nghĩa)
4. Tác động: những đầu vào nào kích hoạt hành vi trường hợp tồi tệ nhất, và ở quy mô nào
5. Sửa: cấu trúc dữ liệu hoặc nguyên thủy để thay thế

Một vé trả lời tất cả năm cái là tự chứa: một người bảo trì chưa bao giờ đọc phân tích của bạn có thể tái tạo phát hiện của bạn và xác minh bản sửa của bạn. Những chiếc vé bỏ qua (3) hoặc (4) yêu cầu người bảo trì lặp lại phân tích độ phức tạp của bạn trước khi họ có thể hợp nhất. Sự ma sát đó làm giảm xác suất hợp nhất.

Độ tin cậy tăng lên. Một PR đầu tiên bao gồm một vé rõ ràng, một bản vá được nhắm mục tiêu tốt, & một bài kiểm tra điểm chuẩn được hợp nhất. Một PR thứ hai từ cùng một tác giả được xem xét với ma sát ít hơn. Một PR thứ ba được xem xét bởi người bảo trì đã hợp nhất hai cái đầu tiên. Danh tiếng trong nguồn mở là một sổ cái của các tạo tác: mỗi bản vá được chấp nhận kiếm được sự tin tưởng cho cái tiếp theo.

Viết một vé lỗi tối thiểu cho một MOAD-0001 mà bạn mong đợi tìm thấy trong một thư viện đồ thị. Bao gồm: (1) một tên tệp/hàm có thể xảy ra, (2) cấu trúc dữ liệu & hoạt động, (3) một câu lệnh độ phức tạp, (4) một kịch bản tác động điển hình, (5) bản sửa.

Đọc Một Ứng Cử Viên Thực

Đây là một ứng cử viên MOAD-0001 thực sự trong Python. Đọc nó và hoàn thành giao thức phân loại.

class DependencyResolver:
    def resolve(self, package, resolved=None, seen=None):
        if resolved is None:
            resolved = []
        if seen is None:
            seen = []
        if package in seen:
            return
        seen.append(package)
        for dep in self.registry.get_dependencies(package):
            self.resolve(dep, resolved, seen)
        resolved.append(package)
        return resolved

Các câu hỏi phân loại:

1. Cấu trúc dữ liệu `seen` là gì?
2. Hoạt động nào chạy dựa trên nó ở dòng 6?
3. `seen` có phát triển theo kích thước đầu vào không?
4. Vòng lặp chạy các cuộc gọi đệ quy có phát triển theo kích thước đầu vào không?
5. Đây là một MOAD-0001 được xác nhận hay một dương tính giả?
Làm việc thông qua năm câu hỏi phân loại cho mã này. Sau đó viết bản sửa một dòng và giải thích tại sao nó không thay đổi kết quả đầu ra của hàm.

Bản Vá Của Bạn

Một lỗi được xác nhận với điểm tăng đột ngột cao cần một bản vá hoàn chỉnh: bản sửa mã, một bài kiểm tra chứng minh sự cải thiện, & tóm tắt bài MOAD.

Bài kiểm tra phải là bài kiểm tra hiệu suất, không phải bài kiểm tra tính đúng đắn. Một bài kiểm tra tính đúng đắn vượt qua trước và sau bản sửa — đó là điểm; đầu ra không thay đổi. Một bài kiểm tra hiệu suất ở hai kích thước đầu vào chứng minh sự cải thiện:

import time

def build_graph(n):
    # n packages, each depending on the previous one
    return {f'pkg{i}': [f'pkg{i-1}'] if i > 0 else [] for i in range(n)}

for n in [100, 1000, 5000]:
    registry = build_graph(n)
    resolver = DependencyResolver(registry)
    start = time.perf_counter()
    resolver.resolve(f'pkg{n-1}')
    elapsed = time.perf_counter() - start
    print(f'n={n}: {elapsed:.4f}s')

Trước bản sửa, thời gian trôi qua phát triển theo bình phương với n. Sau bản sửa, nó phát triển tuyến tính. In cả hai và bao gồm các con số trong mô tả PR của bạn.

Tóm tắt bài MOAD bao gồm: tên mô hình, chất nền (trình phân giải phụ thuộc Python), phương pháp phát hiện (grep để in seen trong đó seen bắt đầu dưới dạng []), bản sửa, & một liên kết đến PR của bạn. Bài đăng được đăng trên undefect.com dưới dạng miền công cộng. Các kỹ sư tương lai tìm kiếm 'tìm kiếm danh sách thành viên Python trong vòng lặp chậm' sẽ tìm thấy nó.

Bạn đã xác nhận & bổ sung MOAD-0001 trong một công cụ đóng gói Python phổ biến. Trước khi bạn mở PR, ba điều nào bạn bao gồm trong mô tả PR, và tại sao mỗi điều lại quan trọng đối với người bảo trì?