SlideShare a Scribd company logo
1	of	6
InvertingDependencies
photo credit: Stéfan	(http://www.flickr.com/photos/st3f4n/4085958000/)	()	via
photopin	(http://photopin.com)	cc	(http://creativecommons.org/licenses/by-nc-sa/2.0/)
Polymorphism is the super power of the OO designer. However, many designers don't exploit
this power, they use inheritance for structural purposes. In a language like Java, this results in
an abuse of the instanceof statement	(http://www.javapractices.com/topic/TopicAction.do?Id=31)	.
Maybe Polymorphism is not the right word; maybe we should use multiple personality
disorder (not as sexy as polymorphism when you're trying to sell your OO suite...). Depending
on the runtime context, the object does not change form, it does not morph, it changes
behavior, it behaves as another object.
But the interesting part of this mechanism is how the dependencies align. Looking at the
dependencies from a UML Class diagram viewpoint, inheritance goes in the opposite
direction as composition or aggregation.
The next example shows two different ways for the print method of Object to invoke the
myFunction method of Child. The first case, Child inherites from Object (Template Method
Pattern	(http://sourcemaking.com/design_patterns/template_method)	) this require the myFunction
method to be present in Object. In the second case, Object depends on Child and invokes it.
2	of	6
Object
void	print()
Child
int	myFunction()
Object
int	myFunction()
void	print()
Child
int	myFunction()
However looking at it from a UML sequence diagram viewpoint, the direction of the method
invocation is not reversed.
o:Object c:Child
print()
myFunction()
Concretely, inheritance is a tool that offers the possibility to inverse dependencies arrows
while preserving the direction of behavioral arrows! This super power can be extremely
powerful in light of architectural styles that impose constraints on the direction of
dependencies.
Examples of constraints imposed on the direction of dependencies are Robert C. Martin's
"The Dependency Rule"	(http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html)	and the
layers architectural style. The later imposes a downward "can use" relationship between
layers. By using inheritance, one can respect this structural constraint of downward
dependencies yet allow behavior to invoke upwards.
Let see how all this works, but to do so, let's use a programming language that is not object
oriented. This way the details will not be hidden away by syntactic sugar or by compiler magic.
Let's start by defining Object with a simple struct (Object.h
(https://github.com/luctrudeau/InvertingDependencies/blob/master/Object.h)	)
struct	Object;
struct	Object	build(int	a,	int	b);
struct	Object	{
				int	a;
				int	b;

3	of	6
The first line is a forward declaration, it's required because the Object structure is used inside
the definition of the Object structure. Next, there's the build function that is the equivalent of
a constructor/factory. Finally the Object structure is defined. Notice that the last two
declarations are function pointers. These two function pointers are myFunction that expects
an Object structure as parameter and print that also expects an Object structure as parameter.
Notice that all the implementation details are hidden in Object.c (this is encapsulation). The
idea behind this header file is to expose only the structure but not the behavior. No one
knows, how build work, or even what's in myFunction or print, but they know that these
functions exist. This separation is key in flipping the direction of the dependency without
flipping the direction of invocation.
To find out what the behavior is, we can look at the Object.c
(https://github.com/luctrudeau/InvertingDependencies/blob/master/Object.c)	file.
Now we know that myFunction points to an add function, and that print simply does a printf.
Even if not all languages use the same keyword, the concept of an abstract method is
generally available. We can match this concept to the functions pointers. If these pointers are
not assigned then the method is abstract. This is why you can't instantiate classes with
abstract methods.
Notice that the parameter of the functions inside the Object structure are structures of type
Object. For now, we can think of this as a solution to the problem of accessing the values of
the instance of the Object structure, but we will see shortly that there's another more
				int	(*myFunction)(struct	Object);
				void	(*print)(struct	Object);	
};
#include	"Object.h"
int	add(struct	Object	o)
{
				return	o.a	+	o.b;
}
void	print(struct	Object	o)
{
				printf("Result	=	%dn",	o.myFunction(o));
}
struct	Object	build(int	a,	int	b)
{
				struct	Object	o;
				o.a	=	a;
				o.b	=	b;
				o.myFunction	=	&add;
				o.print	=	&print;
				return	o;
}

4	of	6
profound mechanism at work here. Some programming languages hide this detail behind the
"this" keyword, others like python will make the instance parameter visible to developer and
define it as the first parameter of every method.
Let's say main.c wants to use the Object structure, it only need to include "Object.h", it does
not need to care about Object.c. If we look at the dependencies we can see the inversion effect.
The main.c file depends on Object.h but Object.h does not depend upon Object.c, it's the other
way around Object.c depends upon Object.h. The header file is an abstraction.
main.c
Object.h
struct	Object
struct	Object	build(int	a,	int	b)
Object.c
int	add(struct	Object	o){...}
void	print(struct	Object	o){...}
struct	Object	build(int	a,	int	b)	{...}
<<includes>>
<<includes>>
Now let's try inheritance, I'm not interested in structural inheritance, I don't want to add a
third variable to Object. I'm interested in polymorphism; I want to change the behavior of
Object.
This is the content of Child.h	(https://github.com/luctrudeau/InvertingDependencies/blob/master/Child.h)
The Child depends on Object.h and defines a new constructor/factory buildChild. Let's look at
its behavior (Child.c	(https://github.com/luctrudeau/InvertingDependencies/blob/master/Child.c)	)
#include	"Object.h"
struct	Object	buildChild(int	a,	int	b);

#include	"Child.h"
int	sub(struct	Object	o)
{
				return	o.a	-	o.b;
}
struct	Object	buildChild(int	a,	int	b)
{
				struct	Object	o	=	build(a,b);
				o.myFunction	=	&sub;
				return	o;
}

5	of	6
Instead of invoking the add function, the Child version of the Object structure will invoke the
sub function. Notice how the buildChild function invokes build of Object and then overrides
the myFunction function pointer.
Now we have an Object that acts like a Child, yet almost no one needs to know. The only
entity that needs to know is the one calling buildChild function instead of the build function.
This switch can be executed dynamically at runtime. Looking at main.c we can see that the
choice between the build or the buildChild functions is performed dynamically based on a
random variable.
Dependency injection	(http://martinfowler.com/articles/injection.html)	is exactly what is going on
inside the print function. At runtime, when the buildChild function is selected, the Child
variant of Object is being injected into the print function. This is interesting because the type
of the parameter is mandatory (aka closed	(http://en.wikipedia.org/wiki/Open/closed_principle)	) but its
behavior is not (aka open	(http://en.wikipedia.org/wiki/Open/closed_principle)	).
The Child variant of Object can be developed years after Object was written, by completely
different developers, yet it will still work inside print function without requiring modifications
to the print function.
#include	<stdio.h>
#include	<stdlib.h>
#include	<time.h>
#include	"Object.h"
#include	"Child.h"
int	main()
{
				struct	Object	o;
				srand(time(0));
				if	(rand()	%	2)
				{
								o	=	buildChild(5,	3);
				}	else	{
								o	=	build(2,	3);
				}
				o.print(o);
}

6	of	6
main.c
Object.h
struct	Object
struct	Object	build(int	a,	int	b)
Object.c
int	add(struct	Object	o){...}
void	print(struct	Object	o){...}
struct	Object	build(int	a,	int	b)	{...}
Child.h
struct	Object	buildChild(int	a,	int	b)
Child.c
int	sub(struct	Object	o){...}
struct	Object	buildChild(int	a,	int	b)	{...}
<<includes>><<includes>>
<<includes>>
<<includes>>
<<includes>>
Not only does this allows the Object's print function to invoke the Child's sub function
without depending on it, but to do so Child is the one depending on the Object.
Ad

Recommended

Js: master prototypes
Js: master prototypes
Barak Drechsler
 
Null Object Design Pattern
Null Object Design Pattern
tcab22
 
Design patterns in javascript
Design patterns in javascript
Ayush Sharma
 
Javascript Prototype Visualized
Javascript Prototype Visualized
军 沈
 
C questions
C questions
parm112
 
New microsoft office word document (2)
New microsoft office word document (2)
rashmita_mishra
 
How prototype works in java script?
How prototype works in java script?
InnovationM
 
Interesting Facts About Javascript
Interesting Facts About Javascript
Manish Jangir
 
Javascript Objects Deep Dive
Javascript Objects Deep Dive
Manish Jangir
 
Javascript Prototypal Inheritance - Big Picture
Javascript Prototypal Inheritance - Big Picture
Manish Jangir
 
Javascript Design Patterns
Javascript Design Patterns
Subramanyan Murali
 
Javascript Design Patterns
Javascript Design Patterns
Iván Fernández Perea
 
Java Static Factory Methods
Java Static Factory Methods
Ye Win
 
Prototype
Prototype
Aditya Gaur
 
Introduction to Design Patterns in Javascript
Introduction to Design Patterns in Javascript
Santhosh Kumar Srinivasan
 
Factory Design Pattern
Factory Design Pattern
Jaswant Singh
 
Avoid creating unncessary objects
Avoid creating unncessary objects
Ye Win
 
Design Patterns Illustrated
Design Patterns Illustrated
Herman Peeren
 
Patterns In-Javascript
Patterns In-Javascript
Mindfire Solutions
 
JavaScript - Programming Languages course
JavaScript - Programming Languages course
yoavrubin
 
Design pattern (Abstract Factory & Singleton)
Design pattern (Abstract Factory & Singleton)
paramisoft
 
25 java tough interview questions
25 java tough interview questions
Arun Banotra
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Philip Schwarz
 
Oop Extract
Oop Extract
Ganesh Samarthyam
 
Scalable JavaScript Design Patterns
Scalable JavaScript Design Patterns
Addy Osmani
 
Angular Interview Questions & Answers
Angular Interview Questions & Answers
Ratnala Charan kumar
 
Compositionality and Category Theory - a montage of slides/transcript for sec...
Compositionality and Category Theory - a montage of slides/transcript for sec...
Philip Schwarz
 
Definitions of Functional Programming
Definitions of Functional Programming
Philip Schwarz
 
Ppt of c++ vs c#
Ppt of c++ vs c#
shubhra chauhan
 
Oop
Oop
Jun-jun Lagman
 

More Related Content

What's hot (20)

Javascript Objects Deep Dive
Javascript Objects Deep Dive
Manish Jangir
 
Javascript Prototypal Inheritance - Big Picture
Javascript Prototypal Inheritance - Big Picture
Manish Jangir
 
Javascript Design Patterns
Javascript Design Patterns
Subramanyan Murali
 
Javascript Design Patterns
Javascript Design Patterns
Iván Fernández Perea
 
Java Static Factory Methods
Java Static Factory Methods
Ye Win
 
Prototype
Prototype
Aditya Gaur
 
Introduction to Design Patterns in Javascript
Introduction to Design Patterns in Javascript
Santhosh Kumar Srinivasan
 
Factory Design Pattern
Factory Design Pattern
Jaswant Singh
 
Avoid creating unncessary objects
Avoid creating unncessary objects
Ye Win
 
Design Patterns Illustrated
Design Patterns Illustrated
Herman Peeren
 
Patterns In-Javascript
Patterns In-Javascript
Mindfire Solutions
 
JavaScript - Programming Languages course
JavaScript - Programming Languages course
yoavrubin
 
Design pattern (Abstract Factory & Singleton)
Design pattern (Abstract Factory & Singleton)
paramisoft
 
25 java tough interview questions
25 java tough interview questions
Arun Banotra
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Philip Schwarz
 
Oop Extract
Oop Extract
Ganesh Samarthyam
 
Scalable JavaScript Design Patterns
Scalable JavaScript Design Patterns
Addy Osmani
 
Angular Interview Questions & Answers
Angular Interview Questions & Answers
Ratnala Charan kumar
 
Compositionality and Category Theory - a montage of slides/transcript for sec...
Compositionality and Category Theory - a montage of slides/transcript for sec...
Philip Schwarz
 
Definitions of Functional Programming
Definitions of Functional Programming
Philip Schwarz
 
Javascript Objects Deep Dive
Javascript Objects Deep Dive
Manish Jangir
 
Javascript Prototypal Inheritance - Big Picture
Javascript Prototypal Inheritance - Big Picture
Manish Jangir
 
Java Static Factory Methods
Java Static Factory Methods
Ye Win
 
Introduction to Design Patterns in Javascript
Introduction to Design Patterns in Javascript
Santhosh Kumar Srinivasan
 
Factory Design Pattern
Factory Design Pattern
Jaswant Singh
 
Avoid creating unncessary objects
Avoid creating unncessary objects
Ye Win
 
Design Patterns Illustrated
Design Patterns Illustrated
Herman Peeren
 
JavaScript - Programming Languages course
JavaScript - Programming Languages course
yoavrubin
 
Design pattern (Abstract Factory & Singleton)
Design pattern (Abstract Factory & Singleton)
paramisoft
 
25 java tough interview questions
25 java tough interview questions
Arun Banotra
 
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Scala 3 by Example - Algebraic Data Types for Domain Driven Design - Part 2
Philip Schwarz
 
Scalable JavaScript Design Patterns
Scalable JavaScript Design Patterns
Addy Osmani
 
Angular Interview Questions & Answers
Angular Interview Questions & Answers
Ratnala Charan kumar
 
Compositionality and Category Theory - a montage of slides/transcript for sec...
Compositionality and Category Theory - a montage of slides/transcript for sec...
Philip Schwarz
 
Definitions of Functional Programming
Definitions of Functional Programming
Philip Schwarz
 

Similar to Inverting Dependencies (20)

Ppt of c++ vs c#
Ppt of c++ vs c#
shubhra chauhan
 
Oop
Oop
Jun-jun Lagman
 
Abstract
Abstract
snehajyothi
 
OOPS Basics With Example
OOPS Basics With Example
Thooyavan Venkatachalam
 
Object oriented programming
Object oriented programming
MH Abid
 
Object Oriented Programming using C++(UNIT 1)
Object Oriented Programming using C++(UNIT 1)
Dr. SURBHI SAROHA
 
OOPS IN C++
OOPS IN C++
Amritsinghmehra
 
Polymorphism.Difference between Inheritance & Polymorphism
Polymorphism.Difference between Inheritance & Polymorphism
huzaifaakram12
 
Object Oriented Programming using C++: Ch09 Inheritance.pptx
Object Oriented Programming using C++: Ch09 Inheritance.pptx
RashidFaridChishti
 
Inheritance.ppt
Inheritance.ppt
KevinNicolaNatanael
 
4-OOPS.pptx
4-OOPS.pptx
SatyamMishra237306
 
Inheritance
Inheritance
sourav verma
 
Core idea driving and defining OO: using dynamic polymorphism to invert key a...
Core idea driving and defining OO: using dynamic polymorphism to invert key a...
Philip Schwarz
 
INHERITANCE.pptx
INHERITANCE.pptx
AteeqaKokab1
 
Oop concepts
Oop concepts
baabtra.com - No. 1 supplier of quality freshers
 
Visula C# Programming Lecture 7
Visula C# Programming Lecture 7
Abou Bakr Ashraf
 
OOP, API Design and MVP
OOP, API Design and MVP
Harshith Keni
 
CSharp_03_Inheritance_introduction_with_examples
CSharp_03_Inheritance_introduction_with_examples
Ranjithsingh20
 
C++ Multiple Inheritance
C++ Multiple Inheritance
harshaltambe
 
Unit 3
Unit 3
R S S RAJU BATTULA
 
Ad

More from Luc Trudeau (11)

Revue de l'année 2019 dans le monde des codecs videos
Revue de l'année 2019 dans le monde des codecs videos
Luc Trudeau
 
I don’t care if you have 360 Intra directional predictors
I don’t care if you have 360 Intra directional predictors
Luc Trudeau
 
Les technologies actuelles et futures de l'ott
Les technologies actuelles et futures de l'ott
Luc Trudeau
 
Chroma from Luma Intra Prediction for AV1
Chroma from Luma Intra Prediction for AV1
Luc Trudeau
 
Chroma From Luma Status Update
Chroma From Luma Status Update
Luc Trudeau
 
ML2 et le Codetributhon
ML2 et le Codetributhon
Luc Trudeau
 
HTTP Long Polling is awesome
HTTP Long Polling is awesome
Luc Trudeau
 
UML Class Diagrams are Awesome
UML Class Diagrams are Awesome
Luc Trudeau
 
Orchestre de services
Orchestre de services
Luc Trudeau
 
HTTP et REST
HTTP et REST
Luc Trudeau
 
Architecture vs Design
Architecture vs Design
Luc Trudeau
 
Revue de l'année 2019 dans le monde des codecs videos
Revue de l'année 2019 dans le monde des codecs videos
Luc Trudeau
 
I don’t care if you have 360 Intra directional predictors
I don’t care if you have 360 Intra directional predictors
Luc Trudeau
 
Les technologies actuelles et futures de l'ott
Les technologies actuelles et futures de l'ott
Luc Trudeau
 
Chroma from Luma Intra Prediction for AV1
Chroma from Luma Intra Prediction for AV1
Luc Trudeau
 
Chroma From Luma Status Update
Chroma From Luma Status Update
Luc Trudeau
 
ML2 et le Codetributhon
ML2 et le Codetributhon
Luc Trudeau
 
HTTP Long Polling is awesome
HTTP Long Polling is awesome
Luc Trudeau
 
UML Class Diagrams are Awesome
UML Class Diagrams are Awesome
Luc Trudeau
 
Orchestre de services
Orchestre de services
Luc Trudeau
 
Architecture vs Design
Architecture vs Design
Luc Trudeau
 
Ad

Recently uploaded (20)

Transmission Media. (Computer Networks)
Transmission Media. (Computer Networks)
S Pranav (Deepu)
 
Zoneranker’s Digital marketing solutions
Zoneranker’s Digital marketing solutions
reenashriee
 
Integrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FME
Safe Software
 
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Alluxio, Inc.
 
Shell Skill Tree - LabEx Certification (LabEx)
Shell Skill Tree - LabEx Certification (LabEx)
VICTOR MAESTRE RAMIREZ
 
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
WSO2
 
How the US Navy Approaches DevSecOps with Raise 2.0
How the US Navy Approaches DevSecOps with Raise 2.0
Anchore
 
Download Adobe Illustrator Crack free for Windows 2025?
Download Adobe Illustrator Crack free for Windows 2025?
grete1122g
 
How Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines Operations
Insurance Tech Services
 
FME as an Orchestration Tool - Peak of Data & AI 2025
FME as an Orchestration Tool - Peak of Data & AI 2025
Safe Software
 
Reimagining Software Development and DevOps with Agentic AI
Reimagining Software Development and DevOps with Agentic AI
Maxim Salnikov
 
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
BradBedford3
 
What is data visualization and how data visualization tool can help.pdf
What is data visualization and how data visualization tool can help.pdf
Varsha Nayak
 
Automated Migration of ESRI Geodatabases Using XML Control Files and FME
Automated Migration of ESRI Geodatabases Using XML Control Files and FME
Safe Software
 
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
Maharshi Mallela
 
About Certivo | Intelligent Compliance Solutions for Global Regulatory Needs
About Certivo | Intelligent Compliance Solutions for Global Regulatory Needs
certivoai
 
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
IFI Techsolutions
 
Open Source Software Development Methods
Open Source Software Development Methods
VICTOR MAESTRE RAMIREZ
 
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Technologies
 
What is data visualization and how data visualization tool can help.pptx
What is data visualization and how data visualization tool can help.pptx
Varsha Nayak
 
Transmission Media. (Computer Networks)
Transmission Media. (Computer Networks)
S Pranav (Deepu)
 
Zoneranker’s Digital marketing solutions
Zoneranker’s Digital marketing solutions
reenashriee
 
Integrating Survey123 and R&H Data Using FME
Integrating Survey123 and R&H Data Using FME
Safe Software
 
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Meet You in the Middle: 1000x Performance for Parquet Queries on PB-Scale Dat...
Alluxio, Inc.
 
Shell Skill Tree - LabEx Certification (LabEx)
Shell Skill Tree - LabEx Certification (LabEx)
VICTOR MAESTRE RAMIREZ
 
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
Application Modernization with Choreo - The AI-Native Internal Developer Plat...
WSO2
 
How the US Navy Approaches DevSecOps with Raise 2.0
How the US Navy Approaches DevSecOps with Raise 2.0
Anchore
 
Download Adobe Illustrator Crack free for Windows 2025?
Download Adobe Illustrator Crack free for Windows 2025?
grete1122g
 
How Insurance Policy Management Software Streamlines Operations
How Insurance Policy Management Software Streamlines Operations
Insurance Tech Services
 
FME as an Orchestration Tool - Peak of Data & AI 2025
FME as an Orchestration Tool - Peak of Data & AI 2025
Safe Software
 
Reimagining Software Development and DevOps with Agentic AI
Reimagining Software Development and DevOps with Agentic AI
Maxim Salnikov
 
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
Women in Tech: Marketo Engage User Group - June 2025 - AJO with AWS
BradBedford3
 
What is data visualization and how data visualization tool can help.pdf
What is data visualization and how data visualization tool can help.pdf
Varsha Nayak
 
Automated Migration of ESRI Geodatabases Using XML Control Files and FME
Automated Migration of ESRI Geodatabases Using XML Control Files and FME
Safe Software
 
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
Maharshi Mallela
 
About Certivo | Intelligent Compliance Solutions for Global Regulatory Needs
About Certivo | Intelligent Compliance Solutions for Global Regulatory Needs
certivoai
 
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
IFI Techsolutions
 
Open Source Software Development Methods
Open Source Software Development Methods
VICTOR MAESTRE RAMIREZ
 
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Technologies
 
What is data visualization and how data visualization tool can help.pptx
What is data visualization and how data visualization tool can help.pptx
Varsha Nayak
 

Inverting Dependencies

  • 1. 1 of 6 InvertingDependencies photo credit: Stéfan (http://www.flickr.com/photos/st3f4n/4085958000/) () via photopin (http://photopin.com) cc (http://creativecommons.org/licenses/by-nc-sa/2.0/) Polymorphism is the super power of the OO designer. However, many designers don't exploit this power, they use inheritance for structural purposes. In a language like Java, this results in an abuse of the instanceof statement (http://www.javapractices.com/topic/TopicAction.do?Id=31) . Maybe Polymorphism is not the right word; maybe we should use multiple personality disorder (not as sexy as polymorphism when you're trying to sell your OO suite...). Depending on the runtime context, the object does not change form, it does not morph, it changes behavior, it behaves as another object. But the interesting part of this mechanism is how the dependencies align. Looking at the dependencies from a UML Class diagram viewpoint, inheritance goes in the opposite direction as composition or aggregation. The next example shows two different ways for the print method of Object to invoke the myFunction method of Child. The first case, Child inherites from Object (Template Method Pattern (http://sourcemaking.com/design_patterns/template_method) ) this require the myFunction method to be present in Object. In the second case, Object depends on Child and invokes it.
  • 2. 2 of 6 Object void print() Child int myFunction() Object int myFunction() void print() Child int myFunction() However looking at it from a UML sequence diagram viewpoint, the direction of the method invocation is not reversed. o:Object c:Child print() myFunction() Concretely, inheritance is a tool that offers the possibility to inverse dependencies arrows while preserving the direction of behavioral arrows! This super power can be extremely powerful in light of architectural styles that impose constraints on the direction of dependencies. Examples of constraints imposed on the direction of dependencies are Robert C. Martin's "The Dependency Rule" (http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html) and the layers architectural style. The later imposes a downward "can use" relationship between layers. By using inheritance, one can respect this structural constraint of downward dependencies yet allow behavior to invoke upwards. Let see how all this works, but to do so, let's use a programming language that is not object oriented. This way the details will not be hidden away by syntactic sugar or by compiler magic. Let's start by defining Object with a simple struct (Object.h (https://github.com/luctrudeau/InvertingDependencies/blob/master/Object.h) ) struct Object; struct Object build(int a, int b); struct Object { int a; int b; 
  • 3. 3 of 6 The first line is a forward declaration, it's required because the Object structure is used inside the definition of the Object structure. Next, there's the build function that is the equivalent of a constructor/factory. Finally the Object structure is defined. Notice that the last two declarations are function pointers. These two function pointers are myFunction that expects an Object structure as parameter and print that also expects an Object structure as parameter. Notice that all the implementation details are hidden in Object.c (this is encapsulation). The idea behind this header file is to expose only the structure but not the behavior. No one knows, how build work, or even what's in myFunction or print, but they know that these functions exist. This separation is key in flipping the direction of the dependency without flipping the direction of invocation. To find out what the behavior is, we can look at the Object.c (https://github.com/luctrudeau/InvertingDependencies/blob/master/Object.c) file. Now we know that myFunction points to an add function, and that print simply does a printf. Even if not all languages use the same keyword, the concept of an abstract method is generally available. We can match this concept to the functions pointers. If these pointers are not assigned then the method is abstract. This is why you can't instantiate classes with abstract methods. Notice that the parameter of the functions inside the Object structure are structures of type Object. For now, we can think of this as a solution to the problem of accessing the values of the instance of the Object structure, but we will see shortly that there's another more int (*myFunction)(struct Object); void (*print)(struct Object); }; #include "Object.h" int add(struct Object o) { return o.a + o.b; } void print(struct Object o) { printf("Result = %dn", o.myFunction(o)); } struct Object build(int a, int b) { struct Object o; o.a = a; o.b = b; o.myFunction = &add; o.print = &print; return o; } 
  • 4. 4 of 6 profound mechanism at work here. Some programming languages hide this detail behind the "this" keyword, others like python will make the instance parameter visible to developer and define it as the first parameter of every method. Let's say main.c wants to use the Object structure, it only need to include "Object.h", it does not need to care about Object.c. If we look at the dependencies we can see the inversion effect. The main.c file depends on Object.h but Object.h does not depend upon Object.c, it's the other way around Object.c depends upon Object.h. The header file is an abstraction. main.c Object.h struct Object struct Object build(int a, int b) Object.c int add(struct Object o){...} void print(struct Object o){...} struct Object build(int a, int b) {...} <<includes>> <<includes>> Now let's try inheritance, I'm not interested in structural inheritance, I don't want to add a third variable to Object. I'm interested in polymorphism; I want to change the behavior of Object. This is the content of Child.h (https://github.com/luctrudeau/InvertingDependencies/blob/master/Child.h) The Child depends on Object.h and defines a new constructor/factory buildChild. Let's look at its behavior (Child.c (https://github.com/luctrudeau/InvertingDependencies/blob/master/Child.c) ) #include "Object.h" struct Object buildChild(int a, int b);  #include "Child.h" int sub(struct Object o) { return o.a - o.b; } struct Object buildChild(int a, int b) { struct Object o = build(a,b); o.myFunction = &sub; return o; } 
  • 5. 5 of 6 Instead of invoking the add function, the Child version of the Object structure will invoke the sub function. Notice how the buildChild function invokes build of Object and then overrides the myFunction function pointer. Now we have an Object that acts like a Child, yet almost no one needs to know. The only entity that needs to know is the one calling buildChild function instead of the build function. This switch can be executed dynamically at runtime. Looking at main.c we can see that the choice between the build or the buildChild functions is performed dynamically based on a random variable. Dependency injection (http://martinfowler.com/articles/injection.html) is exactly what is going on inside the print function. At runtime, when the buildChild function is selected, the Child variant of Object is being injected into the print function. This is interesting because the type of the parameter is mandatory (aka closed (http://en.wikipedia.org/wiki/Open/closed_principle) ) but its behavior is not (aka open (http://en.wikipedia.org/wiki/Open/closed_principle) ). The Child variant of Object can be developed years after Object was written, by completely different developers, yet it will still work inside print function without requiring modifications to the print function. #include <stdio.h> #include <stdlib.h> #include <time.h> #include "Object.h" #include "Child.h" int main() { struct Object o; srand(time(0)); if (rand() % 2) { o = buildChild(5, 3); } else { o = build(2, 3); } o.print(o); } 