Showing posts with label coding. Show all posts
Showing posts with label coding. Show all posts

Tuesday, December 4, 2007

Back from the Dead

So I started coding again, I had to clean out the cruft and get things working the way they were meant to. There are a couple of different projects I am working on at the moment. AutoNant is Public Domain and ZoeTools is GPL. The sudoku code is loosely based on code of an unknown license (for now).

The first is a set of useful utility classes calle ZoeTools. It currently has three seperate assemblies: Algorithms.DancingLinks (a Knuth DLX implementation), Objects.LinkedMatrix (a matrix which is used by the previous assembly) and Tools.Hasher (a progressive file hasher, mainly for large files). They are designed to be stable and well-tested. If useful, I encourage you to use them in your projects.

The second is a meta-build-system. I like NAnt for building .Net projects and it is much nicer to use than autotools and make. However, it is also verbose and I was finding that I had to keep copy-and-pasting boiler-plate code. Since it is XML, I figured it would be easy to set up an XSLT-based system to create .build files from a minimal description. It did turn out awkward on the backend but on the front-end, all you have to do is create a short XML .autonant file and run it throught an XSLT processor. The trade-off is that your directory structure is standardized. There are various pros and cons for this setup but I like it. It relies heavily on symlinks though and would prove difficult on file systems which don't have symlink capability or which have awkward limited systems (such as Windows' NTFS). I would only recommend trying it out on a *nix box.

My programs are all made with development versions of Boo and Mono so you may have to grab them from SVN and build them yourself. If you install into /usr/local/, you will have to run "export MONO_GAC_PREFIX=/usr/local" so it can find the assemblies.

My first cleaning task was to change all the symlinks in the build/ and external/ directories to point to lower-case versions of their names. The reason for this is that when you checkout modules from SVN, they're in lower-case so this just makes it easier.

The next step was to tell AutoNant where to find the Boo.NAnt.Tasks.dll extension library. Unfortunately, Debian chooses not to include it in its packaging of Boo. Since I use the SVN version, it's not that big of a deal but still makes for an awkward oversight. If you download that file, just place it in /usr/lib/boo/ and all should be fine. I'm not entirely sure how I made it before telling NAnt where to find the file... What I did was add a tag which will get added to your top-level .build file which contains the location for the required library. It currently is created dumbly, whether your project is in Boo or not but it not used if it does not need Boo. I'll probably fix that tomorrow. The default file location is /usr/local/lib/boo so you might have to alter that in your projects' generated .build file.

After that finally got setup, I was on my way and running... well, almost. It seems that one of Boo's "useful" modules was removed - Boo.Lang.Useful.IO.TextFile. This made it easy to read in a file without having to create a StreamReader. However, .Net 2.0 added a useful System.IO.File.ReadAllLines static method, which greatly shortens code to simply read in a small text file. The first example reads a line and prints it, continuing until no more lines can be read. The second reads in a text file into an List and then prints each item. So, the second actually processes the list twice but there are many cases in which the first method also processes it twice and so it's not so bad. For small files, I'm sure the effect is negligible.

.Net 1.1 (C#).Net 2.0 (C#).Net 2.0 (Boo)
using (StreamReader reader = File.OpenText ("test.txt")) {
 string input = null;
 while ((input = reader.ReadLine ()) != null)
  Console.WriteLine (input);
}
foreach (string input in File.ReadAllLines ("test.txt")) 
 Console.WriteLine (input);
for input in File.ReadAllLines ("test.txt"):
 print input

If you would like to try out my programs, here's all you have to do:

  • svn co http://autonant.googlecode.com/svn/trunk autonant
  • svn co http://zoetools.googlecode.com/svn/trunk zoetools
  • svn co http://sudokusolver-boo.googlecode.com/svn/trunk sudokusolver-boo
[You may have to edit zoetools/ZoeTools.Algorithms.DancingLinks/default.build, zoetools/ZoeTools.Objects.LinkedMatrix/default.build, and sudokusolver-boo/default.build if your Boo.NAnt.Tasks.dll is not in /usr/local/lib/boo.]
  • cd sudokusolver-boo
  • nant
  • cd bin
  • cp ../test/sudoku.txt .
  • mono SudokuSolver.exe

Have fun and if you have any trouble, questions, ideas, etc, please comment!

Tuesday, November 20, 2007

Music Player Ideas - Part Two

This is a follow up to my previous post regarding a new music player currently in the concept stage. The previous post introduced the project and listed several good ideas for the project from the programmer's perspective (generalizable to other projects). This is a list from the user's perspective.

Interface design for Calliope
  1. Single-Window. I don't like the messy, multi-window approach of applications like The Gimp, Pidgin (aka. Gaim) or Muine. Unneeded parts may be hidden on-demand instead.
  2. Playlist-Oriented. The main region should be a playlist, similar to Muine and unlike iTunes.
  3. Album-Oriented. Albums should be simple to add or remove from the playlist as well as individual songs. Album covers should feature prominently.
  4. Simple. The interface should be simple, straight-forward and designed to integrate well with other applications. Pluggable user-interfaces are a possible solution. Clutter is an anathema. Both the interface and the memory/disk footprint should be kept minimal.
  5. Extensible. Third-party plugins provide a valuable way to add functionality to a program, there should be a simple interface for adding/removing, enabling/disabling and configuring particular plugins.

What else can you think of?

Monday, November 19, 2007

Music Player Ideas - Part One

So it's been a while since I've done any Muine work or even anything at all since my computer has been out of order and I have been too busy and broke to get it set up again. Well, things are changing, I've got some parts on the way and we'll bring this blazing fast Pentium II back up to suck my life away chasing bugs sometime next week.

So, to get a jumpstart on this whole shift back to hacking (it's cold and icky outside anyway), here is a brainstorm for my next project. This post is similar to the one I made a few months ago (note the "Gnome 2.18! Booyah!" ~ Gnome 2.20 was recently released on its six month time-schedule).

I'm not seeking to terribly re-invent the wheel, although music players are a dime-a-dozen now. What would make my player stand out from the crowd? Well, having worked on Muine a fair bit, most of my ideas are realized in that project. However, I have my own objections to other ideas and design decisions.

I think the name "Calliope" is not taken and might work. So, let's go with that. What would Calliope look like, to the user and the programmer?

Coding for a new project
(User interaction to follow)
  1. Written in .Net/Mono. If glue code is needed, consider generalizing it in a seperate library. This incurs an unfortunate overhead compared to C/C++ but I believe it is well worth it.
  2. Written in Boo. Boo is a beautiful little language inspired by Python. I came from the Perl/Python/Ruby world with little C/C++ experience (my skills are still poor). I loved the .Net platform for it's power in sharing libraries (even ones written in C) and statically-typed nature. Many bugs which show up in runtime with interpreted languages instead show up at compile-time in compiled languages. Like essentially everyone, I strongly associated .Net with C#. However, I loathed having to type far more than I believed I needed to in order to get my point across. Boo is much more intelligent than C# but is a .Net language so it's fully interoperable with other .Net languages such as VB.Net, C# and Nemerle. As the Boo homepage puts it, Boo is "a finger friendly language."
  3. Designed to be portable. No *nix-isms or Gnome dependencies (like Muine). Even possibly consider seperating the front-end from the back-end and making the front-ends pluggable. We don't want to turn into "crazy theme heaven" but it'd be nice to make it look like Windows, Mac, Gnome, or KDE on their respective platforms rather than a one-size-fits-all model. If statement 1 is followed, it may be possible to even run on different platforms without recompiling!
  4. Tested from the beginning. Unit tests and other forms of automated testing can be very helpful. I went from simply running the program and doing a couple simple tasks and hoping it didn't crash to making much more robust programs and libraries that were unit tested, thus catching many bugs automatically. It's much easier to start with testing than to implement it later. At first it feels awkward and inane but it is well worth the extra bit of effort. Before you commit, write unit tests. Always do bounds-checking. NUnit is the unit testing suite par exellence.
  5. Documented. They say, "If it was hard to write, it should be hard to understand." Well, "they" obviously never had to work on a collaborative project or even come back to one several months later. Perl is joked about for being a "write-once" language because you can never decipher what it was that you had hacked together. I'm not suggesting full-on formal comments that take more space than the actual code, just a quick summary and notes. I haven't tried it yet but the Natural Docs parser looks nicer than the C# XML comments.
  6. Easy to build. The NAnt build-engine is much superior to 'make' but requires awkward, long-winded XML. I have written a set of XSLT scripts called AutoNant to make everyone's life much simpler. It requires a standardized code tree though and doesn't support multiple directories under src/ (which, IMHO, is good because it forces people to split off libraries). Symlinks are used to tie the whole system together, including dependencies so you can build the whole shebang if a library changes. Of course, this means it doesn't work on systems which don't support symlinks (namely, Windows XP and earlier ~ Vista has mklink, which should work) but for distribution, the whole thing can be tar'ed up with dereferenced links (thus importing copies of dependencies' source if they are small and obscure).
  7. Well-organized. Organizing your code makes life easier. I use a pattern of: Objects, Variables, Constructors, Properties, Public Methods, Private Methods. Each section has a header and within that section, all methods are alphabetical and sub-categories are defined if needed. Please don't make 1000 line classes or 100 line methods. I also try to call only one method per statement (thus: foo (bar (baz)); becomes: bar_baz = bar (baz); foo (bar_baz);). This seems to help keep code clear. I'm simple-minded, I know so things need to be kept in short phrases. Indeed, 80 (78, actually) characters is about right (I don't indent for namespace or class so that saves a few) for reading without being crazy verbose and jamming too much on a line. Finally, use tabs to line up statements please, that's why God invented them.