tag:blogger.com,1999:blog-73172458222886371852024-02-18T23:51:47.516-08:00Graham Hacking ScalaThe point of "Graham Hacking Scala" is to share with you my knowledge of and experience with the Scala programming language. The blog will contain everything from introductions to basic features through to in-depth analysis of complex techniques and problems. When I make mistakes, you will learn from my mistakes. When I discover cool features, you will learn about them, too.Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.comBlogger51125tag:blogger.com,1999:blog-7317245822288637185.post-91160479125920745472012-11-22T19:46:00.002-08:002012-11-22T19:46:46.661-08:00Graham Now Hacking Scala at GrahamLea.comThis is just a quick post for people who've been following 'Graham Hacking Scala' to let you know that I am now blogging - often about Scala but sometimes about other stuff - at <a href="http://www.grahamlea.com/">www.grahamlea.com</a> Hope to see you there!
Graham.Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-20108628242956192762012-01-20T19:26:00.000-08:002012-01-20T19:46:17.082-08:00JavaScript and Scala: Good Parts and BadI've just finished reading <a href="http://www.amazon.com/gp/product/0596517742/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&tag=belmontechno-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596517742">"JavaScript: The Good Parts" by Douglas Crockford</a>. It's a fantastic book, mostly because it's incredibly concise, elaborating only the details that experienced programmers should need to understand the true form of JavaScript. If you do ANY JavaScript programming and you haven't read it, I suggest you go out and get it straight away, and don't write a single line more of buggy JS code until you do.<br />
<br />
<b>What is 'this'?</b><br />
Early on in the book, Crockford highlights one of JavaScript's oddest and most dangerous quirks: the late binding of 'this'. Basically, whenever you call a function, the value of 'this' within the function is determined by HOW you called the function!<br />
<br />
To demonstrate: If object 'a' has a function called 'run()' and you invoke it like this:<br />
<pre class="brush: text">a.run();
</pre>
then the value of 'this' within 'run()' will be 'a'. JavaScript is a functional language, so functions can be passed around as values. If you instead invoked the function above using only a reference to the function value, like this:<br />
<pre class="brush: text">var f = a.run;
f();
</pre>
then the value of 'this' within 'run()' will be... the global variable pool! As you can imagine, that can lead to some pretty nasty and hard to track bugs. <br />
<br />
<b>Functional Limitations</b><br />
<b> </b>If you're a fan of functional programming, you might have tweaked straight away that this could place limits on the usefulness of functions as first class objects, and specifically higher-order functions (i.e. functions that take other functions in their parameters). <br />
<br />
Here's an example of an object that doesn't work with higher-order functions:<br />
<pre class="brush: text">var object1 = {
total: 0,
add: function(numbers) {
var i;
for (i = 0; i < numbers.length; i++) {
this.total += numbers[i]
}
return this.total;
}
};
var valueOf = function (f, p1) {
return f(p1);
}
var numbers = [1, 2, 3, 4];
document.writeln(object1.add(numbers) + " / " + valueOf(object1.add, numbers));
// outputs: 10 / NaN
</pre>
Obviously the reason this quirk causes confusion is because JavaScript has borrowed a keyword from other languages but uses it to mean something subtly different. Most OO languages use 'this' to represent a pointer to an object in which the function seemingly resides. Importantly, in OO/functional languages, when a function is used as a value, it takes with it a closure around 'this' that is used when invoking it. In JavaScript, however, the 'this' pointer just refers to the object on which the function was called, or if there was no object, just to the global variable pool.<br />
<br />
<b>This Naughtiness Explained</b><br />
There is a reason for this weirdness. Because JavaScript is classless, the function doesn't actually belong to the object in which it resides. In fact, it's not hard to imagine situations where JavaScript's behaviour is what you'd expect. If I took a function from one object and placed it in another object (which I can do, because the function is also a value), I actually would expect 'this' to refer to the new object when I invoked it, and JavaScript provides just that capability:<br />
<pre class="brush: text">var b = {};
b.run = a.run;
b.run(); // 'this' will refer to 'b'
</pre>
Once you understand where JavaScript is coming from a bit better, it's not too hard to see the solution to this problem. 'this' doesn't provide a closure around the context where your function was defined, so if you want a closure around the context where your function was defined, then give your function a closure around that context, rather than assuming that 'this' will be the same context whenever the function is invoked. To demonstrate this by correcting the example above:<br />
<pre class="brush: text">var object2 = (function () {
var that = {};
that.total = 0;
that.add = function(numbers) {
var i;
for (i = 0; i < numbers.length; i++) {
that.total += numbers[i]
}
return that.total;
};
return that;
})();
document.writeln(object2.add(numbers) + " / " + valueOf(object2.add, numbers));
// outputs: 10 / 20
</pre>
<b>Scala: The Bad Parts?</b><br />
<b> </b>Does any of this have anything to do with Scala? Well, in the details, no, but in the general sense there is a very important approach in Crockford's book. His suggested solution to the problem above is simple: don't use 'this' in JavaScript and don't use its accompanying feature, 'new'. In fact, he suggests not using LOTS of features of JavaScript. He dedicates 14 pages of appendix to listing them. <br />
<br />
Crockford also spends a very un-indulgent two pages discussing the modern phenomenon of "feature-driven design", both in products and programming languages, explaining how "Features that offer value to a minority of users impose a cost on all users" and concluding the book with this pearler: "It would be nice if products and programming languages were designed to have only good parts."<br />
It was those two lines that caused me to reflect on Scala. I started asking myself questions like: Are there too many features in Scala? Are there parts that aren't "good parts"? Are there features that very few people make use of but that cost everyone because of the complexity they add? From my own experience, the answer to all three of these is "yes". <br />
<br />
Crockford explains that we all crave simplicity and that, when we aren't given it, we make it for ourselves by creating our own feature subset, and I realised that I've done this to some extent in the way I use Scala. So finally I began wondering how long it will be until someone publishes "Scala: The Good Parts", complete with appendices listing all the features that you should steer clear of for everyone's sake. What confusing or dangerous feature of Scala do you reckon will be at the top of the list?
<br /><br />
<b style="color: #444444;">Want to learn more?</b><br />
<br />
<table><tbody>
<tr><td style="vertical-align: top;">From Amazon...<br />
<br />
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=0596517742" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></td><td style="vertical-align: top;">From Book Depository...<br />
<br />
<a href="http://www.bookdepository.com/JavaScript-Good-Parts-Douglas-Crockford/9780596517748/?a_aid=belmonttechnology"><img src="http://belmonttechnology.com.au/javascript_the_good_parts_small.png" style="border: 0pt none;" /></a></td></tr>
</tbody></table>Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com3tag:blogger.com,1999:blog-7317245822288637185.post-69663410800022350962012-01-08T22:44:00.000-08:002012-01-09T01:23:35.255-08:00Updates to Scala/Spring/Hibernate/Maven WebappOne of the projects I maintain is a public domain code base on <a href="https://github.com/">GitHub </a>called Scala-Spring-Hibernate-Maven-Webapp. The repository contains source code for kickstarting your own webapp project using the latest versions of <a href="http://www.scala-lang.org/">Scala</a>, <a href="http://www.springsource.org/features/modern-web">Spring Web</a>, <a href="http://www.hibernate.org/">Hibernate </a>and <a href="http://maven.apache.org/">Maven</a>.<br />
<br />
<b>Project Updates</b><br />
I've been committing some major changes over the last couple of weeks, including:<br />
<ul>
<li>Upgrading to Scala 2.9.1, Spring 3.1.0 and Hibernate 4.0.0 </li>
<li>Adding to the existing <a href="http://en.wikipedia.org/wiki/Representational_state_transfer">REST-ful </a>Create and Retrive examples some Update and Delete operations </li>
<li>Adding server-side form validation using <a href="http://www.openscope.net/2010/02/08/spring-mvc-3-0-and-jsr-303-aka-javax-validation/">JSR-303 annotations </a>with Spring Web MVC </li>
<li>Creating examples of automated web testing using <a href="http://seleniumhq.org/">Selenium WebDriver </a>and the <a href="http://code.google.com/p/selenium/wiki/PageObjects">PageObjects </a>pattern</li>
</ul>
If you're about to start your own project with these technologies, or are just keen to see how they all work together, you can get your own copy of the source code from here:<br />
<a href="https://github.com/GrahamLea/scala-spring-hibernate-maven-webapp">https://github.com/GrahamLea/scala-spring-hibernate-maven-webapp</a><br />
<br />
<b>Resolved Issues</b><br />
I encountered a couple of time-consuming issues during the upgrades to the latest versions and I think it
would be worth sharing how they were resolved in order to save some time for others googling for solutions to
the same problems.<br />
<br />
<b>Spring Schema SAXParseException</b><br />
After upgrading the versions of all the Spring Schemas in my Spring XML files, I started getting the following
error while trying to start up the webapp:
<br />
<pre class="brush: scala">org.xml.sax.SAXParseException: cos-all-limited.1.2: An ''all'' model group must appear in a particle with '{'min occurs'}'='{'max occurs'}'=1, and that particle must be part of a pair which constitutes the '{'content type'}' of a complex type definition.
</pre>
At first this appears to be a bug in the Spring schema, but a bit more investigation revealed that it is, in
fact, a bug in an old version of the Xerces XML parser library. In my case, an old version of the library was
being pulled in through commons-dbcp. The solution I took was to explicitly add a dependency on the latest
version of Xerces:
<br />
<pre class="brush: xml"> <dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.9.1</version>
<scope>runtime</scope>
</dependency>
</pre>
<br />
<b>Hibernate Function Not Supported</b> <br />
After upgrading Hibernate to 4.0.0, I started getting this error message whenever I tried to execute a query:
<br />
<pre class="brush: scala">org.hibernate.exception.GenericJDBCException: This function is not supported
Caused by: java.sql.SQLException: This function is not supported
</pre>
I don't remember whether HSQLDB appeared in the stack trace or not, but the solution to this was to upgrade
the version of HSQLDB I was using from 1.8.0.10 to 2.2.6. If you get the same error and you're not using
HSQLDB, I would suggest considering an upgrade of your JDBC driver or maybe even your database server.<br />
<br />
<b>"No Session found for current thread" </b><br />
Also after upgrading to Spring 3.1.0 and Hibernate 4.0.0, and after changing all my Hibernate 3 Spring beans
to the corresponding Hibernate 4 versions, I started getting the old classic "No Session found for current
thread" error when trying to view any page with a transaction. I thought this was very odd, because the
traditional solution to this has always been to make sure you have an OpenSessionInViewInterceptor, but I
already had one, defined like this:
<br />
<pre class="brush: xml"> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list><ref bean="openSessionInViewInterceptor"/></list>
</property>
</bean>
</pre>
By pure chance, I'd seen a Spring documentation page earlier the same day where I'd noticed an alternative way
of declaring interceptors using the 'mvc' namespace:
<br />
<pre class="brush: xml"> <mvc:interceptors>
<ref bean="openSessionInViewInterceptor"/>
</mvc:interceptors\>
</pre>
Replacing my old DefaultAnnotationHandlerMapping definition with the one above got my
OpenSessionInViewInterceptor working again and solved the "No Session found for current thread".<br />
<br />
<b>No Appenders for Log4J</b><br />
Finally, this one is a bit silly, but I spent a good half hour on it without finding any good help on the web
so I thought it was worth documenting. At some point I started getting this error out of <a href="http://logging.apache.org/log4j/1.2/">Log4J </a>every time I
started my webapp:
<br />
<pre class="brush: scala">log4j:WARN No appenders could be found for logger
</pre>
After all kinds of googling, experiments with winding back dependency upgrades and investigations into
ClassLoaders, I eventually noticed that I just had a typo in the Log4J configuration file:
<br />
<pre class="brush: scala">og4j.rootCategory=INFO,Console
</pre>
Notice the 'l' missing at the start of that line? Ouch. So if you're getting this error message about no
appenders and you think your log4j config is all set up properly, check whether the config for your root
category is correct before investing too much time in breakpoints inside Log4J classes.
<br />
<br />
<span style="font-weight: bold;">Want to learn more?</span><br />
Here's some books you might find useful if you plan to go further with Spring, Hibernate, Scala or Maven:<br />
<div style="background-color: #666666; color: white; text-align: center;">
From Amazon</div>
<br />
<table><tbody>
<tr><td><iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1933988134" style="height: 240px; width: 120px;"></iframe><br />
</td><td><iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=193239415X" style="height: 240px; width: 120px;"></iframe><br />
</td><td><iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1430224991" style="height: 240px; width: 120px;"></iframe><br />
</td><td><iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0981531601" style="height: 240px; width: 120px;"></iframe><br />
</td><td><iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0596007507" style="height: 240px; width: 120px;"></iframe><br />
</td></tr>
</tbody></table>
<br />
<br />
<div style="background-color: #666666; color: white; text-align: center;">
From The Book Depository</div>
<br />
<a href="http://www.bookdepository.co.uk/book/9781933988139/Walls/?a_aid=belmonttechnology" target="_blank">Spring in Action - Craig Walls & Ryan Breidenbach (Manning)</a><br />
<br />
<a href="http://www.bookdepository.co.uk/book/9781932394153/Hibernate-in-Action/?a_aid=belmonttechnology" target="_blank">Hibernate in Action - Gavin King & Christian Bauer (Manning)</a><br />
<br />
<a href="http://www.bookdepository.co.uk/book/9781590599792/Spring-Recipes/?a_aid=belmonttechnology" target="_blank">Spring Recipes - Gary Mak (Apress)</a><br />
<br />
<a href="http://www.bookdepository.co.uk/book/9780981531601/Programming-in-Scala/?a_aid=belmonttechnology" target="_blank">Programming in Scala - Martin Odersky, Lex Spoon & Bill Venners (Artima)</a><br />
<br />
<a href="http://www.bookdepository.co.uk/book/9780596007508/Maven-a-Developers-Notebook/?a_aid=belmonttechnology" target="_blank">Maven - A Developer's Notebook - Vincent Massol & Timothy M. O'Brien (O'Reilly)</a>Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-33127806767311790332011-12-20T23:26:00.000-08:002011-12-21T02:06:58.715-08:00SodaTest 0.2.1 Released<span style="font-size: small;"></span><br />
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">I've just released the second
milestone of SodaTest, the spreadsheet-driven integration testing
framework.</span></div>
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">A significant change with this
release is that SodaTest is now available from the Maven Central
repository. You should be able to access the latest versions of all
<a href="http://search.maven.org/#search%7Cga%7C1%7Csodatest">SodaTest artefacts from Maven Central</a> right now as org.sodatest :
sodatest-* : 0.2.1</span></div>
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">As well as a couple of small bug
fixes, this release incorporates a number a improvements based on
feedback from use of SodaTest in corporate environments. The key
enhancments were:</span></div>
<ul>
<li><span style="font-size: small;">Coercions can now be created
in Java without any knowledge of Scala</span></li>
<li>
<span style="font-size: small;">Built-in support was added for
coercing strings into Java enums</span></li>
<li>
<span style="font-size: small;">An implicit function is
available for converting into a Coercion any function with the type:
(String) => _ </span>
</li>
<li>
<span style="font-size: small;">A CurrencyAmountCoercion and
CurrencyAmountCoercionForJava are now available for coercing a
variety of financial value formats into your own custom Currency or
Money class</span></li>
<li>
<span style="font-size: small;">Reports no longer report a
mismatch due to trailing empty cells in the actual output</span></li>
<li>
<span style="font-size: small;">A bunch of usability fixes
such as handling unusual situations, reporting better error messages,
correct usage messages, more scaladoc and READMEs.</span></li>
</ul>
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">You can view the full <a href="https://github.com/GrahamLea/SodaTest/issues/search?q=0.2">list ofissues that were resolved as part of 0.2.1 on GitHub</a>.</span></div>
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">So, if you've been holding out
from using SodaTest wondering if anyone is using it for real, whether
it's going to be improved over time, and whether you should even
bother trying it out, the answers are yes, yes and yes!</span></div>
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">(And in case you're wondering why
this release is 0.2.1 and not 0.2, it's because 0.2 got lost in the
first, failed attempt to release from Sonatype to Maven Central.)</span></div>
<a name='more'></a><span style="font-size: small;"><br /></span><br />
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">SodaTest (Spreadsheet-Driven Testing) is an open-source
framework for creating Executable Requirements for Integration,
Functional and Acceptance testing.</span></div>
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">SodaTest allows the creation of
executable test cases as spreadsheets in a format that is easily
readable by non-programmers, with the goal of being easily
understood, edited or even authored by the non-technical Customers of
the software under test.</span></div>
<div class="western" lang="en" style="line-height: 115%; margin-bottom: 0.35cm;">
<span style="font-size: small;">SodaTest is written in Scala and
allows test fixtures to be written in Scala or Java.</span></div>Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-68252441940454133872011-12-08T18:00:00.001-08:002011-12-08T18:13:34.477-08:00Will Typesafe Address Scala Criticisms?If you've been paying attention to the Scala corner of the web over the last week, you'll no doubt have heard something about <a href="http://yammer.com/">Yammer</a> - an enterprise-focussed social network - switching from Scala back to Java.<br />
<br />
If you've been on holidays and missed it all, basically what happened was that <a href="http://codahale.com/">Coda Hale</a>, the Infrastructure Architect at Yammer, wrote <a href="http://codahale.com/downloads/email-to-donald.txt">a private email</a> to the <a href="http://typesafe.com/">Typesafe</a> team giving loads of mostly critical feedback regarding <a href="http://www.scala-lang.org/">Scala</a>, but <a href="http://codahale.com/the-rest-of-the-story/">the email was subsequently leaked</a> and became the talk of the town, among both Scala supporters, like <a href="http://lift.la/scalas-version-fragility-make-the-enterprise">David Pollak</a>, and critics, such as <a href="http://blog.joda.org/2011/11/real-life-scala-feedback-from-yammer.html">Stephen Colebourne</a>. <br />
<br />
<br />
<b>A Painfully Honest Critique</b><br />
<br />
Firstly, let me summarise the main points in Coda's email:<br />
<br />
* Yammer have decided to change their "basic infrastructure stack" from Scala to Java.<br />
<br />
* The main reason is that Scala has "friction and complexity" that isn't offset by enough productivity gain.<br />
<br />
* Some seemingly simple constructs in Scala, e.g. List, actually have very complex interfaces and behaviour that necessitate explaining a lot of concepts to beginners. The belief by some that this complexity can be ignored except by library authors has proven to be false in practice.<br />
<br />
* The most vocal members of the Scala online community are generally very academic in their practice and discussion of Scala.<br />
<br />
* Existing libraries seem to be being re-written just because people want to practice their use of advanced functional programming concepts, but these re-writes are then being recommended as the library of choice.<br />
<br />
* The Yammer team eventually decided the most sensible way to deal with the Scala community was to ignore it.<br />
<br />
* Learning Scala properly is important, but doing so is neither quick nor easy.<br />
<br />
* Java is not going away, so the choice to use Scala is actually a choice to use Scala and Java, along with the interaction challenges that brings.<br />
<br />
* The Yammer team had "endless issues" with SBT, and found themselves writing plugins to replicate Maven functionality.<br />
<br />
* Switching to Maven solved most of their problems, but they found it has been marginalised by the Scala community, with poor support and constant encouragement to switch to SBT.<br />
<br />
* The backwards-incompatibility of Scala major releases requires library authors to cross-compile, which has resulted in library re-invention when authors are no longer committed to the project.<br />
<br />
* The backwards-incompatibility also causes headaches for developers, which has resulted in many production Scala deployments not being upgraded to 2.9.<br />
<br />
* Yammer found idiomatic Scala code performed very poorly. By eliminating for-comprehensions, avoiding Scala's collection library, avoiding closures and marking everything with private[this], they were able to achieve speed ups of 100x in some components.<br />
<br />
So that was that. For what it's worth, Coda's email is also quite complimentary of Scala. I think he gives the impression that he likes it and would really like to keep using it, but the realities of making it work in a day-to-day production-deploying team have weighed them down so much that the benefits have been eclipsed.<br />
<br />
<b>A Frustratingly Measured Official Response</b><br />
<br />
Not long after Coda's email became public, Typesafe <a href="http://blog.typesafe.com/getting-down-to-work">published on their blog what is quite obviously a public response to the email</a>, and it's that blog I'd like to take a closer look at today. <br />
<br />
Here are the main points from the Typesafe blog:<br />
<br />
* Typesafe are investing in Scala IDE support by contributing to the Scala IDE for Eclipse<br />
<br />
* They are addressing the learning curve by developing training courses, but also provided references to some of the free resources on the web.<br />
<br />
* 'scalac' is slow because it has more work to do than 'javac', but they are investigating using parallel and incremental techniques to improve speed, with a focus on improving sbt.<br />
<br />
* If you don't want to (or can't) upgrade your Scala version, you can purchase commercial support from Typesafe to get access to long-term maintenance releases of previous versions.<br />
<br />
* In order to reduce people's major-release upgrade issues, they are planning to fold a bunch of existing libraries into the Scala release .<br />
<br />
* They take performance seriously, but are wary of engaging in premature optimisation.<br />
<br />
* Typesafe are not just focused on the Scala language and core libraries but also on frameworks to help build applications more easily.<br />
<br />
* They describe the Scala community using a couple of niceties as well as the words "opinionated" and "quirky".<br />
<br />
* They say there's many places where Scala could be improved and they're hard at work doing so.<br />
<br />
* They mention Yammer amongst a group of other companies with successful production deployments of Scala.<br />
<br />
<br />
<br />
<b>What Aren't They Telling Us?</b><br />
<br />
What I think is most interesting about this response is the things it doesn't mention and the places where it's specific about what they're doing to solve issues.<br />
<br />
Firstly, there's no mention of <b>Maven</b>. There is some commitment to improving compile times, but they seem to suggest that this will be for sbt users only. It has to be considered odd that Maven has been given so little attention by the chief proponents of Scala. One of the main advantages often cited for adopting Scala is its easy integration with Java, "so you can continue using all your favourite libraries". But the commitment to prolonging the life of people's Java API knowledge doesn't extend to the Java build chain. Should it? Why is Maven important? It's important because it works, and it's almost ubiquitous. It has had years and years of work poured into it and has been tested and improved by feedback from hundreds of thousands of users and plugin developers. It has a global ecosystem that is well understood. It has become a lingua franca; many people would know how to build their project with Maven but couldn't tell you how to build it with javac and jar. If you want to distribute your project to the world through Maven Central via Sonatype's Nexus repository, they've got fantastically detailed instructions for how to do so... with Maven. The Java-fluent world - which Typesafe want to convert into the Scala world - don't need another build tool. We need relatively minor improvements to Maven and its plugins to ensure we can keeping working without having to learn something completely new.<br />
<br />
Secondly, Typesafe give no commitment to eliminating the <b>backwards compatibility </b>problems in future major releases. In fact, one of the parts of their workaround - the offering of paid support for people who want to continue using older releases - actually makes it in their interest to not solve the problem. The other half of their workaround - bringing certain libraries into the Scala release - will mean that, as a developer, your backwards compatibility issues will only be solved if your taste in libraries is similar to those of the Typesafe team. If you like a library that hasn't been deemed worthy of inclusion, you'll be left with all the same cross-compiling and "version-x-for-scala-y" dependency issues that you have now.<br />
<br />
Thirdly, they seem to fob off Yammer's <b>performance problems </b>as an issue specific to their environment, suggesting that fixing such things for everybody would be "premature optimisation". I've heard this argument before: that it only makes sense for companies like Yammer and Twitter to spend time optimising tiny bits of code because it can save them millions across all their computers. But the same argument applies to small businesses just as well. If my business is growing rapidly, but I have limited cash flow, having a 100x performance increase is going to make a significant contribution to my bottom line if I can serve all of my customers on one machine instead of 100 machines. "Premature optimisation" is a phrase that should be reserved for application developers, not framework developers. Just optimise the hell out of it, please.<br />
<br />
Finally: the <b>community</b>. While Typesafe dropped a small comment about the community in its response, its really not an issue that they can solve, though I do think it will greatly effect the measure of their success in the long term. Really, the comments in Coda's email should be a wake up call to the Scala community at large: a sizable Scala software development team, full of very smart people who've written some very scalable and successful software, found the Scala community to be so fractured and unhelpful that they eventually decided to ignore it and, I would assume, not be a part of it. That's not just a loss for the community, but also a warning, because for every developer that finds the community unhelpful and so decides to program Scala in his own microcosm, there will be numerous others who decide to not bother with Scala at all for the same reason. This alone could be a weighty enough issue to relegate Scala to a hobby language in the long term rather than seeing wide-spread adoption in the enterprise community.<br />
<br />
<br />
<br />
<b>Hope and Trepidation</b> <br />
<br />
When I originally read through Coda's email I was nodding my head in agreement and hoping that Typesafe would be listening carefully and would take it as an opportunity to shift their focus, maybe just temporarily, but long enough to knock over these major objections. Unfortunately, when I read through Typesafe's response, I didn't see any real hint that they plan to fix the problems that I find most annoying. In some cases I even saw excuses about why they won't be doing anything. I don't think "We're focusing on making sbt better" is a response to "Why isn't there decent Maven support?". I know they've been <a href="http://twitter.com/#%21/odersky/status/144593957735772160">meeting with influential Scala teams in the days since this response</a>, I just hope they listen to what they've got to say.<br />
<br />
So now I'm left feeling a little unsure about Scala. Will it continue to improve for me and people like me? People who like to use IDEA + Maven, not Eclipse + sbt, who are educated in creating applications rather than composing mathematical proofs? Or is the current state of the art in Scala, along with its broad range of minor but resonating annoyances, what I should expect to still be grappling with in five years time? Only time will tell whether Typesafe can navigate this wave of criticism and find a promised land of general popularity, but I think it is an indication that Scala's window of opportunity has entered the waning phase, and now is the critical time at which to capitalise on the extant interest.<br />
<br />
What do <b>YOU </b>think?<br />
Do you sympathise with the Yammer team's frustrations?<br />
Are you confident that Typesafe will listen and respond to current criticisms with relevant and prompt action?Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com4tag:blogger.com,1999:blog-7317245822288637185.post-25955188164847314392011-10-26T14:24:00.000-07:002011-10-26T15:22:45.645-07:00Top 10 Reasons Java Programs Envy Scala<br />
I presented a talk at the 2nd meeting of the new <a href="http://www.meetup.com/scalasyd/">ScalaSyd Meetup </a>last night. I talked through the "Top 10 Reasons Java Programs Envy Scala" in an attempt to give Java developers a taste of some little things that could make them much more productive if they switch to Scala.<br />
<br />
If you'd like to watch the Prezi, or listen to the talk (or both!), here are the links:<br />
<br />
<a href="http://www.prezi.com/07yqjyfcotn6/top-10-reasons-java-programs-envy-scala/">Presentation: Top 10 Reasons Java Programs Envy Scala (Graham Lea)</a><br />
<br />
<a href="http://www.soundcloud.com/grahamlea/top-10-reasons-java-programs-envy-scala">Audio Simulcast: Top 10 Reasons Java Programs Envy Scala (Graham Lea)</a><br />
<br />
At the end of the talk, I mention that people who are tempted to learn Scala might want to look at my blog post, <a href="http://www.grahamhackingscala.blogspot.com/2010/12/guide-to-learning-scala-by-graham.html">Graham's guide to learning Scala</a>.<br />
<br />
If you'd like to have a look at the code examples used in the talk you can <a href="https://github.com/GrahamLea/JavaProgramsEnvyScala">view them on or clone them from GitHub</a>.Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com8tag:blogger.com,1999:blog-7317245822288637185.post-23742304109107025162011-10-11T01:59:00.000-07:002011-10-11T01:59:41.119-07:00Presenting at ScalaSyd, October 26In two weeks' time I'll be presenting a talk at the recently-formed <a href="http://www.meetup.com/scalasyd/">ScalaSyd Meetup</a>. The title of the talk is "Top 10 Reasons that Java programs envy Scala"; the synopsis: "A whirlwind tour through 10 productivity-increasing features of Scala that aims to inspire Java developers to jump on the Scala bandwagon for their own coding pleasure."<br />
<br />
There will be some other talks, Atlassian are providing the venue, pizza and drinks and JetBrains have donated some swag to dish out. It should be a good night so if you'll be in Sydney on Wednesday October 26, make a plan to drop in and make sure you <a href="http://www.meetup.com/scalasyd/events/34058882/">RSVP on Meetup.com</a>. Hope to see you there!Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-32640197627204981402011-09-23T21:52:00.000-07:002011-09-23T21:54:11.903-07:00Code Writers vs Code CreatorsIt's occurred to me recently that one of the key turning points for a professional software developer is the realisation that you don't have to make do with the tools you've got - you can create your own tools. This is why 'The Pragmatic Programmer' recommends activities like learning scripting languages and using code generation. <br />
<br />
<span style="color: #444444; font-size: small;"><b>What is your Goal?</b></span><br />
As a software engineer, my key goal is to CREATE software. A lot of the time, creating will mean WRITING software (i.e. typing out a program), but that isn't always the case. Many pieces of code have large amounts of boilerplate, or contain elements that are repeated again and again across the code base. Usually this means that the code could have been derived from some description of the end result that was simpler than the code itself. And wherever that is the case, the code is a candidate for being tool-aided or tool-generated.<br />
<br />
<b style="color: #444444;">What is a Tool?</b><br />
Now, tools can take many forms. Sometimes you just need to abstract a super class from some existing code, rather than copying code, and that base class becomes a tool for solving any similar problem. If you have a similar problem across a number of different applications, you might pull code out into a library that can be reused across those code bases. <br /><br />I'm using a pretty loose definition of 'tool' here. Basically I consider anything a tool if it has no function by itself, but can be used to create things which can perform a function. Base classes and libraries definitely fit this definition, but I hope that for the majority of developers this kind of reuse is bread and butter. <br /><br />The kind of tool-creation I think we should aspire to is a little more high-level than this. At regular points in the creation of software, every programmer, and sometimes even whole teams, will come across problems where they feel awkward with the solution and with the process for creating it. So what I'm advocating is that developers and teams need to have the courage in these situations to put down the normal tools and say, "This isn't working. We need better tools for this task." Sometimes there will be existing tools for solving your problem, and sometimes you'll have to create the right tool yourself. But the key quality is to be on the lookout for situations where the productivity of your code creation is being hampered by something, and to be ready to say out loud, "let's take the time to fix this". The problem might be irrelevant boilerplate, repetetive details, or it may even be something not directly related to coding, like a randomly failing build or an automated process that sends you too many emails. Anything that's stealing time away from value creation and could potentially be semi-automated can become the target of tooling.<br />
<br />
<b style="color: #444444;">What's the Catch?</b><br />
Of course, there's common sense to be used in deciding when to employ a tool or create one. If you're going to write your own tool, you need to make a really honest (i.e. pessimistic) estimation of the ROI (return on investment): Could the time it will take you to write the tool end up being longer than the time it will save you? Is this problem (and hence the tool to solve it) happening again and again or is it just a one off? Will the tool require ongoing maintenance that will significantly offset the gain it provides? You also need to have the discipline to create just the tool that YOU need, and to not try to solve the larger, generic set of problems that are like yours, but which you don't have. Remember: the purpose of creating a tool is to get you to the finish line faster, not to divert you from the race entirely because you're finding it uninteresting.<br />
<br />
<b style="color: #444444;">Are Your Eyes Open to Opportunities for Greater Productivity?</b><br />
At the end of the day, though, I believe there will often come times for every developer where they find a problem that justifies the creation of a custom tool. If this hasn't been your experience, I'd like to challenge you to think about this: is the charge of your occupation to write lines of code as fast as possible, or to deliver working solutions as fast as possible? Assuming you're not paid by the line, you're really being paid to be a Code Creator, not just a Code Writer. That means you have a responsibility to use the right tools for the job, and hence a mandate to create them if they don't exist. <br />
<br />
<b style="color: #444444;">Want to learn more?</b><br />
<br />
<table width="100%"><tbody>
<tr><td style="vertical-align: top;">From Amazon...<br />
<br />
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as4&m=amazon&f=ifr&ref=ss_til&asins=020161622X" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe></td><td style="vertical-align: top;">From Book Depository...<br />
<br />
<a href="http://www.bookdepository.co.uk/Pragmatic-Programmer-Andy-Hunt/9780201616224/?a_aid=belmonttechnology"><img src="http://belmonttechnology.yoodoos.com/the_pragmatic_programmer_small.png" style="border: 0pt none;" /></a></td></tr>
</tbody></table>
Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com3tag:blogger.com,1999:blog-7317245822288637185.post-47924815328521912352011-08-04T05:31:00.000-07:002011-08-04T05:50:52.238-07:00How to Create a Webapp with Scala, Spring, Hibernate and Maven in Late 2011Way back in the ancient history of January 2010, I wrote a <a href="http://grahamhackingscala.blogspot.com/2010/01/scala-spring-hibernate-maven-webapp-how.html">walk-through of how to create a webapp with Scala, Spring Hibernate and Maven</a>.<br /><br />As with all things, technologies have progressed, as have other things, including the way code is shared online. So I decided it was time to update the code form that post and share it somewhere more modern.<br /><br />You can now find my <a href="https://github.com/GrahamLea/scala-spring-hibernate-maven-webapp">code for starting a Scala + Spring + Hibernate + Maven Webapp on GitHub</a>.<br /><br />At the time of writing, this project uses Scala 2.9.0-1, Spring 3.0.5.RELEASE and Hibernate 3.6.5.Final. I hope to keep it updated as new versions of these libraries are released, and also to add some more flesh to the example as time permits. (Ha!)<br /><br />In you're looking more for a tutorial rather than just code, the <a href="http://grahamhackingscala.blogspot.com/2010/01/scala-spring-hibernate-maven-webapp-how.html">original post still serves as a great walk-though</a> of all the steps that went into creating the sample webapp, as well as showing lots of mistakes that I made that are probably quite common.<br /><br /><span style="font-weight: bold;">Want to learn more?</span><br />Here's some books you might find useful if you plan to go further with Spring, Hibernate, Scala or Maven:<br /><p style="text-align: center; background-color: #666666; color: #FFFFFF">From Amazon</p><br /><table><tbody><tr><td><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1933988134" style="width:120px;height:240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=193239415X" style="width:120px;height:240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1430224991" style="width:120px;height:240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0981531601" style="width:120px;height:240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0596007507" style="width:120px;height:240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td></tr></tbody></table><br /><br /><p style="text-align: center; background-color: #666666; color: #FFFFFF">From The Book Depository</p><br /><a href="http://www.bookdepository.co.uk/book/9781933988139/Walls/?a_aid=belmonttechnology" target="_blank">Spring in Action - Craig Walls & Ryan Breidenbach (Manning)</a><br /><br /><a href="http://www.bookdepository.co.uk/book/9781932394153/Hibernate-in-Action/?a_aid=belmonttechnology" target="_blank">Hibernate in Action - Gavin King & Christian Bauer (Manning)</a><br /><br /><a href="http://www.bookdepository.co.uk/book/9781590599792/Spring-Recipes/?a_aid=belmonttechnology" target="_blank">Spring Recipes - Gary Mak (Apress)</a><br /><br /><a href="http://www.bookdepository.co.uk/book/9780981531601/Programming-in-Scala/?a_aid=belmonttechnology" target="_blank">Programming in Scala - Martin Odersky, Lex Spoon & Bill Venners (Artima)</a><br /><br /><a href="http://www.bookdepository.co.uk/book/9780596007508/Maven-a-Developers-Notebook/?a_aid=belmonttechnology" target="_blank">Maven - A Developer's Notebook - Vincent Massol & Timothy M. O'Brien (O'Reilly)</a>Graham Leahttp://www.blogger.com/profile/07862939329898536954noreply@blogger.com2tag:blogger.com,1999:blog-7317245822288637185.post-91302339291766380572011-06-04T19:50:00.000-07:002011-07-01T06:46:23.225-07:00What's the best way to transform a list with a cumulative function?I've been doing this kind of thing a lot lately: I have a list of somethings. I want a new list based on that list, but it's not a straight one-to-one <code>map()</code> operation - each value in the resulting list is a function of the corresponding value <i>and all values before it</i> in the input list. (I'm sure there's a one-word name for this type of function, but I don't specialise in maths vocab.)<br /><br /><span style="font-weight: bold;">Example</span><br />As an example to discuss, imagine I have a list of numbers, and I want a list of the cumulative totals after each number:<br /><pre class="brush: scala"> def main(args: Array[String]) {<br /> val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)<br /> val cumulativeTotals = ... ?<br /> println(cumulativeTotals)<br />}<br /></pre>should output:<pre class="brush: text">List(1, 3, 6, 10, 15, 21, 28, 36, 45, 55)</pre><span style="font-weight: bold;"><br />Funky Folds</span><br /><br />So, until the other day, I've usualy been doing this with a <code>foldLeft()</code>:<pre class="brush: scala"> private def cumulativeTotalFolded(numbers: List[Int]): Seq[Int] = {<br /> numbers.foldLeft((0, List[Int]()))((currentTotalAndCumulativeTotals, n) => {<br /> val (currentTotal, cumulativeTotals) = currentTotalAndCumulativeTotals<br /> (currentTotal + n, (currentTotal + n) :: cumulativeTotals)<br /> })._2.reverse<br />}</pre>Now, I'm not holding that up as a good example of anything. Folds can be hard to understand at the best of times. A fold that passes around a <code>Tuple2</code> as the accumulator value is not code that simply communicates to the next guy what's going on.<br /><br /><span style="font-weight: bold;">Stream Simplicity</span><br />So, after a particularly hairy instance of one of these the other night, I lay in bed trying to think of a better way. It struck me ('round about 1am) that <code>Stream</code>s are a much more natural construct for calculating cumulative functions.<br /><br />If you haven't come across <code>Stream</code>s before, they're basically a way to define a collection recursively be providing the first value in the collection and a <i>function</i> that will calculate the next element in the collection (and, recursively, all the elements after it) as each subsequent element is requested by the client.<br /><br />Streams are good for this problem because the iteration through the list is simple, while the "next" value usually has easy access to the "previous" value, so to speak. I've used this once or twice now and I like it a lot better.<br /><br />For the problem above, my solution using a Steram looks like this:<pre class="brush: scala"> private def cumulativeTotalStream(numbers: List[Int], total: Int = 0): Stream[Int] = {<br /> numbers match {<br /> case head :: tail =><br /> Stream.cons(total + head, cumulativeTotalStream(tail, total + head))<br /> case Nil => Stream.Empty<br /> }<br />}</pre>(Note: to make this work with the println() above, you'll need to <code>toList()</code> the <code>Stream</code>.<br /><br /><span style="font-weight: bold;">Recursion Wrangling</span><br />There is, of course, another obvious way, which is to construct the list using a recursive function that passes two accumulators: one for the current total and one for the resulting <code>List</code> of totals that is accumulating:<pre class="brush: scala">@tailrec<br />private def cumulativeTotalRecursive(<br /> numbers: List[Int], currentTotal: Int = 0, cumulativeTotals: List[Int] = Nil): Seq[Int] = {<br /><br /> numbers match {<br /> case head :: tail =><br /> cumulativeTotalRecursive(tail, currentTotal + head, (currentTotal + head) :: cumulativeTotals)<br /> case Nil => cumulativeTotals.reverse<br /> }<br />}</pre>There's nothing wrong with this solution, and it probably performs much better than the <code>Stream</code> version, but I feel a bit weird about passing so many parameters around for such a simple operation.<br /><br />I could reduce the parameter count by getting the <code>currentTotal</code> from the accumulator list instead of passing it around:<pre class="brush: scala"> @tailrec<br />private def cumulativeTotalRecursive2(<br /> numbers: List[Int], cumulativeTotals: List[Int] = Nil): Seq[Int] = {<br /><br /> (numbers, cumulativeTotals) match {<br /> case (number :: tail, Nil) => cumulativeTotalRecursive2(tail, List(number))<br /> case (number :: tail, lastTotal :: otherTotals) => <br /> cumulativeTotalRecursive2(tail, (number + lastTotal) :: cumulativeTotals)<br /> case (Nil, _) => cumulativeTotals.reverse<br /> }<br />}</pre> but then the function body ends up more complex than the one with an extra parameter, which isn't a good trade-off.<br /><br /><span style="font-weight: bold;">Mutability the key to Simplicity?</span><br />Finally, I thought about the possibility of solving it with a <code>for</code> comprehension. I realised quickly that I'd need a mutable variable, but the result is a very, very simple piece of code:<pre class="brush: scala"><br /> private def cumulativeTotalComprehension(numbers: List[Int]): Seq[Int] = {<br /> var currentTotal = 0<br /> for (n <- numbers) yield {<br /> currentTotal += n<br /> currentTotal<br /> }<br /> }<br /></pre>I'm pretty sure this wouldn't look as pretty for a lot of the problems I've been tackling with the <code>foldLeft()</code> but, mind you, none of them looked very pretty either. Is this an okay solution? Do Scala afficionados going to vomit in disgust when they see the <code>var</code> keyword?<br /><br /><span style="font-weight: bold;">Your Turn</span><br />What I'd really like to know is whether there's an idiomatic way of doing this that I've just never come across.<br /><br />That's all I can come up with at the moment. I'm sure there's other ways to do it. One that looks simple, takes a sinlge parameter and runs fast would be ideal. If you've got some good ideas of other ways to do this, please leave something in the comments!<br /><br /><span style="font-weight: bold;">Want to learn more?</span><br />If all of this has just made you think you might need to do a bit more study on what recursion, Streams or folding are, try one of these great books:<br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0596155956" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0981531601" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780596155957/Programming-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://belmonttechnology.yoodoos.com/Programming_in_Scala_Odersky_small.png" /></a> <a href="http://www.bookdepository.co.uk/book/9780981531601/Programming-in-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://belmonttechnology.yoodoos.com/programming_scala_oreilly_small.png" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-7317245822288637185.post-82930702501776090212011-06-01T04:23:00.000-07:002011-06-01T19:51:34.743-07:00Introducing SodaTest: Spreadsheet-Driven Integration Testing for Scala and JavaI'd like to reveal what I've been working on in my spare time for the last couple of months.<br /><br /><span style="font-weight: bold;">The Announcement</span><br /><br /><a href="https://github.com/GrahamLea/SodaTest">SodaTest: "Spreadsheet-Driven Integration Testing"</a>, is an open-source framework for creating Executable Requirements for Integration and Acceptance testing in Scala and Java.<br /><br />The impetus for starting this project was to attempt to create a tool that improves on Ward Cunningham's <a href="http://fit.c2.com/">Framework for Integration Testing, "FIT"</a>. As an 'Executable Requirements' testing tool, it can also be considered as an alternative to <a href="http://fitnesse.org/">Fitnesse</a>, <a href="http://www.concordion.org/">Concordion</a>, <a href="http://rspec.info/">RSpec</a>, <a href="http://cukes.info/">Cucumber</a>, <a href="http://jdave.org/">JDave</a>, <a href="http://jbehave.org/">JBehave</a>, <a href="http://www.specflow.org/">SpecFlow</a>, and <a href="http://www.thoughtworks-studios.com/agile-test-automation">Thoughtworks' Twist</a>.<br /><br /><span style="font-weight: bold;">The Background<br /><br /></span>We used FIT in anger when I first arrived at my current workplace over four years ago. Since then I've watched the team become first dissatisfied with it, then scathing and fearing of it, before abandoning development of new FIT tests in place of Integration Tests written in JUnit. Nevertheless, we all still felt that Executable Requirements were a Good Thing and made a couple of failed restarts in trying to get back on the wagon.<br /><br />From my own perspective, many of our issues (but not all) were to do with the tool. I identified two main issues that I'd seen hurt people over and over: the input format and the programming model. So I set out to create something that solved these two problems while remaining fairly close to what I think is a great foundation in FIT.<br /><br /><span style="font-weight: bold;">The Result</span><br /><br />The result is a tool I've called SodaTest. It uses spreadsheets, in the form of comma-separated value (CSV) files, as the input format. The contents of the spreadsheet are basically small individual tables, much like what would appear in a FIT test. There is a required but simple structure to the tables and a minimum of special words and symbols to provide some context to the parser.<br /><br />I also aimed to keep the programming model as simple as possible. I tried to make sure there is only noe sensible way things could be done, so as not to confuse developers with options. I've gone to lengths to ensure developers of Fixtures will have to do a minimum of work by having the framework do a lot of boilerplate work for them. Lastly, I've structured and named everything in a way that I believe will guide developers in the right direction (by which I mean away from mistakes that I have made in the past while writing FIT tests).<br /><br />I've also taken the time to add a little sugar here and there that I thought was missing from FIT, for example integration with JUnit and a more comprehensive set of built-in coercion strategies for converting strings into strong types.<br /><br />I'm quite pleased with the result. (I wouldn't be telling people about it if I wasn't!) Yesterday I released version 0.1 of SodaTest and people should be able to use this first release of SodaTest to create tests that do almost everything that FIT could do, but with less effort in creating the tests, writing the Fixtures, and getting the whole lot executing in their environment.<br /><br />You can find out more about the motivation for SodaTest and the features it includes by <a href="https://github.com/GrahamLea/SodaTest/blob/master/README.md">reading the README on GitHub</a>.<br /><br />While SodaTest is written almost entirely in Scala (and the most benefit will be gained by using Scala as the language for writing Fixtures), I've also written the sodatest-api-java extension that <span style="font-weight: bold;">allows SodaTest Fixtures to be written in Java</span>. There is one limitation where Scala is (currently) still needed, but I reckon 95% of Fixtures should be able to be written entirely in Java if that is something you care about.<br /><br /><span style="font-weight: bold;">The Next Steps</span><br /><br />The next steps for SodaTest are clear to me: Dogfood, Broadcast, Feedback and Evolve.<br /><br />I want to convince my team at work to start experimenting with Executable Requirements again using my home-grown tool; I'd love it if other people in the Scala and Java communities could download this tool and give it a little tryout during their next iteration or two; I want to hear Feedback from people about what's good about SodaTest, what needs more work and whether there's parts that are just plain horrible; and, if the feedback is positive enough to consider SodaTest a preliminary success, I want to continue improving it in the areas where it's still holding people back.<br /><br />There is already <a href="https://github.com/GrahamLea/SodaTest/blob/master/Roadmap.md">a Roadmap of possible features to add</a>, but now it's really time to get it in people's hands and find out from users what is the next most important thing it needs to do.<br /><br /><span style="font-weight: bold;">Try It Out!</span><br /><br />If you're a Scala or Java software developer and Executable Requirements are either a passion of yours or something you've been wanting to try out, why don't you give SodaTest a try? You don't have to commit to it, just write a couple of tests with it, get them running, then passing, and send me some feedback. All feedback is useful, even if you think it sucks! (As long as you tell me why.)<br /><br />To get started with SodaTest, I suggest you:<br /><ul><li>Read the <a href="https://github.com/GrahamLea/SodaTest/blob/master/README.md">SodaTest Project README</a></li><li>Use Git to clone and have a look at the <a href="https://github.com/GrahamLea/SodaTest/tree/master/sodatest-examples">examples included with the project</a></li><li>Download SodaTest and write a test. If you're using Maven, you can use the repository and dependencies below, otherwise <a href="http://grahamlea.github.com/SodaTest/m2repository/org/sodatest/">you can download JARs from GitHub</a>.</li></ul><br /><pre class="brush: xml"><repositories><br /> <repository><br /> <id>sodatest-github-repo</id><br /> <name>SodaTest repository on GitHub</name><br /> <url>http://grahamlea.github.com/SodaTest/m2repository/ </url><br /> </repository><br /></repositories><br /><dependencies><br /> <dependency><br /> <groupId>org.sodatest</groupId><br /> <artifactId>sodatest-api</artifactId><br /> <version>0.1</version><br /> <scope>test</scope><br /> </dependency><br /> <dependency><br /> <groupId>org.sodatest</groupId><br /> <artifactId>sodatest-runtime</artifactId><br /> <version>0.1</version><br /> <scope>test</scope><br /> </dependency><br /></dependencies><br /></pre>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-7317245822288637185.post-49228905258306002732011-05-22T05:18:00.001-07:002011-05-22T05:19:25.749-07:00Explaining Scala to Your Wife Through KnittingOn Friday night I was sitting in my kitchen coding up some Scala. (Oh, what excitement a having small, sleeping child brings to Friday nights!)<br /><br />My wife, who is a die-hard knitter, came into the room and, having seen me do little in the evenings for the last few years except code Scala, asked, "Is Scala just the bee's knees?"<br /><br />My response, purely from reflex, was "No. CODING is the bee's knees!"<br /><br />"Sure," she said (with a roll of the eyes, I suspect), "but is it like knitting something really interesting? Compared to Java, I mean?"<br /><br />"Not quite," I said, "it's like if you had electric knitting needles that would let you start off the row and once you've done the interesting bit, the needles take over and do the rest of the row for you. So you'd just knit the interesting bits, not the dumb bits. With Java, though, you spend a lot of time writing dumb stuff."<br /><br />"Right," she said, "that would be cool."<br /><br />Yes, it would be cool. Sadly for knitters, electric knitting needles do not exist. Java programmers, on the other hand, have the freedom to use Scala if we want to stop doing dumb stuff.<br /><br />How would you explain Scala to your wife?Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-7317245822288637185.post-81413970974178688142011-05-16T19:33:00.000-07:002011-07-01T06:48:07.121-07:00Scala's Match is Not Switch++Scala's <code>match</code> operator is a beautifully powerful beast. It can do some really sophisticated stuff with very little effort. However, if your introduction to '<code>match</code>' was along the lines of, "It's like Java's '<code>switch</code>', but better", then I want to offer a word of caution. I'll show an example where this thinking caused problems for me, briefly explain <code>match</code> and explain how I look at it now to prevent this confusion for myself.<br /><br /><b>A (Bad) Example</b><br />Some things can look quite straightforward, but at runtime act quite differently from how they look. You might call these bugs. Take the following snippet as an example. What do you think this prints out?<pre class="brush: scala;"><br />object TestingObject {<br /> def main(args: Array[String]) {<br /> val testValue = "Boris"<br /> val inputValue = "Natasha"<br /> List(inputValue) match {<br /> case List(testValue) => println("Match!")<br /> case _ => println("No match")<br /> }<br /> }<br />}<br /></pre>Because you're a smart alec and you know what makes for an interesting blog, you have probably correctly guessed that this prints out "Match!".<br /><br />Let's try and get a little more information...<pre class="brush: scala;"><br />object TestingObject {<br /> def main(args: Array[String]) {<br /> val testValue = "Boris"<br /> val inputValue = "Natasha"<br /> List(inputValue) match {<br /> case List(testValue) => println("Match! testValue = " + testValue)<br /> case _ => println("No match")<br /> }<br /> }<br />}<br /></pre>The code now prints "Match! testValue = Natasha". This gives us a bit more insight into what's going on. Obviously the <code>testValue</code> that is defined in the <code>case</code> expression is not a reference to the original <code>val testValue</code> but a declaration of a new reference with a different scope.<br /><br />My mistake when I wrote this code was to believe that everything that I put between <code>case</code> and <code>=></code> was an <b>input</b> to the matching algorithm, i.e. it was going into some <code>==</code> or <code>.equals()</code> that happens under the hood. This is true in Java's <code>switch</code> statement, where everything in the case must be a constant, but it's certainly not how things work in Scala's <code>match</code>.<br /><br /><b>New Perspective</b><br />I prefer now to think of <code>match</code> the other way around to how it was first introduced to me: I now consider the use of an explicit <a href="http://www.scala-lang.org/node/112">extractor object</a> to be the <i>normal</i> case, and I think of any other form of <code>case</code> expression, such as matching against a constant value, as syntactic sugar for some built-in, implicit extractor.<br /><br />When you use an extractor object, you have an object that defines an <code>unapply()</code> function which accepts an object of the type you are matching as a parameter. The <code>unapply()</code> function can either return a <code>Boolean</code> or an <code>Option</code>. If it returns a <code>Boolean</code>, then <code>true</code> means the argument is a match and <code>false</code> means that it wasn't. If it returns an <code>Option</code>, then <code>None</code> means that it wasn't a match, while a <code>Some</code> indicates it <i>did</i> match. Not only this, but the object contained in the <code>Some</code> becomes available to the expression on the right of the <code>=></code>, assuming you give it a name in the case expression. I think this is the most significant difference between <code>switch</code> and <code>match</code>: In Scala, the <code>case</code> expression has <b>outputs</b>.<br /><br />My problem in the example at the start was caused because I thought of <code>List(testValue)</code> in the <code>case</code> expression as an input, but it's not. It's actually the name of an Extractor object (<code>List</code>) and a name given to the output of that Extractor (<code>testValue</code>).<br /><br />My new way of thinking is to pretend that everything in a Scala <code>case</code> is an extractor. So when I look at a <code>case</code> that is matching a plain old constant, I think to myself, "That's calling an extractor that returns <code>true</code> if the input value equals the constant. If I see <code>case x: Int =></code> I think, "That's calling an extractor that returns <code>Some(x)</code> if the object is an <code>Int</code> or <code>None</code> if it's not.<br /><br /><b>Re-Program Yourself</b><br />So, my suggestion is to rid yourself of any notion that Scala's <code>match</code> is like "<code>switch</code> on steroids". That view can lead to the false belief that <code>match</code> is a <code>switch</code> that can deal with all kinds of interesting, non-constant input values. In actual fact, the <code>case</code>s in <code>match</code> are all about Extractors, not inputs, and matching against constant values in the same way as <code>switch</code> is best thought of as just a nice little trick that the compiler does for you to hide the Extractor.<br /><br /><b>Want to Learn More?</b><br />If you suspect that a bit too much of your Scala knowledge may come from blogs that were comparing it with Java, reading one of these books might help:<br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0596155956" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0981531601" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780596155957/Programming-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://belmonttechnology.yoodoos.com/Programming_in_Scala_Odersky_small.png" /></a> <a href="http://www.bookdepository.co.uk/book/9780981531601/Programming-in-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://belmonttechnology.yoodoos.com/programming_scala_oreilly_small.png" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-7317245822288637185.post-65881141294372775412011-04-13T15:55:00.000-07:002011-07-01T06:48:25.153-07:00'Programming in Scala' book now FREEIf you're looking to learn Scala or looking to broaden your knowledge thereof, you'll be pleased to know that it's just been announced that the first edition of 'Programming in Scala' by Martin Odersky (the creator of Scala), Lex Spoon, and Bill Venners is now FREE online in HTML format.<br /><br />Here's the announcement:<br /><a href="http://groups.google.com/group/scala-announce/browse_thread/thread/502c7d5a386e357f">http://groups.google.com/group/scala-announce/browse_thread/thread/502c7d5a386e357f</a><br /><br />Here's the online version:<br /><a href="http://www.artima.com/pins1ed/">http://www.artima.com/pins1ed/</a><br /><br />If you want to grab a hard copy as well, you can get it here...<br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0981531601" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780596155957/Programming-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://belmonttechnology.yoodoos.com/Programming_in_Scala_Odersky_small.png" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-59126031665177181772011-01-18T02:32:00.000-08:002011-07-01T06:49:01.359-07:00Scala Pragmatism: Ignore CanBuildFromAfter <a href="http://grahamhackingscala.blogspot.com/2010/12/convert-lists-to-map-scala.html">a recent blog of mine about converting two lists to a map</a>, a commentor wrote that they were...<br /><blockquote>trying to understand the code I read [in] the ScalaDoc for the zip() [function]:<br /></blockquote><pre class="brush: scala;">def zip[A1 >: A,B,That](that: Iterable[B])(implicit bf: scala.collection.generic.CanBuildFrom[Repr,(A1, B),That]): That<br /></pre><blockquote>would you please help us to read/understand this?</blockquote><br />This is indeed curly stuff which, I'll have to admit, I wouldn't be able to fully explain without consulting a text book or two to get the terms right. Then you'd also have to read the same text books before you could understand my explanation.<br /><br />If I can take some poetic license with the question, though, I think what the poster really wants to know is why the signature is so complex when the intent of the function is so simple. So instead of explaining the intricate details of what this signature means, I'm going to explain why, to make practical use of the <code>zip()</code> function, you don't need to understand the above signature, as well as a little bit about what the added complexity actually achieves.<br /><br />Firstly: Why you don't need to bother too much.<br /><br />If you look at the <a href="http://www.scala-lang.org/api/current/scala/collection/immutable/List.html">Scala API for List</a>, you'll see that as well as the above signature for <code>zip()</code>, it also lists a "[use case]" signature for zip, which is simply this:<br /><pre class="brush:scala;">def zip [B] (that: Iterable[B]) : List[(A, B)]</pre>The purpose of this 'Use Case' signature is to let you know you that, most of the time, you will be able to call <code>zip()</code> on a <code>List</code> and pass in just another <code>List</code> (or some other concrete subclass of <code>Iterable</code>) and get back a <code>List</code> of <code>Tuple2</code>s. Just like this:<pre>scala> val list1 = List(1, 2, 3)<br />list1: List[Int] = List(1, 2, 3)<br /><br />scala> val list2 = List('a', 'b', 'c')<br />list2: List[Char] = List(a, b, c)<br /><br />scala> val result = list1.zip(list2)<br />result: List[(Int, Char)] = List((1,a), (2,b), (3,c))<br /></pre>That's the pragmatic part, and the most important part to understand. If you cast your eyes down the <code>List</code> scaladoc, you'll notice that there's lots of these use cases. (You should understand why this is the case once you understand why the extra complexity is there.)<br /><br />To sum that up: to use the <code>zip</code> function, you just have to pass in an <code>Iterable</code>. You will rarely, if ever, need to know what <code>CanBuildFrom</code> is or what all those type parameters refer to.<br /><br />Secondly: Why then have all that complexity in the signature, when I'm not using it?<br /><br /><span style="font-style: italic;">Whoa!</span><span style="font-style: italic;"> That's actually not true!</span> The fact that we've called the function without explicitly providing that second parameter <span style="font-style: italic;">doesn't</span> mean that you haven't <span style="font-style: italic;">used</span> the extra complexity. In fact, you have used it, and it's provided you a small benefit, all without you realising. This is where a little bit of magic happens...<br /><br />In understanding <span style="font-style: italic;">why</span> that signature is so complex, the key is actually in the explanation above of what <code>zip</code> does. Note that I said that you can call <code>zip()</code> on a <code>List</code> and pass in just another <code>List</code>, and you will get back another <code>List</code>. This is actually a little bit amazing. It probably doesn't seem that amazing, but then you have to consider that the implementation of the <code>zip</code> function is not actually defined on the <code>List</code> class, but is defined in a trait that <code>List</code> inherits from called <a href="http://www.scala-lang.org/api/current/scala/collection/IterableLike.html"><code>IterableLike</code></a>. What is surprising here is that the <code>IterableLike</code> trait doesn't know anything about the <code>List</code> class, and yet its <code>zip</code> function is able to return an instance of <code>List</code>. (And remember that <a href="http://grahamhackingscala.blogspot.com/2010/02/how-to-convert-java-list-to-scala-list.html">Scala's List is a concrete class, very different from Java's List interface</a>.)<br /><br />This is what the <code>CanBuildFrom</code> parameter is all about: it allows functions like <code>zip</code> to be defined once, high up in the collections API hierarchy, but then to also return a different type of result <span style="font-style: italic;">depending on</span> the type of the collection on which the method is actually invoked. To put that in practical terms: if I call <code>zip</code> on a <code>List</code>, I'll get back a <code>List</code> of tuples, but if I call <code>zip</code> on a <code>mutable.HashSet</code>, I'll get back a <code>mutable.HashSet</code> of tuples. The same goes for <code>map()</code> and <code>filter()</code> and countless other functions. This is the magic: these functions don't know anything about these concrete types they are returning, but you haven't had to tell it about the concrete types either! To achieve the same result in Java without any casting, you would have to override the <code>zip</code> function in each and every concrete subclass of <code>IterableLike</code> from which you wished to return a specific collection type. (<span style="font-style: italic;">Edit: Actually, I don't think this is true. I think I've figured out in my head a way to do it that doesn't require casting or overriding.</span>)<br /><br />There is just one mystery left: why don't you have to pass in an instance of <code>CanBuildFrom</code>? As you can see, the parameter list containing this parameter is <code>implicit</code>. This means that, if this parameter list is not explicitly defined in any invocation, the Scala compiler will to attempt to find a variable or object that is in scope, and declared to be implicit, and also meets the type criteria of the parameter. So you don't have to provide a <code>CanBuildFrom</code> instance because scalac is tracking one down for you.<br /><br />But where is it tracking it down from? All code has to come from somewhere, right? At first, I thought that there might be one <code>CanBuildFrom</code> instance in the <a href="http://www.scala-lang.org/api/current/scala/Predef$.html"><code>Predef</code></a> object that served the needs of nearly every collection. The real answer is a bit less exciting: each concrete subclass provides its own instance of <code>CanBuildFrom</code> in its <a href="http://programming-scala.labs.oreilly.com/ch06.html#CompanionObjects">companion object</a>, though in many cases this definition is as simple as creating a new instance of <code>GenericCanBuildFrom</code>. I have to be honest and admit that I haven't yet figured out how this definition in the companion object makes its way into the <code>zip</code> function and other functions. While you unwittingly import the companion object whenever you import a collection type, you haven't imported all the companion object's <span style="font-style: italic;">functions</span> into scope. Perhaps someone with a bit more patience for searching the Scala source code will nice enough to explain it in the comments.<br /><br />So, to sum up:<br /><ul><li>You don't need to understand <code>CanBuildFrom</code> in order to use functions that have one in their signature.</li><li>Look for "[use case]" entries in the scaladoc for the collections API and use those as the basis for function calls unless the compiler seems to be telling you to do otherwise</li><li>The advantage of the complex function signatures is that the definition can be written once, but can return many different concrete types of collection, without you having to tell it how to do that.</li></ul><br /><span style="font-weight: bold;">Want to learn more?</span><br /><br />If you'd like to get a bit more detail about how Scala's collections and the related classes like <code>CanBuildFrom</code> operate under the covers, there is a series of pages on scala-lang describing some of the <a href="http://www.scala-lang.org/docu/files/collections-api/collections-impl.html">implementation details of Scala's new collections API</a>.<br /><br />And if you <span style="font-weight: bold; font-style: italic;">really</span> want to know every last thing about why this signature looks the way it looks and how it works, you might want to read the academic Scala paper, <a href="http://www.cs.kuleuven.be/%7Eadriaan/files/higher.pdf">'Generics of a Higher Kind'</a>, but please don't post questions about that on my blog! ;)<br /><br />If you just want to learn a bit more about Scala, try one of these:<br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0596155956" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0981531601" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780981531601/Programming-in-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://belmonttechnology.yoodoos.com/programming_scala_oreilly_small.png" /></a> <a href="http://www.bookdepository.co.uk/book/9780596155957/Programming-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://belmonttechnology.yoodoos.com/Programming_in_Scala_Odersky_small.png" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-7317245822288637185.post-44653393723706179962011-01-10T04:49:00.001-08:002011-01-11T05:31:28.429-08:00Scala == Effective Java ?I started reading <a href="http://www.amazon.com/gp/product/0321356683?ie=UTF8&tag=belmontechno-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0321356683">Joshua Bloch's Effective Java</a><img src="http://www.assoc-amazon.com/e/ir?t=belmontechno-20&l=as2&o=1&a=0321356683" alt="" style="border: medium none ! important; margin: 0px ! important;" border="0" height="1" width="1" />last week. I'll have to admit that I haven't read it before, but only because I've been told by several people, "you already do most of what's in there anyway." Seeing as we tell all the new recruits to read it, I thought I should actually flip through it myself so I know what's in there.<br /><br />Books of best practices are always written in relation to domains that have many possibilities for bad practices (choosing otherwise would make for a very short book). Reading the first chapter of Effective Java, I was amused as I realised that, if you're <a href="http://grahamhackingscala.blogspot.com/2010/01/why-your-company-should-let-you-use.html">coding in Scala instead of Java</a>, many of the book's recommendations are either unnecessary, because Scala doesn't permit the corollary bad practice, or built into the language of Scala, or made easier to implement than they are in Java. This isn't a criticism of the book, but an observation that the state of the art is moving on, and Java is being left behind.<br /><br />From the first 25 items in the book, here are my notes on practices that either become easier to follow or unnecessary if you are using Scala:<br /><br /><span style="font-weight: bold;">Item 1: Consider static factory methods</span><br />One of the four advantages given for <a href="http://www.javapractices.com/topic/TopicAction.do?Id=21">static factory methods</a> is that construction of classes with type parameters is briefer through static methods because the type parameters can be inferred on a parameterised method call. Scala solves this one by inferring type parameters on constructors, but not only that. It infers LOTS of types, almost everywhere: fields, local variables, method return types, anonymous function parameters - <a href="http://www.scala-lang.org/node/127">all can usually have their type inferred from the context</a>, meaning that Scala code has a lot less declarative noise, while still remaining statically type-checked.<br /><br /><span style="font-weight: bold;">Item 2: Consider the Builder pattern instead of long constructors</span><br />Joshua writes himself that the <a href="http://en.wikipedia.org/wiki/Builder_pattern">Builder pattern</a> simulates the combination of named parameters and default parameters that are found in other languages, and <a href="http://www.scala-lang.org/node/2075">Scala supports named and default parameters</a>. What he means by "simulates" is that you need to write a whole extra Builder class in Java to get the nice Builder effect at the client site, whereas in Scala, you essentially get a Builder for free every time you write a constructor.<br /><br /><span style="font-weight: bold;">Item 3: Enforce Singletons</span><br />While code-enforced <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singletons</a> have gone out of fashion a bit with the popularity of <a href="http://www.picocontainer.org/comparisons.html">IoC containers</a>, they're still around a lot and these rules are still important. <a href="http://tutorials.jenkov.com/scala/singleton-and-companion-objects.html">Scala supports singletons at the language level, providing the 'object' keyword</a> which, substituted for the word 'class' in a declaration, will compile a singleton object into your code instead of a class. The generated object follows all of Josh's recommendations, including deserializing to the same instance (as long as you use Scala's @serializable rather than extends java.io.Serializable)<br /><br /><span style="font-weight: bold;">Item 4: Enforce non-instantiability with private constructors</span><br />There's really only two cases where you want to do this: singletons (see above), and utility classes, which are really just singletons that have no state. Either way, Scala's 'object' keyword for creating singletons is the simple answer.<br /><br /><span style="font-weight: bold;">Item 5: Avoid auto-boxing</span><br />The recommended panacea for <a href="http://download.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html">unwanted auto-boxing</a> is to prefer primitives wherever possible. Now, Scala is a purely object-oriented language, which means <a href="http://www.scala-lang.org/node/128">there are no primitives</a>, and all numbers, characters and booleans are represented at the language level as objects. However, Scala uses of these primitive wrapper objects compile to byte code which uses Java's primitives wherever possible, so this recommendation is implemented for you by the Scala compiler.<br /><br /><span style="font-weight: bold;">Items 7, 8 and 9: Overriding toString, hashCode and equals</span><br />If you're authoring an immutable data structure, <a href="http://www.scala-lang.org/node/107">declaring your Scala class as a case class</a> will tell the compiler to automatically implement toString, hashCode and equals for you, along with an unapply() method that can be used in a <a href="http://www.scala-lang.org/node/120">pattern matching</a> clause. (There are <a href="http://stackoverflow.com/questions/4653424/what-are-the-disadvantages-to-declaring-scala-case-classes">some disadvantages to using Scala's case classes</a>, but I believe they work well for most situations.)<br /><br /><span style="font-weight: bold;">Item 11: Override clone() judicously</span><br />While Scala as a language doesn't provide an answer to this one, it's considered best-practice Scala to favour <a href="http://en.wikipedia.org/wiki/Immutable_object">immutable types</a>, with transformation being much favoured over mutation. Following this principle will reduce the need to ever use clone(), because immutable objects can be shared among many clients and threads without the shared-mutable-state worry that might cause you to consider cloning something.<br /><br /><span style="font-weight: bold;">Item 14: Use public accessors methods rather than public fields</span><br />While Scala appears to have public fields - and indeed to make fields public by default - in fact <a href="http://programming-scala.labs.oreilly.com/ch06.html#UniformAccessPrinciple">Scala implements Bertrand Myer's "Uniform Access Principle"</a>, with all access to fields (which are in fact all private) being made through accessor and mutator functions that have the same name as the field. In other words, the compiler writes get and set methods for you and everything that looks like field access in your code actually goes through these methods.<br /><br /><span style="font-weight: bold;">Item 15: Minimize mutability</span><br />As already mentioned, it's considered Scala best practice to shun mutable state as much as possible. One of Josh's four recommendations for decreasing mutability is to make values final wherever possible. All Scala fields and local variables must be preceded by either 'val', indicating immutability (of the reference), or 'var', indicating that the reference can change. (Function parameters are always vals, and hence final.) Forcing programmers to make this choice when each variable is declared encourages the practice of using a lot of immutability, compared to final which is an optional modifier and seen by many as extra noise in most declarations.<br /><br /><span style="font-weight: bold;">Item 18: Prefer interfaces to abstract classes</span><br /><a href="http://www.scala-lang.org/node/126">Scala has traits</a> - abstract classes that essentially allow multiple inheritance of function definitions (as opposed to interfaces, which only inherit function declarations). The possibility of multiple inheritance discounts quite a few of the disadvantages Josh raises against using abstract classes in Java. Of course, it also introduces some new issues, and exacerbates some others, like those Josh lists in Item 16 about preferring composition+delegation over inheritance. Multiple inheritance is a double-edged sword, for sure.<br /><br /><span style="font-weight: bold;">Item 21: Use function pointers</span><br /><a href="http://www.scala-lang.org/node/134">Scala, as a functional language</a>, has functions as first-class members of the language, with every function naturally being available as an object (same as what Josh calls a function pointer) should the need arise. It also supports <a href="http://www.scala-lang.org/node/133">anonymous, inline functions</a>, which, if available in Java, could reduce current "function pointer" logic like this:<br /><code>new Thread(new Runnable() { public void run() { System.println("Running"); } } );</code><br />down to something like this:<br /><code>new Thread({System.println("Running")})</code><br /><br /><span style="font-weight: bold;">Item 23: Don't use raw generic types</span><br />Scala doesn't allow you to write code that uses raw generic types, even if those types are defined in Java: it just won't compile. For what it's worth, raw generic types are not a feature, but merely an artefact of backwards-compatibility. Scala, not trying to be backwards-compatible with Java 4, just doesn't need raw types and, as a result, is able to provide stricter type safety for type-parameterised classes and functions.<br /><br /><span style="font-weight: bold;">Item 25: Prefer Lists over Arrays</span><br />While you should probably still prefer <a href="http://www.scala-lang.org/api/current/scala/collection/immutable/List.html">Scala's List class</a> to Arrays for most applications, Scala prevents the chief problem cited with Java's arrays. In Java, you can cast a String[] to an Object[] and then assign a Long to one of the entries. This compiles without error, but will fail at runtime. In Scala, however, arrays are represented in source code as a parameterized class, Array[T], where T is an <span style="font-style: italic;">invariant</span> <span style="font-style: italic;">type parameter</span>. This basically just means that you can't assign an Array[String] to an Array[Object], and so Scala prevents this problem at <span style="font-style: italic;">compile</span> time rather than choking at runtime.<br /><br /><span style="font-weight: bold;">Scala == Effective Java ?</span><br />So I'm going to put this question out there:<br />If 'Effective Java' is considered essential reading, and the best practices in it are the de facto standard for writing good programs, shouldn't we all be giving serious consideration to switching to a language that is so very close to Java, but makes good programming even easier?<br /><br /><span style="font-weight: bold;">Want to learn more?</span><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=444499&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0321356683" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0596155956" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe></td><td style="vertical-align: top;">From Book Depository...<br /><a href="http://www.bookdepository.co.uk/book/9780321356680/Effective-Java/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Effective_Java_small.png" /></a> <a href="http://www.bookdepository.co.uk/book/9780596155957/Programming-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Programming_Scala_OReilly_small.png" /></a></td><br /></tr></tbody></table>Unknownnoreply@blogger.com14tag:blogger.com,1999:blog-7317245822288637185.post-18025650888887415902010-12-30T18:55:00.000-08:002010-12-31T19:22:48.423-08:00How to convert two Scala Lists into a Map<span style="font-style: italic; color: rgb(204, 153, 51);"><span style="font-weight: bold;">Update:</span></span><br /><br />Since I posted this 24 hours ago, no fewer than 13 lovely people have left comments to let me know that this is actually far, far easier than I thought. There is a function on the <code>List</code> class (since 2.8.0, I think someone said), inherited from <code>TraversableOnce</code>, called <span style="font-size:130%;"><code style="font-weight: bold;">toMap()</code></span> which, if the sequence contains <code>Tuple2</code>s, will make a <code>Map</code> from them.<br /><br />So the ideal solution is simply:<br /><pre class="brush: scala">(keys zip values) toMap<br /></pre>Now the question is: How come everyone else knows about this and I didn't? :(<br /><br />A couple of people also mentioned that you don't need to convert a List into an Array to be able to pass it into a var args method (but you still need the funky noise). Handy!<br /><br />Thanks, everyone.<br /><br /><br /><span style="font-style: italic; color: rgb(204, 153, 51);"><span style="font-weight: bold;">Original Post...</span></span><br /><br />Not sure if this will ever be of use to anyone else, but I thought I'd put it out there just in case.<br /><br /><span style="font-weight: bold;">Problem:</span><br />You have a <code>List/Seq</code> of keys and a <code>List/Seq</code> of values, with the key at index n in one list matching the value at index n in the other. But what you really want is to convert them into a <code>Map</code>.<br /><br /><span style="font-weight: bold;">Solution:</span><br /><pre class="brush: scala">Map(keys.zip(values).toArray: _*)<br /></pre><br /><span style="font-weight: bold;">Explanation:</span><br />The steps here are:<br /><ol><li>"Zip" the keys list with the values list, which creates a <code>List</code> of <code>Tuple2</code> objects</li><li>Convert the list of <code>Tuple</code>s to an <code>Array</code> of <code>Tuple</code>s. This is necessary because the <code>Map</code> object, which extends <code>MapFactory</code>, doesn't have any <code>apply()</code> methods that deal with lists but only the one that accepts a <span style="font-style: italic;">var args</span> parameter of <code>Tuple2</code>s.</li><li>Add this funky noise <code>": _*"</code> which tells Scala to pass the <code>Array</code> as multiple varargs parameters, rather than trying to pass the whole <code>Array</code> as the first parameter.<br /></li></ol>Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-7317245822288637185.post-11545600388993111542010-12-16T02:10:00.000-08:002010-12-17T12:54:24.566-08:00Graham's Guide to Learning ScalaIt's a pretty widely-accepted view that, as a programmer, learning new languages is a <span style="font-style: italic;">Good Idea</span> (tm). Most people with more than one language under their belt would say that learning new languages broadens your mind in ways that will positively affect the way you work, even if you never use that language again.<br /><br />With the Christmas holidays coming up and many people likely to take some time off work, this end of the year presents a great opportunity to take some time out from your week-to-week programming grind and do some learning.<br /><br />With that in mind, I present "Graham's Guide to Learning Scala". There are many, many resources on the web for learning about Scala. In fact, I think there's probably too many! It would be quite easy to start in the wrong place and quickly get discouraged.<br /><br />So this is not yet another resource to add to the pile. Rather, this is a guided course through what I believe are some of the best resources for learning Scala, and in an order that I think will help a complete newbie pick it up quickly but <span style="font-style: italic;">without</span> feeling overwhelmed.<br /><br />And, best of all, it has 9 Steps!<br /><br /><span style="font-size:85%;">[Note: Many of the resources have a slant towards teaching programmers that know Java, but I imagine if you know any other popular OO language like C++, C#, Ruby, Python, Objective-C or Smalltalk, you shouldn't have a problem picking it up.]</span><br /><br />Are you ready? Here goes...<br /><br /><span style="font-weight: bold;">Step 1: Lay the Foundation</span><br /><br />Read <a href="http://www.scala-lang.org/node/25">'Introduction to the Scala Language' on scala-lang.org</a><br /><br />This single page is a succinct but dense description of Scala and will let you know what you're in for, and why you should keep going.<br /><br /><br /><span style="font-weight: bold;">Step 2: Get the Tools</span><br /><br />Download and install <a href="http://www.scala-lang.org/downloads">the latest Scala release</a><br /><br />Download and install the <a href="http://www.jetbrains.com/idea/download/">latest IntelliJ IDEA *Community Edition* release </a><br /><br />Open IDEA and <a href="http://www.jetbrains.com/idea/plugins/">install the 'Scala' plugin</a><br /><br /><br /><span style="font-weight: bold;">Step 3: Hello, World!</span><br /><br />Create a new IDEA project with a Scala module.<br />Create a new file called HelloWorld.scala and paste in the following code:<br /><br /><pre class="brush: scala">object HelloWorld {<br /> def main(args: Array[String]) {<br /> println("Hello, world!")<br /> }<br />}</pre><br />Hit Ctrl-Shift-F10 to run it.<br />Congratulations! First Scala program done and dusted!<br /><br /><br /><span style="font-weight: bold;">Step 4: Commute your Java skills to Scala</span><br /><br />Read Daniel Spiewak's <a href="http://www.codecommit.com/blog/scala/roundup-scala-for-java-refugees">'Scala for Java Refugees' series</a>.<br /><br />This should give you enough knowledge and experience with Scala syntax to be able to write Scala that does most of the things you can do in Java.<br /><br />Make sure you enter the code examples into IDEA and try them out as you go. I suggest typing them out instead of copy-paste, because that's likely to give you exposure to common syntax mistakes and compiler errors.<br /><br /><br /><span style="font-weight: bold;">Step 5: Open Your Eyes</span><br /><br />Read through <a href="http://www.scala-lang.org/node/104#book-navigation-104">the 'Tour of Scala' on scala-lang.org</a><br /><br />These short pages will give you some exposure to some of the more advanced features of Scala. Don't worry if you don't understand everything - just keep reading. You're not trying to learn how to use all these things, just to know that they're around.<br /><br /><br /><span style="font-weight: bold;">Step 6: Learn the Basics, the Ins & the Outs</span><br /><br />Read chapters 1 to 8 of <a href="http://programming-scala.labs.oreilly.com/">Dean Wampler & Alex Payne's 'Programming Scala' (O'Reilly)</a><br /><br />This is where the learning gets heavy. We're talking about more than half a book here. You'll learn everything from basic syntax (some of which you'll already know from the Refugees series) to Scala's more advanced patterns for object-oriented programming, an introduction to Scala's functional programming capabilities and some of the curly edges of Scala's type system.<br /><br />Again, make sure you try out running the code samples in IDEA. I suggest you also have a play around with some of the concepts in your own little test classes. Any time you find yourself thinking "I wonder if I can use this feature to do this?", grab a keyboard and find out for yourself.<br /><br /><br /><span style="font-weight: bold;">Step 7: Open the Dragon Scroll and Release your Scala Fu</span><br /><br />Take a break from learning and do some hacking!<br /><br />Think of a simple idea that you'd like to implement in Scala, then code it! (Seriously, I recommend keeping it REALLY simple.) If you can't think of something yourself, you can steal <a href="http://grahamhackingscala.blogspot.com/2009/09/scala-beyond-hello-world.html">my idea of writing a function to perform word-wrapping</a>.<br /><br /><br /><span style="font-weight: bold;">Step 8: Take a Walk around the Grounds</span><br /><br />Read the rest of <a href="http://programming-scala.labs.oreilly.com/">'Programming Scala'</a> (chapters 9 to 14)<br /><br />The rest of the book covers some of the peripheral libraries and concepts in Scala that contribute to making it a great language, like <a href="http://programming-scala.labs.oreilly.com/ch09.html">Agents for multi-threaded programming</a>, <a href="http://programming-scala.labs.oreilly.com/ch10.html">"herding" XML input and output</a> and <a href="http://programming-scala.labs.oreilly.com/ch11.html">building blocks for creating domain-specific languages</a>, as well as reviewing <a href="http://programming-scala.labs.oreilly.com/ch14.html">some of the tools that have sprung up in the Scala ecosystem</a>.<br /><br /><br /><span style="font-weight: bold;">Step 9: Go Forth and Hack!</span><br /><br />This is where the directed part of the journey ends, but hopefully it's only the first step.<br /><br />What you do with Scala next is up to you, but by this point you know more than enough about Scala to start using it seriously at home or even at work, for fun, or for making some serious cash! If you do make some serious cash by hacking Scala, please remember how it all started and send a little monetary "Thank you" my way. ; )<br /><br /><br /><span style="font-weight: bold;">Addendum: Getting Help</span><br /><br />Perhaps it was a little presumptuous of me to effectively say "go away now and code". Chances are, you'll need some help as you keep experimenting, learning and doing more and more cool stuff with Scala.<br /><br />The two best places that I've found to connect with other Scala users are <a href="http://www.scala-lang.org/node/199#scala-user">the scala-user mailing list</a> run by scala-lang.org and, for curly technical problems that you just can't figure out yourself, <a href="http://stackoverflow.com/">stackoverflow.com</a>. Actually, reading through <a href="http://stackoverflow.com/questions/tagged/scala">other people's Scala questions on Stack Overflow</a> can also be a great way to pick up new ideas!<br /><br /><br /><span style="font-weight: bold;">Want to learn more?</span><br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0596155956" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=143022844X" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780596155957/Programming-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Programming_Scala_OReilly_small.png" /></a> <a href="http://www.bookdepository.co.uk/book/9781430228448/Pro-Scala/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Pro_Scala_small.png" /></a></td></tr></tbody></table>Unknownnoreply@blogger.com10tag:blogger.com,1999:blog-7317245822288637185.post-39807392656913884172010-11-16T18:43:00.000-08:002010-11-16T20:05:46.926-08:00SpringOne 2GX 2010 and Scala<span style="font-weight: bold;">SpringOne 2GX 2010 Wrap-Up</span><br /><br />My last entry was the last of my notes from SpringOne 2010 in Chicago.<br />Here's a list of all my entries from the conference below in case you missed any:<br /><ul><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/10/spring-31-whats-new-springone-juergen.html">What's New in Spring Framework 3.1</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/10/lean-software-groovy-springone-hamlet.html">Slimmed Down Software: A Lean, Groovy Approach</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/10/spring-roo-introduction-johnson-schmidt.html">Introduction to Spring Roo</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/10/online-transaction-authorization-batch.html">Creating the Next Generation of Online Transaction Authorization</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/10/spring-roo-gwt-springone-google-web.html">How to Build Business Applications using Google Web Toolkit and Spring Roo</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/10/groovy-concurrent-programming-springone.html">Groovy and Concurrency</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/11/concurrent-distributed-applications.html">Concurrent and Distributed Applications with Spring</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/11/html5-css3-springone-grelle-andrews_11.html">Harnessing the Power of HTML5</a></span></h3></li><li><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/11/gradle-springone-hans-docketer-groovy.html">Gradle - A Better Way to B<span>uild</span></a></span></h3></li><li style="font-weight: bold;"><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/11/spring-integration-extending-springone.html">Extending Spring Integration</a></span></h3></li><li style="font-weight: bold;"><h3 style="font-weight: normal;" class="post-title entry-title"><span style="font-size:85%;"><a href="http://grahamhackingscala.blogspot.com/2010/11/gemfire-nosql-springone-jags-ramnarayan.html">GemFire SQLFabric - "NoSQL database" scalability using SQL</a></span></h3> </li></ul><span>If you're interested in watching the full content of some of the t</span>alks, I notice that they have just started <a href="http://www.infoq.com/SpringOne_2010">publishing SpringOne videos on InfoQ</a>, including <a href="http://www.infoq.com/presentations/SpringOne-2GX-2010-Keynote">Rod Johnson's keynote</a>. I imagine this set will grow over the coming weeks.<br /><br /><span style="font-weight: bold;">Is This a Scala Blog or a Spring Blog?</span><br /><br />I copped a little bit of flak recently due to all these Spring posts appearing on <a href="http://www.planetscala.com/">Planet Scala</a>, an aggregation site for Scala blogs. The complainer's main issue was that I was spamming Planet Scala with "posts unrelated to Scala" and I think the core point of my response is worth repeating here.<br /><br />One of the main reasons for Scala's popularity is its tight integration with Java. This integration allows Scala programs "access to thousands of existing high-quality libraries". It <a href="http://www.scala-lang.org/node/104">says so on the Scala website</a>. Of all these "thousands of libraries", the <a href="http://www.springsource.org/about">Spring Framework</a> is without a doubt the most popular enterprise framework for the JVM.<br /><br />It's obviously not the case that everyone with any interest in Scala will also be interested in Spring. In fact I think there is probably a higher percentage of programmers in the Scala community who are utterly un-interested in enterprise web applications than there would be in the Java community. However, I believe that anyone applying Scala in an enterprise context, or even thinking about applying it there, is either pretty interested in Spring or, if they're not, probably should be, at least to the extent where they know what it does and where it's headed. Ergo, Spring posts on my Scala blog. I hope some of you have enjoyed the information, and I apologise to those that it may have annoyed.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-7317245822288637185.post-48391030690118319012010-11-13T18:44:00.000-08:002010-11-14T17:21:39.508-08:00SpringOne 2010: GemFire SQLFabric - "NoSQL database" scalability using SQL<span style="font-size:85%;"><span style="font-style: italic;">I spent the second-last week of October at SpringOne 2GX 2010 in Chicago and I thought some of you might get something useful out of my notes. These aren’t my complete reinterpretations of every slide, but just things I jotted down that I thought were interesting enough to remember or look into further. </span></span><br /><br /><span style="font-weight: bold;">GemFire SQLFabric - "NoSQL database" scalability using SQL </span><br />presented by <a href="http://www.blogger.com/profile/01088990426487508645">Jags Ramnarayan</a> and <a href="http://www.linkedin.com/in/gideonlow"><span style="text-decoration: underline;">Gideon Low</span></a><a href="http://www.springone2gx.com/conference/speaker/david_brown"></a><br /><br />Jags started by proposing that the <a href="http://en.wikipedia.org/wiki/ACID">ACID semantics</a>, which basically aim to ensure every change to a database is written to disk, are limited in the performance they can achieve due to being essentially I/O-bound. He also suggested the desire for these semantics is rooted in history when storage hardware and networks were slow and unreliable. Though he didn't say it explicitly, I think he was suggesting that this is no longer the case, with the implication being that we no longer need ACID.<br /><br />He outlined how the <a href="http://en.wikipedia.org/wiki/NoSQL">"NoSQL" movement</a> actually has nothing to do with <a href="http://en.wikipedia.org/wiki/SQL">SQL</a> at all - i.e. the query language - but with the data structures - <a href="http://en.wikipedia.org/wiki/Relational_database">relational databases</a> - that have typically been the subject of these queries. His point: You don't have to reinvent data querying just because you're re-inventing the data structure.<br /><br />That, of course, led into the design of <a href="http://www.gemstone.com/products/sqlfabric">GemFire SQLFabric</a>, the data management technology that was <a href="http://www.vmware.com/company/news/releases/spring-gemstone.html">acquired by SpringSource/VMWare in May 2010</a>. Jags said that, from an application developer's perspective, using GemFire SQLFabric is mostly identical to using other databases, just with a different JDBC URL and some custom DDL extensions.<br /><br />I didn't jot down Jags' description of <a href="http://www.gemstone.com/products/gemfire">GemFire</a>, but here is the spiel from the front page:<br /><br /><blockquote>GemFire Enterprise is in-memory distributed data management platform that pools memory (and CPU, network and optionally local disk) across multiple processes to manage application objects and behavior</blockquote><br /><br />Jags outlined a bit of the structure of a GemFire cluster and then said that, because of the structure, it didn't give great performance for key-based access, <span style="text-decoration: line-through;">or for joins, which left me wondering what is was good for!</span> <span style="font-style: italic;">(Edit: Turns out I misheard him. The performance is </span><span style="font-weight: bold; font-style: italic;">better</span><span style="font-style: italic;"> for joins compared to other object data grids.)</span> I think he clarified the join part later, though, when he discussed that data needing to be joined in a query must be co-located on a single node.<br /><br />The GemFire table creation DDL provides extensions for specifying how a table is to be <a href="http://en.wikipedia.org/wiki/Replication_%28computer_science%29">replicated</a> or <a href="http://en.wikipedia.org/wiki/Partition_%28database%29">partitioned</a>, and how much redundancy should back the partitions. These extensions allow the DBA to ensure that data to be queried together is co-located.<br /><br />If no partitioning or replication options are specified in the table DDL, GemFire will make decisions about default options for these based on the relationships (i.e. foreign keys) apparent in the table definition.<br /><br />He said that GemFire uses the JDBC drivers and query planning and optimisation code from <a href="http://db.apache.org/derby/">Apache Derby</a>.<br /><br />While talking about joins, Jags mentioned that co-location of joined data is required in order to achieve <a href="http://en.wikipedia.org/wiki/Scalability">linear scaling</a>. He mentioned that co-location of data is only currently a restriction of GemFire, implying that they intend to remove this restriction, though he didn't mention whether they would be tackling the linear scaling problem when they do this.<br /><br />He talked about the way in which many of the design decisions they make in GemFire are focussed on making the absolute minimum number of <a href="http://en.wikipedia.org/wiki/Seek_time">disk seeks</a>. I think that's hard-core stuff! I've been coding commercially for over ten years now and I've never once thought about how many disk seeks my code is causing.<br /><br />Gideon showed some of the networking that occurs to make GemFire work and discussed how there is a central component called a '<a href="http://www.gemstone.com/docs/6.1.0/product/docs/japi/com/gemstone/gemfire/distributed/Locator.html">Locator</a>' that the cluster nodes use to find each other and which also performs load balancing of client requests. Strangely, this seemed like a classic <a href="http://en.wikipedia.org/wiki/Single_point_of_failure">single-point-of-failure</a> to me, but there was no discussion about that problem.<br /><br />I came away not really being sure what GemFire could be used for. Jags' comments about ACID at the start seemed to suggest that he thinks we are over-obsessed with reliability in the modern age. However, in my finance day job, we need to be 100% certain that pretty much every piece of data we push to the databases is stored for good when the transaction ends. Even 99.9999% (yes, six nines!) is not good enough: if 1 in every million DB transactions goes missing, money will go missing and we'll have a very angry customer on the phone. Unfortunately, they didn't cover during the talk how (or whether) GemFire handles reliability requirements like these.<br /><br />Having said all that, however, I noticed that GemStone have an <a href="http://www.gemstone.com/hardest-problems">essay on their site called "The Hardest Problems in Data Management"</a>, in which they discuss the demanding needs of financial applications and suggest that while the popular "<a href="http://en.wikipedia.org/wiki/Eventual_consistency">eventually consistent</a>" distributed databases do not measure up to these demands, their implementation does. Having read a few paragraphs, they certainly seem to know what they're talking about from a theory perspective. If you're seriously looking for a solution in this space, I would suggest you have a good read of their documentation rather than just relying on my scratchy notes here.<br /><br /><span style="font-weight: bold;">Want to learn more?</span><br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0393333949" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0136086209" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780393333947/The-Big-Switch/?a_aid=belmonttechnology"><img style="border: 0pt none ;" src="http://www.belmonttechnology.com.au/images/bookdepository/The_Big_Switch_small.png" border="0" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-7317245822288637185.post-86505860377450139312010-11-13T01:08:00.000-08:002010-11-13T03:18:07.075-08:00SpringOne 2010: Extending Spring Integration<span style="font-size:85%;"><span style="font-style: italic;">I spent the second-last week of October at SpringOne 2GX 2010 in Chicago and I thought some of you might get something useful out of my notes. These aren’t my complete reinterpretations of every slide, but just things I jotted down that I thought were interesting enough to remember or look into further. </span></span><br /><br /><span style="font-weight: bold;">Extending Spring Integration</span><br />presented by <a href="http://www.joshlong.com/">Josh Long</a> (<a href="http://twitter.com/starbuxman">@starbuxman</a>) and <a href="http://www.springsource.com/people/ozhurakousky">Oleg Zhurakousky</a> (<a href="http://twitter.com/z_oleg">@z_oleg</a>)<br /><br />One of the most interesting things these guys said is that integration, as an industry need, is extending beyond the specialty of systems integration and toward customer integration: that is, getting systems to integrate with the users, or the users' devices, rather than just neighbouring systems.<br /><br />Though I've been to <a href="http://grahamhackingscala.blogspot.com/2010/11/concurrent-distributed-applications.html">two</a> <a href="http://grahamhackingscala.blogspot.com/2010/10/online-transaction-authorization-batch.html">other</a> talks that mentioned or demonstrated <a href="http://www.springsource.org/spring-integration">Spring Integration</a> (SI), this is the first one I'd attended that focused on it exclusively. Hence, this was the first place where I received the simple definition of SI that I've been searching for. The answer was that, at it's core, Spring Integration is just an embedded message bus.<br /><br />The guys went on to describe the basics of <a href="http://www.eaipatterns.com/">enterprise integration patterns</a> and of Spring Integration in particular...<br /><br /><a href="http://static.springsource.org/spring-integration/reference/html/ch03.html">Channels</a> are the most important concept in SI. These can be <a href="http://static.springsource.org/spring-integration/reference/html/ch03s02.html">point-to-point or publish-subscribe</a> and can also be synchronous or <a href="http://en.wiktionary.org/wiki/asynchronous">asynchronous</a>. Enterprise Integration involves lots of different types of components for connection and processing the messages travelling through Channels: <a href="http://static.springsource.org/spring-integration/reference/html/ch09.html">Transformers</a>, <a href="http://static.springsource.org/spring-integration/reference/html/ch08.html">Filters</a>, <a href="http://static.springsource.org/spring-integration/reference/html/ch07.html">Routers</a>, <a href="http://static.springsource.org/spring-integration/reference/html/ch10.html">Splitters</a>, <a href="http://static.springsource.org/spring-integration/reference/html/ch11.html">Aggregators</a>, etc. All these are not Spring-invented terms but are commonly accepted integration patterns.<br /><br />There is a <a href="http://www.springsource.org/roo">Spring Roo</a> add-on for Spring Integration currently in development. There are no milestones yet but apparently it is currently useable. (It's <a href="http://git.springsource.org/spring-integration/roo-addon">available from the SpringSource GIT repository under spring-integration/roo-addon</a>)<br /><br />It seemed very simple from a quick demo to create a persistent queue with just a few lines of XML. This is the kind of stuff that I'm very interested in. Unfortunately, there was no discussion about <a href="http://en.wikipedia.org/wiki/X/Open_XA">transaction coordination</a> between the queues and other data sources.<br /><br />A '<a href="http://static.springsource.org/spring-integration/reference/html/ch05.html">Service Activator</a>', which is typcially the end point of a message chain, can simply be any <a href="http://en.wikipedia.org/wiki/Plain_Old_Java_Object">POJO</a> that defines a method that accepts the payload of messages, but is itself completely message- and SI-agnostic. In other words, you can use SI to deliver messages to your <span style="font-weight: bold;">existing</span> <a href="http://martinfowler.com/eaaCatalog/serviceLayer.html">service-layer components</a> without any change to their code. Pretty neat.<br /><br />In response to a question, it was said that you <span style="font-style: italic;">could</span> use a Service Activator to implement filters, transformers, etc., by holding a reference to the next channel in the chain, however this would bring integration concerns into the domain of your business logic.<br /><br />They explained how the whole point of Spring Integration is to separate this logic away from you business logic, so your business code just deals with payloads and handles business-ey stuff, while your integration components - be they out-of-the-box ones or custom extensions - just deal with integration concerns and know little about the business function (other than routing). In a nutshell: The Spring team believe integration should be a configuration concern, not a business logic concern. This was a bit of a lightbulb moment for me.<br /><br />There is a <a href="http://git.springsource.org/spring-integration/samples">Spring Integration Samples project</a> showing lots of different ways to use SI <span style="font-weight: bold;">and</span> they have <a href="https://jira.springframework.org/browse/INTSAMPLES">a JIRA where you can request the addition of new samples</a>! Good stuff.<br /><br />After the talk ended, I wanted to ask a question about transaction coordination between Service Activators and message queues, but unfortunately, there were about 20 other people that wanted to ask questions as well so I couldn't get a word in.<br /><br />I almost forgot that this talk was about <span style="font-weight: bold;">extending</span> Spring Integration. I'm sorry to say that I didn't write too much down about this because <a href="http://git.springsource.org/spring-integration/samples/blobs/master/applications/cafe/src/main/java/org/springframework/integration/samples/cafe/annotation/DrinkRouter.java">creating your own integration components is just so easy</a> that's it's not really worth me re-documenting it. They did talk a little bit about rolling your own <a href="http://static.springsource.org/spring-integration/reference/html/ch06.html">inbound and outbound channel adapters</a> at either end of a channel in order to integrate with systems that the SI components don't yet support, but this stuff was a little over my head being a SI newbie.<br /><br />One thing that I'm still keen to know but which I haven't been able to glean so far is exactly how transactional message queues like <a href="http://www.rabbitmq.com/">RabbitMQ</a> fit into the picture. Are they installed as some special implementation of a Channel? Or is a message broker just another SI-agnostic endpoint? (Perhaps using an channel adapters?) Or can you use either approach, depending on your circumstances (e.g. single-process system with persistence vs. distributed system)? If you have any experience in this area, any comments you're able to add to reveal some more depth would be greatly appreciated.<br /><br />If you're interested in watching the video of this talk, it's been <a href="http://www.infoq.com/presentations/Extending-Spring-Integration">published on InfoQ</a> (1 hr 22 min)<br /><br /><span style="font-weight: bold;">Want to learn more?</span><br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0321200683" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1430224975" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780321200686/Enterprise-Integration-Patterns/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Enterprise_Integration_Patterns_small.png" border="0" /></a> <a href="http://www.bookdepository.co.uk/book/9781430224976/Spring-Enterprise-Recipes/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Spring_Enterprise_Recipes_small.png" border="0" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-42457890032363770552010-11-12T18:28:00.000-08:002010-11-13T02:53:37.460-08:00SpringOne 2010: Gradle - A Better Way to Build<span style="font-size:85%;"><span style="font-style: italic;">I spent the second-last week of October at SpringOne 2GX 2010 in Chicago and I thought some of you might get something useful out of my notes. These aren’t my complete reinterpretations of every slide, but just things I jotted down that I thought were interesting enough to remember or look into further. </span></span><br /><br /><span style="font-weight: bold;">Gradle - A Better Way to Build<br /></span>presented by<a href="http://skillsmatter.com/expert/java-jee/hans-dockter"> Hans Docketer</a><br /><br /><span style="font-size:85%;"><span style="font-style: italic;">Note that any references to the Gradle User Guide from this blog entry are to version 0.8, as that was the most recent GA version at the time of writing. If you are using a later version of Gradle, you can might want to check the <a href="http://gradle.org/userguide.html">latest User Guide</a> instead.<br /><br /></span></span>Hans is the creator and lead developer of the <a href="http://gradle.org/">Gradle build system</a>. He’s also the CEO of <a href="http://www.gradle.biz/">Gradle Inc.</a>, a consulting company specialising in project automation.<br /><br />First up, Hans explained that Gradle is actually mostly written in Java, with only the DSL being written in <a href="http://groovy.codehaus.org/">Groovy</a>.<br /><br />Gradle supports building <a href="http://www.gradle.org/0.8/docs/userguide/java_plugin.html">Java</a>, <a href="http://www.gradle.org/0.8/docs/userguide/scala_plugin.html">Scala</a>, <a href="http://www.gradle.org/0.8/docs/userguide/groovy_plugin.html">Groovy</a>, <a href="http://www.gradle.org/0.8/docs/userguide/war_plugin.html">Web projects</a>, etc.<br /><br />It appeared very easy to <a href="http://gradle.org/tutorial_java_projects.html#N10451">add a Maven dependency</a><a href="http://gradle.org/tutorial_java_projects.html#N10451"> into the classpath</a>. (Probably <a href="http://maven.apache.org/guides/getting-started/index.html#How_do_I_use_external_dependencies">easier than in Maven</a>!)<br /><br />He demoed an example of <a href="http://gradle.org/custom_tasks.html">developing a small, custom build operation</a> that copied an image (of <a href="http://www.springsource.com/about/management">Rod Johnson</a>) into the META-INF/ directory of any output JARs that had 'spring' in the name. While this was possible with only a few lines of code, I have to say that the code wasn’t all that intuitive and I think you would have to know quite a lot about the way Gradle structures things before you can easily write tasks like this yourself.<br /><br />There’s a very easy method for <a href="http://gradle.codehaus.org/Plugins#Plugins-AspectJplugin">importing Gradle tasks from external sources</a> by specifying not much more than a URL.<br /><br />Hans said that, in comparing Gradle to Maven and Ant, he believes the use of Groovy in Gradle instead of XML is not the main differentiator, but its design is where the gains come from.<br /><br />He gave a pretty impressive demo of how Gradle detects changes in sources, tests, classpaths and even the Gradle script itself, and then only rebuilds those parts of the project that absolutely need to be built (and, of course, the things that depend on them).<br /><br />While Gradle can be used to build projects that <span style="font-style: italic;">aren’t</span> written in Groovy, it was my observation that you probably need to have a fair level of proficiency in Groovy in order to compose anything other than a basic build script.<br /><br />It’s pretty easy to separate the declarative parts of a custom task from the imperative parts by defining a class at the bottom of the script that. (I found it interesting that, even though the syntax of a Gradle file is mostly declarative, Hans was still referring to the file as a '<a href="http://en.wikipedia.org/wiki/Script_%28computing%29">script</a>'.)<br /><br />Gradle exhibits heavy integration with <a href="http://ant.apache.org/">Ant</a> that is also bi-directional, i.e. <a href="http://www.gradle.org/0.8/docs/userguide/ant.html#dependsOnTask">Ant tasks can depend on Gradle tasks</a>.<br /><br />Hans highlighted that Maven’s defaults (which he called a “strong opinion”) for things like project directory structure are one reason that people will avoid migrating existing projects to Maven. While this might be true, I think it’s based on a misconception - in reality, it’s quite trivial to <a href="http://maven.apache.org/pom.html#Build_Element">override the defaults of things directory locations</a> in a <a href="http://maven.apache.org/pom.html#What_is_the_POM">Maven POM</a>.<br /><br />Gradle uses coloured output, which I think is pretty cool for a Java-based build tool.<br /><br />Hans noted that the flexibility of Groovy means that creating custom operations in a build script is pretty easy. Having seen smart people spend a week or two writing a pretty simple <a href="http://maven.apache.org/guides/plugin/guide-java-plugin-development.html">custom plugin for Maven</a>, I think making the customisation process easier is definitely a win. (On the other hand, in four years of using Maven, we've only ever created one Mojo. We have, though, often used the Ant plugin to "break out of the box".)<br /><br />Hans gave a demonstration of <a href="http://www.gradle.org/0.8/docs/userguide/multi_project_builds.html">dependencies between sub-projects of a larger project</a> which was pretty impressive, showing Gradle building and testing both dependency and dependant projects based on what changes had occurred.<br /><br />He talked about how performance is a big focus of Gradle, in particular getting the dependency and change behaviour right to ensure that Gradle only ever builds things that have been affected by changes.<br /><br /><a href="http://gradle.org/0.8/docs/userguide/artifact_management.html#uploading_to_maven_repositories">Gradle is able to generate a pom.xml file for a project</a> and deploy an artefact to a Maven repository along with the generated POM.<br /><br />Gradle doesn’t support (out of the box) a ‘release’ action like <a href="http://maven.apache.org/plugins/maven-release-plugin/">Maven’s Release Plugin</a> (which creates branches and tags in the code repository, deploys build artefacts to a remote repository and automatically updates version numbers in the build files on head/trunk to the next snapshot). However, Hans said that they eventually want to develop a full deployment pipeline based on Gradle, which will be one of the focus points after version 1.0 has been released.<br /><br /><span style="font-weight: bold;">Want to learn more?</span><br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1934356093" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1932394842" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9781934356098/Programming-Groovy?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Programming_Groovy_small.png" border="0" /></a> <a href="http://www.bookdepository.co.uk/book/9781932394849/Groovy-in-Action/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Groovy_in_Action_small.png" border="0" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-57864665199505606012010-11-11T18:33:00.001-08:002010-11-12T00:21:17.039-08:00SpringOne 2010: Harnessing the Power of HTML5<span style="font-size:85%;"><span style="font-style: italic;">I spent the second-last week of October at SpringOne 2GX 2010 in Chicago and I thought some of you might get something useful out of my notes. These aren’t my complete reinterpretations of every slide, but just things I jotted down that I thought were interesting enough to remember or look into further. </span></span><br /><br /><span style="font-weight: bold;">Harnessing the Power of HTML5</span><br />presented by <a href="http://www.springone2gx.com/conference/chicago/2010/10/speakers/scott_andrews">Scott Andrews</a> (<a href="http://twitter.com/scothis">@scothis</a>)and <a href="http://www.springone2gx.com/conference/speaker/jeremy_grelle">Jeremy Grelle</a> (<a href="http://twitter.com/jeremyg484">@jeremyg484</a>)<br /><br />First up, the guys cleared up some confusion by explaining that the term HTML5 is currently being used to encompass much more than just the latest W3C HTML spec, but also all of the related sets of technologies that are now being standardised in an attempt to ease the creation of <a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29">dynamic webapps</a>. It really means <a href="http://en.wikipedia.org/wiki/HTML5">HTML 5</a> + <a href="http://www.w3.org/Style/CSS/current-work#table">CSS 3</a> + new JavaScript APIs like <a href="http://en.wikipedia.org/wiki/WebSockets">WebSockets</a> and <a href="http://en.wikipedia.org/wiki/Web_Workers">WebWorkers</a>.<br /><br />They demonstrated a lot of the upcoming technologies through the rest of the talk by showing a presentation from <a href="http://www.html5rocks.com/">html5rocks.com</a>, a site Google has put together to promote the stuff.<br /><br /><a href="http://en.wikipedia.org/wiki/Web_Storage">Web storage</a> (which, ironically, means storing data on the client) is coming. Local storage – a basic key/value store – is pretty much standardised. Another idea for a <a href="http://dev.w3.org/html5/webdatabase/">client-side database</a> is still being discussed, but has been <a href="http://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/">implemented in WebKit</a> and hence is available on many mobile devices. Note that the data in this database would, like cookies, not be accessible by scripts from other sites, but would be unsecured on the local machine. Likely uses are things like data storage for offline access of cloud data. (That's cloud <span style="font-style: italic;">computing</span> data, not meterological readings.)<br /><br />There is now an <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html">application cache manifest</a> that allows the server to instruct the browser about cacheable resources and allows the browser to skip checking the last modified date/time of these resources as long as the date/time of the manifest hasn’t changed.<br /><br />Web Workers allow JavaScript code to execute something in a separate process. They mentioned that this is specifically a <span style="font-style: italic;">process</span> and not a <span style="font-style: italic;">thread,</span> the implication being that the spawned process doesn’t have access to the memory of the parent.<br /><br />Web Sockets are being billed as the new <a href="http://en.wikipedia.org/wiki/XMLHttpRequest">XHR</a> and the new <a href="http://en.wikipedia.org/wiki/Comet_%28programming%29">Comet</a>.<br /><br /><a href="http://onepixelahead.com/2010/05/31/html5-notification-example/">Javascript Notifications</a> will allow the application to request the browser to show a <a href="http://growl.info/about.php">Growl</a>-style status popup, but only if the user has already given permission for the site to show these.<br /><br />Drag and drop is being supported at the browser level.<br /><br />There is a proposal to provide access to a user’s current latitude and longitude.<br /><br />Scott and Jeremy recommended that people not try to use these new features directly, but continue to use the various existing JavaScript libraries that already do the same thing, with the hope being that these libraries will, over time, be upgraded to use (and abstract) the native support where it is available (assuming the native support will be better than the current methods).<br /><br />There are <a href="http://diveintohtml5.org/semantics.html#new-elements">new semantic tags in HTML 5</a> for <header>, <nav>, <section>, <article>, <aside><br /><br /><a href="http://blog.whatwg.org/the-road-to-html-5-link-relations">HTML 5 includes new link/rel types</a> include ‘pingback’ which will allow a page to provide a URL for the browser to call if the user leaves the site, and ‘prefetch’ to specify other pages for the browser to load into the cache in anticipation of where the user might go next.<br /><br />There are <a href="http://http//www.w3.org/TR/html5/the-input-element.html#attr-input-type">new HTML form input types</a> that restrict the type of data that can be entered as well as providing some visual, optimisation and input hints, which is especially useful on mobile devices. New input types include date, email, range, search, tel, color and number.<br /><br />There is also the ability to provide basic client-side authentication (without JavaScript) by specifying constraints such as <code>required</code> or a <a href="http://www.w3.org/TR/html5/common-input-element-attributes.html#the-pattern-attribute">regular expression pattern</a>. A new CSS <code>:invalid</code> <a href="http://www.w3schools.com/css/css_pseudo_classes.asp">pseudo-class</a> can be styled to change the appearance of invalid fields declaratively.<br /><br />There are new tags for defining ‘<a href="http://www.w3schools.com/html5/tag_meter.asp">meter</a>’ and ‘<a href="http://www.w3schools.com/html5/tag_progress.asp">progress</a>’ elements (the latter for both indeterminate and % complete).<br /><br />There are plans to support <a href="http://www.webmonkey.com/2010/02/embed_audio_and_video_in_html_5_pages/">embedded audio and video in HTML 5</a> without the need for any plugins, although there are currently <a href="http://en.wikipedia.org/wiki/HTML5_video#Default_video_format_debate">arguments going on about what codec</a> should be the standard.<br /><br />There’s a <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html">Canvas element</a> for just <a href="http://diveintohtml5.org/canvas.html#divingin">drawing pretty much anything</a> using Java2D-like shape, line and fill constructs. There is a <a href="http://slides.html5rocks.com/#slide24">pretty impressive example in the Google slides where photos can be dragged, rotated and scaled</a>. JavaScript is required to change the contents of the canvas, but the API as a concept looks pretty neat.<br /><br />There is support for JavaScript events coming out of SVG objects using native HTML tags.<br /><br /><a href="http://www.w3schools.com/css/pr_pseudo_first-child.asp">CSS 2 selectors like ‘first-child’</a> are being more widely supported and new ones like ‘not’ are coming in as well.<br /><br /><a href="http://randsco.com/index.php/2009/07/04/p680">CSS is introducing font downloading</a>, allowing <a href="http://sixrevisions.com/css/font-face-guide/">everyone visiting you site to see the same font</a> without having to use <a href="http://en.wikipedia.org/wiki/Fahrner_Image_Replacement">image replacement</a>. (As someone who's had to do a bit of this in the past, I have to say 'yay!')<br /><br />There are STILL experiments with having <a href="http://www.alistapart.com/articles/css3multicolumn">CSS manage column-based layouts</a> (link from 2005!), although this is only implemented in WebKit at the moment.<br /><br /><a href="http://www.css3.info/preview/hsl/">CSS3 will support HSL (Hue/Saturation/Luminance) colour definitions</a>.<br /><br /><a href="http://www.w3.org/TR/css3-background/#the-border-radius">border-radius for rounded corners is becoming standard</a>, except in IE 9!!! Says the speaker: “So IE will be square.” (I've since tracked down an <a href="http://blogs.msdn.com/b/ie/archive/2009/11/18/an-early-look-at-ie9-for-developers.aspx">announcement on msdn.com that seems to suggest that border-radius will be in IE9</a>.)<br /><br /><a href="http://www.leemunroe.com/css3-gradients/">Gradients</a>, <a href="http://robertnyman.com/2010/03/16/drop-shadow-with-css-for-all-web-browsers/">shadows</a> and <a href="http://www.the-art-of-web.com/css/css-animation/">animations</a> are all getting some standardised support in CSS3.<br /><br />It will be possible to <a href="http://www.adequatelygood.com/2010/7/Saner-HTML5-History-Management">intercept changes to the history</a> (e.g. capture the back button) within an Ajax app and load data rather than allowing a whole-page refresh.<br /><br />There is a library called <a href="http://atmosphere.java.net/">Atmosphere</a> that provides a server-side abstraction over Comet and WebSockets to allow these protocols to be handled on any <a href="http://en.wikipedia.org/wiki/List_of_Servlet_containers">Java web server</a> (many of which currently support this stuff but through proprietary APIs).<br /><br />They showed a pretty cool example where they were using Canvas and WebSockets on the client side with <a href="http://static.springsource.org/spring-batch/">Spring Batch</a> and <a href="http://www.springsource.org/spring-integration">Spring Integration</a> on the server side to parse a large file, stream interesting data to the client through an Integration channel and visualise that data in the browser.<br /><br />I've found this funky little website callled <a href="http://caniuse.com/">caniuse.com</a> that allows you to specify browser names and versions along with HTML 5 features that you would like to use and it will show you the level of support in each browser & version for that technology.<br /><br /><span style="font-weight:bold;">Want to learn more?</span><br /><br /><table width="100%"><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1430227907" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1934356689" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9781430227908/Pro-HTML-5-Programming/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Pro_HTML_Programming_small.png" border="0" /></a> <a href="http://www.bookdepository.co.uk/book/9781934356685/HTML5-and-CSS3/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Pragmatic_HTML5_CSS3_small.png" border="0" /></a><br /></td></tr><br /></table>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-74376880497905605142010-11-06T04:44:00.000-07:002010-11-07T03:44:42.057-08:00SpringOne 2010: Concurrent and Distributed Applications with Spring<span style="font-style: italic;font-size:85%;" >I spent the second-last week of October at SpringOne 2GX 2010 in Chicago and I thought some of you might get something useful out of my notes. These aren’t my complete reinterpretations of every slide, but just things I jotted down that I thought were interesting enough to remember or look into further.<br /></span><br /><span style="font-weight: bold;">Concurrent and Distributed Applications with Spring</span><br />presented by <a href="http://www.springsource.com/people/dsyer">Dave Syer</a><br /><br />My favourite quote from this talk, and possibly from the whole conference, is one which I want to take back to my workplace and put into practice with avengeance:<br /><br /><blockquote>Using single-threaded algorithms on 32-core machines is a waste of money</blockquote><br />Dave also presented a really simple but useful definition of <a href="http://en.wikipedia.org/wiki/Thread_safety">thread-safety</a>:<br /><br /><blockquote>Thread safety = properly managing <a href="http://en.wikipedia.org/wiki/Concurrency_%28computer_science%29">concurrent</a> access to shared, <a href="http://en.wikipedia.org/wiki/Immutable_object">mutable</a> state</blockquote><br />Applying this definition, you can see there are three ways to tackle thread-safety: you can either eliminate <span style="font-style: italic;">mutability</span>, or you can eliminate <span style="font-style: italic;">sharing</span> or you can eliminate <span style="font-style: italic;">concurrency</span>. Eliminating concurrency is the core aim of mutexs and locks, e.g. <code>synchronized</code> blocks. Eliminating mutability is one of the chief design idioms of <a href="http://en.wikipedia.org/wiki/Functional_programming">functional programming</a>.<br /><br />On the topic of eliminating shared resources, Dave pointed towards the frequent use of <a href="http://download.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html">ThreadLocal</a> within the Spring Framework to associate unshared resources to individual threads. He made note of the potential for memory leaks with ThreadLocal, highlighting that, with the long-running threads in most servers, you have to ensure you clean each ThreadLocal up when you’re finished otherwise your data will hang around forever. (Sounds like going back to pairing new & <a href="http://en.wikipedia.org/wiki/Delete_%28C%2B%2B%29">delete</a>!)<br /><br />Dave talked about a method on <a href="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html">ExecutorService</a> that I've never used before called <a href="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html#invokeAny%28java.util.Collection%29">invokeAny()</a> that will execute every task in a given list of tasks concurrently (assuming a multi-threaded ExecutorService implementation) and return the result of the first one to complete. The remainder of the tasks are interrupted. I imagine where you might use this is if you have a situation where you have two or three different algorithms, each of which can outperform the other two for certain structures of data, but where the most efficient algorithm for a given individual input can't be (easily) determined before execution. So, on a many-multi-core machine, you have the option of just running all three against the same data, taking the result from the first algorithm to complete and killing the others.<br /><br />Dave briefly discussed an emerging (I think?) pattern for concurrency called <a href="http://www.eecs.harvard.edu/%7Emdw/proj/seda/">Staged Event-Driven Architecture or SEDA</a>.<br /><br />He mentioned that Spring Integration 2.0 (<a href="http://blog.springsource.com/2010/10/29/spring-integration-2-0-release-candidate-1/">RC1 released Oct 29</a>) includes <a href="http://static.springsource.org/spring-integration/docs/2.0.x/reference/htmlsingle/#transactions">support for transactional, persistent message queues</a>.<br /><br />He highlighted the difference between between a <span style="font-weight: bold; font-style: italic;">distributed Applications</span> (running the <span style="font-style: italic;">same</span> binary on multiple nodes) and a <span style="font-weight: bold; font-style: italic;">distributed Systems</span> (running <span style="font-style: italic;">related</span>, <span style="font-style: italic;">communicating</span> applications across multiple nodes). He said that it was wise to prefer looser coupled messaging architectures for distributed <span style="font-style: italic;">Systems</span> because of the likelihood of unsynchronised release cycles.<br /><br /><span style="font-weight: bold;">Want to learn more?</span><br /><br /><table width="100%"><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0321349601" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0123705916" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9780321349606/Java-Concurrency-in-Practice/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Java_Concurrency_In_Practice_small.png" border="0" /></a> <a href="http://www.bookdepository.co.uk/book/9780123705914/The-Art-of-Multiprocessor-Programming/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/The_Art_of_Multiproceesor_Programming_small.png" border="0" /></a></td></tr></table>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-7317245822288637185.post-34395322536365181532010-10-29T19:23:00.000-07:002010-10-31T03:43:15.514-07:00SpringOne 2010: Groovy and Concurrency<span style="font-size:85%;"><span style="font-style: italic;">I spent the second-last week of October at SpringOne 2GX 2010 in Chicago and I thought some of you might get something useful out of my notes. These aren’t my complete reinterpretations of every slide, but just things I jotted down that I thought were interesting enough to remember or look into further. </span></span><br /><br /><span style="font-weight: bold;">Groovy and Concurrency</span><br />presented by <a href="http://www.springone2gx.com/conference/chicago/2010/10/speakers/paul_king">Paul King</a><br /><br />Paul by started by mentioning a library called <a href="http://functionaljava.org/">Functional Java</a> which, to me, looks like an attempt at porting a bunch of ideas present in <a href="http://www.scala-lang.org/">Scala</a> over to Java, and another one called <a href="http://kilim.malhar.net/">Kilim</a>, which is an Actors library for Java.<br /><br />Paul said that his main argument for why you should use <a href="http://groovy.codehaus.org/">Groovy</a>, rather than Scala or <a href="http://clojure.org/">Clojure</a>, is that Groovy is closer to the Java syntax and, hence, is more easily integrated with Java. (In my personal experience, I can’t say I’ve ever had any problems <a href="http://www.codecommit.com/blog/java/interop-between-java-and-scala">integrating Java with Scala</a>. Going the other way (using Scala in Java) has some gotchas, but wouldn't be described as hard.)<br /><br />Groovy supports a very nifty pipe (‘<code>|</code>’) operator extension to the <a href="http://download.oracle.com/javase/6/docs/api/java/lang/Process.html">java.lang.Process</a> class, allowing you to easily pipe <span style="font-style: italic;">stdout</span> to <span style="font-style: italic;">stdin</span> between two or more processes, just like in a shell.<br /><br />I've now heard Google Collections (now part of the <a href="http://code.google.com/p/guava-libraries/">Guava libraries</a>) mentioned for about the 5th time this week. I really should check out what these are because they’re very popular!<br /><br /><a href="http://groovy.codehaus.org/ExpandoMetaClass+-+Methods">Groovy supports adding functions to classes, and even individual objects, at runtime</a>. That is, your code can contain statements that add members to an existing type. This is not creating an inline definition of a new type, but actually changing the type at runtime, as you might do in JavaScript. They call this <a href="http://groovy.codehaus.org/Dynamic+Groovy">Dynamic Groovy</a>. I've never really got my head around why meta-programming - programs that write programs (and then run them) - is a good idea, but I've also read <a href="http://www.paulgraham.com/avg.html">Paul Graham saying that this feature gave him a major competitive advantage</a>, so there must be something mind-bending about it. Perhaps I just need to give it a try?<br /><br />Groovy has an <a href="http://groovy.codehaus.org/Immutable+AST+Macro">@Immutable annotation</a> that, as well as making the contained fields final (without you declaring them so), is also shorthand for adding getters, <code>toString()</code>, <code>hashCode()</code> and <code>equals()</code> to a class based on just the field names and types. <a href="http://www.scala-lang.org/node/107">Case classes in Scala</a> provide the same functionality along with the added bonus of making <a href="http://www.scala-lang.org/node/120">pattern matching</a> simple.<br /><br />He mentioned two Java concurrency libraries, one called <a href="http://code.google.com/p/jetlang/">Jetlang</a> for <a href="http://en.wikipedia.org/wiki/Message_passing">message-based concurrency</a> (the Jetlang site itself refers to Jetlang being similar to <a href="http://www.scala-lang.org/node/242">Scala's Actors</a>) and <a href="http://www.jppf.org/">JPPF</a>, a <a href="http://en.wikipedia.org/wiki/Grid_computing">grid-computation</a> library. The JPPF intro uses domain language similar to that of <a href="http://grahamhackingscala.blogspot.com/2010/10/online-transaction-authorization-batch.html">Spring Batch</a>, with regards to jobs and tasks.<br /><br />He talked a bit about <a href="http://gpars.codehaus.org/">GPars</a> (short for Groovy Parallel Systems), a concurrency library specifcally for Groovy.<br /><br />He also said that <a href="http://en.wikipedia.org/wiki/Software_transactional_memory">shared transactional memory</a> looked interesting but didn’t go into it much beyond mentioning the <a href="http://multiverse.codehaus.org/overview.html">Multiverse</a> library. I have seen this term bandied around a little, in particular due to a couple of people attempting to implement it in Scala, but I've never looked into it - it's frequency hasn't yet punched through my signal/noise filter.<br /><br />He gave a little preview of what the GPars guys are trying to achieve with a <a href="http://gpars.codehaus.org/Dataflow">“Dataflows” library</a>. You use a DSL to describe a dependency graph between steps in your (complex, but parallelisable) algorithm and Dataflows will automatically run in parallel those parts of the algorithm that are not dependent, synchronising at the points where multiple asynchronous outputs are required to enter the next step.<br /><br /><span style="font-weight: bold;">Want to learn more?</span><br /><br /><table width="100%"><tbody><tr><td style="vertical-align: top;">From Amazon...<br /><br /><iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=1932394842" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe> <iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=FFFFFF&IS2=1&npa=1&bg1=FFFFFF&fc1=000000&lc1=4444CC&t=belmontechno-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=0123705916" style="width: 120px; height: 240px;" marginwidth="0" marginheight="0" frameborder="0" scrolling="no"></iframe><br /><br /></td><td style="vertical-align: top;">From Book Depository...<br /><br /><a href="http://www.bookdepository.co.uk/book/9781932394849/Groovy-in-Action/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/Groovy_in_Action_small.png" border="0" /></a> <a href="http://www.bookdepository.co.uk/book/9780123705914/The-Art-of-Multiprocessor-Programming/?a_aid=belmonttechnology"><img style="border: 0pt none;" src="http://www.belmonttechnology.com.au/images/bookdepository/The_Art_of_Multiproceesor_Programming_small.png" border="0" /></a><br /></td></tr></tbody></table>Unknownnoreply@blogger.com0