Có phải nó không đúng cách / Thiết kế xấu để đặt một chủ đề / công nhân nền trong một lớp?


15

Tôi có một lớp sẽ đọc từ Excel (C # và .Net 4) và trong lớp đó tôi có một nhân viên nền sẽ tải dữ liệu từ Excel trong khi UI vẫn có thể phản hồi. Câu hỏi của tôi là như sau: Có phải là một thiết kế xấu khi có một nhân viên nền trong một lớp học? Tôi có nên tạo lớp của mình mà không có nó và sử dụng một nhân viên nền để vận hành trên lớp đó không? Tôi không thể thấy bất kỳ vấn đề nào thực sự tạo ra lớp học của mình theo cách này nhưng sau đó tôi lại là một người mới nên tôi nghĩ rằng tôi sẽ đảm bảo trước khi tiếp tục.

Tôi hy vọng rằng câu hỏi này có liên quan ở đây vì tôi không nghĩ nó nên có trên stackoverflow khi mã của tôi hoạt động, đây chỉ là một vấn đề thiết kế.


3
tại sao bạn nghĩ rằng nó có thể sai?
Alb

1
@ Alb - thật khó để nói Mã của tôi hoạt động và đáp ứng nhu cầu của tôi, tuy nhiên, tôi dự định sử dụng điều này trong một dự án mà tôi sẽ tạo nguồn mở. Tôi muốn đảm bảo rằng mã của tôi không "chỉ hoạt động" và thực sự được thiết kế tốt.
Jetti

Câu trả lời:


21

Tôi có nên tạo lớp của mình mà không có nó và sử dụng một nhân viên nền để vận hành trên lớp đó không?

Vâng, bạn nên. Và tôi sẽ cho bạn biết lý do - bạn đang vi phạm Nguyên tắc Trách nhiệm duy nhất . Bằng cách kết hợp chặt chẽ lớp truy cập tài liệu excel với cách nó truy cập tài liệu excel, bạn loại bỏ khả năng mã "trình điều khiển" (bất kỳ mã nào sử dụng mã này) để thực hiện theo cách khác. Làm thế nào khác nhau, bạn có thể yêu cầu? Điều gì xảy ra nếu mã điều khiển có hai thao tác mất nhiều thời gian nhưng muốn chúng là tuần tự? Nếu bạn cho phép bộ điều khiển khả năng xử lý luồng, nó có thể thực hiện cả hai tác vụ chạy dài cùng nhau trong một luồng. Điều gì xảy ra nếu bạn muốn truy cập tài liệu excel từ ngữ cảnh không phải UI và không cần phải xử lý luồng?

Bằng cách chuyển trách nhiệm phân luồng ra cho người gọi, bạn cho phép mã linh hoạt hơn, làm cho nó có thể tái sử dụng nhiều hơn.


2
+1 để trả lời câu hỏi thực tế được hỏi và trả lời tốt.
Adam Lear

+1 - Cảm ơn bạn Nemi. Bạn trả lời câu hỏi của tôi trên, tôi đánh giá cao nó. Tôi sẽ rút nó ra khỏi lớp và đưa nó vào một lớp mới, cảm ơn bạn một lần nữa!
Jetti

@Nemi - vậy có thể chấp nhận được không nếu tôi tạo một phương thức khác có thể tải đồng bộ và sau đó có phương thức không đồng bộ? Hoặc sẽ tốt hơn nếu có một phương thức tải đồng bộ và sau đó đi từ đó?
Jetti

1
Cá nhân tôi sẽ không có phương thức đồng bộ hóa và phương pháp không đồng bộ. Bạn vẫn đang ghép trách nhiệm. Tôi đã làm việc với vấn đề chính xác này nhiều lần. Những gì tôi đã làm là tạo ra một Trình điều khiển tác vụ được mô hình hóa sau SwingWorker, nhưng có mã cụ thể cho ứng dụng của chúng tôi. Trình điều khiển tác vụ đã làm những việc như cập nhật thanh tiến trình, thay đổi con trỏ chuột, v.v ... Có vẻ như mã tấm nồi hơi luôn phải tạo một Trình điều khiển tác vụ để thực hiện cuộc gọi, nhưng cuối cùng, mã này mạnh hơn và dễ bảo trì hơn.
Nemi

Cảm ơn Nemi! Tôi ước tôi có thể nâng cao bạn một lần nữa bởi vì bạn chắc chắn đã trả lời câu hỏi của tôi và chỉ cho tôi đi đúng hướng. Cám ơn bạn một lần nữa!!
Jetti

3

Đó là thiết kế tốt để có các hoạt động UI hoạt động trong một luồng riêng biệt từ các tác vụ nền. Nếu không, UI trở nên không phản hồi khi ứng dụng bận.

Nếu bạn có thể tách phần hoạt động trong luồng nền sang lớp riêng của nó, mã sẽ sạch hơn.


1
Mặc dù đúng, từ cách tôi đọc câu hỏi của anh ấy, anh ấy không gặp vấn đề gì trong việc hiểu điểm này.
Nemi

Tôi xin lỗi nếu câu hỏi của tôi bị đọc sai. Tôi biết rằng tách giao diện người dùng và các tác vụ nền là thiết kế tốt (nếu không cần thiết, tệp excel thử nghiệm của tôi có hơn 8k hàng và sẽ khiến chương trình có vẻ không phản hồi). Câu hỏi của tôi về cơ bản là tốt để kết hợp chặt chẽ chuỗi với lớp Excel.
Jetti

0

Tôi sẽ tách UI của bạn khỏi tác vụ nền của bạn bằng các lớp riêng biệt. Làm như vậy khuyến khích sự tách biệt các mối quan tâm. Mã UI và logic nghiệp vụ không nên trộn lẫn.


Nói rõ hơn, lớp tôi không chạm vào UI. Nó có hai sự kiện cho phép bất cứ điều gì đang sử dụng nó để cập nhật giao diện người dùng nếu cần thiết, nhưng bản thân lớp tôi không chạm vào giao diện người dùng.
Jetti

0

Từ những gì tôi nhớ về BackgroundWorkers là họ cung cấp một số phương thức liên kết như khả năng gửi các bản cập nhật tiến độ tới UI. Không có quy tắc nào nói rằng bạn không thể sử dụng nó từ một lớp khác.

Ngoài ra, nếu bạn đang thực hiện việc lặp mà không yêu cầu các mục được xử lý theo một thứ tự cụ thể, hãy xem xét sử dụng ThreadPool thay thế (hoặc nếu bạn đang trên .NET 4 sử dụng Thư viện song song tác vụ ).


Cám ơn phản hồi của bạn. Tôi đã tạo hai sự kiện trong lớp sẽ kích hoạt tiến trình (về cơ bản bao bọc sự kiện tiến trình BackgroundWorker, vì BackgroundWorker là riêng tư) sẽ gửi tiến trình đến UI (thanh tiến trình).
Jetti
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.