7.21.2011

Interfaces in classic C

I like interfaces. They provide an abstract hull for a concrete implementation, very much a good solution for more complex operations that share exactly the same set of operations but differ in implementation. However, I hate interfaces if it's about memory storages like linked lists, arrays, trees and so on. I strongly dislike the concept of iterators, due to many reason including non-predictable runtime performance if you look at the code without knowing datatype is behind. Algorithms should always take advantage of the type of storage they are designed for, no discussion. However, I like interfaces for stuff that's bears some more abstraction, possibly not differing between RAM and harddisk and stuff like that. Though it's, all in all, all just memory and can be memory-mapped nowadays if it's not coverable via non-mapped addressing... I struggle with the decision of rethinking some elementary ITK principles and waging whether I should keep it purely based on direct addresses or extend it with interfaces. Not using interfaces will force the user to create his own memory mapping, but doesn't blow up the whole toolkit. And using interfaces for data storages... No, this would make me even with normal C++ programming and iterator-alike concepts. If I stick to one concept, I'll drag the it through hell and back, that's it. I believe it's better to rely those common hardware features provided by atleast Unix/Linux system (what I doubt). Interfaces produce quite a mess and the only thing I could deem them fruitful is when it comes to dynamic and automatic use of them, chain operations and so on. For example, my forwarding memory allocation model works like that, you just need need to pass a second interface in case it's not allocatable from where you requested it. I could also leave it to the user to do this, but that's a nasty thing cause you usually just want to get some memory and know whether it is possible, or not. I also gives you no advantage of not using interfaces in this case cause there are so many places you can allocate memory in, that it'd be a mess to always implemented that where you need to allocate stuff. So, passed once it stays the same all the time and you don't need to worry. That's different with iterator interfaces cause the only most efficient algorithm is the one that makes best use of it's storage class - there is no other possibility, even the most optimized, abstract algorithm has it's caveats depending on what kind of memory you're operating on. However, that's a tad of philosophy I have to admit, but that's driving a programmer's nuts, isn't it? Well, atleast I know that better results come out when a programmer realizes that.

Hm I guess I sorted interfaces out this time. Sure, all ITK modules have interfaces, too. But that's on a library level, not a in-program function level using structures and so on. I also created some kind of "roadmap" where I'm keeping track of all the modules and ideas I want to realize as well what's finished and what I'm working on. Some things are finished but not yet tested due to my manic type-without-testing approach I sometimes doing almost perfect with no compilation errors or bugs. Especially in my case, it proved fast and safe in development cause I can hack in all my ideas and implementation details with not fear of bugs or annoying error outputs and then systematically debug with no interruption until it works as expected. Maybe I just found the perfect programming rhythm for my kind of person. But I can't deny that the process itself (header first, implementation following, debugging loop) is heavily interface-based cause, as I mentioned above, all modules have interfaces, too. Even a simple function prototyp for a single cpp file is an interface, show exceptionally minimal. It's, however, good to know that I can still wrap all my headers into component-like access structures. The last assignment I'll have to present on Friday, where I had to complete program a component platform just to get the mark using Qt/C++, made me realize how actually interesting the concept of dynamically loading binaries is. I also noticed that before, but I didn't do anything to test it for kicks. Now that I simply know how easy it is and how more easy it is with conventional C (atleast for Linux developers), I think it's a good idea to provide some wrapper functionality for it, later. Wrapper are your best friends as long as they provide only on additional layer between you and your victim.

No comments: