<?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>BlueRope</title>
	<atom:link href="http://bluerope.org/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://bluerope.org</link>
	<description></description>
	<lastBuildDate>Sat, 17 Apr 2010 13:01:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>BRDocBase update</title>
		<link>http://bluerope.org/?p=88</link>
		<comments>http://bluerope.org/?p=88#comments</comments>
		<pubDate>Sat, 17 Apr 2010 11:20:54 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[BRDocBase]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=88</guid>
		<description><![CDATA[A whole mess of updates for BRDocBase.  My simple little framework is somewhat less simple unfortunately.
###iPhone Support
As I&#8217;m working on CrankTunes for iPhone, I had to make a few changes internally.  I was using blocks in a couple of places and had a few other very minor changes (like including Foundation rather than [...]]]></description>
			<content:encoded><![CDATA[<p>A whole mess of updates for BRDocBase.  My simple little framework is somewhat less simple unfortunately.
<span id="more-88"></span>###iPhone Support
As I&#8217;m working on <a href="http://blueropesoftware.com/cranktunes">CrankTunes</a> for iPhone, I had to make a few changes internally.  I was using blocks in a couple of places and had a few other very minor changes (like including Foundation rather than Cocoa).  I was happy with how easy this was.</p>

<h3>SQLite storage</h3>

<p>The strategy for storing documents is now in it&#8217;s own class, and determined by the docbase config file.  With this I added a class to store documents in a SQLite database.  Originally I wanted to use <a href="http://1978th.net/tokyocabinet/">Tokyo Cabinet</a>, however after further looking at the LGBL issues, I realized it&#8217;s not really feasible for an iPhone application.  So I went with SQLite instead, basically using it as a simple key-value storage mechanism.</p>

<p>There are now 3 different local storage mechanisms: my initial hash file storage, SQLite storage, and a simple single file storage.  Really, if &#8216;present me&#8217; could go back and talk to &#8216;past me&#8217;, I probably wouldn&#8217;t have written the hash file storage.  I wanted something that was easy to view in a text editor for development/testing purposes.  It&#8217;s not bad, but a single file is much better and SQLite is a better form for release.</p>

<p>In a premature optimization (since I don&#8217;t think I really need it yet), I also added support for document indexing.  It&#8217;s only implemented in SQLite storage and probably will never be in either of the other storage formats.  I mostly did it out of curiosity to see how I can detect the appropriate fields in an NSPredicate and use them if possible in a query.  It&#8217;s still very basic support but it works.  I added a few class methods to NSPredicate simply to assist in building predicates that utilize the indexes.</p>

<h3>Syncing</h3>

<p>A fourth storage mechanism was added as well: remote storage.  Along with it there is a sync server that will work with it.  All this is very preliminary but it will sync documents between a client and server.  The server is currently Mac only since it uses <code>NSSocketPort</code>, but I think it&#8217;ll be an easy change to use <code>CFSocket</code> instead to get it working on iPhoneOS.  The sync client is currently pretty draconian about any change conflicts.  Right now the later change always wins.  If the change dates happen to be equal, the server version is used.  Eventually a delegate will be used to allow the app to decide what to do about conflicts.  The server uses Bonjour to advertise itself, and there&#8217;s no form of authentication built in, so running it allows anyone on the local network to access the served docbase.</p>

<h3>Other Stuff</h3>

<p>There&#8217;s probably a bunch of other small changes that went in that I&#8217;m not thinking of right now.  One thing I did want to highlight is class extensions.  I&#8217;m trying to be somewhat careful about what classes I add categories to.  Right now 3 framework classes are extended.  <code>NSMutableDictionary</code> has methods to make it conform to the <code>BRDocument</code> protocol, as well as a convenience constructor to build a proper document dictionary (adding the document id, document type, and modification date automatically).  <code>NSDate</code> has methods to format dates in a docbase-friendly format.  Mostly this is for SQLite, since it seems to like UTC times without the addition of a timezone offset.  And, as I mentioned earlier, <code>NSPredicate</code> has some methods to build predicates that are more likely to hit indexes.</p>

<p>So that&#8217;s it.  Like I mentioned, it&#8217;s no longer a simple 1 or 2 files, but I&#8217;m pretty happy with it so far.  I was especially excited to have it running on the iPhone and syncing with documents on the Mac.</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=88</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeIgniter for Webapps</title>
		<link>http://bluerope.org/?p=84</link>
		<comments>http://bluerope.org/?p=84#comments</comments>
		<pubDate>Mon, 29 Mar 2010 21:25:32 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=84</guid>
		<description><![CDATA[In a totally non Cocoa-related post, I just wanted to give my quick thoughts on CodeIgniter.In case no one has guessed, I really like Ruby and Ruby on Rails, even though I don&#8217;t get to often use them.  However there&#8217;s a few issues that make it not always practical.  First, if you have [...]]]></description>
			<content:encoded><![CDATA[<p>In a totally non Cocoa-related post, I just wanted to give my quick thoughts on <a href="http://codeigniter.com/">CodeIgniter</a>.<span id="more-84"></span>In case no one has guessed, I really like <a href="http://www.ruby-lang.org/en/">Ruby</a> and <a href="http://rubyonrails.org/">Ruby on Rails</a>, even though I don&#8217;t get to often use them.  However there&#8217;s a few issues that make it not always practical.  First, if you have a shared hosting service, then there&#8217;s a good chance they don&#8217;t support running Rails.  Second, deployment of rails is a bit more involved than copying files to the server.  Those aren&#8217;t really big deals if you&#8217;re making a web app that really needs the power, but I&#8217;m willing to admit Rails is overkill for my company website.</p>

<p>So as I was figuring out how I want to build my website, I looked at least briefly at a few LAMP-based solutions (A quick disclaimer: I&#8217;m not a &#8216;web developer&#8217;, so go easy on me if I say something erroneous or that you violently disagree with).  I went from heavier weight frameworks (<a href="http://www.joomla.org/">Joomla</a>, <a href="http://expressionengine.com/">ExpressionEngine</a>) to considering just coding PHP pages myself when I found <a href="http://codeigniter.com/">CodeIgniter</a> which seemed just right (yes, the Goldilocks metaphor went through my head at the time I was checking it out).</p>

<h3>What&#8217;s Great</h3>

<p>Like a lot of frameworks today, CodeIgniter borrows heavily from Rails.  It follows a similar MVC pattern, and uses a somewhat similar directory structure.  I had actually never done any coding in PHP before this, and it helped a lot that it followed a familiar pattern, to reduce the amount I was learning at once.</p>

<p>Deployment is also simple.  Other than needing to mess around with htaccess a bit to get the routing working like I wanted and setting up the database, it was just a matter of copying files to the server.  Most of the site-specific configuration is located a few files, so just excluding those means updating the site is pretty easy.</p>

<p>Probably the thing I liked most about it is something that not everyone will like.  I like to write code rather than click buttons to add new pages or content.  I don&#8217;t really consider myself a control freak, but it drives me nuts that I can&#8217;t see or at least don&#8217;t have a good picture in my head on what&#8217;s going on behind the scenes to make a web page appear. Perhaps I&#8217;m being unfair when I compare it to CMS frameworks like Joomla and ExpressionEngine, but these are the things I checked out when I went searching, so at very least they&#8217;re comparable as &#8216;frameworks to build a website with&#8217;.</p>

<h3>What&#8217;s Less Than Great</h3>

<p>The mapping from a URL to a controller method has one limitation that bothered me.  You can configure it to pass parameters in the path, or in query string, but not both.  For a full featured REST API this would really bother me, but it&#8217;s just a minor annoyance otherwise.</p>

<p>The framework&#8217;s support for models is kind of weak.  Okay, it&#8217;s really weak.  It&#8217;s really nothing more than &#8216;put your database code here&#8217;.  No relationships, migrations, or any of the good stuff you may want.  Once again though,  I was developing simple company website with very few database needs, so it wasn&#8217;t a big deal.</p>

<h3>The End Result</h3>

<p>I was surprised by how both easy CodeIgniter and PHP was to pick up.  I didn&#8217;t mind at all the temporary switch from Cocoa development, and won&#8217;t mind too much when I have to go and update it.</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=84</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>My thoughts on Core Data</title>
		<link>http://bluerope.org/?p=82</link>
		<comments>http://bluerope.org/?p=82#comments</comments>
		<pubDate>Mon, 08 Mar 2010 22:27:28 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[CoreData]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=82</guid>
		<description><![CDATA[In the last few weeks, there was a lot going around about Core Data and why it may or may not be a good idea.  There was Matt Gallagher&#8217;s post: The differences between Core Data and a Database.  Then Brent Simmons kicked off a whole slew of other posts with On switching away [...]]]></description>
			<content:encoded><![CDATA[<p>In the last few weeks, there was a lot going around about Core Data and why it may or may not be a good idea.  There was Matt Gallagher&#8217;s post: <a href="http://cocoawithlove.com/2010/02/differences-between-core-data-and.html">The differences between Core Data and a Database</a>.  Then Brent Simmons kicked off a whole slew of other posts with <a href="http://inessential.com/2010/02/26/on_switching_away_from_core_data">On switching away from Core Data</a>, such as:</p>

<ul>
<li>Manton Reece: <a href="http://www.manton.org/2010/02/i_dont_use.html">I don&#8217;t use Core Data either</a></li>
<li>Gus Mueller <a href="http://shapeof.com/archives/2010/02/brent_simmons:_on_switching_away_from_core_data.html">doesn&#8217;t like it&#8217;s smell</a></li>
</ul>

<p>There are others as well.  I was dying to post about this but was even more determined to get my first release out the door.  Now that that&#8217;s done, I figured I&#8217;d share my thoughts.
<span id="more-82"></span>I think Gus comes closest to my own feelings when he say&#8217;s he doesn&#8217;t like it&#8217;s smell.  Although maybe he didn&#8217;t need to be beaten on the head as much as I did to come to this realization (someone not liking EJB is just proof that they&#8217;re not totally nuts).  The problem I see with Core Data isn&#8217;t with Core Data in particular, but with object-relational mapping as a whole.</p>

<p>I have used a lot of object-relational mapping tools:  Hibernate, NHibernate, ActiveRecord (from Rails), DataMapper (another Ruby one), and of course, Core Data itself (I&#8217;ve never used EOF however).  I&#8217;ve also created custom object-relational mappers (several times in differing languages) on top of very large data models.  After all this my conclusion is that it&#8217;s best to avoid having to do this mapping.</p>

<p>Here&#8217;s my theory on how all this started.  In the beginning, there were databases, and we put data in them, and life was good.  Well, really it wasn&#8217;t, because then came along object-oriented programming, and we realized that life would be better if we used this and instead of data, we have objects.  Of course we still needed a place to save the objects, so we figured out many different ways to shove our objects into a database.  Fast-forward many years and now it&#8217;s basically standard practice: make your objects, convert them into data for databases, then get them back out converting them back into objects.</p>

<p>Really, all of various tools do an incredible job of managing this assuming you let them own the data model completely (I won&#8217;t talk about using them on legacy systems since it&#8217;s a nightmare and doesn&#8217;t really relate to Core Data) and it gets you a bunch of things:</p>

<ul>
<li>In general switching to different SQL databases isn&#8217;t too bad</li>
<li>You have some powerful searching capabilities at your hands</li>
<li>Depending on your backend, it can scale (although Core Data&#8217;s failure to scale in certain situations is what started this whole thing off)</li>
<li>You have all the other potential side benefits of a database &#8211; transactions, sharing data between clients, etc.</li>
</ul>

<p>Sometimes this stuff is important.  In Core Data&#8217;s case and in the case of almost kind of desktop application (where the database is local) this is all irrelevant or untrue.  In the meantime you&#8217;ve set your self up with the biggest limitation of a SQL database: all of your objects must be mapped to tabular data.  In the simple cases, this isn&#8217;t a big deal.  However, the more complicated your object model gets, the more complicated this mapping gets or the more your constrained in how you can even design your object model.  In short, the fewer translations your objects/data/whatever must go through, the better.</p>

<p>It&#8217;s easy to see the evidence of this impedance mismatch in Core Data.  You want ordered collections?  You&#8217;ll have some work to do.  Or how about dealing with the synthetic ids of newly created objects?  Or (common to all object-relational mappers) the hackery that goes on to deal with inheritance?  All of these problems are solvable, but they&#8217;re just a few indications that SQL databases might not be ideal for storing objects.</p>

<p>So what&#8217;s the solution?  I&#8217;m not sure.  No, neither <a href="http://couchdb.apache.org/">CouchDB</a> nor my own CouchDB-inspired <a href="http://github.com/njallain/BRDocBase">BRDocBase</a> are really answers (in case you thought that&#8217;s where I was headed).  They&#8217;re not intended for generic object persistence.  Whatever happened to object databases?  I know some are still around, and I&#8217;ve seen really cool stuff done in Smalltalk with them.  Of course &#8217;seeing cool stuff done&#8217; is not at all the same as actually developing with one, which I have zero experience with.  I&#8217;d love to see an Objective-C based OODB, and have often thought of developing one for fun, but I know that if I&#8217;m not using it in an actual product it wouldn&#8217;t come out right (that&#8217;s just me&#8230;I need to be actually using it to see if something is a good idea or horrible one).</p>

<p>As mentioned by a few others, Aaron Hillegass is working on <a href="http://weblog.bignerdranch.com/?p=232">BNRPersistence</a> which sounds interesting.  I haven&#8217;t looked deeply into it, and Brent Simmons <a href="http://inessential.com/2010/02/26/core_data_post_follow-up_notes">mentioned the LGPL issue of Tokyo Cabinet</a>.  I&#8217;m under the impression that including an LGPL component is fine fine for non-free, close-sourced products, as long as you share the source (and your changes) of that component (but I&#8217;m definitely no lawyer).  I&#8217;m certainly planning on taking a better look at it though.</p>

<p>Before I finish I just wanted to make clear that I am not at all saying &#8216;Core Data sucks, don&#8217;t use it&#8217;.  It&#8217;s still the best general-purpose solution for persisting objects for a desktop Cocoa application (although I really wish they&#8217;d add ordered collections).  I would say, that if your data is more tabular in nature and you do more of the kinds of operations SQL is good at (searching, scaling to lots of rows, etc) you might consider doing your own database access.  But even if we had an awesome Cocoa OODB available to us, I&#8217;d say the same thing (the right tool for the right job).  The main point of my lengthy, semi-rant is that it seems the development community as a whole has gone down this path of object-relational mapping and accepted it as The Way to be persisting our objects and I just wish we had better options.</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=82</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CrankTunes Released</title>
		<link>http://bluerope.org/?p=80</link>
		<comments>http://bluerope.org/?p=80#comments</comments>
		<pubDate>Sun, 07 Mar 2010 13:03:21 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[CrankTunes]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=80</guid>
		<description><![CDATA[Although I haven&#8217;t posted in a couple of weeks, I haven&#8217;t been slacking.  I&#8217;m pleased to announce my first app: CrankTunes.I won&#8217;t talk too much specifically about the app here (since this is a technical blog), but I will say it&#8217;s definitely something that&#8217;s fulfilling a need of my own.  I took up [...]]]></description>
			<content:encoded><![CDATA[<p>Although I haven&#8217;t posted in a couple of weeks, I haven&#8217;t been slacking.  I&#8217;m pleased to announce my first app: <a href="http://blueropesoftware.com/cranktunes">CrankTunes</a>.<span id="more-80"></span>I won&#8217;t talk too much specifically about the app here (since this is a technical blog), but I will say it&#8217;s definitely something that&#8217;s fulfilling a need of my own.  I took up cycling about 4 years ago, but am forced to ride indoors often.  Ironically, yesterday was the first day this year that I got outside for a ride.</p>

<p>Being a developer, all the non-coding tasks needed to release software are particularly painful.  I&#8217;m not really done either, as I still have to figure out everything I&#8217;m going to do to market it.  However, there were some fun coding-related challenges that I went through and I&#8217;ll probably have a post or two about those in the near future.</p>

<p>Right now, I&#8217;ve heaved my sigh of relief, and it&#8217;s time to get on that big, scary &#8216;market CrankTunes&#8217; task on my todo list.  I now regret all the times I&#8217;ve ranted against people in marketing departments.</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=80</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Safari-like Search Field Control</title>
		<link>http://bluerope.org/?p=74</link>
		<comments>http://bluerope.org/?p=74#comments</comments>
		<pubDate>Mon, 15 Feb 2010 23:31:28 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=74</guid>
		<description><![CDATA[Last weekend I went looking for a way to duplicate the functionality of Safari&#8217;s search field.  This began an epic journey that has nearly killed me&#8230;hopefully it&#8217;s true what they say and I&#8217;m stronger for it.Before I go much further, I should mention that someone was kind enough to point out an implementation of [...]]]></description>
			<content:encoded><![CDATA[<p>Last weekend I went looking for a way to duplicate the functionality of Safari&#8217;s search field.  This began an epic journey that has nearly killed me&#8230;hopefully it&#8217;s true what they say and I&#8217;m stronger for it.<span id="more-74"></span>Before I go much further, I should mention that someone was kind enough to point out an implementation of something similar to what I want at <a href="http://summerofcamino.com/">Summer of Camino 2009</a>.  I have little doubt that it would&#8217;ve been a lot simpler to use someone else&#8217;s (probably superior) implementation.  Unfortunately it looks like it&#8217;s GPL and while I have no problem sharing my code, I&#8217;ll be using it in a closed source application.  So off I went in an attempt to build my own.</p>

<p>Did I mention I&#8217;ve never done a custom control before?  Some drawing in views, sure, but never a control.  Let alone one with a weird menu that stays open while you type in a text field.  I imagined it would be a learning experience, and I definitely learned a lot about being frustrated (my knowledge of making a custom control is still iffy).</p>

<p>The main functionality I was looking for from Safari&#8217;s search field was:</p>

<ul>
<li>menu includes search matches (Suggestions) as well as recent searches</li>
<li>menu opens when the user enters text that has possible matches (rather than just when the button is clicked)</li>
<li>menu will update the matches while the user continues to type</li>
<li>change focus from the text view to the menu and back with the arrow keys</li>
</ul>

<p>I started out by snooping around in Safari using <a href="http://www.fscript.org/">F-Script</a>.  It&#8217;s using subclasses of <code>NSSearchField</code> and <code>NSSearchFieldCell</code> to do it&#8217;s job, so I figured that would be a good thing to try out first.  Unfortunately, I just couldn&#8217;t figure out how to keep the menu open.  After a bit of fruitless hacking to try an mimic Safari, I decided to give up on subclassing <code>NSSearchField</code> and start instead with <code>NSTextField</code>.  <code>NSSearchField</code> just lets you provide a template menu and then at some point it uses that menu to build a new one with the placeholders fixed up with recent searches, etc.  It&#8217;s a fine concept, but I thought it was getting in the way of my understanding on how to keep the stupid menu open.</p>

<p>Still I couldn&#8217;t figure out how so make menu open.  Finally, I started making some progress when I gave up on using a menu at all and decided to fake it with a child window.  I can&#8217;t be sure, but my suspicion is that Safari is doing the same thing (my F-Script skills aren&#8217;t advanced enough to figure it out).</p>

<p>Once I had the menu problem solved, my only barrier was my complete lack of control programming knowledge.  I forged on fearlessly (or foolishly) ahead and got something that basically work.  So am I happy with the results?  Not really.  I had enough issues in dealing with managing the control&#8217;s focus that I feel I just don&#8217;t get it yet and there should be better ways to do it.  I know part of the problem is the funkiness of NSTextField and the associated field editor and how the first responder is set between the two.  I&#8217;m also coming to somewhat regret not sticking with subclassing <code>NSSearchField</code> and <code>NSSearchFieldCell</code> since I had some issues drawing the control with the search icon inside the text field&#8217;s border.</p>

<p>In the end though, it works well enough for me (for now).  I&#8217;m still planning on revisiting it at some point to try and clean up the messiness but right now I don&#8217;t think I&#8217;m in the right mind to look at it.  There are also definitely some limitations that I don&#8217;t feel affect me (yet).  Since the menu is completely fake, you don&#8217;t get much flexibility from it.  You can&#8217;t have submenus or view-based menu items for instance.  Also, there&#8217;s no asynchronous behavior in populating the menu.  If, for some reason, the <code>BRSearchFieldDataSource</code> needs a long time to produce a set of results, there&#8217;s no built in support for handling that.</p>

<p>For the brave, insane, and those who wish to mock me, the source is available on github here: <a href="http://github.com/njallain/BRSearchField">BRSearchField</a>.  Using it isn&#8217;t too bad.  The only non-straightforward part that isn&#8217;t illustrated by the code is that you add an <code>NSTextField</code> in Interface Builder, then must change it&#8217;s class to <code>BRSearchField</code> and it&#8217;s cell&#8217;s class to <code>BRSearchFieldCell</code>.  Other than that, set it&#8217;s data source and search menu prototype either in IB or in code and you should be (hopefully) good to go.</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=74</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NSSound Versus iTunes</title>
		<link>http://bluerope.org/?p=71</link>
		<comments>http://bluerope.org/?p=71#comments</comments>
		<pubDate>Sun, 14 Feb 2010 15:12:17 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=71</guid>
		<description><![CDATA[One of the applications I&#8217;m working on gets songs from iTunes and plays them.  It doesn&#8217;t use iTunes to play the music, but just to locate them.  The playing is left to NSSound.  This all works fine&#8230;except when it doesn&#8217;t
It had been a bit of time since I worked on my app, [...]]]></description>
			<content:encoded><![CDATA[<p>One of the applications I&#8217;m working on gets songs from iTunes and plays them.  It doesn&#8217;t use iTunes to play the music, but just to locate them.  The playing is left to <code>NSSound</code>.  This all works fine&#8230;except when it doesn&#8217;t
<span id="more-71"></span>It had been a bit of time since I worked on my app, and I had upgraded to Snow Leopard.  While fixing new problems that popped up, one had me stumped.  Every once in a while, it would just suddenly exit.  It took be a bit to figure out that it was when I was trying to create an <code>NSSound</code>.  It didn&#8217;t happen every time, and only with particular songs.  Then I realized what it was: copy protected AAC files.</p>

<p>Sure enough, when I ran the application outside the debugger, there were no issues playing the songs in question.  So, somewhere inside <code>NSSound</code> (I imagine pretty deep) it&#8217;s detecting that a debugger is attached and just exiting to prevent hacking the copy protection.  It makes sense, but I wasn&#8217;t able to find any specific mention of this and   I&#8217;m sure I never encountered this before Snow Leopard.</p>

<p>Perhaps it&#8217;s common knowledge and I just missed it, but I thought I&#8217;d mention it anyway.  Okay, I admit, I actually first encountered it a few months ago, then again just the other day and I had forgotten what caused it.  I figured if I posted about the problem it would help me remember the next time I hit it <img src='http://bluerope.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=71</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Migrator for DocBase</title>
		<link>http://bluerope.org/?p=69</link>
		<comments>http://bluerope.org/?p=69#comments</comments>
		<pubDate>Sun, 07 Feb 2010 14:10:58 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=69</guid>
		<description><![CDATA[I made a few updates for DocBase: a configuration file for a document database and a migrator to handle configuration changes.  Read on for a few details.
### Configuration

As I was developing my app, I noticed that I was quickly outgrowing the measly 17 buckets I had originally hard coded for a database.  It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I made a few updates for <a href="http://github.com/njallain/BRDocBase">DocBase</a>: a configuration file for a document database and a migrator to handle configuration changes.  Read on for a few details.
<span id="more-69"></span>### Configuration</p>

<p>As I was developing my app, I noticed that I was quickly outgrowing the measly 17 buckets I had originally hard coded for a database.  It&#8217;s not too bad for a hundred or so documents, but probably not sufficient for several thousand documents.  I knew it really need to be configurable.  So in comes the docbase configuration file.</p>

<p>The configuration is just saved as another JSON dictionary in the document database folder and right now it only contains the setting for the number of buckets.  There&#8217;s a few important changes that go along with this.</p>

<p>I moved anything that might give cause an error (within reason) outside of the initializer for <code>BRDocBase</code>.  Now, if something is wrong, like it can&#8217;t create the database or the configuration is wrong it&#8217;ll give an error on the first call to one of the main methods (anything that has an error parameter).  Basically, all the file-based initialization is done lazily.  I&#8217;ve never seen an init method take an error parameter, and it just feels wrong to me.</p>

<p>If a configuration isn&#8217;t passed to the init method, one of two things will happen.  If it&#8217;s a new database, a default configuration will be used.  Otherwise, the configuration that already exists will be used.  In either this case, the <code>configuration</code> property will return <code>nil</code> until it has actually completed its lazy initialization.  If a configuration is passed on initialization and it doesn&#8217;t match the existing configuration, the lazy initialization will fail with a configuration mismatch error (this can be useful in updating a configuration).</p>

<h3>Migrator</h3>

<p>Without someway to migrate a database, there&#8217;s no way to change the configuration, so I added <code>BRDocBaseMigrator</code>.  It&#8217;s pretty simple class right now that can update a database to use a new configuration.  It just uses brute force to read and re-write all the documents in the database in the new configuration.</p>

<p>The migrator is smart enough to not do anything if the configuration matches.  In that case, the original document database will be returned.  So if fairly simple to create/open a database that always has a particular configuration:</p>

<pre><code>NSString* path = ...;
NSDictionary* config = ...;
NSError* error;
BRDocBase* docBase = [[BRDocBaseMigrator docBaseMigrator]
    update:[BRDocBase docBaseWithPath:path]
    toConfiguration:config 
    error:&amp;error];
</code></pre>

<p>Now if the configuration isn&#8217;t what is wanted, it&#8217;ll be updated.  Otherwise it will just return.</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=69</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit Testing Tricks With Method Replacement</title>
		<link>http://bluerope.org/?p=63</link>
		<comments>http://bluerope.org/?p=63#comments</comments>
		<pubDate>Fri, 05 Feb 2010 01:49:13 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=63</guid>
		<description><![CDATA[Automated unit tests can be incredibly awesome and incredibly frustrating.  Sometimes, in order to write a unit test you&#8217;re forced to design your code in such a way as to make the test feasible to write.  Often this is a good thing (even though it&#8217;s annoying at the time you realize you need [...]]]></description>
			<content:encoded><![CDATA[<p>Automated unit tests can be incredibly awesome and incredibly frustrating.  Sometimes, in order to write a unit test you&#8217;re forced to design your code in such a way as to make the test feasible to write.  Often this is a good thing (even though it&#8217;s annoying at the time you realize you need to refactor), but other times its just not practical.  In these cases, method replacement might do the trick.<span id="more-63"></span>I don&#8217;t at all think that method replacement is a substitute for well-factored code, but often there&#8217;s just that one not-very-unit-test-friendly thing that your class under test needs to do: read a file, access the network, interact with the UI, or something similar.  Sure, you could factor out that one piece into it&#8217;s own class, then provide a way to use a mock instance in your class under test.  If theres a lot going on, then maybe that&#8217;s the way to go, but for small cases it&#8217;ll often lead to messier, less understandable code, not cleaner code.  In these cases, method replacement works great.</p>

<p>In an <a href="http://bluerope.org/?p=52">earlier post</a>, I talked about extending a class at runtime using (what Ruby calls) modules and I&#8217;ve added a <a href="http://github.com/njallain/Modules">github repository</a> for it.  It covers most of the functionality we need with the exception of undoing the changes it made.  The implementation for this (along with absolutely no error checking) is pretty short:</p>

<pre><code>+(void)revertMethod:(SEL)methodName onClass:(Class)cls
{
    NSString* savedSelectorName = [[NSString alloc] initWithFormat:
        @"%s_%s", class_getName(cls), sel_getName(methodName)];
    SEL savedSelector = NSSelectorFromString(savedSelectorName);
    Method savedMethod = class_getInstanceMethod(cls, savedSelector);
    IMP savedImp = method_getImplementation(savedMethod);
    Method existingMethod = class_getInstanceMethod(cls, methodName);
    method_setImplementation(existingMethod, savedImp);
}
</code></pre>

<p>If you read the other post, you&#8217;ll notice that we saved the original implementation of a method in a new method: <code>&lt;class name&gt;_&lt;method name&gt;</code>.  This way, when <code>revertMethod:onClass:</code> is called, we can just reset the implementation.  The one thing we can&#8217;t do is get rid of our backup method since this capability was removed from Objective-C 2.0 apparently&#8230;oh well.</p>

<p>Now that we have a way to reset our method back, using it is a piece of cake.  Pretend our class under test, <code>Foo</code>, has a method <code>readDataFromFile</code> that returns a string from some configuration file.  We don&#8217;t want to be bothered with this during a test, or we want to supply specific values for it while testing.  So we might create our fixture as follows:</p>

<pre><code>@implementation FooTest

-(void)setup
{
    [BRClassExtender 
        extendClass:[Foo class] 
        withModule:[FooTest class] 
        override:YES 
        method:@selector(readDataFromFile)];
}

-(void)tearDown
{
    [BRClassExtender 
        revertMethod:@selector(readDataFromFile) 
        onClass:[Foo class]];
}

-(void)testConfiguration
{
    // do something with foo
}

// this is our replacement implementation
-(NSString*)readDataFromFile
{
    return @"my configuration";
}
@end
</code></pre>

<p>Now rather than opening some file and reading it, we simply return the string specified.  Note that the method can be private since the test case doesn&#8217;t care if it&#8217;s in the interface of <code>Foo</code> or not.</p>

<p>Using this kind of testing technique can be a slippery slope.  Obviously, if we do this, we&#8217;re no longer testing the implementation of the method we overrode.  I prefer only using it if I can keep the overridden methods really small and it&#8217;s easy for me to verify they work by some other means (like running the actual application).</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=63</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adventures with NSCollectionView</title>
		<link>http://bluerope.org/?p=59</link>
		<comments>http://bluerope.org/?p=59#comments</comments>
		<pubDate>Mon, 01 Feb 2010 22:29:31 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[Cocoa]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=59</guid>
		<description><![CDATA[So I&#8217;ve been neck deep in attempting to make my user interface pretty and simple to use.  Anyone who thinks creating effective UIs is easy is either nuts or way smarter than me.

I&#8217;ve been going back and forth between using an NSTableView and an NSCollectionView for a list of items, and I think I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve been neck deep in attempting to make my user interface pretty and simple to use.  Anyone who thinks creating effective UIs is easy is either nuts or way smarter than me.</p>

<p>I&#8217;ve been going back and forth between using an NSTableView and an NSCollectionView for a list of items, and I think I&#8217;m settling on the NSCollectionView, but there are definitely some interesting challenges.
<span id="more-59"></span>A couple of quick notes: I&#8217;m building for Snow Leopard so a few of my comments only apply to 10.6-only builds.  Also, all my comments here come from my own experience with <code>NSCollectionView</code> rather than actual knowledge about how it works internally.  So, I could easily be wrong when I mention how I think something is working.</p>

<h3>NSCollectionViewItem</h3>

<p>First up is <code>NSCollectionViewItem</code>.  In 10.6 it&#8217;s now a subclass of <code>NSViewController</code>.  Noticing this helped me understand a lot better how an <code>NSCollectionView</code> might handled in code.  Previously I never viewed it as something I should subclass, but now it seems obvious that if I want to handle actions from controls an item view, I put it in my own <code>NSCollectionViewItem</code> subclass.</p>

<p>There&#8217;s a problem when I take this a bit further though.  The <code>NSCollectionViewItem</code> that I set up in the nib isn&#8217;t actually the instance gets used when the application is running.  That instance is just a prototype, underneath the hood it&#8217;ll be cloned, and Cocoa seems to take care of all the messy work of setting up the actions and bindings that I set up in Interface Builder.</p>

<p>It doesn&#8217;t, however, fix up my outlets automatically.  Any outlets that I add to my subclass, I need to handle on my own.  This can be done by overriding <code>copyWithZone:</code>.  There&#8217;s a catch however: this won&#8217;t work with outlets pointing to objects on the controller&#8217;s corresponding view.</p>

<h3>NSView</h3>

<p>Conceptually, each <code>NSCollectionViewItem</code> cloned is paired with an <code>NSView</code> (actually, from my understanding, only enough views will be created to fill the <code>NSCollectionView</code> and they are reused).  While the controllers are cloned with <code>copyWithZone:</code> the views are not, they are simply created anew from the data in the nib for each additional one that&#8217;s needed.  When you set up outlets pointing to items in that view, they&#8217;re pointing to items that, I believe, are never even actually used.</p>

<p>Unfortunately, I didn&#8217;t stumble upon a good way to have outlets pointing to objects in the view.  The only way I could think of doing this was to set the <code>tag</code> value on controls I&#8217;m interested in and search through subviews to find them.  As I mentioned above, bindings seem to be handled by the framework as you&#8217;d expect, so hopefully outlets into the view won&#8217;t be needed.</p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=59</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A couple of BRDocBase changes</title>
		<link>http://bluerope.org/?p=57</link>
		<comments>http://bluerope.org/?p=57#comments</comments>
		<pubDate>Sat, 23 Jan 2010 03:26:15 +0000</pubDate>
		<dc:creator>Neil</dc:creator>
				<category><![CDATA[Dev Journal]]></category>
		<category><![CDATA[BRDocBase]]></category>

		<guid isPermaLink="false">http://bluerope.org/?p=57</guid>
		<description><![CDATA[I&#8217;ve been using BRDocBase fine in development for a few weeks.  While it&#8217;s nowhere near complete, I haven&#8217;t had any real need for new features or performance improvement for my modest needs until now.
### Document Change Flag

The first thing I wanted was a change flag on documents.  This will be the first optional [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using BRDocBase fine in development for a few weeks.  While it&#8217;s nowhere near complete, I haven&#8217;t had any real need for new features or performance improvement for my modest needs until now.
<span id="more-57"></span>### Document Change Flag</p>

<p>The first thing I wanted was a change flag on documents.  This will be the first optional method on the <code>BRDocument</code> protocol.  If the property doesn&#8217;t exist on a document object, everything will proceed as it did before.  I went with the property name <code>isDocumentEdited</code> since that&#8217;s the method name on <code>NSDocument</code>.  I&#8217;m not really going for any kind of <code>BRDocument</code> to <code>NSDocument</code> parity but I decided a familiar name was best.</p>

<p>One important functional change is that if the document implements the property and it&#8217;s not set, the <code>saveDocument:error:</code> method will not save the document.  At first, I had save doing absolutely nothing with the document if the flag was set, this caused a small issue with new documents though.  Currently, a <code>nil</code> return value means an error occurred and the error object is appropriately set.  So now there are a few options:</p>

<ul>
<li>Return nil with no error set</li>
<li>Go ahead and set the id, but still don&#8217;t save the document</li>
<li>Ignore the <code>isDocumentEdited</code> flag in this case and save the document</li>
<li>Return nil with an error</li>
<li>Raise an exception</li>
</ul>

<p>I went with the 4th option.  The first is the worst in my mind since it forces a user of BRDocBase to account for a nil error even when nil is returned from save.  The other options aren&#8217;t really bad.  Since this is really kind of an odd situation and I consider it a developer error (new documents should be automatically set as edited) I may at some point change it to raise an exception.  Although exceptions aren&#8217;t used a lot in Cocoa, a developer error warrants an exception in my mind.</p>

<h3>A New Hash Algorithm</h3>

<p>While I was in the code I realized that my in-memory storage of documents that had been retrieved had a possible problem.  To make saves quicker, internally I&#8217;m storing documents similar to the file based stored.  There&#8217;s a top dictionary keyed by the bucket ids containing dictionaries itself mapping <code>documentId</code> to the document object.  But since the bucket number is generated by hashing the <code>documentId</code>, if the inner dictionary happens to have the same number of buckets as the file based storage, we&#8217;d end up with 100% collisions in the dictionary.</p>

<p>That led me to think of a less likely, but way more serious problem.  What if Apple changed the hash algorithm on NSString?  I wouldn&#8217;t think this is likely, but the structure of <code>BRDocBase</code> storage is dependent on Apples internal implementation.  So rather than depend on this, to assign bucket numbers I now use a a different hash algorithm: <a href="http://isthe.com/chongo/tech/comp/fnv/">FNV-1</a>.  I saw other, more complicated and faster algorithms, but I don&#8217;t really need ultimate speed for my purposes.  Of course this means that any document database I have is now useless.  Since it&#8217;s still early in development, I didn&#8217;t bother writing something to convert my existing databases and just trashed them.</p>

<p>Finally, I put BRDocBase up on github.  It&#8217;s available here <a href="http://github.com/njallain/BRDocBase">BRDocBase</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bluerope.org/?feed=rss2&amp;p=57</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
