6 ms·
Why Ruby is not my favorite language
- charlesju 18y agoSo what's the alternative?
- mdasen 18y agoWell, the alternative could be more like Python. Python supports both object methods and functions. Ruby only supports object methods. However, Ruby does allow you to define methods outside of an object - these become methods of the Object class. As such, any methods defined like functions become changes to all objects since they inherit from Object. Python is also very explicit about its namespacing and imports. In Python, you should always be able to know where any name you're using is coming from. In the example from the article, 'to_yaml' is added by requiring rubygems. That isn't so apparent (in the way that 'gem' being added by requiring rubygems would be apparent). Names are reused all the time. Names sometimes aren't related to their package in an apparent way. With Python, you have three options (one of which Python programmers will flog you for): from package import name, name2 import package from package import * -- should really only be used in an interactive python shell and not in programs In the first one, you could then call name(something) or name2(something). BUT you can see exactly where those names are coming from -- package. Unlike to_yaml which could come from wherever, it's explicit that it comes from 'package'. In the second one, you can do package.name(something) and the like. Similarly, you can see that it comes from 'package'. Ruby is really flexible, but I would argue that the author is correct in assessing that the ability to modify all objects implicitly is a bad thing.
- timr 18y agoAlso, information hiding is rumored to be important in real software. Ruby gives you the ability to nominally "hide" data, but it's trivially easy for any later programmer to violate the encapsulation. It's DHINO programming -- Data Hiding In Name Only. Not only isn't this considered a bad idea in the Ruby world, but it's actually a common technique. Use a third-party library, and you may well be re-writing core parts of the language. Sound good? You can't prevent it. I like parts of Ruby; it's a fun language. But the author is right -- it's not a language for large projects, or projects with more than a few programmers. My alternative to Ruby would allow the fast-and-loose stuff that makes Ruby fun, but also give you a way to make classes immutable and guarantee data-hiding and encapsulation when you need to do real software engineering.
- davidw 18y agoI don't like the "real software engineering is big heavy Java projects" thing (aka "bondage and discipline"). Plenty of "real software engineering" has been done to great effect with dynamic languages. Here's a random idea: rather than strict locks, perhaps transparency would be a good approach. Load up a third party library, and you get informed that it's fiddling with things, and can then find out what. Maybe it really does need to fiddle with things. Or maybe in a given situation, fiddling with things is the most efficient way of accomplishing something.
- aaronblohowiak 18y agoYea, it is fairly trivial to enable logging every time a method is overridden or added to any class in ruby. Dynamic code inspection like in JavaScript would be pretty cool, too.
- timr 18y ago"rather than strict locks, perhaps transparency would be a good approach" Transparency is a great, but you still need rules when you're working with any code that's bigger than what you can hold in your head at any given time. Doubly so when you're working with a team. Programming in a team is hard in the same way that taking care of a room full of toddlers is hard -- obviously, you want everything out in the open, but you also want to hide the sharp objects, put caps over things that can shock, and otherwise make the big, transparent room as soft and bouncy as possible. You need locks on the cabinets full of poisonous chemicals. Obviously, the locks need to be open-able, but only in special situations, and certainly not by nosy toddlers. (Before you criticize me for being paternalistic, realize that I include myself in the "toddler" category. I much prefer code that's written in a defensive style, because it's easier for me to maintain later on -- and that's where any programmer spends the majority of his time. I've developed this attitude because I know that I'm stupid, not because I'm arrogant.)
- Xichekolas 18y agoWhile I agree that writing code defensively is the way to go when a team is involved and/or you plan to have to maintain the code for years, I don't think it's the language's job to take away all the 'sharp objects'. Programmers should be smart enough to know what is sharp and how to avoid it when needed, and they should collaborate enough that no one can sneak through sloppy code. I'd rather have the ability to do certain things and rarely use it than not have the ability at all. If other programmers are constantly doing really dumb things, don't use their code in your projects.
- siong1987 18y agoDon't care about the alternative. Just use whatever you are good at. Don't get into this endless programming languages war.
- bluishgreen 18y agoNo, its not an endless war. Use Python.
- mechanical_fish 18y agoIs there a tool here, begging to be written? Why can't I point to a Ruby object and ask it "Hey, where did that method come from? Which file/method/object defined that? Which were the last three files/methods/objects to redefine that?" Obviously, you wouldn't want to enable this feature on a production server. But it might be a useful debugging tool. Worth a try, anyway. Such a thing would only help in tracking down problems. It wouldn't resolve the larger problems of, e.g., namespace collision. ("Oops, library foo and library bar both tried to define an Object.stupify() method!"), though it might make such issues easier to detect. And it would be quite easy to write perverse programs that would defeat my proposed debugger thingy, or even cause it to melt. ("My program uses singletons to dynamically redefine methods on other singletons.") But you could perhaps mitigate the latter by restricting this tool to monitoring Ruby's built in classes, and/or whatever classes the user specifically chooses to aim it at. Moreover, if a piece of Ruby code did cause the metaprogramming-tracker to dump core, that fact might serve as a valuable code smell of its own.
- ruby_roo 18y agoHeh. Oddly, the solution to convoluted monkeypatching might be monkeypatching itself. Any reason why you couldn't extend the Object class to have this self-knowledge? Or couldn't a library be required at program start that works like Perl's 'use strict;', keeping you on the straight and narrow and not falling into the tempting trap of extending classes when you shouldn't be?
- mechanical_fish 18y agothe solution to convoluted monkeypatching might be monkeypatching itself Yes, the very same thought occurred to me. Set a monkey to catch a monkey! I didn't suggest it myself, because I've been away from Ruby just long enough that I didn't remember whether one could accomplish this in pure Ruby, or if one would have to ascend up a level and do it in the interpreter.
- catch23 18y agoyeah, it's possible in pure ruby. You can do stuff to prevent monkey patching, as well as do stuff to make it easier for future monkey patchers. I prefer libraries to not do either, to make code easier to use.
- deleted 18y ago[deleted]
- lsb 18y agoIt's a fundamental problem of language design. In Lisp, extending the built-in functions is trivial, so lots of people built Lisp up into the language to solve their problem in, and Ruby makes it easy to do the same. Rails is extends the language, and some people like it. Even the JSON gem does -- when you do "require 'json'", you give arrays the power to convert themselves to json strings. Ruby lets you convert arrays to Ruby-evallable strings, so it's natural to convert them to JSON-parseable strings. So, do you do what Java does, in making the String class final? Languages only exist for people who speak them, so you need to gauge the social aspects whenever you choose a language. Perhaps Java means that your bozo coworker won't trample your toes. Perhaps Haskell means that you can import just as much as you want. That's ultimately your call. There are lots of valid complaints about Ruby 1.8: the syntax can be baroque, the scoping rules have too many gotchas, they're (thinking of) taking out continuations in the next version, the VM is dog-slow. But 200 methods on an object is small fries in comparison.
- blasdel 18y agoI had a great question in a job interview yesterday: "What do you like least about your least favorite programming language?". I picked Ruby as my least favorite, as there's not many languages out there that undermine themselves so totally (I may not want to program in basic, but it does what it says on the tin). Here's my answer: Matz's decision-making process He tries to make Ruby be all things to all people Lots of confusing sugar and overloading baked in I much prefer Guido's hard pragmatism The panoply of function types: Methods, Blocks, Procs, Lambdas All intertwined and yielding into one another. I love that in Python there is only one: Objects with a __call__ method, defined metacircularly. The culture of adding/overloading methods on base classes Many gems do this en masse, and there are a lot of low-quality gems Especially disastrous because it's unscoped, and infects the whole process For a language with four scoping sigils it sure screws up scope a lot The Matz Ruby Implementation The opposite of turtles-all-the-way-down (Smalltalk crushed beneath Perl) It punishes you for taking advantage of Ruby's strengths The standard library is written almost entirely in C It doesn't use Ruby message dispatch to call other C code. That means that if you overload a built-in, other built-ins won't use it Anything fiddly that's not written in C will be dog slow
- mhartl 18y agoI had a great question in a job interview yesterday For what it's worth, this has recently become a 'standard' interview question for developers. I predict that people will start game it by having a canned response, thereby rendering it virtually useless---just like all other standard interview questions.
- blasdel 18y agoHilariously, I had already written an answer to the preceding question: "What do you like least about your favorite programming language?" for an email to someone else just a day earlier. Granted it's still a terrific question -- expository about the applicant, and easy to banter about to detect bullshit / plagiarism.
- jamesbritt 18y ago
- ruby_roo 18y agoSo there's this Ruby tool called RDoc that will introspect your project and tell you all about what's inside. Problem solved? Here, look at RDoc's features (from the RDoc website): --Generates structured HTML documentation from Ruby source. --Authomatically extracts class, module, method, and attribute definitions. These can be annonated using inline comments. --Analyzes method visibility. --Handles aliasing. --Uses non-intrusive and implicit markup in the comments. --Readers of the original source needn't know that it is marked up at all. Or to come at this from a slightly different angle, don't Ruby's introspection powers provide a release valve for the problems the author is talking about? Anyway, this is just another occasion to state the old adage, "With great power comes great responsibility." You don't have to crapify your Ruby projects if you don't want to. If you need to enforce clarity at all times, I see no better alternative than Python (which I think makes it a better candidate for scientific or math-intensive projects, MRI slowness aside [although I am curious about the implications of genetic algorithms + Ruby introspection]). I do speculate that if you take two programmers of equal skill levels and give one Python and the other Ruby, the Rubyist can gain a productivity advantage over the Pythonista via judicious use of Ruby hackery. But this comes at a cost: it does require more thoughtfulness before execution. Maybe you don't want to think that hard, and that's a totally legitimate and respectable position. In the end, which of the two languages you choose will probably have more to do with personal workflow preferences or project management ideologies. In the case of Rails, yes, it hacks in a DSL and extends Ruby classes, but Rails relies heavily on conventions and things being put in designated areas. It's therefore hard to get lost in a Rails project unless you really have no respect for the conventions (in which case, it doesn't matter what language or framework you're using).
- Tichy 18y agoI wonder how much of the monkey patching is really necessary? Recently I have looked at Rails again, and in prototype (Javascript) "function" is monkey patched to have a bind method, so you can write function.bind(object). In Mochikit you have a method bind(function, object). It is not even longer to type. Mochikit is not monkey patched - although admittedly "bind" is in the global scope. Mochikit can prevent the global scope optionally, though. That is just one example, but I suppose it is more attitude than necessity that makes the difference here...
- KirinDave 18y agoThis argument is totally spurious. You can find terrible, brain-bending libraries in every language. Why is ruby a write-off because of ActiveRecord? Seems like the implicit argument is that Root-Object modifications are unmaintainable. But the reality is that assertion really isn't backed up anywhere. There are lots of valid complaints against Ruby. This is not one of them.
- deleted 18y ago[deleted]
- Locke 18y agoAnother (old?) rant about open classes aka "monkey patching". There's a lot of fear and hand wringing over open classes. It's certainly a language feature that can be abused, but it's also incredibly useful. There are things you can do to be safe: Check for the existence of methods before adding them. Don't overwrite existing standard lib methods. If you do overwrite one, alias it, call the alias from your replacement which should add something without noticeably changing the original behavior. If you write unit tests, it shouldn't be too difficult to detect that a library you depend on has changed the behavior of a standard method in an unacceptable way. I've encountered collisions like this, maybe, a handful of times and each time finding and resolving the problem was not difficult. I've been writing ruby software for several years now, and there are definitely libraries that annoy me (ahem activesupport), but the utility of having open classes has far outweighed any of the negatives. Let's face it, in any programming ecology there are going to be some awful libraries. Bad programmers don't need open classes to do damage.