You can learn Ruby in 4 hours. This talks isn't to learn Ruby, but rather
to show facets of Ruby. Ruby has made programming fun again for
Dave. It's also made him more productive.
Languages and tools make a difference
Ruby has variables, methods, but no types in methods. When Dave first started
using Ruby, he had a strong typing background - and was terrified of Ruby's
un-typed feature. He first thought Ruby was a toy language for hobbyists
because of the lack of typing. Now, many years later, he really likes the
lack of typing and hardly even has bugs relating to typing. He notes that
with Java we store most of our data in Collections - and those are all Objects
- so Java is essentially un-typed as well. How often do you get ClassCastExceptions?
The rooms concensus is not not a whole lot. To make up for the
lack of typing, Ruby developers tend to write a lot more unit tests.
ActiveRecord - Ruby O/R Mapping Library
Ruby on Rails - not a single line of XML. Uses intelligent defaults and allows
you to override them. The following creates a wrapper around the "ranks"
table.
class Rank < ActiveRecord::Base
end
The original author of RoR thinks that every database table should be plural,
so singular class names map to plural table names. It's even smart enough
to change Person to a "people" database table. Apparently it has a bunch
of the singular-to-plural mappings for the English language built-in. The
key to Rails is clever defaulting - allow you to write a lot less
code, but override if you really need to.
ActiveRecord has many lifecyle hooks (17) that you can override. For example,
before_save, before_destroy, validate. For example
def before_save
self.when_added ||= Time.now
end
I wonder if Rails has any support for transactions and specifying propagation
behavior on transactions? I asked Dave this question and it sounds like ActiveRecord
has a rich support for transactions - and even wraps the "save" method with
a transaction by default.
"Ruby is pretty damn good at web applications"
Simple CGI is a common choice. FastCGI and mod_ruby in Apache are other common
choices. There are also a number of different web frameworks for Ruby:
- Roll-your-own
- Templating systems
- erb
- Amarita
- RDoc templates
- Iowa - similar to WebObjects
- Ruby on Rails
Ruby on Rails - MVC Framework
Contoller - one method per view. Setup context (a.k.a. the model) for views.
Views contain "rhtml" - HTML with embedded Ruby. Lots of helper functions.
Can access model data (context) setup by Controller. The name of the method
in the Controller determines the name of the view file. A "select" method
will dispatch to a "select.rhtml" file. The method name to call in a Controller
is determined by the URI - for example, /ranks/view calls the "view" method
in the RanksController class. Pretty slick! I like the idea of smart defaults
- IMO this should be used a lot more in webapps. I'd love to get away from
mapping URLs in Struts, Spring and WebWork.
Rails has built-in support for configurable URLs - so you can change query
strings to more slash-type URLs. What about things like client-side validation,
success messages and sortable/pageable tables? Do those exist in Rails? I
asked Dave and he said said they have good support for success messages with
a "flash" concept and the post-to-redirect problem is almost non-existant
because most controller invocations are redirects. Client-side validation
and sortable/pageable tables don't exist in Rails.
Rails has Needles - and IoC framework similar to Pico. However, there's a
fair amount of traffic on the mailing list and a lot of Ruby developers think
they just don't need IoC. Dave's suggestion is to use Class Injection.
The largest Ruby application is probably Daves - 55,000 lines or code, couple
hundred thousand users. There are entire companies who write all all their
applications in Ruby. The founder of Rails wrote it so he could write Basecamp
- which is only 4500 lines of code.
Good stuff Dave - and definitely a nice overview of Rails. Will I be digging
in an using Rails anytime soon? Not this year, I'm going to have some fun
with Tapestry and JSF first. Maybe next year.
SmartFactory - one factory for all factories. Allows developers to handle
failures rather depending on various factories. Unfortunately, you will have
to do Casts. Stuart things that Generics should've never been added and instead
we should just have no casts. Instead, the compiler should inject the cast
implicitly.
Document d = SmartFactory.getInstance();
Java might be a lot more powerful if we could return a different type from
constructors - like Class Clusters in Objective-C. You can get a lot of dynamic
features in Java using AspectJ. Java Developers
have a lot of responsibility when they start using aspects.
Stuarts talk was 3 hours and I only attended the first half. He's a very good
speaker and I enjoyed listening to him more a lot. The basic gist of his
talk seemed to be that Java should be more dynamic, and using AspectJ, it
can be. I thought he was going to recommend we switch languages - so I was
surprised to here him recommend AOP. The last example he gave was how to
interrupt a FileInputStream so you could test the condition in a unit test.
I can see how this could be quite useful for causing network or database
failures and seeing how your application behaves.
The first session I attended was Erik Hatcher's Ant Hacks talk. The first
half of his talk was about Ant in general and was most of the stuff covered
in Java Development with Ant. The good stuff was the 2nd half when he covered
all the new stuff in Ant 1.6. Steve is working on an update to Java Development
with Ant - shoujld will be a lot thinner. Below are some notes I took on
what's new in 1.6.
- <image> task. Requires Java Advanced Imaging API
- Performs image manipulation
- <import> task
- No more entity ref includes needed - can use Ant properties for
file reference now.
- OO Nature
- mix in imported build files - call super on imported
file by specifying depends="${ant.project.name}.target"
where the project.name is specified in the imported build
file. Only targets that are overridden will get prefixed
with namespace.
- target overriding -
main build file takes precedence
- "abstract" targets - requires main build file implementation
- <subant> task - Recurses tree
- Two modes: 1) same build file in each sub directory 2) crawl
a tree and run same build file on all subdirectories
- Can have targetless build files. Everything outside a target gets executed
before any targets
- <presetdef> - Use the same task and optionally repeat. Define the options
once, give it a name and refer to it later. Can override attributes later
in the build.xml file. Only works for one task at a time.
- <macrodef> - bye bye antcall. Much faster than antcall - does all the
same things
- You can specify attributes and elements as part of the definition.
Tasks are wrapped in a <sequential> tag.
- attributes are referred to in tasks using @{attribute}
- elements are simple placeholders using XML <element/>
- I could really use this stuff in AppFuse to replace the compile-module
and test-module targets
- "spawn" a new attribute on <java> - allows process to live past
when Ant dies
- <scriptdef> - allows you to use all kinds of scripting languages - i.e.
Groovy, JavaScript, etc.
- the project, attributes and elements are given to you - so you
can easily grab them in the scripts
- helpful to know Ant's API when writing
- <antlib> - componentizes definition of types and tasks
- anything that defines stuff - put in antlib.xml (i.e. <taskdef>)
- mostly designed for Ant task distributors because they can package
an antlib.xml with a namespace
- has root element
of <antlib> instead of XML
- xmlns:antcontrib="antlib:net.sf.antcontrib" - brings
in all tasks into your project
I really liked Erik's talk because AppFuse was inspired by his Java Development
with Ant book. Its build.xml file was intially based on Erik's sample app
and therefore, the first half of his talk pretty much pointed out tips and
tricks that I'm currently using. The 2nd half of his talk was highlighting
the new features of 1.6 - which he's suggested I adopt in the past. I've
never had much desire (or time) to dig in and update AppFuse's build.xml
file to 1.6. However, after attending his talk - it seems like it should
be pretty easy to do. Good bye <antcall>, hello <macrodef>.
Later: One of the coolest things I saw in Erik's talk was how his Ant logging was color coded. I asked him about it and all your need to do is specify "-logger org.apache.tools.ant.listener.AnsiColorLogger" in an ANT_ARGS environment variable. Good stuff!
It's time for another NFJS conference. I attended the one in June and had an awesome experience. I doubt I'll cover it as much as I did last time, that's just a lot of work - not to mention my cell phone's data bill was $300! As I look through the sessions, I'm noticing that it's a great thing to attend 2 of these conferences - b/c you can skip all the sessions you saw the first time. Since there's usually 2-3 good ones per time slot, reducing that down to 1-2 is nice.
This afternoon, I'm planning to attend sessions by Erik Hatcher and Stuart Halloway. Erik for Ant 1.6 and Subversion (maybe even Lucene) and Stuart for "dynamic, reflective languages". Since much of AppFuse's build.xml is based on Erik's Java Dev with Ant sample app, it'd be nice to figure out how to take advantage of 1.6 features (especially since 1.6.2 is required). I've never seen Stuart speak before, but I've heard he's excellent.
Saturday I plan on learning more about Tapestry from Erik (in a 3-hour session!). Since adding Tapestry to AppFuse is my next open-source development effort, this weekend and ApacheCon are good opportunities to learn more about it. I know, I should just buck up and read the book (I made it to page 100 a couple of weeks ago, nothing since), but it's tough to find the time.
I'll probably skip out tomorrow afternoon and work on Spring Live since Chapter 10 is due by Monday and I'm not done yet. Sunday, I'll be talking about AppFuse making open-source easier. "Brain, get ready to be stuffed."