Representation of a dependency edge. Contains information about the source and target {@code Key>}s, as well as the properties of the edge (optional/requried, lazy/eager).
Dependencies also store the context in which the dependency arose. This is not part of the dependency's identity from the point of view of equals() and hashCode(), which ultimately means that if the same dependency arises in several different contexts, we will pick an arbitrary instance (specifically, the first one encountered, see {@link DependencyGraph}).