# d20 die roll string parser and roller in C#



## FormerlyDickensC (Feb 14, 2008)

This is not a compiled app, just one class written in C#. 

This is a static class 'Dice' using a static method 'Roll(string)' that accepts any normal type die roll string (including parenthetical groupings) and outputs the individual rolls, grouping break-downs, and totals as a string. I took this code from HERE , and hacked the java code into C#. 

It works really well. Very versatile. It can take any number of dice, and any number of sides per dice, and any amount of modifiers. Spaces are not a problem for the string. Leave them in or out. 

I love the use of parenthetical groupings. I think this is where it really shines. 

EXAMPLE Input strings: 
"(3d6+5)+10d12+(5d6+2)"
"10(10d100)"
"2d42+6d7-44"

EXAMPLE Output Strings: 
"(5d6+15)+1d6 = 4+1+2+3+4+15+2 = 29+2 = 31"
"(5d6+15)+1d6 = 4+2+4+2+1+15+1 = 28+1 = 29"
"2d6+15 = 2+5+15 = 7+15 = 22"

This from the original coder: ...as you can see the parenthesis collect the different dice into separate groups in the next-to-last column, so for example:
(1+2+3)+4 = 1+2+3+4 = 6+4 = 10

To implement, call the Dice.Roll(string) method.  There are actually two overloaded Roll methods.  The second takes three int's and is used by the first. 

The reason I made this was b/c I could find an infinite number of die rollers on the web, but no die roller that could accept complex roll strings AND was written in C# AND had the code available to look at. Hence the reason I post the code, and not a compiled app. There are enough of those.  But I did find a java version here on these forums, and translated that and added some more code to it.  Use it to make your own app.  If you can't code, buy a book and learn how. I was an English major and I taught myself to code. .NET is a decent platform with good, free IDE's. Ideal for the hobbyist. 

Check it out, take a look at the comments. Since I basically took all the code and cobbled pieces together, there might be ways to make it more efficient or elegant. But it can roll over a thousand rolls in a second, so whats the need to worry about it? I suggest you enter the string "1000(1000d100)" and see how long it takes. I guess that'd be like a million rolls, right?

Code is posted as is, use it at your own peril. I encourage reuse and modification of it, just include the original author's name etc etc. All the normal stuff. I'm not responsible for any of your own stupid decisions.

This is the first, and probably last thing I will ever contribute. But, hey...at least its something!

Bitches!


P.S. If you find any bugs, let me know here.


----------



## Plane Sailing (Feb 22, 2008)

Nice job, thanks for sharing it.


----------



## FormerlyDickensC (Feb 22, 2008)

Plane Sailing said:
			
		

> Nice job, thanks for sharing it.



thanks for noticing!


----------



## FormerlyDickensC (Mar 13, 2008)

*A bug fix*

Had to make a fix to the code where if you passed a die-string using only one die it would malfunction. So now, if you pass in "1d6" or "1d1000" or whatever it will. 

I have also pasted the code here in the post below. 

PS. I hate that I have to zip the file in order to upload it. 


```
public static class Dice
    {
        private static Random randomGenerator = new Random();

        /// <summary>
        /// Pass a die roll string in any standard d20-type format, including 
        /// parenthetical rolls, and it will output a string breaking down each 
        /// roll as well as summing the total. This works very nicely. The code was
        /// hacked from java code from Malar's RPG Dice Version 0.9 By Simon Cederqvist 
        /// (simon.cederqvist(INSERT AT HERE) gmail.com). 13.March.2007
        /// http://users.tkk.fi/~scederqv/Dice/
        /// His same license still applies to this code. But if you figure out how to
        /// make a million dollars off this code, then you're smarter than me and 
        /// you deserve to keep it.  On the other hand, share and share alike. 
        /// </summary>
        /// <param name="diceString">This is a standard d20 die roll string, parenthesis 
        /// are allowed. Example Input: (2d8+9)+(3d6+1)-10</param>
        /// <returns>A string breaking down and summing the roll. Example Output: 
        /// (2d8+9)+(3d6+1)-10 = 7+4+9+5+1+2+1-10 = 20+9-10 = 19</returns>
        public static string Roll(string diceString)
        {
            StringBuilder finalResultBuilder = new StringBuilder();
            string tempString = "";
            int intermediateTotal = 0;
            ArrayList sums = new ArrayList();
            ArrayList items = new ArrayList();
            ArrayList dice = new ArrayList();
            int totals = 0;
            bool collate = false;
            bool positive = true;
            string validChars = "1234567890d";
            char[] diceCharArray = diceString.ToLower().ToCharArray();

            for (int i = 0; i < diceString.Length; i++)
            {
                switch (diceCharArray[i])
                {
                    case '+':
                        {
                            if (tempString.Length < 1)
                            {
                                positive = true;
                                break;
                            }
                            dice = calcSubStringRoll(tempString);
                            for (int j = 0; j < dice.Count; j++)
                            {
                                if (!positive)
                                {
                                    items.Add(-1 * Convert.ToInt32(dice[j].ToString()));
                                    intermediateTotal += (-1 * Convert.ToInt32(dice[j].ToString()));
                                }
                                else
                                {
                                    items.Add(Convert.ToInt32(dice[j].ToString()));
                                    intermediateTotal += (Convert.ToInt32(dice[j].ToString()));
                                }
                            }
                            if (!collate)
                            {
                                sums.Add(intermediateTotal);
                                intermediateTotal = 0;
                            }
                            positive = true;
                            tempString = "";
                            break;
                        }
                    case '-':
                        {
                            if (tempString.Length < 1)
                            {
                                positive = false;
                                break;
                            }
                            dice = calcSubStringRoll(tempString);
                            for (int j = 0; j < dice.Count; j++)
                            {
                                if (!positive)
                                {
                                    items.Add(-1 * Convert.ToInt32(dice[j].ToString()));
                                    intermediateTotal += (-1 * Convert.ToInt32(dice[j].ToString()));
                                }
                                else
                                {
                                    items.Add(Convert.ToInt32(dice[j].ToString()));
                                    intermediateTotal += (Convert.ToInt32(dice[j].ToString()));
                                }
                            }
                            if (!collate)
                            {
                                sums.Add(intermediateTotal);
                                intermediateTotal = 0;
                            }
                            positive = false;
                            tempString = "";
                            break;
                        }
                    case '(': collate = true; break;
                    case ')': collate = false; break;
                    default:
                        {
                            if (validChars.Contains("" + diceCharArray[i]))
                                tempString += diceCharArray[i];
                            break;
                        }
                }
            }

            // And once more for the remaining text
            if (tempString.Length > 0)
            {
                dice = calcSubStringRoll(tempString);
                for (int j = 0; j < dice.Count; j++)
                {
                    if (!positive)
                    {
                        items.Add(-1 * Convert.ToInt32(dice[j].ToString()));
                        intermediateTotal += (-1 * Convert.ToInt32(dice[j].ToString()));
                    }
                    else
                    {
                        items.Add(Convert.ToInt32(dice[j].ToString()));
                        intermediateTotal += (Convert.ToInt32(dice[j].ToString()));
                    }
                }
                sums.Add(intermediateTotal);
                intermediateTotal = 0;
            }

            //// Print it all.
            finalResultBuilder.Append(diceString + " = ");
            for (int i = 0; i < items.Count; i++)
            {
                if (Convert.ToInt32(items[i].ToString()) > 0 && i > 0)
                    finalResultBuilder.Append("+" + items[i].ToString());
                else
                    finalResultBuilder.Append(items[i].ToString());
            }
            if (sums.Count > 1 && items.Count > sums.Count)
            { // Don't print just one, or items again.
                finalResultBuilder.Append(" = ");
                for (int i = 0; i < sums.Count; i++)
                {
                    if (Convert.ToInt32(sums[i].ToString()) > 0 && i > 0)
                        finalResultBuilder.Append("+" + sums[i].ToString());
                    else
                        finalResultBuilder.Append(sums[i].ToString());
                }
            }
            for (int i = 0; i < sums.Count; i++)
                totals += Convert.ToInt32(sums[i].ToString());
            finalResultBuilder.Append(" = " + totals + "\n");

            return finalResultBuilder.ToString();
        }


        /// <summary>
        /// Rolls the specified number of die each with the specified number of
        /// sides and returns the numeric result as a string. I had to introduce a 
        /// call to Thread.Sleep() so that the random num gen would seed differently on 
        /// each iteration. 
        /// </summary>
        /// <param name="numberOfDice">The number of die to roll.</param>
        /// <param name="numberOfSides">The number of faces on each dice rolled.</param>
        /// <param name="rollMod"></param>
        /// <returns>A string containing the result of the roll.</returns>
        public static string Roll(int numberOfDice, int numberOfSides, int rollMod)
        {
            // don't allow a Number of Dice less than or equal to zero
            if (numberOfDice <= 0)
                throw new ApplicationException("Number of die must be greater than zero.");

            // don't allow a Number of Sides less than or equal to zero
            if (numberOfSides <= 0)
                throw new ApplicationException("Number of sides must be greater than zero.");

            //// Create the string builder class used to build the string
            //// we return with the result of the die rolls.
            //// See: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemtextstringbuilderclasstopic.asp
            //StringBuilder result = new StringBuilder();

            // Declare the integer in which we will keep the total of the rolls
            int total = 0;
            
            // repeat once for each number of dice
            for (int i = 0; i < numberOfDice; i++)
            {
                // Create the random class used to generate random numbers.
                // See: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemRandomClassTopic.asp

                // Get a pseudo-random result for this roll
                int roll = randomGenerator.Next(1, numberOfSides);

                // Add the result of this roll to the total
                total += roll;

                //// Add the result of this roll to the string builder
                //result.AppendFormat("Dice {0:00}:\t{1}\n", i + 1, roll);
            }
            
            return (total + rollMod).ToString();

            //// Add a line to the result to seperate the rolls from the total
            //result.Append("\t\t--\n");

            //// Add the total to the result
            //result.AppendFormat("TOTAL:\t\t{0}\n", total);

            //// Now that we've finished building the result, get the string
            //// that we've been building and return it.
            //return result.ToString();            

        }

        /// <summary>
        /// This function merely breaks down the *basic* die roll string
        /// into the requsite integers. It is used by the above Roll(string) 
        /// method. 
        /// </summary>
        /// <param name="s">A simple die roll string, such as 3d6. Nothing more.</param>
        /// <returns>Returns an ArrayList of int's containing the various die
        /// rolls as passed in as a parameter.</returns>
        public static ArrayList calcSubStringRoll(string s)
        {
            int x, d;
            ArrayList dice = new ArrayList();
            if (s.Contains("d"))
            {
                x = Convert.ToInt32(s.Split('d')[0]);
                d = Convert.ToInt32(s.Split('d')[1]);

                // I loop here so that each roll is added to the ArrayList, and 
                // therefore works properly with the code I hacked from java above. 
                for (int i = 0; i < x; i++)
                    dice.Add(Dice.Roll(1, d, 0));
            }
            else
                dice.Add(Convert.ToInt32(s));

            return dice;
        }
    }
```


----------



## azhrei_fje (Mar 13, 2008)

Thank you for posting your code!  I don't know C#, but I have a mild curiosity of what the language looks like, so I appreciate having a class that I can understand its function. 

Having said that, I would like to point out that in a true object-oriented design, this implementation would likely need to change somewhat.

For example, the class should not be deciding how the data is returned to the caller.  Instead, the caller should register a "callback" function and your class would then call that function either multiple times with each die result passed as a parameter each time, or a single time with a list of values passed as an array/linked list/etc.

I can explain further, if you'd like, or you can check out the book _Design Patterns_ by the Gang of Four (the only one I can ever remember is Gamma; look it up on Amazon thought and you'll find it quickly).  One of the chapters is on the Observer/Observable design pattern and that pattern is a really good idea for a dice rolling class.  In fact, when I teach OOA&D and get to chapter on design patterns, I often use the dice roller as an example of this pattern.  Taken to its logical extreme, the output is completely decoupled from the class itself, allowing an entire hierarchy of classes which implement the callback method.

Anyway, as I mentioned at the beginning, thanks for the code snippet.  I'm looking forward to perusing it in detail.


----------



## FormerlyDickensC (Mar 13, 2008)

my apologies for getting on a rant here, buuuuuuuuut.......

dude...it rolls dice.....and its a static method, thats all. 

using delegates (or call back methods) is overkill for such a simple piece of code.  The vast majority of the code is simply parsing the string. If you want to have the method sometimes return an *int *and sometimes a *string*..then just overload it or create multiple methods..or use the '*out*' keyword. (my fault, you said you weren't familiar with C#). But I think you said you were writing a WPF app, so you should be familiar with .NET, right? or was that someone else?

but the point of the method was to parse the die roll string..you mentioned that your delegate would pass in each die roll or an array of rolls...well if they're already parsed from the input string then there is no need for the method. just instantiate your own *Random *object and roll directly. 

I'm fully versed in the Observer pattern, I must argue that your use of it as you explained is not what I would consider the most efficient. Calling various delegate (or callback) methods is the same as calling overloads, and is unnecessary. It introduces complexity where there need be none. 



> For example, the class should not be deciding how the data is returned to the caller. Instead, the caller should register a "callback" function and your class would then call that function either multiple times with each die result passed as a parameter each time, or a single time with a list of values passed as an array/linked list/etc.



 .....ummmm no. maybe if we were dealing with a highly diversified object model then that would be appropriate.  But we're not. We're dealing with strings, int's, and one little method. 

Look, I'm not trying to pick an argument or be a pain or a jerk. But implementing the pattern in the way you explain is really not necessary or helpful.  

Bottom Line: There are only two possible types the caller would want the data returned as....a string or an int. The best answer, imo, is simply return as int and let the caller cast to string as needed. Simple. Elegant. 

No need for delegates. Besides, the caller is not observing anything. The caller is not waiting for something to happen on the part of the dice roller. The caller simply wants a result from his given input. Applying the Observer pattern is nonsensical in this case. 

Be careful how you implement grand ideas. Sometimes, you just need to do what you have to do, and no more. Plus I didn't write the code or algorithm, I translated it from Java that another person posted here. I left the algorithm intact.  Remember the major point of the method is to parse text. Take a look at my explanation in the first post. 

If you teach analysis and design, answer this question that I came across: http://forums.microsoft.com/MSDN/ShowPost.aspx?siteid=1&PostID=2994966

Again, I apologize for my rudeness if that is how I'm coming across. It is not my intention.


----------



## FormerlyDickensC (Mar 13, 2008)

and if you're talking about the format of the string returned (and all the extraneous info about the die roll), thats just done for demonstration purposes. I assume that anyone using the code would take that out as needed. like I said, the best thing would be just to return type int.


----------



## azhrei_fje (Mar 13, 2008)

dickenscider said:
			
		

> Again, I apologize for my rudeness if that is how I'm coming across. It is not my intention.



Yeah, perhaps I came across that way too.  My apologies. 

I used to write code.  Lots of it.  (But you know the saying, "Those who can't do, teach." )

Anyway, my experience over the last 30 years (ouch!  THAT LONG?!) has been that if I don't write something generic in the beginning, I end up redesigning/reimplementing it again later.  Usually this happens when I'm writing code for myself, because I think, "Well, I'm only ever going to use this code in this application.  Why bother to do a grand design when the code won't be reused anywhere else?"  And of course, you know what usually happens... 

In any case, the Observer pattern is supposed to separate an object that generates events from the object that interprets those events.  This is going to get long-winded, but I'll try to get through it all anyway... 

Imagine a hierarchy of classes such as DieRoller that takes a dice string to parse and generates a list of random numbers.  How should those numbers be displayed?  They could be displayed on a terminal, drawn on the screen as graphics elements, flashed on LEDs hooked up to the parallel port, spoken aloud, and so on.  Because the data might be used in many different ways, the specific implementation should not be in the DieRoller class.

Instead, a new class called DieObserver is created.  (This would actually be an interface, but I'm simplifying.)  The DieObserver would implement a callback, such as *dieRollUpdated(DieRoller dr)*.  When the DieRoller class is told to roll its dice, each random number generated causes DieRoller to invoke the *dieRollUpdated()* method of a DieObserver that was passed in at the time the DieRoller was created.  The DieObserver object can now query back to the original DieRoller using the passed in parameter and ask it what the latest roll was.  (The query back to DieRoller is done to avoid hard-coding a data type into the parameter list of the *dieRollUpdated* method, and hence, makes the DieObserver more generic and reusable.  And, it many cases allows a single DieObserver to be used by multiple DieRollers; not in this example, though.)

This allows me to use DieObserver as the top class in a hierarchy of classes:  GraphicsDieObserver, LEDDieObserver, TerminalDieObserver, and so on.  The main application passes the dice string to be parsed to the DieRoller, and as it generates random numbers it passes them to a particular DieObserver and the DieObserver is responsible for building the result.  In your code example, that would be StringDieObserver -- it would simply concatenate all of the values together into a string.

Because the DieObserver was passed to the DieRoller at instantiation time, the main application can have a reference to the DieObserver cached and 
later call a method of the DieObserver to retrieve the string.

Empirical data suggests that object-oriented code has roughly 15%-20% more lines of code than a procedural program (Martin Fowler, _UML Distilled, 2nd Edition_).  This means that it takes longer to get from the starting point to the end result.  But if analysis patterns and design patterns are applied at each step along the way, the resulting code is highly modular and quite easy to reuse in other applications later.  This means that the next version of the code can be released sooner, that the readability of the code is improved, and that maintenance is easier.

<rant>
I read somewhere that, "[...] software doesn't need maintenance.  It doesn't require periodic oil changes and its tires don't wear out.  Instead, the functionality required of the software changes.  Software doesn't need maintenance -- it needs redesign and reimplementation."  I like that quote because it pinpoints one of the major problems with software production today:  the feeling that the code is such a mess that it needs to be redone from the ground up.  Why would that happen?  It happens because the A&D steps were skipped or severely limited so that the program did not include the proper design elements.  Since the design was not robust enough in the beginning, the patches made later to add functionality instead just obscure the existing functionality!  Instead of patching a single class to add functionality, that subsystem of the application should be sent back to the A&D folks so that they can evaluate what the proper design should be to accommodate the change in functionality that is desired and then the code reimplemented.
</rant>

Concerning the link to the Microsoft web site, I understand the goal behind the question, but I'm not sure I understand whether the question is asking for a design that will accomplish what the OP is asking about or if the OP wants an implementation.  The answer provided by the next post mentions the Provider pattern and this seems like a good way to go.  If the question was concerning the C# implementation, ie. "How do I implement this in C#?", then I can't help. 

Again, I apologize again for the long-winded reply.  And yes, this probably seems like a lot of work to go through to get from point A to point B.  I have found that if I write all of my code as though it were going into a library/framework instead of into a specific application, I end up with generic, reusable classes more often.  It is hard to discipline myself, however, when I think that I just want something quick and dirty that works.


----------



## Plane Sailing (Mar 13, 2008)

dickenscider said:
			
		

> thanks for noticing!





So I've just come back from a WPF course via work, and I've been inspired to write a D&D related program 

I'll include this class and let you know if I discover any (other!) bugs in the process.

Cheers


----------



## FormerlyDickensC (Mar 14, 2008)

@azhrei, that sounds more like a *model-view-controller* pattern (or n-tier)...but really that is a type of observer pattern I suppose. In your description, this class is just (a portion of) the controller not the observer or viewer. I'd leave it up to the GUI code to type cast or transform the data as necessary. I really expect anyone using this code to tailor it. Also, since the UI should know when a die roll was called, there shouldn't necessarily need to be an event handler to update the UI. I suppose there could be, but I'd find it odd if the UI didn't know when a call was made by (assumedly) the end-user. 

@Plane Sailing, I think you can simplify the code if you like. It outputs a long string when only the actual die roll result is probably most useful. The extra info in the output is just there for display purposes in case you want to show a breakdown of the rolls to the UI or whatever consumer/caller. 

About the link to the MSDN forums, I saw that post and really REALLY wanted to know the answer to the question b/c I would love to create an app like that. Or at least would love to see the source for it. 

And w/ 4E coming soon, I think there will be a big desire for new apps supporting the new edition. 

It's been a good conversation. I've enjoyed it. Thanks!


----------



## Plane Sailing (Mar 15, 2008)

dickenscider said:
			
		

> @Plane Sailing, I think you can simplify the code if you like. It outputs a long string when only the actual die roll result is probably most useful. The extra info in the output is just there for display purposes in case you want to show a breakdown of the rolls to the UI or whatever consumer/caller.




Yes, I simplified it to just return an int. For my money a static method is exactly what is needed here - I never need to know the state of the dice at any point, it doesn't have to exist as a distinct entity. It just provides me the die rolling function when I need it.

I'm having fun with Test-Driven Development at the moment, and it is proving more beneficial than I thought it would 

FWIW my little 'project' is to create a client-server 'dungeon viewer' app which will be like a simplified version of the new thing by electronic arts.

Cheers


----------



## FormerlyDickensC (Mar 16, 2008)

@Plane Sailing,

You like TDD? I just hate writing the tests. But I should use it more often. Definitely is a good practice/habit/method. 

Is your 'dungeon viewer' app like MapTools? If so, that would be great..esp one in C# 

And, to which "new thing by electronic arts" are you referring? I'm not familiar. 

Keep me posted if you ever release the app and/or source. Ever thought about hosting it on CodePlex? I think CP has come a long way since it was first introduced. (I feel like such a M$ whore).


----------



## Plane Sailing (Mar 17, 2008)

I'm only just getting into TDD as a result of an inspirational conference last week. Visual Studio 2008 has some really nice tools for generating test stubs (including using reflection for testing of private methods), and one of the design elements that I'm trying out is typically using lots of small, easily testable methods rather than a few big methods.

My 'Dungeon Viewer' would be like the thing demonstrated in the videos by WotC (and I meant to write 'WotC' when it came out 'electronic arts' for reasons unknown!).

I rather like the idea of having rooms that contain features and creatures, and the DM (server) gets to see all the rooms with a certain level of ambient light and 'public' visibility, while the PC (client) view has light from light sources (torches, spells etc) and only rooms that they have visited have 'public' visibility - rooms that they have not seen yet are marked as 'private' by the DM and don't appear on their client.

It will be an interesting opportunity to use WPF features like 3D support, easy scaling and transformation of graphic primitives, XAML binding to XML data sources and similar stuff. 

I'm most at home with OO classes, then XML and XAML/WPF is furthest away from my comfort zone, so that is the rough order that I'm tackling things in 

I'll certainly let you know how I get on with it!

Cheers


----------



## azhrei_fje (Mar 17, 2008)

dickenscider said:
			
		

> @azhrei, that sounds more like a *model-view-controller* pattern (or n-tier)...but really that is a type of observer pattern I suppose.



Actually, it's just *model-view*, as there's no UI component to act as *controller*. 

The DieRoller is the *model*, providing storage for the data (although it doesn't actually store the data, it generates it on-the-fly) and the DieObserver provides an implementation for the *view*.

The *MVC* pattern is much more sophisticated and unnecessary in this case, while having a DieRoller object that can be customized could be quite useful.


----------



## Mustrum_Ridcully (Mar 18, 2008)

Plane Sailing said:
			
		

> I'm only just getting into TDD as a result of an inspirational conference last week. Visual Studio 2008 has some really nice tools for generating test stubs (including using reflection for testing of private methods), and one of the design elements that I'm trying out is typically using lots of small, easily testable methods rather than a few big methods.
> 
> My 'Dungeon Viewer' would be like the thing demonstrated in the videos by WotC (and I meant to write 'WotC' when it came out 'electronic arts' for reasons unknown!).
> 
> ...



The interesting part of WPF is how much you can actually do in your XAML. I started in a new project 1 1/4 years ago, and looking back, there is so much I (and the others in my team) could have done much more elegant by relying only on XAML, using (Data)Triggers and Setters, or Control & DataTemplates.
My advice: 
Try to understand how this stuff works as soon as you notice that you write code-behind that directly changes your visual representation (ranging from adding whole visual elements over setting the content of ItemControls to switching Visibility of elements on or off (Hidden/Collapsed).
Off course, before you do that, you need to understand DataBinding and also Converters.
Oh, and understing Resources and ResourceDictionary is also important. 

And then - note that 3D in WPF isn't exactly... the fastest. We were a bit disappointed in that area - looks nice, but performance is not great. (Though we still have some ideas how to optimize it. And with "we" I mean my colleague, since I did little - or rather nothing - in that area.)


----------



## ThirdWizard (Mar 19, 2008)

Plane Sailing said:
			
		

> I'm only just getting into TDD as a result of an inspirational conference last week. Visual Studio 2008 has some really nice tools for generating test stubs (including using reflection for testing of private methods), and one of the design elements that I'm trying out is typically using lots of small, easily testable methods rather than a few big methods.




If you're just starting out, you might want to read Test Driven Development: By Example. It's pretty good for learning the basics of TDD.

 I use NUnit and I _love_ it! I don't do "true" TDD because I work in a production environment. But, I still do love it.

AFAIK NUnit doesn't work with 3.x yet, though.


----------



## FormerlyDickensC (Mar 19, 2008)

@ThirdWizard, have you any experience with the new built in unit testing in VS2008? Or do you know of any comparison of it with NUnit? I don't think there has been a whole lot of new development with NUnit and, like you said, I don't think it explicitly supports .NET 3.x. (although I'm sure it works fine or as normal). 

I was just wondering what the word is on whether built-in VS2008 unit testing is up to snuff.

Thanks,


----------



## ThirdWizard (Mar 28, 2008)

dickenscider said:
			
		

> @ThirdWizard, have you any experience with the new built in unit testing in VS2008? Or do you know of any comparison of it with NUnit? I don't think there has been a whole lot of new development with NUnit and, like you said, I don't think it explicitly supports .NET 3.x. (although I'm sure it works fine or as normal).
> 
> I was just wondering what the word is on whether built-in VS2008 unit testing is up to snuff.
> 
> Thanks,




Little late...

I haven't done any unit testing with VS2008, unfortunately. I haven't worked on any production-level projects under 2008 as of yet, since while I'm all about the new and shiny, nobody else (especially my manager!) seems to be wanting to take the plunge on it. I don't guess I can blame them. 

I haven't even read about it on a blog! Usually that's where I wait to read about things before trying them myself. Nobody seems to be jumping head first into VS2008 either...


----------



## FormerlyDickensC (Mar 28, 2008)

True. If I was a manger, I'd be trying to figure out the justification for the cost expenditure. Unless your doing some WPF/3.5 stuff there really is no reason, and even then you could get around with other things I suppose. Does VS05 support C#3.0 and LINQ? Can't remember. 

But, I've played a little bit with the unit testing in VS08. I like how it generates the tests for you. Thats nice, but might need a little polishing. Should be really rock solid in the next version. But if you write your tests first (as they say you should) then the test generation isn't so helpful. 

All in all, I like VS08, but unless there is a specific reason to pay for it, its kind of like Vista (but not that bad)....its nice, but do you REALLY need it...type of thing.


----------



## ThirdWizard (Mar 30, 2008)

dickenscider said:
			
		

> True. If I was a manger, I'd be trying to figure out the justification for the cost expenditure. Unless your doing some WPF/3.5 stuff there really is no reason, and even then you could get around with other things I suppose. Does VS05 support C#3.0 and LINQ? Can't remember.




Oh, LINQ is amazing. We do a lot with databases at my job and we've decided that our internal APIs would be aided a lot with LINQ. Especially since VS2008 allows you to browse our databases without having to use other applications. So, I won't have to have Query Analyzer and SQL Management Studio open while I'm doing my programming nearly as often. Plus, those LINQ statements are so much easier to read.

Still not enough leverage to go to 3.0, though. 

Well, we actually have one program that we needed WPF for, however, while it is "super important" to the heads, its just a frivolous little application in reality.



> But, I've played a little bit with the unit testing in VS08. I like how it generates the tests for you. Thats nice, but might need a little polishing. Should be really rock solid in the next version. But if you write your tests first (as they say you should) then the test generation isn't so helpful.




I'll have to give it a try. We have VS2008 from our MSDN account that we play with to keep up to date.



> All in all, I like VS08, but unless there is a specific reason to pay for it, its kind of like Vista (but not that bad)....its nice, but do you REALLY need it...type of thing.




Until that's what everone wants to see on resumes.  Although 2.0 isn't nearly as bad as 1.1.


----------



## Chris Tavares (Apr 1, 2008)

NUnit 2.4.7 was just released, so it's under development. Whether you like the direction NUnit has gone in is a very different question.

VS unit tests and NUnit tests are pretty much on par feature wise. VS has some nice features for testers (like web tests and setting up database stuff) which are completely useless for, and actually interfere with, developer unit testing.

The thing is, VS Unit Tests were designed for testers, not for developers. So it's got tons of stuff about managing and building test lists, storing reports, repeating runs, etc. None of which is anything that's even remotely useful for developer unit tests.

The VS test runner is a little better in 2008, but it's still awkward. If you want a really good unit testing experience, go download from http://www.testdriven.net/ . It's a VS addin that lets you right click on a test class or method, or on anything in the solution explorer, and it'll go out and run the tests. It's the simplest thing that could possibly work, and it works fantastically well.

As for the observer discussion, put me down on the "overkill" side. I'm a big fan of the YAGNI principle: You Ain't Gonna Need It. I've had lots of projects in the past where I've put in generality that "I know I'm going to need!" but ended up not needing at all. The result being carrying around lots of maintenance burden for overly general stuff that wasn't even being used.

Yeah, I'm one of those agile hippy freaks I guess. ;-)


----------



## wenoc (Apr 3, 2008)

Whoa!
I thought my dieroller had gone and been forgotten as soon as it was bumped off the front page. I guess I was wrong. I'm happy to see someone caught an interest!  

Oh, and I know it's _Wenoc_ here and _Malar_ in the original source, but I kinda got stuck with the latter nick since fifteen years ago or so, and it felt so stupid to create a profile with that name on these boards. I'm sure you understand.


----------



## FormerlyDickensC (Apr 4, 2008)

Thanks for sharing your code to begin with.  Share and share alike!


----------



## Plane Sailing (Apr 10, 2008)

Mustrum_Ridcully said:
			
		

> ... XAML, using (Data)Triggers and Setters, or Control & DataTemplates.
> My advice:
> Try to understand how this stuff works as soon as you notice that you write code-behind that directly changes your visual representation (ranging from adding whole visual elements over setting the content of ItemControls to switching Visibility of elements on or off (Hidden/Collapsed).
> Off course, before you do that, you need to understand DataBinding and also Converters.
> Oh, and understing Resources and ResourceDictionary is also important.




I'm finding some of the things "wow" and then I want to do something myself and I'm thinking "huh?" as I try to work out from various blogs how to do something I want to do. Binding a ListBox to my ObservableCollection object is currently proving more difficult than I've been led to expect by various books!

One of the bits I'm finding frustrating with the XAML side of things is how to debug databinding - if I'm not seeing the data items I'm expecting to see, it seems much more difficult than the old faithful "attach a breakpoint and see what's happening" that you can do with procedural code!

Don't get me wrong - I'm in love with some of the things you can do with triggers, templates, resources and the like  It is just sussing out the "right" way of doing things which can be a pain sometimes   

Cheers


----------



## Mustrum_Ridcully (Apr 10, 2008)

Plane Sailing said:
			
		

> I'm finding some of the things "wow" and then I want to do something myself and I'm thinking "huh?" as I try to work out from various blogs how to do something I want to do. Binding a ListBox to my ObservableCollection object is currently proving more difficult than I've been led to expect by various books!
> 
> One of the bits I'm finding frustrating with the XAML side of things is how to debug databinding - if I'm not seeing the data items I'm expecting to see, it seems much more difficult than the old faithful "attach a breakpoint and see what's happening" that you can do with procedural code!
> 
> ...



Yes, the debugging often seems to become a lot more difficult. If you're using Visual Studio 2008 and .NET 3.5, it's possible to get the .NET source code for debugging purposes online. (100% legal, but you won't be able to change it, off course.) I haven't tried it yet, since I am still stuck with 2005 and .NET 3.0.

How do you want to bind your ObservableCollection? One of the easiest way to do it is to expose the ObservableCollection as a (possibly dependency) property on your control. 
You can now use a syntax like this


```
ItemsSource={Binding ElementName=ControlWithDesiredProperty, Path=ItemCollectionPropertyName}
```

This would assume that you're naming your control in the XAML with x:Name=ControlWithDesiredProperty
(x being your "http://schemas.microsoft.com/winfx/2006/xaml" namespace.)


If you go deeper into templating, you will probably use TemplateBinding and RelativeSources in your bindings, and will do without using elementnames. Instead of using the ElementName, you can also set the DataContext to that element (if you have multiple bindings to the same element, this will probably clear up the code...)

What usually isn't enough is just setting the ItemsSource property to your desired collection (in code) if you expect the collection itself to be replaced often. (If you use change its contents, it will work fine).


----------



## Plane Sailing (Apr 11, 2008)

Mustrum_Ridcully said:
			
		

> How do you want to bind your ObservableCollection? One of the easiest way to do it is to expose the ObservableCollection as a (possibly dependency) property on your control.
> You can now use a syntax like this
> 
> 
> ...




The approach I'm attempting to use at the moment is putting in windows.resources an ObjectDataSource as follows


```
<ObjectDataProvider x:Key="CreaturesDS"  ObjectType="classes:Creatures" MethodName="Load">
    <ObjectDataProvider.MethodParameters>
        <system:String>creatures.xml</system:String>
    </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
```

and then I create a CollectionViewSource which I bind my objects to. Well, that's the theory anyway, but I've not got that working properly yet!

I've had great success with XmlDataSource and two-way binding to an external xml file, which has made populating my critters xml very easy now.

(Oh yes - I've found that VS2008 will send run time errors to the Output window when debugging, which can be helpful - even if I miss my breakpoints and examining variables!)

Cheers


----------



## Mustrum_Ridcully (Apr 19, 2008)

I'd really love to give you some useful comments here, but I haven't done anything with the
ObjectDataProvider or ObjectDataSource classes yet. And I feel like I might have missed something important or useful. But maybe not, I am not sure how or where I could use it. (We're using XML, but never display it directly...)
Maybe I get some experimenting done another time, but my hopes are slim. 

Or did you figure it out yourself already? Inquiring minds demand to know!


----------

