Less Code and Less Bugs : with Functional Programming languages

With a FP language many problems can
be solved with elegantly less code and
less-code leads to less-bugs.

Functional Programming (FP) insider know that, because they have personally experienced it. This can be tweeted and blogged many times, but how can others believe this? How do you prove it?

That problem inspired me to do some investigation. We need facts. What I’ve found so far are two studies that show this from a data analysis side. There is some evidence that both is true, according to these newer papers from 2014, based on data analysis of source code and its history from Github and from Rosetta Code :

Functional languages have a smaller relationship to defects than other language classes where as procedural languages”
– [1] A Large Scale Study of Programming Languages and Code Quality in Github
Functional and scripting languages provide significantly more concise code than procedural and object-oriented languages.”
– [2] A Comparative Study of Programming Languages in Rosetta Code


In [2] the data analysis covers 8 widely used languages representing the major programming paradigms
- procedural: C and Go;
- object-oriented: C# and Java;
- functionalF#  and  Haskell;  
- scripting:  Python  and  Ruby


I think the “less code” property is underestimated, because the too easy Lines of Code (LOC) counting is ridiculed. Looking beyond the LOC of the code base to the more important depending consequences :

less code  ->  less to read (more often than write!) and understand   -> 
less to review ->  less to communicate ->  less to refactor -> 
less to test  ->  less bugs  -> 
less to maintain  ->  less cost!!!

Btw. less code -> more time to think -> better solution -> more fun!


References

Other related analysis about software quality metrics, especially circular dependencies can be found here:
- “Comparing F# and C# with dependency networks
- “Cycles and modularity in the wild – Comparing some real-world metrics of C# and F# projects”

[1] A Large Scale Study of Programming Languages and Code Quality in Github
Baishakhi Ray, Daryl Posnett, Vladimir Filkov, Premkumar T Devanbu, Department of Computer Science, University of California, Davis, CA, 95616, USA
2014 http://dl.acm.org/citation.cfm?id=2635922

[ Update 4.10.2017 ]

[1] A Large-Scale Study of Programming Languages and Code Quality in GitHub
By Baishakhi Ray, Daryl Posnett, Premkumar Devanbu, and Vladimir Filkov

2017 https://cacm.acm.org/magazines/2017/10/221326-a-large-scale-study-of-programming-languages-and-code-quality-in-github/fulltext


[2] A Comparative Study of Programming Languages in Rosetta Code
Sebastian Nanz, Carlo A. Furia, Department of Computer Science, ETH Zurich, Switzerland
2014 http://arxiv.org/abs/1409.0252

Weniger Softwarefehler durch Klarheit – null ist Vergangenheit in F#

Die null ist leider die Quelle vieler Laufzeitfehler.

Die null-en befüllen die Code-Basis und machen sie weniger gut lesbar und wartbar.

Ein typisches Codefragment in C#:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
// C#
if (x != null) 
{
    return UseALanguageWithoutNull( x );
}
else
{
    return null;
}

Wie es ohne null aussieht

1: 
2: 
// F#
UseALanguageWithoutNull x

Null vs. Option.None?

Wir wissen dass in F# alle Werte initialisiert sind und niemals mit null. Mit der Ausnahme, dass von einer .Net Komponente die nicht in F# geschrieben ist, ein Rückgabewert oder ein Out Parameter als null daherkommt.

Was ist nun, wenn man den Zustand von nicht vorhanden in F# abbilden will?

Dazu dient der Option Type. Dieser kann None oder Some 'T sein. Wobei ‘T ein beliebiger Type sein kann, also z.B. ein int, ein String oder ein Array.

Jetzt könnte man ja sagen es ist genau das selbe?

1: 
2: 
null    vs.     None
obj     vs.     Some 'T

Die Unterschiede sind:

  • Es ist nicht umständlicher einen Wert in einen Option type zu packen. Auch wenn es im ersten Augenblick so aussehen mag. Der Nutzen überwiegt!
  • Der Type ‘T von Some ist bekannt, und auch von None, also welcher Type der keinen Wert hat. Dies ermöglicht die exakte statische Type Überprüfung durch den Compiler, was zu sicherem Code führt. Es wird also nicht zur Laufzeit implizit ge-castet.
  • Elimination der Mehrfachbedeutung von null. Wie oben schon erwähnt: Bedeutet null nun, nicht initialisiert oder nicht zugewiesen oder nicht vorhanden oder kein Ergebnis oder Fehler ? Da jede Variable auch null sein kann, muss der Programmierer immer mitdenken, was für Zustände die Variable haben könnte und was diese im Kontext nun bedeutet. Vergisst er es oder missinterpretiert er es, hilft ihm der Compiler nicht, erst zur Laufzeit unter bestimmten Bedingungen (Zustände, Daten) kann es dann zu null-Exceptions kommen. Im Gegensatz dazu, mit dem Option Type ist es absolut klar und der Compiler weiss es auch und hilft!
union case Option.None: Option<'T>
type obj = System.Object

Full name: Microsoft.FSharp.Core.obj
union case Option.Some: Value: 'T -> Option<'T>