La inversion de control, no es exclusiva de un lenguaje y como me encanta GO, voy a utilizarlo como base para el ejemplo.

Realmente entendiendo el acoplamiento y aplicándolo a tu día a día, ya te podrías considerar un buen programador. Aunque obviamente hay mas conceptos a parte del acoplamiento, como es la cohesion entre «cosas» y la reutilización. Pero el acoplamiento es muy importante para que un proyecto sea «flexible«

El objeto tiene el control

La imagen que he puesto en el principio del post, no tiene el «control invertido». Pogamos el código

package main

import "fmt"

type Developer struct {
	Name     string
	Type     string
	Language string
}
type Printer struct {
	Dev Developer
}

func New() Printer {
	d := Developer{
		Name:     "Alberto",
		Type:     "Backend",
		Language: "Go",
	}
	return Printer{Dev: d}
}

func (p *Printer) SayHello() {
	d := p.Dev
	fmt.Printf("Developer [Name: %s] [Type: %s] [Language: %s]", d.Name, d.Type, d.Language)
}

func main() {
	h := New()
	h.SayHello()
}

El código se ha complicado y no tiene mucho sentido, pero sólo es para ilustrar como cambiamos el control de la creación de instancias y desacoplamos.

Pero que coñ…

Es una locura que el objeto printer cree lo que quiere imprimir. Esto acopla la creación de Developer dentro del «constructor» de printer. (como he dicho antes no tiene mucho sentido).

Ahora y en el ejemplo que he puesto antes printer tiene un acoplamiento con developer y es el que tiene el «control», para crear dicho developer. Que problemas tenemos aquí, a parte del acoplamiento ?. No podemos reutilizar Developer en ningún sitio, ya que es de uso interno, esto nos obligaría a crear en cada parte que se necesite este developer una instancia igual.

Invirtiendo el control

Para invertir el control, debemos sacar la responsabilidad de la creación de developer fuera de printer

package main

import "fmt"

type Developer struct {
	Name     string
	Type     string
	Language string
}
type Printer struct {
	Dev Developer
}

func New(d Developer) Printer {
	return Printer{Dev: d}
}

func (p *Printer) SayHello() {
	d := p.Dev
	fmt.Printf("Developer [Name: %s] [Type: %s] [Language: %s]", d.Name, d.Type, d.Language)
}

func main() {
	d := Developer{
		Name:     "Alberto",
		Type:     "Backend",
		Language: "Go",
	}
	h := New(d)
	h.SayHello()
}

Si!. Así de simple, invertir el control es quitar el control de la instanciación de objetos a un contexto superior que cree el gráficos de dependencias (hablaremos de esto en la inyección de dependencias).

Más adelante hablaremos de inyección de dependencias / evento, para gestionar la inversión de control. Añadiremos interfaces para ilustrar la inyección y como se resuelven, como se generan los ágrafos, etc..

Deja una respuesta