Tuesday, March 10, 2009

Coding right feels good.

I have been converting my 2750 project from a hellish nightmare to dreamy pie. When I first wrote things, back in assignment one, I needed a main, and server functions. Thus, main.c and serverfuncs.c were born.

How much hard coded, non-modular spaghetti I managed to throw together is ridiculous. Over the course of the next two assignments, I expanded main.c and serverfuncs.c - never by much. It was incremental, but repeated. Over and over again I added a single function, three lines here, four there.

I ended up with a 150 line main.c with a 70 line while loop full of garbage, and a 550 line serverfuncs.c, which had keyboard io, dynamic library loading, network functions, fifo functions - shit was not so cash.

My project has been to nicify this in time to use it for the database portion of the assignment, which will be due in a day or two. I am feeling very good about it at the moment.


Are now my code files. Main is about 20 lines of intensely readable code, and everything else just works marvelously at the moment. The only errors valgrind gives are dlopen() related, and there are no leaks.

What became network.c used to be a series of functions which figured out the size of a file, read the entire thing into memory as a string, then repeatedly ran a function on the string which would find replacement tags and replace them. It then wrote the string to a temporary file, which would be read back in moments later to be sent out to the client.

The repeated function - this was the worst part. "replacements" was called on the string 'data', which could be very large. "replacements" would load up the first search string, and then perform a strstr() on "data" repeatedly looking inside it. When it found the string it wanted, it would perform a lot of loopy string manipulation and pointer arithmetic, allocate a new string of a slightly altered size from data's, copy everything over, then free data. Repeatedly until it couldn't find the search string in data any more. Repeatedly until it ran out of possible search strings.

Now, when a tag is found by yacc, it gets passed into the new "replacements", which acts very similarly, but only on a small piece of text, and in a much less complicated fashion with less string and pointer manipulation. It was nice to see entire functions bite the dust as everything became streamlined.

I still have the gui/fifos to reimplement (the code is there, just needs to be brought over), and lex/yacc to fix. Then there's the database portion of the assignment. Which is due Wednesday at midnight / Thursday at 9:00 AM. In other words, I haven't got a lot of time left.

This has been a good part of an ongoing lesson in time management. Balancing the development of this code with TAing, SOCIS, Senate, and 3 other courses (now 2) has been difficult, but not impossible.

I've gained a lot of respect for proper code as opposed to messy code - and learned that even the intent of "doing things right" is meaningless when you don't know what "right" is, or adhere to it when you find out.

Challenges ahead? I'm not certain how to actually find the dynamic bits with whitespace - unless lex and yacc return every possible tag and I check it, I have no idea how I'm going to get them to find a dynamically loaded string as part of a precompiled token/rule.

Also, there's the instability that my program had during the last assignment. I don't know what caused it - and I spent a long, long time walking through valgrind traces looking. If I can make it be more stable with a <20 line delta, that's great - but it's unlikely I can do so.

Also: letter writing went well enough. Glad to have that done. And good night.

No comments: