Francis,
I think we see many things the same way. It’s most excellent to hear
your
perspectives.
On 5/2/06, Francis C. [email protected] wrote:
to be a lot more careful with a straight razor than with a Norelco, but
having deep experience with dangerous and powerful shaving systems isn’t
necessarily all that valuable from a business point of view. In other
words,
the Norelco represents progress precisely because it lets you be somewhat
sloppy, without getting a bloody mess.
I agree that Java promotes some bad programming habbits by hiding the
impact
of these habbits until late in the process. Moving developers farther
away
from the “metal” and dealing with programmers who don’t know assembler
and
don’t know Java byte-code and don’t understand that computing resources
are
not infinite leads to less than optimal code and much less than optimal
coding practices. I don’t think Ruby is any better from this
perspective.
I find it worse in some ways because I can’t review the source code of
the
method I’m calling to see what it’s doing under the covers.
“What… David… Ruby is open source and a scripting language… how
can
you not be able to see what’s happening?!?” In Java I know what class
is
being called. I can open that class if the source code is available. I
can
decompile that class to see the Java source code (Paul M.o from
http://ahpah.com mathematically proved a 1-to-1 correspondence between
Java
byte-code and Java source code.) Ruby with mixins, etc. makes it much
more
difficult to track down where the code that’s going to execute came
from.
Now with Ruby the perception is that we’re going back to the straight
razor.
have. (I learned to avoid self-modifying code way back in the assembler
days.)
I love Meta-Programming. I gave a presentation about it at the Silicon
Valley Ruby Conference. I’ve used it to develop a domain specific
langage
for web site navigation ( http://rubyforge.org/projects/sitemap )
Duck-typing is very helpful/useful. NextStep (now OS X my first true
love
in operating systems/development environments) was built on Objective-C.
Objective-C was duck-typed (although the concept of ‘Protocols’ was
introduced into the language which is much like Java interfaces.)
IMHO, code blocks are the most powerful part of Ruby. Passing code that
will be called inside another method (iterators are the best example of
this) is the big mind-shift and the huge chunk of power that Ruby has
over
Java. With that being said, I’ve written a meta-programming system in
Java
that generates byte-code at runtime and spoon-feeds the byte-code to the
JVM… but I digress.
One of the challenges that I’ve seen with MetaProgramming in Ruby is
that
there are few examples of using it for good. ActiveRecord is a very
good
example of MetaProgramming and why MetaProgramming is so excellent (in
Java,
we created intermediate super-classes for each OR mapped class.) Most
of
the other examples of MetaProgramming (e.g., the stuff in Why’s Poinent
Guide) just makes up for the lack of certain things in the Ruby langauge
(
e.g., class constants that work as expected.)
MetaProgramming can be very bad when MixIns muck with and change the
behavior of my existing methods. This is even worse when ‘gem update’
changes the behavior of the MixIn such that when I do a normal update of
my
production system, my app stops working because some clever guy changed
the
behavior of one of my classes.
My point is that if we try to make Ruby fit into established large-team
methodologies, we may be throwing away what makes Ruby special in the
first
place. And we’ll end up with an incrementally-better Java. And in a
corporate environment, there are always more reasons not to rock the boat
than to do so. Which means that if we accept that model, Ruby will simply
not succeed in the enterprise.
I disagree. I think we can add things… optional things… to the Ruby
language (we can even add them via MixIns a la the DbC MixIn and the
type-checking MixIn) that allows Ruby to be a liquid experience for
building
small apps/scripts, but allows Ruby to have more hospitable to
Enterprise
use (e.g., a update Module to enforce packages/Module names for all code
that’s not loaded from /usr/lib/ruby/*… etc.)
What I believe is happening, but has yet to fully emerge into
visibility, is
many, that is exactly the problem!
I think you’re on to something. The combination of Rails/Gems/Engines
is a
very excellent way of creating software components that can be shared
across
teams. The Login Engine seems to me to be a better piece of software
than
many login/authentication Enterprise Java Bean implementations that I’ve
seen. Plus the ability to “subclass” the Login Engine just by putting
properly named files in your part of the project is wicked cool. I
think
Engines may be the first step down a new and better path of large-scale
component delivery.
What are “large systems,” really, and why is Java perhaps the better
tool
ideas like “Design by Contract,” which seek to automate and “freeze” the
And Ruby may be part of the answer.
Yes… Ruby is part of the answer.
Another part of the answer may be Engines.
I think a third part of the answer is Domain Specific Languages. I’ve
been
working on DSLs for 15 years. My first Domain Specific Language was a
spreadsheet called Mesa. Wait… think… yes… a spreadsheet is a
Domain
Specific Language for expressing a wide variety of financial and
business
logic. More formally, in 1999/2000/2001, I wrote a series of domain
specific languages (workflow, O-R mapping, Object-HTML-multi-page form
mapping, web site navigation.) The syntax of these DSLs was XML. The
semantics (the words used) was specific to the domain. A business
person
could look at the logic in these DSLs in an XML editor and understand
the
logic that was expressed. That’s pretty important… the original
business
intent was preserved in the expression that the computer could execute.
It’s very, very rare to see a computer program written in any language
that
preserves the original intent in such a way that a non-programmer could
understand it. What was unique about these DSLs was that they could
include
snippets of Java code that could call out to other parts of the system.
The net-net is that Ruby is excellent glue for building systems. It’s
an
exellent platform for building DSLs (SiteMap
http://rubyforge.org/projects/sitemap was ~ 800 LOC in Ruby vs. 6,000
LOC in
Java.)
Ruby is in my opinion, has the potential for being the next step in the
evolution of enterprise development systems. It, however, has to
respect
the systems and methodologies that have evolved in the enterprise and it
can
shape and change those methodologies just as Java has.
If I sound like an advocate for enterprise SOAs, well I am. But I have a
long background in large distributed systems, and what I see with SOA
today
is first-generation thinking, focused primarily on transport protocols
rather than on finding a more organic way for large ordered systems to
spontaneously emerge, which is what should be happening. And the way we
think about traditional large-systems development may be the stumbling
block.
Discrete islands of logic that may or may not be in the same address
space
is a most excellent perspective.
I’ve been thinking a lot about building a distributed object framework
in
Ruby. Two of biggest (and least-appreciated) technical reasons why this
hasn’t worked in the past are the “fragile superclass” problem and the
“destruction at a distance” problem. Ruby potentially relaxes both of
these
problems. I think the “aspect-oriented” stuff that Java people love so
much
really doesn’t work in any other context, because it tries to established
horizontal levels across large chunks of code that have direct textual
visibility to all the other chunks. It’s just not natural to the way Ruby
should work at large scales.
NextStep had Distributed Objects that worked really, really well back 12
years ago. Ruby, taking a lot of its ideas from SmallTalk, as did
Objective-C, is a great candidate for distributed systems. Getting back
to
my love of code blocks… they make writing asynchronous code much, much
easier. Just pass the “do” block to the distributed call and it gets
executed when the call finishes.
Anyway I don’t have the answers (yet) and there is a long way to go. But
I
don’t think Ruby should be “improved” to fit traditional large-system
methodology. I think the reverse (somehow) is closer to true.
Perhaps Ruby should be enhanced… it’s enhancements will lead to more
adoption… so it can change the way people think… so the world is
more
Ruby?