On 5/3/06, David P. [email protected] wrote:
I am a very, very good programmer. I’ve written more than a dozen
commercial applications including Mesa which was used by Wall Street traders
as part of a automated trading systems.
Commercial software is not necessarily the benchmark of good. This
is not meant to reflect upon your capabilities, but I think it’s sort
of pointless to mention this.
But I used C++ and later Java to help keep order. I used the machine and
the tools to help me do the right thing. After all, if you have tools, why
not use them. I can refactor the Java code using Eclipse because of Java’s
strong typing (e.g., migrating some of the code in Integer to use generics
and enumerations.)
Yes, this helps. It’s too bad we don’t have better refactoring tools
in ruby. But I think a lot of refactoring that is necessary in
Java/C++ etc is not necessary in Ruby.
How do you make a method ‘abstract’ in Ruby? One way would be to just
delete it from the class which things will inherit from. Since the
refactoring patterns seem to be simpler, since the codebase is
substantially smaller, and the time to write this code is far less,
auomated refactoring is less of a life saver. Don’t get me wrong, i’m
not saying it wouldn’t be a great thing… what i am saying is the
time saved by automated tools in Java would be hard to compare with
the time saved by not using Java.
I would never have been able to write Mesa (95%+ of the code base came from
my hands) or Integer (50%+ of the code base came from my hands) if not for
the compiler tools. They helped me write better code.
Is there anything a compiler did that a well written unit test
couldn’t? If so, what features of the compiler tools were most
essential to you?
In the begining, Mesa was all Objective-C. I found it increasingly
difficult to refactor code, etc. without the tools that C++ brought to the
table (if I changed a method name, I’d do a compile and all the places in
the code that called that method would be flagged, etc.)
Sounds like exactly what happens when I change a method name in
Ruport, except it’s my function by function unit tests which do this
for me.
Ruby forces the developer to do more work and think more. This is okay if
you’ve got a small team that has a mind-meld. This is more and more
difficult when you have larger and larger teams. It’s not a question of
dicipline or quality of developers, it’s a question of how much people can
hold in their heads. People can only remember so many naming conventions,
code conventions, etc. Using the machine rather than the developer to deal
with these issues is why we have machines in the first place.
Have you ever worked to implement code based on tests someone else has
written, or to extend code which is covered by another set of tests?
I may have totally missed the boat in Java / C++ as to how a compiler
will save my life here, but I’ll tell you one thing, well written
tests tell me exactly what’s amiss, and they even give me a little
insight into where and why.
It’s great fun to work through the Test First Challenge for ruby (or
the original Java version even ). This might be a good example of how
someone else (or even yourself) can mold an interface and a set of
behaviors before implementation and ensure that the code will conform
to this.
Sorry to go off on you, but your argument is the same argument that people
used to claim that C++ was better because developers managed memory rather
than having the machine manage memory. Machines are better than developers
at managing memory. Machines are better than humans at enforcing rules.
You were right when you said that computers are better than developers
at memory management. Luckily, Ruby is an excellent language as far
as handling dynamic typing, memory allocation, and all these things
that would be scary for us to do by hand… Still, there is a human
component to all of this, and I’ll trust myself to design a better API
than the computer, so a language that doesn’t get in my way when I’m
doing this, is A Good Thing. I also trust that I will understand the
behaviors of my software better than the computer will… this is
where test driven development really shines.
Machines are better at enforcing rules, without a doubt. But machines
cannot understand rules, nor can they change them, nor can they know
when it’s okay to break them. That is uniquely human, and is
important to any creative process.
In the begining of a coding project, it’s better to worry about the thing
one is building rather than worrying about the rules and structures of what
one is coding. But as a project evolves and grows beyond a few people, it’s
better to have the rules by which the code was written included in the
code… not mearly as comments, but as constructs that tools can enforce.
This helps keep everybody in the same dicipline without some stupid
construct like “The Hungarian System” with managers at Microsoft losing
bonus if their developers weren’t writing “Hungarian” code.
Um… unit tests? Functional tests? Acceptance tests?
Guard rails are good. Lines on the road are good. If I was the only driver
on the road and I knew the roads that I was driving or was blazing new
trails… sure… I’d prefer to have fewer obsticles. But once you have
lots of drivers, even excellent drivers, driving over a well defined set of
roads, keeping them driving in harmony is a lot better than letting them go
willy-nilly all over the place.
I don’t know. Nice analogy, but to me, Ruby is not a road, but a wide
open space. When you’re working with wide open spaces, you don’t need
to worry so much about crashing into each other.
Ruby would be better if I could put up guard rails around certain system
features so that one would have to be explicit about using those features (
e.g., the #unsafe block modifier in C#.) Ruby would be better if I could
say, “only the following classes/modules can change the behavior of my
classes” so that some MixIn that I know nothing about changes something in
my code.
Sure, it’d be nice to see stuff like this. But it’s something that’s
secondary to the design goals of the language, and in my experience,
doesn’t come into practical necessity in ruby development. There are
bound to be plenty of edge cases, and for those, things like this
would be nice. But the power of this language is that it doesn’t
get in your way. If you’re not using that power, you might be much
happier in a language with a lot more rules. Some applications really
do need strictness like this, but many others do not.
This is not a binary argument (either Java or Ruby). This is not a “Java is
absolutely better than Ruby” argument. This is a discussion about how to
borrow from other systems to make an excellent system (Ruby) even better for
an important class of developers.
Yes, I think it’s important to find ways for certain applications to
be written ‘safely’ in Ruby, but part of that is changing the way you
think about things when you are working in different languages. What
works for Java is not necessarily good for Ruby. It doesn’t mean that
Java must be used for big applications and Ruby can’t scale… it just
means that you have to design differently when you are using languages
which are very different philosophically.
That’s not a bad thing, and with it in mind, if there are ways to
tighten things up optionally (and I do think that RAA has at least a
few libs that help), I say that’s a great thing.
But it doesn’t mean that the language should be changed to meet these
goals. Ruby’s not broken