Đường dẫn để đánh máy 4 triệu dòng mã Python. Phần 3

Chúng tôi trình bày cho các bạn chú ý phần thứ ba của bản dịch tài liệu về đường dẫn mà Dropbox đã đi khi triển khai hệ thống kiểm tra loại cho mã Python.

Đường dẫn để đánh máy 4 triệu dòng mã Python. Phần 3

→ Các phần trước: 1 и 2

Đạt 4 triệu dòng code gõ được

Một thách thức lớn khác (và mối quan tâm phổ biến thứ hai trong số những người được khảo sát nội bộ) là việc tăng số lượng mã được kiểm tra loại trong Dropbox. Chúng tôi đã thử một số cách tiếp cận để giải quyết vấn đề này, từ việc tăng kích thước của cơ sở mã được gõ một cách tự nhiên đến việc tập trung nỗ lực của nhóm mypy vào suy luận kiểu tự động tĩnh và động. Cuối cùng, có vẻ như không có chiến lược chiến thắng đơn giản nào cả, nhưng chúng tôi đã có thể đạt được sự tăng trưởng nhanh chóng về số lượng mã chú thích bằng cách kết hợp nhiều cách tiếp cận.

Kết quả là kho Python lớn nhất của chúng tôi (có mã phụ trợ) có gần 4 triệu dòng mã chú thích. Công việc gõ mã tĩnh được hoàn thành trong khoảng ba năm. Mypy hiện hỗ trợ nhiều loại báo cáo phạm vi mã khác nhau giúp theo dõi tiến trình nhập dễ dàng hơn. Đặc biệt, chúng tôi có thể tạo các báo cáo về mã có sự mơ hồ về loại, chẳng hạn như việc sử dụng rõ ràng một loại Any trong các chú thích không thể xác minh được hoặc với những thứ như nhập thư viện của bên thứ ba không có chú thích loại. Là một phần của dự án nhằm cải thiện độ chính xác của việc kiểm tra loại trong Dropbox, chúng tôi đã góp phần cải thiện định nghĩa loại (còn gọi là tệp sơ khai) cho một số thư viện nguồn mở phổ biến trong kho lưu trữ Python tập trung đánh máy.

Chúng tôi đã triển khai (và tiêu chuẩn hóa trong các PEP tiếp theo) các tính năng mới của hệ thống kiểu cho phép các kiểu chính xác hơn cho một số mẫu Python cụ thể. Một ví dụ đáng chú ý về điều này là TypeDict, cung cấp các kiểu cho các từ điển giống JSON có một bộ khóa chuỗi cố định, mỗi khóa có một giá trị thuộc loại riêng. Chúng tôi sẽ tiếp tục mở rộng hệ thống loại. Bước tiếp theo của chúng tôi có thể sẽ là cải thiện khả năng hỗ trợ về số của Python.

Đường dẫn để đánh máy 4 triệu dòng mã Python. Phần 3
Số dòng mã chú thích: máy chủ

Đường dẫn để đánh máy 4 triệu dòng mã Python. Phần 3
Số dòng mã chú thích: client

Đường dẫn để đánh máy 4 triệu dòng mã Python. Phần 3
Tổng số dòng mã chú thích

Dưới đây là tổng quan về các tính năng chính của những việc chúng tôi đã làm để tăng số lượng mã chú thích trong Dropbox:

Chú thích nghiêm ngặt. Chúng tôi dần dần nâng cao yêu cầu về mức độ nghiêm ngặt của chú thích mã mới. Chúng tôi bắt đầu với các mẹo nói dối gợi ý thêm chú thích vào các tệp đã có một số chú thích. Hiện tại, chúng tôi yêu cầu chú thích kiểu trong các tệp Python mới và trong hầu hết các tệp hiện có.

Đánh máy báo cáo. Chúng tôi gửi cho các nhóm báo cáo hàng tuần về mức độ nhập mã của họ và đưa ra lời khuyên về những gì cần chú thích trước.

Sự phổ biến của mypy. Chúng tôi nói về mypy tại các sự kiện và nói chuyện với các nhóm để giúp họ bắt đầu với chú thích loại.

Thăm dò ý kiến. Chúng tôi tiến hành khảo sát người dùng định kỳ để xác định các vấn đề lớn. Chúng tôi sẵn sàng tiến khá xa trong việc giải quyết những vấn đề này (thậm chí tạo ra một ngôn ngữ mới để tăng tốc mypy!).

Hiệu suất. Chúng tôi đã cải thiện đáng kể hiệu suất của mypy bằng cách sử dụng daemon và mypyc. Điều này được thực hiện để giải quyết những bất tiện phát sinh trong quá trình chú thích và để có thể làm việc với số lượng lớn mã.

Tích hợp với các biên tập viên. Chúng tôi đã xây dựng các công cụ hỗ trợ chạy mypy trong các trình soạn thảo phổ biến trên Dropbox. Điều này bao gồm PyCharm, Vim và VS Code. Điều này giúp đơn giản hóa đáng kể quá trình chú thích mã và kiểm tra chức năng của nó. Những loại hành động này phổ biến khi chú thích mã hiện có.

Phân tích tĩnh. Chúng tôi đã tạo một công cụ để suy ra chữ ký hàm bằng các công cụ phân tích tĩnh. Công cụ này chỉ có thể hoạt động trong các tình huống tương đối đơn giản nhưng nó đã giúp chúng tôi tăng mức độ bao phủ loại mã mà không cần nỗ lực nhiều.

Hỗ trợ cho các thư viện của bên thứ ba. Nhiều dự án của chúng tôi sử dụng bộ công cụ SQLAlchemy. Nó tận dụng khả năng động của Python mà các loại PEP 484 không thể mô hình hóa trực tiếp. Chúng tôi, theo PEP 561, đã tạo tệp sơ khai tương ứng và viết plugin cho mypy (mã nguồn mở), giúp cải thiện khả năng hỗ trợ SQLAlchemy.

Những khó khăn chúng tôi gặp phải

Con đường đạt tới 4 triệu dòng mã được đánh máy không phải lúc nào cũng dễ dàng đối với chúng tôi. Trên con đường này, chúng tôi gặp nhiều ổ gà và mắc một số sai lầm. Đây là một số vấn đề chúng tôi gặp phải. Chúng tôi hy vọng rằng việc kể về chúng sẽ giúp những người khác tránh được những vấn đề tương tự.

Thiếu tập tin. Chúng tôi bắt đầu công việc của mình bằng cách chỉ kiểm tra một lượng nhỏ tệp. Bất cứ điều gì không có trong các tập tin này đều không được kiểm tra. Các tập tin đã được thêm vào danh sách quét khi các chú thích đầu tiên xuất hiện trong đó. Nếu thứ gì đó được nhập từ một mô-đun nằm ngoài phạm vi xác minh, thì chúng ta đang nói về việc làm việc với các giá trị như Any, chưa hề được thử nghiệm. Điều này dẫn đến sự mất đi đáng kể độ chính xác khi gõ, đặc biệt là trong giai đoạn đầu của quá trình di chuyển. Cho đến nay, cách tiếp cận này đã hoạt động hiệu quả một cách đáng ngạc nhiên, mặc dù một tình huống điển hình là việc thêm tệp vào phạm vi đánh giá sẽ phát hiện ra các vấn đề ở các phần khác của cơ sở mã. Trong trường hợp xấu nhất, khi hai vùng mã biệt lập được hợp nhất, trong đó các loại độc lập với nhau đã được kiểm tra, hóa ra loại của các vùng này không tương thích với nhau. Điều này dẫn đến nhu cầu thực hiện nhiều thay đổi đối với các chú thích. Bây giờ nhìn lại, chúng tôi nhận ra rằng lẽ ra chúng tôi nên thêm các mô-đun thư viện cốt lõi vào khu vực kiểm tra kiểu của mypy sớm hơn. Điều này sẽ làm cho công việc của chúng tôi dễ dự đoán hơn nhiều.

Chú thích mã cũ. Khi bắt đầu, chúng tôi có khoảng 4 triệu dòng mã Python hiện có. Rõ ràng là việc chú thích tất cả đoạn mã này không phải là một nhiệm vụ dễ dàng. Chúng tôi đã tạo một công cụ có tên PyAnnotate có thể thu thập thông tin loại khi chạy thử nghiệm và có thể thêm chú thích loại vào mã của bạn dựa trên thông tin được thu thập. Tuy nhiên, chúng tôi chưa nhận thấy việc áp dụng rộng rãi công cụ này. Việc thu thập thông tin về loại diễn ra chậm và các chú thích được tạo tự động thường yêu cầu nhiều chỉnh sửa thủ công. Chúng tôi đã nghĩ đến việc tự động chạy công cụ này mỗi khi xem lại mã hoặc thu thập thông tin loại dựa trên phân tích một số lượng nhỏ yêu cầu mạng thực tế, nhưng quyết định không làm như vậy vì cả hai cách tiếp cận đều quá rủi ro.

Kết quả là, có thể lưu ý rằng hầu hết mã đã được chủ sở hữu của nó chú thích theo cách thủ công. Để hướng dẫn quá trình này đi đúng hướng, chúng tôi chuẩn bị báo cáo về các mô-đun và chức năng đặc biệt quan trọng cần được chú thích. Ví dụ: điều quan trọng là cung cấp chú thích kiểu cho mô-đun thư viện được sử dụng ở hàng trăm nơi. Nhưng một dịch vụ cũ đang được thay thế bằng một dịch vụ mới không còn quá quan trọng để chú thích nữa. Chúng tôi cũng đang thử nghiệm sử dụng phân tích tĩnh để tạo chú thích loại cho mã cũ.

Nhập khẩu theo chu kỳ. Ở trên, tôi đã nói về việc nhập khẩu theo chu kỳ ("các mối rối phụ thuộc"), sự tồn tại của nó đã gây khó khăn cho việc tăng tốc mypy. Chúng tôi cũng đã phải làm việc chăm chỉ để giúp mypy hỗ trợ tất cả các loại thành ngữ do việc nhập khẩu theo chu kỳ này gây ra. Gần đây chúng tôi đã hoàn thành một dự án thiết kế lại hệ thống lớn nhằm khắc phục hầu hết các vấn đề của mypy liên quan đến nhập khẩu tuần hoàn. Những vấn đề này thực sự bắt nguồn từ những ngày đầu của dự án, từ Alore, ngôn ngữ giáo dục mà dự án mypy ban đầu tập trung vào. Cú pháp Alore giúp bạn dễ dàng giải quyết vấn đề bằng các lệnh nhập theo chu kỳ. Mypy hiện đại đã thừa hưởng một số hạn chế từ việc triển khai đơn giản trước đó (điều này rất phù hợp với Alore). Python làm cho việc nhập vòng tròn trở nên khó khăn, chủ yếu là do các biểu thức không rõ ràng. Ví dụ: một thao tác gán thực sự có thể xác định bí danh loại. Mypy không phải lúc nào cũng có thể phát hiện những thứ như thế này cho đến khi hầu hết vòng nhập được xử lý. Không có sự mơ hồ như vậy ở Alore. Những quyết định sai lầm được đưa ra trong giai đoạn đầu của quá trình phát triển hệ thống có thể gây bất ngờ khó chịu cho người lập trình nhiều năm sau đó.

Kết quả: con đường dẫn đến 5 triệu dòng mã và những chân trời mới

Dự án mypy đã đi được một chặng đường dài - từ những nguyên mẫu ban đầu đến hệ thống kiểm soát 4 triệu dòng mã sản xuất. Khi mypy phát triển, gợi ý kiểu của Python đã được chuẩn hóa. Ngày nay, một hệ sinh thái mạnh mẽ đã phát triển xung quanh việc gõ mã Python. Nó có một nơi hỗ trợ thư viện, nó chứa các công cụ phụ trợ cho IDE và trình soạn thảo, nó có một số hệ thống kiểm soát kiểu, mỗi hệ thống đều có ưu và nhược điểm riêng.

Mặc dù việc kiểm tra kiểu đã được cung cấp tại Dropbox nhưng tôi tin rằng chúng ta vẫn đang ở giai đoạn đầu của việc gõ mã Python. Tôi nghĩ công nghệ kiểm tra kiểu sẽ tiếp tục phát triển và cải tiến.

Nếu bạn chưa sử dụng tính năng kiểm tra kiểu trong dự án Python quy mô lớn của mình thì hãy biết rằng bây giờ là thời điểm rất tốt để bắt đầu chuyển sang kiểu gõ tĩnh. Tôi đã nói chuyện với những người đã thực hiện quá trình chuyển đổi tương tự. Không ai trong số họ hối tiếc về điều đó. Kiểm tra kiểu làm cho Python trở thành ngôn ngữ phù hợp hơn nhiều để phát triển các dự án lớn so với “Python thông thường”.

Gởi bạn đọc! Bạn có sử dụng tính năng kiểm tra kiểu trong các dự án Python của mình không?

Đường dẫn để đánh máy 4 triệu dòng mã Python. Phần 3
Đường dẫn để đánh máy 4 triệu dòng mã Python. Phần 3

Nguồn: www.habr.com

Thêm một lời nhận xét