Tại sao phải phát triển thư viện nội bộ cho các ứng dụng nội bộ?


10

Tôi đang gặp khó khăn trong việc hiểu tại sao bạn nên phát triển các thư viện nội bộ được sử dụng riêng cho việc phát triển các ứng dụng nội bộ. Tôi đánh giá cao rằng nếu tôi muốn sử dụng phần mềm mà ai đó bên ngoài tổ chức đã viết thì họ có thể gửi cho tôi tệp tiêu đề và tệp .a hoặc .so và tôi chỉ có thể liên kết nó với dự án của mình (giả sử chúng được biên dịch trong cùng môi trường) .

Nhưng tại sao một thư viện nội bộ phải được phát triển để được liên kết với một ứng dụng nội bộ khi tôi có quyền truy cập vào các tệp tiêu đề và triển khai và chỉ có thể đưa chúng vào cây nguồn của tôi và biên dịch tất cả chúng lại với nhau?

Nói cách khác: nếu một số mã nguồn được viết, làm thế nào để bạn quyết định xem nó có nên được biên dịch vào thư viện nhị phân và liên kết với ứng dụng của bạn hay chỉ bao gồm trong các tệp nguồn của dự án và được biên dịch thường xuyên?

Khi tôi nói 'bao gồm' các tệp trong mỗi dự án, tôi không có ý sao chép và dán từng tệp vào cây nguồn của dự án hiện đang được phát triển. Ý tôi là phát triển một số thư mục / thư viện (riêng biệt cho bất kỳ dự án nào) có chứa mã nguồn chung có thể được đưa vào các tệp của dự án theo cách thông thường, tức là #include.

ps Tôi đang nói về phát triển c / c ++ ở đây cho nhiều ứng dụng máy tính để bàn.


Câu trả lời:


25

Có rất nhiều lý do để tạo thư viện và thư viện dùng chung, (trong tệp dll hoặc .so) ngay cả để sử dụng nội bộ:

  1. Tái sử dụng trên các dự án sạch hơn nhiều
  2. Tách trách nhiệm - một phần mã của bạn có thể phù hợp hơn với các nhà phát triển hoặc nhóm khác nhau
  3. Bạn có thể hưởng lợi từ các cải tiến trong các thư viện mà các nhóm khác thực hiện mà không phải xác định mã cụ thể
  4. Thời gian xây dựng nhanh hơn, nếu thư viện ổn định thì không cần xây dựng lại.
  5. Dung lượng đĩa - bạn có thể chỉ có thư viện và các tiêu đề trong dự án
  6. Nếu bạn sử dụng các thư viện dùng chung, bạn có thể tiết kiệm bộ nhớ chỉ với một bản sao được tải vào RAM ngay cả khi một số chương trình đang sử dụng nó
  7. Bạn thường kết thúc với tài liệu tốt hơn và kiểm tra các thư viện
  8. Thiết kế và mã sạch hơn - suy nghĩ về việc cấu trúc mọi thứ vào các thư viện sẽ dẫn đến các nhóm chức năng liên quan trong mỗi thư viện và bạn có xu hướng tách mã chung, vào các thư viện , từ các chi tiết cụ thể của ứng dụng, trong ứng dụng .
  9. Nếu bạn có các thuật toán độc quyền trong các thư viện, bạn có thể hạn chế quyền truy cập vào nguồn, ví dụ: không cho phép các nhà thầu hoặc các nhóm có nguồn gốc có được tại nguồn.
  10. Mã thư viện có thể được đặt theo một giấy phép khác cho Ứng dụng, ban đầu nó được viết như một phần của, một số công ty thậm chí còn được biết đến với các thư viện Nguồn mở mà họ tự hào - đạt được danh tiếng lớn trong cộng đồng Nguồn mở và đôi khi có những cải tiến lớn trở lại.

Một số công ty thậm chí có một thực hành kế toán nơi các dự án tạo thư viện nhận được một số tiền bồi hoàn cho mỗi lần sử dụng lại.


1
Hoặc trong một biến thể của điểm 9, bạn có thể giải phóng thư viện theo giấy phép khác với mã ứng dụng chính.
Michael Borgwardt

@MichaelBorgwardt - Điểm tốt nhắc điểm 10 ở trên.
Steve Barnes

Ngoài ra, có một số mã làm thư viện riêng giúp tránh các phím tắt trong khi lập trình, chẳng hạn như "Tôi sẽ chỉ thêm tham số bổ sung này vào đây .." và giúp tìm ra các cách tốt hơn để triển khai các tính năng cần thiết.
Valdas

11

Một số lý do có thể khác có thể áp dụng cho các dự án lớn hơn, không cần thiết:

  • Thời gian biên dịch: Các dự án C ++ nguyên khối khổng lồ với hàng ngàn tệp, hàng nghìn lớp, hàm, v.v. có thể mất một thời gian rất dài để biên dịch (làm tổn hại đến năng suất nếu bạn muốn biên dịch lại mỗi khi bạn thay đổi một vài dòng mã). Các thư viện được liên kết tĩnh và liên kết động được biên dịch độc lập và không cần biên dịch lại nếu nguồn của chúng không thay đổi.

  • Phân tách hợp lý các mô-đun hoặc hệ thống con riêng biệt : Các hệ thống lớn thường dễ quản lý hơn nếu các khu vực chức năng riêng biệt được đặt trong các mô-đun riêng biệt và các nhà phát triển không phải đối mặt với việc tìm kiếm thông qua các thư mục / dự án khổng lồ chứa hàng ngàn tệp / lớp.

  • Ranh giới giữa các nhà phát triển / nhóm : Các nhà phát triển xây dựng chức năng mới riêng biệt cùng một lúc có thể làm giảm khả năng xung đột hợp nhất nếu có thể có mỗi nhà phát triển làm việc trong các mô-đun khác nhau.

  • Mã không được phát hành vào môi trường sống : Ví dụ: thư viện kiểm tra đơn vị hoặc thư viện 'giả' được sử dụng để kiểm tra dành cho nhà phát triển để thay thế cho thành phần hệ thống trực tiếp (phần cứng, API, hệ thống từ xa, cơ sở dữ liệu, v.v.)

  • Cờ trình biên dịch : Nếu bạn thấy mình ở vị trí rất đáng tiếc khi tích hợp với API của bên thứ 3 nào đó mong đợi một cờ trình biên dịch kỳ lạ, thì thư viện có thể là "lớp khử nhiễm" nằm giữa API của bên thứ 3 và phần còn lại của ứng dụng.

  • Các tính năng tùy chọn / Tối ưu hóa : Trong các hệ thống lớn, một ứng dụng có thể đợi trước khi tải một số mô-đun được liên kết động vào bộ nhớ khi chạy nếu chúng không quan trọng đối với chức năng cơ bản của ứng dụng.


Nhìn chung, nhiều dự án nội bộ thường là các ứng dụng vi mô nhỏ không được hưởng lợi từ việc chia thành các thư viện riêng biệt. Nếu bạn đang làm việc trong một dự án nhỏ với tư cách là nhà phát triển đơn độc, thì bạn có thể không cần phải lo lắng về việc chia mã của mình vào các thư viện (chưa ...). Đừng quên nguyên tắc YAGNI .


3
@downvoter - bạn có thể giải thích lý do cho downvote không? Phản hồi về câu trả lời là hữu ích để cải thiện chất lượng của trang web này cho mọi người.
Ben Cottrell

4

Câu hỏi ban đầu của bạn có thể đã gây ra sự hiểu lầm ở đây cho hầu hết các câu trả lời khác. Vì bạn dự định không sao chép mã hiện có trên các dự án, nhưng bao gồm cùng các tệp nguồn từ các dự án khác nhau làm tham chiếu , bất kỳ đối số "mã trùng lặp" nào cũng trở nên vô nghĩa, cũng như nhiều đối số khác được trình bày.

Lưu ý điều này đôi khi (- không phải luôn luôn -) một kỹ thuật hợp lý . Trong thực tế, khi bạn đặt tất cả các tệp nguồn bạn muốn sử dụng lại trên các dự án vào một thư mục bao gồm riêng biệt, bạn cũng đã xây dựng một thư viện - một thư viện mã nguồn, không phải là một lib nhị phân. Đặc biệt là trong C ++, khi tạo các thư viện chung với các mẫu, không có gì lạ khi có các lib chỉ có tiêu đề, chỉ cần một bao gồm đơn giản và không có các chuẩn bị liên kết riêng.

Vì vậy, tôi đoán câu hỏi thực sự của bạn là - khi nào xây dựng libs mã nguồn, hoặc khi nào thích libs nhị phân được biên dịch trước? Trong câu trả lời cũ hơn trên trang web này , tôi đã thảo luận về một số ưu và nhược điểm của libs chỉ tiêu đề, có thể nó giúp bạn. Ưu điểm chính của libs mã nguồn là, chúng không yêu cầu được biên dịch với cùng cờ thời gian chạy và / hoặc trình biên dịch / trình liên kết tương thích như ứng dụng sử dụng chúng. Hạn chế là thời gian biên dịch bổ sung và yêu cầu cung cấp quyền truy cập vào mã nguồn (rõ ràng không phải là vấn đề đối với loại dự án "nội bộ" mà bạn có trong đầu).


Đúng là tôi có nghĩa là một thư viện mã nguồn phổ biến cho nhiều dự án nơi bạn chỉ tham chiếu các tệp mà bạn cần thông qua chỉ thị #include điển hình - Tôi không biết thuật ngữ này cho đến khi bạn nói và tôi sẽ chỉnh sửa câu hỏi bây giờ Câu trả lời liên kết của bạn là rất hữu ích quá.
Andrew Murtagh

@AndrewMurtagh: thực tế là bạn đã nhanh chóng chấp nhận câu trả lời của MichaelBorgwardt làm tôi ngạc nhiên, bởi vì những gì anh ấy viết dường như là một sự hiểu lầm của anh ấy hoặc của tôi.
Doc Brown

Anh ấy đã làm rõ sự nhầm lẫn ban đầu mà tôi có khi phân nhóm mã sẽ phổ biến cho nhiều dự án thành một gói (dù đó là trong thư viện nhị phân hoặc thư viện mã nguồn) nhưng tôi đã nói về việc có một thư mục nguồn duy nhất mã có thể được chia sẻ trên các dự án và không sao chép và dán từng tệp vào từng dự án vì tôi có thể cần chúng.
Andrew Murtagh

2

Tôi đồng ý với những người bình luận khác khi họ viết rằng bạn không nên sao chép mã. Tuy nhiên, trong trường hợp của bạn, có vẻ như bạn (hoặc những người bạn làm việc cùng) đang tạo thư viện cho mã không bị trùng lặp ở nơi khác.

Trong trường hợp này, tôi thận trọng chống lại khái quát sớm . Đôi khi người ta cảm thấy như một đoạn mã sẽ được tái sử dụng. Tuy nhiên, không biết chi tiết thân mật về trường hợp sử dụng thứ hai sẽ sử dụng mã như thế nào, rất dễ dàng dành thêm thời gian cho các tính năng "tái sử dụng" không thực sự hữu ích trong các trường hợp bổ sung hoặc đưa ra các giả định chứng minh sai trong trường hợp thứ hai.

Viết một "thư viện" cho một trường hợp sử dụng có thể biến thành một bài tập rất tốn kém mà không có bất kỳ khoản tiền nào --- Tôi đã bị điều này cắn nhiều lần.

Chi phí ví dụ:

  1. Thời gian / năng lượng dành cho việc xem xét các trường hợp sử dụng "chung"
  2. Thời gian dành để "thư viện" phân phối cho "khách hàng" của bạn (mã của riêng bạn)
  3. Áp lực trong tương lai để sử dụng "thư viện" ngay cả khi nó không hoàn toàn khớp với trường hợp sử dụng tiếp theo

Quy tắc chung của tôi là: không tạo mã vào thư viện trừ khi tôi có ít nhất 2 nơi riêng biệt cần mã.


2
Tôi đã thấy gần như chính xác những lý do tương tự được sử dụng bởi một số nhà phát triển là tại sao mã của họ chỉ nằm trong một tệp nguồn> 20k. Khi kết hợp với cách đặt tên kỳ quặc và nhận xét kém, bạn sẽ sớm có mã để viết lại nhanh hơn là duy trì.
Steve Barnes

Điểm tuyệt vời: Tôi chắc chắn không tranh cãi về việc viết mã có thể đọc được, có thể đọc được. Các tệp riêng biệt, các phương thức / lớp được đặt tên tốt và cấu trúc gói là tất cả các thành phần quan trọng của khả năng bảo trì. Quan điểm của tôi chỉ là chi phí cho việc viết + phân phối một thư viện rất lớn phải chịu khi chỉ có một trường hợp sử dụng duy nhất cho "thư viện".
Sam

1
Ngược lại, tôi không tranh luận rằng bạn nhất thiết phải đóng gói và phân phối thư viện trong mọi trường hợp, chỉ cần viết và cấu trúc như thể một ngày nào đó mã của bạn trở thành thư viện thường đáng giá một chút nỗ lực và thường trả cổ tức ngay cả khi mã không bao giờ trở thành phân phối như một thư viện.
Steve Barnes

1

tại sao một thư viện nội bộ nên được phát triển chỉ để được liên kết với một ứng dụng nội bộ khi tôi có quyền truy cập vào các tệp tiêu đề và triển khai và chỉ có thể đưa chúng vào cây nguồn của tôi và biên dịch tất cả chúng lại với nhau?

Bởi vì nếu bạn "chỉ đưa chúng vào cây nguồn của tôi", bạn đang sao chép mã .

Vấn đề với điều đó là bạn sẽ không được hưởng lợi từ bất kỳ cải tiến nào (bao gồm các lỗi nghiêm trọng) được tạo bởi dự án mà bạn đã sao chép mã từ đó, và họ cũng sẽ không được hưởng lợi từ bất kỳ cải tiến nào bạn thực hiện.

Bạn có thể nghĩ rằng bạn có thể giải quyết vấn đề này bằng cách chỉ cần sao chép phiên bản mã mới nhất vào cây nguồn của bạn thường xuyên, thậm chí có thể tự động bằng cách sử dụng một mô hình con trong git hoặc một cái gì đó tương tự. Nhưng sau đó, bạn sẽ liên tục bị phá vỡ bản dựng vì những thay đổi API không tương thích. Mặt khác, một thư viện có API công khai "chính thức" mà các nhà phát triển của nó biết không thể thay đổi mà không hợp tác với khách hàng.

Cuối cùng, có thể có những lý do kỹ thuật - có thể giữ một phần mã làm thư viện để nó có thể được tải tùy ý hoặc thậm chí được tải và dỡ theo yêu cầu, và do đó làm giảm việc sử dụng bộ nhớ khi không cần sử dụng bộ nhớ?


1
Vì vậy, theo tôi hiểu, lý do chính để tạo một số đoạn mã vào thư viện là khi nó sẽ được sử dụng trên các dự án khác nhau (ngay cả khi chúng được phát triển nội bộ) để mã đó không bị trùng lặp, cập nhật, duy trì riêng biệt? Và nếu bạn chỉ đang phát triển một dự án duy nhất thì không cần phải tạo một cái gì đó vào thư viện (trừ khi bạn có ý định sử dụng nó trong các dự án tiếp theo vào một ngày sau đó).
Andrew Murtagh

@AndrewMurtagh: Vâng, đó chính xác là cách tôi đặt nó. Mặc dù có thể có lý do kỹ thuật quá; Tôi không quen thuộc với việc phát triển C / C ++ - có thể việc giữ một phần mã làm thư viện là cần thiết để có thể tải tùy chọn hoặc thậm chí được tải và dỡ theo yêu cầu, và do đó giảm sử dụng bộ nhớ khi không cần sử dụng bộ nhớ?
Michael Borgwardt

Tôi tin rằng có thể có thể thông qua các thư viện chia sẻ. Cảm ơn đã làm rõ, tôi sẽ đánh dấu câu trả lời của bạn là được chấp nhận.
Andrew Murtagh

Gần như mọi VCS trong thập kỷ qua đều hỗ trợ các tham chiếu hoặc mô đun con bên ngoài. Điều này loại bỏ mã trùng lặp và vấn đề lỗi. Có thể bao gồm thêm thông tin về lý do tại sao đây không phải là một giải pháp khả thi nếu bạn vẫn tin rằng chúng là những vấn đề hợp lệ.
Sirisian

Cũng nghĩ trong bảo trì. 1) lib có thể được duy trì độc lập và song song. 2) Là mã dễ dàng để thay thế. 3) Cơ sở mã nhỏ dễ quản lý hơn cho các nhóm nhỏ và dễ hiểu hơn cho mọi người. 4) nếu thời gian tiếp thị là quan trọng, bạn sẽ thích có các bản dựng nhanh hơn. Mã trong libs là mã bạn không biên dịch lặp đi lặp lại trong đường ống dẫn (IMO). 5) Đó là mã có thể tái sử dụng đáng tin cậy ... Bạn đã tạo nó ;-)
Laiv

1

Tôi muốn giải thích chi phí cho giải pháp của bạn về lâu dài.

Rõ ràng, việc thêm một thư viện vào một dự án có một số chi phí, tất cả ở trên nếu đó là lần đầu tiên: quy trình công việc phải được thay đổi, đôi khi ngay cả cơ sở hạ tầng và một số thành viên trong nhóm có thể không thích nó (lúc đầu). Vì vậy, những lợi thế của giải pháp của bạn là rõ ràng, vì nó áp đặt chi phí ít hơn bây giờ .

Tuy nhiên, khi dự án của bạn phát triển, chi phí của "thư viện giả" sẽ. Giả sử bạn có một "thư viện giả" Ađược sử dụng bởi một ứng dụng và một người kiểm tra đơn vị. Mỗi khi bạn thêm một cpp vào A, bạn phải thêm nó vào cả hai dự án, nếu không chúng sẽ không liên kết.

Điều gì xảy ra nếu "thư viện giả" của bạn được sử dụng bởi một "thư viện giả" khác B? Bạn phải thêm cpp mới của bạn trong một loạt các dự án hơn. Và nếu Bchuyển sang sử dụng thư viện khác? Bạn sẽ phải xóa các cpps Atrong tất cả các dự án chỉ phụ thuộc vào B.

Tất cả điều này sẽ là miễn phí nếu một thư viện thực sự sẽ được sử dụng. Vì vậy, câu hỏi là, cần bao nhiêu cpps để biện minh cho việc chuyển sang một thư viện thực sự?

Nhưng chờ đã, còn có nhiều tài sản thế chấp hơn: Một nhà phát triển không thích công việc ngu ngốc này là săn tất cả các dự án cần cpp mới và sẽ thêm mã / lớp của anh ấy vào đâu đó vào các tệp đã có, đó không phải là một điều tốt trong Về lâu dài.

Vì vậy, sử dụng "thư viện giả" có thể là bước đầu tiên để phá vỡ một dự án nguyên khối, nhưng bạn không nên chờ đợi quá lâu để biến nó thành một thư viện thực sự để có thể sử dụng các lợi thế của nó.


0

Nhưng tại sao một thư viện nội bộ phải được phát triển để được liên kết với một ứng dụng nội bộ khi tôi có quyền truy cập vào các tệp tiêu đề và triển khai và chỉ có thể đưa chúng vào cây nguồn của tôi và biên dịch tất cả chúng lại với nhau?

Nếu thư viện chỉ được sử dụng bởi một ứng dụng thì có lẽ bạn không cần nó như một thư viện riêng.

Nếu thư viện được sử dụng bởi 3.500 ứng dụng sau đó bạn hoàn toàn làm cần nó như một thư viện riêng.

Điều gì nếu có một lỗi trong thư viện và bạn cần sửa nó? Hoặc một số thay đổi theo luật định hoặc quy định đi kèm có nghĩa là bạn phải thay đổi cách thư viện hoạt động?

Nếu nó nằm trong một thư viện riêng thì bạn có thể (có khả năng) sửa thư viện, kiểm tra lại và triển khai lại và mọi lợi ích của ứng dụng từ bản sửa lỗi.

Nếu chỉ trong mã nguồn là "cục bộ" cho mỗi ứng dụng, thì bạn phải thay đổi, xây dựng lại, kiểm tra lại và triển khai lại từng ứng dụng riêng lẻ . Đó là một nhiều lớn hơn (tức là tốn kém hơn) tập thể dục.

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.