En aquest tema, explorarem els principis fonamentals que guien el disseny de programari robust, escalable i mantenible. Aquests principis són essencials per a qualsevol arquitecte de sistemes o desenvolupador que desitgi crear solucions tecnològiques eficients i efectives.
- Principis KISS (Keep It Simple, Stupid)
El principi KISS defensa la simplicitat en el disseny de programari. La idea és mantenir el codi tan simple com sigui possible per facilitar la comprensió, el manteniment i la modificació.
Exemples:
- Codi Simple: Evitar la complexitat innecessària en el codi.
- Funcions Curtes: Escriure funcions que facin una sola cosa i la facin bé.
- Principi DRY (Don't Repeat Yourself)
El principi DRY promou la reducció de la duplicació de codi. Quan un codi es repeteix, és més difícil de mantenir i actualitzar.
Exemples:
- Reutilització de Codi: Crear funcions o mòduls reutilitzables.
- Abstracció: Utilitzar classes i funcions per encapsular comportaments comuns.
# Exemple de reutilització de codi def calcular_area_rectangle(amplada, altura): return amplada * altura def calcular_area_quadrat(costat): return calcular_area_rectangle(costat, costat)
- Principi YAGNI (You Aren't Gonna Need It)
El principi YAGNI aconsella no implementar funcionalitats que no siguin necessàries en el moment. Això ajuda a mantenir el codi net i evita la complexitat innecessària.
Exemples:
- Funcionalitats Essencials: Implementar només les funcionalitats que són necessàries ara.
- Evitar Sobredisseny: No anticipar necessitats futures que poden no arribar mai.
# Exemple de codi sense funcionalitats innecessàries def calcular_area_rectangle(amplada, altura): return amplada * altura
- Principi de Responsabilitat Única (SRP)
El principi de responsabilitat única estableix que una classe o mòdul ha de tenir una sola raó per canviar, és a dir, ha de tenir una única responsabilitat.
Exemples:
- Classes Cohesionades: Cada classe ha de tenir una única responsabilitat.
- Mòduls Independents: Dividir el codi en mòduls independents amb responsabilitats clares.
# Exemple de classe amb responsabilitat única class GestorDeUsuaris: def crear_usuari(self, nom, correu): # Lògica per crear un usuari pass class GestorDeCorreus: def enviar_correu(self, destinatari, assumpte, missatge): # Lògica per enviar un correu pass
- Principi de Substitució de Liskov (LSP)
El principi de substitució de Liskov estableix que els objectes d'una classe derivada han de poder substituir els objectes de la seva classe base sense alterar el comportament del programa.
Exemples:
- Herència Correcta: Les subclasses han de complir amb el contracte establert per la classe base.
- Polimorfisme: Utilitzar el polimorfisme per garantir la substituïbilitat.
# Exemple de principi de substitució de Liskov class Animal: def fer_soroll(self): pass class Gos(Animal): def fer_soroll(self): return "Bup Bup" class Gat(Animal): def fer_soroll(self): return "Miau" def fer_soroll_animal(animal): print(animal.fer_soroll()) gos = Gos() gat = Gat() fer_soroll_animal(gos) # Bup Bup fer_soroll_animal(gat) # Miau
- Principi de Segregació d'Interfícies (ISP)
El principi de segregació d'interfícies estableix que els clients no han de dependre d'interfícies que no utilitzen. És millor tenir moltes interfícies específiques que una interfície general.
Exemples:
- Interfícies Específiques: Crear interfícies petites i específiques per a cada funcionalitat.
- Evitar Interfícies Grans: No crear interfícies que forcin els clients a implementar mètodes que no necessiten.
# Exemple de principi de segregació d'interfícies class Imprimible: def imprimir(self): pass class Escanejable: def escanejar(self): pass class Impressora(Imprimible, Escanejable): def imprimir(self): print("Imprimint document") def escanejar(self): print("Escanejant document")
- Principi d'Inversió de Dependència (DIP)
El principi d'inversió de dependència estableix que els mòduls d'alt nivell no han de dependre dels mòduls de baix nivell. Ambdós han de dependre d'abstraccions.
Exemples:
- Dependència d'Abstraccions: Utilitzar interfícies o classes abstractes per definir dependències.
- Injecció de Dependències: Injectar les dependències a través de constructors o mètodes.
# Exemple de principi d'inversió de dependència class Repositori: def guardar(self, dades): pass class RepositoriSQL(Repositori): def guardar(self, dades): print("Guardant dades en SQL") class Servei: def __init__(self, repositori: Repositori): self.repositori = repositori def processar(self, dades): self.repositori.guardar(dades) repositori_sql = RepositoriSQL() servei = Servei(repositori_sql) servei.processar("Algunes dades")
Exercicis Pràctics
Exercici 1: Aplicar KISS i DRY
Refactoritza el següent codi per aplicar els principis KISS i DRY:
def calcular_area_rectangle(amplada, altura): return amplada * altura def calcular_area_quadrat(costat): return costat * costat def calcular_area_cercle(radi): return 3.14 * radi * radi
Solució:
def calcular_area_rectangle(amplada, altura): return amplada * altura def calcular_area_quadrat(costat): return calcular_area_rectangle(costat, costat) def calcular_area_cercle(radi): return 3.14 * radi * radi
Exercici 2: Aplicar SRP
Refactoritza el següent codi per aplicar el principi de responsabilitat única:
class GestorDeDocuments: def crear_document(self, contingut): # Lògica per crear un document pass def enviar_document(self, destinatari, document): # Lògica per enviar un document pass
Solució:
class GestorDeDocuments: def crear_document(self, contingut): # Lògica per crear un document pass class GestorDeCorreus: def enviar_document(self, destinatari, document): # Lògica per enviar un document pass
Conclusió
Els principis de disseny de programari són fonamentals per crear sistemes robustos, escalables i fàcils de mantenir. Aquests principis ajuden a evitar la complexitat innecessària, promouen la reutilització del codi i asseguren que el programari sigui fàcil de modificar i estendre. En el proper tema, explorarem els patrons de disseny, que són solucions provades per a problemes comuns en el disseny de programari.
Arquitectures de Sistemes: Principis i Pràctiques per Dissenyar Arquitectures Tecnològiques Robustes i Escalables
Mòdul 1: Introducció a les Arquitectures de Sistemes
- Conceptes Bàsics d'Arquitectura de Sistemes
- Importància d'una Bona Arquitectura
- Tipus d'Arquitectures de Sistemes
Mòdul 2: Principis de Disseny d'Arquitectures
Mòdul 3: Components d'una Arquitectura de Sistemes
Mòdul 4: Escalabilitat i Rendiment
Mòdul 5: Seguretat en Arquitectures de Sistemes
Mòdul 6: Eines i Tecnologies
Mòdul 7: Casos d'Estudi i Exemples Pràctics
- Cas d'Estudi: Arquitectura d'un Sistema de Comerç Electrònic
- Cas d'Estudi: Arquitectura d'una Aplicació de Xarxes Socials
- Exercicis Pràctics