Dependency hell

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Dependency hell (англ. Ад зависимостей) - это разговорный термин, обозначающий раздражение от некоторого программного обеспечения, которое зависит от специфичных версий других ПО.[1] Проблемы с зависимостями возникают у общих пакетов/библиотек, у которых некоторые другие пакеты имеют зависимости от несовместимых и различных версий общих пакетов. Если установлена одна версия общего пакета/библиотеки, для решения этой проблемы пользователю/администратору понадобится получить новые или старые версии зависимых пакетов. Это, в свою очередь, может нарушить работу других зависимых пакетов и добавить проблем в другой набор пакетов, таким образом образуя настоящий ад.

Обзор[править | править исходный текст]

Often, rather than "reinventing the wheel", software is designed to take advantage of other software components that are already available, or have already been designed and implemented for use elsewhere. This could be compared to how people building a house might buy off-the-shelf components, such as bricks, windows, and doors, rather than producing everything themselves.

Even for a builder, it can be a problem if a building is designed for a certain door type, and only doors with different specifications are available. However, in the software world, where components evolve rapidly and depend significantly on one another, this problem becomes more pronounced.[2]

The issue of dependency hell may be regarded as an anti-pattern, where the fault lies less with the suppliers of the products than with the framework into which they have to fit.

Виды проблем[править | править исходный текст]

"Dependency hell" принимает несколько форм:

множество зависимостей
An application depends on many libraries, requiring lengthy downloads, large amounts of disk space, and not being very portable (all libraries must be ported for the application to be ported). It can also be difficult to locate all the dependencies, which can be fixed by having a repository (see below). This is partly inevitable; an application built on a given platform (such as Java) requires that platform to be installed, but further applications do not require it. This is a particular problem if an application uses a small part of a big library (which can be solved by refactoring), or a simple application relies on many libraries.
длинные цепочки зависимостей
app depends on liba, which depends on libb, ..., which depends on libz. This is distinct from "many dependencies" if the dependencies must be resolved manually (e.g., on attempting to install app, the user is prompted to install liba first. On attempting to install liba, the user is then prompted to install libb.). Sometimes, however, during this long chain of dependencies, conflicts arise where two different versions of the same package are required[3] (see conflicting dependencies below). These long chains of dependencies can be solved by having a package manager that resolves all dependencies automatically. Other than being a hassle (to resolve all the dependencies manually), manual resolution can mask dependency cycles or conflicts.
конфликтующие зависимости
Если app1 зависит от libfoo 1.2, а app2 зависит от libfoo 1.3, и различные версии libfoo не могут быть одновременно установлены, то app1 и app2 нельзя одновременно использовать (или установить, если установщики проверяют зависимости). When possible, this is solved by allowing simultaneous installations of the different dependencies. Alternatively, the existing dependency, along with all software that depends on it, must be uninstalled in order to install the new dependency. A problem on Linux systems with installing packages from a different distributor (which is not recommended or even supposed to work) is that the resulting long chain of dependencies may lead to a conflicting version of glibc, the single most important library. If this happens, the user will be prompted to uninstall thousands of packages.
циклические зависимости
If appX, version 1 depends on app2, which depends on app3, which depends on app4, which depends on the original appX, version 0, then, in systems such as RPM or dpkg, the user must install all packages simultaneously.[4] - hence on Linux circular dependencies are often the result of a user misunderstanding the packaging system.[источник не указан 1573 дня] On other platforms, however, the packaging system may not be able to resolve the circular dependency.

Решения[править | править исходный текст]

Нумерация версий
The most obvious (and very common) solution to this problem is to have a standardised numbering system, wherein software uses a specific number for each version (aka major version), and also a subnumber for each revision (aka minor version), e.g.: 10.1, or 5.7. The major version only changes when programs that used that version will no longer be compatible. The minor version might change with even a simple revision that does not prevent other software from working with it. In cases like this, software packages can then simply request a component that has a particular major version, and any minor version (greater than or equal to a particular minor version). As such, they will continue to work, and dependencies will be resolved successfully, even if the minor version changes.
Параллельная установка различных версий ПО
The version numbering solution can be improved upon by elevating the version numbering to an operating system supported feature. This allows an application to request a module/library by a unique name and version number constraints, effectively transferring the responsibility for brokering library/module versions from the applications to the operating system. A shared module can then be placed in a central repository without the risk of breaking applications which are dependent on previous or later versions of the module. Each version gets it own entry, side by side with other versions of the same module. This solution is used in Windows operating systems since Windows Vista, where the Global Assembly Cache is an implementation of such a central registry with associated services and integrated with the installation system/package manager.
Хороший пакетный менеджер
Some package managers can perform smart upgrades, in which interdependent software components are upgraded at the same time, thereby resolving the major number incompatibility issue too.
Many current Linux distributions have also implemented repository-based package management systems to try to solve the dependency problem. These systems are a layer on top of the RPM, dpkg, or other packaging systems that are designed to automatically resolve dependencies by searching in predefined software repositories. Typically these software repositories are FTP sites or websites, directories on the local computer or shared across a network or, much less commonly, directories on removable media such as CDs or DVDs. This eliminates dependency hell for software packaged in those repositories, which are typically maintained by the Linux distribution provider and mirrored worldwide. Although these repositories are often huge it is not possible to have every piece of software in them, so dependency hell can still occur. In all cases, dependency hell is still faced by the repository maintainers.[5] Examples of these systems include Apt, Yum, Urpmi, ZYpp, Portage, Pacman and others.
PC-BSD (an operating system based on FreeBSD) avoids dependency hell by placing packages and dependencies into self-contained directories, which avoids breakage if system libraries are upgraded or changed. PC-BSD uses its own "PBI" (Push Button Installer) for package management.[6][7]
Настройки установщика
Because different pieces of software have different dependencies, it is possible to get into a vicious circle of dependency requirements, or (possibly worse) an ever-expanding tree of requirements, as each new package demands several more be installed. Systems such as Debian's APT can resolve this by presenting the user with a range of solutions, and allowing the user to accept or reject the solutions, as desired.
Easy Adaptability in Programming
If application software is designed in such a way that its programmers are able to easily adapt the interface layer that deals with the OS, window manager or desktop environment to new or changing standards, then the programmers would only have to monitor notifications from the environment creators or component library designers and quickly adjust their software with updates for their users, all with minimal effort and a lack of costly and time-consuming redesign. This method would encourage programmers to pressure those upon whom they depend to maintain a reasonable notification process that is not onerous to anyone involved.
Software appliances
Another approach to avoiding dependency issues is to deploy applications as a software appliance. A software appliance encapsulates dependencies in a pre-integrated self-contained unit such that users no longer have to worry about resolving software dependencies. Instead the burden is shifted to developers of the software appliance.
Портативные приложения
An application (or version of an existing conventional application) that is completely self-contained and requires nothing to be already installed. It is coded to have all necessary components included, or is designed to keep all necessary files within its own directory, and will not create a dependency problem. These are often able to run independently of the system to which they are connected.  Applications in RISC OS and the ROX Desktop for Linux use application directories, which work in much the same way: programs and their dependencies are self contained in their own directories (folders).[8]

На других платформах[править | править исходный текст]

On specific computing platforms, "dependency hell" often goes by a local specific name, generally the name of components.

См. также[править | править исходный текст]

Примечания[править | править исходный текст]

  1. Michael Jang Linux annoyances for geeks. — O'Reilly Media, 2006.
  2. Donald, James (2003-01-25). «Improved Portability of Shared Libraries» (Princeton University). Проверено 2010-04-09. (недоступная ссылка)
  3. Dependency hell
  4. Nix fixes dependency hell on all Linux distributions. linux.com (22 декабря 2008). — «All popular package managers, including APT, RPM and the FreeBSD Ports Collection, suffer from the problem of destructive upgrades. When you perform an upgrade -- whether for a single application or your entire operating system -- the package manager will overwrite the files that are currently on your system with newer versions. As long as packages are always perfectly backward-compatible, this is not a problem, but in the real world, packages are anything but perfectly backward-compatible. Suppose you upgrade Firefox, and your package manager decides that you need a newer version of GTK as well. If the new GTK is not quite backward-compatible, then other applications on your system might suddenly break. In the Windows world a similar problem is known as the DLL hell, but dependency hell is just as much a problem in the Unix world, if not a bigger one, because Unix programs tend to have many external dependencies.»  Проверено 22 мая 2013.
  5. Package Management. Проверено 12 февраля 2013.
  6. The PBI Format for 9.0 and Beyond (Modified on 9 November 2012 when retrieved). Проверено 12 февраля 2013. PC-BSD Wiki page.
  7. Application directories. Проверено 7 сентября 2013.
  8. Weinstein, Paul Is Linux Annoying?. linuxdevcenter.com (11 сентября 2003). Проверено 10 апреля 2010.

Внешние ссылки[править | править исходный текст]