lunes, 7 de diciembre de 2020

Programación mínima, C# vs Python

Por puro divertimento, me ha dado por pensar cuál sería el programa mínimo que podría hacer para un compañer@ que me pide descargar una página web a un fichero.

Para esta prueba voy a comparar a C# con Python.

De Python se dice que es un lenguaje expresivo, es decir, que con una única línea de código Python se hace normalmente más que con otro lenguaje de programación (ni lo confirmo ni lo desmiento, yo creo que esta afirmación estás basada más en list comprehension o en como hacer swap de 2 variables).

Por ejemplo, si comparamos un swap de variables en Python y en C#, a priori ganaba Python, pero C# se ha puesto las pilas y empatan en número de líneas:

my_var = "my_var"
your_var = "your_var"
my_var, your_var = your_var, my_var  # this is expressive
print(my_var, your_var)  # your_var my_var
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var myVar = "myVar";
            var yourVar = "yourVar";
            (myVar, yourVar) = (yourVar, myVar);  // This is expressive too
            Console.WriteLine($"{myVar} {yourVar}");  // yourVar myVar
        }
    }
}

Como el rival a batir es Python, veamos como haríamos la descarga de la página a un fichero:

from urllib import request
request.urlretrieve("https://www.google.es/", "google.html")

2 líneas de código es bien, menos código menos oportunidad de meter bugs.

Ahora en C#:

using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using (var httpClient = new HttpClient())
            {
                File.WriteAllText("google.html", await httpClient.GetStringAsync("https://www.google.es/"));
            }
        }
    }
}

Necesitamos hacer algo, esos malvados pythonistas nos están echando en cara que ellos en 2 líneas han hecho lo mismo que nosotros en 17. Es hora de sacar la artillería pesada, top level statements de C# 9 y .NET 5:

System.IO.File.WriteAllText("google.html", 
    await new System.Net.Http.HttpClient().GetStringAsync
    ("https://www.google.es/"));

Ahora el problema lo tiene Python, con C# lo hemos hecho en 1 línea (si no eres muy de C#, simplemente he partido la línea en varias para mejorar su legibilidad). En cualquier caso ¡menos líneas no se podían!

Habiendo escrito el mínimo código viable para llevar a cabo la tan magna tarea encomendada, todavía nos queda distribuir nuestra aplicación. Para Python vamos a usar pyinstaller y para C# directamente la CLI de dotnet.

Con Python ha sido necesario los siguientes pasos (dejando a un lado el tema de los entornos virtuales) y se ha generado un fichero .exe con un tamaño de 7,23 MB

pip install pyinstaller
pyinstaller --onefile main.py

Con C# y aprovechándonos del trimming, tenemos un fichero .exe con un tamaño de 4,33 MB (más pequeño que en Python)

dotnet publish --self-contained -c Release -r win-x64 -p:PublishTrimmed=True -p:TrimMode=Link -p:PublishSingleFile=true

Bueno, pues me quedo más tranquilo, C# está dando pasos de gigante, hemos sido capaces de escribir el mismo código de Python en menos líneas y con un menor tamaño del distribuible, queda claro que C# es un señor lenguaje y plataforma... y además también expresivo... y Python me gusta mucho, ¡ojo!, es sólo que necesitaba una cabeza de turco.

Un saludo!