Một cuộc thảo luận gần đây trong cộng đồng Python đã khơi mào cuộc tranh luận về các thực hành tốt nhất trong kiến trúc khi sử dụng Pydantic , thư viện xác thực dữ liệu phổ biến. Cuộc trò chuyện tập trung vào việc liệu các nhà phát triển có nên giữ các mô hình Pydantic chỉ trong phạm vi ranh giới ứng dụng hay cho phép chúng thâm nhập khắp codebase, bao gồm cả logic miền cốt lõi.
Câu hỏi kiến trúc cốt lõi
Vấn đề chính xoay quanh việc phân tách mối quan tâm trong các ứng dụng lớn hơn. Một số nhà phát triển ủng hộ việc chỉ giữ các mô hình Pydantic ở các cạnh của ứng dụng - trong các lớp API và giao diện dữ liệu bên ngoài - trong khi sử dụng các dataclass hoặc đối tượng Python thuần túy cho logic nghiệp vụ nội bộ. Cách tiếp cận này tuân theo các nguyên tắc kiến trúc sạch, nơi lớp miền vẫn độc lập với các thư viện và framework bên ngoài.
Tuy nhiên, cộng đồng đang chia rẽ về việc liệu sự phân tách này có mang lại lợi ích thực sự hay chỉ đơn giản tạo ra sự phức tạp không cần thiết. Những người chỉ trích cho rằng việc duy trì các mô hình dữ liệu riêng biệt dẫn đến mã boilerplate quá mức và logic ánh xạ giữa các biểu diễn khác nhau của cùng một dữ liệu. Họ đặt câu hỏi liệu các lợi ích lý thuyết của việc ghép nối lỏng có biện minh cho chi phí thực tế của việc duy trì nhiều loại đối tượng hay không.
Cân nhắc về hiệu suất và thực tiễn
Hiệu suất nổi lên như một yếu tố quan trọng khác trong cuộc tranh luận. Các mô hình Pydantic , bất chấp những tối ưu hóa gần đây, mang theo chi phí xác thực có thể không cần thiết cho các hoạt động nội bộ. Một số nhà phát triển báo cáo rằng Pydantic có thể trở thành nút thắt cổ chai trong các ứng dụng có cấu trúc phân cấp đối tượng lồng nhau sâu, nơi chi phí xác thực tích lũy đáng kể.
Cuộc thảo luận cũng đề cập đến tốc độ phát triển so với tính thuần khiết của kiến trúc. Đối với các đội nhỏ hơn và các ứng dụng đơn giản hơn, các lớp trừu tượng bổ sung có thể làm chậm quá trình phát triển mà không mang lại lợi ích có ý nghĩa. Sự phức tạp trở nên được biện minh hơn khi các ứng dụng phát triển và nhiều đội cần làm việc với các mô hình dữ liệu được chia sẻ.
So sánh hiệu suất:
- Các model Pydantic : tốn kém hơn 8 lần khi khởi tạo so với các class Python thông thường
- Truy cập thuộc tính: chậm hơn 50% so với các class tiêu chuẩn
- Dataclasses : nhanh hơn 2 lần so với Pydantic trong việc tạo đối tượng
- Dataclasses đã biên dịch (với mypyc ): cải thiện hiệu suất gấp 10 lần so với Pydantic
Các cách tiếp cận và công cụ thay thế
Một số thành viên cộng đồng đề xuất các giải pháp trung gian, chẳng hạn như sử dụng các thư viện như Dacite để chuyển đổi giữa các mô hình Pydantic và dataclass thuần túy khi cần thiết. Những người khác khuyến nghị giữ việc xác thực ở các ranh giới trong khi sử dụng các cấu trúc dữ liệu đơn giản hơn bên trong, hoặc sử dụng các mô hình Pydantic khác nhau cho các ngữ cảnh khác nhau thay vì loại bỏ hoàn toàn thư viện.
Lợi ích lớn nhất bạn nhận được là có thể có nhiều tính linh hoạt hơn xung quanh việc xác thực khi mô hình đầu vào không giống với mô hình cơ sở dữ liệu.
Cuộc trò chuyện cũng làm nổi bật cách quyết định kiến trúc này thường phụ thuộc vào cấu trúc đội và độ phức tạp của ứng dụng. Điều gì hoạt động cho một nhà phát triển đơn lẻ xây dựng một API đơn giản có thể không mở rộng được cho các hệ thống lớn hơn, phức tạp hơn với nhiều điểm tích hợp.
Các Thư Viện Thay Thế Được Đề Cập:
- Dacite: Chuyển đổi dictionary thành các dataclass lồng nhau, được thiết kế đặc biệt để khởi tạo các cấu trúc đối tượng phức tạp
- Marshmallow: Thư viện serialization/validation cũ hơn, được coi là ít cồng kềnh hơn Pydantic
- SQLModel: Kết hợp Pydantic với SQLAlchemy cho các thao tác cơ sở dữ liệu
- Protobuf: Định dạng serialization nhị phân có thể chuyển đổi thành Python dataclass, JSON và chuỗi nhị phân
Kết luận
Cuộc tranh luận phản ánh những căng thẳng rộng lớn hơn trong kiến trúc phần mềm giữa chủ nghĩa thực dụng và các thực hành tốt nhất về mặt lý thuyết. Trong khi các nguyên tắc kiến trúc sạch đề xuất giữ các phụ thuộc bên ngoài ra khỏi logic nghiệp vụ cốt lõi, các lợi ích thực tế phải được cân nhắc với sự phức tạp bổ sung và chi phí phát triển. Cộng đồng Python tiếp tục vật lộn với việc tìm ra sự cân bằng phù hợp giữa tính thuần khiết của kiến trúc và năng suất của nhà phát triển, mà không có sự đồng thuận rõ ràng nào xuất hiện về cách tiếp cận tốt nhất cho mọi tình huống.
Tham khảo: Keep Pydantic out of your Domain Layer