Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When exactly does a class/package depend on another?

Many articles/books/.... talk about class or package dependency, few explain what it is. I did find some definitions, but they vary and probably don't cover all cases. E.g.:

  • "when one class uses another concrete class within its implementation" (so there exists no dependency on an interface?)
  • "when a class uses another as a variable" (what about inheritance?)
  • "if changes to the definition of one element may cause changes to the other" (so dependency is a transitive relationship not just on packages, but also on class level?)
  • "the degree to which each program module relies on each one of the other modules" (but how do you define "relies"?)

Further aspects to consider are method parameters, dependency injection, aspect oriented programming, generics. Any more aspects?

So, can you give a (formal) definition for dependency amongst classes and amongst packages that is fool-proof and covers all these cases and aspects?

like image 656
DaveFar Avatar asked Sep 03 '11 16:09

DaveFar


People also ask

What is the relationship of objects classes and a package?

A class is like a Template, where an you put set Behaviors (Methods) and properties (Instance variables) which every Object of its kind will Posses. but package is totally different and has nothing to do with technical part. It is just for the purpose of Readability and Organizing your code.

Does class order matter in Java?

No it does not matter at all where in the class the method declaration is placed. When you actually call a method Java will go through the entire class looking for it either way, so the placement is irrelevant.

What is dependencies in Java?

Dependency injection enables you to turn regular Java classes into managed objects and to inject them into any other managed object. Using dependency injection, your code can declare dependencies on any managed object.

Does every class belong to package Java?

Every Java class must belong to a package. You can explicitly name the package by providing a package statement in the beginning of the source file.


3 Answers

If you are asking for dependency in the context of inversion of control or dependency injection, well, you're probably interested in classes that interact with one another directly. That means mostly constructor parameters and properties.

In the context of a UML domain diagram, you're probably interested in "real world" dependency. A dog needs food. That's a dependency. The dog's Bark() method returns a Sound object: that's not something you're interested in, in a UML domain model. The dog doesn't depend on sounds to exist.

You could go philosophical on this also: All classes depend on each other to accomplish a common goal; a (hopefully) great software.

So, all in all, dependency or coupling is not a matter of yes or no. It really depends on the context and on a degree of coupling (weak, strong). I thinks that explains why there are some many divergent definition of dependency.

like image 97
Bryan Menard Avatar answered Oct 04 '22 01:10

Bryan Menard


I wrote a blog post on that topic a while ago: Understanding Code: Static vs Dynamic Dependencies. Basically you need to make a difference between static dependencies, those that are resolved by the compiler at compile-time, and dynamic dependencies, those that are resolved by the runtime (JVM or CLR) at run-time.

static dependencies are typically provoked by calls to static/final methods, read/write to a field, in the definition of the class C the implementation of the interface I by C ... all these associations between code elements that can be found explicitly in the bytecode and source code.

dynamic dependencies are typically provoked by everything that abstracts a method call at compile time, like calls to abstract/virtual methods (polymorphism), variables or parameters typed with an interface (the implementation class is abstracted at compile-time), but also delegates (.NET) or pointers to function (C++).

Most of the time, when you'll read about dependencies in the literature, they are talking about static dependencies.

A static dependencies is direct (meaning not transitive). A tool like NDepend that I mention in the blog post, can also infer indirect (or call it transitive) static dependencies from the set of direct static dependencies.

The idea I defend in the blog post is that when it comes to understand and maintain a program, one needs to focus mostly on the static dependencies, the ones found in the source code.. Indeed, abstractions facilities are used to, well ... abstract, implementation for callers. This makes source code much more easy to develop and maintain. There are however situations, typically at debugging time, where one needs to know what's really behind an abstraction at run-time.

like image 23
Patrick from NDepend team Avatar answered Oct 03 '22 23:10

Patrick from NDepend team


This post is about static dependency - for dynamic dependency and the difference, see Patrick Smacchia's answer.

In an easy to understand way: an entity (class or package) A depends on an entity B when A cannot be used standalone without B.

Inheritance, aggregation, composition, all of them introduces dependency between related entities.

so there exists no dependency on an interface?

there is, but interface only serves as the glue.

what about inheritance?

see above.

so dependency is a transitive relationship not just on packages, but also on class level?

yep.

but how do you define "relies"?

see above "easy to understand" definition. also related to the 3rd definition you posted.


Update:

So if you have interface A in Package P1, and class C in Package P2 uses A as

  • method parameter, or
  • local variable woven into C via AOP, or
  • class C implements A, or
  • class C<E extends A>,

then C depends on A and P2 depends on P1.

But if interface A is implemented by class B and class C programs against the interface A and only uses B via dependency injection, then C still (statically!) only depends on A, not on B, because the point of dependency injection is that it doesn't make glued components dependent.

like image 25
LeleDumbo Avatar answered Oct 04 '22 00:10

LeleDumbo