<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Don Abrams is a web programmer currently living in Newark, Delaware USA.</description><title>log.debug( Don )</title><generator>Tumblr (3.0; @donabrams)</generator><link>http://blog.donabrams.me/</link><item><title>Testing Javascript for the Browser</title><description>&lt;p&gt;I experience a lot of pain trying to test my javascript for use in a browser. Some of this has been relieved by categorizing the flavor of code and testing each flavor differently. I can usually break down browser code flavors into the following:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Synchronous utility code&lt;/li&gt;
&lt;li&gt;Interact with the DOM (read, add event listener, fire event, write)&lt;/li&gt;
&lt;li&gt;Handle some event&lt;/li&gt;
&lt;li&gt;Make some server request&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;If your code isn&amp;#8217;t separating these things, it probably should. This is how I test each of these flavors:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;This calls for standard unit testing, test input -&amp;gt; test output. These should make no XHR calls, select arbitrary nodes from the DOM at large, and fire no events unless that is ALL they do and its pretty clear from the function/class name they do so. If your test for this is unmanageable, odds are your function is doing too much.&lt;/li&gt;
&lt;li&gt;These are basically view tests. I&amp;#8217;d recommend using &lt;a href="https://github.com/tmpvar/jsdom" title="jsdom"&gt;jsdom&lt;/a&gt; to mock the DOM during these test. Firing events should also be part of your integration tests as one event can override another, stop propagation early, or forget to stop event propagation without being caught here.&lt;/li&gt;
&lt;li&gt;These are asynchronous tests. Similar to unit testing, you just pass in an event with test args and make sure it calls the right function stubs/events. I like how mocha handles async testing via a timeout. You can also use this timeout to optimize for speed.&lt;/li&gt;
&lt;li&gt;Use sinon to stub XHR requests. If you use websockets, stub them as well (I haven&amp;#8217;t found a sinon for websockets yet, but it should be easy enough). You can pass in test input, test the message passed to the xhr/websocket stub, and wala! Note: please don&amp;#8217;t put logic in XHR callbacks. Instead, please fire and trigger an event. Testing the server response should be part of the server test code. I&amp;#8217;d love to share the same request/response data for callback testing and server testing, but I haven&amp;#8217;t done this before so I can&amp;#8217;t say how it works out.&lt;/li&gt;
&lt;/ol&gt;</description><link>http://blog.donabrams.me/post/30882659299</link><guid>http://blog.donabrams.me/post/30882659299</guid><pubDate>Tue, 04 Sep 2012 15:31:00 -0400</pubDate></item><item><title>Internet3</title><description>&lt;p&gt;network-accessible storage + ad hoc networks  === Internet 3&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;There aren&amp;#8217;t centralized server apps or client apps, but peer apps. &lt;/li&gt;
&lt;li&gt;You store your peers data and they store yours. &lt;/li&gt;
&lt;li&gt;You communicate directly with devices close to you. &lt;/li&gt;
&lt;li&gt;Access to the network is free.&lt;/li&gt;
&lt;li&gt;The internet is only used to &amp;#8216;jump&amp;#8217; across other dense networks.&lt;/li&gt;
&lt;li&gt;Most of your stuff is on the peer network.&lt;/li&gt;
&lt;li&gt;If you live in a dense place like a city, no need for a cell plan, as you use less battery connecting to a nearby peer device rather than a tower 1/2 mile away.&lt;/li&gt;
&lt;li&gt;The network doesn&amp;#8217;t go down when the power does.&lt;/li&gt;
&lt;li&gt;Some people are gateways to the wider internet and charge you to jump out&amp;#8212; but you set your price and if someone else nearby offers it lower you use them instead. &lt;/li&gt;
&lt;li&gt;You&amp;#8217;ll never pay for a local phone plan again.&lt;/li&gt;
&lt;li&gt;You can broadcast messages to just people nearby.&lt;/li&gt;
&lt;li&gt;You can download apps from your peers or send them.&lt;/li&gt;
&lt;li&gt;You can share music and videos to people next to you without any authorization. &lt;/li&gt;
&lt;li&gt;When you are at a crowded event you get better signal, not worse.&lt;/li&gt;
&lt;li&gt;You can cache pages looked at while browsing internet on your device so others can access it free or faster (but only if you want to).&lt;/li&gt;
&lt;li&gt;Banks issue you codes that are equivalent to cash. You sign it and send it to the receiver with a description of what you are buying. They can&amp;#8217;t cash it without verifying their own identities, yours, and the description.&lt;/li&gt;
&lt;li&gt;Verifying identity will likely be the biggest industry, and may be municipal or for-profit driven.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;It would be an interesting world and it&amp;#8217;s possible now.&lt;/p&gt;</description><link>http://blog.donabrams.me/post/29634799796</link><guid>http://blog.donabrams.me/post/29634799796</guid><pubDate>Fri, 17 Aug 2012 14:59:22 -0400</pubDate></item><item><title>How HTTP servers/libs could work</title><description>&lt;p&gt;This is more a brainstorming session than anything else. J2EE has been killing me of late and I&amp;#8217;ve been trying to explain to coworkers how Node.js/Connect and Ruby/Rails work differently&lt;/p&gt;
&lt;p&gt;HTTP Server&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;You should always be able to access the response and request.&lt;/li&gt;
&lt;li&gt;You should always have access to a session identifier if it exists and be able to remove it.&lt;/li&gt;
&lt;li&gt;Resource Mapping should consist of mapping urls to resources. A resource should be a static file or a controller. In order to support generic controllers, variables may be extractable from a URL. Static resources should be cached and listened to for changes!&lt;/li&gt;
&lt;li&gt;There should be an easy way to listen and post to a web socket in addition to subscribing to open/close events&lt;/li&gt;
&lt;li&gt;There should be a way to intercept a static file or controller request&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The above rules should be the sole extent of an Http Server.&lt;/p&gt;
&lt;p&gt;HTTP Utilities:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;There should be an easy way to extract HTML Form data from a request.&lt;/li&gt;
&lt;li&gt;There should be an easy way to extract POST data from a request.&lt;/li&gt;
&lt;li&gt;There should be an easy way to add cookies to a response and retrieve cookies from a request.&lt;/li&gt;
&lt;li&gt;There should be an easy way to urlize and de-urlize a string&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Container Utilities:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;There should be an easy way to extract JSON and XML from a String&lt;/li&gt;
&lt;li&gt;There should be an easy way to stream bits in from a request and out to a response&lt;/li&gt;
&lt;li&gt;There should be an easy way to Map a Dictionary of List of String to and from HTML form data&lt;/li&gt;
&lt;li&gt;There should be an easy way to associate data with a session, and delete a session&lt;/li&gt;
&lt;/ol&gt;</description><link>http://blog.donabrams.me/post/22335505976</link><guid>http://blog.donabrams.me/post/22335505976</guid><pubDate>Thu, 03 May 2012 16:17:57 -0400</pubDate></item><item><title>"You always hear people say, “kids don’t like math!” Correction…kids..."</title><description>“You always hear people say, “kids don’t like math!” Correction…kids don’t like feeling dumb. People don’t like feeling dumb.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;Bryan Meyer, &lt;a href="http://www.doingmathematics.com/2/post/2012/04/putting-the-cart-before-the-horse.html"&gt;&lt;a href="http://www.doingmathematics.com/2/post/2012/04/putting-the-cart-before-the-horse.html"&gt;http://www.doingmathematics.com/2/post/2012/04/putting-the-cart-before-the-horse.html&lt;/a&gt;&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.donabrams.me/post/20596528807</link><guid>http://blog.donabrams.me/post/20596528807</guid><pubDate>Fri, 06 Apr 2012 13:08:12 -0400</pubDate></item><item><title>Apache Balancer Names are Case Insensitive</title><description>&lt;p&gt;In apache 2.2.22,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; # yay &lt;br/&gt; &amp;lt;Proxy balancer://yay stickysession=JSESSIONID failonstatus=500,501,502,503&amp;gt;&lt;br/&gt; BalancerMember &lt;a href="http://webqa1.somewhere.com:8400/yay/"&gt;http://webqa1.somewhere.com:8400/yay/&lt;/a&gt; retry=10 route=webqa1&lt;br/&gt; BalancerMember &lt;a href="http://webqa2.somewhere.com:8400/yay/"&gt;http://webqa2.somewhere.com:8400/yay/&lt;/a&gt; retry=10 route=webqa2&lt;br/&gt; &amp;lt;/Proxy&amp;gt;&lt;br/&gt; ProxyPass /reslife/ balancer://yay/ &lt;br/&gt; # YAY &lt;br/&gt; &amp;lt;Proxy balancer://YAY stickysession=JSESSIONID failonstatus=500,501,502,503&amp;gt; &lt;br/&gt; BalancerMember &lt;a href="http://webqa1.somewhere.com:8400/YAY/"&gt;http://webqa1.somewhere.com:8400/YAY/&lt;/a&gt; retry=10 route=webqa1 &lt;br/&gt; BalancerMember &lt;a href="http://webqa2.somewhere.com:8400/YAY/"&gt;http://webqa2.somewhere.com:8400/YAY/&lt;/a&gt; retry=10 route=webqa2 &lt;br/&gt; &amp;lt;/Proxy&amp;gt; &lt;br/&gt; ProxyPass /YAY/ balancer://YAY/ &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Will produce a balancer called &amp;#8220;balancer://yay&amp;#8221; with 4 workers mapped to both /YAY and /yay. Requests will randomly stick to one or the other. Fun bug/feature of the day.&lt;/p&gt;</description><link>http://blog.donabrams.me/post/20355842606</link><guid>http://blog.donabrams.me/post/20355842606</guid><pubDate>Mon, 02 Apr 2012 13:34:00 -0400</pubDate></item><item><title>"If Bitcoin ever went mainstream, Bitcoin’s broadcast-every-transaction-to-everybody..."</title><description>“If Bitcoin ever went mainstream, Bitcoin’s broadcast-every-transaction-to-everybody infrastructure may turn out to be a bottleneck.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;Coding the Wheel, &lt;a href="http://www.codingthewheel.com/archives/could-bitcoin-revolutionize-online-poker"&gt;&lt;a href="http://www.codingthewheel.com/archives/could-bitcoin-revolutionize-online-poker"&gt;http://www.codingthewheel.com/archives/could-bitcoin-revolutionize-online-poker&lt;/a&gt;&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.donabrams.me/post/19969501419</link><guid>http://blog.donabrams.me/post/19969501419</guid><pubDate>Mon, 26 Mar 2012 17:09:30 -0400</pubDate></item><item><title>"Twitter is often mislabeled as a social network when it’s actually more of a real-time..."</title><description>“Twitter is often mislabeled as a social network when it’s actually more of a real-time information network. Yes, people make connections, but they tend to connect based on shared interests and location above existing friendships. You don’t follow your friends from high school, or others with whom you have nothing in common; You follow people who have something to say. […] Twitter is the most expansive, real-time, searchable window to the world today.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;Mat Honan, &lt;a href="http://gizmodo.com/5895010/the-case-against-google" title="The Case Against Google - Gizmodo"&gt;The case against Google&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.donabrams.me/post/19905302354</link><guid>http://blog.donabrams.me/post/19905302354</guid><pubDate>Sun, 25 Mar 2012 14:37:00 -0400</pubDate></item><item><title>“Both of them recognized a cultural wrong, they envisioned...</title><description>&lt;iframe src="http://player.vimeo.com/video/36579366" width="400" height="225" frameborder="0"&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;“Both of them recognized a cultural wrong, they envisioned a world without that wrong, and they dedicated themselves to fighting for a principle.”&lt;/p&gt;</description><link>http://blog.donabrams.me/post/19892421315</link><guid>http://blog.donabrams.me/post/19892421315</guid><pubDate>Sun, 25 Mar 2012 10:23:21 -0400</pubDate></item><item><title>"The truth though, is that doing what you’ve been doing is going to get you what you’ve..."</title><description>“The truth though, is that doing what you’ve been doing is going to get you what you’ve been getting. If the narrative is getting in the way, if the archetypes you’ve been modeling and the worldview you’ve been nursing no longer match the culture, the economy or your goals, something’s got to give.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;Seth Godin, &lt;a href="http://sethgodin.typepad.com/seths_blog/2012/03/extending-the-narrative.html"&gt;&lt;a href="http://sethgodin.typepad.com/seths_blog/2012/03/extending-the-narrative.html"&gt;http://sethgodin.typepad.com/seths_blog/2012/03/extending-the-narrative.html&lt;/a&gt;&lt;/a&gt;&lt;/em&gt;</description><link>http://blog.donabrams.me/post/19792975056</link><guid>http://blog.donabrams.me/post/19792975056</guid><pubDate>Fri, 23 Mar 2012 15:48:15 -0400</pubDate></item><item><title>OnBeforeUnload Ajax Browser Support</title><description>&lt;h2&gt;Unsupported&lt;/h2&gt;
&lt;ul id="unsupported"&gt;&lt;li&gt;iPad1 Safari - Mozilla/5.0 (iPad; CPU OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3&lt;/li&gt;
&lt;li&gt;Opera - Opera/9.80 (Macintosh; Intel Mac OS X 10.7.3; U; en) Presto/2.10.229 Version/11.61&lt;/li&gt;
&lt;li&gt;iPad2 Safari - Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9B176 Safari/7534.48.3&lt;/li&gt;
&lt;li&gt;iPhone Safari - Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5&lt;/li&gt;
&lt;li&gt;iPhone Opera - Opera/9.80 (iPhone; Opera Mini/6.5.1.23995/27.1366; U; en) Presto/2.8.119 Version/11.10&lt;/li&gt;
&lt;/ul&gt;&lt;h2&gt;Supported&lt;/h2&gt;
&lt;ul id="supported"&gt;&lt;li&gt;Chromium - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/11.10 Chromium/17.0.963.79 Chrome/17.0.963.79 Safari/535.11&lt;/li&gt;
&lt;li&gt;Chrome - Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79 Safari/535.11&lt;/li&gt;
&lt;li&gt;Firefox 11 - Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0&lt;/li&gt;
&lt;li&gt;IE9 - Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)&lt;/li&gt;
&lt;li&gt;IE7 - Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)&lt;/li&gt;
&lt;li&gt;OSX 10.7 Safari - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16&lt;/li&gt;
&lt;li&gt;Android browser - Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; DROIDX Build/4.5.1_57_DX5-35) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Source: &lt;a href="https://gist.github.com/2172114"&gt;&lt;a href="https://gist.github.com/2172114"&gt;https://gist.github.com/2172114&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</description><link>http://blog.donabrams.me/post/19784922249</link><guid>http://blog.donabrams.me/post/19784922249</guid><pubDate>Fri, 23 Mar 2012 12:00:00 -0400</pubDate></item><item><title>"In this position I saw first hand the disconnect that currently exists
between vocational/career..."</title><description>“In this position I saw first hand the disconnect that currently exists&lt;br/&gt;
between vocational/career tech education and traditional high schools—the&lt;br/&gt;
result being students following both paths are basically being cheated of a&lt;br/&gt;
well rounded education.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;span&gt;Maureen Carruthers on School Factory Boards&lt;/span&gt;&lt;/em&gt;</description><link>http://blog.donabrams.me/post/19730275515</link><guid>http://blog.donabrams.me/post/19730275515</guid><pubDate>Thu, 22 Mar 2012 09:15:49 -0400</pubDate></item><item><title>"i agree wholeheartedly with more or less everything except your last point. i think the word..."</title><description>“i agree wholeheartedly with more or less everything except your last point. i think the word ‘slut’ is always harmful because it’s lazy, and i think lazy language encourages lazy thinking and a lack of empathy, diminishing our ability to recognise others as real human beings. some people do hurtful or manipulative things, but perhaps those people have better selves that they haven’t yet figured out how to be. perhaps they are just vicious on purpose, but that doesn’t occur in a vacuum either.”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;span&gt;Liz Turner, &lt;/span&gt;&lt;span&gt;&lt;strong&gt;&lt;a href="http://9gag.com/gag/3144092"&gt;http://9gag.com/gag/3144092&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/em&gt;</description><link>http://blog.donabrams.me/post/18869905249</link><guid>http://blog.donabrams.me/post/18869905249</guid><pubDate>Tue, 06 Mar 2012 18:37:16 -0500</pubDate></item><item><title>Software Engineering for English Majors</title><description>&lt;p&gt;I have a belief that English majors can make great software engineers. Useful traits of the typical English major that transfer over well to Software Engineering:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Can critically analyze&lt;/li&gt;
&lt;li&gt;Know the power and importance of naming&lt;/li&gt;
&lt;li&gt;Can spell&lt;/li&gt;
&lt;li&gt;Are focused on people&lt;/li&gt;
&lt;li&gt;Naturally think in terms of stories&lt;/li&gt;
&lt;li&gt;Understand what it means to iteratively improve something&lt;/li&gt;
&lt;li&gt;Can communicate intent&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I&amp;#8217;ve developed a curriculum I am using to teach a couple people now. Its a syntax-last approach. So far the progression is like this:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Organizing a how-to [Putting on shoes example]&lt;/li&gt;
&lt;li&gt;Reducing a how-to to functions&lt;/li&gt;
&lt;li&gt;Naming functions and stateful definitions&lt;/li&gt;
&lt;li&gt;Reusing, replacing, and composing functions (refactoring as well)&lt;/li&gt;
&lt;li&gt;Interfaces&lt;/li&gt;
&lt;li&gt;Unit Tests&lt;/li&gt;
&lt;li&gt;Side effects (methods vs. functions)&lt;/li&gt;
&lt;li&gt;Properties and states [Shoes example]&lt;/li&gt;
&lt;li&gt;Objects and message passing [List example]&lt;/li&gt;
&lt;li&gt;Synchronous vs. asynchronous&lt;/li&gt;
&lt;li&gt;Classes as Object templates&lt;/li&gt;
&lt;li&gt;Inheritance and Mixins (and its limits) [ToDo List and Book checkout examples]&lt;/li&gt;
&lt;li&gt;Exceptions&lt;/li&gt;
&lt;li&gt;Mocking&lt;/li&gt;
&lt;li&gt;Collections (Bags, Sets, Lists, Maps)&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Strings&lt;/li&gt;
&lt;li&gt;Building programs&lt;/li&gt;
&lt;li&gt;Dependency management&lt;/li&gt;
&lt;li&gt;Conditionals&lt;/li&gt;
&lt;li&gt;Loops&lt;/li&gt;
&lt;li&gt;Finite State Machines&lt;/li&gt;
&lt;li&gt;Regular Expressions&lt;/li&gt;
&lt;li&gt;Stacks and Queues (special lists)&lt;/li&gt;
&lt;li&gt;Streams&lt;/li&gt;
&lt;li&gt;Packets and Protocols (and how the internet works)&lt;/li&gt;
&lt;li&gt;Encryption&lt;/li&gt;
&lt;li&gt;Many to Many, One to Many, Many to One, and One to One relationships&lt;/li&gt;
&lt;li&gt;Key/Value and Document Databases&lt;/li&gt;
&lt;li&gt;Map/Reduce&lt;/li&gt;
&lt;li&gt;Singletons&lt;/li&gt;
&lt;li&gt;Row/Relational Databases&lt;/li&gt;
&lt;li&gt;Locking, Transactions, and Mutability&lt;/li&gt;
&lt;li&gt;Design patterns (at least Bridge, Observer, Visitor, Composite, Decorator, Factory)&lt;/li&gt;
&lt;li&gt;Model2, MVC, and other Architectural patterns&lt;/li&gt;
&lt;li&gt;HTML, CSS, JSON, XML, and other famous acronyms&lt;/li&gt;
&lt;li&gt;How to choose a language and framework&lt;/li&gt;
&lt;li&gt;Metacircular evaluators and creating your own languages (DSLs)&lt;/li&gt;
&lt;li&gt;Working with clients&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;It seems like a lot, but its really only about 10-15 classes. Many of the examples can just be extended and reused. My girlfriend Alice is my primary guinea pig, but I&amp;#8217;m picking up a few more.&lt;/p&gt;
&lt;p&gt;To be even more focused than English majors, I&amp;#8217;m really trying to gear this towards librarians, many of whom will soon be out of jobs. Let me know if you want a more detailed write-up of my progress and lesson plans&amp;#8212; I&amp;#8217;ll publish more eventually.&lt;/p&gt;</description><link>http://blog.donabrams.me/post/18577732659</link><guid>http://blog.donabrams.me/post/18577732659</guid><pubDate>Thu, 01 Mar 2012 19:27:00 -0500</pubDate></item><item><title>On increasing the quality and quantity of virtual content</title><description>&lt;p&gt;Nowadays in the industrialized world, survival is easy. We live in a world where we are paying more and more money for virtual objects rather than physical objects. A high percentage of the objects we buy exist merely to display and interact with these virtual objects.&lt;/p&gt;
&lt;p&gt;However, this world is different than the &amp;#8220;old&amp;#8221; material world. Unlike with material objects, virtual objects can be duplicated without cost. This has led to the rise of the aggregators: big, wonderful companies who aggregate your data, music, information, etc. Aggregators such as Google, Yahoo, Apple make the bulk of the money the internet makes. However, each one is destroying its reason for existence; the way an aggregator makes more money is to reduce the cost of the content it aggregates to as close to zero as possible. Content creators make an ever slimmer slice of the pie. This negatively affects the quality and quantity of the content and eventually the aggregators destroy its market.&lt;/p&gt;
&lt;p&gt;Content creators need to fight back. But they can&amp;#8217;t in a digital world. Piracy is too easy, unstoppable. Once something is free, it can never be locked down again.&lt;/p&gt;
&lt;p&gt;So right now we are turning the virtual world into a police state. A world where every digital transaction is read, analyzed and watched. The fight against piracy will always be there in this world as people copy virtual objects from the regulated world to their walled off gardens. To truly stop piracy, you&amp;#8217;d have to give up all privacy, turning this world into a real police state.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t think that&amp;#8217;s what I want my future to be. &lt;/p&gt;
&lt;p&gt;The only alternative I&amp;#8217;ve seen is to change the funding model. You don&amp;#8217;t sell instances of IP; you sell its existence. We create a digital world where IP is bought before it&amp;#8217;s ever disbursed.&lt;/p&gt;
&lt;p&gt;This is a hard world. Someone has to pay for digital content or it will never be created. You fight against the prisoner&amp;#8217;s dilema; if I think the idea is good enough to fund, then the bloke next to me will fund it and I don&amp;#8217;t need to. Any successful system will have to fight this.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s also a tough sell. Content creators are often like gamblers. If they win, they win big. If they lose, as they usually do, they just play again (&amp;#8220;bad luck&amp;#8221;). More content creators think they will win big than actually will. This new world changes them into salaried or contract workers. If they &amp;#8220;win big&amp;#8221; they don&amp;#8217;t profit as highly. If they &amp;#8220;lose&amp;#8221;, they might get fired or not be able to pick up another job. There are ways to mitigate this: safety nets or bonus systems. Bonuses are possible: you&amp;#8217;d just have to separate evaluation from investment.&lt;/p&gt;
&lt;p&gt;In summary, I don&amp;#8217;t trust the police state model. I understand the romantic appeal of winning big, but I don&amp;#8217;t think its sustainable in this new digital world. If we hope to increase the quality and quantity of digital content, I think the world needs to start paying for it before it&amp;#8217;s published.&lt;/p&gt;</description><link>http://blog.donabrams.me/post/16705499345</link><guid>http://blog.donabrams.me/post/16705499345</guid><pubDate>Sun, 29 Jan 2012 13:04:00 -0500</pubDate></item><item><title>My Javascript Toolchain</title><description>&lt;p&gt;Editor: Textmate&lt;/p&gt;
&lt;p&gt;Design Patterns: Underscore, Coffeescript&lt;/p&gt;
&lt;p&gt;DOM: jQuery&lt;/p&gt;
&lt;p&gt;Dependency Management: Require.js when needed&lt;/p&gt;
&lt;p&gt;Testing: Mocha&lt;/p&gt;
&lt;p&gt;Coverage: node-jscoverage?&lt;/p&gt;
&lt;p&gt;Async: q or Step, haven&amp;#8217;t decided yet&lt;/p&gt;
&lt;p&gt;AOP: YouAreDaChef&lt;/p&gt;
&lt;p&gt;Templates: Jade, Stylus, jQote2&lt;/p&gt;
&lt;p&gt;HTTP: Express&lt;/p&gt;
&lt;p&gt;MVVM: Knockout/Knockback/Backbone, Derby/Racer&lt;/p&gt;</description><link>http://blog.donabrams.me/post/16042670109</link><guid>http://blog.donabrams.me/post/16042670109</guid><pubDate>Tue, 17 Jan 2012 21:58:00 -0500</pubDate></item><item><title>NoSQL Rundown</title><description>&lt;p&gt;This is more for my reference later, the MBA version of &lt;a href="http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis" title="Ultimate NoSQL Comparison"&gt;&lt;a href="http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis"&gt;http://kkovacs.eu/cassandra-vs-mongodb-vs-couchdb-vs-redis&lt;/a&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to make a _____ use _______&lt;/p&gt;
&lt;p&gt;Wiki, CouchDB&lt;/p&gt;
&lt;p&gt;Offline/Online App, CouchDB&lt;/p&gt;
&lt;p&gt;Stateful Chat Server, Redis&lt;/p&gt;
&lt;p&gt;Twitter clone, MongoDB&lt;/p&gt;
&lt;p&gt;Online FPS, Membase&lt;/p&gt;
&lt;p&gt;Payment system, Riak&lt;/p&gt;
&lt;p&gt;Facebook, Neo4j&lt;/p&gt;
&lt;p&gt;Logging, Cassandra&lt;/p&gt;</description><link>http://blog.donabrams.me/post/15590257849</link><guid>http://blog.donabrams.me/post/15590257849</guid><pubDate>Mon, 09 Jan 2012 19:04:30 -0500</pubDate></item><item><title>Under</title><description>&lt;p&gt;James Hague has &lt;a href="http://www.planeterlang.org/en/planet/article/A_Programming_Idiom_Youve_Never_Heard_Of/" title="Under"&gt;a post up&lt;/a&gt; at Planet Erlang that describes an keyword called &amp;#8216;under&amp;#8217; in the programming language J.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;F = A under B
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is equivalent to&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;F = function() {
  B.inverse(A(B(this)));
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Theoretically, this would be very useful for situations in which you do B, then do A, then undo B. This includes adding in frequency space (Fourier transforms), file I/O and database connections (open then close), and parsing (escape some values, do a function, then unescape).&lt;/p&gt;
&lt;p&gt;Ruby supports a similar pattern to this by taking blocks (that would be equivalent to A). However, ruby lacks internal knowledge of an inverse function (or even if a function is inversible).&lt;/p&gt;
&lt;p&gt;In Javascript, closures can operate to take functions blocks as well. Making a layer over Node.js file I/O that uses closures (rather than a callback) might save a lot of time and suffering in the future (especially since forgetting to undo certain actions is a very common production problem).&lt;/p&gt;
&lt;p&gt;However, enough of theory. Lets look at the first example James shows, the magnitude of an array:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mag = sum under square&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The definition I used for &amp;#8216;under&amp;#8217; fits this example pretty well:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Array.prototype.mag = function() {
  square.inverse(sum(square(this)));
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this to work in JavaScript though, square() would need to square each entry in the array AND square.inverse() would need to take a scalar. So to be real inverses, they&amp;#8217;d need more complex implementations. They could be implemented something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var sum = function(a) {
  return _.reduce(a, function(m, n){ return m + n; });
};
var square = function(a) {
  return _.isArray(a) ? _.map(a, square) : (a * a);
};
square.inverse = function(a) {
  return _.isArray(a) ? _.map(a, sqrt) : Math.sqrt(a);
};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is rather wordy. Here it is with Coffeescript:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;F = (x) -&amp;gt;
  B.inverse A B x

sum = (a) -&amp;gt; _.reduce a, (m,n) -&amp;gt; m+n
square = (a) -&amp;gt; _.isArray(a) ? _.map a, (a) -&amp;gt; a^2 : a^2
square.inverse = (a) -&amp;gt; _.isArray(a) ? _.map a, (a) -&amp;gt; Math.sqrt(a) : Math.sqrt(a)&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;//define mag the 'hard' way
mag = (x) -&amp;gt; 
  square.inverse sum square x
//define using 'under'
mag = sum under square&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So an under keyword in Coffeescript would save exactly 19 characters. I&amp;#8217;m not sure this is common enough to warrant a new language feature. However, I do like the idea of explicitly stating that a function is an inverse though (and its quite testable).&lt;/p&gt;
&lt;p&gt;Maybe a utility function would be enough:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mag = first(square)
  .andAtTheEnd(Math.sqrt)
  .andInTheMiddle (x) -&amp;gt;
    sum x&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This might make more sense with a file I/O example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;translatefile = first(openFile)
  .andAtTheEnd(closeFile)
  .andInTheMiddle (openfile) -&amp;gt;
    translate openfile&lt;/code&gt;&lt;/pre&gt;</description><link>http://blog.donabrams.me/post/15294674585</link><guid>http://blog.donabrams.me/post/15294674585</guid><pubDate>Wed, 04 Jan 2012 09:11:00 -0500</pubDate></item><item><title>Why I Love Aspect Oriented Programming</title><description>&lt;p&gt;EDIT: &lt;a href="https://github.com/raganwald/homoiconic/blob/master/2011/11/YouAreDaChef.md#readme" title="AOP"&gt;Someone saying the same&lt;/a&gt; as me, only better&amp;#8212; And he wrote &lt;a href="https://github.com/raganwald/YouAreDaChef" title="Awesome Coffeescript AOP Implementation"&gt;an awesome Coffeescript AOP implementation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I found AspectJ (through Spring) and immediately fell in love with the idea of Aspect Oriented Programming (AOP).&lt;/p&gt;
&lt;p&gt;Say I have this method:&lt;/p&gt;
&lt;pre&gt;&lt;code class="java"&gt;String getDescription(String code) {
  String descr = databaseLookup(code,
      someConstantOrClassVariableKeys);
  //Some cleanup of descr, maybe even appending of (code)
  descr = cleanUpDescr(descr);
  return descr;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I want to cache the result of some method. The only problem is that just when my program is in high demand, the client realizes they want to change some description and I can&amp;#8217;t restart the app. Usually I&amp;#8217;d have to instance and configure a cache somewhere, manage it, and create some hook so that cache can be cleared without restarting the app. If you do a lot of work you can boil this problem down to this:&lt;/p&gt;
&lt;pre&gt;&lt;code class="java"&gt;Cache descrCache = someConfig();
String getDescription(String code) {
  if (descrCache.contains(code, someConstantOrClassVariableKeys))
    return descrCache.get(code, someConstantOrClassVariableKeys)
  String descr = databaseLookup(code,
      someConstantOrClassVariableKeys);
  //Some cleanup of descr, maybe even appending of (code)
  descr = cleanUpDescr(descr);
  if (descr != null)
    descrCache.put(descr, code, someConstantOrClassVariableKeys)
  return descr;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OK, I can deal with this a few times.&lt;/p&gt;
&lt;p&gt;Now imagine I have to add validation to the method arguments. And security based on the user (another class variable) and some of the arguments. Oh, and I want to cache security. Suddenly, its a nightmare of a function and separating the purpose of the function from the added features is disturbingly hard.&lt;/p&gt;
&lt;p&gt;This is when Aspect-oriented programming comes into play. I just wrap the method with some before or around interceptors and life is peachy. My original method code doesn&amp;#8217;t change. It might look something like this when completed:&lt;/p&gt;
&lt;pre&gt;&lt;code class="java"&gt;String getDescription(String code) {
  String descr = databaseLookup(code,
      someConstantOrClassVariableKeys);
  //Some cleanup of descr, maybe even appending of (code)
  descr = cleanUpDescr(descr);
  return descr;
}
//cache the description globally by caching the lookup and the cleanup separately
Cache dbCache = new SomeCache();
@aspect databaseLookup(ProxiedMethod m, String code, 
    Object someConstantOrClassVariableKeys) {
  if (dbCache.contains(code, someConstantOrClassVariableKeys))
    return dbCache.get(code, someConstantOrClassVariableKeys);
  String s = m.execute(code, someConstantOrClassVariableKeys);
  dbCache.put(s, code, someConstantOrClassVariableKeys);
  return s;
}
Cache cleanupDescrCache = new SomeCache();
@aspect cleanUpDescr(ProxiedMethod m, String descr) {
  if (cleanupDescrCache.contains(descr))
    return cleanupDescrCache.get(descr);
  String s = m.execute(descr);
  cleanupDescrCache.put(s, descr);
  return s;
}
//add validation
@aspect getDescription(ProxiedMethod m, String code) {
 if (isValid(code))
    return m.execute(code);
  return null;
}
//add security
@aspect getDescription(ProxiedMethod m, String code) {
  boolean isAllowed = doSecurity(code);
  if (isAllowed)
    return m.execute(code);
  throw new SecurityError();
}
//cache the security
Cache securityCache = new SomeCache();
@aspect doSecurity(ProxiedMethod m, String code) {
  if (securityCache.contains(code))
    return securityCache.get(code);
  boolean isAllowed = m.execute(code);
  securityCache.put(code, isAllowed);
  return s;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Its no where close to the right syntax and I am missing key implementation details, but the pattern is sound. At this point I could even take the cache logic out into a separate class that takes the ProxiedMethod as an argument and automatically instances a cache.&lt;/p&gt;
&lt;p&gt;Doing AOP in javascript is as easy as replacing the method you want to call with the wrapper. Here&amp;#8217;s a &lt;a href="http://stackoverflow.com/questions/1005486/javascript-aop-libraries" title="Javascript AOP implementations"&gt;list of implementations&lt;/a&gt; with various syntaxes. I do enjoy the regex passing to wrap multiple functions in one go.&lt;/p&gt;</description><link>http://blog.donabrams.me/post/15258756215</link><guid>http://blog.donabrams.me/post/15258756215</guid><pubDate>Tue, 03 Jan 2012 17:13:00 -0500</pubDate></item><item><title>First Impressions of Several Node.js Web Frameworks</title><description>&lt;p&gt;&lt;a href="ttp://senchalabs.github.com/connect/" title="Connect"&gt;Connect&lt;/a&gt; - Rack for Node.js. Yay for easy middleware config.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://expressjs.com/" title="Express"&gt;Express&lt;/a&gt; - Sinatra is to Rack as Express is to Connect. &lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mauricemach/zappa" title="Zappa"&gt;Zappa&lt;/a&gt; - Conventions for express and &lt;a href="http://socket.io/" title="Socket.IO"&gt;socket.io&lt;/a&gt; written in Coffeescript.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://railwayjs.com/" title="RailwayJS"&gt;RailwayJS&lt;/a&gt; - Rails for Node without the community. I&amp;#8217;d rather be on rails. If you care about async, see &lt;a href="https://github.com/igrigorik/async-rails" title="Async Rails"&gt;async-rails&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/socketstream/socketstream" title="SocketStream"&gt;SocketStream&lt;/a&gt; - Webserver built on connect that wraps websockets quite nicely. If I wanted to have more than one entry point I&amp;#8217;d have to do a lot of work (I&amp;#8217;d love to have &lt;a href="http://itsnat.sourceforge.net/php/spim/spi_manifesto_en.php" title="The Single Page Interface Manifesto"&gt;single page interface&lt;/a&gt; support or at least something like &lt;a href="http://benalman.com/projects/jquery-bbq-plugin/" title="jQuery BBQ"&gt;BBQ&lt;/a&gt; baked in). It looks like the initial page load is large and lazy loading is not supported. Great for small to medium single page apps with one entry point.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://derbyjs.com/" title="Derby"&gt;Derby&lt;/a&gt; - Closest thing to an MVVM that lets you ignore client/server lines yet (via &lt;a href="https://github.com/codeparty/racer" title="Racer"&gt;racer&lt;/a&gt;). Connect-like route setup. Uses &lt;a href="http://mustache.github.com/" title="Mustache"&gt;mustache&lt;/a&gt;-like HTML templates and &lt;a href="http://learnboost.github.com/stylus/" title="Stylus"&gt;Stylus&lt;/a&gt; for CSS templates. I&amp;#8217;ll miss using &lt;a href="http://jade-lang.com/" title="Jade"&gt;Jade&lt;/a&gt; templates (slated for 0.3 release). To evaluate Derby vs. SocketStream I&amp;#8217;d have to read/write a few apps, no opinions yet.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://flatironjs.org/" title="Flatiron"&gt;Flatiron&lt;/a&gt; - Its hard to talk about this framework from a high level because it has several independent components:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Director is a different approach to routing that more easily supports hierarchal pages. &lt;/li&gt;
&lt;li&gt;Union is a middleware layer that replaces connect but still supports connect middleware.  I&amp;#8217;m not seeing a ton of value in this. &lt;/li&gt;
&lt;li&gt;Plates is a templating engine that is very limited since it doesn&amp;#8217;t support binding lists to templates (looping) or conditionals. &lt;/li&gt;
&lt;li&gt;Resourceful is an object&amp;lt;-&amp;gt;document mapper thats implementation-agnostic. &lt;/li&gt;
&lt;li&gt;Broadway is a plugin format with an event-based lifecycle. &lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The code is clean and well-written, but I&amp;#8217;m not seeing why I&amp;#8217;d use this framework over the others mentioned here. That being said, there are many useful patterns to learn from in the flatiron stack.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jed/kibi" title="Kibi"&gt;Kibi&lt;/a&gt; - Cute and small (but not obscuring) client-side web framework. This is a great start for teaching web servers (code is 80 lines or so) with templating, url patterns, and jsonp solely driven by the client-side!&lt;/p&gt;
&lt;p&gt;Let me know about any other interesting and/or quality frameworks.&lt;/p&gt;</description><link>http://blog.donabrams.me/post/14817018107</link><guid>http://blog.donabrams.me/post/14817018107</guid><pubDate>Mon, 26 Dec 2011 12:50:00 -0500</pubDate></item><item><title>Why I Bothered To Learn Node.js</title><description>&lt;p&gt;So I&amp;#8217;ve been spending my time lately jumping onto the node.js bandwagon. I did this for three reasons:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;I think Javascript is the best language to teach basic programming concepts and be productive as early as possible. Prior to node, this was not the case. Node added dependency management, system level calls, and other programming concepts that made Javascript move out of the DOM-only arena and become a &amp;#8220;real&amp;#8221; programming language. Since I plan on teaching an intro programming class this Spring, I figured working with some server-side js would make me more qualified.&lt;/li&gt;
&lt;li&gt;Coffeescript is a great distillation of js design patterns. As I have no problem with whitespace-dependent syntax, it&amp;#8217;s beautiful for writing terse meaningful code (even if it can produce wordier js than handcoding).&lt;/li&gt;
&lt;li&gt;I don&amp;#8217;t want to write either the communication layer between the server &amp;amp; client or different validators for the server &amp;amp; client. Manually specifying url patterns for ajax services really needs to go out of style. I have not found a Node.js framework that does this for me yet, but I know it is possible&amp;#8212; I&amp;#8217;m just hoping someone has done (most of) the hard work for me.&lt;/li&gt;
&lt;/ol&gt;</description><link>http://blog.donabrams.me/post/14813072185</link><guid>http://blog.donabrams.me/post/14813072185</guid><pubDate>Mon, 26 Dec 2011 11:02:00 -0500</pubDate></item></channel></rss>
