|
| 1 | +# ╔═════════════════════════════════════╗ |
| 2 | +# ║ Autor: Kenys Alvarado ║ |
| 3 | +# ║ GitHub: https://github.com/Kenysdev ║ |
| 4 | +# ║ 2024 - Python ║ |
| 5 | +# ╚═════════════════════════════════════╝ |
| 6 | + |
| 7 | +# ------------------------------------------------- |
| 8 | +# * SOLID: PRINCIPIO DE RESPONSABILIDAD ÚNICA (SRP) |
| 9 | +# ------------------------------------------------- |
| 10 | +# Se centra en la claridad, la cohesión y la separación de intereses. |
| 11 | +# Cada clase debe tener una única razón para cambiar. |
| 12 | +# Los metodos de una clase deben estar estrechamente relacionadas. |
| 13 | + |
| 14 | +""" |
| 15 | +* EJERCICIO #1: |
| 16 | +* Explora el "Principio SOLID de Responsabilidad Única (Single Responsibility |
| 17 | +* Principle, SRP)" y crea un ejemplo simple donde se muestre su funcionamiento |
| 18 | +* de forma correcta e incorrecta. |
| 19 | +""" |
| 20 | + |
| 21 | +#_______________________________________ |
| 22 | +# SIN APLICAR EL PRINCIPIO: |
| 23 | + |
| 24 | +class Program(): |
| 25 | + def __init__(self): |
| 26 | + self.customers: list = [] |
| 27 | + self.suppliers: list = [] |
| 28 | + |
| 29 | + def add_customer(self, name): |
| 30 | + self.customers.append(name) |
| 31 | + |
| 32 | + def add_supplier(self, name): |
| 33 | + self.suppliers.append(name) |
| 34 | + |
| 35 | + def remove_customer(self, name): |
| 36 | + self.customers.remove(name) |
| 37 | + |
| 38 | + def remove_supplier(self, name): |
| 39 | + self.suppliers.remove(name) |
| 40 | + |
| 41 | + |
| 42 | +#_______________________________________ |
| 43 | +# APLICANDO EL PRINCIPIO: |
| 44 | + |
| 45 | +class Customers(): |
| 46 | + def __init__(self): |
| 47 | + self.customers: list = [] |
| 48 | + |
| 49 | + def add(self, name: str): |
| 50 | + self.customers.append(name) |
| 51 | + |
| 52 | + def remove(self, name: str): |
| 53 | + self.customers.remove(name) |
| 54 | + |
| 55 | + # ... más métodos relacionados. |
| 56 | + |
| 57 | +class Suppliers(): |
| 58 | + def __init__(self): |
| 59 | + self.suppliers: list = [] |
| 60 | + |
| 61 | + def add(self, name: str): |
| 62 | + self.suppliers.append(name) |
| 63 | + |
| 64 | + def remove(self, name: str): |
| 65 | + self.suppliers.remove(name) |
| 66 | + |
| 67 | + # ... más métodos relacionados. |
| 68 | + |
| 69 | + |
| 70 | +""" |
| 71 | +* EJERCICIO #2: |
| 72 | +* Desarrolla un sistema de gestión para una biblioteca. El sistema necesita |
| 73 | +* manejar diferentes aspectos como el registro de libros, la gestión de usuarios |
| 74 | +* y el procesamiento de préstamos de libros. |
| 75 | +* Requisitos: |
| 76 | +* 1. Registrar libros: El sistema debe permitir agregar nuevos libros con |
| 77 | +* información básica como título, autor y número de copias disponibles. |
| 78 | +* 2. Registrar usuarios: El sistema debe permitir agregar nuevos usuarios con |
| 79 | +* información básica como nombre, número de identificación y correo electrónico. |
| 80 | +* 3. Procesar préstamos de libros: El sistema debe permitir a los usuarios |
| 81 | +* tomar prestados y devolver libros. |
| 82 | +* Instrucciones: |
| 83 | +* 1. Diseña una clase que no cumple el SRP: Crea una clase Library que maneje |
| 84 | +* los tres aspectos mencionados anteriormente (registro de libros, registro de |
| 85 | +* usuarios y procesamiento de préstamos). |
| 86 | +* 2. Refactoriza el código: Separa las responsabilidades en diferentes clases |
| 87 | +* siguiendo el Principio de Responsabilidad Única. |
| 88 | +""" |
| 89 | + |
| 90 | +#____________________________________________________________________________ |
| 91 | +# SIN APLICAR SRP: |
| 92 | + |
| 93 | +class Library(): |
| 94 | + def __init__(self): |
| 95 | + self.books: dict = {} |
| 96 | + self.users: dict = {} |
| 97 | + self.borrowed: dict = {} |
| 98 | + |
| 99 | + def add_book(self, id_book: int, title: str, author: str, stock: int): |
| 100 | + if id_book in self.books: |
| 101 | + self.books[id_book]['stock'] += stock |
| 102 | + self.books[id_book]['available'] += stock |
| 103 | + print("El libro ya existe, se actualizó el inventario.") |
| 104 | + |
| 105 | + else: |
| 106 | + self.books[id_book] = { |
| 107 | + 'title': title, |
| 108 | + 'author': author, |
| 109 | + 'stock': stock, |
| 110 | + 'available': stock |
| 111 | + } |
| 112 | + print(f"\nSe agrego el libro '{title}'.") |
| 113 | + |
| 114 | + def add_user(self, id_user: int, name: str, email: str): |
| 115 | + if id_user in self.users: |
| 116 | + print("Usuario ya existee") |
| 117 | + |
| 118 | + else: |
| 119 | + self.users[id_user] = { |
| 120 | + 'name': name, |
| 121 | + 'email': email |
| 122 | + } |
| 123 | + print(f"\nSe agrego a '{name}'.") |
| 124 | + |
| 125 | + def lend_book(self, id_borrowed: int, id_user: int, id_book: int): |
| 126 | + if id_book not in self.books: |
| 127 | + print("Este libro no existe") |
| 128 | + return |
| 129 | + |
| 130 | + if id_user not in self.users: |
| 131 | + print("Este usuario no existe") |
| 132 | + return |
| 133 | + |
| 134 | + if self.books[id_book]['available'] > 0: |
| 135 | + self.borrowed[id_borrowed] = { |
| 136 | + 'id_user': id_user, |
| 137 | + 'id_book': id_book |
| 138 | + } |
| 139 | + self.books[id_book]['available'] -= 1 |
| 140 | + print(f"\nSe presto el libro '{id_book}'.") |
| 141 | + |
| 142 | + else: |
| 143 | + print(f"No hay libro disponible.") |
| 144 | + |
| 145 | + def return_book(self, id_borrowed: int): |
| 146 | + if id_user not in self.borrowed: |
| 147 | + print("No está registrado.") |
| 148 | + |
| 149 | + else: |
| 150 | + self.books[id_borrowed[id_book]]['available'] += 1 |
| 151 | + del self.borrowed[id_borrowed] |
| 152 | + print("Retorno exitoso.") |
| 153 | + |
| 154 | + def print_books(self): |
| 155 | + print("Lista de libros:\n", self.books) |
| 156 | + |
| 157 | + def print_users(self): |
| 158 | + print("Lista de usuarios", self.users) |
| 159 | + |
| 160 | + def print_borrowed(self): |
| 161 | + print("Lista de libros prestados", self.borrowed) |
| 162 | + |
| 163 | +#____________________________________________________________________________ |
| 164 | +# APLICANDO SRP: |
| 165 | + |
| 166 | +class LibraryData: # uso de SINGLETON para tener datos globales |
| 167 | + _instance = None |
| 168 | + |
| 169 | + def __new__(cls): |
| 170 | + if not cls._instance: |
| 171 | + cls._instance = super().__new__(cls) |
| 172 | + cls.books = {} |
| 173 | + cls.users = {} |
| 174 | + cls.borrowed = {} |
| 175 | + |
| 176 | + return cls._instance |
| 177 | + |
| 178 | +#___________________ |
| 179 | +class Books: |
| 180 | + def __init__(self): |
| 181 | + self.data = LibraryData() |
| 182 | + |
| 183 | + def add(self, id_book: int, title: str, author: str, stock: int): |
| 184 | + if id_book in self.data.books: |
| 185 | + self.data.books[id_book]['stock'] += stock |
| 186 | + self.data.books[id_book]['available'] += stock |
| 187 | + print("El libro ya existe, se actualizó el inventario.") |
| 188 | + return |
| 189 | + |
| 190 | + self.data.books[id_book] = { |
| 191 | + 'title': title, |
| 192 | + 'author': author, |
| 193 | + 'stock': stock, |
| 194 | + 'available': stock |
| 195 | + } |
| 196 | + print(f"\nSe agrego el libro '{title}'.") |
| 197 | + |
| 198 | + def print_dic(self): |
| 199 | + print("\nLibros:") |
| 200 | + if self.data.books: |
| 201 | + for ky, values in self.data.books.items(): |
| 202 | + print(f"{ky}: {values}") |
| 203 | + else: |
| 204 | + print("- Vacio") |
| 205 | + |
| 206 | +#___________________ |
| 207 | +class Users: |
| 208 | + def __init__(self): |
| 209 | + self.data = LibraryData() |
| 210 | + |
| 211 | + def add(self, id_user: int, name: str, email: str): |
| 212 | + if id_user in self.data.users: |
| 213 | + print("Usuario ya existe.") |
| 214 | + return |
| 215 | + |
| 216 | + self.data.users[id_user] = { |
| 217 | + 'name': name, |
| 218 | + 'email': email |
| 219 | + } |
| 220 | + print(f"\nSe agrego a '{name}'.") |
| 221 | + |
| 222 | + def print_dic(self): |
| 223 | + print("\nUsuarios:") |
| 224 | + if self.data.users: |
| 225 | + for ky, values in self.data.users.items(): |
| 226 | + print(f"{ky}: {values}") |
| 227 | + else: |
| 228 | + print("- Vacio") |
| 229 | + |
| 230 | +#___________________ |
| 231 | +class BorrowedBooks: |
| 232 | + def __init__(self): |
| 233 | + self.data = LibraryData() |
| 234 | + |
| 235 | + def _verify(self, id_user: int, id_book: int) -> bool: |
| 236 | + if id_book not in self.data.books: |
| 237 | + print("Este libro no existe") |
| 238 | + return False |
| 239 | + |
| 240 | + if id_user not in self.data.users: |
| 241 | + print("Este usuario no existe") |
| 242 | + return False |
| 243 | + |
| 244 | + if self.data.books[id_book]['available'] <= 0: |
| 245 | + print(f"El libro no está disponible.") |
| 246 | + return False |
| 247 | + |
| 248 | + return True |
| 249 | + |
| 250 | + def lend(self, id_borrowed: int, id_user: int, id_book: int): |
| 251 | + if self._verify(id_user, id_book) == False: |
| 252 | + return |
| 253 | + |
| 254 | + self.data.borrowed[id_borrowed] = { |
| 255 | + 'id_user': id_user, |
| 256 | + 'id_book': id_book |
| 257 | + } |
| 258 | + self.data.books[id_book]['available'] -= 1 |
| 259 | + print(f"\nSe presto el libro '{id_book}'.") |
| 260 | + |
| 261 | + def return_book(self, id_borrowed: int): |
| 262 | + if id_borrowed not in self.data.borrowed: |
| 263 | + print("No está registrado.") |
| 264 | + return |
| 265 | + |
| 266 | + id_book = self.data.borrowed[id_borrowed]['id_book'] |
| 267 | + self.data.books[id_book]['available'] += 1 |
| 268 | + del self.data.borrowed[id_borrowed] |
| 269 | + print(f"\nRetorno exitoso del libro '{id_book}'.") |
| 270 | + |
| 271 | + def print_dic(self): |
| 272 | + print("\nLibros prestados:") |
| 273 | + if self.data.borrowed: |
| 274 | + for ky, values in self.data.borrowed.items(): |
| 275 | + print(f"{ky}: {values}") |
| 276 | + else: |
| 277 | + print("- Vacio") |
| 278 | + |
| 279 | +#_________________________________ |
| 280 | +# Pruebas positivas |
| 281 | + |
| 282 | +books = Books() |
| 283 | +users = Users() |
| 284 | +borrowed_books = BorrowedBooks() |
| 285 | + |
| 286 | +# id, title, author, stock |
| 287 | +books.add(1, "Libro A", "Ben", 1) |
| 288 | +books.add(2, "Libro B", "Dan", 3) |
| 289 | + |
| 290 | +# id, name, email |
| 291 | +users. add( 10, "Zoe", "[email protected]") |
| 292 | +users. add( 11, "Ana", "[email protected]") |
| 293 | + |
| 294 | +books.print_dic() |
| 295 | +users.print_dic() |
| 296 | +borrowed_books.print_dic() |
| 297 | + |
| 298 | +# id_borrowed, id_user, id_book |
| 299 | +borrowed_books.lend(100, 10, 1) |
| 300 | +borrowed_books.lend(101, 11, 2) |
| 301 | + |
| 302 | +books.print_dic() |
| 303 | +borrowed_books.print_dic() |
| 304 | + |
| 305 | +# id_borrowed |
| 306 | +borrowed_books.return_book(100) |
| 307 | +borrowed_books.return_book(101) |
| 308 | + |
| 309 | +books.print_dic() |
| 310 | +borrowed_books.print_dic() |
| 311 | + |
| 312 | +borrowed_books.lend(103, 11, 1) |
| 313 | + |
| 314 | +#_________________________________ |
| 315 | +# Pruebas negativas |
| 316 | +print("\n_____\nPruebas negativas") |
| 317 | +books.add(2, "..", "..", 1) |
| 318 | +users.add(11, "..", "..") |
| 319 | +borrowed_books.lend(104, 10, 1) |
| 320 | +borrowed_books.return_book(100) |
| 321 | + |
0 commit comments