Dynamic languages work closer to how you design software

Some people I talk to have struggled with the usefulness of a dynamic language such as IronPython. To understand why dynamic languages are faster to develop in, let’s take a look at how developers design. Robert Glass, in his article The Cognitive View: A Different Look at Software Design, references studies that show that:

designers, mentally and at lightning speed, were doing the following things:

  1. They constructed a mental model of a proposed solution to the problem.
  2. They mentally executed the model—in essence, running a simulation on the model—to see if it solved the problem.
  3. When they found that it didn’t (usually because it was too simple), they played the inadequate model back against those parts of the problem to see where it failed, and enhanced the model in those areas.
  4. They repeated steps 1-3 until they had a model that appeared to solve the problem.

Now, look at what Benjamin Pollack does when using what he calls REPL in Smalltalk:

    1. Add or modify a few methods in a couple of classes
    2. Open up a Workspace (Smalltalk’s REPL) and print out the results of some arbitrary code that tests what you just wrote
    3. If you hit a bug, you can easily inspect any value in the entire system to find the error
    4. Once you find it, make the change, massage any “damaged” data back to pristine state by hand using the Workspace, and then resume execution where the breakpoint happened to see whether your fix worked
    5. Repeat

If you map steps 3 and 4 in the second list to step 3 in the first list, they are almost identical!

So developing in a dynamic language (or at least a well-constructed dynamic language) works closer to how you think. And since the essence of software development is design, removing artificial barriers to understanding helps you develop faster and/or with higher quality.

I’m not advocating throwing away .NET or Java, but for solving business problems, when I want to focus on the domain problem and not the implementation in curly braces, End If’s, or angle brackets, dynamic languages are a (good) answer.

This entry was posted in .NET, Agile, Python. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

18 Responses to Dynamic languages work closer to how you design software

  1. Ok Scott, I’ll send you back your decoder ring… but not before I make a copy and send you the original one back! Or did I send you the copy?

  2. Darrell,

    I used to think you were my friend. We hung out on line. We drank at Tech-Ed. We made plans to visit each other. Now I read that you’re dabbling in the mantic arts. I don’t think I can be your friend anymore. You’ve upset the apple cart with your heretic ideas and you’re dragging skeletons out of the closet that should have remained buried. I don’t know why you can’t just let sleeping dogs lie. Software development is much than just challenging people’s ideas, you know. Many of us are trying to live nice, peaceful lives without having to think all the time. Just lay off man. And I want my Spiderman decoder ring back. I would only have given it to a true pal.

  3. Isaac Gouy says:

    “My whole point… was to show how you could use a dynamic language to prototype…”

    To paraphrase, what you actually show is: ‘developing with a REPL (or at least a well-constructed REPL) works closer to how you think’

    You’re conflating IDE capability (REPL) with dynamic type-checking.

    Believe me, working with Smalltalk in Notepad sucks big!

  4. Isaac – You can use NUnit and TDD. TDD is a way of codifying your mental model about how something should work. The first list was a general “how developers design” list.

    My whole point with Benjamin Pollack’s list was to show how you could use a dynamic language to prototype your understanding of a problem domain without getting to far into the implementation details.

  5. Isaac Gouy says:

    And back to Benjamin Pollack, the next day we find that he simply didn’t know how to use the IDE…

    “Firstly, thanks to the numerous people (including Joel) who pointed out that VisualStudio.NET does support fix-and-continue for C/C++ and has since Visual C++ 6. Oops.”


  6. Isaac Gouy says:

    “map steps 3 and 4 in the second list”
    Why wouldn’t we be using SUnit and TDD?

    Seems like you’ve slipped back to the bad-ole days of code-and-fix.

  7. Isaac Gouy says:

    Here’s REPL for Java:
    DrJava: Using the Interactions Pane

    Here’s REPL for OCaml
    The Objective Caml interactive toplevel

  8. Darrell says:

    IDE features can be incorporated even in dynamically typed languages using a process known as type inference. Anders H. has been talking about the possibility of including it in C# 3.0 (the next next version :) and I for one think it would be a great step.

  9. Scott says:

    Darren O: “Intellisense… > sliced bread …” etc…

    Darren, I think you’re confusing IDE features with language features. I have “intellisense” in Xcode when I’m writing Objective C code for OS X and Objective C is a dynamic dispatch/typing language. The Ruby interpreter has a “check syntax” swtich, basically a compiler, that will catch your syntax errors. I can’t speak about Python as I haven’t used it. Ruby also has an interactive shell, which lets you play with the objects, reflect over them, in a similar manner to the Smalltalk environment. That’s much better than intellisense.

    “if it compiles, it will never fail” – HOO BOY, if you can make that statement, you should probably be asking for more money than you currently are. There are a lot of errors that only show up at runtime, even in statically typed languages. If you are using a compiler to catch your syntax errors (besides spelling errors, our people are renowned for spelling errors), you need to know the language better.

    “And it will never have to be changed” – So are you saying dynamic code changes spontaneously? ;) Method signatures magically gain more parameters? Strings no longer accept chars in their arrays? The bottom line, for me at least, is that dynamic, message based languages make it much easier for me to write programs. Why do I care if the actual type of the object I’m passing in is an “Employee” or a “User” if all I’m doing is calling “toString()”

  10. Darren Oakey says:

    Darrell – sorry – I tend to be an absoluteist with my language, and come out sounding more extreme than I actually mean..
    I guess all I was trying to get at was that I didn’t agree with that picture of design – I do believe in – as you say, component orientated development.

    Instead of doing
    “what do you want”
    “build a crappy version as quickly as possible”
    while true
    “tweak it”

    I’d rather -

    “have a vague idea of what you want”
    while true
    pick the tiniest and best defined piece of it
    build it
    bulletproof it
    deliver it

    Mainly because I’ve never in my commercial life worked on a project where there was only one developer – in fact most of the time I’m working on projects where I haven’t met most of the people writing other parts of the system – I don’t know how good or bad they are, and the only way I’ve found of making sure my stuff doesn’t get blamed for something is to put iron walls around it.

    With the confusion between dynamic/compiled or static/strong – because it wasn’t the main part of what I was saying, I sort of glossed over the whole dynamic/compiled issues –

    there are a few – starting with the ability to hide the code – I think people underrate the benefits of a “black box”. I think there is a lot of value to having to code things with access only to the interface, not to the internal workings. If people know the internal workings of something – without fail, they will rely on something in there – and that’s not guaranteed not to change.

    Also, compiler protection – yes, people can get around it – but they have to explicitly do it. There are times for that – but people have been forced to think about what they are doing, and if it screws up, it’s there fault – at least the compiler warns them.

    most importantly, and this is going to sound silly – but I think people underrate the value of intellisense. I believe VS or Eclipse intellisense improves my speed of development by something like a factor of 5. In Ruby, when I’m using an unfamiliar class library, I’m spending ages wandering through poorly written documentation. In C#, if I have to use a class which was just written by someone else, it’s easy – I hit “.” – up comes a list of methods – I pick the one that looks right, hit “(” and see a list of parameters – “oh – I need one of those” – I create one of those in a similar way, move on to the next parameter, and I’m done. It’s not a little thing – an “aid” – it’s truly a fundamental different level in programming – and it’s very difficult to do in the traditonal dynamic languages.

    but as for actually enforcing stuff at compile time – I’m not saying that you get no bugs, but more and more often we make components that work 100% the first time they compile, and go for years without ever having a bug – it’s becoming the norm – not the exception. Let me give you an example –

    we built a plugin system that worked on reflection and types to find the appropriate display for various objects. Suppose someone else has made a new employee class – I have a list, and want to display the object.

    I throw in a line
    ShowObjectToUser( _list.selectedItem );

    yay – it works, I’m showing up a generic screen which dumps the contents of the object. But what if I want a custom display of it? I make a new user control, and go

    public class EmployeeDisplay : UserControl, IPluginDisplay
    … generated stuff…

    I got most of the above by hitting control space and picking from a list – I click on the interface and get the stub generated:

    void IPluginDisplay.Show( Employee value )


    I add a two ValueDisplays and a ShortAddressDisplay to the designer, title them all and then add the lines

    if (value == null)
    _firstName.text = Safe( value.FirstName );
    _lastName.text = Safe( value.LastName );
    if (value.AddressList.Contains( AddressType.Primary))
    _addressDisplay.Value = value.AddressList[ AddressType.Primary];

    All of the above I got from intellisense menus – I have probably never seen this object before.

    but once that compiles – I’ve added a new object to the system. Every list, every display where that object is used now uses my new component.

    And I guarantee you – even though I just wrote it while I was typing this – if it compiles, it will never fail. For any reason. And it will never have to be changed, unless the actual business requirements of what need to be shown change.

    This is what the compiler guarantees. It guarantees to me that if the person who created the employee class decides to change “LastName” to “Surname” – they also have to fix the component. This is what dynamic languages can’t give you…

    and it all comes down to the design. Compiled languages give you the ability to _safely_ design a tiny piece of the puzzle, and be completely confident that you don’t even have to think about any other part of the puzzle – it’s all just going to “work” when we put it all together.

  11. Darren – you’re confusing strong and weak typing with dynamic and compile-time typing. Python IS strongly typed, but it’s dynamic typing.

    In any compiled language I can force dynamic typing. I can cast objects to other types and I can even create objects at run-time using reflection. So I should never use any of that according to your design philosophy? In that case NUnit should not even exist!

    And according to your comment, a compiler solves all problems? So you’ve never written a bug in a compiled program, only in Ruby? That’s hard to believe. In fact, I think it’s garbage (to quote your blog post about this). But that’s picking on just a small part of your argument.

    I’m all for contracts, but I don’t think trying to enforce everything at compile-time is the way to go. Plus what you are talking about sounds more like component-oriented programming, which was not the point of this blog post. This was more focused at understanding a small problem domain as quickly as possible. I think that prototyping to understand a given problem domain is a valuable exercise, and one which is better done in an interpreted language than in a compiled one.

    And finally I did say in a comment that I would probably then write the resulting solution in .NET. Python already offers some plugins that generate Java or C code, so .NET might not be far off. But the reason all those programs are written in compiled languages is performance, which I was also not addressing in this post. In fact most of those apps aren’t even written in managed languages (such as .NET or Java) for performance reasons. As managed languages become faster, more programs will be written in them. And the same for interpreted languages.

  12. Dave says:

    Darren certainly hit the nail on the head with regards to strong typing:

    “Failing at runtime isn’t good enough.”

    I would go a step further and say that failing at runtime is not acceptable, especially if you could have easily caught the bug at compile time.

    Remember, the compiler is your friend :-)

  13. Darren Oakey says:

    I would disagree with this post.

    I think a lot of people when they are talking about software “design” simplify things too much, by taking out the only two elements that really matter, which are:

    * when you start any real software project, you only have knowledge of less than 1% of the eventual requirements

    * Most real software projects are too big for a single person to have a handle on the whole project

    So – what does that mean in practice? It means that you never get to design a “System”, you are always designing a tiny piece of the system.

    now, for an experienced programmer, and with the power of tools these days, programming a component is easy – you see the problem, you build your tests, your objects – and it works. Software has matured to that point – we aren’t “debugging” any more – work first time is the norm.

    ALL of the difficulty comes with the “others” – ie who do I have to communicate with, the “past” – I have to build on this legacy code, or whatever… and most importantly the “future”

    ie – how do I guarantee that when I leave, or it’s handed to the maintenance group, or when someone else in the development team who I’ve never met picks it up and uses it, without reading a single word of the code documentation (which I haven’t [and never will] had time to write yet) or the source code (which they don’t have access to)…

    How do I guarantee it will never fail?

    There is only one way I know of – CONTRACTS. You put a big line around what you are doing. You say you can give me one of these, that fulfils this this and this… and I will give you back one of these, and this this and this will have been done.

    And I promise that it will never fail.

    And there’s only one good way of doing that. Compiler upheld strong typing. Failing at runtime isn’t good enough.

    In summary:

    * Good “traditonal” system design up front is pointless and impossible.

    * Building lots of little single-purpose unbreakable pieces always results in an almost optimal system design, and removes most of the risk associated with the system.

    * The only reliable way of building a solid component is to have an agreed contract, and if you have a contract, it should be ENFORCED – (by a compiler?)

    dynamic languages are FUN – hey I truly LOVE Ruby – it’s a beautiful language. But there is a very good reason why 99.9999% of the good programs of the world (Photoshop, Word etc) are written in strongly typed, compiled languages.

  14. Dave says:

    If dynamic languages such as IronPython help to facilitate design, then I’m all for it. That certainly seems to be very worthwhile, especially from a POC standpoint.

  15. Dave – I personally would write in IronPython because it’s closer to the problem domain. I have to spend less time fiddling around with stuff.

    If I need to iterate over something, I just put it in a list and I have a strongly typed collection already! I don’t need to setup something using generics (which isn’t too bad), or if I’m using .NET 1.1, I’ll be putzing around with collections and all sorts of non-domain-related problems. Even with Resharper or CodeRush there’s no way you could implement it as easily as:
    li = [myDomainOject1, myDomainObject2]

    Once the business logic is ironed out, maybe I write it in C# or VB. But at least I can move as fast as I need to when I’m working on the problem.

    Trying to convince someone that hasn’t seen how easy a dynamic language is that’s also a master at a compiled language is very difficult. The objection is always “I can do that faster in C# (VB)!” Well, until you learned C#/VB well enough, you could probably do things in VB6 or ASP faster too! It’s important to separate an individual’s proficiency of a language from the productivity of the language itself FOR A GIVEN DOMAIN. Again, this is why I would probably not do UI work with Python – I think that Windows Forms and ASP.NET are the fastest way to develop UIs. :)

  16. -e says:

    Now you’re talking like a Mort! :)

    I would agree, it does help with the iterative process of problem solving to remove the obstacles that a declarative language provides. I think that’s where Visual Basic shined, and the way a lot of us non-CS developers have managed to enter the ranks.

    The problem I see is that it becomes harder to maintain the code, because when you develop like that, it has a tendency to devolve into hacking away until it works, which is the enemy of maintainability. Or, maybe (ok, definitely) you have more discipline than me, and you can code like that and still have maintainability?

    But for prototyping, it has a lot of merit. Maybe I’ll have to switch gears and instead of putting off learning Ruby, put off learning IronPython instead, since that would allow me to have a prototype closer toward the C# code I would eventually write…

  17. John Wood says:

    >>I don’t think language should ever be a factor in software design as it’s part of the implementation details.<<

    I think his point is that, some languages lend themselves to helping with the design and not just the implementation. When the language constructs (and environment to some degree) match your intention more closely, then they become more a part of the design process than just coding the solution.

    Think of CASE tools for example. There’s still a (declarative) language at the root of that somewhere, yet those are definitely a big part of the design process in some companies.

  18. Dave says:

    Maybe once I put my fingers on the bits I’ll get it because the way I look at it, when I write C# or VB.NET code, I AM focusing on the domain problem and not on curly braces or End If statements. I already know those languages to the point where I rarely need to go look up syntax, thus they now allow me to focus on the business problem at hand.

    As for software design, good designs are language-agnostic. I don’t think language should ever be a factor in software design as it’s part of the implementation details. I can’t imagine being on a project where a design was put forth and then when it came time to decide on a language, the design needs to be modified because of issues with the chosen language.

    And going back to our conversation at TechEd, if a developer is a master in C#, why would he/she write the business logic in IronPython?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>