Inversion of (Coupling) Control in Java

<strong>What is the inversion of control? And what is dependency injection? These types of questions are often met with code examples, vague explanations, and what has been identified on StackOverflow as 'low-quality answers.'</strong>

What is the inversion of control? And what is dependency injection? These types of questions are often met with code examples, vague explanations, and what has been identified on StackOverflow as 'low-quality answers.'

We use inversion of control and dependency injection and often push it as the correct way to build applications. Yet, we can not clearly articulate why!

The reason is we have not clearly identified what control is. Once we understand what we are inverting, the concept of inversion of control versus dependency injection is not actually the question to be asked. It actually becomes the following:

Inversion of Control = Dependency (state) Injection + Thread Injection + Continuation (function) Injection

To explain this, well, let’s do some code. And yes, the apparent problem of using code to explain inversion of control is repeating, but bear with me, the answer has always been right before your eyes.

One clear use of inversion of control/ dependency injection is the repository pattern to avoid passing around a connection. Instead of the following:

public class NoDependencyInjectionRepository implements Repository<Entity> {

public void save(Entity entity, Connection connection) throws SQLException {
// Use connection to save entity to database
}
}

Dependency injection allows the repository to be re-implemented as:

public class DependencyInjectionRepository implements Repository<Entity> {

@Inject Connection connection;

public void save(Entity entity) throws SQLException {
// Use injected connection to save entity to database
}
}

Now, do you see the problem we just solved?

If you are thinking “I can now change the connection to say _REST calls,” _and this is all flexible to change, well, you would be close.

To see if the problem has been resolved, do not look at the implementation. Instead, look at the interface. The client calling code has gone from:

repository.save(entity, connection);

to the following:

repository.save(entity);

We have removed the coupling of the client code to provide a connection on calling the method. By removing the coupling, we can substitute a different implementation of the repository (again, boring old news, but bear with me):

public class WebServiceRepository implements Repository<Entity> {

@Inject WebClient client;

public void save(Entity entity) {
// Use injected web client to save entity
}
}

With the client able to continue to call the method just the same:

repository.save(entity);

The client is unaware that the repository is now calling a microservice to save the entity rather than talking directly to a database. (Actually, the client is aware but we will come to that shortly.)

So, taking this to an abstract level regarding the method:

R method(P1 p1, P2 p2) throws E1, E2

// with dependency injection becomes

@Inject P1 p1;
@Inject P2 p2;
R method() throws E1, E2

The coupling of the client to provide arguments to the method is removed by dependency injection.

Now, do you see the four other problems of coupling?

At this point, I warn you that you will never look at the code the same again once I show you the coupling problems. This is the point in the Matrix where I ask you if you want to take the red or blue pill. There is no going back once I show you how far down the rabbit hole this problem really is — refactoring is actually not necessary and there are issues in the fundamentals of modeling logic and computer science (ok, big statement but read on — I can’t put it any other way).

So, you chose the red pill.

Let’s prepare you.

To identify the four extra coupling problems, let’s look at the abstract method again:

@Inject P1 p1;
@Inject P2 p2;
R method() throws E1, E2

// and invoking it
try {
R result = object.method();
} catch (E1 | E2 ex) {
// handle exception
}

What is coupled by the client code?

  • The return type

  • The method name

  • The handling of exceptions

  • The thread provided to the method

Dependency injection allowed me to change the objects required by the method without changing the client code calling the method. However, if I want to change my implementing method by:

  • Changing its return type

  • Changing its name

  • Throwing a new exception (in the above case of swapping to a micro-service repository, throwing an HTTP exception rather than a SQL exception)

  • Using a different thread (pool) to execute the method than the thread provided by the client call

This involves “refactoring” all client code for my method. Why should the caller dictate the coupling when the implementation has the hard job of actually doing the functionality? We should actually invert the coupling so that the implementation can dictate the method signature (not the caller).

This is likely the point you look at me like Neo does in the Matrix going “huh”? Let implementations define their method signatures? But isn’t the whole OO principle about overriding and implementing abstract method signature definitions? And that’s just chaos because how do I call the method if it’s return type, name, exceptions, arguments keep changing as the implementation evolves?

Easy. You already know the patterns. You just have not seen them used together where their sum becomes a lot more powerful than their parts.

So, let’s walk through the five coupling points (return type, method name, arguments, exceptions, invoking thread) of the method and decouple them.

We have already seen dependency injection remove the argument coupling by the client, so one down.

Next, let’s tackle the method name.

Method Name Decoupling

Many languages, including Java lambdas, allow or have functions as first class citizens of the language. By creating a function reference to a method, we no longer need to know the method name to invoke the method:

Runnable f1 = () -> object.method();

// Client call now decoupled from method name
f1.run()

We can even now pass different implementations of the method around dependency injection:

@Inject Runnable f1;
void clientCode() {
f1.run(); // to invoke the injected method
}

OK, this was a bit of extra code with not much additional value. But again, bear with me. We have decoupled the method’s name from the caller.

Next, let’s tackle the exceptions from the method.

Method Exceptions Decoupling

By using the above technique of injecting functions, we inject functions to handle exceptions:

Runnable f1 = () -> {
@Inject Consumer<E1> h1;
@Inject Consumer<E2> h2;
try {
object.method();
} catch (E1 e1) {
h1.accept(e1);
} catch (E2 e2) {
h2.accept(e2);
}
}

// Note: above is abstract pseudo code to identify the concept (and we will get to compiling code shortly)

Now, exceptions are no longer the client caller’s problem. Injected methods now handle the exceptions decoupling the caller from having to handle exceptions.

Next, let’s tackle the invoking thread.

Method’s Invoking Thread Decoupling

By using an asynchronous function signature and injecting an Executor, we can decouple the thread invoking the implenting method from that provided by the caller:

Runnable f1 = () -> {
@Inject Executor executor;
executor.execute(() -> {
object.method();
});
}

By injecting the appropriate Executor, we can have the implementing method invoked by any thread pool we require. To re-use the client’s invoking thread, we just use a synchronous Exectutor:

Executor synchronous = (runnable) -> runnable.run();

So now, we can decouple a thread to execute the implementing method from the calling code’s thread.

But with no return value, how do we pass state (objects) between methods? Let’s combine it all together with dependency injection.

Inversion of Control (Coupling)

Let’s combine the above patterns together with dependency injection to get the ManagedFunction:

public interface ManagedFunction {
void run();
}

public class ManagedFunctionImpl implements ManagedFunction {

@Inject P1 p1;
@Inject P2 p2;
@Inject ManagedFunction f1; // other method implementations to invoke
@Inject ManagedFunction f2;
@Inject Consumer<E1> h1;
@Inject Consumer<E2> h2;
@Inject Executor executor;

@Override
public void run() {
executor.execute(() -> {
try {
implementation(p1, p2, f1, f2);
} catch (E1 e1) {
h1.accept(e1);
} catch (E2 e2) {
h2.accept(e2);
});
}

private void implementation(
P1 p1, P2 p2,
ManagedFunction f1, ManagedFunction f2
) throws E1, E2 {
// use dependency inject objects p1, p2
// invoke other methods via f1, f2
// allow throwing exceptions E1, E2
}
}

OK, there’s a lot going on here but it’s just the patterns above combined together. The client code is now completely decoupled from the method implementation, as it just runs:

@Inject ManagedFunction function;
public void clientCode() {
function.run();
}

The implementing method is now free to change without impacting the client calling code:

  • There is no return type from methods (slight restriction always being void, however necessary for asynchronous code)

  • The implementing method name may change, as it is wrapped by the ManagedFunction.run()

  • Parameters are no longer required by the ManagedFunction. These are dependency-injected, allowing the implementing method to select which parameters (objects) it requires

  • Exceptions are handled by injected Consumers. The implementing method may now dictate what exceptions it throws, requiring only different Consumers injected. The client calling code is unaware that the implementing method may now be throwing an HTTPException instead of an SQLException . Furthermore, Consumers can actually be implemented by ManagedFunctions injecting the exception.

  • The injection of the Executor allows the implementing method to dictate its thread of execution by specifying the Executor to inject. This could result in re-using the client’s calling thread or have the implementation run by a separate thread or thread pool

All five coupling points of the method by its caller are now decoupled.

We have actually “Inverted Control of the Coupling.” In other words, the client caller no longer dictates what the implementing method can be named, use as parameters, throw as exceptions, which thread to use, etc. Control of coupling is inverted so that the implementing method can dictate what it couples to by specifying it’s a required injection.

Furthermore, as there is no coupling by the caller, there is no need to refactor code. The implementation changes and then configures in it’s coupling (injection) to the rest of the system. Client calling code no longer needs to be refactored.

So, in effect, dependency injection only solved 1/5 of the method coupling problem. For something that is so successful for only solving 20 percent of the problem, it does show how much of a problem coupling of the method really is.

Implementing the above patterns would create more code than it’s worth in your systems. That’s why open-source OfficeFloor is the “true” inversion of control framework and has been put together to lessen the burden of this code. This has been an experiment in the above concepts to see if real systems are easier to build and maintain with “true” inversion of control.

Summary

So, the next time you reach for the Refactor Button/Command, realize that this is brought on by the coupling of the method that has been staring us in the face everytime we write code.

And really, why do we have the method signature? It is because of the thread stack. We need to load memory onto a thread stack, and the method signature follows the behavior of the computer. However, in the real world, the modeling of behavior between objects offers no thread stack. Objects are loosely coupled with very small touch points — not the five coupling aspects imposed by the method.

Furthermore, in computing, we strive towards low coupling and high cohesion. One might possibly put forward a case that,in comparison to ManagedFunctions, methods are:

  • High coupling: methods have five aspects of coupling to the client calling code

  • Low cohesion: as the handling of exceptions and return types from methods starts blurring the responsibility of the methods over time, continuous change and shortcuts can quickly degrade the cohesiveness of the implementation of the method to start handling logic beyond its responsibility

Originally published by Daniel Sagenschneider at https://dzone.com

Learn more

Java Programming Masterclass for Software Developers

☞ http://school.edusavecoupon.net/p/rJW0qu-he

The Java Design Patterns Course

☞ http://school.edusavecoupon.net/p/26SyjmZOu

Selenium WebDriver with Java -Basics to Advanced+Frameworks

☞ http://school.edusavecoupon.net/p/Bkz0SUOaf

☞ Introduction to Java Stream API

Java Fundamentals: Learn Java for absolute beginners |Simpliv

Java Fundamentals: Learn Java for absolute beginners |Simpliv

Java Fundamentals: Learn Java for absolute beginners

Description
This is the best course to learn to program in Java in Spanish from scratch and without any experience in this fabulous programming language. This is the first course where we will study the Fundamentals of Java, and we will take you step by step until you acquire the bases of the Java language and you can start to study more advanced Java topics.

The content is divided into perfectly structured levels, each level supported by the previous one, with the aim of adding Java knowledge incrementally and so you can focus on mastering the issues little by little and gradually. So ensure the success of your Java training.

We will also offer support for any doubts about the didactic material included in this Java Fundamentals course.

We manage a new teaching methodology that we have called Speed ​​Learning. This methodology consists of concise videos that go directly to the point to be studied, complemented by eBooks with explanations and step-by-step images (which you can print, or search for any text you need, or use for your offline study), since As we know we can not do text search within a video. In addition, our methodology includes perfectly structured and very didactic exercises that will allow you to accelerate your eLearning learning. No loss of time in videos where you have to watch the instructor codify an exercise, too much theory, little practice or anything like that. Our Speed ​​Learning methodology guarantees that in the shortest possible time you will acquire the necessary knowledge for the Java professional and working world.

The Java Fundamentals course includes the following topics for study:

Lesson 1 - Starting with Java Technology

The amazing world of Java programming

What is Java technology (from a practical approach)

Our first Java program from scratch

Lesson 2 - Variables and Operators in Java

Use of Variables in Java and what we use them for

Types of Data in Java and how they are classified

Management and Classification of operators in Java

Lesson 3 - Control statements in Java

Using the if-else structure and where to use it

Handling the switch structure and when applying it

Lesson 4 - Handling Loops in Java

Use of the for loop and its use

Using the while loop and how to apply it

Use of the do-while loop and when to use it

Lesson 5 - Object Oriented Programming

Introduction to Object Oriented Programming (OOP)

Handling Classes in Java

Use of Objects in Java

Lesson 6 - Functions in Java

Declaration of Methods or Functions in Java

Use and call of functions in Java

Lesson 7 - Data Management in Java

Using Arrays in Java

Management of Matrices in Java

Lesson 8 - Inheritance in Java

Inheritance Management in Java

Use of superclasses and subclasses in Java

Final Level Laboratory

Final Exercise where everything learned in this Level is integrated

At the end you get a certificate of having completed the Java Fundamentals course.

We wait for you on the other side.

Ing. Ubaldo Acosta

Founder of Global Mentoring

Passion for Java Technology

Who this course is for:

Anyone who wants to learn how to program in Java
Basic knowledge
Basic knowledge of PC use
Basic management of an operating system such as Windows, Mac or Linux
It is not necessary to know how to program, we will start from scratch !!!
The attitude and desire to start coding and learning Java once and for all from scratch!
What will you learn
Have the basics of the programming language with Java
You will know the basic syntax of the Java language
Manage the concept of Variables and Operators in Java
We will study Object Oriented Programming with Java
You will learn the Control Statements and Loops in Java
We will see the concept of Functions with Java
We will study the concept of Inheritance in Java
We will learn to use Arrays in java
We will handle the concept of Matrices in Java
We will learn to Design Classes in Java
We will make a final application with everything learned in the course
To know more:

Java Essentials : Learn Core Java From Basic to Advance

Java Essentials : Learn Core Java From Basic to Advance

Learn Java Programming Using Practical Assignments. Start Building Back-end Web Applications Robust Test Automation Frameworks By End Of The Course. Learn More!

Description
This is only Java related course and it's great because it covers just the right amount of Java which is needed to leaning programming, java.

This is a comprehensive yet simple course on java programming language and it concentrates on Java programming concepts.

*************************** No Prior Coding Experience Needed ***************************

This course assumes that you have no programming background. If you have some experience then, it's just a bonus point. You have never code, have some experience or have a lot of experience any other programming language, this course is one stop place for you.

Java is one of the most and useful programming languages to learn You can build back-end of web applications and build robust test automation framework. Specially for Selenium WebDriver GUI automation, Java is most popular choice and has the largest community.

Each lecture consist of a video screencast and code files

There are quizzes, homework to test your knowledge

High focus on practice and asking questions

You will also learn coding best practices

Market is never short of jobs in Java programming language, there are ample of jobs in both Java development and Automation Testing using Java.

What are you waiting for? Enroll today and learn the powerful Java language !!!

Basic knowledge
Nothing else! It’s just you, your computer and your hunger to get started today
Java concepts are covered in the course, no experience needed
Windows/MAC computer
What will you learn
You will be able to EXPLAIN, DESIGN and IMPLEMENT efficient java Programs
You will be confident to clear test automation interviews
Understand the concepts of Object Oriented Programming Language
Complete understanding of java
Expert-level knowledge of Java code (+ advanced tips and tricks used by the pros)
Suitable for beginner programmers and ideal for users who learn faster when shown
To learn more:

Fundamentos de Java: Aprende Java desde cero, sin misterios | Simpliv

Fundamentos de Java: Aprende Java desde cero, sin misterios | Simpliv

Fundamentos de Java: Aprende Java desde cero, sin misterios

Description
This is the best course to learn to program in Java in Spanish from scratch and without any experience in this fabulous programming language . This is the first course where we will study the Java Fundamentals, and we will take you step by step until you acquire the basics of the Java language and so you can start studying more advanced Java topics.

The content is divided into perfectly structured levels , each level supported by the previous one, with the aim of adding Java knowledge incrementally so that you can focus on mastering the issues little by little and gradually. So ensure the success of your Java training.

In other offer support of any doubt teaching materials included in this course Fundamentals of Java.

To make matters worse, we handle a new teaching methodology that we have called Speed ​​Learning. This methodology consists of concise videos that go directly to the point to study, complemented with eBooks with explanations and step-by-step images (which you can print, or search for any text you need, or use for your offline study), since as we know we cannot do text search within a video. In addition, our methodology includes perfectly structured and very didactic exercises, which will allow you to accelerate your eLearning learning. Without wasting time on videos where you have to watch the instructor codify an exercise, too much theory, little practice or anything like that. Our Speed ​​Learning methodology guarantees that in the shortest possible time you will acquire the necessary knowledge for the professional and professional world of Java.

The Java Fundamentals course includes the following topics of study:

Level. Java basics

Lesson 1 - Starting with Java Technology

The amazing world of Java programming
What is Java technology (from a practical approach)
Our first Java program from scratch
Lesson 2 - Variables and Operators in Java

Use of Variables in Java and what we use them for
Data types in Java and how they are classified
Operator Management and Classification in Java
Lesson 3 - Control sentences in Java

Use of the if-else structure and where to use it
Management of the switch structure and when to apply it
Lesson 4 - Cycle Management in Java

Use of the for cycle and its use
Use of the while cycle and how to apply it
Use of the do-while cycle and when to use it
Lesson 5 - Object Oriented Programming

Introduction to Object Oriented Programming (OOP)
Class Management in Java
Using Objects in Java
Lesson 6 - Functions in Java

Declaration of Methods or Functions in Java
Use and call of functions in Java
Lesson 7 - Data Management in Java

Using Arrangements in Java
Matrix Management in Java
Lesson 8 - Inheritance in Java

Inheritance Management in Java
Use of superclasses and subclasses in Java
Final Level Laboratory

Final Exercise where everything learned in this Level is integrated
At the end you get a certificate of having completed the Java Fundamentals course.

We wait for you from the other side.

Ing. Ubaldo Acosta

Founder of Global Mentoring

Passion for Java Technology

Who this course is for:

Anyone who wants to learn to program in Java
Basic knowledge
Basic knowledge of PC use
Basic operation of an operating system such as Windows, Mac or Linux
It is not required to know how to program, we will start from scratch !!!
The attitude and desire to start coding and learning Java once and for all from scratch !!!
What will you learn
Have the basics of the programming language with Java
You will know the basic syntax of the Java language
Will handle the concept of Variables and Operators in Java
We will study Object Oriented Programming with Java
You will learn Control Sentences and Cycles in Java
We will see the concept of Functions with Java
We will study the concept of Inheritance in Java
We will learn to use Arrangements in java
We will handle the concept of Matrices in Java
We will learn to Design Classes in Java
We will make a final application with everything learned in the course
To continue: