Weblogs Código

Variable not found

Si las shadow properties no existen como propiedades en la entidad, ¿cómo podemos inicializarlas en el seed de Entity Framework Core?

marzo 19, 2019 07:20

Entity Framework Core Vamos con un post rapidito, al hilo de una pregunta que planteaba el amigo Javier  R. vía el formulario de contacto del blog, sobre el artículo donde veíamos las shadow properties de Entity Framework Core, cuya respuesta creo que puede ser interesante para alguien más.

En concreto, la duda le surgía al combinar las capacidades de data seeding de EF con las propiedades ocultas, y básicamente era:
Dado que las shadow properties no existen en la entidad, ¿cómo podemos establecerlas en el momento del seeding de datos?
Bien, aunque no es fácil de descubrir de forma intuitiva, la solución es bastante sencilla. Si nos fijamos en el intellisense del método que utilizamos para el poblado de datos, HasData(), podemos observar varias sobrecargas; por ejemplo, en la siguiente captura se puede ver la información mostrada al invocar este método para la entidad Friend:

Intellisense en HasData()


Fijaos que, aunque estemos hablando de la entidad Friend, HasData() admite la posibilidad de enviarle cualquier tipo de objeto, y ahí es donde está la clave. Podemos enviarle simples objetos anónimos, de los que extraerá el valor para sus propiedades; dado que no existe un tipado específico, podemos introducir en ellos todas las propiedades que nos interesen poblar, incluidas las shadow properties de la entidad:
// Entidad:
public class Friend
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Birthdate { get; set; }
}

// Contexto de datos:
public class FriendsContext : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Friend>()
.Property<DateTime>("UpdatedAt");
builder.Entity<Friend>()
.Property<string>("UpdatedBy")
.HasMaxLength(20);

// Seeding con objetos anónimos:
builder.Entity<Friend>().HasData(
new { Id = 1, Name = "Lisa Smith", Birthdate = new DateTime(1984, 3, 22),
UpdatedAt = DateTime.Now, UpdatedBy = "jmaguilar"
},
new { Id = 2, Name = "Malcolm Wesser", Birthdate = new DateTime(1970, 9, 1),
UpdatedAt = DateTime.Now, UpdatedBy = "jmaguilar"
}
);
}
...
}
Fácil, ¿eh?

Hey, pero... ¿y si no me gustan los objetos anónimos?

Si eres de los que prefieren hacer funambulismo sobre la red de protección que nos proporciona el tipado fuerte con chequeo en compilación, también hay una solución para ti ;)

En este caso, bastaría con crear una clase con los campos que queramos, y enviar instancias a HasData() como si se tratara de objetos anónimos.
public class FriendsContext : DbContext
{
private class SeedFriend
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Birthdate { get; set; }

public DateTime UpdatedAt { get; set; }
public string UpdatedBy { get; set; }
}

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Friend>()
.Property<DateTime>("UpdatedAt");
builder.Entity<Friend>()
.Property<string>("UpdatedBy")
.HasMaxLength(20);

// Seeding con objetos de tipos arbitrarios:
builder.Entity<Friend>().HasData(
new SeedFriend { Id = 1, Name = "Lisa Smith", Birthdate = new DateTime(1984, 3, 22),
UpdatedAt = DateTime.Now, UpdatedBy = "jmaguilar"
},
new SeedFriend { Id = 2, Name = "Malcolm Wesser", Birthdate = new DateTime(1970, 9, 1),
UpdatedAt = DateTime.Now, UpdatedBy = "jmaguilar"
}
);
}
}
Espero que os sea de utilidad :)

Publicado en: www.variablenotfound.com.

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

Koalite

Y tú, ¿qué haces los fines de semana?

marzo 18, 2019 05:42

Últimamente he llegado a varios hilos en twitter sobre la conveniencia o no de que los desarrolladores dediquemos nuestro tiempo libre a actividades relacionadas con el desarrollo de software.

Vaya por delante que, como muy bien decía Modesto San Juan:

Creo que lo de decirle a la gente lo que tiene que hacer o no hacer no tiene mucho sentido.

Pero también me parece interesante esta puntualización de Rafael Casuso:

Creo que tampoco son conscientes de la presión que este bombardeo de actividad frenética IT causa en muchos compañeros. Si en algo podemos ayudar las voces conocidas a quitar esa presión creo que es positivo.

No sé si cuento como voz conocida, pero ya que tengo un blog y escribo cosas en él, me uno al debate.

Llevo 18 años dedicado al desarrollo de software profesionalmente. Siempre me ha gustado y, durante casi todo ese tiempo, he dedicado más o menos parte de mi tiempo libre a aprender sobre cosas relacionadas con el desarrollo.

Durante los últimos 7 años y medio además he estado escribiendo este blog, he sido razonablemente activo en redes sociales, e incluso he asistido a algunos eventos (tampoco muchos). Todo eso me da cierta experiencia en primera persona de lo que supone pertenecer a “la comunidad” del desarrollo.

Sin embargo, como comentaba hace unos días con Miguel Ángel Pastor, desde hace dos años le dedico mucho menos tiempo. Ahora mismo prefiero dedicar más parte de mi tiempo libre a estar con mi familia y disfrutar de mi hija que a ir a un evento de fin de semana.

Eso cuadra con lo que contaba Rafael en este hilo sobre dedicar el fin de semana a desconectar y estar con los tuyos.

Podría venderlo como un (mal) ejemplo de conciliación familiar o de lo que implica ser padre. Nada más lejos de mi intención. Si hago esto, más allá de la responsabilidad que crea que tengo con mi familia, es porque es lo que más me apetece hacer. Al menos ahora. Es lo que más disfruto.

Y eso es importante. Disfrutar.

Cuando dedicaba muchas horas de mi tiempo libre a jugar con lenguajes de programación o con nuevos frameworks o a leer sobre desarrollo de software, lo hacía porque disfrutaba. Disfrutaba por el mero hecho de aprender sin necesidad de buscar una utilidad a lo que estaba aprendiendo y sin más objetivo que pasármelo bien.

Por eso no veo ningún problema en que alguien quiera dedicar su tiempo libre a aprender (sobre software, sobre historia antigua o sobre repostería) si disfruta con ese aprendizaje.

Comprendo que esto se puede volver en nuestra contra, como explica Diana Aceves:

Pero, lo más importante, normalmente menciono que el principal problema es que las empresas den por normalizado el que tengas que tener side projects para mostrar en los procesos de selección, porque entonces ya no es tan “voluntario” lo de currar fuera de horas de trabajo.

Sin duda esto es un problema, pero no ya porque dediques el tiempo libre al desarrollo de software o al cultivo de tulipanes, sino porque no tiene mucho sentido hablar de tiempo libre cuando necesariamente tienes que dedicarlo a algo concreto. ¿Qué clase de libertad es esa?

También es cierto que en esta profesión (¿y en todas?) es necesario mantenerse actualizado (aunque no haga falta aprender cosas nuevas tan rápido como pueda parecer), y de una forma u otra eso requiere tiempo. En un mundo ideal es tu empresa la que te permite destinar tiempo durante la jornada laboral para ello, pero todos sabemos que no siempre vivimos en un mundo ideal.

Que puntualmente necesites sacrificar (y ojo, que esa es la palabra: sacrificar) parte de tu tiempo libre para obtener algo a cambio es perfectamente razonable. Para mi es equivalente al que compagina los estudios con un trabajo. ¿Lo tiene más complicado que el que puede estudiar mientras le mantienen sus padres? Por supuesto. Pero a veces no hay otra alternativa.

Esto que ocurre desde un punto de vista laboral, también se manifiesta desde un punto de vista de “comunidad”, postureo o como quieras llamarlo. Lo plantea Rafael en el tweet que citaba al principio.

Es fácil sentirse abrumado al ver que las figuras más reconocidas reconocibles del mundillo del desarrollo no paran de hacer cosas. Dar charlas. Asistir a eventos. Publicar posts. Compartir enlaces en twitter. Contribuir en proyectos open source.

Hacer todo esto está muy bien, pero vuelvo al punto anterior: está muy bien si lo disfrutas. Si hacer este tipo de cosas se convierte en algo necesario para sentirte alguien guay como tus ídolos y te acaba generando ansiedad, es el momento de replantearse tus prioridades.

En resumen, ya lo decía Modesto en su tweet: no tiene mucho sentido decirle a nadie lo que debe hacer con su tiempo.

En mi opinión, es fundamental ser capaz de diferenciar las cosas que haces porque necesitas y las cosas que haces para disfrutar y tener muy claro hasta dónde puedes llegar con cada una.

Si disfrutas dedicando tiempo libre a cosas relacionadas con el desarrollo, estupendo. Si prefieres dedicar tu tiempo libre a otras actividades, perfecto. Si no te queda más remedio que sacrificar tu tiempo libre para conseguir algo…, bueno, a veces es inevitable, pero trata de estar seguro de que lo que quieres conseguir realmente merece la pena.

No hay posts relacionados.

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

Variable not found

Enlaces interesantes 354

marzo 18, 2019 07:25

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

Otros

Publicado en: www.variablenotfound.com.

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

Blog Bitix

Ejemplo de Reactive Streams en Java

marzo 17, 2019 09:00

Java

Los streams representan un flujo de elementos producidos por un productor y consumidos por uno o más consumidores. Para procesar los elementos del stream se pueden emplear dos modelos, el modelo push donde el productor produce elementos para el consumidor que es avisado cuando hay un nuevo elemento disponible y el modelo pull en el que es el consumidor el que solicita al productor nuevos elementos que los genera bajo demanda. Ambos modelos presentan problemas cuando el productor y el consumidor no funcionan a la misma velocidad de elementos producidos o procesados. La solución es proporcionar un stream que se adapta a la velocidad de ambos. Los reactive streams son empleados cuando los elementos son producidos y consumidos en tiempo real como en sistemas de mensajes o peticiones HTTP en vez de un flujo constante como un dispositivo de almacenamiento.

Una estrategia es conocida como backpressure que consiste en que el suscriptor notifica al productor cuántos elementos puede procesar de modo que el productor solo envía el número de elementos solicitados. La implementación de la solución son los reactive stream que proporcionan un mecanismo estándar asíncrono para el stream con backpressure. Estos evitan que el productor se bloquee por no poder entregarlos al ser rápido produciendo elementos o el suscriptor tenga un buffer grande o descarte algunos elementos por ser lento al consumirlos o se bloquee esperando nuevos elementos si es rápido consumiéndolos.

En la API entre otras novedades de la versión 9 de Java se han añadido las siguientes clases para soportar reactive streams embebidas en la clase Flow, Flow.Publisher, Flow.Subscriber, Flow.Subscription, Flow.Processor y SubmissionPublisher en el paquete java.util.concurrent incluido en el módulo java.base.

Un Publisher publica elementos para los Subscriber basándose en sus demandas recibidas. Un suscriptor se subscribe a un productor. El productor proporciona un token de suscripción con el que el suscriptor puede solicitar N elementos al productor. Cuando los elementos están disponibles el productor envía N o menos elementos al suscriptor. Posteriormente el suscriptor puede solicitar más elementos.

En el ejemplo de código un productor produce y los consumidores procesan elementos a cierto ritmo, dependiendo de la velocidad relativa de cada uno se usará un modelo push o pull. La clase Flow.Processor permite procesar los elementos del productor para aplicarles alguna transformación antes de que sean entregados a los consumidores, actual como consumidor y productor. En este stream de números enteros se aplica la función elevarlos al cuadrado.

 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package io.github.picodotdev.blogbitix.reactivestreams;
import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;
import java.util.stream.IntStream;
public class Main {
private static class PrintSubscriber implements Flow.Subscriber<Integer> {
private Flow.Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
subscription.request(1);
}
@Override
public void onNext(Integer item) {
System.out.println("Received item: " + item);
subscription.request(1);
Sleeper.sleep(1000);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("PrintSubscriber completed");
}
}
public static class PowProcessor extends SubmissionPublisher<Integer> implements Flow.Processor<Integer, Integer> {
private Flow.Subscription subscription;
@Override
public void onSubscribe(Flow.Subscription subscription) {
this.subscription = subscription;
subscription.request(1);
}
@Override
public void onNext(Integer item) {
submit(item * item);
subscription.request(1);
}
@Override
public void onError(Throwable error) {
error.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("PowProcessor completed");
close();
}
}
private static class Sleeper {
private static void sleep(int time) {
try {
Thread.sleep(time);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
Flow.Processor<Integer, Integer> processor = new PowProcessor();
Flow.Subscriber<Integer> subscriber = new PrintSubscriber();
publisher.subscribe(processor);
processor.subscribe(subscriber);
IntStream.range(0, 10).forEach(it -> {
publisher.submit(it);
Sleeper.sleep(2000);
});
publisher.close();
}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Received item: 0
Received item: 1
Received item: 4
Received item: 9
Received item: 16
Received item: 25
Received item: 36
Received item: 49
Received item: 64
Received item: 81
PowProcessor completed
PrintSubscriber completed

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 ./gradlew run.

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

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

Entrevista a Pedro Francisco Hernández Mayor de Kronos

marzo 16, 2019 06:43

Recientemente pudisteis leer el artículo sobre el juego C.R.B. (Cuerpo Rompe Bolas), desarrollado por KRONOS en 1993. KRONOS, sin embargo, no eran más que tres jóvenes aficionados afincados en Murcia (Pedro Francisco Hernández Mayor, Gregorio Ortiz Fernández y Antonio José Ortiz Fernández), que a base de pasión, lograron desarrollar un título que acabaría traspasando nuestras […]

La entrada Entrevista a Pedro Francisco Hernández Mayor de Kronos aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

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

Blog Bitix

Varias consideraciones importantes para trabajar con importes correctamente (tipo de datos, precisión y guardado)

marzo 16, 2019 10:00

Java

Entre las cosas básicas a tener en cuenta en una aplicación que maneja fechas está en guardarlas en la zona horaria UTC que no sufre de cambios por zona horaria de verano o invierno, cambian más habitualmente de lo que parece e incluso por temas políticos.

Otra consideración distinta en aplicaciones que manejan importes es usar la clase BigDecimal en vez de los tipos de datos de coma flotante float o double ya que los datos de coma flotante no son capaces de representar adecuadamente algunos valores numéricos en base 10. El asunto de este artículo es por que además de usar BigDecimal es aconsejable guardar los importes con al menos un dígito decimal más de la precisión necesaria para evitar problemas en los redondeos al aplicar operaciones matemáticas como multiplicación, división o porcentajes para algunos impuestos como el IVA, comisiones, descuentos o cambios de divisa.

Sin utilizar una mayor precisión de 2 decimales puede ocurrir que algunos importes tengan una diferencia de céntimos. Por ejemplo, los precios se pueden introducir o bien el precio del producto antes de aplicar el IVA, comisiones o descuentos o puede introducirse en el precio que paga el usuario después de aplicar el IVA y en ambos casos al realizar el cálculo del precio con IVA y el cálculo del precio base ha de coincidir. Por ello la recomendación es utilizar al menos un decimal más de la precisión necesaria.

Otras pautas importantes son guardar los importes redondeados que el usuario ve en la factura para evitar discrepancias hacia arriba de algún céntimo en la suma de los importes y aplicar el IVA, comisión o descuento no a cada producto individual sino a la suma de los importes de todos ellos.

Este artículo sobre Cómo hacer una aplicación que soporte precios con decimales sin errores están muy bien explicadas con ejemplos varios de todos estos puntos imprescindibles al manejar importes, recomendable leerlo.

Pero el tipo de datos BigDecimal tampoco es el mas apropiado con el que trabajar si la aplicación maneja múltiples divisas, en este caso es recomendable utilizar la librería Java Money que además ofrece soporte para ratios de conversión los cuales pueden obtenerse de proveedores externos que los proporcionan actualizados a lo largo del tiempo.

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

Picando Código

Cómics Marvel – Leyendo a los Inhumanos: Black Bolt

marzo 14, 2019 02:00

Escrito por Saladin Ahmed y con arte de Christian Ward, Black Bolt fue la primera serie mensual del rey de los Inhumanos de Marvel Cómics. Se publicó originalmente en Mayo de 2017, y terminó en el #12 en Abril de 2018. Fue compilada en dos tomos: Hard Time y Home Free. A continuación les cuento de uno de mis cómics preferidos de Inhumans y que recomiendo ampliamente:

Tomo 1: Hard Time

Black BoltEsta historia se desarrolla entre Inhumans Vs X-Men y Royals. Pero puede ser leída sin tener contexto de lo que pasó antes (o lo que pasa después). Lo que tenemos que saber es que Black Bolt despierta en una prisión, todo lo demás nos iremos enterando más adelante. La narrativa se inclina hacia la ciencia ficción, donde el escritor Saladin Ahmed tiene bastante experiencia.

En un principio resulta de esos cómics que se apartan un poco de la continuidad, pudiendo tener más soltura a la hora de contar cosas. Pero eventualmente empiezan a aparecer referencias y conexiones de las que no se puede escapar del todo en un universo compartido. Por ese lado disfruté mucho que la historia fuera bastante independiente más allá del contexto, pero que lentamente empezara a conectarse con el universo Marvel con el que uno está familiarizado. Como dije antes, no se necesita de haber leído historias de Black Bolt que vinieron antes para disfrutarlo.

Esto no quiere decir que esté completamente despegado de la mitología Inhumana. Pero me da la impresión que no conocer mucho los personajes antes de leer este título no le quita disfrute. Aunque si son seguidores de Inhumans, seguro van a disfrutarlo más todavía.

Black BoltSi bien Black Bolt es el protagonista y centro de la trama, van apareciendo personajes de la prisión que generan dinámicas muy interesantes y entretenidas. Esto aporta mucho, algunos son viejos conocidos y otros nuevos, pero se ganan la empatía del lector más allá de las razones por las cuales se encuentran en la prisión.

La alianza de Black Bolt con sus compañeros cae en el recurso narrativo de la “banda de inadaptados que se une con un fin común”. Pero el libro tiene un muy buen balance entre “una historia sobre Black Bolt” y “una aventura de Black Bolt en un grupo”, más a lo Inhumans clásico. A través del desarrollo de los personajes, entre otras cosas se analiza el tema del bien y del mal y la redención. Algo que corre peligro de caer en clichés o historias simplistas. Pero cuando está bien escrito como en este caso, es un éxito.

Viendo la tapa del primer número y ojeando las primeras hojas, podemos notar que el arte es otro punto alto de la serie. Las primeras páginas del primer número son un deleite visual con poco texto que de a poco nos lleva de paseo a este mundo donde se desenvuelve la trama. Christian Ward se encarga de todo el arte, y lo hace de manera espectacular. La prisión juega un poco con la mente de sus prisioneros, y el estilo del artista es ideal para representar ciencia ficción medio psicodélica que en lo personal disfruto mucho.

Hace un buen uso dinámico de las viñetas y “splash pages” (las viñetas que ocupan todo un par de páginas abiertas, pero no sé la traducción). Es así que la historia y el arte se complementan perfectamente. Vale la pena tener en cuenta otros trabajos de Christian Ward, y si quieren tener una idea de qué va la cosa, visiten su sitio web.

Hard Time colecciona los números 1 al 6 de Black Bolt y pueden encontrarlo en Amazon. Es un excelente cómic y lo recomiendo mucho, más allá que conozcan a Black Bolt o los Inhumans.

Próximamente les cuento sobre el desenlace y segundo tomo: Home Free.

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

Picando Código

Crystal: Lenguaje de programación inspirado en Ruby

marzo 13, 2019 11:00

Lenguaje de programación Crystal

Crystal es un lenguaje de programación de propósito general orientado a objetos. Su sintaxis está inspirada en Ruby pero no busca ser compatible. Surgió del amor a la eficiencia para escribir código de Ruby, y el amor a la eficiencia para ejecutar código C. Busca ser lo mejor de ambos mundos.

Entre las diferencias fundamentales con Ruby se encuentran:

  • Es un lenguaje compilado, el código es convertido a código de máquina nativo a través de LLVM. Ruby, por otro lado, es un lenguaje interpretado.
  • Tiene un sistema de tipado estático, por lo que la comprobación de tipos se realiza durante la compilación. Esto agrega una capa más de seguridad al código, evitando errors de tipos. Ruby es dinámicamente tipado, por lo que los tipos se revisan en ejecución. Sin embargo, el compilador de Crystal cuenta con un sistema de inferencia de tipos, por lo que no es necesario declarar los tipos de todos los valores y ejecuciones ya que el compilador los puede detectar. De esta manera, el código se mantiene limpio, y esto es parte de la filosofía del lenguaje.

El siguiente código nos muestra la inferencia de tipos en acción:

puts typeof("Fernando") #=> String
puts typeof(12) #=> Int32
puts typeof(42.0) #=> Float64

También podemos definir el tipo con anotaciones:

@nombre : String
@edad : Int32

Todo es un objeto: Al igual que en Ruby, en Crystal todo es un objeto (tiene un tipo, responde a algunos métodos).

Recién va por la versión 0.27.2, así que está creciendo y cambiando rápidamente todavía. De todas formas hay algunos valientes que se han animado a usarlo en producción. El proyecto cuenta con un Roadmap que define las cosas que quieren tener en el lenguaje, así como preguntas frecuentes y una excelente documentación.

Otras cosas interesantes de Crystal sobre las que me gustaría escribir más adelante: union types (tipos de datos especiales que pueden poseer varias representaciones), Macros (sistema para meta programación), Modelo de concurrencia e integración con librerías C (tiene una sintaxis dedicada para llamar a bibliotecas nativas de forma sencilla).

Instalar Crystal

Crystal puede ser instalado en Debian, Ubuntu, RedHat, CentOS, Arch Linux, Gentoo, Alpine, FreeBSD, y demás sistemas, desde un tar.gz o compilado desde el código fuente. Si usan el gestor de versiones asdf, hay un plugin para eso. Podemos ver las distintas instrucciones de instalación en la documentación.

El comando crystal

Una vez instalado, deberíamos tener el comando crystal disponible en nuestra terminal. Los archivos de código fuente Crystal tienen la extensión .cr. Para ejecutar un archivo de código fuente Crystal, escribimos:

$ crystal run archivo.cr

El comando `run` compila el código a un binario ejecutable en una ubicación temporal y lo ejecuta. Con el comando crystal build, podemos crear un binario ejecutable:

Crystal build

También existe crystal eval para pasarle código Crystal a crystal run desde la línea de comando o a través de un pipe por la entrada estándar. La lista completa de opciones está en la documentación usando el compilador.

Creando proyectos Crystal

El comando crystal también incluye el parámetro init, que inicializa un directorio con un proyecto. El primer parámetro de init es el tipo de proyecto. Las dos opciones son lib, una biblioteca reutilizable y app, una aplicación sin el objetivo de ser usada como dependencia:


$ crystal init app prueba
create prueba/.gitignore
create prueba/.editorconfig
create prueba/LICENSE
create prueba/README.md
create prueba/.travis.yml
create prueba/shard.yml
create prueba/src/prueba.cr
create prueba/spec/spec_helper.cr
create prueba/spec/prueba_spec.cr
Initialised empty Git repository in /home/fernando/workspace/crystal/prueba/.git/

Shards: Manejo de dependencias

Shards es a Crystal lo que las gemas son a Ruby. Las aplicaciones y bibliotecas Crystal cuentan con un archivo shard.yml que declara las dependencias del proyecto. Shards se distribuye con Crystal, así que lo tenemos disponible en nuestra terminal. Con shard init, creamos un archivo shard.yml de ejemplo, seguido de shard install para instalar las dependencias y especificarlas en un archivo shard.lock.

Por ejemplo en el proyecto recién creado, agrego las siguientes líneas al archivo shard.yml:

dependencies:
  cossack:
    github: crystal-community/cossack
    version: ~> 0.1
  

Cossack es un cliente HTTP bastante simple para Crystal. Se instala al ejecutar shards install y ya lo puedo usar en el código fuente. Dentro del archivo src/prueba.cr del mismo proyecto escribo:

require "cossack"

module Prueba
  VERSION = "0.1.0"

  def self.hola
    response = Cossack.get("https://picandocodigo.net/api")
    puts response.body
  end
end

Prueba.hola

Y podemos ejecutarlo con crystal run para ver los resultados:
crystal run src/prueba.cr

Testeando Código Crystal

Crystal viene equipado con una biblioteca de testing en el módulo Spec. Incluye un DSL (lenguaje de dominio específico) inspirado en RSpec, por lo que resulta súper familiar para programadores Ruby. Cuando inicié mi proyecto más arriba,ya se creó un directorio /spec con un archivo de ejemplo. Modificando un poco el archivo prueba.cr para que retorne el valor de lo que obtiene Cossack en vez de imprimirlo en pantalla con puts, podemos escribir un test bastante sencillo:

describe Prueba do
  it "calls Picando Código's API" do
    Prueba.hola.should eq "¡Chau!"
  end
end

Y si corremos los tests, tenemos una falla! (TDDeando, por supuesto):

$ crystal spec
F

Failures:

1) Prueba calls Picando Código's API
Failure/Error: Prueba.hola.should eq "¡Chau!"

Expected: "¡Chau!"
got: "¡Hola!"

# spec/prueba_spec.cr:5

Finished in 744.67 milliseconds
1 examples, 1 failures, 0 errors, 0 pending

Failed examples:

crystal spec spec/prueba_spec.cr:4 # Prueba calls Picando Código's API

Cambiando la expectativa del test a “¡Hola!” hacemos que pase:

describe Prueba do
  it "calls Picando Código's API" do
    Prueba.hola.should eq "¡Hola!"
  end
end
$ crystal spec
.

Finished in 861.99 milliseconds
1 examples, 0 failures, 0 errors, 0 pending

Como ven, es bastante sencillo empezar a usar Crystal. Espero con este post lograr despertar el interés por el lenguaje, y con suerte tener algún intercambio al respecto. Los comentarios están abiertos si quieren dejar su opinión, ¿conocían Crystal? ¿Le ven futuro?

Por mi parte voy a seguir investigando el lenguaje e intentar escribir algunos proyectitos, así como analizar las herramientas ya disponibles, e iré compartiéndolo por acá.

Más información sobre Crystal:

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

Picando Código

Nuevo servicio gratuito para compartir archivos online de forma segura – Firefox Send

marzo 13, 2019 10:00

Este nuevo servicio de Mozilla se llama Firefox Send. Mediante cualquier navegador web, nos permite subir archivos de manera gratuita y compartirlos con otros usuarios. Tenemos bastante control de seguridad sobre los archivos que compartimos. Podemos limitar la cantidad de veces que puede ser descargado, y cuánto tiempo va a durar (para un máximo de 7 días). El archivo no va a quedar guardado indefinidamente en algún servidor en la nube. También podemos asignarle un password, para asegurarnos que solamente quienes sepan el password puedan descargarlo.

Firefox Send

La interfaz es bastante simple, podemos arrastrar archivos hacia la página o elegirlos desde un navegador de archivos, elegimos las opciones y lo(s) subimos. El servicio cuenta con encriptado de punta a punta, y podemos compartir archivos de hasta 1GB. Si queremos enviar hasta 2.5GB, podemos crear una cuenta gratuita Firefox.

Una vez subido, podemos enviar un enlace de descarga a otro usuario. Para la descarga no es necesario loguearse ni tener ningún tipo de cuenta. Tan simple y rápido como enviar un mail. Próximamente estará disponible como aplicación Android también.

Send fue diseñado por Mozilla con la privacidad como principio fundamental. Los archivos están protegidos y nuestra información es manejada de manera privada y segura. Mozilla es una fundación sin fines de lucro cuyo objetivo es que internet sea abierta y accesible para todos. No lucran con nuestros datos, así que de mi parte, son de las pocas marcas en las que confío por ahora.

El servicio empezó como un experimento de Test Pilot, y fue mejorando hasta que Mozilla decidió que era tiempo de promoverlo a un proyecto independiente. El código fuente está disponible en GitHub bajo la licencia libre Mozilla Public License Version 2.0.

Visita Firefox Send

 

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

Fixed Buffer

Cómo medir tiempos en C# y .Net con precisión

marzo 13, 2019 09:35

Cómo medir tiempos en .Net  (con precisión)

Hace unos días mientras comíamos los compañeros de trabajo, salió el tema sobre lo preciso o impreciso que puede ser medir tiempos desde el sistema operativo. Mis compañeros (programadores C/C++ en su mayoría), tenían dudas sobre lo preciso que puede ser medir tiempos desde un entorno administrado. Nunca he necesitado tales precisiones, así que era totalmente novato en ese tema, pero hoy que he tenido un momento, he investigado un poco sobre cómo medir tiempos en C# y .Net con precisión:

La clase Stopwatch

En C#, el ecosistema .Net nos provee de una herramienta ya lista para utilizar con una precisión de microsegundo (si el hardware lo permite) dentro del namespace “System.Diagnostics“. Está herramienta es la clase Stopwatch . Esta disponible en todos los entornos a partir de .Net Framework 2.0 (incluyendo .Net Core y .Net Standard), así que si no la conocías, es una buena idea añadirla al cinturón.

Para usarla, simplemente es necesario instanciarla y llamar a sus métodos Start y Stop, después nos devuelve un TimeSpan con el tiempo transcurrido:

Stopwatch timeMeasure = new Stopwatch();
timeMeasure.Start();
int operacion = 10 / 4;
timeMeasure.Stop();
Console.WriteLine($"Tiempo: {timeMeasure.Elapsed.TotalMilliseconds} ms");

Pero no se queda ahí, la clase también tiene dos propiedades estáticas (ReadOnly) que nos pueden dar mucha información sobre la medida:

  • IsHighResolution (bool): Nos va a indicar si el hardware permite mediciones de alta precisión.
  • Frequency (long): Nos va a dar el valor de ticks (mediciones) por segundo que soporta nuestro hardware.

Con estos dos datos extra, podemos saber si nuestra medida es de alta precisión, e incluso la resolución de la medida:

using System.Diagnostics;
//------
Stopwatch timeMeasure = new Stopwatch();
timeMeasure.Start();
int operacion = 10 / 4;
timeMeasure.Stop();
Console.WriteLine($"Tiempo: {timeMeasure.Elapsed.TotalMilliseconds} ms");
Console.WriteLine($"Precision: {(1.0 / Stopwatch.Frequency).ToString("E")} segundos");
if (Stopwatch.IsHighResolution)
    Console.WriteLine("Alta precisión");
else
    Console.WriteLine("Baja precisión");

Después de probarlo, ya puedo decirles a mis compañeros que se pueden medir tiempos en C# y .Net con precisión y sin nada que envidiar a otros lenguajes de más bajo nivel como C/C++.

**La entrada Cómo medir tiempos en C# y .Net con precisión se publicó primero en Fixed Buffer.**

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

Coding Potions

Tutorial NPM - Todo lo que necesitas saber

marzo 13, 2019 12:00

Introducción ¿Qúe es NPM? Si eres desarrollador web, sobre todo en la parte del frontend, seguramente ya conozcas NPM. NPM es un gestor de paquetes para Javascript. Es una especie de Maven (si usas Java te sonará) para paquetes Javascript, es decir, sirve para instalar y gestionar versiones de paquetes y librerías js. NPM lleva mucho tiempo siendo el referente en cuanto a gestores de paquetes javascript, pero desde hace un tiempo le ha salido un competidor: Yarn.

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

Picando Código

Awesome Rubies – Una colección de Rubies increíbles

marzo 12, 2019 02:00

Ruby

Awesome Rubies es una lista de “Rubys” (¿”Rubíes”?), o distintas implementaciones del lenguaje e información al respecto. La más conocida es MRI (Matz’s Ruby Interpreter), la implementación “de referencia” y probablemente la más usada. Actualmente se llama CRuby porque es un esfuerzo colaborativo y no “de Matz”, y existen además otras implementaciones como Rubinius, JRuby: Implementación de Ruby en la JVM y unas cuantas más.

Si has estado siguiendo Ruby, o has ido a conferencias recientemente, probablemente ya sepas de Ruby 3×3. Mi primer encuentro con el concepto “Ruby 3×3” fue en Euruko 2017. donde Matz abrió la conferencia con un Keynote sobre el futuro de Ruby. La idea es que la versión 3 de Ruby (esperada para el año que viene) va a ser 3 veces más rápida que la versión 2.0. Y con el trabajo que se viene haciendo para lograrlo, se vienen varias cosas interesantes en el lenguaje.

Siguiendo con Awesome Rubies, en la lista podemos ver las versiones principales (CRuby, JRuby, TruffleRuby), así como menores o próximas a salir (Topaz – Ruby en Python, GoRuby – Ruby en Go 🤦, etc) y versiones discontinuadas como IronRuby (.NET), MacRuby (Objective-C), y más. Desde ahí podemos acceder a más información sobre el recurso en particular. También encontraremos enlaces a investigaciones, papers, libros, benchmarks y otros recursos.

Algo que me resultó particularmente interesante fue ver en la lista dos lenguajes de programación que vengo siguiendo con interés desde hace un tiempo: Elixir y Crystal. No son exactamente versiones de Ruby, pero le veo sentido que estén listados como parte de la familia. Crystal tiene una sintaxis como Ruby, pero es estáticamente tipado y compila a código máquina (tengo un post sobre Crystal en borradores…). Elixir es un lenguaje de programación funcional que corre sobre la máquina virtual de Erlang, y su sintaxis está inspirada en la de Ruby.

También interesante ver en la lista Mirah, un lenguaje de programación que Charles Nutter presentó en Ruby Conf Uruguay 2010. Creo que la idea es algo así como una reimplementación de Java pero con la sintaxis de Ruby. Debería leer más…

Volviendo a Crystal y Elixir, obviamente no es coincidencia que venga estudiándolos y estén en la lista. Elixir es el más distinto de los dos, porque cambia el paradigma de programación mucho más radicalmente. Pero surgió de un miembro importante de la comunidad Ruby: José Valim. José parece seguir la filosofía de Ruby “Matz is nice and so we are nice”. Si bien Elixir todavía no ha agarrado mucha tracción como otros lenguajes o tecnologías que deben su éxito mayormente al apoyo de grandes corporaciones, es una buen lenguaje para aprender programación funcional. Y aunque sea lentamente, sigue creciendo, y Erlang no se va a ir a ningún lado por unos cuantos años. Por eso tiene sentido que varios rubistas “se hayan mudado” a Elixir o complementen su trabajo en Ruby con él.

Crystal es todavía bastante joven, pero también promete y mucho. Más adelante comentaré más al respecto.

Habiendo usado otros lenguajes, me sigue pareciendo importante la parte de la comunidad, abierta e inclusiva, además de “amable” como Matz. También que los lenguajes más allá de sus ventajas y decisiones técnicas, parecen seguir el paradigma -como Ruby- de ser diseñados para el programador y no para la computadora. O por lo menos así lo siento con Ruby, Elixir y eventualmente supongo que Crystal. Son lenguajes con ese “no sé qué” que por lo menos a mí me motiva aprender y disfruto usándolos. Así que no me parece una mala decisión de carrera especializarme en “Rubies”, e incluir Elixir y Crystal ahí.

Visiten Awesome Rubies para adentrarse más en este mundillo de rubíes.

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

Picando Código

Humble Book Bundle: Libros de Linux por Wiley

marzo 12, 2019 10:00

Humble Bundle tiene un nuevo paquete de e-books sobre Linux, programación y varias certificaciones. 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 by Wiley

Pagando USD 1 o más, el paquete incluye:
Linux Essentials, Ubuntu Linux Toolbox: 1000+ Commands for Power Users, Linux All-In-One For Dummies, Beginning Linux Programming.

Pagando USD 8, todos los anteriores más:
Linux Bible, Shell Scripting: Expert Recipes for Linux, Bash, and more, Linux Server Security: Hack and Defend,
CompTIA Linux+ and LPIC Practice Tests: Exams LX0-103/LPIC-1 101-400, LX0-104/LPIC-1 102-400, LPIC-2 201, and LPIC-2 202, Professional Linux Kernel Architecture

Finalmente, pagando USD 15 obtenemos el paquete completo con todos los anteriores y:
Linux Command Line and Shell Scripting Bible, CompTIA Linux+ Powered by Linux Professional Institute Study Guide: Exams LX0-103 and LX0-104, LPIC-1: Linux Professional Institute Certification Study Guide: Exams 101 and 102, LPIC-2: Linux Professional Institute Certification Study Guide: Exams 201 and 202, Red Hat Enterprise Linux 6 Administration: Real World Skills for Red Hat Administrators, Assembly Language Step-by-Step: Programming with Linux

Al momento de pagar, elegimos cómo repartir el dinero, con la opción de donar a la charidad “Freedom to Read”:
La Fundación Freedom to Read (FTRF) es una organización legal y educativa sin fines de lucro afiliada a la Asociación de Bibliotecas Americana. FTRF protege y defiende la Primera Enmienda de la Constitución y apoya el derecho de las bibliotecas de recolectara – y el acceso individual a – información.

La promoción termina el 25 de marzo, visita el Humble Book Bundle: Linux by Wiley

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

Variable not found

Shadow properties en Entity Framework Core

marzo 12, 2019 07:45

Entity Framework CoreSeguimos hablando de características interesantes de Entity Framework Core, y en esta ocasión nos detendremos en las shadow properties, o propiedades ocultas.
A grandes rasgos, se trata de la capacidad de este framework para gestionar propiedades de una entidad que existen en el almacén datos pero no en la clase .NET que la representa en el mundo de los objetos.

De forma intuitiva podemos saber que esto ya existía en las versiones clásicas de Entity Framework. Por ejemplo, cuando introducíamos una propiedad de navegación entre dos entidades sin usar una clave foránea de forma explícita, el propio marco de trabajo creaba, por convención, una columna en la base de datos para almacenar dicha referencia, como en el siguiente escenario:
public class Friend
{
public int Id { get; set; }
public string Name { get; set; }
// Se crea una columna CountryId en la base de datos,
public Country Country { get; set; } // pero no existe en la entidad.

}
El valor de dicha columna CountryId no podía ser manipulada de forma directa porque se trataba de información usada internamente para gestionar las relaciones y su valor era obtenido y actualizado de forma transparente para nosotros.

Pues bien, Entity Framework Core aporta la capacidad para gestionar este tipo de campos "ocultos" para servir a nuestros propios intereses. De esta forma, podríamos añadir a una entidad propiedades que no tienen por qué estar visibles en la clase .NET en forma de propiedades; un ejemplo podría ser el clásico "IsDeleted" cuando implementamos borrado lógico, o información de auditoría como los tradicionales "UpdatedAt" o "UpdatedBy".

Definición de propiedades ocultas

La definición de shadow properties sólo puede realizarse utilizando el API fluido de configuración disponible a través del objeto ModelBuilder suministrado al método OnModelCreating() del contexto de datos.

Por ejemplo, el siguiente bloque de código añade a la entidad Friend las propiedades ocultas UpdatedAt y UpdatedBy, que podrían sernos de utilidad para almacenar información interna de auditoría:
// Entidad:
public class Friend
{
public int Id { get; set; }
public string Name { get; set; }
}

// Contexto de datos:
public class FriendsContext : DbContext
{
public DbSet<Friend> Friend { get; set; }

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Friend>()
.Property<DateTime>("UpdatedAt");
builder.Entity<Friend>()
.Property<string>("UpdatedBy").HasMaxLength(80);
}
}
Y esto es todo, así de sencilla es la creación de shadow properties :)

Consultar o establecer el valor de una propiedad oculta de una entidad

Dado que estas propiedades no aparecen en las clases .NET que representan a las entidades de datos, no podemos acceder a sus valores utilizando expresiones como objeto.Propiedad desde nuestro código. Sus valores están gestionados directamente por el change tracker de Entity Framework, por lo que debemos recurrir a él para hacerlo.

Por ejemplo, el siguiente código muestra cómo acceder a las propiedades ocultas de una entidad obtenida previamente:
var friend = ctx.Friends.FirstOrDefault();
if(friend != null)
{
var name = friend.Name;
var updatedBy = ctx.Entry(friend).Property<string>("UpdatedBy").CurrentValue;
var updatedAt = ctx.Entry(friend).Property<DateTime>("UpdatedAt").CurrentValue;
Console.WriteLine($"{name} was updated by {updatedBy} at {updatedAt}");
}
De la misma forma, para actualizar el valor de las shadow properties, tendremos que esta la misma shadow property podríamos hacerlo como sigue:
var friend = ctx.Friends.FirstOrDefault();
if(friend != null)
{
ctx.Entry(friend).Property<string>("UpdatedBy").CurrentValue = "John Smith";
ctx.Entry(friend).Property<DateTime>("UpdatedAt").CurrentValue = DateTime.Now;
ctx.SaveChanges();
}

Incluir shadow properties en expresiones de consulta

Obviamente, el hecho de que no tengamos propiedades en la entidad para acceder a estos valores condiciona también la forma en que debemos utilizarlos desde LINQ en los predicados o criterios de consultas.

Pero de nuevo, tenemos una fórmula bastante sencilla para conseguirlo obteniendo una referencia válida para el árbol de expresión a través del método EF.Property(). En el siguiente ejemplo vemos cómo filtrar las entidades para obtener sólo aquellas actualizadas durante el último minuto:
var since = DateTime.Now.AddMinutes(-1);
var friendsRecentlyUpdated = ctx.Friends
.Where(b => EF.Property<DateTime>(b, "UpdatedAt") > since);
Publicado en Variable not found.

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

Variable not found

Enlaces interesantes 353

marzo 11, 2019 07:45

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

Otros

Publicado en: www.variablenotfound.com.

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

Blog Bitix

Componentes en el cliente con Web Components usando JavaScript, HTML y CSS

marzo 08, 2019 05:00

JavaScript
HTML

En la rapidez con la que evolucionan las tecnologías una tendencia es el usar componentes en el lado del cliente y en los navegadores de una aplicación o página web. Los componentes son muy útiles ya que siguen los principios de encapsulación deseables una la programación que hace que un componente oculte los detalles del funcionamiento interno. Esta encapsulación hace que su funcionamiento interno sea más fácilmente entendible, por otro lado son reutilizables conociendo únicamente la interfaz que exponen y componer otros más complejos con otros más simples.

Han surgido varias librerías en JavaScript para desarrollar componentes en el lado del cliente, una de las primeras es Angular, otra React y otra es Vue pero el organismo W3C ha definido un estándar para desarrollar componentes, que los navegadores han de implementar. El estándar se llama Web Components está formado por varias especificaciones.

  • Custom Elements: permite definir nuevas etiquetas que el navegador es capaz de interpretar, hace el etiquetado de una página más sencillo.
  • Shadow DOM: el contenido HTML oculto de las etiquetas personalizadas.
  • HTML Templates: etiquetado HTML no visualizado por el navegador, utilizables para definir la estructura de los elementos sin tener que crearlo con código JavaScript.

Los Custom Elements se definen mediante código JavaScript con la función CustomElementRegistry.define() que recibe como parámetros el nombre de la etiqueta, la clase que la implementa y opcionalmente el elemento del que hereda. Hay dos tipos de Web Components los autónomos que heredan de HTMLElement y los personalizados que heredan de un elemento más concreto como un párrafo o botón, en cada caso de declaran de forma diferente en la función define y la etiqueta que la representa en el HTML en el ejemplo usando la etiqueta <hello-world> o <p is=“hello-world-customized”>.

Usando una definición de clase para el Custom Element se añade su funcionalidad, entre ella su etiquetado y estilos propios del componente, los elementos se añaden al Shadow DOM con la función appendChild() del objeto shadow obtenido con attachShadow(). El Custom Element puede tener atributos para recibir datos que se recuperan con la función getAttribute() y hasAttribute().

Con las funciones connectedCallback(), disconnectedCallback(), adoptedCallback(), attributeChangedCallback() y observedAttributes() del ciclo de vida un Web Component será notificado cuando se añada a una página, cuando se quite, cuando un atributo cambie su valor.

El Shadow DOM compone el etiquetado oculto del Web Compnent, las etiquetas HTML y los estilos CSS. El Shadow DOM es exclusivo del Web Component y está aislado del resto de modo que las clases CSS de estilos no entrarán en conflicto con las de otros Web Components aunque tengan los mismos nombres, esto hace menos necesarias las nomenclaturas que se utilizan precisamente para evitar los conflictos.

 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
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
class HelloWorld extends HTMLElement {
static get observedAttributes() {
return ["observed"];
}
constructor() {
super();
let style = document.createElement("style");
style.textContent = ".paragraph { font-size: 2em; font-weight: bold; }";
let paragraph = document.createElement("p");
paragraph.setAttribute("class", "paragraph");
paragraph.textContent = "Hello World!";
let shadow = this.attachShadow({mode: "open"});
shadow.appendChild(style);
shadow.appendChild(paragraph);
}
connectedCallback() {
console.log("HelloWorld element added to page.");
}
attributeChangedCallback(name, oldValue, newValue) {
console.log("HelloWorld element attributes changed.");
console.log({name: name, oldValue: oldValue, newValue: newValue});
}
}
// ...
 customElements.define("hello-world", HelloWorld);
// ...
 </script>
</head>
<body>
...
<hello-world observed="value"></hello-world>
...
</body>
</html>
 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
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
class HelloWorldCustomized extends HTMLParagraphElement {
// ...

constructor() {
super();
let style = document.createElement("style");
style.textContent = ".paragraph { font-size: 2em; font-weight: bold; }";
let span = document.createElement("span");
span.setAttribute("class", "paragraph");
span.textContent = "Hello World! (Customized)";
let shadow = this.attachShadow({mode: "open"});
shadow.appendChild(style);
shadow.appendChild(span);
}
// ...
 }
// ...
 customElements.define("hello-world-customized", HelloWorldCustomized, { extends: "p" });
// ...
 </script>
</head>
<body>
...
<p is="hello-world-customized"></p>
...
</body>
</html>

Para hacer más sencilla la creación del etiquetado de los Web Components en vez de usando código JavaScript con las funciones createElement() y appendChild() está la especificación de HTML Templates. Plantillas en las que además se puede incluir los estilos CSS.

 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
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
class HelloWorldTemplate extends HTMLElement {
// ...

constructor() {
super();
let template = document.getElementById('hello-world-template');
let shadow = this.attachShadow({mode: 'open'})
shadow.appendChild(template.content.cloneNode(true));
}
// ...
 }
// ...
 customElements.define("hello-world-template", HelloWorldTemplate);
// ...
 </script>
</head>
<body>
...
<template id="hello-world-template">
<style>
.paragraph {
font-size: 2em;
font-weight: bold;
}
</style>
<p class="paragraph">Hello World! (Template)</p>
</template>
...
<hello-world-template></hello-world-template>
...
</body>
</html>

Además con los slots se le puede proporcionar al Web Component un fragmento de HTML.

 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
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
class HelloWorldSlot extends HTMLElement {
// ...

constructor() {
super();
let template = document.getElementById('hello-world-slot');
let shadow = this.attachShadow({mode: 'open'})
shadow.appendChild(template.content.cloneNode(true));
}
// ...
 }
// ...
 customElements.define("hello-world-slot", HelloWorldSlot);
// ...
 </script>
</head>
<body>
...
<template id="hello-world-slot">
<style>
.paragraph {
font-size: 2em;
font-weight: bold;
}
</style>
<p class="paragraph"><slot name="text">Hello World! (Slot)</slot></p>
</template>
...
<hello-world-slot></hello-world-slot>
<hello-world-slot>
<span slot="text">Hello World! (Slot Custom)</span>
</hello-world-slot>
...
</body>
</html>
Etiquetado y eventos de varios Web Components

En la página de documentación los Web Components en MDN esta muy bien detallados. Los componentes de lado del cliente permiten desarrollar elementos funcionales reutilizables y compuestos entre ellos. Combinado con una interfaz REST o GraphQL en el lado del servidor es una forma de construir una aplicación o página web. JSF, Wicket, Apache Tapestry son frameworks web Java que proporciona componentes con ciertas similitudes pero en el lado del servidor.

La compatibilidad de los navegadores de los Web Components es amplia, no necesita de librerías JavaScript adicionales ya que el soporte está incluido en el navegador pero React y Vue están disponibles con anterioridad y proyectos como Redux y Vuex proporcionan el manejo del estado de los componentes.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub.

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

Picando Código

Se viene Rust Latam Montevideo 2019 – Conferencia latinoamericana de Rust

marzo 08, 2019 02:30

Los días 29 y 30 de marzo de 2019 en Montevideo, Uruguay, se realiza la primera conferencia latinoamericana del lenguaje de programación Rust: Rust Latam.

¿Qué es Rust?

Si tenés curiosidad por aprender sobre Rust, ¡éste es el lugar correcto!

Rust es un lenguaje de programación de sistemas que corre increíblemente rápido, previene segfaults, y garantiza seguridad en programación multihilos. La promesa es permitir construir software confiable y eficiente aprovechando potentes chequeos del compilador y un set de herramientas maduro que ayudará y asistirá durante todo el proceso.

Sobre la conferencia:

Rust Latam Montevideo

La Conferencia Rust Latam es el evento líder en América Latina por y para el movimiento Rust, y una de las oportunidades anuales más grandes de networking en la comunidad local de Rust. Esta conferencia de un fin de semana con sesiones interactivas, actividades prácticas, y charlas junta a más de 200 defensores, desarrolladores y entusiastas del lenguaje de programación Rust de todo el mundo. En marzo, la gente e ideas de la comunidad latinoamericana de Rust saltará de la pantalla para aprender, discutir, debatir y enfrentar Rust en persona. Nuestra primera conferencia Rust Latam anual empieza en Montevideo.

En marzo, tendremos ese mismo espíritu vehemente de las reuniones locales. También tendremos a la gente y recursos para hacer un gran impacto. Una conferncia de dos días – series de talleres y oradores – con decenas de expertos y principiantes significa que podemos avanzar el pensamiento en cómo tú y tu equipo pueden usar características de Rust para crear una amplia gama de nuevas aplicaicones de software, como motores de juegos, sistemas operativos, sistemas de archivos, componentes de navegadores web y motores de simulación para realidad virtual. Podemos forjar nuevas sociedades, podemos entrenar a los programadores del mañana y podemos alimentar a la construcción comunitaria a través de los países de América Latina.

Oradores

Docenas de expertos y principantes, lo que significa que podemos progresar mucho pensando en cómo tú y tu equipo pueden usar Rust.

Comunidad

Una meta compartida es conectar a la gente haciendo de Rust el mejor lenguaje de programación y la mejor comunidad.

Compromiso

Rust Latam Conf es sólo el comienzo. Para este primer año, esperamos dejar a Montevideo sintiéndose inspirado y comprometido.

Estimulando

Nos movemos hacia una comunidad más abierta e inclusiva para alimentar nuestra misión, el mejor Lenguaje de Programación Rust para todos.

La conferencia cuenta con un Código de Conducta, buscando ser un evento inclusivo, acogedor para todos y en contra de cualquier tipo de acoso u hostigamiento.

Charlas y Talleres

Va a haber dos keynotes, y charlas sobre Rust, Python, WebAssembly, Serverless, Macros y más. También un día entero de talleres incluyendo uno de Introducción a Rust:

El workshop introductorio está orientado a personas que desean conocer Rust y que tienen experiencia en otro lenguaje de programación. Este servirá de introducción a los conceptos fundamentales que hacen a Rust un lenguaje de progrmación diferente como; pertenencia, tiempos de vida y el sistema de tipos.

Al mismo tiempo los asistentes se podrán familiarizar con la sintaxis del lenguaje.

El workshop será una mezcla de conceptos teoricos y ejercicios cortos que apliquen a dichos conceptos.

Entradas y ubicación

La conferencia se realizará en el clásico Auditorio Torre de las Telecomunicaciones ANTEL, Calle Guatemala, 1075, Montevideo, Uruguay.

Hay dos tipos de entrada a la venta: Supporter por USD 100 (entrada con acceso total + aportar para que se haga la conferencia) y Regular USD 50 (entrada con acceso total a la conferencia). Las entradas se pueden comprar en este enlace.

La organización también está ofreciendo entradas gratis mediante un programa especial de becas. La idea es atraer nuevos entusiastas de Rust y darles la posibilidad que puedan descubrir más sobre este maravilloso lenguaje de programación:

Si eres un estudiante o profesor en latinoamérica, en áreas relacionadas con la ciencia y la ingeniería y te gustaría participar activamente en comunidades Open-Source y/o estás interesado en aprender sobre Rust, esta es una gran oportunidad para descubrir más acerca de este seguro, eficiente y rápido lenguaje de programación. Para ser seleccionado como beneficiario de este programa, hay que llenar este cuestionario antes del viernes 20 de marzo. El programa cubre el ingreso de manera gratuita al evento completo. Esto incluye workshops (29 de marzo) y la conferencia (30 de marzo, incluye almuerzo).

Más información

¡No se la pierdan! Ojalá pudiera ir…

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

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

Cosas interesantes con Take Command

marzo 07, 2019 08:01

Hace casi 15 años que publiqué el artículo La potencia de TakeCommand y 4NT. Me he dado cuenta que sigo siendo un fiel usuario de Take Command y sus variantes TCC y TCC/LE. Aprovechando en lanzamiento de la versión 24, y después de Resaltado de sintaxis en Take Command hoy voy a explicar algunos comandos […]

La entrada Cosas interesantes con Take Command aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

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

Variable not found

Cómo crear un paquete NuGet y publicarlo en Nuget.org

marzo 05, 2019 06:21

Blogger invitado

Blogger invitado

Jorge Turrado

Apasionado de la programación, siempre buscando la manera de mejorar el día a día con el desarrollo de tecnologías .NET. Apasionado de este momento tan cambiante y fabuloso para ser desarrollador C#.
Blog: Fixed Buffer
Tras la última colaboración me quedé con ganas de más y, después de que José me haya vuelto a invitar, vengo a hablaros de los paquetes Nuget.

Como desarrollador del ecosistema .NET, seguro que alguna vez has usado el gestor de paquetes NuGet (y si aún no lo has hecho, lo acabarás haciendo antes o después, créeme). Esta herramienta permite empaquetar componentes que cumplen una necesidad determinada, ya sea de terceros o internos de nuestra empresa, dejándolos listos para obtenerlos e incluirlos rápidamente en nuestros proyectos sin tener que compilarlos cada vez o almacenarlos en forma de binarios en una enorme carpeta con cientos de librerías.

Su máximo referente es el repositorio público Nuget.org, integrado dentro de Visual Studio y repositorio de facto de .NET Core, aunque también existen repositorios NuGet privados, o incluso puedes crear el tuyo sin ningún problema bajándote el paquete Nuget.Server desde el propio Nuget.org e implementándolo, ¿es poético verdad? 😊).

NuGetAhora que hemos introducido qué es NuGet para quien no lo supiese, tal vez te hayas preguntado cómo es posible crear un paquete NuGet y publicarlo para que otros desarrolladores puedan utilizarlo. Vamos a ver que es algo realmente sencillo.

Obtener nuestra API key

Lo primero que necesitamos es obtener nuestra API KEY en Nuget.org, y para ello antes de nada debemos acceder al servicio.

Login en Nuget.org

Hay que tener en cuenta que es necesario utilizar una cuenta Microsoft para poder loguearnos, pero basta que sea una cuenta de Hotmail u Outlook.

Una vez que nos hemos logueado, pulsamos sobre nuestro nombre para abrir el menú, y vamos a la opción "API Keys":

Menú API keys en Nuget.org

Y tras ello, ampliamos la sección "Create":

Sección "Create" en Nuget.org

En el formulario que nos aparece es donde vamos a dar los datos para crear la clave:

Formulario de creación de API key

Los datos que nos va a pedir son:
  • Nombre de la clave: Aquí vamos a ponerle un nombre que nos permita identificar la clave para gestionarla después.
     
  • Duración: Este es el tiempo de vida de la clave. Una vez pasado ese tiempo, tendremos que renovarla.
     
  • Permisos: Aquí le indicamos si queremos que sólo pueda hacer actualizaciones de paquetes, o crear nuevos paquetes también.
     
  • Patrón de permisos de acceso: Con esto vamos a indicar a qué paquetes queremos que se pueda acceder con esta clave. En caso de que tengamos algún paquete ya creado, también podremos seleccionarlo.
Para nuestro caso, vamos a crearlo con permisos de actualización y poder crear nuevos paquetes, y en el patrón de acceso le vamos a poner un “*” para poder acceder a todos, ya que va a ser nuestra clave de trabajo como desarrollador. Si lo que estuviésemos haciendo es una clave para un servicio de CI/CD, lo conveniente sería ajustar los permisos para no permitir control total sobre la cuenta. Después, basta con pulsar sobre el botón “Create”.

Una vez se pulsemos para crear la clave, nos la mostrará en el apartado “Manage”, dándonos la posibilidad de copiarla. Sólo nos va a dejar copiarla esta vez, por lo que es importante que nos la guardemos en un sitio a salvo, ya que, si la volvemos a necesitar y no la hemos copiado, tendremos que regenerarla.

Obtener la API key

Con esto ya tenemos lo necesario para poder publicar un paquete en Nuget.org, así que sólo nos queda crear el paquete, para lo que vamos a crear un proyecto de librería en Visual Studio. La recomendación es crearla con .NET Standard en su versión más baja posible, ya que con eso conseguimos que funcione multiplataforma y con la mínima versión del framework posible, siempre que esa versión incluya todas las APIs que necesitamos.

Tabla de compatibilidad de .NET Standard

Para nuestro ejemplo, vamos a crear una librería .NET Standard 1.0, ya que no vamos a necesitar ninguna API, aunque lo normal es que necesitemos una versión más alta. Para seleccionar la versión de .NET Standard, debemos ir a las propiedades del proyecto de nuestra librería, y seleccionarla en el desplegable.

Selección de versión de .NET Standard

Configurando nuestro proyecto para generar un paquete

Dentro de las opciones, también vamos a ir a la pestaña “Paquete”, donde le vamos a indicar los datos del paquete.

Propiedades del paquete

Aquí conviene rellenarlo todo, así como darle etiquetas que faciliten buscar el paquete para quien busque algo que resuelva su problema, pero como mínimo debe tener un “Id. de paquete” único y una versión, ya que es el nombre con el que aparecerá en el repositorio. Una buena idea es buscar en Nuget.org si ya existe un paquete con el nombre que queremos darle, porque si ya existe no podremos subir el nuestro.

Pese a que esos sean los datos mínimos, es recomendable añadir información adicional sobre el paquete, como el nombre del autor, información de copyright, una descripción ampliada o las direcciones URL del proyecto, entre muchos otros. La siguiente captura de pantalla muestra el formulario prácticamente relleno en su totalidad para nuestro proyecto de ejemplo:

Propiedades del paquete totalmente cumplimentadas

Una vez tenemos esto listo, basta con que sigamos trabajando en nuestro código de manera normal como lo haríamos en cualquier otro proyecto.

Publicando nuestro paquete en Nuget.org desde línea de comandos

Cuando queremos publicar nuestro paquete, lo primero que vamos a hacer es generarlo, para lo que seleccionaremos la opción “Paquete {nombre de nuestro paquete}” desde el menú “Compilar” de Visual Studio.

Opciones de Visual Studio para generar el paquete

Esto nos va a dejar en la carpeta de salida un archivo “.nupkg” que contiene la librería y todos sus metadatos. Este es el fichero que tendremos que mandar a Nuget.org para que el paquete esté disponible.

Archivo .nupkg en la carpeta de salida
Para poder publicar en Nuget.org, necesitamos tener un cliente Nuget en el equipo, esto se puede conseguir de varias maneras, pero la que nos garantiza poder publicar sin problema, es instalar el cliente completo como se indica en la documentación. Una vez que lo tengamos, basta con un sencillo comando:
nuget push Ruta al paquete\YourPackage.nupkg -ApiKey <tu_API_key> -Source https://api.nuget.org/v3/index.json
Donde los dos parámetros que le indicamos:
  • -ApiKey: Es nuestra clave de acceso al repositorio de paquetes.
  • -Source: Es la URL que nos da el repositorio de paquetes para para enviarle cambios.
En mi caso, como he abierto la PowerShell en la carpeta del paquete, queda algo así:
nuget push NugetColaboracionVNF.1.0.1.nupkg -ApiKey oy2p6bvabu65fjuafebah2oeajh3u5zunjtw6keynpo2uu -Source https://api.nuget.org/v3/index.json
Cuando lo ejecutamos, veremos información en consola indicando que el paquete ha sido enviado correctamente.

Resultado en consola de un envío correcto

Va a pasar un rato hasta que nuestro paquete esté disponible para descargarlo, ya que primero tiene que ser validado por el sistema y luego añadido al índice. Después de este tiempo (nos avisa por email cuando el proceso termina), podemos verlo y descargarlo sin ningún problema.

Paquete ya publicado en Nuget.org

Con esto hemos conseguido crear y publicar nuestro paquete en Nuget.org, de manera que sea posible consumirlo como un paquete más. De todos modos, es cierto que el proceso no es todo lo automatizado que podríamos esperar, y requiere que seamos nosotros quienes nos encargamos de actualizar la versión y subir el paquete cada vez que queramos. En caso de no actualizar la versión y volverlo a subir, nos dará un error diciéndonos que ese paquete ya existe, por ejemplo, si volvemos a lanzar el mismo comando de antes.

Error en consola indicando que el paquete ya existe

Publicando el paquete desde la interfaz web de Nuget.org

Otra opción es utilizar la interfaz web de nuget.org para subir el paquete (con las mismas limitaciones de versiones que hemos comentado y no es automatizable). Esto puede ser útil si no queremos meternos en la labor de automatizar el proceso (aunque como veremos, es muy sencillo).

Para utilizar la interfaz web, dentro del menú desplegable, vamos a “Upload Package”:

Menú para subir paquete a través de la interfaz web

Y dentro del formulario que nos aparece, pulsamos sobre el botón “Browse” para abrir el navegador de archivos y seleccionar el paquete. Una vez seleccionado, se subirá automáticamente, apareciendo tras ello una ventana de verificación con los datos del paquete:

Pantalla de verificación del paquete

Si estamos de acuerdo con todos los metadatos del paquete, simplemente hay que pulsar el botón “Submit” al final de la página.

Envío definitivo del paquete

En cualquier caso, si pensamos que vamos a necesitar actualizar versiones frecuentemente, o simplemente queremos desentendernos de tener que subir los paquetes manualmente, esto se puede solucionar fácilmente utilizando un sistema de despliegue continuo, que sea quien se encargue de identificar la versión y de enviársela al gestor de paquetes.

Si quieres saber cómo puedes hacerlo, facilitándote mucho la vida, como continuación de esta entrada y de mi serie sobre CI/CD, he publicado la entrada:
Además, si nuestro proyecto es abierto, es casi obligatorio habilitar SourceLink para nuestro paquete (si no sabes que es SourceLink, échale un ojo a mi entrada hablando sobre ello), de modo que el código fuente se pueda descargar bajo demanda para que quien utilice nuestro paquete pueda depurarlo. De esta forma podrá ver si el error es suyo, y tal vez si el error está en el paquete te proporcionen información relevante para solucionar el problema.

Esto es realmente fácil, basta con que editemos el archivo “.csproj” y añadamos las siguientes líneas al <PropertyGroup>:
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
<RootNamespace>{NombrePaquete}</RootNamespace>
<AssemblyName>{NombrePaquete}</AssemblyName>
Y el siguiente ItemGroup:
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub"
Version="1.0.0-beta-63127-02" PrivateAssets="All" />
</ItemGroup>
Un ejemplo del ".csproj" completo:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.0</TargetFramework>
<PackageId>NugetColaboracionVNF</PackageId>
<Authors>VariableNotFound &amp;&amp; FixedBuffer</Authors>
<Company>Jorge Turrado Ferrero</Company>
<Product>NugetColaboracionVNF</Product>
<AssemblyName>NugetColaboraciónVNF</AssemblyName>
<RootNamespace>NugetColaboraciónVNF</RootNamespace>
<Description>Paquete de ejemplo para entrada sobre como publicar un paquete manualmente y con CI/CD</Description>
<Copyright>VariableNotFound &amp;&amp; FixedBuffer</Copyright>
<PackageProjectUrl>https://github.com/FixedBuffer/CreacionPaqueteNuget</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/FixedBuffer/CreacionPaqueteNuget/blob/master/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/FixedBuffer/CreacionPaqueteNuget</RepositoryUrl>
<PackageTags>ejemplo</PackageTags>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<Version>1.0.1</Version>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RootNamespace>NugetColaboracionVNF</RootNamespace>
<AssemblyName>NugetColaboracionVNF</AssemblyName>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub"
Version="1.0.0-beta-63127-02" PrivateAssets="All" />
</ItemGroup>
</Project>
Con esto me despido, ha sido un placer poder volver a colaborar con Variable Not Found, y como dije la última vez, ¡si me dejan volveré pronto! 😊
José M. Aguilar> Ha sido un placer tener por aquí de nuevo, Jorge. Continuaremos atentos a tu blog, y, por supuesto, esperamos que te animes más veces a publicar en Variable Not Found.

Publicado en Variable not found.

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

Fixed Buffer

Herramientas de desarrollo: AppVeyor

marzo 05, 2019 09:00

La imagen muestra el logo de Nuget y AppVeyor

Hoy vengo con otra entrada de esas que me hacen ilusión, y es que volvemos a colaborar con José de VariableNotFound, esta vez para hablar de cómo crear paquetes Nuget (con SourceLink, por supuesto), sobre el repositorio Nuget.org, y sobre como publicar nuestros paquetes automáticamente con un sistema de CI/CD como AppVeyor.

En la primera parte de la entrada, que se ha publicado en VariableNotFound hablábamos de cómo crear un paquete Nuget con SourceLink y publicarlo en Nuget.org (si no sabes lo que es, deberías echarle un vistazo a la entrada hablando del tema). Como comentábamos al final, hacerlo a mano se hace tedioso, por eso es una buena idea utilizar una herramienta de Despliegue Continuo (CD por sus siglas en ingles).

En su momento publique en el blog de compañero de trabajo unas entradas sobre AppVeyor en las que explicaba como añadir AppVeyor a nuestro repositorio. Hoy, vamos a continuar aquella entrada añadiendo el CD hacia Nuget.org (aunque repasemos la parte que es común).

En primer lugar, nos tendremos que crear una cuenta en AppVeyor, algo que es muy fácil si tenemos cuenta de GitHub. Simplemente vamos a “Sign in” y seleccionamos iniciar con GitHub (u otros servicios).

Añadiendo AppVeyor a nuestro repositorio

Login AppVeyor

Con nuestra cuenta creada, añadimos el proyecto con el botón “NEW PROJECT”

Señala el botón de crear proyecto en AppVeyor

Y después, seleccionamos el proyecto que queremos, y pulsamos sobre el botón “Add”

Con esto, nuestro proyecto se compilará automáticamente cada vez que hagamos un “push” al repositorio y ejecutará las pruebas unitarias, aunque obviamente fallará porque aún no hemos configurado que tiene que hacer.

Para configurarlo, vamos a la pestaña “settings”

En primer lugar, en el menú “General” vamos a tener que bajar hasta casi el final, y seleccionar “On” en la opción “.NET Core .csproj patching “, con esto, vamos a conseguir cambiar la versión del paquete a la que queramos. Recordemos, qué si intentamos resubir un paquete con la misma versión que uno que ya existe, fallará. Como lo que nos interesa es que la versión se actualice y no se repita, vamos a utilizar la variable de AppVeyor “version“, la cual depende de los campos “Next build number” y “Build version format“, siendo el primero el número de compilación (es autoincremental) y el segundo la versión “Major” que queremos que tenga nuestro paquete, una vez hecho, pulsamos sobre el botón “Save” para guardar los cambios.

La imagen muestra como activar el parcheo de versión del paquete Nuget en AppVeyor

Pasamos al menú “Environment”, en este solo vamos a necesitar seleccionar la imagen de Visual Studio 2017 y pulsar en el botón “Save”.

La imagen muestra como seleccionar Visual Studio 2017 en AppVeyor

Ahora vamos con el menú “Build”, aquí le vamos a indicar como tiene que hacer la compilación, además de ejecutar scripts para preparar los prerrequisitos que tengamos, por ejemplo, hacer un “nuget restore”. Esta es quizás la parte más compleja del trabajo.

Lo primero, seleccionamos la configuración “Release” escribiéndolo en el apartado “Configuraton” al inicio, y después hay que bajar casi hasta el final para seleccionar que queremos hacer un paquete (“Package NuGet projects”), que queremos incluir los símbolos para SourceLink (“Include NuGet symbol packages”), y por último y muy importante (si no, no compilará), añadir un comando previo a la compilación que ejecutará un “nuget restore”.

La imagen muestra la configuración del menú "Build" de AppVeyor

Con esto, tras pulsar en “Save”, si hacemos cambios sobre el repositorio, podemos ver que ejecuta toda la integración continua.

La imagen muestra la salida de la consola de AppVeyor

Configurando el despliegue en Nuget.org desde AppVeyor

Por último, vamos al menú “Deployment”, y añadimos un nuevo despliegue pulsando sobre “Add deployment” y seleccionando Nuget en la lista desplegable. Ahora, simplemente introducimos nuestra API Key, le decimos que no queremos publicar un paquete de símbolos, y por ultimo y MUY IMPORTANTE, como no queremos que se haga deploy de cada push, añadimos la condición de que para hacer un deploy, tiene que ser un push con un “tag”, esto lo conseguimos poniendo como condición que la variable de AppVeyor “APPVEYOR_REPO_TAG” sea true.

La imagen muestra la configuración de el despliegue en AppVeyor

Si con esto pulsamos sobre salvar, y mandamos un nuevo tag al repositorio, veremos cómo al igual que si lo enviábamos manualmente, aparece disponible en Nuget.org. Como siempre, dejo el código fuente en GitHub.

En próximas entradas, hablaremos sobre como utilizar Azure Pipelines como CD además de CI y las ventajas que tiene cerrar el ciclo CI/CD.

**La entrada Herramientas de desarrollo: AppVeyor se publicó primero en Fixed Buffer.**

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

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

Cuerpo Rompe Bolas (C.R.B.)

marzo 04, 2019 02:47

Creo que Risky Woods fue el último juego de PC que homenajeé aquí, y de eso hace casi una década. Hoy vamos a hablar de Cuerpo Rompe Bolas o C.R.B. para abreviar. Estamos a principio de 1990, los PC han avanzado y la mayoría de títulos comerciales con capaces de representar 256 colores en pantalla […]

La entrada Cuerpo Rompe Bolas (C.R.B.) aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

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

Variable not found

Enlaces interesantes 352

marzo 04, 2019 07:34

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

Otros

Publicado en Variable not found.

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

Koalite

¿Qué significa new this() en Javascript?

marzo 04, 2019 05:06

Que Javascript es un lenguaje con un diseño sumamente confuso un tanto peculiar es algo que a estas alturas ya no se le escapa a nadie. Todos conocemos los típicos ejemplos de comportamientos impredecibles cuando se empiezan a mezclar las reglas de coerción de tipos con operadores como +, == o ===.

Aun así, si algo tengo que reconocerle a Javascript es que siempre puedes encontrar algo nuevo que te sorprenda. Lo último ha sido ver código parecido a éste:

const x = new this();

Si viendo ese código ya tienes clarísimo lo que hace, te puedes ahorrar el resto del post. Por el contrario, si a simple vista te resulta tan extraño como a mi, vamos a intentar descifrarlo poco a poco.

this en Javascript

Éste debe de ser el único blog que queda en internet sin hablar de esto, y tampoco quiero profundizar mucho ahora, pero para entender lo que significa new this() primero es necesario recordar cómo funciona this en Javascript.

En lenguajes como C# o Java, this hace referencia a la instancia actual de la clase sobre la que se está ejecutando un método. El valor de this queda fijado por la clase en que está definido el método y siempre será una instancia de esa clase (o de una clase derivada de ella).

En el caso de Javascript, this hace referencia al objeto sobre el que se ejecuta una función, pero al no haber un concepto de clase comparable al de C#/Java (y no, la sintaxis class no significa lo mismo), la cosa cambia bastante porque podemos hacer que una función esté enlazada a diferentes objetos:

function sayHello() {
  console.log('Hi, ' + this.name);
}

const m = { name: 'Marcos', sayHello }
m.sayHello() // Hi, Marcos

const j = { name: 'Juan', sayHi: sayHello }
j.sayHi(), // Hi, Juan

Podemos crear una función, asignarla a distintos objetos, y el valor de this al ejecutar la función dependerá del objeto que la contenga en cada momento. Esto no es del todo cierto y se puede controlar mejor con las funciones bind, call, apply, o usando funciones arrow, pero ahora eso nos importa relativamente poco.

La idea con la que te tienes que quedar es que this no tiene nada que ver con clases, sino que referencia el objeto sobre el que se ejecuta una función, que puede coincidir o no con el objeto en el que se definió.

Funciones y objetos en Javascript

En Javascript podemos crear objetos mediante la sintaxis para objetos literales, como veíamos en el ejemplo anterior, o usando funciones constructoras. Y poco más. La sintaxis “nueva” para definir clases es, en realidad, azucar sintáctico sobre las funciones constructoras, pero se puede traducir a ellas. De hecho, cualquier función en Javascript se puede usar como función constructora si la invocamos con new (aunque a veces eso tenga poco sentido):

function sum(a, b) {
  return a + b;
}

const x = new sum(1, 2);
x instanceof sum // true

Además, las funciones en Javascript también son objetos, por lo que pueden tener sus propiedades adicionales y a las que les podemos enlazar otras funciones:

function sum(a, b) {
  return (a + b) * sum.factor;
}
sum.factor = 2;
sum.incFactor = function() { sum.factor ++; }

sum.incFactor();
sum(1, 2) === 9; // true (1 + 2) * 3

Atando cabos

Pensando en lo que acabamos de ver (y que en el fondo ya sabíamos) sobre this y las funciones como objetos en Javascript, es fácil razonar lo que hace ese extraño new this() que veíamos al principio del post.

Imagina este código:

function Person() {
}

Person.create = function() {
  return new this();
}

const p = Person.create();
p instanceof Person; // true

Si entendemos la función como un objeto y le asociamos una propiedad que es otra función, en esa otra función this se referirá a la propia función y, como hemos visto, cualquier función podemos usarla como una función constructora.

Podemos hacer una traducción aproximada del código anterior a sintaxis de clases y tendríamos el mismo resultado:

class Person {
  static create() {
    return new this();
  }
}

const p = Person.create();
p instanceof Person; // true

Esto funciona incluso con relaciones de herencia, permitiendo tener métodos estáticos cuyo comportamiento cambia dependiendo del punto de la jerarquía desde el que se invoquen:

class Employee extends Person {
}

const e = Employee.create();
e instanceof Employee; // true
e instanceof Person; // true

Dependiendo de si invocamos el “método estático” desde el objeto que representa a la clase base o a la clase derivada, el valor de this cambiará y crearemos un tipo de objeto u otro.

Y todo esto, ¿para qué sirve?

Pues la verdad es que no tengo ni idea, más allá de que resulte curioso para pasar el rato. Quizá en algún escenario en el que tuvieras que simular factorías para una jerarquía de “clases” pueda tener algún uso, pero estoy casi seguro de que siempre vas a poder encontrar un diseño más sencillo de seguir.

Conclusión

Javascript es un lenguaje que tiene muchas pegas, pero la flexibilidad que ofrece hace que en ocasiones puedes encontrar planteamientos interesantes desde el punto de vista de metaprogramación. Al manejar muy pocos tipos de primitivas y tener una frontera muy difusa entre ellas (como el caso de las funciones que también son objetos) puedes hacer muchas guarrerías cosas que son complicadas en otros lenguajes de programación.

A veces incluso pueden resultar útiles, como el caso de crear nuevas clases dinámicamente desde funciones, como vimos al hablar de los componentes de orden superior en ReactJS.

Lo importante, con Javascript o con cualquier lenguaje, es intentar entender cómo funcionan las cosas que utilizamos y no quedarnos con la sensación de ser los más listos sólo porque sabemos tirar un par de pantallas con el framework de turno.

Posts relacionados:

  1. Usando C# para entender los constructores de Javascript
  2. Modificar una clase en Javascript: Eliminar los markers de Google Maps
  3. Javascript: Diferencias entre declaración de función y expresión con función

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

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

GEM y Locomotive BASIC

marzo 01, 2019 04:25

Aunque últimamente he hablado a menudo de GEOS y Ensemble, mi primer entorno gráfico para PC fue GEM (Graphics Environment Manager). Lo vi en un Amstrad PC-1512 de la oficina de mi padre, no solamente los entornos gráficos eran algo super-avanzado en aquella época, sino que además venía con Locomotive BASIC 2, un BASIC interpretado […]

La entrada GEM y Locomotive BASIC aparece primero en Bitácora de Javier Gutiérrez Chamorro (Guti).

» 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