Saturday, July 9, 2011

Latest Thoughts on QubLib

I wasn't able to work on QubLib very much this week, and any work that I did put in went to my data structures. I did some thinking about how the STL and QubLib could work together, but that's a topic for another day when I do something with it. Today, I think I'll talk briefly about a long term goal.
One thing that I'm sure we've all noticed lately is the increase in platforms that are actually making money in today's world. Ten or fifteen years ago, for the most part everything was Windows. If you developed software that was intended to run on Windows you were pretty much guaranteed a large pool of potential customers. However, with the advent of smartphones, the game is a little different now. People still use their PCs, which now may be either a Windows or a Mac. Linux is a viable option, but I just don't ever see it becoming a mainstream operating system like Windows and OS X. However, humor me and imagine that developing for a Linux system is important. That means that you have three desktop platforms that you have to develop for. Then, people go ahead and decide that they want their smartphones to be able to communicate and share data with their desktops. Did I mention that they want to be able to do it regardless of what they're running on the desktop or their smartphone? So, if a smartphone could run Palm OS, Symbian, Android, or iOS, it doesn't matter. All of those should be able to talk with your Windows, OS X, or Linux desktop. If you approach this problem with a system agnostic data transfer approach, then maybe using bluetooth or the internet you can transfer data no problem, but data transfer isn't the real issue. The real issue is software development. How on earth are you supposed to have a system that runs on each of those desktop and smartphone platforms, and then how are you supposed to be able to keep those systems in sync with each other? Oh, and did I mention that the programs have to be written in different languages? Android runs Java, iOS runs Objective-C, and Symbian runs something... I'm not really sure yet which is the most viable option, but right now I think they operate best with Qt C++.
This is a future goal of mine. If a person develops something with QubLib in C++ and they don't use any of the special features of a language that aren't common to other languages, then it really shouldn't be too difficult to do cross-language compilation. That way, a person would be able to develop their software in Java for Android systems, and then push the button and their Objective-C and C++ versions are automatically generated. It's a long shot, but I think it's possible. I know that systems similar to this work on projects like the Unreal Engine used for game development, but those systems force the developer to program in the Unreal Scripting language, and then the system will convert the scripting language to the platform dependent code. Why can't I program in what I'm familiar in? Why can't I develop in C++ and have Java code pop out the other end?
It's days like this that I wish that I didn't have to work for a living. Anyways, that's all for today. Keep coding!

Saturday, July 2, 2011

QubLib Continues

Work on QubLib does continue, even if I don't write about it very often. Actually there's been a lot of work going on. I want to write more in my life, which is probably why I've been keeping a journal more thoroughly lately, but I want to keep posting about QubLib too, because I feel it's a really exciting project. Anyways, here's the big thing that I've been working on lately:

Data Structures.

It seems as though I'm destined to work on these forever just because I've changed my design for them so many times, but I think I've finally hit on an architecture that pays off dividends. So, how have I designed them this time around? Let me explain with pictures!

So here's my original data structure design for a LinkedList. It's pretty simple, but that's what I miss about it. I really like the idea of manipulating objects by an explicitly declared interface, and this takes that interface to two different levels: IContainer and IList. I specifically split my interfaces this way because it allows me to share test cases across my data structures. I can talk about that another time, but my test framework works on interfaces, so I can use one set of IContainer test cases on my LinkedList, ArrayList, BinarySearchTree, and anything else that implements the IContainer interface. It's pretty cool and it's saved me a lot of time. Anyways, this was the original design. However, the more I worked with LinkedList and ArrayList, I realized that they shared a bit of code, especially things like checking bounds on the list. So, I decided that they should both inherit from an abstract base class that would implement that functionality and they could use the inherited version.

Tada! ListBase (and several other DataStructureType-Base classes) were born. It was right about this time that I read Effective C++ by Scott Meyers, which I highly recommend to any serious C++ developer. It definitely gave me a more in-depth knowledge of C++. One thing that it also introduced me to was the idea that a class's public interface should be non-overridable by its subclasses and that the functions that a class would override would be protected. I quickly implemented that because I saw the value in pushing error checking higher up the inheritance tree. I don't have it drawn, but a ContainerBase was born out of this design, and it quickly had its own error checking functionality so that by the time a function got down to LinkedList or ArrayList I knew that I had a valid state. It was pretty nice. It led me to discover the dreaded inheritance diamond that gave life to virtual inheritance in C++, but I feel as though I understand that topic now, and I'm once again a happy camper. Then, I began to have some more issues.
I try to test my code with my testing framework that I talked about earlier as much as I can. One caveat with my testing strategies is that I loathe friend classes. I think they're pretty much the devil of computer programming, at least in C++. I don't know if it's my engineering background, but I don't like exceptions to rules, and a friend class is just that: an exception. However, sometimes when you're testing, you really would like to test the internals of a class to make sure that they are working properly. What is a developer to do? One option is to reveal those internals as public functions so that the test code can access and test them, but doesn't that kind of defeat the purpose of making them "internal functions"? I don't want to reveal them on purpose! What's a programmer to do? Enter my latest design strategy:

I call it the crazy-big-and-complicated-architecture-that-is-so-very-nice-but-takes-forever-to-implement data structure pattern! As you can see, the number of classes that I had at the beginning has doubled to get to this structure, but now I can reveal the ArrayList classes to the programmer who will use QubLib and then I can reveal ArrayListImpl to my test cases. ArrayList essentialy defers to ArrayListImpl for everything and it maintains a clean API for a developer to work with. I actually also ended up creating a ContainerBase that functions like ListBase, except on the IContainer level. It's complex, but I think it's worth it. This design also lets me add another class that I cleverly call "List" on the same level as ArrayList and LinkedList. Its sole job is to defer to the fastest default IList data structure in my library. That means that I can swap implementations under the hood, and no one will have to change their code. They'll see an improvement in their library performance just because I changed the backend. I love programming. I was once told that every computer science problem can be solved by just adding another layer of indirection, and boy does that seem to be the case here.

Anyways, that's what I've been working on now. I'm planning on taking this architecture to my smart pointers next and getting a really clean interface there too, and then onto my strings. Lots of work, but I think it'll really pay off once I get this project moving more.

That's all for today. I'll be back next week (hopefully). Keep coding!