Shrink, Script, Shape

In a recent blog post about null reference exceptions, Don Syme bemoaned the status quo:

Unfortunately a sort of stasis, or lack-of-will seems to be gripping the industry at the moment. People stick with their existing languages, though occasionally make noises about needing non-null types (thus making C# and Java even more complex, when we should be ridding ourselves of this curse altogether).

So why do people stick with their existing languages, and what can we do to increase F# adoption? I think it is useful to start by considering what someone faces when they decide to investigate F#. They will find very useful material online, covering a range of topics, and after a little browsing will find themselves faced with a barrage of concepts:

  • Non-nullability
  • Immutability
  • Expression-oriented programming
  • First class functions
  • Higher order functions
  • Pattern matching
  • Discriminated unions
  • Partial function application
  • Currying
  • Recursion instead of loops
  • Monads

Switch Book Cover
And how do people react when faced with so much information? Switch, a book by Chip and Dan Heath, provides some answers and, as the subtitle suggests, provides ways to tackle this kind of problem. In it the authors make the point that effecting change requires not just rational arguments, but also emotional arguments and adapting the environment of the target audience.

As engineers, we tend to focus on the rational, and therefore often ignore factors that could have a larger impact. Indeed, there are a wealth of good online articles making rational arguments for wider F# adoption, and yet uptake is not as large as we’d like.

Maybe it is time to take a deep breath and dive into the uncomfortable world of emotional arguments and environmental manipulation?

I think there are three concepts from the book that are applicable here:

Shrink the Change

Coaches are masters of shrinking the change. By pushing…to attain a sequence of “small, visible goals”, they build momentum…A small win reduces importance (“this is no big deal”), reduces demands (“that’s all that needs to be done”), and raises perceived skill levels (“I can do at least that”). All three of these factors will tend to make change easier and more self-sustaining.

We need to reduce that mountain of information into a manageable molehill. I think that involves under-playing the host of benefits and instead focussing on just one or two. We can emphasise that first class and higher order functions are at least somewhat familiar via LINQ. And we can tackle just one of the new concepts at a time – perhaps non-nullability because everyone understands the problem and therefore will understand the benefit of eliminating null references.

I’d also suggest further shrinking the change by encouraging people to start with a single component in F# rather than a full system. However, the interop with other languages weakens the non-nullability argument, so we need to be careful.

Script the Critical Moves

Change brings new choices that create uncertainty…that yield decision paralysis…Change begins at the level of individual decisions and behaviours, but that’s a hard place to start because that’s where the friction is. Inertia and decision paralysis will conspire to keep people doing things the old way. To spark movement you need to provide crystal-clear guidance. That’s why scripting is important…

The barrage of concepts listed earlier is what leads to decision fatigue. To prevent this we need to carefully script the exact steps people should take. So, sticking with non-nullability, we need to show exactly how the single component could be developed to avoid null references. And we need to be specific about how to tackle interop with “dirty” code e.g. how to use the interop features in FSharpx to convert nulls to Options.

Shape the Path

…Alternatively, you can simply make the journey easier. Create a steep downhill slope and give them a push. Remove some friction from the trail.

Anything that gets in the way of making a change, even if it only constitutes a small obstacle, will reduce the likelihood of the change being adopted. Therefore anything we can do to remove the obstacles will be beneficial.

A recent InfoQ survey asked the question “why are you not using functional languages?”, and the top two answers are revealing:

  1. Couldn’t find developers (770 votes)
  2. Insufficient tool support (618 votes)

The first reason is a chicken-and-egg situation, so we need to find a way to increase adoption within the developer community – that is the topic of this post. The second reason is more interesting. It specifically mentions automated refactoring support, and that is certainly an area where F# is weak. I’ve heard the (rational) argument that refactoring tools aren’t as important for functional languages, but we need to forget about whether the argument is valid: if there is a perceived tooling problem, then adoption will be adversely affected. This is a case of us failing to “Shape the Path”.

A Crazy Idea

Refactoring tools are extremely hard to write, and require a level of dedicated resource that mean it is unlikely to happen as a spare-time effort, so should we instead start a community-lead fund-raising campaign (Kickstarter?) to pay for the initial development? I can imagine that certain companies would be glad to publicly sponsor such an effort, and that individuals would chip in too.

Summary

In order to increase adoption of F#, we need to make the change seem as small, undaunting and easy as possible. The first two can be tackled through tutorials that focus of explaining, in detail, how to achieve a specific benefit. I think the benefit to address is non-nullability, but I’d be very interested to hear other ideas.

A big hurdle in making adoption as easy as possible is lack of tool support. Here I think the scale of the task means we need a more radical approach. Is there sufficient interest, and is the community large enough, to fund such a project?

14 thoughts on “Shrink, Script, Shape

    • 1. I think the idea *is* to chase molehill after molehill. A series of small, undaunting steps that adopters can complete and see clear benefits will help to build confidence and enthusiasm for tackling subsequent challenges.

      2. Yes, I think the project would have to be open source. The idea would be to fund the initial heavy-lifting to write a viable refactoring engine + basic plugin for, say, Visual Studio that provide a couple of key refactors (rename function + extract function?). This is another example of shrinking the change by reducing the amount of effort required for contributors to get involved.

  1. It seems the idea is to reduce visibility to increase focus on a specific area (molehill) so that obstacles seem more manageable (or maybe so that goals are more visible?). This strategy seems plausible, but active manipulation of yourself and others (and through emotional arguments at that), seems to be a dangerous/risky proposition. How do you get your visibility back? Or do we always want limited visibility?

    I wonder how effective automated refactoring can be for a functional language? I’m coming from mostly doing C#+Javascript for the last five years, and what I miss most when reading/working with functional code is a VS+ReSharper like environment that makes it easy to navigate and understand the code. I think this problem is compounded by also having to learn a lot of new syntax and trying to figure out that various idioms of functional languages. We need visibility about WHAT the code means.

    • I don’t see it as a permanent reduction in visibility. It is just focussing on one or two key benefits at a time to allow people to make the important first step of adopting the language in a limited scope, low risk manner. Then they will be able to assess whether they want to continue to explore another benefit, and so on. At any point they can choose to abandon it or dive in feet first, using the wealth of information available on the internet. Nothing is permanently hidden.

      I know of a couple of efforts to develop refactoring tools (http://fsharprefactor.codeplex.com/ and https://github.com/JetBrains/FSharper), so I assume that it is possible. However, neither is progressing as fast as I’d like to see, and that is where I think a community-lead effort could change things.

      • I think the open source efforts are good but its not likely that production ready tools will be built any time soon unless there is a dedicated funded build.

        I have been trying to gauge interest in this aspect lately and it seems as though at least a couple of companies would be interested in funding such an effort.

        • I think we’re agreed on the need for a funded build :)

          I find the idea of keeping it open source quite appealing, so that when the funding runs out, the community can keep the development going. Having said that, I’m not averse to a paid product. I just want a useable tool!

  2. Most of us already have running production system using C# with a solid code base. So switching language mean doing a new assembly in F# and for us that’s a big step. If we could switch from C# to F# with baby step it would be easier.
    A baby step for me would be to be able to do F# in C# project.

      • I dont think the new assembly is a big step its the impedance mismatch between the two paradigms. Im my experience lots of C# assemblies are just poorly written. Let me rephrase that, most C# assemblies are written in an over pattern oriented manner with numerous over complexities rather than following design principles. When you interface with these assemblies with F# it becomes even more evident.

  3. Maybe we need to consider the case of Johnny Eveydev.

    Johnny is a C# developer, he has been developing tools in .net for a few years and considers himself a good C# developer. He has seen people talking about F# and why its soo awesome, and has run through some basic tutorials but has never done anything extensive in it.

    One day a new greenfield project comes along, after looking at the spec’s an image of a OO C# system begins to form in his mind. At this point does F# even enter his thoughts? If not why not? For some reason it occurs to Johnny that maybe this would be a good time to try out some of that F# he has heard about and he begins to try and form a picture of part of the system in F#… nothing happens… he tries again… nothing, he cant see what the solution would look like At this point Johnny knows what a OO C# solution would look like, but has little or no plan of how an F# solution would look.. Would he continue down the F# path? If so why? For some reason (perhaps the extra strong cup of tea next to him) Johnny continues down the F# route, he still doesn’t have much of a plan but he knows what he would write in C# so it can’t be that hard to fill in the implementation with F# can it? If Johnny writes F# while thinking in this OO C# frame of mind will he find it easier or more difficult to write the F# code. Will he get any benefit from writing F# in this way? How should he be going about designing his first project using F#? Johnny starts coding… Its tough going, every function takes him 3 or 4 times as long to write as it would have in C# because the syntax are weird and nothing works the way he expects, pretty soon he is on his 3rd cup of extra strong earl gray but feels like he is making little progress Why is he finding this so difficult? Is it because of the language? How does he feel at this point towards F# near the end of the day Johnny has burned out the kettle and is in some serious need of a bathroom break. he looks back on the F# he has written and well… its a mess to say the least… Johnny wonders how to fix this up, there must be some simple rename symbol functions for F# in visual studio right? there must be something that allows him to move a function to another file, there must be something that allows him to go to definition!?! Johnny packs up his things and leaves the office and his first day of F# programming behind him. That evening he thinks about the system again and thinks of what he has written, and compares it to his beautiful C# vision Will Johnny keep writing in F# tomorrow? What was Johnnys major problem? was it the refactoring tools?

    I think that to increase the level of F# usage in the community we need to get the Johnny Everydevs of this world on side. Refactoring tools are of course a major concern of anyone planning on building and maintaining an F# solution, but from the perspective of the novice user like Johnny it is probably not the major thing stopping them. I think the major thing that stops people like Johnny is the comfort and safety of C# and the fear of the unfamiliar F#. Why make the jump? Why fix what isn’t broken? These are the questions of the non-enthusiast or indifferent-ist if you will. How do we make their journey easier?

    The more Johnny Everydevs we have, the more incentive there is for companies (like jetbrains) to create tools to support them.

    • Great comment! You should turn it into a blog post :)

      You are absolutely right about the magnitude of the change faced by someone when they try to write their first F# code. And that is why we need to “shrink the change” and “script the steps” in order that they can see a series of smaller, lower risk steps that they can take. Tomas Petricek tweeted about unit testing as a possible entry point, and I think there could be good mileage in that. You only need to know a minimum of syntax, your existing testing frameworks will work, you get to see how F# tests can be more readable than their C# counterparts (using double backticks notation, and also the higher signal-to-noise ratio of F# code), and you get backtrack at any point by simply switching back to writing tests in C#.

  4. Pingback: F# Weekly #16, 2013 | Sergey Tihon's Blog

Leave a Reply