Mam teraz kilka dużych, opartych na sieci produktów dla wielu najemców, i wkrótce zobaczę, że będzie wiele dostosowań, które są specyficzne dla najemcy.
Dodatkowe pole tu czy tam, może dodatkowa strona lub dodatkowa logika w środku przepływu pracy - tego rodzaju rzeczy.
Niektóre z tych dostosowań można wprowadzić do podstawowego produktu i to świetnie. Niektóre z nich są bardzo specyficzne i mogłyby wchodzić w drogę innym.
Mam na myśli kilka pomysłów na zarządzanie tym, ale żaden z nich nie wydaje się dobrze skalować. Oczywistym rozwiązaniem jest wprowadzenie mnóstwa ustawień na poziomie klienta, umożliwiających włączenie różnych „funkcji” dla poszczególnych klientów. Minusem tego jest oczywiście ogromna złożoność i bałagan. Możesz wprowadzić naprawdę ogromną liczbę ustawień, az czasem różne rodzaje logiki (prezentacja, biznes) mogą wymknąć się spod kontroli. Następnie pojawia się problem pól specyficznych dla klienta, który prosi o coś czystszego niż dodanie do istniejących tabel kilku pól zerowalnych.
Co więc robią ludzie, aby sobie z tym poradzić? Force.com wydaje się być mistrzem rozszerzalności; oczywiście stworzyli platformę od podstaw, która jest super rozszerzalna. Możesz dodać do prawie wszystkiego za pomocą interfejsu internetowego. FogBugz zrobił coś podobnego, gdy stworzył solidny model wtyczki, który, jeśli się nad tym zastanowić, mógł być zainspirowany Mocą. Wiem, że poświęcili na to dużo czasu i pieniędzy i jeśli się nie mylę, zamierzałem wykorzystać je wewnętrznie do przyszłego rozwoju produktu.
Brzmi jak coś, co kusiło by mnie do zbudowania, ale prawdopodobnie nie powinno. :)
Czy jedyna droga to ogromna inwestycja w architekturę wtykową? Jak radzisz sobie z tymi problemami i jakie widzisz wyniki?
EDYCJA: Wygląda na to, że FogBugz poradził sobie z tym problemem, budując dość solidną platformę, a następnie wykorzystując ją do złożenia swoich ekranów. Aby go rozszerzyć, należy utworzyć bibliotekę DLL zawierającą klasy, które implementują interfejsy, takie jak ISearchScreenGridColumn, i która staje się modułem. Jestem pewien, że zbudowanie tego urządzenia było niezwykle drogie, biorąc pod uwagę, że mają dużą liczbę programistów i pracowali nad nim przez miesiące, a ich powierzchnia wynosi prawdopodobnie 5% wielkości mojej aplikacji.
W tej chwili poważnie zastanawiam się, czy Force.com jest właściwym sposobem na poradzenie sobie z tym problemem. Jestem twardym facetem ASP.Net, więc jest to dziwna pozycja, w której mogę się znaleźć.
źródło
Odpowiedzi:
Napotkałem podobny problem i powiem ci, jak to zrobiłem.
Po pierwsze, istnieje biblioteka lub silnik „rdzenia”. To w zasadzie prowadzi program, o ile już się zorientowałeś. Obsługuje rzeczy wspólne dla każdego systemu, od dynamicznego renderowania formularzy, zarządzania użytkownikami i kontami, ról, jak go nazywasz, robi to.
Każda część systemu jest zawarta w module. Moduł ma zależności (inne moduły, od których zależy). Na przykład system „podstawowy” ma zabezpieczenia (użytkownicy, grupy, role, zasady haseł), ustawienia regionalne (tłumaczenia, kraje, kultury), repozytorium plików, e-mail itp. Każdy moduł definiuje się za pomocą pliku xml. Plik xml zasadniczo określa schematy, tabele, klasy obliczeniowe, definicje ekranów itp. Są one odczytywane podczas uruchamiania aplikacji, jeśli data pliku uległa zmianie .
Moduły specyficzne dla klienta mają własne pliki xml i własną bibliotekę DLL. Wszystko plus i działa odpowiednio i przejrzyście z resztą systemu. Aż do zastąpienia istniejących widoków MVC niestandardowymi, niestandardowym kodem i niestandardowymi modelami widoków.
Jeśli klient chce rozszerzyć istniejącą funkcjonalność, xml / system zapewnia metodę, w której mogę „wyprowadzić” jeden moduł z drugiego. Nowy moduł ma wszystkie istniejące funkcje, ale ze specyficznymi wymaganiami klienta w nowej bibliotece DLL oraz z rozszerzonym plikiem XML, który może dokonywać modyfikacji. Zastrzeżenie polega na tym, że w rzeczywistości nie mogą usunąć istniejących pól w tym systemie, ale możemy go rozszerzyć i zapewnić zupełnie nowe obiekty i funkcje.
źródło
Posiadanie dużej ilości logiki wersjonowania i warstw kodu do zarządzania nie stanowi wartości dodanej dla Twojej aplikacji / witryny internetowej. Wymaga także większej mocy mózgu, aby zrozumieć, co się dzieje, i odwraca uwagę od rdzenia tego, co robisz.
Radzę inaczej. Radzę, aby sprawy były proste, a nie złożone.
Zachowaj jedną bazę kodu, która jest taka sama dla wszystkich. Każda dodana funkcja jest funkcją dla wszystkich. Ograniczaj tylko liczbę przedmiotów lub miejsca do przechowywania lub jakieś wymierne rzeczy, a nie funkcje. Powodem jest ilościowe określenie rzeczy, takich jak pamięć, liczba wpisów danych itp., Których programowanie jest tak proste i można je zastosować do niewielkiej garści rzeczy, które naprawdę ograniczają użytkownika do szaleństwa w Twojej aplikacji. To musi być zaprogramowane tylko po dodaniu elementów zamiast logiki funkcji. Co jeśli funkcje są powiązane z innymi funkcjami? Kodowanie tego jest bardzo skomplikowane.
Aby zakwalifikować moją odpowiedź, zbudowałem platformę e-commerce, którą mam dla wielu klientów i nauczyłem się trudnego sposobu zachowania wszystkich ich osobliwości. Skończyło się na zerwaniu łańcucha i stworzyłem jedną stronę administracyjną, która jest wielodostępna dla e-commerce. Następnie mam strony internetowe, które pobierają dane z połączeń serwisowych. Dzięki temu różne zespoły w różnych technologiach mogą wdrażać określone funkcje witryn e-commerce, a ja co miesiąc zarabiam na tej samej infrastrukturze i nie dbam o to, co robią. Ograniczam użycie tylko liczbami, a nie funkcjami. To łatwiejsze. Klient może wybrać własnego dostawcę do budowy swojej witryny i nie jestem już zaangażowany w te decyzje.
Mam również usługę subskrypcji SAAS do zarządzania treścią. Działa to również według poziomów użytkowania, a klienci mogą dodawać własne wtyczki, jeśli chcą, podczas gdy mój zespół dodaje więcej funkcji dla wszystkich.
To tylko moje doświadczenie z uderzenia głową w ścianę po tak długim czasie, a następnie natknięcia się na coś prostszego.
Jeśli coś zawsze będzie specyficzne dla każdego klienta, nie twórz ram dla tego. Podziel go na najprostsze części, aby część ramowa działała dla wszystkich, a następnie wytnij resztę, abyś mógł ją rozszerzyć dla osoby.
źródło
Oprogramowanie, nad którym pracuję, ma dodatkowe pola dla rozszerzenia użytkownika. Każdy element danych dla tych pól można przypisać do istniejącego wiersza w głównych tabelach aplikacji. Na przykład jeśli twoje oprogramowanie zawiera klientów, a każdy klient listę zamówień, wówczas dostosowywana tabela danych będzie zawierała kolumnę dla kluczy obcych do tabeli klientów i tabeli zamówień, z których tylko jedna będzie inna niż null. Albo to, albo kilka tabel, z których każda ma niestandardowe pola dla jednej tabeli.
Jest to prosty i wydajny sposób przechowywania dodatkowych danych dla użytkownika. Konieczne byłoby przechowywanie dodatkowych informacji o nazwach i typach tych pól.
Dotyczy to niestandardowych pól dla klienta. W przypadku niestandardowego zachowania interfejs API usług internetowych zezwala na rozszerzenia.
źródło
1) Uruchamianie kodu innej osoby na posiadanych urządzeniach jest dość trudnym problemem. Albo możesz im zaufać, albo rozsądnie odroczyć odpowiedzialność, będziesz musiał bardzo mocno wyodrębnić ich kod i mieć ponadprzeciętne przywiązanie do bezpieczeństwa. Ponieważ system wtyczek pozwala na większą funkcjonalność, rośnie trudność zapewnienia bezpieczeństwa. Rzeczy takie jak odmowa usługi (wtyczki zużywają zbyt dużo zasobów), wyciek informacji (wtyczki mogą uzyskiwać dostęp do danych innych najemców) itp. Mogą być bardzo realne i kłopotliwe, nie wziąłbym w tym udziału, chyba że mógłbym bardzo dobrze poznać ludzi te problemy lub bardzo zdolni ludzie, którzy mają dużo czasu, aby to naprawić.
2) Tak, modułowość i możliwości dostosowania są trudne. Takie rzeczy jak wzorzec strategii może pomóc (wymyślna nazwa wskaźników funkcji; w Javie jest zwykle implementowana przez zadeklarowanie interfejsu, który użytkownicy klasy mogą zaimplementować w celu dostosowania zachowania twojego kodu), ale będziesz chciał być bardzo odizolowany i oddzielony kod, aby to działało.
3) Pod względem danych może to być jeden z przykładów przydatnego przechowywania bez schematów. Jeśli masz relacyjny model danych, problematyczne są tabele z dużą ilością kolumn dla różnych klientów (tak, masz wiele zerowalnych kolumn, co jest złe ; jednym z powodów jest to, że ustawienie poprawnych ograniczeń jest trudne lub niemożliwe) ograniczenia, które nie pozwalają na pojawienie się nieprawidłowych kombinacji wartości null]). Dodawanie klienta konkretnych tabel (czyli
users
afoo_users
, zusers
gospodarstwa pól ważny dla wszystkich klientów ifoo_users
posiadające specyficzne fileds Foo) jest lepszy; możesz łatwo mieć poprawne ograniczenia, ale RDBMS może nie poradzić sobie z tym płynnie (z powodu eksplozji łączenia, ograniczeń liczby tabel itp.) i prawdopodobnie będzie wyglądał brzydko w twoim kodzie.Może się zdarzyć, że zaimplementujesz magazyn kluczy i wartości w twoim systemie RDBMS, co sprawi, że Twój model danych będzie mniej relacyjny i spowoduje dyskomfort (tj. Relacyjne bazy danych działają najlepiej z modelami relacyjnymi). Nie jestem pewien, czy rozwiązanie NoSQL ogólnie pasuje do problemu, ale niefrasobliwość większości implementacji może być zaletą.
źródło