Friday, February 24, 2012

A DSL for Continuation Passing Style in Scala


trait CPS {

  val dispatcher: Dispatcher
  
  def immediate[T](pProc: => T)(implicit pEscape: Escape): Call[T] = {
    new ImmediateCall(() => pProc)(pEscape)
  }
  
  def deferred[T](pProc: => T)(implicit pEscape: Escape): Call[T] = {
    new DeferredCall(() => pProc)(pEscape)
  }
  
  trait Call[T] {
    val escape: Escape
    val procBlock: () => T
    def evaluate(): T = procBlock()
    def continuation(pContBlock: (T) => Unit): Continuation[T]
  }
  
  class DeferredCall[T](val procBlock: () => T)(implicit val escape: Escape) extends Call[T] {
    def continuation(pContBlock: (T) => Unit): Continuation[T] = {
      new Continuation(pContBlock, this)
    }
  }
  
  class ImmediateCall[T](val procBlock: () => T)(implicit val escape: Escape) extends Call[T] {
    def continuation(pContBlock: (T) => Unit): Continuation[T] = {
      val cont = new Continuation(pContBlock, this)
      cont()
      cont
    }
  }

  class Continuation[T](val contBlock: (T) => Unit, val call: Call[T]) {
    def apply() {
      dispatcher.dispatch(call.procBlock, contBlock, call.escape)
    }
  }

  trait Dispatcher {
    def dispatch[T](pProcBlock: () => T, pContBlock: (T) => Unit, pEscape: Escape): Unit
  }
  
  trait Escape {
    def apply(pThrowable: Throwable): Unit
  } 
  
}

object BlockingCPS extends CPS {
  
  val dispatcher: Dispatcher = new Dispatcher {
    def dispatch[T](pProcBlock: () => T, pContBlock: (T) => Unit, pEscape: Escape): Unit = {
      try {
        pContBlock(pProcBlock())
      } catch {
        case t => pEscape(t)
      }
    }
  }
  
}

object NonBlockingCPS extends CPS {
  
  import akka.actor.Actor
  import akka.actor.Actor._
  
  case class Run[T](val procBlock: () => T, val contBlock: (T) => Unit, val escape: Escape)
  
  class CPSRunner extends Actor {
    def receive = {
      case Run(procBlock, contBlock, escape) => 
        try {
          contBlock(procBlock())
        } catch {
          case t => escape(t)
        }
    }  
  }
  
  val dispatcher: Dispatcher = new Dispatcher {
    def dispatch[T](pProcBlock: () => T, pContBlock: (T) => Unit, pEscape: Escape): Unit = {
      try {
        runnerRef ! Run(pProcBlock, pContBlock, pEscape)
      } catch {
        case t => pEscape(t)
      }
    }
  }

  private val runnerRef = actorOf[CPSRunner]
  runnerRef.start()

}


object Examples {
  
  import NonBlockingCPS._
   
  implicit object EscapeHandler extends Escape {
    def apply(pThrowable: Throwable): Unit = {
      println("Escaping test block with error: " + pThrowable)
      pThrowable.printStackTrace()
    }
  }
  
  def main(args: Array[String]) {
    runFactorial()
    runStringToDecimal()
  }
  
  def runFactorial() {

    factorial(0)
    factorial(1)
    factorial(2)
    factorial(3)
    factorial(4)
    factorial(5)
    factorial(6)
    factorial(7)
    factorial(8)
    
    def printResult(pResult: (Int, Int)) { 
      println("%d! = %d".format(pResult._1, pResult._2))
    }
    
    def factorial(pNumber: Int) {
      pNumber match {
        case 0 => printResult((0, 1))
        case n => factIter(1, pNumber)
      }
      def factIter(product: Int, n: Int) {
        immediate { 
          (n * product, n) 
        } continuation { folding: (Int, Int) =>
          if (folding._2 < 2) printResult((pNumber, folding._1))
          else factIter(folding._1, folding._2 - 1)
        }
      }
    } 
    
  }
  
  def runStringToDecimal() {
    
    val stringToDecimal = deferred {
      "123"
    } continuation { string =>
      immediate {
        BigDecimal(string)
      } continuation { decimal =>
        println("Decimal: " + decimal)
      }      
    }

    stringToDecimal()
    stringToDecimal()
    stringToDecimal()
    
  }
  
}

Monday, June 20, 2011

Non-Blocking Resource Pools with Scala Actors

This blog post is in regard to my presentation at the most recent meetup of the Atlanta Scala Enthusiasts group.

Thanks to all of you who attended the meeting -- I had a great time.  A special thanks goes to Jon Steelman and Consilium1 for hosting the group!

The gist of the presentation was:

1) Multi-core processors allow massive concurrency
2) Thread-based concurrency won’t scale to massive
3) Event-based concurrency will scale to massive
4) Enterprise software must scale to pass on cost savings
5) Enterprise resource pools use threaded concurrency and won’t scale
6) Non-blocking resource pools use Scala Actors
7) Non-blocking resource pools can handle massive bursts
8) Non-blocking resource pools give back pressure signals and can be tuned

I presented an abstraction for non-blocking resource pools in Scala and demonstrated a resource pool of checksum accumulators.  The test program simulated bursts of 3,000, 10,000 and 5,000 requests contending for a pool of just 10 resources.  The test program then ran a rolling load of 500 requests every 2 seconds.

The server process handled the load well.  Throughput reached a maximum but the system continued to service the bursts at the expense of latency.

Some of the members discussed similar approaches where they used queuing middleware.  In general, I think it’s impressive that we can accomplish this safely (message-based concurrency) within the language itself without using other middleware.

My presentation slides have been posted at:

and source code has been posted at:

Thursday, May 5, 2011

Cross Platform Mobile Apps


I just finished reading Martin Fowler’s bliki post on Cross Platform Mobile [1], and I must tell you, it resonated strongly with me since I’ve spent more than 15 years working on GUI interfaces for enterprise software and the underlying architectures that support them.

Martin points out that the rise of so many mobile platforms, each with a different UI, has people looking at cross-platform toolkits that allow you to write a mobile app once and then deploy it to a range of mobile devices.  He then asks the question, “Are these toolkits worth using?” After touching on the major problem of porting UI controls, he highlights what I consider to be the biggest problem, the great disparity in how mobile UI’s approach user interaction. As a result, Martin thinks cross-platform toolkits are a dead-end.

Martin concludes by saying, “If it’s worth building a native app, it’s worth building it properly, including an individual user experience design for that platform.” He goes on to say that if you want to support lots of mobile platforms, but aren’t prepared to deal with the cost of native apps, then use web apps designed for mobile platforms.

I must point out that Martin is describing a cross-platform technique known as cross-compiling. This technique involves a 4GL programming language, cross-platform UI libraries, or a visual programming environment as a way to express program models. The program models are then used to generate real programs. Cross-compiling means that the tool can generate multiple real programs for different platforms thereby creating the illusion that you program once for multiple platforms. As Martin points out, the problem with cross-compiling is the lack of fidelity with the target platform.

It appears that the industry thinks there are only two solutions to the cross-platform mobile problem: cross-compiling and web apps (with HTML 5 being the latest rage). However, there is a third. It's the declarative solution, which is the solution provided by Catavolt. Programmers declare the user interface and declare the screen flow in data structures. These declarations are interpreted by a user interface kernel (there exists one kernel for each target platform). A large amount of the application programming is unspecified by the programmer. Instead, the kernel is free to behave in a way that is unique to its native platform. This approach allows a lot of freedom in the kernels and allows them to be very native (high fidelity). The kernel only has to ensure that the rules of the declarative model are enforced.

This declarative approach to user interfaces is part of a new architecture [2] that is completely independent of UI technologies. If I had to list the essential features that make it all possible, it would be the following:
  • Dialog Models – These objects replace application controllers.   Dialog models look like entities, but are coarse grained and completely independent of the underlying domain model.  This novel layer allows much code to be factored out of the UI program and into the server program.
  • Redirections – The typical rich interface contains navigation logic.  Redirections allow navigation code to be factored out of the UI program and into the sever program.  Redirections are similar to hyper-links but they exist deeper in the framework stack and are therefore open to a higher level of reuse.  Think “hyper-objects”.
  • Metadata – All conceptual entities (not implementation entities) are defined with metadata.  Furthermore, all UI elements are defined with metadata.  This includes forms, lists, graphs, maps, etc.  Dialog models, redirections, and metadata combine to make a powerful mechanism for driving native user interfaces from the server.
  • User Interface Kernel – Each UI platform that interacts with this architecture has a kernel program that begins interacting with dialog models through a workbench definition, which is similar to a home page.  The UI kernel is lightweight and driven by the server through dialog models, redirections, and metadata.
  • Simple Object Interface – All clients interact with the server through a single API called the Simple Object Interface.  Although simple in its object-oriented design, this API supports sophisticated interactions.  The server driven approach used by the user interface kernel is a consequence of the contract between the UI kernel and dialog models.  Conversations don’t have to be server driven.  If there’s a need, UI programs can be written to act directly on dialog models without redirections.  Not all clients have to be a human interface.  Web services are an example of machines interacting through the SOI.

Developing mobile applications for enterprise software is a scaling problem – Many User Roles times Many Applications times Many Platforms.  Sure, you can write mobile web apps, but it’s quite obvious that users prefer a native experience and the extra level of device integration.

A cost-effective solution to native applications for mobile devices requires an innovative approach.


Sunday, May 1, 2011

Time to Redesign Your Enterprise Architecture

We’ve certainly reached a tipping point in personal computing.  I’m not sure whether the iPhone or iPad caused the tip, but there’s one thing I know for sure, the market has changed.  Windows is now less than 50% of internet-connected devices, down from 97% ten years ago [1].  This swing in the market is causing enterprises to scramble and figure out how to better leverage less expensive smart phones and tablets. 

Smart phones and tablets are exciting, but we must also pay attention to new developments in other areas like application deployment, multi-core processors, alternative databases, soft hardware [2], and new programming languages.  Taken as a whole, these new developments offer tremendous potential for developing wildly innovative, distributed, and low cost solutions.  These developments almost certainly require a redesign in your enterprise architecture.  The good news is that your redesign can be incremental over time [3].

The rest of this post is my commentary on the technological areas that I think will have the greatest impact on enterprise architecture.

New User Devices

The Development: The iPhone was available in 2007, the Android in 2008, the iPad in 2010, and since then, an explosion of smart phones and tablets have entered the market.  Later this year, Microsoft Surface 2.0 will be available for purchase and will offer new user experiences and interactions.

The Challenge: Designing software to be flexible so that new devices and native applications can be easily folded into a system is difficult.  Beyond the architecture challenges sits a work effort challenge.  Developing multiple native applications to run on multiple device types is a multiplicative work effort.  Some might think that HTML 5 is the answer.  HTML 5 will certainly help deliver a better user experience than current HTML, but I believe the majority of apps delivered will still be native because of the integrated, unique, and immersive user experience.

Application Deployment

The Development: For the past decade, the web server has been the obvious choice for simple, low cost application deployment.  The general idea was that you could deploy your app to any user that ran a web browser, which meant you could reach just about anyone since virtually every user was a Windows PC running Internet Explorer.  The App Store opened in July 2008, and in less than 3 years, the App Store has proven a formidable competitor to the web server for deploying applications.

The Challenge: Programmers must re-train and develop to a more traditional client-server model.  Enterprises must re-tool their processes to use either a public app store or a private system that manages applications and devices instead of web pages and web resources.

Multi-Touch User Interfaces

Introduction: Since the late 1980's the mouse pointer and keyboard have been the standard devices for user input into PCs and laptops.  In 2007, the iPhone created a radically new experience by combining multi-touch recognition with animated graphics.  The resulting interface was space-efficient, intuitive, and most importantly, immersive.  Thanks to Apple, today there's a higher standard for how users expect to interact with their computers.

Challenges: Designing for multi-touch requires new knowledge and skills in human-computer interaction.  Both designers and programmers must become effective at integrating new multi-touch technology into applications.

Multi-Core Processors

Introduction: Processors were originally developed with only one core to process instructions.  Recently, processor manufactures experienced greatly diminished gains from increasing processor speeds (operating frequency).  To continue delivering regular performance gains, manufacturers like Intel turned to multi-core designs, which allow different threads to run on separate processors.

Challenge: Herb Sutter described the multi-core challenge in his “The Free Lunch Is Over” article [4].  “The key difference [between faster processors and more processor cores], which is the heart of this article, is that the performance gains are going to be accomplished in fundamentally different ways for at least the next couple of processor generations. And most current applications will no longer benefit from the free ride without significant redesign.”

Soft Hardware (aka Cloud Hardware)

Introduction: The latest buzz phrase is “Cloud Computing”.  From a software architecture perspective, this is the ability to wrap hardware resources in software.  The result is an opaque set of APIs that system architects use to dynamically grow and shrink IT resources – on demand.

Challenge: This new topology is a challenge to software architects because it requires a level of elasticity that is not yet designed into enterprise systems.

Alternative Databases

Introduction: Cloud computing, multi processors, and highly concurrent applications encourage clusters of servers in order to achieve 24/7/365 redundancy and fail-safe services.  These services can produce massive amounts of persistent data (think Facebook or Twitter).  As it turns out, traditional SQL databases based on the ACID principle don’t scale properly.  See CAP Theorem [5] and CAP PACELC [6].  In response to these new requirements, the industry has settled on a class of database servers known as NoSQL [7]. 

Challenges: These new databases discourage the use of SQL and encourage a denormalized entity schema, which is a change in thinking for traditional database designers and a change in APIs and technique for database programmers.

New Programming Languages

Introduction: This new era of computing is quite sophisticated with a variety of new problems not found in today’s enterprise.  There are specialized programming languages (like Erlang) that might address some problems, but what’s needed is a multi-paradigm language suitable for a whole range of problems.  Fortunately, we have the Scala programming language [8], which was designed specifically to support functional and object-oriented paradigms, but more importantly, to be extended to support other paradigms like message-passing concurrency.

Challenges: Solving tomorrow’s problems in enterprise software will require a multitude of programming techniques that go beyond the object-oriented techniques most common today.  For example, actor based concurrency is arguably a better concurrency model for highly scalable systems.  Architects and programmers must increase their knowledge and skills if they expect to be effective.

References

[1] CNBC video

[2] “Soft Hardware” is a phrase I coined to better help my clients understand the essence of hardware in the cloud.

[3] Catavolt Extender is an example of reusing your current applications along side new technology to produce mobile applications.  Disclosure: I am the chief architect at Catavolt.

[4] “The Free Lunch is Over”

[5] CAP Theorem

[6] PACELC

[7] NoSQL

[8] Scala Programming Language