Why I swapped C#.NET for Python as my default language and platform (and won’t be going back)
I’m not a “professional developer”, I never have been. I’ve been a tinkerer, hacker, innovator and (at some point) a product manager. I don’t code for money, I code for fun and I innovate for money (which involves a lot of coding).
I just took my SurfaceBook back to the Microsoft store after a tormented 6 months of issues and frustration and I realised that I don’t use Visual Studio anymore, I don’t develop in C# and Python is now my tool of choice. This wasn’t a totally conscious decision, I’m lazy, I use whatever helps me get the job done quickly and somehow I’ve gone from 100% C# to 100% Python.
Let me explain some retrospective reasoning. I’m sure most developers don’t have the luxury of choice, but this article is more trying to encourage C#.NET developers to give Python a go and never take mediocre as an option.
The Web ecosystem is single-track in C#.NET
Microsoft .NET is both the core-libraries and the CLR. C# itself is a language which has it’s own compiler that creates CLR executables. In 2016, I want to create my applications as small, reusable packages, or as a service or API that can be used from a UI. When I make the UI for a service, I seperate the responsibility of controlling the backend and the front-end into seperate projects, so that I can provide REST APIs to consumers.
In the .NET ecosystem, Microsoft provide the tools, and you must eat your vegetables.
In 2011, there was WCF (formerly ADO.NET) Data Services for REST-ful applications, then in 2013 we had OWIN in Katana, which replaced the entire stack with a lightweight version.
Then in 2014/2015 we had ASP.NET WebAPI, then ASP.NET WebAPI 2 (with some breaking changes).
Then we had ASP.NET 5 WebAPI (which changed its name to ASP.NET Core) and now ASP.NET MVC 6 (or Core?). Each and every time, the interfaces change, the namespaces change, the contracts change, the best practices/common practices go totally out of the window. Any ‘reusable’ modules you made for logging, metrics, authentication have to be thrown away and rewritten.
It gets quite tedious.
So, they should just stop evolving? Well, no, but creating a service that receives HTTP/RESTful messages and executes some code is a fairly well known and understood problem. Following Microsoft’s API ecosystem continued change of skirt is time consuming and costly, with little or no benefit to my application.
With Python, I can choose which REST framework I want to use and stick with it. Some are really simple and lightweight, like Flask, Bottle or Pecan, some are feature complete, like Djang0-REST.
I pick one, I learn it and I stick with it (I picked Flask-RESTful)
I can never find the libraries I need on NuGet.org
I wanted to write a small app that starts a docker container and orchestrates some cloud services. So I considered using Rancher, Kubernetes and CoreOS Fleet.
In C#.Net on NuGet.org
- Kubernetes gave 1 package- KubeNET, which is an autogenerated library with no documentation
- Rancher, Fleet- nothing
On pypi.python.org I get a list of options, most with some documentation and licenses included.
- Kubernetes — kubernetes-py, pykube, kploy, python-kubernetes. I looked through and found the one that had the best API and documentation and met my license requirements
- Rancher — Rancher-metadata, cattle-prod, cattle
- Fleet -FleetPy, PyFleet and Fleet
OK, so if I stick with .NET I have to write my app and also publish a client library for whichever tool I use. This has been the same for my NLP work, the IoT/hardware work I’ve done.
NuGet.org is full of abandonware and unlicensed libraries
The top-10 packages on NuGet.org at the time of writing are:
Newtonsoft.JSON, jQuery and EF6 are Open-Source (MIT, EF6 is Apache2), System.IO, System.Reflection and System.Runtime are Microsoft.NET licensed projects (as-is). There are a lot of non-licensed or closed packages on nuget.org. When I hit and issue, I want to fix it, raise a pull request and improve the ecosystem. The status-quo in nuget seems to be a fire-and-forget style of package publishing.
On PyPI, the picture is a little different, almost everything is open-source, community projects. The most popular projects tend to have multiple contributors and fairly well maintained. There is still a lot of abandonware, but its more infrequent (and you can tell in the website). Getting package maintainers to republish packages once they have accepted fixes is also a little challenging.
People don’t seem to bother documenting .NET packages
In Python, you have Sphinx, the default cookiecutter templates tend to have a docs folder, a tests folder and your source code. You can publish to ReadTheDocs with fairly little hassle. As a consequence, a lot of the packages I pull off PyPI are documented (with varying quality).
For .NET, I managed to generate code-docs from a series of powershell, XML stylesheets and some magic in AppVeyor (https://github.com/tonybaloney/St2Client/blob/master/appveyor.yml) but it was a pain. Apparently I’m the only one who’s ever bothered trying to create simple library documentation automatically for NuGet.
.NET on any other platform than Windows doesn’t work
I don’t really need to explain this one, but Linux is a real thing, people use it. It is inevitable that I come across something that is built for Linux only, then I have to ditch .NET. Yes, DotNetCore is going to cure world hunger, but it takes a long time to get people to think about other operating systems (and file systems). Just getting the executable to run is only a fraction of the problem.
Things I don’t like about Python
Python on Windows is still kinda-sucky. I come across packages that assume I’m running on Linux (and try and create a process thread of a Linux binary that doesn’t exist). The Ubuntu subsystem for Windows will close that gap.
The whole Python 3/2 thing is irritating. I always start my projects on 2, I contribute fixes to libraries that are written in 2 to add 3 functionality and I still hit roadblocks and default back to 2.
Things I miss in C#.NET
ReSharper. Functioning libraries for Azure. NCrunch.