2012-11-29 35 views
5

Tôi có một ứng dụng C# WinForms trong Visual Studio 2010 được sử dụng bởi hai khách hàng khác nhau. Chức năng cơ bản của ứng dụng là giống nhau cho mỗi khách hàng, nhưng một số dòng mã nhất định (tên của các thủ tục lưu trữ, tài nguyên, các hành vi nhất định) khác nhau giữa các phiên bản. Cho đến nay, tôi đã giữ ứng dụng trong cùng một dự án và sử dụng các chỉ thị tiền xử lý khi xây dựng/xuất bản để chuyển đổi giữa triển khai để sử dụng. Tuy nhiên, phạm vi của dự án đã phát triển đến một điểm mà điều này không còn khả thi nữa.Duy trì và triển khai hai phiên bản của một ứng dụng đồng thời

Vì quá nhiều mã được chia sẻ, tôi đang cố gắng tránh sao chép các tệp mã nguồn. Tôi tự hỏi cách tiếp cận tốt nhất là duy trì một ứng dụng đòi hỏi các phiên bản khác nhau sẽ được triển khai đồng thời.

+0

Chỉ thị tiền xử lý không nên được sử dụng để xử lý các chi nhánh. –

+0

Đồng ý. Điều này bắt đầu như một ứng dụng nhỏ trong nhà mà các khách hàng bên ngoài bày tỏ sự quan tâm, vì vậy chúng tôi cần một giải pháp nhanh chóng để tách biệt. – WickerPopstar

Trả lời

4

Sử dụng giao diện để xác định các lớp học của bạn. Có một giao diện có nghĩa là bạn có thể có nhiều triển khai của cùng một giao diện, một cho mỗi máy khách. Điều này sẽ yêu cầu bạn phân tích codebase hiện tại của bạn và xác định các phân tách hợp lý trong mã của bạn nơi các giao diện này có thể được xác định.

Sau đó, bạn có thể tải giao diện khi cần thiết dựa trên ứng dụng khách. Bạn có thể, ví dụ, làm điều này thông qua cấu hình. Dựa trên giá trị cấu hình bạn tải Perform1 hoặc Implementation2. Có rất nhiều, rất nhiều cách để hoàn thành bit cụ thể này. Bạn nên đọc về tiêm phụ thuộc, đảo ngược kiểm soát và có một cái nhìn tại các công cụ như Ninject, Autofac, Unity. Nó có thể thực sự khó khăn lúc đầu xem xét làm thế nào bạn đã được sử dụng chỉ thị tiền xử lý nhưng nhìn thấy như thế nào ứng dụng của bạn đang phát triển, bạn sẽ cần tái cấu trúc này để xảy ra. Hãy ghi nhớ rằng nếu bạn không làm điều đó ngay bây giờ, việc tái cấu trúc này sẽ đắt hơn rất nhiều sau khi ứng dụng của bạn trở nên phức tạp hơn.

+0

Tôi đã có linh cảm nó là một vấn đề kiến ​​trúc, và cảm ơn cho các thuật ngữ (tiêm phụ thuộc, IOC, vv). Đó là những thuật ngữ tôi đã mất tích khi tìm kiếm một giải pháp. – WickerPopstar

2

Chức năng khác nhau phải là một phần của kiến ​​trúc của ứng dụng. Nếu bạn cần chức năng khác nhau cho các khách hàng khác nhau, hãy trừu tượng hóa nó đi - tạo một giao diện kết thúc hành vi, sau đó thực hiện nó theo hai cách khác nhau trong hai hội đồng khác nhau. Sau đó, (tùy thuộc vào cơ chế triển khai của bạn), bạn có thể gửi ứng dụng của mình bằng một tệp DLL hoặc một tệp DLL khác. Để tránh phải biên dịch lại, thêm tài liệu tham khảo, v.v., bạn có thể sử dụng các khuôn khổ Dependency Injection như Ninject, Castle Windsor, MEF vv. Đó là kiến ​​trúc "giống như plugin", nếu mã là đủ khác nhau.

Nếu bạn đang nói về văn bản, màu sắc, sự khác biệt cơ bản, chúng chỉ đơn giản là không được mã hóa cứng mà thay vào đó là hướng dữ liệu. Nếu ứng dụng của bạn kết nối internet, ứng dụng có thể tải xuống các cài đặt thích hợp khi người dùng đăng nhập. Khác, điều gì đó để cho biết văn bản/màu sắc/hành vi có thể được đặt trong tệp cấu hình dành riêng cho khách hàng. Bạn có thể sử dụng các biến đổi cấu hình để đơn giản hóa quá trình đó.

+0

Sự khác biệt cơ bản đã được định hướng dữ liệu, thật may mắn. Đó là chức năng chủ yếu. Tôi không quen với các khung công tác đó, nhưng ứng dụng này sử dụng triển khai ClickOnce. Điều đó có thay đổi cách các khung công tác đó được thực hiện không? – WickerPopstar

+0

Tôi có chính xác tình huống tương tự trong dự án của tôi. Ninject, các khung công tác DI khác sẽ hoạt động, nhưng chúng tôi tự động tải xuống các tệp DLL từ URL sau khi ứng dụng được cài đặt: nếu không, mọi khách hàng sẽ nhận được DLL với tất cả logic của khách hàng khác trong cài đặt của riêng họ. Nó không thay đổi nhiều, chỉ là bạn muốn tải hội đồng từ một URL chứ không phải là đĩa. Hoặc những gì bạn có thể làm điều đó từ đĩa anyway :) –

0

Bạn có thể tách riêng một số khác biệt bằng cách sử dụng các tệp tài nguyên, cấu hình hoặc thuộc tính của một số loại. Bằng cách này, tôi có nghĩa là bạn lưu trữ một số loại giá trị trong tệp, chẳng hạn như tên của thủ tục được lưu trữ để sử dụng trong một tình huống cụ thể. Sau đó, mã của bạn đọc tên từ tệp và chạy nó. Bạn có thể thay đổi các giá trị trong tệp mà không cần phải tạo lại mã của mình cho mỗi lần triển khai.

Các vấn đề liên quan