Slashdot Mirror


Optimizing Development For Fun

chromatic writes "Geoff Broadwell has written an analysis of optimizing an open source project for fun, specifically the Pugs project. Broadwell argues that making development fun and easy leads to higher quality code and a faster velocity of development, even when implementing a frivolous project (a toy Perl 6 interpreter) in an uncommon language (Haskell). The Pugs leader, Autrijus Tang, will speak about both Pugs and Haskell at EuroOSCON."

9 of 144 comments (clear)

  1. Here's a MIRROR of the article before site crashed by Hot+Grits · · Score: 0, Informative

    Every project has a set of goals that guide it through the meandering path of development. For some projects, these goals are unspoken, seen only in the primary style of the code, or in the size and shape of its APIs. When Autrijus Tang started the Pugs project to create a Perl 6 compiler, he had an explicit goal: optimize for fun. Fondly referred to as -Ofun -- a typical compiler writer's joke, referring to the standard -O flag used to tell a compiler what its primary optimization goal should be -- optimizing for fun is probably the most important decision Autrijus made. Optimizing for fun has had tremendous benefits. In just 8 months, the Pugs project has gained well over 100 committers, averaging about 30 commits a day for the life of the project. Unlike many projects, these commits do not all come from a handful of people. In fact, the 3 busiest developers can only claim about half the commits; the rest are well spread, with 50% of the developers able to claim 9 or more, 25% having 24 or more, and 10% having over 150 commits each! The team is not just productive, it's also creative. Starting with just a single interpreted backend written in Haskell, Pugs has added compiled backends for JavaScript, Parrot, and Perl 5. Dozens of modules have been written or ported, ranging from encryption algorithms to IRC bots. Various developers have experimented with concepts ranging from continuations and coroutines to self-referential preludes and efficient type inferrence, with working code often leading the official specs. Of course, this should come as no surprise. As any cognitive science expert will tell you, fun is a great way to focus the mind. Developers that aren't enjoying themselves will slow down, write buggy code, make poor decisions, and eventually leave the project (even one that pays). Conversely, rampant fun will bring coders in droves, and give them a passion for their work that shows in quality, quantity, and goodwill. It's a pretty good bet that optimizing for fun will produce a better product than almost any other method. So what's Autrijus's secret for -Ofun? As he puts it, "the essence of fun boils down to instant gratification and a sense of wonder and discovery." Or as chromatic calls it, imagineering. It turns out there's quite a bit that goes into that: * Make -Ofun your primary goal (there can be only one). Next time you're forced to come up with a vision or mission statement, try that one on for size. (If management agrees, you've chosen a good place to work.) Every other goal chosen for the project should either flow from that one, or be secondary to it. * Use modern, decentralized version control. If you're not already using a version control system, shame on you. If you are still using an old system such as CVS, RCS, or SourceSafe, you're really missing out. Modern systems offer atomic changesets (so all edits relating to a single conceptual change can be captured together), full versioning of directories and symbolic links (so that files can be moved, copied, or renamed and still maintain full history), fast tags and branches, and more. Most important, modern version control systems offer decentralized, offline operation. Every developer can keep a local copy of the repository on their laptop, editing and committing locally to their heart's content, even when network access is unavailable. When ready for a merge, the developer can push changes to other developers or to a central "master" repository. Some systems, such as darcs and the git family are decentralized at their core; the excellent SVK client layers decentralization on top of a modern centralized system, Subversion. * Embrace anarchy. One of the key realizations of modern Internet projects (the oft-quoted Web 2.0) is that on the whole, your users can be trusted. The key is that the users also need to have the tools needed to repair any damage the tiny minority may cause. For a development project, modern version control systems can give you "anarchy with an audit trail". If something does go wrong (intentionally or more l

  2. Re:Want to make dev fun? by Eil · · Score: 4, Informative


    Mainly, Python is powerful but has a deliberately shallow learning-curve. The most often-cited reasons are the following Python mantras:

    - Everything is an object
    - Syntax is simple and predictable (but feels a little odd if you're coming from C, C++, Perl, Java, etc)
    - There's one obvious way to do it. (Contrast with Perl's, "There's more than one way to do it.")
    - Batteries included (comes with a large library of modules)

    Pretty sure there are more, but these are the biggies that I can recall. These are the same reasons that many quote for using Ruby as well, but I got around to trying it yet.

    I used to be a big fan of Tcl for it's insanely shallow learning curve. (Even more so than Python.) I wrote a usuable Tk (GUI) app within the first hour of even hearing about it. Too bad it didn't really catch on and mature as well as Python and Perl did over the same time-frame because it really is a nifty language.

  3. Pugs 6.2.10 has just been released. :-) by autrijus · · Score: 4, Informative
    I am delighted to announce Pugs 6.2.10, released during a slashdotting on geoffb's "Optimizing for Fun" column:

    http://developers.slashdot.org/article.pl?sid=05/1 0/09/1831219

    The release tarball will be available from CPAN shortly:

    http://pugscode.org/dist/Perl6-Pugs-6.2.10.tar.gz
    SIZE = 2394516
    SHA1 = 3d8669fdccc3616c99cdde68659759b8b5782859

    With two months of development, this release features more tightly integrated JavaScript and Perl5 code generator backends, a library interface to the Pugs system via support for the Haskell Cabal frameworks, as well as many new tests.

    After the release, the push toward 6.28.0 will begin in earnest, with the newly specified container model and object model integrated back to the main runtime, fleshing out support for the remaining OO features.

    Again, thanks to all the lambdacamels for building this new ship with me. :)

    Enjoy!
    /Autrijus/

    Changes for 6.2.10 (r7520) - Oct 10, 2005

    Feature Changes

    Shared components

    • Support for the Haskell Cabal framework, exposing Pugs as a library to other Haskell users, paving the way for use in IDEs, as well as future Inline::Pugs and Inline::GHC modules
    • Adopted the code convention of expanding literal tab chars to spaces
    • JavaScript backend can be invoked with pugs -B JS
    • Perl 5 backend can be invoked with pugs -B Perl5
    • Pugs will now compile version ranges in use/require statements
    • Significant backend enhancements; see below
    • $?PUGS_BACKEND can be used to tell which runtime is in use
    • exec emulated partially on Win32

    JavaScript backend

    • Passes 91% of the main test suite including TODO failures
    • Integrated with MetaModel 1.0
    • Faster code generation, taking advantage of -CPerl5 output.
    • Switched to continuation passing style CPS to properly support return, ?CALLER_CONTINUATION, coroutines, and sleep
    • Improved support for binding and autodereferentiation
    • Initial support for multi subs
    • Initial support for symbolic dereferentiation
    • List construction no longer creates new containers
    • Miscellaneous performance improvements
    • Named-only arguments +$x and ++$x cant be passed positionally anymore
    • Parts of the Prelude can be written in Perl 5 now to improve performance
    • Perl 5-like regular expressions mostly working
    • Proper UTF-8 handling
    • Support for monkey-but $foo but {...}
    • Support for $CALLER:: and $OUTER::
    • Support for lazy {...} blocks for delayed evaluation
    • Support for temp and let declarations
    • Support for array and hash autovivification
    • Support for array and hash slices
    • Support for evaluating expressions in the PIL2JS shell :e <exp>
    • Support for junctions
    • Support for loading JSAN modules by using use jsan:Module.Name
    • Support for lvalue subroutines foo = ...
    • Support for slurpy hashes in subroutine signatures
    • Support for the Proxy class not yet user-visible
    • Support for the eqv operator
    • Using for with only one element to loop over works now
    • int works correctly on special values like Inf or NaN now
    • substr returns a r/w proxy: substr$str, $pos, $len = $replacement

    Perl 5 backend

    • Passes 33% of the main test suite including TODO failure
  4. That's mistitled by Estanislao+Mart�nez · · Score: 3, Informative

    That shouldn't be called "Avoid Recusion," because you're not really avoiding recursion. What you're doing (as the wiki itself explains) is abstracting it into a higher-order function. Still a pretty damn important technique that one should master in functional languages--recognizing the "shape" of a loop (is it a map? a left or right fold? an unfold?), and implementing the looping logic as a higher-order function separately from its specific uses.

  5. Re:It's not frivolous by chromatic · · Score: 2, Informative

    I meant that Pugs started as a frivolous project in the same sense that the Linux kernel started as a frivolous project and as much as any learning experience refactorable into useful, non-frivolous code is frivolous.

    I'm not sure when Autrijus realized what he had, but I'm sure he didn't intend to write a full-fledged Perl 6 implementation with pluggable backends targeting Perl 5, Parrot, the JVM, and JavaScript, at least not at first.

  6. Re:Let's run with this idea a little by qbwiz · · Score: 2, Informative

    I think that that's where the unit tests come in. If something doesn't compile, or it doesn't pass the unit tests, then it cannot be checked in. There could also be known-good checkpoints, which enable users and possibly even developers to work on something that should work.

    --
    Ewige Blumenkraft.
  7. Re:Want to make dev fun? by jma05 · · Score: 2, Informative

    All good. But don't get confused between static and strong typing. Python is dynamically and strongly typed, not weakly typed.

  8. Re:Want to make dev fun? by jonastullus · · Score: 2, Informative

    EXAMPLE:

    def test(arr = []):
        return arr

    t = test()
    t.extend(["hello", "world"])

    u = test()
    print u

    RESULT:

    $ ./test.py
    hello
    hello hello

    REASON:

    the default value expression is evaluated once, when the function
    object is created, and the resulting object is bound to the argument.

    FIX / WORKAROUND:

    if you want to create a new object on every call, you have to do
    that yourself:

    def __init__( self, myList=None):
        if myList is None:
            myList = [] # create a new list
        self.myList = myList

  9. Re:Want to make dev fun? by jonastullus · · Score: 2, Informative

    *darn*, i totally bogged up the result:

    RESULT:

    $ ./test.py
    > ["hello", "world"]