Getting Real Review

Posted by Micah Fri, 13 Oct 2006 05:02:00 GMT

This Monday my colleagues and I went to 37 Signals’ Getting Real workshop. Overall I give the workshop a thumbs up. They seem to be a good groups of guys.


from left to right: DHH, Gilberto Medrano, Paul Pagel, Jason Fried, Me

I’ll summarize by saying that the workshop is about how 37 Signals works. How they make decisions, how they build software, how they design software, and how they sell it. They were very candid about everything and that was refreshing.

At the end of it all, my colleagues and I begged the question: what did we learn? We all agreed that we didn’t really learn anything except that our philosophy is very similar theirs. However, there were a few points of contentions.

37 Signals builds their own software and they have a system that suits their purpose perfectly. 8th Light develops software for clients and that means we have to do things differently. One difference was acceptance tests. During the workshop, Gilberto asked what 37 Signals’ opinion was on FIT and acceptance tests. David (DHH) responded by saying that they don’t use or need acceptance tests because acceptance tests can’t capture the design and usability aspects of their software. I actually had this conversation with DHH a year back or so at a Ruby gathering in Chicago and he was of the same opinion. I agreed with him then and agree with him now. If I was building my own software and was essentially my own customer, I wouldn’t use acceptance tests either. But when building software for clients, acceptance tests become a critical tools for communication. Clients have expectations and no matter how many words they use or gestures they make, their intent does not become concrete until you put it down in an executable format. I would not dare to engage in a contract development arrangement with out acceptance tests.

There were a few other strategies that work for 37 Signals but wont work for 8th Light, such as hiring strategies and distributed workforce. Mostly this is based on 8th Light’s apprenticeship model.

If you get the chance to go to their workshop, check it out. And keep your eye on these guys. Their tools are pretty sharp and I trust they’ll impress us plenty more.

Ruby and Human Compilers

Posted by Paul Pagel Tue, 26 Sep 2006 18:38:00 GMT

In Paul Graham’s Book, Hackers and Painters, he talks about patterns and Human Compilers. I started to think about how some traditional Object-Oriented patterns are implemented in different languages. What problems do these patterns solve?


Paul Graham’s human compiler is an interesting concept I would like to explore more with relation to ruby, which is what I have been working in lately. The object-oriented design patterns I have been taught are intended for one reason, to increase productivity. These patterns produce well decoupled, easily testable, clean, and reused code that makes it easier for developers to extend and maintain an application. It is the mind of the developer that produces this compiler to be able to read and interpret these patterns to perform workflow optimizations. When I see a pattern in the code, I can easily navigate the implementation and the problem that it is solving. I can hold the entire context in my mind to work on that piece of code. This human compiler is what allows me to move quickly through an unfamiliar piece of code. Moving to dynamic languages, I see the context I need shrinking in the traditional way, holding onto patterns. So I started to wonder, could we build patterns into the language better, or eliminate the need for them? Are the GOF patterns mostly just a method of satisfying our human compiler for statically typed languages?


I have suspicions that moving to ruby from C++/C#/Java will eliminate the need for many of the design patterns we have coveted in those languages. I would like to explore a few of them to prove this thesis. I want to look at the patterns that have helped make testing/design/decoupling better and see how they are different in ruby. Also, how can we transfer the values behind those patterns? The patterns were all based on good decisions, and can we learn anything from them or should we throw away the thought process that made them necessary?

Lets start by taking the most commonly used pattern, Abstract Server. Writing in C#, I need to create interfaces to make sure I don’t violate the Interface –Segregation Principle and depend on concrete classes. This becomes a big deal in a statically typed language because you don’t want to have to depend on a specific type. However, in ruby, you respond to messages of a class, which don’t care what type the return values are. Also, because it is a compiled language, you don’t want to have to recompile the clients of a class just because the implementation changes. In fact, in ruby, the Interface-Segregation violation goes away since there is no need for explicit interfaces to abstract, rather every class becomes an interface for itself.


Have you ever been working on a java/C++/ C# project and noticed an inheritance hierarchy that makes you twinge? Statically typed languages abuse inheritance by definition. Why do you need interfaces? Shouldn’t an abstraction be one of behavior? In ruby, you send messages to objects, which is the same type of firewall, as each object acts as its own interface. However, since an inheritance tree got there, you need to decouple it since it is growing large and not maintainable. Or have you seen interfaces placed in front of a class for the sole value of abstraction. A good example of this I have seen is with Views in the Model/View/Presenter pattern. Something that looked like this:

public interface ISomeView
{}

public class SomeView : ISomeView
{//some implementation}



This uses the philosophy that the Views need to be decoupled from the Presenters. This is true, but the point of decoupled is missed. Decoupling is a method of using firewalls to hide the implementation of code from its clients (Abstract Server). How does this degenerate do this? It doesn’t. I have seen projects where inheritance is used liberally and there are interfaces for everything. I have also seen projects where inheritance is used conservatively and composition is used for everything, to prevent the formation of highly coupled inheritance trees. Finding the proper balance in static languages is difficult, but it is also a problem that should not exist. In ruby, inheritance is used on a YAGNI basis, as you only use it in the clearest of cases. It makes inheritance a tool to be used rather than monitored for abuses.

In ruby, you only inherit through necessity of behavior rather than clarity for form. Inheritance in most static languages is used as a tool for design patterns to make the code easier to read/work on/maintain for the developers. This is unnecessary in ruby since it is built into the language. Ruby does it instead of your human compiler. Writing beautiful code in java meant making the code clean and decoupled. Inheritance is no longer needed to do that in ruby, as it only serves a utilitarian purpose. Form is just as important in ruby as it is in static languages, it is just expressed without using features meant to serve efficiency purposes.

PreFactoring

Posted by Paul Pagel Sun, 23 Jul 2006 04:46:00 GMT

Prefactoring is when you see a piece of code which the story you are working on which has a refactorings which would make your story easier. I have seen prefactoring to be a dangerous process. On one hand, you save time when you know that this refactorings will need to be done. You are faced with the choice of writing temporary code (in the sense of duplicate then refactor) or refactoring, then writing quality code. The software designer in me always wants to choose the prefactoring solution, since it gets to make code cleaner, remove duplication, and be more efficient. Then I can stand on the mountain top waving my flag.

There are a few problems right off the bat. First, the uber-developer in all of us will refactor as much as we can, therefore refactor based scope creep is bound to show up. I don’t really know how to stay away from scope creep in this manner.

Prefactoring can lead to a version of design up front which is detrimental if you don’t need it. However, sometimes you know up front this design simplification will cut the story time in half. Do you prefactor? What kinds of smells make it ok or terrible to prefactor?

I have tried backing my way in and using test(s) as a life jacket, so once the test passes, the refactoring is done. However, the problem with this is it leaves me with half done refactorings. The code is constantly moving up in quality, however, it might not look it due to the inconsistencies produced by half done refactorings. I generally think of a complete refactorings as something that made my system better in some manner I would like developers who are extending the behavior of the system to use the refactorings as a model.




Do my refactorings make the system easier to extend? Half-factorings don’t, but they do provide a manageable slope moving positive. I don’t have the time to tackle the big refactorings, but I don’t want to leave them unfinished.



Wed, 22 Mar 2006 09:27:50, Uncle Bob, Half-factorings Paul, Keep the code clean! If the tests pass when the refactoring is half-done, then complete the refactoring. If you can’t complete the refactoring in this iteration, then keep putting effort into it during subsequent iterations. Make sure the team knows, so they can put some effort in too.

There are often times when a new story is easier to implement in a structure different from the one that exists. Refactoring (or “pre-factoring”) the system into that new structure to make that story easy to implement is often a good approach. However, leaving the refactoring in a half-finished state is messy.


Wed, 22 Mar 2006 18:30:36, Micah Martin, Prefactor ”’Prefactor”’ - I like that. If I counted all the time I’ve had to delete my prefactored code…. I believe there’s an Big Up Front Designer in all of us. Face it, BDUF is fun! Frequently I look at a prefactoring that I’ve just completed and realize I’ve been BDUFfing. Most of the time I delete it all because it’s too complex and unnecessary.

Sun, 23 Jul 2006 08:14:08, Sebastian Kubeck, BDUF To be honest, I never got BDUF right. Untill today, I need to start over one to four times untill I get what I want. I was convinced that I’m just lacking the skills to get it right the first time. Fortunately, I found out that people that are much smarter and much more experienced than me don’t get it right the first time either.

I learned in school that Mozart just wrote down his music which was already completely finished in his head. I was toled later that this is just another myth about this guy. Beethoven permanetly adapted his works. His handwritings are hard to read because his corrections. Bach adapted his works depending on the number of musiciants he could afford.

Conclusion: If not even the geniuses mentioned above get it right the first time, how should we “ordinary people” should ever be able to do it?

Older posts: 1 2 3 4 5