Translate

miércoles, 28 de febrero de 2018

Un resumen de Scala for the Impatient, parte 38


Extractors con un argumento o ninguno.

Si un unapply método extrae un solo valor este debe retornar un Optional por ejemplo: 


object Number {
def unapply(input: String): Option[Int] =
try {
Some(input.trim.toInt)
} catch {
case ex: NumberFormatException => None
}
}

Con este extractor podemos extraer el numero de un string :

val Number(n) = "1729"

Un extractor puede chequear un valor en este caso debe retornar un booleano:

object IsCompound {
def unapply(input: String) = input.contains(" ")
}


Se puede utilizar un extractor para agregar un test en una expresión pattern matching:


author match {
    case Name(first, IsCompound()) => …
    case Name(first, last) => …

 }

El método unapplySeq

Si utilizamos el extract en una secuencia, estaremos llamando a unapplySeq que retorna Option[Seq[A]] , donde A es el valor extraído:

object Name {
def unapplySeq(input: String): Option[Seq[String]] =
if (input.trim == "") None else Some(input.trim.split("\\s+"))
}


Dado este método ahora podemos utilizar un conjunto de parámetros:

author match {
   case Name(first, last) => …
   case Name(first, middle, last) => …
   case Name(first, “van”, “der”, last) => ...
}

Ojo, no se puede tener un método unapply y un unapplySeq con similar parámetros. 

Invocación dinámica

Scala es un lenguaje de tipado estático y fuertemente tipado.  Es decir que informa los errores de tipo en momento de compilación.

Si un tipo extiende de el trait scala.Dynamic, entonces el método llamadas, getters y setters se reescriben como llamadas a métodos especiales que pueden inspeccionar el nombre de la llamada original y los parámetros, y luego tomar acciones arbitrarias.

Veamos algunos ejemplos. Supongamos que la persona es una instancia de un tipo que se extiende
de Dynamic. Una declaración:

person.lastName = "Doe"

se puede remplazar:

person.updateDynamic ("lastName") ("Doe")

La clase Person debe tener dicho método:

clase Persona {
    ...
    def updateDynamic (campo: String) (newValue: String) {...}
}

Depende de nosotros si implementamos el método updateDynamic.

Otro ejemplo:

val name = person.lastName

puede ser remplazado por:

val name = name.selectDynamic("lastName")

El metodo selectDynamic debe retornar un valor simple. 

En scala existe DynamicProps que extiende a Dynamic y sobre escribe sus métodos:

class DynamicProps(val props: java.util.Properties) extends Dynamic {
    def updateDynamic(name: String)(value: String) {
        props.setProperty(name.replaceAll("_", "."), value)
    }

    def selectDynamic(name: String) =
        props.getProperty(name.replaceAll("_", "."))
    }
}

domingo, 25 de febrero de 2018

Que es machine learning?


Encontre un post de la gente de codecademy que esta muy bueno. Este post trata de explicar ¿qué es el aprendizaje automático, quién debe aprenderlo y cuándo puedo visitar Westworld?

El aprendizaje automático evolucionó a partir del reconocimiento de patrones y la aplicación de algoritmos que pueden aprender de los datos y luego hacer predicciones, y está estrechamente relacionado con las estadísticas computacionales. Esto nos indica el post.

Sin más que aconsejarlos que lo lean dejo el link:
http://news.codecademy.com/what-is-machine-learning/?utm_source=customer.io&utm_medium=email&utm_campaign=fortnightly_2-22-18&utm_content=whatismachinelearning

miércoles, 21 de febrero de 2018

Libros Gratuitos!!!

Quiero compartir un mail que me llego de java code geeks con unos libros gratuitos:

Download Dev Guides!

 
Moving your application to the cloud isn’t as simple as porting over your code and configurations to someone else’s infrastructure – nor should it be. Cloud computing represents a paradigm shift in the world of application architecture from vertical scalability to horizontal scalability. This new paradigm has much to offer organizations that want to build highly scalable and dynamic applications, but it has its dangers, too – if you’re not careful and purposeful in how you prepare for the cloud, your application could suffer. In this white paper, we’ll discuss how to reap the performance benefits of the cloud and avoid the common pitfalls.
 
 
Cloud computing has been gaining momentum for years. As the technology leaves the early adopter phase and becomes mainstream, many organizations find themselves scrambling to overcome the challenges that come with a more distributed infrastructure. One of those difficulties is getting through a major cloud migration. It is one thing to roll out a few applications and cloud pilot projects, it is an entirely different challenge to start using the cloud across multiple lines of business at massive scale. That is the point that organizations are beginning to reach, and the time has come to take a serious look at cloud migration best practices. Read this eBook to meet the cloud world and its importance for businesses moving to the cloud.
 
 
Mockito is an open source testing framework for Java released under the MIT License. The framework allows the creation of test double objects (mock objects) in automated unit tests for the purpose of Test-driven Development (TDD) or Behavior Driven Development (BDD). In software development there is an opportunity of ensuring that objects perform the behaviors that are expected of them. One approach is to create a test automation framework that actually exercises each of those behaviors and verifies that it performs as expected, even after it is changed. Developers have created mock testing frameworks. These effectively fake some external dependencies so that the object being tested has a consistent interaction with its outside dependencies. 
 
 
JUnit is a unit testing framework to write repeatable tests. JUnit has been important in the development of test-driven development, and is one of a family of unit testing frameworks which is collectively known as xUnit that originated with SUnit. A research survey performed in 2013 across 10,000 Java projects hosted on GitHub found that JUnit, (in a tie with slf4j-api), was the most commonly included external library. (Source) In this ebook, we provide a compilation of JUnit tutorials that will help you kick-start your own programming projects. We cover a wide range of topics, from basic usage and configuration, to multithreaded tests and integration with other testing frameworks. With our straightforward tutorials, you will be able to get your own projects up and running in minimum time.
 

martes, 20 de febrero de 2018

Un resumen de Scala for the Impatient, parte 37


Los métodos apply y update

En scala podemos extender la sintaxis de llamada de funciones :

f(n1, n2, n3, …)

Si f es una función o un método, se ejecuta. De lo contrario, se llama al método apply por lo tanto es equivalente a llamar a

f.apply(n1, n2, n3, …)

De la misma manera si se utiliza la notación de función con asignación se llama al método update :

f(n1, n2, n3, …) = value

Es similar a llamar a :

f.update(n1, n2, n3, …, value)

Este mecanismo es utilizado en arrays y maps :

val scores = new scala.collection.mutable.HashMap[String, Int]
scores("Bob") = 100 // es como llamar a scores.update("Bob", 100)
val bobsScore = scores("Bob") // es como llamar a scores.apply("Bob")

El método apply también es usado para retornar instancias de objetos, sin tener que llamar al constructor con el new :

class Fraction(n: Int, d: Int) {

}

object Fraction {
def apply(n: Int, d: Int) = new Fraction(n, d)
}

De esta manera podemos hacer lo siguiente:

val result = Fraction(3, 4) * Fraction(2, 5)

Extractors

Un extractor es un objeto que puede desaplicar un método. Se puede pensar esto como el método contrario a el apply. Por ejemplo si el apply agrega un elemento a una lista el extractor debería quitar este elemento.

Por ejemplo el objeto Fraction tiene un método apply que retorna una Fraction a partir de un numerador y un denominador. El extractor debería retornar un numerador y un denominador a partir de una Fraction.

object Fraction {
def unapply(input: Fraction) =
if (input.den == 0) None else Some((input.num, input.den))
}

Por lo general el método unapply retorna un Option dado que puede haber un error cuando queremos desaplicar un método. En el ejemplo si el denominador es 0 retorna None.

val Fraction(a, b) = f;
val tupleOption = Fraction.unapply(f)
if (tupleOption == None) throw new MatchError
// tupleOption is Some((t1 , t2))

En el ejemplo el método apply y unapply son inversos pero esto no es obligatorio.

Graylog, guarda y consulta tus logs de forma centralizada.


Graylog es un producto que permite consultar y almacenar registros de aplicaciones de forma centralizada y eficiente. Para esto utiliza MongoDB para almacenar los log y Elasticsearch para la búsqueda e indexación.

Con Graylog se puede guardar los registros de forma centralizada, detectar problemas de manera temprana y de esta manera resolverlos más rápidamente.

A la vez Graylog provee un sistema de administración de registros con el cual se puede consultar registros de forma interactiva y rápida y permite almacenar registros de diferentes servidores, dispositivos de red y aplicaciones.

De esta forma este producto permitirá auditar la aplicación de forma económica y eficiente. Permitiendo a los auditores ganar tiempo y centralizarse en su trabajo en vez de envolverlos en problemas técnicos. 

Y algo sumamente importante es que es Open source.

Dejo link: https://www.graylog.org/

lunes, 19 de febrero de 2018

MongoDB 4.0 incluye transacciones de múltiples documentos

MongoDB 4.0 incluye transacciones de múltiples documentos. Eso es todo. Toda la info...

Pero si no sabes:

El soporte para transacciones de documentos múltiples, es una técnica para el aislamiento de instantáneas a menudo asociada con las bases de datos relacionales PostgreSQL y Oracle. Y es la piedra angular ACID

MongoDB 4.0 ofrecerá la capacidad de realizar una lectura consistente. Es decir, devolverá solo los datos como se conocía en el momento en que comenzó la operación de lectura. Las versiones anteriores de MongoDB podían arrojar resultados que no necesariamente eran consistentes con ningún punto en el tiempo. Incluso podría omitir documentos o devolver varias versiones del mismo documento en una sola consulta. Pero esto ahora cambio.

Dejo link:
http://www.zdnet.com/article/mongodb-cto-how-our-new-wiredtiger-storage-engine-will-earn-its-stripes/

jueves, 15 de febrero de 2018

Top de lenguajes que tenes que aprender en el 2018



Me encontre un post sobre los lenguajes que debes aprender este 2018, si no lo sabes. Y en resumen los lenguajes son los siguientes :

  1. JavaScript
  2. TypeScript (si bien no es un lenguaje, es un framework que suma características a un lenguaje, por lo tanto es valido)
  3. Python
  4. Java
  5. Kotlin
  6. C & C++
  7. PHP
  8. Swift
  9. Scala
Lindo ranking veo algunos lenguajes viejos, pero salvo algunos puntos, estoy de acuerdo. 



martes, 13 de febrero de 2018

Un Post sobre el blog!


Tarde o temprano le tenía que tocas al blog hablar de el mismo. Por lo tanto te paso unos datos recopados del blog que no te van a servir de nada. Tal vez podes tirar estos datos en una reunión familiar, pero no se, velo...

  • El blog nace en julio del 2009 y los primeros post eran publicaciones de tp de la facultad.
  • El año que viene cumplimos 10 años. Me acabo de dar cuenta
  • Tenemos publicados 1815 post, con este 1816.


Los temas son variados pero por lo general Java, Linux, Scala, es decir lenguajes de programación y software libre. 


Les paso un gráfico:




Si no lo ven muy bien hagan click y se agranda (eso le digo a las chicas) , se los prometo.


Si clasificamos a el blog por tag tendremos el siguiente top ten (quitando a otros)

  1. Java
  2. Linux
  3. Scala
  4. Python
  5. javascript
  6. Ruby
  7. Apache
  8. php
  9. C++
  10. Haskell


Y eso es todo amigos...

Si tienen preguntas, en los comentarios.

Ah, y notaron que hay un botón para donar dinero? 

Programación Orientada a Objetos en Python, parte 4


Las propiedades “privadas”, no existen en Python :(

Sin embargo, hay una convención que se sigue en la mayoría del código Python: un nombre prefijado con un guión bajo (por ejemplo, _spam) debería tratarse como una propiedad privada

Cualquier identificador con la forma __spam (al menos dos guiones bajos al principio, como mucho un guión bajo al final) es textualmente reemplazado por _nombredeclase__spam, donde nombredeclase es el nombre de clase actual al que se le sacan guiones bajos del comienzo (si los tuviera). Se modifica el nombre del identificador sin importar su posición sintáctica, siempre y cuando ocurra dentro de la definición de una clase.

La modificación de nombres es útil para dejar que las subclases sobreescriban los métodos sin romper las llamadas a los métodos desde la misma clase. Por ejemplo:

class Mapeo:
    def __init__(self, iterable):
        self.lista_de_items = []
        self.__actualizar(iterable)

    def actualizar(self, iterable):
        for item in iterable:
            self.lista_de_items.append(item)

    __actualizar = actualizar   # copia privada del actualizar() original

class SubClaseMapeo(Mapeo):

    def actualizar(self, keys, values):
        # provee una nueva signatura para actualizar()
        # pero no rompe __init__()
        for item in zip(keys, values):
            self.lista_de_items.append(item)

Hay que aclarar que las reglas de modificación de nombres están diseñadas principalmente para evitar colisiones de nombres; es posible acceder o modificar una variable que es considerada como privada. Esto hasta puede resultar útil en circunstancias especiales, tales como en el depurador.

Note que el código pasado a exec o eval() no considera que la clase que invoca sea la clase actual; esto es similar al efecto de la sentencia global, efecto que es de similar manera restringido a código que es compilado en conjunto. La misma restricción aplica a getattr(), setattr() y delattr(), así como cuando se referencia a __dict__ directamente.

A veces es útil tener un tipo de datos similar al “registro” de Pascal o la “estructura” de C, que sirva para juntar algunos pocos ítems con nombre. Una definición de clase vacía funcionará perfecto:

class Empleado:
    pass

juan = Empleado()  # Crear un registro de empleado vacío

# Llenar los campos del registro
juan.nombre = 'Juan Pistola'
juan.depto = 'laboratorio de computación'
juan.salario = 1000

Algún código Python que espera un tipo abstracto de datos, en particular puede frecuentemente recibir. En cambio una clase que emula los métodos de aquel tipo de datos. Por ejemplo, si tenés una función que formatea algunos datos a partir de un objeto archivo, podés definir una clase con métodos read() y readline() que obtengan los datos de alguna cadena en memoria intermedia, y pasarlo como argumento.

Los objetos método de instancia tienen atributos también: m.__self__ es el objeto instancia con el método m(), y m.__func__ es el objeto función correspondiente al método.

lunes, 12 de febrero de 2018

Programación Orientada a Objetos en Python, parte 3


Python soporta la herencia y la herencia múltiple. Una definición de clase con múltiples clases base se ve así:

class ClaseDerivada(Base1, Base2, Base3):
    <declaración-1>
    .
    .
    .
    <declaración-N>

Si un atributo no se encuentra en ClaseDerivada, se busca en Base1, luego (recursivamente) en las clases base de Base1, y sólo si no se encuentra allí se lo busca en Base2, y así sucesivamente.

El orden de resolución de métodos cambia dinámicamente para soportar las llamadas cooperativas a super(). Este enfoque es conocido en otros lenguajes con herencia múltiple como “llámese al siguiente método” y es más poderoso que la llamada al superior que se encuentra en lenguajes con sólo herencia simple.

No nos olvidemos del problema del diamante, Por ejemplo, todas las clases heredan de object, por lo tanto cualquier caso de herencia múltiple provee más de un camino para llegar a object. Para que las clases base no sean accedidas más de una vez, el algoritmo dinámico hace lineal el orden de búsqueda de manera que se preserve el orden de izquierda a derecha especificado en cada clase, que se llame a cada clase base sólo una vez, y que sea monótona (lo cual significa que una clase puede tener clases derivadas sin afectar el orden de precedencia de sus clases bases). En conjunto, estas propiedades hacen posible diseñar clases confiables y extensibles con herencia múltiple.


Programación Orientada a Objetos en Python, parte 2

Bueno, ya vimos clases y herencia en python. Esta segunda parte vamos a seguir hablando de la construcción de objetos.

La operación de instanciación crea un objeto vacío. En muchas ocasiones necesitamos crear objetos en un estado inicial particular. Por lo tanto se puede definir un método especial llamado __init__(), de esta forma:

def __init__(self):
    self.datos = []

Cuando definimos un método __init__(), la instanciación de la clase automáticamente invoca a __init__(). Entonces, en este ejemplo, una instancia nueva e inicializada se puede obtener haciendo:

x = MiClase()

Por supuesto, el método __init__() puede tener argumentos para mayor flexibilidad. En ese caso, los argumentos que se pasen al operador de instanciación de la clase van a parar al método __init__(). Por ejemplo,

>>> class Complejo:
...     def __init__(self, partereal, parteimaginaria):
...         self.r = partereal
...         self.i = parteimaginaria
...
>>> x = Complejo(3.0, -4.5)
>>> x.r, x.i
(3.0, -4.5)

Python permite las variables de instancia son para datos únicos de cada instancia y las variables de clase son para atributos y métodos compartidos por todas las instancias de la clase:

class Perro:

    tipo = 'canino'                 # variable de clase compartida por todas las instancias

    def __init__(self, nombre):
        self.nombre = nombre        # variable de instancia única para la instancia

  >>> d = Perro('Fido')
  >>> e = Perro('Buddy')
  >>> d.tipo                    # compartido por todos los perros
  'canino'
  >>> e.tipo                    # compartido por todos los perros
  'canino'
  >>> d.nombre                  # único para d
  'Fido'
  >>> e.nombre                  # único para e
  'Buddy'

Todo valor es un objeto, y por lo tanto un objeto conoce su clase (también llamado su tipo). Ésta se almacena como objeto.__class__ y es un objeto.




domingo, 11 de febrero de 2018

Programación Orientada a Objetos en Python


Como les dije anteriormente estoy estudiando nuevamente python para unas cosas que tengo que hacer. Más allá de esto, vamos a repasar los conceptos de poo en python.

Primero y principal python implementa la poo con clases, como lo hacen la mayoría de los lenguajes. Las clases son una abstracción de un conjunto de objetos, esto luego define el tipo de nuestros objetos. Veamos las clases en python:

class Objeto:
    pass

class Antena:
    pass

class Pelo:
    pass

class Ojo:
    pass

Como se puede ver se usa la convención CamelCase para el nombre de las clases, y por supuesto las clases pueden tener atributos y métodos:

class Objeto():
    color = "verde"
    tamanio = "grande"
    aspecto = "feo"
    antenas = Antena()
    ojos = Ojo()
    pelos = Pelo()

    def flotar(self):
        print 12

Por alguna razón que desconozco el primer parámetro de los métodos debe ser self (en este punto alguien me puede ayudar?). Y tambien se utiliza la misma convención.

Todo muy lindo pero donde están los objetos? veamos como instanciar objetos :

et = Objeto()
print et.color
print et.tamanio
print et.aspecto
et.color = "rosa"
print et.color

Una característica de poo es la herencia que esta implementada en python tambien, se agrega la clase padre entre paréntesis luego del nombre de la clase :


class NuevoObjeto(Objeto):
    pie = Pie()

    def saltar(self):
        pass

Podemos heredar de la clase object que es la clase principal de Python:

class Antena(object):
    color = ""
    longitud = ""

class Pelo(object):
    color = ""
    textura = ""

Luego seguimos con el miniresumen.

sábado, 10 de febrero de 2018

Que trae de nuevo Java 9 ?


Voy a hacer un minipost de las características nuevas que trae Java 9, luego desarrollo cada una de forma individual.

JShell: REPL: Porfin!!! un repl en java. Para los que no saben que es un repl, la wikipedia dice lo siguiente : Un bucle Lectura-Evaluación-Impresión ("REPL" o "Read-Eval-Print-Loop"), también conocido como alto nivel interactivo o consola de lenguaje, es un entorno de programación computacional simple e interactivo que toma las entradas individuales del usuario, las evalúa y devuelve el resultado al usuario; un programa escrito en un entorno REPL es ejecutado parte por parte.

Métodos privados en las interfaces: Java 8 nos proporcionó la implementación de métodos predeterminado y estático en Interfaces; sin embargo, no podemos crear métodos privados en las interfaces. Si nos encontramos en una situación en la que tenemos múltiples métodos predeterminados en una interfaz que contiene la misma funcionalidad. En este escenario, normalmente refactorizaríamos estos métodos predeterminados para llamar a un método privado que contenga la funcionalidad compartida y ahora podemos hacer esto en java 9 :

public interface MyInterface {

    default void interfaceDefaultMethod() { init(); }

    default void interfaceSecondDefaultMethod() { init(); }

    // This is the declaration of the Private Method in Interface

    private void init() { ... }

}

Java 9 Module System: Claramente esto necesita un post en si. Pero para resumir podemos decir: Hasta la versión de Java 8 estábamos usando los contenedores monolíticos para diseñar nuestras aplicaciones basadas en Java. Hay dos problemas principales fundamentales con este diseño: Código difícil de encapsular y no hay ninguna noción de dependencias explícitas entre las diferentes partes de un sistema. Para evitar estos problemas fundamentales, Java 9 introdujo el sistema de módulos. Estos son algunos de los principales beneficios que obtenemos del Sistema de Módulos.

Los JDK, JRE, JAR actuales, etc. ahora están divididos en módulos más pequeños, por lo que solo podemos usar los módulos que deseamos. Esto ayuda a reducir la aplicación para dispositivos más pequeños.

Fuerte soporte para encapsulación. Las API internas no críticas están ocultas ahora, ya que los módulos ocultan detalles internos y no deseados de forma muy segura. Esto mejora la seguridad de la aplicación.

Mejoras en Javadoc: Java 9 ahora admite la búsqueda de documentación API internamente dentro de Javadoc.

HTTP/2 Client: Se ha lanzado una nueva API cliente HTTP/2 para soportar el protocolo HTTP/2 y las características de websockets. Este es un reemplazo del antiguo "HttpUrlConnection".

Nuevo esquema de cadena de versiones: Proporciona un formato de cadena de versión simplificado que ayuda a distinguir claramente las versiones principales, secundarias, de seguridad y actualización de parches.

El nuevo formato de cadena de versión se alinea con las prácticas actuales de la industria, en particular las versiones semánticas (servidor). El formato es el siguiente:

$ MAJOR. $ MENOR. $ SEGURIDAD. $ PATCH

Archivos JAR múltiple releases: Extiende el formato de archivo JAR para permitir que múltiples versiones de archivos de clase específicos de versiones de Java coexistan en un solo archivo.

Un JAR de múltiples releases (MRJAR) contiene directorios adicionales versionados para clases y recursos específicos para versiones de plataforma Java particulares. 

Mejoras en Stream API: La mejora en Stream API permite filtrar flujos entrantes de datos de serialización de objetos para mejorar la seguridad y la solidez.

Los clientes de serialización de objetos pueden validar su entrada más fácilmente, y los objetos exportados de Invocación de Método Remoto (RMI) también pueden validar los argumentos de invocación más fácilmente.

Los clientes de serialización implementan una interfaz de filtro que está configurada en un ObjectInputStream. Para RMI, el objeto se exporta a través de RemoteServerRef que establece el filtro en MarshalInputStream para validar los argumentos de invocación ya que no están agrupados.



Mailrelay, una de las mejores plataformas de email marketing que existen en el mercado


MailRelay es una herramienta de envío de emails. No! No es un cliente de correo, es una plataforma de email marketing avanzado con características de gran alcance. Te permite crear, enviar y gestionar tus boletines enviados vía emails con estadísticas completas, a la vez podes analizar el comportamiento del suscriptor.

Mailing marketing ??  Si, tambien se lo conoce como ciberbuzoneo  o en inglés: e-mailing es un método de marketing directo que utiliza el correo electrónico como medio de comunicación comercial para enviar mensajes a una audiencia. De esta forma podes tener al tanto a tus clientes de las novedades de tu empresa, nuevos productos, ofertas, etc...

Cuando se trata de correos masivos y envío masivo, no hay ninguna diferencia real entre los dos términos. Ambos significan envío masivo de email promocional para sus clientes y contactos. A veces, las personas confunden con correos masivos de spam. Sin embargo, la diferencia entre ambos es que el spam es no solicitado, mientras que el correo masivo es basado en permisos. Email marketing masivo tiene algunas ventajas muy profundas sobre todas las demás formas de marketing.

Con MailRelay podemos crear boletines y enviárselas a un grupo de suscriptores, a la vez la herramienta analiza el comportamiento del subscriptor, de esta forma podemos saber cual es el articulo más visitado, y que suscriptores vieron que articulo pudiendo analizar las necesidades de los clientes según esta información.

MailRelay no solo permite crear campañas de email marketing sino que tambien darle un correcto seguimiento y tener un contacto real con los clientes. Y es muy importante este seguimiento tanto para fidelizar al cliente como para estimular las ventas.

Entre otras ventajas podemos nombrar:

  • Un seguimiento inteligente de los clientes: con esta herramienta podes saber que necesita cada suscriptor y podemos hacer un seguimiento de los clientes y sus necesidades. 
  • No vamos a ser catalogados como spam:  Mailrelay cumple con todas las normas de correo electrónico anti-spam, haciendo que la puntuación antispam sea menos posible.
  • Templates para nuestros boletines:  Mailrelay cuenta con una completa biblioteca de templates gratuitos que podemos utilizar. 
  • SMTP de alto rendimiento:  Mailrelay nos ofrece un servicio smtp que se distingue por su alto rendimiento. 
  • Facilidad de uso: No es necesario que contrates a un programador o un diseñador gráfico, cualquier persona puede utilizar este servicio. 
  • Atención personalizada: Recibe atención personalizada y respuesta inmediata a tus dudas.



Y además de estas características cuenta con muchas promociones y descuentos. Por ejemplo Mailrelay es el único software de email marketing que permite enviar gratis 75.000 emails al mes a 15.000 suscriptores con autorespondedores incluidos.

Hoy día son muchas las empresas que buscan vender más, conseguir más visibilidad, fidelizar a sus clientes y destacar sobre su competencia. Objetivos todos dirigidos a garantizar la viabilidad de la empresa o proyecto. Objetivos que no son nada fáciles de conseguir y mantener.

Mailrelay tiene más de 15 años de experiencia en e-mail marketing, tanto desarrollando una herramienta de email marketing efectiva, como es Mailrelay, como ayudando a los clientes a mejorar sus resultados, llegar a la bandeja de entrada, solucionar sus problemas de spam, etc.

Como conclusión les aconsejo que vean con buenos ojos a Mailrelay dado su excelente soporte y sus ofertas. Y además es un excelente producto. Mailrelay te permite gestionar tu e-mail marketing de forma fácil y efectiva

Dejo link:
https://mailrelay.com/es

martes, 6 de febrero de 2018

20 libros que un desarrollador java debe leer en el 2018

En Dzone nos sugieren libros para leer en el 2018 y estoy bastante de acuerdo con la lista por lo tanto la comparto:

1. Java 8 in Action


best Java 8 books for programmers

2. Clean Architecture


best software architecture books for programmers

3. Grokking Algorithms

best Algorithm books for programmers

4. Building Microservices: Designing Fine-Grained Systems


best Microservices books for programmers

5. Soft Skills


best soft skill books for programmers

6. Database Design for Mere Mortals


best database design books for programmers

7. Making Java Groovy


best Groovy books for Java programmers

8. Groovy in Action, Second Edition


Image title

9. TCP/IP Illustrated


best book to learn TCP/IP protocol

10. UML Distilled


best book to learn UML

11. Hibernate Tips


Best book to learn Hibernate for experienced programmers

12. The Art of Agile Development


Best book to learn Agile

13. Essential Scrum


Best book to learn Scrum

14. Java Performance Companion


Best book to learn Java Performance Tuning

15. High-Performance Java Persistence


Best book to learn Java Persistence

16. Functional Programming in Scala


Best books to learn functional programming in Scala

17. Scala for the Impatient


Best books to learn  Scala

18. Head First JavaScript


Best books to learn JavaScript

19. SQL CookBook


Best books to learn SQL

20. The Complete Software Developer's Career Guide


Best books to take care of career development
Puff!! Tenemos mucho para leer!!

Dejo link: https://dzone.com/articles/20-books-java-programmers-should-read-in-2018