27 October 2012

ccnet config in source control

Two posts ago I had a comment from Ignace in which he suggests the idea of having the configuration file of ccnet in the cvs (perforce in his and my case, but the idea applies to other systems as well). This is indeed a brilliant idea, because if you do that, the state of the code on the cvs will match the state of the config file (or build script, what it actually is). This is something you really need because more often than not the code and the way you build it are thightly coupled. It made me put on the thinking cap.

You cannot put the config file next to the code base, because
  • There are multiple projects in one config file, so in what project would you include it then?
  • There are multiple branches of a project, so what branch should define the build process for all other branches? What with merging branches then?

Another problem is that the server who uses the build script is a server. It cannot open up p4v and get the latest version. So if this needs to be done manually you can just as well just edit the script on the server an be done with it. The only reason to have the script on the cvs would be for logging purposes and backtracking. Not a good motivator, people would easily forget to update the script on the cvs, thus having the config out of sync which defeats the whole purpose then.

Googling a bit on this topic brought me to this post, which is actually the perfect solution for above issues. The config in the post did not work, at least not on the 1.8.2 server and with perforce, so here is my version:

<project name="Config File Monitor">
    <workingDirectory>%depot-root%\BuildServers\ServerName\</workingDirectory>
    <triggers>
        <intervalTrigger seconds="60"/>
    </triggers>
    <sourcecontrol type="p4">
        <view>//depot/BuildServers/ServerName/ccnet.config</view>
        ... and the other params you need ...
    </sourcecontrol>
    <tasks>
        <nullTask />
    </tasks>
    <publishers>
        <xmllogger />
    </publishers>
</project>

Add this project to your config file, place the file at the location specified in it (use a separate folder for each server) and change the path in the ccservice.config file. The project will check every minute if there is a new version of the config file and update it if needed. Since the server is monitoring that file it will automatically reload the configuration. I have not noticed any performance issues on the server of checking perforce every minute. Also note, I really needed to add the nulltask, otherwise it wouldn't work - no idea why, never bothered to check why.

I wanted to test this out for a while before posting about it, but now I know I'm very happy with this solution. We don't have to give special access anymore to some path on the server for users to be able to change the build config, they can just use perforce. The versions are in sync with the builds, and since you need to add a new project for every new branch it's good that the config file resides in its own folder - no messing with branches or anything. People can now also always review how a build is made themselves and don't have to ask the person responsible for the build server how the the build is made. A fine idea by Ignace and a fine solution I've found.

Have fun with this!

25 September 2012

Video screensaver

On my old XP pc I used to have a video screensaver, where I could enter a list of filenames of movies that then would be played on all connected monitors. Very cool! I used to collect all the trailers of CG movies I could get and use that list for the screensaver.

It's not the one I used, but apparently microsoft even made an official video screensaver (for XP). Now on windows 7 I'd like the same, and it should be possible according to this site. I tried but failed to accomplish this with the "windows live essentials".

So I wrote one myself. It turns out that a windows screensaver is very easy to write. I also messed around with various video playing methods in C#, using directx or directshow but none of them were as easy as using a simple media element from the WPF. Since I wrote this for .Net 3.5 that functionality is available.

Only downside to the media element is that it's not easy to synchronize them, so there is a small difference in the starting point of the movies on all screens. But most of the time it is small enough to ignore. It's something that I still want to fix so I might write an update on this post.

If you like you can download it here. The configuration is simple: turn on or off the audio, and provide a folder where to look for files. It only searches for .mov, .avi and .wmv files and does not search recursively. It could use some extra testing so if you run into trouble, you know how to find me :)

Installation: unzip the scr file to a location you like, right-click it and select 'Install'. And you need the .Net 3.5 framework of course.

Edit:

I uploaded an update with some bugfixes: the screensaver used to crash if you specified an empty path to search for videos, and there was an issue with the media element on my and steven's laptop if our extra monitor was connected. It is a known issue with Microsoft but it seems they do not bother to fix it. Luckily there is a workaround.

Edit 2:

By request, here is the link to the git repository I've set up. I converted the project to a vs 2012 solution; somehow I don't have the small sync issue anymore, but I suspect that this is because of my newer graphics card that I have in the meantime.

05 September 2012

ccnet 1.8.* and powershell

Two weeks ago I finally got my Windows Server 2008 R2! Hurray! I can now start on my buildserver for all the projects that I'm working on.

It cannot be over-emphasized how important it is to have a buildserver for your project. In fact, it is even an item in the c++ coding standards book: "Use an automated build system"
Some people ask me what the use is of a buildserver, and I answer them: "Do you want to take the responsibility to release a product that has not been build by a buildserver? Do you want to release a build that has been put together manually by somebody of the team, in the hope he remembers to take all the right steps, that he is completely in sync with the cvs, without locally changed files? Or even worse, say you want to release a second version, this time another person must do the build (the first one is on holliday), are you sure he knows all the steps, that he is in sync and that he has the correct compiler installed?"

This is only one reason why you'd use a buildserver, I can think of many more. Even for a small project, that only you yourself work on, it is good to let the buildserver build it. One reason (there are more): small one-person projects tend to become bigger projects and attract more developers and before you know it there is a small team working on it, or it is used in a bigger project. I've seen this happen more often than not.

But that's not the topic that I want to write about. For years I've been using ccnet, an open source, .Net based build server. Extremely easy to use, very versatile.
Recently the latest version 1.8.0 was released so I installed it on my new server. I haven't had the time yet to review the new features because I need my projects up and running fast.

One of the important features I always use is the assembly version labeller, which for me looks like:

<labeller type="assemblyVersionLabeller">
<major>1</major>
<minor>2</minor>
<incrementOnFailure>false</incrementOnFailure>
</labeller>

In combination with perforce this gives me a version number as an environment variable that looks like 1.2.{buildnumber}.{versionnumber}. From that number I know what build it was, and with what version on perforce it was build. With this number it is key to incorporate it as mush as possible in the application; in the installer, in the exe, in the assemblies, etc. Because with this information, if your application is in the field and you start receiving bugs and feedback, you always know exactly about which version people are talking, you know exactly with what files that exe was build that had a specific error, you know when they fucked up and when you did. It's something I've learned from dire experience at Larian. There were a lot of versions of Divinity II made and the first ones did not have a good version number, which made it impossible to track bugs and user's versions.

So for C# exe's and assemblies I use this powershell script:

$version = [environment]::GetEnvironmentVariable("CCNetLabel","Process")
foreach($arg in $args)
{
$file = [System.IO.Path]::Combine($arg, "Properties\AssemblyInfo.cs")
$old = "`"[0-9]+.\s?[0-9]+.\s?[0-9]+.\s?[0-9]+`""
$new = "`"" + $version + "`""
(Get-Content $file) | % {$_ -Replace $old , $new} | Set-Content -Path $file
}

As argument you give it the folder of your assembly, and it will change the version numbers to the ccnet label version number. This needs to be done before the devenv task and the result is an assembly or exe with correct version numbers if you look at the details of the file. This is extremely convenient to ask a user what version of a certain file they have, or to check yourself what version you're using.

And then hell started for me, somehow the script that I've used on several other ccnet servers, didn't work on the new one. I had the executing policy correct (even for 64bit Windows) which is the common pitfall, but no luck.
To make a long story short: the 1.8.0 and 1.8.1 version of ccnet place the arguments for your script before your script instead of after in the command line, a typo I guess. Luckily it is open source so you can easily create a quick fix until it is fixed in a new version (it really is easy, the source compiles right out of the zip).

But what I forgot was that the "scriptsDirectory" parameter must be absolute or the task takes the default one (which does not exist for the LocalSystem user). You'd expect that you can give a relative path as in all other ccnet tasks, but not for the powershell task. Apparently this is a bug that's always been in there, but I forgot. I looked in the source to fix it but it appears te be a little more tricky than I imagined.

In any case, you're warned now, and you can follow this thread on the ccnet user group if you'd like to know if it gets resolved. There's also some more info there.

09 August 2012

Stage orientation woes

When developing an air application for android and/or iOS, you somtimes want the app not to be available in a certain orientation, for example landscape only. I'm making such an app.

The problem with air is that there is no easy solution to do this. There are several issues that make life hard.
First you need to specify what you want in the air application.xml config file. If you don't need a specific orientation you set autoOrients to true and you're almost done. For a specific orientation, you need to set this value to false. 

Then you need to specify the aspect ratio, which in our case needs to be landscape instead of portrait. It should not be necessary for the auto orient case to set this value, since it will automatically adjust, but it does have an impact on the start orientation of your app, regardless of the current orientation of your device. The problem here is that the orientation of the device is 'unknown' at startup, so the stage is set to the default until the device orientation is first known. 

But when your app can deal with all orientations this is not so big a problem. If you want only landscape or portrait however, it's another story. Setting the autoOrients value to false means you have to set the stage orientation yourself. Just settings the stage orientation to the device orientation is not an option unfortunately.
There are 5 values for the orientation: default, upsidedown, left, right and unknown.

With autoOrients set to true and tracing stage and device orientation I noticed the following rule: 

if stage.deviceOrientation == left then stage.orientation == right
if stage.deviceOrientation == right then stage.orientation == left

 
This was true both on android and iOS, on an iPad2, iPad3 and a Samsung Galaxy Tablet.
Also, the 'default' orientation for iOS is portrait, while for android it is landscape. For tablets at least, it might be different for mobiles.

The device orientaion when your application starts is still unknown, so we cannot just set the correct orientation based on that.

After much testing and googling, I came up with the following code. I found a lot of other sites stating to have the solution, but they did not cover all cases I found. This code might not cover all of yours, let me know if it doesn't, I'd like to know what I can do to improve.



public class LandscapeMain extends Sprite 
{
 private var isDefaultLandscape:Boolean = true; 
 private var cycles:int = 0;
 private var CHECK_ROTATION_INTERVAL:int = 16 - 1;
 
 public function LandscapeMain():void 
 {
  var isLandscapeNow:Boolean = (stage.fullScreenWidth > stage.fullScreenHeight);
  if(isLandscapeNow && (stage.orientation == StageOrientation.ROTATED_LEFT || stage.orientation == StageOrientation.ROTATED_RIGHT)){
   isDefaultLandscape = false;
  }
  stage.addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);
 }
 
 private function onEnterFrame(e:Event):void
 {
  cycles++;
  if ( (cycles & CHECK_ROTATION_INTERVAL)  == 0 && stage.deviceOrientation != StageOrientation.UNKNOWN && !isEqualOrientation(stage.orientation, stage.deviceOrientation))
  {
   var goingToDefault:Boolean = (stage.deviceOrientation == StageOrientation.DEFAULT || stage.deviceOrientation == StageOrientation.UPSIDE_DOWN);
   if ((goingToDefault && isDefaultLandscape) || (!goingToDefault && !isDefaultLandscape))
   {
    if (stage.deviceOrientation == StageOrientation.ROTATED_LEFT)
     stage.setOrientation(StageOrientation.ROTATED_RIGHT);
    else if (stage.deviceOrientation == StageOrientation.ROTATED_RIGHT)
     stage.setOrientation(StageOrientation.ROTATED_LEFT);
    else
     stage.setOrientation(stage.deviceOrientation);
   }
  }
 }
 
 private static function isEqualOrientation(a:String, b:String):Boolean
 {
  if (a == StageOrientation.ROTATED_LEFT)
  {
   if (b == StageOrientation.ROTATED_RIGHT) 
    return true;
   else
    return false;
  }
  if (a == StageOrientation.ROTATED_RIGHT)
  {
   if (b == StageOrientation.ROTATED_LEFT) 
    return true;
   else
    return false;
  }
  return a == b;
 }
}

24 June 2012

AS3 - hate it or love it

And I'm not sure whether I hate or love it :)

The last few weeks I've been learning Flash, AS3, Flex and Air since I started developing an air app and am working on some other flash projects.
I was very reluctant to use Flash for those projects (Id' rather use Unity) but the choice for Flash was due to legacy content that I need to use. And let's face it, Unity is not an engine where we you can use vector graphics easily, nor are there much other engines that lend themselves well to vector graphics. (If there are, tell me, I'd like to get to know them - should I start using html5 perhaps?)

I was happily surprised that, all-in-all, as3 isn't that bad a programming language. In less than a weeks time I was able to get a decent looking app running on my galaxy tab. It's clear that the learning curve for as3 isn't steep.

But learning as3 via google is horror though. There are a lot of resources out there and a lot of forums where people help each other out, just as you have for other programming languages.
But the problem for flash/flex/air developers is that there is AS3 *and* AS2. AS2 looks a lot like AS3, but isn't at all the same. That makes it hard for a newbie to find help on google, because some solutions you find work for both, and some only for one language and it is sometimes not obvious to tell in what language a solution is provided.

And then there is the distinction between a flash, flex or air application. In all three there are different libraries available to get stuff done, so if you're looking on the web for help you need to be sure that the solution you find is for the right environment. For example I was looking how I can send an e-mail (with attachment) from my app on a mobile device. There are a lot of possible ways to do this, via a mailto url, via smtp, via php, etc. But these are all more for online web apps and all seem to be a little hacky to me. There's a clean solution that involves writing an 'ANE' (air native extension) that can send e-mail. I haven't found an existing one so I'll start writing my own. It took me some googling and trying out before I came to that conclusion.

So now I know: AS3 developers have no real well documented working environment, the api is hard to search, contains few examples, the web is full of people writing various opinions on how to solve things, confusing all the time as2 with as3 and flash with flex and air. Add the fact that quite some flash developers are more artist than programmer... The AS3 developers must be extremely jealous of C++/C#/Java developers who have a well documented api and lots of good code samples on the web with decent IDE's (don't get me started on those).

But what led me to write this post is this: a few days ago I added an on screen fps and memory counter -a healthy reflex of every game programmer I think- and saw immediately that the memory leaks were going through the roof. I looked for references that somehow where being kept around, but couldn't find any. So we ask our friend google-man. This post lists all actions you can take to free up memory. What the frak, it's enough to write an entire destructor in every class you have, so what's the point of having a managed environment then?

Luckily I found this and this post, explaining the inner workings of the flash garbage collector. From it I learned that I don't need to do anything else than I'm used to do in C# (that is implementing IDisposable if your class contains non-managed resources like file handles), except for this: use weak references for event listeners. I changed all my event handlers and behold, the leaking was gone.

But not many people know this, most examples that you find on the web don't use weak references, so there must be a lot of leaking swf's out there. My god, horrible.

Let me end with saying this: flash and as3 isn't bad at all, au contraire it's great that you can create nice visual elements with very few code and combine them in apps very easily. I like to work with flash because of that, you have results very fast. But for a programmer, it's horror.

17 May 2012

C# - Initialization of enums

I notice that I want to write too much based on what I have read in Effective C#, so I'll post bits and pieces instead of one big article, here comes a small one:

Initialization and enums

If an object is instantiated all member variables are initialized, with a given initializer or 0/null if none was specified. References are always null, bools are always false, number values are 0, and... enums are set to 0.

Wow! I never realized that, I kinda assumed that an enum value was set to the first value defined in the enum, but this is clearly not the case - and shouldn't be. It does imply that you always need to have a 0-value in your enums, or you risk having an enum variable with an undefined value. Also, when using the [Flags] modifier, None = 0.

21 April 2012

Games from Belgium

The gaming industry is slowly growing in Belgium. I notice it online on blogs and websites. Let me give you some interesting links.

It has been a while since I've revisited Fabrice l'été's post on his blog with links to game studios in Belgium. This post exists already for some years and is still growing. There are at least 10 more companies since I last looked! I've just added four more in the comments and you'll find some other interesting links there.

The Digital Arts and Entertainment course (amongst others) delivers each year more and more students skilled to start in this industry or even start their own company.

There's talk with the federal government and the Flemish government to support this growing industry financially and some projects are getting funding already.

The Flemish government has a whole website on this very subject, with various links in the industry. They also come with a list of gaming companies.

I recently worked for Eurautomat, a company that makes gambling games and websites. The technology they use is the same used in 'classic' games: for the arcade games Unity is used, flash for the website, Linux and OpenGL, etc. The games are mostly simple 2d flash-like games but the bonus games can grow into full 3d animated scenes. I attended the ICE event this year where I learned that the gambling-game industry is big, very big. Unity also had a booth there and has one next year.

Now the Belgian gambling commission has begun restricting online gambling sites, which is a good thing. There is a white list with 10 websites, which have all received B+ licenses, and 4 with A+ licenses. There's also a black list, it's forbidden by law to play on these websites and you can get fined for it. This protects the players but also makes competition in Belgium fair. All I want to say with this: these are just 10 more websites that will be needing games to be developed and at least some of them are already developed in Belgium.

So I see a bright future for games in Belgium. Who's attending Gamehub next week? Is there a community growing?

Have some other interesting links? Post them in the comments!

19 April 2012

Perforce on a freenas

Lately I installed an old pc with freenas 8.0.2 for backup purposes as well as a centralized depository for our home media, music and pictures.

At both Larian and Newfort we used perforce for source control. I also have worked in the past with svn, cvs, git and plastic scm. My scm of choice remains perforce, I feel most confident with that system.

Perforce is now free for 20 users and 20 work spaces which is a huge improvement over their former 2 users. So for my own projects at home, let's install perforce on the freenas. Mind you, I have almost no experience with linux/unix (I worked with some debian version at the KULeuven) so I made a lot of beginner mistakes.

  1. Make sure to activate the ssh service on the freenas, that way you can use putty to login on the freenas via the network instead having to be connected to the pc. You start in the C-shell, which is important since some commands that are available in csh are not in bash and vice versa. For example, setting environment variables in bash is done with 'export', while in csh it's done with 'setenv'.
  2. I have a disk of 122 GB where I created a ZFS volume on called p4disk.
  3. Then I setup the folders, get the p4 and p4d binaries and make them executable
    cd /mnt/p4disk/
    mkdir bin
    mkdir p4root
    cd bin
    wget http://www.perforce.com/downloads/perforce/r11.1/bin.freebsd70x86/p4d
    wget http://www.perforce.com/downloads/perforce/r11.1/bin.freebsd70x86/p4
    chmod +x p4 p4d
  4. On another drive I created a folder to store the journal. Since you need this to restore the server it should not be on the same drive as the server.
    cd /mnt/TERRA01
    mkdir p4
  5. Then we need to make sure the server is run when the freenas boots. It seems like there are a million ways to accomplish that (I hate that) and this is how I did it. If there is a better way please tell me :)
    mount -uw /
    cd /conf/base/etc/rc.d/
    nano perforce
    The first command is needed to make the drive writable, and then we need to add our service in the rc.d folder. But not in the /etc/rc.d/ folder since that one is always reset after a reboot. 'nano perforce' opens the nano editor to write our service script.
  6. Paste this:
    #!/bin/sh -e
    export P4ROOT=/mnt/p4disk/p4root
    export P4PORT=1666
    PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/bin:/mnt/p4disk/bin"
    p4d -J /mnt/TERRA01/p4/journal &
  7. Save the file and continue:
    chmod +x perforce
    cd /conf/base/etc/
    nano rc.conf
  8. Go to the last line and add:
    perforce_enable="YES"
  9. Reboot and done!

If I read these steps again it seems simple enough. I had some weird issues though, all because I'm not that Linux-savvy. A difficult one was that my server was very slow. If I called 'p4 info' on my PC, it took 5 seconds to get a reply. After much googling I found out this was due to a reverse dns look up on the server that failed. Some perforce calls, 'p4 info' among others, perform a reverse dns look up and that slowed it down.

The solution offered by perforce was to include all clients in the hosts file, which is not much of a solution if you ask me. I eventually found out that the server, and all my PC's in the house too, received three ip-addresses of dns-servers from the router: the router itself and two from my ISP. However my router is not a dns server, so all reverse dns calls on my router failed, causing the delay. A firmware update for the router is not available, so unfortunately I had to set the dns ip's from my ISP by hand on the freenas. From then on, perforce ran smooth. Gonna buy myself a new router I think.

With the steps I describe the perforce server is run by the root user. Some other how-to's, like for example installing svn on a freenas, say I should've created a perforce group and user and let that user run the server. I didn't bother and have no idea whether or not that's a good thing. If not, tell me why :). The main reason why I skipped it was because the 'sudo' command wasn't available on the freenas and I could not find how to install it.

Now that all runs fine, I can start experimenting with everything I read in my Effective C# book. I was afraid that the book wouldn't be as good as I hoped, but it turns out to live up to expectations. I'll post something about what I've read later.

11 April 2012

Restarting a service with powershell

It was one of those days. I realized that I've been doing the same small task over and over and so I thought: let's put that into a script. But then the writing of the scripts turns out to be a bit more complicated as expected. I should stop then and get on with my work, but nah, the challenge's there, I can't help it.

I should start writing all those little scripts down, just as a reference for later if I need it again but can't find it anymore. Let's do that now for one particular task.

What I needed to do: shutdown a service on a remote computer, copy some files on that remote computer from a remote computer (but only from the last added folder) and then start the service again. So I started with a bat file (windows, yes) but quickly discovered that determining the last added folder isn't that easy in a bat file. You can check whether a date is equal, but not if it's smaller or greater.

So let's try a powershell script for a change! I used to install software for that on XP, but now that I'm using Windows 7 that's not needed anymore, luckily.

Do not forget to set the execution policy, because default it is set to 'restricted' and I for one always forget on a new pc

    cmd
    powershell
    Set-ExecutionPolicy Unrestricted

After much googling I came up with this script:

&"sc.exe" \\192.168.1.yyy stop NameOfService
sleep -s 5
$from = "\\192.168.1.xxx\from\"
$to= "\\192.168.1.yyy\to\"
$a = Get-ChildItem $from| Where-Object {$_.PSIsContainer -eq $True} | sort -prop LastWriteTime | select -last 1
&robocopy "$from$a" $to*.* /S
&"sc.exe" \\192.168.21.yyy start NameOfService

Use sc to stop the service. Wait for 5 seconds because it can take a while before the service actually stops (should be a while-loop that checks the state perhaps, but 5 seconds was enough for me in all cases encountered). And then we have the power of powershell, we get all the folders sorted by last write time and select the last one, and the result of that is used in a robocopy call. At the end the service is started again.

God that was easy. I never go back to bat files again. It's only a matter of time and practice and I'll be writing them as quickly as a bat file.

10 April 2012

Does the file exist? No easy question.

I shout 'How do I check whether a file exists in C#' and somebody immediately responds 'File dot Exists'.

I shout 'How do I check whether a file exists in C++' and I get no answer.

It is something I can get really frustrated from. C++ is widely regarded as a good and high level language, and I'd like to agree, but in the year 2012 I expect more from a language. How on earth is it possible that experienced C++ developers cannot answer that simple question in a snap? I googled the question, and the answer is far from clear. I have the impression that this is the best method:

#include <sys/stat.h>
bool FileExists(const char* filename)
{
      struct stat buf;
      return (stat(filename, &buf) != -1);
}

Another good option I found was:

#include <fstream>
bool FileExists(const char *filename)
{
 std::ifstream ifs(filename);
 return ifs.is_open();
}

That's almost the same as the previous one and fstream is included more often. However in the first version you're not actually opening the file afaik.

The next one is horrible, it even throws an exception! For a file check! And it's platform dependent.

#include <Windows.h>
bool FileExists(char* filePath)
{
 DWORD fileAtt = GetFileAttributesA(filePath);
 if(fileAtt == INVALID_FILE_ATTRIBUTES)
  throw GetLastError();
 return ( ( fileAtt & FILE_ATTRIBUTE_DIRECTORY ) == 0 ); 
}

There are a bunch of variations of above three circulating on the web. Boost also has a function, so if you use boost you'd probably should use that.

If you do not want to write this function in every cpp where you'd need it, you should put it in a header. If you don't want the name to collide with another existing function with the same name, you should put it in a namespace. You might put it in a library with some other common functions, a toollib or something that you include in all your projects, which means that you need to compile it to various targets, perhaps various platforms. The toollib gets changes in every project, so you need to keep it compatible across projects, or you'll be having various versions of your toollib...

So this is what saddens me. Why is it so hard to have some changes in the language? wouldn't it be ideal if we had

#include <fstream>
...
if(std::ifstream::exists(filename))
{
...

in our code where we want the check. Just as C# has it for example:

...
if(System::IO:File.Exists(filename))
{
...
It would be in the stl, every compiler would implement it as efficient as possible, live would be beautiful.

02 April 2012

Effective C#

Now that I own the c++ coding standards book, I also want to buy the Effective C++ book by Scott Meyers. I also already read it at Larian front to back and I know its worth.

But since I'm currently developing more in C# I thought I'd look for similar quality books about that language. I just ordered Effective C# by Bill Wagner and I hope it's as good as the C++ books.

While looking for it, I also found this code project article that has the same title. It offers some tips but unfortunately without explaining why the tips apply. But at least I learned some small ideas that I can use in the future:

  • I can write strings with an @ in front and then I don't have to worry about double backslashes to have a single backslash in my path.
  • I really should start using stringbuilders, I know I have to use them but the only time I want to concatenate strings is when I want to have some debugging output. I'm too lazy to create stringbuilders at that time and since they're only executed in debug mode I don't want to bother with them. But when I do concatenate strings in release, I should use stringbuilders, let's do that from now on.
  • Let's look into ngen
  • Wow, 'checked', handy keyword!

    And concerning the 'for' versus 'foreach' discussion: I want to delve more deeply into that because let's face it, foreach is soooo easy to use that I do not want to ditch it just because it would be a little less efficient. I want to know for sure that's the case and when that's the case. I hope my new book (arriving in 2-3 days) will provide me with an answer.
  • 22 March 2012

    Source control anyone?

    In the same book I mentioned in the previous post, the writers state in their preface that one of the goals of the rules in the book is: 'Each item must need saying'. As an example they give 'Use an editor', and indeed that rule goes without saying.

    I thought the same thing about source control, everyone uses source control for a project large enough, obviously. So why put it as a rule in the book?

    But then I experienced myself that this rule indeed 'needs saying'. Recently I came in contact with a company -no need to mention names- that does software development in mainly C++, on Linux and Windows, also in assembly... without source control. Without it.

    I still can't really believe it and I don't want to know how they have to manage, but lesson learned: the item clearly needs saying.

    As I will be moving to another company in May, I already wonder what source control system they use. I silently hope they use Perforce (as does Larian and as does Newfort since I introduced it there). I know it's not free, it's even quite expensive if you ask me, but their P4V tool, together with plugins for 3rd party software is unmatched, at least imho.
    I like the idea of git and mercurial, and I've been working with git lately. I think it's a very good system, I only want a client tool that's as good as P4V for it. Mmm, challenge. Nah, don't have the time for it.

    Well, off to work then :)

    19 March 2012

    Coding standards

    A must read for every C++ programmer is without doubt this book. I just bought it for myself today but I have read it back to back some years ago while I still worked at Larian.

    I am myself very interested in programming languages in general and I feel that this book has given me a good understanding of the C++ language. Since I read the book I think more ahead about a class and its functions before I start to write the code. I feel I also write less bugs and far more structured code, I even find bugs faster! If only such a book existed for C# and Java.

    So I started re-reading some of the chapters. I'm currently more often working in C# and Java and I noticed that quite a few of the guidelines/best practices presented in the book also apply evenly well on those two languages, especially the first chapter. For example the first 'rule': 'Don't sweat the small stuff.', summarized as 'Don't enforce personal tastes or obsolete practices.' With the team at Newfort we started creating some sort of C# coding agreement to use in our code and I must say that we violated this rule a few times. This rule for example implies that you do not specify where your braces should be for your if construct; every programmer should be capable of reading and writing it. The rule only mentions that you should be consistent on file level.

    The odd thing is though, that several C# standards (including the one we knocked up ourselves) specifically mention how to brace your loops and if-then-else code.In hindsight, I must say that I agree with my mates Sutter and Alexandrescu. Why on earth would we bother with the placing of braces or specific line length or indent length, etc as long as it's structured, readable and consistent.

    The next three rules also apply on C# and Java and other programming languages, but that's for a later post, bedtime now for me :) Kiddies tend to make you tired.

    Read the book!