tag:blogger.com,1999:blog-101626392009-06-13T15:53:06.567-03:00Rafael ramblingRafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.comBlogger72125tag:blogger.com,1999:blog-10162639.post-6165666984192622642009-03-07T18:45:00.006-03:002009-03-09T21:24:13.776-03:00Software<blockquote><br /><span style="font-style: italic;">This is my Quality is Dead hypothesis: a pleasing level of quality for end users has become too hard to achieve while demand for it has simultaneously evaporated and penalties for not achieving it are weak. The entropy caused by mindboggling change and innovation in computing has reached a point where it is extremely expensive to use traditional development and testing methods to create reasonably good products and get a reasonable return on investment. Meanwhile, user expectations of quality have been beaten out of them. When I say quality is dead, I don’t mean that it’s dying, or that it’s under threat. What I mean is that we have collectively– and rationally– ceased to expect that software normally works well, even under normal conditions. Furthermore, there is very little any one user can do about it.</span><br /></blockquote><p style="text-align: right;"><a href="http://www.satisfice.com/blog/archives/224">James Bach</a></p><br /><blockquote style="font-style: italic;">If you look at engineering or maths, we've been doing that for thousands of years, so we now know how to build a building and make it solid. With code, we've been doing computer science for 70-75 years, so we are still scratching the surface - we don't have a real theory or like physics, where they have a good foundation. We have the Turing machine that doesn't really reflect distributed computation. The lambda calculus captures certain parts, then there is a lot of process algebra, but it's not yet clear that we really have understood everything, which I think is fantastic, because that means there is opportunity to discover new things.</blockquote><p style="text-align: right;"><a href="http://www.infoq.com/interviews/LINQ-Erik-Meijer">Erik Meijer</a></p><br /><blockquote style="font-style: italic;">Much of what is wrong about our field is that many of the ideas that happened before 1975 are still the current paradigm. He <span>[Alan Kay]</span> has a strong feeling that our field has been mired for some time, but because of Moore’s law, there are plenty of things to work on. The commercialization of personal computing was a tremendous distraction to our field and we haven’t, and may not, recover from it.<br /><br />One of Alan’s undergraduate degrees is in molecular biology. He can’t understand it anymore despite having tried to review new developments every few years. That’s not true in computer science. The basics are still mostly the same. If you go to most campuses, there is a single computer science department and the first course in computer science is almost indistinguishable from the first course in 1960. They’re about data structures and algorithms despite the fact that almost nothing exciting about computing today has to do with data structures and algorithms.</blockquote><p style="text-align: right;"><a href="http://www.windley.com/archives/2006/02/alan_kay_is_com.shtml">Alan Kay (paraphrased by Phil Windley)</a></p><p style="text-align: right;">[Actually, check the comments for Alan's clarification].<br /></p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-616566698419262264?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com3tag:blogger.com,1999:blog-10162639.post-60211359266680092742008-07-17T02:59:00.002-03:002009-01-27T01:46:33.168-02:00Comments on Comments on the Previous post<div xmlns='http://www.w3.org/1999/xhtml'><ul><li>Henry Ware <a href='http://www.nabble.com/Re:--scala-user--Phantom-types-td18372260.html#a18373739'>suggested</a> a modification to the <a href='http://snippets.dzone.com/posts/show/5741'>builder with abstract members</a> removing a lot of the boilerplate. Incidentally, this is a nice illustration of how nested types can be <a href='http://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/are-nested-clas.html'>put to a good use</a> in Scala.</li><li>Justin <a href='http://blog.rafaelferreira.net/2008/07/type-safe-builder-pattern-in-scala.html?showComment=1215638460000#c1427852678424330516'>ported</a> the code to Haskell, which was very cool.</li><li>A couple of commenters suggested that languages with support for default parameter values (like Python and Groovy) don't need elaborate constructs such as the builder pattern. There are two ways to respond. One is to remind that the intent of the pattern, specially as originally described in the GoF book, has little to do with optional data. The other is to acknowledge that I probably put too much emphasis on this issue and forgot to mention a very common idiom for building objects in Scala: just declare mandatory "parameters" as abstract vals and optional ones as concrete vals with default values, like so:<br/><pre class='prettyprint'>abstract class OrderOfScotch {<br/> val brand:String<br/> val mode:Preparation<br/> val isDouble:Boolean <br/> val glass:Option[Glass] = None<br/>}</pre><br/>And to instantiate:<br/><pre class='prettyprint'>val myDose = new OrderOfScotch {val brand = "Bobby Runner"; val mode = OnTheRocks; val isDouble = false}</pre></li><li>I guess that's it. Thanks y'all.<br/></li></ul></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-6021135926668009274?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com2tag:blogger.com,1999:blog-10162639.post-17886548726024009402008-07-09T03:42:00.006-03:002008-07-09T19:02:52.564-03:00Type-safe Builder Pattern in Scala<i>The Builder Pattern is an increasingly popular idiom for object creation. Traditionally, one of it's shortcomings in relation to simple constructors is that clients can try to build incomplete objects, by omitting mandatory parameters, and that error will only show up in runtime. I'll show how to make this verification statically in Scala.</i><br /><br /><br />So, let's say you want to order a shot of scotch. You'll need to ask for a few things: the brand of the whiskey, how it should be prepared (neat, on the rocks or with water) and if you want it doubled. Unless, of course, you are a pretentious snob, in that case you'll probably also ask for a specific kind of glass, brand and temperature of the water and who knows what else. Limiting the snobbery to the kind of glass, here is one way to represent the order in scala.<br /><pre class='prettyprint'>sealed abstract class Preparation /* This is one way of coding enum-like things in scala */<br />case object Neat extends Preparation<br />case object OnTheRocks extends Preparation<br />case object WithWater extends Preparation<br /><br />sealed abstract class Glass<br />case object Short extends Glass<br />case object Tall extends Glass<br />case object Tulip extends Glass<br /><br />case class OrderOfScotch(val brand:String, val mode:Preparation, val isDouble:Boolean, val glass:Option[Glass])</pre><br />A client can instantiate their orders like this:<br /><pre class='prettyprint'>val normal = new OrderOfScotch("Bobby Runner", OnTheRocks, false, None)<br />val snooty = new OrderOfScotch("Glenfoobar", WithWater, false, Option(Tulip));</pre><br />Note that if the client doesn't want to specify the glass he can pass None as an argument, since the parameter was declared as Option[Glass]. This isn't so bad, but it can get annoying to remember the position of each argument, specially if many are optional. There are two traditional ways to circumvent this problem — define telescoping constructors or set the values post-instantiation with accessors — but both idioms have their shortcomings. Recently, in Java circles, it has become popular to use a variant of the <abbr title='Gang of Four'>GoF</abbr> Builder pattern. So popular that it is Item 2 in the second edition of Joshua Bloch's <a href='http://www.amazon.com/gp/redirect.html?ie=UTF8&location=http%3A%2F%2Fwww.amazon.com%2FEffective-Java-2nd-Joshua-Bloch%2Fdp%2F0321356683%2F&tag=rafaeldivagan-20&linkCode=ur2&camp=1789&creative=9325'>Effective Java</a><img width='1' height='1' border='0' style='border: medium none ! important; margin: 0px ! important;' alt='' src='http://www.assoc-amazon.com/e/ir?t=rafaeldivagan-20&l=ur2&o=1'/>. A Java-ish implementation in Scala would be something like this:<br /><pre class='prettyprint'>class ScotchBuilder {<br /> private var theBrand:Option[String] = None<br /> private var theMode:Option[Preparation] = None<br /> private var theDoubleStatus:Option[Boolean] = None<br /> private var theGlass:Option[Glass] = None<br /><br /> def withBrand(b:Brand) = {theBrand = Some(b); this} /* returning <b>this</b> to enable method chaining. */<br /> def withMode(p:Preparation) = {theMode = Some(p); this}<br /> def isDouble(b:Boolean) = {theDoubleStatus = some(b); this}<br /> def withGlass(g:Glass) = {theGlass = Some(g); this}<br /><br /> def build() = new OrderOfScotch(theBrand.get, theMode.get, theDoubleStatus.get, theGlass);<br />}</pre><br />This is almost self-explanatory, the only caveat is that verifying the presence of non-optional parameters (everything but the glass) is done by the Option.get method. If a field is still None, an exception will be thrown. Keep this in mind, we'll come back to it later.<br /><br />The var keyword prefixing the fields means that they are mutable references. Indeed, we mutate them in each of the building methods. We can make it more functional in the traditional way:<br /><pre class='prettyprint'>object BuilderPattern {<br /> class ScotchBuilder(theBrand:Option[String], theMode:Option[Preparation], theDoubleStatus:Option[Boolean], theGlass:Option[Glass]) {<br /> def withBrand(b:String) = new ScotchBuilder(Some(b), theMode, theDoubleStatus, theGlass)<br /> def withMode(p:Preparation) = new ScotchBuilder(theBrand, Some(p), theDoubleStatus, theGlass)<br /> def isDouble(b:Boolean) = new ScotchBuilder(theBrand, theMode, Some(b), theGlass)<br /> def withGlass(g:Glass) = new ScotchBuilder(theBrand, theMode, theDoubleStatus, Some(g))<br /><br /> def build() = new OrderOfScotch(theBrand.get, theMode.get, theDoubleStatus.get, theGlass);<br /> }<br /><br /> def builder = new ScotchBuilder(None, None, None, None)<br />}</pre><br />The scotch builder is now enclosed in an object, this is standard practice in Scala to isolate modules. In this enclosing object we also find a factory method for the builder, which should be called like so:<br /><pre class='prettyprint'>import BuilderPattern._<br /><br />val order = builder withBrand("Takes") isDouble(true) withGlass(Tall) withMode(OnTheRocks) build()</pre><br />Looking back at the ScotchBuilder class and it's implementation, it might seem that we just moved the huge constructor mess from one place (clients) to another (the builder). And yes, that is exactly what we did. I guess that is the very definition of encapsulation, sweeping the dirt under the rug and keeping the rug well hidden. On the other hand, we haven't gained all the much from this "functionalization" of our builder; the main failure mode is still present. That is, having clients forget to set mandatory information, which is a particular concern since we obviously can't fully trust the sobriety of said clients<a href='#n1'>*</a>. Ideally the type system would prevent this problem, refusing to typecheck a call to build() when any of the non-optional fields aren't set. That's what we are going to do now.<br /><br />One technique, which is very common in Java fluent interfaces, would be to write an interface for each intermediate state containing only applicable methods. So we would begin with an interface VoidBuilder having all our withFoo() methods but no build() method, and a call to, say, withMode() would return another interface (maybe BuilderWithMode), and so on, until we call the last withBar() for a mandatory Bar, which would return an interface that finally has the build() method. This technique works, but it requires a metric buttload of code — for <b>n</b> mandatory fields <b>2<sup>n</sup></b> interfaces should be created. This could be automated via code generation, but there is no need for such heroic efforts, we can make the typesystem work in our favor by applying some generics magic. First, we define two abstract classes:<br /><pre class='prettyprint'>abstract class TRUE<br />abstract class FALSE<br /></pre><br />Then, for each mandatory field, we add to our builder a generic parameter:<br /><pre class='prettyprint'>class ScotchBuilder[HB, HM, HD](val theBrand:Option[String], val theMode:Option[Preparation], val theDoubleStatus:Option[Boolean], val theGlass:Option[Glass]) {<br /><br /> /* ... body of the scotch builder .... */<br /><br />}</pre><br />Next, have each withFoo method pass ScotchBuilder's type parameters as type arguments to the builders they return. But, and here is where the magic happens, there is a twist on the methods for mandatory parameters: they should, for their respective generic parameters, pass instead TRUE:<br /><pre class='prettyprint'>class ScotchBuilder[HB, HM, HD](val theBrand:Option[String], val theMode:Option[Preparation], val theDoubleStatus:Option[Boolean], val theGlass:Option[Glass]) {<br /> def withBrand(b:String) = <br /> new ScotchBuilder[TRUE, HM, HD](Some(b), theMode, theDoubleStatus, theGlass)<br /><br /> def withMode(p:Preparation) = <br /> new ScotchBuilder[HB, TRUE, HD](theBrand, Some(p), theDoubleStatus, theGlass)<br /><br /> def isDouble(b:Boolean) = <br /> new ScotchBuilder[HB, HM, TRUE](theBrand, theMode, Some(b), theGlass)<br /><br /> def withGlass(g:Glass) = <br /> new ScotchBuilder[HB, HM, HD](theBrand, theMode, theDoubleStatus, Some(g))<br />}</pre><br />The second part of the magic act is to apply the world famous <a href='http://www.artima.com/weblogs/viewpost.jsp?thread=179766'>pimp-my-library</a> idiom and move the build() method to an implicitly created class, which will be anonymous for the sake of simplicity:<br /><pre class='prettyprint'>implicit def enableBuild(builder:ScotchBuilder[TRUE, TRUE, TRUE]) = new {<br /> def build() = <br /> new OrderOfScotch(builder.theBrand.get, builder.theMode.get, builder.theDoubleStatus.get, builder.theGlass);<br />}</pre><br />Note the type of the parameter for this implicit method: <b>ScotchBuilder[TRUE, TRUE, TRUE]</b>. This is the point where we "declare" that we can only build an object if all the mandatory parameters are specified. And it really works:<br /><pre>scala> builder withBrand("hi") isDouble(false) withGlass(Tall) withMode(Neat) build()<br />res5: BuilderPattern.OrderOfScotch = OrderOfScotch(hi,Neat,false,Some(Tall))<br /><br />scala> builder withBrand("hi") isDouble(false) withGlass(Tall) build() <br /><console>:9: error: value build is not a member of BuilderPattern.ScotchBuilder[BuilderPattern.TRUE,BuilderPattern.FALSE,BuilderPattern.TRUE]<br /> builder withBrand("hi") isDouble(false) withGlass(Tall) build()</pre><br />So, we achieved our goal (see the full listing below). If you are worried about the enormous parameter lists inside the builder, I've posted <a href="http://snippets.dzone.com/posts/show/5741">here</a> an alternative implementation with abstract members instead. It is more verbose, but also cleaner.<br /><br />Now, remember those abstract classes TRUE and FALSE? We never did subclass or instantiate them at any point. If I'm not mistaken, this is an idiom named Phantom Types, commonly used in the ML family of programming languages. Even though this application of phantom types is fairly trivial, we can glimpse at the power of the mechanism. We have, in fact, codified all 2<sup>n</sup> states (one for each combination of mandatory fields) as types. ScotchBuilder's subtyping relation forms a lattice structure and the <b>enableBuild()</b> implicit method requires the supremum of the poset (namely, <b>ScotchBuilder[TRUE, TRUE, TRUE]</b>). If the domain requires, we could specify any other point in the lattice — say we can doll-out a dose of any cheap whiskey if the brand is not given, this point is represented by <b>ScotchBuilder[_, TRUE, TRUE]</b>. And we can even escape the lattice structure by using Scala inheritance. Of course, I didn't invent any of this; the idea came to me in <a href='http://scholar.google.com.br/scholar?cluster=15738227024751313970'>this</a> article by Matthew Fluet and Riccardo Pucella, where they use phantom types to encode subtyping in a language that lacks it.<br /><br /><hr/><br /><pre class="prettyprint">object BuilderPattern {<br /> sealed abstract class Preparation<br /> case object Neat extends Preparation<br /> case object OnTheRocks extends Preparation<br /> case object WithWater extends Preparation<br /><br /> sealed abstract class Glass<br /> case object Short extends Glass<br /> case object Tall extends Glass<br /> case object Tulip extends Glass<br /><br /> case class OrderOfScotch(val brand:String, val mode:Preparation, val isDouble:Boolean, val glass:Option[Glass])<br /><br /> abstract class TRUE<br /> abstract class FALSE<br /><br /> class ScotchBuilder<br /> [HB, HM, HD]<br /> (val theBrand:Option[String], val theMode:Option[Preparation], val theDoubleStatus:Option[Boolean], val theGlass:Option[Glass]) {<br /> def withBrand(b:String) = <br /> new ScotchBuilder[TRUE, HM, HD](Some(b), theMode, theDoubleStatus, theGlass)<br /><br /> def withMode(p:Preparation) = <br /> new ScotchBuilder[HB, TRUE, HD](theBrand, Some(p), theDoubleStatus, theGlass)<br /><br /> def isDouble(b:Boolean) = <br /> new ScotchBuilder[HB, HM, TRUE](theBrand, theMode, Some(b), theGlass)<br /><br /> def withGlass(g:Glass) = new ScotchBuilder[HB, HM, HD](theBrand, theMode, theDoubleStatus, Some(g))<br /> }<br /><br /> implicit def enableBuild(builder:ScotchBuilder[TRUE, TRUE, TRUE]) = new {<br /> def build() = <br /> new OrderOfScotch(builder.theBrand.get, builder.theMode.get, builder.theDoubleStatus.get, builder.theGlass);<br /> }<br /><br /> def builder = new ScotchBuilder[FALSE, FALSE, FALSE](None, None, None, None)<br />}<br /></pre><br /><br /><br /><p id='n1'>* Did you hear that noise? It's the sound of my metaphor shattering into a million pieces</p><br /><br /><i>EDIT 2008-07-09 at 19h00min: Added introductory paragraph.</i><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-1788654872602400940?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com14tag:blogger.com,1999:blog-10162639.post-72367479028567478832008-04-08T04:52:00.010-03:002008-12-11T16:55:04.263-02:00A couple of interesting DSLsIt may not yet be an industry tsunami, but there certainly is a growing wave of interest in Domain Specific Languages. As <a href="http://lambda-the-ultimate.org/node/2302">often happens</a> when thinking about programming language design, there appears to be an excessive concern with syntax and little talk of semantics. Dave Thomas <a href="http://pragdave.blogs.pragprog.com/pragdave/2008/03/the-language-in.html">points out</a> how much effort is wasted playing syntactic games to make code look like English; effort that would be better spent identifying and representing the domain. To prove his point he talks about make and active record and Groovy builders as examples of successful DSLs. I've stumbled upon some more examples of semantically interesting DSLs on a couple of papers and thought it would be worthwhile to share some stuff I learned in the process.<br /><br /><br /><span style="font-weight: bold;font-size:180%;" >Kay</span><br />Alan Kay is one of the giants in our little <a href="http://www.laputan.org/catfish/archives/000199.html">science</a>, known for his fearless disposition to carry out "big ideas". His most recent endeavor, partnering with Ian Piumarta and others, is a good example of that. The project is called "Steps Toward the Reinvention of Programming" and aims to build a complete software system, from the metal up to the applications, in under 20 KLOC. Some of that magic will be achieved through, you guessed it, domain specific languages. To quote from first published <a href="http://www.vpri.org/pdf/steps_TR-2007-008.pdf">report</a>.<br /><span style="font-style:italic;"><blockquote><br />We also think that creating languages that fit the problems to be solved makes solving the problems easier, makes the solutions more understandable and smaller, and is directly in the spirit of our “active-math” approach. These “problem-oriented languages” will be created and used for large and small problems, and at different levels of abstraction and detail.<br /></blockquote></span><br />The project is only a year-old, so it is understandably far from the goal of a full-system. But they have already delivered bits and pieces that give an idea of the path forward. A particularly cool part is their TCP/IP stack implementation. The first step in any networking stack is to unmarshal packet headers according to some specification. For IP we look in RFC-791 and find a lovely piece of ASCII art describing just that:<br /><br /><div style="overflow:auto"><pre><br />+-------------+-------------+-------------------------+----------+----------------------------------------+<br />| 00 01 02 03 | 04 05 06 07 | 08 09 10 11 12 13 14 15 | 16 17 18 | 19 20 21 22 23 24 25 26 27 28 29 30 31 |<br />+-------------+-------------+-------------------------+----------+----------------------------------------+<br />| version | headerSize | typeOfService | length |<br />+-------------+-------------+-------------------------+----------+----------------------------------------+<br />| identification | flags | offset |<br />+---------------------------+-------------------------+----------+----------------------------------------+<br />| timeToLive | protocol | checksum |<br />+---------------------------+-------------------------+---------------------------------------------------+<br />| sourceAddress |<br />+---------------------------------------------------------------------------------------------------------+<br />| destinationAddress |<br />+---------------------------------------------------------------------------------------------------------+<br /></pre></div><br /><br />Most implementations just <a href="http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/inet/ip/ip.c">hardcode</a> these definitions, and those for TCP, and for UDP, and so on. Of course the footprint of the traditional approach is too high for Kay and Piumarta purposes. They opted for a seemingly odd technique: just grab the data from the specifications. Here is, in its entirety, the code for unmarshaling IP headers:<br /><br /><div style="overflow:auto"><pre><br /> { structure-diagram }<br />+-------------+-------------+-------------------------+----------+----------------------------------------+<br />| 00 01 02 03 | 04 05 06 07 | 08 09 10 11 12 13 14 15 | 16 17 18 | 19 20 21 22 23 24 25 26 27 28 29 30 31 |<br />+-------------+-------------+-------------------------+----------+----------------------------------------+<br />| version | headerSize | typeOfService | length |<br />+-------------+-------------+-------------------------+----------+----------------------------------------+<br />| identification | flags | offset |<br />+---------------------------+-------------------------+----------+----------------------------------------+<br />| timeToLive | protocol | checksum |<br />+---------------------------+-------------------------+---------------------------------------------------+<br />| sourceAddress |<br />+---------------------------------------------------------------------------------------------------------+<br />| destinationAddress |<br />+---------------------------------------------------------------------------------------------------------+<br /> ip -- Internet Protocol packet header [RFC 791]<br /><br /></pre></div><br /><br />This is actual working code. But wait; didn't they just swept the parsing dirt under the rug? The rug here being the code to parse this fine looking tables. Surprisingly, that code is a whopping 27 lines of clean grammar definitions with semantic actions. The "trick", so to speak, is the underlying parsing mojo provided my Piumarta's <a href="http://www.cs.ucla.edu/%7Eawarth/ometa/">OMeta</a> system. Which is, by the way, itself implemented in about 40 lines of OMeta code. Yeah, turtles all the way down and all that stuff...<br /><br />Ok, this is all very cute, but I seem to have fallen on my own trap and can't stop talking about syntax. The next bit of this networking stack is a little more interesting, the problem now is to handle each incoming TCP packet according to a set of specified rules such as "in response to a SYN the server must reply with a SYN-ACK packet". Here is the code:<br /><br /><div style="overflow:auto"><pre><br />['{ svc = &->(svc? [self peek])<br /> syn = &->(syn? [self peek]) . ->(out ack-syn -1 (+ sequenceNumber 1) (+ TCP_ACK TCP_SYN) 0)<br /> req = &->(req? [self peek]) . ->(out ack-psh-fin 0 (+ sequenceNumber datalen (fin-len tcp))<br /> (+ TCP_ACK TCP_PSH TCP_FIN)<br /> (up destinationPort dev ip tcp<br /> (tcp-payload tcp) datalen))<br /> ack = &->(ack? [self peek]) . ->(out ack acknowledgementNumber<br /> (+ sequenceNumber datalen (fin-len tcp))<br /> TCP_ACK 0)<br /> ;<br /> ( svc (syn | req | ack | .) | . ->(out ack-rst acknowledgementNumber<br /> (+ sequenceNumber 1)<br /> (+ TCP_ACK TCP_RST) 0)<br /> ) *<br /> } < [NetworkPseudoInterface tunnel: '"/dev/tun0" from: '"10.0.0.1" to: '"10.0.0.2"]]<br /><br /></pre></div><br /><br />The set of rules above is nothing more than a grammar and the code to construct response packets is implemented as corresponding semantic actions. This snippet is much harder do grok than the pretty tables we just saw, but it's much more interesting as well. The crucial idea is to pattern-match on the stream of incoming packets looking for flag patterns and respond accordingly. What's nice is that they already had a well-honed pattern matching language in OMeta's <a href="http://en.wikipedia.org/wiki/Parsing_expression_grammar">Parsing Expression Grammars</a>. I should note that a powerful parsing engine is not a Golden Hammer, but it is a useful and underutilized computational model. And realizing that is much more significant, IMHO, than the <a href="http://en.wikipedia.org/wiki/Procrustes">procrustean</a> effort of trying to shoehorn "natural language" text into a general purpose programming language.<br /><br /><br /><span style="font-weight: bold;font-size:180%;" >Pierce</span><br />Now let's turn our attention to a different kind of DSL, developed for the Harmony <a href="http://www.seas.upenn.edu/%7Eharmony/">project</a> led by Pierce at UPenn. The problem to solved <a href="http://www.cis.upenn.edu/%7Ebcpierce/papers/lenses-toplas-final.pdf">here</a> is synchronizing bookmark data among different browsers. Seems a far cry from "reinventing computer programming", but there are some intricacies involved, as we shall soon see. The basic approach taken is to transform each browser-specific representation to an abstract view, synchronize the data in this abstract form, and than propagate it back to the concrete form. If you squint hard enough you can see these transformations are a form of the general "view-update problem" known from database literature. Instead of <span id="xhi8"><b id="ny5r">extracting</b></span> a <span id="qi-e"><b id="joqv">view</b></span> from a set of <span id="cl96"><b id="igo8">tables</b></span>, updating it, and <span id="wyv0"><b id="w1wm">propagating</b></span> the changes back to the original tables, they <span id="p8xo"><b id="yd95">get</b></span> an <span id="s-r3"><b id="j6_b">abstract representation</b></span> from a <span id="qkl-"><b id="eg1h">concrete</b></span> one, update it (the synchronization proper), and <span id="wjjd"><b id="m:yb">putback</b></span> the modified data to the original concrete format. So, one concrete input for Mozila would be the following html-ish file:<br /><br /><div style="overflow:auto"><pre><br /><html><br /> <head> <title>Bookmarks</title> </head><br /> <body><br /> <h3>Bookmarks Folder</h3><br /> <dl><br /> <dt> <a href=\"www.google.com\"<br /> add_date=\"1032458036\">Google</a> </dt><br /> <dd><br /> <h3>Conferences Folder</h3><br /> <dl><br /> <dt> <a href=\"www.cs.luc.edu/icfp\"<br /> add_date=\"1032528670\">ICFP</a> </dt><br /> </dl><br /> </dd><br /> </dl><br /> </body><br /></html><br /></pre></div><br /><br />The abstract representation of that data is :<br /><br /><div style="overflow:auto"><pre><br />{name -> Bookmarks Folder<br /> contents -><br /> [{link -> {name -> Google<br /> url -> www.google.com}}<br /> {folder -><br /> {name -> Conferences Folder<br /> contents -><br /> [{link -><br /> {name -> ICFP<br /> url -> www.cs.luc.edu/icfp}}]}}]}<br /></pre></div><br /><br />That's a textual representation of a labeled tree. Each {..} is a tree node, subnodes are identified by a label (i.e. label -> {...} ) and stuff inside square brackets are lists. So, basically we have two tree "schemas" and wish to translate between them. Here is where domain specific languages will come into play. We could naively propose to just whip up a couple of XSLTs and be done with it. The <span id="t29t"><b id="b7_2">get</b></span> direction would be trivial, but the <span id="s85w"><b id="t6fj">putback </b></span>is trickier. Note that the abstract representation lacks information about the add_date of the bookmarks; this is because not all browsers store this data. In a way, the abstract format is a minimal subset of the kinds of data that each browser is interested in. So, the putback of new bookmarks coming from non-Mozilla browsers could just default to some arbitrary date value, but we don't want to lose the data we have for existing bookmarks! This rules-out using a simple stylesheet for the <span id="g663"><b id="ocu8">putback</b></span>.<br /><br />Essentially, this is why the view-update problem is an interesting research question. The relevance to this post is the path Harmony's team chose to solve it, building a bidirectional language*. It's similar to a functional language, but instead of functions they have lenses. A lens is a pair of functions, one for <span id="gmuq"><b id="gvcu">get</b></span> (from the <span id="o9q."><b id="d5om">concrete</b></span> to the <span id="n6ho"><b id="rcxh">abstract</b></span>) and one for <span id="v9ah"><b id="yw_h">putback</b></span>. A <span id="xj6_"><b id="rpgv">putback</b></span> lens takes a modifed <span id="hjzt"><b id="r.84">abstract</b></span> element <span id="j1q8"><u id="pq28">and</u></span> the original <span id="shy5"><b id="tmn0">concrete</b></span> element, mapping to an update <span id="hcur"><b id="n9wb">concrete</b></span> element.<br /><br />Rephrasing more formally, though diverging from the notation used in the paper, a lens <span id="tc56"><b id="w.in">L</b></span> would be a pair of functions <span id="l6xb"><b id="vu_-">(Lg, Lp)</b></span>. Using <span id="jaua"><b id="huu5">A</b></span> as the domain of abstract elements and <span id="dg55"><b id="v5uu">C</b></span> for the domain of the concrete elements, the functions would be defined in:<br /><br /><div id="apvp"><span id="fbsk"><b id="t3-2">Lg: C -> A</b></span><br /><span id="jj2t"><b id="zzvy">Lp: (C x A) -> C</b></span><br /><div id="v_sj" style="text-align: left;"><br />So far we haven't gained much, but the above definitions allow us to express our requirements of "information conservation" as equations:<br /><br /><span id="efp2"><b id="lrjr">Lp(Lg(c), c) = c</b></span> for all <span id="xwte"><b id="lmjy">c</b></span> in <span id="ewwa"><b id="hv1k">C</b></span><br /><span id="p2:7"><b id="mk-d">Lg(Lp(a, c)) = a</b></span> for all <span id="f.x2"><b id="mgeu">a</b></span> in <span id="h924"><b id="sr35">A</b></span> and <span id="hqoq"><b id="zv3z">c</b></span> in <span id="vhgi"><b id="ormi">C</b></span><br /></div></div><br />Any lens obeying this equations can be called "well-formed". To exemplify, here is the identity lens (the arrow pointing up is the get and the opposite is the putback):<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AUV7ymG1mDc/R_sxiVpAJgI/AAAAAAAAABs/53GVJm4rVDo/s1600-h/id_lens.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_AUV7ymG1mDc/R_sxiVpAJgI/AAAAAAAAABs/53GVJm4rVDo/s320/id_lens.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5186793861841692162" /></a><br /><br />Absolutely uninteresting, as to be expected from any identity operation, but note that last line. It is the lens' type signature. Yes, this DSL has a full-blown type system! Take a look at a more interesting example, the map lens, which is analogous to the map function from functional programming:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_AUV7ymG1mDc/R_sx-VpAJhI/AAAAAAAAAB0/37UspwUtgOY/s1600-h/map_lens.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_AUV7ymG1mDc/R_sx-VpAJhI/AAAAAAAAAB0/37UspwUtgOY/s320/map_lens.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5186794342878029330" /></a><br /><br />The behavior isn't complicated, <span id="yb-h"><b id="yau.">map</b></span> is parametrized by another lens <span id="fmx."><b id="vry-">l</b></span>, and just applies it to each subnode in the concrete tree for <span id="o5fg"><b id="n5:.">get</b></span>. In the putback direction, it also just applies the putback for each element in the abstract tree, relying on the assumption that <span id="z2ld"><b id="vkkn">l</b></span> behaves correctly for nodes missing in <span id="i106"><b id="k_s.">c</b></span>. Now look at the scary type signature, which, to be perfectly honest, I don't fully comprehend myself. It is there to assure the well-formedness of map (and a couple of other properties), based on the type of <span id="fous"><b id="gf.f">l</b></span>.<br /><br />Lest I reproduce the entire paper here, and completely butcher it in the process, I'll cut to the final chapter of the story and show the program that maps between Mozilla's bookmark format and the abstract representation:<br /><br /><div style="overflow:auto"><pre><br />link =<br /> hoist *;<br /> hd [];<br /> hoist a;<br /> rename * name;<br /> rename href url;<br /> prune add_date {$today};<br /> wmap {name -> (hd []; hoist PCDATA)}<br /><br />folder = hoist *;<br /> xfork (*h} {name}<br /> (hoist *t;<br /> hd [];<br /> rename dl contents)<br /> wmap {name -> (hoist *;<br /> hd [];<br /> hoist PCDATA)<br /> contents -> (host *;<br /> list_map item)}<br /><br />item =<br /> wmap {dd -> folder, dt -> link};<br /> rename_if_present dd folder;<br /> rename_if_present dt link<br /><br />bookmarks =<br /> hoist html;<br /> hoist *l<br /> tl {|head --> {| * --> [ {|title --> {|* --><br /> [{|PCDATA --> Bookmarks|}]|}|}]|}|};<br /> hd [];<br /> hoist body;<br /> folder<br /></pre></div><br /><br />I'm afraid I'm unable to explain much of this program without going deeper than is appropriate here. But see how much is accomplished in probably fewer lines of code than would be required for expressing a mere transformation in XSLT . And of course, the whole bookmark synchronization thing is just a toy problem; the resulting system is powerful enough to tackle larger beasts. See the other papers in the project website, where they apply lenses to the traditional relational view-update problem, to character Strings and to data replication in distributed settings.<br /><br /><br /><span style="font-size:180%;"><span style="font-weight: bold;">Wrapping up</span></span><br /><ul><li>DSL design is language design, and that involves more than just syntax.</li><li>Sometimes an well-known computational model can be repurposed to fit domain requirements, like Kay and Piumarta did adopting a grammar parsing engine to process a packet stream.</li><li>Automata and similar non-turing-complete models can be very useful in Domain Specific Languages.<br /></li><li>Sometimes it pays to develop whole new semantics for your DSL.</li><li>Of course there is little that is actually "wholly new" in the world. Taking Harmony's semantics for example, the team did apply a lot of <a href="http://en.wikipedia.org/wiki/Domain_theory">domain theory</a> to prove the totality of their lens combinators.<br /></li><li>If you can identify invariants that are hard to get right, it may pay to express them in a type system. But be warned that this is no child's play; even Pierce didn't go all the way to building a typechecker for his lenses.<br /></li><li>Have fun!</li></ul><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-7236747902856747883?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com5tag:blogger.com,1999:blog-10162639.post-20620802917908329182007-12-14T07:14:00.000-02:002007-12-14T07:17:47.258-02:00Semantic RamblingsThis past Tuesday I attended a talk about the Semantic Web and social networks by Sun's <a href="http://blogs.sun.com/bblfish">Henry Story</a>. I've <a href="http://blogs.sun.com/rafaelferreira/entry/bblfish_at_usp">posted</a> my impressions, mixed with some uninformed commentary about semweb in general, on my work blog.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-2062080291790832918?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-48407038626822425822007-12-09T23:19:00.000-02:002007-12-10T00:33:32.723-02:00REST Beyond the Obvious<div id="lqt5" style="padding: 1em 0pt; text-align: center;"><a href="http://flickr.com/photos/andresv/378372229/"><img style="width: 500px; height: 375px;" src="http://docs.google.com/File?id=dd34rvt4_34gr8q45dt" /></a></div> <p style="margin-bottom: 0in;">Now that the heat of the REST vs. SOA battle seems to be dissipating, we can try to shed some light into how the choice of a resource centric design affects overall enterprise architecture. We can start by following a thought experiment. Imagine a company growing so fast the HR staff is overwhelmed by the task of forwarding all the new job openings to recruiting agencies. Our job is to automate this problem away. Using REST.</p><p style="margin-bottom: 0in;"><br /></p> <h3>The basics<br /></h3> <p style="margin-bottom: 0in;">As RESTful Web Services go, this one seems pretty simple. One resource per job opening, represented with a simple custom XML format; maybe a collection resource, listing all current openings; and possibly also a search resource, to look for openings with specific attributes. Something like this:</p><br /><div style="margin-left: 5%; margin-right: 5%;"><table style="border-color: rgb(255, 102, 0);" border="1" cellspacing="0" width="87%"> <col width="100*"> <col width="24*"> <col width="132*"> <thead> <tr valign="top"> <th width="39%"> <span style="font-size:85%;">URI Template</span> </th> <th width="9%"> <span style="font-size:85%;">Method</span> </th> <th width="52%"> <span style="font-size:85%;">Representation</span> </th> </tr> </thead> <tbody> <tr valign="top"> <td width="39%"> <span style="font-size:85%;">/job_opening/{id}</span> </td> <td width="9%"> <span style="font-size:85%;">GET</span> </td> <td width="52%"> <span style="font-size:85%;">Job Opening XML <a title="Schema" href="http://relaxng.org/" id="ufqq">Schema</a></span> </td> </tr> <tr valign="top"> <td width="39%"> <span style="font-size:85%;">/job_openings</span> </td> <td width="9%"> <span style="font-size:85%;">GET</span></td> <td width="52%"> <span style="font-size:85%;">Links to all openings as a custom schema or with <a title="XOXO" href="http://microformats.org/wiki/xoxo" id="a9yd">XOXO</a>.</span> </td> </tr> <tr> <td width="39%"><span style="font-size:85%;">/job_openings/find?{query_params}</span> </td> <td width="9%"><span style="font-size:85%;">GET</span></td> <td width="52%"><span style="font-size:85%;">Custom schema or XOXO or atom feed, all w/ <a title="Opensearch" href="http://www.opensearch.org/" id="uhzj">Opensearch</a> elements.</span> </td> </tr> </tbody></table></div> <p style="margin-bottom: 0in;">So, how do we create the job opening resources? The obvious choice would be to apply the traditional RESTful <a title="collections pattern" href="http://bitworking.org/news/restful_json" id="qc6-">collections pattern</a>: a POST to the /job_openings collection with an entity body containing the xml representation of the opening triggers the creation of a new resource, whose URL would then be returned in the <a title="RFC 2616 - Sec 14.30 - Location Header" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30" id="wy43">location</a> header of the response.<br /></p><p style="margin-bottom: 0in;"><br /></p> <h3>Shaking things up<br /></h3><p style="margin-bottom: 0in;">But there is an alternate model: let client departments simply publish job_opening resources by themselves, on their departmental web servers. There is a vast array of options to do such a thing, none of them requiring users to write XML, of course. IT could whip up a word processor macro to convert documents to our xml format, and save them to a web server. In the MsWorld, one could use Word's XML <a title="support" href="http://blog.jonudell.net/2007/02/05/a-conversation-with-brian-jones-about-office-and-xml/" id="um1m">support</a> for inserting elements from the job_opening namespace into a document and publish it to an WebDav enabled server, maybe using Sharepoint. In the OpenOffice universe, we could just as easily save a document as <a title="OASIS OpenDocument/ISO/IEC 26300" href="http://xml.openoffice.org/" id="yax-">ODF</a>, pass it trough an xml transformation to the job_opening format, and then publish it to an Web Server. The publishing itself can be made with a number of techniques, from FTPing to a shared directory to using an Atompub client with a <a title="mod_atom: an open source project driven by Tim Bray" href="http://www.google.com/search?as_q=mod_atom&as_sitesearch=tbray.org" id="rh-n">compatible server</a> to the aforementioned WebDav protocol. A completely different, and much more complex, option would be to have the department run an instance of a custom job openings application, maybe even something similar to the “obvious choice” outlined above, but I really don't see how it could be useful.</p> <p style="margin-bottom: 0in;"><a id="x7r5" href="http://flickr.com/photos/josefstuefer/9500503/" target="_blank"><img style="margin: 1em 1em 0pt 0pt; width: 240px; height: 240px; float: left;" src="http://docs.google.com/File?id=dd34rvt4_35hhzngndm" /></a>So far, all very cute and distributed, postmodern even, but does it work? I mean, the end goal is to send all the openings info to external recruiting companies, and just throwing the resources at the internal web doesn't quite accomplish that. The missing piece of the puzzle is a simple crawler; a small piece of software that scans the web by following links and looks for resources that <a title="RFC 2616 - Sec 14.1 - Accept header" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1" id="n_z3">accept</a> being viewed as job_openings. A side effect of most publishing options mentioned in the past paragraph is that a link is created to the newly available document in some sort of listing. Our crawler needs only to know how to get at those listings and how to parse them looking for links. If you think parsing is complicated, I urge you to think about the following code snippet: /(src|href)="(.*?)"/</p><br /><p style="margin-bottom: 0in;"><br /></p><p style="margin-bottom: 0in;"><br /></p> <h3>What If...<br /></h3> <p style="margin-bottom: 0in;">Since this is a thought experiment, we can get more, well, experimental. Let's see what could be gained from shunning XML altogether and using an HTML <a title="microformat" href="http://microformats.org/" id="x_o.">microformat</a> for the job_opening resource representations. This would expand even more the publishing options. For instance, a plain Wordpress blog, maybe already used as a bulletin board of sorts by some department, could be repurposed as a recruiting server. Another benefit would be to have every document in the system in human-readable form, not XML “human-readable”, but really human-readable. </p> <p style="margin-bottom: 0in;">Now, suppose the company decided it just wasn't growing fast enough, went ahead and bought a smaller competitor. And of course, this competitor already had an in-house recruiting application. Being of a more conservative nature, which just might explain why they weren't market leaders, their IT department built it as a traditional Web front-ed / RDBMS backed application. How do we integrate that with our REST-to-the-bone job openings system? First we note that there is no need to have the data available in real-time, after all, no company needs to hire new people by the minute. Given that, the simplest solution would probably be a periodic process (someone said cron?) that extracts the data directly from the database, transforms it to our job_opening format and shoves it in some web server. </p><br /><br /><h3>So what?<br /></h3> <p style="margin-bottom: 0in;">I can't say if this scenario were for real would I choose such a distributed approach. Maybe a quick Rails app running on a single server would better fit the bill. But that's not the point of our little exercise in architectural astronautics, we are here to think about the effects of REST's constraints to overall architecture. So, let's recap some of them:<a href="http://flickr.com/photos/rafaeldff/2098699545/"><img id="l1vb" style="margin: 1em 0pt 0pt 1em; width: 200px; height: 240px; float: right;" src="http://docs.google.com/File?id=dd34rvt4_31hqbsf6g7" /></a></p> <ul> <li><p style="margin-bottom: 0in;">The line between <i>publishing content</i> and <i>using an application</i> blurs. “Static” documents and active programs have equal footing as members of the system.<br /></p> </li><li><p style="margin-bottom: 0in;">Thanks to the uniform interface constraint, the mere definition of a data format allows for unplanned integration.</p> </li><li><p style="margin-bottom: 0in;">If we add a standard media type to the mix, we can take advantage of established infrastructure, as in the case of a blogging platform reused as a “service endpoint” simply by adoption of HTML microformats.</p> </li><li><p style="margin-bottom: 0in;">REST in HTTP encourages <a title="Excellent piece by Sean McGrath" href="http://www.itworld.com/AppDev/nlsebusiness070410/" id="tidb">pull-based architectures</a> (think of our HR crawler), which aren't all that common outside of, well, HTTP web applications</p> </li><li><p style="margin-bottom: 0in;">The very idea of a service may fade away in a network of distributed connected resources. The closest thing to a <i>service</i> in our system is the crawler, but note that it does its work autonomously, no one ever actually <i>calls</i> the service.</p></li><li>Links (aka <a title="hypermidia" href="http://www.ics.uci.edu/%7Efielding/pubs/dissertation/rest_arch_style.htm" id="g7vn">hypermidia</a>) are a crucial enabler for loosely-coupled distributed services. In some sense, everything is a <a title="service registry" href="http://www.looselycoupled.com/stories/2005/registry-infr0131.html" id="smfu">service registry</a>. </li><li><p style="margin-bottom: 0in;">One of the forgotten buzzwords of the 90's, intranet, may come to have a new meaning.</p> </li></ul><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-4840703862682242582?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com2tag:blogger.com,1999:blog-10162639.post-79032657577176464542007-12-02T22:38:00.000-02:002007-12-04T02:32:46.565-02:00Metaprogramming and conjuring spells<div style="text-align: right;"><span style="font-style: italic;">"A computational process is indeed much like a sorcerer's idea of a spirit. It cannot be seen or touched. It is not composed of matter at all. However, it is very real. It can perform intellectual work. It can answer questions. It can affect the world by disbursing money at a bank or by controlling a robot arm in a factory. The programs we use to conjure processes are like a sorcerer's spells. They are carefully composed from symbolic expressions in arcane and esoteric </span><em style="font-style: italic;">programming languages</em><span style="font-style: italic;"> that prescribe the tasks we want our processes to perform."</span><br />- Abelson and Sussman — <a href="http://mitpress.mit.edu/sicp/full-text/sicp/book/node4.html">SICP</a></div><br /><br />Among the plethora of metaphors that plague our field, I find computing as incantation of spells one of the least annoying. Some <a href="http://images.google.com/images?q=James+Gosling">fellow</a> <a href="http://images.google.com/images?q=jim+gray">with</a> <a href="http://research.microsoft.com/users/lamport/">a</a> <a href="http://images.google.com/images?q=Richard+Stallman">long</a> <a href="http://homepages.cs.ncl.ac.uk/brian.randell/NATO/N1968/DIJKSTRA.html">beard</a> writes odd-looking prose that will later, through some magical process, turn <a href="http://en.wikipedia.org/wiki/Dot_com_bubble">lead into gold</a> or help vanquish some inept demon. Man, that <a href="http://en.wikipedia.org/wiki/Charmed">show</a> sucked, I don't know why anyone would watch that shit, specially the reruns Tuesday to Saturday at 04AM and Monday to Friday at 12PM on channel 49. Well, anyway, what's interesting about the analogy is that it shows the dual nature of software: it is both a magical process and a bunch of scribbled lines. To mix metaphors a bit, we can say that software is, at the same time, a machine and the specification for that machine.<br /><br />This is what makes metaprogramming possible and, also, what makes it unnecessary. By the way, when I write "metaprogramming", I'm specifically thinking about mutable meta-structures, <span style="font-style: italic;">changing the tires while the car is running metaprogramming</span>, not mere introspection. Throwing away that mundane car analogy and getting back to our wizardry metaphor, metaprogramming would be like a spell that modifies itself while being casted. This begs the question, beyond fodder for bad TV Show scripts, what would this be useful for? My answer: for very little, because if the <del>wizard </del>programmer already has all the information needed for the metaprogram, then he might as well just program it... To make this a little less abstract, take a simple example of Ruby metaprogramming:<br /><pre>01 class DrunkenActress<br />02 attr_writer :blood_alcohol_level<br />03 end<br />04<br />05 shannen_doherty = DrunkenActress.new<br />06 shannen_doherty.blood_alcohol_level = 0.13<br /></pre>By the way, I'm not a Rubyist, so please let me know if the example above is wrong. The only line with meta-stuff is line 2, where a method named "attr_writer" is being called with an argument of :blood_alcohol_level. This call will change the DrunkenActress class definition to add accessor methods for the blood_alcohol_level attribute. We can see that it worked in line 6, where we call the newly defined setter.<br /><br />But the programmer obviously already knows that the DunkenActress class needs to define a blood_alcohol_level attribute, so we see that meta-stuff is only applied here to save a few keystrokes. And that is not a bad motivation in itself, more concise code often is easier to understand. Then again, there are other ways to eliminate this kind of boilerplate without recursing to runtime metaprogramming, such as macros or even built-in support for common idioms (in this case, properties support like C# or Scala).<br /><br />There may be instances where the cleanest way to react to information available only in runtime is trough some metaprogramming facility, but I have yet to encounter them. Coming back to Rubyland, Active Record is often touted as a poster child for runtime metaprogramming, as it extracts metadata from the database to represent table columns as attributes in a class. But those attributes will be accessed by code that some programmer will write — and that means, again, that the information consumed by the metaprogram will need to be available in development time. And indeed it is, in the database. So ActiveRecord metaprogramming facilities are just means to delegate the definition of some static structure to an external store, with no real dynamicity involved. If it were not so, this <a href="http://blogs.sun.com/tor/entry/ruby_screenshot_of_the_week20">kind of thing</a> would be impossible. Also note that recent Rails projects probably use Migrations to specify schema info in yet another static format.<br /><br />To summarize, runtime mutable metaprogramming is like that bad purple translucent special effect, it is flashy, but ultimately useless. Anyway, that's my current thinking in the matter, but I still need to read more on <a href="http://www.citeulike.org/tag/staging">staging</a>.<br /><br /><span style="font-style: italic;">[EDIT: corrected a mistake relating to the code sample]</span><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-7903265757717646454?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-1111702829112723212007-11-29T19:06:00.000-02:002007-11-29T19:10:01.813-02:00JSR-311 at USPI gave a talk about RESTful Web Services and JSR-311 at our local USPJUG meeting, the slides are available <a href="http://blogs.sun.com/rafaelferreira/entry/rest_demo">here</a> (in portuguese).<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-111170282911272321?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com2tag:blogger.com,1999:blog-10162639.post-87075316812342549852007-11-14T22:03:00.000-02:002007-11-14T22:06:18.680-02:00Event "Conexão Java 2007"This past week I've attended an event called Conexão Java. I've posted my notes <a href="http://blogs.sun.com/rafaelferreira/entry/cj2007">on the other blog</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-8707531681234254985?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com1tag:blogger.com,1999:blog-10162639.post-80591647686284090062007-10-15T16:51:00.000-02:002007-10-15T16:55:23.015-02:00Link-blogI've setup an alternate feed that splices my <a href="http://del.icio.us/rafaeldff">bookmarks</a> from <a href="http://del.icio.us/">del.icio.us</a> with this blog's entries. You can find it <a href="http://feeds.feedburner.com/RafaelRamblingAndLinks">here</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-8059164768628409006?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com1tag:blogger.com,1999:blog-10162639.post-14144358473787379732007-10-13T21:58:00.000-03:002007-10-15T00:25:14.544-02:00Pondering<blockquote style="font-style: italic;">"Formal methods will never have any impact until they can be used by people that don’t understand them."</blockquote><div style="text-align: right;">Tom Melham<br /></div><br /><br /><blockquote style="font-style: italic;">"The original study that showed huge variations in individual programming productivity was conducted in the late 1960s by Sackman, Erikson and Grant (1968). They studied professional programmers with an average of 7 years' experience and found that the ratio of initial coding time between the best and worst programmers was about 20 to 1, the ration of debugging times over 25 to 1, of program size 5 to 1, and of program execution speed about 10 to 1. They found no relationship between a programmer's amount of experience and code quality or productivity.<br /><br />Although specific rations such as 25 to 1 aren't particularly meaningful , more general statements such as "There are order-of-magnitude differences among programmers'" are meaningful and have been confirmed by many other studies of professional programmers (Curtis 1981, Mills 1983, DeMarco and Lister 1985, Curtis et al. 1986, Card 1987, Boehm and Papaccio 1988, Valett and McGarry 1989, Boehm et al. 2000)."<br /></blockquote><div style="text-align: right;">Steve McConnell<br /><a href="http://www.amazon.com/gp/product/0735619670?ie=UTF8&tag=rafaeldivagan-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0735619670">Code Complete, Second Edition</a><img src="http://www.assoc-amazon.com/e/ir?t=rafaeldivagan-20&l=as2&o=1&a=0735619670" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" /></div><br /><br /><blockquote style="font-style: italic;">"If you look at the way software gets written in most organizations, it's almost as if they were deliberately trying to do things wrong. In a sense, they are. One of the defining qualities of organizations since there have been such a thing is to treat individuals as interchangeable parts. This works well for more parallelizable tasks, like fighting wars. For most of history a well-drilled army of professional soldiers could be counted on to beat an army of individual warriors, no matter how valorous. But having ideas is not very parallelizable. And that's what programs are: ideas."<br /></blockquote><div style="text-align: right;">Paul Graham<br /><a href="http://www.paulgraham.com/head.html">Holding a Program in One's Head</a><br /></div><br /><br /><blockquote style="font-style: italic;">"Software entities are more complex for their size than perhaps any other human construct because no two parts are alike (at least above the statement level). If they are, we make the two similar parts into a subroutine--open or closed. In this respect, software systems differ profoundly from computers, buildings, or automobiles, where repeated elements abound. [...]<br /><br />The complexity of software is an essential property, not an accidental one. Hence, descriptions of a software entity that abstract away its complexity often abstract away its essence. For three centuries, mathematics and the physical sciences made great strides by constructing simplified models of complex phenomena, deriving properties from the models, and verifying those properties by experiment. This paradigm worked because the complexities ignored in the models were not the essential properties of the phenomena. It does not work when the complexities are the essence."</blockquote><div style="text-align: right;">Fred Brooks<br /><a href="http://scholar.google.com/scholar?hl=en&lr=&safe=off&cluster=9642008317513099198">No Silver Bullet</a><br /></div><br /><br /><blockquote style="font-style: italic;">"Architecture is intended to be facilitative, of course, in that a good architecture should enable developers to build applications quickly and easily, without having to spend significant amounts of time re-inventing similar infrastructure across multiple projects. [...]<br /><br />But an architecture is also intended to be restrictive, in that it should channel software developers in a direction that leads to all of these successes, and away from potential decisions that would lead to problems later. In other words, as Microsoft's CLR architect Rico Mariani put it, a good architecture should enable developers to "fall into the pit of success", where if you just (to quote the proverbial surfer) "go with the flow", you make decisions that lead to all of those good qualities we just discussed. "</blockquote><div style="text-align: right;">Ted Neward<br /><a href="http://blogs.tedneward.com/2007/09/20/Hard+Questions+About+Architects.aspx">Hard Questions About Architects</a><br /></div><br /><br /><span style="font-style: italic;"><blockquote>"The more interesting your types get, the less fun it is to write them down!"<br /></blockquote></span><div style="text-align: right;">Benjamin C. Pierce<br /><a href="http://www.cis.upenn.edu/%7Ebcpierce/papers/tng-lics2003-slides.pdf">Types and Programming Languages - The Next Generation</a><br /></div><br /><br /><blockquote><span style="font-style: italic;">"If you don’t know the difference between a group, a ring, and a field, you have no business overloading operators. </span> <p style="font-style: italic;">Now I’m not saying that one has to take a course in abstract algebra before you can be a competent programmer. You don’t as long as the language you program in doesn’t support operator overloading (or as long as you’re wise enough not to use it if it does). However since most programmers are didn’t get beyond ODEs in college (if indeed they got that far–some of my comp sci friends struggled mightily with calculus and had to retake it repeatedly), one can’t responsibly design a language that requires mathematical sophistication in the 99th percentile for proper use."</p></blockquote><p style="font-style: italic;"></p><p style="text-align: right;">Elliotte Rusty Harold<br /><a href="http://cafe.elharo.com/java/operator-overloading/">Operator Overloading: Trickier Than it Looks</a></p><br /><br /><blockquote style="font-style: italic;">"You used to start out in college with a course in data structures, with linked lists and hash tables and whatnot, with extensive use of pointers. Those courses were often used as weedout courses: they were so hard that anyone that couldn't handle the mental challenge of a CS degree would give up, which was a good thing, because if you thought pointers are hard, wait until you try to prove things about fixed point theory.<br /><br />All the kids who did great in high school writing pong games in BASIC for their Apple II would get to college, take CompSci 101, a data structures course, and when they hit the pointers business their brains would just totally explode, and the next thing you knew, they were majoring in Political Science because law school seemed like a better idea. I've seen all kinds of figures for drop-out rates in CS and they're usually between 40% and 70%. The universities tend to see this as a waste; I think it's just a necessary culling of the people who aren't going to be happy or successful in programming careers."<br /></blockquote><div style="text-align: right;">Joel Spolsky<br /><a href="http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html">The Perils of JavaSchools</a><br /></div><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-1414435847378737973?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-71229068800266843542007-10-06T03:50:00.000-03:002008-12-11T16:55:05.313-02:00Four booksAnother blog post, still no inspiration for anything creative, so lets just rehash that old bloggers' recipe of stuffing some "cultural" reviews in a post and hope it passes for content. Excited yet?<br /><br /><h4>Concepts, Techniques, and Models of Computer Programming</h4><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.com/gp/product/0262220695?ie=UTF8&tag=rafaeldivagan-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0262220695"><br /><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://1.bp.blogspot.com/_AUV7ymG1mDc/RwBevHMW4pI/AAAAAAAAAAs/sD_xJ2ZPYow/s320/2108ZG1TTPL._AA_SL160_.jpg" alt="" id="BLOGGER_PHOTO_ID_5116193340170625682" border="0" /></a><img src="http://www.assoc-amazon.com/e/ir?t=rafaeldivagan-20&l=as2&o=1&a=0262220695" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" />First up is Peter Van Roy's "Concepts, Techniques, and Models of Computer Programming". Don't let that big title scare you away. The book is pretty hefty in itself, but don't let that scare you either, it is a great read. But what is it about, you may ask? Well, CTM - as it is affectionately called - could sit comfortably on the "programming paradigms" shelf, alongside Sebesta and Kamin. All books that aim to take the reader through a stroll down the computing Zoo, allowing him or her to gaze in awe of the strength of higher order functions, be amused by the quirkiness of dataflow variables, marvel at the elegant logical predicates lying under a sunny...<br /><br />Ok, I took the metaphor too far, sorry about that. What I was trying to say is that CTM doesn't limit itself to enumerate paradigms accompanying each with a brief description and a couple of examples and leaving it at that. Van Roy's text goes further by discussing in reasonable depth programming techniques applicable to each <span style="font-style: italic;">computation model </span>(the authors prefer to avoid the term "paradigm") and, more that that, advising the reader on how to best integrate them.<br /><br />The technical approach that enables this leveling is to describe the models in terms of a <span style="font-style: italic;">kernel language</span> that is expanded throughout the book. Each chapter shows how the kernel language needs to be augmented to support the required features, how it is interpreted by an <span style="font-style: italic;">abstract machine</span> and what syntactic sugar can be added on top of the kernel to ease programming.<br /><br />It would not be a fair review if I didn't relate at least one negative point, but it is a minor one. I think that the approach to logic/relational programming would be more representative of the usual intent if the language was more predicate-and-fact based. Or, to put it in other words, I like the Prolog syntax better than the "Relational Oz" one. As the authors explain, both approaches are semantically equivalent in their core, so I'm nitpicking. Overall, I can safely say that I recommend this book. It is, if you pardon the cliché, an eye-opener, making it clear that the "mainstream" imperative and stateful programming model is but one of many equally significant alternatives.<br /><br /><h4>Engines of Logic</h4><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.com/gp/product/0393322297?ie=UTF8&tag=rafaeldivagan-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0393322297"><br /><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://4.bp.blogspot.com/_AUV7ymG1mDc/Rwg1d3MW4qI/AAAAAAAAAA0/tQkml2xCtCQ/s320/21JKCXP8WVL._AA_SL160_.jpg" alt="" id="BLOGGER_PHOTO_ID_5118399763654828706" border="0" /></a><img src="http://www.assoc-amazon.com/e/ir?t=rafaeldivagan-20&l=as2&o=1&a=0393322297" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" />If you've ever been subject to any formal instruction in computing (or "informatics" or Information Systems or whatever), you probably had to endure at least one lecture on the "history of computing", which usually amounts to a lengthy enumeration of machines. If you were particularly unlucky, it started with some blabber about the abacus back in who-the-fuck-cares AD, and it invariably went on to spend a great deal of time discussing punched cards and looms. Yeah, freaking looms! I'm sure Joseph Marie Jacquard is a swell guy and all, but is a rudimentary mechanical input system all that important in the grand scheme of things? My answer, of course, is no. As Dijkstra put it: "Computer science is as much about computers as astronomy is about telescopes". And that is why Engines of Logic is such a great little book, it seeks to give an account of the history of ideas that culminated in modern computing.<br /><br />We see how Leibnitz' utopia of a machine to automate human reasoning, up to the point of forever settling all disputes and intellectual arguments, evolved to a series of formal mathematical systems for "calculating with thoughts" (mathematical logic) by the hand of such great man as Boole, Frege, Cantor, Gödel, and others, culminating with the notion of "universal computers" and their actual realization. The book reads like a good popular science work, with amusing biographical anecdotes scattered throughout the nine chapters. Although, contrary to many works in this genre, Engines of Logic is not afraid of stating formulas and proving theorems when when deeper insight is required*. Check out a small excerpt from the chapter on David Hilbert for a sample of the lighter side of the book:<br /><span style="font-style: italic;"><blockquote>During my own graduate student days in the late 1940s, anecdotes about Göttingen in the 1920s were still being repeated from one generation of students to the next. We heard about the endless cruel pranks that Carl Ludwig Siegel played on on the hapless Bessel-Hagen, who remained ever gullible. My own favorite story was about the time that Hilbert was seen day after day in torn trousers, a source of embarrassment to many. The task of tactfully informing Hilbert of the situation was delegated to his assistant, Richard Courant. Knowing the pleasure Hilbert took in strolls in the countryside while talking mathematics, Courant invited him for a walk. Courant managed matters so that the pair walked through some thorny bushes, at which point Courant informed Hilbert that he had evidently torn his pants on one of the bushes. "Oh no," Hilbert replied, "they've been that way for weeks, but nobody notices".</blockquote></span>Also of note in the paragraph I quoted is the personal touch given at times by the author, Martin Davis. He is a theoretical computer scientist, with the distinction of being present in Princeton back in the 1950s, in the companion of chaps like John Von Neumann, Kurt Gödel, Hermann Weyl and Albert Einstein. As an author, Davis is probably best known for writing more technical books on computability and complexity. But please, make no mistake, this is emphatically not an academic textbook; it goes to great pains to clearly explain subtle concepts like Cantor's diagonal method, achieving a balance between rigor and ease that is hard to come by**.<br /><br /><h4>1984</h4><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.com/gp/product/0151010269?ie=UTF8&tag=rafaeldivagan-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0151010269"><br /><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://3.bp.blogspot.com/_AUV7ymG1mDc/RwhFLnMW4rI/AAAAAAAAAA8/D6u_-V_8XM4/s320/11KNYJ5S45L._AA_SL160_.jpg" alt="" id="BLOGGER_PHOTO_ID_5118417042308260530" border="0" /></a><img src="http://www.assoc-amazon.com/e/ir?t=rafaeldivagan-20&l=as2&o=1&a=0151010269" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" />It is sad that I only got around to reading this book now. "Now" meaning late 2006, as these reviews are a little bit behind schedule... Anyway, as I'm having a hard time finding worthy adjectives, I guess something I could say is that after finishing 1984 I felt utterly stunned. It is powerful and it is important, so put it on your reading list if you haven't already.<br /><br />A final observation is that the edition I'm linking to - a combined printing of Animal Farm and 1984 published by Harcourt - is cheap and pretty good. The preface is signed by Christopher Hitchens.<br /><br /><h4>Snow Crash</h4><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.com/gp/product/0553380958?ie=UTF8&tag=rafaeldivagan-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0553380958"><br /><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://2.bp.blogspot.com/_AUV7ymG1mDc/RwhH8XMW4sI/AAAAAAAAABE/ndBCkukG7xo/s320/21BD5J2MB5L._AA_SL160_.jpg" alt="" id="BLOGGER_PHOTO_ID_5118420078850138818" border="0" /></a><img src="http://www.assoc-amazon.com/e/ir?t=rafaeldivagan-20&l=as2&o=1&a=0553380958" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" />I'm getting lazy (well, lazier) so this will be short: good book, so-so plot, so-so characters, awesome ambiance.<br /><br /><br /><br /><br /><br /><br /><br /><br /><br />* To be fair, some of the most tricky proofs for non-crucial topics are left to end notes. Still, those notes are far easier to read than most academic mathematical tomes.<br />** Off the top of my head, I can only think of Nagel and Newman's book on Gödel's proof.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-7122906880026684354?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-16131951095547271082007-09-03T03:14:00.000-03:002007-09-03T03:35:24.212-03:00Concurrency and the demand for computingOn my previous post I expressed some doubt with the “market” for rich internet applications. The skepticism was rooted on an observation that the demand side of the equation isn't looking so promising: what applications will emerge benefiting from those wonderful technologies?<br /><br />I find myself thinking along similar lines with regard to concurrency. For the sake of analysis, lets split the space of applications in server-based and client-based. Members of the first group basically deal with responding to requests coming over the network. This means that there is a naturally high degree of parallelism and, of course, this has been exploited for a long time. The typical scenario is some serial business application code atop a middleware platform that handles threading and I/O. This means that on the server front, the “multicore revolution” will impact little on most software development efforts. Now, desktop software developers don't have such luck – the era of surfing on Moore's Law is really over. And so what? The way I see it,* raw computing has ceased to be an important bottleneck, long gone are the days of watching a crude hourglass animation while the CPU labored away. Not that we do any less waiting by now, these days we spend our time waiting for the network.<br /><br />Anyway, maybe the concurrency boogieman is less scary than we think.<br /><br /><br />*(this is a blog, after all)<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-1613195109554727108?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com3tag:blogger.com,1999:blog-10162639.post-37954260015803618992007-08-27T14:33:00.000-03:002007-08-27T17:09:37.413-03:00The Wealth of SoftwareOne of the hot topics in 2007, much like it was in <a href="http://www.google.com/archivesearch?q=%22thin+client%22&btnG=Search+Archives&as_ldate=1997&as_hdate=1997">1997</a>, is the rich versus thin client issue: will the future of software lay purely on the cloud, or will rich fat desktop apps suffer a revival? This old debate was rekindled earlier this year by the announcements of Adobe AIR, Microsoft Silverlight and Sun JavaFX; all fighting for the so-called Rich Internet Apps (RIA) market. I guess the neologism is marginally better that the previous buzzword, AJAX, which still makes me cringe a little bit. In fact, I blame Jesse James Garrett for the worsening of my case of <a href="http://en.wikipedia.org/wiki/Bruxism">bruxism</a>, but I'm digressing...<br /><br />What brought me to this weary debate is the historical perspective brought by Herb Sutter in <a href="http://herbsutter.spaces.live.com/blog/cns%212D4327CC297151BB%21266.entry">this </a>recent post. He argued that we are seeing a manifestation of a cycle where computing moves periodically between the center and the edges, a movement driven by an imbalance between resources:<br /><blockquote style="font-style: italic;">"More specifically, it's the industry constantly rebalancing the mix of several key technology factors, notably: <ul><li><strong>computation</strong> capacity available on the edge (from motes and phones through to laptops and desktops) and in the center (from small and large servers through to local and global datacenters) </li><li><strong>communication</strong> bandwidth, latency, cost, availability, and reliability"</li></ul></blockquote>While this seems reasonable enough, I think there is an element missing: he scarcely mentions the role of the applications that run on those systems. The article presents a purely supply-side analysis of the computing marketplace, to put it in "economic" terms. To illustrate the importance of the demand-side, I expanded Herb's chronology table with important application classes of each epoch:<br /><table class="MsoNormalTable" style="" border="0" cellpadding="0" cellspacing="5"> <tbody><tr style=""> <td style="padding: 3.75pt;" valign="top"> <p><strong><span style="color:navy;">Era/Epoch</span></strong> <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><strong><span style="color:navy;">The Center</span></strong> <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><strong><span style="color:navy;">The Edge</span></strong> <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><strong><span style="color:navy;">Apps<o:p></o:p></span></strong></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Precambrian <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p>ENIAC <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Military calculations.<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Cambrian <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p>Walk-up mainframes <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Huge business batch processing.<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Devonian <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>Terminals and time-sharing <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Big business batch processing<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Permian <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>Minicomputers <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Scientific computation, maybe? I don’t know…<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Triassic <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>Microcomputers, personal computers <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Spreadsheets, desktop publishing.<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Jurassic <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>File and print servers <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Departmental or Small-Business DB apps. (think video rental service software)<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Cretaceous <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p>Client/Server, server tier <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p>Client/Server, middle tier <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">OLTP (for instance, bank account management)<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Paleocene <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>PDA <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">PIM<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Eocene <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p>Web servers <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Web portals (Yahoo!, Excite!, …)<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Oligocene <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>ActiveX, JavaScript<br />PDA phone <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Web based apps. (Hotmail, many ASP/JSP/PHP db apps).<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Miocene <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p>E-tailers <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">?<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Pliocene <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>Flash, <st1:city st="on"><st1:place st="on">AJAX</st1:place></st1:city> <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Fancy web apps (Flickr, Google Maps)<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Pleistocene <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p>Web services<br />Data centers <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Google Data, DabbleDB?<o:p></o:p></b></p> </td> </tr> <tr style=""> <td style="padding: 3.75pt;" valign="top"> <p>Holocene <o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p><o:p> </o:p></p> <br /></td> <td style="padding: 3.75pt;" valign="top"> <p>Google Gears<br />Adobe AIR<br />Silverlight<o:p></o:p></p> </td> <td style="padding: 3.75pt;" valign="top"> <p><b style="">Now what?<o:p></o:p></b></p> </td> </tr> </tbody></table><br />Now, what do we fill in that last cell? What are the killer apps of the RIA platforms? There is no clear answer, but I see basically two niches that can be a good fit for the space: apps that handle audiovisual media (<a href="http://www.youtube.com/">youtube</a>, <a href="http://www.picnik.com/">picnik</a>, etc.) and apps that require rich modes of interaction (<a href="http://earth.google.com/">Google Earth</a>). Its important to bear in mind that media intensive operations are expensive all around, from server storage space to quality digital video cameras for the users. Also, in many cases AJAXian alternatives exist (see <a href="http://pixenate.com/">PX8N</a> or any other Web2.0 reflective-logoed startup in techcrunch). Regarding the other niche, applications using novel user interaction features, it seems cool in theory, but apart from a handful of HCI journals there is very little action in this space nowadays. And that's probably good, because most attempts at UI innovation fall flat on the user's faces, as DHH eloquently argues in <a href="http://www.hanselman.com/blog/HanselminutesPodcast65MartinFowlerAndDavidHeinemeierHansson.aspx">this</a> podcast. All in all, skepticism is healthy as usual, but I don't see the door closed shut to a richer software landscape.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-3795426001580361899?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-2331141182058689762007-08-19T01:53:00.000-03:002007-08-19T02:11:04.873-03:00Administrivia<ul><li>I realized there is no point in keeping the blog bilingual, so from now on all posts will be in English. I may, some day, open another portuguese-only blog, but not anytime soon (I can barely post here more than once a month)</li><li>But I do have another blog. I should have announced this a while ago, but better late then never, I guess. It is at <a href="http://blogs.sun.com/rafaelferreira">http://blogs.sun.com/rafaelferreira</a>. It is there because I've been working for Sun for the past few months - I'm a Sun Campus Ambassador at the University of São Paulo. That means, BTW, that if you're a student or a professor at USP and want to engage with Sun, I'm you're guy (hint: my name is Rafael Ferreira and all email addresses at Sun are formed as Firstname.Lastname@sun.com). On a related note, we have setup a JUG for the USP community at https://uspjug.dev.java.net/</li><li>Oh, and obviously, all opinions expressed here are my own and not necessarily shared by Sun Microsystems or any of my co-workers. Duh.<br /></li></ul><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-233114118205868976?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-15827161887689218822007-06-25T03:30:00.000-03:002008-12-11T16:55:05.357-02:00Pull my StringsMy favorite Joel Spolsky article is <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">The Law of Leaky Abstractions</a>. It may not be the wittiest or the most controversial, but makes up for it in shear importance. Joel's site is down right now (something that doesn't happen frequently), but wikipedia says that the Law was worded as:<br /><span style="font-size:130%;"><br /></span><div style="text-align: center;"><span style="font-weight: bold;font-size:100%;" >"All non-trivial abstractions, to some degree, are leaky."</span><br /></div><br />Well, some pretty trivial abstractions are leaky too. What is the type you use most in your programs? Probably int, but after that? For me it is String (currently java.lang.String or scala.String to be annoyingly more precise).<br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://en.wikipedia.org/wiki/Pull_My_Strings"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_AUV7ymG1mDc/Rn9q_eyKW1I/AAAAAAAAAAc/Nk-Wlz5m1MU/s320/string.jpg" alt="" id="BLOGGER_PHOTO_ID_5079896543524969298" border="0" /></a><br />That is a pretty shitty* abstraction, don't you think? String is supposed to be short for StringOfCharacters. Leaving aside the fact that shorthanding is a bad practice, the name may not be wrong, per se, but it does nothing to characterize the meaning of the type in our programs. Why not Text? It is semantically more accurate and actually shorter than "String".<br /><br /><br /><br />* To retain the plumbing analogy.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-1582716188768921882?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com2tag:blogger.com,1999:blog-10162639.post-72740886023599972212007-06-18T02:56:00.000-03:002007-06-18T18:34:30.761-03:00FuturologiaA minha bola de cristal enxerga duas tendências* para as linguagens de programação do futuro*:<br /><ul><li>Quantificação. Só porque PROLOG foi uma frustração coletiva, não significa que suas idéias sejam inúteis. A propósito, quantificação é a <a href="http://scholar.google.com/scholar?hl=en&lr=&safe=off&cluster=16963206302371419919">parte</a> mais interessante de AOP, IMNSHO.</li><li>Metaprogramação reflexiva profunda. <a href="http://desciclo.pedia.ws/wiki/Malha%C3%A7%C3%A3o">Bonito isso né</a>, eu li num livro. Falando sério, acredito que a importância de metaprogramação é óbvia, o que não é tão óbvio são os qualificadores "reflexivo" e "profundo". O primeiro vem da observação que se estado mutável é um problema, então metaestado mutável é um metaproblema maior ainda. E "profunda" porque eu acho que a reflexão tem que atingir até o nível da AST - o Erik Meijer <a href="http://www.infoq.com/interviews/erik-meijer-linq">nesta</a> entrevista com a InfoQ fala bem sobre isso, como "quoting" é um conceito fundamental em sistemas formais.<br /></li></ul><br />* Definições:<br /><span style="font-weight: bold;">tendência</span> == algo que eu quero que aconteça.<br /><span style="font-weight: bold;">futuro</span> == ponto no tempo distante o suficiente para que: (a) a tendência supracitada tenha se realizado ou (b) ninguém mais se lembre deste post.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-7274088602359997221?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-50608822842250621062007-05-27T18:36:00.000-03:002007-05-28T17:05:40.306-03:00IDLs para REST?<p style="margin-bottom: 0cm;"><br /><i>[Edit: O Aristotle Pagaltzis tratou deste mesmo tema <a href="http://plasmasturm.org/log/460/">neste post</a>.]</i><br /></p><br /><p style="margin-bottom: 0cm;">Antes de mais nada, um aviso para quem usa a porcaria do blogger: o “auto-save” <a href="http://groups.google.com/group/blogger-help-troubleshoot/browse_thread/thread/a74f7a837dc377d0/64b6ade70116e0e1?lnk=gst&q=lost+draft&rnum=8#64b6ade70116e0e1">não funciona</a>! Como o leitor já deve ter deduzido, eu descobri esse problema de maneira pouco agradável, perdendo o resultado de algumas horas de digitação. Vamos tentar de novo...</p> <p style="margin-bottom: 0cm;">Se eu ainda me lembro, comecei explicando que fui motivado por dois posts com que esbarrei por aí na internet. Primeiro foi o Roy Fielding na lista REST-discuss <a href="http://tech.groups.yahoo.com/group/rest-discuss/message/8367?var=1">comentando</a> que um dos princípios do estilo não é bem compreendido. O segundo foi o Daniel Quirino <a href="http://nullability.org/wp-trackback.php?p=96">bloggando</a> sobre uma deficiência do REST, a ausência de linguagens de descrição de interface. Citando o Daniel citando ele próprio: </p> <p style="margin-bottom: 0cm;"></p><blockquote><p style="margin-bottom: 0cm;">“WSDL cumpre um papel muito importante neste contexto de <b>servir</b> outros sistemas, uma vez que existe uma maneira <b>padrão</b> para se descrever para outras <b>máquinas</b> todos os serviços que estão sendo oferecidos. “</p> <p style="margin-bottom: 0cm;"></p></blockquote><p style="margin-bottom: 0cm;">Parece razoável, não? O provedor de um serviço escreve um documento WSDL descrevendo as operações oferecidas e os tipos de dados de entrada e saída de cada. A partir daí, para se desenvolver um cliente do serviço basta obter uma cópia do WSDL, usar alguma ferramenta para gerar artefatos correspondentes e invocar as operações como se fossem chamadas de procedimento locais(*).<br /></p> <p style="margin-bottom: 0cm;">Essa descrição não se aplica a serviços RESTful. Para começar, o conceito de operação é muito diferente – só existe um conjunto fixo delas para todos os recursos no sistema inteiro. No caso do HTTP, as operações são os famosos verbos GET, PUT, POST e DELETE(**). Ok, mas para onde vai a semântica que estava nas operações? A princípio parece que vai parar na identificação de recursos: uma chamada getStockQuote(“SUNW”) se transforma em um GET na URL http://example.com/stock/SUNW.</p><p style="margin-bottom: 0cm;">Mas REST é um pouco mais complicado do que isto. Aliás, os argumentos a favor do estilo por ser mais simples do que WS-* estão ligeiramente equivocados, IMHO. O foco principal do REST é a escalabilidade, em vários sentidos, desde uma preocupação em controlar a carga nos servidores em relação à demanda(***) até um entendimento de como habilitar <a href="http://en.wikipedia.org/wiki/Network_effect">network effects </a>para aumentar o valor da rede inteira à cada contribuição individual. Na tese do Roy Fielding este foco <a href="http://www.ics.uci.edu/%7Efielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5">leva</a> à quatro restrições que guiam a arquitetura: “identification of resources; manipulation of resources through representations; self-descriptive messages; and, hypermedia as the engine of application state”. Uma destas é o tal princípio que o Roy observou ser mal compreendido, consegue adivinhar qual?</p><p style="margin-bottom: 0cm;">O ganhador é “hypermedia as the engine of application state”, que de fato parece bem mais obscuro que os demais. A idéia aqui é, no meu entendimento, que o estado da aplicação é conhecido somente pelo cliente mas é dirigido pelo servidor. Conhecido somente pelo cliente porque o estilo exige que o servidor não mantenha informação alguma sobre “sessões” com um cliente. Isso mesmo, cookies com <i>sessionid</i>s e assemelhados não são RESTful. A parte de “dirigido pelo servidor” pede um exemplo; vamos considerar o funcionamento dos forms html. O browser recebe um documento contendo uma tag <span style="font-weight: bold;"><form action="alguma_uri"></span> definindo o destino e subtags <span style="font-weight: bold;"><input ...></span> especificando os dados a serem preenchidos. O usuário entra com seus dados, aperta <b>submit</b> e o browser faz um POST no recurso identificado por <b>alguma_uri</b> passando uma representação <b>application/x-www-form-urlencoded</b> das informações. Percebam que o cliente não precisava saber a priori para qual URI POSTar seus dados, ela foi obtida do servidor. Em outras palavras, a transição de estado se deu no cliente seguindo um link (hipermídia). O Sam Ruby explica isso bem melhor que eu <a href="http://www.intertwingly.net/blog/2005/03/09/Distributed-State-Machines">aqui</a>.</p> <p style="margin-bottom: 0cm;">Essa restrição ajuda a permitir que porções diferentes do sistema evoluam independentemente, por exemplo se um servidor decidir mudar sua estrutura de navegação basta começar a servir URIs diferentes em seus links e os clientes continuam operando sem sofrer alterações. Outras características do REST, como <span lang="en-US">content</span>-<span lang="en-US">negotiation</span> baseada em tipos padronizados, também contribuem para facilitar este requisito. E é claro que evolução independente é crucial para um sistema que pretende atingir escala global. Aí está o link com a escalabilidade, no <span lang="en-US">pun</span> <span lang="en-US">intended.</span></p> <p style="margin-bottom: 0cm;">Por isso que muitos RESTfarians criticam as linguagens de descrição de interface, inclusive WADL. Como já vimos no caso do WSDL, elas acoplam um cliente com uma definição de serviços em “tempo de compilação”, por assim dizer. E mais, há quem defenda o uso de documentos análogos à estes padrões de descrição de interfaces, mas pensados para serem interpretados por clientes em tempo de execução. Uma iniciativa deste tipo é o <a href="http://www.markbaker.ca/2003/05/RDF-Forms/">RDF-forms</a>, a respeito do qual eu não sei absolutamente nada.</p> <p style="margin-bottom: 0cm;">Isso ainda é controverso, e os oponentes apresentam um argumento forte – IMHO de novo – que comunicação programática entre aplicações, estilo EAI, é muito diferente do sistema interativo de hipermídia global para o qual REST foi concebido. Na minha opinião pessoal, independente de ortodoxias, considere adotar REST para suas APIs públicas, mesmo se não seguir rigorosamente todos os preceitos do doutor Fielding.</p><br /><p style="margin-bottom: 0cm;"><br /></p><br /><br /><p style="margin-bottom: 0cm;">* Uma equipe esperta vai saber que a confiabilidade e a latência destas chamadas são muito diferentes de invocações locais, mas isso não muda muito o processo em linhas gerais.</p> <p style="margin-bottom: 0cm;">** E mais HEAD, OPTIONS e outros primos pobres.</p> <p style="margin-bottom: 0cm;" lang="en-US">*** Caching, caching, caching</p><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-5060882284225062106?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-43563124134667210532007-02-23T20:31:00.000-02:002007-02-23T20:43:44.812-02:00Design Patterns are not Recipes<h4>The controversy</h4>Over the past few months, I've been seeing some Design Patterns backlash on the blogosphere, I guess it is accompanying the agile anti-hype phase that's also strong these days. The most rabid attack came from Mark Dominus, <a href="http://blog.plover.com/prog/design-patterns.html" title="making">making</a> the case that many innovations in programming languages in the past decades were in response to common practices that could be described as patterns, had the pattern format been known back then. Take, for instance, what we now know as a procedure call: code to stack up register values and return address followed by a jump instruction. Before assemblers became available, programmers used to recode this every time they wanted a subroutine. Dominus sees this observation as a sign that something is wrong with the patterns movement:<br /><blockquote>"Identification of patterns is an important driver of progress in programming languages. As in all programming, the idea is to notice when the same solution is appearing repeatedly in different contexts and to understand the commonalities. This is admirable and valuable. The problem with the "Design Patterns" movement is the use to which the patterns are put afterward: programmers are trained to identify and apply the patterns when possible. Instead, the patterns should be used as signposts to the failures of the programming language. As in all programming, the identification of commonalities should be followed by an abstraction step in which the common parts are merged into a single solution."<br /></blockquote>Professor Ralph Johnson, one of the original "Gang of Four" members, <a href="http://www.cincomsmalltalk.com/userblogs/ralph/blogView?entry=3335803396" title="Design patterns and language design">responded</a>:<br /><blockquote>"No matter how complicated your language will be, there will always be things that are not in the language. These things will have to be patterns. So, we can eliminate one set of patterns by moving them into the language, but then we'll just have to focus on other patterns. We don't know what patterns will be important 50 years from now, but it is a safe bet that programmers will still be using patterns of some sort."<br /></blockquote>Dominus <a href="http://blog.plover.com/prog/johnson.html" title="retorts">retorts</a> with subtler arguments, and I encourage you to read his article to avoid any misinterpretations of my part. But I'll still quote what I believe is the core of his thinking:<br /><blockquote> <p>"What I imagine is that when pattern <i>P</i> applies to language <i>L</i>, then, to the extent that some programmer on some project finds themselves needing to use <i>P</i> in their project, the use of <i>P</i> indicates a deficiency in language <i>L</i> for that project. </p> <p> The absence of a convenient and simple way to do <i>P</i> in language <i>L</i> is not always a problem. You might do a project in language <i>L</i> that does not require the use of pattern <i>P</i>. Then the problem does not manifest, and, whatever <i>L</i>'s deficiencies might be for other projects, it is not deficient in that way for your project. </p> <p> (...) </p> <p> But to the extent that some deficiency does come up in your project, it is a problem, because you are implementing the same design over and over, the same arrangement of objects and classes, to accomplish the same purpose. If the language provided more support for solving this recurring design problem, you wouldn't need to use a "pattern". Consider again the example of the "subroutine" pattern in assembly language: don't you have anything better to do than redesign and re-implement the process of saving the register values in a stack frame, over and over?" </p> </blockquote> <h4>My take<br /></h4> Mark seems to be worried that programming language innovation will be stifled by the patterns movement, on account of programmers being taught to mimic patterns on their code instead of applying that energy on incorporating them into programming languages. It is important to first acknowledge, as himself put it, that it is valuable to identify commonalities in software design, one could even say this is a precondition for evolving a programming language. So, he sees the problem in not working to embody these commonalities in the language. From my exposure to the patterns literature, I believe the movement is not in any way against incorporating patterns as programming language features. It is implicit in this passage from <a href="http://c2.com/cgi/wiki?DesignPatternsBook" title="GoF">GoF</a>, page 4:<br /><blockquote>"Our patterns assume Smalltalk/C++-level language features, and that choice determines what can and cannot be implemented easily. If we assumed procedural languages, we might have included design patterns called "Inheritance," "Encapsulation," and "Polymorphism." similarly, some of our patterns are supported directly by the less common object-oriented languages. CLOS has multi-methods, for example, which lessen the need for a pattern such as Visitor"<br /></blockquote>And explicit in Ralph Johnson's aforementioned blog post: "Many of the patterns will get subsumed by future languages, but probably not all of them". Now that we know that design patterns are contextual and <span style="font-style: italic;">can</span> be incorporated as language features, we must ask if the emphasis of the patterns movement isn't displaced. Why go to the trouble of publishing large books describing at length things like intent, motivation, participants, consequences, related patterns, etc, when we could just inventory all patterns and shove our favorites in our programming languages? One very simple reason is that not all patterns would yield benefit from being reified. Dominus says that people often mentioned to him MVC as an example of a pattern so complex that it could not be absorbed in a programming languge. But, of course, they were all wrong and he was right, since novel systems like Ruby on Rails or subtext do exactly that, definitively confirming his thesis that the only impediment was an atrocious lack of imagination on the part of his opponents! This is all very strange to me, since "MVC" came to life as pretty concrete software - it was the GUI development framework bundled with Smalltalk-80. Many years later, after several separate versions were developed, it was described and published as an (architectural) pattern. Leaving object orientation early history aside, lets get back to the matter of patterns that aren't targets for reification. One example is the Façade(185) design pattern. As one of the most frequently applied GoF patterns, described having as it's Intent to "provide a unified interface to a set of interfaces in a subsystem", there can be no doubt that it is indeed recurring. Looking at the Structure and Participants sections, we can see that it is very simple, just a Façade class that depends on many other (unidentified) subsystem classes inside a boundary. A consequence of this simplicity is that there would be little gain in incorporating this pattern into a programming language, as it doesn't really represent specific interactions that have to be recoded each time the pattern is applied.<br /><br />One could respond that if that is the case, then the pattern is useless. It describes a solution so simple that a programmer who has never heard of the "Façade design pattern" would probably be able to construct it by himself. The error in this judgment is that a pattern's merit isn't measured by how interestingly or usefully it gives a solution to a problem. Knowing that its not hard to <span style="font-style: italic;">invent Façade</span> does not detract from the fact that being able to <span style="font-style: italic;">talk about Façade</span> is a big design win in itself. Patterns are as much an aid to communication as they are vehicles to disseminate knowledge.:<br /><blockquote>"Naming a pattern immediately increases our design vocabulary. It lets us design at a higher level of abstraction. Having a vocabulary for patterns lets us talk about them with our colleagues, in our documentation, and even to ourselves. It makes it easier to think about designs and to communicate them and their trade-offs to others."[GoF, page 3]<br /></blockquote>On the other hand, we already mentioned that some of the patterns are indeed amenable to reification. In this case there are two paths to choose from: coding it as a library atop usual language abstraction mechanisms or incorporating it as a basic language feature. Dominus second post argues that this choice is a mere implementation detail. Now, to paraphrase him, his point seems completely daft, which may I interpret to mean that there's something that went completely over my head. The difference is obvious: if some feature can be implemented as a library, any programmer that wants it can write it exactly one time and reuse as appropriate; no language modification required. As a contributor to CPAN , he should know well that nowadays much software reuse is done through open source libraries, lowering the recode count to zero for it's users. This is a crucial distinction, as adding something to the language has a huge impact on the whole technical ecosystem, from increased barrier to entry to pernicious interaction between features (non-orthogonality).<br /><br />Lets take another look at Dominus' central proposition:<br /><blockquote>"(...) when pattern <i>P</i> applies to language <i>L</i>, then, to the extent that some programmer on some project finds themselves needing to use <i>P</i> in their project, the use of <i>P</i><span style="font-style: italic;"> </span>indicates a deficiency in language <i>L</i> for that project. "<br /></blockquote>I believe the most important question here is: what does it mean to "<span style="font-style: italic;">use [pattern] P</span>"? If you take it to mean <span style="font-style: italic;">follow the steps from P's description, possibly copying some code from the "Implementation" section</span>, then this reasoning makes sense. But patterns are not merely recipes, and a pattern language is not a cookbook! One way in that patterns differ from recipes is that, as we saw in Façade, the Solution section can be of little importance compared to the communication gain from just naming the pattern. Another difference is that there is wide latitude in implementation strategies for each pattern, not to mention cases where multiple patterns present themselves as design alternatives for a set of forces.<br /><br />Speculating a bit, I believe the origin of this antagonism toward design patterns is that the idea of a recurrent structure is antithetical to a certain <span style="font-style: italic;">ethos</span> present in the software development community. Mark Dominus summarizes this feeling well in this passage "<span style="font-style: italic;">As in all programming, the identification of commonalities should be followed by an abstraction step in which the common parts are merged into a single solution.</span>" It can also be formulated as a call to arms: Don't repeat yourself! Or better yet, DRY! (the love for TLAs is another part of the programming ethos :). I don't dispute that eliminating repetition is an important design heuristic, but I sometimes wonder if it can be taken too far, becoming a sort of factorization fetishism that is detrimental to productivity.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-4356312413466721053?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com7tag:blogger.com,1999:blog-10162639.post-91829203351926816412007-02-12T05:14:00.000-02:002007-01-18T12:56:02.914-02:00God<a href="http://www.youtube.com/watch?v=NAW0wnj0Xi8&feature=RecentlyWatched&page=1&t=t&f=b">George</a> <a href="http://www.youtube.com/watch?v=bZzT2pmz7VY&feature=RecentlyWatched&page=1&t=t&f=b">Carlin</a> <a href="http://www.youtube.com/watch?v=no40BlyA3YQ&feature=RecentlyWatched&page=1&t=t&f=b">is</a> <a href="http://www.youtube.com/watch?v=iAAMPS2MaTs&feature=RecentlyWatched&page=1&t=t&f=b">f*cking</a> <a href="http://www.youtube.com/watch?v=D0zsZ6K-tQo&feature=RecentlyWatched&page=1&t=t&f=b">awesome</a>.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-9182920335192681641?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-39121936632995100022007-01-10T16:43:00.000-02:002007-01-16T20:10:33.918-02:00Domain Specific Languages e Estratificação por Estabilidade2007 mal começou e o meme das DSLs já está provocando polêmica. Eric Evans, em entrevista na InfoQ, disse:<br /><br /><blockquote style="font-style: italic;">"More out on the cutting-edge are the efforts in the area of domain-specific languages (DSLs), which I have long believed could be the next big step for DDD. To date, we still don't have a tool that really gives us what we need. But people are experimenting more than ever in this area, and that makes me hopeful." </blockquote><a href="http://fragmental.com.br/blog/?p=292">Philip Calçado</a> citou o Evans e foi além, afirmando que "<span style="font-style: italic;">DSLs são iminentes mas as ferramentas simplesmente ainda não chegaram lá</span>". Escrevendo em tom mais cético, Rodrigo Kumpera <a href="http://www.kumpera.net/blog/index.php/2007/01/06/dsls-vao-ter-o-mesmo-fim-que-aop/">comentou</a> que DSLs ainda parecem uma tecnologia de um exemplo só; da mesma maneira que toda palestra de AOP fala de logging, toda introdução à DSLs fala em configuração. Citando:<br /><br /><blockquote style="font-style: italic;">"Todos estão falando o tempo todo sobre como configuração é um problema a ser resolvido por linguagens de domínio. Até o Martin Fowler comete essa gafe em sua <a href="http://www.infoq.com/presentations/domain-specific-languages">palestra na JAOO 2006</a>! O problema é o mesmo que logging, eu diria, representa nenhum risco a complexidade de um projeto. Quantos realmente já tiveram problemas relacionados a dificuldade de colocar logging em uma aplicação? Configuração idem."</blockquote>Eu acho que a analogia com AOP não procede. Tracing/logging é de fato um caso de uso (quase trivial, BTW) para AOP. Precisamos analisar configuração com mais cuidado. Tome por exemplo uma aplicação de eCommerce B2C tradicional (você pode imaginar que é, quem sabe, uma loja de, sei lá.., animais de estimação). Na primeira iteração do software, cada item à venda tem um preço de catálogo cadastrado. Essa decisão logo se mostra inflexível, pois uma variação sazonal nos preços é comum no varejo. O requisito é atendido com uma nova feature permitindo que se estabeleça um perentual de desconto/acréscimo por mês para cada produto. A interface com o usuário para esta feature se localiza numa tela entitulada "Configurações". Mais adiante percebe-se que a flexibilidade ainda está aquém do ideal, os clientes querem definir regras de preço mais complicadas, como:<br /><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;">se vendeu mais de 500 na semana passada, acréscimo de 10%.</span><br /></blockquote></span>Pode-se inserir estas regras (hard-coded) no meio do sistema ou decidir por manter a parametrização externa e usar uma DSL. Em qualquer caso, ainda podemos chamar isto de configuração?<br />Sabendo que código e dados são basicamente a mesma coisa, eu vejo a aplicação de DSLs como decisões a respeito de que tipo de informação <em>faz parte</em> do sistema, e que tipo de informação consiste em <em>parametrização "externa"</em>. No fim das contas, é técnica para atender ao "<a href="http://www.objectmentor.com/resources/articles/stability.pdf">Stable Dependencies Principle (S0P)</a>", deve-se isolar as porções de um software com maior volatilidade e uma linguagem específica - talvez até editável por usuários finais - é uma boa alternativa para implementar os módulos menos estáveis.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-3912193663299510002?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com1tag:blogger.com,1999:blog-10162639.post-28005386148732447012006-12-17T02:02:00.000-02:002008-12-11T16:55:05.620-02:0051%<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://xkcd.com/c197.html"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_AUV7ymG1mDc/RYTBwhl2qMI/AAAAAAAAAAM/8znQCUgyCvw/s400/ninja_turtles.png" alt="" id="BLOGGER_PHOTO_ID_5009341724937857218" border="0" /></a><br /><br />by <a href="http://xkcd.com/">Randall Munroe</a> (<a href="http://creativecommons.org/licenses/by-nc/2.5/">CC Attribution-NonCommercial 2.5</a>)<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-2800538614873244701?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com1tag:blogger.com,1999:blog-10162639.post-24315037228677628562006-12-03T18:29:00.000-02:002006-12-05T02:17:37.891-02:00More Stupid Tiger TricksI'm trying to collect some idioms for programming with Java 5 generics, with varying degrees of usefulness, that I found scattered on different places. <i>[Edit]Hopefully I fixed the whitespace problems on the code snippets. Blogger is pretty weak for working with source code, but now I believe its alright. As a bonus, I threw in another item on the end. I guess I'm all out of generic idioms for now.[/Edit]</i><br /><br /><h3>Union Types</h3><br />Let's say I have a method to remotely execute some task. Its signature could be something like this:<br /><pre><code><br /> public void compute(Runnable task)<br /></code></pre><br />But there is a catch, we would also like the argument to be Serializable. We could define an application specific interface like<br /><pre><code><br /> interface Task extends Runnable, Serializable {}<br /></code></pre><br />but that would prevent us from accepting exiting classes that just happened to implement both of these interfaces. Java 5 allows us to specify exactly that with union type bounds for type arguments. It is actually pretty easy, see how we apply the technique to our example:<br /><pre><code><br /> public <T extends Runnable & Serializable> void compute(T task)<br /></code></pre><br />I advice you to reserve this idiom mostly for interacting with third-party code. If you find the need to require union types frequently on your own code, there is probably something wrong with the design and some refactoring may be in order.<br /><br /><h3>Casting with a type token</h3><br />"Know and use the libraries" is one of the most important items in Josh Bloch's Effective Java book. It's also one I frequently violate, only to regret later on. For instance, had I read class Class' documentation attentively, I could have avoided many unchecked cast warnings. An example is in order:<br /><pre><code><br /> class Registry {<br /> public void storeObject(Object obj) { }<br /> public T getObject(Class<T> ofClass) {}<br /> }<br /></code></pre><br />I think this class is pretty self explanatory, it can store an object indexed by it's class and later retrieve the stored instance. The challenge is how to implement it without upsetting the compiler. (And yes, @SupressWarnings("unchecked") is cheating...). For those of you who have done your homework and read class Class' javadocs you know this isn't much of a challenge after all, see:<br /><pre><code> <br /> class Registry {<br /> private Map<Class<?>, Object> objects = new HashMap<Class<?>, Object>();<br /><br /> public void storeObject(Object obj) {<br /> objects.put(obj.getClass(), obj);<br /> }<br /><br /> public <T> T getObject(Class<T> ofClass) {<br /> Object instance = objects.get(ofClass);<br /> return <span style="color: rgb(51, 51, 255); font-weight: bold;">ofClass.cast(instance)</span>;<br /> }<br /> }<br /></code></pre><br /><h3>Safe dynamic class loading</h3><br />More goodies from Class class. Let's see how to dynamically load using generics. Again, we start with an example:<br /><pre><code><br /> public interface ServiceLocator {<br /> public Executor getExecutor();<br /> }<br /></code></pre><br />This is a simple service locator that knows how to get an Executor instance. Service locators usually find service instances from naming services (in a Java EE environment, JNDI is most likely). But a simpler implementation could just read concrete class names from a properties file and instantiate the objects on construction. Let's take a shot at coding this up:<br /><pre><code><br /> class ServiceLocatorProps implements ServiceLocator {<br /> private Executor executor;<br /> <br /> public ServiceLocatorProps() throws Exception {<br /> Properties props = new Properties();<br /> props.load(getClass().getResourceAsStream("services.properties"));<br /> <br /> String executorClassName = props.getProperty(<br /> "java.util.concurrent.Executor");<br /> <br /> <span style="color: rgb(51, 51, 255); font-weight: bold;">Class<Executor> executorClass =<br /> (Class<Executor>) Class.forName(executorClassName);</span> //WARNING!!<br /> this.executor = executorClass.newInstance();<br /> }<br /> <br /> public Executor getExecutor() {<br /> return executor; <br /> } <br /><br /> }<br /></code></pre><br /><br />Please don't pay attention to the inexistent Exception handling. The point here is that the call to Class.forName() is followed by an unckecked cast and the compiler will promply warn us all about it. The correct code for this constructor would be:<br /><pre><code><br /> public ServiceLocatorProps() throws Exception {<br /> Properties props = new Properties();<br /> props.load(getClass().getResourceAsStream("services.properties"));<br /> <br /> String executorClassName = props.getProperty(<br /> "java.util.concurrent.Executor");<br /> <br /> <span style="color: rgb(51, 51, 255); font-weight: bold;">Class<?> loadedClass = Class.forName(executorClassName);<br /> Class<? extends Executor> executorClass = loadedClass.asSubclass(Executor.class);</span> <br /> this.executor = executorClass.newInstance();<br /> }<br /></code></pre><br /><h3>Subclass to capture type arguments</h3><br />This last one is not so much an idiom as a kludge to get around erasure. Most people who use generics in their code eventually get bitten by this problem, as I already bitched about <a href="http://rfframblings.blogspot.com/2006/09/arrays-genricos-e-o-maldito-compilador.html">before</a>. Anyway, sometimes one way to get around the information loss is to subclass the parametrized type. This is because, unlike an instance of a generic type, a subclass does retain type argument information. For an example, see the <a href="http://blogs.tedneward.com/2006/11/28/Java5+Generics+And+Just+Not+Quite+There.aspx">problem</a> recently posted by Ted Neward and my <a href="http://blogs.tedneward.com/2006/12/01/Followup+On+The+Java+Generics+Post.aspx">proposal</a> for a "solution" (its the last one). A much more sophisticated example, including reflection, can be found on <a href="http://blog.caelum.com.br/2006/10/29/brincando-com-generics-o-bizarregenericdao/">this</a> Caelum blog post (it is in portuguese, but the code is understandable).<br /><i>[Edit: one more item:]</i><br /><h3>Generic Wrapper</h3><br />I guess I can't properly call this one an idiom, since I only saw it once. I'm talking about the <a href="http://download.java.net/jdk6/docs/api/java/sql/Wrapper.html">java.sql.Wrapper</a> interface in jdbc4. It is s a 2-method interface: <i>isWrapperFor(Class<?> iface)</i> and <i><T> T unwrap(Class<T> iface)</i>. It exists to expose extensions to a predefined API in a typesafe manner. I would serioulsy consider something like this when implementing a public extensible API/SPI.<br /><i>[/Edit]</i><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-2431503722867762856?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0tag:blogger.com,1999:blog-10162639.post-60790398330365633102006-11-18T16:07:00.000-02:002006-11-18T16:20:29.528-02:00Disabilng subversion localization.I had a hard time figuring how to disable svn localization features, so this post is just here in the hope that it can help the next person who encounters this problem. Its very simple, actually. Subversion obeys traditional Unix internationalization environment variables even when running on other operating systems, so one can just set the LC_ALL env variable to "C" (without the quotations marks) and the console tools will work just as installed on an english language system.<br /><br />Why did I want to do this? One reason is that the locale handling is broken by default on Windows, but its not hard to fix this (just set the APR_ICONV_PATH environment variable to the \iconv directory on your svn installation). I did it because some build scripts found in the wild work by parsing svn output and localization obviously screws them up.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-6079039833036563310?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com3tag:blogger.com,1999:blog-10162639.post-12377855013912579362006-11-18T15:39:00.000-02:002006-11-18T16:43:39.405-02:00I'm (still) not deadThis is where I should be excusing myself for being "way too busy" to update my blog and promising that things will get back to "normal" soon. But I'm not actually so busier than usual, it's just that every post I thought about writing ended up larger that expected and taking more time that I have available (I think my brain needs a better job scheduling algorithm). I'll post something decent soon. Or not so soon, but eventually...<br /><br />Anyway, this is not a link blog - I just can't seem to be able to write any commentary with less than ten lines - but I maintain my del.icio.us bookmarks reasonably well. So, if anyone is curious about stuff I find interesting take a look at <a href="http://del.icio.us/rafaeldff">http://del.icio.us/rafaeldff</a>.<br /><br />I'll end this useless keepalive post with another musical recommendation: The Jam is a pretty cool old band. Listen to "Eton Rifles", it sounds a bit like a Clash song.<div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/10162639-1237785501391257936?l=blog.rafaelferreira.net'/></div>Rafael de F. Ferreirahttp://www.blogger.com/profile/03350776762967743057noreply@blogger.com0