Piekło zależności - Dependency hell
Piekło zależności to potoczne określenie frustracji niektórych użytkowników oprogramowania, którzy zainstalowali pakiety oprogramowania, które są zależne od określonych wersji innych pakietów oprogramowania.
Problem z zależnościami pojawia się, gdy kilka pakietów ma zależności od tych samych pakietów udostępnionych lub bibliotek, ale zależą one od różnych i niekompatybilnych wersji pakietów udostępnionych. Jeśli udostępniony pakiet lub bibliotekę można zainstalować tylko w jednej wersji, może być konieczne rozwiązanie problemu przez uzyskanie nowszych lub starszych wersji pakietów zależnych. To z kolei może złamać inne zależności i przenieść problem do innego zestawu pakietów.
Problemy
Piekło zależności przybiera kilka form:
- Wiele zależności
- Aplikacja jest uzależniona od wielu bibliotek , wymaga długiego pobierania, dużej ilości miejsca na dysku i jest bardzo przenośna (wszystkie biblioteki są już przeniesione, co umożliwia łatwe przeniesienie samej aplikacji). Trudne może być również zlokalizowanie wszystkich zależności, które można naprawić poprzez posiadanie repozytorium (patrz poniżej). Jest to częściowo nieuniknione; aplikacja zbudowana na danej platformie obliczeniowej (np. Java ) wymaga zainstalowania tej platformy, ale dalsze aplikacje jej nie wymagają. Jest to szczególny problem, jeśli aplikacja korzysta z niewielkiej części dużej biblioteki (co można rozwiązać poprzez refaktoryzację kodu ) lub prosta aplikacja opiera się na wielu bibliotekach.
- Długie łańcuchy zależności
- Jeśli
appzależy odliba, który zależy odlibb, ..., który zależy odlibz. Różni się to od "wielu zależności", jeśli zależności muszą być rozwiązane ręcznie (np. przy próbie instalacjiappużytkownik jestlibanajpierw proszony o zainstalowanie . Przy próbie zainstalowanialibaużytkownik jest następnie proszony o zainstalowanielibbitd.). Czasami jednak podczas tego długiego łańcucha zależności pojawiają się konflikty, gdy wymagane są dwie różne wersje tego samego pakietu (zobacz konflikty zależności poniżej). Te długie łańcuchy zależności można rozwiązać, mając menedżera pakietów, który automatycznie rozwiązuje wszystkie zależności. Poza problemami (w celu ręcznego rozwiązania wszystkich zależności), ręczne rozwiązywanie może maskować cykle zależności lub konflikty. - Sprzeczne zależności
- Jeśli
app1zależy odlibfoo 1.2, iapp2zależy odlibfoo 1.3, a różne wersje programulibfoonie mogą być jednocześnie instalowane, toapp1iapp2nie mogą być jednocześnie używane (lub instalowane, jeśli instalator sprawdzi zależności). Jeśli to możliwe, jest to rozwiązywane przez umożliwienie jednoczesnej instalacji różnych zależności. Alternatywnie istniejąca zależność wraz z całym oprogramowaniem od niej zależnym musi zostać odinstalowana w celu zainstalowania nowej zależności. Problem w systemach Linux z instalowaniem pakietów od innego dystrybutora (co nie jest zalecane lub nawet powinno działać) polega na tym, że wynikający z tego długi łańcuch zależności może prowadzić do konfliktowej wersji standardowej biblioteki C (np. GNU C Library ), od których zależą tysiące pakietów. Jeśli tak się stanie, użytkownik zostanie poproszony o odinstalowanie wszystkich tych pakietów. - Zależności kołowe
- Jeśli
application Azależy od określonej wersji programu i nie może działać bez określonej wersji programuapplication B, aleapplication Bz kolei zależy od określonej wersji programu i nie może działać bez niejapplication A, uaktualnienie dowolnej aplikacji spowoduje uszkodzenie innej. Ten schemat może być głębszy w rozgałęzieniu. Jego wpływ może być dość duży, jeśli dotyczy podstawowych systemów lub samego oprogramowania: menedżer pakietów (A), który do działania wymaga określonej biblioteki wykonawczej (B), może się zablokować (A) w środku procesu, gdy aktualizacja tej biblioteki (B) do następnej wersji. Z powodu nieprawidłowej wersji biblioteki (B), menedżer pakietów (A) jest teraz uszkodzony - dlatego nie jest możliwe wycofanie lub obniżenie wersji biblioteki (B). Typowym rozwiązaniem jest pobranie i wdrożenie obu aplikacji, czasami z tymczasowego środowiska. - Zależności menedżera pakietów
- Może się zdarzyć, że piekło zależności wyniknie z zainstalowania przygotowanego pakietu przez menedżera pakietów (np. APT ), ale jest to mało prawdopodobne, ponieważ główne menedżery pakietów dojrzały, a oficjalne repozytoria są dobrze utrzymane. Tak jest w przypadku aktualnych wydań Debiana i głównych pochodnych, takich jak Ubuntu . Piekło zależności może jednak wynikać z instalacji pakietu bezpośrednio przez instalator pakietu (np. RPM lub dpkg ).
- Zależność od diamentu
- Gdy biblioteka A zależy od bibliotek B i C, zarówno B, jak i C zależą od biblioteki D, ale B wymaga wersji D.1, a C wymaga wersji D.2. Kompilacja kończy się niepowodzeniem, ponieważ w końcowym pliku wykonywalnym może istnieć tylko jedna wersja D.
- Menedżerowie pakietów, tacy jak yum , są podatni na konflikty między pakietami swoich repozytoriów, powodując piekło zależności w dystrybucjach Linuksa, takich jak CentOS i Red Hat Enterprise Linux .
Rozwiązania
- Numeracja wersji
- Bardzo częstym rozwiązaniem tego problemu jest stworzenie ujednoliconego systemu numeracji, w którym Oprogramowanie wykorzystuje szereg specyficzny dla każdej wersji (aka wersji głównej ), a także subnumber dla każdej rewizji (aka moll wersji ), np: 10 .1, lub 5. 7 . Wersja główna zmienia się tylko wtedy, gdy programy korzystające z tej wersji nie będą już kompatybilne. Wersja pomocnicza może ulec zmianie nawet przy prostej poprawce, która nie uniemożliwia pracy z nią innego oprogramowania. W takich przypadkach pakiety oprogramowania mogą po prostu zażądać komponentu, który ma określoną wersję główną i dowolną wersję pomocniczą (większą lub równą określonej wersji pomocniczej). W związku z tym będą nadal działać, a zależności zostaną pomyślnie rozwiązane, nawet jeśli zmieni się wersja pomocnicza. Wersjonowanie semantyczne (znane również jako „SemVer”) jest jednym z przykładów próby wygenerowania specyfikacji technicznej, która wykorzystuje specjalnie sformatowane liczby do stworzenia schematu wersjonowania oprogramowania.
- Prywatne według wersji aplikacji
- Ochrona plików systemu Windows wprowadzona w systemie Windows 2000 uniemożliwiała aplikacjom nadpisywanie systemowych bibliotek DLL. Zamiast tego zachęcano programistów do używania „prywatnych bibliotek DLL”, kopii bibliotek na aplikację w katalogu aplikacji. Wykorzystuje to charakterystykę ścieżki wyszukiwania systemu Windows, zgodnie z którą ścieżka lokalna ma zawsze priorytet przed katalogiem systemowym z bibliotekami systemowymi. Pozwala to na łatwe i efektywne cieniowanie wersji bibliotek przez konkretne aplikacje, zapobiegając tym samym piekłu zależności.
- PC-BSD, aż do wersji 8.2 włącznie, poprzednik TrueOS (system operacyjny oparty na FreeBSD ) umieszcza pakiety i zależności w samodzielnych katalogach w /Programs , co pozwala uniknąć awarii w przypadku aktualizacji lub zmiany bibliotek systemowych. Używa własnego "PBI" (Instalator Push Button) do zarządzania pakietami.
- Instalacja wielu wersji obok siebie
- Rozwiązanie numeracji wersji można ulepszyć, podnosząc numerację wersji do funkcji obsługiwanej przez system operacyjny. Dzięki temu aplikacja może zażądać modułu/biblioteki za pomocą unikalnej nazwy i ograniczeń numeru wersji, skutecznie przenosząc odpowiedzialność za pośrednictwo w pośrednictwie wersji biblioteki/modułu z aplikacji na system operacyjny. Współdzielony moduł można następnie umieścić w centralnym repozytorium bez ryzyka uszkodzenia aplikacji, które są zależne od poprzednich lub późniejszych wersji modułu. Każda wersja otrzymuje swój własny wpis obok innych wersji tego samego modułu.
- Rozwiązanie to jest stosowane w systemach operacyjnych Microsoft Windows od Windows Vista, gdzie Global Assembly Cache jest implementacją takiego centralnego rejestru z powiązanymi usługami i jest zintegrowany z systemem instalacyjnym/menedżerem pakietów. Gentoo Linux rozwiązuje ten problem za pomocą koncepcji zwanej slotowaniem, która umożliwia instalowanie wielu wersji bibliotek współdzielonych.
- Inteligentne zarządzanie pakietami
- Niektórzy menedżerowie pakietów mogą przeprowadzać inteligentne aktualizacje, w których współzależne komponenty oprogramowania są aktualizowane w tym samym czasie, rozwiązując w ten sposób również problem niezgodności głównych numerów.
- Wiele obecnych dystrybucji Linuksa zaimplementowało również systemy zarządzania pakietami oparte na repozytorium , aby spróbować rozwiązać problem zależności. Systemy te stanowią warstwę nad pakietami RPM , dpkg lub innymi systemami pakowania, które są zaprojektowane do automatycznego rozwiązywania zależności poprzez wyszukiwanie w predefiniowanych repozytoriach oprogramowania . Przykładami takich systemów są Apt , Yum , Urpmi , ZYpp , Portage , Pacman i inne. Zazwyczaj repozytoria oprogramowania to witryny FTP lub witryny internetowe, katalogi na komputerze lokalnym lub udostępniane w sieci lub, znacznie rzadziej, katalogi na nośnikach wymiennych, takich jak dyski CD lub DVD. Eliminuje to piekło zależności dla oprogramowania spakowanego w tych repozytoriach, które są zwykle utrzymywane przez dostawcę dystrybucji Linuksa i są dublowane na całym świecie. Chociaż te repozytoria są często ogromne, nie można w nich umieścić każdego oprogramowania, więc nadal może wystąpić piekło zależności. We wszystkich przypadkach opiekunowie repozytorium wciąż stoją przed piekłem zależności.
- Opcje instalatora
- Ponieważ różne programy mają różne zależności, możliwe jest wpadnięcie w błędne koło wymagań związanych z zależnościami lub stale rosnące drzewo wymagań, ponieważ każdy nowy pakiet wymaga zainstalowania kilku kolejnych. Systemy takie jak Advanced Packaging Tool Debiana mogą rozwiązać ten problem, prezentując użytkownikowi szereg rozwiązań i pozwalając użytkownikowi na akceptację lub odrzucenie rozwiązań, zgodnie z potrzebami.
- Łatwa adaptacja w programowaniu
- Jeśli oprogramowanie aplikacyjne jest zaprojektowane w taki sposób, aby jego programiści byli w stanie łatwo dostosować warstwę interfejsu, która zajmuje się systemem operacyjnym, menedżerem okien lub środowiskiem graficznym do nowych lub zmieniających się standardów, to programiści musieliby jedynie monitorować powiadomienia od twórców środowiska lub projektantów bibliotek komponentów i szybko dostosowują swoje oprogramowanie z aktualizacjami dla użytkowników, a wszystko to przy minimalnym wysiłku i bez kosztownych i czasochłonnych przeprojektowań. Ta metoda zachęciłaby programistów do wywierania nacisku na tych, od których są zależni, aby utrzymywali rozsądny proces powiadamiania, który nie jest uciążliwy dla nikogo zaangażowanego.
- Ścisłe wymagania dotyczące zgodności w tworzeniu i utrzymaniu kodu
- Jeśli aplikacje i biblioteki są opracowywane i utrzymywane z myślą o gwarantowanej kompatybilności wstecznej, każda aplikacja lub biblioteka może zostać zastąpiona nowszą wersją w dowolnym momencie bez naruszania czegokolwiek. Chociaż nie zmniejsza to mnogości zależności, znacznie ułatwia pracę menedżerów pakietów lub instalatorów.
- Urządzenia programowe
- Innym sposobem uniknięcia problemów z zależnościami jest wdrażanie aplikacji jako oprogramowania . Urządzenie programowe hermetyzuje zależności we wstępnie zintegrowanej, samodzielnej jednostce, dzięki czemu użytkownicy nie muszą już martwić się rozwiązywaniem zależności oprogramowania. Zamiast tego ciężar zostaje przeniesiony na twórców oprogramowania.
- Aplikacje przenośne
- Aplikacja (lub wersja istniejącej konwencjonalnej aplikacji), która jest całkowicie samodzielna i nie wymaga niczego do zainstalowania. Jest zakodowany tak, aby zawierał wszystkie niezbędne komponenty, lub został zaprojektowany tak, aby wszystkie niezbędne pliki znajdowały się w jego własnym katalogu i nie spowoduje problemów z zależnościami. Często są one w stanie działać niezależnie od systemu, do którego są podłączone. Aplikacje w RISC OS i ROX Desktop for Linux korzystają z katalogów aplikacji , które działają w bardzo podobny sposób: programy i ich zależności są niezależne we własnych katalogach (folderach).
- Ta metoda dystrybucji okazała się również przydatna przy przenoszeniu aplikacji zaprojektowanych dla platform uniksopodobnych do systemu Windows, przy czym najbardziej zauważalną wadą jest wielokrotna instalacja tych samych bibliotek współdzielonych . Na przykład instalatory Windows dla gedit , GIMP i XChat zawierają identyczne kopie zestawu narzędzi GTK , których te programy używają do renderowania widżetów. Z drugiej strony, jeśli każda aplikacja wymaga różnych wersji GTK, jest to prawidłowe zachowanie i skutecznie pozwala uniknąć piekła zależności.
Specyficzne dla platformy
Na określonych platformach obliczeniowych „piekło zależności” często występuje pod nazwą lokalną, zazwyczaj nazwą komponentów.
- DLL Hell – forma piekła zależności występującego w systemie Microsoft Windows .
- Konflikt rozszerzeń – forma piekła zależności występującego w klasycznym systemie Mac OS .
- Piekło JAR – forma piekła zależności występujących w środowisku Java Runtime Environment, zanim narzędzia do budowania, takie jak Apache Maven, rozwiązały ten problem w 2004 roku.
- Piekło RPM – forma piekła zależności występującego w dystrybucji Red Hat Linuksa i innych dystrybucjach wykorzystujących RPM jako menedżera pakietów.
Zobacz też
- Zarządzanie konfiguracją – techniki i narzędzia do zarządzania wersjami oprogramowania
- Coupling – formy zależności między artefaktami oprogramowania
- Dynamiczna eliminacja martwego kodu
- Menedżer pakietów
- PBI
- Urządzenie programowe
- Menedżer pakietów Nix
- Lewy pad