It was December 11th, 2012, and I was scared. Not because of the impending Mayan apocalypse, mind you, but because it was my first day doing something completely alien to me: developing software on a new platform, a new language, and having a completely new product to deliver.
That’s a lot of change to handle at once.
Looking back, .NET development would probably be just as scary to a seasoned Python developer as it is the other way around. At least I hope so, because Python development was initially very scary to me.
.NET development is based (almost) singularly around Microsoft’s tooling, and Microsoft has deep pockets, so they can spend money on marketing and great documentation. Where their documentation fails (and it does fail — who wants to study method signatures all the time?) the MVP community takes over and writes eloquent blog posts about some esoteric part of a new framework that behaves quite unexpectedly.
There are certainly not a lot of popular web frameworks in .NET. If you’re in the corporate world (hello, 80% of you), you’re likely either on Webforms or ASP.NET MVC. That’s a really small playground comparatively, making it much easier to ‘ramp up’ (especially if you include the sheer number of questions on Stack Overflow regarding those frameworks.
In Python, you’ve got a number of smaller frameworks, with Django as the BMOC. Django’s documentation is a complete 180 from MSDN, with an emphasis on prose over method signatures.
With .NET, the answer is normally a code sample away. With Django, it could be a code sample away, but normally it isn’t, it’s buried in some prose. An example that comes to mind is formsets, which were (unluckily for me) one of the first things I had to deal with in Django.
With Python development, you necessarily have access to the source code. For instance, you can read through the source code for Django on github, or if you have a neat editor like PyCharm, you can simply click to view it (much in the same way ‘Go to definition’ works in Visual Studio).
For Windows based development, the toolchain normally looks like the following:
- Visual Studio 2010/2012
- TortoiseHG (or Git for Windows)
- ReSharper (a must have. Really.)
- SQL Server Management Studio (regardless of DB location)
- Terminal Services (Remote Desktop)
- A really beefy machine. Really Beefy:
- 8-core Intel i7 @ 2.93 Ghz
- SSD (in my case, a 120 GB)
- 8 GB Ram
- Nvidia 9600 (For dual monitors)
For Linux based development, (at least in Python):
Almost the first thing I noticed when starting out with Python development is just how easy it is to debug. In .NET, the workflow is:
- write code
- run unit tests (you do have those, right? RIGHT?)
- wait for application to JIT on IIS (or reset IIS and then wait for application to JIT if you’re using Spring.NET or some other DI/IoC that hangs out in resident memory)
- find error
- start all over again
Even on the beefiest of machines, that entire loop is still at least two minutes (I’ve seen it take as long as 5 minutes on larger solutions). That’s a long time to be staring at a screen.
In Python (specifically developing in Django), here’s the workflow:
- write code
- save code
- refresh website
- find error.
Time? About 10 seconds. Maybe. That’s an incredibly fast turn-around time, and makes unit testing less attractive (that’s not the only thing, which I’ll get to later).
What makes the workflow in Python so spectacularly different? It’s the nature of the beast. While Python isn’t strictly interpreted , it still doesn’t have the overhead compiling a .NET assembly has.
Another difference in Python development is just how easy it is to write scratch code (I’m thinking specifically of Django’s “shell_plus” module, but the same holds true with iPython):
It’s literally one command:
python manage.py shell_plus
And that command drops you into a REPL that has all the items in your Django project imported. Need to load a model? It’s already there. This somewhat reduces the need to use unit-tests as scratch code. You can test behavior in the shell, and then add it to your program.
Database development in Django is completely different than in any .NET project I’ve ever worked on. Django has its own built-in ORM, and the mere act of creating a model creates a Database table. With the South migration library, you can even version control your database and it’s all in one place. It’s simple to set up, and compared to the .NET model of database development, it’s painless. But it’s not without its own problems:
– The default is to have your Model objects be Django DB Model objects, and that means they’re bloated, ugly, and carrying around persistence information. This complicates unit testing (and unit testing is no longer unit testing when you bring in a database). If you want to get around that, maybe with a Functional Core, Imperative Shell model, you have to do *a lot* of work. I’m currently trying this approach on a personal project, and it *sucks*.
– Unit testing a Django application is not unit testing. By default, it pulls in your entire database. That’s integration testing. SSDs are required if you want your ‘unit tests’ to be fast, because Django is happily spinning up a database for your tests.
In .NET, database development reminds me of building a house from scratch *every*, *single* time. There have been improvements with the Code First Entity Framework stuff, but nothing as turnkey as Django’s ORM.
Deployment wise, .NET deployed applications don’t need as much scaling out of the box for large sites as Python/Django projects do. The deployment tooling for python projects isn’t as great as some of the solutions for .NET (I’m thinking of Jenkins vs. Octopus for .NET). I’ll get into deployment tooling for Python in a later post, but essentially it’s built for developers to deploy, not for *anyone* to deploy.
Overall, I’d have to say that .NET and Python development have different strengths. Neither side has a clear advantage over the other, at least for *large* projects.
In Part III, I’ll talk about my Development set-up, and why I’m moving to Mac OS X for Python development.