Commit c02178d1 authored by Nicole Alvarado's avatar Nicole Alvarado

Entrega TP SOLID

parents
Pipeline #47 failed with stages
in 10 seconds

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

module.exports = createStatementData = function (invoice, plays) {
let statementData = {};
statementData.customer = invoice.customer;
statementData.performances = invoice.performances.map(enrichPerformance);
statementData.totalAmount = totalAmount(statementData.performances);
statementData.totalVolumenCredits = totalVolumenCredits(statementData.performances);
return statementData;
function enrichPerformance(aPerformance) {
// const calculator = new PerformanceCalculator(aPerformance, playFor(aPerformance));
const calculator = createPerformanceCalculator(aPerformance, playFor(aPerformance));
const result = Object.assign({}, aPerformance);
result.play = playFor(result);
result.amount = calculator.amount;
result.volumeCredits = calculator.volumeCredits;
return result;
}
function playFor(aPerformance) {
return plays[aPerformance.playID];
}
function totalAmount(somePerformances) {
return somePerformances.reduce((prev, aPerformance) => prev + aPerformance.amount, 0);
}
function totalVolumenCredits(somePerformances) {
return somePerformances.reduce((prev, aPerformance) => prev + aPerformance.volumeCredits, 0);
}
function createPerformanceCalculator(aPerformance, aPlay) {
switch (aPlay.type) {
case "tragedy":
return new TragedyCalculator(aPerformance, aPlay);
case "comedy":
return new ComedyCalculator(aPerformance, aPlay);
default:
throw new Error(`unknown type: ${this.play.type}`);
}
}
return statementData;
}
class PerformanceCalculator {
constructor(aPerformance, aPlay) {
this.performance = aPerformance;
this.play = aPlay;
}
get amount() {
throw new Error('amount not supported in PerfomanceCalculator');
}
get volumeCredits() {
throw new Error('volumeCredits not supported in PerfomanceCalculator');
}
}
class TragedyCalculator extends PerformanceCalculator {
get amount() {
let result = 40000;
if (this.performance.audience > 30) {
result += 1000 * (this.performance.audience - 30);
}
return result;
}
get volumeCredits() {
return volumeCreditsComposer(this.performance.audience);
}
}
class ComedyCalculator extends PerformanceCalculator {
get amount() {
let result = 30000;
if (this.performance.audience > 20) {
result += 10000 + 500 * (this.performance.audience - 20);
}
result += 300 * this.performance.audience;
return result;
}
get volumeCredits() {
return volumeCreditsComposer(this.performance.audience) + Math.floor(this.performance.audience / 5);
}
}
function volumeCreditsComposer(aAudience){
return Math.max(aAudience - 30, 0);
}
\ No newline at end of file
module.exports = {
default: `--format-options '{"snippetInterface": "synchronous"}' --publish-quiet`
}
Luego de agregar el contenido de statementHTML.js al final del código de statement.js, verifiqué su correcta ejecución.
Dentro del statement.js existen 2 funciones para armar un texto, ya sea en texto plano con RenderPlaintText() y RenderHTML(). Para hacer un buen uso de ello y aplicar LSP, primero se creó la clase Render, y al ser una abstracción, el método renderData(aData) que contiene, lo compartirá con las subclases que extienden de ella. Estas subclases van a ser creadas a partir de las dos funciones para armar el texto mencionadas anteriormente.
LSP propone que "las clases derivadas deben poder reemplazarse por sus clases base". En lo realizado anteriormente se respeta esto, ya que la clase RenderPlainText y RenderHTML tienen el mismo método que "heredaron" de la clase base Render, pero cada uno lo implementa, lo ejecuta de manera diferente, como lo indican sus nombres.
Posteriormente, para poder implementar DIP, se creó una Factory, la función createRender(aFormat), que se encarga de retornar la clase u objeto que se necesite (en este caso, según sea texto o html), recibe como parámetro el formato y según ello retornara el objeto, lo cual es independiente, ya que en caso de querer "soportar" otro tipo de formato, simplemente se lo agrega al Switch de la función y se crea la función para determinado formato separada del resto del código.
Luego de verificar la ejecución de forma polimórfica del renderizado anterior, se agregó un nuevo currency. Antes se encontraba únicamente la función USD() para el formato de las divisas, para extender el comportamiento y poder agregar otro formato, en este caso ARS, pesos argentinos, primero se creó la función ARS(). Me di cuenta que para realizar los Tests, tenía que intercalar entre las dos funciones, cuando los llamamos en los dos renders, ya sea para text o html, si quería que sean con dólares o pesos argentinos, tenía que cambiar el nombre de la función dependiendo lo que necesitaba. A ello, había que aplicarle LSP, se creó una generalización, una superclase llamada Currency, y sus dos clases derivadas USD y ARS. En la superclase se encuentra el método getFormat(aNumber), que se va a replicar en las subclases, donde cada una la va a definir para hacer la conversión de un numero a un formato según sea dólares o pesos argentinos. Para poder implementar DIP, se creó otra Factory, createCurrency(aCurrency), para que de acuerdo al currency que reciba, retorne el objeto, el currency que corresponda. DIP en realidad se va a implementar cuando se implemente esa función en algún lugar, en este caso, dentro de la clase Render, dentro del cual su constructor va a recibir la currency.
Al principio el stepdefs.js lo que hacía era una invocación a statement del print-the-bill.js, para que cada vez que necesitemos hacer un test simplemente le mandábamos a imprimir statement. Como se modificó el statement, aparte de recibir un tipo de formato de texto, va a tener que recibir una currency, y para que se pruebe de forma polimórfica, se realizó una combinación de los 4 casos, el cual no tiene que importar ya sea texto con USD, html con USD, texto con ARS y html con ARS. Entonces se tuvo que agregar los que faltaban para verificar que se realizaba de manera polimórfica. Esto implica que debía añadirlos también en el print-the-bill.feature, qué es lo que esperaba que devuelva y qué tiene que devolver.
En resumen, antes había dos exports, uno para html, statementHTML y otro de texto statement, y en stepdefs.js los llamaba dependiendo el formato del texto, entonces no se considera polimórfico. Ahora al usar la misma función para todos los casos comprobamos ese polimorfismo.
# language: es
Característica: Imprimir la factura de una compañía teatral
Necesaria para liquidar el borderau
Escenario: imprimr la factura de BigCo en texto plano
Dado el listado de la facturación de espectáculos
"""
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "as-like",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
"""
Y la lista de obras
"""
{
"hamlet": {
"name": "Hamlet",
"type": "tragedy"
},
"as-like": {
"name": "As You Like It",
"type": "comedy"
},
"othello": {
"name": "Othello",
"type": "tragedy"
}
}
"""
Cuando mando a imprimir el borderau en texto con dolares
Entonces debería imprimir el borderau en texto con dolares
"""
Statement for BigCo
Hamlet: $650.00 (55 seats)
As You Like It: $580.00 (35 seats)
Othello: $500.00 (40 seats)
Amount owed is $1,730.00
You earned 47 credits
"""
Cuando mando a imprimir el borderau en texto con pesos argentinos
Entonces debería imprimir el borderau en texto con pesos argentinos
"""
Statement for BigCo
Hamlet: $650,00 (55 seats)
As You Like It: $580,00 (35 seats)
Othello: $500,00 (40 seats)
Amount owed is $1.730,00
You earned 47 credits
"""
Escenario: imprimr la factura de BigCo en HTML
Dado el listado de la facturación de espectáculos
"""
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "as-like",
"audience": 35
</