Los principios SOLID son un conjunto de buenas prácticas de diseño de software que ayudan a crear código más mantenible, escalable y flexible. A continuación se explican cada uno de ellos aplicados en el contexto de Angular, con ejemplos prácticos.

1. S: Principio de Responsabilidad Única (Single Responsibility Principle - SRP)

Cada clase, componente o servicio debe tener una única responsabilidad. En Angular, esto significa que un componente o servicio debe hacer solo una cosa.

Ejemplo:

Supongamos que tienes un componente que se encarga tanto de obtener los datos de un servidor como de mostrarlos en pantalla. Esto viola el SRP porque tiene dos responsabilidades.

Incorrecto:

typescript
@Component({
  selector: 'app-user',
  templateUrl: './user.component.html'
})
export class UserComponent {
  users: any[];

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.http.get('api/users').subscribe((data) => {
      this.users = data;
    });
  }
}

Aquí el componente está manejando tanto la obtención de los datos como la presentación.

Correcto: Separa la lógica de obtención de datos en un servicio.

typescript
@Injectable({
  providedIn: 'root'
})
export class UserService {
  constructor(private http: HttpClient) {}

  getUsers() {
    return this.http.get('api/users');
  }
}

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html'
})
export class UserComponent {
  users: any[];

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.userService.getUsers().subscribe((data) => {
      this.users = data;
    });
  }
}

Ahora el componente solo se encarga de mostrar los datos, y el servicio se encarga de obtenerlos.


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

Las clases, módulos o funciones deben estar abiertas para extensión, pero cerradas para modificación. En Angular, esto se traduce en que los servicios o componentes deben poder extenderse sin necesidad de ser modificados.

Ejemplo:

Supongamos que tenemos un servicio que realiza operaciones básicas de log (registro).

Incorrecto:

typescript
@Injectable({
  providedIn: 'root'
})
export class LoggerService {
  logMessage(message: string) {
    console.log(message);
  }
}

Si más adelante necesitas agregar un nuevo tipo de log, como escribir en un archivo, tendrías que modificar este servicio.

Correcto: Podrías utilizar un patrón de diseño que permita la extensión sin modificar el código existente, como el patrón de estrategia.