<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kent Tong&#039;s personal thoughts on information technology</title>
	<atom:link href="http://agileskills2.org/blog/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://agileskills2.org/blog</link>
	<description>Kent Tong&#039;s personal thoughts on information technology</description>
	<lastBuildDate>Wed, 04 Jan 2012 14:25:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Implementing an async servlet in Scala with less than 10 lines of code</title>
		<link>http://agileskills2.org/blog/2012/01/03/implementing-an-async-servlet-in-scala-in-less-than-10-lines/</link>
		<comments>http://agileskills2.org/blog/2012/01/03/implementing-an-async-servlet-in-scala-in-less-than-10-lines/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 09:53:40 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=361</guid>
		<description><![CDATA[What is async servlet and why use it? An async servlet can tell the container that it will handle a request later, so that the current thread is not tied up and can be used for another request. Why is it useful? For example, if the request is going to do something relatively time consuming [...]]]></description>
			<content:encoded><![CDATA[<p>What is async servlet and why use it? An async servlet can tell the container that it will handle a request later, so that the current thread is not tied up and can be used for another request. Why is it useful? For example, if the request is going to do something relatively time consuming (e.g., generating a report from a DB), instead of tying up the thread doing nothing waiting for the data, you can free up the thread for other requests and wait for the data in a background thread. When the data is received, you can complete the response.
</p>
<p>It turns out to be very easy to implement an async servlet (new in servlet 3.0). In Scala, it took less than 10 lines of code (not counting brace brackets and imports):</p>
<pre class="brush: scala; title: ; notranslate">
package com.ttdev.webqos
import javax.servlet.http._
import java.util.concurrent._

class MyServlet extends HttpServlet {
  private val pool = Executors.newFixedThreadPool(1) // create a thread pool

  override def doGet(req: HttpServletRequest, res: HttpServletResponse) {
    req.startAsync  //tel the container the response will be generated later
    pool.execute(new Runnable() {  // add the runnable to the queue
      def run {  // when a thread in pool picks up the runntable...
        res.getWriter.append(&quot;hello world!&quot;)  // write the response
        req.getAsyncContext.complete  // tell the container that the response is done
      }
    })
    // return without a response yet
  }

}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2012/01/03/implementing-an-async-servlet-in-scala-in-less-than-10-lines/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What is software architecture</title>
		<link>http://agileskills2.org/blog/2011/12/30/what-is-software-architecture/</link>
		<comments>http://agileskills2.org/blog/2011/12/30/what-is-software-architecture/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 07:11:43 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=353</guid>
		<description><![CDATA[Practical definition Many people have different interpretations of what software architecture actually means. Some people take it as the high level decomposition of the system (subsystems or physical distribution). However, a much better interpretation is simply &#8220;the most important design decisions&#8221;. What are important design decisions? If they are going to impact what you (or [...]]]></description>
			<content:encoded><![CDATA[<h3>Practical definition</h3>
<p>Many people have different interpretations of what software architecture actually means. Some people take it as the high level decomposition of the system (subsystems or physical distribution). However, a much better interpretation is simply &#8220;the most important design decisions&#8221;. What are important design decisions? If they are going to impact what you (or your customer) care the most, then it is important. Typically, if the design decision is going to impact the availability, performance, scalability, security, usability, manageability, maintainability, cost, then it is part of the architecture.</p>
<h3>Examples</h3>
<p>Below are some examples of architectural decisions:</p>
<ul>
<li>Availability: how to build in redundancy in all the layers (storage, middle tier) and how to fail-over (e.g., client initiated vs virtual IP)? How to handle excessive load (e.g., QoS)? Selecting well proven products with strong support?</li>
<li>Scalability: how to scale (scale out or scale up) and load balance?</li>
<li>Performance: multi-threading, algorithm, processing in batches?</li>
<li>Security: encrypting data against exposure, using HMAC to check data integrity, secure communication, auditing?</li>
<li>Manageability: monitoring and operational control (e.g., logging, JMX)? Live upgrading (OK to upgrade just one node at a time in a cluster)?</li>
<li>Maintainability: automated tests, using a language, tools and frameworks familiar to the team, proper layering of the code (UI, service, data access layers)?</li>
<li>Cost: language, tools and frameworks familiar to the team, open source vs commercial products?</li>
</ul>
<h3>Specifying and maintaining the architecture</h3>
<p>I find the best way to specify the architecture is to explain it in use cases (e.g., how to perform fail-over when a certain component fails or how to ensure security in a typical use case).</p>
<p>Also, specifying the architecture is just the first step. Some team members may make sub-optimal architectural decisions in programming without knowing it, or you may realize that your initial decisions can be further improved when you see the code. Therefore, as the architect, your work is far from over and you must keep the architecture (as implemented in the code) fit as the project goes.</p>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/12/30/what-is-software-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reaction to &#8220;Clojure: Towards The Essence Of Programming&#8221; from a Scala perspective</title>
		<link>http://agileskills2.org/blog/2011/08/28/reaction-to-clojure-towards-the-essence-of-programming-from-a-scala-perspective/</link>
		<comments>http://agileskills2.org/blog/2011/08/28/reaction-to-clojure-towards-the-essence-of-programming-from-a-scala-perspective/#comments</comments>
		<pubDate>Sun, 28 Aug 2011 05:20:05 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Functional programming]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[clojure]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=334</guid>
		<description><![CDATA[How Scala addresses those problems Just watched Howard Lewis Ship&#8217;s Clojure: Towards The Essence Of Programming, which is an excellent introduction to Clojure and how it addresses the problems in Java. As a Scala fan, I thought it would be a good idea to see how one could use Scala to do the same. Ceremony [...]]]></description>
			<content:encoded><![CDATA[<h3>How Scala addresses those problems</h3>
<p>Just watched Howard Lewis Ship&#8217;s <a href="http://www.infoq.com/presentations/Clojure-Towards-The-Essence-Of-Programming">Clojure: Towards The Essence Of Programming</a>, which is an excellent introduction to Clojure and how it addresses the problems in Java. As a Scala fan, I thought it would be a good idea to see how one could use Scala to do the same.</p>
<h3>Ceremony vs Essence</h3>
<p>Howard uses the example below to show how much ceremony (code with little real info) is required, hiding the essence (the real intention) when using Java to sort a list of Stock objects (a portfolio) either using different properties such as open values or last trade values:</p>
<pre class="brush: java; title: ; notranslate">
 public static void sortByOpen(List&lt;Stock&gt; portfolio) {
    //ceremony: a lot of code but very little real info
    Comparator&lt;Stock&gt; c = new Comparator&lt;Stock&gt;() {
       public int compare(Stock o1, Stock o2) {
          return o1.getOpen() - o2.getOpen(); //essence: the beef is here
       }
    };
    Collections.sort(portfolio, c);
}
</pre>
<p>The Clojure version is:</p>
<pre class="brush: fsharp; title: ; notranslate">
//a Stock object is just a map with each field as a key. &quot;:open&quot; is the key to get the open value.
(sort-by :open portfolio)
</pre>
<p>In Scala, it can be as simple as the Clojure version:</p>
<pre class="brush: scala; title: ; notranslate">
//full version: using an anonymous function instead of a comparator object
portfolio.sortBy((s: Stock) =&gt; s.open)

//simpified version: sortBy is expecting the argument to be a function
// (Stock) =&gt; SOME-RESULT-TYPE, so we don't need to declare the
//type for &quot;s&quot;.
portfolio.sortBy((s) =&gt; s.open)

//final version: as &quot;s&quot; only appears once in the function body, just use
//an underscore and get rid of the parameter declaration.
portfolio.sortBy(_.open)
</pre>
<p>The Clojure version is like the final Scala version in the first attempt because it doesn&#8217;t need typing information in the code. In Scala, the compiler infer it from the code.
<p>In addition, in Clojure the object is just a map so people can refer to a property directly with its name without referring to the object. In Scala, we must use something to denote the object in the form of obj.property. However, the underscore syntax eliminates the need to declare that object, so the code is still very succinct. </p>
<p>The benefits of the Scala approach are:
<ul>
<li>Compile time checking: if the property name mismatches the Stock class, in the Scala the compiler will tell us immediately.</li>
<li>Runtime performance: it is a lot faster to access the property by offset than by looking up a key.
<li></ul>
<p>The cost we pay is mainly the learning curve: we must learn how Scala infers the typing information so that we know what to type and what to NOT type and learn the meaning of the underscore in an anonymous function.<br />
<h3>Form is structure</h3>
<p>I may not be fully understanding this example. Howard uses the Fahrenheit conversion,  f =9*c/5+32, to show that in Clojure the form (the look on the surface) is the same as the structure (the actual relationship):</p>
<pre class="brush: fsharp; title: ; notranslate">
//the look is the same as the actual syntax tree
(+
  (/
    (* 9 c)
    5)
  32)
</pre>
<p>I definitely think the Java or Scala version is much simpler and more concise:</p>
<pre class="brush: scala; title: ; notranslate">
9*c/5+32
</pre>
<p>This is, after all, what we call DSL. Arithmetics has its rules of precedence and associativity, allowing us to write in a very succinct form to express more complex structure.</p>
<h3>Read Eval Print Loop</h3>
<p>Scala has it too. I like it very much too.</p>
<h3>Functional programming</h3>
<p>Howard that moves onto functional programming with examples using filter, reduce, map, for comprehension, stream. Obviously, Scala can do all these in a similar fashion. For example, to get the last trade total value of the portfolio, we can map each stock to its last trade value and then use reduce to sum them all up. In Clojure:</p>
<pre class="brush: fsharp; title: ; notranslate">
//#() means anonymous function. % refers to the one and only parameter (the stock).
(reduce + (map #(* (% :last-trade) (% :shares)) portfolio))
</pre>
<p>In Scala:</p>
<pre class="brush: scala; title: ; notranslate">
//+ in Scala is not a function, but a method. So we can't use it directly;
//instead, use an anonymous function with underscores again.
portfolio.map((s)=&gt;s.lastTrade*s.shares).reduceLeft(_+_)
</pre>
<p>There is not much difference. However, I think the significance is much deeper. The question is not whether functional programming is supported or not, but how much it is intended to be used in place of procedural programming. Scala allows both styles of programming, which may or may not be a good thing, depending on how you view it. If you&#8217;re committed to the functional programming style for concurrency, testability, predictability, then using a language that is less capable of procedural programming is actually a good thing. If you&#8217;re more comfortable with procedural programming and just using functional programming in a smaller scale, then a hybrid language would be better.</p>
<h3>Extending the language with DSL</h3>
<p>Then Howard moves onto extending Clojure with DSL. One example he uses is building a DOM tree with a DSL.</p>
<pre class="brush: fsharp; title: ; notranslate">
(defview root-index
  [env]
  :html [
    :head [
      :title [ &quot;Cascade Blog&quot; ]
    ]
    :body [
      :h1 [ &quot;Cascade Blog&quot; ]
      :ul { :class &quot;recent-postings&quot; } [
        (template-for [posting (recent-postings env)]
          :li [
             (render-link env show-posting (posting :id) (posting :title))
           ])
      ]
    ]
  ])
</pre>
<p>As an exercise I implemented a similar DOM DSL in Scala:</p>
<pre class="brush: scala; title: ; notranslate">
//the DSL is implemented in the Html object
import Html._

//using the DSL to define a DOM tree
p @@ (&quot;style&quot; -&gt; &quot;color: red&quot;) containing (
        &quot;This is an &quot;,
        b containing (&quot;interesting&quot;),
        &quot;DOM tree&quot;
        )
</pre>
<p>They aren&#8217;t that different except that in Clojure each list item is separate from its neighbors by being enclosed in its own () but in Scala we must use a comma to separate the list items. So, choose your own poison: either tolerate a million ()&#8217;s or the ugly commas in the DSL.</p>
<p>Another difference is that in Clojure text can be freely mixed in the DOM tree as there is no typing restriction, while in Scala text is magically converted into a TextNode object. Again, the latter provides structure, compile-time protection and runtime performance, but we must learn the implicit conversion mechanism to understand what is going on.</p>
<p>Just to be complete, the DOM DSL is implemented in Scala as below:</p>
<pre class="brush: scala; title: ; notranslate">
//a DOM node
class Node

//a text node
case class TextNode(val text: String) extends Node

//an element node
case class Element(val name: String,
                   val attrs: Map[String, String],
                   val children: Seq[Node]) extends Node {
  def this(name: String) = this (name, Map(), List())

  //we can use symbols as method names, but @ is a reserved keyword in Scala,
  //so I used @@ as the name of the method that adds attributes to the element.
  def @@(attrPairs: (String, String)*) =
    //just add each pair to the map
    Element(name, attrPairs.foldLeft[Map[String, String]](Map())(_ + _), children)

  //add the child nodes (elements or text nodes) to this element
  def containing(children: Node*) = Element(name, attrs, children)
}

object Html {
  //convert strings into text nodes automatically
  implicit def string2TextNode(s: String) = TextNode(s)
  def p = new Element(&quot;p&quot;)
  def b = new Element(&quot;b&quot;)
}
</pre>
<p>Howard also shows the need for lazy evaluation so that some code is only executed on demand. For example, the DSL code to generate each &lt;li&gt; is repeatedly called in a loop. In Clojure lazy evaluation is implemented with macros which generate well-form code instead of arbitrary text. This seems to be more powerful (able to do more) than the call-by-name mechanism Scala, although I don&#8217;t know if/when this extra power is really needed.</p>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/08/28/reaction-to-clojure-towards-the-essence-of-programming-from-a-scala-perspective/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Revealing the Scala magician’s code: method vs function</title>
		<link>http://agileskills2.org/blog/2011/08/21/revealing-the-scala-magician%e2%80%99s-code-method-vs-function/</link>
		<comments>http://agileskills2.org/blog/2011/08/21/revealing-the-scala-magician%e2%80%99s-code-method-vs-function/#comments</comments>
		<pubDate>Sun, 21 Aug 2011 07:28:48 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=328</guid>
		<description><![CDATA[How&#8217;s a method different from a function in Scala? A method can appear in an expression as an internal value (to be called with arguments) but it can&#8217;t be the final value, while a function can: Parameter list is optional for methods but mandatory for functions A method can have no parameter list or have [...]]]></description>
			<content:encoded><![CDATA[<h3>How&#8217;s a method different from a function in Scala?</h3>
<p>A method can appear in an expression as an internal value (to be called with arguments) but it can&#8217;t be the final value, while a function can:</p>
<pre class="brush: scala; title: ; notranslate">
//a simple method
scala&gt; def m(x: Int) = 2*x
m: (x: Int)Int

//a simple function
scala&gt; val f = (x: Int) =&gt; 2*x
f: (Int) =&gt; Int = &lt;function1&gt;

//a method can't be the final value
scala&gt; m
&lt;console&gt;:6: error: missing arguments for method m in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
       m
       ^

//a function can be the final value
scala&gt; f
res11: (Int) =&gt; Int = &lt;function1&gt;
</pre>
<h3>Parameter list is optional for methods but mandatory for functions</h3>
<p>A method can have no parameter list or have one (empty or not), but a function must have one (empty or not):</p>
<pre class="brush: scala; title: ; notranslate">
//a method can have no parameter list
scala&gt; def m1 = 100
m1: Int

//a method can have an empty parameter list
scala&gt; def m2() = 100
m2: ()Int

//a function must have a parameter list
scala&gt; val f1 = =&gt; 100
&lt;console&gt;:1: error: illegal start of simple expression
       val f1 = =&gt; 100
                ^
//a function's parameter list could be empty
scala&gt; val f2 = () =&gt; 100
f2: () =&gt; Int = &lt;function0&gt;
</pre>
<p>Why a method can have no parameter list? See below.</p>
<h3>Method name means invocation while function name means the function itself</h3>
<p>Because methods can&#8217;t be the final value of an expression, so if you write a method name and if it doesn&#8217;t take any argument (no argument list or an empty argument list), the expression is meant to call that method to get the final value. Because functions can be the final value, if you just write the function name, no invocation will occur and you will get the function as the final value. To force the invocation, you must write ():</p>
<pre class="brush: scala; title: ; notranslate">
//it doesn't have a parameter list
scala&gt; m1
res25: Int = 100

//it has an empty parameter list
scala&gt; m2
res26: Int = 100

//get the function itself as the value. No invocation.
scala&gt; f2
res27: () =&gt; Int = &lt;function0&gt;

//invoke the function
scala&gt; f2()
res28: Int = 100
</pre>
<h3>Why we can provide a method when a function is expected?</h3>
<p>Many Scala methods such as map() and filter() take functions arguments, but why can we provide methods to them like:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; val myList = List(3, 56, 1, 4, 72)
myList: List[Int] = List(3, 56, 1, 4, 72)

//the argument is a function
scala&gt; myList.map((x)=&gt;2*x)
res29: List[Int] = List(6, 112, 2, 8, 144)

//try to pass a method as the argument instead
scala&gt; def m3(x: Int) = 3*x
m3: (x: Int)Int

//still works
scala&gt; myList.map(m3)
res30: List[Int] = List(9, 168, 3, 12, 216)
</pre>
<p>This is because when a function is expected but a method is provided, it will be automatically converted into a function. This is called the ETA expansion. This makes it a lot easier to use the methods we created. You can verify this behavior with the tests below:</p>
<pre class="brush: scala; title: ; notranslate">
//expecting a function
scala&gt; val f3: (Int)=&gt;Int = m3
f3: (Int) =&gt; Int = &lt;function1&gt;

//not expecting a function, so the method won't be converted.
scala&gt; val v3 = m3
&lt;console&gt;:5: error: missing arguments for method m3 in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
       val v3 = m3
                ^
</pre>
<p>With this automatic conversion, we can write concise code like:</p>
<pre class="brush: scala; title: ; notranslate">
//10.&lt; is interpreted as obj.method so is still a method. Then it is converted to a function.
scala&gt; myList.filter(10.&lt;)
res31: List[Int] = List(56, 72)
</pre>
<p>Because in Scala operators are interpreted as methods:</p>
<ul>
<li>prefix: op obj is interpreted as obj.op.</li>
<li>infix: obj1 op obj2 is interpreted as obj1.op(obj2).</li>
<li>postfix: obj op is interpreted as obj.op.</li>
</ul>
<p>You could write 10< instead of 10.<:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; myList.filter(10&lt;)
res33: List[Int] = List(56, 72)
</pre>
<h3>How to force a method to become a function?</h3>
<p>When a function is not expected, you can still explicitly convert a method into a function (ETA expansion) by writing an underscore after the method name:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; def m4(x: Int) = 4*x
m4: (x: Int)Int

//explicitly convert the method into a function
scala&gt; val f4 = m4 _
f4: (Int) =&gt; Int = &lt;function1&gt;

scala&gt; f4(2)
res34: Int = 8
</pre>
<h3>A call by name parameter is just a method</h3>
<p>A call by name parameter is just a method without a parameter list. That's why you can invoke it by writing its name without using ():</p>
<pre class="brush: scala; title: ; notranslate">
//use &quot;x&quot; twice, meaning that the method is invoked twice.
scala&gt; def m1(x: =&gt; Int) = List(x, x)
m1: (x: =&gt; Int)List[Int]

scala&gt; import util.Random
import util.Random

scala&gt; val r = new Random()
r: scala.util.Random = scala.util.Random@ad662c

//as the method is invoked twice, the two values are different.
scala&gt; m1(r.nextInt)
res37: List[Int] = List(1317293255, 1268355315)
</pre>
<p>If you "cache" the method in the body, you'll cache the value:</p>
<pre class="brush: scala; title: ; notranslate">
//cache the method into y
scala&gt; def m1(x: =&gt; Int) = { val y=x; List(y, y) }
m1: (x: =&gt; Int)List[Int]

//get the same values
scala&gt; m1(r.nextInt)
res38: List[Int] = List(-527844076, -527844076)
</pre>
<p>Is it possible to maintain the dynamic nature of x in the body? You could cache it as a function by explicitly converting it:</p>
<pre class="brush: scala; title: ; notranslate">
//explicit conversion, but then you must invoke the function with ().
scala&gt; def m1(x: =&gt; Int) = { val y=x _; List(y(), y()) }
m1: (x: =&gt; Int)List[Int]

scala&gt; m1(r.nextInt)
res39: List[Int] = List(1413818885, 958861293)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/08/21/revealing-the-scala-magician%e2%80%99s-code-method-vs-function/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>equals() and Scala</title>
		<link>http://agileskills2.org/blog/2011/08/06/equals-and-scala/</link>
		<comments>http://agileskills2.org/blog/2011/08/06/equals-and-scala/#comments</comments>
		<pubDate>Sat, 06 Aug 2011 15:48:06 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=323</guid>
		<description><![CDATA[Problem with equals() The problem with equals() is that it is difficult to get it right. For example, for a simple class Foo, you may write the equals() method as: The problem is that what happens if the other object (&#8220;that&#8221;) belongs to a subclass of Foo, which may have its own fields? As the [...]]]></description>
			<content:encoded><![CDATA[<h3>Problem with equals()</h3>
<p>The problem with equals() is that it is difficult to get it right. For example, for a simple class Foo, you may write the equals() method as:</p>
<pre class="brush: scala; title: ; notranslate">
class Foo(val i: Int) {
  override def equals(that: Any) = {
    that match {
      case f: Foo =&gt; f.i == i
      case _ =&gt; false
    }
  }
}
</pre>
<p>The problem is that what happens if the other object (&#8220;that&#8221;) belongs to a subclass of Foo, which may have its own fields? As the equals() method is only comparing the &#8220;i&#8221; field, it will ignore the other fields and return true prematurely. Below is such a subclass Bar:</p>
<pre class="brush: scala; title: ; notranslate">
class Bar(i: Int, val j: Int) extends Foo(i) {
  override def equals(that: Any) = {
    that match {
      case b: Bar =&gt; super.equals(b) &amp;&amp; b.j == j
      case _ =&gt; false
    }
  }
}
</pre>
<p>With the erroneous equals() method in Foo, we could get incorrect results:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; val f1 = new Foo(2)
f1: Foo = Foo@14c0275

scala&gt; val b1 = new Bar(2, 3)
b1: Bar = Bar@171bc3f

scala&gt; f1.equals(b1)
res0: Boolean = true

scala&gt; b1.equals(f1)
res1: Boolean = false
</pre>
<h3>A solution to the problem</h3>
<p>The problem is that the equals() method in Foo is treating the Bar object exactly as a base Foo object, but the equality contract in Bar has changed from that in Foo. Of course, not every subclass of Foo will use a different equality contract; some do and some don&#8217;t (by default, we should assume that they don&#8217;t). Therefore, the equals() method in Foo should make sure that the &#8220;that&#8221; object uses the same equality contract as &#8220;this&#8221;:</p>
<pre class="brush: scala; title: ; notranslate">
object FooEqualityContract {
}

class Foo(val i: Int) {
  //by default all Foo objects and subclass objects use this equality contract
  val equalityContract: Any = FooEqualityContract

  override def equals(that: Any) = {
    that match {
      //make sure the two objects are using the same equality contract
      case f: Foo =&gt; f.equalityContract == this.equalityContract &amp;&amp; f.i == i
      case _ =&gt; false
    }
  }
}
</pre>
<p>Now, as Bar is using its own equality contract, it should say so:</p>
<pre class="brush: scala; title: ; notranslate">
class Bar(i: Int, val j: Int) extends Foo(i) {
  //tell others that we're using our own equality contract
  override val equalityContract: Any = BarEqualityContract

  override def equals(that: Any) = {
    that match {
      case b: Bar =&gt; super.equals(b) &amp;&amp; b.j == j
      case _ =&gt; false
    }
  }
}
</pre>
<p>Now, the equals() method in Foo will rightly determine that a Bar object is using a different equality contract and thus will never be equal to a bare Foo object:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; val f1 = new Foo(2)
f1: Foo = Foo@34b350

scala&gt; val b1 = new Bar(2, 3)
b1: Bar = Bar@7c28c

scala&gt; f1.equals(b1)
res2: Boolean = false

scala&gt; b1.equals(f1)
res3: Boolean = false

scala&gt; val b2 = new Bar(2, 3)
b2: Bar = Bar@5dd915

scala&gt; b1.equals(b2)
res6: Boolean = true
</pre>
<p>Of course, it should also work for subclasses that use the same equality contract:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; val f2 = new Foo(2) { }
f2: Foo = $anon$1@a594e1

scala&gt; f1.equals(f2)
res9: Boolean = true

scala&gt; f2.equals(f1)
res10: Boolean = true
</pre>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/08/06/equals-and-scala/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple but highly useful feature request for DNS</title>
		<link>http://agileskills2.org/blog/2011/07/15/a-simple-but-highly-useful-feature-request-for-dns/</link>
		<comments>http://agileskills2.org/blog/2011/07/15/a-simple-but-highly-useful-feature-request-for-dns/#comments</comments>
		<pubDate>Fri, 15 Jul 2011 14:54:25 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[failover]]></category>
		<category><![CDATA[health check]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=320</guid>
		<description><![CDATA[Most people believe that by having two Windows domain controllers can provide transparent fail over, i.e., if one DC fails, the clients will automatically use the other. However, this is not true. The client will simply use the first DC returned by the DNS. Similarly, if you use DNS to load-balance between multiple web servers, [...]]]></description>
			<content:encoded><![CDATA[<p>Most people believe that by having two Windows domain controllers can provide transparent fail over, i.e., if one DC fails, the clients will automatically use the other. However, this is not true. The client will simply use the first DC returned by the DNS. Similarly, if you use DNS to load-balance between multiple web servers, when one of them fails, some clients will still be directed to it.</p>
<p>To fix the problem, there is a very simple solution: enhance the DNS server to perform a health check against the resulting host of the resource record. For example, the administrator could specify the TCP port to connect to as in the imaginary syntax below:</p>
<pre>  www        A      1.1.1.1    80     ; return this record only if we can connect to its TCP port 80
  www        A      1.1.1.2    80
  www        A      1.1.1.3    80
</pre>
<p>Of course, the health check could be more general, then you could use a script:</p>
<pre>  www        A      1.1.1.1    web-check.sh  ; return this record only if the script returns true
</pre>
<p>where the IP would be passed to that script as an argument for checking.</p>
<p>It works for domain controllers too:</p>
<pre>  _ldap._tcp.dc._msdcs.foo.com.   SRV  1.1.1.1  dc-check.sh
  _ldap._tcp.dc._msdcs.foo.com.   SRV  1.1.1.2  dc-check.sh</pre>
<p>Finally, one might ask why implement this checking in the DNS server instead of the clients? The idea is that problems should be detected  as early as possible to avoid bad effects downstream. In concrete terms, if a server  is down but the DNS server (broker) still refers the clients to it, many clients will need to perform this health check themselves. But if the DNS server performs this health check, the checking is only done once, saving a lot of trouble downstream.</p>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/07/15/a-simple-but-highly-useful-feature-request-for-dns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Revealing the Scala magician&#8217;s code: expression</title>
		<link>http://agileskills2.org/blog/2011/05/01/revealing-the-scala-magicians-code-expression/</link>
		<comments>http://agileskills2.org/blog/2011/05/01/revealing-the-scala-magicians-code-expression/#comments</comments>
		<pubDate>Sun, 01 May 2011 15:04:30 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=308</guid>
		<description><![CDATA[Scala is truly magical. However, sometimes it is not easy to understand how it performs the magic. Below are some common questions and their answers. Why some of expressions below work (can be evaluated and printed) but the other don&#8217;t? The first expression doesn&#8217;t work because Math.min is a method, but a method is not [...]]]></description>
			<content:encoded><![CDATA[<p>Scala is truly magical. However, sometimes it is not easy to understand how it performs the magic. Below are some common questions and their answers.</p>
<h4>Why some of expressions below work (can be evaluated and printed) but the other don&#8217;t?</h4>
<pre class="brush: scala; gutter: false; title: ; notranslate">
Math.min  //doesn't work
Math.min _  //works
val f: (Int, Int)=&gt;Int = Math.min  //works
</pre>
<p>The first expression doesn&#8217;t work because Math.min is a method, but a method is not a value in Scala. The second expression works because the underscore asks Scala to convert the method to a function, which is indeed a value in Scala. The third expression also works because when Scala is expecting a function value from the expression but finds a method, it will convert it to a function automatically.</p>
<h4>Why some of expressions below work but the other don&#8217;t?</h4>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach println  //works
List(2, 3, 5) foreach println(_) //doesn't work
List(2, 3, 5) foreach (println(_)) //works
</pre>
<p>The first one works because foreach is expecting a function, while println (of the Predef object which has been imported automatically) is a method, not a function, but as mentioned above Scala will convert it into a function automatically because a function is expected. So it works.</p>
<p>The second one is trying to create an anonymous function:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach ((x)=&gt;println(x))
</pre>
<p>However, in Scala only a &#8220;top level&#8221; expression can be a function. In this case, println(_) is only a &#8220;term&#8221; in an expression (foreach is the operator) but not a top level expression, so the compiler won&#8217;t try to make it an anonymous function. Instead, it will search further to find the first enclosing top level expression (in this case, the whole expression you entered) and turn it into an anonymous function:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
(x)=&gt;List(2, 3, 5) foreach println(x)
</pre>
<p>But then the type of x can&#8217;t be inferred, so it is an error. Also, println(x) returns a value of (), the only value of the class Unit, which is not what foreach wants anyway (a function taking an Int).</p>
<p>With this knowledge, you can see why the third expression works:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach (println(_)) //works
</pre>
<p>This is because with the parentheses, a top level expression is expected, so Scala will make println(_) an anonymous function:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach ((x)=&gt;println(x)) //works
</pre>
<h4>Why some of expressions below work but the other don&#8217;t?</h4>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach (println(&quot;hi&quot;+_))  //doesn't works
List(2, 3, 5) foreach (println &quot;hi&quot;+_)  //doesn't works
List(2, 3, 5) foreach (Predef println &quot;hi&quot;+_)  //works
</pre>
<p>The first expression doesn&#8217;t work because the first top level expression found is &#8220;hi&#8221;+_ due to the parentheses. So, Scala will treat it as:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach (println((x)=&gt;&quot;hi&quot;+x))  //doesn't works
</pre>
<p>So you&#8217;re printing a function to the console and returning a unit value () to foreach. In order to fix the problem, you may try to get rid of the parentheses so &#8220;hi&#8221;+_ is no longer a top level expression:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach (println &quot;hi&quot;+_)
</pre>
<p>The problem is that Scala will now try to parse:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
println &quot;hi&quot;+_
</pre>
<p>as:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
expr1 op1 expr2 op2 ...
</pre>
<p>println is assumed to be an expression instead of a prefix operator because only !, ~, +, &#8211; can be prefix operators. So, println will be treated as an expression while the String &#8220;hi&#8221; will be treated as an operator, which is obviously incorrect.</p>
<p>To fix this problem, you can provide a real object as expr1, which is the Predef object:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach (Predef println &quot;hi&quot;+_)
</pre>
<p>Note that there are two operators: println and +. Because all symbolic operators have higher precedence than identifier operators, + will be applied first.</p>
<p>So, the first enclosing top level expression is turned into an anonymous function:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach ((x)=&gt;Predef println &quot;hi&quot;+x)
</pre>
<p>Because in Scala &#8220;e1 op e2&#8243; is treated as e1.op(e2), the code is treated as:</p>
<pre class="brush: scala; gutter: false; title: ; notranslate">
List(2, 3, 5) foreach ((x)=&gt;Predef.println(&quot;hi&quot;.+(x)))
</pre>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/05/01/revealing-the-scala-magicians-code-expression/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Great way to learn the Scala API: Scala interpreter</title>
		<link>http://agileskills2.org/blog/2011/04/22/great-way-to-learn-the-scala-api-scala-interpreter/</link>
		<comments>http://agileskills2.org/blog/2011/04/22/great-way-to-learn-the-scala-api-scala-interpreter/#comments</comments>
		<pubDate>Fri, 22 Apr 2011 08:15:16 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Scala]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[scala interpreter]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=301</guid>
		<description><![CDATA[If you have already learned the language construct of Scala, the next step is to learn its API. If you&#8217;re a Java programmer, usually you&#8217;ll try to do that by writing small Scala programs in an IDE. However, there is a much better way: using the Scala interactive interpreter. This way you can inspect the [...]]]></description>
			<content:encoded><![CDATA[<p>If you have already learned the language construct of Scala, the next step is to learn its API. If you&#8217;re a Java programmer, usually you&#8217;ll try to do that by writing small Scala programs in an IDE. However, there is a much better way: using the Scala interactive interpreter. This way you can inspect the effect of each line of code as soon as you press Enter. This is quite non-obvious for Java programmers because there is no such thing in the Java tool set.</p>
<p>For example, you&#8217;d like to learn about the Seq trait in Scala. So you open the API page of it and find a long list of methods. Let&#8217;s say you&#8217;re interested in learning the behaviors of the following methods:</p>
<pre class="brush: scala; title: ; notranslate">
/** Appends all elements of this sequence to a string builder. The written text consists of the string representations (w.r.t. the method toString) of all elements of this sequence without any separator string. */
def addString(b: StringBuilder): StringBuilder
</pre>
<p>To do that, you issue the &#8220;scala&#8221; command from a shell/command prompt and then explore the method like:</p>
<pre class="brush: scala; title: ; notranslate">
kent@dragon:~$ scala
Welcome to Scala version 2.8.0.r20327-b20091231020112 (Java HotSpot(TM) Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala&gt; val a = List(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)
a: List[Int] = List(a, b, c)

scala&gt; val b = new StringBuilder
b: StringBuilder = 

scala&gt; b.append(&quot;hi&quot;)
res0: StringBuilder = hi

scala&gt; a.addString(b)
res1: StringBuilder = hiabc
</pre>
<p>From the experiment, it is clear that the addString() method will append all the elements of the Seq to the string builder.</p>
<p>Let&#8217;s consider another. You&#8217;re interested in:</p>
<pre class="brush: scala; title: ; notranslate">
/** Multiplies up the elements of this collection. num is an implicit parameter defining a set of numeric operations which includes the * operator to be used in forming the product.
*/
def product[B &gt;: A](num: Numeric[B]): B
</pre>
<p>So, try it in the Scala interpreter:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; val a = List(3, 5, 2)
a: List[Int] = List(3, 5, 2)

scala&gt; a.product
res2: Int = 30
</pre>
<p>So it seems to work fine. Possible to override the * operator? From the API doc it is clear that the default being used is the IntIsIntegral object:</p>
<pre class="brush: scala; title: ; notranslate">
package scala.math

class Numeric {
  object IntIsIntegral extends IntIsIntegral with IntOrdering {
     ...
  }
}
</pre>
<p>So, the first try is:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; import scala.math.Numeric._
import scala.math.Numeric._

scala&gt; val x = new IntIsIntegral {
     | override def times(x: Int, y: Int) = x+y;
     | }
&lt;console&gt;:9: error: object creation impossible, since method compare in trait Ordering of type (x: Int,y: Int)Int is not defined
</pre>
<p>Oops, forgot to specify the IntOrdering trait which defines the compare() method. So, do it now:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; import scala.math.Ordering._
import scala.math.Ordering._

scala&gt; val x = new IntIsIntegral with IntOrdering {
     | override def times(x: Int, y: Int) = x+y;
     | }
x: java.lang.Object with math.Numeric.IntIsIntegral with math.Ordering.IntOrdering = $anon$1@1e5d007
</pre>
<p>We have successfully created a new object to redefine the * operator as just addition. Now, pass it to the product() method:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; a
res5: List[Int] = List(3, 5, 2)

scala&gt; a.product(x)
res6: Int = 11
</pre>
<p>It should be 3+5+2=10 but why the result is 11? Recall that it is doing multiplication, so it is using 1 as the seed for calculation (1+3+5+2). To change the seed from 1 to, say, 0, we can override the one() method:</p>
<pre class="brush: scala; title: ; notranslate">
scala&gt; val x = new IntIsIntegral with IntOrdering {
     | override def times(x: Int, y: Int) = x+y;
     | override def one = 0;
     | }
x: java.lang.Object with math.Numeric.IntIsIntegral with math.Ordering.IntOrdering = $anon$1@11a9f20

scala&gt; a.product(x)
res7: Int = 10
</pre>
<p>Obviously now it works.</p>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/04/22/great-way-to-learn-the-scala-api-scala-interpreter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Five signs that your talents are not being appreciated</title>
		<link>http://agileskills2.org/blog/2011/04/05/five-signs-that-your-talents-are-not-appreciated/</link>
		<comments>http://agileskills2.org/blog/2011/04/05/five-signs-that-your-talents-are-not-appreciated/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 12:51:14 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Cobit]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=295</guid>
		<description><![CDATA[Here are the five signs: Late arrival to the office. Your boss is so blind to see your great contributions to the company, therefore you are so de-motivated that you come in to the office late everyday. Micro-management. Your boss is always trying to micro-manage you by telling you the &#8220;right&#8221; ways to do things [...]]]></description>
			<content:encoded><![CDATA[<p>Here are the five signs:</p>
<ol>
<li><strong>Late arrival to the office.</strong> Your boss is so blind to see your great contributions to the company, therefore you are so de-motivated that you come in to the office late  everyday.</li>
<li><strong>Micro-management.</strong> Your boss is always trying to micro-manage you by telling you the &#8220;right&#8221; ways to do things such as agile methodologies, but actually you know those aren&#8217;t just good as your way because you&#8217;ve been in the trenches long before your boss.</li>
<li><strong>Rejecting your good suggestions.</strong> You have been pushing a complete conversion to a cutting edge technology to double the productivity of the team, but your boss just won&#8217;t listen.</li>
<li><strong>Incompetent peers.</strong> Your peers  are so incompetent and have been hampering the product   launch. Even though you have been telling them their problems, they just   don&#8217;t get it.</li>
<li><strong>Being blamed.</strong> Your peers are so jealous of your great abilities that they try to isolate you and blame you for everything that has gone wrong.</li>
</ol>
<p>These signs seemingly indicate that people aren&#8217;t appreciating your talents, but the fact is you may be just living in your own little world and will probably be fired in a few months! The  truth that you may not be understanding right now is:</p>
<ol>
<li><strong>Late arrival to the office (Lack of commitment).</strong> Even if you aren&#8217;t happy with your job or the way you&#8217;re treated, you should still demonstrate your commitment to your duties. Arriving late is an obvious way to say that you have no commitment.</li>
<li><strong>Micro-management (Not accepting advise for improvement).</strong> Seeing the difficulties you face, your boss is trying to help you by giving you good advice. But you are so attached to your ego and stubborn to see any values in any new approaches.</li>
<li><strong>Rejecting your good suggestions (Not understanding the priorities of the company).</strong> Your suggested technology may seem great to yourself, but actually it may be just too premature or is not among the top priorities of the company. Everyone is trying to tell you that but you just won&#8217;t listen.</li>
<li><strong>Incompetent peers (Destroying harmony).</strong> You may be good or not, but it is never a good idea to pick the mistakes of others. You will appear like an asshole to all your peers. Instead, you should help others improve.</li>
<li><strong>Being blamed (Not seeing your own mistakes).</strong> Be brave and admit it, those mistakes were yours. If you don&#8217;t see your own mistakes, you&#8217;ll never grow.</li>
</ol>
<p>Fortunately, it is not too late to realize your own mistakes. Stop denying and you&#8217;ll have a much brighter future.</p>
<p>ps, if you’d like to learn more about IT management and governance, check out <a href="http://agileskills2.org/ITGBE/">IT Governance by Examples</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/04/05/five-signs-that-your-talents-are-not-appreciated/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>A story for development outsourcing clients</title>
		<link>http://agileskills2.org/blog/2011/03/27/a-story-for-development-outsourcing-clients/</link>
		<comments>http://agileskills2.org/blog/2011/03/27/a-story-for-development-outsourcing-clients/#comments</comments>
		<pubDate>Sun, 27 Mar 2011 10:46:19 +0000</pubDate>
		<dc:creator>Kent Tong</dc:creator>
				<category><![CDATA[Cobit]]></category>

		<guid isPermaLink="false">http://agileskills2.org/blog/?p=280</guid>
		<description><![CDATA[Once upon a time there was a client who had contracted a carpenter to make a chair for him. In order to protect his own interests, he spent a lot of time specifying the dimensions of the chair, the material and etc. Then he negotiated with the carpenter to settle on the cost and duration. [...]]]></description>
			<content:encoded><![CDATA[<p>Once upon a time there was a client who had contracted a carpenter to make a chair for him. In order to protect his own interests, he spent a lot of time specifying the dimensions of the chair, the material and etc. Then he negotiated with the carpenter to settle on the cost and duration. In addition, he set up a monetary reward for early delivery and a daily penalty for each day late.</p>
<p>Then there was another client who spent a lot of time looking for and selecting a carpenter with good reputation for excellent customer satisfaction. He only told the carpenter that he needed a chair that is comfortable to sit on and then drafted a sketch of the chair. Then he  negotiated with the carpenter to settle on the cost and duration. There was no reward for early delivery and no penalty for late delivery. They agreed to discuss to adjust the cost and duration if there turned out to be  a need.</p>
<p>Then what was the result? The first client got the chair earlier than the deadline and the carpenter got the reward. However, when the client sat on the chair, it was not that comfortable. Because the carpenter rushed to finish it, the craftsmanship was poor and as a result, the chair was broken in a year. Then, it was found that low-graded wood was used in the inner, hidden part of the chair.</p>
<p>In contrast, the other client found that the chair was not that comfortable during the making. So he discussed with the carpenter to make the necessary change. The cost was increased by a little and the duration was longer by a little, but the carpenter had enough time for him to make a quality chair that he is proud of, which finally lasted for 10 years.</p>
<h2><span>The moral of the story<br />
</span></h2>
<p>The moral of the story is that in any project there are four factors to be considered: cost, time, scope and quality. If any of those changes, at least one of the other must change accordingly. The problem is, most people will try to fix/specify all those in planning, but in really only cost and time can be easily fixed, while it is very difficult to fix/specify the scope and quality (they are fuzzy and dynamic). So, from the view of the contractor, to meet the fixed cost and time, he has every incentive to minimize the scope (only make  what is explicitly told and nothing else) and reduce the quality (uncomfortable to sit, poor craftsmanship, low-graded wood).</p>
<p>The reward and the penalty make the matter worse. They double the importance of meeting the time factor, so they double the incentive for the contractor to minimize the scope and reduce the quality.</p>
<p>To solve this problem, many people try to make the scope and quality even better specified. However, this effort is futile as scope and quality are related to the needs of human which is fuzzy and dynamic. In the example of the chair, what is the quality? Perhaps that it should be comfortable to sit on, that it should last long, etc. But these aren&#8217;t objective (what is comfortable?) nor can be measured immediately (how long it will last?), so they can&#8217;t be used to bind the behavior of the contractor.</p>
<p>Therefore, there must be a second level of defense to deal with this fuzziness and dynamics. In addition to specifying the scope and quality at our best effort, we must also identify the contractor who really cares for quality. The idea is that he will work for quality on a higher-level (what we really care about) instead of focusing on meeting lower-level but objective metrics which do not necessarily fully reflect quality. That is the best insurance that we can get. Of course, to allow him to work for the fuzzy and dynamic scope and quality, we must be prepared to renegotiate with him to adjust the cost and duration as necessary.</p>
<p>ps, if you&#8217;d like to learn more about IT management and governance, check out <a href="http://agileskills2.org/ITGBE/">IT Governance by Examples</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://agileskills2.org/blog/2011/03/27/a-story-for-development-outsourcing-clients/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 2.253 seconds -->

