Mandy's Tech Blog2021-04-10T17:20:57+00:00http://www.fallingcanbedeadly.com.com/Amanda Mitchellhttp://www.fallingcanbedeadly.com,/posts/surprising-useeffect-behaviorA surprising behavior of React's useEffect2019-02-10T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>Since React 16.8 came out earlier this week, I’ve been playing around with hooks in personal projects so that I can better understand their ins and outs.</p>
<p>Many of the hooks that accept callbacks also take an optional array of values that are used for optimization purposes:
if none of the values in the array change between renders, the callback is skipped.</p>
<p>The <a href="https://reactjs.org/docs/hooks-reference.html#useeffect">docs</a> contain a tantalizing hint about the future:</p>
<blockquote>
<p>The array of inputs is not passed as arguments to the effect function.
Conceptually, though, that’s what they represent:
every value referenced inside the effect function should also appear in the inputs array.
In the future, a sufficiently advanced compiler could create this array automatically.</p>
</blockquote>
<p>Until “the future” comes, determining which values should appear in the inputs array seems like a really tedious
(and error prone!) code review task,
so I tried writing a utility method to remove some of the “sharp edges”:</p>
<script src="https://gist.github.com/6ee451a559c57246259a3c96ee549370.js"></script>
<p>With this utility method, the values <em>are</em> passed to the callback.
If the callback is defined outside of the component, then it becomes <em>impossible</em> for it to use any unlisted values,
making code review much simpler.</p>
<p>Unfortunately, it has a critical flaw when used with refs.</p>
<p>Suppose I have a component that needs to attach an event handler directly to a DOM node:</p>
<script src="https://gist.github.com/dbbff27a8b7ac25bf6530a0052ed13db.js"></script>
<p><em>Aside: that this is more than just a hypothetical example: React attaches all event handlers at the document level.</em>
<em>One unfortunate consequence of this is that Chrome will force any touch event handlers to be passive.</em>
<em>This is undesirable for things like drawing controls which may need to call <code class="language-plaintext highlighter-rouge">preventDefault</code> to stop undesirable scrolling.</em></p>
<p>As written, this effect will <em>never</em> be attached to the <code class="language-plaintext highlighter-rouge">canvas</code> element unless an ancestor of <code class="language-plaintext highlighter-rouge">CanvasElement</code> triggers a re-render.</p>
<p>This is the case because the value provided to <code class="language-plaintext highlighter-rouge">addTouchListener</code> gets bound at render time:
<em>before</em> <code class="language-plaintext highlighter-rouge">canvasRef.current</code> is set to an actual <code class="language-plaintext highlighter-rouge">canvas</code> element.
It’s not until the second render–when <code class="language-plaintext highlighter-rouge">canvasRef.current</code> is set to the value from the first render–that <code class="language-plaintext highlighter-rouge">addTouchListener</code> is called with a DOM element.</p>
<p>This leads to another interesting discovery. Suppose we abandon <code class="language-plaintext highlighter-rouge">useBoundEffect</code> so that we can pass the correct value to <code class="language-plaintext highlighter-rouge">addTouchListener</code>:</p>
<script src="https://gist.github.com/f4abe8775fb496e9cd4b3bfe02ea7d7b.js"></script>
<p>In this version, the effect attaches the event handler after the first render, as desired, but it <em>also</em> cleans up and re-attaches on the <em>second</em> render.
This happens for the same reason that the event handler was not attached the first time: the initial value of <code class="language-plaintext highlighter-rouge">canvasRef.current</code> is what is used to determine
whether the effect needs to be re-run.</p>
<p>React itself <em>could</em> provide a solution to this by allowing the second argument to be specified as a function that returns an array, instead of the array itself.
If React called this function immediately before applying the effect, it would enable a much more precise calculation of whether it needs to be re-applied.</p>
<p>On the other hand, I’m not keen to wait on such a feature, so I decided to see if I could emulate it.
This is what I came up with:</p>
<script src="https://gist.github.com/a9f9586aff7dd8b63b02ec2a1e868bf7.js"></script>
<p>In this version, we have to use <em>two</em> effects. The first runs on every render to determine whether the inputs have changed.
The second is necessary to clean up when the component is unmounted: it runs only on the first render and sets up a cleanup method.</p>
<p><em>Aside #2: if you try to use this in your code and supply the second argument in the form <code class="language-plaintext highlighter-rouge">() => [value1, value2]</code>, you may get an error</em>
<em>from the Typescript compiler complaining that the return type is not compatible with the expected type.</em>
<em>This happens because Typescript is really conservative about inferring arrays as tuples.</em>
<em>If you want to avoid adding a bunch of explicit types everywhere,</em>
<em>you can define a method like this to give the compiler the necessary hint:</em></p>
<script src="https://gist.github.com/6b4917780cee8dc910848214bc6d2317.js"></script>
<p><em>With this in place, the second argument would change to the form <code class="language-plaintext highlighter-rouge">() => createTuple(value1, value2)</code>.</em>
<em>I’m hopeful that future versions of Typescript will make this simpler, as there are a number of GitHub Issues related to tuple inference;</em>
<em>on the other hand, there are no concrete proposals, so I’m not holding my breath.</em></p>
http://www.fallingcanbedeadly.com,/posts/wkwebview-cookiesSend Cookies to a WKWebView With This One Weird Trick2017-06-29T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>Back in iOS 8, Apple introduced a new control for hosting web content: <code class="language-plaintext highlighter-rouge">WKWebView</code>.
In most respects, it’s far superior to the old <code class="language-plaintext highlighter-rouge">UIWebView</code>:
it’s faster, has fewer rendering issues, and provides better Javascript support.</p>
<p>However, one area in which <code class="language-plaintext highlighter-rouge">WKWebView</code> is demonstrably worse is in its handling of cookies.
iOS provides a service called <code class="language-plaintext highlighter-rouge">NSHTTPCookieStorage</code> that is used by most HTTP-related functionality, including <code class="language-plaintext highlighter-rouge">UIWebView</code>—but not <code class="language-plaintext highlighter-rouge">WKWebView</code>.</p>
<p>The reason for this is documented in a <a href="https://bugs.webkit.org/show_bug.cgi?id=140191">long-lived webkit bug</a>.
In <code class="language-plaintext highlighter-rouge">WKWebView</code>, most of the underlying functionality actually lives in a process outside of your application.
Among other benefits, this policy allows Apple to use a JavaScript engine that produces executable code at runtime without giving all processes this privilege.
Unfortunately, this complicates interactions with things that <em>do</em> live in your application—like cookie stores.
While this issue <em>has</em> been addressed on master, it’s not yet in a shipping version of iOS. (it looks like iOS 11 may provide a way to interact with <code class="language-plaintext highlighter-rouge">WKWebView</code>’s cookie store)</p>
<p>For apps that host web applications that depend on cookies for authentication, this poses a major problem.
Although web requests originating in the application can access the shared cookie store, these cookies are never propagated to the web view, meaning that subsequent AJAX requests or page navigations will be unauthenticated.</p>
<p>The most popular solution on <a href="https://stackoverflow.com/questions/26573137/can-i-set-the-cookies-to-be-used-by-a-wkwebview">the bathroom wall</a> appears to be injecting extra Javascript into each page to programmatically set the cookie.
While this works, it requires dynamically generating Javascript, which is kind of gross.</p>
<p>If you have control of the server hosting your web content, there’s another way to slip your cookies into a <code class="language-plaintext highlighter-rouge">WKWebView</code>:
just get the server to send back a <code class="language-plaintext highlighter-rouge">Set-Cookie</code> header in its response to your initial navigation request.
In the case of an app that I was recently working on, we added a small bit of code on the server looking for an <code class="language-plaintext highlighter-rouge">X-Echo-Cookie</code> HTTP header.
For any request containing this header, it would include a <code class="language-plaintext highlighter-rouge">Set-Cookie</code> header whose content was whatever was in the request’s <code class="language-plaintext highlighter-rouge">Cookie</code> header.</p>
<p>By including this header on our initial navigation request, we were able to get the cookie to “jump” from the application’s cookie store to <code class="language-plaintext highlighter-rouge">WKWebView</code>’s.
While this solution doesn’t cover complex scenarios, like the cookie being updated or invalidated while the user is navigating, it worked just fine for our scenario.</p>
http://www.fallingcanbedeadly.com,/posts/enabling-react-native-jsx-extensionEnabling .jsx files in React Native2017-06-16T01:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>React Native is a really cool developing technology, but it forces some strange defaults on its users.
One such choice is the <a href="https://github.com/facebook/react-native/issues/2303">refusal to support the <code class="language-plaintext highlighter-rouge">.jsx</code> extension out of the box</a>.
While Babel (which is also required by React Native) has no problem handling JSX syntax in <code class="language-plaintext highlighter-rouge">.js</code> files, many style guides (including <a href="https://github.com/airbnb/javascript/issues/982">AirBnB’s linter rules</a>) require JSX syntax to be isolated to <code class="language-plaintext highlighter-rouge">.jsx</code> files.</p>
<p>Although the core React Native team doesn’t show any signs of reversing their stance, it is possible in recent versions to extend the list of permissible file extensions.
I haven’t been able to find any mention of it in the official documentation, but React Native allows customizing <a href="https://github.com/facebook/react-native/blob/29d9c35e122861d86c70b1e27a6e34eda4d82369/local-cli/util/Config.js#L145-L165">several parts of the packager pipeline</a>, including the list of acceptable file extensions for source files.</p>
<p>Configuration options are specified in much the same way as in webpack: you create a Javascript module the exports an object containing all of the fields that you want to override.
It <em>appears</em> that there are two ways to provide this file to React Native, but one of them is a trap.</p>
<h2 id="how-not-to-do-it">How Not To Do It</h2>
<p>The React Native scripts provide a <code class="language-plaintext highlighter-rouge">--config</code> option, so you can supply any file as the configuration module.
However, it has two major flaws.</p>
<p>The first is that the scripts take this value as provided on the commandline and pass it directly to a call to <code class="language-plaintext highlighter-rouge">require</code> deep in the guts of React Native.
This means that your path must either be relative to wherever the <code class="language-plaintext highlighter-rouge">require</code> call resides (which is naturally subject to change), or it has to be an absolute path.
Yuck.</p>
<p>The other limitation shows up when you try to run your app in the iOS simulator (and presumably the Android simulator, but I haven’t tested this).
When you run <code class="language-plaintext highlighter-rouge">yarn ios</code> (or <code class="language-plaintext highlighter-rouge">npm run ios</code>) in a project that includes native components, the React Native script builds your application in one Terminal window while spawning another Terminal process to handle Javascript bundling—and it doesn’t forward your configuration file to the child location.</p>
<p>This means that if you want reliable configuration overrides, you have to rely on magic.</p>
<h2 id="magic">Magic</h2>
<p>React Native’s configuration loader will search all of its ancestor directories for a file called <code class="language-plaintext highlighter-rouge">rn-cli.config.js</code>, and it will load the one closest to the root directory.
This means that if you create a file with that name at your project root, it will be loaded and used automatically, no matter which React Native script you’re using.
<del>It also means that if you want to be really evil to one of your coworkers who left a machine unlocked, you can run <code class="language-plaintext highlighter-rouge">touch /rn-cli.config.js</code> to completely break any projects using a custom configuration.</del></p>
<p>So how do we use this knowledge to enable <code class="language-plaintext highlighter-rouge">.jsx</code> files?
We just add this config:</p>
<script src="https://gist.github.com/db396f354a9626abac78ee1d95c74a9f.js"></script>
<noscript>If you had Javascript enabled, you'd see a <a href="https://gist.github.com/db396f354a9626abac78ee1d95c74a9f.js">gist</a> here.</noscript>
<p>Now you can use <code class="language-plaintext highlighter-rouge">.jsx</code> files with abandon!</p>
http://www.fallingcanbedeadly.com,/posts/surprising-stream-readasync-behaviorWhat Happens in the Default Implementation of Stream.ReadAsync Will Shock You2017-06-16T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<blockquote>
<p>tl;dr The base implementation of <code class="language-plaintext highlighter-rouge">Stream.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)</code> doesn’t do what you might reasonably expect with respect to cancellation.
Make sure you check whether your <code class="language-plaintext highlighter-rouge">Stream</code> subclass provides a proper implementation before relying on it.</p>
</blockquote>
<p>A common pattern when cancelling a <code class="language-plaintext highlighter-rouge">Task</code> is to then wait for it to complete.
This ensures that any unmanaged resources that the <code class="language-plaintext highlighter-rouge">Task</code> might be using are then safe to clean up:</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cancellationTokenSource</span><span class="p">.</span><span class="nf">Cancel</span><span class="p">();</span>
<span class="k">try</span>
<span class="p">{</span>
<span class="n">task</span><span class="p">.</span><span class="nf">GetAwaiter</span><span class="p">().</span><span class="nf">GetResult</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">catch</span> <span class="p">(</span><span class="n">OperationCanceledException</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="c1">// dispose of other stuff...</span>
</code></pre></div></div>
<p>However, this pattern can lead to application hangs if the <code class="language-plaintext highlighter-rouge">Task</code> in question doesn’t do a good job of supporting cancellation, and the .NET Framework makes it surprisingly easy to fall into Pits of Failure.
One such pit of failure is <code class="language-plaintext highlighter-rouge">Stream.ReadAsync</code>.</p>
<h2 id="background">Background</h2>
<p>I recently needed to build a system to communicate between a couple of processes running on the same machine.
Eventually, I settled on using Windows’ named pipes, which are exposed in the .NET Framework as <code class="language-plaintext highlighter-rouge">NamedPipeServerStream</code> and <code class="language-plaintext highlighter-rouge">NamedPipeClientStream</code>.</p>
<p>For both ends of the pipe, I created a simple manager class that creates a <code class="language-plaintext highlighter-rouge">Task</code> that handles connecting/reconnecting to the pipe and listening for messages from the other end until canceled.
In the <code class="language-plaintext highlighter-rouge">Dispose</code> method of the manager, I followed the pattern described above.
In the <code class="language-plaintext highlighter-rouge">Task</code>, the <code class="language-plaintext highlighter-rouge">CancellationToken</code> was checked at each iteration, and it was also passed to all async calls.
To a casual reader, the implementation appeared flawless.</p>
<p>The processes also both hung on <code class="language-plaintext highlighter-rouge">Dispose</code> if they ever succeeded in connecting to each other.
Pausing the process in the debugger indicated that the hanging thread was waiting for the <code class="language-plaintext highlighter-rouge">Task</code> to finish, and no threads were currently associated with the <code class="language-plaintext highlighter-rouge">Task</code>.</p>
<h2 id="huh">Huh?</h2>
<p>In terms of the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa365590(v=vs.85).aspx">Win32 API</a>, a named pipe is <em>mostly</em> just a file:
named pipe clients can even create them by calling <code class="language-plaintext highlighter-rouge">CreateFile</code> directly.
This means that under the hood, they support nearly all of the same operations as files, including overlapped I/O and <code class="language-plaintext highlighter-rouge">CancelIoEx</code>.</p>
<p>If you take a look at .NET Core’s implementation, you’ll even find that the Windows-specific implementation of
<a href="https://github.com/dotnet/corefx/blob/bfac45a/src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Windows.cs#L84-L136"><code class="language-plaintext highlighter-rouge">ReadAsync</code></a>
creates an instance of a subclass of <code class="language-plaintext highlighter-rouge">TaskCompletionSource</code>
<a href="https://github.com/dotnet/corefx/blob/b9953de/src/System.IO.Pipes/src/System/IO/Pipes/PipeCompletionSource.cs#L137-L151">that uses these features</a>.
You could easily be forgiven for assuming that the .NET Framework would be implemented in exactly the same way.</p>
<p>But you’d be wrong.</p>
<p>Instead, the .NET Framework, as of .NET 4.7, provides no override of <code class="language-plaintext highlighter-rouge">ReadAsync</code>, which means that it delegates to <code class="language-plaintext highlighter-rouge">Stream</code>’s
<a href="https://github.com/dotnet/coreclr/blob/ebda0e6/src/mscorlib/src/System/IO/Stream.cs#L410-L417">default implementation</a>.
This implementation checks the value of the <code class="language-plaintext highlighter-rouge">CancellationToken</code> at the beginning of the method;
if it has not been triggered, it discards the token and delegates to a <code class="language-plaintext highlighter-rouge">BeginRead</code>/<code class="language-plaintext highlighter-rouge">EndRead</code>-based implementation of async I/O.</p>
<p>This is what caused my hang.</p>
<h2 id="workarounds">Workarounds</h2>
<p>I’m not aware of a general-purpose workaround that will work for every subclass of <code class="language-plaintext highlighter-rouge">Stream</code>.</p>
<p>In the case of <code class="language-plaintext highlighter-rouge">NamedPipeClientStream</code> and <code class="language-plaintext highlighter-rouge">NamedPipeServerStream</code>, it is possible to <code class="language-plaintext highlighter-rouge">Dispose</code> the stream during an asynchronous read, which will have the effect of terminating the read.
If you do this, you may also need to be prepared to catch an <code class="language-plaintext highlighter-rouge">ObjectDisposedException</code> when waiting for your <code class="language-plaintext highlighter-rouge">Task</code> to complete.</p>
<p>You could also use P/Invoke to drop down directly to the Win32 API to create a named pipe as a <code class="language-plaintext highlighter-rouge">SafeFileHandle</code> and pass it to the <code class="language-plaintext highlighter-rouge">FileStream</code> constructor:
<code class="language-plaintext highlighter-rouge">FileStream</code> <em>does</em> override <code class="language-plaintext highlighter-rouge">ReadAsync</code> in terms of overlapped I/O and <code class="language-plaintext highlighter-rouge">CancelIoEx</code>, so you could call it without worrying about your <code class="language-plaintext highlighter-rouge">Task</code> becoming orphaned.
On the other hand, you’d also have to continue dropping to the Win32 API to handle all of the connection-oriented logic.</p>
<p>In any case, if you’re writing code that deals with <code class="language-plaintext highlighter-rouge">Stream</code>s and needs to handle cancellation, make sure your subclass properly supports it!</p>
http://www.fallingcanbedeadly.com,/posts/monkeyspace-talk-slides-and-notesMonkeySpace Talk Slides and Notes2013-07-26T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>I delivered my first conference talk at MonkeySpace yesterday. The video will be available at some point, but in the meantime, here are the slides and some notes to help make sense of them.</p>
<script async="true" class="speakerdeck-embed" data-id="e4d27400d88d0130de013addc031b9b8" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js">
</script>
<noscript>If you had Javascript enabled, you'd see a <a href="https://speakerdeck.com/davidmitchell/server-side-mono-how-ready-is-it">slide deck</a> here.</noscript>
<h3 id="overview">Overview</h3>
<p>Mono is a potentially attractive option for organizations that are already using ASP.NET because IIS is a pain to configure and Windows licenses can get really expensive.</p>
<p>Many libraries indicate that they support Mono, but there is little information about using it for web sites and services beyond basic, “getting started” tutorials. I’m trying to document and publish my experiments as I go along to help others who might be trying this and in the hope that more people will start documenting their experiences, too.</p>
<p>The major snags I encountered were:</p>
<ul>
<li>xbuild doesn’t have a good fallback mechanism for unkown profiles (we use the Client Profile for some assemblies)</li>
<li>Microsoft’s format for Forms Authentication cookies is undocumented and difficult to reverse engineer. (see my <a href="http://www.fallingcanbedeadly.com/posts/decoding-forms-authentication-cookies-with-mono">earlier post</a> on this topic)</li>
<li>Mono’s support for SQL Server hasn’t received significant updates for 2008 and 2012.</li>
<li><a href="http://newrelic.com">New Relic</a>—an awesome monitoring service we use—doesn’t support Mono.</li>
</ul>
<p>I worked around all of these issues and even built my own version of the New Relic Profiler (linked below). In testing a simple service, I encountered very inconsistent performance that was quite sensitive to GC pauses.</p>
<p>There was a period of about seven minutes during which the performance of the Mono version of the service was as good as—or better than—its Windows counterpart, so I plan to continue investigating. These are some initial areas I intend to look into:</p>
<ul>
<li>Is the New Relic profiler itself causing noise?</li>
<li>Does Mono 3.2 solve this issue? (I tested with one of the 3.0.x releases)</li>
<li>Is there something about the application’s architecture that causes difficulty for sgen?</li>
<li>Would a stack other than ASP.NET MVC give me better throughput?</li>
</ul>
<h3 id="image-credits">Image Credits</h3>
<p>Several of the images that I used were licensed under Creative Commons. Here are links to their original locations:</p>
<ul>
<li><a href="http://www.flickr.com/photos/87473264@N00/348551209/in/photolist-wNq8B-BsSBE-BsSCP-CC26F-DmTxu-Fh7Tf-FrYhM-KS9kf-Lw1Ar-LPdRU-MXN5u-NPVmd-NTVYC-24YVt1-2CRkgx-348sMH-38Vb5G-3ijD4C-3nLMEw-3N9cQu-48nN8D-4nzuyL-4nEpqG-4oU4d1-4rhuDV-4yrA7c-4BrzRm-4EyxPB-4G38Lv-4Hg2Qx-4HS4Jp-4HXvXF-4QDR2i-4UnLpK-4VT7yL-553Xsd-55R1Tu-56zThs-5959u3-5aghr9-5crX6o-5dsRpT-5fibHe-5iNqEp-5ng2kr-5o5Ga8-5oKXcg-5q3WYL-5sTkGu-5CgFn1-5FLBDT">“Why?” by Kevin Lau</a></li>
<li><a href="http://www.flickr.com/photos/36495803@N05/8463683689/in/photolist-dTUAhR-dUSc9a-9dGPED-agvquQ-b7NFzr-dmyfCP-9ZA9J6-aYWk56-aFAaK6-aFATbM-dSZe91-bt4mNt-bH1iX8-chEwR9-cnchKE-aFDjPB-8usD9K-bzmxxS-aFAQEv-bta55K-bZvUDS-brd1K2-aFAPtx-bi1bhM-a2YSa6-a2Y7cz-dB7F8e-889HV4-bta3kH-9q3RuT-aWUuqV-ayZVrf-biaRHp-89qVPo-8GE2S4-buW1s2-9t6RfD-8HWvej-aarLAr-9kJxyv-8ipnFE-9wUujx-7HKuTk-9NNJjU-egE3Qz-7B552e-7M4MWJ-a9JfVU-dLLgir">“Forex Money for Exchange in Currency Bank” by epSos .de</a></li>
<li><a href="http://www.flickr.com/photos/7269902@N07/7136403625/">“History in 12 Minifigs” by R D L</a></li>
<li><a href="http://www.flickr.com/photos/johnjoh/321893075/in/photolist-urMAB-vVqN6-Ai5pW-FwjdL-GMKdR-JKHDS-Mxen8-NKvmt-2ahVgP-31ovCr-31ovFZ-37grTZ-3e2NRt-3iEAoL-4bbvhk-4c9R3V-4du4o4-4dFzoR-4iuDMX-4wKxDh-4CGAqF-4FXeKn-4JL9ey-4WpFx7-564PmD-57hZaz-57i13P-57na3u-57nc6Y-5ajoq4-5pKB3t-5rTHim-5t6zg6-5t6zPz-5t6Aw2-5vJJSz-5vZveg-5wUa9b-5GKAEG-5GN89s-5HtB23-5NyQjC-5RUp6K-5SEzEa-5UzE2k-5ZKpW3-5ZKqnu-619XaV-6cWRC7-6gFSf5-6i5VLY/">“Lots of cats” by star5112</a></li>
<li><a href="http://www.flickr.com/photos/11483960@N08/2765541278/in/photolist-5do85b-5iUes7-5mnk9i-5mrApb-5o6Ekm-5uLcFr-5wf4nR-5CbAnt-5PXSRw-5RC6W9-5T46tX-5Vm5ou-6darm5-6jfnWP-6wJT7C-6xmosH-6ChpLF-6GkyZe-6LLmHD-6M1SiA-6NqF1j-6Px47W-6SfAhg-6TPqGP-6TPqPH-6XHi6q-6Zqdxz-75myaX-76XxoE-79zCDj-79ACow-7r9TAS-ankbfD-8yAS1d-8KNvPy-8yARHo-bhWimK-7Zafgf-aF6Qco-8SJLpt-8dQjyK-bLuHoD-dudGyw-85kx1H-cXY2dw-ce2jXL-a1zjeT-8Hupa5-9EWf6o-amruxf-85oFoU">“Whack A Mole Fever” by TPapi</a></li>
<li><a href="http://www.flickr.com/photos/65267324@N00/2634354055/in/photolist-51MKFv-57jmsB-5jc7yc-5kwQKi-5oJjzt-5ugwTs-5A6bTc-5BGBtF-5Cd2Si-5Cz2bY-5DPEGh-5GZpQ3-5HfaBT-5JmWkJ-5KufLN-5NfPwD-5WmFHh-5ZtjUM-61rX5o-625ALm-64KSFx-655rbv-659Hio-659HWQ-65JeoN-67p7kx-67p7q4-68pTzx-68qxWn-68qK4c-68uKSd-68uXoG-68uXrj-68uXtL-68uXB3-692ema-6aJP8t-6bn3P6-6cX1di-6cX1Hp-6dhGT7-6dLrMh-6e15mK-6fCUkN-6j9TM8-6j9Vte-6j9YAT-6ja6Jz-6jamxR-6jaqFv-6jat7H">“Basement Cat wuz once in Ceiling” by Noah Friedman</a></li>
<li><a href="http://www.flickr.com/photos/ehacke/4584260984/">“Cat Attack - Computer Scenario 56/365 V” by static416</a></li>
<li><a href="http://www.flickr.com/photos/simpson6642/6040658117/in/photolist-acMXcT-aZepzB-cLR3N1-akHNg8-cioUk3-93janC-98AXzu-8bdgCv-dt1omG-8PYk5e-dFz6YJ-aknMcM-8uqsJk-7XLFJ8-f76baM-7zD1YF-8FnFyd-8qWpC4-dGt1po-eULJqW-akrpug-8cz7sx-8Eywu1-8FE5eD-aQWB3t-8F7LJJ/">“Cobweb abandoned, like the building” by simpson6642</a></li>
<li><a href="http://www.flickr.com/photos/gerlos/3119891607/">“Binoculars portrait (dscn4659_mod_vign_sm)” by gerlos</a></li>
<li><a href="http://www.flickr.com/photos/a_brit_abroad/7932306622">“A herd of yaks passing the campsite” by Gavin Bishop</a></li>
<li><a href="http://www.flickr.com/photos/12488254@N06/4307204153/in/photolist-7yBxJz-9eUjAs-9eUjLy-9eUm4U-9eRctM-a78nij-8TQzL5-8Hwp6J-9eUn6N-9eUni3-9eUmUb-9eUmEf-9eRdYk-9trQRJ-9bk8tQ-cCsr3o-bDYRzP-9HvYkQ-9Htdq6-9eUkbj-9eRdbZ-9eRcS2-9rSRkX-bHwjfK-dpvNPg-bHv7Jv-e4Cjo1-cRecju-aAZD4T-bgKm64-ck98oC-951GGT-9662C7">“P365 alternate image” by Katie</a></li>
<li><a href="http://www.flickr.com/photos/icopythat/6500632/">“alone” by Chad Nicholson</a></li>
</ul>
<h3 id="other-links">Other Links</h3>
<ul>
<li>Projects advertising support for Mono
<ul>
<li><a href="http://servicestack.net/">ServiceStack</a></li>
<li><a href="http://github.com/NancyFx/Nancy">Nancy</a></li>
<li><a href="http://github.com/SignalR/SignalR">SignalR</a></li>
</ul>
</li>
<li>Sites known to be using Mono
<ul>
<li><a href="http://xamarin.com">Xamarin</a> (the HTTP headers say they’re using nginx and ASP.NET MVC 3)</li>
<li><a href="https://twitter.com/demisbellot/status/349585542641487872">ServiceStack</a> (problems with the setup are indicated <a href="https://twitter.com/demisbellot/status/349586375428931586">here</a>)</li>
</ul>
</li>
<li>Documentation for setup
<ul>
<li><a href="http://www.mono-project.com/Config_system_web_authentication">Forms Authentication on Mono</a></li>
<li><a href="http://www.mono-project.com/FAQ_Security">Getting HTTPS to work on Mono</a></li>
</ul>
</li>
<li>Code that I wrote while researching this topic
<ul>
<li><a href="https://gist.github.com/5350992">How to parse a .NET Forms Authentication Cookie</a></li>
<li><a href="https://github.com/amanda-mitchell/NewRelicShim">Shim between the .NET Profiling API and the New Relic Profiler</a></li>
<li><a href="https://github.com/LogosBible/mono/tree/methodrewrite">“Rough Draft” of method rewriting API in Mono</a></li>
<li><a href="https://github.com/amanda-mitchell/NewRelicProfiler">New Relic profiler for Mono</a></li>
</ul>
</li>
<li>Other
<ul>
<li><a href="https://twitter.com/carlfish/status/357289566866120705">Joke about yak-shaving on twitter</a></li>
<li><a href="https://newrelic.com/docs/dotnet/new-relic-for-net">New Relic’s lack of support for Mono</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/bb384493.aspx">Limitations of the .NET Profiling API</a></li>
</ul>
</li>
</ul>
http://www.fallingcanbedeadly.com,/posts/http-100-continue-latency-and-youHTTP 100 Continue, Latency, and You2013-04-24T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<h3 id="tldr">TL;DR</h3>
<p>You probably shouldn’t send an <code class="language-plaintext highlighter-rouge">Expect: 100-continue</code> header in your HTTP
requests—especially if you’re making requests against a server running
IIS or Nginx. If you’re using .NET, you have to explicitly opt out of
sending this header by setting <code class="language-plaintext highlighter-rouge">Expect100Continue</code> to <code class="language-plaintext highlighter-rouge">false</code> on the
<code class="language-plaintext highlighter-rouge">ServicePoint</code> of any <code class="language-plaintext highlighter-rouge">HttpWebRequest</code> that you create.</p>
<h3 id="background">Background</h3>
<p>In a recent project, I found myself digging into the details surrounding
the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3">100 Continue
status</a>
in HTTP 1.1. The project involves uploading (potentially) large files to
the server, and it initially seemed like explicitly supporting <code class="language-plaintext highlighter-rouge">100
Continue</code> would be a good way to preserve bandwidth.</p>
<h3 id="the-problem">The Problem</h3>
<p>First off, there’s surprisingly little reliable documentation about this status
code beyond RFC 2616 itself. IIS automatically sends a <code class="language-plaintext highlighter-rouge">100 Continue</code> for
<em>any</em> request containing an <code class="language-plaintext highlighter-rouge">Expect: 100-Continue</code> header, and it wasn’t
clear from my research whether there is actually a way to disable
this—at the very least, it’s not possible from within the context of a
plain old ASP.NET application.</p>
<p>As I investigated further, I discovered that it’s actually somewhat
common for servers to handle this without allowing application code to
have a say in what happens. Nginx’s reverse proxy module behaves this
way, and projects like Gunicorn even <a href="http://docs.gunicorn.org/en/latest/deploy.html#nginx-configuration">depend on this
behavior</a>
in order to prevent a <a href="http://ha.ckers.org/slowloris/">certain class</a> of
DOS attack.</p>
<p>Normally, this would be the end of my investigation: what initially
seemed like a cool feature would be a pain to implement, and after
reading up on it more, it really seemed to be of dubious value. But then
I started reading up on related parts of the .NET framework…</p>
<h3 id="httpwebrequest">HttpWebRequest</h3>
<p>It seems that the designers of the .NET framework weren’t allowed to talk to the
developers of IIS. If they had, the .NET framework designers might have
noticed that sending an <code class="language-plaintext highlighter-rouge">Expect: 100-Continue</code> header to servers that
<em>always</em> respond with <code class="language-plaintext highlighter-rouge">100 Continue</code> serves <em>absolutely no purpose</em>. In
fact, the current behavior is <em>worse</em> than useless because it
introduces unnecessary latency any time that you call out to an external
web service. For an application that makes an occasional web request,
this might not be so bad, but inside of a web service with cross-service
dependencies, or on a mobile device with naturally high latency, this is
a big deal.</p>
<p>Fortunately, <a href="http://haacked.com/archive/2004/05/15/http-web-request-expect-100-continue.aspx">this header can be
disabled</a>: every <code class="language-plaintext highlighter-rouge">HttpWebRequest</code> has a
<code class="language-plaintext highlighter-rouge">ServicePoint</code> with an <code class="language-plaintext highlighter-rouge">Expect100Continue</code> property. If you set this to
<code class="language-plaintext highlighter-rouge">false</code>, you’ll save yourself an unnecessary round trip. Better yet:
write yourself a little utility method that creates an <code class="language-plaintext highlighter-rouge">HttpWebRequest</code>
and disables the header, then flame anyone who doesn’t use it.</p>
<p>Happy Hacking!</p>
http://www.fallingcanbedeadly.com,/posts/decoding-forms-authentication-cookies-with-monoDecoding Forms Authentication Cookies With Mono2013-04-23T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>Lately, I’ve been experimenting with migrating web services from .NET on
Windows to Mono on Ubuntu. While getting the code building and running
in a VM was not terribly difficult, I soon found that authentication was
a roadblock.</p>
<p>Our web services run across several subdomains. We’re moving towards
using OAuth for everything, but many services still use Forms
Authentication with a cookie that is shared across all subdomains.
However, when I tried to use my cookie with a service running on Mono, I
was treated as an unauthenticated user.</p>
<p>The first barrier to shared authentication between .NET and Mono is
actually
<a href="http://www.mono-project.com/Config_system.web_authentication">well-documented</a>:
the default cookie name under Mono is <code class="language-plaintext highlighter-rouge">.MONOAUTH</code>, rather than
<code class="language-plaintext highlighter-rouge">.ASPXAUTH</code>.
Upon discovering this, I quickly modified my Web.config to explicitly
set the cookie to <code class="language-plaintext highlighter-rouge">.ASPXAUTH</code>…and nothing happened.</p>
<p>Another early discovery was that Mono base-64 encodes the cookie, while
.NET uses base-16. Again, changing this (in my case, by using a custom
build of Mono) had no effect—I was still treated as an unauthenticated
user.</p>
<p>Eventually, after quite a bit of digging around, I learned that the
binary format for .NET’s Forms Authentication cookie is <em>undocumented</em>,
so Mono had to implement a reasonable—yet incompatible—alternative
format. Furthermore, if you choose to encrypt the cookie, .NET adds an
extra 28 bytes of padding to the cookie using an unspecified hash
function—my best guess is that this has something to do with avoiding
<a href="http://weblogs.asp.net/scottgu/archive/2011/12/28/asp-net-security-update-shipping-thursday-dec-29th.aspx">hash collision
attacks</a>.</p>
<p>In any case, I spent a lazy Saturday afternoon poking around with the
format and arrived at a method of decoding the cookie, which is included
here for your reading pleasure:</p>
<script src="https://gist.github.com/5350992.js">
</script>
<noscript>If you had Javascript enabled, you'd see a <a href="https://gist.github.com/5350992">gist</a> here.</noscript>
<p>As you can see, it’s very proof-of-concepty, and it assumes specific
encryption and signing algorithms, but it gets the job done and should
be pretty easy to extend and generalize. Just drop this code into your
Global.asax.cs, provide your favorite implementation of base-16 string
to bytes, and you’re good to go.</p>
<p>Happy hacking!</p>
http://www.fallingcanbedeadly.com,/posts/building-mono-on-mac-os-x-2011-editionBuilding Mono on Mac OS X (2011 Edition)2011-04-13T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>Quite a bit has changed since I wrote my post a few years ago on building Mono for OS X. So much has changed, in fact, that I've decided that a new post on the topic is in order. These instructions assume that you're using Snow Leopard. They should work on Leopard with minimal changes, but your mileage may vary.</p>
<h4>Prerequisites</h4>
<p>Installing the prerequisites for Mono is much simpler than it once was. Previously, Mono had external dependencies like glib, which would mean you'd need to install MacPorts, but they've taken steps in the last year to reduce and eliminate such dependencies.</p>
<h5>Git</h5>
<p>If you haven't yet heard about git, stop hiding under that rock! The Mono source is hosted on GitHub, so if you want to download and build it, you'll need a copy of Git. You can acquire it <a href='http://git-scm.com/'>here</a>.</p>
<h5>XCode</h5>
<p>XCode 4 is now a $4.99 download in the Mac app store. If you're too cheap for that, you can still (as of the time of this writing) grab XCode 3 <a href='http://developer.apple.com/devcenter/mac/index.action'>here</a> (free registration required). A copy may also be on one of the discs that came with your Mac.</p>
<h5>Mono</h5>
<p>While you can (theoretically) bootstrap Mono, it's not something I recommend unless you enjoy pain. Save yourself some trouble and download the latest version <a href='http://www.go-mono.com/mono-downloads/download.html'>here</a>.</p>
<h4>Get the Source</h4>
<p>The Mono source code is now <a href='https://github.com/mono/mono'>hosted on GitHub</a>. Open your Terminal and clone the repository by issuing the command</p>
<pre><code>git clone git://github.com/mono/mono.git</code></pre>
<h4>Build and Install</h4>
<p>First, you'll need to run <code>autogen.sh</code>. Here's how I usually invoke it:</p>
<pre><code>./autogen.sh --with-sgen=no --with-xen_opt=no --prefix=/opt/mono-`git rev-parse HEAD` --with-mcs-docs=no --disable-nls</code></pre>
<p>My rationale for each option is listed below.</p>
<ul>
<li><code>--with-sgen=no</code>: The Mono team considers the SGen garbage collector to be production ready, but I've had problems with it, so I still turn it off.</li>
<li><code>--with-xen_opt=no</code>: I'm not running Xen, so there's no need for this.</li>
<li><code>--prefix=/opt/mono-`git rev-parse HEAD`</code>: You may want to just use <code>--prefix=/opt/mono</code>. I include the git revision in the path to make it easier to keep a number of parallel installations around for testing purposes.</li>
<li><code>--with-mcs-docs=no</code>: The documentation takes a while to build and generally won't be much different than what's in your installed copy of Mono. Save yourself some time and leave it out.</li>
<li><code>--disable-nls</code>: I don't need this particular feature. If you do, leave it in.</li>
</ul>
<p>Assuming that <code>autogen.sh</code> completes successfully, you can now build it with</p>
<pre><code>make -j1</code></pre>
<p>Depending upon how your development environment is set up, you may not need the <code>-j1</code>. However, if your default <code>MAKEFLAGS</code> has a different <code>-j</code> option, you'll want to use this. Otherwise, the Mono build can fail in strange ways. Once this is done, run <code>sudo make install</code>, and you'll be all set!</p>
http://www.fallingcanbedeadly.com,/posts/rewrite-history-with-git-filter-branchRewrite History with git-filter-branch2011-02-08T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>I've found <a href='http://dound.com/2009/04/git-forever-remove-files-or-folders-from-history/'>this page</a> useful on a few occasions, so I'm linking it from here so that I don't forget where it is.</p>
<p>The author demonstrates how to use git-filter-branch to completely remove files from a git repository. I haven't felt compelled to take all the steps that he does in order to get rid of the files, but it's an excellent reference for the command, nonetheless.</p>
http://www.fallingcanbedeadly.com,/posts/customized-urls-in-rails-with-to-paramCustomized URLs in Rails with to_param2010-08-17T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>This is probably one of the most basic concepts for experienced Rails developers, but I had a hard time finding what I was looking for on Google, which means that other people are having a hard time too, so here's my first little contribution to the Rails community…</p>
<p>I recently moved from SubText to a tiny little (incomplete!) blog engine that I wrote for myself in Rails. While working on it, I was also reading a little bit about SEO; one of the concepts expressed was that each url on your site should have something to do with the content of the page to which it refers. While Rails has good defaults for a lot of things, a url like http://example.com/posts/123 certainly leaves room for improvement.</p>
<p>While I knew that I could accomplish the affect that I wanted by creating a bunch of custom routes in routes.rb, I wanted to be able to take advantage of <code>map.resource</code> and methods such as <code>link_to</code>, which seemed to insist upon using the record ID of my ActiveRecord model.</p>
<p>Until I found <code>to_param</code>.</p>
<p><code>to_param</code>, as it turns out, is a very simple method that you can override in any ActiveRecord model. Whatever value you return from this method will be used in any urls generated by methods like <code>link_to</code>. The one caveat is that after you do this, you must change the code for any of your controllers so that they look up records based on this new external ID. In many cases, this may be as simple as changing <code>MyController.find(params[:id])</code> to <code>MyController.find_by_name(params[:id])</code>.</p>
http://www.fallingcanbedeadly.com,/posts/objective-c-reference-counting-from-the-bottom-upObjective-C Reference Counting From the Bottom Up2010-04-03T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>I've been interviewing a lot of Objective-C developers, lately. In my mind, one of the most fundamental parts of working with Objective-C is understanding how reference counting works, and I'm consistently surprised by how many people are unable to clearly describe it. In this post, I'll outline the absolute minimum that anyone working with Objective-C ought to know about reference counting. If you find yourself in an interview with me, and you can describe everything in this blog post, <del>I'll know where you got your information</del> you'll be doing better than most.</p>
<h4>The Basics</h4>
<p>Objective-C objects are reference counted. This means that each object comes with a little counter, and anyone can modify the value of this counter by calling retain (to increase the value) or release (to decrease the value). When the value of the counter reaches 0, the dealloc method is called on the object, and any memory associated with the object is reclaimed by the system.</p>
<p>A good developer will make use of this system by calling retain on objects whose pointers are being stored in other objects and calling release on those objects when the pointer no longer needs to be stored. This is, in fact, the reason that we call it "reference counting": the counter is intended to indicate how many objects (or, in some cases, global variables) are holding references to the object.</p>
<h4>Deadly Embraces and Retain Cycles</h4>
<p>When two objects each call retain on the other, we call it a "deadly embrace": if no other action is taken, the objects will never be deallocated. This is widely regarded as a "bad thing".</p>
<p>When this sort of pattern occurs with more than two objects (for example, A retains B, B retains C, and C retains A), it is called a "retain cycle", and these can be even nastier to deal with.</p>
<p>Deadly embraces and retain cycles are dealt with by either preventing one object in the cycle from retaining its "parent" or by having explicit cleanup logic that is executed when it is certain that the objects are no longer needed. Really elite developers sometimes create proxy objects to stand in for one of the objects, although a full discussion of this technique is beyond the scope of this post.</p>
<h4>Autorelease</h4>
<p>The autorelease method is perhaps the most widely misunderstood concept in Objective-C memory management, although in practice, it's actually relatively simple.</p>
<p>At the beginning of each iteration through your application's run loop, an NSAutoreleasePool is created. At the end of each iteration it is destroyed. You can also create and destroy NSAutoreleasePools anytime you wish to do so (for example, you generally need to manually create and destroy them in background threads; more on this, later).</p>
<p>When you call autorelease on an object, the object searches for the most recently created NSAutoreleasePool in its thread. Assuming that it finds a pool, it adds itself to the list of objects that need to be released. When the NSAutoreleasePool is destroyed, it calls release on each object that is in its list--if an object is listed multiple times, release is called multiple times. If the object fails to find an NSAutoreleasePool, a message is logged to the console and the object is leaked (this is why you need to create an NSAutoreleasePool when doing work on a background thread).</p>
<h4>Ownership and Object Creation</h4>
<p>While the notion of "ownership" is not baked into the semantics of Objective-C, one object can be thought to "own" another if it has called retain on the object or has created an instance of the object via the alloc or copy methods. An object that owns another is responsible for calling release on that object when it is no longer needed.</p>
<p>This brings us to an interesting question: what should be done for a method that creates an object but isn't called alloc or copy? In order for the object to be active, its retain count must be at least 1, but the calling method cannot be relied upon to call release.</p>
<p>The answer, of course, is to use the autorelease method. This allows the retain count to be a non-zero value when the method returns, and if nothing is done to keep the object alive, it will be reclaimed when the active NSAutoreleasePool is destroyed.</p>
<h4>Property Getters and Setters</h4>
<p>Care must be taken when writing a method that sets a property value. The naive implementation of such a method looks like this:</p>
<figure class="highlight"><pre><code class="language-objc" data-lang="objc"><span class="k">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setProperty</span><span class="p">:(</span><span class="n">id</span><span class="p">)</span><span class="nv">value</span>
<span class="p">{</span>
<span class="p">[</span><span class="n">propertyField</span> <span class="nf">release</span><span class="p">];</span>
<span class="n">propertyField</span> <span class="o">=</span> <span class="p">[</span><span class="n">value</span> <span class="nf">retain</span><span class="p">];</span>
<span class="p">}</span></code></pre></figure>
<p>This is bad: if value is the same as propertyField, and the retain count of this object is 1 when we enter the method, the first line of the method will cause the object to be deallocated, and the second line will cause bad things to happen (although bad stuff may not happen immediately, which is worse).</p>
<p>This problem can be worked around by retaining value before releasing propertyField, by ensuring that the values are not equal to each other before performing the operation, or even by autoreleasing propertyField instead of releasing it (although this adds overhead).</p>
<p>Another interesting problem in this space involves methods that get property values. Again, the naive implementation of such a method looks like this:</p>
<figure class="highlight"><pre><code class="language-objc" data-lang="objc"><span class="k">-</span> <span class="p">(</span><span class="n">id</span><span class="p">)</span><span class="n">property</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">propertyField</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>99 times out of a hundred, this will work fine. This of course means that when you run into that one time it doesn't work, it's going to be a huge pain to debug. Here's the case in which you can get into trouble:</p>
<figure class="highlight"><pre><code class="language-objc" data-lang="objc"><span class="n">id</span> <span class="n">foo</span> <span class="o">=</span> <span class="p">[</span><span class="n">obj</span> <span class="nf">property</span><span class="p">];</span>
<span class="p">[</span><span class="n">obj</span> <span class="nf">setProperty</span><span class="p">:</span><span class="n">bar</span><span class="p">];</span>
<span class="p">[</span><span class="n">foo</span> <span class="nf">doSomething</span><span class="p">];</span></code></pre></figure>
<p>If the retain count of propertyField is 1 at the beginning of this block, then the second line will cause it to drop down to zero and be reclaimed. This means that the third line will be performed on an object that has been deallocated, which is, to say the least, less than ideal. The solution to this is to modify the property getter so that it calls retain <em>and</em> autorelease on propertyField before returning it. This has no net effect on the retain count of the object, but it does ensure that the object will stay alive at least until the active NSAutoreleasePool goes out of scope.</p>
http://www.fallingcanbedeadly.com,/posts/so-many-projectsSo Many Projects…2010-03-10T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>I have a <em>lot</em> of side projects at various phases of investigation right now. So many, in fact, that I'm quite sure that I won't get around to actually implementing even half of them. Because completed projects are more important to me than the right to say that I wrote the code, I'm going to list some of them here in the hopes that someone on the lazywebs will be inspired to do something with my vague description.</p>
<p><strong>Add New Features to Clang</strong>. The Objective-C runtime (at least Apple's version of it) allows any string to be specified as the name of a class, but existing Objective-C compilers only allow letters, numbers, underscores and dollar signs in class names. I'd really love to introduce the ability to have class names with greater variety. Apple has already shown their willingness extend the Objective-C language; I'm just going one step further. Here are a few more ideas that I'd like to see in clang:</p>
<ul>
<li>Namespaces: a @namespace keyword could be added to Objective-C. Classes defined within a namespace would have the namespace and a period or double colon prepended to its name. This would allow everyone to abandon the practice of prefixing class names with silly two or three letter abbreviations. Anyone adding namespaces would probably want to add a @using keyword, too.</li>
<li>Greater applicability of the @dynamic keyword: currently, @dynamic can only be applied to properties. However, all sorts of methods could conceivably be dynamically implemented, and expanding the scope of @dynamic would allow someone to disable the compiler warnings for any method whose implementation will be provided at runtime.</li>
<li>Integration with other languages/runtimes: specifically, it would be pretty cool to be able to access objects in the Mono runtime and call methods on them, etc. This is probably the most unlikely of my ideas in this space to be implemented…</li>
</ul>
<p><strong>Refactor Monodevelop</strong>. Monodevelop has great support for things like syntax highlighting and code completion, but most of these features are very tightly tied to Gtk#, and if you want to access such features using a different UI framework, you're out of luck. I'd like to see Monodevelop refactored so that there is a library of common, platform-agnostic code that could conceivably be used from a variety of applications. I know I'd use it.</p>
<p><strong>Write an Objective-C interop library for .NET that uses IDynamicMetaObjectProvider</strong>. Objective-C is a very dynamic language, so this sort of implementation makes quite a bit of sense. Individual Objective-C objects would likely inherit directly from SafeHandle and implement IDynamicMetaObjectProvider; all/most method invocation would happen via DynamicMetaObject. Then, using C#'s new dynamic keyword, most of the functionality in Cocoa would be accessible without the need for an enormous wrapper library.</p>
http://www.fallingcanbedeadly.com,/posts/a-very-amazon-christmasA Very…Amazon…Christmas2008-12-13T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>You know that we’re in the Internet age when four out of five Christmas shoppers in my family use Amazon for shipping:<a href="/images/AmazonChristmas.jpg"><img title="Amazon boxes under a Christmas tree" style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" height="180" alt="Amazon boxes under a Christmas tree" src="/images/AmazonChristmas.jpg" width="240" border="0" /></a> </p>
<p>The family members who sent us stuff through Amazon didn’t opt for gift wrap (it’s a pretty expensive option), so we have to wait for Christmas day to even know who each package is <em>for</em>, let alone what it is or who ordered it. Perhaps we are seeing the formation of a new holiday tradition?</p>
http://www.fallingcanbedeadly.com,/posts/killer-apps--youre-doing-it-wrongKiller Apps—You're Doing it Wrong2008-08-09T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>During my morning journey through all that is new and noteworthy today, I ran across <a href="http://www.linux.com/feature/144170">this article</a> about a "killer development tool" for Linux. The author of this article claims that the tool is "going to make ISVs and other programmers start to love developing for Linux."</p>
<p>I must admit that my interest was piqued. I've done at least a little bit of development on each of the major platforms (Windows, Mac, various flavors of Linux), and I must say that tool support had a big effect on the pleasantness of each experience. Furthermore, while I understand that many developers are quite comfortable with Linux, the lack of a "big neon sign" saying "start here" was a big turn off for me (contrast this with Visual Studio for Windows and XCode for MacOS, and you'll begin to understand what I mean).</p>
<p>So what <em>is</em> this amazing tool? As it turns out, it's a package that helps developers find incompatibilities between their applications and various distributions of Linux.</p>
<p>That's a "killer" application? It's going to make me "love" developing for Linux?</p>
<p>Pardon my incredulity, but applying a band-aid over a problem that doesn't even exist (for the most part) on other platforms does not a killer application make. Nor will it make a person "love" developing for that platform. At the very most, one might say that it "makes the platform less painful" or "eases the burden associated with developing for the platform."</p>
<p>But "love?"</p>
<p>Not so much. I think I'll stick with Windows and MacOS for now, thankyouverymuch.</p>
<p>So today's lesson: if your "killer application" just eases the pain associated with a problem that doesn't exist in other environments, you're doing it wrong.</p>
http://www.fallingcanbedeadly.com,/posts/nsducttape-now-supports-rudimentary-two-way-communicationNSDuctTape now supports (rudimentary) two-way communication2008-03-07T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>This is just a quick note to let you know that NSDuctTape now supports communication in both directions (i.e.-you can now instantiate and manipulate Objective C objects from .NET). The support is still rudimentary, and it's not especially robust, but it's there, and it works. Currently, the new code is only available through Subversion, but I'll probably clean it up a bit and post a new download this weekend.</p>
http://www.fallingcanbedeadly.com,/posts/bindings-and-the-model-view-controller-patternBindings and the Model-View-Controller Pattern2008-03-04T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>There has been a lot of talk lately about the usefulness (or lack thereof) of design patterns in software, but the <a href="http://en.wikipedia.org/wiki/Model_view_controller">Model-View-Controller pattern</a> is, without a doubt, one of my favorites. For any who are unfamiliar with it, Model-View-Controller separates the code of an application into three tiers: code that presents an interface to the user (View), code that actually does useful stuff (Model), and code that glues it all together (Controller). On many platforms, such as Apple's Cocoa or Microsoft's WPF, the view may be partially (or completely) implemented without explicitly writing any code, which can greatly speed the development process.</p>
<p>One under-utilized implication of the Model-View-Controller Pattern is that very careful application of the pattern allows models to be reused in multiple contexts; for example, a model might be used as the backbone of both a Windows application and a web application (or <em>theoretically,</em> for a Windows application and a Macintosh application; this is currently rather difficult, although I am working to make it a <a href="http://fallingcanbedeadly.com/blog/archive/2008/02/18/about-nsducttape.aspx">practical reality</a>). However, even when the models are reused, the views and controllers must be rewritten from scratch. In the case of the view, this is often not a terrible burden, especially when there are good tools for creating views on your platform of choice. On the other hand, rewriting a controller is tedious, boring work. Most of the time, a controller does little more than shuttle data between the view and the model and occasionally disable a control or two. You'd think that there'd be an easier way to hook everything up that didn't involve so much pain and suffering.</p>
<p>As it turns out, you'd be right.</p>
<p>A number of modern MVC frameworks provide a relatively new facility known as "bindings". The UI widgets in such frameworks provide you with the opportunity to specify data sources for various properties (for example, the text in a text field or the enabled state of a button). At runtime, the widgets sign up to receive notifications when the applicable properties on their data sources change (generally using something akin to the <a href="http://en.wikipedia.org/wiki/Observer_pattern">Observer pattern</a>). If the data source changes its value for a property, the view will automagically catch this update and change its display accordingly. Likewise, when the user changes a value in the UI, the view propagates this change down to the model.</p>
<p>While this ability to bind directly to a model is incredibly useful and can greatly reduce the amount of code required for many applications, it also leaves us with a question: where do we put all that code that doesn't exactly fit in a model but that also cannot be adequately represented in the view (for example, the enabled state of a button)? One answer that has been proposed is Dan Crevier's <a href="http://blogs.msdn.com/dancre/archive/2006/10/11/datamodel-view-viewmodel-pattern-series.aspx">DataModel-View-ViewModel pattern</a>. In this pattern, the model (which is renamed to the "data model") and the view remain essentially unchanged, but the controller morphs into being just another model. However, rather than modeling the underlying data, a view model keeps track of application state.</p>
<p>When properly designed, a view model is much more unit testable than a controller, and it seems to me that it ought to be more portable between MVC frameworks, as well. Unfortunately, this pattern comes with a practical hurdle that must be overcome: sometimes, a desired behavior cannot be adequately modeled in a way that is usable by the view. It's often tempting to use this as an excuse to bake platform specific code into a view model, but I find this to be inelegant. In such cases, a developer has two options: either new UI widgets can be created (or extended) to understand the new behaviors, or a controller may be reintroduced in order to serve as a bridge between the view model and the view.</p>
<p>I'm fairly certain that each of these approaches has situations in which it is the best solution, but I strongly suspect that a new controller is the best choice in the majority of cases. While this method does add a fourth tier to the system, which will increase complexity, I believe that in most cases, it will ultimately be less work than baking new functionality right into a view toolkit.</p>
<p>I really wish I could come up with a snappy ending for this post, but it just isn't coming, tonight. In closing, if you're not using MVC in your designs right now (or if you're using it in an undisciplined fashion), I strongly recommend that you study up on it and see if it's right for you. If you're already using MVC, but you aren't using bindings, I'd suggest that you look into whether or not your framework supports them, as they can save you from quite a bit of tedious code.</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4b02a969-077e-4a06-8b7a-729f048659e9" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/mvc" rel="tag">mvc</a>,<a href="http://technorati.com/tags/designpatterns" rel="tag">designpatterns</a></div>
http://www.fallingcanbedeadly.com,/posts/tutorial-for-nsducttape-now-availableTutorial for NSDuctTape now available2008-02-23T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>I've posted an <a href="http://code.google.com/p/nsducttape/wiki/TutorialOne">introductory tutorial</a> to NSDuctTape on Google Code.</p>
<p>Expect more in the not-too-distant future.</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:f0aa0eff-db8c-44c6-ba12-529e134364c0" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/nsducttape" rel="tag">nsducttape</a>,<a href="http://technorati.com/tags/.net" rel="tag">.net</a>,<a href="http://technorati.com/tags/mac" rel="tag">mac</a>,<a href="http://technorati.com/tags/mono" rel="tag">mono</a></div>
http://www.fallingcanbedeadly.com,/posts/crazy-extention-methods-tolazylistCrazy Extension Methods: ToLazyList2008-02-21T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>Way back in November, I promised to show how to optimize my final version of GetPrimes. Today, I give you the solution to the problem:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">using</span> <span class="nn">System</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Collections.Generic</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span>
<span class="k">namespace</span> <span class="nn">Utility</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">EnumerableUtility</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">IList</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">ToLazyList</span><span class="p"><</span><span class="n">T</span><span class="p">>(</span><span class="k">this</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">list</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="n">LazyList</span><span class="p"><</span><span class="n">T</span><span class="p">>(</span><span class="n">list</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">class</span> <span class="nc">LazyList</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="p">:</span> <span class="n">IList</span><span class="p"><</span><span class="n">T</span><span class="p">>,</span> <span class="n">IDisposable</span>
<span class="p">{</span>
<span class="k">public</span> <span class="nf">LazyList</span><span class="p">(</span><span class="n">IEnumerable</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">list</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">_enumerator</span> <span class="p">=</span> <span class="n">list</span><span class="p">.</span><span class="nf">GetEnumerator</span><span class="p">();</span>
<span class="n">_isFinished</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
<span class="n">_cached</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="n">T</span><span class="p">>();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">T</span> <span class="k">this</span><span class="p">[</span><span class="kt">int</span> <span class="n">index</span><span class="p">]</span>
<span class="p">{</span>
<span class="k">get</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="p"><</span> <span class="m">0</span><span class="p">)</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ArgumentOutOfRangeException</span><span class="p">(</span><span class="s">"index"</span><span class="p">);</span>
<span class="k">while</span> <span class="p">(</span><span class="n">_cached</span><span class="p">.</span><span class="n">Count</span> <span class="p"><=</span> <span class="n">index</span> <span class="p">&&</span> <span class="p">!</span><span class="n">_isFinished</span><span class="p">)</span>
<span class="nf">GetNext</span><span class="p">();</span>
<span class="k">return</span> <span class="n">_cached</span><span class="p">[</span><span class="n">index</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">set</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotSupportedException</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">Count</span>
<span class="p">{</span>
<span class="k">get</span>
<span class="p">{</span>
<span class="nf">Finish</span><span class="p">();</span>
<span class="k">return</span> <span class="n">_cached</span><span class="p">.</span><span class="n">Count</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="n">IEnumerator</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="nf">GetEnumerator</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">current</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">current</span> <span class="p"><</span> <span class="n">_cached</span><span class="p">.</span><span class="n">Count</span> <span class="p">||</span> <span class="p">!</span><span class="n">_isFinished</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">current</span> <span class="p">==</span> <span class="n">_cached</span><span class="p">.</span><span class="n">Count</span><span class="p">)</span>
<span class="nf">GetNext</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">current</span> <span class="p">!=</span> <span class="n">_cached</span><span class="p">.</span><span class="n">Count</span><span class="p">)</span>
<span class="k">yield</span> <span class="k">return</span> <span class="n">_cached</span><span class="p">[</span><span class="n">current</span><span class="p">];</span>
<span class="n">current</span><span class="p">++;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Dispose</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">_enumerator</span><span class="p">.</span><span class="nf">Dispose</span><span class="p">();</span>
<span class="n">_isFinished</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="nf">IndexOf</span><span class="p">(</span><span class="n">T</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">result</span> <span class="p">=</span> <span class="n">_cached</span><span class="p">.</span><span class="nf">IndexOf</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
<span class="k">while</span> <span class="p">(</span><span class="n">result</span> <span class="p">==</span> <span class="p">-</span><span class="m">1</span> <span class="p">&&</span> <span class="p">!</span><span class="n">_isFinished</span><span class="p">)</span>
<span class="p">{</span>
<span class="nf">GetNext</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="n">_cached</span><span class="p">.</span><span class="nf">Last</span><span class="p">().</span><span class="nf">Equals</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
<span class="n">result</span> <span class="p">=</span> <span class="n">_cached</span><span class="p">.</span><span class="n">Count</span> <span class="p">-</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Insert</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">,</span> <span class="n">T</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotSupportedException</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">RemoveAt</span><span class="p">(</span><span class="kt">int</span> <span class="n">index</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotSupportedException</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Add</span><span class="p">(</span><span class="n">T</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotSupportedException</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">Clear</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotSupportedException</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="nf">Contains</span><span class="p">(</span><span class="n">T</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nf">IndexOf</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="p">!=</span> <span class="p">-</span><span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">CopyTo</span><span class="p">(</span><span class="n">T</span><span class="p">[]</span> <span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">arrayIndex</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">item</span> <span class="k">in</span> <span class="k">this</span><span class="p">)</span>
<span class="n">array</span><span class="p">[</span><span class="n">arrayIndex</span><span class="p">++]</span> <span class="p">=</span> <span class="n">item</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="n">IsReadOnly</span>
<span class="p">{</span>
<span class="k">get</span> <span class="p">{</span> <span class="k">return</span> <span class="k">true</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="kt">bool</span> <span class="nf">Remove</span><span class="p">(</span><span class="n">T</span> <span class="n">item</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotSupportedException</span><span class="p">();</span>
<span class="p">}</span>
<span class="n">System</span><span class="p">.</span><span class="n">Collections</span><span class="p">.</span><span class="n">IEnumerator</span> <span class="n">System</span><span class="p">.</span><span class="n">Collections</span><span class="p">.</span><span class="n">IEnumerable</span><span class="p">.</span><span class="nf">GetEnumerator</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="nf">GetEnumerator</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">GetNext</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(!</span><span class="n">_isFinished</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">_enumerator</span><span class="p">.</span><span class="nf">MoveNext</span><span class="p">())</span>
<span class="p">{</span>
<span class="n">_cached</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">_enumerator</span><span class="p">.</span><span class="n">Current</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="n">_isFinished</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span>
<span class="n">_enumerator</span><span class="p">.</span><span class="nf">Dispose</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">private</span> <span class="k">void</span> <span class="nf">Finish</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(!</span><span class="n">_isFinished</span><span class="p">)</span>
<span class="nf">GetNext</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">readonly</span> <span class="n">List</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">_cached</span><span class="p">;</span>
<span class="k">readonly</span> <span class="n">IEnumerator</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">_enumerator</span><span class="p">;</span>
<span class="kt">bool</span> <span class="n">_isFinished</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Essentially, what the above code does is to wrap an IEnumerable<T> in a layer that disguises it as an IList<T>. Any value that we evaluate is automatically cached for easy lookup later, but we also don't evaluate values until they are specifically demanded.</p>
<p>The implication of this is that you no longer have to choose between caching all of your values up front and evaluating them lazily&emdash;you can have both with relatively little overhead.</p>
<p>Returning to our example of computing primes, if we simply replace this line:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="n">primes</span> <span class="p">=</span> <span class="n">knownPrimes</span><span class="p">.</span><span class="nf">Concat</span><span class="p">(</span><span class="n">computedPrimes</span><span class="p">)</span></code></pre></figure>
<p>With this one:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="n">primes</span> <span class="p">=</span> <span class="n">knownPrimes</span><span class="p">.</span><span class="nf">Concat</span><span class="p">(</span><span class="n">computedPrimes</span><span class="p">).</span><span class="nf">ToLazyList</span><span class="p">();</span></code></pre></figure>
<p>Then everything is suddenly fine, and we can compute primes at a very rapid rate.</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:b74d0556-3055-4fb5-9cce-604d4b6e65cd" style="PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">Technorati Tags: <a rel="tag" href="http://technorati.com/tags/.net">.net</a>,<a rel="tag" href="http://technorati.com/tags/C%23+3.0">C# 3.0</a>,<a rel="tag" href="http://technorati.com/tags/extension%20methods">extension methods</a></div>
http://www.fallingcanbedeadly.com,/posts/nsducttape-on-google-codeNSDuctTape on Google Code2008-02-20T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>This is by no means a huge update, but NSDuctTape is now <a href="http://code.google.com/p/nsducttape/">hosted</a> on Google Code. You can download the source (or binaries) from there, and the code is also hosted on their Subversion servers.</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:28e4dfd7-fde7-4891-b478-45d71a962110" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/nsducttape" rel="tag">nsducttape</a>,<a href="http://technorati.com/tags/mac" rel="tag">mac</a>,<a href="http://technorati.com/tags/mono" rel="tag">mono</a>,<a href="http://technorati.com/tags/.net" rel="tag">.net</a></div>
http://www.fallingcanbedeadly.com,/posts/announcing-nsducttapeAnnouncing NSDuctTape2008-02-19T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>About a year ago, I started looking for a way to create applications for OS X using the .NET Framework. I found a couple of alternatives, such as <a href="http://www.cocoasharp.org/">Cocoa#</a> and <a href="http://www.imeem.com/developers.aspx">Dumbarton</a>, but neither of them seemed to be quite what I was looking for.</p>
<p>Cocoa# is a project that aims, first and foremost, to create CLR wrappers for most of the classes in the Cocoa library and secondarily, to allow developers to craft classes that are capable of being accessed by Objective C runtime. At first, this sounded like exactly what I wanted--until I realized that Cocoa strongly encourages the use of the Model-View-Controller pattern in its applications, meaning that most of the code written for such an application would be classes that Objective C would be accessing. While the wrappers are cool, the overhead required to create a class that is consumable by the Objective C runtime makes it less than appealing.</p>
<p>Next, I turned to Dumbarton. However, I quickly turned away when I realized that applications using Dumbarton are required to host mono in such a way as to require the application to be released under the GPL <em>[Update: Paolo Molaro, a significant contributor to the Mono project, informs me that this statement is inaccurate. In any case, I would still argue that the issue is confusing enough that many would shy away from using Dumbarton, even if there really is no licensing requirement]</em>. I have nothing against using (or contributing to) GPLed software, but I don't really want to be tied down to it as soon as I begin developing an application.</p>
<p>What was I to do? I looked into contributing to Cocoa#, but its design philosophy is completely different from my own, and I quickly realized that if I wanted to be happy with the result, I would have to write my own library from scratch.</p>
<p>So I did.</p>
<p>I'm posting a very early release of my new library, NSDuctTape, on the website, today. My goal in designing the application was to remove as much friction as possible from the process of designing Model and Controller classes, with the understanding that most views will be defined using Apple's Interface Builder. Today's release supports Models pretty well, and it also supports bindings from Cocoa objects to CLR object properties, so Controllers aren't even always necessary.</p>
<p>I'll post a tutorial soon, but for the moment, you can <a href="http://code.google.com/p/nsducttape/">download</a> it.</p>
<p>Stay tuned for more!</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:f03c6d8a-7936-4af8-bc3b-ffdf5424ea65" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/nsducttape" rel="tag">nsducttape</a>,<a href="http://technorati.com/tags/mac" rel="tag">mac</a>,<a href="http://technorati.com/tags/mono" rel="tag">mono</a>,<a href="http://technorati.com/tags/.net" rel="tag">.net</a></div>
http://www.fallingcanbedeadly.com,/posts/applications-of-iterateApplications of Iterate()2007-11-12T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>Since the code snippets in my previous post consisted mostly of vague hand-waving, I thought it would be good to spend some time today showing how Iterate() can be useful in common algorithms. Consider a fairly standard prime number generator:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">Primes</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="nf">GetPrimes</span><span class="p">(</span><span class="kt">ulong</span> <span class="n">max</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">list</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="p">{</span> <span class="m">2</span> <span class="p">};</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">ulong</span> <span class="n">candidate</span> <span class="p">=</span> <span class="m">3</span><span class="p">;</span> <span class="n">candidate</span> <span class="p"><</span> <span class="n">max</span><span class="p">;</span> <span class="n">candidate</span> <span class="p">+=</span> <span class="m">2</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">sqrt</span> <span class="p">=</span> <span class="p">(</span><span class="kt">ulong</span><span class="p">)</span><span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="kt">bool</span> <span class="n">isPrime</span> <span class="p">=</span> <span class="k">true</span><span class="p">;</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">prime</span> <span class="k">in</span> <span class="n">list</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">prime</span> <span class="p">></span> <span class="n">sqrt</span><span class="p">)</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">candidate</span> <span class="p">%</span> <span class="n">prime</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">isPrime</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">isPrime</span><span class="p">)</span>
<span class="n">list</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">list</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Surely, one could provide additional optimizations to this routine, but it will serve our purposes as it is. So where do we start? The easiest simplification is to get rid of the inner loop because it is already characterized as an operation on a collection. Let's begin by moving the first breaking condition out of the loop:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="kt">var</span> <span class="n">smallPrimes</span> <span class="p">=</span> <span class="n">list</span><span class="p">.</span><span class="nf">TakeWhile</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">sqrt</span><span class="p">);</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">prime</span> <span class="k">in</span> <span class="n">smallPrimes</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">candidate</span> <span class="p">%</span> <span class="n">prime</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">isPrime</span> <span class="p">=</span> <span class="k">false</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Having done this, it now becomes clear that we are verifying a condition against all elements of a collection. We can rewrite this as:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="kt">bool</span> <span class="n">isPrime</span> <span class="p">=</span> <span class="n">list</span><span class="p">.</span><span class="nf">TakeWhile</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">sqrt</span><span class="p">).</span><span class="nf">All</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">candidate</span> <span class="p">%</span> <span class="n">n</span> <span class="p">!=</span> <span class="m">0</span><span class="p">);</span></code></pre></figure>
<p>Of course, now that we're only using isPrime in one place after its definition, we may as well not have it as a temporary variable:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">for</span> <span class="p">(</span><span class="kt">ulong</span> <span class="n">candidate</span> <span class="p">=</span> <span class="m">3</span><span class="p">;</span> <span class="n">candidate</span> <span class="p"><</span> <span class="n">max</span><span class="p">;</span> <span class="n">candidate</span> <span class="p">+=</span> <span class="m">2</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">sqrt</span> <span class="p">=</span> <span class="p">(</span><span class="kt">ulong</span><span class="p">)</span><span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">list</span><span class="p">.</span><span class="nf">TakeWhile</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">sqrt</span><span class="p">).</span><span class="nf">All</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">candidate</span> <span class="p">%</span> <span class="n">n</span> <span class="p">!=</span> <span class="m">0</span><span class="p">))</span>
<span class="n">list</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>These are fine modifications, but they may have left you wondering when Iterate() becomes useful. To demonstrate this, let's begin by applying it in the most obvious place:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">static</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="nf">GetPrimes</span><span class="p">(</span><span class="kt">ulong</span> <span class="n">max</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">list</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="p">{</span> <span class="m">2</span> <span class="p">};</span>
<span class="kt">var</span> <span class="n">candidates</span> <span class="p">=</span> <span class="n">EnumerableUtility</span><span class="p">.</span><span class="n">Iterate</span><span class="p"><</span><span class="kt">ulong</span><span class="p">>(</span><span class="m">3</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">max</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p">+</span> <span class="m">2</span><span class="p">);</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">candidate</span> <span class="k">in</span> <span class="n">candidates</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">sqrt</span> <span class="p">=</span> <span class="p">(</span><span class="kt">ulong</span><span class="p">)</span><span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">list</span><span class="p">.</span><span class="nf">TakeWhile</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">sqrt</span><span class="p">).</span><span class="nf">All</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">candidate</span> <span class="p">%</span> <span class="n">n</span> <span class="p">!=</span> <span class="m">0</span><span class="p">))</span>
<span class="n">list</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">list</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>Well, that doesn't make our code clearer, shorter, or more efficient! However, having a foreach loop <em>does</em> make it clearer that we are performing a filter operation on the collection before actually doing anything with the values:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">static</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="nf">GetPrimes</span><span class="p">(</span><span class="kt">ulong</span> <span class="n">max</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">list</span> <span class="p">=</span> <span class="k">new</span> <span class="n">List</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="p">{</span> <span class="m">2</span> <span class="p">};</span>
<span class="kt">var</span> <span class="n">candidates</span> <span class="p">=</span> <span class="n">EnumerableUtility</span><span class="p">.</span><span class="n">Iterate</span><span class="p"><</span><span class="kt">ulong</span><span class="p">>(</span><span class="m">3</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">max</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p">+</span> <span class="m">2</span><span class="p">);</span>
<span class="kt">var</span> <span class="n">primes</span> <span class="p">=</span> <span class="n">candidates</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span>
<span class="n">candidate</span> <span class="p">=></span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">sqrt</span> <span class="p">=</span> <span class="p">(</span><span class="kt">ulong</span><span class="p">)</span><span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="k">return</span> <span class="n">list</span><span class="p">.</span><span class="nf">TakeWhile</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">sqrt</span><span class="p">).</span><span class="nf">All</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">candidate</span> <span class="p">%</span> <span class="n">n</span> <span class="p">!=</span> <span class="m">0</span><span class="p">);</span>
<span class="p">});</span>
<span class="k">foreach</span> <span class="p">(</span><span class="kt">var</span> <span class="n">prime</span> <span class="k">in</span> <span class="n">primes</span><span class="p">)</span>
<span class="n">list</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="n">prime</span><span class="p">);</span>
<span class="k">return</span> <span class="n">list</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>As an aside, if you're not yet comfortable with closures, you may be a bit unsettled by the ordering of statements in this snippet: it appears as if we are checking the list of primes before we have actually populated it! Rest assured that this is not the case: the Where() function, as it is implemented in System.Core.Enumerable, does not calculate the next value in its result until that value is actually requested. Because we never request a new value until we've added all previous values to the list, we have nothing to fear (note, on the other hand, that other implementations of Where(), such as the one included the upcoming ParallelFX library, may not share this implementation detail, so be sure you're using the right one!).</p>
<p>It would seem that we are near the end of possible refactorings for this routine. However, to believe this is to forget that we are not required to calculate all the values in the list ourselves! Getting rid of list, we finally arrive at this:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">static</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="nf">GetPrimes</span><span class="p">(</span><span class="kt">ulong</span> <span class="n">max</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">knownPrimes</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">ulong</span><span class="p">[]</span> <span class="p">{</span> <span class="m">2</span><span class="p">,</span> <span class="m">3</span> <span class="p">};</span>
<span class="kt">var</span> <span class="n">candidates</span> <span class="p">=</span> <span class="n">EnumerableUtility</span><span class="p">.</span><span class="n">Iterate</span><span class="p"><</span><span class="kt">ulong</span><span class="p">>(</span><span class="m">5</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">max</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p">+</span> <span class="m">2</span><span class="p">);</span>
<span class="n">IEnumerable</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="n">primes</span> <span class="p">=</span> <span class="k">null</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">computedPrimes</span> <span class="p">=</span> <span class="n">candidates</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span>
<span class="n">candidate</span> <span class="p">=></span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">sqrt</span> <span class="p">=</span> <span class="p">(</span><span class="kt">ulong</span><span class="p">)</span><span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="k">return</span> <span class="n">primes</span><span class="p">.</span><span class="nf">TakeWhile</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">sqrt</span><span class="p">).</span><span class="nf">All</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">candidate</span> <span class="p">%</span> <span class="n">n</span> <span class="p">!=</span> <span class="m">0</span><span class="p">);</span>
<span class="p">});</span>
<span class="n">primes</span> <span class="p">=</span> <span class="n">knownPrimes</span><span class="p">.</span><span class="nf">Concat</span><span class="p">(</span><span class="n">computedPrimes</span><span class="p">);</span>
<span class="k">return</span> <span class="n">primes</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>Once again, we have a rather clever use of closures, but I hope this one isn't quite as jarring as the last one might have been. While it may at first appear that we are using primes before it has been assigned a real value, recall that the evaluation of Where() does not occur until values are requested from it, which no longer even happens in this function.</p>
<p>It is also perhaps worth noting that our list of known primes has expanded to include 3. The reason for this is that failure to do so would cause infinite recursion when attempting to access the first value in computedPrimes. If it doesn't seem obvious to you, try it and see for yourself :).</p>
<p>One significant benefit to this latest refactoring is that we now only calculate each prime upon demand. Because of this, we may as well compute all primes from 1 to ulong.MaxValue, and forget about the max parameter:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">static</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="nf">GetPrimes</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">knownPrimes</span> <span class="p">=</span> <span class="k">new</span> <span class="kt">ulong</span><span class="p">[]</span> <span class="p">{</span> <span class="m">2</span><span class="p">,</span> <span class="m">3</span> <span class="p">};</span>
<span class="kt">var</span> <span class="n">candidates</span> <span class="p">=</span> <span class="n">EnumerableUtility</span><span class="p">.</span><span class="n">Iterate</span><span class="p"><</span><span class="kt">ulong</span><span class="p">>(</span><span class="m">3</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p">!=</span> <span class="kt">ulong</span><span class="p">.</span><span class="n">MaxValue</span><span class="p">,</span> <span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p">+</span> <span class="m">2</span><span class="p">).</span><span class="nf">Select</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p">+</span> <span class="m">2</span><span class="p">);</span>
<span class="n">IEnumerable</span><span class="p"><</span><span class="kt">ulong</span><span class="p">></span> <span class="n">primes</span> <span class="p">=</span> <span class="k">null</span><span class="p">;</span>
<span class="kt">var</span> <span class="n">computedPrimes</span> <span class="p">=</span> <span class="n">candidates</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span>
<span class="n">candidate</span> <span class="p">=></span>
<span class="p">{</span>
<span class="kt">var</span> <span class="n">sqrt</span> <span class="p">=</span> <span class="p">(</span><span class="kt">ulong</span><span class="p">)</span><span class="n">Math</span><span class="p">.</span><span class="nf">Sqrt</span><span class="p">(</span><span class="n">candidate</span><span class="p">);</span>
<span class="k">return</span> <span class="n">primes</span><span class="p">.</span><span class="nf">TakeWhile</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">n</span> <span class="p"><=</span> <span class="n">sqrt</span><span class="p">).</span><span class="nf">All</span><span class="p">(</span><span class="n">n</span> <span class="p">=></span> <span class="n">candidate</span> <span class="p">%</span> <span class="n">n</span> <span class="p">!=</span> <span class="m">0</span><span class="p">);</span>
<span class="p">});</span>
<span class="n">primes</span> <span class="p">=</span> <span class="n">knownPrimes</span><span class="p">.</span><span class="nf">Concat</span><span class="p">(</span><span class="n">computedPrimes</span><span class="p">);</span>
<span class="k">return</span> <span class="n">primes</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>Aside from removing max, our only significant change has been to candidates, which is now defined as all odd numbers from 5 to ulong.MaxValue (the trickiness with the call to Select() is to keep ourselves from trying to go past MaxValue).</p>
<p>While we now have some beautiful code, you may have noticed that the last two snippets run significantly more slowly than their fully imperative counterparts. The reason for this is that we are no longer caching our prime numbers, so whenever we have to iterate through the list, all primes must be recalculated. Does this mean that we are doomed? Certainly not! In fact, a very minor change to this code is all that is necessary, but the details will have to wait until the next post.</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9a656fba-d586-4d3f-a102-a6ef4f125e66" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/functional%20programming" rel="tag">functional programming</a>,<a href="http://technorati.com/tags/C#%203.0" rel="tag">C# 3.0</a>,<a href="http://technorati.com/tags/.net" rel="tag">.net</a></div>
http://www.fallingcanbedeadly.com,/posts/beyond-loopsBeyond Loops2007-10-29T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>Lately, I've been reading quite a bit about the functional programming concepts that are finally coming to C#. The benefits of this new hybrid (imperative/functional) style are numerous, from greater readability (for those who grasp the new idioms, anyway) to more convenient parallelization. However, I've seen very little about the advantage that excites me most: eliminating loops.</p>
<p><strong>What?!</strong></p>
<p>Okay, I'm not really advocating that we actually stop writing code that contains loops—after all, the most reasonable alternative to loops is recursion, and recursion hurts my brain. I am instead suggesting that the time has come for most of our loops to be abstracted away, and here is my first attempt at hiding them:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">public</span> <span class="k">static</span> <span class="k">class</span> <span class="nc">EnumerableUtility</span>
<span class="p">{</span>
<span class="k">public</span> <span class="k">static</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">Iterate</span><span class="p"><</span><span class="n">T</span><span class="p">>(</span><span class="n">T</span> <span class="n">initial</span><span class="p">,</span> <span class="n">Func</span><span class="p"><</span><span class="n">T</span><span class="p">,</span> <span class="kt">bool</span><span class="p">></span> <span class="n">fnContinue</span><span class="p">,</span> <span class="n">Func</span><span class="p"><</span><span class="n">T</span><span class="p">,</span> <span class="n">T</span><span class="p">></span> <span class="n">fnNext</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="n">T</span> <span class="n">current</span> <span class="p">=</span> <span class="n">initial</span><span class="p">;</span> <span class="nf">fnContinue</span><span class="p">(</span><span class="n">current</span><span class="p">);</span> <span class="n">current</span> <span class="p">=</span> <span class="nf">fnNext</span><span class="p">(</span><span class="n">current</span><span class="p">))</span>
<span class="k">yield</span> <span class="k">return</span> <span class="n">current</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">static</span> <span class="k">void</span> <span class="n">ApplyToAll</span><span class="p"><</span><span class="n">T</span><span class="p">>(</span><span class="k">this</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">list</span><span class="p">,</span> <span class="n">Action</span><span class="p"><</span><span class="n">T</span><span class="p">></span> <span class="n">fnAction</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">foreach</span> <span class="p">(</span><span class="n">T</span> <span class="n">item</span> <span class="k">in</span> <span class="n">list</span><span class="p">)</span>
<span class="nf">fnAction</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p><em>(Note: Did It With .NET <a href="http://diditwith.net/2007/09/20/BuildingFunctionsFromFunctionsPart1PartialApplication.aspx">defines a similar function</a>, Sequence(), that operates similarly but specifies the arguments in a different order. I prefer my function, but mine could be replaced by his by calling Sequence(initial, fnContinue, fnNext). Either way, the effect is the same.) </em></p>
<p>Why is this so great? All I really did was put a couple loops into a function, right? Well…sort of, but if you'll stick with me, I think that you'll see that these functions have some significant advantages.</p>
<h4>The Problem</h4>
<p>In order to compute very much that is of interest to anyone, a language must support sequence, choice, and repetition. When taken in isolation, each of these concepts is easy to grasp, but when combined, they can very quickly exceed the limits of human comprehension. Personally, I find that a few big loops will tax my abilities faster than either of the other two structures, but I also find that repetition tends to be the least frequently abstracted of the three basic constructs.</p>
<h4>New Paradigm</h4>
<p>Let's look at some code:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="kt">var</span> <span class="n">somethingOrOther</span> <span class="p">=</span> <span class="n">initialValue</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="nf">SomeCondition</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">))</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nf">SomeOtherCondition</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">))</span>
<span class="nf">DoStuff</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">);</span>
<span class="n">somethingOrOther</span> <span class="p">=</span> <span class="nf">GetNext</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>Or its common counterpart:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="k">for</span> <span class="p">(</span><span class="kt">var</span> <span class="n">somethingOrOther</span> <span class="p">=</span> <span class="n">initialValue</span><span class="p">;</span> <span class="nf">SomeCondition</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">);</span> <span class="n">somethingOrOther</span> <span class="p">=</span> <span class="nf">GetNext</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">)))</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nf">SomeOtherCondition</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">))</span>
<span class="nf">DoStuff</span><span class="p">(</span><span class="n">somethingOrOther</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>The details and complexity vary, but I've seen code like this many times in my (admittedly short) career. We've been trained to accept such things as normal, but is this really as good as it gets? Here are some of the issues I see:</p>
<ul>
<li>If the code is sufficiently complex, it becomes difficult to determine with certainty where somethingOrOther is assigned—especially if the original developer was undisciplined.</li>
<li>In the case of the first example, we have an iterator left outside the scope of the loop, which is just asking for trouble.</li>
<li>We're mixing repetition and choice, which will lead to confusion as the complexity of the loop grows.</li>
</ul>
<p>However, the operations defined in EnumerableUtility allow us to think of this as a series of operations on a list, rather than as a loop:</p>
<figure class="highlight"><pre><code class="language-c#" data-lang="c#"><span class="kt">var</span> <span class="n">items</span> <span class="p">=</span> <span class="n">EnumerableUtility</span><span class="p">.</span><span class="nf">Iterate</span><span class="p">(</span><span class="n">initialValue</span><span class="p">,</span> <span class="n">SomeCondition</span><span class="p">,</span> <span class="n">GetNext</span><span class="p">);</span>
<span class="n">items</span> <span class="p">=</span> <span class="n">items</span><span class="p">.</span><span class="nf">Where</span><span class="p">(</span><span class="n">SomeOtherCondition</span><span class="p">);</span>
<span class="n">items</span><span class="p">.</span><span class="nf">ApplyToAll</span><span class="p">(</span><span class="n">DoStuff</span><span class="p">);</span></code></pre></figure>
<p>How is this better? First of all, the second and third operations now appear as a single operation or a list, rather than as a series of operations or individual items—and I find this to be easier on my mental model. Second, we no longer have to concern ourselves about strange assignments to our iterator because the iterator itself has been abstracted away! Finally, having all of the primary operations (enumerating the values, filtering them, and performing an operation on the remaining values) separated from each other allows us to consider each in isolation, which is significantly easier on the brain. </p>
<p>Next time, I intend to introduce some common algorithms and show how using lists instead of loops can simplify their implementation. </p>
http://www.fallingcanbedeadly.com,/posts/and-now-for-something-completely-differentAnd now for something completely different!2007-08-01T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>I just had to point out this <a href="https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=290180">bit of feedback</a> for Visual Studio 2008 Beta 2. Did <em>you</em> notice the issue when you clicked through the license?</p>http://www.fallingcanbedeadly.com,/posts/subversion-on-the-macintoshSubversion on the Macintosh2007-07-19T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<h4>Prerequisites</h4>
<ol>
<li>Move Apache 1.3 to Apache 2. This is actually much less painful that it sounds, but it's quite necessary because Subversion doesn't support anything less than Apache 2. You can try running multiple versions of Apache from one box if you like, but in my case, I found that it was easier to just make the switch. If we're lucky, Apple will put Apache 2 on Leopard, and we won't ever have to worry about this part again. Here's how you get Apache 2 on your machine:
<ol>
<li>Run FinkCommander (you got that back when you were reading my first article on .NET development, right?)</li>
<li>Install the apache2 package. That wasn't so hard, was it?<br />
</li>
</ol>
</li>
<li>If you're also serving up ASP.NET on this machine, rebuild mod_mono (discussed in part 2 of my .NET development series). When you run the configuration script, add <code>--with-apxs=/sw/bin/apxs2</code> to the command line arguments.
<ol>
<li>If you've installed a CruiseControl.NET dashboard (as discussed in part 3 of the .NET development series), then at the end of /sw/etc/apache2/httpd.conf, add:</li>
</ol>
</li>
</ol>
<figure class="highlight"><pre><code class="language-apache" data-lang="apache"><span class="nc">Alias</span> /ccnet "/web/ccnet"
AddMonoApplications <span class="ss">default</span> "/ccnet:/web/ccnet"
<span class="p"><</span><span class="nl">Location</span><span class="sr"> /ccnet</span><span class="p">>
</span> <span class="nc">SetHandler</span> mono
<span class="p"></</span><span class="nl">Location</span><span class="p">></span></code></pre></figure>
<p>Installing Subversion</p>
<ol>
<li>Run FinkCommander and install the libapache2-mod-svn package.</li>
<li>Run <code>sudo mkdir /svn</code>, where <code>/svn</code> is the path where you want to store your repository.</li>
<li>Run <code>sudo svnadmin create /svn</code>.</li>
<li>Run <code>sudo chown -R www /svn</code>, where <code>www</code> is the name of the user the Apache uses.</li>
<li>Edit <code>/sw/etc/apache2/mods-enabled/dav_svn.conf</code>; the comments should explain what you need to do here.</li>
<li>Restart Apache (<code>/sw/etc/sbin/apache2ctl -k restart</code>).</li>
</ol>
<p>At this point, you should have a pretty basic Subversion server set up at <code>http://your-machine/svn</code>. Of course, there are all sorts of other things that you can do to your repository, like set it up for secure access, put it on a different port, and what-have-you, but I haven't had need for any of these features (I'm running on a small, personal network). However, I would suspect that setting up these features would not vary as much from platform to platform as the initial setup procedure does, so try Google if you need that stuff.</p>
<h4>Caveats</h4>
<p>Sadly, I lost my notes on how to get Apache 2 to start up at boot. However, I did find this <a href="http://forums.macnn.com/79/developer-center/322362/tutorial-installing-apache-2-php-5-a/">forum posting</a> that suggests that it can be accomplished by replacing the Apache 1.3 startup scripts with links to the Apache 2 scripts.</p>
<p>I've also found that sometimes, even though I have Apache 2 set up to start up at boot, it fails to do so, or CruiseControl.NET fails to start (or eventually locks up). However, this happens infrequently enough that I haven't bothered to track down the root of the problem, and a reboot (or two) generally fixes it. If anyone reading this happens to stumble upon a solution to my problem, I'd love to hear about it.</p>
http://www.fallingcanbedeadly.com,/posts/developing-for-net-on-the-mac-part-3-continuous-integrationDeveloping for .NET on the Mac, Part 3: Continuous Integration2007-07-13T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p>If you're not already into automated testing and continuous integration, I highly recommend taking a serious look at it, although making a comprehensive argument for the practice is rather beyond the scope of this article. In any case, if you <em>are</em> into continuous integration, you'll definitely want to set up an instance of CruiseControl.NET (or whatever continuous integration server you use) on a Macintosh--the behavior of Mono varies slightly from platform to platform, so you can't really be sure that your code works properly on the Mac unless you test on a Mac.</p>
<p>Let's get down to business, then, shall we?</p>
<p>Prerequisite:</p>
<ul>
<li>I expect that you've already followed through the two opening posts in this series. At a minimum, you need to have an Apache server with mod_mono installed on it.</li>
</ul>
<ol>
<li>Grab CruiseControl.NET from their <a href="http://sourceforge.net/project/showfiles.php?group_id=71179&package_id=83198">SourceForge page</a>. Get the file named CruiseControl.NET-[Version].zip where [Version] is the latest version number.</li>
<li>Unzip the file and copy the contents of webdashboard into a directory that Apache can access. For the purpose of these instructions, I'll be calling it <code>/web/ccnet</code>.</li>
<li>Open <code>/etc/http/httpd.conf</code> in your favorite editor, and add this to the end:</li>
</ol>
<figure class="highlight"><pre><code class="language-apache" data-lang="apache"><span class="nc">Alias</span> /ccnet "/web/ccnet"
AddMonoApplications <span class="ss">default</span> "/ccnet:/web/ccnet"
<span class="p"><</span><span class="nl">Location</span><span class="sr"> /ccnet</span><span class="p">>
</span> <span class="nc">SetHandler</span> mono
<span class="p"></</span><span class="nl">Location</span><span class="p">></span></code></pre></figure>
<p>If you have your permissions set up correctly, you should now be able to see your CruiseControl.NET dashboard by going to http://your-server/ccnet/. But wait: we don't have the actual CruiseControl.NET service running! To get this set up, we need a few more steps:</p>
<ol>
<li>Copy the contents of CruiseControl.NET's <code>server</code> directory into some convenient location, such as <code>/usr/local/ccnet</code>.</li>
<li>Edit <code>ccservice.exe.config</code> to your heart's content; make sure that you also create a valid <code>ccnet.config</code>. Neither of these tasks varies from the standard CruiseControl.NET installation procedures, so refer to the <a href="http://ccnet.thoughtworks.com">CruiseControl.NET site</a> for details on this part.</li>
<li>To get the service running when you first boot your Mac, create a new directory in <code>/Library/StartupItems</code> called <code>ccnet</code>.</li>
<li>In this directory, create two files. One should be called <code>StartupParameters.plist</code>, and the other should be called <code>ccnet</code>. Here's what needs to be in <code>StartupParameters.plist</code>:</li>
</ol>
<pre><code>{
Description = "CruiseControl.NET Server";
Provides = ("ccnet")
OrderPreference = "Late";
Messages =
{
start = "Starting CruiseControl.NET";
top = "Stopping CruiseControl.NET";
restart = "Restarting CruiseControl.NET"
};
}</code></pre>
<p>And here's what you put in the file called ccnet:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c">#!/bin/sh</span>
<span class="c"># startup script for service CruiseControl.NET</span>
<span class="nb">.</span> /etc/rc.common
<span class="k">case</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="k">in
</span>start<span class="p">)</span>
ConsoleMessage <span class="s2">"Starting CruiseControl.NET"</span>d
<span class="k">if</span> <span class="o">[</span> <span class="nt">-x</span> /usr/local/ccnet/ccservice.exe <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
/Library/Frameworks/Mono.framework/Versions/Current/bin/mono-service2 <span class="nt">-d</span>:/src/ccnet /usr/local/ccnet/ccservice.exe
<span class="k">fi</span>
<span class="p">;;</span>
<span class="k">esac</span>
<span class="nb">exit </span>0</code></pre></figure>
<p>Now, if you restart your Mac and navigate to your CruiseControl.NET page, you should have a running instance of ccnet running whatever tests you have set it up to perform.</p>
<p>A couple of notes about the StartupItem I've provided:</p>
<ul>
<li>StartupItems have been replaced with some fancy new technology called launchd in OS X 10.4. However, I could never get that thing to work, and StartupItems work fine, so this is what I've got.</li>
<li>Obviously, I provide no warranty for this. YMMV, but this is what worked for me.</li>
<li>You'll note that StartupItems are also supposed to have the ability to start and restart themselves. I'm lazy—if I need to restart the service, I reboot.</li>
<li>On that note, I've noticed that occasionally, when rebooting, ccservice.exe doesn't initialize as it should. I've never figured out why this happens, but usually another reboot or two fixes it. It doesn't bother me because I rarely reboot my continuous integration server, but if anyone learns a workaround, let me know.</li>
</ul>
<p>Well, that's it for this post. Next time, I'll probably talk about installing Subversion on a Mac. It's not strictly a .NET topic, but it is a quite handy thing to have around, and there are a couple of gotchas to installing it in OS X.</p>
http://www.fallingcanbedeadly.com,/posts/developing-for-net-on-the-mac-part-2-serving-aspnetDeveloping for .NET on the Mac, Part 2: Serving ASP.NET Pages2007-07-01T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p><em>[Updated 2/11/09: Included information about my experience in making a fresh build on a fresh install of Leopard]</em></p>
<p>Getting a Macintosh to serve up ASP.NET content is actually pretty simple. Mono's primary support for ASP.NET comes through an Apache plugin called mod_mono. This is very good news for the Mac user because Apache version 1.3 comes as part of Tiger. As long as you don't need to run other plugins that require newer versions of Apache (like Subversion), setting up ASP.NET on a Mac could scarcely be easier.</p>
<p>Prerequisites:</p>
<ul>
<li>I'm assuming that you've already read and followed <a href="http://www.fallingcanbedeadly.com/blog/archive/2007/06/29/developing-for-.net-on-the-mac-part-1-building-mono.aspx">Part 1</a> of this series. At a minimum, you should have:
<ul>
<li>The Subversion client</li>
<li>A directory for Subversion checkouts (which I refer to as <code>~/src/mono</code>)</li>
<li>A binary distribution of Mono from their <a href="http://www.mono-project.com/downloads">website</a></li>
</ul>
</li>
</ul>
<p>Here's what you need to do:</p>
<ol>
<li>Open a terminal and go to <code>~/src/mono</code>.</li>
<li>Check out the code for mod_mono. This command should get the job done: <code>svn checkout svn://anonsvn.mono-project.com/source/trunk/mod_mono</code>.</li>
<li>Go to <code>~/src/mono/mod_mono</code> and run the command <code>./autogen.sh --prefix=/Library/Frameworks/Mono.framework/Versions/Current</code>.</li>
<li><em>Update: on a fresh install of Leopard, I found that <code>autogen.sh</code> and <code>configure</code> were failing because a tool named <code>libtoolize</code> was renamed to <code>glibtoolize</code>, and the configuration scripts were not configured to handle this. You can fix the problem either by creating an alias for <code>libtoolize</code> or by editing the single line in <code>autogen.sh</code> that refers to <code>libtoolize</code> to point to <code>glibtoolize</code>, instead; furthermore, based on what I read <a href="http://www.gotmono.com/cgi-bin/yabb/YaBB.pl?board=INSTALL;action=display;num=1201877102">here</a>, it seems that the configuration script fails to detect the 64-bit architecture on some Macs. If this happens to you (you'll know because Apache will fail to start up), run <code>CFLAGS="-m64" ./autogen.sh --prefix=/Library/Frameworks/Mono.framework/Versions/Current</code> followed by a <code>make clean</code> and <code>make</code>.</i></li>
<li>Follow this by running <code>make && make install</code>. Note that you will probably need elevated permission to complete the installation ste.</li>
<li>Edit <code>/etc/httpd/httpd.conf</code> and add this to the end of the file: <code>Include /private/etc/httpd/mod_mono.conf</code>. <em>Update: in Leopard, this is <code>/etc/apache2/httpd.conf</code>.</em></li>
<li>Open System Preferences and select "Sharing".</li>
<li>Check the box next to "Personal Web Sharing".</li>
</ol>
<p>At this point, you should have basic support for ASP.NET on your Mac. The last step that you performed turned on Apache, which by default will look for content in /Library/WebServer/Documents, and putting aspx files ino this folder should result in them being handled by mod_mono.</p>
<p>It should be noted that many applications will require more advanced setup than this (for example, applications like the CruiseControl.NET web dashboard want to be able to handle <em>all</em> web requests for their directory, not just the ones pointing to aspx files), but this is a topic for another post.</p>http://www.fallingcanbedeadly.com,/posts/developing-for-net-on-the-mac-part-1-building-monoDeveloping for .NET on the Mac, Part 1: Building Mono for the First Time2007-06-30T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p><i>Update: the process for building Mono has changed significantly since I first wrote this. You can view updated instructions <a href='http://fallingcanbedeadly.com/posts/building-mono-on-mac-os-x-2011-edition'>here</a>.</i></p>
<p>Ever since I first heard about Mono, I've been fascinated by the potential of .NET to become a viable platform for software that targets multiple OSes. Unfortunately, I've discovered (as seems to be the case with many OSS projects), the documentation aimed towards beginners is quite limited, especially when one ventures away from running Mono on Linux.</p>
<p>I've spent many hours trying to get my development environment for the Mac just right, and at times, it's been a rather painful process. So, in the interest of reducing the pain felt by any beginners following after me, I've decided to start recording my processes for getting things set up. At best, this blog will become a useful resource for anyone doing .NET development on the Mac. At worst...well, at least I'll be able to set things up again the next time I have to wipe a hard drive or replace a machine.</p>
<p>One of the first things that I've found in my work is that the Mono installer available from the <a href="http://www.mono-project.com">Mono Project</a> is rarely sufficient for doing any serious development work: bugs abound in the new parts of Mono (I've found a number of problems in generics), and sometimes, I simply can't resist the urge to dig in and fix them. Therefore, when setting up a new development environment, my first goal is generally to get a custom build of Mono up and running.</p>
<p>Here's how I do it:</p>
<p>Prerequisites:</p>
<ul>
<li>Install Mac OS X—this one's kind of a no-brainer, but just for the record, I'm currently running version 10.4.10. This is the case both for my first-generation Mac Mini and my Mac Pro.</li>
<li>Install XCode—again, this shouldn't be too surprising, but I'm aiming for completeness, here :).</li>
<li>Install Fink—I've found that this is the best way to get a lot of the common Unix tools you'll need along the way. Personally, I prefer using <a href="http://finkcommander.sourceforge.net/">FinkCommander</a>, which puts a nice GUI on top of Fink. Be sure to follow all of the installation instructions on their website, or things can go mysteriously and confusingly wrong.</li>
<li>Install pkg-config, glib2-dev, and svn-client; you can get these through Fink.</li>
<li>Install and install an <a href="http://mono-project.com/downloads">official distribution of Mono</a>—sometimes it comes in handy.</li>
</ul>
<p>The actual work:</p>
<ol>
<li>Create a folder for your mono source. For the purpose of these instructions, I'll assume you're going to put it in <code>~/src/mono</code>.</li>
<li>Open a Terminal window and go to <code>~/src/mono</code>. Run the command <code>svn checkout svn://anonsvn.mono-project.com/source/trunk/mono svn://anonsvn.mono-project.com/source/trunk/mcs</code>. This will download the code for the core Mono libraries and the Mono Compiler System. They'll end up in <code>~/src/mono/mono</code> and <code>~/src/mono/mcs</code>.</li>
<li>Create a folder into which you can install your custom build. I put mine in <code>/opt/mono</code>.</li>
<li>Run the command <code>cd ~/src/mono/mono && ./autogen.sh —prefix=/opt/mono</code>. This step should get Mono ready to build.</li>
<li>You're now ready to build and install: <code>make && make install</code>. I'd love to be able to recommend that you also insert <code>make check</code> in that list, but the sad fact is that Mono on MacOS actually fails a number of tests.</li>
</ol>
<p>After you've done all this, you should have a working (custom) build of Mono working on your machine. You can, at any time, upgrade to the latest code by going to <code>~/src/mono</code> and running the command <code>svn update mono mcs</code>. Generally, you'll be able to jump straight to building Mono again, but you may sometimes be required to also run <code>autogen.sh</code>.</p>
<p>Also, it's often very handy to have a script around that will set up all of your paths and whatnot to your custom build of mono. The <a href="http://www.mono-project.com/Parallel_Mono_Environments">Parallel Mono Environments</a> page on the Mono website describes this, although I had to modify mine a bit to get it working right. Here's what it looks like now:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c">#!/bin/bash</span>
<span class="nv">MONO_PREFIX</span><span class="o">=</span>/opt/mono
<span class="nv">GNOME_PREFIX</span><span class="o">=</span>/opt/gnome
<span class="nb">export </span><span class="nv">LD_LIBRARY_PATH</span><span class="o">=</span><span class="nv">$MONO_PREFIX</span>/lib:/sw/lib:<span class="nv">$LD_LIBRARY_PATH</span>
<span class="nb">export </span><span class="nv">C_INCLUDE_PATH</span><span class="o">=</span><span class="nv">$MONO_PREFIX</span>/include:<span class="nv">$GNOME_PREFIX</span>/include:/sw/include:/Library/Frameworks/Mono.framework/Versions/1.2.2.1/include/libpng
<span class="nb">export </span><span class="nv">ACLOCAL_PATH</span><span class="o">=</span><span class="nv">$MONO_PREFIX</span>/share/aclocal
<span class="nb">export </span><span class="nv">PKG_CONFIG_PATH</span><span class="o">=</span><span class="nv">$MONO_PREFIX</span>/lib/pkgconfig:<span class="nv">$GNOME_PREFIX</span>/lib/pkgconfig:/sw/lib/pkgconfig:/usr/lib/pkgconfig:/usr/local/lib/pkgconfig:/usr/X11R6/lib/pkgconfig:/Library/Frameworks/Mono.framework/Versions/1.2.2.1/lib/pkgconfig
<span class="nv">PATH</span><span class="o">=</span><span class="nv">$MONO_PREFIX</span>/bin:<span class="nv">$PATH</span>:/sw/bin
<span class="nv">PS1</span><span class="o">=</span><span class="s2">"[mono] </span><span class="se">\w</span><span class="s2"> @ "</span></code></pre></figure>
<p>Mine is stored in <code>~/mono-dev-env</code> and is invoked via <code>source ~/mono-dev-env</code></p>
<p>That's it for my first post on setting up a development environment for Mac/.NET development. In the future, I'll go into setting up mod_mono (for ASP.NET), CruiseControl.NET (you <em>do</em> have unit test you'd like to run regularly, don't you?), and Subversion (I realize that Subversion isn't strictly related to .NET, but I didn't have a Subversion server when I started this project, and trying to figure out how to get it set up wasn't terribly fun).</p>http://www.fallingcanbedeadly.com,/posts/just-switched-to-subtext-195Just switched to SubText 1.9.52007-06-11T00:00:00+00:00Amanda Mitchellhttp://www.fallingcanbedeadly.com/<p><em>Update: Google Analytics tells me that people are coming to my blog for information about installing Subtext on GoDaddy's servers. Because I'm such a wonderful person, I'm adding instructions for how to do this. (7-4-07)</em></p>
<p><em>Update 2: Mikeas has posted more detailed instructions on how to modify the Web.config that comes with Subtext, including a couple of things that I had forgotten to mention (like e-mail). You can view his instructions <a href="http://www.redgreenblur.com/blog/archive/2007/07/25/subtext.aspx">here</a>.</em></p>
<p>I used to be on dasBlog, but it was difficult to install onto GoDaddy's servers, and the version I was using didn't have support for ASP.NET 2.0 (which is needed for some other development that I want to do), so I switched to SubText.</p>
<p>With any luck, I'll actually get around to posting real content here in the future…</p>
<p><h4>Installing SubText on GoDaddy's Servers</h4></p>
<p>This wasn't originally what I had intended to blog about, but it seems to be why people are coming to my site right now, so here's how I did it. For the sake of completeness, I'm using GoDaddy's Deluxe Windows Hosting for this site, and it runs me about seven bucks a month.</p>
<ol>
<li>Log into your GoDaddy account; then, go to My Account -> Hosting & Servers -> My hosting account -> Open Control Panel. </li>
<li>Go to Settings -> ASP.NET Runtime
<ol>
<li>Open the properties for Content Root and make sure that your ASP.NET version is 2.0. If you have to change it, be aware that it may take some time for GoDaddy to update its servers, and it's not a terribly great idea to upload files to your server until this is done. </li>
<li>Create a directory (I'm assuming you'll call it 'blog'). Give it Read, Web, Write, and SetRoot permissions. </li>
<li>If you want to use <em>Photo Galleries</em> or the <em>MetaWeblog API's MediaObject, </em>you'll also need to create a directory called blog/Images and make sure that it has similar permissions (I haven't actually done this part, since the <a href="http://www.subtextproject.com/Home/About/Docs/Installation/tabid/111/Default.aspx">setup guide</a> says it's optional) </li>
<li>Be aware that steps 2 and 3 may take a while to complete on GoDaddy's end. I don't recommend uploading files until the Control Panel says that everything is up to date. </li>
</ol>
</li>
<li>Go to Databases -> SQL Server
<ol>
<li>Create a database that uses SQL Server 2005. Most of the settings won't matter a whole lot, but you'll want to make sure that you remember the password, at least for a few minutes. :) </li>
<li>Once the database is set up, grab the ODBC connections string for your new database (you can find this by going to the details page of the new database and clicking the configuration button). Remove the "Driver" attribute from this string, and put your password into it. </li>
</ol>
</li>
<li>Modify Subtext's Web.Config file and insert the connection string that you got in step 3. The location for this should be somewhere around line 40. The name of the string is "subtextData". </li>
<li>Once GoDaddy is done setting up all of your directories and databases, ftp to your site and upload all of your content into /blog. </li>
<li>Navigate to http://yourdomain.sometld/blog. Subtext should make the rest of the process easy. </li>
</ol>
<p>A note about automatic redirecting:</p>
<p>For whatever reason, GoDaddy has elected to not allow you to change the ASP.Net permissions on your root folder, and 404 redirects won't work for visiting http://yourdomain.sometld/. If, like me, your blog is the primary content on your site, and this is the first thing that you'd like visitors to see, you can configure a Default.aspx that will redirect people to http://yourdomain.sometld/blog. Here's what mine looks like:</p>
<figure class="highlight"><pre><code class="language-aspx-cs" data-lang="aspx-cs"><%@ Page language="c#" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html>
<head runat="server">
<title></title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<% Response.Redirect("http://www.fallingcanbedeadly.com/blog"); %>
</form>
</body>
</html></code></pre></figure>
<p>Anyway, this is how I have my blog set up, and I would assume that it would work for most users, but I make no guarantees to this effect. Let me know how it turns out for you!</p>