Archive for the ‘Perfect Software’ Category

Time Tracking with GTimeLog

Sunday, July 27th, 2008

So I’ve recently started doing some on-the-side contracting work for a relative, so I need to keep track of the time I spend on various tasks.

After some looking around, I decided to give GTimeLog a try, because it seemed to be exactly what I needed without anything extra. I especially like how it has a nice, simple, text-based file format, so I can write my own scripts to fiddle with it if I feel so inclined.

It also has support for launching your favorite mail program to send of daily, weekly, or monthly reports, or export reports as CSV to a spreadsheet program, both of which could come in handy depending on the situation.

I would surely recommend any programmer I know to give it a try for any contract work they might be doing. Well, I suppose anyone I know who’s doing computer-based contract work, really.

The interface looks like the following (click for a larger image):

(more…)

In Search of The Perfect Editor

Saturday, April 12th, 2008

I’ve been searching for the perfect editor ever since I started programming. I’ve found many along the way which have worked to get the job done, but I’ve never really found “The One True Editor.”

Yes, I have used Emacs, and no, it is not it. There are many things I enjoy about Emacs, but there are many things I dislike, and recently Emacs got to the point for me where the bad outweighed the good. I could write a whole post on why I’ve forsaken Emacs, but I’m not going to.

I’ve found a couple of editors which meet my minimum requirements of being small, simple, and easily extendable. They also have some cool features built in, which always helps.

(more…)

In Search of Perfect Software

Friday, April 11th, 2008

The Problem

There are many pieces of software in the world, but very few of them are anywhere near what one would consider “perfect.”

I don’t blame anyone in particular for this. Writing perfect software is quite difficult if the software is to accomplish any sort of non-trivial task. Some come close to the lofty goal of perfection.

Even still, there are certain areas where the mark has always been missed, if only enough to be slightly annoying. I’m being purposely vague here because there are lots of different things wrong with lots of different pieces of software. I’ll get more specific later.

Probably the biggest contributer to this problem is the fact that nobody really knows what perfect software is. I usually know what annoys me about a particular piece of software, but I’m not always sure what would be a better solution.

My solution

There are some types of software which have gotten closer than others to perfection. Web browsers, for example. I’ll readily admit that there are things which annoy me about Firefox, but on the whole it’s a good piece of software, and improving all the time. I have some ideas of my own about the was a browser should do certain things, and I’m not about to go hacking about in the monstrous labyrinth that is the Mozilla source code, so I’ve [started my own browser project][mybrowser]. It will probably never catch up with the other, “real” browsers, but it will keep me entertained and provide me a way to prototype various ideas I have for user interfaces.

There are also some good programming languages out there. Languages like Python, Erlang, and many others make programming “fun again.” Still, for every language there’s something that’s missing, or something that might be cool to be able to do, some area which has been left mostly unexplored. Once again, I’ve started [some][booter] [prototyping][stacklang] so I can play around with some new ideas and push some boundaries which I think should be pushed (or at least ones which look as though they may be fun to push).

So what’s the way to write perfect software?

(more…)

Doing it Right from the Beginning

Monday, December 17th, 2007

My coworker Scott Martin recently posted a list of things to do from the beginning of a project..

I had planned to post something along those same lines myself, but I guess he beat me to it.

I’ll throw in my two cents with a much shorter and vaguer list, with my comments and a few extra items as well. This will make a lot more sense if you read the list at the above link first.

  • Internationalization + Smarty

    These two items go together. Basically, there shouldn’t be any text which makes its way to the users which comes from anything but a template file. Seriously, don’t put text in your code.

  • Code standards

    Here’s a secret: what your standards are really doesn’t matter. It’s the fact that you have standards that matters. It’s really annoying to read code with two different layouts. Pick one and stick with it.

  • Code generation

    I disagree with Scott about code generation being bad. The one thing that needs to be done for it to be okay, however, is for it to be generated, and updated, automatically. The first code you should write isn’t the code to generate the code, but the code to call the code to generate the code when the source of the data used to generate the code is changed.

    For example, if you are reading in one file to generate another, then before you read in the file, run some code which checks the last modified time of the generated file and compares that with the last modified time of the source file, if the source file is newer, regenerate.

    If you feel so inclined, also check the timestamp on the code which generates the file, and if it is newer than the generated file, regenerate also. This will get rid of the instance where you change the generator code but don’t change the input file.

    Alternatively, if you have some sort of interface or tool which generates the input file, have that tool run the script to update the generated file.

  • URL rewriting

    As we all know, Cool URIs don’t change. So make some sensible decisions at the start of your site design, and stick with the URLs from there on out. All you need is a single script to redirect all URLs to (except images and CSS and things), which then delegates the work out to some actual PHP files. This is also helpful in that it makes it so you don’t have to have all of your PHP files inside of your document root, just the one that does the routing, which brings me to my first new rule…

  • Keep non-documents out of your document root.

    The fewer things you actually have in your document root, the fewer unexpected security holes there will be. If a file is not going to be directly accessed from a web browser, don’t put it where a web browser can get to it. All of your configuration files and almost all of your code should be kept out of your document root.

    A structure like the following works well:

    • application root
      • htdocs – static HTML files, images, CSS files, a single code file to load in other files based on the requested URL
      • src – all of your actual code. Set your inclide_path to here and keep everything neatly organized into subdirectories
      • templates – Smarty, or whatever templates you are using.
      • cache – whatever sort of disk cache you need. This includes Smarty cache, RSS feed cache, etc…
  • Don’t Repeat Yourself (DRY)

    This is basic stuff right here, but it can never be said enough: Don’t write code that does the same thing as code you’ve already written. Or if you have to do so, then combine the two pieces of code together. It is a huge pain when you have to figure out why something is working the old way when you already changed the code that does that thing to do it a new way.

    If you are copying and pasting code, then something is probably wrong.

  • Don’t Repeat Other People/Don’t Reinvent the Wheel

    This one is a bit different. What I mean by this is don’t write any code that you don’t have to. If somebody else has a library that already does what you want, use that, unless there is a very, very compelling reason for you not to. If a library has licensing issues, or is really slow, or doesn’t fit into your platform somehow, it might makes sense to write it yourself, but first check to see if there’s already something else which meets your needs.

    Spending an hour searching something is going to take less time than writing it yourself.

What guidelines do you follow from the start with every project that you do?

BooTer Reduced

Friday, November 30th, 2007
Edit: Apparently the way to prove a new esoteric language is turing-complete is to implement a [BF][] interpreter. This technique has been used to show that [LOLCODE is turing complete][lolcode-bf], so I suppose I could target that as the first non-trivial program to write as soon as I get a working BooTer interpreter :D Or, I suppose I could implement a LOLCODE interpreter in BooTer in which I could run a BF interpreter…

Thinking about BooTer, I decide that I wasn’t making it esoteric enough..so I’ve slimmed down my specification for simpler implementation, and much more difficulty doing anything useful with it :)

The only thing allowed is simple expressions and boolean ternary expressions. No comma-separated lists of expressions, no assigning expressions to variables, no symbols, no quoting of expressions.

Maybe in the future I’ll re-expand it out into a more “real” language, but for now I just want to do something that I can do simply and easily without accidentally building an entire broken LISP.

So, with all that stuff gone..what’s left? What’s different now?

  • The boolean-ternary operator is in an order which won’t drive me insane to write programs in. The boolean expression comes first. If true, the expressions evaluates to the second expression, if not, it evaluates to the third. This now works basically just like the ternary operator in most other languages…but with a different syntax and the possibility of using the re-eval operator.

  • A BooTer program is now a single boolean-ternary (booter) expression, with optional nested booter expressions.

  • The center portion of a booter expression (the “boo” part), must evaluate to either true or false. False is represented by the integer 0, or by null. Anything else is true.

  • null is represented by the lack of a value. This is useful for instances where the left or right portion of an expression will never be used, for example: ( ...do something here... : x = 5 : )

  • There are only numbers and strings as primitive types.

  • Variable names can start with upper or lowercase letters.

  • There’s only a single array type. Array items are assigned and accessed using the standard [] subscript operator. Creation of an array is implicit with the assignment of the first item to that array. If you use the subscript operator to make an assignment to a previously existing variable, the old variable is overwritten with the new array. The previous array literal syntax still applies. Only primitive values and variable names can be used in the array literal syntax.

  • Math and boolean order of operations are the same as in most programming languages these days.

  • The re-eval operator, ^, still works as previously stated.

  • Comments start with a semicolon and continue to the end of a line.

The previous example programs are both a bit more complex than they were previously (but hey, the parser and interpreter will be much easier to implement!):

Infinite NOOP loop: ( ^ : : )

100 bottles of beer:

(n = 101 :
  (
    (n = n-1 : 
      print [n, "bottles of beer on the wall!\n"] : 
    ) : 
    ^ : 
  ) : 
)

In the beer example, assume that print prints the items passed into its array to the stdout and then evaluates to the same string it printed out.

  • While n is greater than 0, the sub-expression will evaluate to the string returned by print, which by the rules above equates to true, thus causing the re-eval operator to be evaluated, looping back to the expression (n = n-1).

  • When n finally gets assigned 0, the expression will evaluate to the third, empty, sub-expression, which equates to false, which means the center of the outer expression now evaluates to false as well, and thus the third expression of the outer expression is evaluated. It evaluates to null, which is the return of the program.

Here’s a BooTer “for loop” with more of an explanation of what’s going on:

(i = -1 :              ; initialize loop variable
  (
    (100 > i = i + 1 : ; increment loop variable, check it against condition
      ...              ; do things, must evaluate to true
    :
      ...              ; this one must evaluate to false (leaving it empty works)
    ) 
  :
    ^                  ; re-evaluate this expression, causing the loop
  :
    ...                ; whatever can go here, this will be evaluated after the loop is done
  )
: )                    ; done, this last sub-expression will never be run

Even with this new “simplified” syntax, it’s enough to make your head hurt. Now I just need to actually write a reference implementation with some standard library calls, then try to write something non-trivial with it. Who wants to try their hand at writing a BooTer web server?