<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Ahalmeida&#039;s Weblog</title>
	<atom:link href="http://ahalmeida.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://ahalmeida.com</link>
	<description>Software development, agile and some random thoughts</description>
	<lastBuildDate>Sat, 11 Feb 2012 01:54:43 +0000</lastBuildDate>
	<language>pt-br</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='ahalmeida.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Ahalmeida&#039;s Weblog</title>
		<link>http://ahalmeida.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://ahalmeida.com/osd.xml" title="Ahalmeida&#039;s Weblog" />
	<atom:link rel='hub' href='http://ahalmeida.com/?pushpress=hub'/>
		<item>
		<title>Neo4j&#8217;s Cypher internals &#8211; Part 2: All clauses, more Scala&#8217;s Parser Combinators and query entry point</title>
		<link>http://ahalmeida.com/2011/09/22/neo4js-cypher-internals-part-2-all-clauses-more-scalas-parser-combinators-and-query-entry-point/</link>
		<comments>http://ahalmeida.com/2011/09/22/neo4js-cypher-internals-part-2-all-clauses-more-scalas-parser-combinators-and-query-entry-point/#comments</comments>
		<pubDate>Thu, 22 Sep 2011 14:00:38 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[neo4j]]></category>
		<category><![CDATA[OpenSource]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=248</guid>
		<description><![CDATA[Recalling the first post During the previous post, I&#8217;ve explained what is Neo4j and then, explained how graph traversal could be done on Neo4j using the Java API. Next, I&#8217;ve introduced Cypher and how it helped write queries, in order to retrieve data from the graph. After introducing Cypher&#8217;s syntax, we dissected the Start Clause, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=248&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>Recalling the first post</h2>
<p>During the <a href="http://ahalmeida.com/2011/09/06/how-neo4j-uses-scalas-parser-combinator-cyphers-internals-part-1/">previous post</a>, I&#8217;ve explained what is Neo4j and then, explained how graph traversal could be done on Neo4j using the Java API. Next, I&#8217;ve introduced Cypher and how it helped write queries, in order to retrieve data from the graph. After introducing Cypher&#8217;s syntax, we dissected the Start Clause, which is the start point (duh) for any query being written on Cypher. If you hadn&#8217;t read it, <a href="http://ahalmeida.com/2011/09/06/how-neo4j-uses-scalas-parser-combinator-cyphers-internals-part-1/">go there</a>, and then come back to read this one.</p>
<p>In this second part, I&#8217;ll show the other clauses existents in Cypher, the Match, Where, Return, Skip and Limit, OrderBy and Return. Some will be simple, some not and I&#8217;ll go in a more detailed way on those clauses that aren&#8217;t so trivial. After that, we will take a look at the Cypher query entry point, and how the query parsing is unleashed.</p>
<p>Nuff said, let&#8217;s get down to business.</p>
<h2>The other clauses</h2>
<p>At the moment of this writing, Neo4j is composed by 6 clauses: Start (seen in the first part of this series), Match, Where, Return, OrderBy and Skip Limit. Recalling the first post, we used a sample Cypher query to show its syntax and it also showed all 6 clauses in action. Let&#8217;s see it again:</p>
<pre>start programmer=(3) match (programmer)-[:PAIRED]-&gt;(pair) where pair.age &gt; 30 return pair, count(*) order by age skip 5 limit 10</pre>
<p>Since start clause was already explained, let&#8217;s go, clause by clause, form left-to-right, starting by the match clause.</p>
<h3>The Match Clause</h3>
<p>Probably the most complicated clause. It&#8217;s implementation may be somewhat confusing at a first sight, however, looking calmly, it is not that scary. So, let&#8217;s go step by step.</p>
<p>First of all, the Match Clause is where we define patterns of paths we want to query information for. These paths can be directed, we can identify them, it is possible to define the relationship types of these paths and so on. Taking a look at our sample query, we can highlight only the match part of the query:</p>
<pre>match (programmer)-[:PAIRED]-&gt;(pair)</pre>
<p>This is a simple case, where we are defining the path from the programmer with the PAIRED relationship incoming at a pair. So far so good, however, this is easy to get complex, for instance, if we don&#8217;t care about one side of the relationship, we can omit its identifier:</p>
<pre>match (programmer)-[:PAIRED]-&gt;()</pre>
<p>And if we care about the relationship, as in case of returning it (more about returns in the future), we can identify it:</p>
<pre>match (programmer)-[relationship:PAIRED]-&gt;()</pre>
<p>It is possible to define several patterns and multiple relationships, such as:</p>
<pre>match (programmer)-[:PAIRED]-&gt;(pair)&lt;-[:FRIEND]-(rose)</pre>
<p>Which in this case matches the programmer that paired with someone who is Rose&#8217;s friend.</p>
<p>In order to we get it in a simple way, we check the definition of the methods at the MatchClause trait, so we can see how this grammar is defined:</p>
<p><pre class="brush: scala;">
trait MatchClause extends JavaTokenParsers with Tokens {

  def matching: Parser[(Match, NamedPaths)] = ignoreCase(&quot;match&quot;) ~&gt; rep1sep(path, &quot;,&quot;)

  def path: Parser[Any] = pathSegment | parenPath | noParenPath

  def parenPath: Parser[NamedPath] = identity ~ &quot;=&quot; ~ &quot;(&quot; ~ pathSegment ~ &quot;)&quot;

  def noParenPath: Parser[NamedPath] = identity ~ &quot;=&quot; ~ pathSegment

  def pathSegment: Parser[List[Pattern]] = node ~ rep1(relatedTail)

  def node: Parser[Option[String]] = parensNode | relatedNode

  def parensNode: Parser[Option[String]] = &quot;(&quot; ~&gt; opt(identity)
  def relatedNode: Parser[Option[String]] = opt(identity)

  def relatedTail = opt(&quot; relationshipInfo
  def relationshipInfo = opt(identity) ~ opt(&quot;?&quot;) ~ opt(&quot;:&quot; ~&gt; identity) ~ opt(&quot;^&quot; ~ wholeNumber ~ &quot;..&quot; ~ wholeNumber)
}
</pre></p>
<p>We can see the entry point of the match clause, defined by the <code>matching</code> method, at line 3, which expects a <code>match</code> keyword followed by a repetition of path, whose definition is at line 5, which is defined by either a <code>pathSegment</code>, <code>parenPath</code> or a <code>noParenPath</code>.</p>
<p>For those that don&#8217;t know Scala very well, the <code>Option</code> means that the object is optional, and if it not exists, when we have the possibility to return an alternative object.</p>
<p>The <code>parenPath</code> and <code>noParenPath</code> are easy, they are paths defined either with or without parenthesis. While the <code>pathSegment</code> is defined by a <code>node</code> followed by a repetition of a <code>relatedTail</code>. The <code>node</code> is defined by optional parenthesis and identifier.</p>
<p>The <code>relatedTail</code> parser is where the relationship itself is defined. With an optional incoming (&lt;) direction, a mandatory &#8211; (dash), an optional <code>relationshipInfo</code>, which must appear inside brackets and followed by another dash, an optional outgoing (&gt;) direction, also followed by a <code>node</code> definition.</p>
<p>Finishing the grammar definition, the <code>relationshipInfo</code> is defined by an optional relationship identifier (in case you want to refer to it in the future, for instance, returning it), followed by an also optional question mark, which identify an optional relationship. Following, you can define the relationship name you want to match and it is followed by an optional ^ (circumflex) sign with two numbers seperated by &#8220;..&#8221;, which is used to identify hops that can be matched, for instance ^1..4 (from 1 to 4 hops).</p>
<p>Phew, huge syntax, means&#8230; huge transformations into an AST. Let&#8217;s get to it, starting from the bottom to the top.</p>
<p>First, let&#8217;s take a look at the <code>relationshipInfo</code> method&#8217;s definition:</p>
<p><pre class="brush: scala;">
  def relationshipInfo: Parser[(Option[String], Option[String], Option[(Int, Int)], Boolean)] = opt(identity) ~ opt(&quot;?&quot;) ~ opt(&quot;:&quot; ~&gt; identity) ~ opt(&quot;^&quot; ~ wholeNumber ~ &quot;..&quot; ~ wholeNumber) ^^ {

    case relName ~ optional ~ Some(relType) ~ None =&gt; (relName, Some(relType), None, optional.isDefined)

    case relName ~ optional ~ Some(relType) ~ Some(&quot;^&quot; ~ minHops ~ &quot;..&quot; ~ maxHops) =&gt; (relName, Some(relType), Some((minHops.toInt, maxHops.toInt)), optional.isDefined)

    case relName ~ optional ~ None ~ Some(&quot;^&quot; ~ minHops ~ &quot;..&quot; ~ maxHops)  =&gt; (relName, None, Some((minHops.toInt, maxHops.toInt)), optional.isDefined)

    case relName ~ optional ~ None ~ None =&gt; (relName, None, None, optional.isDefined)
  }
</pre></p>
<p>The method returns a parser of a tuple containing 4 informations, which will be retrieved through the transformation applied on the input. The pattern on the first case, checks if the relationship name is passed, the question mark and the relationship type have been informed and the hops part of the match was omitted. If so, it builds a tuple containing all these informations retrieved in the case. The other 3 cases are variations of the first one, checking the presence and absence of other informations and transforming them into the same Scala tuple.</p>
<p>The next one is the <code>relatedTail</code> method, which defines the relationship direction and the right side node. This parser returns a tuple with informations regarding the direction and also all of the previous <code>relationshipInfo</code> parser.</p>
<p><pre class="brush: scala;">
  def relatedTail = opt(&quot; relationshipInfo     case back ~ &quot;-&quot; ~ relInfo ~ &quot;-&quot; ~ forward ~ end =&gt; relInfo match {
      case Some((relName, relType, varLength, optional)) =&gt; (back, relName, relType, forward, end, varLength, optional)
      case None =&gt; (back, None, None, forward, end, None, false)
    }
  }
</pre></p>
<p>The node itself is defined by the following parsers:</p>
<p><pre class="brush: scala;">
  def node: Parser[Option[String]] = parensNode | relatedNode

  def parensNode: Parser[Option[String]] = &quot;(&quot; ~&gt; opt(identity)  throw new SyntaxException(&quot;Matching nodes without identifiers have to have parenthesis: ()&quot;)
    case x =&gt; x
  }
</pre></p>
<p>At above&#8217;s code, we can see that a node can be defined with or without parenthesis. However, when not caring about the node, thus, not identifying it, you must at least use the parenthesis, otherwise, SyntaxException will be thrown.</p>
<p>Now, it is possible to take a look at how the <code>path</code>s are transformed. At <code>path</code> definition, we saw that it can be composed by either path with and without parenthesis or a <code>pathSegment</code>.</p>
<p><pre class="brush: scala;">
  def path: Parser[Any] = pathSegment | parenPath | noParenPath

  def parenPath: Parser[NamedPath] = identity ~ &quot;=&quot; ~ &quot;(&quot; ~ pathSegment ~ &quot;)&quot; ^^ {
    case p ~ &quot;=&quot; ~ &quot;(&quot; ~ pathSegment ~ &quot;)&quot; =&gt; NamedPath(p, pathSegment: _*)
  }

  def noParenPath: Parser[NamedPath] = identity ~ &quot;=&quot; ~ pathSegment ^^ {
    case p ~ &quot;=&quot; ~ pathSegment =&gt; NamedPath(p, pathSegment: _*)
  }
</pre></p>
<p>Looking at the code, both <code>parenPath</code> and <code>noParenPath</code> parsers are doing simple transformations to create <code>NamedPath</code> objects with the identity (the <code>p</code> variable) and the <code>pathSegment</code>, which contains all the information of the path.</p>
<p>The <code>pathSegment</code> parser is a little more complicated and it parses for the <code>node</code> followed by the repetition of the <code>relatedTail</code> (already defined above).</p>
<p><pre class="brush: scala;">
  def pathSegment: Parser[List[Pattern]] = node ~ rep1(relatedTail) ^^ {
    case head ~ tails =&gt; {
      var fromNode = namer.name(head)

      val list = tails.map(_ match {
        case (back, rel, relType, forward, end, varLength, optional) =&gt; {
          val toNode = namer.name(end)
            val dir = getDirection(back, forward)

          val result: Pattern = varLength match {
            case None =&gt; RelatedTo(fromNode, toNode, namer.name(rel), relType, dir, optional)
            case Some((minHops, maxHops)) =&gt; VarLengthRelatedTo(namer.name(None), fromNode, toNode, minHops, maxHops, relType, dir, optional)
          }

          fromNode = toNode

          result
        }
      })

      list
    }
  }
</pre></p>
<p>The first thing is to match the <code>node</code> part and the <code>relatedTail</code>, interestingly identified as <code>head</code> and <code>tails</code>, respectively. Then it finds the name of the node. However, remember that it can be unnamed, which in this case, a little trick is done inside the name method at line 3.</p>
<p><pre class="brush: scala;">
  class NodeNamer {
    var lastNodeNumber = 0

    def name(s: Option[String]): String = s match {
      case None =&gt; {
        lastNodeNumber += 1
        &quot;  UNNAMED&quot; + lastNodeNumber
      }
      case Some(x) =&gt; x
    }
  }
</pre></p>
<p>The <code>NodeNamer</code> class creates a counter for the unnamed nodes, so it can uniquely name them, and if the node is already named, it will return the given name itself. Small curiosity here, is that one might identify a node as UNNAMED1 and also not identify another node in the query, which will make two nodes being called UNNAMED1 <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Continuing on the <code>pathSegment</code> method, between line 5 and 19 the list of the related tails is transformed into a list of <code>Pattern</code> (the <code>result</code> val created at line 10). These <code>result</code>s are aggregated by the <code>map</code> method and in the end, is returned to the <code>list</code> val at line 5, which is returned at line 21.</p>
<p>All of these operations are unleashed by the <code>matching</code> clause, which transforms all the previously parsed pieces in a tuple of <code>Match</code> and <code>NamedPaths</code>:</p>
<p><pre class="brush: scala;">

  def matching: Parser[(Match, NamedPaths)] = ignoreCase(&quot;match&quot;) ~&gt; rep1sep(path, &quot;,&quot;) ^^ {
    case matching =&gt; {
      val unamedPaths: List[Pattern] = matching.filter(_.isInstanceOf[List[Pattern]]).map(_.asInstanceOf[List[Pattern]]).flatten
      val namedPaths: List[NamedPath] = matching.filter(_.isInstanceOf[NamedPath]).map(_.asInstanceOf[NamedPath])

      (Match(unamedPaths: _*), NamedPaths(namedPaths: _*))
    }
  }
</pre></p>
<p>Phew&#8230; long one! Tired? C&#8217;mon, there is more clauses to tackle, but thankfully, the most extense is over.</p>
<h3>The Where Clause</h3>
<p>Ahh the where clause. With their longs 3 lines of code, seems very simple and think that can fool us, take a look:</p>
<p><pre class="brush: scala;">

trait WhereClause extends JavaTokenParsers with Tokens with Clauses {
  def where: Parser[Clause] = ignoreCase(&quot;where&quot;) ~&gt; clause
}
</pre></p>
<p>That&#8217;s it. But digging deeper, what the heck is <code>clause</code>? In fact, it is a definition derived by the <code>Clauses</code> trait, that is almost self explanatory, so let&#8217;s check just the main clause:</p>
<p><pre class="brush: scala;">

  def clause: Parser[Clause] = (orderedComparison | not | notEquals | equals | regexp | hasProperty | parens | sequenceClause) * (
    ignoreCase(&quot;and&quot;) ^^^ { (a: Clause, b: Clause) =&gt; And(a, b)  } |
    ignoreCase(&quot;or&quot;) ^^^  { (a: Clause, b: Clause) =&gt; Or(a, b) }
    )
</pre></p>
<p>It takes possibilities for the where clause, such as &gt;, &gt;=, not equals (that can be both &lt;&gt; or != and so on. The <code>*</code> combinator, means that it will be interleaved with the right side (the <code>and/or</code>) and the right side will determine how the transformation will be made, in that case, in a <code>And</code> or <code>Or</code> objects, with both left and right side clauses. By the way, the <code>^^^</code> transformation operator, means that it is changing the successful result by what is following it, in this case, the <code>And</code> or <code>Or</code> objects.</p>
<p>You can take a look at the <code>Clauses</code> trait in the repository for more details on the syntax. There is no other new things on the trait, so, by now, it might be a good exercise to do.</p>
<h3>The Return Clause</h3>
<p>How Cypher parses what we want our query to return? The answer for this question is in the <code>ReturnClause</code> trait. It is a simple parse, without tricks, so let&#8217;s get into the trait:</p>
<p><pre class="brush: scala;">
trait ReturnClause extends JavaTokenParsers with Tokens with ReturnItems {

  def returns: Parser[(Return, Option[Aggregation])] = ignoreCase(&quot;return&quot;) ~&gt; opt(&quot;distinct&quot;) ~ rep1sep((aggregate | returnItem), &quot;,&quot;)
</pre></p>
<p>The <code>returns</code> method is defined by a <code>return</code> keyword, followed by an optional <code>distinct</code> definition with a repetition of an <code>aggregate</code> or a <code>returnItem</code>, which are defined in the <code>ReturnItems</code> trait, which defines the aggregate functions, such as min(), max(), avg() and so on and the possible <code>returnValues</code>, such as an <code>entity</code>, a <code>value</code> or a <code>nullableProperty</code>.</p>
<p><pre class="brush: scala;">
trait ReturnItems extends JavaTokenParsers with Tokens with Values {
  def returnItem: Parser[ReturnItem] = returnValues ^^ {
    case value =&gt; ValueReturnItem(value)
  }

  def returnValues: Parser[Value] = nullableProperty | value | entityValue

  def countFunc: Parser[AggregationItem] = ignoreCase(&quot;count&quot;) ~&gt; parens(returnValues) ^^ { case inner =&gt; ValueAggregationItem(Count(inner)) }
  def sumFunc: Parser[AggregationItem] = ignoreCase(&quot;sum&quot;) ~&gt; parens(returnValues) ^^ { case inner =&gt; ValueAggregationItem(Sum(inner)) }
  def minFunc: Parser[AggregationItem] = ignoreCase(&quot;min&quot;) ~&gt; parens(returnValues) ^^ { case inner =&gt; ValueAggregationItem(Min(inner)) }
  def maxFunc: Parser[AggregationItem] = ignoreCase(&quot;max&quot;) ~&gt; parens(returnValues) ^^ { case inner =&gt; ValueAggregationItem(Max(inner)) }
  def avgFunc: Parser[AggregationItem] = ignoreCase(&quot;avg&quot;) ~&gt; parens(returnValues) ^^ { case inner =&gt; ValueAggregationItem(Avg(inner)) }
  def countStar: Parser[AggregationItem] = ignoreCase(&quot;count&quot;) ~&gt; parens(&quot;*&quot;) ^^ { case &quot;*&quot; =&gt; CountStar()  }

  def aggregate:Parser[AggregationItem] = (countStar | countFunc | sumFunc | minFunc | maxFunc | avgFunc)
}
</pre></p>
<p>Getting back to the <code>ReturnClause</code> trait, let&#8217;s take a look at the complete code and examine the transformation:</p>
<p><pre class="brush: scala;">
  def returns: Parser[(Return, Option[Aggregation])] = ignoreCase(&quot;return&quot;) ~&gt; opt(&quot;distinct&quot;) ~ rep1sep((aggregate | returnItem), &quot;,&quot;) ^^
    { case distinct ~ items =&gt; {
      val list = items.filter(_.isInstanceOf[AggregationItem]).map(_.asInstanceOf[AggregationItem])

      val none: Option[Aggregation] = distinct match {
        case Some(x) =&gt; Some(Aggregation())
        case None =&gt; None
      }

      (
        Return(items.filter(!_.isInstanceOf[AggregationItem]): _*),
        list match {
          case List() =&gt; none
          case _ =&gt; Some(Aggregation(list : _*))
        }
      )
    }}
</pre></p>
<p>The transformation creates a list of <code>AggregationItem</code>s and assign it to the <code>list</code> val at line 3. Then it does a matching against the distinct part, and if informed, assign an aggregation to the <code>none</code> val, otherwise, it will assign a <code>None</code>, which is an object that represents no value, in Scala.</p>
<p>At line 11, it prepares the result produced by the parser, which must by a tuple between a <code>Return</code> object and the <code>Option[Aggregation]</code> indicating that the distinct was or wasn&#8217;t set.</p>
<p>In regard to the <code>Return</code>, it takes all <code>items</code> defined to be returned and returns only those that aren&#8217;t aggregation items. While all the aggregation items are store now in the <code>list</code> val, which is matched at line 12. In case of being an empty list, just return the result of the aggregation checked, otherwise, take all the <code>AggregationItem</code>s, and store it inside the <code>Aggregation</code> object to be returned within the tuple. The result will be a <code>(Return, Option[Aggregation])</code> tuple.</p>
<h3>The OrderBy Clause</h3>
<p>We can always define how the results will be ordered and by which results. Parsing the order by part of the query is the job of the <code>OrderByClause</code> trait, which defines the <code>order</code> method.</p>
<p><pre class="brush: scala;">
def order: Parser[Sort] = ignoreCase(&quot;order by&quot;)  ~&gt; rep1sep(sortItem, &quot;,&quot;) ^^
    {
      case items =&gt; Sort(items:_*)
    }
</pre></p>
<p>Nothing new here, therefore, let&#8217;s check the <code>sortItem</code> definition.</p>
<p><pre class="brush: scala;">
  def sortItem :Parser[SortItem] = (aggregate | returnItem) ~ ascOrDesc ^^ {
    case returnItem ~ reverse =&gt; {
      returnItem match {
        case ValueReturnItem(EntityValue(_)) =&gt; throw new SyntaxException(&quot;Cannot ORDER BY on nodes or relationships&quot;)
        case _ =&gt; SortItem(returnItem, reverse)
      }
    }
  }
</pre></p>
<p>The <code>aggregate</code> is where we can use a <code>sum()</code> or <code>max()</code> function to return something, while a <code>returnItem</code> can be a <code>nullableProperty</code> or an identifier, and after it, is verified if the ordering must be <code>asc</code> or <code>desc</code>.</p>
<p>In the case of the <code>returnItem</code> being a node or a relationship, the SyntaxException is thrown, since it doesn&#8217;t make sense on ordering in anything that is not an aggregate or a property.</p>
<p>In the end, the <code>Sort</code> object with the items to where the sorting will be performed is generated to the AST.</p>
<h3>The Skip and Limit Clause</h3>
<p>A simple one to finish this combo. The &lt;&gt;SkipLimitClause is the simplest clause amongst all the other ones. It&#8217;s composed by to definitions, the <code>skip</code> and the <code>limit</code>:</p>
<p><pre class="brush: scala;">
trait SkipLimitClause extends JavaTokenParsers with Tokens {
  def skip: Parser[Int] = ignoreCase(&quot;skip&quot;) ~&gt; positiveNumber ^^ { case startAt =&gt; startAt.toInt }

  def limit: Parser[Int] = ignoreCase(&quot;limit&quot;) ~&gt; positiveNumber ^^ { case count =&gt; count.toInt }
}
</pre></p>
<p>Taking a look at the code, we can see in both instructions, the keywords (skip and limit) being ignored and we can also see that it demands a positive number. And the transformation only converts the result, which is a String, to an Int.</p>
<h2>The entry point, where everything starts. Also, where everything ends</h2>
<p>Now that we know how each clause is defined, it is possible put them in sequence. So, in the query first will come the Start clause, then the Match clause and so on. This is one of the responsibilities of the CypherParser class, which is defined as:</p>
<p><pre class="brush: scala;">class CypherParser extends JavaTokenParsers
with StartClause
with MatchClause
with WhereClause
with ReturnClause
with SkipLimitClause
with OrderByClause
with StringExtras {
   // code will come here
}
</pre></p>
<p>Note that the CypherParser class is composed by all of the clause&#8217;s before discussed traits, therefore, making possible the use of the definitions made on each clause trait. Continuing on the CypherParser class, we have the <code>query</code> method, which uses the pieces defined before:</p>
<p><pre class="brush: scala;">
def query: Parser[Query] = start ~ opt(matching) ~ opt(where) ~ returns ~ opt(order) ~ opt(skip) ~ opt(limit)
</pre></p>
<p>Taking a look at the <code>query</code> method, we can see that the whole query itself, is defined by a mandatory <code>start</code> clause, an optional <code>match</code> clause and <code>where</code>, followed by a mandatory <code>return</code> clause and an optional <code>skip</code> and <code>limit</code> clauses. All of these small methods were explained before in this post (again, the <code>start</code> was explained on the first post).</p>
<p>Now that the query is defined, we should transform it in a AST and the way this is done in Cypher is as the following:</p>
<p><pre class="brush: scala;">
  def query: Parser[Query] = start ~ opt(matching) ~ opt(where) ~ returns ~ opt(order) ~ opt(skip) ~ opt(limit) ^^ {

    case start ~ matching ~ where ~ returns ~ order ~ skip ~ limit =&gt; {
      val slice = (skip,limit) match {
        case (None,None) =&gt; None
        case (s,l) =&gt; Some(Slice(s,l))
      }

      val (pattern:Option[Match], namedPaths:Option[NamedPaths]) = matching match {
        case Some((p,NamedPaths())) =&gt; (Some(p),None)
        case Some((Match(),nP)) =&gt; (None,Some(nP))
        case Some((p,nP)) =&gt; (Some(p),Some(nP))
        case None =&gt; (None,None)
      }

      Query(returns._1, start, pattern, where, returns._2, order, slice, namedPaths)
    }
  }
</pre></p>
<p>One step at a time. First thing that is done is the pattern matching against the result, therefore, checking that everything is in place. Then, some specific matches are done. The first one against a <code>(skip, limit)</code> tuple at line 4. If none of them is passed, a <code>None</code> object is returned and assigned to the <code>slice</code> val at line 4. Otherwise, a <code>Some</code> object containing a <code>Slice</code> with the skip and limit values is assigned to <code>slice</code>. The <code><a href="https://github.com/neo4j/community/blob/665a6833a459fab5c9b9db529da454c80d79f96d/cypher/src/main/scala/org/neo4j/cypher/commands/Query.scala#L46" target="_blank">Slice</a></code> class definition is as simple as:</p>
<p><pre class="brush: scala;">
case class Slice(from: Option[Int], limit: Option[Int])
</pre></p>
<p>The second operation being done on the code, starting at line 9, deals with the match clause that was done. It matches if the match clause was done with and/or without named paths and patterns. If both have been used, it creates a <code>Some</code> object containing both the pattern and the named paths used, if just one of them is defined, the unused one will become a <code>None</code> object. In the end, both will be assigned to a tuple representing the pattern used and the named paths used.</p>
<p>Then, a <code>Query</code> object is constructed, with all the results of the before applied parsers. And we now have a complete AST, with the <code>Query</code> as its starting point. We can see the <code>Query</code> class definition:</p>
<p><pre class="brush: scala;">
case class Query(returns: Return, start: Start, matching: Option[Match], where: Option[Clause], aggregation: Option[Aggregation],
                 sort: Option[Sort], slice: Option[Slice], namedPaths: Option[NamedPaths])
</pre></p>
<p>The only missing piece to reach at the CypherParser class is the <code>parse(queryText: String)</code> method, whose work is to simply delegate the <code>queryText</code> processing to Scala&#8217;s Parser Combinators library. In case of success, the result (the <code>Query</code> object) is returned. If it is not successful, the appropriate error message is used to indicate that the parsing process failed. Below, is the complete code for the <code>parse</code> method:</p>
<p><pre class="brush: scala;">
  @throws(classOf[SyntaxException])
  def parse(queryText: String): Query = {
    val MissingQuoteError = &quot;&quot;&quot;`\.' expected but `.' found&quot;&quot;&quot;.r
    val MissingStartError = &quot;&quot;&quot;string matching regex `\(\?i\)\\Qstart\\E' expected.*&quot;&quot;&quot;.r
    val WholeNumberExpected = &quot;&quot;&quot;string matching regex `\\d\+' expected.*&quot;&quot;&quot;.r
    val StringExpected = &quot;&quot;&quot;string matching regex `'\(\[\^'\\p\{Cntrl\}\\\\\]\|\\\\\[\\\\\/bfnrt\]\|\\\\u\[a-fA-F0-9\]\{4\}\)\*'' .*&quot;&quot;&quot;.r

    parseAll(query, queryText) match {
      case Success(r, q) =&gt; r
      case NoSuccess(message, input) =&gt; message match {
        case MissingQuoteError() =&gt; fail(input, &quot;Probably missing quotes around a string&quot;)
        case MissingStartError() =&gt; fail(input, &quot;Missing START clause&quot;)
        case WholeNumberExpected() =&gt; fail(input, &quot;Whole number expected&quot;)
        case StringExpected() =&gt; fail(input, &quot;String literal expected&quot;)
        case &quot;string matching regex `-?\\d+' expected but `)' found&quot; =&gt; fail(input, &quot;Last element of list must be a value&quot;)
        case &quot;string matching regex `(?i)\\Qreturn\\E' expected but end of source found&quot; =&gt; throw new SyntaxException(&quot;Missing RETURN clause&quot;)
        case _ =&gt; throw new SyntaxException(message)
      }
    }
  }
</pre></p>
<p>Now we have a complete parser. Which does parse the whole query and generates an AST or an error message if something went wrong during the parsing process.</p>
<h2>Coming up next</h2>
<p>After the parsing process happened successfully, we have built all the AST. Which means, it is now possible to take some action over it. However, we are not sure that the generated AST will be what we were expecting. We are not sure that the parser works correctly (it works, but just pretend by now that we are not sure <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). In the next part, I&#8217;ll cover how the unit testing of the AST was made and how Neo4j guys did an amazing job to generate documentation through the tests.</p>
<br />Filed under: <a href='http://ahalmeida.com/category/neo4j/'>neo4j</a>, <a href='http://ahalmeida.com/category/opensource/'>OpenSource</a>  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/248/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/248/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/248/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/248/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/248/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/248/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/248/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/248/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/248/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/248/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/248/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/248/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/248/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/248/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=248&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2011/09/22/neo4js-cypher-internals-part-2-all-clauses-more-scalas-parser-combinators-and-query-entry-point/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>How Neo4j uses Scala&#8217;s Parser Combinator: Cypher&#8217;s internals &#8211; Part 1</title>
		<link>http://ahalmeida.com/2011/09/06/how-neo4j-uses-scalas-parser-combinator-cyphers-internals-part-1/</link>
		<comments>http://ahalmeida.com/2011/09/06/how-neo4j-uses-scalas-parser-combinator-cyphers-internals-part-1/#comments</comments>
		<pubDate>Tue, 06 Sep 2011 12:47:57 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[neo4j]]></category>
		<category><![CDATA[OpenSource]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=201</guid>
		<description><![CDATA[Introduction I think that most of us, software developers, while kids, always wanted to know how things were made by inside. Since I was a child, I always wanted to understand how my toys worked. And then, what I used to do? Opened&#8217;em, sure. And of course, later, I wasn&#8217;t able to re-join its pieces [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=201&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>I think that most of us, software developers, while kids, always wanted to know how things were made by inside. Since I was a child, I always wanted to understand how my toys worked. And then, what I used to do? Opened&#8217;em, sure. And of course, later, I wasn&#8217;t able to re-join its pieces properly, but this is not this post subject <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . Well, understanding how things works behind the scenes can teach us several things, and in software this is no different, and we can study how an specific piece of code was created and mixed together with other code.</p>
<p><a href="http://ahalmeida.files.wordpress.com/2011/09/cypher.jpg"><img class="size-medium wp-image-232 alignleft" title="cypher" src="http://ahalmeida.files.wordpress.com/2011/09/cypher.jpg?w=300&#038;h=190" alt="" width="300" height="190" /></a>In this series of posts I&#8217;ll share what I&#8217;ve found inside <a title="Neo4j" href="http://neo4j.org" target="_blank">Neo4J</a> implementation, specifically, at <a title="Cypher" href="http://docs.neo4j.org/chunked/stable/cypher-query-lang.html" target="_blank">Cypher&#8217;s</a> code (its query language).</p>
<p>In this first part, I&#8217;ll briefly introduce Neo4J and Cypher and then I&#8217;ll start to explain the internals of its parser and how it works. Since it is a long (very very long subject, in fact), part 2 and subsequents are coming very very soon.</p>
<p>And BTW, <strong>this is a very long post</strong>, so, if you prefer, go grab a nice cup of coffee or tea, a jar of juice, something to eat, and then, come back to read.</p>
<h2>First of all, what is Neo4J?</h2>
<p>We are all very used to the relational paradigm, however, everyday, non relational databases receives more and more attention from the community. That happens for several reasons, including, better data modeling, improved scalability, sky rocketing performance enhancements and so on. Non relational databases became popular by the name of <a title="NOSQL" href="http://nosql-database.org/" target="_blank">NOSQL</a>, and several implementations exists, such as <a title="Riak" href="http://www.basho.com/" target="_blank">Riak</a>, <a title="Redis" href="http://redis.io/" target="_blank">Redis</a>, <a title="CouchDB" href="http://couchdb.apache.org/" target="_blank">CouchDB</a>, <a title="MongoDB" href="http://www.mongodb.org/" target="_blank">MongoDB</a> and <a title="HBase" href="http://hbase.apache.org/" target="_blank">lots</a> of <a title="Kyoto" href="http://fallabs.com/kyotocabinet/" target="_blank">others</a>.</p>
<p>Each one of these implementations do have its particularities and some are better suited for a kind of problem and others are better suited to another kind of problems. Within these implementations, we can highlight Neo4J, which is a fully ACID compliant graph database, which means your data are as graphs (with nodes, relationships and properties on them), thus, having high speed through graph traversals (<a href="http://twitter.com/#!/iansrobinson/status/68627385418919936" target="_blank">and we all know that storing graph like data inside a relational database is not a good idea</a>).</p>
<p>For a more interesting introduction to Neo4J, you can check <a href="http://www.infoq.com/presentations/Neo4j-NOSQL-and-Graph-Databases" target="_blank">Emil Eifrem&#8217;s presentation</a> and this nice <a href="http://www.infoq.com/articles/graph-nosql-neo4j" target="_blank">InfoQ post</a>.</p>
<h2>How to find data on the graph?</h2>
<p>So, let&#8217;s consider the following problem:<em> &#8220;I want to know who are all the employees that paired programmed with a given programmer&#8221;.</em></p>
<p>In order to solve retrieve informations from the graph, Neo4J provides an <a href="http://docs.neo4j.org/chunked/stable/tutorials-java-embedded-traversal.html" target="_blank">API</a> which allows us to traverse the graph and retrieve this information. With this traversal API, we can write Java code to describe how we want to traverse the graph:</p>
<p><pre class="brush: java;">
TraversalDescription description = Traversal.description()
    .breadthFirst()
    .relationships(Relationships.PAIRED, Direction.OUTGOING)
    .evaluator(Evaluators.excludeStartPosition());

description.traverse( startNode ); // Retrieves the traverser
</pre></p>
<p>Besides the traversal described above works pretty well, people may seem confused with all these Java code describing the traversal, and those who want to use Neo4J <a href="http://neo4j.rubyforge.org/guides/index.html" target="_blank">within JRuby</a>, for instance, might have to adapt its code in order to achieve the same result. Another issue may be a Sysadmin wanting to perform ad-hoc queries on the database. How make this easily possible, without having to write Java code? Huumm, ohh well, why not we have a single query language which we can define traversals. Then comes Cypher, the Neo4J query language.</p>
<p>With Cypher, above&#8217;s traversal would be described as:</p>
<pre>start programmer=(3) match (programmer)-[:PAIRED]-&gt;(pair) return pair</pre>
<p>In this example, 3 means the starting node&#8217;s id of our query. We are also matching the relationships called PAIRED outgoing from the <code>programmer</code> and labeling the incoming node as <code>pair</code>. In the end, we&#8217;re telling we want to return all the retrieved pairs. That&#8217;s it.</p>
<p>We can even do more complex things on our traversal, for instance, we can apply filters to values, ordering, aggregation, pagination and so on. Thus, we can retrieve only the pairs whose age are more than 30 years (considering that we have an age property).</p>
<pre>start programmer=(3) match (programmer)-[:PAIRED]-&gt;(pair) where pair.age &gt; 30 return pair, count(*) order by age skip 5 limit 10</pre>
<p>Imagine doing all these things, writing the Java code. Sure it is possible, however, not so straightforward as Cypher. And believe me, there is much more combinations and complex queries you can do.</p>
<h2>Defining Cypher</h2>
<p>Cypher is an <a href="http://martinfowler.com/bliki/DomainSpecificLanguage.html" target="_blank">external DSL</a>, just like <a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html" target="_blank">HQL (Hibernate Query Language)</a> and the <a href="http://www.eclipse.org/aspectj/doc/next/progguide/examples-basic.html#examples-joinPoints" target="_blank">AspectJ syntax</a>, for instance. Therefore, somewhere it needs to be parsed, its correctness must be checked and then it should be executed, in Cypher&#8217;s case, retrieving the results we asked for.</p>
<p>But, in order to write an external DSL, we should define its grammar, which will give the guidelines of how the language is supposed to be structured and what is and isn&#8217;t valid. In order to express this definition, we can use some variation of <a href="http://www.garshol.priv.no/download/text/bnf.html" target="_blank">EBNF syntax</a>, which provides us a clear way to expose the language definition.</p>
<p>First of all, let&#8217;s choose a small subset of Cypher to describe, which will be the focus of this first post, in this case, the <code>start</code> clause, where we have defined the id we wanted to retrieved and we named our starting point <code>programmer</code>. Taking a look at the EBNF definition, we would have something like the following:</p>
<pre>start ::= "start" {"," nodeByIds | nodeByIndex | nodeByIndexQuery | relsByIds | relsByIndex }

nodeByIds ::= identity "=" "(" {"," number} ")"

nodeByIndex ::= identity "=" "(" identity "," identity "," string ")"

nodeByIndexQuery ::= identity "=" "(" identity "," string ")"

relsByIds ::= identity "=" "&lt;" { "," number } "&gt;"

relsByIndex ::= identity "=" "&lt;" identity "," identity "," string "&gt;"</pre>
<p>Above, <code>identity</code> is an identifier, for instance, the &#8220;<code>programmer</code>&#8221; identifier, &#8220;<code>{}</code>&#8221; means that whatever is inside, can appears repeatedly and with a separator, while | is denoting alternative production.</p>
<p>With that information, now we know that in order to write a proper start clase, we can&#8217;t use semi-colon as a separator, we must use parenthesis to group the ids, and we can have as much ids as we want. Easy right?</p>
<p>Now that we have a grammar defined for the start clause, we must have a way put it into action, which mean, we must parse a given instruction, check its validity and then take some action with what instruction was informed.</p>
<h2>Parsing, Cypher and Parser Combinators</h2>
<p>One possibility to parse the query is to use a parser generator tool, like Antlr or YACC. However, some functional programming languages, such as Scala and Haskell, provides an embedded tool to make possible to parse these languages. That tool is known as Parser Combinator. In this case, Cypher uses Scala&#8217;s Parser Combinator library. If you don&#8217;t have any familiarity with Parsers and Parser Combinators, you can check <a href="http://www.google.com.br/url?sa=t&amp;source=web&amp;cd=2&amp;ved=0CCEQFjAB&amp;url=http%3A%2F%2Fciteseerx.ist.psu.edu%2Fviewdoc%2Fdownload%3Fdoi%3D10.1.1.142.5002%26rep%3Drep1%26type%3Dpdf&amp;ei=7aVlTor3EMW9tgeK-sWJCg&amp;usg=AFQjCNGlwaejNUTGmlj_RJhkNA1YN3sLGA&amp;sig2=g4ZdSoJoXzpazN1d5zeM2Q" target="_blank">this excellent article</a> from Odersky and Moors.</p>
<p>Remember the start clause previously described? We can describe it in a <strong>very</strong> similar way in Scala. In fact, Neo4J&#8217;s Cypher codebase have a <a href="http://www.scala-lang.org/node/126" target="_blank">trait</a>, which is very similar to a Java interface, called <code><a href="https://github.com/neo4j/community/blob/master/cypher/src/main/scala/org/neo4j/cypher/parser/StartClause.scala" target="_blank">StartClause</a></code>, with the definition we did above, with just a few changes on the syntax we used.</p>
<p><pre class="brush: scala;">
def start: Parser[Start] = ignoreCase(&quot;start&quot;) ~&gt; rep1sep(nodeByIds | nodeByIndex | nodeByIndexQuery | relsByIds | relsByIndex, &quot;,&quot;)

def nodeByIds = identity ~ &quot;=&quot; ~ &quot;(&quot; ~ rep1sep(wholeNumber, &quot;,&quot;) ~ &quot;)&quot;

def nodeByIndex = identity ~ &quot;=&quot; ~ &quot;(&quot; ~ identity ~ &quot;,&quot; ~ identity ~ &quot;,&quot; ~ string ~ &quot;)&quot;

def nodeByIndexQuery = identity ~ &quot;=&quot; ~ &quot;(&quot; ~ identity ~ &quot;,&quot; ~ string ~ &quot;)&quot;

def relsByIds = identity ~ &quot;=&quot; ~ &quot;
def relsByIndex = identity ~ &quot;=&quot; ~ &quot;</pre></p>
<p>The code above looks very similar to the EBNF alike we did before, we just translated the syntax to Scala language, except about a few nuances. For instance, in this example, we use the <code>~</code> method, that represents a sequence, before we represented the sequence, simply placing elements from left to right. We also used the <code>rep1sep</code> method means a repetition with a separator (the same effect of &#8220;<code>{}</code>&#8221; on the EBNF example).</p>
<p>However, where are these <code>~</code> and <code>rep1sep</code> methods defined? In fact, looking at the <code>StartClause</code> trait definition, we have:</p>
<p><pre class="brush: scala;">
trait StartClause extends JavaTokenParsers with Tokens {
  // code here
}
</pre></p>
<p>The <a href="http://www.scala-lang.org/api/current/scala/util/parsing/combinator/JavaTokenParsers.html" target="_blank"><code>JavaTokenParsers</code> trait itself</a>, comes from the <code><a href="http://www.scala-lang.org/api/current/scala/util/parsing/combinator/Parsers.html" target="_blank">scala.util.parsing.combinator.Parsers</a></code> trait (keep that in mind, it will be very important in the future), which defines <code>~</code> and the <code>rep1sep</code> amongst some other methods which we&#8217;ll talk later.</p>
<p>So far, so good, <strong>but I&#8217;ve cheated a little bit</strong>, the history (and the code) is not yet complete.</p>
<p>While parsing the given input (a query sample) against the defined grammar, we can get back the results, so we can process it later, for instance, we can grab the identifier used in the start clause, node ids and so on, and then, with these information, it is possible to perform the desired traversal.</p>
<p>Scala&#8217;s Parser Combinator allows us to grab all these informations in the form of a Semantic Model, which can better describe these informations, thus, instead of grabbing bare Strings and a List of node ids, it is possible transform them in an object, representing these informations, for instance, in the case of a query by ids, we could get an instance of a <code>NodeById</code> class, or in the case of querying by index, we could get a <code>NodeByIndex</code> instance. And Hell Yeah, we can do this, by using the <code>^^</code>, which allow us to apply a function against the parser result, allowing us to build the Semantic Model we want as the AST (Abstract Syntax Tree). In this case, the portion of the tree that represents querying by a node id, is an object of the <code>NodeById</code> class.</p>
<p>We can use the <code>^^</code> operator in a pattern matching way, matching the parts of the query we want, in order to form any other result, which in the case of the <code>nodeByIds</code> method in Cypher&#8217;s <code>StartClause</code>, is the following:</p>
<p><pre class="brush: scala;">
def nodeByIds = identity ~ &quot;=&quot; ~ &quot;(&quot; ~ rep1sep(wholeNumber, &quot;,&quot;) ~ &quot;)&quot; ^^ {
  case varName ~ &quot;=&quot; ~ &quot;(&quot; ~ id ~ &quot;)&quot; =&gt; NodeById(varName, id.map(_.toLong).toSeq: _*)
}
</pre></p>
<p>What happens in above code is that, it matches against what was got during the parsing, and <code>varName</code> will be the variable name used on the query, while the <code>id</code> is a List of ids, which later gets transformed to an splat (varargs) of Longs, in the somewhat strange <code>_*</code> if your are not used to Scala, and passed to the <code>NodeById</code> constructor. The <code>NodeById</code> instance is then returned from the <code>nodeByIds</code> method.</p>
<p>However, since the class <code>StartClause</code> is composed by the <code>scala.util.parsing.combinator.Parsers</code> trait, an implicit conversion defined there, will promote the <code>NodeById</code> object that is returning to an object of Parser[NodeById], so it can keep parsing the rest of the input (the match clause, where clause and so on, recursively, other parts, that will be covered on the next post).</p>
<p>Taking a look at the <code>NodeById</code> class, we can see its definition, inside the <code><a href="https://github.com/neo4j/community/blob/master/cypher/src/main/scala/org/neo4j/cypher/commands/StartItem.scala" target="_blank">StartItem.scala</a></code> file:</p>
<p><pre class="brush: scala;">
case class NodeById(varName:String, id: Long*) extends NodeStartItem(varName)

abstract class NodeStartItem(varName:String) extends StartItem(varName)

abstract sealed class StartItem(val variable:String)
</pre></p>
<p>Notice 2 important things here: First, that these classes has no behavior, they just hold the data for the Semantic Model. And looking at the same file, is possible to find all the other classes used to form the Semantic Model of the Start Clause, such as, <code>NodeByIndex</code>, <code>RelationshipById</code> and so on. And second, there is a hierarchy between them. The <code>NodeById</code> class extends the <code>NodeStartItem</code> which comes from the <code>StartItem</code>. Looking further in the StartItem.scala file, we see that all classes that form this Semantic Model, follow this hierarchy. The complete code of the <code>StartItem.scala</code> file, looks like:</p>
<p><pre class="brush: scala;">
abstract sealed class StartItem(val variable:String)

abstract class RelationshipStartItem(varName:String) extends StartItem(varName)

abstract class NodeStartItem(varName:String) extends StartItem(varName)

case class RelationshipById(varName:String, id: Long*) extends RelationshipStartItem(varName)

case class NodeByIndex(varName:String, idxName: String, key:String, value: Any) extends NodeStartItem(varName)

case class NodeByIndexQuery(varName:String, idxName: String, query: Any) extends NodeStartItem(varName)

case class RelationshipByIndex(varName:String, idxName: String, key:String, value: Any) extends RelationshipStartItem(varName)

case class NodeById(varName:String, id: Long*) extends NodeStartItem(varName)
</pre></p>
<p>This complete code, makes easier to see the hierarchy existing between the classes involved in the AST definition.</p>
<h2>Back to the StartClause trait</h2>
<p>Taking a further look at the other methods inside the <code>StartClause</code> trait, such as, the <code>nodeByIndex</code>, <code>nodeByIndexQuery</code>, the rules are the same (except for the <code>start</code> method, that I&#8217;ll talk next).</p>
<p>The <code>start</code> method follow the same rules as the other ones, however, some soe far unexplained things appears on it, which is the <code>~&gt;</code> and <code>|</code> combinators.</p>
<p><pre class="brush: scala;">
def start: Parser[Start] = ignoreCase(&quot;start&quot;) ~&gt; rep1sep(nodeByIds | nodeByIndex | nodeByIndexQuery | relsByIds | relsByIndex, &quot;,&quot;) ^^ (Start(_: _*))
</pre></p>
<p>The <code>~&gt;</code> is the selective sequence combinator, which in this case, means, &#8220;ignore what is immediately in the left&#8221;, in this case, the &#8220;start&#8221; keyword, which doesn&#8217;t mean anything on our Semantic Model. After this, we have a repetition of <code>nodeByIds</code> or <code>nodeByIndex</code> or <code>nodeByIndexQuery</code> and so on, all using a comma separator. Notice that we are combining the five parsers right now (Someone told Parser Combinators?) in order to create the whole <code>start</code> clause.</p>
<p>The last thing the method does is, to transform the list of instances of <code>StartItem</code> (remember the hierarchy defined on the <code>StartItem.scala</code> file?) into a splat (varargs) and pass them to the <code>Start</code> constructor.</p>
<p>A small clarification, for those not used to Scala, is the <code>Start(_: _*)</code>. What this code does is, call the <code>Start</code> class constructor, passing to it an splat (did you see the <code>_*</code>?) of <code>_</code>, which in this case, represents a list of <code>StartItem</code>s.</p>
<p>And that&#8217;s it, now we have the <code>start</code> clause of Cypher demystified. And we even understand how it is composed and works. Now we are half way to understand how the other parts of Cypher are composed. Phew!!!</p>
<h2>1st part&#8217;s conclusion</h2>
<p>At this first part, I hope it was possible to understand how a small subset of Cypher is defined, and how it uses Scala&#8217;s parser combinator for it. But there&#8217;s a lot of other things to see, such as, how the others clauses of Cypher are tied together, how error reporting is done, how the query is executed after the parse process happens and so on.</p>
<p><em>Special thanks to <a href="http://twitter.com/porcelli" target="_blank">@porcelli</a>, for some kind suggestions on this post.</em></p>
<br />Filed under: <a href='http://ahalmeida.com/category/neo4j/'>neo4j</a>, <a href='http://ahalmeida.com/category/opensource/'>OpenSource</a> Tagged: <a href='http://ahalmeida.com/tag/neo4j/'>neo4j</a>, <a href='http://ahalmeida.com/tag/opensource-2/'>opensource</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/201/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/201/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/201/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=201&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2011/09/06/how-neo4j-uses-scalas-parser-combinator-cyphers-internals-part-1/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>

		<media:content url="http://ahalmeida.files.wordpress.com/2011/09/cypher.jpg?w=300" medium="image">
			<media:title type="html">cypher</media:title>
		</media:content>
	</item>
		<item>
		<title>Meu ambiente de desenvolvimento em 7 itens</title>
		<link>http://ahalmeida.com/2010/12/29/meu-ambiente-de-desenvolvimento-em-7-itens/</link>
		<comments>http://ahalmeida.com/2010/12/29/meu-ambiente-de-desenvolvimento-em-7-itens/#comments</comments>
		<pubDate>Wed, 29 Dec 2010 19:49:49 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[ambiente]]></category>
		<category><![CDATA[Comunidade]]></category>
		<category><![CDATA[comunidade]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=183</guid>
		<description><![CDATA[O @abstractj e o @anderson_leite me intimaram a participar da brincadeira então aí vamos nós: Máquina / Sistema Operacional Há algum tempo atrás eu sempre me dividi entre usar Windows e Linux, confesso que nunca tive uma preferência entre um ou outro, então, eu tinha um Desktop com partições meio a meio e as vezes [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=183&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>O <a href="http://twitter.com/abstractj" target="_blank">@abstractj</a> e o <a href="http://twitter.com/anderson_leite">@anderson_leite</a> me intimaram a participar da brincadeira então aí vamos nós:</p>
<p><strong>Máquina / Sistema Operacional</strong></p>
<p>Há algum tempo atrás eu sempre me dividi entre usar Windows e Linux, confesso que nunca tive uma preferência entre um ou outro, então, eu tinha um Desktop com partições meio a meio e as vezes usava uma e por vezes outra.</p>
<p>Desde março de 2009 eu tenho um MacBook alumínio (não, não é o Pro e sim, ele saiu de linha 3 semanas depois q eu comprei) com o Snow Leopard. O coitado está ainda com 2GB e aguentando o tranco, mas vai ser trocado logo logo. Uso direto pra programar e no meu dia-dia (filmes, jogos e afins). Em casa tenho também um Dell, com meio Ubuntu 10.4 e uma outra partição com Windows Vista, mas esse quem vem usando é a patroa.</p>
<p><strong>Editor</strong></p>
<p>Depende da linguagem. Quando mexo com Ruby eu prefiro desenvolver no Vim mesmo enquanto que quando estou no Java eu utilizo o Eclipse (não consegui me habituar ao Eclim). Já mexi bastante com PHP no Zend e no próprio Eclipse e comecei desenvolvendo no Visual Studio 6.0 lá em 2002.</p>
<p>Em alguns momentos pra escrever materiais didáticos utilizo o vim com o plugin pra AFC: <a title="VIM AFC" href="http://github.com/adrianoalmeida7/vim-afc" target="_blank">http://github.com/adrianoalmeida7/vim-afc</a></p>
<p><strong>Terminal</strong></p>
<p>Sempre preferi o bash, então quando usava Windows tratava de colocar um Cygwin.</p>
<p><strong>Browser</strong></p>
<p>Utilizava bastante o Firefox, mas hoje em dia tenho ficado mais no Chrome, apesar de preferir o Firebug ao equivalente nativo do chrome.</p>
<p><strong>Software</strong></p>
<p>Eclipse, Vim, as vezes o TextMate, Keynote, os post-its nativos do mac, Dropbox, Adium, Tweetdeck, Preview, GMail entre outros.</p>
<p><strong>Source-code</strong></p>
<p>Hoje em dia só Git, mas já foi o tempo do SVN, CVS e Source Safe.</p>
<p><strong>Música</strong></p>
<p>Não gosto muito de ouvir música enquanto desenvolvo / escrevo. Prefiro um ambiente mais silencioso, ou o barulho normal da rua. De qualquer forma, muitas vezes deixo o fone no ouvido, mesmo que não esteja tocando nada. Quando escuto música trabalhando prefiro música francesa, mas é raro.</p>
<p><strong>Próximos <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </strong></p>
<p>E o invite pros próximos vai pro <a href="http://twitter.com/davidpaniz" target="_blank">@davidpaniz</a>, <a href="http://twitter.com/gabaiel" target="_blank">@gabaiel</a> e a <a href="http://twitter.com/hannelita" target="_blank">@hannelita</a></p>
<br />Filed under: <a href='http://ahalmeida.com/category/ambiente/'>ambiente</a>, <a href='http://ahalmeida.com/category/comunidade/'>Comunidade</a> Tagged: <a href='http://ahalmeida.com/tag/ambiente/'>ambiente</a>, <a href='http://ahalmeida.com/tag/comunidade-2/'>comunidade</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/183/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/183/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/183/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/183/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/183/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/183/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/183/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/183/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/183/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/183/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/183/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/183/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/183/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/183/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=183&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2010/12/29/meu-ambiente-de-desenvolvimento-em-7-itens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>YQL! Parte 3: Usando tabelas do YQL! em uma aplicação Ruby e Java com Restfulie</title>
		<link>http://ahalmeida.com/2010/10/19/yql-parte-3-usando-tabelas-do-yql-em-uma-aplicacao-ruby-e-java-com-restfulie/</link>
		<comments>http://ahalmeida.com/2010/10/19/yql-parte-3-usando-tabelas-do-yql-em-uma-aplicacao-ruby-e-java-com-restfulie/#comments</comments>
		<pubDate>Tue, 19 Oct 2010 12:54:28 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[restfulie]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yql]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=160</guid>
		<description><![CDATA[Nos dois posts anteriores foi explicado como desenvolver as tabelas do YQL!, inclusive escrevendo o código Javascript para tabelas que envolviam uma lógica mais complexa. Nesse post eu vou mostrar como é possível utilizar uma tabela já criada (usando como exemplo a tabela criada no post anterior) tanto em uma aplicação Ruby quanto em uma [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=160&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Nos <a href="http://ahalmeida.com/2010/08/25/yql-parte-1-o-basico-sobre-busca-de-dados-publicos/" target="_blank">dois</a> <a href="http://ahalmeida.com/2010/09/01/yql-parte-2-criando-novas-tabelas/" target="_blank">posts</a> anteriores foi explicado como desenvolver as tabelas do <a href="http://developer.yahoo.com/yql/console/" target="_blank">YQL!</a>, inclusive escrevendo o código Javascript para tabelas que envolviam uma lógica mais complexa. Nesse post eu vou mostrar como é possível utilizar uma tabela já criada (usando como exemplo a tabela criada no post anterior) tanto em uma aplicação Ruby quanto em uma aplicação Java utilizando o <a href="http://restfulie.caelumobjects.com/" target="_blank">Restfulie</a> para acessar.</p>
<p><strong>O que é o Restfulie?</strong></p>
<p>O Restfulie é uma biblioteca que permite acessar serviços REST através de uma interface agradável. Além disso, os serviços REST podem possuir hypermedia em suas respostas e através da biblioteca é possível navegar sobre os links através da própria API.</p>
<p><strong>Em Ruby com uma aplicação Rails</strong></p>
<p>Considerando que você esteja utilizando RVM (e se não estiver, <a href="http://rvm.beginrescueend.com/" target="_blank">já está na hora</a>) e com o Rails 3 configurado, adicione a gem do Restfulie ao seu Gemfile:</p>
<p><pre class="brush: ruby;">
gem 'restfulie'
</pre></p>
<p>Em seguida, crie um novo controller para conseguirmos fazer uma tela para visualizar os resultados:</p>
<p><pre class="brush: plain;">
rails g controller cursos
</pre></p>
<p>No seu controller, adicione um método novo que fará a ação de buscar as informações da tabela do YQL! e disponibilizar essas informações para a View:</p>
<p><pre class="brush: ruby;">
def index
  #vamos adicionar codigo aqui
end
</pre></p>
<p>No método index vamos declarar duas variáveis, uma para guardar a url do YQL! e outra para armazenar a query que vamos executar. Com isso teremos:</p>
<p><pre class="brush: ruby;">
def index
  base_url = &quot;http://query.yahooapis.com/v1/public/yql&quot;
  query = &quot;use 'http://ahalmeida.me/tabelas_yql/caelum.proximoscursos.xml'; select * from caelum.proximoscursos;&quot;
  #vamos fazer a consulta aqui
end
</pre></p>
<p>O próximo passo é executarmos a consulta com o Restfulie. Para isso, basta adicionarmos o seguinte código:</p>
<p><pre class="brush: ruby;">
Restfulie.at(base_url).get(:q =&gt; query)
</pre></p>
<p>O que o código acima faz é uma requisição get para a <code>base_url</code> passando um parâmetro q cujo valor é a query que desejamos executar. Podemos pegar a resposta desse método get e guardarmos em uma variável. Essa variável guardará uma estrutura de hashes que representa a mesma estrutura do XML devolvido pelo serviço. No caso, o XML devolvido pelo YQL! é algo similar com:</p>
<p><pre class="brush: xml;">
&lt;query xmlns:yahoo=&quot;http://www.yahooapis.com/v1/base.rng&quot;
    yahoo:count=&quot;1&quot; yahoo:created=&quot;2010-10-19T12:51:13Z&quot; yahoo:lang=&quot;en-US&quot;&gt;
    &lt;results&gt;
        &lt;cursos&gt;
            &lt;curso&gt;
                &lt;nome&gt;FJ-26:
Laborat&amp;oacute;rio Web com JSF2 e CDI&lt;/nome&gt;
                &lt;data&gt;23/10 a 27/11&lt;/data&gt;
                &lt;periodo&gt;S&amp;aacute;bado (9:00 as 17:00)&lt;/periodo&gt;
                &lt;cidade&gt;Rio de Janeiro&lt;/cidade&gt;
                &lt;comentario/&gt;
            &lt;/curso&gt;
            &lt;!-- outros cursos aqui ... --&gt;
        &lt;/cursos&gt;
    &lt;/results&gt;
&lt;/query&gt;
</pre></p>
<p>Com isso o código para conseguirmos buscar todos os cursos com o Restfulie dessa estrutura de XML da resposta é:</p>
<p><pre class="brush: ruby;">
resp = Restfulie.at(base_url).get(:q =&gt; query)
@cursos = resp['query']['results']['cursos']['curso']
</pre></p>
<p>Dessa forma a classe CursosController ficaria:</p>
<p><pre class="brush: ruby;">
class CursosController &lt; ApplicationController   
  def index
    base_url = &quot;http://query.yahooapis.com/v1/public/yql&quot;
    query = &quot;use 'http://ahalmeida.me/tabelas_yql/caelum.proximoscursos.xml'; select * from caelum.proximoscursos;&quot;  
    resp = Restfulie.at(base_url).get(:q =&gt; query)
    @cursos = resp['query']['results']['cursos']['curso']
  end
end
</pre></p>
<p>A variável cursos disponibilizada para a view é um Array contendo objetos que possuem as informações dos cursos devolvidas pelo YQL!. Para finalizar podemos criar uma view para o index do Controller que acabamos de fazer e mostrar as informações dos cursos:</p>
<p><pre class="brush: plain;">
&lt;% @cursos.each do |c| %&gt;
  &lt;%= c.nome %&gt;
  &lt;%= c.periodo %&gt;
&lt;% end %&gt;
</pre></p>
<p><strong>Em Java</strong></p>
<p>O processo em Java é similar. Através do Restfulie que está disponível em http://github.com/caelum/restfulie-java você consegue também consumir serviços REST, no entanto é necessário escrever um pouco mais de código do que na versão Ruby, por características da linguagem.</p>
<p>De qualquer maneira, uma vez que tenha baixado o Restfulie e configurado em seu projeto, vai ser necessário representar através de classes a estrutura do XML que será devolvido. No caso da query de cursos da Caelum teremos as seguintes classes:</p>
<p><pre class="brush: java;">
@XStreamAlias(&quot;query&quot;)
public class Query {
    private Results results;
}

@XStreamAlias(&quot;results&quot;)
public class Results {
    private	Cursos cursos;
}

@XStreamAlias(&quot;cursos&quot;)
public class Cursos {
    @XStreamImplicit(itemFieldName=&quot;curso&quot;)
    private List cursos;
}

@XStreamAlias(&quot;curso&quot;)
public class Curso {
    private String nome;
    private String data;
    private String periodo;
    private String cidade;
    private String comentario;
}
</pre></p>
<p>Em seguida podemos criar uma instância do Restfulie e registrar os tipos que desejamos receber:</p>
<p><pre class="brush: java;">
RestClient client = Restfulie.custom();
client.getMediaTypes().register(new XmlMediaType().withTypes(Query.class));
</pre></p>
<p>O próximo passo é executarmos a requisição e pegarmos o objeto que representa o XML e percorrermos todos os cursos:</p>
<p><pre class="brush: java;">
Response response = client.at(&quot;http://query.yahooapis.com/v1/public/yql?q=use%20'http%3A%2F%2Fahalmeida.me%2Ftabelas_yql%2Fcaelum.proximoscursos.xml'%3B%20select%20*%20from%20caelum.proximoscursos%3B&quot;).accept(&quot;text/xml;charset=utf-8&quot;).get();

Query q = response.getResource();

for (Curso c : q.getResults().getCursos().getCursos()) {
    System.out.println(c.getNome());
}
</pre></p>
<p>Logicamente, esse código pode ser reaproveitado em qualquer tipo de aplicação (seja web ou Desktop).</p>
<p><strong>Conclusão</strong></p>
<p>Para utilizar uma tabela criada basta consumir essa tabela através de uma API que envie requisições HTTP. O ideal é que ela também torne agradável trabalhar com a resposta. Nesse caso utilizei o Restfulie, mas poderia ter sido também qualquer outra biblioteca, como o HTTParty.</p>
<br />Filed under: <a href='http://ahalmeida.com/category/javascript/'>Javascript</a>, <a href='http://ahalmeida.com/category/web-2/'>Web</a> Tagged: <a href='http://ahalmeida.com/tag/java/'>java</a>, <a href='http://ahalmeida.com/tag/restfulie/'>restfulie</a>, <a href='http://ahalmeida.com/tag/ruby/'>ruby</a>, <a href='http://ahalmeida.com/tag/web/'>web</a>, <a href='http://ahalmeida.com/tag/yql/'>yql</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/160/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=160&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2010/10/19/yql-parte-3-usando-tabelas-do-yql-em-uma-aplicacao-ruby-e-java-com-restfulie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>YQL! Parte 2: Criando novas tabelas</title>
		<link>http://ahalmeida.com/2010/09/01/yql-parte-2-criando-novas-tabelas/</link>
		<comments>http://ahalmeida.com/2010/09/01/yql-parte-2-criando-novas-tabelas/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 13:00:09 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yql]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=99</guid>
		<description><![CDATA[Recapitulando No primeiro post (leia aqui) eu falei sobre a busca de dados públicas na web e da utilização básica das tabelas do YQL! e a criação de queries através de tabelas já existentes dentro do próprio serviço (sejam do próprio Yahoo! ou desenvolvidas por outras pessoas). E quando não existe uma tabela pronta? Existem [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=99&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Recapitulando</strong></p>
<p>No primeiro post (<a href="http://ahalmeida.com/2010/08/25/yql-parte-1-o-basico-sobre-busca-de-dados-publicos/" target="_blank">leia aqui</a>) eu falei sobre a busca de dados públicas na web e da utilização básica das tabelas do <a href="http://developer.yahoo.com/yql/console/">YQL!</a> e a criação de queries através de tabelas já existentes dentro do próprio serviço (sejam do próprio Yahoo! ou desenvolvidas por outras pessoas).</p>
<p><strong>E quando não existe uma tabela pronta?</strong></p>
<p>Existem tabelas no YQL! para realizarmos diversas pesquisas sobre os mais variados tipos de informação. No entanto, apesar do YQL! disponibilizar essas tabelas para que possamos consultar informações, nem sempre existirá uma tabela para o que desejamos buscar. O que fazemos nesse caso?</p>
<p><strong>Consultando informações de forma genérica</strong></p>
<p>Para permitir que possamos consultar informações de variadas fontes, o próprio YQL! disponibiliza uma tabela chamada &#8220;html&#8221;. Essa tabela permite que seja feita requisições para qualquer URL procurando por algo dentro da resposta gerada. A pesquisa dentro do HTML é feita através de XPath, que é uma linguagem para fazer buscas dentro de documentos XML. (Caso você não conheça XPath, ou é como eu que vive esquecendo a sintaxe, uma boa referência é a <a href="http://www.w3schools.com/xpath/xpath_intro.asp">seção no site da w3schools dedicada ao assunto</a>.)</p>
<p>Para mostrar como fazer uma pesquisa genérica, vou utilizar como exemplo o calendário de cursos disponível na <a href="http://www.caelum.com.br" target="_blank">página inicial do site da Caelum</a>. Para extrair as informações da tabela, o XPath adequado é o seguinte:</p>
<p><pre class="brush: plain;">
//div[@id='calendario']/table/tbody/tr
</pre></p>
<p>Traduzindo o comando: Em qualquer lugar do documento, busque uma <em>div</em> cujo id é calendario e dentro dessa <em>div</em> eu quero todos os <em>tr</em> que vão estar dentro de um <em>tbody</em> que vai estar dentro de um table.</p>
<p>Com isso, podemos montar nossa query da seguinte forma no YQL!:</p>
<p><pre class="brush: sql;">
select * from html where xpath=&quot;//div[@id='calendario']/table/tbody/tr&quot; and url=&quot;http://www.caelum.com.br&quot;
</pre></p>
<p>Ao executar essa query no console do YQL! o resultado retornado será todas as Tags &lt;tr&gt; da listagem dos cursos.</p>
<p><strong>Criando sua própria tabela da forma simples</strong></p>
<p>Agora que conseguimos realizar nossa consulta e buscamos as informações desejadas, podemos começar a melhorar os nossos resultados. O primeiro ponto é que deixar esse XPath explícito na query pode não ser algo tão agradável dependendo da utilização e situação. Nesse caso, queremos que a nossa consulta seja executada com um simples:</p>
<p><pre class="brush: sql;">
select * from caelum.proximoscursos
</pre></p>
<p>e ainda assim a query original deve ser executada. Muito mais agradável, não? Para isso, precisamos criar a nossa própria tabela.</p>
<p>O processo de criação de uma tabela do YQL! não é complicado, apesar que precisamos lidar com alguns XMLs a princípio. Primeiramente, precisamos criar um arquivo .xml com o nome de nossa tabela, nesse caso caelum.proximoscursos.xml. E definir alguns meta-dados, como autor e descrição da tabela. Além disso, no mesmo XML, dizemos qual é a query que deverá ser executada. Isso é feito através de um simples código Javascript, que é executado quando a query for disparada.</p>
<p>Esse Javascript fica dentro das Tags &lt;bindings&gt;&lt;select&gt;&lt;execute&gt; dentro do XML e é executado quando invocamos a tabela. Para executarmos a consulta, basta nesse Javascript adicionarmos o seguinte código:</p>
<p><pre class="brush: jscript;">
var url = 'http://www.caelum.com.br';
var xpath = &quot;//div[@id='calendario']/table/tbody/tr&quot;;
response.object = y.query('select * from html where url=&quot;' + url + '&quot; and xpath=&quot;' + xpath + '&quot;').results;
</pre></p>
<p>O objetivo desse código é fazer uma chamada ao serviço de queries do Yahoo! através da função query() passando a consulta que desejamos realizar e mandamos recuperar seu resultado. Nada mais que isso.</p>
<p>O resultado final desse XML pode ser visto em: <a href="http://ahalmeida.me/tabelas_yql/caelum.proximoscursos_html.xml" target="_blank">http://ahalmeida.me/tabelas_yql/caelum.proximoscursos_html.xml</a></p>
<p>E para executá-lo no console do YQL!, basta importá-lo adicionando antes da query o comando &#8220;use&#8221; e executar a consulta:</p>
<p><pre class="brush: sql;">
use 'http://ahalmeida.me/tabelas_yql/caelum.proximoscursos_html.xml';
select * from caelum.proximoscursos_html;
</pre></p>
<p>Pronto! Tabela criada e pronta para o uso.</p>
<p><strong>Complicando mais a tabela para melhorar os resultados</strong></p>
<p>A tabela criada anteriormente possui um grande problema. Os dados retornados por ela ainda estão no meio de um HTML, cheio de formatação e sem nenhuma semântica com relação ao domínio da informação que desejamos buscar. Para melhorar isso, é preciso usar um pouquinho de Javascript para formatar o resultado que a query devolverá.</p>
<p>A ideia é que seja feito um parse do HTML retornado, para que seja devolvido um XML ou um JSON para que fique mais fácil trabalhar com as informações retornadas.</p>
<p>Para isso, é preciso escrever um pouco mais de Javascript na Tag &lt;execute&gt;. Diferentemente da tabela que retorna o proprio HTML, agora é precisar tomar algumas decisões sobre esse HTML e gerar um novo XML. Para parsear e criar um novo XML, uma forma possível de fazer isso no Javascript é através do E4X (ECMAScript for XML), para conhecer mais e aprender como usar, vale uma lida <a href="http://www.devx.com/webdev/Article/33393/1954" target="_blank">aqui</a>.</p>
<p>Com o E4X é possível navegar no XML e realizar verificações e pegar valores. Com isso, pode-se a partir do resultado da query pegar as tags &lt;tr&gt; do mesmo da seguinte forma:</p>
<p><pre class="brush: jscript;">
trs = query.results.tr;
</pre></p>
<p>E em seguida é possível iterar sobre todos os &lt;tr&gt; através do for each:</p>
<p><pre class="brush: jscript;">
for each(var tr in trs) { ... }
</pre></p>
<p>Devido à estrutura do HTML retornado pela pesquisa, é retornado também um &lt;th&gt; com o nome do agrupamento por mês dos cursos, que não é necessário no retorno da pesquisa, por isso, podemos verificar se existe um elemento desse tipo dentro do &lt;tr&gt; e caso exista, ignoramos essa linha. Isso é possível, entre outras formas, através da seguinte verificação:</p>
<p><pre class="brush: jscript;">
if(tr.elements('th').length() == 0) { /* entao não é a coluna do agrupamento do mês e podemos pegar os resultados */ }
</pre></p>
<p>Com isso agora é possível iterar sobre as células (&lt;td&gt;) da coluna e recuperar seus valores. Dessa forma haverá um outro for each para iterar nas células, e dentro de cada célula haverá uma verificação para saber em qual célula o for está posicionado no momento e com isso retirar a informação do HTML de forma adequada (dentro de um link, de uma tag &lt;p&gt; ou do atributo &#8220;title&#8221; do &lt;td&gt;).</p>
<p>O código completo dessa tabela pode ser encontrada <a href="http://github.com/adrianoalmeida7/yql-tables/tree/master/caelum/" target="_blank">no meu repositório no github</a> (em breve vou mandar o pull request pro repositório oficial, quero fazer umas melhorias antes, como uns filtros por unidade <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>
<p>E para vê-la em produção, você pode executar o seguinte comando:</p>
<p><pre class="brush: sql;">
use 'http://ahalmeida.me/tabelas_yql/caelum.proximoscursos.xml'; select * from caelum.proximoscursos;
</pre></p>
<p><strong>Conclusão</strong></p>
<p>Criar tabelas no YQL! não é uma tarefa difícil, no entanto, as vezes pode ser uma tarefa um pouco maçante, por conta de todo o parsing do resultado da query. De qualquer maneira, é um código que será escrito uma vez e que raramente irá se alterar. Para saber TODOS os detalhes possíveis sobre a criação e utilização das tabelas, <a href="http://developer.yahoo.com/yql/guide/index.html" target="_blank">recomendo uma lida com calma na documentação do YQL!</a>. No próximo post vou falar sobre como utilizar essa tabela criada em uma aplicação web.</p>
<br />Filed under: <a href='http://ahalmeida.com/category/web-2/'>Web</a> Tagged: <a href='http://ahalmeida.com/tag/web/'>web</a>, <a href='http://ahalmeida.com/tag/yql/'>yql</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/99/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=99&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2010/09/01/yql-parte-2-criando-novas-tabelas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>YQL! Parte 1: O básico sobre busca de dados públicos</title>
		<link>http://ahalmeida.com/2010/08/25/yql-parte-1-o-basico-sobre-busca-de-dados-publicos/</link>
		<comments>http://ahalmeida.com/2010/08/25/yql-parte-1-o-basico-sobre-busca-de-dados-publicos/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 15:28:33 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yql]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=76</guid>
		<description><![CDATA[O problema de buscar dados públicos Muitas vezes precisamos que nossa aplicação disponibilize dados os quais não temos em nosso banco de dados. Isso é muito comum atualmente com aplicações que precisam exibir as mensagens mais recentes de uma pessoa no twitter, a lista de amigos de alguém no facebook ou até mesmo as informações [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=76&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>O problema de buscar dados públicos</strong></p>
<p>Muitas vezes precisamos que nossa aplicação disponibilize dados os quais não temos em nosso banco de dados. Isso é muito comum atualmente com aplicações que precisam exibir as mensagens mais recentes de uma pessoa no twitter, a lista de amigos de alguém no facebook ou até mesmo as informações sobre os hospitais disponíveis em uma dada região.</p>
<p>Em todos esses casos, as informações existem, mas não a temos em nossa aplicação. Justamente para isso, muitos serviços atualmente fornecem uma API para que seja possível recuperar e manipular esses dados. No entanto, o mundo não é perfeito e a grande maioria dos dados que precisamos não estão disponíveis em uma API que seja fácil de acessar. Consequência? Temos que usar os famigerados &#8220;crawlers&#8221;, que são scripts que acessam uma ou mais páginas em busca de informações que nos sejam úteis, mas nem sempre escrever um crawler é uma tarefa simples.</p>
<p><strong>YQL! &#8211; Yahoo Query Language</strong></p>
<p>Justamente para facilitar a consulta de dados públicos na internet, o Yahoo! criou uma ferramenta chamada <a href="http://developer.yahoo.com/yql" target="_blank">YQL! (Yahoo! Query Language)</a>. O objetivo é que seja disponibilizada uma linguagem semelhante ao SQL, porém com o objetivo de realizar consultas em sites na web. Para utilizarmos, não precisamos de muito, basta acessar o console disponível em <a href="http://developer.yahoo.com/yql/console/" target="_blank">http://developer.yahoo.com/yql/console/</a> e brincar com as queries, recuperando um XML ou um JSON como resposta.</p>
<p><strong>Primeira consulta: buscando algo no Yahoo! Answers</strong></p>
<p>O YQL! já possui diversas tabelas disponíveis para consultarmos que nos abstraem toda a complexidade de pesquisar no site de determinado serviço. Por exemplo, podemos consultar sobre como dormir bem no Yahoo! Answers, para isso, basta executarmos uma query que busque na tabela <strong>answers.search</strong> por &#8220;how to sleep well&#8221;, mas que parâmetros temos de colocar em nossa query para isso? Podemos descobrir essas informações executando o seguinte comando:</p>
<blockquote><p>desc answers.search</p></blockquote>
<p>Grande parte das tabelas existentes no YQL! provêem uma <a href="http://developer.yahoo.com/answers/V1/questionSearch.html" target="_blank">URL de documentação</a> (visível dentro da Tag documentationURL), de qualquer forma, caso a documentação não exista para alguma tabela, é possível também através do desc ver a lista de parâmetros que a query recebe e a partir daí inferir o uso.</p>
<p>Olhando a documentação da tabela vemos que o parâmetro &#8220;query&#8221; indica pelo o quê procuramos e teremos a seguinte consulta:</p>
<blockquote><p>select * from answers.search where query=&#8221;how to sleep well&#8221;</p></blockquote>
<p><strong>Integrando com uma aplicação (qualquer linguagem)</strong></p>
<p>Mas como faço para usar esses resultados na minha aplicação? Simples, o YQL! fornece uma API Rest a qual podemos invocar passando como parâmetro a query que desejamos realizar. Basta invocar http://query.yahooapis.com/v1/public/yql?q=SUA_QUERY_VEM_AQUI que o resultado é retornado. No próprio console, no painel inferior existe um campo com a URL já pronta para ser copiada e utilizada na sua aplicação.</p>
<p>Por ser uma URL simples, é possível invocá-la de qualquer aplicação cuja linguagem suporte requisições HTTPs. Dependendo da linguagem utilizada, é possível utilizar uma ferramenta que faça a requisição e auxilie no parsing do XML/JSON da resposta, como o <a href="http://restfulie.caelumobjects.com/" target="_blank">Restfulie</a> (que existe para várias plataformas) e o <a href="http://httparty.rubyforge.org/" target="_blank">HTTParty</a> no Ruby.</p>
<p><strong>Tabelas públicas</strong></p>
<p>No YQL! também é possível criar tabelas novas e disponibilizar essas tabelas para que outras pessoas possam utilizá-las, essas tabelas são conhecidas como &#8220;Community Tables&#8221; e pode ser criada por qualquer pessoa (a parte 2 cobrirá a criação de tabelas). Nessas tabelas disponíveis, é possível por exemplo, consultar informações no IMDB, <a href="http://github.com/yql/yql-tables/tree/master/brazil/correios/" target="_blank">buscar o status de uma encomenda no através do site dos correios</a> (tabela feita pelo <a href="http://gc.blog.br" target="_blank">Guilherme Chapiewski</a>), buscar dados de músicas e bandas no Last.fm assim por diante.</p>
<p>O uso dessas tabelas se dá da mesma maneira que o uso das tabelas já providas pelo Yahoo!, ou seja, vá até o console, teste a sua query até ela recuperar as informações da forma que você precisa e utilize a URL em sua aplicação (nas próximas partes desse post colocarei um exemplo de uso em uma aplicação Ruby, mas que pode ser aplicado facilmente em outras linguagens).</p>
<p><strong>Conclusão</strong></p>
<p>Essa primeira parte é só uma introdução sobre o YQL!. Algumas buscas vão requerer tarefas mais avançadas, como criar tabelas, fazer joins nas tabelas e assim por diante, que serão vistos nos próximos posts.</p>
<br />Filed under: <a href='http://ahalmeida.com/category/web-2/'>Web</a> Tagged: <a href='http://ahalmeida.com/tag/web/'>web</a>, <a href='http://ahalmeida.com/tag/yql/'>yql</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/76/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/76/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/76/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=76&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2010/08/25/yql-parte-1-o-basico-sobre-busca-de-dados-publicos/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>Usando melhor o RVM: trabalhando com gemsets</title>
		<link>http://ahalmeida.com/2010/04/12/usando-melhor-o-rvm-trabalhando-com-gemsets/</link>
		<comments>http://ahalmeida.com/2010/04/12/usando-melhor-o-rvm-trabalhando-com-gemsets/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 13:00:18 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=78</guid>
		<description><![CDATA[O RVM (Ruby Version Manager) é uma ferramenta que permite que se trabalhe com diferentes versões de Ruby numa mesma máquina de forma simples. A ideia desse post não é falar sobre como configurar o RVM do zero. Caso esteja interessado nisso, dê uma lida no post do Fabio Akita. Uma das coisas mais comuns [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=78&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>O <a href="http://rvm.beginrescueend.com/" target="_blank">RVM</a> (Ruby Version Manager) é uma ferramenta que permite que se trabalhe com diferentes versões de Ruby numa mesma máquina de forma simples.</p>
<p>A ideia desse post não é falar sobre como configurar o RVM do zero. Caso esteja interessado nisso, dê uma lida no post do <a href="http://akitaonrails.com/2010/01/01/limpando-meu-ambiente-de-desenvolvimento" target="_blank">Fabio Akita</a>.</p>
<p>Uma das coisas mais comuns em tempos de Rails 3 é possuirmos aplicações já feitas em Rails 2, e enquanto isso queremos desenvolver em Rails 3. A solução para trabalharmos de forma simples e organizada com gems de versões diferentes dentro de uma mesma versão de ruby é usando as gemsets do RVM.</p>
<p>Uma gemset, como o próprio nome diz, é um conjunto de gems, no qual você atribui um nome para elas, e consegue alternar entre os mesmos facilmente. Dessa forma, podemos alternar entre diferentes versões de gems executando um simples comando no shell. Isso é útil para testarmos compatibilidades entre os nosso código e as versões das gems que ele utiliza.</p>
<p>O primeiro passo para criar uma gemset, considerando que o RVM já esteja instalado é: <code>rvm gemset create nome_da_gemset</code>. Com isso, uma nova gemset é criada com o nome definido. Agora que já temos a gemset criada, podemos utilizá-la com o comando <code>rvm gemset use nome_da_gemset</code>. É possível também trocar para uma gemset específica de uma versão definindo a RVM que se quer utilizar junto da gemset: <code>rvm use 1.9.1@nome_da_gemset</code>.</p>
<p>Para instalar gems dentro dessa versão, basta utilizar <code>gem install nome_da_gem</code> (<strong>sem o sudo</strong>).</p>
<p>Por padrão, as instalações do ruby dentro do RVM já possuem uma gemset. Para voltar para ela, basta acessar diretamente a sua rvm com <code>rvm use 1.9.1</code>, por exemplo.</p>
<p>Mas, nesse monte de gemsets, como posso saber em qual eu estou e quais eu tenho disponíveis para utilizar? Para o primeiro, existe o comando <code>rvm gemset name</code>.</p>
<p>É possível alterar o script do seu .bash_profile para mostrar o nome da gemset em que você está também,  basta adicionar ao script que o próprio RVM sugere, o seguinte comando: <code>(`rvm gemset name`)</code>, com isso, ele ficará da seguinte forma:</p>
<p><code>export PS1='\w `~/.rvm/bin/rvm-prompt i v` (`rvm gemset name`) `git branch 2&gt; /dev/null | grep -e ^* | sed -E  s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`\[33[37m\]$\[33[00m\] '</code></p>
<p>Para listar as gemsets disponíveis, basta executar <code>rvm gemset list</code> e caso não precisa mais de uma gemset, basta executar <code>rvm gemset delete nome_da_gemset</code>.</p>
<p>Por fim, uma outra funcionalidade bastante útil é a criação de arquivos .rvmrc. Esses arquivos funcionam como um script de inicialização da rvm, e podem ser colocados inclusive dentro do diretório do seu projeto, dessa forma, você pode fazer com que quando você acesse o diretório do seu projeto pelo shell da sua máquina ele posicione o seu RVM na versão correta do seu ruby e também na gemset adequada.</p>
<p>Vale a pena dar uma olhada no <a href="http://rvm.beginrescueend.com/" target="_blank">site oficial</a> para saber mais, tem muitas outras funcionalidades no RVM que podem ajudar bastante no desenvolvimento.</p>
<p><strong>Editado</strong>: Existe uma forma mais simples de mostrar a gemset no PS1. Basta adicionar o parâmetro &#8220;g&#8221; ao rvm-prompt. Dessa forma, ficará:</p>
<p><code>export PS1='\w `~/.rvm/bin/rvm-prompt i v g` `git branch 2&gt; /dev/null | grep -e ^* | sed -E  s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`\[33[37m\]$\[33[00m\] '</code><br />
Obrigado Nelson Haraguchi por apontar.</p>
<br />Filed under: <a href='http://ahalmeida.com/category/ruby-2/'>Ruby</a> Tagged: <a href='http://ahalmeida.com/tag/rails/'>rails</a>, <a href='http://ahalmeida.com/tag/ruby/'>ruby</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/78/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/78/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/78/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=78&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2010/04/12/usando-melhor-o-rvm-trabalhando-com-gemsets/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>Uma estratégia para aprender coisas novas</title>
		<link>http://ahalmeida.com/2010/04/05/uma-estrategia-para-aprender-coisas-novas/</link>
		<comments>http://ahalmeida.com/2010/04/05/uma-estrategia-para-aprender-coisas-novas/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 17:26:41 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[Estudo]]></category>
		<category><![CDATA[estudo]]></category>
		<category><![CDATA[linguagens]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=53</guid>
		<description><![CDATA[Uma das formas mais comuns que as pessoas tem de aprender algo novo, por exemplo, uma nova linguagem de programação é através de livros, e testando os códigos para fixar o conhecimento. Essa prática talvez seja a mais usada atualmente, no entanto, para mim não a considero suficiente. Infelizmente uma das coisas que acabam acontecendo [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=53&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Uma das formas mais comuns que as pessoas tem de aprender algo novo, por exemplo, uma nova linguagem de programação é através de livros, e testando os códigos para fixar o conhecimento. Essa prática talvez seja a mais usada atualmente, no entanto, para mim não a considero suficiente.</p>
<p>Infelizmente uma das coisas que acabam acontecendo ao praticar os códigos que vêm em determinados livros é um simples copia e cola (apesar de que na maioria dos livros eles dizem para testarmos códigos diferentes, mudarmos o problema etc). Esse copia e cola leva a falsa sensação de que se aprendeu bastante coisa porque por mais que o código funcione, o resultado seja uma interface bonita e funcional, nós não pensamos para escrever aquele código e se você não pensou para escrever, significa que você vai esquecê-lo logo logo.</p>
<p>Recentemente, além de testar códigos de livros, e feito meus próprios exemplos, uma prática que vêm se saindo bastante satisfatória é a de escrever um resumo sobre o assunto (capítulo lido, por exemplo). Acontece que esse resumo, é escrito numa linguagem como se estivesse explicando para outra pessoa o conceito.</p>
<p>A ideia é totalmente inspirada na máxima de que &#8220;quando se ensina se aprende duas vezes&#8221; e que é verdade. Sempre que se está explicando algo para uma outra pessoa, descobre-se alguma coisa nova e você fixa melhor aquele conhecimento.</p>
<p>Esse resumo não precisa seguir uma linha formal, pode ser feito inclusive em bullet points, por exemplo, abaixo tem um pequeno trecho de quando eu estava aprendendo Flex há algum tempo atrás, e foi quando eu utilizei esse técnica pela primeira vez:</p>
<blockquote>
<div id="_mcePaste">
<ul>
<li>Quando trabalhamos com o Flex, já percebemos que podemos escrever tanto MXML quanto ActionScript. Mas, como será que as tags foram definidas? Como elas são executadas?</li>
<li>No fundo todas as tags do MXML são componentes ActionScript, são classes ActionScript.</li>
<li>Logo, se os componentes lá do MXML são classes, então podemos em algum momento no nosso ActionScript instanciá-las?</li>
<li>Ou seja, podemos criar nossos componentes customizados como (como classes Action Script) e utilizá-los no MXML.</li>
</ul>
</div>
</blockquote>
<p>É claro que comigo isso funciona e pode não funcionar para outras pessoas, afinal, cada uma possui sua própria forma de aprendizado que acha melhor e mais produtiva.</p>
<p>Mas fica aí como sugestão se você ainda não encontrou sua forma ideal de aprender coisas novas.</p>
<br />Filed under: <a href='http://ahalmeida.com/category/estudo-2/'>Estudo</a> Tagged: <a href='http://ahalmeida.com/tag/estudo/'>estudo</a>, <a href='http://ahalmeida.com/tag/linguagens/'>linguagens</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/53/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=53&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2010/04/05/uma-estrategia-para-aprender-coisas-novas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>Cross-domain AJAX requests with JSONP</title>
		<link>http://ahalmeida.com/2009/10/04/cross-domain-ajax-requests-with-jsonp/</link>
		<comments>http://ahalmeida.com/2009/10/04/cross-domain-ajax-requests-with-jsonp/#comments</comments>
		<pubDate>Sun, 04 Oct 2009 06:42:10 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[jsonp]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=48</guid>
		<description><![CDATA[AJAX requests are very common nowadays, because it can improve user experience on your application, and also boost it&#8217;s usability. Asynchronous requests can be used for instance, to invoke an URI in order to process some logic without committing the browser on waiting until the end of the request. So, the user can still use [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=48&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>AJAX requests are very common nowadays, because it can improve user experience on your application, and also boost it&#8217;s usability. Asynchronous requests can be used for instance, to invoke an URI in order to process some logic without committing the browser on waiting until the end of the request. So, the user can still use the page, even if the logic hasn&#8217;t finished yet.</p>
<p><strong>Cross-domain AJAX call, what is the matter?</strong></p>
<p>However, there is a scenario where an application A, at www.applicationA.com needs to do an AJAX request to an URI at application B, let&#8217;s say www.applicationB.com/aGivenURI.</p>
<p>When this request is done, you&#8217;ll be faced with the nice and meaningful message &#8220;<em>Access to restricted URI denied.</em>&#8220;, or some variation on this message. But, what the heck is happening here? Why I can&#8217;t do a request to this other site?</p>
<p>The problem is&#8230;. the application B is at other domain, and browsers, for security reasons, don&#8217;t allow one to make request for a domain which isn&#8217;t your own domain (or a sub-domain of your domain).</p>
<p>And now, what do I do, if I can&#8217;t do an AJAX request to MY application whose domain isn&#8217;t the same as the application B? You could possibly do a server side request to that URI, and it would work, however, this is not AJAX.</p>
<p><strong>JSONP to the rescue<br />
</strong></p>
<p>If we pay carefully attention, we CAN do cross-domain request on our HTML sources. If you add the following snippet to your code, at the application A:</p>
<p><pre class="brush: jscript;">
&lt;script src=&quot;http://www.applicationB.com/aGivenURI&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
</pre></p>
<p>This code DOES a call to the application B, so, now we are doing a cross-domain request. So, if we can make a cross domain request this way, what if we instead of doing and XMLHttpRequest for doing AJAX request, we just created these &lt;script&gt; blocks on the fly, dynamically, thus, having &#8220;almost&#8221; the same behavior from the AJAX request.</p>
<p>Why almost? What will the given URI give to us? Ok, it&#8217;ll give us back the JSON we needed, probably, simple as the following:</p>
<p><pre class="brush: jscript;">
{message: 'New car added successfully', model: 'Ferrari'}
</pre></p>
<p>But, if it&#8217;s being added at our code, there&#8217;s just no way to retrieve this JSON. Because, it&#8217;s a javascript file that&#8217;s being imported to my page, dynamically. But this is easy, what if we just wrap this JSON under a function and just make the function return this JSON, that way, we could make a call to that function, and it&#8217;ll return the JSON we need. So, now, the javascript code retrieved from the application B will be:</p>
<p><pre class="brush: jscript;">
saveInformations({message: 'New car added successfully', model: 'Ferrari'});
</pre></p>
<p>And now, all we need to do to retrieve this JSON is a call to the saveInformations function. It works as a callback function.</p>
<p>Generally, these javascripts are generated dynamically, and so, you would also might be able to choose the name of you callback function, most of the times, passing a parameter to the requested URI.</p>
<p>This technique that just consists on exploring the use of the &lt;script&gt; tag, and adding it dynamically to your page, making it possible to do cross-domain requests, and retrieve the value by defining callback functions, is called <strong>JSONP</strong> (JSON Padding).</p>
<p><strong>Simplifying it with JQuery</strong></p>
<p>JQuery makes it very transparent to use JSONP, it does all the boilerplate code to create the script tag dynamically and invoke the callback function. All you have to do is to define the parameter callback=?, and if the parameter is present, JQuery will do all the needed to do JSONP, otherwise, it&#8217;ll do a normal AJAX request.</p>
<p><pre class="brush: jscript;">
$.getJSON(&quot;www.applicationB.com/aGivenURI?callback=?&quot;, function(data) {
    alert(data.model + &quot; - - &quot; + data.message);
});
</pre></p>
<p>Pretty simple.</p>
<br />Publicado em Web Tagged: ajax, jsonp, web <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/48/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/48/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/48/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=48&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2009/10/04/cross-domain-ajax-requests-with-jsonp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
		<item>
		<title>Comments on ThoughtWorks Anthology</title>
		<link>http://ahalmeida.com/2009/07/12/comments-on-thoughtworks-anthology/</link>
		<comments>http://ahalmeida.com/2009/07/12/comments-on-thoughtworks-anthology/#comments</comments>
		<pubDate>Mon, 13 Jul 2009 00:17:32 +0000</pubDate>
		<dc:creator>Adriano de Almeida</dc:creator>
				<category><![CDATA[Estudo]]></category>
		<category><![CDATA[livros]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[tw]]></category>

		<guid isPermaLink="false">http://ahalmeida.com/?p=33</guid>
		<description><![CDATA[I&#8217;ve just finished reading the &#8220;ThoughtWorks Anthology&#8221; book, motivated by Guilherme Silveira and learned some really useful things on it, that I would like to expand a little. Besides the less technical articles published on it, I really enjoyed the chapter written by Jeff Bay called &#8220;Object Calisthenics&#8221;, where the writer propose 9 exercises in [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=33&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just finished reading the &#8220;<a href="http://www.amazon.com/ThoughtWorks-Anthology-Technology-Innovation-Programmers/dp/193435614X/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1247399462&amp;sr=8-1" target="_blank">ThoughtWorks Anthology</a>&#8221; book, motivated by <a href="http://guilhermesilveira.wordpress.com/">Guilherme Silveira</a> and learned some really useful things on it, that I would like to expand a little.</p>
<p>Besides the less technical articles published on it, I really enjoyed the chapter written by Jeff Bay called &#8220;Object Calisthenics&#8221;, where the writer propose 9 exercises in order to improve the reader way of writing code, making it&#8217;s code cleaner and easiear to understand therefore easier to test.</p>
<p>I&#8217;ll just sum up the 3 ones that I found more interesting and add a few things:</p>
<p><strong>Do not have more than one identation level inside a method</strong></p>
<p>Take the following method, which simply increase the price of some products if it&#8217;s value are above 50:</p>
<p><pre class="brush: java;">
public void redefinePrices(List products, Integer toIncrease) {
	for(Product p : products) {
		Integer actualValue = p.getActualValue();
		if(actualValue &gt; 50) {
			p.setActualValue(actualValue + toIncrease);
		}
	}
}
</pre></p>
<p>As you can see, inside this method there are two identation levels, which makes the code easier to read if we had only one, like the following:</p>
<p><pre class="brush: java;">
public void redefinePrices(List products, Integer toIncrease) {
	for(Product p : products) {
		increaseValue(p, toIncrease);
	}
}

private void increaseValue(Product product, Integer toIncrease) {
	Integer actualValue = product.getActualValue();
	if(actualValue &gt; 50) {
		product.setActualValue(actualValue + toIncrease);
	}
}
</pre></p>
<p>Ok, now there&#8217;s two methods, but, there&#8217;s no doubt that the redefinePrices method is clearer than in the first version. The advantage of this approach is that your code becomes self-descriptive, with the method call inside it. When you need to read the method redefinePrices, instead of interpret conditional logics or loops, just read what is being done inside the nested method described by the increaseValue method name.</p>
<p><strong>Avoid abbreviation on names</strong></p>
<p>One of the largest mistakes I see on projects nowadays are the use of abbreviation on classes, methods and variables name. The use of abbreviation often leads to a code full of hard to understand names, which affects mostly those who are new to the project, increasing their learning curve on the domain model and consequently from the software itself.</p>
<p>I use to say that abbreviation is a plague that exists on software development, and it&#8217;s hard to get rid of it. It&#8217;s tempting to, for instance, instead of writing <em>generateCardCode</em> to write generateCC. This may also indicate that you have some problems regarding ubiquitous language on your project.</p>
<p>Jeff Bay also says that you may try to make your names to take no longer than 2 words. I&#8217;m not so severe on that, but I believe that 3 words are enough to make a good name (of course, this do not include test names).</p>
<p><strong>Do not use else clauses</strong></p>
<p>When using if/else clauses, it&#8217;s common to make the code inside these clauses hard to understand. This is even more evident when you have a complex block of if/else clauses, making the logic cumbersome and complex. There are some approaches used to deal with this problem. The first, and simpler one is to just return the value you want. Say, that you have the following code:</p>
<p><pre class="brush: java;">
public boolean shouldAcceptRequest(Destination destination) {
	if(destination.address().equals("foo")) {
		return true;
	} else {
		return false;
	}
}
</pre></p>
<p>You can simplify it to just one line, and also improve the readability of this piece of code:</p>
<p><pre class="brush: java;">
public boolean shouldAcceptRequest(Destination destination) {
	return destination.address().equals("foo");
}
</pre></p>
<p>However, there are some cases when only returning the value is not enough, you may want to perform a small check before deciding what to return, like in the following example:</p>
<p><pre class="brush: java;">
public Integer divideValues(Integer a, Integer b) {
	if (b == 0)
		return 0;
	else
		return a / b;
}
</pre></p>
<p>You can introduce ternary operator to make the code above cleaner:</p>
<p><pre class="brush: java;">
public Integer divideValues(Integer a, Integer b) {
	return b == 0 ? 0 : a / b;
}
</pre></p>
<p>There&#8217;s also the classical case when what you&#8217;re wanting to test against an if/else clause can be abstracted on objects, and you can introduce the Strategy pattern, so you can remove the if clauses, and the executed behavior will be decided from the implementation it&#8217;ll be passed to be executed, like the example below:</p>
<p><pre class="brush: java;">
public void applyDiscount(Customer customer, Product product) {
	product.applyDiscount(customer.discountRate());
}
</pre></p>
<p>In the previous example, it doesn&#8217;t matter if it is a RegularCustomer or a SporadicCustomer, they have different discount rates, but since I&#8217;m using polymorphism (note the Customer interface), I can treat them the same way, but the discountRate method return different values for each kind of customer.</p>
<p><strong>Conclusion</strong></p>
<p>While reading the book, there are others techniques proposed by Jeff Bay, that I didn&#8217;t went into here. Some might say that a few of these issues are very radical, in fact, as proposed as an exercise from the writer, you won&#8217;t need to do this everyday, but just try to save some 1000 lines of code, or a time-box (say, a week) to follow these advices, and you&#8217;ll see how this changes the way you&#8217;ll write your everyday code.</p>
<br />Publicado em Estudo Tagged: livros, review, tw <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ahalmeida.wordpress.com/33/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ahalmeida.wordpress.com/33/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/ahalmeida.wordpress.com/33/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/ahalmeida.wordpress.com/33/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/ahalmeida.wordpress.com/33/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/ahalmeida.wordpress.com/33/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/ahalmeida.wordpress.com/33/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/ahalmeida.wordpress.com/33/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/ahalmeida.wordpress.com/33/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/ahalmeida.wordpress.com/33/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/ahalmeida.wordpress.com/33/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/ahalmeida.wordpress.com/33/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/ahalmeida.wordpress.com/33/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/ahalmeida.wordpress.com/33/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=ahalmeida.com&amp;blog=3189823&amp;post=33&amp;subd=ahalmeida&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://ahalmeida.com/2009/07/12/comments-on-thoughtworks-anthology/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="" medium="image">
			<media:title type="html">Adriano de Almeida</media:title>
		</media:content>
	</item>
	</channel>
</rss>
