2012-11-29 14 views
5

Mam aplikację C# WinForms w Visual Studio 2010, z której korzystają dwaj różni klienci. Podstawowa funkcjonalność aplikacji jest taka sama dla każdego klienta, ale niektóre linie kodu (nazwy procedur składowanych, zasoby, niektóre zachowania) są różne w różnych wersjach. Do tej pory zachowałem aplikację w tym samym projekcie i użyłem dyrektyw preprocesora podczas budowania/publikowania, aby przełączać się między tym, z którego wdrożenia korzystać. Jednak zakres projektu urósł do punktu, w którym nie jest to już możliwe.Obsługa i wdrażanie dwóch wersji aplikacji jednocześnie

Ponieważ tak dużo kodu jest udostępniane, staram się unikać powielania plików kodu źródłowego. Zastanawiam się, jakie jest najlepsze podejście do utrzymania aplikacji, która wymaga jednoczesnego wdrażania różnych wersji.

+0

Dyrektywy preprocesora nie powinny być używane do obsługi gałęzi. –

+0

Uzgodnione. Zaczynało się to od małej, wewnętrznej aplikacji, którą interesowali się klienci zewnętrzni, dlatego potrzebowaliśmy szybkiego rozwiązania problemu separacji. – WickerPopstar

Odpowiedz

4

Użyj interfejsów, aby zdefiniować swoje klasy. Posiadanie interfejsu oznacza, że ​​możesz mieć wiele implementacji tego samego interfejsu, po jednym dla każdego z klientów. Będzie to wymagało analizy istniejącej bazy kodów i identyfikacji logicznych separacji w kodzie, w którym można zdefiniować te interfejsy.

Następnie użytkownik może załadować interfejs zgodnie z potrzebami klienta. Możesz na przykład zrobić to poprzez konfigurację. Na podstawie wartości konfiguracyjnej wczytujesz Implementation1 lub Implementation2. Istnieje wiele, wiele sposobów na osiągnięcie tego konkretnego kawałka. Powinieneś przeczytać na temat wstrzyknięcia zależności, odwrócenia kontroli i spojrzeć na narzędzia takie jak Ninject, Autofac, Unity.

Może to być na początku trudne, biorąc pod uwagę sposób, w jaki korzystasz z dyrektyw preprocesora, ale widząc jak aplikacja rośnie, będziesz potrzebować tego refaktoryzacji. Pamiętaj, że jeśli nie zrobisz tego teraz, refaktoryzacja będzie dużo droższa później, gdy twoja aplikacja stanie się bardziej skomplikowana.

+0

Miałem przeczucie, że to problem architektury, i dzięki za terminologię (zastrzyk zależności, IOC, itp.). To były terminy, których mi brakowało podczas szukania rozwiązania. – WickerPopstar

2

Różne funkcje powinny być częścią architektury aplikacji. Jeśli potrzebujesz różnych funkcji dla różnych klientów, rozwiń je - utwórz interfejs, który otoczy zachowanie, a następnie zaimplementuj go na dwa różne sposoby w dwóch różnych złożeniach. Następnie (w zależności od mechanizmu wdrażania) możesz wysłać aplikację z jedną lub drugą biblioteką DLL. Aby uniknąć ponownej kompilacji, dodawania odniesień, itp., Możesz używać frameworków Dependency Injection takich jak Ninject, Castle Windsor, MEF itd. To jest architektura "podobna do wtyczki", jeśli kod jest wystarczająco inny.

Jeśli mówisz o tekście, kolorach, podstawowych różnicach, po prostu nie powinny być one sztywno zakodowane, lecz oparte na danych. Jeśli twoja aplikacja jest podłączona do Internetu, może pobrać odpowiednie ustawienia, gdy użytkownik się zaloguje. Inaczej, coś, co wskazywałoby na to, że tekst/kolory/zachowanie można umieścić w pliku konfiguracyjnym specyficznym dla klienta. Możesz użyć transformacji config, aby uprościć ten proces.

+0

Podstawowe różnice są już oparte na danych, na szczęście. To przede wszystkim funkcjonalność. Nie jestem zaznajomiony z tymi frameworkami, ale ta aplikacja używa wdrożenia ClickOnce. Czy to zmienia sposób wdrażania tych ram? – WickerPopstar

+0

Mam dokładnie taką samą sytuację w moim projekcie. Ninject, inne struktury DI będą działały, ale dynamicznie pobierane są biblioteki DLL z adresu URL po zainstalowaniu aplikacji: w przeciwnym razie każdy klient otrzymuje bibliotekę DLL z całą logiką innych klientów we własnej instalacji. Nie zmienia się zbytnio, wystarczy, że ładujesz zestawy z adresu URL, a nie z dysku. Albo co możesz zrobić z dysku i tak :) –

0

Być może niektóre różnice można oddzielić, korzystając z plików zasobów, konfiguracji lub właściwości. Rozumiem przez to, że przechowujesz jakąś wartość w pliku, taką jak nazwa procedury przechowywanej do użycia w konkretnej sytuacji. Następnie twój kod odczytuje nazwę z pliku i uruchamia ją. Możesz zmienić wartości w pliku bez potrzeby ponownego budowania kodu dla każdego wdrożenia.

Powiązane problemy