From: David Pollak Date: 2006-05-03T23:00:15+09:00 Subject: Re: Sharp knives and glue ------=_Part_44555_10165406.1146664809149 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Francis, I think we see many things the same way. It's most excellent to hear your perspectives. On 5/2/06, Francis Cianfrocca wrote: > > I broadly agree with most of this, inlcuding your rants on stability. But > are we missing something more fundamental? > > Java incrementally improves on C/C++ in many ways. But fundamentally, it > has > a very dangerous tendency to encourage sloppy thinking among > less-experienced programmers, because the language takes care of so many > things for you. Well, that comment can be read two ways, can't it? You > have > 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 impac= t 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 ca= n decompile that class to see the Java source code (Paul Martino 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= . > You're arguing for tools and mechanisms to scale to enterprise-sized > projects. I spent most of the last three years writing Ruby programs that > looked very much like incrementally-improved C++ programs. It took me a > long > time to grok duck-typing, but when the penny finally dropped it really > changed everything. People coming to Ruby without the baggage of many > years > of commercial C/C++/Java experience don't seem to have this problem, nor > do > they have the mental blocks against metaprogramming that people like me > 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 buildin= g 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, i= s > that Ruby is successfully extending the same kind of partitioned > development > model that has worked so well in the open-source world generally. If you > accept that Ruby may be revolutionary rather than evolutionary, then ask > yourself why that may be so. To me the value of metaprogramming and > duck-typing are that they permit a tremendously powerful way to re-imagin= e > the mapping of elements from real-world problem domains to elements of > computer programs. They help us model the world better. And yes, that can > mean changing the behavior of already-established and stable objects. But > to > 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 acros= s 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 > for them? Well, one model is to think of a large system as a relatively > large collection of fine-grained, domain-specific elements. Problems aris= e > both because of the size of the set (and the number of interactions) and > the > fact that they are domain-specific, which means they only matter to a > small > number of organizations, perhaps no more than one. So in turn, they don't > benefit from the evaluation of a broad community. Well, if you think of a > large system that way, you are really facing an essentially insurmountabl= e > design challenge. There are too many moving parts. So people respond with > ideas like "Design by Contract," which seek to automate and "freeze" the > interactions among various system components. Well, the rigor which with > this is done may actually be part of the reason that large systems get > large > in the first place! You end up adding more components because you have no > ability to modify the existing ones in a context that won't arbitrarily > break their existing contracts. There may in fact be a tipping point at > which system size starts to conflict directly with constructability. But > we > know from real-world experience that this is not true in other engineerin= g > disciplines, so the question becomes: is there a different way to do this= ? > 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 includ= e 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 i= n 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 ca= n 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? -- -------- David Pollak's Ruby Playground http://dppruby.com ------=_Part_44555_10165406.1146664809149--