![]() |
Articles Feed |
Categories
Archives
- August 2010 (1)
- July 2010 (5)
- June 2010 (4)
- April 2010 (3)
- March 2010 (2)
- February 2010 (2)
- January 2010 (1)
- December 2009 (1)
- October 2009 (2)
- September 2009 (2)
- August 2009 (1)
- July 2009 (5)
- June 2009 (2)
- May 2009 (2)
- April 2009 (8)
- March 2009 (7)
- January 2009 (2)
- December 2008 (3)
- November 2008 (5)
- October 2008 (4)
- September 2008 (6)
- August 2008 (4)
- July 2008 (5)
- June 2008 (5)
- May 2008 (4)
- April 2008 (2)
- February 2008 (4)
- January 2008 (2)
- December 2007 (2)
- November 2007 (2)
- October 2007 (2)
- September 2007 (1)
- August 2007 (3)
- July 2007 (1)
- June 2007 (4)
- May 2007 (7)
- April 2007 (2)
- February 2007 (3)
- January 2007 (3)
- November 2006 (3)
- October 2006 (3)
- September 2006 (17)
- November 2004 (1)
MMEmail: My First Clojure Open Source Contribution
by: micah | April 21st, 2010 | 0 comments »
While working on website for my sister, I was perturbed that there were no libraries on Clojars for sending email. I was using Leiningen which will download and include all your dependancies for you (so sweet!). Yet, with the library I found, I had to manually download all the required jars. Call me lazy but being forced to manually download dependancies seems like cruel and unusual punishment these days.
So I solved the problem:
MMEmail
Simple Clojure library for sending email, with just one jar!
Installation
Leiningan:
- (defproject your-project "0.0.0"
- :dependencies [[mmemail "1.0.0"]]
Jar File
…can be downloaded at http://clojars.org/repo/mmemail/mmemail/1.0.0/mmemail-1.0.0.jar
Usage:
Include the library
- (use 'mmemail.core)
The Easy Way
mmemail.core is the only include you need. It contains only 2 methods, the fist being send-email.
It takes a map that includes all the configuration and email parameters. That’s it.
- (send-email {:host "smtp.gmail.com"
- :port 465
- :ssl true
- :user "road@gmail.com"
- :password "runner"
- :to "joe@acme.com"
- :subject "Greetings"
- :body "Meep Meep!"})
Most of the parameters are required, but based on your server configuration you might get away without these:
- :ssl
- :password
- :subject
It also accepts the following optional parameters:
- :from (defaults to :user)
- :cc
- :bcc
The recipient parameters (:to, :cc, :bcc) may be a string, for one recipient, or a sequence of strings, for multiple recipients.
The Convenient Way
It can be annoying to pass such a big map into the function, and typically you’ll want to get all the server configuration
out of the way. This is where the second function of mmemail.core (create-mailer) comes into play.
- (def my_mailer (create-mailer {:host "smtp.gmail.com"
- :port 465
- :ssl true
- :user "road@gmail.com"
- :password "runner"}))
create-mailer will return a new function with all the configuration baked in. So in the future, you can send email
like so:
- (my_mailer {:to "joe@acme.com"
- :subject "Greetings"
- :body "Meep Meep!"})
The create-mailer accepts email parameters that will be used as defaults when the generated function is called.
- (def my_mailer (create-mailer {:subject "Greetings"
- :body "Meep Meep!"
- :host "smtp.gmail.com"
- :port 465
- :ssl true
- :user "road@gmail.com"
- :password "runner"}))
- (my_mailer {:to "joe@acme.com"})
License
Copyright 2010 Micah Martin. All Rights Reserved. MMEmail and all included source files are distributed under terms of the GNU LGPL.
TDD in education, they're doing it wrong
by: eric | April 9th, 2010 | 4 comments »
This blog post originally appeared on a blog I maintain for my current game development class. Generally speaking my posts over there are pretty specific to the classes I’m taking, and aren’t appropriate for this blog. Recently however my instructor, who is an extremely smart and accomplished developer in the game development industry, described a common misconception about TDD that prompted me to rant on that blog. Since the subject is TDD I’m placing it here, edited to make more sense.
Recently in class our professor said something like this, “TDD says you should only write the simplest code that can possibly pass the test, and that leads to spaghetti code with a lof conditional logic.” Sadly this left me shaking my head. I’ve been doing TDD every single day for the last 3 years professionally, and intermittently for 2 years before that, and I can say for certain that TDD never caused me to write spaghetti code. Of course I’ve written spaghetti code, including some of the code I TDD’d for the previous class (I’m not real happy with my memory system) but that wasn’t caused by TDD. The crux of the professor’s argument seems to come from a mistaken understanding of TDD. He seems to have TDD as a three step process:
- Write the test
- Write the smallest amount of code to make the test pass
- Repeat
Unfortunately it’s missing a crucial step – refactor! Yes we initially write the simplest code that can possibly pass, but we don’t leave it that way. We write that simple code so we can refactor with a green bar, something that unfortunately my professor doesn’t understand.
When I write the minimal amount of code refactoring becomes easier, because I have a suite of passing tests. In school students and teachers throw around the term refactoring a lot, but are usually unaware that when Martin Fowler wrote the book on Refactoring, defining it for the software development community, he required unit tests. You can’t guarantee your behavior did not change unless you have tests around the behavior, which is why I hear so many students say things like “I’m almost done refactoring but the code doesn’t build yet.” Refactoring is meant to be small steps, in a definite process, so that at the end of each refactoring (such as extract method) I have the same behavior as before, but better code. Most people who refactor don’t have tests, take huge steps and eventually end up hacking and slashing something back together that is close to (but not the same) as their original behavior. That’s not refactoring, that’s hacking - and most students clearly don’t know the difference.
At this point the blog went into a description of how you’re supposed to do TDD, but if you’re reading this blog you probably already know how to do that. The point of moving this here is to point out that TDD is making inroads at the university level, but it has a long way to go. Those doing TDD are a distinct minority, those that are are doing it wrong, and they’re getting bad information. Furthermore let’s remember these are smart people. The professor for my class is frakking brilliant, and the students are amongst the best in the university, and yet in spite of that when they start their first job they’ll do so without writing unit tests. The good news is that smart people are trying out TDD, in an industry (games) that is notoriously slow to adopt software development methodologies, so we are winning. It’s just taking longer than we thought.
JRuby Helps Us Craft Quality Software
by: doug | April 6th, 2010 | 0 comments »
"It's kind of a Frankenstein." We've used this phrase more than a few times to describe the architecture and technology used to design a product that was recently released after almost a year of development by the software craftsmen of 8th Light. The product is a multi-platform, PC management application for library computer labs written primarily in Ruby, run on the JVM with JRuby. The user interface is written in erb-templated HTML and Javascript, and is displayed in an embedded web browser. JNA (Java Native Access) is used to call operating system specific functions that enable an insane amount of control over the desktop. The various JRuby components communicate with each other over DRb.
But the most amazing thing about this project is that we are using JRuby to deliver a portable, rich desktop app using the best of web technologies. We chose JRuby because it increased portability and performance and reduced development time.
At 8th Light we had tried before to build products for our clients using Ruby, but we always hit a dead end when it came to deployment. For our clients who provide software products instead of software services, the applications must install easily and completely on the end customers machines while still protecting the intellectual property of our client. We tried very hard to make technologies like RubyScript2exe work, but in the end a packing and unpacking solution was too slow and still left our client's source code open for the reading on the installed computer.
As we began the project about a year ago, we discovered that JRuby had reached the point where it could be a viable platform for us to be able to build products that our client's customers could easily deploy in their own environments. Our solution was to bundle all of our JRuby code into jars after it had been encrypted. By patching into the JRuby load service we were able to decrypt the source on the fly and leave the code bundled and encrypted on the disk at all times.
JRuby allows us dirt simple access to Java's huge collection of libraries, along with plenty of custom Java libraries our client had already written. We also go back the other way, implementing Java interfaces in JRuby and using those objects in Java code. This fluidity allows us to always pick the best tool for the job. Early in the project, this also helped to sell the technology to our client. They were wary of a new language that none of their in-house developers knew, but we were able to reassure them that they could easily drop back into Java at any time.
At one point in the project, the client's development team jumped on the project to add a new configuration interface to the server side of the application. The team wanted to use a set of Java tools that they were already familiar with, but needed to make calls into the JRuby side of the application to get and set the configuration values. We built a new Java interface for them and implemented it in JRuby—then from our Ruby initialization code, called a static Java function back on the Main class, passing in the configuration object. This allowed the client's team to initialize their java objects with the instance of our JRuby class that we had provided.
- //The Java Interface
- public interface ConfigurationStore
- {
- void put(Map<string> pairs);
- void put(String key, String value);
- String get(String name);
- }
- #The Ruby Implementation
- class ConfigurationStore
- include Java::package.ConfigurationStore
- def get(key)
- .....
- end
- # Notice how we were able to implement the function
- # overloading present in the interface by
- # using a variable arguments in one ruby method.
- def put(*args)
- if args.size == 2
- ....
- elsif args.size == 1
- .....
- else
- raise ArgumentError.new("put() takes a Hash
- (or a Java Map) or a key and value pair")
- end
- end
- end
We wanted to be extra sure that the class we were writting in Ruby would work from Java before we handed it over, so in addition to the rspecs we wrote to test the Ruby class, we also wanted to write a JUnit Test. Normally, we inject a JRuby object into Java by calling a Java function from a JRuby method and passing along the JRuby object that is to be used. In this case we wanted to actually instantiate the Ruby object in the setup of a JUnit test. We dug around in the JRuby APIs and were able to leverage the fact that the RubyRuntimeAdapter returns the last thing evaluated. We were able to use the toJava() method on the IRubyObject returned from eval and cast the result into the interface class. Then we were free to write JUnit tests exercising the functionality of the JRuby class.
- // instantiating a Ruby object in Java
- RubyInstanceConfig config = new RubyInstanceConfig();
- Ruby runtime = JavaEmbedUtils.initialize(new ArrayList(), config);
- RubyRuntimeAdapter evaler = JavaEmbedUtils.newRuntimeAdapter();
- IRubyObject result = evaler.eval(runtime, "require 'configuration_store';" +
- "config_store = ConfigurationStore.new");
- store = (ConfigurationStore) result.toJava(ConfigurationStore.class);
We do a lot of things at 8th Light to ensure that we can deliver very high quality code to our clients as fast as is responsible. One of the most important things we do is work in highly productive languages. JRuby enables us to write most of the complicated business logic of our application in the highly productive Ruby language and still provide a viable deployment scheme that allows our clients to successfully sell their product to their customers.
This article appears in the April 6th, 2010 Engine Yard Newsletter
#
