Skip to content

Comment on Building .NET projects is a world of pain and here's how we should solve it

Comments

Building .Net projects cannot really be solved in a way that compares well with nix systems.

- Windows had no programmability until recently with Powershell. On Linux, I can script literally everything from database installs to component updates.

- Powershell. Unfortunately they got their design wrong. Unix is a text and file based OS; you can script any server configuration with tools like awk. Windows apps doesn't have such a concept. To do stuff, you call... duh.. API!*

- The above resulted in millions of programmers not really getting it. Need a component, alright an MSI file. They don't understand how programmability of the environment can vastly simplify the act of programming itself.

- NuGet solves only a part of the problem. For non-trivial projects, there are tons of things that you need to automate besides library references.

In short, Windows is horrible if you have used anything else. And that is by design gone wrong, somewhere in the 90s.

* When they made the decision to build Powershell, they also had a chance to adopt bash or cygwin. I consider this a historic loss; the lack of a familiar/tasteful shell effectively shut (many of) the best programmers out of the Windows eco-system forever.

I am not exactly Windows biggest fan, but one of my pet peeves is talking to a Unix developer who assumes that Windows doesn't do something because it doesn't do it how Unix does it, or who blindly assume that the Unix version is superior by definition of being Unix.

Windows has had programmability for a long time. In Unix, programmability means programs that eat text and generate text. On Windows, it means COM objects. Specifically, most programs--everything from big, end-user focused ones, like Word and Excel, to server components like IIS, to low-level stuff like the Ethernet configuration--is exposed through COM objects. While this was consumable from C++ and Visual Basic since Windows 3.1, Microsoft provides the Windows Script Host, or WSH, since Windows 98 and Windows 2000 (with optional installs back to Windows NT 4 and Windows 95) that allows trivially scripting them using much simpler languages. Specifically, two languages come by default (JScript and VBScript), and plugins exist for every traditional Unix language I can think of (Tcl, Perl, Python, Ruby, and even PHP). You can also use any language that has COM bindings (most of them) to use these interfaces if you don't like what WSH provides.

Is this different from Unix? Yes. Is it worse than Unix? That depends. You can have strongly typed rich data, which is a big improvement on text streams for bigger workloads. You can trivially interact with running applications, which is something that is intermittently available on Linux through DBus, the use of SIGUSR, and the like (program-dependent). You can easily work with data that are not trivially represented by text, like nested dictionaries. On the flip side, I do understand that COM and DCOM are more complicated than text streams, but I think that's a trade-off, not an immediately gimme.

Now, the one thing annoying here is that WSH is based on COM, whereas most modern Windows is based on .NET. .NET allows a much richer object system than does COM, so Microsoft replaced WSH with PowerShell so that users could still use a common scripting language, but easily work with the .NET type system. bash/Cygwin would not have been an appropriate choice here. Modeling PowerShell on those systems was; if you look at the language, you'll find it takes heavy inspiration from traditional shell scripting languages, including bash and Perl, but it differs again due to the focus on objects v. text.

So no, it is not fair to say that Windows is not programmable. I also don't think it's obvious that forcing bash to play nice with Windows would've been better than PowerShell, which would've either resulted in giving up a lot of Windows programmability, or forking bash to work better with the Windows way of doing things--neither an improvement.

Even before PowerShell, Windows had thousands of COM objects in the system that can invoked within a scripting language like .vbs or any language that has APIs for accessing com objects like ActiveState perl. The Windows Explorer shell, Windows Media Player, not to mention Microsoft Office applications, have object models that are exposed and available to programmed against. I am not so sure that UNIX has anything better, since it seems all the functionality that UNIX has is also available in Windows. Then, there is also WMI (Windows Management Instrumentation) objects for all the low-level system operations.

I'd just like to add to this that *nix developers don't appreciate COM for what it really added to windows.

In Linux you only generally call C functions from higher level languages (and sometimes C++). Python programmers use python libraries and sometimes C libraries. Ruby programmers use ruby libraries and sometimes C libraries.

Never will you see someone calling in to a Ruby library from a Python program.

On windows via COM you get Perl calling in to C++ calling in to C# calling in to VB.NET.

So where is the problem? Installing stuff? Yeah, it's not as easy, as for example `sudo apt-get install make autoconf automake libgif-dev libtool g++ gettext libglib2.0-dev libpng12-dev libfontconfig1-dev mono-gmcs git libx11-dev libexif-dev libjpeg-dev libpng-dev libtiff-dev`.

But it doesn't change the fact that everything needs gazillion of other dependencies. I have no problem installing MSI files on production server and then leave it be for couple of years.

I think you can install via script just fine these days.

http://docs.nuget.org/docs/reference/package-manager-console...

Unix is a text and file based OS; you can script any server configuration with tools like awk. Windows apps doesn't have such a concept.

Why is this a problem? Why would I want to use awk when I can use the powershell object pipeline? Do you even know how powershell works?

One problem with powershell is that it's ridiculously slow compared to bash, and the utilities it calls are often extremely heavy compared to unix variants.

Bash (etc) work by passing things around between processes - and there can be many of these processes in a complex shell script, possibly hundreds in parallel, or many more after each other (ever done an `xargs -n 1`?) Of course, that's only ever going to work if each process is fairly light.

As a world-encompassing scripting tool, powershell is also process based. However, it's also .NET based, and many of the sub-processes (such as new powershells or "small" scripts) are themselves implemented in .NET. However, .NET is not a lightweight VM, and many process allocate quite a bit of memory. No OS deals graciously with out-of-memory, but windows is particularly bad - allocated but unused memory must be pagefile backed, so heavy processes cause swap grinding pretty easily. (Linux tries to pretend it has memory until it's written, then kills random stuff).

Another fairly specific problem is that the .NET Regex engine is terrifying slow compared to grep; it uses a backtracking potentially exponential algorithm. Searching and extracting text from files (e.g. logfiles) is a fairly common shell task, so this is a problem. In all fairness, if you're not generating regexes programmatically, and you know the pitfalls, and you can spend time tuning problematic regexes, it's not too hard to work around (but that's still a hassle and a waste of time).

Both of these problems have bitten me in practice. I've had machines start swapping so badly that before you really notice what's going on the mouse cursor freezes (when the OS updates the mouse cursor once a minute, you know you're screwed). I've also have real out-of-memory moments with sudden lockups+bluescreens. Similarly, I've had log-parses take hopelessly long due to the poor regex implementation.

For simple orchestration, powershell isn't too bad, but that's just a subset of what shell-scripting is used for in unix.

Personally, I've got a few CLR helpers and just write scripts in F# or C# now. The regex implementation is no better, of course, but with a "real" language you tend not to rely on regexes quite as heavily since you've got easier access to other tools. And as to performance - if your subscripts are largely .NET themselves, you can stay inside one instance of the CLR the overhead of another thread/task is negligible.

The best programmers are the ones able to deliver what the customer wants regardless of the required tooling.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.