@icarusmx/creta 1.3.4 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/creta.js +8 -1576
- package/codex-refactor.txt +13 -0
- package/lib/builders/LessonBuilder.js +228 -0
- package/lib/builders/MenuBuilder.js +154 -0
- package/lib/builders/ProjectBuilder.js +56 -0
- package/lib/cli/index.js +81 -0
- package/lib/commands/help.js +5 -0
- package/lib/constants/paths.js +9 -0
- package/lib/data/enunciados.js +44 -0
- package/lib/data/lessons/index.js +25 -0
- package/lib/data/lessons/lesson1-system-decomposition.js +312 -0
- package/lib/data/lessons/lesson2-object-requests.js +318 -0
- package/lib/data/lessons/lesson3-only-way.js +349 -0
- package/lib/data/lessons/lesson4-operation-signatures.js +332 -0
- package/lib/data/lessons/lesson5-interface-set.js +341 -0
- package/lib/data/lessons/lesson6-interface-design.js +407 -0
- package/lib/data/lessons/lesson7-object-definition.js +375 -0
- package/lib/data/lessons/sintaxis/terminal-basico.js +46 -0
- package/lib/data/menus.js +43 -0
- package/lib/data/messages.js +28 -0
- package/lib/executors/enunciados-executor.js +63 -0
- package/lib/executors/portfolio-executor.js +167 -0
- package/lib/executors/proyectos-executor.js +23 -0
- package/lib/executors/sintaxis-executor.js +7 -0
- package/lib/templates/LevelModifier.js +287 -0
- package/lib/utils/file-utils.js +18 -0
- package/lib/utils/input.js +15 -0
- package/lib/utils/output.js +4 -0
- package/package.json +4 -1
- package/refactor.txt +581 -0
- package/test/enunciados.test.js +72 -0
- package/lessons/lesson1-system-decomposition.js +0 -313
- package/lessons/lesson2-object-requests.js +0 -309
- package/lessons/lesson3-only-way.js +0 -324
- package/lessons/lesson4-operation-signatures.js +0 -319
- package/lessons/lesson5-interface-set.js +0 -326
- package/lessons/lesson6-interface-design.js +0 -391
- package/lessons/lesson7-object-definition.js +0 -300
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// LECCIÓN 6: El énfasis al diseñar los objetos debe estar en la definición de sus solicitudes e interfaces
|
|
4
|
-
// Enfoque práctico: Sistema bancario con diseño interface-first y encapsulación
|
|
5
|
-
|
|
6
|
-
import { createInterface } from 'readline'
|
|
7
|
-
|
|
8
|
-
export class Lesson6InterfaceDesign {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.rl = createInterface({
|
|
11
|
-
input: process.stdin,
|
|
12
|
-
output: process.stdout
|
|
13
|
-
})
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async start() {
|
|
17
|
-
console.log("\n💡 ¿Por qué es importante?")
|
|
18
|
-
console.log("- Las interfaces definen QUÉ hace un objeto, no CÓMO lo hace")
|
|
19
|
-
console.log("- Facilita la colaboración entre objetos")
|
|
20
|
-
console.log("- Permite cambiar implementaciones sin afectar otros objetos")
|
|
21
|
-
console.log("- Hace el código más mantenible y extensible")
|
|
22
|
-
|
|
23
|
-
await this.waitForEnter("\nPresiona Enter para comenzar el ejercicio práctico...")
|
|
24
|
-
|
|
25
|
-
await this.practicalExercise()
|
|
26
|
-
await this.conclusion()
|
|
27
|
-
|
|
28
|
-
this.rl.close()
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async practicalExercise() {
|
|
32
|
-
console.clear()
|
|
33
|
-
console.log("🛠️ EJERCICIO PRÁCTICO: Sistema Bancario")
|
|
34
|
-
console.log("=" .repeat(50))
|
|
35
|
-
console.log("🎯 Objetivo: Diseñar interfaces ANTES de implementar")
|
|
36
|
-
console.log("\nVamos a crear un sistema bancario donde:")
|
|
37
|
-
console.log("- BankAccount representa una cuenta con balance privado")
|
|
38
|
-
console.log("- Transaction registra movimientos entre cuentas")
|
|
39
|
-
console.log("- Bank gestiona múltiples cuentas y validaciones")
|
|
40
|
-
|
|
41
|
-
await this.waitForEnter("\nPresiona Enter para ver cómo diseñar las interfaces...")
|
|
42
|
-
|
|
43
|
-
await this.step1_DefineRequests()
|
|
44
|
-
await this.step2_DefineInterfaces()
|
|
45
|
-
await this.step3_ImplementObjects()
|
|
46
|
-
await this.step4_TestInteraction()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
async step1_DefineRequests() {
|
|
50
|
-
console.clear()
|
|
51
|
-
console.log("📋 PASO 1: Definir las Solicitudes")
|
|
52
|
-
console.log("=" .repeat(40))
|
|
53
|
-
console.log("Antes de escribir código, pensemos: ¿Qué solicitudes debe manejar cada objeto?")
|
|
54
|
-
console.log("\n🏦 BankAccount debe poder:")
|
|
55
|
-
console.log(" - Consultar balance (sin exponer el dato interno)")
|
|
56
|
-
console.log(" - Recibir dinero (depósito)")
|
|
57
|
-
console.log(" - Enviar dinero (con validación interna)")
|
|
58
|
-
console.log(" - Proporcionar información de la cuenta")
|
|
59
|
-
|
|
60
|
-
console.log("\n📊 Transaction debe poder:")
|
|
61
|
-
console.log(" - Registrar origen, destino y monto")
|
|
62
|
-
console.log(" - Proporcionar detalles del movimiento")
|
|
63
|
-
console.log(" - Validar si la transacción es válida")
|
|
64
|
-
|
|
65
|
-
console.log("\n🏛️ Bank debe poder:")
|
|
66
|
-
console.log(" - Crear nuevas cuentas")
|
|
67
|
-
console.log(" - Procesar transferencias entre cuentas")
|
|
68
|
-
console.log(" - Validar operaciones antes de ejecutarlas")
|
|
69
|
-
console.log(" - Llevar registro de todas las transacciones")
|
|
70
|
-
|
|
71
|
-
await this.waitForEnter("\n✅ ¡Excelente! Ya definimos QUÉ debe hacer cada objeto. Presiona Enter para definir las interfaces...")
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async step2_DefineInterfaces() {
|
|
75
|
-
console.clear()
|
|
76
|
-
console.log("🔌 PASO 2: Definir las Interfaces (Firmas de Operación)")
|
|
77
|
-
console.log("=" .repeat(50))
|
|
78
|
-
console.log("Ahora especifiquemos CÓMO se solicitan estas operaciones:")
|
|
79
|
-
|
|
80
|
-
console.log("\n// BankAccount Interface")
|
|
81
|
-
console.log("class BankAccount {")
|
|
82
|
-
console.log(" constructor(accountNumber, ownerName, initialBalance) → BankAccount")
|
|
83
|
-
console.log(" getBalance() → number // ⚠️ ENCAPSULACIÓN: acceso controlado")
|
|
84
|
-
console.log(" getAccountInfo() → {number, owner, balance}")
|
|
85
|
-
console.log(" deposit(amount) → boolean")
|
|
86
|
-
console.log(" send(amount, targetAccount) → boolean // ⚠️ VALIDACIÓN interna")
|
|
87
|
-
console.log("}")
|
|
88
|
-
|
|
89
|
-
console.log("\n// Transaction Interface")
|
|
90
|
-
console.log("class Transaction {")
|
|
91
|
-
console.log(" constructor(from, to, amount, timestamp) → Transaction")
|
|
92
|
-
console.log(" getDetails() → {from, to, amount, timestamp, status}")
|
|
93
|
-
console.log(" isValid() → boolean")
|
|
94
|
-
console.log("}")
|
|
95
|
-
|
|
96
|
-
console.log("\n// Bank Interface")
|
|
97
|
-
console.log("class Bank {")
|
|
98
|
-
console.log(" createAccount(ownerName, initialBalance) → BankAccount")
|
|
99
|
-
console.log(" transfer(fromAccount, toAccount, amount) → Transaction")
|
|
100
|
-
console.log(" getAllTransactions() → Array<Transaction>")
|
|
101
|
-
console.log(" validateOperation(account, amount) → boolean")
|
|
102
|
-
console.log("}")
|
|
103
|
-
|
|
104
|
-
console.log("\n💡 Observa que cada operación especifica:")
|
|
105
|
-
console.log(" a) Nombre de la operación (getBalance, send, transfer, etc.)")
|
|
106
|
-
console.log(" b) Insumos necesarios (amount, targetAccount, etc.)")
|
|
107
|
-
console.log(" c) Valor que regresa (boolean, Transaction, etc.)")
|
|
108
|
-
console.log("\n🔒 Nota especial: getBalance() encapsula el acceso al estado interno")
|
|
109
|
-
console.log("🛡️ Nota especial: send() incluirá validación antes de ejecutar")
|
|
110
|
-
|
|
111
|
-
await this.waitForEnter("\n✅ Interfaces definidas. Presiona Enter para implementar...")
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async step3_ImplementObjects() {
|
|
115
|
-
console.clear()
|
|
116
|
-
console.log("⚙️ PASO 3: Implementar los Objetos")
|
|
117
|
-
console.log("=" .repeat(40))
|
|
118
|
-
console.log("Ahora que tenemos las interfaces claras, implementemos:")
|
|
119
|
-
|
|
120
|
-
console.log("\n// Implementación de BankAccount")
|
|
121
|
-
console.log(`class BankAccount {
|
|
122
|
-
constructor(accountNumber, ownerName, initialBalance) {
|
|
123
|
-
this.accountNumber = accountNumber
|
|
124
|
-
this.ownerName = ownerName
|
|
125
|
-
this.#balance = initialBalance // 🔒 PRIVADO: no se accede directamente
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// 🔑 ENCAPSULACIÓN: método GET para acceder al balance
|
|
129
|
-
getBalance() {
|
|
130
|
-
return this.#balance
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
getAccountInfo() {
|
|
134
|
-
return {
|
|
135
|
-
number: this.accountNumber,
|
|
136
|
-
owner: this.ownerName,
|
|
137
|
-
balance: this.#balance // Controlamos qué se expone
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
deposit(amount) {
|
|
142
|
-
if (amount > 0) {
|
|
143
|
-
this.#balance += amount
|
|
144
|
-
return true
|
|
145
|
-
}
|
|
146
|
-
return false
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// 🛡️ VALIDACIÓN: método SEND con lógica interna
|
|
150
|
-
send(amount, targetAccount) {
|
|
151
|
-
// Validación interna ANTES de ejecutar
|
|
152
|
-
if (amount > 0 && this.#balance >= amount) {
|
|
153
|
-
this.#balance -= amount
|
|
154
|
-
targetAccount.deposit(amount)
|
|
155
|
-
return true
|
|
156
|
-
}
|
|
157
|
-
return false // Fondos insuficientes o monto inválido
|
|
158
|
-
}
|
|
159
|
-
}`)
|
|
160
|
-
|
|
161
|
-
await this.waitForEnter("\nPresiona Enter para ver Transaction...")
|
|
162
|
-
|
|
163
|
-
console.log("\n// Implementación de Transaction")
|
|
164
|
-
console.log(`class Transaction {
|
|
165
|
-
constructor(fromAccount, toAccount, amount) {
|
|
166
|
-
this.fromAccount = fromAccount
|
|
167
|
-
this.toAccount = toAccount
|
|
168
|
-
this.amount = amount
|
|
169
|
-
this.timestamp = new Date()
|
|
170
|
-
this.status = 'pending'
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
getDetails() {
|
|
174
|
-
return {
|
|
175
|
-
from: this.fromAccount.accountNumber,
|
|
176
|
-
to: this.toAccount.accountNumber,
|
|
177
|
-
amount: this.amount,
|
|
178
|
-
timestamp: this.timestamp,
|
|
179
|
-
status: this.status
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
isValid() {
|
|
184
|
-
return this.amount > 0 &&
|
|
185
|
-
this.fromAccount.getBalance() >= this.amount
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
execute() {
|
|
189
|
-
if (this.isValid()) {
|
|
190
|
-
const success = this.fromAccount.send(this.amount, this.toAccount)
|
|
191
|
-
this.status = success ? 'completed' : 'failed'
|
|
192
|
-
return success
|
|
193
|
-
}
|
|
194
|
-
this.status = 'failed'
|
|
195
|
-
return false
|
|
196
|
-
}
|
|
197
|
-
}`)
|
|
198
|
-
|
|
199
|
-
await this.waitForEnter("\nPresiona Enter para ver Bank...")
|
|
200
|
-
|
|
201
|
-
console.log("\n// Implementación de Bank")
|
|
202
|
-
console.log(`class Bank {
|
|
203
|
-
constructor() {
|
|
204
|
-
this.accounts = []
|
|
205
|
-
this.transactions = []
|
|
206
|
-
this.nextAccountNumber = 1000
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
createAccount(ownerName, initialBalance) {
|
|
210
|
-
const account = new BankAccount(
|
|
211
|
-
this.nextAccountNumber++,
|
|
212
|
-
ownerName,
|
|
213
|
-
initialBalance
|
|
214
|
-
)
|
|
215
|
-
this.accounts.push(account)
|
|
216
|
-
return account
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
transfer(fromAccount, toAccount, amount) {
|
|
220
|
-
const transaction = new Transaction(fromAccount, toAccount, amount)
|
|
221
|
-
|
|
222
|
-
// El Bank valida ANTES de ejecutar
|
|
223
|
-
if (this.validateOperation(fromAccount, amount)) {
|
|
224
|
-
const success = transaction.execute()
|
|
225
|
-
this.transactions.push(transaction)
|
|
226
|
-
return transaction
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
transaction.status = 'failed'
|
|
230
|
-
this.transactions.push(transaction)
|
|
231
|
-
return transaction
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
validateOperation(account, amount) {
|
|
235
|
-
return amount > 0 && account.getBalance() >= amount
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
getAllTransactions() {
|
|
239
|
-
return [...this.transactions]
|
|
240
|
-
}
|
|
241
|
-
}`)
|
|
242
|
-
|
|
243
|
-
await this.waitForEnter("\n✅ Implementación completa. Presiona Enter para probar la interacción...")
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
async step4_TestInteraction() {
|
|
247
|
-
console.clear()
|
|
248
|
-
console.log("🧪 PASO 4: Probar la Interacción entre Objetos")
|
|
249
|
-
console.log("=" .repeat(45))
|
|
250
|
-
console.log("Veamos cómo los objetos colaboran usando sus interfaces:")
|
|
251
|
-
|
|
252
|
-
console.log("\n// Crear el sistema bancario")
|
|
253
|
-
console.log("const bank = new Bank()")
|
|
254
|
-
console.log("const cuenta1 = bank.createAccount('Ana García', 1000)")
|
|
255
|
-
console.log("const cuenta2 = bank.createAccount('Carlos López', 500)")
|
|
256
|
-
console.log("")
|
|
257
|
-
console.log("// 🔑 ENCAPSULACIÓN: Solo podemos acceder al balance via getBalance()")
|
|
258
|
-
console.log("console.log('Balance Ana:', cuenta1.getBalance()) // 1000")
|
|
259
|
-
console.log("console.log('Balance Carlos:', cuenta2.getBalance()) // 500")
|
|
260
|
-
console.log("")
|
|
261
|
-
console.log("// 🛡️ VALIDACIÓN: send() verifica internamente antes de ejecutar")
|
|
262
|
-
console.log("const exitoso = cuenta1.send(300, cuenta2) // ✅ Tiene fondos")
|
|
263
|
-
console.log("console.log('Transferencia exitosa:', exitoso) // true")
|
|
264
|
-
console.log("")
|
|
265
|
-
console.log("const fallido = cuenta1.send(1500, cuenta2) // ❌ Fondos insuficientes")
|
|
266
|
-
console.log("console.log('Transferencia fallida:', fallido) // false")
|
|
267
|
-
console.log("")
|
|
268
|
-
console.log("// El estado interno se mantiene íntegro")
|
|
269
|
-
console.log("console.log('Balance final Ana:', cuenta1.getBalance()) // 700")
|
|
270
|
-
console.log("console.log('Balance final Carlos:', cuenta2.getBalance()) // 800")
|
|
271
|
-
|
|
272
|
-
console.log("\n🎯 Resultado esperado:")
|
|
273
|
-
console.log("Balance Ana: 1000")
|
|
274
|
-
console.log("Balance Carlos: 500")
|
|
275
|
-
console.log("Transferencia exitosa: true")
|
|
276
|
-
console.log("Transferencia fallida: false")
|
|
277
|
-
console.log("Balance final Ana: 700")
|
|
278
|
-
console.log("Balance final Carlos: 800")
|
|
279
|
-
|
|
280
|
-
await this.waitForEnter("\nPresiona Enter para ver los beneficios de este enfoque...")
|
|
281
|
-
|
|
282
|
-
console.clear()
|
|
283
|
-
console.log("🌟 BENEFICIOS DEL DISEÑO INTERFACE-FIRST EN SISTEMAS BANCARIOS")
|
|
284
|
-
console.log("=" .repeat(60))
|
|
285
|
-
console.log("1. 🔒 Encapsulación: El balance está protegido, solo accesible via getBalance()")
|
|
286
|
-
console.log("2. 🛡️ Validación: send() incluye lógica de negocio interna")
|
|
287
|
-
console.log("3. 🎯 Claridad: Cada objeto tiene responsabilidades financieras bien definidas")
|
|
288
|
-
console.log("4. 🔗 Colaboración: Los objetos saben exactamente cómo solicitar operaciones")
|
|
289
|
-
console.log("5. 🧪 Testeable: Podemos simular cuentas y transacciones fácilmente")
|
|
290
|
-
console.log("6. 📚 Mantenible: Las interfaces documentan el contrato bancario")
|
|
291
|
-
|
|
292
|
-
console.log("\n💡 Ejemplo de extensibilidad:")
|
|
293
|
-
console.log("// Podemos crear diferentes tipos de cuenta sin cambiar Bank")
|
|
294
|
-
console.log("class SavingsAccount extends BankAccount {")
|
|
295
|
-
console.log(" getBalance() {")
|
|
296
|
-
console.log(" return super.getBalance() + this.calculateInterest()")
|
|
297
|
-
console.log(" }")
|
|
298
|
-
console.log("}")
|
|
299
|
-
console.log("")
|
|
300
|
-
console.log("class CreditAccount extends BankAccount {")
|
|
301
|
-
console.log(" send(amount, target) {")
|
|
302
|
-
console.log(" // Permite sobregiro hasta el límite de crédito")
|
|
303
|
-
console.log(" if (amount > 0 && (this.getBalance() + this.creditLimit) >= amount) {")
|
|
304
|
-
console.log(" // ... lógica específica")
|
|
305
|
-
console.log(" }")
|
|
306
|
-
console.log(" }")
|
|
307
|
-
console.log("}")
|
|
308
|
-
console.log("")
|
|
309
|
-
console.log("// Las cuentas pueden enviarse dinero directamente!")
|
|
310
|
-
console.log("const savingsAcc = new SavingsAccount(123, 'María', 1000)")
|
|
311
|
-
console.log("const creditAcc = new CreditAccount(456, 'Juan', 500, 2000) // límite crédito")
|
|
312
|
-
console.log("savingsAcc.send(300, creditAcc) // ¡Funciona con cualquier tipo de cuenta!")
|
|
313
|
-
console.log("")
|
|
314
|
-
console.log("// O podemos usar el Bank para registro completo:")
|
|
315
|
-
console.log("bank.transfer(savingsAcc, creditAcc, 300) // Crea Transaction automáticamente")
|
|
316
|
-
|
|
317
|
-
await this.waitForEnter("\nPresiona Enter para continuar con la conclusión...")
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
async conclusion() {
|
|
321
|
-
console.clear()
|
|
322
|
-
console.log("🎓 CONCLUSIÓN: Diseño basado en Interfaces (Sistema Bancario)")
|
|
323
|
-
console.log("=" .repeat(55))
|
|
324
|
-
console.log("🎯 Hemos demostrado que:")
|
|
325
|
-
console.log("\n1. El ÉNFASIS debe estar en definir QUÉ solicitudes maneja cada objeto")
|
|
326
|
-
console.log("2. Las INTERFACES son el CONJUNTO de todas las firmas de operación")
|
|
327
|
-
console.log("3. Cada FIRMA especifica: nombre, insumos y valor de retorno")
|
|
328
|
-
console.log("4. La IMPLEMENTACIÓN viene después, siguiendo el contrato")
|
|
329
|
-
console.log("5. Los objetos COLABORAN a través de estas interfaces bien definidas")
|
|
330
|
-
|
|
331
|
-
console.log("\n📋 Firmas de operación en nuestro ejemplo:")
|
|
332
|
-
console.log("• BankAccount.getBalance() → number")
|
|
333
|
-
console.log("• BankAccount.send(amount, targetAccount) → boolean")
|
|
334
|
-
console.log("• Bank.createAccount(ownerName, initialBalance) → BankAccount")
|
|
335
|
-
console.log("• Bank.transfer(fromAccount, toAccount, amount) → Transaction")
|
|
336
|
-
console.log("• Transaction.getDetails() → {from, to, amount, timestamp, status}")
|
|
337
|
-
|
|
338
|
-
console.log("\n🔑 La interfaz de BankAccount es el CONJUNTO completo:")
|
|
339
|
-
console.log(" {getBalance, getAccountInfo, deposit, send}")
|
|
340
|
-
console.log("🔑 La interfaz de Bank es el CONJUNTO completo:")
|
|
341
|
-
console.log(" {createAccount, transfer, getAllTransactions, validateOperation}")
|
|
342
|
-
|
|
343
|
-
console.log("\n💡 Beneficios de este enfoque:")
|
|
344
|
-
console.log("• ENCAPSULACIÓN: getBalance() protege el acceso al estado interno")
|
|
345
|
-
console.log("• VALIDACIÓN: send() ejecuta lógica de negocio antes de operar")
|
|
346
|
-
console.log("• CONTRATO CLARO: Cada firma especifica exactamente qué esperar")
|
|
347
|
-
console.log("• COLABORACIÓN: Los objetos conocen las firmas de otros objetos")
|
|
348
|
-
|
|
349
|
-
console.log("\n📚 Conexión con lecciones anteriores:")
|
|
350
|
-
console.log("• Lección 2: Los objetos interactúan a través de solicitudes ✓")
|
|
351
|
-
console.log("• Lección 3: Las solicitudes son la única forma de ejecutar operaciones ✓")
|
|
352
|
-
console.log("• Lección 4: Cada operación tiene nombre, insumos y valor de retorno ✓")
|
|
353
|
-
console.log("• Lección 5: La interfaz es el conjunto de todas las firmas ✓")
|
|
354
|
-
console.log("• Lección 6: El énfasis está en definir solicitudes e interfaces ✓")
|
|
355
|
-
|
|
356
|
-
console.log("\n🚀 Próximo paso:")
|
|
357
|
-
console.log("Practica este enfoque en tus propios proyectos:")
|
|
358
|
-
console.log("1. Define primero QUÉ debe hacer cada objeto")
|
|
359
|
-
console.log("2. Especifica las interfaces (firmas de operación)")
|
|
360
|
-
console.log("3. Incluye validaciones internas en tus métodos")
|
|
361
|
-
console.log("4. Encapsula el estado, expón solo lo necesario")
|
|
362
|
-
console.log("5. Haz que los objetos colaboren a través de solicitudes")
|
|
363
|
-
|
|
364
|
-
console.log("\n💭 Reflexión final:")
|
|
365
|
-
console.log("Antes de implementar cualquier objeto, pregúntate:")
|
|
366
|
-
console.log("• ¿Cuáles son TODAS las firmas de operación que necesito?")
|
|
367
|
-
console.log("• ¿Qué nombre, insumos y valor de retorno tendrá cada firma?")
|
|
368
|
-
console.log("• ¿Cómo van a colaborar los objetos usando estas firmas?")
|
|
369
|
-
console.log("• ¿El CONJUNTO de firmas forma una interfaz coherente?")
|
|
370
|
-
|
|
371
|
-
console.log("\n🏆 ¡Has completado el ejemplo más importante del diseño orientado a objetos!")
|
|
372
|
-
console.log("Ahora entiendes que el ÉNFASIS debe estar en definir el CONJUNTO")
|
|
373
|
-
console.log("completo de firmas de operación ANTES de implementar.")
|
|
374
|
-
|
|
375
|
-
await this.waitForEnter("\n✨ ¡Lección 6 completada! Presiona Enter para salir...")
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
async waitForEnter(message) {
|
|
379
|
-
return new Promise((resolve) => {
|
|
380
|
-
this.rl.question(message, () => {
|
|
381
|
-
resolve()
|
|
382
|
-
})
|
|
383
|
-
})
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// Para usar la lección independientemente
|
|
388
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
389
|
-
const lesson = new Lesson6InterfaceDesign()
|
|
390
|
-
await lesson.start()
|
|
391
|
-
}
|
|
@@ -1,300 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// LECCIÓN 7: Un objeto es un conjunto de datos y procedimientos que operan sobre esos datos
|
|
4
|
-
// Enfoque conceptual: Entender qué es un dato, qué es un procedimiento, y por qué están unidos
|
|
5
|
-
|
|
6
|
-
import { createInterface } from 'readline'
|
|
7
|
-
|
|
8
|
-
export class Lesson7ObjectDefinition {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.rl = createInterface({
|
|
11
|
-
input: process.stdin,
|
|
12
|
-
output: process.stdout
|
|
13
|
-
})
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async start() {
|
|
17
|
-
await this.waitForEnter("\nPresiona Enter para comenzar...")
|
|
18
|
-
|
|
19
|
-
await this.conceptualExercise()
|
|
20
|
-
await this.conclusion()
|
|
21
|
-
|
|
22
|
-
this.rl.close()
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async conceptualExercise() {
|
|
26
|
-
console.clear()
|
|
27
|
-
console.log("Para entender qué ES un objeto,")
|
|
28
|
-
console.log("primero debemos entender dos conceptos fundamentales:")
|
|
29
|
-
console.log("")
|
|
30
|
-
console.log("1. ¿Qué es un DATO?")
|
|
31
|
-
console.log("2. ¿Qué es un PROCEDIMIENTO?")
|
|
32
|
-
|
|
33
|
-
await this.waitForEnter("\nPresiona Enter para continuar...")
|
|
34
|
-
|
|
35
|
-
await this.step1_WhatIsData()
|
|
36
|
-
await this.step2_WhatIsProcedure()
|
|
37
|
-
await this.step3_WhyTogether()
|
|
38
|
-
await this.step4_ObjectDefinition()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async step1_WhatIsData() {
|
|
42
|
-
console.clear()
|
|
43
|
-
console.log("¿Qué es un DATO?")
|
|
44
|
-
console.log("=" .repeat(50))
|
|
45
|
-
|
|
46
|
-
console.log("\n🔍 Un dato es información que describe el estado de algo")
|
|
47
|
-
|
|
48
|
-
await this.waitForEnter("\nPresiona Enter para ver ejemplos conceptuales...")
|
|
49
|
-
|
|
50
|
-
console.log("\n📦 Ejemplos de datos:")
|
|
51
|
-
console.log("")
|
|
52
|
-
console.log("• El saldo de una cuenta")
|
|
53
|
-
console.log(" → Este número describe cuánto dinero hay")
|
|
54
|
-
console.log("")
|
|
55
|
-
console.log("• El nombre de un usuario")
|
|
56
|
-
console.log(" → Este texto describe quién es")
|
|
57
|
-
console.log("")
|
|
58
|
-
console.log("• El estado de una puerta (abierta/cerrada)")
|
|
59
|
-
console.log(" → Este valor describe la condición actual")
|
|
60
|
-
console.log("")
|
|
61
|
-
console.log("• La lista de productos en un carrito")
|
|
62
|
-
console.log(" → Esta colección describe qué contiene")
|
|
63
|
-
|
|
64
|
-
await this.waitForEnter("\nPresiona Enter para continuar...")
|
|
65
|
-
|
|
66
|
-
console.log("\n💡 Característica clave de los datos:")
|
|
67
|
-
console.log("Los datos DESCRIBEN, no HACEN nada por sí mismos")
|
|
68
|
-
console.log("")
|
|
69
|
-
console.log("El saldo de 5000 no se deposita solo")
|
|
70
|
-
console.log("El nombre 'María' no se cambia solo")
|
|
71
|
-
console.log("La puerta cerrada no se abre sola")
|
|
72
|
-
console.log("")
|
|
73
|
-
console.log("Los datos son PASIVOS. Solo representan información.")
|
|
74
|
-
|
|
75
|
-
await this.waitForEnter("\nPresiona Enter para ver qué es un procedimiento...")
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async step2_WhatIsProcedure() {
|
|
79
|
-
console.clear()
|
|
80
|
-
console.log("¿Qué es un PROCEDIMIENTO?")
|
|
81
|
-
console.log("=" .repeat(50))
|
|
82
|
-
|
|
83
|
-
console.log("\n🔍 Un procedimiento es una secuencia de pasos que MODIFICA o LEE datos")
|
|
84
|
-
|
|
85
|
-
await this.waitForEnter("\nPresiona Enter para ver ejemplos conceptuales...")
|
|
86
|
-
|
|
87
|
-
console.log("\n⚙️ Ejemplos de procedimientos:")
|
|
88
|
-
console.log("")
|
|
89
|
-
console.log("• Depositar dinero en una cuenta")
|
|
90
|
-
console.log(" → MODIFICA el dato 'saldo' sumándole una cantidad")
|
|
91
|
-
console.log("")
|
|
92
|
-
console.log("• Cambiar el nombre de un usuario")
|
|
93
|
-
console.log(" → MODIFICA el dato 'nombre' asignándole un nuevo valor")
|
|
94
|
-
console.log("")
|
|
95
|
-
console.log("• Abrir una puerta")
|
|
96
|
-
console.log(" → MODIFICA el dato 'estado' de 'cerrada' a 'abierta'")
|
|
97
|
-
console.log("")
|
|
98
|
-
console.log("• Consultar el saldo")
|
|
99
|
-
console.log(" → LEE el dato 'saldo' sin modificarlo")
|
|
100
|
-
|
|
101
|
-
await this.waitForEnter("\nPresiona Enter para continuar...")
|
|
102
|
-
|
|
103
|
-
console.log("\n💡 Característica clave de los procedimientos:")
|
|
104
|
-
console.log("Los procedimientos son ACTIVOS. Hacen algo con los datos.")
|
|
105
|
-
console.log("")
|
|
106
|
-
console.log("Un procedimiento sin datos no tiene sentido:")
|
|
107
|
-
console.log(" • ¿Depositar en dónde?")
|
|
108
|
-
console.log(" • ¿Cambiar qué nombre?")
|
|
109
|
-
console.log(" • ¿Abrir cuál puerta?")
|
|
110
|
-
console.log("")
|
|
111
|
-
console.log("Los procedimientos NECESITAN datos para operar")
|
|
112
|
-
|
|
113
|
-
await this.waitForEnter("\nPresiona Enter para ver por qué están unidos...")
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async step3_WhyTogether() {
|
|
117
|
-
console.clear()
|
|
118
|
-
console.log("¿Por qué DATOS y PROCEDIMIENTOS están JUNTOS?")
|
|
119
|
-
console.log("=" .repeat(50))
|
|
120
|
-
|
|
121
|
-
console.log("\n🤔 La pregunta fundamental:")
|
|
122
|
-
console.log("Si los datos describen el estado,")
|
|
123
|
-
console.log("y los procedimientos modifican ese estado,")
|
|
124
|
-
console.log("¿no deberían estar relacionados?")
|
|
125
|
-
|
|
126
|
-
await this.waitForEnter("\nPresiona Enter para ver la respuesta...")
|
|
127
|
-
|
|
128
|
-
console.log("\n✨ La respuesta: EL OBJETO")
|
|
129
|
-
console.log("")
|
|
130
|
-
console.log("Un objeto es la unión natural de:")
|
|
131
|
-
console.log(" • Los datos que describen SU estado")
|
|
132
|
-
console.log(" • Los procedimientos que operan sobre ESE estado")
|
|
133
|
-
|
|
134
|
-
await this.waitForEnter("\nPresiona Enter para ver un ejemplo conceptual...")
|
|
135
|
-
|
|
136
|
-
console.log("\n📍 Ejemplo conceptual: Una cuenta bancaria")
|
|
137
|
-
console.log("")
|
|
138
|
-
console.log("┌─────────────────────────────────────┐")
|
|
139
|
-
console.log("│ OBJETO: Cuenta │")
|
|
140
|
-
console.log("├─────────────────────────────────────┤")
|
|
141
|
-
console.log("│ DATOS (estado): │")
|
|
142
|
-
console.log("│ • saldo │")
|
|
143
|
-
console.log("│ • titular │")
|
|
144
|
-
console.log("│ • activa │")
|
|
145
|
-
console.log("├─────────────────────────────────────┤")
|
|
146
|
-
console.log("│ PROCEDIMIENTOS (operaciones): │")
|
|
147
|
-
console.log("│ • depositar │")
|
|
148
|
-
console.log("│ • retirar │")
|
|
149
|
-
console.log("│ • consultarSaldo │")
|
|
150
|
-
console.log("│ • desactivar │")
|
|
151
|
-
console.log("└─────────────────────────────────────┘")
|
|
152
|
-
|
|
153
|
-
await this.waitForEnter("\nPresiona Enter para continuar...")
|
|
154
|
-
|
|
155
|
-
console.log("\n🔗 La relación esencial:")
|
|
156
|
-
console.log("")
|
|
157
|
-
console.log("• 'depositar' opera sobre 'saldo'")
|
|
158
|
-
console.log(" → No tiene sentido depositar sin un saldo que modificar")
|
|
159
|
-
console.log("")
|
|
160
|
-
console.log("• 'desactivar' opera sobre 'activa'")
|
|
161
|
-
console.log(" → No tiene sentido desactivar sin un estado que cambiar")
|
|
162
|
-
console.log("")
|
|
163
|
-
console.log("• 'consultarSaldo' lee 'saldo'")
|
|
164
|
-
console.log(" → No tiene sentido consultar sin un saldo que leer")
|
|
165
|
-
|
|
166
|
-
await this.waitForEnter("\nPresiona Enter para continuar...")
|
|
167
|
-
|
|
168
|
-
console.log("\n💭 La intuición:")
|
|
169
|
-
console.log("Los datos y los procedimientos están ATADOS entre sí")
|
|
170
|
-
console.log("")
|
|
171
|
-
console.log("No existen datos sin procedimientos que los manipulen")
|
|
172
|
-
console.log("No existen procedimientos sin datos sobre los que operen")
|
|
173
|
-
console.log("")
|
|
174
|
-
console.log("Esta unión es lo que llamamos: OBJETO")
|
|
175
|
-
|
|
176
|
-
await this.waitForEnter("\nPresiona Enter para ver la definición completa...")
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async step4_ObjectDefinition() {
|
|
180
|
-
console.clear()
|
|
181
|
-
console.log("La Definición Completa")
|
|
182
|
-
console.log("=" .repeat(50))
|
|
183
|
-
|
|
184
|
-
console.log("\n💎 'Un objeto es un conjunto de datos y procedimientos")
|
|
185
|
-
console.log(" que operan sobre esos datos'")
|
|
186
|
-
|
|
187
|
-
await this.waitForEnter("\nPresiona Enter para desglosar la definición...")
|
|
188
|
-
|
|
189
|
-
console.log("\n🔍 Desglose de la definición:")
|
|
190
|
-
console.log("")
|
|
191
|
-
console.log("1️⃣ 'Un objeto es un CONJUNTO'")
|
|
192
|
-
console.log(" → No es un solo elemento, es una agrupación")
|
|
193
|
-
console.log(" → Datos y procedimientos forman una unidad")
|
|
194
|
-
console.log("")
|
|
195
|
-
|
|
196
|
-
await this.waitForEnter("Presiona Enter para continuar...")
|
|
197
|
-
|
|
198
|
-
console.log("2️⃣ '...de DATOS'")
|
|
199
|
-
console.log(" → Información que describe el estado del objeto")
|
|
200
|
-
console.log(" → Valores que representan lo que el objeto 'es'")
|
|
201
|
-
console.log(" → PASIVOS: no hacen nada por sí mismos")
|
|
202
|
-
console.log("")
|
|
203
|
-
|
|
204
|
-
await this.waitForEnter("Presiona Enter para continuar...")
|
|
205
|
-
|
|
206
|
-
console.log("3️⃣ '...y PROCEDIMIENTOS'")
|
|
207
|
-
console.log(" → Secuencias de pasos que modifican o leen datos")
|
|
208
|
-
console.log(" → Operaciones que representan lo que el objeto 'hace'")
|
|
209
|
-
console.log(" → ACTIVOS: transforman el estado")
|
|
210
|
-
console.log("")
|
|
211
|
-
|
|
212
|
-
await this.waitForEnter("Presiona Enter para continuar...")
|
|
213
|
-
|
|
214
|
-
console.log("4️⃣ '...que OPERAN SOBRE esos datos'")
|
|
215
|
-
console.log(" → Los procedimientos NO operan sobre datos ajenos")
|
|
216
|
-
console.log(" → Solo modifican/leen los datos del MISMO objeto")
|
|
217
|
-
console.log(" → Esta es la relación fundamental")
|
|
218
|
-
|
|
219
|
-
await this.waitForEnter("\nPresiona Enter para ver por qué esto importa...")
|
|
220
|
-
|
|
221
|
-
console.clear()
|
|
222
|
-
console.log("¿Por qué esta definición es fundamental?")
|
|
223
|
-
console.log("=" .repeat(50))
|
|
224
|
-
|
|
225
|
-
console.log("\n🎯 Sin entender qué ES un objeto,")
|
|
226
|
-
console.log(" no podemos entender los otros 6 enunciados:")
|
|
227
|
-
console.log("")
|
|
228
|
-
console.log("• Enunciado 1: ¿Cómo descomponemos en objetos")
|
|
229
|
-
console.log(" si no sabemos qué es un objeto?")
|
|
230
|
-
console.log("")
|
|
231
|
-
console.log("• Enunciado 2: ¿Cómo interactúan los objetos")
|
|
232
|
-
console.log(" si no entendemos su naturaleza?")
|
|
233
|
-
console.log("")
|
|
234
|
-
console.log("• Enunciado 3: ¿Por qué solicitudes son la única forma")
|
|
235
|
-
console.log(" de invocar procedimientos?")
|
|
236
|
-
console.log("")
|
|
237
|
-
console.log("• Enunciado 4: ¿Qué firmas tienen las operaciones")
|
|
238
|
-
console.log(" (los procedimientos) del objeto?")
|
|
239
|
-
console.log("")
|
|
240
|
-
console.log("• Enunciado 5: ¿Qué es la interfaz del objeto")
|
|
241
|
-
console.log(" sino el conjunto de sus operaciones?")
|
|
242
|
-
console.log("")
|
|
243
|
-
console.log("• Enunciado 6: ¿Por qué diseñar las interfaces primero")
|
|
244
|
-
console.log(" si no sabemos que exponen operaciones?")
|
|
245
|
-
|
|
246
|
-
await this.waitForEnter("\nPresiona Enter para la conclusión...")
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
async conclusion() {
|
|
250
|
-
console.clear()
|
|
251
|
-
console.log("🎓 Conclusión: La Naturaleza del Objeto")
|
|
252
|
-
console.log("=" .repeat(50))
|
|
253
|
-
|
|
254
|
-
console.log("\n📌 Lo que aprendimos:")
|
|
255
|
-
console.log("")
|
|
256
|
-
console.log("1. Un DATO describe el estado (información pasiva)")
|
|
257
|
-
console.log("2. Un PROCEDIMIENTO modifica o lee datos (acción activa)")
|
|
258
|
-
console.log("3. Un OBJETO une datos con sus procedimientos")
|
|
259
|
-
console.log("4. Esta unión no es arbitraria, es esencial")
|
|
260
|
-
|
|
261
|
-
console.log("\n💡 La intuición central:")
|
|
262
|
-
console.log("")
|
|
263
|
-
console.log("Los datos no existen aislados")
|
|
264
|
-
console.log("Los procedimientos no operan en el vacío")
|
|
265
|
-
console.log("El objeto es la unión natural de ambos")
|
|
266
|
-
|
|
267
|
-
console.log("\n🔗 Conexión con el resto del paradigma:")
|
|
268
|
-
console.log("")
|
|
269
|
-
console.log("Ahora que sabemos QUÉ es un objeto,")
|
|
270
|
-
console.log("podemos entender:")
|
|
271
|
-
console.log(" • Cómo descomponerlos (enunciado 1)")
|
|
272
|
-
console.log(" • Cómo se comunican (enunciados 2, 3)")
|
|
273
|
-
console.log(" • Cómo se diseñan (enunciados 4, 5, 6)")
|
|
274
|
-
|
|
275
|
-
console.log("\n💭 Reflexión final:")
|
|
276
|
-
console.log("")
|
|
277
|
-
console.log("Antes de diseñar sistemas orientados a objetos,")
|
|
278
|
-
console.log("debemos entender la naturaleza fundamental del objeto:")
|
|
279
|
-
console.log("")
|
|
280
|
-
console.log(" 'Un conjunto de datos y procedimientos")
|
|
281
|
-
console.log(" que operan sobre esos datos'")
|
|
282
|
-
|
|
283
|
-
await this.waitForEnter("\n✨ ¡Lección 7 completada! Presiona Enter para continuar...")
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
async waitForEnter(message) {
|
|
287
|
-
return new Promise((resolve) => {
|
|
288
|
-
this.rl.question(message, () => {
|
|
289
|
-
console.log("\n")
|
|
290
|
-
resolve()
|
|
291
|
-
})
|
|
292
|
-
})
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// Para usar la lección independientemente
|
|
297
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
298
|
-
const lesson = new Lesson7ObjectDefinition()
|
|
299
|
-
await lesson.start()
|
|
300
|
-
}
|