From: Gregory Brown Date: 2006-05-04T01:36:33+09:00 Subject: Re: Sharp knives and glue On 5/3/06, David Pollak 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 :)