Once again this year I wanted to have something to amuse me while on holiday. This time I did tell some of you in advance what I planned to do (although to begin with the ideas were very vague).
Now I need to explain to you how this worked out. I created a branch in which to do the work (#768).
Goal
The goal was to improve the experience of code development and debugging in the Visual Studio Express environment.
Actually the goal was not too ambitious because the current experience of using Visual Studio Express is a bit grim. It is not possible to start OpenPetra Client in debug mode because it soon falls over, and Visual Studio Express (I am told) does not have ‘Attach to Process’. At least the fully-paid-for version that I use does have this feature, so I have been using Visual Studio for my last two branches. I think when I first started coding OpenPetra there must have been something with the SharpDevelop (SD4) projects that meant that you had to debug using Attach To Process in that IDE as well. So as far as the debugging method is concerned, for the last year it has made no difference to me which IDE I used. But I became aware since I started it has become possible to debug in SharpDevelop by simply launching the debugger using the green arrow button – but that was not possible in the VS Express IDE. So that became my starting point.
Background
Some of you will already know this (because you probably wrote the code) but there is some C# code that creates the project and solution files that you find in the delivery folder from ‘templates’ which vary slightly between IDE’s. The three IDE’s we support at present are MonoDevelop2, SharpDevelop4 and VS2010.
Debugging Using VS2010
Fixing the problem of running OpenPetra direct from the Visual Studio IDE required a very small change to one of the VS2010 templates. Whichever IDE you use requires that the debugger command line has our configuration filename passed as a command line parameter. This command line parameter section of the template file is in a different section for VS2010 from where it is in SharpDevelop4. Getting this right now means that I can launch OpenPetra client using the green arrow button in the VS2010 IDE and hit any breakpoint I like to set – so in one sense I had immediately achieved my original goal.
I have to say that one of the most significant differences I have noticed between SD4 and VS2010 is the speed with which the IDE displays the value of variables while debugging. In SD4 it seems to take even 30 seconds to populate the little tree view windows that allow you to drill down to see the value of a variable. In VS2010 it is instantaneous. Is this just me or do you find this too?
Adding YAML Files to the Project
I am a great believer that all source files that are under source code control and required by a project should be included in the project. This is because the IDE tries to be just that – an Integrated Development Environment. So in our case this means that, by having the YAML files as part of the project they become part of the IDE and you edit your YAML and then edit the C# code (and then continue to debug) all inside the IDE. So having found out how the project code generation worked, I set about making the YAML files part of the projects.
I have to say that doing this is really nice. All the files you need to work on for a particular screen are all in one place and double clicking brings up the file in the editor where it becomes easy to flick from one IDE window to another. (This is another difference between VS2010 and SD4: in VS2010 the windows are all numbered on the Window menu. So the previous window you were working on is always Alt+W 2 and the previous one to that is Alt+W 3. I remain totally defeated how to easily get back to the previous window in Linux-based software, but maybe again the problem is me.)
This also makes the creation of new screens based on existing ones quite a simple process. You choose your starter screen and make copies of the YAML and ManualCode files, giving them the new screen name. Then, using the Developer’s Assistant you build the C# files from the YAML (to get the –generated.cs ones). Then you use the Assistant to generate the solution with no compile – and the project is re-generated with all your new files as part of the project (it takes about ten seconds). Now, in the IDE, you set to work on the actual code and compilation. So there is no need to add files to the project yourself. You just let the automated code do it for you from the files in the folder!
Just in case you do not like the idea of including the YAML files in the project, I have only modified the VS2010 template at the current time. But I can’t really see any reason why you would not want this in all IDE’s.
Other Miscellaneous Files
I then took the same line of argument and extended the approach to other useful files. These can be added to solutions. In this category I included the UINavigation file and the CacheableTablesAndLists file – both of which I have needed to modify in work that I have done this year.
Here you can see that I have added a Definitions folder to the solution in which I have placed the two files. This applies to the OpenPetra and OpenPetra Client solutions. For the OpenPetra Server solution I just add CacheableTablesAndLists. For Tools and Testing I do not add any files.
If you like this idea, you may want to suggest other files that would be good to have in the IDE.
As above, at present this feature is only in the VS2010 template collection until you agree you would like it in SD4 too.
YAML Forms Preview
I then took a break from project code generation and started on the Developer’s Assistant. As you know, Timo has provided a valuable new feature to aid screen development, by which it is possible to preview new screens while in the screen layout stage of development.
So the Assistant now has a new button to launch this task.
Application Icon in Project Definition
Up to now the project files that we generate do not have a section to specify the icon to use for the executable file name – the one that shows in the taskbar and in Windows Explorer. This has been one of the main reasons that I have sent you my build of the Assistant because I have kept a separate project file that does generate the icon in the exe.
So now I have added the required section to the project template so that
• If the project generates a WinExe, and
• If the project folder contains an ICO file
then the generated project uses the ICO as the application icon.
As a result I will be happy to stop using my ‘project on the side’.
This template change has been applied to all three IDE’s but certainly needs testing in Linux. Can you also have a think whether there are any EXE projects that have an icon file that you would not want to be applied to the EXE?
Pre- and Post-Build Actions
This last item is the trickiest to explain – so bear with me! Any project can have an optional pre- and/or post-build action, which is typically to run a script or an executable file. Since my goal was to make the whole code development and debugging cycle as seamless as possible, I needed to add a pre-build action to stop the server and a post-build action to start the server. So the development cycle goes like this – and I am assuming that you are working on the OpenPetra or OpenPetra Client solution since I think that is what most of us do.
First you edit code somewhere in one of the projects that you want to test. You set a breakpoint so that when the program gets to the new code you can step through it.
You want to click on the green ‘start debugging’ button, which is going to compile the project and launch the debugger. But sometimes the recompilation will involve shared code with the server and, if the server is running, this fails because the new DLL’s cannot be copied. So what is needed is a pre-build action on the first shared DLL to be compiled that will stop the server. (It is never that easy to predict if the IDE is going to need to recompile shared files.)
Once the whole build completes successfully the debugger launches the client application – and log-in to the server fails because the server is not running! So what is needed is a post-build action on the client EXE that starts the server before the debugger starts.
With these two actions it becomes possible to ‘live’ in the IDE and edit code, set a breakpoint, run, debug, stop, edit and go round again. When you combine this capability with the features I mentioned earlier of having all the code that you need to edit as part of the project inside the IDE, I hope you can begin to see that I came a long way towards my goal that I started with.
So how have pre- and post-build actions been implemented?
First you need to understand that they belong to a specified project. So my pre-build action applies to the Ict.Common project and my post-build action applies to the OpenPetra Client project.
Second, this feature only applies to project generation that is launched from the Developer’s Assistant. This is not a ‘Nant’ feature (mainly because I am not very familiar with Nant) but is activated by ‘Environment’ variables that the Assistant sets up before launching the Nant task. So you cannot set up these actions by running in the DOS window. You have to generate the solution files using the Assistant.
Third, you have to think carefully about the consequences of these actions. Take the action to stop the server, for example. This action is part of the project – so the action occurs whenever the project is built. In the case of Ict.Common, this project actually gets built several times because it is part of several solutions – so every time it is built, it wants to take the action. This is not really the true purpose. Our purpose is just to do it when we compile inside the IDE.
So, as a result of these considerations, I have implemented the functionality as follows. The pre- and post-build actions are optional, but if selected (see below) they are only added to the project if you select ‘generate solution with no compile’. So, to be clear, if you then generate the solution differently the actions are not written to the projects. The actions are selected on a new Advanced Options dialog that is accessed from a new Advanced button on the Options Tab.
So the way that I assume you will work is as follows. Assume you have created a new branch. The first thing is to point to the new branch in Developer’s Assistant. Then on the options page, select the database, create the configuration files and initialise them. Back on the main tab, generate the solution with full compile. This will ensure that all the client and server code gets built (using msbuild). Now check the optional actions you wish to include using the new dialog. Finally select and run Generate Solution With No Compile. You are now ready to open your IDE for the client solution. Choose Rebuild All to compile the code in the IDE and then you can work in the IDE knowing that you have a working server that will always stop and start when you need it to.
At some point (if you have modified any shared code) you will probably want to run ‘generate solution with full compile’ again so that the server gets compiled with the new changes. If so, simply re-run ‘generate solution with no compile’ again afterwards to get the actions back into the project again.
It is the responsibility of the Developer’s Assistant to start and stop the server. An instance of the Assistant that is already running can do this; otherwise a new instance starts up, executes the action and then shuts down.
Miscellaneous
I found one bug in the Assistant in code I added for the last release I sent out in which I had incorrectly coded the most recent ‘exception’ to the list of allowable uses of the word ‘error’ when parsing the Nant output for errors. I fixed this.
Conclusions
I am really pleased with the results. Now I can spend a lot of time just in the IDE and I have access to all the C# and YAML that I need to edit. I can edit, compile, start, stop and single step through any piece of code and switch between windows easily. I only need to Alt+TAB from the IDE to the Assistant when I need to generate C# code from YAML, then when the YAML looks right visually I can Alt+TAB back to the IDE to get the behaviour correct.
I am aware that some of these changes will need testing carefully in the Linux platform, but I will be interested to hear any comments and reactions to these ideas in general.