Monday, September 29, 2008

Vim C# Compiling

This is the first post in my series on using Vim to do C# development. You can read the introduction into why someone might want to do that here.

The most important thing to be able to do comes in two parts:
  1. Compile
  2. Step through errors
In college we did development in Java without any kind of IDE. So you typed in your text editor. Then switched to the DOS prompt and "javac"ed. When there were errors, which there always were, you opened the file with the error and navigated to the line where it occurred. This was slow and tedious, but not the end of the world. Until you get used to Visual Studio and being able to F5, and then simply double click on an error.

How do we do the same thing in Vim? First, we have to compile. To start with, I'm going to compile using the following command:
devenv slnname.sln /Build Debug

This will perform the build exactly like Visual Studio would, just without opening Visual Studio. I put this command in a .bat file in the same directory as the .sln called build.bat.

To get Vim to use this batch file to compile:
set makeprg=build.bat

Now from within Vim just type :make when your current directory (:cd) is the one containing the build.bat file, and your solution will build.

What about parsing out the errors? Easy:
set errorformat=\ %#%f(%l\\\,%c):\ %m

This tells Vim how to parse the error output.

Now if there are errors, hitting Enter will take you directly to the file and line where the first error occurred. :cn will take you to the next and :cp will take you to the previous. :cl will list all errors. Read :help quickfix.txt for more.

You could also use msbuild to compile your solution. The command for this is simply msbuild /nologo /v:q. It will find the .sln in the current directory and build it for you. However, with this command you have to modify your .csproj so that the error output includes full paths (otherwise the errorformat wont be able to parse it). To do that, just add the following line to the common PropertyGroup element of your .csproj:
<GenerateFullPaths>True</GenerateFullPaths>

The error format is the same as for devenv. But you don't need the build.bat (if you will always have only one solution in the directory at a time), instead you can use this:
set makeprg=msbuild\ /nologo\ /v:q

Now you can happily compile C# solutions and step through errors from right inside Vim.

If you don't like having to add the GenerateFullPaths node to your project file, you can add it to the msbuild command line instead as follows:
:set makeprg=msbuild\ /nologo\ /v:q\ /property:GenerateFullPaths=true

There is one more enhancement we can make. Vim has the ability to easily switch between compilers and set all the settings that the compiler needs as part of the switch. You can enable this by creating a "devenv.vim" file in vimfiles\compiler (on windows) containing the following code:
" Vim compiler file
" Compiler: DevEnv

if exists("current_compiler")
finish
endif
let current_compiler = "devenv"

if exists(":CompilerSet") != 2 " older Vim always used :setlocal
command -nargs=* CompilerSet setlocal <args>
endif

" default errorformat
CompilerSet errorformat=\ %#%f(%l\\\,%c):\ %m

" default make
CompilerSet makeprg=build.bat

To use this, just type :compiler devenv. Or, if you want Vim to always use this anytime you're editing a C# file (a file with a .cs extension) add the following to your _vimrc:
" setup C# building
if !exists("autocommands_loaded")
let autocommands_loaded = 1
autocmd BufNewFile,BufRead *.cs compiler devenv
endif

If you have any improvements to add, please let me know in the comments!

Sunday, September 28, 2008

Visual Studio Development

When I work on C# programs (which is what I do for a living, so I do it a lot), I work in Visual Studio. Currently, that means VS2008.

VS has lots of wonderful features, including:
  1. Intellisense
  2. "Go to definition"
  3. Integrated building and error output parsing
  4. Integrated debugging
  5. Solution/Project management
  6. Windows Forms/WPF designer
  7. Basic Refactoring
You can add Re-sharper, and then you get more, including:
  1. Compile as you type
  2. Code form suggestions
  3. Find file by name search
  4. Find method/class by name search
This is all wonderful, but it comes at a price. Namely, speed. Because VS can't possibly know when you're going to want what features, it has to prepare them all continuously. This means opening a solution takes forever. Opening the designer takes forever. Building takes forever. Add Resharper and your problems just get worse.

It's a trade-off. Lots of people are willing to sacrifice speed for the convenience of these features. Until recently, I was one of these people.

A lot depends on the kind of work you do. For awhile now, my kind of work has had me opening and closing different solutions many times through out the day. As well as having multiple instances of VS open at the same time.

First I got rid of Resharper. I had to. There were times when I could type faster than the letters could appear on the screen because it was busy compiling my changes. Plus, I realized that I didn't like it's implied style of development. With Resharper, it's assumed that the code you're writing should be perfect the first time. So it's always formatting it for you, and suggesting shorter ways you could write it, or pointing out that you could move this variable from here to there, etc.

I discovered that I don't write code line by line, I write it in "logical units", working through the details. Then I go back and make everything perfect when I'm satisfied with it. My mind is on more than just the one line I'm currently typing. I'm thinking about the whole thing. So when Resharper wants me to stop and think about some minor code form improvement, or when it suddenly moves my code around "formatting" it, it only serves to distract me.

So Resharper had to go. I did miss knowing that I'd typed an error without having to wait for a build. And I also missed being able to open a file by just typing it's name in the search box. But I found those to be very minor niceties overall.

There's this article that Steve Yegge wrote called Effective Emacs. He talks about all kinds of minor little Emacs details. But his larger point is that because he knows how to use Emacs so well, and because it does only what he asks it to, he is very efficient with it.

This got me thinking about Visual Studio, and all the time I spend waiting for it, or clicking around looking for things (files in Solution Explorer, methods/classes in Intellisense). I realized that the power of Visual Studio is that it tries to do so much for you, and hide so much (mostly) irrelevant detail from you. This makes it easier to learn how to develop things. And it can also save you time by generating code, and build scripts, etc for you.

Intellisense is the best example of this. It's always guessing what you're probably trying to type. This is great because it helps remind you what the full method names are, or what parameters they accept.

Visual Studio's whole goal in life is to require the programmer to do as little work and put in as little effort as possible. On the surface of it this seems great. But I suspect that less work and less effort doesn't always result in greater productivity.

For example, it's easier to randomly click through Intellisense, looking for something that might do what you want than it is to look up documentation. But the documentation is more likely to show you the right way to do what you're looking for, and explain it to you. You just have to put in more effort reading through it.

So, wouldn't it be better in the long run to use a tool that is very powerful, but stupid? Allowing you to do exactly what you want, but not trying to guess what you want, and not trying to do it all for you?

It seems quite clear to me that if you're willing to put in the effort, you could get a better development experience using something other that Visual Studio. You'll spend less time waiting for VS to do things for you, and more time thinking about just how you want to do it. You'll get to state what you're looking for, rather than clicking all over trying to find it. Basically, your mind will be more actively engaged, instead of passively waiting for VS to solve problems for you.

I'm not suggesting that Visual Studio is worthless. I'm just suggesting that there may be times when using a different tool would be better, and other times when VS would be better. Why not figure out what those times are, and use the right tool at the right time?

I've been working on that. My tool of choice is gVim, because I know it the best, and I like the modal editing concept better than shortcut key acrobatics. I'm going to write a series of posts documenting everything I've done to try and use Vim to develop C# in an environment where everyone else is using only VS.

In the meantime, let me know what you think about the idea of VS = least possible effort != greater productivity.

Links to Posts in Series:
Vim C# Compiling
Vim TFS Integration
Vim Intellisense
Vim Help Integration
Vim Snippets
Vim Code Folding
Vim to and from Visual Studio
Vim File Editing
Vim Learning
Vim File Navigation

Monday, September 22, 2008

MVC and MVP

Do a google search for MVC MVP and you will find no shortage of posts on the topic.

If you want pictures and diagrams and code samples I'll let you do the Google search. But, in brief, MVC stands for Model View Controller, MVP stands for Model View Presenter. What's the difference?

There is no difference! Well, if you look at it in enough detail, you'll be able to come up with all kinds of stuff, but if you look at the overall picture, there's really no practical difference.

Ok, I knew you wouldn't be happy with that answer... In MVC the View is stateless. When you interact with it (by clicking a button, for example) that action is forwarded directly to the "Controller" which then renders a new View.

In MVP, the View may or may not have state. In either case, when you interact with it the View handles that action (aka, the View has hooked into an event) and forwards the action into a call to the "Presenter." Unlike in MVC where a new View is rendered, in MVP the Presenter has to cause the View to update somehow. This can be done with data binding, or by the method on the Presenter returning data that the View parses, or by the Presenter raising an event that the View receives, or even by the Presenter calling a method on the View...

There is one other element. In MVC, there is a Controller for every View. In MVP, you don't strictly have to have one Presenter for every View. You could have many Presenters per View. You could have a Presenter for every "Control" in your View. Or you could have a Presenter for logical regions of your View.

In the end, the View is the same in both cases: it displays stuff. The Model is the same in both cases: it represents the data. And the Controller/Presenter is the same: it does stuff that the user asked for.

MVC is very applicable to the web, where actions on the rendered html page "post back" to the Controller on the web server.

MVP is very applicable to Windows Forms and WPF where actions on the Form/Window raise events which delegate the majority of the work to the Presenter.

Clearly, these patterns are pretty simple. But they get a lot of attention, and there is a lot of confusion surrounding them. Partly this is because Computer Scientists all have a bit of the Martin Fowler syndrome in them, so we feel like we need to classify everything. We like to have everything all lined up and tagged and placed in the right pigeon hole. Sometimes this is a good thing, other times it can lead to a "can't see the forest for the trees" type of problem.

But mainly, I think these patterns confuse people because they're named horribly. In MVC, the Controller doesn't control the View. The word "controller" invokes an image of a puppet master pulling the strings. The Controller is much more hands off than that. It's really more like an Interpreter or a Router which says, "Ah, I see you clicked the Send button. Allow me to route that to the proper sending authorities, and then I'll send you a new view." So while it certainly does control the application and how the view responds to action, "Controller" is just too loaded of a word.

In MVP, I really can't understand where the word "Presenter" came from. Maybe it's supposed to make you think of a presentation where the Powerpoint slides are the View, and the person talking and moving the slides ahead is the Presenter. But in reality it sounds more like there are two views... I think of the Presenter more like a Calculator. You're working out some equation on paper (the View) and using a calculator to execute certain functions for you, the results of which you record on the paper.

In the end the titles get in the way. What we want is a way to separate as much of our logic as we can from the display. This allows us to do a few things:
  1. Test our logic with TDD
  2. Change the display without requiring huge changes to our logic
  3. Change our logic without requiring huge changes to our display
At least, this is how I'm looking at it right now. I reserve the right to learn something new tomorrow and start from scratch.