Nguy hiểm của ứng dụng nguyên khối khổng lồ


20

Dự án lớn mà tôi đang thực hiện trong vài năm nay là một ứng dụng điều khiển (và mọi thứ) của một thiết bị tiên tiến, trái tim của phần sụn.

Thiết bị này khá tiên tiến, với nhiều chức năng khác nhau hơn tôi có thể nói từ bộ nhớ và 98% trong số chúng được xử lý bởi một thực thi khổng lồ này. Một mặt, chương trình này khá dễ bảo trì, được mô đun hóa tốt bên trong, được ghi chép đúng cách, có sự phân tách hợp lý các chức năng bởi các thư mục và tệp, v.v.

Nhưng cuối cùng, tất cả được tập hợp thành một ứng dụng thực hiện mọi thứ từ giao tiếp cơ sở dữ liệu từ xa, xử lý màn hình cảm ứng, xử lý hàng tá giao thức truyền thông, đo lường, một số thuật toán điều khiển, quay video, thời gian mặt trời mọc và ngày lễ Phục sinh (nghiêm túc, và chúng là cần thiết cho các mục đích rất nghiêm trọng!) ... Nói chung, những thứ liên quan rất mỏng, thường chỉ liên quan thông qua một số dữ liệu nhỏ giọt giữa một số mô-đun xa.

Nó có thể được thực hiện khi một số thực thi riêng biệt giao tiếp với nhau, giả sử, qua các ổ cắm, với mục đích cụ thể hơn, có thể được tải / dỡ khi cần, v.v. Không có lý do cụ thể tại sao nó được thực hiện theo cách này.

Trong một tay, nó hoạt động, và nó hoạt động tốt. Dự án đơn giản hơn, không cần duy trì xây dựng nhiều nhị phân. Cấu trúc bên trong cũng dễ dàng hơn, khi bạn chỉ có thể gọi một phương thức hoặc đọc một biến thay vì nói chuyện qua các socket hoặc bộ nhớ dùng chung.

Nhưng mặt khác, kích thước, quy mô của thứ này chỉ khiến tôi phát điên, cảm giác như đang lái Titanic. Tôi luôn được dạy để mô đun hóa, và gộp mọi thứ vào một tập tin khổng lồ cảm thấy sai. Một vấn đề tôi biết là sự cố nghiêm trọng của một mô-đun (thậm chí không đáng kể) bị sập tất cả - nhưng chất lượng mã đảm bảo điều này không thực sự xảy ra trong các phiên bản phát hành. Mặt khác, phân tách nội bộ và lập trình phòng thủ đảm bảo điều này vẫn sẽ chạy chính xác ngay cả khi một nửa các mô-đun bên trong thất bại bình thường vì một số lý do.

Những nguy hiểm khác tôi đã bỏ qua? Tại sao điều này làm tôi khó chịu? Đây chỉ là nỗi sợ phi lý không rõ? Là làm cho các dự án lớn nghiêm trọng theo cách này là một thực tế được chấp nhận? Hoặc làm dịu nỗi sợ hãi của tôi hoặc cho tôi một lý do chính đáng để tái cấu trúc phiên bản 2.0 thành nhiều tệp nhị phân nhỏ hơn.


7
Nếu mặt trời mọc quá sớm, nước Anh sẽ trôi ra biển.
Tối đa

1
Hoặc áp lực trong lõi Trái đất tăng nhẹ.
StuperUser

1
@Maxpm Tôi thấy những gì bạn đã làm ở đó ... xkcd.com/687
teto

3
@Maxpm: May mắn thay, ứng dụng của chúng tôi không lái bình minh và hoàng hôn. Chúng tôi tin rằng Công chúa Celestia sẽ không thất bại trong công việc của mình.
SF.

1
@rwong: 1. Thiết bị bị dừng để nâng cấp. Mặc dù nó sẽ tồn tại các bản cập nhật một cách nhanh chóng, chúng tôi không muốn bất kỳ kết quả bất ngờ nào trong trường hợp cập nhật bị lỗi vì bất kỳ lý do nào. 2. ARM9 lõi đơn với Linux nhúng. Có một CPU thứ hai, giám sát hoạt động mà không cần hệ điều hành, xác minh CPU chính tạo ra đầu ra lành mạnh.
SF.

Câu trả lời:


5

Ngoại trừ nhận xét nhỏ ở cuối (thứ hai, CPU giám sát), bạn có thể mô tả công ty của tôi. Yup, chúng ta cũng cần lễ Phục sinh.

Vâng, chúng tôi một chút nữa cùng. Chúng tôi đã phân tách thực thi lớn và cố gắng sử dụng các thành phần tiêu chuẩn cho các bit tiêu chuẩn. Không chính xác là sự cải thiện lớn mà bạn hy vọng. Trong thực tế, hiệu suất đang trở thành một nỗi đau lớn ngay cả trên phần cứng mạnh hơn. Và chi phí bảo trì chưa thực sự giảm khi có hàng tấn mã để tuần tự hóa và đồng bộ hóa dữ liệu trên các giao diện hẹp.

Bài học tôi đã học? Có một thực thi duy nhất là một giải pháp đã được chứng minh tốt cho các hệ thống nhỏ và chúng tôi có nhiều thập kỷ kinh nghiệm trong việc quản lý nó. Tất cả các công cụ của chúng tôi hỗ trợ nguyên bản. Tính mô đun cũng có thể được thực hiện trong một lần thực thi, và khi bạn cần thỏa hiệp về tính mô đun vì các lý do khác thì hack vẫn còn nhỏ.


Cảm ơn - không có mục "thực hành tốt nhất để được theo dõi / hy sinh" và "trọng số lợi ích tiềm năng so với nhược điểm tiềm năng" có ích như những người có kinh nghiệm trực tiếp từ phía bên kia của hàng rào.
SF.

23

Thiết bị này khá tiên tiến, với nhiều chức năng khác nhau hơn tôi có thể nói từ bộ nhớ và 98% trong số chúng được xử lý bởi một thực thi khổng lồ này. Một mặt, chương trình này khá dễ bảo trì, được mô đun hóa tốt bên trong, được ghi chép đúng cách, có sự phân tách hợp lý các chức năng bởi các thư mục và tệp, v.v.

Bạn tự nói điều đó - nó khá dễ bảo trì, được mô đun hóa tốt ...

Theo tôi, và hầu hết quản lý sẽ đồng ý với tôi về vấn đề này, những thay đổi không bao giờ nên được thực hiện vì lợi ích của những thay đổi. Không có gì sai với chương trình này (mô tả của bạn) ngoài việc nó không tuân theo các xu hướng lập trình mới nhất (được đề cập trong các câu trả lời khác).

Vâng, đó là một chương trình lớn hơn ... nhiều người trước đây cũng đã từng. Nó cũng được ghi chép lại, vì vậy tất cả những gì bạn phải làm là nghiên cứu tổ chức nội bộ của nó và bạn sẽ thấy logic trong đó. Tôi nghi ngờ rằng tất cả những người trước khi bạn viết nó là bất tài. Vì vậy, hãy khám phá nó một chút, tìm hiểu nó ... sau đó, duy trì nó như vậy cho đến khi một lý do chắc chắn để viết lại nó bật lên. Người quản lý của bạn sẽ biết ơn bạn vì có tỷ lệ chi phí / hiệu ứng tốt.

Những nguy hiểm khác tôi đã bỏ qua? Tại sao điều này làm tôi khó chịu? Đây chỉ là nỗi sợ phi lý không rõ? Là làm cho các dự án lớn nghiêm trọng theo cách này là một thực tế được chấp nhận? Hoặc làm dịu nỗi sợ hãi của tôi hoặc cho tôi một lý do chính đáng để tái cấu trúc phiên bản 2.0 thành nhiều tệp nhị phân nhỏ hơn.

Nó làm bạn khó chịu vì nó lớn - nhưng sau đó, một lần nữa, không ai mong bạn sẽ học được tất cả trong một tuần. Vì vậy, làm việc, từng mảnh, từng chút một, cho đến khi bạn có được hang của nó. Cuối cùng, bạn sẽ biết rằng nó có thể được tổ chức tốt như nó là, và nó được tổ chức như thế nào.

Nếu bạn viết lại nó, bạn sẽ hoàn thành tương tự, nhưng đồng thời làm hỏng nó cho tất cả những người đã quen với tổ chức mã trước đó. Bằng cách này, chỉ có bạn phải "thích nghi".


16

Tôi sẽ cảm thấy tốt hơn nếu bạn nói rằng bạn có mọi thứ được bao bọc trong các bài kiểm tra đơn vị. Nếu bạn không, bạn nên xây dựng một bộ thử nghiệm trước khi nghĩ đến việc tìm kiếm lại ứng dụng.

Có một bộ kiểm tra sẽ cải thiện sự hiểu biết của bạn về ứng dụng và sẽ cho bạn biết khi nào một thay đổi trong ứng dụng phá vỡ một cái gì đó.


2
Nhưng điều đó áp dụng cho cả kiến ​​trúc có thể ...
SF.

3
Vâng, đúng vậy ...
Robert Harvey

10
... và do đó, câu trả lời này không thêm bất cứ điều gì vào cuộc thảo luận ngoại trừ để thúc đẩy thử nghiệm đơn vị.
benzado

2
@benzado: Trong kịch bản của OP, có tầm quan trọng tối đa.
Robert Harvey

2
@ironcode: Hãy xem một cuốn sách như "Làm việc hiệu quả với Mã kế thừa". Điều đầu tiên anh nói trong cuốn sách đó là "Nếu bạn chưa có bộ kiểm tra đơn vị với độ bao phủ mã cao, hãy viết chúng trước, trước khi bạn làm bất cứ điều gì khác. " Tôi nói rằng lời khuyên đó có liên quan nhiều hơn ở đây, cho rằng OP đặc biệt hỏi "Tôi đã bỏ qua những nguy hiểm nào khác."
Robert Harvey

8

Nếu mã được mô đun hóa tốt với độ khớp nối thấp và độ gắn kết cao, nó được phân vùng hiệu quả. Chi phí truyền thông phải thấp hơn trong một quy trình so với trường hợp có nhiều quy trình.

Đối với các hệ thống nhúng, một quy trình của bạn có thể loại bỏ nhu cầu triển khai O / S để chạy tất cả các quy trình bạn sẽ tạo. Bạn cũng sẽ cần phải thực hiện một hệ thống để kiểm tra xem tất cả các quy trình đang chạy và khởi động lại chúng nếu có thể. Nếu không thể, bạn sẽ cần phải phản ứng tương ứng.

Việc tách mã thành các tệp thực thi riêng biệt cũng sẽ làm tăng kích thước tổng thể của mã nguồn khi bạn cần triển khai tất cả mã máy khách / máy chủ giữa các mô-đun. Bạn cũng sẽ cần nhiều trường hợp kiểm tra hơn để xử lý mã này và các trường hợp khi quá trình máy chủ không có ở đó. Các dự án lớn là lớn, loại bỏ sự phức tạp không cần thiết như đã được thực hiện ở đây giúp giữ cho chúng nhỏ nhất có thể.

Thử nghiệm là một loại cá trích đỏ ở đây, vì các vấn đề sẽ vẫn còn đó dù có hay không có thử nghiệm. Thử nghiệm tốt với một trong hai lựa chọn thiết kế chắc chắn nên được khuyến khích. Tôi mong đợi, thử nghiệm đơn giản hơn với mã nguyên khối.

Buộc một sự cố khi cần thiết cũng dễ dàng hơn với một thực thi nguyên khối.


1
+1, kỹ thuật là về sự đánh đổi, các nhị phân nhỏ hơn cũng có chi phí
benzado

+1 Tôi đồng ý hết lòng. Không có lý do cụ thể được đưa ra để đảm bảo nhiều thực thi. Giao tiếp và phối hợp giữa các thực thi có giá của nó.
Erick Robertson

+1: Nếu nó không bị hỏng, đừng sửa nó.
Bob Murphy

1

Nếu tôi làm việc trên một ứng dụng nguyên khối lớn như vậy, những thứ khiến tôi hoảng sợ là thiếu sự đóng gói, độ gắn kết thấp, khớp nối cao và cách kiểm tra tất cả những điều này. Những tảng đá nguyên khối lớn thường là một lời mời từ bỏ kiến ​​trúc phù hợp và bắt đầu đi xuống một quả bóng bùn lớn .

Một khi điều đó đang xảy ra, thử nghiệm trở thành một cơn ác mộng và bạn đang trên con đường lạc hậu.

Tuy nhiên, nếu mã của bạn được cấu trúc tốt, và được duy trì tốt, và các nguyên tắc gắn kết cao, khớp nối thấp và đóng gói phù hợp được tuân thủ, thì tôi thấy ít lý do để cấu trúc lại nó thành các đơn vị nhỏ hơn.

Bạn muốn có bài kiểm tra tốt tại chỗ, mặc dù.


1

Lý tưởng nhất, câu trả lời là có. Có nhiều nhị phân có khả năng làm cho nó ổn định hơn ....

... tuy nhiên, bạn cũng đã đề cập rằng mã trong cơ sở mã nguyên khối được viết và mô đun hóa tốt, điều đó có nghĩa là bạn không phải đối phó với một mớ hỗn độn lớn, chỉ là một cơ sở mã khổng lồ ...

Nhìn chung, tôi sẽ nói rằng câu nói phù hợp là "Đừng để người hoàn hảo là kẻ thù của điều tốt". Mặc dù tôi cảm thấy rằng bạn đúng khi nói rằng một cơ sở mã nguyên khối là xấu, tôi cũng cảm thấy rằng nó không đáng để nỗ lực để lo lắng về nó.

Sẽ là hợp lý khi tiến lên phía trước bằng cách đặt các đoạn mã mới vào nhị phân của riêng họ, nhưng quay lại và tái cấu trúc có lẽ không đáng để bạn sử dụng.


1

Nếu bạn đang sử dụng một tiến trình đơn lẻ, có một số cơ hội hơn một con trỏ hoang dã từ một trong các mô-đun phụ của bạn sẽ làm hỏng một phần bộ nhớ quan trọng (và phá vỡ toàn bộ sự việc).

Nếu bạn đang sử dụng các quy trình khác nhau, ít nhất bạn không sử dụng cùng một heap hoặc ngăn xếp cuộc gọi và cũng có thể dễ dàng hơn để khởi động lại một quy trình con.

Cấu trúc bên trong cũng dễ dàng hơn, khi bạn chỉ có thể gọi một phương thức hoặc đọc một biến thay vì nói chuyện qua các socket hoặc bộ nhớ dùng chung.

Việc phân chia lại mọi thứ trong nhiều quy trình cũng sẽ buộc bạn phải dọn sạch thiết kế và tránh việc mọi mô-đun bắt đầu sử dụng các phương thức bên trong của các mô-đun khác.

Điều đó được nói rằng nó có thể là một nhiệm vụ khó khăn.

Những gì bạn có thể bắt đầu làm, là quyết định rằng mọi mô-đun mới phải là một quy trình riêng biệt.


Bạn đang giả định rất nhiều về môi trường hệ điều hành và phần cứng thời gian chạy, đặc biệt là khi có liên quan đến phần mềm chữa cháy và thiết bị nhúng.
Patrick Hughes

0

Khi tôi đi vào vương quốc nơi dự án quá lớn để tìm kiếm tất cả cùng một lúc, tôi xây dựng một biểu đồ để treo trên tường, đặt ra tất cả các phần lớn và cách chúng khớp với nhau. Sau đó, khi tôi đang làm việc, tôi có thể tham khảo mô-đun tôi đang tập trung và có một lời nhắc trực quan về cách nó phù hợp với tổng thể.

Hoàn toàn có thể là sự phức tạp và nguy hiểm của việc duy trì một hệ thống xây dựng và phiên bản cho nhiều nhị phân bị ngắt kết nối sẽ vượt xa sự khó chịu của bạn với một dự án lớn và nguyên khối như vậy.

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.