Leyendo el libro, "Software Architecture Patterns" les dejo este pequeño resumen:
El patrón arquitectónico Event-Driver se utiliza para crear arquitecturas escalables, se puede utilizar en grandes aplicaciones como en pequeñas.
Este patrón arquitectónico tiene 2 topologías, el mediador y el broker (corredor, como es una fea traducción dejo su nombre en ingles).
La topología del mediador se utiliza comúnmente cuando se necesita orquestar múltiples pasos dentro de un evento a través de un mediador central, mientras que la topología de broker se utiliza cuando se desea encadenar sucesos sin el uso de un mediador central. Debido a que las características de la arquitectura y las estrategias de implementación difieren entre estas dos topologías, es importante entender cada una de ellas para saber cuál es la más adecuada para cada situación particular.
La topología del mediador es útil para eventos que tienen varios pasos y requieren algún nivel de orquestación para procesar el evento.
Hay cuatro tipos principales de componentes de arquitectura dentro de la topología del mediador: colas de eventos, un mediador de eventos, canales de eventos y procesadores de eventos. El flujo de eventos comienza con un cliente que envía un evento a una cola de eventos, que se utiliza para transportar el evento al mediador de eventos. El mediador de eventos recibe el evento inicial y orquesta dicho evento enviando eventos asíncronos adicionales a los canales de eventos para ejecutar cada paso del proceso. Los procesadores de eventos, que escuchan en los canales de eventos, reciben el evento del mediador de eventos y ejecutan lógica empresarial específica para procesar el evento.
La implementación más simple y más común del mediador de eventos es a través de frameworks open source como Spring Integration, Apache Camel o Mule ESB. Los flujos de eventos en estos frameworks se implementan típicamente a través de código Java o un DSL (lenguaje específico de dominio). Para una mediación y una orquestación más sofisticadas, puede utilizar BPEL (lenguaje de ejecución de procesos empresariales) junto con un motor BPEL open source como Apache ODE. BPEL es un lenguaje XML estándar que describe los datos y los pasos necesarios para procesar un evento inicial. Para aplicaciones muy grandes que requieren una orquestación mucho más sofisticada (incluyendo pasos que involucran interacciones humanas), puede implementar el mediador de eventos utilizando un gestor de procesos empresariales (BPM) como jBPM.
La topología broker se diferencia de mediador porque no hay un mediador central y único, sino que el flujo de eventos esta distribuido a través de los componentes del procesador de eventos de una manera similar a una cadena a través de un agente de mensajes ligero (por ejemplo, ActiveMQ, HornetQ, etc.). Esta topología es útil cuando se tiene un flujo de procesamiento de eventos relativamente simple y no desea (o necesita) orquestación de eventos centrales.
Hay dos tipos principales de componentes de arquitectura dentro de la topología de intermediario: un componente de broker y un componente de procesador de sucesos. El componente de broker puede centralizarse o federarse y contiene todos los canales de eventos que se utilizan en el flujo de eventos.
El patrón de arquitectura event-driver es un patrón relativamente complejo de implementar, principalmente debido a su naturaleza asincrónica distribuida. Al implementar este patrón, debe abordar varios problemas de arquitectura distribuida, como la disponibilidad de procesos remotos, la falta de capacidad de respuesta y la lógica de reconexión de intermediarios en caso de un fallo del intermediario o mediador.
Una consideración a tener en cuenta al elegir este patrón de arquitectura es la falta de transacciones atómicas para un solo proceso de negocio. Debido a que los componentes del procesador de eventos están altamente disociados y distribuidos, es muy difícil mantener una unidad transaccional de trabajo a través de ellos. Por esta razón, al diseñar su aplicación utilizando este patrón, debe pensar continuamente sobre qué eventos pueden y no pueden ejecutarse de forma independiente y planificar la granularidad de los procesadores de sucesos en consecuencia. Si descubre que necesita dividir una sola unidad de trabajo en los procesadores de eventos, es decir, si utiliza procesadores independientes para algo que debería ser una transacción indivisa, probablemente no sea el patrón adecuado para su aplicación.
Dejo link: http://radar.oreilly.com/2015/02/variations-in-event-driven-architecture.html
Translate
domingo, 16 de julio de 2017
sábado, 15 de julio de 2017
Libros gratuitos sobre tecnología Microsoft
Microsoft nos regala muchísimos libros de tecnologías microsoft desde .net, powershell, azure hasta office y windows.
Sin más comentarios dejo link:
https://blogs.msdn.microsoft.com/mssmallbiz/2017/07/11/largest-free-microsoft-ebook-giveaway-im-giving-away-millions-of-free-microsoft-ebooks-again-including-windows-10-office-365-office-2016-power-bi-azure-windows-8-1-office-2013-sharepo/
jueves, 13 de julio de 2017
Concurrent Programming in Erlang
Luego de terminar el curso de Erlang en future learn, ahora me entero que hay un curso de concurrencia en erlang. Aunque comienza en agosto, vale la pena publicar, (y para no olvidarme) luego haré un post para recordarles.
Si bien estos cursos son gratuitos hay que pagar para recibir la certificación.
Entre información general podemos decir que el curso esta dictado en ingles (con subtitulos) por la universidad de Kent (creo que no tiene nada que ver con superman).
Y el contenido es el siguiente:
- Processes and messages in Erlang
- Message-passing concurrency
- Designing for robustness
- Handling errors and dealing with exceptions
- Testing and fixing concurrency
- Multicore and distributed Erlang
- OTP: The Open Telecom Platform
Dejo link:
https://www.futurelearn.com/courses/concurrent-programming-erlang/
miércoles, 12 de julio de 2017
Real World OCaml
Quiero compartir este libro online gratuito, es sobre OCaml un lenguaje que desconozco totalmente.
Dejo link:
https://realworldocaml.org/
Keras, la red neuronal neutral escrita en Python
Como lo dije anteriormente Keras el la red neuronal neutral escrita en Python y con la capacidad de correr cualquier TensorFlow, CNTK o Theano.
Esta librería fue desarrollada con el foco a permitir una experimentación rápida.
Utilice Keras si necesita una librería de aprendizaje que:
- Permite un prototipado fácil y rápido (a través de la facilidad de uso, modularidad y extensibilidad).
- Soporta redes convolucionales y redes recurrentes, así como combinaciones de los dos.
- Se ejecuta sin problemas en la CPU y la GPU.
La estructura de datos de Keras es un modelo, una forma de organizar capas. El modelo más simple es el modelo Sequential, una pila lineal de capas. Para arquitecturas más complejas, debe utilizar la API funcional de Keras, que permite crear gráficos arbitrarios de capas.
Veamos una secuencia:
from keras.models import Sequential
model = Sequential()
from keras.layers import Dense, Activation
model.add(Dense(units=64, input_dim=100))
model.add(Activation('relu'))
model.add(Dense(units=10))
model.add(Activation('softmax'))
Una vez que su modelo se vea bien, se configura el proceso de aprendizaje con .compile ():
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
Si es necesario, puede configurar su optimizador. Un principio básico de Keras es hacer las cosas razonablemente simples, mientras que permite al usuario tener totalmente el control cuando lo necesitan (el control final es la fácil extensibilidad del código fuente).
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.SGD(lr=0.01, momentum=0.9, nesterov=True))
Ahora puede iterar en sus datos de entrenamiento:
# x_train and y_train are Numpy arrays --just like in the Scikit-Learn API.
model.fit(x_train, y_train, epochs=5, batch_size=32)
Alternativamente, puede alimentar lotes a su modelo manualmente:
Model.train_on_batch (x_batch, y_batch)
Evalúe su rendimiento en una sola línea:
Loss_and_metrics = model.evaluate (x_test, y_test, batch_size = 128)
O generar predicciones sobre nuevos datos:
Classes = model.predict (x_test, batch_size = 128)
Y listo!
Dejo link: https://keras.io/
Tuplas en C#
Desde .net core, estoy estudiando un poco más C#
Vamos desde el principio, que es una tupla? Una tupla es una estructura de datos que especifica una secuencia de elementos.
Una tupla puede retornar un numero de elementos de diferente tipo sin expecificar una nueva estructura. Esto puede ser util para retornar diferentes elementos de defirente tipo o aceptarlos como parámetros.
System.Tuples es el namespace donde se pueden encontrar las tuplas en C#
Veamos un ejemplo:
class TupleExample
{
static void Main()
{
// Create three-item tuple.
Tuple<int, string, bool> tuple =
new Tuple<int, string, bool>(10, "csharpstar", true);
// Access tuple properties.
if (tuple.Item1 == 10)
{
Console.WriteLine(tuple.Item1);
}
if (tuple.Item2 == "easywcf")
{
Console.WriteLine(tuple.Item2);
}
if (tuple.Item3)
{
Console.WriteLine(tuple.Item3);
}
}
}
Podemos no conoces el tipo de los elementos:
class TupleExample
{
static void Main()
{
// Use Tuple.Create static method.
var tuple = Tuple.Create("Csharpstar", 10, true);
// Test value of string.
string value = tuple.Item1;
if (value == "csharpstar")
{
Console.WriteLine(true);
}
// Test Item2 and Item3.
Console.WriteLine(tuple.Item2 == 10);
Console.WriteLine(!tuple.Item3);
// Write string representation.
Console.WriteLine(tuple);
}
}
Cuando utilizar tuplas?
Las tuplas se usan comúnmente de las siguientes maneras:
- Para representar un solo conjunto de datos. Por ejemplo, una tupla puede representar un registro de base de datos, y sus componentes pueden representar campos individuales del registro.
- Facilitar el acceso y la manipulación de un conjunto de datos.
- Para devolver varios valores de un método sin utilizar parámetros de salida
- Pasar valores múltiples a un método a través de un solo parámetro.
domingo, 9 de julio de 2017
GraphQL vs REST
Como sabrán me gustan las comparaciones, y estaba leyendo InfoQ y me encontre con un articulo sobre GraphQL vs REST.
Espero que todos conozcan REST, pero que es GraphQL? GraphQL es un lenguaje de consulta de datos, diseñado y usado en Facebook para solicitar y entregar datos a las aplicaciones móviles y web desde 2012. Para más info : https://emanuelpeg.blogspot.com.ar/2015/10/graphql.html
Cuales son sus ventajas ante rest y diferencias?
- GraphQL reduce el trafico red al permitirle recuperar todos los datos que necesita en una sola consulta.
- GraphQL es el modelo WYSIWYG, hacer que el código cliente sea menos propenso a errores.
- HTTP RESTful aprovecha más consistencia y previsibilidad haciendo uso de códigos de http (por ejemplo 404 si no encuentra la entidad) y de los metodos Post, Put, Delete, etc.
- Hypermedia de APIs Restful, permiten que los clientes vayan descubriendo la información y como encontrarla.
- HTTP ya implementa una caché, mientras que GraphQL no lo hace.
- GraphQL es útil porque proporciona un esquema para los consumidores, pero estas no necesariamente esta documentada.
Para concluir, no hay bala de plata, y es sólo una cuestión de elegir lo que tiene más sentido para los requerimientos.
Dejo link: https://www.infoq.com/news/2017/07/graphql-vs-rest
http://graphql.org/
https://apihandyman.io/and-graphql-for-all-a-few-things-to-think-about-before-blindly-dumping-rest-for-graphql/
miércoles, 5 de julio de 2017
Python Pedia
Si queres aprender python y más tecnologías Python Pedia es el sitio que estabas buscando. En este sitio podes encontrar todo sobre Python y muchas tecnologías más.
Entre las categorías encontramos desarrollo:
Entre las categorías encontramos desarrollo:
- Científico y numérico
- De Juegos
- Web
- Python core
- Testing
- Comunidad
- Interfaces
- Embebido
- Redes
- Acceso a base de datos
- Tutoriales
- etc...
Dejo link:
martes, 4 de julio de 2017
Un resumen de Scala for the Impatient, parte 24
Campos Abstractos
En Scala puede haber campos abstractos, y este campo abstracto es un campo sin valor inicial.
abstract class Person {
val id: Int //no esta inicializado, por lo que es abstracto igual que su getter y setter
var name: String //también abstracto
}
Esta clase si la vemos desde java no va tener estos atributos y los métodos getters y setters van a ser abstractos.
Dada la siguiente clase si queremos extenderla debemos definir estos atributos, por ejemplo:
class Employee(val id: Int) extends Person { // una subclase concreta
var name = "" // propiedad concreta
}
Como se puede ver no es necesario la palabra clave “override” para sobrescribir campos.
A la vez se puede utilizar esta clase abstracta por medio de la instanciación de una clase anónima, la cual debe establecer los valores :
val fred = new Person {
val id = 1729
var name = "Fred"
}
Construcción ordenada y definición temprana.
Cuando se desea sobrescribir un campo y se usa este campo en el constructor de la superclase, el resultado es un comportamiento poco intuitivo.
Veamos un ejemplo, supongamos que queremos modelar una criatura puede ver una dimensión y solo 10 unidades de medida:
class Creature {
val range: Int = 10
val env: Array[Int] = new Array[Int](range)
}
Pero una hormiga puede ver solo 2 :
class Ant extends Creature {
override val range = 2
}
Desafortunadamente ahora tenemos un problema, el rango es un valor que es utilizado en el constructor de la superclase y el constructor de la superclase se ejecuta antes del constructor de la subclase. Vamos que sucede en mayor detalle:
Como se puede ver env se inicializo como un vector de 0 y debía ser de 2.
Existen diferentes soluciones a este problema pero podemos nombrar 3:
En esta sección vamos a explorar la ultima opción. Para definir un campo con definición temprana lo podemos hacer de la siguiente manera:
class Bug extends {
override val range = 3
} with Creature
Note que with es una palabra reservada, que se encuentra antes de la superclase.
En Scala puede haber campos abstractos, y este campo abstracto es un campo sin valor inicial.
abstract class Person {
val id: Int //no esta inicializado, por lo que es abstracto igual que su getter y setter
var name: String //también abstracto
}
Esta clase si la vemos desde java no va tener estos atributos y los métodos getters y setters van a ser abstractos.
Dada la siguiente clase si queremos extenderla debemos definir estos atributos, por ejemplo:
class Employee(val id: Int) extends Person { // una subclase concreta
var name = "" // propiedad concreta
}
Como se puede ver no es necesario la palabra clave “override” para sobrescribir campos.
A la vez se puede utilizar esta clase abstracta por medio de la instanciación de una clase anónima, la cual debe establecer los valores :
val fred = new Person {
val id = 1729
var name = "Fred"
}
Construcción ordenada y definición temprana.
Cuando se desea sobrescribir un campo y se usa este campo en el constructor de la superclase, el resultado es un comportamiento poco intuitivo.
Veamos un ejemplo, supongamos que queremos modelar una criatura puede ver una dimensión y solo 10 unidades de medida:
class Creature {
val range: Int = 10
val env: Array[Int] = new Array[Int](range)
}
Pero una hormiga puede ver solo 2 :
class Ant extends Creature {
override val range = 2
}
Desafortunadamente ahora tenemos un problema, el rango es un valor que es utilizado en el constructor de la superclase y el constructor de la superclase se ejecuta antes del constructor de la subclase. Vamos que sucede en mayor detalle:
- Se llama al constructor de Ant
- El constructor de Ant llama al constructor de criatura
- El constructor de criatura inicializa range en 10 y luego inicializa env con el método getter de range que fue sobrescrito, este no utiliza el de criatura sino el de hormiga que aun no fue inicializado. Por lo tanto env es un vector de 0, porque 0 es el entero por defecto.
- Hormiga establece a range en 2.
Como se puede ver env se inicializo como un vector de 0 y debía ser de 2.
Existen diferentes soluciones a este problema pero podemos nombrar 3:
- Declarar val como final. Esto es seguro pero no flexible.
- Declarar val como lazy, esto es seguro, flexible pero un poco ineficiente.
- Declarar este campo como “early definition” o definición temprana en la subclase.
En esta sección vamos a explorar la ultima opción. Para definir un campo con definición temprana lo podemos hacer de la siguiente manera:
class Bug extends {
override val range = 3
} with Creature
Note que with es una palabra reservada, que se encuentra antes de la superclase.
domingo, 2 de julio de 2017
Libro Gratuito: Scala, The New web Architecture
Manning nos regala un libro que contiene varios capítulos de varios libros sobre Scala, Akka y Play.
Sin más dejo link: http://freecontent.manning.com/wp-content/uploads/scala-the-new-web-architecture.pdf
sábado, 1 de julio de 2017
Que cursos de codeschool puedo hacer de forma gratuita?
Empezó las vacaciones por lo tanto esta bueno si hacemos un cursito, y si es cortito, mejor. Estos cursos gratuitos vienen al pelo:
Try C#
Rangos en Kotlin
Todos hablan Kotlin, desde que es un lenguaje soportado por android se ha vuelto un famoso y con mucha publicidad. Y no vamos a ser la excepción.
En este caso vamos hablar de los rangos. Los rangos se define para cualquier tipo comparable, pero se usa principalmente para primitivos. Empecemos con algo simple un if, que nos permita saber si un numero se encuentra en un rango:
if ( i in 1 .. 10 ) { // equivalente a 1 <= i && i <= 10
println(i);
}
Veamos un for:
for (i in 1..4) print(i) // imprime "1234"
for (i in 4..1) print(i) // no imprime nada
//Usando downTo()
for (i in 4 downTo 1) print(i) // Ahora si imprime! "4321"
//Lo mismo pero con clausura:
(1..4).reversed().forEach(System.out::print)
//Si queremos saltarnos algunos valores:
for (i in 1..4 step 2) print(i) // imprime "13"
for (i in 4 downTo 1 step 2) print(i) // imprime "42"
for (i in 1 until 10) {
println(i)
}
Dejo link: http://developersjournal.in/pondering-over-kotlin-ranges/
jueves, 29 de junio de 2017
Novedades de Swift 4 con ejemplos
Encontré un articulo por demás interesante que nos muestra las novedades de swift con ejemplos.
Dejo link:
http://www.appcoda.com/swift4-changes/?utm_content=bufferbefa9&utm_medium=social&utm_source=plus.google.com&utm_campaign=buffer
Dejo link:
http://www.appcoda.com/swift4-changes/?utm_content=bufferbefa9&utm_medium=social&utm_source=plus.google.com&utm_campaign=buffer
miércoles, 28 de junio de 2017
Parámetro implícito en Scala
"Este es el primer paso para implementar la abstracción contextual en Scala". ¿Qué quiero decir con esto?
Abstracción: La capacidad de nombrar un concepto y usar sólo el nombre después.
Contextual: Un fragmento de un programa produce resultados o resultados en algún contexto. Nuestros lenguajes de programación son muy buenos para describir y abstraer lo que se producen. Pero casi no hay nada disponible para abstraer sobre las entradas que los programas obtienen de su contexto. Un ejemplo para resolver esto es la inyección de dependencias.
Los tipos de funciones implícitas son una forma sorprendentemente sencilla y general de hacer abstractables los patrones de codificación que resuelven estas tareas, reduciendo el código clásico y aumentando la aplicabilidad. Para entender esto debemos entender los parámetro implícito
En un lenguaje funcional, las entradas a un cálculo se expresan más naturalmente como parámetros. Uno podría simplemente aumentar las funciones para tomar parámetros adicionales que representan configuraciones, capacidades, diccionarios, o cualquier otro dato contextual que las funciones necesiten. El único inconveniente de esto es que a menudo hay una gran distancia en el gráfico de llamadas entre la definición de un elemento contextual y el sitio donde se utiliza. En consecuencia, se hace tedioso definir todos esos parámetros intermedios y pasarlos a lo largo de donde finalmente se consumen.
Los parámetros implícitos solucionan la mitad del problema. Ellos no tienen que ser propagados usando código de repetitivo; el compilador se encarga de eso. Esto los hace prácticos en muchos escenarios donde los parámetros simples serían demasiado engorrosos. Los parámetros implícitos también son muy útiles como un mecanismo general de paso del contexto.
Digamos que queremos escribir algún código que está diseñado para ejecutarse en una transacción. En aras de la ilustración, aquí hay una clase de transacción simple:
class Transaction {
private val log = new ListBuffer[String]
def println(s: String): Unit = log += s
private var aborted = false
private var committed = false
def abort(): Unit = { aborted = true }
def isAborted = aborted
def commit(): Unit =
if (!aborted && !committed) {
Console.println("******* log ********")
log.foreach(Console.println)
committed = true
}
}
La transacción encapsula un registro, al que se pueden imprimir mensajes. Puede estar en uno de los tres estados: run, commit o abort. Si la transacción se confirma, imprime el registro almacenado en la consola.
El método de transacción permite ejecutar un determinado código dentro de una transacción recién creada:
Abstracción: La capacidad de nombrar un concepto y usar sólo el nombre después.
Contextual: Un fragmento de un programa produce resultados o resultados en algún contexto. Nuestros lenguajes de programación son muy buenos para describir y abstraer lo que se producen. Pero casi no hay nada disponible para abstraer sobre las entradas que los programas obtienen de su contexto. Un ejemplo para resolver esto es la inyección de dependencias.
Los tipos de funciones implícitas son una forma sorprendentemente sencilla y general de hacer abstractables los patrones de codificación que resuelven estas tareas, reduciendo el código clásico y aumentando la aplicabilidad. Para entender esto debemos entender los parámetro implícito
En un lenguaje funcional, las entradas a un cálculo se expresan más naturalmente como parámetros. Uno podría simplemente aumentar las funciones para tomar parámetros adicionales que representan configuraciones, capacidades, diccionarios, o cualquier otro dato contextual que las funciones necesiten. El único inconveniente de esto es que a menudo hay una gran distancia en el gráfico de llamadas entre la definición de un elemento contextual y el sitio donde se utiliza. En consecuencia, se hace tedioso definir todos esos parámetros intermedios y pasarlos a lo largo de donde finalmente se consumen.
Los parámetros implícitos solucionan la mitad del problema. Ellos no tienen que ser propagados usando código de repetitivo; el compilador se encarga de eso. Esto los hace prácticos en muchos escenarios donde los parámetros simples serían demasiado engorrosos. Los parámetros implícitos también son muy útiles como un mecanismo general de paso del contexto.
Digamos que queremos escribir algún código que está diseñado para ejecutarse en una transacción. En aras de la ilustración, aquí hay una clase de transacción simple:
class Transaction {
private val log = new ListBuffer[String]
def println(s: String): Unit = log += s
private var aborted = false
private var committed = false
def abort(): Unit = { aborted = true }
def isAborted = aborted
def commit(): Unit =
if (!aborted && !committed) {
Console.println("******* log ********")
log.foreach(Console.println)
committed = true
}
}
La transacción encapsula un registro, al que se pueden imprimir mensajes. Puede estar en uno de los tres estados: run, commit o abort. Si la transacción se confirma, imprime el registro almacenado en la consola.
El método de transacción permite ejecutar un determinado código dentro de una transacción recién creada:
def transaction[T](op: Transaction => T) = {
val trans: Transaction = new Transaction
op(trans)
trans.commit()
}
La transacción actual se debe pasar a lo largo de una cadena de llamadas a todos los lugares que necesitan para acceder a ella. Para ilustrar esto, aquí están tres funciones f1, f2 y f3 que se llaman entre sí, y también acceder a la transacción actual. La manera más conveniente de lograr esto es pasar la transacción actual como un parámetro implícito.
def f1(x: Int)(implicit thisTransaction: Transaction): Int = {
thisTransaction.println(s"first step: $x")
f2(x + 1)
}
def f2(x: Int)(implicit thisTransaction: Transaction): Int = {
thisTransaction.println(s"second step: $x")
f3(x * x)
}
def f3(x: Int)(implicit thisTransaction: Transaction): Int = {
thisTransaction.println(s"third step: $x")
if (x % 2 != 0) thisTransaction.abort()
x
}
El programa principal llama a f1 en un nuevo contexto de transacción e imprime su resultado:
def main(args: Array[String]) = {
transaction {
implicit thisTransaction =>
val res = f1(args.length)
println(if (thisTransaction.isAborted) "aborted" else s"result: $res")
}
}
lunes, 26 de junio de 2017
Un Ejemplo de Polimorfismo en C++
La idea es que una empresa tiene un conjunto de bienes los cuales tienen un valor y a la vez algunos bienes pueden ser amortizados (La amortización es un término económico y contable, referido al proceso de distribución de gasto en el tiempo de un valor duradero. Adicionalmente se utiliza como sinónimo de depreciación en cualquiera de sus métodos.)
Los bienes se clasifican en inmuebles, muebles y rodados. A la vez los inmuebles no pierden el valor en el tiempo (es decir no son amortizables) . El software debe proveer una forma de saber el valor de todos los bienes y calcular su amortización.
Para resolver este problema vamos a definir 1 clase abstracta bien que describa la característica que tienen los bienes de saber su valor y la característica de calcular la amortización. A la vez vamos a crear un gestor contable que imprima las amortizaciones.
Veamos la clase abstracta bien:
bien.h :
#ifndef BIEN_H
#define BIEN_H
#include <iostream>
class Bien
{
protected:
double valor = 0.0;
public:
Bien();
double virtual amortizar() = 0;
void setValor(double valor);
friend std::ostream& operator<<(std::ostream& os, const Bien& obj);
};
#endif // BIEN_H
#include "bien.h"
Bien::Bien()
{
this->valor = 0;
}
void Bien::setValor(double valor){
this->valor = valor;
}
std::ostream& operator<<(std::ostream& os, const Bien& obj){
return os << "Bien : " << obj.valor;
}
rodado.h :
#ifndef RODADO_H
#define RODADO_H
#include <iostream>
#include "bien.h"
class Rodado : public Bien
{
protected:
int km = 0;
public:
Rodado();
double amortizar();
void setKm(int km);
};
#endif // RODADO_H
rodado.cpp :
#include "rodado.h"
Rodado::Rodado()
{
}
double Rodado::amortizar(){
int por = this->km /1000;
return this->valor * ((0.1) * por);
}
void Rodado::setKm(int km){
this->km = km;
}
Veamos mueble.h:
#ifndef MUEBLE_H
#define MUEBLE_H
#include <iostream>
#include "bien.h"
class Mueble : public Bien
{
protected:
int anioCreacion = 1900;
public:
Mueble(int anioCreacion);
double amortizar();
void setAnioCreacion(int anioCreacion);
};
#endif // MUEBLE_H
mueble.cpp :
#include "mueble.h"
Mueble::Mueble(int anioCreacion)
{
this->anioCreacion = anioCreacion;
}
double Mueble::amortizar(){
int dif = 2017 - this->anioCreacion;
return this->valor * (dif * 0.05);
}
void Mueble::setAnioCreacion(int anioCreacion){
this->anioCreacion = anioCreacion;
}
Veamos el inmueble que le puse "Terreno" por lo tanto veremos a terreno.h :
#ifndef TERRENO_H
#define TERRENO_H
#include <iostream>
#include "bien.h"
class Terreno : public Bien
{
public:
Terreno();
double amortizar();
};
#endif // TERRENO_H
terreno.cpp :
#include "terreno.h"
Terreno::Terreno()
{
}
double Terreno::amortizar(){
return 0.0; //no amortiza por eso retorna 0
}
Ahora veremos el gestor contable que no hace mucho en el ejemplo, pero usen la imaginación y piensen que debería guardar los registros, calcular asientos, etc.
gestorcontable.h :
#ifndef GESTORCONTABLE_H
#define GESTORCONTABLE_H
#include <iostream>
#include "bien.h"
using namespace std;
class GestorContable
{
public:
GestorContable();
void imprimir(Bien * unBien);
};
#endif // GESTORCONTABLE_H
gestorcontable.cpp :
#include "gestorcontable.h"
GestorContable::GestorContable()
{
}
void GestorContable::imprimir(Bien * unBien){
cout << *unBien << " amortizacion : "<< unBien->amortizar() << endl;
}
Como pueden ver el Bien es abstracto y sus especializaciones polimorficas y el gestor contable usa esas características y utiliza el polimorfismo de esta manera no importa que bien deba imprimir, como el calculo de la amortización lo sabe hacer cada bien, cada bien calculara su amortización por lo tanto lo hará correctamente.
Recuerden que el polimorfismo se refiere a la propiedad por la que es posible enviar mensajes sintácticamente iguales a objetos de tipos distintos. El único requisito que deben cumplir los objetos que se utilizan de manera polimórfica es saber responder al mensaje que se les envía.
Espero que les sirva!!
Antes de despedirme les muestro el main:
#include <iostream>
#include "bien.h"
#include "mueble.h"
#include "rodado.h"
#include "terreno.h"
#include "gestorcontable.h"
using namespace std;
int main()
{
GestorContable gestorContable = GestorContable();
Bien * unTerreno = new Terreno();
unTerreno->setValor(12000.0);
gestorContable.imprimir(unTerreno);
Bien * unRodado = new Rodado();
Rodado * o = 0;
// Esto lo hago solo para mostrar un cambio de tipos.
if (o = reinterpret_cast<Rodado*> (unRodado)) {
o->setKm(2450);
}
unRodado->setValor(400000.00);
gestorContable.imprimir(unRodado);
Bien * unMueble = new Mueble(2000);
unMueble->setValor(47000.00);
gestorContable.imprimir(unMueble);
return 0;
}
Suscribirse a:
Entradas (Atom)