Principios SOLID en Go: de la teoría a la práctica en Golang

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

Principios SOLID en Go: teoría y práctica de la A a la Z



SOLID es el acrónimo de cinco principios fundamentales del diseño orientado a objetos, formulados por Robert Martin (Tío Bob). A pesar de que Go no es un lenguaje clásicamente orientado a objetos (no tiene clases ni herencia en el sentido tradicional), estos principios son aplicables y críticamente importantes para crear código de calidad, mantenible y escalable. En este artículo, analizaremos cada principio SOLID con ejemplos de la práctica real en Go.



1. Single Responsibility Principle (SRP) — Principio de Responsabilidad Única



Esencia: Cada módulo, estructura o función debe tener una sola razón para cambiar. En otras palabras, deben encargarse de una tarea claramente definida.



Problema: A menudo, los desarrolladores colocan toda la lógica en una sola estructura: validación, guardado en la base de datos, envío de correo electrónico, formateo de la respuesta. Esto lleva a "objetos divinos" (God Objects) que son difíciles de probar y modificar.



Solución en Go: Divida la responsabilidad entre diferentes estructuras y paquetes.



// ❌ Mal: Una sola estructura lo hace todotype UserService struct {    db *sql.DB    mailer *Mailer}

func (s *UserService) CreateUser(name, email string) error { // 1. Validación if !strings.Contains(email, "@") { return errors.New("correo inválido") } // 2. Guardado en la BD _, err := s.db.Exec("INSERT INTO users (name, email) VALUES ($1, $2)", name, email) if err != nil { return err } // 3. Envío de correo de bienvenida return s.mailer.Send(email, "¡Bienvenido!", "Gracias por registrarte")}

// ✅ Bien: Separación de responsabilidadestype UserValidator struct{}func (v *UserValidator) Validate(email string) error { if !strings.Contains(email, "@") { return errors.New("correo inválido") } return nil}

type UserRepository struct { db *sql.DB}func (r *UserRepository) Save(name, email string) error { _, err := r.db.Exec("INSERT INTO users (name, email) VALUES ($1, $2)", name, email) return err}

type WelcomeMailer struct { mailer *Mailer}func (m *WelcomeMailer) Send(email string) error { return m.mailer.Send(email, "¡Bienvenido!", "Gracias por registrarte")}

type UserService struct { validator *UserValidator repo *UserRepository mailer *WelcomeMailer}

func (s *UserService) CreateUser(name, email string) error { if err := s.validator.Validate(email); err != nil { return err } if err := s.repo.Save(name, email); err != nil { return err } return s.mailer.Send(email)}


Consejo práctico: Si no puede describir brevemente lo que hace su función o método sin usar la conjunción "y", es probable que se haya violado el SRP.



2. Open-Closed Principle (OCP) — Principio de Abierto/Cerrado



Esencia: Las entidades de software (estructuras, funciones, paquetes) deben estar abiertas para la extensión, pero cerradas para la modificación. Esto significa que debe poder agregar nuevo comportamiento sin modificar el código existente.



Solución en Go: Use interfaces para abstraer el comportamiento.



// ❌ Mal: Al agregar un nuevo tipo de pago, se debe modificar la función ProcessPaymenttype PaymentProcessor struct{}

func (p *PaymentProcessor) Process(paymentType string, amount float64) { if paymentType == "credit_card" { // lógica para tarjeta de crédito } else if paymentType == "paypal" { // lógica para PayPal } // Al agregar "crypto" — se debe agregar un nuevo else if}

// ✅ Bien: La interfaz permite extender la funcionalidad sin modificar el códigotype PaymentMethod interface { Pay(amount float64) error}

type CreditCard struct{}func

Blogs

Book Recommendations