Bless me Father, for I have sinned. It's been one two three weeks since my last post. Wow. Time gets away. And it's not because I've been doing nothing. It is that I've been doing a bunch of experimental code that, if I posted about it, nobody would care. Actually that's not true. I'd care. The truth is that an hour's experimenting with code takes me two hours to write up. I need to get the experimenting done and I really can't afford that much time.
The principle of Six Things seems to come up for me all the time. I wish I could link to a useful explanation of Six Things, but nothing comes to hand right now. It was probably an ABC Science Show podcast I listened to. Basically the average human brain can hold and process only six pieces of information simultaneously and maintain some level of effectiveness. For example, you could ask anybody to memorise a 6-digit number and they'll (usually) do it well. Give them a 12-digit number and they'll get it wrong more often than not.
As we deal with more "inputs", we get progressively less effective. This happens a lot when I'm coding, but even more so when I'm experimenting. I may be writing a function that has multiple variables, a loop or two and some conditionals. This pretty-much uses all of my brain. If, as often happens when I'm coding, I come up with questions about coding, I have to write them down. Or else they're taking up space in my mind and making me less effective. As much as I'd like to think I am of above-average intelligence and possess super-human coding abilities the mundaneness of my daily existence serves to reinforce that, alas, I'm only normal.
But the questions always stack up faster than the answers. So I usually get to a point with my experimenting that I have to call a halt to it, or else disappear down that rabbit hole and never come out. Each time I try to quit I have to assess "did I get the answer I wanted? Did that experiment achieve something?" Usually it does.
So what have I been doing? Well, it started with my last post. I was very happy with how little code I needed to get the GPS data to display. I've displayed GPS data a dozen or so ways now, and the last one is the neatest I think. So I went on a mission to see how I could tokenize the data. I wanted the NMEA sentence, that looks like this:
$GPRMC,030245.000,A,3246.4637,S,15136.1167,E,0.38,142.83,160111,,*1B
... to be broken up by commas so it can be interpreted as numeric data:
Time: 030245.000
GPS Status: A
Latitude: 3246.4637 S
Longitude: 15136.1167 E
etc.
As usual I took it to the extreme and then went a bit further. The thought of having lots of Strings annoyed me. Processing GPS data happens at least 5 times per second. It's character data and all has to be converted to numbers to be useful. So I became fixated on the efficiency of my code. Allocating and destroying String objects is not efficient. (Reusing existing String object is much more efficient, but I thought of that much later). Efficiency, I found, takes three forms. A program that's inefficient to the point of being useless:
Of course I'm trying to tread a path between all three. Now back to Strings.
The built-in String type had some of the functionality I wanted, but not all. It also used all those arcane-looking functions like atoi() memcpy() etc. so I distrusted it from the start. (I'd love to read the implementation of these functions but I still can't find the code.) I wondered what it would be like to build my own string class - and so began the experiment.
I wrote a class called Text. It defined a string as a character array much the way String does. However, instead of allocating an extra by of memory at the end to hold the NULL character (\0) I used a character pointer (char*) to point to the memory address after the end of the string. This adds one byte to the total size (2 bytes for a pointer, less one byte for the null terminator) but I anticipated added benefits because of this. If strings are now defined between two pointers, then any two pointers define a string. So when I have an NMEA sentence, and want a sub-set of that sentence, I only need to define the start and end pointers of the part of the existing sentence I care about. There is no reason to copy the bytes into a separate character array just so they can be terminated by a null.
Everything went well and I created the Text class with it's own ability to allocate and free memory for character arrays and then realised I had actually designed two classes. The Text class does not always need to store its own data. So I defined Text as a class that allocates memory to store text data, and Token to hold only a start and end pointer and associated logic. Oh shit.
As I'm writing this I'm just realising my own mistake. Remember six things? Yeah, well maybe somewhere in the middle of my experimenting I lost track of Thing #71. Text needs to store a start and end pointer. It doesn't care if it's allocating its own storage or using existing memory. I didn't need two classes at all. I guess somewhere along the track I derailed myself.
However, thing number fifty-something still remains. That is, at some point I need to present a "normal" string. How can you print a string defined between pointers? The Print class isn't designed for this. And as yet I haven't thought of a way that someone could call textObject.toString() and get a null-terminated string that Print would accept - without having to instantiate a String object with its associated memory and computational overhead.
So the reason I haven't got any more done on my GPS class is that I'm down an alley-way designing a Text class that's better than String. Of course what may result is that I give up on Text and, with a new appreciation for String, begin to use it willingly. But that hasn't happened yet. So more alley-time for me.
That is all.
The principle of Six Things seems to come up for me all the time. I wish I could link to a useful explanation of Six Things, but nothing comes to hand right now. It was probably an ABC Science Show podcast I listened to. Basically the average human brain can hold and process only six pieces of information simultaneously and maintain some level of effectiveness. For example, you could ask anybody to memorise a 6-digit number and they'll (usually) do it well. Give them a 12-digit number and they'll get it wrong more often than not.
As we deal with more "inputs", we get progressively less effective. This happens a lot when I'm coding, but even more so when I'm experimenting. I may be writing a function that has multiple variables, a loop or two and some conditionals. This pretty-much uses all of my brain. If, as often happens when I'm coding, I come up with questions about coding, I have to write them down. Or else they're taking up space in my mind and making me less effective. As much as I'd like to think I am of above-average intelligence and possess super-human coding abilities the mundaneness of my daily existence serves to reinforce that, alas, I'm only normal.
But the questions always stack up faster than the answers. So I usually get to a point with my experimenting that I have to call a halt to it, or else disappear down that rabbit hole and never come out. Each time I try to quit I have to assess "did I get the answer I wanted? Did that experiment achieve something?" Usually it does.
So what have I been doing? Well, it started with my last post. I was very happy with how little code I needed to get the GPS data to display. I've displayed GPS data a dozen or so ways now, and the last one is the neatest I think. So I went on a mission to see how I could tokenize the data. I wanted the NMEA sentence, that looks like this:
$GPRMC,030245.000,A,3246.4637,S,15136.1167,E,0.38,142.83,160111,,*1B
... to be broken up by commas so it can be interpreted as numeric data:
Time: 030245.000
GPS Status: A
Latitude: 3246.4637 S
Longitude: 15136.1167 E
etc.
As usual I took it to the extreme and then went a bit further. The thought of having lots of Strings annoyed me. Processing GPS data happens at least 5 times per second. It's character data and all has to be converted to numbers to be useful. So I became fixated on the efficiency of my code. Allocating and destroying String objects is not efficient. (Reusing existing String object is much more efficient, but I thought of that much later). Efficiency, I found, takes three forms. A program that's inefficient to the point of being useless:
- uses more storage (RAM) than is available at run-time, or
- takes more computational time than constraints allow, or
- has more bytes of code than the processor can store, or
- any combination of the above!
Of course I'm trying to tread a path between all three. Now back to Strings.
The built-in String type had some of the functionality I wanted, but not all. It also used all those arcane-looking functions like atoi() memcpy() etc. so I distrusted it from the start. (I'd love to read the implementation of these functions but I still can't find the code.) I wondered what it would be like to build my own string class - and so began the experiment.
I wrote a class called Text. It defined a string as a character array much the way String does. However, instead of allocating an extra by of memory at the end to hold the NULL character (\0) I used a character pointer (char*) to point to the memory address after the end of the string. This adds one byte to the total size (2 bytes for a pointer, less one byte for the null terminator) but I anticipated added benefits because of this. If strings are now defined between two pointers, then any two pointers define a string. So when I have an NMEA sentence, and want a sub-set of that sentence, I only need to define the start and end pointers of the part of the existing sentence I care about. There is no reason to copy the bytes into a separate character array just so they can be terminated by a null.
Everything went well and I created the Text class with it's own ability to allocate and free memory for character arrays and then realised I had actually designed two classes. The Text class does not always need to store its own data. So I defined Text as a class that allocates memory to store text data, and Token to hold only a start and end pointer and associated logic. Oh shit.
As I'm writing this I'm just realising my own mistake. Remember six things? Yeah, well maybe somewhere in the middle of my experimenting I lost track of Thing #71. Text needs to store a start and end pointer. It doesn't care if it's allocating its own storage or using existing memory. I didn't need two classes at all. I guess somewhere along the track I derailed myself.
However, thing number fifty-something still remains. That is, at some point I need to present a "normal" string. How can you print a string defined between pointers? The Print class isn't designed for this. And as yet I haven't thought of a way that someone could call textObject.toString() and get a null-terminated string that Print would accept - without having to instantiate a String object with its associated memory and computational overhead.
So the reason I haven't got any more done on my GPS class is that I'm down an alley-way designing a Text class that's better than String. Of course what may result is that I give up on Text and, with a new appreciation for String, begin to use it willingly. But that hasn't happened yet. So more alley-time for me.
That is all.
Comments
Post a Comment