Will the destructor be called?

10.08.10 / Programming / Author: astrobunny / Comments: (2)
Tags: , , , ,

Here’s a C++ quiz for all of you: somefunc() will be called from a thread. Do you think this destructor will be called?

class A {
public:
	A () {
		printf("Constructor\t");
	}

	~A() {
		printf("Destructor\n");
	}
};

int somefunc () {
	A inst;
	int* a = 0
	*a = 1;
	return 0;
}

Idioms

21.06.10 / Programming / Author: astrobunny / Comments: (0)
Tags: , , ,

What if

for (int i=0; i<100; i++)
{
	doSomething();
}

// and

for (int i=0; i<100; i+=2)
{
	doSomethingElse();
}

Was

doSomething() for 1..99;
while (i=1,2..99) { doSomethingElse(); };

Would the world be a better place?

That’s Not The Point

29.12.09 / Programming / Author: astrobunny / Comments: (1)

Today I read an interesting chapter in Writing Solid Code, and it showed an example where a supposed optimization led to code bloat:

To represent the hierarchical window structure, Character Windows used a binary tree in which one branch pointed to subwindwos, called “children” and the other branch pointed to windows with the same parent, called “siblings”:

typedef struct WINDOW
{
	struct WINDOW *pwndChild;	/* NULL if no children */
	struct WINDOW *pwndSibling;	/* NULL if no brothers/sisters */
	char *strWndTitle;
	.
	.
	.
} window;		/* Naming: wnd, *pwnd */

You can turn to any algorithm book and find efficient routines to manipulate binary trees, so I was a bit shocked to when I reviewed the Character Windows code for inserting a child window into the tree. The code looked like this:

/* pwndRootChildren is the pointer to the list of top-level windows
 * such as the menu bar and the main document windows.
 */
static window *pwndRootChildren = NULL;

void AddChild(window *pwndParent, window *pwndNewBorn)
{
	/* New windows may have children but not siblings... */
	ASSERT(pwndNewBorn->pwndSibling == NULL);

	if (pwndParent == NULL)
	{
		/* Add window to the top-level root list. */
		pwndNewBorn->pwndSibling = pwndRootChildren;
		pwndRootChildren = pwndNewBorn;
	}
	else
	{
		/*  If Parent's first child, start a new sibling chain;
		 *  otherwise, add child to the end of the existing
		 *  sibling chain.
		 */
		if (pwndParent->pwndChild == NULL)
		{
			pwndParent->pwndChild = pwndNewBorn;
		}
		else
		{
			window *pwnd = pwndParent->pwndChild;
			while (pwnd->pwndSibling != NULL)
			{
				pwnd = pwnd->pwndSibling;
			}
			pwnd->pwndSibling = pwndNewBorn;
		}
	}
}

Despite the fact that the windowing structure was designed to be a binary tree, it hadn’t been implemented that way. Since the root window (the one representing the entire display) never has siblings and never has a title and since you can’t move hide or delete it, … (cut short for tl;dr)… that led somebody to decide that declaring an entire window structure was wasteful, and the wndRoot structure was replaced with pwndRootChildren, a simple pointer to the top level windows.

Replacing wndRoot with a pointer may have saved a few bytes of data space, but the cost in code space was enormous.

Forgive me for copying all that out verbatim, but I think that the complete background is needed to make the point clear. Here’s the code that was supposed to be written that’s found later in the article:

/* pwndDisplay points to the root-level window, which is
 * allocated during program initialization
 */
window *pwndDisplay = NULL;

void AddChild(window *pwndParent, window *pwndNewBorn)
{
	/* New windows may have children but not siblings... */
	ASSERT(pwndNewBorn->pwndSibling == NULL);

	/*  If Parent's first child, start a new sibling chain;
	 *  otherwise, add child to the end of the existing
	 *  sibling chain.
	 */
	if (pwndParent->pwndChild == NULL)
	{
		pwndParent->pwndChild = pwndNewBorn;
	}
	else
	{
		window *pwnd = pwndParent->pwndChild;

		while (pwnd->pwndSibling != NULL)
		{
			pwnd = pwnd->pwndSibling;
		}
		pwnd->pwndSibling = pwndNewBorn;
	}
}

Any experienced programmer in C would have noticed two things:

  • There was a forced special case
  • The cost of the optimization was greater than the yield of the optimization

But anyone can see that. Its obvious because he said it. However, mentioned this common mistake to a couple of colleagues and said that I did make the same kind of mistake, and this is what they said:

Sometimes code that was written back then may be correct back then, but may not be correct now. Just as I wrote an optimization once because computers were not fast enough to handle a certain operation at the time. They do now so that piece of code actually slowed the program down. Also, Opera recently made its engine less memory intensive but more CPU intensive, but after complaints that Opera was taking too much memory, they changed it to be less CPU intensive and more memory intensive. It’s also a balancing act with more input from your users.

The first thing that came to my mind was “Are you listening?” I am not sure if they were trying out of kindness to make me feel better that I make these bugs because of very good reasons and that the badness is unforseeable or that they were just in their own world going off in a skew. Besides the fact that its clearly the latter and that this is not a tradeoff problem nor was it a “we needed it at the time” problem, since it should have been obvious that the supposed optimization was going to cost more than it was worth in memory space alone at the time of writing the code.

I, like many fellow humans am prone to thinking about the more negative side of this. Of course, this was meant to be a negative post, but on the flipside, I learned three mistakes about fellow programmers that I must remember not to make myself.

  1. Winging it
  2. Optimizing with a narrow view
  3. The code I write is always flawless. I’ll fix it later if I have to.

Firstly, winging it and not paying attention to the details of the problem is a fatal mistake I have been guilty of countless times, and have seen many people fall in to as well. our minds are complex-averse, and tend to try and group things into simple groups of things that share the same characteristics based off keywords in a conversation without really understanding it. In this case, my mention of optimization kicked off the ideas of past optimization and tradeoffs in my colleagues’ heads, and was unfortunately all that occupied their heads from that moment on.

Secondly, we programmers are often indulged in our own mindset and steamroll our way through because our egos are big and our power limitless. When we see something that could be good, like an optimization, we tend to bulldoze our way to make sure it gets done.

Thirdly, we programmers are idealists. Not just in the sense that we want everything to be perfect, but we see perfection in everything we write too. This blindness can cause a lot of grief, and the defence is usually “I had no choice at the time”, which is usually an excuse to cover up a more embarrassing mistake.

Finally, coming back to topic after a very very long strayoff, the whole idea of humans and sad facts of software is not the point. The point of the article from the book is to tell you someone’s mistake so you don’t make it, because if this one word of caution saved a bug in a simple subsystem, imagine the number of bugs that would be saved in a complex system of 100 subsystems. These are the kinds of articles books should be packed full of.

GWT: Next level of automation

04.11.09 / Programming / Author: astrobunny / Comments: (0)

After playing a little with GWT, and attempting to add a map into my little webapp, I’ve found that this is really a very good idea. By applying a language to abstract all the small difficulties of programming a webpage for different browsers, you essentially move a larger percentage of the work into actually making the application.

Although GWT isn’t perfect, and to get my app up and running I had to spend about an hour or so searching the internet about fixing up some XMLs to import the libraries properly, once that was done, the source code that involved adding a map to the page and a little Javascript button coule fit on the screen, it is a huge step over having to deal with the difficulties faced by web programmers to make their sites both compatible with IE and Firefox.

Though I advocate using the minimum amount of cool new features on your site, GWT would be the next step toward progress with the current mess that is web application programming right now.

Attempt to rush an RPG

04.05.09 / Programming / Author: astrobunny / Comments: (0)

After reading an article on GameDev about a guy who managed to build an RPG in 40 hours, I decided I’d try my hand at doing an RPG 40 hours too, but in C#. So I started to write the first code on Saturday. After 10 hours of gruelling crunch and brainstorming, I was overwhelmed and realized that I had neither the skill nor discipline to actually make it in 40 hours. I didn’t even have the energy left to write a blog post about the start, much less record the process of doing it. However, I did get to the stage where I had a map and a character walking around somewhat and had a basic dialog system in place, but with no inventory, no stats, no objects, just character and some boring dialog box.

Thanks to the start however, I’ve now found myself with a half-complete RPG engine. I will upload an update sometime soon. Everything used to make the game is just the .NET framework and C# that comes with Visual Studio Express. Perhaps I should try going on for another 30 hours and see how far I can get…

Putting a separator between your elements

16.04.09 / Programming / Author: astrobunny / Comments: (1)
Tags: , , ,

Often when I’m programming, I’ll need to list a bunch of stuff and put commas between them. Like this:

1,2,3,4,5

Usually, this is what I, and most of my colleagues do:

            List<int> nums = new List<int>();
            for (int i = 0; i < 5; i++)
            {
                nums.Add(i);
            }
 
            string msg = "";
            bool first = true;
            foreach (int num in nums)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    msg += ",";
                }
                msg += num.ToString();
            }

After reading Eric Lippert’s little article about the horrid-seeming problem of commas and lists, I noticed him mentioning the method

String.Join

.

Needless to say, I went and tried it, and found that I could do the equivalent of the above, like this:

            List<int> nums = new List<int>();
            for (int i = 0; i < 5; i++)
            {
                nums.Add(i);
            }
 
            string msg = string.Join(",", nums.Select(x => x.ToString()).ToArray());
            Console.WriteLine(msg);

Its kinda amazing how after coding in C# for a good year now that I haven’t noticed the existence of such a method.

Okay, the lambda expression seems a bit messy with all the parens and all, but you get the idea. Still, its a lot better than writing a loop and having the evil “first” variable which kinda clutters the whole thing. Does anyone know an even better way of doing this?

Update: and for my answer to Eric’s next post:

    string msg = "{";
    IEnumerable<string> s = something;
 
    string[] arr = s.ToArray();
 
    if (arr.Length > 1)
    {
        string[] ar2 = { 
                   string.Join(", ", arr, 0, arr.Length - 1 ), 
                    arr[arr.Length - 1] 
               };
 
        msg += string.Join(" and ", ar2);
    }
    else if (arr.Length == 1) msg += arr[0];
 
    msg += "}";

Unit Tests

10.04.09 / Programming / Author: astrobunny / Comments: (0)

Tests are extremely important in software, especially unit tests. I would go as far as saying that tests should be a core part of all the code that you write. Tests however, are also very unpopular among programmers, and many programmers don’t write them at all. That’s right. I’m saying that 90% of the programmers I have ever met almost never write tests for their code. Writing tests seem like a waste of time to most people, despite how important they are, and are thrown to the back of a priorities list that is topped with new features and urgent bug fix tasks.

It is incredible how many programmers actually just code and not write tests. Usually when a programmer fixes a bug or modifies some code, all that he/she would do after it finally compiles is to start the program up, and fiddle around with it a bit to see if it works, and checks it in. I’m sure you can see why this is a bad way to test your changes. For one thing, your program might only work under the very special circumstances you are currently in, which means it only works for you at the time. When you don’t write a test that tests that your change will continue to work the way you expect it to, you risk letting it break when it gets run under different circumstances, or after another change has been made to the program. But that’s pretty obvious to anyone who has worked on a sizeable software project before. Any change is likely to break something, and this is called Regression. Again, familiar term.

Most programmers say that they shouldn’t be the ones writing tests, but the people who test the software. While this is true for requirements testing, I personally feel that if the person who made the change to the code didn’t write the unit tests, who would? Requirements testing are very overall tests which treat the code that its testing like a black box. However, unit tests are there to ensure that regression does not happen, and are extremely targeted tests. Whenever a person makes changes to a codebase, whether to add a feature or fix a bug, that person is the single most qualified person to write those unit tests, not to mention the intimate knowledge possessed by that person of the inner workings of the change that was made and that person’s ability to treat the code changes like a white box and test it that way, by providing pathological inputs to the code to ensure that it functions under the same pressures it was written for.

Some managers too, block the writing of tests because of the view that “tests don’t make money”. I’m glad I don’t currently work under such managers, but I have heard stories from friends who do. I must admit that they don’t make money, but they certainly prevent you from losing money. Whenever a software project gets big, a large amount of time and effort is spent in fixing bugs that are progressively detected. This is called paying off “technical debt”, and that “technical debt” accumulates as more bugs creep into the codebase as a result of the absence of tests that keep an eye on the bugs. Most of the bugs I have seen were bugs caused by myself and for which I did not write tests for, and which only worked for me and a certain time and date and machine, but no other. Drawing from all those bitter experiences, I have developed a certain liking for tests.

However, simply writing tests for your code simply isn’t enough. You need to make sure that if your test fails, it would provide a scope that would allow you to narrow the problem down to a tiny section of your code. Software in practice is almost never trivial, and there are times when you use a piece of code it would draw from a myriad of data inputs and APIs to get its job done. In the company I work for, we write mapping software. This means that our software has an input from data that vendors provide. Often, we write tests that not only test our own code, but also the correctness of the data provided to us by a vendor. For example, a vendor may have a “Broadway” in New York, but another vendor may not. A key component in our software is Geocoding, which allows a person to find the location of a road by simply typing in its name and city. This means that whenever we write a Geocoder test to find a street, its failure could be due to the data not being right, or that the Geocoder could well be malfunctioning. In big software projects, problems like these come often. Which is why you should also write a subset test. Continuing the example of the Geocoder, in addition to the Geocoder test that I wrote, I also wrote a test that makes sure that the street “Broadway” actually existed in the in the data, so that I can tell what’s going on by looking at both tests and see which ones fail.

Tests also should not be too complicated. I’ve seen some tests that are about 400 lines long and have an extreme amount of cyclomatic complexity with if branches and loops in them. These sorts of complexities create the risk of the test itself failing to run properly, which means its less reliable, and if it fails it doesn’t provide the tester with an objective view of what’s not working. A test should be short, and what it is doing should be almost immediately obvious by simply looking at it. A complex test requires that someone test the test, which usually defeats the purpose of writing the test in the first place. Also, sometimes people find themselves writing tests that are complex because the API that the test is testing is hard to use. In that case, the API has already failed the usability test, and should be rewritten.

In short, tests are extremely important because they are like guards that keep an eye on the sewers where bugs have historically crawled out of. If you find that writing a test for something is like writing a full-fledged application, it might help to know that perhaps you aren’t writing a test that is targeted enough, or you may be testing something that isn’t testable, and hence something that isn’t usable, in which case, you might want to revise your code again.

My version of an SQLite Browser

21.03.09 / Programming / Author: astrobunny / Comments: (1)

Get the Flash Player to see this content.

Having used an SQLiteBrowser available for free on Sourceforge, I felt that it didn’t handle big datasets as well as I would have liked, and wasn’t responsive enough when I wanted to browse through large tables. So I decided that I should make own one since I had so many complaints.

I call it “SQLyte” its written with C# and .NET. I’m releasing this application under the GPL V3 (meaning it includes sources!). I’m not including a help file since anyone who would work with SQLite databases would know exactly how to operate it. You can watch the video below if you want to know more about this program.

You can compile this program if you so wish to using Visual Studio 2008. You’ll need to make your own private key. If anyone wishes to port this to Linux/Mono you are welcome to do so. Please drop me a line if you do! Also, if you feel there’s something the program doesn’t do so well, or you feel it just needs something, file a bug!

You can check out the sources by branching this:

bzr push lp:~davidsiaw/sqlyte/sqlyte

Here are some x86 binaries compiled with a strong name that’s only available from bunnylabs:
SQLyte (84)

Edit: Yes, you can modify the tables and use any INSERT, CREATE or DELETE query you like on your database.

GIS data for topography and shorelines and more

20.03.09 / Random / Author: astrobunny / Comments: (1)

I’ve found a site recently that provides data for free on the world’s shorelines and topography. They have got other datasets too that aren’t as complete, but would probably be of interest to those of you who wish to do research on it. For me, when I look at data like this I get the itch to write programs that process and present it. I might just do that eventually. *keeps a note to self*

Updated the b_pool!

20.03.09 / Programming / Author: astrobunny / Comments: (0)

I’ve updated the b_pool again! This one has got some new features such as string functions (not yet complete) and a new b_resize function, which basically acts the same as realloc, except that if you are resizing the last block created on the pool, it will resize it without freeing. This makes it a lot faster and is perfect for string functions. I haven’t tested it yet and its too late at night for me to test it. If anyone would be so keen to write some tests that will break the b_resize function?