9.27.2008

Quick Post: Scala Syntax Primer

I don't normally want to post and run, but this one was just too good to pass up: link

8.27.2008

Meta-programming In Ruby

Last Wednesday (08.27.2008), I attended a presentation given by local ruby "hero" Joe O'Brien. He was presenting techniques for meta-programming in Ruby. Meta-programming is a general topic which applies to many languages, however Ruby provides some very basic methods which result in powerful meta-programming tools for creating dynamic run-time functionality and for enhancing the base language.

Meta-programming Methods

Joe started the presentation with a run-down of some of the meta-programming methods exposed by the base object in Ruby.
  • send--By using the send method with a string value (method name) and a list of parameters you can dynamically choose a method to call. This method is provided in conjunction with the message-passing back-bone used by the Ruby interpreter.
  • method_missing--Implementations of the method_missing message handler can be used to handle messages which are currently not understood by the receiving object. This is an expensive method to use, but can be used to add new functionality in response to an unknown message. ActiveRecord in Rails uses this method to create finder methods when a search is performed.
  • eval--Evaluate a string value as arbitrary Ruby code. User beware Since this method takes a string argument as the code to be evaluated, any code in that string is not checked by the interpreter until the eval statement is executed by the interpreter.
  • define_method--Pass a string value (method name) and a block in order to define a new method defined by the given block. This method takes a block as a parameter and is safer to use than the eval method.
  • methods--Returns an array of the methods currently defined on an object. By calling methods on an object and subtracting the result of calling methods on that object's supertype, you can easily get a list of the methods defined only within that object.
  • attr_reader--The attr_reader method is used to make a private field in an object accessible to other objects.
  • attr_writer--The attr_writer method is used to make a private field in an object settable by other objects.
  • attr_accessor--The attr_accessor method is used to make a private field in an object accessible and settable by other objects.

Example: Declarative Tests and Home-Grown Behavior Driven Development

Joe, being a "test-first bigot" (his words, not mine), was uncomfortable with the idea that it took him nearly 10 lines of code to test one ActiveRecord has_many association. He also expressed his dislike for creating test methods whose names look like test_a_description_of_the_test. His iterative approach to creating a declarative version of this this test method started with the original 10 lines of code in his test method. He extracted that method into a method on the Test::Unit::TestCase class, test_that, which took three arguments, the model under test, the expected has_many association class, and a description of the test as a string. These parameters were used in conjunction with the define_method method to create a new method at run-time which executed the original code. Using this technique, Joe stated that he was able to reduce the tests for many of the ActiveRecord capabilites to one-liners.

8.19.2008

Thanks jTrac, You're Doing a Fine Job

I just wanted to give a shout-out to the members of the jTrac project. jTrac is an issue-tracking system which can be installed out of the box as a stand-alone server using Jetty and HSQLDB, or can be installed as a war in an existing server. jTrac was very easy to install in our existing JBoss instance and required only a few settings and a directory for storing attachments and the application's HSQLDB database files. Once you have it installed and configured, you can create spaces for each of your applications. Each of these spaces can have a set of custom fields as well as a custom set of states and transitions. Write access to each space is limited to only members of that space. In addition you can make transistions dependent on a particular user role within the space. The application seems to be mature enough to be feature complete, but does still have some minor nice-to-haves (book-markable searches, Eclipse Mylyn integration) and missing ui polish.

7.29.2008

Hibernate Bites... (revisited)

An update to this post. Okay, so we have been able to make the caching work with very little changes to our mappings. By moving the cache element from the child entity definition into the collection declaration in the parent entity we have gotten the caching to work.

Finished Exercise #1 for Scala

I've just finished exercise #1 from: knowing.net. Please feel free to critique this code, I am serious about learning Scala and getting introduced to members of the community.

Calculator.scala

package activeactive
class Calculator {
  def main(args:Array[String]): Double = eval(args.toList)
    def eval(args:List[String]): Double = args match {
      case null =>
        throw new IllegalArgumentException(
          "args cannot be null-valued")
      case Nil =>
        throw new IllegalArgumentException(
          "You must provide a function name as the first argument")
      case "sum" :: rest => sum(convertList(rest))
      case "prod" :: rest => product(convertList(rest))
      case "mean" :: rest => mean(convertList(rest))
      case "sqrt" :: rest => sqrt(convertList(rest))
      case _ => throw new IllegalArgumentException(
        "invalid function name. Use 'sum', 'prod', 'mean', or 'sqrt'.")
    }
    def convertList(list: List[String]): List[Double] = list match {
      case Nil => Nil
      case x :: subList => x.toDouble :: convertList(subList)
    }
    def sum(list: List[Double]) =
      (0D :: list) reduceLeft ((x, y) => x+y)
    def product(list: List[Double]) =
      (1D :: list) reduceLeft ((x, y) => x*y)
    def mean(list: List[Double]) = list match {
      case Nil => throw new IllegalArgumentException(
        "The mean function requires at least one operand")
      case _ => sum(list) / list.size
    }
    def sqrt(list: List[Double]) =
      if (sum(list) <= 0)
        throw new IllegalArgumentException(
          "the input values '" + list.toString +
            "' resulted in a sum <= zero.")
      else if (sum(list) == 1D) 1D
      else Math.sqrt(sum(list))
}
EDIT: updated knowing.net link.

7.28.2008

Hibernate Bites...

...us in the butt Our team recently chose to use Hibernate for handling read-only access to data in our configuration and archive databases. Our primary decision for doing this was to use the baked-in caching provided by ehcache. Since then, we have had three major releases, the first two each containing a bit more hibernate than the previous, and the third, our architecture re-design, in which we spread Hibernate into all of the read-only data access classes. Our love affair with Hibernate was deep and passionate. Then disaster struck. During the verification of the installation of our new architecture to the disaster recovery environment, we found that many of our web-service responses were taking much longer than our service-level agreement allowed, significantly longer. One full week later, we have determined that most of the SessionFactory instances which we thought were caching, were in fact not caching. One particular request to our web service caused 43000 queries to be generated from one repeated (x1000) entity retrieval. This problem did not rear its ugly head in the primary environment because the app server and the database are much closer together on the network in the primary environment. The network timing differences were not great between our primary and disaster recovery environments, but when 43000 queries are being issued, each little bit adds up. We diagnosed our problems with a simple jsp that used SessionFactory.getStatistics() to get the collected statistics and then used Statistics.getEntityStatistics(), Statistics.getQueryStatistics(), and Statistics.getSecondLevelCacheStatistics() to display counts for cache misses, entity loads, cache puts, and cache hits. When you have caches defined that are not being used correctly, you will see more misses than puts, or you will see no misses and many puts. To solve our problems, we are looking at modifying some of the basic assumptions we had about how Hibernate does caching. We are removing some of the mappings in which a parent class was created simply to have one single object to retrieve for each id instead of a list of child objects. We are also now making use of the query cache in the situations in which we are using Criteria.list. In the future, we are looking to spread the use of Spring's JdbcTemplate, Select, and Update classes in conjunction with directly using ehcache or a home-grown caching solution. Lesson Learned: Make sure that you are verifying that your SessionFactory instances are actually caching your cacheable entities as early in the project as you can. If you can, make sure that your integration tests are asserting cache statistics, both in the query cache and in the entity cache.

7.27.2008

HelloWorld in Scala with the Eclipse Plug-in

The Eclipse plug-in for Scala makes you jump through two hoops before letting you run your application from the Run... menu:
  1. Your main object must extend Application.
  2. Since main is now overridden, you must use the override keyword on the method definition.
package activeactive
object Main extends Application {
  override def main(args:Array[String]) {
    println("Hello World!")
  }
}

Learning Scala

I attended Stuart Halloway's dynamic language shoot-out presentation at NFJS last night. Ruby, Clojure, and Scala are the three languages in which he spent his time. Stuart claimed that each of these languages were made to run on the JVM in order to piggy-back on the penetration of the JVM in the enterprise. The choice of language you make is mostly unimportant, most of these interesting languages on the JVM provide the same general additions to Java running on the JVM. I intend to learn Scala this year. I feel that Ruby has a lot of penetration in the software development field, but that Scala is the up-and-coming language. I believe that the concepts and idioms in the languages are common enough to allow me to easily learn Ruby next year. My plan of attack for learning Scala:
  1. Install Eclipse 3.4.
  2. Install the Scala plug-in from: http://www.scala-lang.org/tools/eclipse/index.html.
  3. Create a working hello world program.
  4. Complete the exercises from: http://www.knowing.net/index.php/2006/06/16/15-exercises-to-know-a-programming-language-part-1/.
  5. Decide on a personal project for using Scala.
  6. Complete the personal project.
  7. Find a suitable open-source project using Scala.
  8. Learn more about the project's eco-system.
  9. Contribute to the project's mailing list.
  10. Submit patches to the project.
  11. Decide on a work project using Scala.
  12. Complete the work project.
  13. Lather, rinse, repeat.
EDIT: updated knowing.net link.