A lot of people will talk about how you shouldn’t writing “another string class” or try to write “another msg passing framework”. This is because tons and tons of people have done it in the past and it’s stupid to repeat their work.
This is true, but there is also something to be said about the value of avoiding external dependencies, and completely owning your code. When you own your code you understand it through and through, and you can fix problems quickly and expand it just as quickly.
For example, we started the project using the excellent juce framework for the audio engine and basic string functions, and the Qt framework for all the gui stuff. We were effectively working for a software startup and needed to get a product out quickly to pay our salaries, so this totally made sense.
Later on we ran into name conflicts on symbols like “T”, “String”, “ComboBox”, and “macro” – STUPID. Even later on, and continuing on today, we ran into linker problems including project config across multiple platforms, exported symbols related to creating new dlls, basically all kinds of stuff all across the board. We even ended up diving deep into all that platform-specific gui code that we were trying to avoid by using Qt by writing event filters and unit tests to ensure that their code worked as a plugin in an external host app.
Well, Eventually I wrote a simple UVal class to hold atomic types and allow some basic serialization. Over time, this class grew with ascii string functions, then unicode, then url parsing, midi parsing, etc. Today it is completely self-contained, copiable, castable, serializable, basically it totally kicks ass, and can be used with zero dependencies.
Now, the lesson is that if I had just sat down and written the stupid thing (among other similar self-standing classes) with a few good tests from the start, I’d have saved a shit load of time trying to smash all of our dependencies together over various platforms, binary configs, dll exports. I also can jump right in the code to remember how it works and get the thing to work.
These days I use our “UVal” whenever I want a string, and I shudder whenever I see “juce::String”, because it isn’t portable when creating new light-weight binaries because I have to link in juce and all the Carbon/CoreAudio/IOKit/DirectX dependencies. So the lesson reads: “Just write your own damned string class.”
This works because code should be DISPOSABLE. You should be good enough with your tools to re-write things very quickly, and banging out a simple string/url/midi/blob class should not be a big deal. Even in languages like C or C++, your goal should be rapid prototyping and quick, easy, translation of idea to implementation.
These days whenever I look for an external library I look for one of two things:
1) Is it clean enough that I can copy it right into our source tree and rip it apart and modify it as if it were my own – because by then it will be. I did this with the oscpack sources.
2) Is it a good enough example of a cross-platform abstraction that I can not run it but read it and copy the methods into my own similar classes. I did this with Qt and it’s Thread/Mutex/Condtion/Semaphore/SystemSepmaphore classes.
We use the following libraries unmodified in order to stay current with their respective authors:
– PACE (ultra closed source)
I have ripped apart and stolen ideas (NOT code) from the following:
– oscpack (for parsing)
Looking back I would have started from scratch with our own basic widget classes (combobox, listwidget, tablewidget, button, knob, etc) and used ideas and/or code from the Qt classes. There were far too many bugs in Qt for us to wait for fixes from TrollTech, and their behavior is sometimes too complex from trying to comply with native behavior on all of their supported platforms (just select the god damned list item I click on!!!)
Bottom line: own your code, write your classes, move on.