<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Black Bag Operations Network &#187; smalltalk</title>
	<atom:link href="http://www.blackbagops.net/category/smalltalk/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.blackbagops.net</link>
	<description>Weapons and Intelligence in the War Against "Them"</description>
	<lastBuildDate>Sun, 03 Jan 2010 11:44:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Summer of Rails</title>
		<link>http://www.blackbagops.net/2008/09/21/summer-of-rails/</link>
		<comments>http://www.blackbagops.net/2008/09/21/summer-of-rails/#comments</comments>
		<pubDate>Sun, 21 Sep 2008 10:10:00 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[Objective C]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[seaside]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[squeak]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=137</guid>
		<description><![CDATA[I&#8217;ve now worked on three different Rails applications.  One of them was from scratch, the other two I took over from someone else.  The thing I like most about Rails is Active Record &#8211; it just works and it is easy to use &#8211; even for existing databases (although it takes a bit [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve now worked on three different Rails applications.  One of them was from scratch, the other two I took over from someone else.  The thing I like most about Rails is Active Record &#8211; it just works and it is easy to use &#8211; even for existing databases (although it takes a bit more work to specify the mappings).</p>
<p>I have a project coming up that would probably be a great Seaside candidate.  The database has to be postgresql (according to the client).  There is a native cocoa component &#8211; I&#8217;ll probably give <a href-"http://basetenframework.org/">BaseTen</a> a try.  For the web component, the obvious candidates are Rails (although I don&#8217;t know the state of Rails with PG &#8211; only mysql), and Seaside/Glorp &#8211; but I need to use Glorp to work like Active Record since the DB will be the master source of record for the schema.</p>
<p>Sadly, it doesn&#8217;t look like Glorp&#8217;s ActiveRecord on Squeak is ready for prime time, I might have to kind of finish that implementation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2008/09/21/summer-of-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Looking for work again</title>
		<link>http://www.blackbagops.net/2008/03/03/looking-for-work-again/</link>
		<comments>http://www.blackbagops.net/2008/03/03/looking-for-work-again/#comments</comments>
		<pubDate>Mon, 03 Mar 2008 22:21:27 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[seaside]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[squeak]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=116</guid>
		<description><![CDATA[I&#8217;ve been doing a lot of PHP lately &#8211; shopping cart integration, web service clients, lots of ecommerce stuff.  But I&#8217;m coming to the end of these projects and am looking for new challenges.  Got a project or position that I can do remotely?  Drop me a line.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been doing a lot of PHP lately &#8211; shopping cart integration, web service clients, lots of ecommerce stuff.  But I&#8217;m coming to the end of these projects and am looking for new challenges.  Got a project or position that I can do remotely?  Drop me a line.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2008/03/03/looking-for-work-again/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;m a Google Summer of Code Mentor!</title>
		<link>http://www.blackbagops.net/2007/03/21/im-a-google-summer-of-code-mentor/</link>
		<comments>http://www.blackbagops.net/2007/03/21/im-a-google-summer-of-code-mentor/#comments</comments>
		<pubDate>Thu, 22 Mar 2007 07:13:36 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[squeak]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=104</guid>
		<description><![CDATA[Are you a student? Want to make some cash?  Want to do it with Smalltalk?  Sign up for one of my Google Summer of Code projects.
]]></description>
			<content:encoded><![CDATA[<p>Are you a student? Want to make some cash?  Want to do it with Smalltalk?  Sign up for one of my Google Summer of Code <a href="http://wiki.squeak.org/squeak/5936">projects</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2007/03/21/im-a-google-summer-of-code-mentor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cheshire Cat at the Seaside</title>
		<link>http://www.blackbagops.net/2007/02/26/cheshire-cat-software-process/</link>
		<comments>http://www.blackbagops.net/2007/02/26/cheshire-cat-software-process/#comments</comments>
		<pubDate>Tue, 27 Feb 2007 03:36:22 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[seaside]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=103</guid>
		<description><![CDATA[ `Would you tell me, please, which way I ought to go from
here?&#8217;
Alice speaks to Cheshire Cat
`That depends a good deal on where you want to get to,&#8217; said the
Cat.
`I don&#8217;t much care where&#8211;&#8217; said Alice.
`Then it doesn&#8217;t matter which way you go,&#8217; said the Cat. 
Steve Jobs coined a saying Real Artists Ship during [...]]]></description>
			<content:encoded><![CDATA[<p><em> `Would you tell me, please, which way I ought to go from<br />
here?&#8217;</em></p>
<p><em>Alice speaks to Cheshire Cat</em></p>
<p><em>`That depends a good deal on where you want to get to,&#8217; said the<br />
Cat.</em></p>
<p><em>`I don&#8217;t much care where&#8211;&#8217; said Alice.</em></p>
<p><em>`Then it doesn&#8217;t matter which way you go,&#8217; said the Cat. </em></p>
<p>Steve Jobs coined a saying <a href="http://www.folklore.org/StoryView.py?project=Macintosh&#038;story=Real_Artists_Ship.txt">Real Artists Ship</a> during the development of the <a href="http://www.apple.com/getamac/">Macintosh</a>. He was trying to bring the chaos under control a bit and keep people goal oriented.</p>
<p>During any software project, there is a chaotic early period during which the vision is formed and experiments performed to test approaches towards achieving the vision.  The code base during this time will be unstable and generally unusable. Eventually, the general principles will get worked out, the architecture will gel, and the rest of the project is spent converging towards a stable implementation.  When the software reaches an appropriate level of quality and stability, a release is made.</p>
<p>Releases are forks in the software history.  For the supported lifetime of the release, every fix has to be done twice.  Once in the mainline code base that continues to evolve, and once in the stable release branch.  This is just part of the cost of having users.  It is extra work, but without it, you will not attract users.</p>
<p>Software projects without releases are shifting sands and lack the stability required to support great buildings.  I think this is part of what is holding back <a href="http://squeak.org">Squeak</a> and I was really pleased to see <a href="http://st-www.cs.uiuc.edu/users/johnson/">Ralph Johnson</a> of &#8220;<a href="http://en.wikipedia.org/wiki/Design_Patterns">Design Patterns</a>&#8221; fame offer to take on the management of the Squeak 3.10 release.  He is focused on improving the quality of the base system.  This is good because over the years Squeak has accreted a lot of experimental code that sort of works, but isn&#8217;t really production quality.  Now progress is difficult to make because the lack of polish is hindering the development of new capabilities.  Time to clean house to prepare for the next great wave of innovation.</p>
<p>Sadly, the <a href="http://seaside.st">Seaside</a> project hasn&#8217;t taken the same position.  There are a few developers, unpaid who are doing this in their spare time, like all open source projects.  They&#8217;ve done great things to improve the platform.  However they&#8217;ve been working on something they called version 2.7a for awhile and recently announced they were starting 2.8a.  No release for 2.7 was really declared and the criteria for bumping the versions doesn&#8217;t seem well expressed.</p>
<p>Compare this to <a href="http://rubyonrails.com/">Ruby On Rails</a> site, where you can find a big red arrow inviting you to download the latest stable release to get started.  <a href="http://seaside.st">Seaside</a> has no equivalent, and a newbie coming to the seaside project would likely be paralyzed with indecision with all the various branches, labels, and versions available &#8211; nothing clearly labeled &#8217;stable release &#8211; start here&#8217;.</p>
<p>People are not inclined to bet their livelihoods on software of indeterminate stability.  I hope a release culture emerges soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2007/02/26/cheshire-cat-software-process/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Seaside update complete!</title>
		<link>http://www.blackbagops.net/2007/02/06/seaside-update-complete/</link>
		<comments>http://www.blackbagops.net/2007/02/06/seaside-update-complete/#comments</comments>
		<pubDate>Tue, 06 Feb 2007 15:18:51 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[seaside]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[squeak]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=97</guid>
		<description><![CDATA[That was easier than I thought &#8211; thanks to a nearly complete port done by my predecessor.  However, I have finally thrown in the towel and upgraded the entire application to a 3.8 Squeak image.  3.8 brings a lot of baggage I don&#8217;t need &#8211; like character encodings and true type font rendering.
However, [...]]]></description>
			<content:encoded><![CDATA[<p>That was easier than I thought &#8211; thanks to a nearly complete port done by my predecessor.  However, I have finally thrown in the towel and upgraded the entire application to a 3.8 Squeak image.  3.8 brings a lot of baggage I don&#8217;t need &#8211; like character encodings and true type font rendering.</p>
<p>However, enough tools such as squeakmap and glorp have become dependent on the newer apis that integrating new code was getting to be too hard.  So I started with a clean 3.8 image and started loading Monticello packages and eventually ended up with a completely new build.  Then I upgraded the <a href="http://seaside.st">Seaside</a> version.</p>
<p>With a new build and upgraded infrastructure, I then successfully loaded <a href="http://www.lukas-renggli.ch/smalltalk/magritte">Magritte</a> into the image.  So now I have been working through the tutorials.  </p>
<p>More on that later.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2007/02/06/seaside-update-complete/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Database Transplant Successful</title>
		<link>http://www.blackbagops.net/2007/01/31/database-transplant-successful/</link>
		<comments>http://www.blackbagops.net/2007/01/31/database-transplant-successful/#comments</comments>
		<pubDate>Wed, 31 Jan 2007 22:22:36 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[seaside]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[squeak]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=96</guid>
		<description><![CDATA[OmniBase is dead.
I killed it.
The replacement with GLORP has been successful.  Rate of error discovery has stabilized and, after about 3 weeks of production experience and many small fixes, is now below OmniBase&#8217;s on its best day.
A few things I&#8217;ve learned along the way:
1) Put limits on all search queries.  All of them. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.gorisek.com/WikiDoc/WikiPage">OmniBase</a> is dead.</p>
<p>I killed it.</p>
<p>The replacement with <a href="http://www.glorp.org/">GLORP</a> has been successful.  Rate of error discovery has stabilized and, after about 3 weeks of production experience and many small fixes, is now below OmniBase&#8217;s on its best day.</p>
<p>A few things I&#8217;ve learned along the way:</p>
<p>1) Put limits on all search queries.  All of them.  Too many times in the last couple weeks the system became unresponsive for a couple minutes as it fetched every blessed row in the database.  If you&#8217;re getting that much stuff, you&#8217;re not gonna find it.  I&#8217;ve limited all searches to 20 rows.  </p>
<p>2) Use plain old objects wherever possible.  OODBs have a history of being rotten at schema migration.  So all objects used dictionaries for ivar storage.  This makes it easy to add or remove ivars without getting messed up in the OODB as the object&#8217;s &#8216;format&#8217; is always the same.  However, all that hashing and fetching, and searching, isn&#8217;t free.  I didn&#8217;t realize how expensive it was until I ripped it out and replaced them with vanilla ivars.  Zooooom!</p>
<p>Because the mapping is from the objects to the RDBMS through GLORP on an attribute level rather than relying on blitting a whole object as a chunk, the format of the objects is decoupled from the database representation.  Changes in the object&#8217;s binary format has no bearing on the database representation.</p>
<p>3) When generating accessors &#8211; add lazy initialization where nil is not an acceptable value.</p>
<p>4) Keep it meta.  The meta model is the most important thing we have.  With a good meta model all else can be rapidly replaced.  Consequently, I think the next step in evolution &#8211; conversion of the meta model to use <a href="http://www.lukas-renggli.ch/smalltalk/magritte">Magritte</a> and then replacement of the UI to use Magritte as well, will radically improve agility.  </p>
<p>Meanwhile, to prepare, I&#8217;m updating the version of <a href="http://seaside.st">Seaside</a> that the application is built on.  This is turning out to be harder than I thought as Seaside has moved on quite a bit and many classes in my old version have been simply replaced in the newer one.</p>
<p>The really great thing about using meta facilities like glorp and magritte, is that the application continues to shrink until it is mostly just the meta model.</p>
<p>Less code, less bugs.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2007/01/31/database-transplant-successful/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Records and Objects</title>
		<link>http://www.blackbagops.net/2007/01/02/records-and-objects/</link>
		<comments>http://www.blackbagops.net/2007/01/02/records-and-objects/#comments</comments>
		<pubDate>Tue, 02 Jan 2007 18:10:48 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[seaside]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[squeak]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=94</guid>
		<description><![CDATA[I&#8217;ve been slow in posting this because I&#8217;ve been trying to make a deadline and there hasn&#8217;t been time to do anything else.  But at the moment, the data migration scripts are running and I&#8217;m just babysitting a pair of computers watching for problems, tweaking the code, and restarting the migration.
And it is taking [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been slow in posting this because I&#8217;ve been trying to make a deadline and there hasn&#8217;t been time to do anything else.  But at the moment, the data migration scripts are running and I&#8217;m just babysitting a pair of computers watching for problems, tweaking the code, and restarting the migration.</p>
<p>And it is taking forever.  The old <a href="http://www.gorisek.com/WikiDoc/WikiPage?page=OmniBaseâŒ©=English">OmniBase</a> db is about 880M, a fair amount of it is garbage.  A hot backup script written by OmniBase&#8217;s <a href="http://www.gorisek.com/">author</a> takes over 2 hours to run.  It doesn&#8217;t reinflate the objects either.  This is just not scaling.  At any given time, I figure this application hosts perhaps 20 users tops.  On those days, it crawls.</p>
<p>The users have been wanting extracts for generating annual reports for the last 4 months.  I have written numerous scripts to try to generate this for them.  They always fail.  Often, after a few hundred reads, OmniBase will get itself into a state with some hanging locks and will need to be killed.  A script that tries to touch every object in the database takes well over 30 hours to run.  Why?  I&#8217;m not sure.  Also, users are asking for reports that involve complex traversals that take too long.  Not enough entry points into the data.  There has to be a better way.</p>
<p>Enter PostgreSQL.  The best and most free database of the free solutions.  Postgres rocks.  It just works.  The tools are nice.  The data type selection is extensive.  It is easy to extend with additional scripting languages.   The most magical (to me) utility is pg_dump.  This little gem can back up an entire fully populated postgres database with equivalent data, hot while the app is running, in about 10 seconds.  The resulting file is around 140M.  I&#8217;m sold.</p>
<p>Except that, because of the &#8216;magic&#8217; nature of OODBs, this application is written (mostly) as if all objects are just in memory &#8211; so converting to a SQL oriented format just wasn&#8217;t going to be feasible.</p>
<p>So I adopted <a href="http://www2.laubach.at/kwiki/">GLORP</a> and set out to emulate the existing database api.  This has been successsful.  Wildly so.<br />
Glorp uses a meta model &#8211; actually two of them &#8211; one for the databse, one for the objects, plus a mapping model in between.  The whole bundle is contained in a class called DescriptorSystem.  DescriptorSystem is abstract and uses the <a href="http://en.wikipedia.org/wiki/Template_method_pattern">Template Method Pattern</a> to help you build out the models.  You subclass DescriptorSystem and then override methods like allClassNames, allTableNames and so forth.  The initialize method will call these and then start iterating over them calling methods with names derived from items in the list.  So if you have a class Login mapped to a Table LOGIN, you need to add &#8216;Login&#8217; to the list returned by allClassNames, &#8216;LOGIN&#8217; to the list returned by allTableNames, and methods called classModelForLogin that creates and returns the appropriate class model describing Login, and tableForLOGIN that returns an initialized DatabaseTable.</p>
<p>Inside of the classModelForLogin, you create a GlorpClassModel, give it a name, and  then you describe attributes by calling methods like</p>
<p>newAttributeNamed: aSymbol collection: collectionClass of: aClass</p>
<p>for single values and toOne relationships or</p>
<p>newAttributeNamed: aSymbol collection: collectionClass of: aClass, Field, Relationship</p>
<p>for toMany relationships.  Notice that this adds the typing information for attributes that is typically missing in Smalltalk.<br />
The other model represents the underlying database and includes objects like DatabaseTable, DatabaseColumn, ForeignKeyConstraint, DatabaseSequence, DatabaseIndex and such.  Stuff all relational databases have.  You describe your database procedurally, same as you did with the class model, only you implement tableForLOGIN and say things like:<br />
system tableNamed: aString<br />
addColumnNamed: aString type: aDatabaseType<br />
addForeignKeyConstraint: (ForeignKeyConstraint sourceField: srcField targetField: toField)</p>
<p>You have to be totally explicit here, if you need a foreign key field, you have to define it.  If you need a link table, you need to define it.  You have to specify the field for the primary key &#8211; which means the object has to have a field for the primary key.  Glorp doesn&#8217;t figure any of that stuff out for you.</p>
<p>Finally, you specify the mapping from the class model to the table model.  You do this by creating Descriptors (one for each class) and Mappings. Mappings can represent either data fields, or relationships.  There are several kinds.  For instance, a many to many mapping will involve specifying the primary keys of each table, the link table, and the mappings from primary keys to link table fields.  Most of this can be derived from the class model&#8217;s relationship and foreign key constraints.  But you still have to specify it.</p>
<p>At this point, you are probably thinking &#8211; I have 100 classes in my model  That&#8217;s 300 methods I have to write!  And it is all mostly boilerplate!  I couldn&#8217;t agree more.  All you really need is an appropriate metamodel.</p>
<p>In a previous life, I wrote <a href="http://www.apple.com/webobjects/">WebObjects</a> applications.  WebObjects has an ORM called the Enterprise Objects Framework or EOF.  It was light years ahead of its time.  Now, its about average as Apple has neglected WebObjects terribly and nobody I know uses it anymore.  EOF came with a great program called EOModeler and stored the model in text files in <a href="http://en.wikipedia.org/wiki/Property_list">PList</a> format.  I have code that reads and writes PLists in every language I know &#8211; they are insanely useful.</p>
<p>The <a href="http://developer.apple.com/documentation/Webobjects/Reference/API/com/webobjects/eoaccess/EOModel.html">EOModel</a> was the first file format that described all of the meta information required by a typical ORM library.  So I did the easy thing &#8211; leveraged EOModel files to build DescriptorSystems. (I was not <a href="http://incubator.apache.org/cayenne/">alone</a> in realizing this). I subclassed DescriptorSystem and created EODescriptorSystem which reads an EOModel file and builds a DescriptorSystem from it.  (I also wrote my own EOModeler application in Java Swing, both as an experiment, and out of frustration because <a href="http://www.apple.com/">Apple</a> was neglecting WebObjects to an extent that the tools were falling apart.  It works well enough but the experience of writing it put me off <a href="http://java.sun.com/">Java</a> for good).</p>
<p>This experience teaches me that any reasonably expressive meta model can be leveraged to build a descriptor system.Â  In my current porting project, the original developers ended up creating their own ad hoc meta model with explicit modeling of attributes, relationships, and types.Â  I leveraged this to automatically generate a descriptor system from the classes themselves (all domain classes have a common root), and was able to infer link tables, foreign keys, and so forth from the meta model.Â  So from the model I get the schema and the descriptor system.<br />
Of course, translating to relational format required a few subtle changes to the object model, so I also added code to construct the table model directly from PostgreSQL and, by comparing it with the schema generated from the classes, can figure out alter scripts to automate schema migration.Â  This is working great and building out new domain objects has become really easy.Â  I would say with Seaside and this infrastructure, I have surpassed Rails for ease of development.</p>
<p>But I think I can do better and have begun to investigate <a href="http://www.lukas-renggli.ch/smalltalk/magritte">Magritte</a>. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2007/01/02/records-and-objects/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Object Oriented Databases (OODBMS)</title>
		<link>http://www.blackbagops.net/2006/12/20/object-oriented-databases-oodbms/</link>
		<comments>http://www.blackbagops.net/2006/12/20/object-oriented-databases-oodbms/#comments</comments>
		<pubDate>Thu, 21 Dec 2006 07:51:47 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[seaside]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[squeak]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=93</guid>
		<description><![CDATA[I used to be something of an expert on Object Oriented Database Systems, how to use them, etc.  The way you get to be an expert at a technology is to simply get ahead of the adoption curve and spend a bunch of time figuring out how to make the technology work before it [...]]]></description>
			<content:encoded><![CDATA[<p>I used to be something of an expert on Object Oriented Database Systems, how to use them, etc.  The way you get to be an expert at a technology is to simply get ahead of the adoption curve and spend a bunch of time figuring out how to make the technology work before it becomes common knowledge.  At this point, you can charge premium rates as you have scarce knowledge in your posession.</p>
<p>I got to this position by working for some adventurous folks that were willing to take a chance on the hype.  The first one I came across was ObjectStore with C++.  The project didn&#8217;t launch, but we built lots of prototypes and I got a good indoctrination into the ups and downs of OODBMS lore.  Later on I was exposed to some others, Versant, Poet, and some lesser known ones.  Like relational databases, once you get the hang of one, the rest are pretty similar.  The key concepts are:</p>
<p>1) OODBS allow you to create one or more named &#8220;roots&#8221;.  A root is basically a variable &#8211; you ask for the object at root &#8220;foo&#8221; and get it back.  Some only give you one root.  If you only get one root, then almost always you just stick a hash/map/dictionary at the root and pretend you have several anyhow.  The root is your entry point to the data.</p>
<p>2) All object manipulations/accesses must be done within a transaction context.  So you end up digging through your app looking for sensible transaction boundaries.  For a web app, you typically begin a transaction at the beginning of a request and commit it just before sending the response.  You want to keep transactions short so as not to have other users waiting on locks.</p>
<p>3) Objects become part of the database via &#8220;reachability&#8221;.  The OODBMS will &#8220;trace&#8221; your object graph starting at the root upon commit, calculate changes to the graph, and then write the changes to the database.  Any new objects reachable from the root object automatically becomes part of the database.  While this might sound expensive, it generally is quite cheap.</p>
<p>So you generally open a transaction, lookup an object from a root, navigate to the object of interest, make changes, and then commit the transaction.  Many also let you hang onto an object reference across transactions.  The object reference can only be accessed within a transaction &#8211; trying to read data from it outside of a transaction will fail with an exception.  This makes redrawing user interfaces problematic.</p>
<p>OODBs come from the CAD world where you have a network of a zillion objects, all slightly different, where mapping them to a regular container like a db table would be really expensive.  They&#8217;re really good at this object persistence game.  </p>
<p>OODBs are seductive.  They are easy to get started with.  For one thing, you don&#8217;t have to do a data model, just your object model.  Your code is your model.  You make objects, stick them in containers, and forget about them.  Sounds great, right?</p>
<p>But as anyone who has lived with an OODBMS for any period of time knows, Object databases are great, until they&#8217;re not, and then they truly suck.  Here&#8217;s why:</p>
<p>1) Concurrency is very poor.  As I mentioned, OODBs come from the CAD world and work well for storing complex cad models.  But CAD models are seldom updated concurrently by large numbers of people.   As you modify objects within a transaction, the OODB has to obtain locks on your modified objects to guarantee consistency.  Unfortunately, none of them (that I know of) implement object level locking.  Most implement locking at the memory page level.  Spurious lock conflicts where two unrelated objects share a memory page can be common.   Resolving these conflicts can be expensive.  Because, all work must happen withing a transaction, transactions tend to be on the long side.</p>
<p>2) Constant re-fetching of data every transaction makes keeping user interface elements up to date very expensive.  There is no user level in-memory caching without writing user level code to create transient copies.</p>
<p>3) Schema migration is hard, if not impossible.  Your object defines your format.  Adding a field to a class makes your in-memory model inconsistent with the slabs of bits you wrote out before you added the field.  There are ways around this.  The usual one is to have one ivar that is a dictionary.  Otherwise, there are usually some very user un-friendly scripts that have to be run.  In many cases, the database must be taken offline to do this.  So much for your three nines availability.</p>
<p>4) Death by a trillion bug fixes.  I can&#8217;t speak for all, but ObjectStore would require the database be taken offline and an update script be run for every upgrade.  For a site that is supposed to be up all the time, this isn&#8217;t acceptable.  So upgrades were deferred.  When we did this, we found that</p>
<p>5) OODBMS providers have limited resources and will only support versions up to one year old.  If you get too far out of date and your db goes down, you are flat out of luck.  The support people won&#8217;t help you.  Only a really large organization could afford to keep up with all the little point fix releases ObjectStore made in a year &#8211; we couldn&#8217;t afford the man power or the down time.</p>
<p>6) Bugs are forever.  If you put a bug into your program that damages the object model, it becomes enshrined in the database.   Subsequent read code that finds the malformed chunk of the object model will usually fail.  Subtle corruptions build up over time making a full database walk harder and harder to complete over time.   Conventional databases can avoid this by implementing appropriate constraints.</p>
<p>7) No security.  Any screwball developer can destroy your reference data (usually stored in ordered collections off of the root).  A conventional relational database can safeguard important data with roles, permissions, and constraints.</p>
<p> <img src='http://www.blackbagops.net/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> Garbage Collection is not universally available.  Orphaned junk is common.  Some OODBs provide GC utilities, however they can fail if there is corrupt data (see items 6 and 7).</p>
<p>9) No ad hoc query capability.  You have to write a new program to view any data at all.  You need to write programs to update reference data.  You need a program to do anything at all with your data.  No fixing problems with a quick line of SQL.  Searching for unanticipated patterns is difficult.</p>
<p>I&#8217;ve been bitten by all of these issues at one time or another and have recently inherited an application written using a Smalltalk OODB called <a href="http://www.gorisek.com/WikiDoc/WikiPage?page=OmniBaseâŒ©=English">OmniBase</a>.  Debugging this application is extremely painful because launching a debugger results in the transaction being terminated and all object references becoming invalid.  Thus, the data that might provide a clue as to the source of the error is gone.  Additionally, while the author claims to provide support, he simply collects fees and then tells you that your application doesn&#8217;t run in his environment, blames you for writing rotten code, and declines future contact.</p>
<p>So this dog has to go.</p>
<p>Fortunately, you can get most of the benefits of an OODB without the drawbacks by using an Object Relational Mapping framework.  I&#8217;ve selected <a href="http://www2.laubach.at/kwiki/">GLORP</a>, an open source mapping framework that is improving all the time, and found that I can implement support the part of OmniBase&#8217;s API with very little change to the user interface, which is written in <a href="http://seaside.st">Seaside</a> under <a href="http://squeak.org">Squeak</a>.</p>
<p>Next time, I&#8217;ll talk a little bit about how this works.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2006/12/20/object-oriented-databases-oodbms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Got Class?</title>
		<link>http://www.blackbagops.net/2006/10/31/got-class/</link>
		<comments>http://www.blackbagops.net/2006/10/31/got-class/#comments</comments>
		<pubDate>Tue, 31 Oct 2006 22:47:23 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Objective C]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=83</guid>
		<description><![CDATA[In Object Oriented languages, the class is the definition of a kind of object. Classes are arranged in tree-like hierachies with the roots of the tree being very general and the leaves being most specific. So a dessert is a kind of food, and cake is a kind of dessert. Because the class serves as [...]]]></description>
			<content:encoded><![CDATA[<p>In Object Oriented languages, the class is the definition of a kind of object. Classes are arranged in tree-like hierachies with the roots of the tree being very general and the leaves being most specific. So a dessert is a kind of food, and cake is a kind of dessert. Because the class serves as the definition of an object, it makes sense that objects are created by using the class as a template. In other words, classes are used to create objects of the class&#8217;s type.</p>
<p>All of the languages discussed so far, C++, Java, Smalltalk, and Objective C have the notion of a class. What is different is how the languages represent the class itself.</p>
<p>C++ has no runtime representation of a class at all. Instead, all class information is soaked up by the compiler and represented using standard functions and globals with the class name prepended to their &#8220;local&#8221; names. The way a programmer designates a function as belonging to a class is to declare it within the class&#8217;s declaration using the very overworked keyword &#8217;static&#8217;.</p>
<p>class CPlusPlusClass : public BaseObject<br />
{<br />
public:<br />
static void classMember(); // declare the function<br />
&#8230;<br />
}</p>
<p>void CPlusPlusClass::classMember() {&#8230;} // define the function<br />
&#8230;<br />
CPlusPlusClass.classMember(); // really just a long name for a global function</p>
<p>Ditto for class variables. There&#8217;s no such thing in C++ really. Instead the language fakes it by letting you declare the variable in the class declaration&#8217;s namespace and in the end what you&#8217;ve got is a global with a very long name. Since there&#8217;s no class object, there&#8217;s no &#8220;this&#8221; variable and no way to do anything the least bit object oriented in class methods without explicitly naming super classes.</p>
<p>There&#8217;s also no built-in way to abstract object creation. When one wishes to create an object in C++, one uses the &#8216;new&#8217; operator in conjunction with the class name, which coincidentally is also the required name of the initialization function. So in C++ we write:</p>
<p>BaseObject *c = new CPlusPlusClass();<br />
Notice that here &#8211; at the moment of object creation, it is necessary to reveal the actual type of the object. If one desires a more abstract method of instance creation, it is necessary to adopt a factory idiom. Of course, converting to a factory creation mechanism from the use of operator new requires extensive modification of code, similar to the extensive work required to handle a new kind of exception.</p>
<p>Smalltalk takes the opposite extreme. Classes are represented as regular objects and are arranged into an inheritance hierarchy. The special variable &#8220;self&#8221; refers to the class object itself and &#8217;super&#8217; refers to the object that represents the classes superclass. Smalltalk class methods exhibit full polymorphism and class variables are made available to class methods and instance methods in the class&#8217;s instances. The Smalltalk class takes responsibility for instance creation and is thus a factory by default.</p>
<p>For instance, in the Squeak implementation, ImageReadWriter is an abstract class for reading and writing image files. Concrete subclasses exist for JPEG, GIF, PNG and so forth. The abstract base class makes use of class hierarchy navigation to find the correct subclass to render the image data. It looks something like this (error handling omitted):</p>
<p>&#8220;Find the first subclass that claims to be able to understand the binary stream&#8217;s data&#8221;</p>
<p>readerClass := self withAllSubclasses detect: [:subclass | binaryStream reset. (subclass new on: binaryStream) understandsImageFormat].</p>
<p>&#8220;Instantiate a reader from the class&#8221;<br />
reader := readerClass new on: (binaryStream reset).</p>
<p>&#8220;Return the image from the reader&#8221;<br />
^reader nextImage.</p>
<p>The beauty of this approach is that one can always write a new subclass of ImageReadWriter for a new image format and the new format is instantly supported without having to deal with registries or factory idioms.</p>
<p>Techniques like this demonstrate the power of using the object paradigm to represent classes.</p>
<p>Objective C uses a similar approach to Smalltalk with a couple of odd constraints. Objective C class objects lack support for class member variables. Instead one fakes it with static (as in C variables with internal linkage) variables. Also, Objective C performs lazy loading of libraries which means that not all subclasses are necessarily present at any given time. So the subclasses trick is a little hard to perform.</p>
<p>On the other hand, Objective C uses the same object creation mechanism as Smalltalk. So its still possible that the actual class of the object is not the same as the class that created it for you. Thus, the power of using objects to represent classes is mostly preserved.</p>
<p>Java&#8217;s approach is closer to C++ than to Smalltalk. While Java has &#8216;objects&#8217; of type java.lang.Class for representing classes, these &#8216;objects&#8217; have more in common with C structs than with objects in any other sense. Object creation is not performed by the class. Rather Java slavishly copies C++&#8217;s use of operator &#8216;new&#8217;.</p>
<p>Java also makes use of a &#8217;static&#8217; keyword to denote &#8216;class methods&#8217;. But these &#8216;methods&#8217; are actually nothing but functions with long names. In fact, its not possible to do anything polymorphic in a class method. There isn&#8217;t even a way to get ahold of the class object representing the class.</p>
<p>public class A<br />
{<br />
// something that doesn&#8217;t work &#8211; no &#8216;this&#8217;<br />
static void printClassName1() { System.out.println(&#8221;"+this.class); }</p>
<p>// this doesn&#8217;t work either<br />
static void printClassName2() { System.out.println(&#8221;"+getClass()); }</p>
<p>// this does &#8211; but in subclasses it will be wrong<br />
static void printClassName3() { System.out.println(&#8221;"+A.class); }<br />
}</p>
<p>So crippling is the decision to not provide proper class objects, that the Enterprise Java Bean designers found it necessary to simulate class objects with the notion of &#8220;Home&#8221; objects. The &#8220;Home&#8221; object is intended to provide the ability to find existing objects or create new ones for a given class. This is definitely behavior that would ordinarily be put into a class object.</p>
<p>If we had one.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2006/10/31/got-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Painters</title>
		<link>http://www.blackbagops.net/2006/10/20/painters/</link>
		<comments>http://www.blackbagops.net/2006/10/20/painters/#comments</comments>
		<pubDate>Sat, 21 Oct 2006 02:56:52 +0000</pubDate>
		<dc:creator>todd</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[smalltalk]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[squeak]]></category>

		<guid isPermaLink="false">http://www.blackbagops.net/?p=79</guid>
		<description><![CDATA[About three or four years ago, I was playing around with a concept I called Bricks.  It was a way of factoring drawing operations out of UI components to make it easy to create new looks.  The drawing operations were encapsulated into objects called Painters.  I was doing it in Squeak using [...]]]></description>
			<content:encoded><![CDATA[<p>About three or four years ago, I was playing around with a concept I called Bricks.  It was a way of factoring drawing operations out of UI components to make it easy to create new looks.  The drawing operations were encapsulated into objects called Painters.  I was doing it in Squeak using Morphic.  It looked like this: <img src="http://www.blackbagops.net/wp-content/uploads/2006/10/BrickShot.png"></p>
<p>It must have been a good idea because I just ran across <a href="http://weblogs.java.net/blog/joshy/archive/2006/09/introducing_pai.html">something similar</a> from the Java Swing people.</p>
<p>So I&#8217;ve decided to dust it off and pick it up again.  There have been a lot of changes in Morphic and I&#8217;ve given up on reworking the event deliver system, choosing to work with Morphic&#8217;s system, warts and all.  I still think splitting drawing and layout will be valuable. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.blackbagops.net/2006/10/20/painters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
