четверг, 20 февраля 2014 г.

Tools: Command Line

As stated on my about page, I work as .NET developer in a company producing business software. I believe a traditional C# developer spends most of their time in a feature-rich IDE, which is Microsoft Visual Studio in most cases. However, during recent months I’ve been seeing myself gradually moving some of my activities to the command line, where in fact I can achieve a great deal of my goals at much lower cost than in a modern IDE.

My first conscious moves toward command line took place more than a year ago when I did Java development on my previous job. Like the .NET world has its most popular IDE, Java world has its own guys – for instance, Eclipse. Due to the simplicity of things that I built back then I haven’t faced most of the problems, which Eclipse-based developers lament about, though at some point it turned out that I actually want my job to be done a bit faster and a little different than the IDE allowed to. My primary concern was the need to quickly package a couple of JARs, obfuscate them and put the result into an appropriate place. It was easy to achieve something like this through doing all three steps separately: open project in Eclipse and assemble a JAR, launch obfuscator tool and feed the archive to it, put the result wherever it has to go – nothing complex. On the other hand, both launching Eclipse and the obfuscator took some time, with the additional seconds being spent on surfing through the Eclipse menus as well as locating the desired configuration files for the obfuscator, so after running the scenario several times manually I had no choice except for forming a strong desire to automate it. Because I also wanted to understand what Eclipse does under the hood when I ask it to compile the project I got some ant manuals and started automating everything away. In a couple of days I had what I wanted: I could open Powershell, type in ant ship and it would quickly do all the above steps on its own, so that I have only to decide what should be done with the obfuscated JARs. The economy of time that it awarded amazed me so strong, that I even went further and included into the build-file such targets as test and testncommit so that I could not only run tests from the shell, but also check changes into Mercurial in case the tests pass – sort of continuous integration on a single-man project. What made me stick with the command line then was the fact that it could save me from navigating through multiple IDE’s windows in addition to merely running things a bit faster.

Next time I searched for help from the shell during the work on my diploma project. At some stage of a major refactoring I still had a dozen or so very long and slow tests for fat components, which I was going to replace later. Since these classes were not touched during the most days until the time has come to deal with them, there was no reason to waste time on their tests during each run. However, it turned out that one cannot simply ask Visual Studio 2012 tests runner to ignore a couple of TestClasses or TestMethods. In addition to this, the IDE didn’t always successfully discover all the tests upon rebuilding. These little issues made me search for better options and thus find the vstest.console.exe tool, which simply runs the tests from command line. Not surprisingly, it allows to filter the tests being run, for example, by test classes names – that was precisely what I wanted at that moment. A nice thing to mention is that while the command required to run vstest utility with certain tests library and filters is quite long and awkward, most shells, including the PowerShell, allow one to set up different aliases to save some typing, so running tests becomes easier and faster than from the IDE – in addition to providing broader functionality.

Maybe the strongest push in the direction of command line I got from Visual Studio 2012 for C++, when I was experimenting with Cinder graphics library. Here the blocker was the environment’s speed: VS did everything deadly slow – sometimes so slow, that it was literally impossible to put in a line of code. I spent some time on tuning precompiled headers, which helped with compile time and even seemed to improve the situation in editor, still the state of affairs remained awful. What made me finally close Visual Studio and turn to compiling like msbuild.exe MyProject.vcxproj was the fact that in an attempt to increase the speed of IDE and fight the horrible lags I had turned off IntelliSense. While it didn’t help much with the original goal it made me ask myself why do I want to stick with the environment if I get no assistance from it? With quite modest support of C++ in the IDE part of Visual Studio (or without it after disabling IntelliSense) I merely could not find a reason to stay in the slow environment when I could switch to the Sublime + PowerShell combination boosting things considerably. I acknowledge that my Acer Aspire P3 slate with i5 processor is not a powerful machine, while C++ is more difficult to handle than, say, C# with which I did not face such awful quirks – I can even assume that it would be faster should I use a Professional version of Visual Studio instead of the Express one. Nevertheless, I can’t believe that it is so bad that not being able to enter a line of code in the editor for 5 minutes (let alone the timeframes when it builds the project) is considered OK. On the other side, once you turn to the shell, you are able to get binaries in a matter of several seconds after typing in the msbuild.exe MyProject.vcxproj command. In case you change the contents of the precompiled headers, you’ll have to wait a bit more, but at the same time you are not blocked by the build process and it won’t prevent you from looking through your files or switching to the browser. In contrast, if you build from Visual Studio, the only option you have is to get some coffee and take a walk, because it somehow manages to slow down the entire system significantly. This is another crucial characteristic of the command line tools – they tend to do precisely what you ask for, while the complex and shiny IDEs in their pursuit for the users’ satisfaction seem to be doing lots of stuff behind the curtains even when you don’t ask for it. Furthermore, since IDE has this beautiful and handy user interface, it also has a great option of doing some hard work on the UI thread, thus making user face unresponsive windows and feel frustrated, because their own tool stands in their way to getting the job done.

Another area where I quite often use shell-based tools instead of IDE functionality is talking to TFS. One particular example is checking out a file for edit. When the desired file belongs to a solution you work on, the task is pretty easy to accomplish in Visual Studio – you just locate it in the Solution Explorer and chose check out in its context menu. The situation, however, gets a bit worse if you want to edit a file, which is not included into any solution at all – just a file in the repository. In this case you have to open the Source Control Explorer thing, navigate it to the desired file (as far as I remember, unlike Solution Explorer it has no handy Search function) and check it out through the context menu – that is in fact a bit too slow because you have to switch to a certain window and do some folders joggling there. Does command line have something on offer to make the process easier? If you are used to navigating the folder trees like ‘first 2 letters of the desired folder – TAB, … ‘ then absolutely yes, because all you have to do to check-out a file through the command line is type tf checkout path/to/your/file.extension. Although, this is not that significant problem of the IDE and, in fact, I can hardly imagine the way it could have been done better, there are other tasks where Visual Studio clearly sucks in terms of working with version control – most notably, merging.

Since we support several versions of our product, merge is frequently used on a changeset basis, where you fixed a bug in one version and want to merge the fix into another one. What you have to do to accomplish this in Visual Studio is going to cause some pain, because before letting you pick a changeset the IDE will first ask the server for the entire list of those available for merging between the selected branches (or locations inside them). Moreover, in my experience the process of assembling this list sometimes takes up to a minute and in case there exist broken changesets it may finish with a failure message not letting you merge anything. Now, let me ask you a question: why would one want such a list of merge candidates in case they’ve just checked-in the changeset, which they want to merge and know its number? Why couldn’t there be a Merge button in the Changeset Details window in Visual Studio? I don’t know the answer to the second question, but I am pretty sure about the first one – I don’t need this list at all, because I can go and type something like tf merge 4_10 5_00 /version:C159001~C159001 /recursive in the shell and it will instantly merge the changeset 159001 from branch 4_10 to branch 5_00 if that is possible. Certainly, this example does not serve to prove that command line is vastly more powerful than IDEs – instead it just highlights the fact that there are ways to go in making the developers’ tools better and sometimes one doesn’t have to go very far to introduce a major improvement.

Overall, my programming activities, even those started in powerful modern IDEs like Microsoft Visual Studio, sooner or later led me to doing at least a portion of work in command line. While there were always serious reasons for switching from the fancy windows of the former to the awkward, 80s-style text-based environment of the latter, I still don’t believe that this is a sentence to the IDEs and their developers. Instead, I think programming environments are just in the process of becoming better and easier to use tools and sometime later, particularly when the human-computer interaction technologies will afford that, IDEs will give developers as much power and freedom as shells do for several decades already. Still, currently command line offers significant advantages and here are just some of them:
  • Shell is a lot faster;
  • It’s more controllable and does precisely what you ask for, leaving out a lot of yak shaving;
  • In some sense it is easier to navigate;
  • Shell also serves as an entry point to a great deal of things, including your text editors, compilers, diff tools, revision control systems, testing frameworks and whatnot;
  • It allows to set up and hold a piece of context through the use of aliases, functions and variables, which also means that shell is quite customizable;
  • Command line keeps your fingers at the keyboard, which is especially important when coding – even the numerous hotkeys in an IDE can hardly compensate for this;
  • And finally, yes, shell gives one a feeling of being a hacker in one of those legendary movies from 90s. 

What makes you trade a comfortable IDE for a good old command line? Are there any particular tasks that you can’t accomplish in the modern environment, but which are crazy simple to do in the shell? Or maybe you never had to leave the IDE because it satisfies all your needs and never stands between you and your goals? Please, share your opinion!

Комментариев нет:

Отправить комментарий