Tiresome, Tedious Bullshit (on Rails) 39
In his post The Business Advantage of Rails, Giles Bowkett writes:
What makes programmers happy? Elegant systems which make them productive and take tiresome, tedious bullshit out of their daily lives.
People who get tiresome, tedious bullshit out of their way forever are great people to work with. Conversely, tolerating tiresome, tedious bullshit without ever fixing it is absolutely not a character trait you want your hiring process to be biased in favor of.
which sounds like a good idea, except that a lot of programming on a real application, no matter if you do it in Ruby, or Visual C, or COBOL, ends up being a lot of tiresome, tedious bullshit.
Which brings me to something that I've been thinking a lot about lately. At CDD we have a pretty complex Rails app, (as one of the consultants that we're working with said, "I've worked on a dozen Rails apps, and this is about 4 times bigger and more complex than any of them") and as our application gets bigger and bigger I'm starting to see more and more complexity and problems crop up. I feel like we're walking up the same old curve to all of the standard problems you run into when programming a webapp in any language (object model too big to be easily understood, code is getting less and less cohesive, etc). It may have taken a little longer to get there, but I'm pretty sure that we're going to end up in the same place.
Which leads me to another problem. The easiest solution to a lot of these problems, in my experience, has always been to refactor the code. That's what I always ended up doing with Java apps of this size back in the day. Unfortunantly, the state of Ruby refactoring tools, and I'm putting this as nicely as I possibly can, sucks. Even something as simple renaming a class tends to be far more painful than it needs to be.
So the big question now is, have we (and perhaps we're the first team to do this, as I haven't heard much about it from others) finally hit the point where the cost of maintaining our code in Ruby is higher than the savings by writing it in Ruby in the first place? I'm not willing to answer yes to that question yet, but I am starting to see more and more places that have me pining for for the good old days of IntelliJ, with all of the great things it does to make your life easier. It's easy to forget about the amount of tiresome, tedious bullshit that great tools can help us avoid, at least until you start running into that same old bullshit.
Trackbacks
Use the following link to trackback from your own site:
http://kurt.karmalab.org/trackbacks?article_id=tiresome-tedious-bullshit-on-rails&day=25&month=07&year=2007
"Maintenance is 40 to 80% of software costs." Robert L. Glass, Facts and Fallacies of Software Engineering.
You used a framework because the 60% to 20% initial development was fast? Non-static typed languages are quite hard to maintain (some types can't be guessed, especially with lots of meta-programming-magic involved). So the 40 to 80% maintenance will be hard and expensive. As a project manager I had to drop some massive Perl and Python programs in the 90s due to maintenance problems.
"So the big question now is, have we [...] finally hit the point where the cost of maintaining our code in Ruby is higher than the savings by writing it in Ruby in the first place?"
Yes.
"... (and perhaps we're the first team to do this, as I haven't heard much about it from others) ..."
People talk about this all the time, especially people with experience in large legacy apps. The RoR and Ruby community has shut it's ears and has scorched everyone who suggested high maintenance costs for massive Ruby/RoR systems.
Peace
-stephan
Stephan Schmidt :: stephan@reposita.org Reposita Open Source - Monitor your software development http://www.reposita.org Blog at http://stephan.reposita.org - No signal. No noise.
"People talk about this all the time,..." [1}
[1] I talked to some CTOs and project leads about this, and they all shared RoR maintenance problems with big deployments.
As long as there are people writing code then you'll always have this problem. Be it political or technical people will find ways to make things painful.
In the technical space it's usually the different level of expertise (or lack thereof), personal preferences, prejudices and basically anything that can be described as trendy that will surely overtime make you application look like a big pile of poo.
The best defense against this is to keep things separate and truly orthogonal. Bolting onto the same system just makes code rot that more egregious.
Ahh, I remember the good old days when people actually had to refactor their code by hand with only their test coverage and intellect to see them through. If you're that unhappy with the extant refactoring tools, why not write one?
Sounds like a great idea for your next project - a refactoring tool!
@Shadowfiend:
I know the community to shut it's ears to maintenance problems, the argument usually is: Ruby is less noisy, leaner, smaller, more powerful and therefore more orthogonal, so there is no maintenance problem. This attitude might change, but at least from 1998 to around 2006 when I was active with Ruby/RoR projects that was the answer to maintenance problems with Ruby.
Type inference will not help you with all refactoring problems, not all types can be inferenced with DSL frameworks like RoR.
"... though, as most Java IDEs (including, as it happens, IDEA) are gaining Ruby support"
Working on a bigger Grails project, IDE support is great but doesn't help you with refactorings and maintenance. Most of the time, especially as said with meta frameworks as Grails, the IDE has no clue about the type.
For example:
def person = request.map.person
person.smile()
What type is person? The IDE can guess, that person is Person.groovy - or not - and can narrow the type to all types with a smile method - not when I have dynamically added the smile method - or could try to simulate and trace the application (as JTest and others do) and see what one puts into person. Smalltalk has some advantage here, because it not only has compile time information, but runtime information and therefor can deduce what person is, at least at the time when Smalltalk checked the runtime type. This information might be incorporated from a Ruby VM to a Ruby IDE, but we're years from there and even then, not all types can be guessed correctly.
"Regardless, it amuses me greatly when people seem to imply that dynamic languages are hard to add refactoring to [...] when refactoring practically came out of the Smalltalk community, Smalltalk being a dynamic language in exactly the same vein as Ruby."
First, Smalltalk refactoring is about refactoring Smalltalk applications, not about meta-programmed framework DSLs like RoR. I know of no Smalltalk refactoring paper which talks about meta-programmed DSLs.
Second, under the umbrella of refactoring, there are hundreds of concrete refactorings. Some are easy for every kind of language, like "Extract method". Some are harder to do like "Extract superclass and use super class instead". And some IDEs guarantee that your refactorings work, with some refactoring tools you need tests and a lot of manual clean up if something goes wrong. So refactorings are always possible, but some languages do not support secure refactorings (which people call "no-refactorings").
Third, "Smalltalk being a dynamic language in exactly the same vein as Ruby", there is a difference between Smalltalk and Ruby. Smalltalk is dynamic reference/static object language, while Ruby is a dynamic reference/ dynamic object language, at least more than Smalltalk is. So what applies to Smalltalk does not automatically apply to Ruby.
Last not least, Smalltalk uses runtime information to do refactorings, an IDE for Ruby doesn't do that.
Peace -stephan
-- Stephan Schmidt :: stephan@reposita.org Reposita Open Source - Monitor your software development http://www.reposita.org Blog at http://stephan.reposita.org - No signal. No noise.
Don't NetBeans, Eclipse (Aptana) or Komodo all have Rails refactoring tools that you could use?
I know the Ruby community - or the new Ruby community after the RoR influx - shuts its ears, at least from 1998 to 2005 when I was activly using Ruby and RoR from time to time. The usual argument is: Ruby is less noisy, small, lean, has better readability, is more powerful and more orthogonal and therefor there is no maintenance problem. As a project manager I had to drop some massive Perl and Python projects in the 90s, due to maintenance problems, so I have seen dynamic languages fail with bigger code bases. So the Ruby argument was not very convincing to me.
"Regardless, it amuses me greatly when people seem to imply that dynamic languages are hard to add refactoring to [...] when refactoring practically came out of the Smalltalk community, Smalltalk being a dynamic language in exactly the same vein as Ruby."
First under the umrella of refactoring, there are lots of concrete refactorings. Some are easy in every language, like "Extract method". Some are easier in dynamic languages, because you do not have to change every type declaration. Others are harder to do, like "Extract superclass and use superclass instead.". Others are harder still like "Move method" or "Rename method". Some IDEs and tools guarantee secure refactorings, for some tools and languages you need tight tests and a lot of manual clean up after the refactoring should something go wrong or not as intended. Every language supports manual(!) refactorings. You could argue that unsafe refactorings with manual rework are not the same as safe refactorings or are no refactorings at all. But I hope for the best in IDEA with Groovy.
Second there should be some success in the future with tools but not now.
"Refactoring tools and such are getting better, though, as most Java IDEs (including, as it happens, IDEA) are gaining Ruby support."
Support in IDEA - the best IDE :-) will not help much. Working on a bigger Grails project, IDE support is great to have in IDEA. But most of the types in my Grails application cannot be guessed by the IDE, because Grails is a meta-programming DSL not a conventional framework.
Sometimes guessing the type is easy, as in
def person = new Person()
But assuming the Groovy code
def person = request.person
person.smile()
the IDE has problems guessing the type of person. It could guess the type as Person.groovy based on the name - but the programmer could just have been thinking of something else. It could narrow the guess to all types with a smile method, at least when noone has added one during runtime. It could simulate and trace the application (as JTest does to find null pointers) to see what has been put into request.person. Smalltalk has some advantage here because it not only uses compile time but also runtime information. But still it can't guess the type correctly all the time and we're years away from a Ruby VM which supplies runtime type information to an IDE.
Compare that to (legal Groovy code):
Person person = request.person
person.smile()
In that case, the IDE has much fewer problems to "guess" the type of person.
Third, "Smalltalk being a dynamic language in exactly the same vein as Ruby". Ruby is a dynamic reference/ dynamic object language while Smalltalk is a dynamic reference/static object language, at least more static than Ruby. So not everything said about Smalltalk applies to Ruby.
You can write and maintain code with dynamic languages. But it is harder, it needs more discipline and planning. Both of those are seldom available with average programmers and the usual corporate enviroment.
Peace, -stephan
-- Stephan Schmidt :: stephan@reposita.org Reposita Open Source - Monitor your software development http://www.reposita.org Blog at http://stephan.reposita.org - No signal. No noise.
Stephan --
With respect to unsafe refactorings+tests, you may save some work with so-called `safe' refactorings, but they're not really safe at the end of the day. They're type-safe. The difference is large, because maybe the refactoring broke something that didn't directly have to do with the type. So you have to run tests anyway; the only thing that changes is that you have a few problems that you don't have to deal with immediately.
Nonetheless, I don't deny that static types make certain refactoring tasks easier than they are in dynamic languages; the issue is that by doing that, you also sacrifice some flexibility. It's a trade-off, as with many things, and different people prefer different sides of that trade-off.
Now, with respect to type inferencing and guessing -- you're right, of course, correct guessing is often near impossible. But when I was talking about type inferencing, I was talking about the SML/Haskell kind. The one that introduces static types without type annotations. I think it would be interesting to see a Ruby VM (or even an IDE) that could go into a statically typed, type-inferenced mode. You'd lose a lot of the value of duck typing, but it'd be interesting to see what kind of advantages that would give you.
As for Smalltalk being somehow more static than Ruby, it really isn't. What's different is the approach of Smalltalk programmers, who aren't quite as keen to use metaprogramming as Rubyists (who tend to consider the programming-metaprogramming distinction semantic at best). Smalltalk itself is just as dynamic, what with support for doesNotUnderstand: and runtime compiler access. Certain things may not be quite as straightforward, and Smalltalkers seem to be a little more reticent in using some of the metaprogramming features in Smalltalk, but they're there. In fact, occasionally Smalltalk is *more* metaprogramming friendly. For example, the VisualWorks implementation of namespaces allows you access to the list of classes in that namespace, something which isn't quite so simple in Ruby. (/me munches his words; never mind, I'd missed Module#constants :))
Another interesting addition to Ruby would be optional type annotations like Groovy has.
All this aside, I think your final comment is fantastic:
``Both [discipline and planning] are seldom available with average programmers and the usual corporate environment.''
Yes. I've been saying for a time that Java is what you use when you can't rely on all of your programmers being great at what they do. When you can rely on that, your options are far more open, because you can go with more dynamic languages that require more discipline, because you trust that your programmers will have that discipline.
I think that eventually this is a bridge that you're going to cross on any project, with any language. I've been in consulting situations with Java that was much, much harder to maintain than our current code base. I think that my biggest problem is that, even with 95+ percent test coverage, people seem to be far less likely to refactor in Ruby, once again, because the tools suck.
At this point, I would gladly give up some of the metaprograming magic to get better tools. Smalltalk made a decision early on to put some constraints on the language in order to enable the creation of really great tools. Maybe Rubyists should start looking at doing something similar.
"we're years away from a Ruby VM which supplies runtime type information to an IDE."
How do you know this - you might be right but I myself do not claim to be a profit.
The crux of the problem is that development languages have not yet evolved to the efficiency of natural languages. Most goals in CS are to improve human interaction with machines and we have not yet managed to create an inference engine that approaches our human capabilities to imply meaning out of context.
Try to imagine reading a novel (or having a conversation for that matter) where each paragraph is preceded with a declaration of every object about to be used in that paragraph. I suggest that it would be very tedious and non-productive and doubt anyone would bother to finish the novel (or conversation). In fact they would probably be too confused to understand it.
At one time I'm sure many believed that a computer could never better a chess master - we know how that turned out.
Dynamic languages try to mimic natural languages (just as OO tries to mimic real world objects) and I have no doubt they are the future, so I hope rather than giving up on them, people will concentrate on making them better. As Edison put it - 1 percent inspiration and 99 percent perspiration - or we'd all still be in the dark ages.
As far as refactoring in the short term goes, frameworks like RoR make it very easy to skimp on up front specifications and analysis which is probably a good thing on small to medium size projects. But on a large project I think a throw away prototype and a couple of iterations of ever more detailed specifications and models is warranted to minimize the amount of refactoring (and bugs and unwanted or incorrectly implemented features for that matter). Just like one tool shouldn't used for all projects, each development process should be tailored to the scope of the project. So the double edge sword is that RoR makes it very easy to dive in before checking the depth of the water thus risk breaking your neck.
"You can write and maintain code with dynamic languages. But it is harder, it needs more discipline and planning. Both of those are seldom available with average programmers and the usual corporate environment."
I agree this is true for LARGE projects and unfortunately many corporate environments do have this attitude. I think that Google is a welcome exception and is one of the reasons behind their success regardless of what environment they choose to use.
So that being said (for now) if you are going to approach a very large project with little up-front analysis, yes you should use a strongly typed language such as Java as you are going to need all the protection you can get and you will also NEED to do a LOT of refactoring and bug fix maintenance, so you should use the easiest refactoring and test driven language you can find as well.
When I retire and have more time, I plan to contribute to the goal of of better type inference engines - perhaps via the use of genetic algorithms that adapt to programmer patterns and domain usage - similar to the way voice recognition adapts to the user.
Well, we do declare things in natural languages, they're just not done in the annotative way. There's room for some ambiguity when we don't. For example, some poems (and stories) have an unclear persona through whom the poem is being told -- sometimes this is because that persona is just someone needed to tell it, and isn't important, and sometimes it's to leave the option of who it is open.
You don't typically start talking about a chariot or a horse in writing without first saying that they are chariots or horses. Admittedly, when that does happen (say you walk into the middle of a conversation), the human brain can typically figure out what's going on given a few sentences to provide some context. However, we can do this because we have massive amounts of data to cross-reference with. If we walk into a conversation, we might extrapolate that it's about horses because we're talking about racing, betting, and reins. But then, later one we might find out the conversation was actually about camels. Nonetheless, we can still have the conversation about whether racing animals is bad or not, regardless of the animal (duck typing).
So while I agree that some aspects of dynamic languages allow our code to look more natural, I won't say that dynamic typing is the way we operate in day-to-day life. It can be, on occasion, but those occasions suffer from the same ambiguity that dynamic typing can give rise to.
Regardless of my disagreement on that point, though, your goal of contributing to better type inference engines is a noble and cool one :)
Shadowfiend
To your first point: In a large project my goal would be to eliminate as much refactoring as possible by starting with a better thought out design and correct specifications in the first place. It has nothing to do with quality or ease of refactoring. But perhaps I don't understand your intended meaning here.
To your second point: Here is a paragraph between begin and end that is understandable without declarations in my opinion. I have added the declarations to show that this would be tedious and unproductive IMO.
function my_message
Declare:
finding act_of // as opposed to the result
hard complicated // as opposed a soft
testing act_of // as opposed to trying
static stationary // as opposed to noise
follow to_understand // as opposed to tailing someone
test act_of // as opposed to a written piece of paper to fill in
right correct // as opposed to a direction
ect. ect. ect.
Begin
I’m finding this logic hard to follow. Testing is good, coverage is good. Static typing is, among other things, a way to have the compiler test your code for type issues. Since we like testing, this makes static typing good, right?
End
So I guess I will have to just agree to disagree on this one. Yes there will be instances where the inference will be incorrect but just like voice recognition is not perfect it is a valuable non-the-less - I would hate to give up my voice dialing on my cell phone. Nothing wrong with not seeing eye to eye especially when the goal is to better our profession.
I don't think this is a Ruby specific problem, I think this is a team development issue.
Sounds like your team may have waited too late to refactor the code and now the app is too huge to easily break it apart.
Blaming it on Ruby because there isn't a tool out there to do it for you seems like a lame excuse to me.
Refactoring is just like test cases... start early and consistently or you will pay for it later.
Yo, seems like you aren't coding Ruby correctly.
Ruby is about building tests for your code alongside, and maintaining your tests, documentation, and refactoring while making big sweeping changes.
If all you do in any language is add more moronic code because "at least it works", then you are doing it ALL wrong.
Sure you can't code perfect straight off the bat, but if you keep adding moronic methods and classes that are named "duck" then they have methods that are like "quacklikedogbutreport_as_duck", and make dozens of these methods and classes, and don't keep track what you are doing, that isn't coding. That is experimentation.
Most rails apps that are reviewed month to month actually shrink in complexity in code size. If you are just adding bulk and not adding sensibilty to your web app, what is the point.
Functionality is the half-ass pat on the head by boss way. Striving to build robust software is really what you should be looking to do.
Technically, if it's a 'refactoring', then it is safe because the definition of a 'refactoring' is 'a functionally equivalent change'. Programatically effected refactorings are safe as long as the tool is working correctly: if the refactoring isn't safe, the tool should warn you and ask for confirmation---otherwise, it's just a mass edit tool, not a refactoring tool.
Wow, some very detailed responses here. I'd just like to chip in with our real-world experience-- our primary (Rails) app has over 200 extremely complex models that has been in production for over a year, with 6000-7000 customers and 200-300 employees hitting it 24/7 on a single server. This is our primary business app.
Our rate of change has been extremely high, and I'd estimate that we have refactored, overhauled, or changed 60-70% of our Rails codebase over the last year due to major business growth and new government reporting requirements.
The majority of our problems:
1) We were new to the framework, coming from a variety of non-dynamic backgrounds (C# and Java, primarily), and some unfortunate development practices. This led to some very bad Ruby code (yes, you can do that). 2) We had some major performance problems early on. Indexing the database and bumping the bandwidth up past a T1 eliminated most of our performance worries; caching the hell out of everything cacheable has taken care of most of the rest. 3) Setting up a production environment can be pretty painful if you're doing it for the first time. Fortunately we had a pretty rockin' network guy to get everything going for us. (Never, ever let a programmer set up your server. For anything. Ever.)
Rails has it's frustrations, just like anything else, but complaining about refactoring tools is just ignorant (in the non-perjorative sense). Learn your tools; the console is your best friend (in a non-Windows environment), and as one poster mentioned earlier, consistency is key. You can write bags of traditional, top-heavy code slop in Rails, and you will end up with the same problems you had with your C#, Java, or COBOL slop.
Learning Ruby the language instead of just Rails the framework will definitely take you the the next level (especially once you start poking around with metaprogramming, which is not nearly as scary or complicated as it sounds).
To learn Ruby, I can highly recommend Pickaxe, Ruby Cookbook, and the Rails source code.
If anybody is curious about our experience switching from C# to Rails, feel free to hit me up with questions. I obviously can't discuss business details, but I'm wide open for technology questions.
"I don't know that the Rails community has shut its ears in any way, shape, or form."
"Blaming it on Ruby because there isn't a tool out there to do it for you seems like a lame excuse to me."
"Yo, seems like you aren't coding Ruby correctly."
Thanks for proofing my point.
"... 200 extremely complex models ..."
That's a rather small application for enterprise standards. Most people I know think of big projects as projects with > 1000 models and more than 5000 classes (and more than 500KLoc, but that depends on the chosen language). I guess big and small are relative to your enviroment, which makes talking about bigness, scale and maintenance a difficult issue with so many different points of reference.
Peace -stephan
-- Stephan Schmidt :: stephan@reposita.org Reposita Open Source - Monitor your software development http://www.reposita.org Blog at http://stephan.reposita.org - No signal. No noise.
Hmmm, I have experienced this on a previous project, but you have to ask yourself, are you just experiencing what you would on ANY platform, but on rails the speed-bump is more defined.
Regardless, is it the case that rails in large projects is still faster (though by a smaller margin) than doing it in some other platform?
Another point is that I have increasingly realised that many (if not most, myself included) rails users do not actually use it as it is intended.
What I mean is that we are using it as we would any other platform, BUT, what would be better, is to write code with a mind to defining higher level ASLs ABOVE the rails layer.
In effect, use the same approach that DHH used when writing rails itself.
When we start doing THAT (and I am still working on it myself, dunno about you lot) we will probably see slightly better scaling.
But folks, don't forget Fred Brooks.... THERE AIN'T NO SILVER BULLET...
COMPLEXITY is COMPLEX. TOUGH.
So maybe it is a time to look at Smalltalk and web frameworks like Aida/Web or Seaside and maybe you'll end up as I did: after 10 years I still didn't reach a"Tedious Bullshit" syndrome and it seems I won't next 10 years too.
"Thanks for proofing my point." -- Several of the people who replied definitely did, unfortunately. But several people also made cogent arguments to the contrary, which I don't consider to be
closing ears', but ratherdiscussion', which, to me, is far far more productive.Cool re: safe refactorings.
Brian Will -- yes, you're right, of course, but a refactoring tool can only know so much about your code. And if it warns you and asks for confirmation, it's still really a mass edit tool, as you have to double-check the
refactoring' yourself to begin with. True, in Ruby, even some of the most rudimentary refactorings often aren'tsafe' in that regard, but I'd argue that typically you might find yourself modifying less code when you refactor in Ruby than in other languages. I do not, however, speak from too much personal observation, so I can't support that beyond saying, in Stephen Colbert's words, that I feel it in my gut. And since my gut has more nerve endings than my brain... ;)Having worked on very large projects in many languages (including Ruby and Java), I can say that of the languages I've used in anger, I've been less likely to hit this point on Ruby projects. As Soren says, I doubt your problem is language-specific. It may, however, be that your team + Ruby aren't a good match. I don't mean that as a jab. Some people aren't meant to use dynamic languages.
Similarly some problems aren't meant for Rails. One theme that DHH kind of hammers over and over again, whenever people ask him for new features that he personally isn't interested in, is that Rails is opinionated software, and it's justified in having opinions because it targets a pretty specific problem space. It sounds like you shouldn't have written your app in Rails, because the problem space is way too complex for what is, when you get down to it, a framework optimized for simple problems.
In terms of the situation you're now in, I think your only sane option is to write a refactoring browser, either in Rails or RubyCocoa. It depends on the mismatch between your problem space and Rails. If the mismatch is slight, write a refactoring browser, open source it, and the Ruby community will trumpet your name as a hero. If the mismatch is gigantic, rewrite your app in a different framework. If the mismatch is in the middle, it's a judgement call.
Definitely read "Code Generation in Action" before translating your app to a new framework, if that's the route you go for. If you end up on J2EE, you'll have a lot of that good old tiresome tedious bullshit to deal with out the gate, and "CGIA" has some terrific strategies for paring that down to tasks that won't drive you mad.
But I would definitely say go for the refactoring browser instead. Given the progress of the JRuby project, you may be able to get some of that via IntelliJ or Eclipse. Certainly a refactoring browser for Ruby is on the way from one place or another. Tool vendors were all over the place at RailsConf, and it was an enterprise software company that pointed out your post to me.
I people are kind of missing the point. Tests might be able to take care of functional tests, but he doesn't even have the freedom to rework basic classes without worrying if the code will still make sense "type-wise". In a language like Java that's a non-issue. Of course any team should have a nice set of a tests to see if the application still works, but here even the basic premise of type cohesiveness isn't guaranteed if he uses current tools.
A refactoring in Java takes minutes of time even for large models. I'd say the language *is* the problem.
I just made my way through all the comments and discovered all my ideas had already come up, except for "Wait for the vendors," which is probably not the most dynamic suggestion ever made in the history of suggestion-making. But, for what it's worth, that's what I think.
I took a look at your demo. "Find similar molecules with this structure" definitely goes a step beyond the average Rails app. The average Rails app would be more like "Add this molecule to your friends list." But I do have to give you some bad news, your demo's got a mouse rollover which gives me some kind of blurb for an Asterisk telephony demo instead.
Over and over I see people who say the "problem" will eventually be solved by the tool vendors. Which is great but misses the point. Customers are not going to wait for me to add the new feature or fix a bug or do any of the other numerous maintenance tasks. They expect me to be able to solve the problem now. As a business person comments about the programming skills of the given team or the maturity of the tools available does not do a lot to convince me that Ruby/RoR is a good choice for a given project. It is not infrequent for small projects to grow into medium sized projects, which may eventually grow to very large projects. You don't always know upfront the full scope of the application over its full lifetime.
OMG this thread is still going on? Just another in the hundreds of my truck is better than your truck (Java is better Ruby) threads. They always seem to degrade to this.
Nobody ever changes what they do by reading this 'Tiresome, Tedious Bullshit'. They change because they have a desire to find something better - some people would just as soon never change - that's fine too.
Everyone just use whatever you want to and shut the f**K up. It's a waste of everyones time.
"Most people I know think of big projects as projects with > 1000 models and more than 5000 classes"
Which is great, and you probably want a larger, meatier solution from an established vendor for those kinds of projects. I was just sharing our experience. It has been good overall, even though we've had a lot of growth and major changes in the organization. Flexibility and maintainability were and are our top priorities for this software, and barring the pitfalls I've already mentioned, Rails came through for us in a big way.
As someone else here pointed out, Rails is no silver bullet, but it solves a certain range of needs exceptionally well.
I hardly see how civilized discussion between us should get you annoyed, CG. In fact, I hardly see how it affects you at all...
I've told you this before. Your problem is that your tests are tightly coupled to the implementation of what they are testing. Your app does not need to be as complex as it is... A good test suite could help you battle against this fact, but if behavior preserving modifications (a.k.a. refactorings) cannot take place without breaking tests everywhere, then even an automated tool won't help you. Tests are the first weapon in the battle to control complexity, and at CDD they are not being used to their full potential. Decouple testing logic from the internals of your system, and you'll have an easier time. An app the scale of CDD is a very tractable problem.
It's always the same with these new whiz bang neat-o newcomers.
The first 60% of the project - errr I meant professional projects, not some college project - come together in a snap.
The last 40% are a joke and the pro programmer is slashing his wrist wondering why he ever started working with the piece of crap language.
Get burned like this a few time and you'll leave major projects to mature languages, and only use the toys for little projects.
Is the problem that you are not building levels of abstraction higher than what Rails gives you?
Rails deals with complexity by metaprogramming and building new "language extensions" to support ORM and web application control flow. If you work only with the abstractions Rails gives you then you're writing your app in terms of ORM and web application control flow, not in terms of your application's domain itself.
Could you use Rails' techniques to build high-level Ruby dialect that lets you write much less code to describe your application logic?
As the consultant quoted in the post, I should say that I do not think the complexity is too much for ruby or rails.
I attribute the complexity partly to the legacy Java version of the application you inherited and are quite rightly and successfully pounding into non-existence, and partly to the inherent nature of the scientific problem domain. The latter is mostly unavoidable (but you are doing the right thing by leaning on established Java tools via rjb to do the heavy lifting), and the former I have watched crumbling away in the past months.
I do agree with Nathan Sobo on the mockist vs classicist testing however. There is complexity in the application and complexity in the engineering process and I personally find the process complexity more worrisome, which has nothing to do with the language choice.
Crap it is you say. If you cant refactor without you "tools" you can't refactor. If you can't write good tests you can refactor. Refactoring is about small steps, testing is about small steps, if you need an IDE to help you do big jumps, you are just doing it all wrong.