Là một thư viện phổ biến là một ý tưởng tốt?


16

Tôi đã luôn nghĩ rằng một "thư viện chung" là một ý tưởng tốt. Điều đó có nghĩa là một thư viện chứa các chức năng phổ biến thường được yêu cầu bởi một vài ứng dụng khác nhau. Nó dẫn đến việc sao chép / dự phòng ít mã hơn.

Gần đây tôi đã đọc một bài báo (không thể tìm thấy bây giờ) nói rằng đây thực sự là một ý tưởng tồi và đã đi xa để nói rằng đó là một "chống mẫu"

Trong khi có những mặt tích cực của phương pháp này. Phiên bản và quản lý thay đổi có nghĩa là kiểm tra hồi quy cho bộ ứng dụng sử dụng thư viện này.

Tôi bị mắc kẹt trong lối mòn cho dự án mới (Golang) của mình. Sự trùng lặp mã đã được rèn vào tôi trong những năm qua nhưng tôi cảm thấy như tôi nên thử nó lần này.

Trong khi viết bài này, tôi bắt đầu nghĩ rằng cách tiếp cận "lib chung" này là kết quả của việc lướt qua kiến ​​trúc? Có lẽ thiết kế của tôi cần nhiều suy nghĩ?

Quan tâm để nghe suy nghĩ.


2
2 xu của tôi ... Nếu bạn phải thay đổi api thông thường nếu một trong các hệ thống sử dụng nó cần thay đổi đó, thì API hoặc thư viện đó hoàn toàn không phải là thư viện chung
Raja Anbazhagan

1
Tôi thấy rằng có một sự đánh đổi cơ bản giữa sao chép mã và khớp nối. Câu hỏi của bạn là một ví dụ điển hình về điều đó. Số dư bạn đạt được giữa hai người có thể sẽ phụ thuộc vào môi trường mà mã của bạn cuối cùng sẽ thực thi.
Joel Cornett

Hầu hết các nhà phát triển C mà tôi biết đều có một bộ các tiện ích mà họ gọi là "hộp công cụ" của họ. Mặc dù vậy, nó thường không được thu thập vào một thư viện. Đó là "chọn và chọn" nhiều hơn.
Mark Benningfield

2
Ai đó gọi cho Apache và khắc phục sự điên rồ này. Commons Apache
Laiv

Câu trả lời:


21

Thư viện và sử dụng lại hoàn toàn là một điều tốt. Chúng có một nhược điểm rất lớn, đó là nếu không được quản lý cẩn thận, chúng sẽ trở thành tương đương với ngăn kéo trong nhà bếp của bạn chứa tất cả các tỷ lệ cược và kết thúc mà không đi đến đâu khác.

Tôi đã thấy điều này khi hoạt động khi tôi chịu trách nhiệm về các cổng đầu tiên của toàn bộ mã giá trị của đơn vị kinh doanh (hầu hết là mới đối với tôi) đối với các hệ thống 64 bit và thực hiện một cuộc đại tu hoàn chỉnh cho bản dựng và đóng gói của chúng tôi, rất nhiều trong số đó đã được thực hiện bằng tay và đôi khi không tốt lắm. * Chúng tôi có xu hướng xây dựng những gì chúng tôi đã vận chuyển ra khỏi một đống ứng dụng, trong đó khách hàng sẽ nói: "Tôi muốn một hệ thống làm A, B, D và F, cộng với những thứ M và N mà bạn chưa làm và keo hơi khác nhau tích hợp tất cả chúng. " Những gì tất cả đều có điểm chung là một thư viện ngăn kéo rác, trong vài thập kỷ, ** đã tích lũy tất cả những thứ mà mọi người nghĩ nên sử dụng lại. Để làm cho một câu chuyện dài ngắn, một phần mã trong thư viện đã không '. Chúng tôi đã dành rất nhiều thời gian để xây dựng và duy trì những phụ thuộc đó chỉ để thư viện chung sẽ cài đặt, không phải vì chúng tôi thực sự cần chúng.

Đạo đức là các thư viện cần được đối xử như các lớp học và không bị quá tải với quá nhiều trách nhiệm. Đừng đặt trình phân tích cú pháp JSON của bạn trong cùng một thư viện với các hàm đại số tuyến tính của bạn ngay cả khi mọi chương trình bạn viết đều sử dụng cả hai.

Giữ chúng riêng biệt có rất nhiều lợi ích, trong đó lớn nhất là nó buộc các nhà phát triển và nhà đóng gói của bạn phải đưa ra một kế toán chi tiết về những gì sản phẩm của họ thực sự cần thay vì chỉ bao gồm ngăn kéo rác và hành lý đi kèm. Khi bạn thiết lập một hệ thống bằng cách sử dụng các gói được xây dựng, các phụ thuộc hạt mịn đảm bảo rằng chỉ những phần cần thiết mới được cài đặt. Ngay cả khi bạn bỏ bê kho lưu trữ của mình và tiếp tục biên dịch những thứ cũ kỹ, tồi tàn, không có gì không còn được sử dụng để rò rỉ vào những gì bạn gửi.

Tất nhiên, có những trường hợp ngoại lệ như libcnhồi nhét rất nhiều chức năng vào một thư viện. Đó là một trong những trường hợp mà lợi ích của việc làm theo cách đó có thể được lý giải thay vì mù quáng chú ý đến sự nhiệt tình xuống hội trường, người khẳng định rằng bất kỳ cách nào khác ngoài X luôn là thực tiễn xấu.


* Trong quá trình đó, tôi đã phát hiện ra một nhị phân đã được thông qua và không được biên dịch lại từ đầu trong sáu năm.

** Không có gì sai với mã hàng chục năm tuổi. Chúng tôi đã có một số thuật toán quan trọng đã được chứng minh rất rõ rằng chúng tôi đã ngu ngốc để viết lại chúng chỉ vì lợi ích của tính hiện đại.


1
Nguyên tắc nhỏ của tôi là, nếu bạn có ý định đặt tên cho thư viện của mình một cái gì đó như "thông thường", bạn đang gặp rắc rối.
Karl Bielefeldt

9

Xấu hổ quá, tôi đã giới thiệu một thư viện "chung", được đặt tên như vậy, trong môi trường nhóm cách đây vài thập kỷ. Tôi đã không thực sự hiểu động lực hồi đó về những gì có thể xảy ra trong một nhóm phối hợp lỏng lẻo chỉ trong vài tháng.

Khi tôi giới thiệu, tôi nghĩ rằng tôi đã nói rõ và cũng ghi lại rằng đó là những điều mà tất cả chúng ta đều đồng ý, chúng tôi thấy hữu ích trên cơ sở hàng ngày, rằng nó dự định là một thư viện tối giản và thư viện không phụ thuộc vào điều gì khác ngoài thư viện chuẩn để dễ triển khai nhất có thể trong các dự án mới. Suy nghĩ của tôi lúc đó là việc chúng tôi mở rộng ra thư viện tiêu chuẩn cho những thứ mà trong miền cụ thể của chúng tôi, chúng tôi thấy hữu ích hàng ngày.

Và nó bắt đầu đủ tốt. Chúng tôi bắt đầu với một thư viện toán học ( common/math*) các thói quen mà tất cả chúng tôi sử dụng hàng ngày, vì chúng tôi làm việc trong đồ họa máy tính thường nặng về đại số tuyến tính. Và vì chúng tôi thường xen kẽ với mã C, chúng tôi đã đồng ý về một số chức năng tiện ích hữu ích như thế find_index, không giống nhưstd::findtrong C ++, sẽ trả về một chỉ mục cho một phần tử được tìm thấy trong một chuỗi thay vì một trình vòng lặp bắt chước cách các hàm C của chúng ta hoạt động - những thứ thuộc loại này - một chút chiết trung nhưng tối giản và được sử dụng rộng rãi đủ để vẫn quen thuộc và thiết thực với mọi người và sự quen thuộc ngay lập tức là một tiêu chí cực kỳ quan trọng như tôi thấy khi cố gắng tạo ra bất cứ thứ gì "phổ biến" hoặc "tiêu chuẩn" vì nếu nó thực sự là "phổ biến", thì nó phải có chất lượng quen thuộc về nó như là kết quả của nó áp dụng và sử dụng hàng ngày.

Nhưng theo thời gian, ý định thiết kế của thư viện tuột khỏi ngón tay tôi khi mọi người bắt đầu thêm những thứ họ sử dụng mà họ nghĩ rằng họ chỉ có thể sử dụng cho người khác, chỉ để không tìm thấy ai khác sử dụng nó. Và sau đó, một người nào đó bắt đầu thêm các chức năng phụ thuộc vào OpenGL cho các thói quen phổ biến liên quan đến GL. Hơn nữa, chúng tôi đã thông qua Qt và mọi người bắt đầu thêm mã phụ thuộc vào Qt, vì vậy thư viện chung đã phụ thuộc vào hai thư viện bên ngoài. Tại một số thời điểm, ai đó đã thêm các thói quen đổ bóng phổ biến phụ thuộc vào thư viện trình đổ bóng dành riêng cho ứng dụng của chúng tôi và tại thời điểm đó, bạn thậm chí không thể triển khai nó trong một dự án mới mà không đưa vào Qt, OGL, và thư viện trình đổ bóng dành riêng cho ứng dụng của chúng tôi một kịch bản xây dựng không tầm thường cho dự án của bạn. Vì vậy, nó biến thành mớ hỗn độn, phụ thuộc lẫn nhau.

Nhưng tôi cũng đã tìm thấy bằng cách tranh luận những gì nên và không nên vào thư viện này rằng những gì được coi là "phổ biến" có thể dễ dàng biến thành một ý tưởng rất chủ quan nếu bạn không đặt ra một quy tắc rất khó hiểu rằng "phổ biến" là gì những gì mọi người có xu hướng tìm thấy hữu ích trên cơ sở hàng ngày. Bất kỳ sự nới lỏng nào của các tiêu chuẩn và nó nhanh chóng suy giảm từ những thứ mà mọi người đều thấy hữu ích hàng ngày thành một thứ mà một nhà phát triển thấy hữu ích có thể có lợi cho người khác, và tại thời điểm đó, thư viện biến thành một mớ hỗn độn rất nhanh .

Nhưng hơn nữa khi bạn đạt đến điểm đó, một số nhà phát triển có thể bắt đầu thêm mọi thứ vì lý do đơn giản là họ không thích ngôn ngữ lập trình. Họ có thể không thích cú pháp của vòng lặp for hoặc lệnh gọi hàm, tại thời điểm đó, thư viện bắt đầu chứa đầy những thứ chỉ chống lại cú pháp cơ bản của ngôn ngữ, thay thế một vài dòng mã đơn giản không thực sự sao chép bất kỳ logic nào xuống một dòng mã kỳ lạ duy nhất chỉ quen thuộc với nhà phát triển đã giới thiệu một tốc ký như vậy. Sau đó, một nhà phát triển như vậy có thể bắt đầu thêm nhiều chức năng hơn vào thư viện chung được triển khai bằng cách sử dụng các tốc ký như vậy, tại thời điểm đó, các phần quan trọng của thư viện chung trở nên đan xen với những tốc ký kỳ lạ này có vẻ đẹp và trực quan đối với nhà phát triển đã giới thiệu nó nhưng xấu và xa lạ và khó hiểu đối với mọi người khác. Và tại thời điểm đó tôi nghĩ bạn biết rằng mọi hy vọng tạo ra một cái gì đó thực sự "chung" đều bị mất, vì "chung" và "không quen thuộc" là những ý tưởng trái ngược nhau.

Vì vậy, có tất cả các loại giun ở đó, ít nhất là trong môi trường nhóm phối hợp lỏng lẻo, với một thư viện với tham vọng rộng lớn và khái quát như "những thứ thường được sử dụng". Và trong khi vấn đề tiềm ẩn có thể là sự phối hợp lỏng lẻo trên tất cả các vấn đề khác, thì ít nhất nhiều thư viện nhằm phục vụ mục đích khác thường hơn, như một thư viện nhằm cung cấp các thói quen toán học và không có gì khác, có lẽ sẽ không suy giảm đáng kể về mặt thiết kế tinh khiết và phụ thuộc như một thư viện "chung". Vì vậy, khi nhìn lại tôi nghĩ sẽ tốt hơn nhiều nếu nhầm lẫn về phía các thư viện có ý định thiết kế rõ ràng hơn nhiều. Trong những năm qua, tôi cũng thấy rằng mục đích hẹp và khả năng áp dụng là những ý tưởng hoàn toàn khác nhau.

Ngoài ra, tôi thừa nhận ít nhất một chút không thực tế và quan tâm có thể hơi quá về tính thẩm mỹ, nhưng cách tôi có xu hướng nhận thức ý tưởng của tôi về chất lượng của thư viện (và thậm chí là "vẻ đẹp") được đánh giá nhiều hơn bởi liên kết yếu nhất của nó mạnh nhất, theo cách tương tự như nếu bạn đưa cho tôi loại thực phẩm ngon miệng nhất thế giới, nhưng trên cùng một đĩa, đặt thứ gì đó thối rữa lên đó có mùi rất tệ, tôi có xu hướng muốn từ chối toàn bộ đĩa. Và nếu bạn giống tôi về vấn đề đó và tạo ra thứ gì đó mời tất cả các loại bổ sung như một thứ gọi là "chung", bạn có thể thấy mình đang nhìn vào tấm tương tự đó với một thứ gì đó mục nát ở bên cạnh. Vì vậy, tôi cũng nghĩ rằng thật tốt nếu một thư viện được tổ chức và đặt tên và ghi lại theo cách mà nó không ' mời ngày càng nhiều hơn và nhiều bổ sung theo thời gian. Và điều đó thậm chí có thể áp dụng cho các sáng tạo cá nhân của bạn, vì tôi chắc chắn đã tạo ra một số thứ mục nát ở đây và ở đó, và nó "làm mờ" đi rất nhiều nếu nó không được thêm vào đĩa lớn nhất. Việc tách các thứ ra thành các thư viện nhỏ, rất đơn lẻ cũng có xu hướng tách mã tốt hơn, nếu chỉ nhờ vào đức tính tuyệt đối mà nó trở nên ít thuận tiện hơn để bắt đầu ghép mọi thứ.

Sự trùng lặp mã đã được rèn vào tôi trong những năm qua nhưng tôi cảm thấy như tôi nên thử nó lần này.

Những gì tôi có thể đề nghị trong trường hợp của bạn là bắt đầu làm cho nó dễ dàng trong việc sao chép mã. Tôi không nói sẽ sao chép và dán các đoạn mã lớn được kiểm tra kém, dễ bị lỗi xung quanh hoặc bất cứ thứ gì thuộc loại này, hoặc sao chép một lượng lớn mã không tầm thường có xác suất yêu cầu thay đổi trong tương lai.

Nhưng đặc biệt nếu bạn có ý định tạo ra một thư viện "chung", mà tôi cho rằng mong muốn của bạn là tạo ra thứ gì đó có thể áp dụng rộng rãi, có khả năng tái sử dụng cao và có lẽ lý tưởng là thứ gì đó bạn thấy hữu ích như bạn làm trong một thập kỷ kể từ bây giờ , sau đó đôi khi bạn thậm chí có thể cần hoặc muốn một số sao chép để đạt được chất lượng khó nắm bắt này. Bởi vì sự trùng lặp thực sự có thể phục vụ như một cơ chế tách rời. Giống như nếu bạn muốn tách một trình phát video khỏi trình phát MP3, thì ít nhất bạn phải sao chép một số thứ như pin và ổ cứng. Họ không thể chia sẻ những thứ này nếu không chúng được ghép nối một cách không thể tách rời và không thể được sử dụng độc lập với nhau và tại thời điểm đó, mọi người có thể không quan tâm đến thiết bị nữa nếu tất cả những gì họ muốn làm là phát MP3. Nhưng một thời gian sau khi bạn tách hai thiết bị này ra, bạn có thể thấy rằng trình phát MP3 có thể được hưởng lợi từ một thiết kế pin khác hoặc ổ cứng nhỏ hơn trình phát video, tại thời điểm đó bạn không còn sao chép bất cứ thứ gì; những gì ban đầu bắt đầu là sự trùng lặp để cho phép thiết bị phụ thuộc lẫn nhau này tách thành hai thiết bị độc lập, riêng biệt sau đó có thể tạo ra các thiết kế và triển khai không còn dư thừa.

Thật đáng để xem xét mọi thứ từ quan điểm của một người sử dụng thư viện. Bạn có thực sự muốn sử dụngmột thư viện giảm thiểu sao chép mã? Rất có thể là bạn sẽ không vì một thứ sẽ tự nhiên phụ thuộc vào các thư viện khác. Và các thư viện khác đó có thể phụ thuộc vào các thư viện khác để tránh sao chép mã của họ, v.v., cho đến khi bạn có thể cần nhập / liên kết 50 thư viện khác nhau để có được một số chức năng cơ bản như tải và phát tệp âm thanh, và điều đó trở nên rất khó sử dụng . Trong khi đó, nếu một thư viện âm thanh như vậy cố tình chọn sao chép một số thứ ở đây và ở đó để đạt được sự độc lập, nó sẽ trở nên dễ sử dụng hơn trong các dự án mới, và rất có thể nó sẽ không cần được cập nhật gần như thường xuyên vì nó đã thắng ' Không cần thay đổi do một thư viện bên ngoài phụ thuộc của nó thay đổi, có thể đang cố gắng thực hiện mục đích tổng quát hơn nhiều so với những gì thư viện âm thanh cần.

Vì vậy, đôi khi đáng để cố tình chọn sao chép một chút (một cách có ý thức, không bao giờ hết lười biếng - thực sự không cần thiết) để tách rời một thư viện và làm cho nó độc lập bởi vì thông qua sự độc lập đó, nó đạt được phạm vi ứng dụng thực tế rộng hơn và thậm chí ổn định (không có khớp nối hướng tâm hơn). Nếu bạn muốn thiết kế các thư viện có thể tái sử dụng nhiều nhất có thể sẽ kéo dài bạn từ dự án này sang dự án tiếp theo và sau nhiều năm, thì trên hết thu hẹp phạm vi của nó đến mức tối thiểu, tôi thực sự khuyên bạn nên xem xét sao chép một chút ở đây. Và tự nhiên viết các bài kiểm tra đơn vị và đảm bảo rằng nó thực sự được kiểm tra kỹ lưỡng và đáng tin cậy về những gì nó đang làm. Điều này chỉ dành cho các thư viện mà bạn thực sự muốn dành thời gian để khái quát hóa đến một điểm vượt xa một dự án duy nhất.


3

Có ba loại chức năng khác nhau mà bạn có thể xem xét đưa vào thư viện:

  1. Thứ đáng để tái sử dụng cho mọi người.
  2. Công cụ chỉ có giá trị tái sử dụng cho tổ chức của bạn.
  3. Thứ không đáng sử dụng lại.

Loại một là thứ mà thư viện tiêu chuẩn nên tồn tại, nhưng vì một số lý do, không ai có thể tạo ra một (hoặc ai đó? Bạn đã tìm kiếm kỹ chưa?). Trong trường hợp đó hãy xem xét làm cho thư viện của bạn nguồn mở. Chia sẻ công việc của bạn không chỉ giúp người khác, nó cũng giúp bạn, bởi vì bạn sẽ nhận được báo cáo lỗi và bản vá lỗi từ những người dùng khác. Khi bạn nghi ngờ rằng bất kỳ ai sẽ đóng góp cho thư viện của bạn, thì bạn có thể xử lý chức năng thực sự là loại 2 hoặc 3.

Loại thứ hai là những thứ bạn cần nhiều lần, nhưng không ai khác trên thế giới cần nó. Ví dụ: việc triển khai giao thức mạng tối nghĩa để liên lạc với hệ thống phụ trợ do nhà phát triển của bạn phát triển. Trong trường hợp đó, có thể có ý nghĩa khi đưa nội dung đó vào thư viện trong nhà để cải thiện tốc độ phát triển của các ứng dụng mới. Chỉ cần đảm bảo rằng nó không bị ảnh hưởng quá nhiều bởi tính năng creep và bắt đầu chứa những thứ thực sự phù hợp với loại 1 hoặc 3. Ngoài ra, lời khuyên của Blrfl về mô đun hóa là rất tốt: Đừng tạo một Thư viện Conor Corp nguyên khối. Tạo nhiều thư viện riêng biệt cho các chức năng riêng biệt.

Loại ba là chức năng rất đơn giản để thực hiện việc chuyển nó sang thư viện không có giá trị hoặc bạn không chắc chắn mình sẽ cần lại nó ở dạng chính xác trong ứng dụng khác. Chức năng này sẽ là một phần của ứng dụng được phát triển cho. Khi nghi ngờ, nó có thể thuộc về thể loại này.


1

Hầu như tất cả các ngôn ngữ đều có một thư viện chung / tiêu chuẩn, vì vậy điều này được công nhận rộng rãi là một ý tưởng tốt. Sử dụng các thư viện phần thứ ba cho các nhiệm vụ khác nhau thay vì phát minh lại bánh xe cũng thường được coi là một ý tưởng tốt, mặc dù chi phí / lợi ích và chất lượng của thư viện rõ ràng nên được đánh giá trong từng trường hợp.

Sau đó, có các thư viện "tiện ích chung" được sử dụng bởi một nhà phát triển hoặc tổ chức riêng lẻ trong các dự án không liên quan. Đây là loại thư viện có thể được coi là một mô hình chống. Trong trường hợp tôi đã thấy, các thư viện này chỉ sao chép chức năng từ các thư viện tiêu chuẩn hoặc thư viện bên thứ ba nổi tiếng hơn theo cách không chuẩn và tài liệu xấu.


these libraries just replicate functionality from standard librariesĐây không hoàn toàn là một điều xấu, trong javascript bạn đã thêm các thư viện đã triển khai những thứ hiện có để thêm hỗ trợ trên các công cụ js cũ, bạn cũng có libs hỗ trợ Android cho các sdk cũ hơn v.v.
svarog

@svarog: Bạn có nghĩ đến "polyfill" mô phỏng chức năng trong các tiêu chuẩn mới cho các động cơ cũ không hỗ trợ nó một cách tự nhiên không? Tôi không thấy bất kỳ lý do nào để tự viết những điều này, vì có những thư viện nguồn mở nổi tiếng có sẵn cho các mục đích này.
JacquesB

0

Hầu hết các thư viện được chia sẻ giữa các nhóm gây ra nhiều vấn đề hơn họ giải quyết. "Đường dẫn đến địa ngục được lót đường bởi các ý định tốt."

Ngoại lệ là các thư viện đáp ứng hầu hết các trường hợp dưới đây:

  • Có kinh phí bảo trì dài hạn
  • Có một nhóm / cộng đồng hỗ trợ tận tình
  • Có một người sửa lỗi
  • Có phạm vi kiểm tra rộng
  • Có một mục đích duy nhất, được xác định rõ
  • Không có phụ thuộc bản thân (cả lúc xây dựng và thời gian chạy), ngoài các thư viện chuẩn hoặc bán chuẩn
  • Có sự phân biệt rõ ràng giữa api công cộng và nội bộ
  • Có một kênh liên lạc và xử lý để tất cả / nhiều người dùng đồng ý về các tính năng và bản phát hành mới

Trong các công ty điển hình (không khởi nghiệp), hầu như không có điều kiện nào ở trên cho các thư viện được chia sẻ giữa các nhóm. Đó là bởi vì hầu hết các nhóm công ty được trả tiền để cung cấp sản phẩm, không phải thư viện. Một số công ty có chiến lược chia sẻ thành công, như monorepo của Google, nhưng điều này đi kèm với sự đầu tư rất cao vào xây dựng và thử nghiệm cơ sở hạ tầng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.