Principios SOLID en Go: teoría y práctica para desarrolladores

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿Por qué es importante SOLID en Go?

SOLID son cinco principios fundamentales de la programación orientada a objetos que ayudan a crear código flexible, mantenible y extensible. Aunque Go no es un lenguaje OOP clásico (no tiene clases ni herencia), estos principios se aplican perfectamente gracias a las interfaces, la composición y el tipado estricto. En este artículo analizaremos cada principio SOLID con ejemplos en Go para que puedas escribir código de mayor calidad y escalable.



1. Single Responsibility Principle (SRP) — Principio de responsabilidad única

SRP establece: "Un módulo debe tener una sola razón para cambiar". En Go, esto significa que una función, estructura o paquete debe encargarse de una tarea claramente definida.



Ejemplo incorrecto (violación de SRP):

type Report struct {    Title string    Body  string}

func (r *Report) Generate() string { return fmt.Sprintf("<h1>%s</h1><p>%s</p>", r.Title, r.Body)}

func (r *Report) SaveToFile(filename string) error { return os.WriteFile(filename, []byte(r.Generate()), 0644)}

func (r *Report) SendEmail(addr string) error { // lógica de envío de email return nil}

Aquí la estructura Report se encarga de la generación, el guardado y el envío — tres razones diferentes para cambiar.



Ejemplo correcto (cumplimiento de SRP):

type Report struct {    Title string    Body  string}

func (r *Report) Generate() string { return fmt.Sprintf("<h1>%s</h1><p>%s</p>", r.Title, r.Body)}

type ReportSaver struct{}

func (rs *ReportSaver) SaveToFile(report *Report, filename string) error { return os.WriteFile(filename, []byte(report.Generate()), 0644)}

type EmailSender struct{}

func (es *EmailSender) Send(report *Report, addr string) error { // lógica de envío de email return nil}

Ahora cada entidad tiene una única responsabilidad: generación, guardado y envío.



2. Open/Closed Principle (OCP) — Principio de abierto/cerrado

OCP afirma: "Las entidades de software deben estar abiertas para la extensión, pero cerradas para la modificación". En Go esto se logra mediante interfaces y composición.



Ejemplo incorrecto (violación de OCP):

type PaymentProcessor struct{}

func (p *PaymentProcessor) Process(paymentType string, amount float64) { if paymentType == "credit_card" { // procesamiento de tarjeta de crédito } else if paymentType == "paypal" { // procesamiento de PayPal } else if paymentType == "crypto" { // procesamiento de criptomoneda }}

Al agregar un nuevo tipo de pago, habría que modificar el método Process.



Ejemplo correcto (cumplimiento de OCP):

type PaymentMethod interface {    Pay(amount float64) error}

type CreditCard struct{}func (c *CreditCard) Pay(amount float64) error { // lógica de pago con tarjeta return nil}

type PayPal struct{}func (p *PayPal) Pay(amount float64) error { // lógica de pago con PayPal return nil}

type PaymentProcessor struct{}

func (pp *PaymentProcessor) Process(method PaymentMethod, amount float64) error { return method.Pay(amount)}

Ahora para agregar un nuevo método de pago basta con implementar la interfaz PaymentMethod, sin tocar el código existente.



3. Liskov Substitution Principle (LSP) — Principio de sustitución de Barbara Liskov

LSP exige: "Los objetos de un programa deben ser reemplazables por instancias de sus subtipos sin alterar la corrección del programa". En Go esto se refiere a la implementación de interfaces.



Ejemplo incorrecto (violación de LSP):

type Bird interface {    Fly() error}

type Penguin struct{}func (p *Penguin) Fly() error { return errors.New("los pingüinos no vuelan")}

func LetBirdFly(b Bird) {

Blogs

Book Recommendations