Weblogs Código

Blog Bitix

Microservicios con Spring Cloud, Consul, Nomad y Traefik

octubre 12, 2019 12:30

Sin entrar a si los microservicios son adecuados o no son adecuados en una aplicación, está claro que si se utilizan estos tienen varias necesidades. Un servicio de registro y descubrimiento, configuración centralizada, tolerancia a fallos, gateway/load balancer/reverse proxy, trazabilidad y métricas, autenticación, orquestación, … Los microservicios quiza no sean un gran monolito, quizá mas pequeños y con funcinalidad más acotada, pero el hecho de que se comuniquen a través de un medio más complejo y menos fiable como la red en vez de una llamada a un método y sean más numerosos hacen que la complejidad sea incluso mayor. Este artículo propone un ejemplo con Spring Cloud para los servicios, Consul para el registro y descubrimiento, Nomad para la orquestación y Traefik como gateway.

Java
Spring

En otro artículo mostraba un ejemplo de microservicios con Spring Cloud usando únicamente herramientas de Spring. Cada una de esas herramientas cubren una funcionalidad que necesitan los microservicios. Entre ellas:

  • Registro y descubrimiento, con Eureka. Los microservicios son numerosos, de vida efímera creándose y destruyéndose en diferentes ubicaciones por lo tanto necesitan una forma de localizarse unos a otros, la forma para encontrarse es acudiendo a un servicio donde se registran cuando se inician y se descubren cuando necesitan la ubicación de otro servicio.
  • Configuración centralizada, con Spring Cloud Config. Dado el número de microservicios actualizar la configuración de cada uno de ellos puede ser un problema, además dado que se pueden iniciar en diferentes ubicaciones aprovisionarles la configuración adecuada es un reto. En vez de aprovisionar la configuración otra técnica es hacer que cuando se inicien la obtengan de un servicio donde queda centralizada la configuración.
  • Tolerancia a fallos, con Hyxtrix y Resilience4j. El medio de comunicación de los microservicios es a través de la red un medio mucho menos confiable que una llamada a un método en un lenguaje de programación en una aplicación monolítica. De modo que los microservicios han de estar preparados para tolerar fallos en sus comunicaciones con otros servicios.
  • Gateway, load balancer y reverse proxy con tolerancia a fallos, con Zuul. Para aumentar la disponibilidad, escalabilidad y tolerar fallos en algunos servicios se suelen crear varias instancias de cada microservicio pero tener varias instancias hace que sea necesario balancear la carga entre cada una de las instancias. Para que los clientes sean agnósticos del número de instancias se emplea un gateway que proporciona balanceo de carga e implementa a su vez patrones de tolerancia a fallos.
  • Trazabilidad y correlación de trazas entre diferentes servicios, con Spring Cloud Sleuth. Una petición puede desencadenar una cadena de peticiones entre diferentes servicios ubicados en múltiples nodos, para tareas de diagnóstico en caso de querer investigar un bug o que ha ocurrido es necesario correlacionar todas las trazas que ha desencadenado una petición, se implementa asignado un identificativo global a la petición que es transmitido en las llamadas de microservicio a microservicio.

En otro ejemplo sobre OAuth con Spring mostraba otra funcionalidad:

Los microservicios también necesitan monitorización y métricas, en el ejemplo Monitorizar una aplicación Java de Spring Boot con Micrometer, Prometheus y Grafana:

  • Con Prometheus y Grafana. Nuevamente el número de instancias que requiere una arquitectura orientada a microservicios origina la necesidad en mayor medida de conocer el estado del sistema, ya sean métricas de los sistemas como uso de CPU, memoria o almacenamiento o de la aplicación como peticiones por segundo y porcentaje de correctas e incorrectas.

En esta lista falta un orquestador para el despliegue de los microservicios, que se encargue de su ciclo de vida, escalado de instancias y despliegue con estrategias rolling, blue/green y canary. Es una cosa que le faltaba al ejemplo de microservicios con Spring Cloud.

Además, en este ejemplo reemplazo varias de estas herramientas de Spring. Sustituyo el servicio de registro y descubrimiento proporcionado por Eureka por Consul, el gateway, load balancer y reverse proxy proporcionado por Zuul por Traefik y añado el orquestador de microservicios Nomad.

Consul Nomad Traefik

Traefik se configura con los servicios iniciados en los contenedores de Docker utilizando junto con los bloques o stanzas de config y labels en la definición de los servicios de Nomad. Según el criterio definido por el servicio Traefik es capaz de redirigir el tráfico que le llegue al servicio apropiado, entre las posibilidades que puede realizar Traefik es balanceo de carga entre las múltiples instancias que se hayan definido pero también implementa patrones de tolerancia a fallos con reintentos, el patrón circuit breaker o limitar el tráfico para evitar saturar a un servicio con demasiadas peticiones.

El esquema de servicios sería el siguiente. Los job son enviados a Nomad desde la linea de comandos que inicia los contenedores en Docker y registra los servicios en Consul, Traefik monitoriza los contenedores que se inician en Docker y se autoconfigura según las propiedades de los labels definidos para los contenedores. Una vez iniciados los servicios desde la terminal con un curl o desde la aplicación cliente que accede a Consul para conocer la ubicación del servicio de Traefik envían una petición a Traefik que haciendo balanceo de carga la reenvía a una de las instancias del servicio, el servicio responde y Traefik envía la respuesta al cliente. Para ser más funcional Traefik debería configurarse a partir de Consul en vez de Docker para posibilitar que los contenedores pudieran estar en varios nodos.

Esquema arquitectura

La ejecución del ejemplo requiere Docker ya que es en este caso el driver empleado en Nomad para ejecutar los servicios del servicio de configuración, el gateway, el servicio y el cliente del servicio. Nomad además se encarga de registrar los servicios en el servicio de registro y descubrimiento de Consul.

Los contenedores de Docker se añade a una misma red para que puedan comunicarse entre ellos, ha de ser así hasta que no se resuelva una petición de Docker para que los contenedores puedan comunicarse con la máquina host que los alberga.

1
docker network create --subnet 172.30.0.0/16 nomad

Poteriormente hay que ejecutar Consul y Nomad tras lo cual se puede acceder a sus consolas de estado.

1
2
consul agent -dev -ui -client=0.0.0.0
nomad agent -dev

Enviar a Nomad los job de Traefik tras lo cual se puede acceder a su consola de estado. El siguiente paso es enviar el job del servicio que proporciona la configuración a los microservicios. Lo anterior únicamente es infraestructura aún no hay ningún servicio que proporcione alguna funcionalidad, la funcionalidad que proporciona el servicio implementado con Spring es simplemente devolver un mensaje como respuesta a la petición que se le realice, se envía el job del servicio a Nomad. Finalmente, el servicio es consumido por un cliente que realiza una petición al servicio cada 1 segundo.

1
2
3
4
5
6
./gradlew assemble
nomad job run nomad/traefik.nomad
nomad job run nomad/configserver.nomad
nomad job run nomad/service.nomad
nomad job run nomad/client.nomad

Definición de un servicio en un job para Nomad. count define cuantas instancias del servicio se inicia, la stanza update define como será la actualización cuando se actualice el servicio, la stanza labels contiene la configuración para Traefik, check define los parámetros para la monitorización.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
job "service" {
 datacenters = ["dc1"]
group "service" {
 count = 2
update {
 max_parallel = 1
 health_check = "checks"
 min_healthy_time = "20s"
 healthy_deadline = "10m"
 progress_deadline = "20m"
 canary = 1
 stagger = "15s"
}
task "service" {
 driver = "docker"
config {
 image = "openjdk:11-jdk"
 args = [
"bash",
"-c",
 "(cd /app && java -jar /app/service/build/libs/service-1.0.jar --port=8080)"
]
port_map {
 http = "8080"
}
 network_mode = "nomad"
 extra_hosts = [
"traefik:172.30.0.3"
]
 volumes = [
"/home/picodotdev/Software/personal/blog-ejemplos/SpringCloudConsulNomadTraefik/:/app"
]
labels {
 traefik.http.middlewares.service1-stripprefix.stripprefix.prefixes="/service",
 traefik.http.middlewares.service1-retry.retry.attempts="10",
 traefik.http.routers.service1.middlewares="service1-stripprefix,service1-retry",
 traefik.http.routers.service1.rule="PathPrefix(`/service`)",
 traefik.http.services.service1.loadbalancer.server.port="8080"
}
}
service {
 name = "service"
 port = "http"
check {
 type = "http"
 port = "http"
 path = "/actuator/health"
 interval = "5s"
 timeout = "2s"
}
}
resources {
 cpu = 200
 memory = 1024
network {
 mbits = 20
port "http" {}
}
}
}
}
}

Tanto Consul, Nomad como Traefik ofrecen una consola para ver su estado ubicadas en las siguientes direcciones respectivamente accesibles con el navegador http://127.0.0.1:8500, http://127.0.0.1:4646, http://127.0.0.1:8092.

Consolas de administración de Consul, Nomad y Traefik

El código del servicio, del cliente implementados con Spring y la salida del cliente son los siguientes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package io.github.picodotdev.blogbitix.springcloud.service;
...
@RestController
public class DefaultController {
@Autowired
private DefaultConfiguration configuration;
@Autowired
private Tracing tracing;
@Autowired
private Tracer tracer;
private Random random;
private Counter counter;
public DefaultController(MeterRegistry registry) {
this.random = new Random();
this.counter = Counter.builder("service.invocations").description("Total service invocations").register(registry);
}
@RequestMapping("/")
public String home(HttpServletRequest request) throws Exception {
counter.increment();
// Timeout simulation
 //Thread.sleep(random.nextInt(4000));

TraceContext.Extractor<HttpServletRequest> extractor = tracing.propagation().extractor((HttpServletRequest carrier, String key) -> { return carrier.getHeader(key); });
Span span = tracer.nextSpan(extractor.extract(request));
System.out.printf("Service Span (traceId: %s, spanId: %s)%n", span.context().traceIdString(), span.context().spanIdString());
return String.format("Hello world (url: %s, remoteAddress_%s, localAddress: %s, traceId: %s, spanId: %s, key: %s)", request.getRequestURL(),
request.getRemoteAddr(), request.getLocalAddr(), span.context().traceIdString(), span.context().spanIdString(), configuration.getKey());
}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package io.github.picodotdev.blogbitix.springcloud.client;
...
@Component
public class ProxyService {
@Autowired
private LoadBalancerClient loadBalancer;
@Autowired
private Tracing tracing;
@Autowired
private Tracer tracer;
private CircuitBreakerConfig circuitBreakerConfiguration;
private TimeLimiterConfig timeLimiterConfiguration;
private HttpClient client;
public ProxyService() {
circuitBreakerConfiguration = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.recordExceptions(IOException.class, TimeoutException.class)
.build();
timeLimiterConfiguration = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofMillis(2500))
.cancelRunningFuture(true)
.build();
client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_2).build();
}
public String get() {
ServiceInstance instance = loadBalancer.choose("traefik");
URI uri = instance.getUri();
String resource = String.format("%s%s", uri.toString().replace("127.0.0.1", "traefik"), "/service");
HttpRequest.Builder r = null;
try {
r = HttpRequest.newBuilder(new URI(resource)).GET();
} catch (Exception e) {
return getFallback();
}
final HttpRequest.Builder request = r;
Span span = tracer.newTrace().start();
TraceContext.Injector<HttpRequest.Builder> injector = tracing.propagation().injector((HttpRequest.Builder carrier, String key, String value) -> { carrier.header(key, value); });
injector.inject(span.context(), request);
System.out.printf("Client Span (traceId: %s, spanId: %s)%n", span.context().traceIdString(), span.context().spanIdString());
CircuitBreaker circuitBreaker = CircuitBreaker.of("resilience4jCircuitBreakerProxyService", circuitBreakerConfiguration);
TimeLimiter timeLimiter = TimeLimiter.of(timeLimiterConfiguration);
Supplier<CompletableFuture<String>> get = () -> {
return CompletableFuture.supplyAsync(() -> {
try {
HttpResponse<String> response = client.send(request.build(), HttpResponse.BodyHandlers.ofString());
return response.body();
} catch (Exception e) {
return getFallback();
}
});
};
Callable<String> getLimiter = TimeLimiter.decorateFutureSupplier(timeLimiter, get);
Callable<String> getCircuitBreaker = CircuitBreaker.decorateCallable(circuitBreaker, getLimiter);
return Try.of(getCircuitBreaker::call).recover((throwable) -> getFallback()).get();
}
private String getFallback() {
return "Fallback";
}
}

Como hay 2 instancias del servicio y Traefik realiza balanceo de carga utilizando el algoritmo round robbin se observa en la salida con las respuestas que la dirección IP que ha atendido la petición es alternativamente una de las dos instancias del servicio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
...
Service response: Hello world (url: http://172.30.0.3/, remoteAddress_172.30.0.3, localAddress: 172.30.0.4, traceId: 63afa4d0cd4f466c, spanId: 4719dfcc16b6104e, key: value)
Client Span (traceId: 57eeaa436aa09238, spanId: 57eeaa436aa09238)
Service response: Hello world (url: http://172.30.0.3/, remoteAddress_172.30.0.3, localAddress: 172.30.0.5, traceId: 57eeaa436aa09238, spanId: 26dc213be2d933ac, key: value)
Client Span (traceId: 23c748bf222052a6, spanId: 23c748bf222052a6)
Service response: Hello world (url: http://172.30.0.3/, remoteAddress_172.30.0.3, localAddress: 172.30.0.4, traceId: 23c748bf222052a6, spanId: 0404d949c6e04c18, key: value)
Client Span (traceId: c45d66a4ec9cf14c, spanId: c45d66a4ec9cf14c)
Service response: Hello world (url: http://172.30.0.3/, remoteAddress_172.30.0.3, localAddress: 172.30.0.5, traceId: c45d66a4ec9cf14c, spanId: e7f6ccf2efb8234b, key: value)
Client Span (traceId: 2fdb3b71a682d2e6, spanId: 2fdb3b71a682d2e6)
Service response: Hello world (url: http://172.30.0.3/, remoteAddress_172.30.0.3, localAddress: 172.30.0.4, traceId: 2fdb3b71a682d2e6, spanId: 24ac2a8d2bfb1e6e, key: value)
Client Span (traceId: a33b010e02709c6a, spanId: a33b010e02709c6a)
Service response: Hello world (url: http://172.30.0.3/, remoteAddress_172.30.0.3, localAddress: 172.30.0.5, traceId: a33b010e02709c6a, spanId: 0abe6074fc277af6, key: value)
...

En un momento posterior si surge la necesidad de querer desplegar una nueva versión del microservicio basta con generar de nuevo el artefacto del microservicio, cambiando la versión en el archivo build.gradle. El despliegue de la nueva versión se realizan mediante la estrategia canary, manteniendo las instancias con la versión anterior del servicio y añadiendo una nueva con la nueva versión. Si se descubre algún error en la instancia canary se puede revertir el estado a la versión anterior, que consiste en detener la instancia canary. Una vez se comprueba que la instancia con la nueva versión funciona correctamente analizando sus trazas y métricas se envía la order a Nomad de promocionar las instancias de forma progresiva con la versión antigua a la nueva versión.

1
2
3
nomad job run nomad/service.nomad
nomad job promote service
nomad job revert service 0

El servicio exporta métricas en formato para Prometheus que con Grafana. Según se realizan peticiones al servicio el valor de métrica de contador de llamadas al servicio aumenta de forma progresiva.

1
2
3
4
curl http://127.0.0.1:8093/service/actuator/prometheus | grep "service.invocations"
# HELP service_invocations_total Total service invocations
# TYPE service_invocations_total counter
service_invocations_total 20.0

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./run.sh.

» Leer más, comentarios, etc...

Coding Potions

Tutorial básico Vue ≫ Cómo crear componentes y estructura de carpetas

octubre 09, 2019 12:00

Introducción

En este artículo vamos a echar un ojo a los componentes web, una pieza fundamental de VueJS y del desarrollo frontend a día de hoy.

Bien, si recuerdas, hace tiempo vimos qué es VueJS y cómo instalarlo, pero no vimos cómo empezar a usarlo propiamente dicho. Hoy vamos a aprender cómo se organizan los archivos en Vue y cómo crear tu primer componente web.

Pero antes vamos a ver el concepto de los web components por si todavía no lo controlas.

Qué son los componentes web

Logo componentes web

Los componentes web son un concepto relativamente nuevo, aunque realmente llevas utilizándolos mucho tiempo. Un componente web se trata de un elemento de la página web, con vista, estilos y lógica, que puedes reutilizar a lo largo de tu página web.

Realmente todas las etiquetas html son una especie de componentes web porque se componen también de esas partes.

Por ejemplo al crear un elemento html <input>, realmente estás creando una especie de componente web porque se compone del html que se pinta, los estilos que se pintan por defecto y a lógica de poder escribir.

Pues ahora imagínate que puedes crear tu propio componente con un html mucho más complejo, con más estilos CSS que los de por defecto y con una lógica mucho más compleja. Imagina poder crear un componente web llamado calendario. Simplemente poniendo en la página que lo necesites su etiqueta html, por ejemplo <calendar/> podrías crear un calendario totalmente funcional incluso con la lógica de pasar los meses y los años.

Los componentes no son únicos de Vue, es más, desde hace poco los puedes crear de forma nativa en javascript, pero Vue lo que hace es facilitarnos la tarea de crear los componentes web escribiendo menos código y pudiendo hacer cosas mucho más complejas.

Estructura básica de un proyecto Vue

Antes de empezar a crear componentes web es esencial que sepas la estructura que tiene un proyecto de VueJS para que sepas dónde va cada cosa. Los archivos que muestro a continuación son los que hay nada más crear el proyecto con el comando de Vue create:

Estructura de carpetas de Vue

📁 Carpeta node_modules

Como en todo proyecto javascript que utilice los paquetes NPM, aquí también existe esta carpeta en la que se encuentran todas las dependencias ya instaladas del proyecto. Si no sabes cómo utilizar NPM te recomiendo mi tutorial completo de NPM

📁 Carpeta public

En esta carpeta hay dos archivos:

  • favicon.ico: Es el icono que aparece al lado del nombre de la pestaña en el navegador, por defecto es el logo de Vue pero lo puedes cambiar por tu icono en formato .ico
  • public.html: Es el archivo html sobre el que se montará toda la página. Como hemos dicho en capítulos anteriores, al ser una aplicación SPA, todas las vistas se cargan dinámicamente sin tener que recargar la paǵina. Esto significa que toda la página se incrustará dentro de la etiqueta:

    <div id="app"></div>
    

    Por lo que toda la página compartirá este html. Por cierto, si quieres insertar nuevos archivos de estilos o archivos javascript en el head de esta página NO tienes que llamar a tus archivos aquí, esto lo haremos con webpack.

📁 Carpeta src

En la carpeta src se sitúan los archivos fuentes de nuestra página web. En esta carpeta es dónde se crea todo, es decir, aquí van los componentes y las vistas, así como todo el resto de archivos necesarios para hacerlos funcionar.

  • assets: En esta carpeta se encuentran todos los archivos estáticos de tu aplicación. Cuando creas la estructura se añade el archivo logo.png de ejemplo. Cuando quieras meter una imagen, fuentes, o cosas así lo puedes hacer en esta carpeta. Vue y webpack se encargarán de servir los archivos de esta carpeta para que los puedas llamar desde las vistas.
  • components: Aquí se crearan todos los componentes web. Al crear el proyecto te viene el componente HelloWorld.vue de ejemplo. Lo más recomendable es que dentro de esta carpeta crees carpetas para separar los componentes entre sí. Lo que se suele hacer es separar los componentes por páginas o por área a la que pertenece.
  • views: Si al crear el proyecto has seleccionado manualmente que instale vue router para crear las vistas, aparecerá esta carpeta (si no lo has hecho cuando veamos las vistas te enseñaré como instalarlo en un proyecto ya creado). En esta carpeta se sitúan los componentes encargados de cada una de las vistas y rutas de la página. Lo normal es que haya un componente por cada ruta de la página.

📄 Otros archivos

Aparte de las carpetas que acabamos de ver, Vue crea estos archivos. En mi caso al crear el proyecto de Vue seleccioné que las configuraciones vayan en archivos separados para una mejor gestión.

  • .browserslistrc: En este archivo se especifican cuántas versiones hacia atrás se quiere tener compatibilidad con los nevegadores.
  • .eslintrc.js: Aquí se establecen las normas y las configuraciones del eslint, es decir, de la herramienta que te dice los errores y los warnings cuando guardas los archivos. Si hay una regla que no la quieres, aquí la puedes personalizar o quitar directamente.
  • .gitignore: Aquí le dices al git qué ficheros quiere que ignore. Por defecto Vue te habrá colocado los recomendados.
  • babel.config.js: Configuraciones de babel, la herramienta que transpila el javascript generado a código entendible por navegadores antiguos.
  • package.json y package-lock.json: Donde se establecen las versiones de la librerías requeridas. Además se pueden establecer otros parámetros como el nombre de la aplicación, versión, autores, etc.
  • postcss.config.js: Aquí van las configuraciones del transpilador de CSS, en mi caso uso sass.
  • README.md: Archivo que se muestra al entrar en un proyecto en el github o gitlab. Aquí puedes escribir información sobre el proyecto que creas conveniente.

Hello world. Cómo se crea un componente

Bien, pues ahora que hemos visto todo lo básico para empezar, vamos a ver por fin algo de código. Lo primero que tienes que hacer tras crear un proyecto es ejecutar npm run serve o vue serve para ejecutar vue en modo desarrollo y poder abrir la página que estamos desarrollando.

Si ahora abres localhost:8080en tu navegador verás la página de prueba de Vue con lo que has instalado. Hora de abrir el proyecto en tu editor de texto favorito, en mi caso el vscode.

Como hemos visto, los componentes se crean dentro de src/components, si abres esa carpeta te encontrarás con un archivo llamado HelloWorld.vue, ábrelo. Verás algo como esto:

<template>
<div class="hello">
    <h1></h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br />
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
    <li>
        <a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a>
    </li>
    <li>
        <a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a>
    </li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
    <li>
        <a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
    </li>
    <li>
        <a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a>
    </li>
    <li>
        <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a>
    </li>
    <li>
        <a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a>
    </li>
    <li>
        <a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
    </li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
    <li>
        <a href="https://router.vuejs.org" target="_blank" rel="noopener" >vue-router</a>
    </li>
    <li>
        <a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
    </li>
    <li>
        <a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener" >vue-devtools</a>
    </li>
    <li>
        <a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a>
    </li>
    <li>
        <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener" >awesome-vue</a>
    </li>
    </ul>
</div>
</template>

<script>
  export default {
    name: "HelloWorld",
    props: {
      msg: String
    }
  };
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
  h3 {
    margin: 40px 0 0;
  }
  ul {
    list-style-type: none;
    padding: 0;
  }
  li {
    display: inline-block;
    margin: 0 10px;
  }
  a {
    color: #42b983;
  }
</style>

Lo primero, no te asustes. Lo segundo, borra todo el contenido dentro de las etiquetas <template>y déjalo así:

<template>
    <div class="hello">
    Hello world
    </div>
</template>

<script>
  export default {
    name: "HelloWorld",
    props: {
      msg: String
    }
  };
</script>

<style scoped lang="scss">
  h3 {
    margin: 40px 0 0;
  }
  ul {
    list-style-type: none;
    padding: 0;
  }
  li {
    display: inline-block;
    margin: 0 10px;
  }
  a {
    color: #42b983;
  }
</style>

Si ahora abres [localhost:8080](http://localhost:8080) verás que la página ha cambiado y que ahora pone Hello world

Partes que componen un componente en VueJS

Si recuerdas lo que vimos anteriormente, los componentes se componen de 3 partes: la vista, los estilos y la lógica. Vue para diferencias estas 3 partes usa las etiquetas html:

  • Dentro de la etiqueta <template> está el código html del componente. Cada vez que llames al componente, Vue insertará el contenido de esta etiqyeta dentro del DOM de la página web.
  • Dentro de la etiqueta <script> está la lógica del componente. Aquí puedes crear métodos, variables, llamadas al back, etc, es decir, la funcionalidad y el código javascript que está relacionado con el template.
  • Dentro de la etiqueta <style>se encuentran los estilos del componente. Aquí es donde puedes crear estilos css o scss para los elementos que has creado en la etiqueta template.

Los archivos Vue se componen de estas partes en el mismo archivo (Single File Component), a diferencia de Angular que tiene la vista, estilos y lógica de cada componente en archivos separados. Hablemos un poco de cada una de las partes:

La vista

Como hemos dicho aquí puedes escribir los elementos HTML que quieres que tenga el componente cuando lo utilices. Vue cuando renderice el componente y su vista eliminará las etiquetas template y dejará solo su contenido.

Es importante saber que Vue tiene una limitación, no se pueden crear más de un elemento raíz, es decir, este componente no es válido y por tanto salta error:

<template>
  <div class="one"></div>
  <div class="tow"></div>
</template>

Como ves hay dos elementos raíz, los dos div. En cambio este componente si que sería válido:

<template>
  <div class="content">
    <div class="one"></div>
    <div class="tow"></div>
  </div>
</template>

La lógica

Aquí es el lugar en el que escribes la funcionalidad, es decir, el comportamiento del componente. Como veremos más adelante, aquí vas a poder controlar qué ocurre cuando se crea el componente, cuando se destruye, cuando cambia una variable, etc.

Por el momento lo que tienes que saber es que siempre que crees un componente tienes que escribir:

<script>
export default {
  name: "HelloWorld"
};
</script>

Esta es la parte mínima de un componente. En la etiqueta name puedes escribir el nombre del componente, pero siempre en PascalCase (la primera letra en mayúsculas, las palabras juntas y cada una con la primera letra en mayúscula). El campo name no es obligatorio pero viene bien para identificar el componente.

A diferencia de Angular, aquí no tienes que indicar explícitamente que coja la vista de otro archivo.

Creando el componente

Para crear los componentes, lo que yo hago es simplemente crear el fichero con el nombre del componente en PascalCase también (la primera letra en mayúsculas, las palabras juntas y cada una con la primera letra en mayúscula) y creo la estructura básica con todas las partes. Por ejemplo este componente lo crearía dentro de src/components/ con el nombre MiComponente.vue:

<template>
  <p>Mi primer componente en Vue</p>
</template>

<script>
  export default {
    name: "MiComponente"
  }
</script>

<style lang="scss" scoped>
</style>

En la etiqueta style he creado el parámetro lang para poder usar scss pero si quieres usar css básico no hace falta que la pongas (Si creaste el proyecto de Vue de manera manual te habrá preguntado si quieres preprocesadores CSS). También le meto el atributo scoped que sirve para encapsular los estilos.

Al poner scoped, lo que hace Vue es aislar esos estilos para que no afecten a otros componentes de otros archivos, lo que es muy recomendable.

Si dentro de un componente creo un elemento con una clase unos estilos y en otro componente de otro fichero creo la misma clase y le meto otros estilos, los estilos se van a pegar entre sí. Usando scoped tienes la ventaja de poder usar las clases que quieras dentro del componente asegurando que no van a haber conflicto con otros componentes.

Para usar este componente que acabas de crear tienes que hacer lo siguiente. Pongamos que lo quieres insertar en el componente Home de la carpeta /src/views (Si instalaste Vue con el create pero no de la forma manual, o no indicaste que instalara Vue Router puedes importar el componente dentro de App.vue para que veas el ejemplo).

Si abres este componente verás lo siguiente:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
      <HelloWorld msg="Welcome to Your Vue.js App" />
    </div>
</template>

<script>
  // @ es un alias a /src
  import HelloWorld from "@/components/HelloWorld.vue";

  export default {
    name: "home",
      components: {
        HelloWorld
    }
  };
</script>

Si te das cuenta ya se está usando el componente HelloWorld. Los componentes siempre se importan encima del export dentro de la etiqueta script.

<script>
  // @ is an alias to /src
  import HelloWorld from "@/components/HelloWorld.vue";
  import MiComponente from "@/components/MiComponente.vue";

  export default {
  ...
  }

Como dice el comentario, al importar, dentro de la ruta se coloca @ como atajo a la carpeta src. Esto es muy recomedable ponerlo.

Ahora toca añadirlo al objeto components de más abajo. Siempre que quieras usar un componente tienes que importarlo y añadirlo aquí, de lo contrario no funcionará.

components: {
  HelloWorld, 
  MiComponente;
}

Por último lo puedes colocar arriba en la vista. Vue por debajo lo que va a hacer es mirar el objeto components que hemos visto antes, y va a sustituir el nombre del componente en PascalCase por el mismo nombre pero en kebab-case. Esto se hace para que cuadren mejor con los elementos HTML. Por lo que solo tenemos que:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <HelloWorld msg="Welcome to Your Vue.js App" />
    <mi-componente></mi-componente>
  </div>
</template>

Como ves también se pueden usar como PascalCase como el componente de HelloWorld pero es más recomendable en kebab-kase: hello-world

Otro detalle a tener en cuenta es que los componentes los puedes cerrar en la misma etiqueta de apertura:

<mi-componente />

Y listo, ya deberías ver el nuevo componente dentro de la página web. Cada vez que cambies algo de unos de los componentes vas a ver el cambio instantáneamente sin tener que recargar la web.

En conjunto quedaría así:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <HelloWorld msg="Welcome to Your Vue.js App" />
    <mi-componente />
  </div>
</template>

<script>
  // @ is an alias to /src
  import HelloWorld from "@/components/HelloWorld.vue";
  import MiComponente from "@/components/MiComponente.vue";

  export default {
    name: "home",
    components: {
      HelloWorld,
      MiComponente
    }
  };
</script>

Conclusiones

Pues ya has visto cómo se crean los componentes y cómo se pueden usar. Lógicamente puedes meter componentes dentro de componentes que a su vez tienen más componentes. Cuanto más reutilices los componentes mejor. Si por ejemplo te creas un componente para crear botones, si los usas en toda la web, el día que tengas que cambiarlos solo lo tienes que hacer en un sitio.

En próximos capítulos veremos cómo se pueden personalizar los componentes para que sean flexibles y adaptables a cualquier situación.

Como último consejo para desarrollar con Vue te digo que siempre tengas la consola del navegador abierta. Muchas veces los fallos los detectas porque ha habido un error que se muestra ahí, aunque normalmente los errores te los dice Vue en la propia página.

» Leer más, comentarios, etc...

Picando Código

Thunderbird 78 tendrá soporte nativo para OpenPGP

octubre 08, 2019 08:35

A partir de la próxima versión del cliente de correo, Thunderbird tendrá soporte nativo para el cifrado de correos y firmas digitales usando el estándar OpenPGP.

Thunderbird OpenPGP

OpenPGP es un protocolo para el cifrado de comunicación por correo electrónico usando criptografía de llave pública. Está basada en el software PGP (Pretty Good Privacy) original. El protocolo define formatos estándar para mensajes cifrados, firmas y certificados para intercambiar claves públicas.

La nueva funcionalidad reemplazará a Enigmal -la extensión de Thunderbird- que continuará siendo soportada hasta el fin de soporte de Thunderbird 68, en el último cuarto de 2020. Thunderbird 70 estará disponible a principios de 2020.

Existen dos tecnologías que agregan soporte para cifrado punta-a-punta y firmas digitales en los correos electrónicos. Thunderbird ha ofrecido soporte nativo para S/MIME por muchos años y lo continúa haciendo. La extensión Enigmail ha permitido el uso de Thunderbird con software GnuGP externo para mensajes OpenPGP. Dado que los tipos de extensiones van a cambiar en la versión 78, la rama actual de Thunderbird 68.x va a ser la última que podrá ser usada con Enigmal.

Thunderbird 78 proveerá asistencia para migrar configuraciones actuales de Enigmal. El desarrollador de Enigmal, Patrick Brunschwig, trabajará con el equipo de Thunderbird en OpenPGP a partir de ahora. Comentó:

Siempre ha sido mi meta que el soporte para OpenPGP esté incluido en el núcleo del producto Thunderbird. Aunque marcará un final a una larga historia, después de trabajar en Enigmal por 17 años, estoy muy feliz con este resultado.

Los usuarios que no hayan usado Enigmal anteriormente necesitarán optar usar mensajería con OpenPGP, el cifrado no estará habilitado automáticamente. Sin embargo, Thunderbird 78 ayudará a los usuarios a descubrir la nueva funcionalidad.

Para promover la comunicación segura, Thunderbird 78 animará al usuario a realizar confirmación de la pertenencia de claves usadas por los emisores, notificará al usuario si las llaves de los emisores cambian inesperadamente, y si hay un problema, ofrecerá asistencia para resolver la situación.

Todavía no está decidido si Thunderbird 78 soportará las confirmaciones indirectas de pertenencia de claves usadas en el modelo Web Of Trust (WoT), o hasta qué punto. Sin embargo, compartir confirmaciones de pertenencias de claves hechas por el usuario e interacción con servidores de claves OpenPGP será posible.

Pueden leer más información y planes más detallados sobre OpenPGP en Thunderbird en la wiki de Mozilla.

» Leer más, comentarios, etc...

Variable not found

Error en proyectos gRPC al usar un nombre de usuario de Windows con espacios o caracteres especiales

octubre 08, 2019 02:07

gRPCComo un servidor, todos los que tengáis la inmensa fortuna de utilizar en Windows un nombre de usuario con espacios o caracteres especiales como "José María Aguilar", seguro que habéis encontrado alguna vez problemas con aplicaciones o herramientas que fallan cuando intentan acceder a contenidos de la carpeta C:\Users\<Tu nombre>:

Username chungo en Windows

De hecho, llevo ya varios encontronazos de este tipo en los últimos meses (por ejemplo, con Anaconda o con el SDK de Android para Windows), y el último lo he tenido al intentar utilizar las herramientas de Protobuf para la creación de servicios gRPC que, como sabéis, es una de las novedades incluidas en .NET Core 3.

Aunque el problema lo he encontrado trabajando con Visual Studio, ciertamente este IDE tiene poco que decir al respecto; ocurre lo mismo usando línea de comandos o cualquier otro entorno que se base en el tooling oficial de gRPC para .NET.

El problema

El problema es bastante sencillo de reproducir si usáis nombres de usuario de ese tipo. Basta con crear un proyecto de tipo "Servicio gRPC" e intentar compilarlo. Si lo hacemos desde Visual Studio, veremos el siguiente error:

Error 'protoc-gen-grpc: el sistema no puede encontrar la ruta especificada

Y si lo hacemos desde línea de comandos, no mejora mucho la cosa:
C:\test>dotnet new grpc
The template "ASP.NET Core gRPC Service" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on C:\test\test.csproj...
Restauración realizada en 96,36 ms para C:\test\test.csproj.

Restore succeeded.


C:\test>dotnet build
Microsoft (R) Build Engine versión 16.3.0+0f4c62fea para .NET Core
Copyright (C) Microsoft Corporation. Todos los derechos reservados.

Restauración realizada en 19,26 ms para C:\test\test.csproj.
--grpc_out : error : protoc-gen-grpc: El sistema no puede encontrar
la ruta especificada. [C:\test\test.csproj]

ERROR al compilar.

--grpc_out : error : protoc-gen-grpc: El sistema no puede encontrar
la ruta especificada. [C:\test\test.csproj]
0 Advertencia(s)
1 Errores

Tiempo transcurrido 00:00:00.68

C:\test>_
Me encantan estos errores que no dan pistas sobre el origen del problema ;)

La solución

Desde luego, y me lo apunto para mi próxima instalación de Windows, el mejor remedio sería no utilizar un nombre de usuario con espacios ni caracteres extraños. Un "jmaguilar" habría sido perfecto, ho hay necesidad de utilizar el nombre completo ;)
C:\Users\José María Aguilar> _
Pero si ya estamos en un momento en que esto no tiene solución sencilla, podéis seguir los pasos descritos a continuación:

1. Crear un enlace simbólico, o un junction link, por ejemplo en la raíz del disco duro, apuntando hacia el directorio donde se encuentra la carpeta packages de NuGet:
C:\> mklink /j "C:\.nuget" "C:\Users\José María Aguilar\.nuget"
Una vez ejecutado este comando, la carpeta se verá en el explorador de archivos como se muestra en la siguiente captura de pantalla:

  Junction link creado en la carpeta raíz

2. Establecer la variable de entorno NUGET_PACKAGES, que indica la ubicación de la carpeta Packages de NuGet, utilizando el enlace simbólico. En mi caso, es algo como:
NUGET_PACKAGES=C:\.nuget\packages
¡Y esto es todo! Espero que os resulte útil, y recordad que este mismo truco podéis usarlo para otros escenarios en los que ocurra lo mismo :)

Publicado en: Variable not found.

» Leer más, comentarios, etc...

Fixed Buffer

Worker Service: Cómo crear un servicio .Net Core 3 multiplataforma

octubre 08, 2019 08:00

La imagen muestra el logo de .Net Core 3.0

Hace unos meses, hablamos sobre como crear servicios multiplataforma con .Net Core 2, donde veíamos que había que hacer algunas «perrerías» para poder conseguirlo… Ha llegado .Net Core 3, y me ha parecido interesante hablar sobre la nueva manera que nos trae de conseguir esto.

En primer lugar, tenemos una nueva plantilla disponible para esto: Worker Service. Usando esta plantilla, vamos a poder tener un ejemplo para construir nuestro servicio. Aunque perfectamente podemos hacerlo desde una aplicación de consola añadiendo nosotros el código, vamos a «estrenar» la plantilla (si nos dan trabajo hecho, tampoco vamos a decir que no… xD )

Creando la solución

Lo primero por supuesto, es crear nuestra solución, y en ella, vamos a elegir la plantilla «Servicio de trabajo» (Worker Service en inglés):

La imagen muestra la plantilla seleccionada

Esto nos va a crear una solución con dos archivos, Program.cs y Worker.cs. Si abrimos Program.cs, vamos a poder comprobar que nuestro proyecto no es más que una aplicación de consola que crea un «Host» (al igual que hacíamos en .Net Core 2.X).

namespace PostWorker
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();
                });
    }
}

El segundo fichero que tenemos, Worker.cs, tiene una pinta parecida a esta:

namespace PostWorker
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

La principal novedad al crear nuestras tareas dentro del servicio, es que ahora heredamos de la clase abstracta «BackgroundService» (y no de IHostedService como hacíamos en .Net Core 2.X). Esto simplemente es para aportarnos una capa de abstracción sobre su funcionamiento, y realmente es esta clase la que implementa IHostedService y nos ofrece 3 métodos para trabajar con ella:

protected abstract Task ExecuteAsync(CancellationToken stoppingToken)
public virtual Task StartAsync(CancellationToken cancellationToken)
public virtual Task StopAsync(CancellationToken cancellationToken)        

Para crear nuestro servicio básico, tal como lo hace el ejemplo, basta con implementar el primero de ellos (que además al ser abstracto estamos obligados a implementar). Pero vamos a profundizar un poco más…

El primero de ellos, va a ser lo que queremos que se ejecute dentro de nuestro servicio, con la implementación por defecto, cuando arranque el servicio, se va a llamar directamente a ese método en una tarea. De igual manera, cuando el servicio se pare, se cancelará el token. Es importante tener en cuenta el CancellationToken como sistema de control del ciclo de vida, para evitar tener tareas bloqueadas al parar nuestro servicio.

Si necesitamos una funcionalidad un poco más avanzada, como ejecutar algo de código previo al arranque o en la parada, lo que vamos a tener que hacer es sobrescribir los métodos StartAsync y StopAsync según necesitemos, ya que no es obligatorio hacerlo con los dos. Un caso en el que nos podría hacer falta, es cuando necesitamos diferenciar las labores de arranque del servicio con las propias de ejecución. Por ejemplo, si quieres loguear cuando arranca o para tu servicio .Net Core 3:

namespace PostWorker
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        public override async Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Worker starts");
            await base.StartAsync(cancellationToken);
        }

        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Worker stops");
            await base.StopAsync(cancellationToken);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

Es importante señalar, que podemos registrar tantos «Workers» como necesitemos, basta con que lo añadamos en el inyector de dependencias. Por ejemplo, si tuviésemos una clase Worker1 y otra Worker2, nuestro Program.cs se vería algo así:

namespace PostWorker
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker1>();
                    services.AddHostedService<Worker2>();                    
                });
    }
}

Con esto, ya tenemos un código perfectamente funcional como servicio, de hecho, si lo instalamos en Linux como servicio (daemon), podremos comprobar que funciona perfectamente. En cambio, si lo instalamos en Windows, para nuestra sorpresa (o no), simplemente esto no va a funcionar.

Instalando nuestro servicio .Net Core 3 en Windows

Si alguna vez has creado un servicio en Windows, sabes que tiene sus cositas… En .Net Core 2.X, teníamos que hacer ciertas perrerías para conseguirlo, pero por suerte, ahora tenemos un paquete NuGet que nos permite hacerlo sin dificultades (básicamente, hace las perrerías por nosotros). Este paquete es «Microsoft.Extensions.Hosting.WindowsServices«, basta con que lo añadamos a nuestro proyecto y que añadamos su uso en Program.cs con «UseWindowsService» sobre el HostBuilder:

namespace PostWorker
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseWindowsService() //Registramos el paquete
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();                  
                });
    }
}

Este paquete lo que va a hacer, es registrar los servicios necesarios en el inyector de dependencias si corremos sobre Windows, y no hacer nada en el resto de los casos.

Con esto, ya tenemos nuestro servicio en .Net Core 3 listo para instalarlo en cualquier máquina, independientemente del sistema operativo que utilicemos. Si quieres probarlo tú mismo, he dejado el código en GitHub para que puedas salsearlo sin problemas.

**La entrada Worker Service: Cómo crear un servicio .Net Core 3 multiplataforma se publicó primero en Fixed Buffer.**

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 374

octubre 07, 2019 06:15

Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros


Publicado en: www.variablenotfound.com.

» Leer más, comentarios, etc...

Blog Bitix

Guía de inicio del gestor de terminales y sesiones tmux

octubre 04, 2019 04:00

Las personas que usan de forma intensiva la terminal seguramente usando un mutiplexador de terminales como tmux su trabajo es facilitado. Tmux permite dividir una terminal en paneles, ventanas independiente y sesiones. Usando sus múltiples combinaciones de teclas se divide una terminal o una ventana de forma horizontal y vertical en paneles del tamaño que se desee pudiendo de esta forma visualizar al mismo tiempo varias terminales ubicadas en cada panel. También se puede crear una configuración para iniciar tmux con la misma disposición de paneles, ventanas y sesiones.

GNU
Linux

Las terminales gráficas como GNOME Terminal y KDE Konsole soportan pestañas e incluso desde un entorno gráfico en GNU/Linux están disponibles según la distribución varias terminales de texto accesibles con la combinación de teclas Ctrl+Alt+F3 y Ctrl+Alt+F4, con Ctrl+Alt+F2 se puede retornar a la interfaz gráfica. Sin embargo, ninguna de estas opciones permite dividir la misma terminal en varias ventanas o paneles para realizar operaciones y ver los resultados al mismo tiempo. Por otro lado cuando realizamos una sesión SSH y esta finaliza o termina abruptamente por un fallo en la conexión los procesos que se hayan iniciado desde ella son terminados lo que es especialmente grave si se está realizando una operación importante que puede ocasionar problemas.

Tmux es un multiplexador de terminales con soporte para iniciar sesiones. Con tmux en una misma terminal o sesión SSH es posible dividirla en varios paneles y ventanas. También permite iniciar sesiones y salir de ellas sin que los procesos que están corriendo sean terminados lo que permite iniciar una sesión por ejemplo en el trabajo, dejarla suspendida y luego continuarla desde otro equipo, ubicación o ser iniciada por una persona y continuada por otra.

Sesión de tmux en la terminal de GNOME

Tmux al ser un programa de la terminal todas sus opciones se realizan con el teclado, y no son pocas las combinaciones de teclas de su cheatsheet o chuleta. Algunas opciones básicas necesario conocer con son:

  • Dividir una terminal en paneles verticales y horizontales, Ctrl-b “, Ctrl-b %.
  • Cambiar entre paneles, Ctrl-b q 0..9.
  • Cambiar tamaño de un panel, Ctrl-b Up, Ctrl-b Down, Ctrl-b Left, Ctrl-b Right. Una panel se maximiza y minimiza con Ctrl-b z.
  • Cerrar un panel, Ctrl-b x.
  • Cerrar una sesión Ctrl-b :, kill-session.
  • Crear, moverse a otra ventana y cerrar una ventana, Ctrl-b c, Ctrl-b 0..9, Ctrl-b ,.
  • Hacer scroll en las ventanas, Ctrl-b [.

Para facilitar un poco su uso y poder cambiar entre paneles y hacer scroll si se usa en un entorno gráfico se pueden habilitar las funciones del ratón. Basta editar el archivo de configuración ~/.tmux.conf o introducir la opción con Ctrl-b :. En un entorno gráfico habilitar el soporte para el ratón cambia el comportamiento de copiar y pegar, para seleccionar texto hay que hacer uso de la tecla Shift a la vez que se selecciona el texto con el botón izquierdo del ratón.

1
set-option -g mouse on

Para automatizar la configuración inicial de tmux soporta un archivo para personalizarlo a través de un script con comandos. Así por ejemplo si siempre se desea una misma configuración de paneles y ventanas con la misma disposición es posible realizarlo con un script como el siguiente.

1
2
3
4
5
6
#!/usr/bin/env bash
tmux new-session -s "Session" -d
tmux set-option -g mouse on
tmux split-window -h
tmux split-window -v
tmux attach-session -t "Session"

En el manpage de tmux y los enlaces de referencia hay guías con una lista más completa que las operaciones básicas que incluyo en este artículo.

» Leer más, comentarios, etc...

Bitácora de Javier Gutiérrez Chamorro (Guti)

La Edad de Oro del software español

octubre 04, 2019 10:25

Hubo una década, que durante diez años, entre 1982 y 1992, España se convirtió en el segundo desarrollador de sofrware a nivel mundial, precedido solamente por el Reino Unido. En ambos países, aquello resultó ser una sorpresa imprevista, puesto que durante esos años, la tecnología, tanto de hardware como de software estaba en manos de …

La Edad de Oro del software español Leer más »

Artículo publicado originalmente en Bitácora de Javier Gutiérrez Chamorro (Guti)

La entrada La Edad de Oro del software español aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

» Leer más, comentarios, etc...

Variable not found

Novedades en la compilación de vistas en ASP.NET Core 3.0, ¡otra vez!

octubre 01, 2019 07:06

ASP.NET Core MVCLa compilación de vistas y páginas Razor es una de esas features de ASP.NET Core que ha ido dando tumbos y evolucionando a lo largo de las distintas versiones del framework, algunas veces por necesidades técnicas y otras por la búsqueda del funcionamiento más correcto. De hecho, a lo largo de la historia de este blog creo que debe haber pocas cosas de las que haya hablado en tantas ocasiones porque, además, es una característica que me encanta.

Bueno, la cuestión es que en ASP.NET Core 3.0 ha vuelto a cambiar, y esperemos que sea por última vez ;)

Veamos en qué han consistido estos cambios.

Primero: las cosas que no cambian

En ASP.NET Core 3.0, las vistas siguen compilándose cuando deben hacerse estas cosas: en tiempo de compilación. Esto se refleja claramente en la carpeta de binarios, donde, tras compilar, veremos un ensamblado denominado <NombreProyecto>.Views.dll acompañado del correspondiente archivo de símbolos .pdb:

Vistas compiladas en la carpeta de binarios

Además, si examinamos el ensamblado para ver su contenido, podemos observar que en su interior hay clases para cada una de las vistas del proyecto (en este caso, se trata de un proyecto MVC recién creado):

Contenido del archivo Views.dll

Fijaos que no hay nada de Razor ahí; el compilador ha generado una clase para cada vista, y todo lo relativo a su renderizado está implementado en el método ExecuteAsync(). En la captura anterior se puede ver la implementación de uno de esos métodos, y cómo se va generando desde ahí el HTML que se envía al lado cliente.

¿Y qué implica esto? Pues en principio, que para que cualquier cambio en una vista sea tenido en cuenta debemos recompilar el proyecto. Si ejecutamos el proyecto sin depuración o usando dotnet watch run esto no supone ningún problema porque éstas se recompilarán automáticamente cuando sean modificadas, pero es estamos depurando la aplicación sí nos veremos obligados a detener la ejecución y volver a lanzarla.

Otra derivada de la compilación de vistas es que en tiempo de ejecución no es necesario disponer de los archivos .cshtml de las carpetas /Views o /Pages del proyecto, pues todo lo que había en ellas ha sido compilado. Por esta razón, el contenido de dichas carpetas no es incluido por defecto ni en la carpeta de binarios ni al publicar el proyecto.

Obviamente esto tiene sus ventajas, bastante interesantes:
  • Podremos conocer en tiempo de desarrollo si las vistas contienen errores de cualquier tipo, algo que es muy de agradecer ;)
     
  • El paquete de publicación tendrá menos artefactos y, por tanto, podrá la aplicación podrá ser desplegada más rápidamente.
     
  • Dado que las vistas ya están precompiladas, el acceso a las mismas será más rápido desde el primer momento, pues no tienen que volver a pasar por el proceso de compilación.
A cambio, perdemos la interesante posibilidad de realizar pequeños retoques en el código de marcado de una vista o página sin necesidad de compilar y desplegar el proyecto completo.

Novedades: ¿cómo habilitamos la compilación de vistas en runtime?

Con ASP.NET Core 3, esta capacidad es un opt-in, una característica que podemos incluir opcionalmente en nuestras aplicaciones. Para hacerlo, lo primero es añadir el paquete NuGet Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation a nuestro proyecto, y, tras ello, insertar el siguiente código en la configuración de servicios:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews()
.AddRazorRuntimeCompilation();
}
Nota: esto también vale si usamos otros sabores del registro de servicios, como AddRazorPages() o AddMvc().
El mero hecho de introducir estas modificaciones en el proyecto ya nos proporcionará ventajas inmediatas, pues podremos modificar las vistas o páginas al vuelo, incluso mientras estamos depurando la aplicación, y podremos ver de forma inmediata los cambios.

Como ya comentamos la última vez que hablamos del tema, esto nos da lo mejor de los dos mundos: inicialmente partimos con la velocidad de ejecución y ventajas de precompilar vistas en tiempo de desarrollo, sin perder la posibilidad de modificarlas en caliente.

Sin embargo, si publicamos el proyecto veremos que las carpetas /Views o /Pages siguen sin incluirse en la carpeta de resultados.

Incluir las vistas y páginas al publicar

Para conseguirlo, sólo tenemos que abrir el archivo .csproj del proyecto e insertar un elemento CopyRazorGenerateFilesToPublishDirectory establecido a true, como se aprecia en el siguiente bloque de código:
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<CopyRazorGenerateFilesToPublishDirectory>
true
</CopyRazorGenerateFilesToPublishDirectory>
</PropertyGroup>

<ItemGroup>
<PackageReference
Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
Version="3.0.0" />
</ItemGroup>

</Project>
Publicado en: www.variablenotfound.com.

» Leer más, comentarios, etc...

Picando Código

Humble Book Bundle: ebooks de Linux & UNIX por O’Reilly

septiembre 30, 2019 09:00

Humble Bundle tiene un nuevo paquete de e-books sobre Linux, Unix y varias herramientas muy útiles del entorno. Los ebooks están disponibles en PDF, ePUB y MOBI, por lo que pueden ser leídos en casi cualquier dispositivo. Como se acostumbra en los paquetes Humble Bundle, además de elegir el precio, podemos elegir dónde destinamos el dinero que pagamos, incluyendo una organización de beneficencia.

Humble Book Bundle: Linux & Unix por O'Reilly

Tengo el “Mastering Regular Expressions” que compré hace años. Me sirvió mucho en su momento para ampliar mi conocimiento y uso de expresiones regulares. Tengo idea que varios libros más del paquete o compré o leí por ahí. Están todos sumamente interesanes y creo que me voy a comprar el paquete para tenerlos en formato digital portátil. Son herramientas que uso seguido y siempre estoy atento a aprender más.

Pagando USD 1 o más, obtenemos:
Classic Shell Scripting, Linux Device Drivers, Introducing Regular Expressions, grep Pocket Reference, Learning GNU Emacs y Unix Power Tools.

Por USD 8 o más, todos los anteriors y:
Learning the bash shell, Learning the vi and Vim Editors, Linux in a Nuthsell y sed & awk.

Por último por USD 15, todo lo anterior más:
bash Cookbook, Linux System Programming, Mastering Regular Expressions, Effective awk Programming y Linux Pocket Guide.

Comprar el paquete de libros

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 373

septiembre 30, 2019 06:10

Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin / Cross-platform

Otros

Publicado en: www.variablenotfound.com.

» Leer más, comentarios, etc...

Blog Bitix

Novedades de Java 13

septiembre 27, 2019 02:50

Java

Continuando las mejoras incrementales cada seis meses el 17 de septiembre se publico Java 13. Java 13 incorpora algunas nuevas características interesantes que mejoran un facilitan la lectura del código, entre las más destacadas están los bloques de texto y las expresiones switch mejoradas.

Casi coincidiendo con la publicación de Java 13 se publicado [Jakarta EE][jakarta] 8 que únicamente tiene como novedad que su propiedad ha pasado a estar baja la fundación Eclipse, es totalmente compatible con Java EE 8 y sus últimas mejoras, las novedades vendrán en versiones posteriores de Jakarta EE en las que se dará importancia a la tendencia de las aplicaciones para su funcionamiento en entornos orientados a la nube. Casi al mismo tiempo se ha publicado JavaFX 13 ya fuera del JDK en onde puede seguir su propio ciclo de publicaciones independiente del JDK.

Bloques de texto

Para definir una cadena de caracteres que tuviese varias lineas en Java había que emplear concatenación de cadenas, si esa cadena contiene el caracter comilla doble de inicio de cadena había que escaparlo, si esa cadena contenía saltos de línea había que emplear el caracter de escape de salto de línea \n. El resultado es una cadena con problemas de legibilidad por los caracteres de escape que incluye en el código fuente del lenguaje. Esto podría se al definir una cadena de texto que tuviese elementos HTML o JSON.

1
2
3
4
5
String html = "<html>\n" +
" <body>\n" +
" <p class=\"text\">Hello, Escapes</p>\n" +
" </body>\n" +
"</html>\n";

Con los bloques de texto se emplean una triple comilla doble para la apertura y cierre de la cadena.

1
2
3
4
5
6
String html = """
 <html>
 <body>
 <p class="text">Hello, Text Blocks</p>
 </body>
 </html>""";

Como ayuda a las cadenas de texto en la clase String se han añadido varios métodos para eliminar la indentación (String::stripIndent), traducir los caracteres secuencia de escape (String::translateEscapes) y formatear una cadena usando un método de instancia (String::formatted).

Expresiones switch mejoradas

En las novedades de Java 12 se añadió la posibilidad de los switch fueran expresiones que retornan un valor en vez de sentencias y se evita el uso de la palabra reservada break.

1
2
3
4
5
6
String numericString = switch(integer) {
case 0 -> "zero";
case 1, 3, 5, 7, 9 -> "odd";
case 2, 4, 6, 8, 10 -> "even";
default -> "N/A";
};

En Java 13 en vez únicamente el valor a retornar se permite crear bloques de sentencias para cada rama case y retornar el valor con la palabra reservada yield. En los bloques de sentencias puede haber algún cálculo más complejo que directamente retornar el valor deseado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
String numericString = switch(integer) {
case 0 -> {
String value = calculateZero();
yield value;
} ;
case 1, 3, 5, 7, 9 -> {
String value = calculateOdd();
yield value;
};
case 2, 4, 6, 8, 10 -> {
String value = calculateEven();
yield value;
};
default -> {
String value = calculateDefault();
yield value;
};
};

Otras características

Las las otras tres características destacadas Dynamic CDS Archives, ZGC: Uncommit Unused Memory para la mejora del recolector de basura y Reimplement the Legacy Socket API reescribiendo el código para los sockets en lenguaje Java son cambios internos que afectan a la plataforma Java pero no al lenguaje.

» Leer más, comentarios, etc...

Coding Potions

Introducción a VueJS ≫ Qué es y sus características

septiembre 27, 2019 12:00

Introducción

Bienvenido al primer capítulo de una serie de artículos que voy a escribir sobre VueJS. Mi principal finalidad de esta serie es que aprendas a usar VueJS de manera profesional. Voy a intentar enseñarte todos los consejos y funcionalidades de Vue que me hubiera gustado que me enseñaran cuando yo lo estaba aprendiendo.

Si no tienes conocimientos previos de Vue no tengas miedo porque te voy a explicar cómo funciona todo desde el principio. Lo que si que recomiendo es que tengas conocimientos sobre Javascript, HTML y CSS ya que es lo que usa Vue por debajo y lo vas a necesitar.

Pero antes de empezar manos a la obra a programar, hay que ver qué es y para que sirve Vue, cómo se instala y para qué sirve su cli y la estructura de archivos que se crea.

¿Qué es VueJS?

Logo de Vue

Vue JS como su nombre indica es un framework javascript, es decir, es un conjunto de herramientas y funciones que permiten desarrollar páginas web de una manera más cómoda. Vue nace con la necesidad de no tener que escribir tanto código javascript y sobre todo con la idea de ahorrar tiempo al programador.

Vue fue creado por Evan You, ex-trabajador de Google, que decidió crear su propio framework en el año 2014. Desde entonces, Vue ha subido muchísimo de popularidad, gracias a su sencillez y a todo lo que puede ofrecer, que lo vamos a ver a continuación.

¿Para qué sirve VueJS?

Respuesta corta: Para crear páginas web completas.

Respuesta larga: VueJS es una librería javascript pensada para tener un framework con el que desarrollar páginas web. Con Vue puedes crear todas las vistas de tu página web, puedes hacerlas dinámicas, puedes conectarla a un servidor para tener datos dinámicos de una base de datos, etc.

Con Vue puedes hacer desde páginas básicas a cosas más complejas. En ocasiones se compara Vue con JQuery, pero Vue más allá. JQuery está pensado para ahorrar código javascript pero no para hacer páginas web completas (se pueden hacer pero tienes que invertir mucho tiempo). Con Vue ya no vas a necesitar Jquery y tampoco vas a necesitar otras librerías javascript.

En definitiva, Vue es un framework completo pensado para los programadores web, con buena curva de aprendizaje y que se puede usar en todo tipo de webs.

Características de Vue

Vue ofrece todo un conjunto de características y funcionalidades que permiten crear aplicaciones web completas. Si vienes de Angular o React muchas de las cosas que ofrece ya te sonarán, debido a que este framework está inspirado en estos dos.

Como es un framework, va más allá de simplemente ofrecer funciones y utilidades para Javascript. Es una nueva forma de programar páginas web. Pero no te preocupes porque con una buena base de Javascript la curva de aprendizaje no es muy grande.

Si tienes dudas sobre si merece la pena usar Angular o React o VueJS, más abajo voy a hacer una pequeña comparación entre ellos. Antes vamos a ver lo que puede ofrecer.

Modularidad

Lo primero que salta a la vista de Vue es que es completamente modular. A diferencia de Angular que está pensando para ofrecerte todo lo necesario, en Vue tienes más libertad para usar ciertas características. Por ejemplo en Angular si quieres realizar llamadas HTTP puedes usar su propio paquete dentro de Angular. En Vue si quieres realizar estas llamadas tienes que instalar por tu cuenta el paquete que prefieras, axios por ejemplo.

Es decir, mientras que otros frameworks javascript te dan todo lo que necesitas, Vue ofrece lo básico para que puedas elegir si instalar a posteriori las utilidades que necesites.

Reactividad

Vue tiene propiedades reactivas, eso quiere decir que si cambia una variable en una parte de la vista de la página, Vue actualizará su nuevo valor sin necesidad de que lo hagas manualmente. El ejemplo típico es un contador. Si lo quieres hacer en Javascript puro, tienes que actualizar el valor en la vista cada vez que incrementas el contador. En Vue basta incrementar el contador para que se actualice en la página el nuevo valor.

Para casos mucho más complejos que éste, te aseguro que vas a agradecer que Vue sea reactivo.

Componentes web

Logo componentes web

Vue se basa en componentes web. Un componente web es una parte de una web que puede ser reutilizada y que normalmente tiene estilos y funcionalidad aislada.

Si no los conocías ya seguramente te sorprendas al saber que ese concepto ya lo has utilizado si has programado páginas web. Cuando creas una etiqueta html, por ejemplo

Los componentes web básicamente, permiten crear tus propias etiquetas HTML personalizables, es decir, imagina que necesitas crear un calendario y que lo vas a usar en varias vistas de la web. Creando un calendario en forma de componente web, puedes crear calendarios simplemente creando llamando a la etiqueta que tu mismo definas para el HTML, por ejemplo: .

Los componentes web los puedes crear con javascript sin necesitar Vue, pero este framework nos va a facilitar mucho la vida y nos va a ahorrar mucho tiempo.

Virtual DOM

Si hay que hacer un cambio en la vista, en lugar de sustituir directamente los nuevos valores en la vista, Vue creará una especie de réplica del DOM, es decir, de los elementos de la página web para que a la hora de hacer cambios en la vista se hagan de forma más óptima.

Eventos y transiciones

Puedes reaccionar a eventos que se producen en el DOM, por ejemplo cuando el usuario hace click en un elemento, cuando lo mueve, cuando escribe, etc.

Otra de las cosas interesantes de Vue es su sistema de transiciones y animaciones. Es muy sencillo de usar y a la vez puede llegar a ser muy complejo. Las animaciones son las que ya conoces de CSS por lo que no tendrás que aprender sistemas nuevos.

Mixins

Los mixins son funciones y lógica de los componentes que puedes reutilizar y reusar en otros componentes web. Con los mixins puedes compartir cualquier clase de opción que le puedes pasar a los componentes.

Lifecicle (ciclo de vida) de los componentes

Como también pasa en Angular y en React, tienes control sobre todo el ciclo de vida de los componentes, es decir, puedes controlar lo que ocurre antes de que se cargue el componente, lo que pasa justo al cargarse o al destruirse. Esto es útil por ejemplo cuendo queremos que pasen ciertas cosas cuando el usuario entra en una página (por ejemplo llamar a una API REST para cargar los datos)

Aplicaciones SPA gracias a Vue Router

Vue tiene un paquete oficial para poder tener un sistema de rutas. El sistema de rutas llamado vue router, permite tener una página web SPA, es decir, todas las páginas están ya cargadas cuando el usuario entra en la página web de tal forma que cambiar de página es instantáneo. Este sistema no es único de Vue, también lo tiene Angular y React.

Vue vs React vs Angular. ¿Cuál elegir?

Lo primero, podemos comparar el tamaño de todos los frameworks (en el año 2019). Este dato no es muy comparable, ya que Angular ofrece un framework completo, y en el caso de Vue y React, vas a necesitar más librerías si quieres hacer más cosas.

  • Angular: 500+ KB
  • React: 100 KB
  • Vue: 80 KB

En cuanto a la curva de aprendizaje, en mi opinión, Angular es el más difícil de aprender. Con Angular, necesitas aprender Typescript e inyección de dependencias, que, aunque no es muy difícil, añade cierta complejidad en su aprendizaje.

React es más fácil de aprender pero su sintaxis hace que pueda resultar algo lioso para ciertas personas.

Vue en mi opinión, es el más sencillo de aprender, su sintaxis no resulta compleja y tiene una curva de aprendizaje muy asequible.

Angular y React cuentan con el apoyo de una gran compañía. Google en el caso de Angular y React en el caso de Facebook. VueJS no tiene apoyo de grandes compañías, solo de la comunidad, pero si que hay empresas que han desvelado que utilizan Vue como framework en proyectos importantes (Apple, Nike, etc).

Veamos ahora las ventajas de cada uno de ellos en cuanto a lo que puede ofrecer:

Ventajas de Angular:

Logo de Angular

  • Typescript. Aunque al principio cueste más al tener que aprender su sintaxis, al final hace que se tengan menos errores en aplicaciones grandes al poder usar tipado e interfaces.
  • Framework completo. A posteriori no vas a tener que instalar nada nuevo. Viene con todo para crear aplicaciones web completas.
  • MCV. Modelo vista controlador que permite tener los datos separados de la lógica y de su representación
  • Inyección de dependencias. Permite testear mejor los componentes ya que puedes crear mocks de las dependencias. Además permite modularizar mejor el código y abstraerse de los detalles de implementación de las dependencias.
  • Arquitectura muy bien pensada para proyectos grandes. Todo está bien separado y organizado. Esto en proyectos pequeños puede resultar una desventaja porque es más lioso y necesitas más archivos.
  • Servicios. Es una funcionalidad que trae Angular para poder abstraerse de las llamadas a la adquisición de los datos. Puedes tener las llamadas a una API, por ejemplo, en archivos separados que puedes inyectar en los componentes.

Ventajas de React:

Logo de React

  • Tiene una comunidad detrás muy importante. Si tienes algún problema seguramente haciendo una búsqueda en google llegues a solucionarlo ya que a otro programador le habrá pasado lo mismo que a ti.
  • A diferencia de Angular, React no viene con todo un set de utilidades ya creadas. Esto permite que sea mucho más flexible ya que puedes usar o implementar lo que necesites sin necesidad de usar lo que te dan. Esta ventaja también la ofrece Vue.
  • React native. Con esta librería vas a poder crear aplicaciones móviles nativas con React de forma que sin tener que cambiar mucho, puedes crear una web y una aplicación móvil.
  • Si te gusta programar en Javascript con React te vas a sentir bastante cómodo. Aunque Vue también se usa con Javascript, React utiliza javascript para el html y los estilos.

Ventajas de Vue:

Logo de Vue

  • Curva de aprendizaje. En mi opinión y en la de muchos programadores, tardas menos tiempo en aprender los básico para poder desenvolverte con el framework.
  • Arquitectura limpia. Por como está hecho Vue, el código de los componentes queda mucho más ordenado y limpio.
  • Archivos .vue. A diferencia de React con sus archivos jsx, en los archivos vue puedes escribir html y css sin tener que hacerlo dentro de javascript. Está todo perfectamente separado.
  • Comunidad en crecimiento. Aunque Vue no tiene una comunidad tan grande como React y Angular, su comunidad ha tenido un crecimiento espectacular en los últimos tiempos y se según las encuestas va a ir a más.

Yo personalmente pienso que Angular está más enfocado a aplicaciones web grandes, con una estructura muy compleja. Vue y React son más parecidos, la sintaxis de React no me acaba de convencer y si tengo que escoger un framework me quedaría con Vue.

Cómo instalar Vue. Hello world

Bien, si ya te has decidido a utilizar Vue, lo primero es ver cómo se puede crear un proyecto con este framework javascript. Se puede hacer de varias formas:

Con Vue CLI

La opción que yo siempre suelo usar. Vue CLi es una herramienta para línea de comandos que sirve para gestionar proyectos Vue. Para usarla puedes descargarla en tu equipo desde su paquete NPM:

npm install -g @vue/cli

Para que el vue cli se encarge de crear toda la estructura inicial del proyecto ejecuta:

vue create nombre-de-tu-proyecto

Cuando ejecutas ese comando, la terminal te preguntará si quieres las opciones por defecto o quieres personalizarlo

Cómo crear un proyecto con Vue CLI

Si no sabes qué elegir le puedes dar a la opción default, no te preocupes porque todo se puede añadir al proyecto después de haber sido creado. En cuanto le des a esta opción se creará el proyecto y no tendrás que hacer nada más. Las opciones que voy a comentar ahora son por si seleccionas la opción manual.

Si decides manualmente seleccionar las opciones que prefieres, se abrirá otra pantalla en la que podrás instalar algunos paquetes básicos (yo suelo seleccionar vuex para gestionar estado, vue router para poder crear rutas en la web y css preprocessors porque me gusta usar sass). Puedes seleccionar los que quieras a tu gusto con la tecla espacio.

Qué opciones tiene Vue CLI

En la siguiente pantalla aparecerá que tipo de configuración quieres para el eslint, es decir, para el linter que analiza el código en busca de errores. Yo suelo escoger prettier. Luego te saldrá si quieres ejecutar el eslint cada vez que guardas y cada vez que haces commit. Yo recomiendo poner las dos opciones para evitar errores en el código.Lint on sa

La siguiente pantalla te dice si quieres la configuración en el package.json o en archivos dedicados. Yo recomiendo en archivos dedicados para tener todo separado en su lugar.

Yo para esta serie de artículos voy a escoger estas opciones para generar el proyecto de Vue:

  • Babel, Router, CSS Pre-processors, Linter / Formatter
  • History mode: yes. Si pones que no lo que va a hacer Vue es añadir al final de cada ruta un hash (#) para que el navegador no recargue la página al navegar entre ellas
  • Sass / Scss with dart-sass. A mi me gusta sass. Uso dart-sass porque a veces node-sass da problemas.
  • EsLint + Prettier. Es la opción que más me gusta para el linter
  • Lint on save y lint and fix on commit. Muchas veces me ha salvado de subir código con errores
  • Dedicated config files. Más fácil de mantener.

Por último te preguntará si quieres guardar estas opciones para crear proyectos en el futuro y se creará el proyecto.

Importando la librería de Vue

La otra forma de hacerlo, ideal cuando estamos haciendo algo simple o queremos prototipar rápido, consiste en usar directamente el javascript compilado de Vue de forma local o mediante CDN:

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

Importando la librería de Vue ya tienes acceso a la variable global de Vue. Aquí te dejo un ejemplo de un hello world con vue con este método:

https://jsfiddle.net/chrisvfritz/50wL7mdz/

Mediante codesanbox o similares

Existen en Internet páginas gratuitas como codesanbox que permite crear proyectos de Vue. Cuando lo creas, te abre un editor de código online con vista previa por si no quieres instalar nada y quieres hacer pruebas en la nube.

https://codesandbox.io/

Vue CLI. El asistente de línea de comandos de Vue

Vue CLI es una librería que permite usar comandos en la consola del ordenador para automatizar ciertas tareas. Este CLI es muy parecido al que tiene Angular o el que tiene React, es muy recomendable su uso en el día a día para ahorrar tiempo.

Si todavía no has instalado vue cli te vuelvo a dejar el comando:

npm install -g @vue/cli

Si al ejecutar uno de los comandos el asistente te dice que tienes que instalar un addon, ejecuta:

npm install -g @vue/cli-service-global

Veamos los comandos y todo lo que puede ofrecer vue cli:

Serve. Desarrollo en local

vue serve

Sirve para ejecutar la página en local para que puedas ver los cambios mientras desarrollas. Lo bueno de este comando es que tiene hot reloading es decir, cuando haces un cambio en uno de los archivos de vue (excepto en los de configuración globales), se actualiza la página sin necesidad de recargar.

Otra forma de ejecutar este comando, si has creado el proyecto con vue create es mediante el script que se crea en el package.json. Es decir:

npm run serve

Si usas el primer comando lo tienes que hacer dentro de la carpeta src del proyecto y si usas el segundo comando lo tienes que hacer en la carpeta en la que esté el package.json.

Una vez ejecutado el comando, y cuando haya cargado, si abres el navegador en la página http://localhost:8080 podrás ver la página que estás desarrollando. Lo tienes que dejar ejecutándose meintras desarrollas para ver los cambios.

Build. Compilación de tu aplicación web

vue build

El comando build sirve para compilar los archivos para ponerlos en producción, es decir, sirve para poder desplegar vue en un servidor.

Este comando generará todos los archivos javascript compilados y minificados para que los usuarios finales puedan acceder a la página que estás desarrollando. Para ello necesitas un hosting en el que poder usar apache o nginx.

Como el comando anterior, este comando también lo tienes disponible en el package.json.

npm run build

Este comando si que recomiendo tirarlo desde npm porque en el servidor en el que vayas a desplegar la página lo más normal es que tengas npm, así no tienes que instalar el paquete de vue cli.

Vue UI. Interfaz gráfica para administrar proyectos Vue

vue ui

Este comando sirve para ejecutar una interfaz gráfica para poder administrar los proyectos de Vue. Si no te gusta mucho andar con comandos,puedes usar esta interfaz para trabajar de manera más cómoda.

Con esta interfaz puedes crear proyectos de Vue como con el vue create, puedes administrar los que ya tienes, ejecutar desde ahí los proyectos y compilarlos y instalar de forma más cómoda dependencias.

Interfaz gráfica de Vue UI

Añadir plugins con Vue CLI

Si después de haber creado un proyecto con Vue decides instalar una librería que no habías puesto, con este comando vas a poder hacerlo sin tener que configurar nada, por ejemplo:

vue add router

O por ejemplo:

vue add @vue/cli-plugin-eslint

Lo bueno de este comando es que ya te configura los archivos que tenías para añadir la configuración de los nuevos plugins. Si estos mismos paquetes los instalas mediante npm, vas a tener que añadir manualmente su configuración en cada archivo.

Herramientas recomendadas para programar con Vue

Vue tiene un tipo de archivos específico, los .vue y por lo tanto cuando los abras en cualquier IDE o programa no te va a pintar de colores la sintaxis como en otros lenguajes, por lo tanto necesitas instalar plugins en el IDE o editor de texto que utilices.

Editor de texto recomendado para Vue

El editor que yo siempre recomiendo para trabajar con Vue es el VSCode. No solo lo uso para programar en Vue si no que también lo uso para cualquier lenguaje para el frontend, incluso para python.

Te dejo su página web por si te lo quieres descargar. Por cierto, es gratuito y open source.

https://code.visualstudio.com/

Para VSCode existe un plugin ideal para Vue, llamado Vetur. Instalando este plugin vas a tener todo lo necesario para usar Vue en vscode. Este plugin va a hacer que tengas la sintaxis de colores, te va ayudar con el lint y formateado de archivos, tiene autocompletado, snippets, etc.

Para instalarlo puedes buscarlo en la sección Extensions (el último icono del menú de la izquierda).

Vetur, la mejor extensión de Vue CLI

Además, te recomiendo que crees un archivos llamado .editorconfig en la raíz del proyecto con estas opciones:

root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

Este fichero lo que hace es decirle al editor, en este caso al vscode que las tabulaciones sean de dos espacios para cuando creemos los archivos de vue.

Para que funcione te tienes que descargar esta extensión para que el vscode lea el archivo:

https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig

Otros plugins para trabajar con Vue

Conclusiones

Vue, en mi opinión, es uno de los mejores frameworks para el frontend del panorama actual. Es simple, se aprende rápido su estructura es limpia y su comunidad va en aumento.

Con lo que hemos visto hoy deberías tener una idea básica de qué es Vue y como crear la estructura de tu primer proyecto con Vue.

Si te sientes perdido es normal, nos pasa a todos al principio. Te recomiendo que sigas los próximos capítulos de esta serie sobre Vue. Próximamente veremos cómo empezar a programar en Vue y cómo se organiza un proyecto Vue.

» Leer más, comentarios, etc...

Variable not found

Nuevo curso de ASP.NET Core 3 MVC en CampusMVP

septiembre 25, 2019 12:10

CURSO DE ASP.NET Core 3 MVC

Seguramente estáis al tanto de que Microsoft acaba de anunciar la disponibilidad de .NET Core 3.0 y tecnologías relacionadas, incluyendo ASP.NET Core 3.0.

Pues bien, me complace anunciaros que, sólo un día más tarde, desde CampusMVP hemos lanzado el nuevo curso Desarrollo Web con ASP.NET Core 3 MVC.

Se trata de una  gran revisión del curso de desarrollo con ASP.NET Core MVC que ha formado ya con éxito a cientos de desarrolladores de todo el mundo, en la que hemos introducido los cambios y novedades que han venido de la mano de la nueva versión del framework.

En este post intentaremos responder a las siguientes preguntas:

¿En qué consiste el curso de ASP.NET Core 3 MVC?

Este curso se imparte completamente online utilizando la prestigiosa plataforma SELF y siguiendo la contrastada metodología de CampusMVP para asegurar tu éxito a lo largo el proceso de formación.

Aprende ASP.NET Core conmigo en CampusMVP Sin horarios y a tu propio ritmo, pero no estarás solo: contarás con todo el soporte del equipo de CampusMVP y, dado que soy el tutor, me tendrás a tu disposición para la resolución de dudas y ayudarte durante aprendizaje.

La dedicación estimada ronda las 7 u 8 horas semanales, durante un total de 12 semanas. A lo largo de este tiempo estudiarás el framework ASP.NET Core 3 desde sus bases, recorriendo los más de 200 temas que componen el temario y que podrás descargar en formato PDF (más de 600 páginas) al finalizar el curso, para tenerlo como referencia.

Pero el curso no sólo consiste en contenido teórico: a lo largo del mismo encontrarás numerosos ejercicios y prácticas que te ayudarán a conseguir una mejor asimilación de los conceptos, así como consejos, trucos y buenas prácticas que seguro te resultarán de utilidad cuando vayas a aplicar tus nuevos conocimientos.

Esta vez, además, he contado con la inestimable colaboración del amigo Jorge Turrado, Microsoft MVP, desarrollador en Plain Concepts, colaborador en Variable not found y CampusMVP y crack donde los haya, para la realización de los vídeos. Varias horas de grabaciones en las que podrás ver en vivo el funcionamiento de muchas de las características que estudiamos en el curso.

¿Y cómo saber tu nivel de aprovechamiento? Sencillo. Conforme vayas avanzando te propondremos autoevaluaciones que te permitirán conocer tu grado de conocimiento sobre los contenidos.
Al finalizar el curso podrás acreditar su realización mediante un diploma, así como incluirlo en tu perfil certificado de CampusMVP, un perfil online verificable por terceros donde puedes demostrar qué has aprendido con nosotros.

¿Cuáles son los contenidos del curso?

El curso realiza un recorrido completo por ASP.NET Core MVC partiendo desde cero. Tras una breve bienvenida, empezamos presentando ASP.NET Core, describiendo su estructura, arquitectura y principios básicos de funcionamiento, y pasaremos rápidamente a la acción.

Veremos cómo se crean y configuran estos proyectos, y cómo utilizar su estructura modular para añadir componentes que aportarán funcionalidades a nuestras aplicaciones.

Revisaremos muchas características que esta infraestructura proporciona a los frameworks de mayor abstracción como MVC: routing, logging, caching, estado de sesión, settings de aplicación, archivos estáticos, autenticación, autorización, privacidad, I18N, CORS, health status, etc.

Tras ello, nos tomaremos un pequeño respiro para presentar conceptualmente ASP.NET Core MVC, pero volveremos rápidamente al frente de batalla haciendo una pequeña incursión en el desarrollo con este framework. El objetivo en este punto es proporcionar una visión de alto nivel del funcionamiento de este tipo de aplicaciones que, sin entrar en demasiados detalles, nos permitan comprender sus principales “piezas” (modelo, vistas, controladores) y la forma de trabajar con ellas.

A continuación, recorreremos sucesivamente las capas Modelo, Controlador y Vista, detallando al máximo cómo trabajar con las herramientas que nos proporciona el framework MVC para la creación de aplicaciones web. Estudiaremos en profundidad aspectos como el sistema de routing, binders, validaciones, Razor, helpers HTML, tag helpers, view components, buenas prácticas, uso de patrones…

BlogMachineCoreTambién tendremos tiempo para profundizar en el desarrollo de servicios o APIs HTTP/REST, consumibles tanto desde aplicaciones web vía Ajax como desde sistemas externos, utilizando para ello las nuevas y potentes características de negociación de contenidos, binding selectivo, el soporte de problem details o las convenciones para controladores API.

Seguidamente nos centraremos en otros aspectos, como el uso de áreas, la creación de tests unitarios y de integración, o la internacionalización de aplicaciones. También nos detendremos en Razor Pages, un enfoque alternativo que podemos utilizar a la hora de desarrollar sitios web.

Por último, presentaremos BlogMachineCore, una aplicación de ejemplo en la que podrás ver implementadas muchas características vistas en el curso: arquitectura desacoplada, inyección de dependencias, uso de DTOs, autenticación y autorización, áreas, asincronía, URL amigables, tag helpers, Ajax, páginas de error personalizadas, etc.

En definitiva, se trata de un completo temario en el que hemos intentado no dejar nada por detrás. El objetivo es que al finalizar el curso estés en disposición de utilizar ASP.NET Core MVC en tus proyectos profesionales y dar el salto definitivo a las tecnologías “Core”.

Para saber más, puedes ver la ficha completa del curso en la web de CampusMVP.

¿Qué conocimientos previos necesito para seguir el curso?

Requisitos del cursoObviamente, al tratarse de un curso sobre una tecnología web, lo primero que necesitarás conocer, al menos a un nivel básico, es HTML, CSS y Javascript.

También es importante comprender las bases del funcionamiento de las aplicaciones web, es decir, saber identificar cliente y servidor, entender las responsabilidades de cada uno de estos extremos y conocer mínimamente los mecanismos de comunicación entre ellos, básicamente el protocolo HTTP. Si has trabajado antes con alguna tecnología de desarrollo para la web (ASP, ASP.NET Web Forms, MVC, PHP, Express…), probablemente ya conozcas todo lo necesario de estos aspectos.

También debes tener un cierto nivel de programación con .NET y C#. Por ejemplo, en el curso no vamos a explicar conceptos básicos como qué es una clase o una interfaz, ni otros aspectos del lenguaje como expresiones lambda, métodos extensores, tipos anulables, o tipos genéricos; se supone que todo eso debes conocerlo ya. Tampoco explicaremos tipos básicos, como List<T> o StringBuilder, son piezas del framework con las que ya debes haber trabajado antes.

Aunque no es absolutamente imprescindible para completar el curso, sí que es totalmente recomendable conocer tecnologías de acceso a datos, pues para construir aplicaciones web que jueguen con datos seguro que vas a necesitarlas. A lo largo del temario veremos algunos ejemplos de uso de Entity Framework Core, pero no profundizaremos en ellos al escapar del objetivo del curso.

Por último, indicar que el curso comienza de cero en lo relativo al framework ASP.NET Core y MVC, por lo que en ningún momento se asume que tienes conocimientos en versiones anteriores de ASP.NET, ASP.NET Core u otras tecnologías concretas de desarrollo de aplicaciones web. Sin embargo, si las conoces tendrás algo de ventaja porque podrás "mapear" mentalmente algunos conceptos al nuevo framework y te costará mucho menos trabajo aprenderlos.

¿Es este curso para mi?

A priori, si cumples los requisitos citados en el punto anterior, te diría que sí. Pero con matices ;)

Si ya has hecho con nosotros el curso de ASP.NET Core 2, seguramente no te valdrá la pena. Aunque hay algunos cambios relevantes entre estas versiones, la mayoría de aspectos son coincidentes y podrás encontrar en Internet información y guías de migración suficientes como para poder dar el salto por tu cuenta.

Si estás trabajando o has trabajado con otras tecnologías para la web fuera del entorno Microsoft (PHP, Java etc.), pero conoces .NET y C#, en este curso encontrarás un magnífico aliado para acompañarte durante tu salto a ASP.NET Core, partiendo desde cero. Eso sí, aprovecharás los conceptos que ya conoces sobre programación web, y, al finalizarlo, dominarás todo lo que necesitas saber sobre esta tecnología.

Por otra parte, si ya conoces algo de ASP.NET Core pero lo has aprendido “de oídas” o de forma desestructurada, seguro que el curso te resultará muy interesante y provechoso porque te ofrecerá una visión ordenada y profunda de esta tecnología.

Y si vienes de trabajar con frameworks basados en versiones de ASP.NET iguales o anteriores a 4.x, como Web Forms o ASP.NET MVC 5 o anteriores, este curso te encantará.

Como seguro sabrás, ASP.NET Core no es la siguiente versión del framework ASP.NET. Se trata de un reboot en toda regla de la tecnología, que de hecho empezó nuevo desde su versión 1.0 con la intención de convertirse en el mejor framework para el desarrollo de aplicaciones y servicios web, aportando importantes características, algunas de ellas impensables hace sólo unos meses en la pila de tecnologías de Microsoft, como el ser multiplataforma, alto rendimiento, escalabilidad, orientación a la nube, libertad de herramientas de desarrollo, etc.
La oleada de tecnologías "Core" es probablemente el cambio más drástico que hemos sufrido los desarrolladores ASP.NET desde sus inicios, allá por el año 2002.
Por tanto, si vienes de trabajar con ASP.NET sobre estos frameworks anteriores a ASP.NET Core, para saltar a ASP.NET Core tendrás que olvidar muchas de las cosas que ya sabes y aprender a manejar la nueva infraestructura, que ha cambiado radicalmente. Una vez teniendo controlados los cimientos, ya podrás pasar a aprender tecnologías con un nivel de abstracción superior, como el proporcionado por el nuevo framework MVC.

En MVC, a primera vista parece que han cambiado menos cosas, puesto que conceptualmente siguen manteniéndose aspectos que ya se han demostrado válidos en las versiones anteriores del framework. Seguiremos teniendo componentes como controladores, acciones, binding o filtros y continuaremos usando sintaxis Razor para escribir las vistas, pero la práctica totalidad de características ha sufrido cambios.

Aparte, hay novedades muy interesantes como view components o tag helpers, el nuevo enfoque para desarrollar APIs HTTP, o las derivadas de la adopción de ASP.NET Core, como el uso de variables de sesión, inyección de dependencias, la autorización o internacionalización, por citar sólo algunas.

Todos estos cambios son los que hacen que este curso sea especialmente interesante, puesto que te permitirá aprender todo lo necesario para dominar primero la nueva plataforma ASP.NET Core, y luego el framework MVC, de forma estructurada y partiendo desde cero.

Por tanto, resumiendo:
Situación de partidaEste curso es para tiComentarios
He hecho el curso de ASP.NET Core 2 en CampusMVPNo necesitas un curso de ASP.NET Core 3. Las novedades no son tantas.
He aprendido ASP.NET Core por mi cuentaAprenderás muchísimo con el curso. No es lo mismo aprender de oído que seguir un temario completo, ordenado y práctico.
Trabajo o he trabajado con ASP.NET Web FormsDisfrutarás aprendiendo a trabajar con un nuevo framework y una nueva forma de organizar y estructurar tus aplicaciones.
Trabajo o he trabajado con ASP.NET MVC<=5Seguro que te encantará, porque aprenderás a manejar el nuevo framework aprovechando conocimientos que ya tienes.
Conozco C# y .NET y trabajo o he trabajado en la web con otras tecnologíasAprenderás, partiendo desde cero, a manejar con solvencia la nueva infraestructura ASP.NET Core y a programar aplicaciones MVC.

Pero, ¿realmente es ASP.NET Core el futuro de la programación web en entornos Microsoft?

Sin duda. Ya desde Microsoft se pronunciaron oficialmente al respecto hace unos meses, en el post ".NET Core is the Future of .NET" de Scott Hunter, uno de los peces gordos de .NET en Redmond.
Citando palabras textuales:
... all new .NET applications should be based on .NET Core. The primary application types from .NET Framework are supported, and where we did not port something over there is a recommended modern replacement. All future investment in .NET will be in .NET Core. This includes: Runtime, JIT, AOT, GC, BCL (Base Class Library), C#, VB.NET, F#, ASP.NET, Entity Framework, ML.NET, WinForms, WPF and Xamarin.
Es decir, centrándonos en desarrollo para la web, la recomendación oficial es que todos los nuevos proyectos los comencemos usando ASP.NET Core. El framework "clásico" seguirá estando ahí, soportado oficialmente, pero no se va a invertir en él más allá del mero mantenimiento (corrección de bugs, parches de seguridad y similares); de hecho, .NET Framework 4.8 es la última versión que aparecerá de esta tecnología.

Otra prueba de cómo ASP.NET Core ha ido tomando protagonismo con el tiempo es echar un vistazo a las tendencias de búsqueda en Google. El siguiente gráfico, obtenido de Google Trends, da una idea del interés despertado por el nuevo framework y su comparación con otros "sabores" de ASP.NET:

ASP.NET Core trends
Ojo, que si por cualquier motivo debes aprender ASP.NET MVC 5, recuerda que en CampusMVP también tenemos un curso apropiado para tí ;) Pero recuerda que sólo una parte de los conocimientos que adquieras serán válidos cuando saltes a ASP.NET Core MVC más adelante.

Me convence, ¿cuándo empezamos?

Pues cuando tú quieras :) Sólo tienes que visitar la web de CampusMVP, inscribirte, y casi sobre la marcha te facilitarán las credenciales de acceso a la plataforma.
Recuerda que si trabajas para una empresa española este curso podrías hacerlo prácticamente sin coste, gracias a la Formación Bonificada.

¡Eso es todo, amigos!

Bueno, pues creo que con esto quedarán despejadas todas vuestras dudas sobre el curso, o al menos muchas de ellas. Si no es así, no dudéis en contactar con CampusMVP, donde seguro os atenderán de maravilla, o conmigo a través de un comentario, correo electrónico o usando el formulario de contacto del blog.

¡Espero veros a muchos en el curso!

Publicado en: www.variablenotfound.com.

» Leer más, comentarios, etc...

proyectos Ágiles

¿Para qué Agile?

septiembre 24, 2019 08:45

[See this article in English here]

En mi vida profesional ha habido siempre dos lemas importantes: (1) cuál es el “para qué” de lo que se hace y (2) la gente ha de estar “bien” (porque si las personas no están suficientemente motivadas no se puede hacer bien el para qué y, en el peor de los casos, la gente marcha). Consiguientemente, el objetivo de mi trabajo ha sido ayudar a empresas a ser más “Ágiles”, y así todos contentos (ellas y yo). Sin embargo, en los últimos años notaba que algo no acababa de encajar: ¿cuál es el impacto real del “para qué”?

En los últimos decenios todo ha ido cambiando a un mundo cada vez más acelerado, más inmediato, de reacción instantánea… ¿Es esto una sociedad más Ágil?

¿Somos conscientes de lo que estamos “transformando”, de cómo lo que hacemos influye en los comportamientos de las personas? Cada vez la humanidad parece más cortoplacista, impulsiva, con menor capacidad de reflexión. Me da la sensación de que estamos amplificado nuestro instinto animal de depredar al máximo rápidamente, como si no se supiese qué va a pasar en unas horas, como si no hubiese un mañana. Todo es más frío, menos cálido, menos… humano. Eso sin contar con el impacto en las personas a las que sometemos a ser “extensiones de maquinaria” en la cadena productiva, desde la propia producción hasta la entrega en la puerta de nuestra casa, todo tiene que ser para conseguir lo que sea de manera inmediata, con el mínimo esfuerzo… creando también una cultura que ya no valora las cosas ni el esfuerzo para conseguirlas, sin crear interés en lo que realmente “cuestan” de verdad, no sólo a nivel personal sino en global.

A las personas que trabajamos en agilidad organizativa nos gusta pensar de manera sistémica, holística, trabajando la cadena de valor de las compañías. Sin embargo, en estos últimos meses, no deja de aparecer cada vez más información sobre las “entradas” y “salidas” completas de la sociedad en que vivimos (todas ellas MUY relacionadas): calentamiento global, superpoblación, incencios gigantescos (Amazonas, Siberia, Indonesia, …), falta de recursos naturales, tensiones geoestratégicas, despilfarro (mentalidad de “usar y tirar” que hace que muchos bienes acaben rápidamente en vertederos), comer menos carne (ONU), océanos esquilmados y llenos de plástico, …

Entonces, ¿para qué Agile? ¿Para comernos el planeta cinco veces más rápido, cubriéndolo de desperdicios y reduciendo a millones de personas a extensiones de maquinaria?

¿Qué daño/dolor estamos infligiendo ahora mismo y para el futuro? ¿Qué tipo de inestabilidades van a venir a nivel global? ¿De verdad que como especie y sociedad no podemos ir más allá y hacer cosas más trascendentes, que impliquen progreso pero sin dejarlo todo destrozado para futuras generaciones (y destrozándolas a ellas en el futuro!!)? A mí no me gustaría que dentro de unos años mis hijas o su descendencia dijesen que mi generación, que tuvo los datos en la mano, fue la mayor cómplice y miró hacia un lado.

Creo que todos los sistemas tienden a un equilibrio, mucho más abajo, duro y diferente si todo se hizo de manera insostenible. Por ello, es crucial intentar gestionar ese equilibrio… o él te gestionará a ti (de manera abrupta y mucho más dolorosa, como fue hace unos años la crisis financiera-inmobiliaria que todavía sufrimos).

 “Free fall through our midnight / This epilogue of our own fable” (…) “Drifting through this boundlessness / This madness of our own making” (…) “Sound the reveille / To be or not to be / Rise / Stay the grand finale / Stay the reading of our swan song and epilogue

No alt text provided for this image

 En la conferencia anual de Agile Spain del año pasado estuve conversando al respecto con una de las Keynotes, Lyssa Adkins. Me comentó que había bastante gente del mundo Agile que, como yo, era consciente de esa disonancia: trabajamos para que las empresas aceleren el nivel de consumo de sus productos pero eso puede tener un impacto global no positivo. Me quedé más tranquilo (“así pues, no soy demasiado raro”) pero con poco más que una constatación.

En los principios del Agile Manifesto se habla del desarrollo a un paso sostenible y de la motivación de la gente, es decir, cuando se escribió un aspecto importante era no quemar a las personas. Creo que hay que ampliar ese concepto de sostenibilidad y hablar de un Agile sostenible que también considere todos los byproducts de las empresas, con una visión más holística: no “quemar” a las personas y tampoco a la sociedad y el planeta.

Ahora es el momento de aprovechar la Agilidad para hacer un cambio de ciclo, porque necesitamos que sea rápido y utilizar todo nuestro conocimiento para darle la vuelta.

En mi caso, esto ha implicado reconsiderar un principio que hasta ahora se habían quedado en lo más personal y subirlo al nivel profesional: mi lema adicional (3) va a ser trabajar para que, allí donde yo esté, el propósito de la empresa sea sostenible, para que su modelo de negocio sea rentable dejando un balance positivo en el global (empleados, sociedad y ecosistema). Crear/comprar bienes que duren y que sean reciclables para que el sistema sea auto-sostenible (reduciendo así los “pulls” al planeta), aumentar la dignidad de los trabajos de las personas, crear consciencia, educar e intentar cambiar el mindset que nos ha llevado hasta aquí.

Y esto va de todos nosotros, podemos hacer muchas cosas. Si has llegado a leer hasta aquí, es probable que esto también sea importante para ti, seguro que hay alguna cosa que tú puedes hacer, aunque sea pequeña, para este balance en positivo que necesita crear la humanidad 🙂

“One drive to stay alive / It’s elementary / Muster every fiber / Mobilize / Stay alive”

[See this article in English here]

» Leer más, comentarios, etc...

Fixed Buffer

Como medir el rendimiento de nuestro código

septiembre 24, 2019 08:00

La imagen muestra un medidor de velocidad para el entrada "Como medir el rendimiento de nuestro código"

A raíz de las entradas sobre la serie de entradas sobre la reflexión que publicamos antes del parón de verano, he estado escribiéndome con un lector sobre algunas posibles optimizaciones en el código, todas ellas midiendo el rendimiento del código para ver cuál era mejor. Llevaba tiempo queriendo escribir sobre este tema, ¿y que mejor momento qué ahora? 🙂

¿Cómo se mide el rendimiento del código?

Para conseguir datos que nos sirvan para esto, se utilizan pruebas de rendimiento o «benchmarks», los cuales nos van a servir para obtener las métricas que vamos a comparar (tiempo, cpu consumida, ram utilizada…) para decidir si nuestro código tiene el rendimiento esperado. Normalmente, esto se consigue midiendo los datos a comprobar y ejecutando el código un número suficiente de veces para asegurar que los posibles «ruidos externos» no afectan a las métricas.

Imagina que simplemente medimos el tiempo de ejecución de método ejecutándolo solo una vez, cualquier cosa que el sistema operativo ejecute podría falsear los resultados…

En el ecosistema .Net, existe una librería que se distribuye a través de NuGet que nos facilita enormemente esta labor, y es de la que os voy a hablar ahora, esta librería es BenchmarkDotNet, Vamos a ponernos en faena:

Como usar BenchmarkDotNet

Vamos a imaginar que dentro de nuestro código tenemos algo como esto:

public class OperacionesMatematicas
{
    public double Suma(double a, double b)
    {
        return a + b;
    }

    public double Multiplicacion(double a, double b)
    {
        return a + b;
    }

    public double Potencia(double @base, double exponente)
    {
        return Math.Pow(@base, exponente);
    }

    public double Potencia2(double @base, double exponente)
    {
        if (exponente == 0)
            return 1;

        var resultado = @base;
        for (int i = 1; i < exponente; i++)
        {
            resultado = resultado * @base;
        }
        return resultado;
    }
}

Simplemente es una clase que va a hacer ciertas operaciones matemáticas, teniendo además dos maneras de calcular una potencia, utilizando Math.Pow y multiplicando la base por si misma tantas veces como indica el exponente (lo que es una potencia vamos…).

Lo primero que vamos a necesitar para medir el rendimiento de nuestro código, es crear un proyecto de consola que será el que tenga el código para las pruebas, en este caso, lo voy a llamar «BenchmarkRunnerProject». A este proyecto le vamos a añadir el paquete «BenchmarkDotNet«, y vamos a crear una clase donde vamos a añadir la lógica de la prueba:

public class OperacionesMatematicasBenchmark
{
    [Benchmark]
    public void Suma()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Suma(10, 20);
    }

    [Benchmark]
    public void Multiplicacion()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Multiplicacion(10, 20);
    }

    [Benchmark]
    public void Potencia()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Potencia(2, 2);
    }

    [Benchmark]
    public void Potencia2()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Potencia2(2, 2);
    }
}

Por último, solo nos queda añadir al método Main la ejecución de las pruebas:

class Program
{
    static void Main(string[] args)
    {
        var summary = BenchmarkRunner.Run<OperacionesMatematicasBenchmark>();
        Console.Read();
    }
}

Una vez hecho esto, ya solo necesitamos ejecutar el proyecto para que nuestra prueba funcione. Pero ojo, tiene que estar en «Release» para poder medir el rendimiento del código con las optimizaciones del compilador. En caso contrario, nos mostrará un mensaje indicándonos que lo hagamos o desactivemos que tenga que ser Release:

La imagen muestra la salida de la consola cuando ejecutamos un benchamrk sin estar en release

Una vez que se ejecute, nos mostrará los resultados en la propia consola:

La imagen muestra un ejemplo de la salida básica

Con esto, ya tenemos la funcionalidad básica, donde solo medimos el tiempo de ejecución con los parámetros que hemos puesto «hardcoded». Pero tenemos la opción de indicar diferentes parámetros con el atributo «Params»:

public class OperacionesMatematicasBenchmark
{
    [Params(2, 3)]
    public int A { get; set; }

    [Params(2, 200)]
    public int B { get; set; }

    [Benchmark]
    public void Suma()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Suma(A, B);
    }

    [Benchmark]
    public void Multiplicacion()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Multiplicacion(A, B);
    }

    [Benchmark]
    public void Potencia()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Potencia(A, B);
    }

    [Benchmark]
    public void Potencia2()
    {
        var operaciones = new OperacionesMatematicas();
        operaciones.Potencia2(A, B);
    }
}

Con este cambio, vamos a conseguir que se ejecute una prueba con cada una de las configuraciones:

La imagen muestra los resultados de la ejecución son parametros

E incluso ordenarlas si añadimos el atributo «RankColumn» a la clase:

La imagen muestra el resultado con el atributo rankcolum

Existen muchísimas opciones y parametrizaciones que pueden servirte para configurar cada uno de los aspectos del benchmark, e incluso comparando la ejecución en diferentes entornos (.Net Framework, .Net Core, Mono) y diferentes versiones de los entornos. Te recomiendo que le eches un ojo a la documentación para ver todas las opciones disponibles, ya que, es imposible hablar de todas ellas en una única entrada. (Por ejemplo, para medir la RAM con Diagnosers).

Como siempre, dejo el enlace al repositorio en GitHub con el código de la entrada.

**La entrada Como medir el rendimiento de nuestro código se publicó primero en Fixed Buffer.**

» Leer más, comentarios, etc...

Variable not found

¡ASP.NET Core 3.0 ya disponible!

septiembre 24, 2019 06:55

ASP.NET Core 3Como seguro sabréis, hace pocas horas se ha lanzado, en el marco del evento .NET Conf 2019, una nueva oleada de actualizaciones de las principales tecnologías y frameworks "Core":
  • .NET Core 3.0
  • C# 8
  • ASP.NET Core 3.0
  • Blazor server-side
  • Entity Framework Core 3.0
  • Entity Framework 6.3 (sí, ¡compatible con .NET Core!)
  • SignalR 3.0
  • ML.NET
  • Soporte WinForms y WPF para .NET Core 3
  • Visual Studio 2019 16.3
En lo relativo a ASP.NET Core no es que haya sido una auténtica revolución pero, aún así, ASP.NET Core 3.0 trae novedades que vale la pena conocer:
  • Simplificación del archivo de proyecto .csproj
  • Uso del host genérico
  • Introducción del endpoint routing
  • Mayor modularidad en el registro de servicios de MVC
  • Nuevo serializador/deserializador JSON (bye bye, JSON.NET!)
  • Compatibilidad exclusivamente con .NET Core (bye bye, target .NET Framework!)
  • Limpieza de Microsoft.AspNetCore.App
  • Cambios en la compilación de vistas
  • Soporte para gRPC
  • Y, por supuesto, muchas otras mejoras...
Si os interesa conocer más, he publicado en el blog de CampusMVP un artículo detallando estas novedades:

       Novedades de ASP.NET Core 3.0

¡No os lo perdáis!

Publicado en: www.variablenotfound.com.

» Leer más, comentarios, etc...

Fixed Buffer

¡¡.Net Core 3 ya esta disponible!!

septiembre 23, 2019 09:10

La imagen  muestra el nuevo layout de funciones de .Net Core 3

¡¡El ansiado día ha llegado!!. Por fin esta disponible para descarga pública la versión final de .Net Core 3 y de su mano .Net Standard 2.1 y C# 8.0. Puedes seguir el evento en directo aquí.

Durante las próximas semanas hablaremos sobre las muchas novedades que trae para hacer más fácil el cambio (formularios, índices, enumeraciones asíncronas…).

¡¡Se deparan unas semanas apasionantes descubriendo las mejoras que nos trae esta nueva versión del .Net!!

**La entrada ¡¡.Net Core 3 ya esta disponible!! se publicó primero en Fixed Buffer.**

» Leer más, comentarios, etc...

Blog Bitix

Librería editor de markdown JavaScript y procesador de markdown para generar HTML con Java

septiembre 20, 2019 01:00

JavaScript
Java

Algunas aplicaciones permiten escribir contenido para posteriormente mostrarse en una página web. Permitir introducir directamente en texto en formato HTML es peligroso ya que puede causar problemas si no es correcto y ha de validarse para no permitir introducir archivos CSS, archivos JavaScript u otras etiquetas que supongan un problema de seguridad o desmaqueten la página web. Una alternativa es utilizar como entrada texto en formato markdown y posteriormente transformarlo a contenido en formato HTML.

Markdown es un formato de texto simple con una sintaxis que permite introducir títulos, negritas, itálica, listas y listas numeradas, enlaces o imágenes. El texto en formato markdown se puede transformar posteriormente a formato HTML. Hay múltiples librerías de JavaScript para crear un editor markdown con algunos botones para introducir las opciones básicas e incluso previsualizar el contenido.

Como editor JavaScript para markdown de las varias opciones que he encontrado la que más me ha gustado es Editor.md por sus numerosas opciones, documentación y ejemplos, aunque no tiene una versión reciente. Posee barra de herramientas para realizar opciones básicas de edición, previsualizador de contenido HTML, colapsador de secciones, manejadores de eventos, subir imágenes, internacionalización, personalizar la barra de herramientas como está descrito en su sección de ejemplos. En la página de Editor.md en GitHub están documentadas las opciones de configuración.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<html>
<head>
<link rel="stylesheet" href="resources/css/editormd.css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script type="text/javascript" src="resources/js/editormd.min.js"></script>
<script type="text/javascript">
$(function() {
var editor = editormd("test-editor", {
// width : "100%",
 // height : "100%",
 path : "resources/lib/"
});
});
</script>
</head>
<body>
<div id="test-editor">
<textarea style="display:none;">### Editor.md
**Editor.md**: The open source embeddable online markdown editor, based on CodeMirror & jQuery & Marked.
</textarea>
</div>
</body>
</html>
Editor JavaScript de markdown

Una vez que se obtiene el texto en formato markdown en algún momento al visualizarlo como parte del código fuente en una página web hay que transformarlo a formato HTML, para esto en Java hay varias librerías algunas ya obsoletas, antiguas y sin mantenimiento. De las que su desarrollo sigue activa una es Flexmark Java.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.vladsch.flexmark.samples;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.util.data.MutableDataSet;
public class BasicSample {
public static void main(String[] args) {
MutableDataSet options = new MutableDataSet();
// uncomment to set optional extensions
 //options.set(Parser.EXTENSIONS, Arrays.asList(TablesExtension.create(), StrikethroughExtension.create()));

// uncomment to convert soft-breaks to hard breaks
 //options.set(HtmlRenderer.SOFT_BREAK, "<br />\n");

Parser parser = Parser.builder(options).build();
HtmlRenderer renderer = HtmlRenderer.builder(options).build();
// You can re-use parser and renderer instances
 Node document = parser.parse("This is *Sparta*");
String html = renderer.render(document); // "<p>This is <em>Sparta</em></p>\n"
 System.out.println(html);
}
}
1
2
3
dependencies {
implementation "com.vladsch.flexmark:flexmark-all:0.50.40"
}

» Leer más, comentarios, etc...

Picando Código

Primer DLC de Horizon Chase Turbo: Summer Vibes – ya disponible

septiembre 19, 2019 12:30

Hace poco les contaba sobre Horizon Chase Turbo, el juego de carreras de autos inspirado en los grandes hits de los 80’s y 90’s: Out Run, Lotus Turbo Challenge, Top Gear (SNES), Rush, entre otros

Desde ayer está disponible el primer DLC: Summer Vibes, para Nintendo Switch, XBOX One, Steam y PlayStation 4. En este paquete de contenido descargable obtendremos:

  • 1 descapotable exclusivo, ¡homenaje al clásico Out Run!Horizon Chase Turbo
  • 5 apariencias únicas y desbloqueables: Al terminar una carrera al menos en tercer lugar, el jugador garantiza el desbloqueo de la siguiente apariencia. Cada una de las 6 tiene una historia interesante que contar y te hará recordar alguna referencia. Los personajes son: Dos detectives de Miami, dos “valientes amigas que cambiaron su pasado por la carretera”, “una pareja moderna, orgullosa y libre”, “una pareja de fugitivas en un auto naranja” y “un trío que decidió tomarse unas vacaciones y disfrutar de la vida” (¡Save Ferris!).
  • 12 pistas rediseñadas basadas en la campaña principal.
  • Todas las pistas tienen una tabla de clasificación.

En Nintendo Switch, el DLC cuesta USD 1.99 y ya se puede descargar de la eShop. Lo he estado jugando y está bastante bueno. Las pistas son bien veraniegas, perfecto para estos días que el viento está empezando a soplar más frío por el hemisferio norte, y del verano va quedando sólo el recuerdo. Y debo mencionar la música de Barry Leitch que acompaña de forma excelente.

Todavía no terminé la campaña “World Tour”, pero me vengo divirtiendo bastante. Y tengo por desbloquear todavía más autos, actualizaciones y pistas. ¡Hay contenido para un buen rato!

Horizon Chase Turbo: Summer Vibes

 

Horizon Chase Turbo: Summer Vibes

 

Horizon Chase Turbo: Summer Vibes

 

Les dejo el video del DLC:

YouTube Video

Para más información, visita www.horizonchaseturbo.com, y:

  • Únete a la comunidad de Horizon Chase Turbo en Discord.
  • Recursos de prensa para ​Horizon Chase Turbo​ aquí.
  • Horizon Chase Turbo en Facebook
  • Sigue a Horizon Chase Turbo en Twitter
  • Sigue a Horizon Chase Turbo en Instagram.

» Leer más, comentarios, etc...

Arragonán

Domain-Driven Design “in a Shot”

septiembre 17, 2019 12:00

Como parte de mi trabajo en Zara.com una de las cuestiones sobre la que trabajé con mis equipos fue en introducir conceptos de Domain-Driven Design, acompañado del estilo de arquitectura de Ports & Adapters (o Clean/Hexagonal Architecture). Había algunos productos que estábamos arrancando a los que se les presuponía que iban a tener una complejidad de negocio que iba a crecer, además tenían bastante incertidumbre inicialmente y se esperaba que su evolución perdurase en el tiempo al menos un puñado de años.

Empecé a intentar redactar de forma muy condensada un documento con los conceptos relacionados con DDD, por tratar de aligerar nuestras conversaciones sin necesidad de leerse los típicos libros azul, rojo o verde; que además suelen resultar durillos o incluso confusos.

Y aunque finalmente terminamos trabajando en los equipos practicando DDD y Ports & Adapters, no fui capaz de terminar con este documento. El día a día no me permitió dedicarle el tiempo necesario, así que aprovechando ese borrador he ido dedicando ratos posteriormente para terminar de aterrizarlo y servir como complemento a Diseño incremental de software a partir de las interacciones.

Foto de unos machacados, chupito especialidad de un garito de Zaragoza

Introducción

Domain-Driven Design (en adelante DDD) o diseño dirigido por dominio son un conjunto de prácticas que tratan de facilitar el desarrollo de software con un dominio complejo.

DDD se divide en artefactos a nivel estrátegico y táctico. El estratégico podríamos decir que se enfoca más al largo plazo y a lo funcional/dominio: especificaciones, documentación, algunas cuestiones de arquitectura de alto nivel… Mientras que el táctico se enfoca en el diseño más cercano a la implementación, a través de varios patrones y buenas prácticas.

Hay que tener en cuenta que DDD a nivel táctico consta de bastantes tipos de artefactos y que no es necesario utilizarlos todos de golpe y siempre, pero sí creo que es interesante conocerlos para poder sacarles partido en momentos dados.

En mi experiencia DDD casa muy bien tanto con las ideas de arquitectura de Ports & Adapters (más conocida como Hexagonal o Clean) para separar dominio/infraestructura/mecanismo de entrega, como con la práctica de TDD junto a prácticas de Specification by Example/ATDD.

TDD y Specification by Example/ATDD son prácticas más que recomendables. Nos ayudan a tener foco y a facilitar que emerga el diseño poco a poco a través de los flujos autosimilares de Red, Green, Refactor y Specify, Develop, Deploy.

Está fuera del ámbito de este documento la explicación en detalle tanto de estas prácticas como de Ports & Adapters.

Strategic Design

Dentro de los artefactos de Strategic Design se hace énfasis en dividir un problema grande en diferentes subdominios, con contextos delimitados o Bounded Contexts para hacerlo más manejable. Evidentemente, es habitual que distintos subdominios se relacionen entre sí usando distintos patrones de integración.

En cada contexto se establece un Ubiquitous Language basado en su subdominio para evitar equívocos entre cualquier miembro del equipo o stakeholders que participan en su desarrollo, todas las personas involucradas deberían utilizar las mismas palabras para referirse a los mismos conceptos de negocio.

El significado del concepto Product o Purchase en una gran empresa de retail puede tener docenas según el contexto en el que se usa. Pero dentro de un Bounded Context un concepto debe ser canónico, debe tener un único nombre y ese nombre un único significado.

Así que debemos tratar de utilizar un nombrado uniforme en todos los artefactos (código de producción, documentación, tests…) e incluso no está de más tener un glosario de términos como referencia de ese lenguaje ubicuo.

Para facilitar el entender cómo se relacionan los diferentes subdominos podemos visibilizarlo a través de un Context Map. Los context maps nos ayudan a ver qué subdominios existen, cómo se relacionan entre ellos organizativamente y los patrones de integración que hay.

Para quien quiera profundizar en esto, hay diferentes libros, charlas o artículos que entran en mucho más detalle. Por ejemplo: Strategic Domain Driven Design with Context Mapping.

Tactical Design

Los artefactos de Tactical Design son un conjunto de patrones que nos facilitan implementar en código el modelo de dominio dentro de un Bounded Context. Estos patrones pueden tener diferentes implementaciones, estar más o menos desacopladas de frameworks y librerías, etc.

Los modelos

Al modelar dentro de un subdominio encontramos conceptos que no se deben separar nunca, deben formar parte de la misma transacción siempre, estos conceptos son los Aggregates. Estos a su vez están compuestos de una o varias Entities y posiblemente de algunos Value Objects. Siempre habrá una Entity raíz en el Aggregate por la que se deberá acceder al resto de entities y value objects.

Podemos resumir qué es una Entity como algo que tiene un identificador único que lo distingue, aunque cambien el resto de sus atributos, el identificador jamás cambia. Deberíamos evitar tener entidades anémicas (sólo con getters y setters) tratar de empujar la lógica de negocio en lo posible hacia estos artefactos, siempre que no haya dependencias con colaboradores que no sean otras entities o value objects del aggregate.

Los Value Objects en cambio no tienen identidad y deberían ser inmutables por diseño (crearlo con un new y sólo métodos que consultan estado). Nos sirve para modelar conceptos en clases de dominio evitando tener responsabilidades repartidas por usar siempre tipos primitivos. Cuando hablamos de tipos primitivos incluiríamos también clases tipo String, colecciones estándar, etc.

La aproximación más purista lleva a que los atributos de una entity se modelen como value objets, personalmente prefiero empezar con tipos primitivos y si acaso emergen necesidades ir refactorizando a clases.

Un ejemplo muy simplificado de todo esto podría ser un agregado Invoice, dentro del dominio de una herramienta de facturación como este:

class Invoice {
  InvoiceId id; //Value object para encapsular el tipo primitivo
  Collection<InvoiceLine> lines; //Una lista de entity InvoiceLine
  CustomerId customerId; //Value object encapsulando la referencia a una entidad de otro agregado
  ...
  void addLine(InvoiceLine line){ //Método que modifica el estado de la entidad
  ...
}
class InvoiceId {
  String value; //Valor del tipo primitivo
  ...
  Boolean equals(InvoiceId id){
  ...
}
class InvoiceLine {
  InvoiceLineId id; //Value object para encapsular el tipo primitivo
  String description; //Tipo primitivo
  Money amount; //Value object para encapsular cantidad y divisa
  ...
}
...

La persistencia

Por otro lado, lo normal es que queramos persistencia, para lo que tendremos un Repository por cada Aggregate. Se encargará de esconder los detalles de la tecnología de persistencia y los mapeos que fueran necesarios.

Conceptualmente este patrón debería exponer métodos muy similares a una colección y ocultarnos los detalles de implementación: guardar un elemento, borrarlo, métodos básicos de consulta… aunque también es habitual ver expuestos métodos para queries más complejas tipo findAllByStatus o getByEmail frente al uso de query objects.

Los servicios

Como creo que a otras muchas personas, al ir introduciéndome en DDD me costó ver la distinción entre servicios. El que compartan parte del nombre resulta algo confuso, también ver cómo se refieren a la idea de servicios en documentaciones sobre frameworks y muchos artículos. ¿Qué diferencias hay entre Application Services y Domain Services?

Los Application Services son los puntos de entrada a la aplicación, los que orquestan y exponen el modelo de dominio. Personalmente prefiero referirme a ello como Use Cases para facilitar el explicar y entender su cometido; también los he llamado o visto llamar como Actions o Commands.

Sin entrar en mucho detalle a la hora de implementarlo, ya que hay muchísimas aproximaciones de hacerlo, mi preferencia es una clase por Use Case con un sólo método público expuesto. Siguiendo el ejemplo de una herramienta de facturación podríamos tener unas clases RegisterInvoice, AddLineToInvoice… con un método con nombre tipo run o execute.

Para evitar efectos colaterales, evitaremos tener use cases que se llamen entre ellos. Si aparece lógica común y estamos seguros de que estamos duplicando conceptos, podemos crear un Domain Service para actuar como helper.

Los Domain Services vienen a ser clases que encapsulan reglas de negocio que no tienen cabida para moverlos dentro de entities ni value objects. Suelen emerger porque hay reglas de negocio que involucran dependencias a ports o hay que orquestar varios aggregates diferentes.

Intentaremos que esas clases sean pequeñas y tengan una sola responsabilidad.

Sin ser un concepto original de DDD no quiero dejar mencionar la idea de Infrastructure Services, vi usarlo en algunos sitios y lo incorporé a mi terminología. Son simple y llanamente fachadas o clientes de servicios externos que no forman parte de mi dominio, así que los suelo nombrar como Client estilo SolrClient o GiphyClient.

Los eventos

Un Domain Events es algo significativo a nivel de negocio que ha ocurrido en el dominio que modelamos como una clase, tipo: InvoiceRegistered, ProductPublished, UserConfirmed… que contendrán los detalles de lo que ha ocurrido en el dominio para que sea publicado.

Personalmente suelo utilizarlos sólo al ver que el producto que estoy construyendo, además de complejidad, va a tener muchos side-effects o pueda interesar a otros subdominios: alimentar analítica para un dashboard, actualizar contadores, enviar un email, provocar algún trigger en un sistema externo…

La publicación de los eventos la dejaríamos encapsulada en un publisher, dejando a los subscribers la responsabilidad de comprobar si les interesa o no el evento y qué hacer con ello. Esos artefactos a nivel de infraestructura podrían implementarse con múltiples tecnologías: redis pub/sub, AMQP, kafka… O, mi preferencia para empezar a introducirlo, simplemente un patrón observer manejando todo en memoria.


Quienes conozcan Domain-Driven Design verán que he dejado algunas cosas fuera de este artículo y no he entrado a mucho detalle por tratar de condensar, ya que era algo inicialmente pensado para ayudar a asimilar los conceptos para gente que se inicia y acompañarlo con código de aplicaciones reales.

Con el mismo objetivo, personalmente me parece muy interesante un ejercicio similar que hicieron en video (muuuy rápido) los amigos de CodelyTV: DDD en 20 minutos.

Para profundizar más hay multitud de recursos en forma de charlas, libros, cursos…

Relacionados

» Leer más, comentarios, etc...

Picando Código

[Video] – Programmer Passport: Crystal Language Part 1

septiembre 16, 2019 09:31

Bruce Tate es un escritor conocido por libros como Seven Languages in Seven Weeks, Programming Phoenix, y otros títulos más sobre Java, Ruby y Elixir. Presencié su keynote en Code Elixir LDN 2019 (pueden ver el video acá), y también ahí aprendí sobre grox.io.

Grox.io es una nueva plataforma de aprendizaje orientada a la programación. El objetivo es educar a programadores políglotas, siguiendo la premisa de Siete Lenguajes en Siete Semanas. Pueden visitar el enlace para aprender más e inscribirse al newsletter para enterarse cuando empieza el curso.

Mientras tanto, podemos ir viendo un avance del primer curso. Tras un voto de la comunidad, Crystal fue el lenguaje de programación elegido para empezar:

La filosofía central del Lenguaje de Programación Crystal, desde el principio, es tentadora: rápido como C, estilado como Ruby. Agregar rendimiento como C a un lenguaje como Ruby, gratis, es una meta ambiciosa. Casi cualquier gran lenguaje tiene metas claras como ésta.

Históricamente, Crystal tenía la intención inicial de ser un reemplazo totalmente compatible con Ruby, pero que fuera más seguro con tipos y performante. Es rápido. Crystal le gana a Ruby por 5x en casi todos los casos y hasta 300x en algunos benchmarks. Recientemente, Crystal también hizo un empujón grande para incorporar Paralelismo.

En el video Bruce Tate introduce el lenguaje y escuchamos sobre Nicolás di Tada, el fundador de Manas.Tech, el hogar del lenguaje de programación Crystal (N. del. a.: ¡En Buenos Aires, Argentina!).

El video:
YouTube Video

¡Se viene con todo Crystal!

» Leer más, comentarios, etc...

Picando Código

¡Feliz día del Programador!

septiembre 13, 2019 10:00

¡Feliz día del programador colegas! El día del programador se celebra en el día número 256 (28) del año por ser la cantidad de valores representables en un byte de datos (13/9 en los años comunes y 12/9 años bisiestos). Como es tradición, aprovecho la excusa para hacer un repaso de en qué ando desde el último día del programador.

Feliz día del programador

Hablemos de programación: Ruby sigue siendo mi lenguaje principal. Recientemente he estado muy atento a Crystal: un lenguaje con tipos estáticos inspirado en Ruby. En este post, escribí sobre cómo crear un bot de Telegram con un cliente en Crystal, y también desarrollé un shard para validar cédulas de identidad uruguayas (¿suena conocido?). El código fue prácticamente copiar y pegar de la versión de Ruby, con algunas mínimas modificaciones. Pero quedó funcionando con tests, build en Travis y todo. Pueden ver el código fuente en GitHub. También por acá escribí sobre Gleam, lenguaje nuevo sobre BEAM. Por suerte le he venido escapando a Go. 

Me mantengo interesado en Elixir, este año asistí a Code Elixir London y estuvo genial. Vi muchas buenas charlas y cosas interesantes que está haciendo la gente con Elixir. Phoenix LiveView es un despelote y tengo muchas ganas de probarlo. Ojalá para el próximo día del programador les pueda contar de algún proyecto nuevo que programé en Elixir.

He trabajado en varios proyectos propios. Últimamente le estoy metiendo a gamesdb, una gema Ruby para la API de TheGamesDB. El primer commit fue en 2014, y no había escrito nada al respecto en el blog. Espero publicar el proyecto que la inspiró para poder compartirlo por acá algún día. La aplicación está empezada, y tiene la funcionalidad básica, pero desarrollada en formato “MVP” en muy poco tiempo. Ya teniendo la idea y el prototipo (y la gema que permite importar los datos de TheGamesDB), algún día me sentaré a programarla en serio. Tengo al menos dos proyectos más en mente que están a medio empezar pero que me motiva mucho terminarlos para poder usar y compartirlos.

Cada tanto actualizo mi plugin de WordPress: List Category Posts. Tengo ideas de más cosas para WordPress, pero sinceramente me desmotiva un poco programar PHP. No es que sea tan malo, pero al estar en contacto con el lenguaje y su ambiente sólo a través del desarrollo de un plugin de WordPress, es difícil mantenerme interesado (además que el lenguaje no me resulta particularmente atractivo en comparación a otros). Pero seguiré manteniendo éste plugin y List Categories por ahora, y si en algún momento me inspiro publicaré los demás que tengo en mente.

Spacemacs es todavía mi editor de texto. Me hace la vida más fácil y cada vez me gusta más. Me soluciona muchísimo la vida Org-Mode para gestionar trabajo, notas y demás. Escribí un post al respecto en Spacemacs: entorno integrado eficiente y sofisticado para Emacs. Espero que lo vean y descubran lo geniales que son Emacs y Spacemacs.

En conclusión me he mantenido bastante ocupado en cuanto a programación, por más que de repente me resulte más difícil que antes compartir todo eso por el blog. Pero también sigo leyendo muchos cómics, jugando mucho Nintendo, tomando cerveza y escuchando punk rock. Hay cosas que no cambian tanto 🙂

Ya llevo más de 2 años viviendo en Escocia, a pesar de la amenaza del Brexit y quién sabe qué va a pasar. Pero estoy contento acá, me gusta mucho, he hecho muchos amigos nuevos y recibido visitas de gente de Uruguay y sigo volviendo a visitar el paisito. No estoy trabajando más en Cultivate, o sí. Cultivate fue adquirido por Deliveroo, una de éstas empresas grandes en el espacio conocido como “gig economy”, donde básicamente las empresas se ahorran pagar impuestos (Uber, AirBnb, etc). Es la segunda vez que trabajo en una empresa que es adquirida por otra empresa. Veremos qué tal va ésta vez.

Me estoy empezando a sentir viejo en internet. No entiendo muchos comportamientos en redes sociales y mucha cosa me da vergüenza ajena. Estamos interactuando de maneras nuevas y distintas, y no me convence que sean mejores. No estoy hablando de no entender a la gente más joven, muchas veces se trata de gente de mi edad o mayor, y al verles entrar en esa rosca de obtener likes, clics, manipular información, buscar desesperadamente aprobación virtual, pienso “qué pelotudos”. Pero ignórenme, no es más que el abuelo Simpson gritándole a una nube (ya que estamos, recuerden que “la nube” es la computadora de alguien más). Si les pasa lo mismo, les recomiendo desconectarse más. Los libros son un excelente escape a ese bizarro mundo online.

Escribo bastante irregularmente en el blog. La lista de borradores sin publicar crece cada vez más. Por eso a veces termino publicando posts que de repente no son tan extensos, pero por lo menos me fuerzo a terminar de escribir algo “publicable”. Me gusta escribir, y me encanta interactuar con gente que lee lo que escribo. Pero esto se está haciendo cada vez más raro en internet. Las páginas web personales y blogs van muriendo en esta competición por monetizar toda actividad que uno haga, ya sea con streaming, podcasts, y blogs que van quedando inundándonos con anuncios, pop-ups, subscripción a newsletters…

Pero a su vez me deja contento saber que éste es un rincón en internet donde escribo cosas que quiero escribir, sin seguir tendencias o intentar lograr que hagas clic en un enlace para generar una micro ganancia. Y la poca gente que sigue leyendo es porque tiene algún interés en común o le interesa lo que escribo, así que bienvenidos sean. Me vengo proponiendo escribir y publicar más. Aunque no sea sobre programación, software libre o tecnología, voy a postear sobre temas que me interese y divierta. Espero recibir sus comentarios al respecto.

¿En qué andan quienes quedan del otro lado?

El día del programador otros años: 20072008200920102011201220132014201520172018

» Leer más, comentarios, etc...

Fixed Buffer

¡¡FixedBuffer ha cumplido un año!!

septiembre 11, 2019 08:00

La imagen muestra una tarta de cumpleaños

Ya ha pasado el verano, toca volver a la rutina y al trabajo, y volvemos a la carga con el blog. Esta es una publicación especial, porque hoy hace un año, empezamos esta andadura en FixedBuffer.

Este ultimo año ha sido una experiencia muy gratificante, que además me ha dado la posibilidad de colaborar con gente y aprender de ello. De unos cosas más técnicas, de otros cosas más de estilo… Pero en cualquiera de los casos, conocer a compañeros con los que poder ir a comer y hablar de cualquier cosa.

En este último año, he recibido el MVP por parte de Microsoft en tecnologías de desarrollo. También he tenido la posibilidad de dar alguna charla en comunidades técnicas. La verdad es que creo que ha sido un buen año 🙂

Muchas gracias a todos los que durante este año habéis estado al pie del cañón (que se que sois unos cuantos).

Para este año, tenemos más ideas interesantes que seguir contando, como por ejemplo como montar un Identity Server, o colaboraciones que nos hablaran sobre como montar un proxy inverso con Nginx. 🙂 🙂

Por último, vamos a ver cuáles son el Top 5 de las entradas del año:

  1. Haciendo fácil el acceso a datos con Entity Framework Core (Parte 2)
  2. Haciendo fácil el acceso a datos con Entity Framework Core
  3. Generación de ficheros «Excel» (xlsx) con ClosedXML
  4. ClosedXML, una manera fácil de dar formato a nuestros .xlsx
  5. Cómo crear un servicio Net Core multiplataforma

¡¡Muchas gracias a todos los seguidores de FixedBuffer, que sois los que hacéis que esto valga la pena!!

**La entrada ¡¡FixedBuffer ha cumplido un año!! se publicó primero en Fixed Buffer.**

» Leer más, comentarios, etc...

Picando Código

Datos y Cogollos: Edición especial Datacamp 2019

septiembre 09, 2019 02:30

El próximo jueves 12 de setiembre a partir de las 19:00, sumate a la comunidad de Datos Abiertos uruguaya en DATOS Y COGOLLOS. Se trata de un evento organizado por la comunidad de Datos Abiertos local, así que no le pertenece a ninguna organización en particular, y está más que abierto a su sigan sumando nuevas personas y organizaciones:

Llega la tercera edición de este evento para conocer y dar a conocer lo que se está haciendo con datos abiertos, esta vez como evento paralelo del Datacamp 2019 de AGESIC y con la presencia de invitados internacionales 😎🔝.

Datos y Cogollos: Especial Datacamp 2019

¿Qué es esto?

Es un evento para juntar a toda la comunidad trabajando alrededor (o cerca, o con interés) del tema Datos Abiertos, conocer los proyectos que hay en la vuelta, pero sobretodo conocer a las personas que estamos en eso y compartir una charla acompañada por alguna bebida para hacerlo más informal.

Es un formato que empezó en México en 2013, impulsado por SocialTIC bajo el nombre de “Datos y Mezcales” y que hace bastante rato que teníamos ganas de traer a Uruguay.
Está organizado por la comunidad de Datos Abiertos local, así que no le pertenece a ninguna organización en particular y está más que abierto a que se sigan sumando nuevas personas y organizaciones.

¿Qué va a pasar?

Ésta es la agenda que vamos a intentar seguir:
– Bienvenida y presentación de la iniciativa
– Presentaciones relámpago ⚡ (máx. 5 min.) de proyectos y organizaciones
– Brindis y convivencia (asado, chelas, cogollos, helado de dulce de leche, etc.)

¿Cómo me anoto para presentar mi proyecto?

Comentá en ese Meetup y decinos el nombre de persona que presentaría, un correo de contacto y el nombre del proyecto/organización/presentación que quieren compartir. Vamos a ir anotando la lista de oradores/as acá, donde también podés anotarte directamente si así lo preferís.

Las presentaciones pueden ser con diapositivas/video/apoyo audiovisual y solicitamos que cada persona que presente la suba a la web (ej. Google Slides) y pegue el enlace a su presentación en el documento anterior. Buscamos presentaciones y presentadores/as lo más diversas posibles, empezando por apuntar a la paridad de género, así que por favor no se ofendan si preguntamos si es posible que presenten otras personas llegado el caso. ☺
Acá podés encontrar sobre las presentaciones del Primer Datos y Cogollos.

¿Por qué “cogollos”?

Básicamente porque podemos… El evento adapta su nombre a alguna bebida típica del país y así pasó por México (Datos y Mezcales), El Salvador (Datos y Cervezas), Bolivia (Datos y Singanis), Ecuador (Datos y Bielas), Colombia (Datos y Guaros), Costa Rica (Datos y Chiliguaros), Guatemala (Datos y Tragos) y España (Datos y Cañas).
Cuando le toca a Uruguay, optamos por algo que ninguna de las organizaciones amigas de todos esos países podría poner legalmente (o sea, es un poco un chiste interno).

¿Es obligatorio presentar/saber de datos abiertos/tomar/fumar porro?

No, para nada. Cada uno viene y hace lo que quiere.

Más información e inscripciones

» Leer más, comentarios, etc...

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin