|
|
|
good chemistry is complicated, and a little bit messy -LW |
|
| PerlMonks |
evolving an OO solution for a bitstreamby spurperl (Priest) |
| on Oct 21, 2003 at 08:40 UTC ( #300857=perlmeditation: print w/replies, xml ) | Need Help?? |
|
In the past couple of days I'm quite busy with Perl processing of binary files woes. You can read all about it here and here.
In short, though, I need to treat a binary file (or any file for that matter - the notion of "binary file" confuses many people) as a stream of bits. My smallest quanta of information is bits, not bytes - i.e. interesting data may transcend the limits of bytes. It is clear to me that on the top level, I want to work with strings of "1"s and "0"s, and to use Perl's strengths on them - regexes, string-processing and such. What wasn't clear to me is how I was going to get this nice representation from a rudimentary file. A short intermission: I'm not a great fan of OOP, in the sense that it's not a panacea, but rather a YADM (Yet Another Design Methodology). That's because I think it's too hyped. I don't believe thinking of everything as objects. I believe in "the right tool for the job". Where OO seems fit, it can be a great and clean solution. Where it doesn't fit, enforcing it on a design will only make it messy and unnatural. So I started coding. A function would open the file, unpack() it to "00111100...."s and happily use it. But I quickly understood that this reading and unpacking should be abstracted away in another function. I also understood that what I really need is a "stream" abstraction - just ask for N bits, get them and work on them, ask for the next M bits, et cetera. But this clearly starts to separate into two tasks: opening the file, giving away bits. So I tried two subs with shared static data. Frankly, Perl sucks static-variable-wise. They're not directly supported, and must be hacked-over with my() in a BEGIN block. It didn't feel right. This brought me to consider a package. Vars static to packages are supported nicely, and Perl is very good with packages, so why not... So, I happily tucked the code into a package, and just called BitStream::create($filename) and BitStream::get_bits(128). Hey, but I might need more than one stream simultaneously... ahh... objects. Why not treat BitStream as an object, which stores all the info it needs in a %self hash, and does what I need ? In fact, this was very simple. I must admit that Perl implements OO nicely, at least when simple things are done. So...
---------------- UPDATE ----------------
---------------- UPDATE ---------------- get_bits() now nicely handles incomplete reads, returning just as much as there was left in the stream. So, it now looks like this:
-------------
get_bits() | |
script <================ | BitStream | <== file
| |
-------------
Simple, works, clean, b-e-a-u-t-i-f-u-l (forgive my geeky self). But the best part is ahead: If you're read about my binary woes, you know there's also a memory problem. Files can get very big (100s of Megs), so a clever implementation must be thought of. But, the caller of get_bits() doesn't care ! He gets his bits, whatever BitStream does under the hood. As a matter of fact, there are 3 implementations I consider now:
At the moment, the first solution is employed, as it's the simplest. But whatever solution is chosen, the caller just calls get_bits() ! I will add features to BitStream on a need-basis (being the user of yourself rocks). Features like seek()ing and tell()ing a stream, rewind(), reading backwards, etc. But the moral if the story, to relate to the article title, is: use the best tool for the job, employ techniques on a need-basis. Then, you'll have the most elegant solution for each problem possibly with different design methodologies, but what does it matter, as long as it "feels" clean and robust.
Back to
Meditations
|
|
||||||||||||||||||||||||