We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

7 ineffective coding habits MANY F# programmers DON'T have

00:00

Formal Metadata

Title
7 ineffective coding habits MANY F# programmers DON'T have
Alternative Title
Seven ineffective coding habits many F# programmers don't have
Title of Series
Number of Parts
133
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
At BuildStuff'14, Kevlin Henney presented an excellent talk titled "Seven ineffective coding habits of many programmers". As a member of the audience that day and someone who has exhibited many of these habits over the years, I came to realize that using F# has cured me of many of these ineffective habits!In this talk I'll share my thoughts on how the use of F# and functional programming techniques can encourage good programming habits and help you become a better OO programmer.
Software developerCoding theoryProgrammer (hardware)WordDifferent (Kate Ryan album)MereologyVotingSound effectCodeGoodness of fitStaff (military)Right angleProgrammer (hardware)CognitionMaxima and minimaDecision theoryMultiplication signComputer programmingJSONXMLUMLComputer animationLecture/ConferenceMeeting/Interview
CodeAbstractionState of matterSoftware testingSoftware developerFormal languageMultiplication signCodeEntropiecodierungCASE <Informatik>Heegaard splittingWritingFormal languageForm (programming)Computer animation
Software developerShape (magazine)Dijkstra's algorithmCodeDistribution (mathematics)Standard deviationInternet service providerDesign by contractQuantum stateExpressionOracleSource codeDenial-of-service attackMaxima and minimaPrice indexString (computer science)Hill differential equationOvalProgramming languageShape (magazine)EntropiecodierungNoise (electronics)Term (mathematics)Right angleMultiplication signAreaLine (geometry)Computer animation
Physical systemCodeTerm (mathematics)Software maintenanceFrequencyTelecommunicationComputer programmingFaktorenanalyseEntropiecodierungLine (geometry)Multiplication signLattice (order)SurfaceSoftware developerArithmetic meanSoftware bugPoint (geometry)AreaCognitionComputer animationLecture/Conference
Computer programmingFaktorenanalysePhysical systemCodeTerm (mathematics)FrequencySoftware maintenanceTelecommunicationSoftware developerFormal languagePairwise comparisonComputing platformAxiom of choiceMathematical analysisEntropiecodierungProduct (business)Power (physics)Programmer (hardware)Term (mathematics)Object (grammar)Cartesian coordinate systemPairwise comparisonDifferent (Kate Ryan album)Formal languageLine (geometry)ImplementationNumbering schemeRevision controlSpacetimeDecision theoryComputer animation
Source codeCodeTotal S.A.ImplementationRevision controlNumbering schemeMultiplication signProjective planeLevel (video gaming)Insertion lossSoftware developerFormal languageEntropiecodierungMereologyDesign by contractNoise (electronics)Line (geometry)Computer programmingCore dumpLogical constantPower (physics)Source codeData structure2 (number)Computer animation
CodeFormal languageNoise (electronics)2 (number)Arithmetic meanTelecommunicationLine (geometry)MereologyCore dumpCASE <Informatik>EntropiecodierungSoftware developerPlanningProgrammer (hardware)Virtual machineLevel (video gaming)Right angleJSONComputer animation
Software developerMetric systemVisual systemArithmetic meanMaxima and minimaVisualization (computer graphics)BlogInformationEntropiecodierungComputer animation
InformationElement (mathematics)Finitary relationSoftware developerVisual systemMereologyHierarchyData structureInformationElement (mathematics)Order (biology)Theory of relativityGroup actionNatural numberRange (statistics)Different (Kate Ryan album)MereologyCausalityHydraulic jumpReading (process)EntropiecodierungComputer animation
Erlang distributionMessage passingElectric currentModule (mathematics)Line (geometry)Term (mathematics)CodeUniqueness quantificationCircleRadiusAlpha (investment)Multiplication signDataflowGreatest elementRight angleFunctional programmingEntropiecodierungSystem callComputer programmingOrder (biology)Process (computing)InformationLine (geometry)Operator (mathematics)WordWritingResultantField (computer science)Frame problemCASE <Informatik>Parameter (computer programming)Computer animationLecture/Conference
Data type2 (number)Parameter (computer programming)Single-precision floating-point formatData structureCondition numberStatement (computer science)Electronic mailing listHierarchyEntropiecodierungHypermediaElement (mathematics)Visualization (computer graphics)Computer animation
Software developerData typeString (computer science)Computer programmingVisualization (computer graphics)Element (mathematics)Line (geometry)Game theory2 (number)Data structureEntropiecodierungCompilerSpacetimePhysical systemPoint (geometry)Formal languageView (database)Lecture/ConferenceComputer animation
Compiler2 (number)Computer programmingBoundary value problemData structureSpacetimePoint (geometry)Rule of inferenceCompilerEntropiecodierungGoodness of fitLine (geometry)Term (mathematics)MetreFactory (trading post)Computer animation
Software developerCodeLine (geometry)Figurate numberElectronic mailing listData structureFunctional programmingNoise (electronics)Entropiecodierung2 (number)Computer programmingSpacetimeHierarchyOperator (mathematics)Direction (geometry)DataflowComputer animationLecture/Conference
HierarchySoftware developerNP-hardComputerCache (computing)System callFunctional programmingSpacetimeOperator (mathematics)HierarchyDirection (geometry)2 (number)Computer programmingCompilation albumComputer scienceFreewareValidity (statistics)CodeBookmark (World Wide Web)Cache (computing)Reduction of orderNeuroinformatikNoise (electronics)EntropiecodierungNP-hardStrategy gameServer (computing)Arithmetic meanCausalityComputer animationLecture/Conference
Object (grammar)Game controllerService (economics)Proxy serverException handlingFactory (trading post)Process (computing)Strategy gameWordBookmark (World Wide Web)Arithmetic meanDifferent (Kate Ryan album)Meta elementNeuroinformatikCombinational logicEntropiecodierungFactory (trading post)Dilution (equation)MetreGame controllerProcess (computing)Validity (statistics)Computer animation
Template (C++)DivisorFactory (trading post)Factory (trading post)WordArithmetic meanGame controllerGame theoryConnectivity (graph theory)Social classMultiplication signTemplate (C++)Interface (computing)Existential quantificationPhase transitionSoftware developerLecture/ConferenceComputer animation
Software developerCausalityLevel (video gaming)AbstractionStrategy gameScalable Coherent InterfaceProcess (computing)Arithmetic meanLevel (video gaming)CausalitySystem callAbstractionStrategy gameCollaborationismDigitizingTemplate (C++)Block (periodic table)BlogLecture/ConferenceComputer animationMeeting/Interview
Software developerStrategy gameTemplate (C++)Twin primePoint cloudHypermediaBit rateDigital signalSurface of revolutionTemplate (C++)Strategy gamePoint cloud1 (number)HypermediaNumbering schemeFocus (optics)Surface of revolutionDependent and independent variablesLecture/ConferenceComputer animationMeeting/Interview
Software developerNP-hardFunction (mathematics)CountingFunctional programmingProgrammer (hardware)Variable (mathematics)Dependent and independent variablesType theoryPlanningNumbering schemeStructural loadWordSocial class2 (number)Multiplication signComputer programmingGoodness of fitLambda calculusFunctional programmingEscape characterReduction of orderData conversionArithmetic meanEntropiecodierungRoutingNatural numberOrder (biology)Level (video gaming)Line (geometry)Metropolitan area networkScaling (geometry)Forcing (mathematics)VotingConservation lawMeeting/InterviewComputer animation
Software developerVariable (mathematics)Line (geometry)CodeNumbering schemeCodebuchLengthParameter (computer programming)Line (geometry)Variable (mathematics)Lambda calculusEntropiecodierungPhysical lawContext awarenessInterface (computing)LogicBusiness objectPoint (geometry)Computer animation
Regulärer Ausdruck <Textverarbeitung>Pairwise comparisonPosition operatorPattern languageTupleAbstractionContext awarenessImplementationObject (grammar)TupleExpressionMultiplicationDifferent (Kate Ryan album)Interface (computing)AbstractionCarry (arithmetic)Order (biology)Social classPoint (geometry)Pattern languageBusiness objectLink (knot theory)Pattern matchingMachine visionPressureCore dumpReduction of orderStaff (military)Moment (mathematics)Endliche ModelltheorieService (economics)CASE <Informatik>Computer animationLecture/Conference
WordChemical equationSystem on a chipParameter (computer programming)Core dumpWordFrequencyString (computer science)Term (mathematics)SequenceTouchscreenElement (mathematics)Type theoryCountingFunctional programmingComputer programmingGroup actionCategory of beingoutput2 (number)Multiplication signArithmetic meanShape (magazine)TupleObject-oriented programmingKeyboard shortcutLambda calculusLine (geometry)Pattern languageElectronic mailing listInstance (computer science)IntegerEntropiecodierungSoftware bugComputer animation
AbstractionRight angleCondition numberInterface (computing)Level (video gaming)Right angleFunctional programmingObject (grammar)EntropiecodierungAbstractionCondition numberInterface (computing)Social classMultiplication signCodecParameter (computer programming)Computer animationLecture/Conference
Interface (computing)Condition numberExecution unitEquivalence relationPattern languageFunction (mathematics)Single-precision floating-point formatSoftware developerStrategy gameFactory (trading post)Source codeInversion (music)CodecCondition numberParameter (computer programming)Electronic signatureInterface (computing)Functional programmingArrow of timeExecution unitEntropiecodierungBoolean algebraProcess (computing)Pattern languageMultiplication signComputer programmingState of matterType theoryBus (computing)Error messageException handlingComputer animation
Exception handlingInformation securityException handlingCASE <Informatik>Type theoryEntropiecodierungDivision (mathematics)Information securitySocial classIntegerData conversionDesign by contractMathematicsKey (cryptography)Service (economics)Library (computing)WordComputer animation
Exception handlingPhysical systemFunction (mathematics)Exception handlingType theoryRepresentation (politics)Functional programmingOnline helpRow (database)Computer animation
TuplePattern languageAbstractionDew pointException handlingSoftware developerPattern languageTupleAbstractionCartesian coordinate systemMultiplication signException handlingRight angleJunction (traffic)Object (grammar)Level (video gaming)Source codeOnline helpType theoryEntropiecodierungDomain nameComputer animation
OvalString (computer science)Software developerParameter (computer programming)WordAbstractionQuicksortDomain nameLetterpress printingEntropiecodierungCartesian coordinate systemSpacetimePoint cloudFamilyElectronic mailing listFunctional programmingParameter (computer programming)Computer animation
String (computer science)Source codeTime domainPhysical systemSoftware developerEmailAddress spaceType theoryDomain nameExpressionPhysical systemState of matterArmEntropiecodierungRow (database)Integrated development environmentFormal languageSpacetimeComplex (psychology)Social classWordMultiplication signHierarchyObject (grammar)WeightCartesian coordinate systemComplex systemNumbering schemeData managementCloningSemantics (computer science)MereologyComputer animation
Execution unitString (computer science)Error messagePlastikkarteData typeNumbering schemeMeasurementNumbering schemeExecution unitGeneric programmingType theoryAttribute grammarMaß <Mathematik>InformationCore dumpContent (media)Metre2 (number)CuboidMultiplication signDifferent (Kate Ryan album)MereologyCombinational logicString (computer science)Telephone number mappingParameter (computer programming)Set (mathematics)Enumerated typeObject (grammar)CalculationFunctional programmingBitIntegerObservational studyForm (programming)CASE <Informatik>Medical imagingComputer animation
Software developerState of matterElectronic mailing listCountingDigital filterIntegrated development environmentGroup actionProcess (computing)AbstractionState of matterType theoryUsabilitySlide ruleEntropiecodierungImplementationTerm (mathematics)MathematicsData storage deviceCohen's kappaBit rateFunctional programmingMultiplication signBlock (periodic table)Computer animation
Software developerSource codeAbstractionState of matterPlastikkarteNumbering schemeHierarchyRepresentation (politics)Suite (music)State of matterPhysical systemEntropiecodierungMereologyExtension (kinesiology)CASE <Informatik>HierarchyError messageSocial classPattern languageMultiplication signCartesian coordinate systemSet (mathematics)Compilation albumComputer fileMathematicsLogicProjective planeNumbering schemeStatement (computer science)Matching (graph theory)RootPunched cardOperator (mathematics)Closed setProgrammer (hardware)Key (cryptography)ExpressionCausalityUtility software2 (number)WebsiteWater vaporComputer animation
Software developerState of matterEntropiecodierungConstructor (object-oriented programming)Multiplication signProgrammer (hardware)Type theoryOrder (biology)Forcing (mathematics)Computer animation
MathematicsKeyboard shortcutSoftware developerIntegrated development environmentCategory of beingOpen setCartesian coordinate systemVisualization (computer graphics)Numbering schemeBitPeer-to-peerComputer animation
Default (computer science)String (computer science)Default (computer science)Decision theoryType theoryMultiplication signMereologyImperative programming1 (number)Functional programmingFormal languageCartesian coordinate systemCategory of beingWordParity (mathematics)Digital photographyJava appletRight angleSpring (hydrology)Computer animation
Software developerSoftware testingVector potentialState of matterSoftware testingSurfaceComplex (psychology)WordGoodness of fitFocus (optics)Data managementOrder (biology)EntropiecodierungSoftware developerDifferent (Kate Ryan album)Software bugAreaState of matterProcess (computing)Concurrency (computer science)Functional programmingOperator (mathematics)Computer animation
Function (mathematics)CodeSoftware developerSoftware testingFunctional programmingLatent heatSoftware testingReading (process)Cartesian coordinate systemForm (programming)Bookmark (World Wide Web)Computer animation
Software testingElectronic mailing listPersonal digital assistantCategory of beingInvariant (mathematics)Reverse engineeringComputerBlock (periodic table)SubsetCASE <Informatik>Functional programmingSoftware testingElectronic mailing listCategory of beingUnit testingSeries (mathematics)Physical systemBitLengthAdditionDifferent (Kate Ryan album)Type theoryEntropiecodierungoutputAreaSet (mathematics)Parameter (computer programming)Multiplication signErlang distributionIntegerCartesian coordinate systemVirtual machineDegree (graph theory)Confidence intervalBoolean algebraCovering spaceExecution unitWordMathematicsDefault (computer science)Traffic reportingSource codePoint (geometry)ResultantRight angleLine (geometry)MereologyServer (computing)Computer animation
Software developerSource codeSoftware testingType theoryType theorySoftware testingUnit testingCuboidCartesian coordinate systemFormal languageConstraint (mathematics)Compilation albumFluid staticsCompilerCASE <Informatik>Dynamical systemPhysical systemCovering spaceSoftware bugObservational studyContent (media)Product (business)MereologyMultiplication signSource codeComputer animationLecture/Conference
Compilation albumExpressionProduct (business)Software testingSoftware bugMeasurementMultiplication signPhysical systemEntropiecodierungType theoryDifferent (Kate Ryan album)Descriptive statisticsNumbering schemeSuite (music)Execution unitState of matter
Execution unitSoftware testingPhysical systemSystem programmingCategory of beingTLA <Logik>Type theoryProof theoryInternet service providerSeries (mathematics)DatabaseDifferent (Kate Ryan album)BlogInsertion lossPhysical systemSoftware testingType theoryFormal languageProof theoryConsistencyCASE <Informatik>Structural loadTwitterNumbering schemeReading (process)Scripting languageSoftwareLatent heatForm (programming)Cartesian coordinate systemCategory of beingSystem callUnit testingImplementationEquivalence relationResampling (statistics)Web serviceRow (database)Multiplication signProcess (computing)Statement (computer science)View (database)SpeciesInformationWeightComputer clusterTask (computing)Computer animation
CodeAbstractionState of matterSoftware testingSoftware developerShape (magazine)Dijkstra's algorithmCodeMultiplication signPerfect groupRight angleProgramming languageFormal languageSinc functionState of matterDefault (computer science)Programming paradigmInferenceImage resolutionForcing (mathematics)Lecture/ConferenceComputer animationMeeting/Interview
Software developerFormal languageComputer programmingProgramming paradigmGame controllerStructural loadDifferent (Kate Ryan album)Constraint (mathematics)Forcing (mathematics)Term (mathematics)FrequencyAuthorizationProgrammierstilFormal languageAbtrieb <Aerodynamik>Row (database)Lecture/Conference
Programmer (hardware)Software developerCovering spaceFunctional programmingTable (information)CodeHash functionPairwise comparisonPolymorphism (materials science)TheoryComputer fileComputer programModul <Datentyp>ParsingFormal languageParsingComputer programmingInclined planeOrder (biology)CodeSurfaceComputer programmingFocus (optics)Multiplication signFunctional programmingProgrammer (hardware)Core dumpMereologyCartesian coordinate systemComputer animation
Software developerMathematical optimizationRootEntropiecodierungMathematical optimizationFocus (optics)RootFunctional programmingMessage passingGoodness of fitMereologyReplication (computing)Key (cryptography)Self-organizationData structure
Data dictionaryMaxima and minimaCoprocessorLevel (video gaming)Cartesian coordinate systemData dictionaryMultiplication signCore dumpState of matterMereologyMathematicsOrder of magnitudeEntropiecodierungElement (mathematics)TesselationProcess (computing)WebsiteCondition numberGoodness of fitAdditionComputer animation
RecursionSoftware developerComplex (psychology)Personal digital assistantRule of inferenceBeat (acoustics)ImplementationEnterprise architectureImperative programmingMultiplication signRule of inferenceCASE <Informatik>Video gameFunctional programmingInformationSelf-organizationArchaeological field surveyRight angleFormal languageLecture/ConferenceComputer animation
Transcript: English(auto-generated)
Well, good morning everyone, and you might notice that I've actually highlighted the word many here, just so that we are politically correct, because of course, some people is gonna have some of these ineffective coding habits. So to give credit where the credit's due,
this talk was largely inspired by a talk that I saw at the build staff in 2014 by Kevin Henley, who is actually at this conference and giving a talk right now. And as such, habits are concerned, they are by definition things that are very hard to give up once you have them. And whereas a good coding habit can be the difference between being a good programmer to being a great one,
because it helps you make good decisions with a minimal amount of cognitive effort. Bad habits, on the other hand, helps you repeat the same mistakes over and over, sometimes without you even realizing. And after I saw Kevlin's talk, I went back and spent a lot of time reflecting upon the code I've written.
And specifically, I was thinking about the cases where I have also exhibited those ineffective coding habits that Kevlin pointed out. And somehow somewhat to my surprise, that pretty much all the cases that I can recount, I always happened when I was coding in C sharp, even though I spent pretty much an even split
of my time between C sharp and F sharp, at least over the last four or five years. So it led me down a path of asking whether or not the language that I use helps shape the coding habits that I end up forming. And then I came across this quote by Dai Su, who said that programming languages has a devious influence in shaping the way we think.
It shapes our thinking habits, which one would assume would somehow translate also to our coding habits. So let's take a look at some of the things that I came up with. So the first ineffective habit Kevlin pointed out was noisy code, which I think if I say that to you, everyone will have some intuitive understanding
of what it means, and we probably all see it as a negative trait. But at the same time, many of us have habits that without us realizing create a lot of noise to our code. For example, it's easy to see how this piece of code is really noisy, because the sheer amount of the user's comments that's added to what is this,
well, actually a hello world example, or how the code on the left is a lot more noisy in terms of how it implements the same feature as the code on the right. And that actually reminded me of a post that Jeff Atwood wrote a long time ago where he talks about the best code is having no code at all, because every line of code has a cost
from the time and effort it takes for you to write in the first place to having a bigger surface area for bugs to hide in, and if you have more code, it means it takes someone else longer time to read them, and then takes them longer time to understand them and be able to identify and find bugs, and then get to the more important point
of the time to fix bugs and provide more value to your customers. So the more code you have, the more cognitive tax you're paying on your development team. And of course, the more code you have, you need to have more developers to write and maintain them, which means you have more people to talk to to get stuff done, and more meetings, et cetera, et cetera,
and having fewer lines of code you have to maintain means you can also probably be more productive as well. Jeff went on to talk about how we should do whatever possible to increase the productivity of individual programmers, by in terms of the expressive power of the code that they do end up writing.
So having less code to do the same thing, or even better, is the goal that you should be aiming for. So back to this question of, does the language that I use make a difference? Usually, objective comparison between languages are really hard to come by, but fortunately, in the FSharp community, Simon Cousins was able to give us
a very interesting insight into how his company implemented the same application, a non-trivial application in both CSharp and FSharp, and the CSharp implementation has about 350,000 lines of code, and the comparison, well, the numbers just speak for themselves. You can see the FSharp version is less than a tenth the size of the CSharp implementation,
and if you drill down the numbers, by not having braces and not having nodes as a core part of the language, it means you can remove a lot of the noise that you create, a lot of synthetic noise that you generate systematically, because these are part of your language,
so as you write and code in that language, you can generate those noise constantly. And because with functional programming, you can often think and write at the higher level of abstraction, so sometimes when that moves you further away from some of the plumbing details, the integrated details you get with imperative style coding,
it often means that you also need a few lines of code to implement the same features, therefore, you also have to end up writing fewer lines of useful code, and having fewer lines of useful code, which means you also end up having fewer lines of blanks between your code, as well as fewer comments. So all in all, you get a much higher signal
to noise ratio, but that's not even the full story, because the CSharp project took something like five years and had at most eight developers at a time, but they didn't even finish implementing all the features, whereas for the FSharp project, it took less than a year, had at most three developers with only one person who's ever had any prior experience with FSharp,
and they managed to implement all the different contracts they were asked to do. So to quickly recap, by not having braces and not having notes as core part of the language when you're working in FSharp, it means that you generate fewer syntactic noise, and because you can work and think in higher level of abstraction,
it means you often can end up writing fewer lines of code, again, which introduces fewer noise that's associated with blanks and comments. Of course, that's provided that the code that you do end up writing, they're not made much more complex, which means you then have to write more comments to explain them, and that doesn't seem to be the case
for my personal experience at least, and when you have fewer noise, you have a higher signal to noise ratio, fewer lines of code to maintain and write means you are more productive as a developer, also means your employer probably have to hire less programmers, and also incur a lower organizational communication cost
and more importantly, means you can start providing value for your customer faster, which according to Dan North is the only reputational metric that matters to you. So let's move on to Vishal Dishonesty, and on his really good blog, which I was looking at, you check out www.vishalmess.com,
Daniel Higginbotham talked about how a clean design is one that supports visual thinking so that people can meet the information needs with a minimal amount of conscious effort, and of course Daniel is talking about visual design here, but the same principles also applies to code, and for code, it's about how you lay out your code
so that the visual relationships are obvious and accurate so that someone viewing your code can really quickly understand what's going on there. For example, when you lay things over one another with indentation, you're signifying hierarchy, and you're teaching your readers how to process the structure of your code,
and then you went on to say that you convey information by the way you arrange the design's element in relation to one another, and information is understood immediately, if not consciously, by the people viewing your design, and this is great if they're accurate and obvious, but if they're not, it's gonna cause confusion
to your readers, and they have to work very carefully going back and forth between the different parts to make sure that they actually understand, so think back to when you try to read someone's code who's badly organized, they're laid out, and you have to go jump and forth between different methods and different places in order to work out what it is that he's actually trying to do,
and consider how we read English. We read from left to right and top to bottom, and that's how we read code most of the time, except when it comes to nested method and function calls in which the flow has now been reversed. You're going from right to left and then bottom up, so all of a sudden, we've got this disparity
in how we visually process program information in order to understand what it's trying to do. Oops, sorry, didn't, there you go, and it's nice that in FSHAR, a very common idiom is to use the pipes operator, which allows you to write nested function calls
as a pipeline that flows from top to left and then, sorry, left to right and then top to bottom, and the way it works is very simple. We will evaluate the first line, and the result is then passed on to the next line as the last argument. In this case, we complete the call to the field function whose result is then passed on to the next line
and so on and so forth. It's a very popular idiom. Everybody in FSHAR community uses it very heavily, and then the thing that Kevin touched on was the placement of braces and how it affects readability. So if you take this piece of code, for example, where the braces are at the end of the line,
and if you mark every single character with X, so something interesting happened here. So now it's not clear to me where does the argument list end and where does the method body actually start, and even though I know somewhere around there there's an if statement there, it's also not clear to me where the if conditions end
and whether if a body starts. So even though we are aligning our code, the actual structure and hierarchy of our code, of the method is still not very clear without you having to eyeball where the curly braces are. And remember, if the visual relationships between elements are not obvious and accurate,
people are gonna get confused and they're gonna have to work harder to understand what it is that you're trying to present them. So instead, if you just place the braces on a new line, now repeat the same exercise, the structure of our code is much more evident at a glimpse. So turns out, where you put your braces
is not just a matter of personal preference, it's actually important in conveying the structure of your program, and that's the right way to do it. Which is then interesting because in hindsight it's actually quite obvious once it's been pointed out to us by someone else, but how did so many of us miss it in the first place?
And thinking about this, I think from my personal point of view, it's because we have two competing rules really to describe the structure of our code in a C-style language, one to the compiler who only care about where you put your braces and the semi-columns, but then there's also one for humans where we care about white spaces.
And then you keep hearing all these best practices being thrown around that says method shouldn't be longer than 60 lines of code, and when you're just around that boundary instead of refactoring your code and have a few more methods, smaller methods, well, I can cut some corners. I can just put the braces at the end of a line and save myself a couple of lines,
and now I'm just 60 lines of code, so I'm all good. And what you're doing is you actually end up sacrificing readability for the sake of readability. So what if we just use white space to convey structure of our program to both the compiler and to humans? Doesn't that help us remove some of the ambiguity that we have
in terms of where do we place our braces? And finally, we can stop arguing about what's the right way to put your braces, whether it's at the end of a line or is it on a new line? And this actually reminds me of something, a passage from the Zen or Python that says that there should be one, and preferably only one obvious way to do things,
and that's actually one of the things that I like about Lisp as well. So for the same function, this is how I'll do it in the F-sharp. Notice there's no braces anywhere, but when we apply the same exercise, the structure of our code is still very clear, very obvious, and also we end up with a few lines of code because there's fewer syntactic noise.
And remember, less code to do the same thing or better is good. So to recap, we looked at how you can use the pipes operator to help you structure your nested function and method calls as a pipeline that flows in the same direction that we're used to reading things, and how we can use just white spaces
to convey program hierarchy to both the humans and compilers and help us remove a lot of the ambiguities that we have around the placement of braces. And we move on to Lego naming, which is probably my favorite ineffective coding habits
because naming is really hard. We all know this, and in fact, I'm pretty sure everyone in this room has seen this quote before, that there are only two hard things in computer science, cache invalidation and naming things. And of course, someone added something to this, the third one, which is off by one error, which I think is quite funny.
But despite it being very hard, names are very important because they are the one, the only two that we have to describe, to explain what a value does in every place that it shows up in our code without having to scatter comments everywhere. So when it's done right, it can actually act as a nice noise reducer in your code.
But it's, as we all know, it's very difficult to do. So what we often see is we do this practice that the company calls Lego naming, where we glue different words together to try to create more meaning by combining together using common words such as strategy,
enable, service, validate, process, and everybody's favorite factory. And in fact, naming is so hard. I mean, why do it yourself? Just let a computer do it for you. So just go to metanamer.com and you will randomly generate as many different combination of these common words as you want, and you can use them as your meta names.
But sadly, that's not naming. What we're doing is we are labeling our code and adding more words together doesn't necessarily mean that you're adding more meaning. In fact, you often dilute the meaning or the thing that you're trying to name, which is how we end up with gems such as controller factory factory, which I've seen, unfortunately,
way more than what I should have. In fact, if you go to GitHub and search for factory factory, you find so many examples of this kind of labeling and some of which is just, wow, breathtaking. So we've got a class here that's a factory factory that implements typed game component
that is of factory factory or factory and also implements template factory interface that is of factory and factory factory or factory. I don't know, how many times can you write the word factory in a sentence before it gets really boring
and appears obvious to you that something's wrong here? Unfortunately, Lego naming is not limited to us developers either. So this is all based upon an idea of backward causality. If A does B and A is successful, then if you do B, you too will be successful. So being a scientist, I thought,
can we automate this process of copying? So I attended a lot of conferences listening to people talk about strategy, trying to identify various memes or what I like to call business level abstractions of a healthy strategy or BLAs for short. So here are the common BLAs, digital business, big data,
disruptive, innovative, collaborative, competitive advantage ecosystem, blah, blah, blah, blah, blah, I created a strategy template for this. Our strategy is BLA. We will lead a BLA effort of the market through our use of BLA and BLA to build a BLA
and so forth. Then I took common BLAs and the BLA template and auto-generated 64 strategies. So let's go through them. Number one, our strategy is customer focus.
We will lead a disruptive effort of the market through our use of innovative social media and big data to build a collaborative cloud-based ecosystem, et cetera, et cetera. Strategy two, our strategy is innovative digital business, we will lead a growth effort
of the market through our use of customer focus, competitive advantage and disruptive social media to build a collaborative revolution and so on and so on. Number three, no, I'm not really, but what, so I sent these out to a load of friends, put them online, and I got about 150 responses
of three common types. The first one was, this is more or less the exact wording from our business plan. The second was, I've seen two of these used already. And the third one was, are you for hire? So that's Simon Wildley doing his keynote
at the OSCON 2014. So yep, naming is really hard, coming out with a good name for things. It's not easy for anybody, but we have to keep doing it all the time because as programmers, we have to name every single class, every single method, every single variable that we have.
And lack of naming, just such an easy escape route for us. Fortunately, in FSHAR and functional programming in general, the use of anonymous functions or lambdas is such a common place. So that by nature of being anonymous, it means that you don't have to name them. And by using them very often in your code, it means that you have fewer things that you have to name
and the meaning of these lambdas that you often end up with, they are not created by whatever name you give them, but rather by the high order functions that makes use of them. All those high order functions such as a map and filter or reduce. Here's a very simple map reduce example. That's not big data or cloud scale,
but we've got two very simple lambdas here. And often you also find that the lambdas, the scope of the lambdas are really small. Often they're just one-liners or maybe a few lines of code. So you can get away with using really generic names such as for values such as X here as well. But of course, that doesn't sit well with a lot of people.
This comes up in conversations quite a lot. And if you're one of those guys who really dislikes the use of names such as X and F everywhere, I refer you to a really nice post by Mark Seaman who's gonna be talking about F sharp later on this week, where he provided a number of very meaningful
counterarguments. But the best counterargument actually came from none other than Uncle Bob. So in his Clean Code book, he's wrote that the length of names should be related to the length of the scope. You can use very short variable names for tiny scopes, but for bigger scope, you should use longer names.
And the variable names like I and J are just fine if the scope is five lines long. And I'm pretty sure that all of us have used I and J in our folders before. So apply the same logic. If you've got lambdas that are only two lines of code, then X is perfectly fine.
Another thing that I often struggle to name well is when I have one-off implementations for interfaces such as I-compara, especially if I have to have multiple implementations of I-compara for the same domain object based on the different contexts in a way I need to compare them differently. And it's not uncommon for me to see implementations
that are called the compare implementation one, compare implementation two, and so on and so forth, which is why it's nice in F sharp that way you have one-off implementations for things. You can also just use the object expression to create anonymous implementations for these interfaces. And of course, if you see you need
the same implementation in multiple places, then you can start taking your anonymous implementation as you put them into real implementations in the class and given proper names at that point. So again, there are a few things that you have to name. In this case, there are things that you typically struggle to name very well.
Another thing that we use very often, a lot in F sharp, way more than I do in C sharp is tuples, partially because of our ability to do pattern matching against them. And because I can use tuples for a lot of different things, it means I don't have to create as many simple abstractions in order to carry data across, say, multiple steps in the method
or multiple steps in the link query, which again means a few abstractions equals a few things that I have to name. Here's a very simple example of a term frequency program where I take a bunch of string and then I count how many times that each of the strings appears in that list.
Actually, I don't know how familiar everyone is with F sharp. Is this code confusing to anyone? Raise your hand, it's okay. Okay, we go through it, don't worry. So words here is an ID numable of strings, so it's a sequence of strings. And what I've done here, the first step is I say group by itself, which is what ID function does.
So this returns a sequence of tuples where the first element is the word that you're grouping by. The second element is the sequence of words, the same word that I found in my input list. So in C sharp, in the next step, if I want to map that into a word and the count,
you would do, say, tuple here and then access them via tuple.item1, .item2, and so on, which, okay, it works, but it kinda loses the meaning of what it is those elements are. Whereas here in F sharp, what you can do is, okay, I know the shape of the input for my lambda.
What I'll do is I'll apply a pattern that matches the shape and bind the word to a value called word and bind the sequence into a value called group, which I can then use to create another tuple for each instance of those tuples by counting the second element.
I can do the same thing on the next line whereby, okay, I know now the second element of the tuple is now a length, and then I'll just print them using, actually, I've just noticed I've got a bug here. That's the integer. That shouldn't be S there. I should be D. Oops. But even in this very simple example,
we save ourselves having to create two simple types to carry data through just to get sensible names for the properties that we're working with. And Lego naming can also be a symptom of you struggling to find the right level of abstraction to work with in your code. And just like naming, trying to identify the right level of abstraction is really hard,
partially because sometimes they are smaller than an object. And overall, we don't really have a good way to represent a pure piece of functionality. And often, I see this practice being used all the time where you create a very simple interface or class that wraps around the thing that you're really looking for so now you've got two things to name instead of one.
So you can see Lego naming is already kicking here, kicking here. We've got condition checker and check condition. So we can actually improve this. This is much better names for what we're trying to do, but for me, this is still way too much wrapping for what it is I'm really after. In essence here,
a condition is just something that I want to evaluate and get a Boolean back. I want to evaluate it without argument. So this is all I have to do in F sharp. And what this is saying is that condition is any function that takes no argument. Unit is just F sharp's way of saying void or empty argument list. And that arrow just says,
okay, the return value is gonna be a Boolean. So now I can use any function or method that matches this signature as a condition in my code without having to force someone to explicitly implement the interface that I've created earlier. In fact, pretty much all of your old patterns can be represented in function programming
with simple functions. This is a talk that Scott did, I think was it two years ago? Two years ago. So if you have time, go back and watch this, it's great. Another common practice I see a lot is we tend to slap exception to the end of types that represent the exception in our code. And often this is a case of less is more.
So is class not found? Not sound like something that's an error? Do we have to really say it's an exception? And sometimes you can't really do that. So if you remove exception from arithmetic exception, you just get that with arithmetic, which doesn't really tell you much.
But if we put some more thought into it, the only place where we're gonna get arithmetic exception is when you divide integer by zero. So wouldn't integer division by zero be a better name for it? I would say so. Instead of having security exception, maybe security violation sounds more like something that a normal person would say in a conversation.
And in that shot, of course, you can still do the same thing. You can still add suffix to your types that represent exceptions. But the common practice I've seen in the community is to use the lightweight exception keyword and the convention is not then add exception suffix to your type because you already have a keyword here that tells you what it is this type represents.
So to recap, even though F sharp is not a silver bullet, it doesn't stop you from doing Lego naming. And I've done it myself. And I've seen other people do it as well. But there are certain amount, there's quite a lot of tools that at least help make the problem less
because you can use anonymous functions, the lambdas, to remove a lot of things that you have to name usually. And where you have a very short lambdas, you can get away with more generic names as well. So less things that you have to think really hard to name well. And because you can use tuple so easily with pattern matching,
it means there are fewer simple abstraction you have to create just for carrying data across your application. And because no abstraction is too small, you are better able to model your application at the right level of abstraction. And also find that sometimes you can help remove unnecessary layers of abstractions in my code.
And lastly, we also looked at lightweight syntax for defining exceptions in F sharp and how the convention is not at the exception suffix at the end of every type we create. So then we move to under abstraction. So Keflean showed a very nice technique where you can use a tech cloud on your code
to see what pops out. On the right here, we can see an application whose domain is kind of showing through. You can see printer, you can see picture, sorry, printing device, you can see paper. So that gives you, this gives me a rough idea of what sort of problem space that this application is working in. Whereas on the left, I can see a string,
I can see a list, which, well, just about anything. Maybe it's doing a word count, I don't know. Another example, another sort of symptom that you often see with under abstraction is when you have functions and methods that takes a very long list of arguments. And when your argument list is this long,
I think another one or two just doesn't matter anymore. And again, F sharp's not a silver bullet that can stop you from doing under abstraction, but Scott, I love your work. And Scott talked about how you can apply F sharp's type system to help model your domain. Because F sharp has got a very expressive type system.
And you have a certain number of tools for creating, a very lightweight syntax for creating types of hierarchies using records and discriminant unions. So for those of you who haven't seen records before, you can think of it as a lightweight immutable class
that supports the clone and update semantics. So here, I've got a method that takes the employee object and how much I want to raise his salary by rather than mutating the employee state in place, I return a clone of the employee whose salary has now been raised.
And for me, managing state is not a scalable way to build large and complex systems because when you have mutable states, they are interleaving value and time. And Rick Hickey, who's an amazing speaker, he revived the word complex in the English language and it's a very nice way to describe
the mutable states here. And when you have time and space, time and value being to read like this in your code all over the place, it makes it a lot harder to understand and reason about, especially in the concurrent and parallel environment where the ground can be constantly shifted beneath your feet as you're doing some work
but some other part of the application is changing the state as you go. You may have also noticed this little thing here that looks like generics but it's not really. This is in FSHAR what is called a unit of measure. So the way it works is that you can create a type that represents some unit and then decorate it with the measure attribute. And so from here on, you can then use that type
almost as a generic type to add contextual information to any numbers that you're working with and you hand those out of the box, the combination of different units correctly. So 10 meters divided by two seconds gonna give you five meter per second of course but if you try to combine incompatible units together
then you find out compile time. So if you've got a function that is doing some payroll calculation and you're expecting the argument to be in the pounds and not the pens, then you can make that very strong, you can give yourself much stronger static safety by making use of a unit of measure.
For now you can only use it on integers, floats, longs, et cetera but starting from FSHAR5, I think you can actually use it with objects and strings and other types as well which would be very interesting. And then we have discriminated unions which you can think of it as a more powerful enum
or a tagged enum where each of the Ks can be associated with an arbitrary set of types but unlike enums which you can create invalid values by just casting 42 to it because enums are just a facade over integers and bytes. These are full-on types and you can create invalid values
by just casting integer. We look at the discriminated unions a bit more in detail later on but for now let's move on to unencapsulated state. So if under abstraction is like going to a job interview in your pajamas, then having unencapsulated state
would be like wearing your underwear on the outside which is probably not a look that you and I want to really challenge for. So Kevlin uses this example to illustrate a danger of exposing your state to the outside because now we have a mutable state and it's freely available to the outside world.
So not only are you wearing underwear on the outside, you're also permitting anybody to just make changes to it which is a pretty scary thought if you ask me. Of course, you can still do this in F sharp but it's far less likely because as functional programmers, we love immutability, right?
Chances are we probably won't use a mutable internal state in the first place and if you did, we definitely won't expose it to the outside world because we won't maintain our facade of immutability. This is probably how I would write the same implementation in F sharp. I'm not gonna go over it so if you're interested, have a look at the slides afterwards.
And Kevlin also then touched on this idea, this concept of affordance. So in terms of design of everyday things, if you've got a door you want people to push, then don't put a handle that people can assume they can pull, that'd be bad usability design. The idea is that you want to afford the right behavior
but at the same time, make it very difficult or impossible to do the wrong things. And the same principles also applies to how you write your code and design your APIs which Joshua Block did a very good talk on a few years back.
So the goal here is to, as much as possible, make a legal state unrepresentable in your code at all. And normally we do that in F sharp using discriminant unions which allows us to create a finite and closed set of states but only the valid states that our system would ever accept.
The fact is it helps us create a closed hierarchy is something that I don't really have a vocabulary to express, say in C sharp without discriminant unions. So if you've got a class hierarchy in C sharp, it's always possible if the root of your hierarchy is open, otherwise you wouldn't have a hierarchy,
then it's always possible for someone to abuse it by subclassing or just adding a new state to your application that whilst you're writing the rest of your code, you're not aware of. So that's a part of the vocabulary that I find missing when I'm working in C sharp often because sometimes I want things to be always extensible,
that's fine, I can use class hierarchy for that, but don't really have a way to say this is it guys, this is the hierarchy that I will ever have but no more extension unless it goes through me. And of course, when you're working with classes, you have to think about no's all the time and this is the number one invalid state
that everyone in the world has to deal with constantly which is why Sir Tony Hall caused his billion dollar mistake. Fortunately, in F sharp, if you're working fully in F sharp of course, you don't have to think about no's because you just can't create them, at least not easily. Most of the time, the only place you can create, you can have no's in your code is when you do interrupt with your C sharp code
where no's can come in really easily. And when you're using discriminant unions, you can use pattern matching against them so that you have a very nice way to very clearly and easily express all your branching logic in one match statement here. And if you're missing a case
or if someone added a new state in your discriminant union, you also get compile time error or if you really wanna be really strict, you can also just have a change in your project file to turn that warning into an error which is something that I actually do quite often in critical parts of my application.
So to quickly recap, F sharp programmers are unlikely to expose unencaptured state to the outside because we love our immutability. And oops, where's the next slide, there you go. And because you don't have no's, you have to deal with order time and that types are immutable by default. So once they're constructed
and validated at construction time, they know someone can't then go and change them into invalid state. And with a discriminant unions, you have a way to help you make illegal state not representable in your code. Kevin then also then challenged the habit
of always creating setters whenever you have a getter and told us that you need to be more conscious and cautious about what can change and what cannot in your application. But unfortunately, this bad habit of always having getter and setter pairs is such a habit that's been forced by a lot of the modern tooling that we have in our IDEs.
It's so easy in Visual Studio and just any number of other IDEs to just start writing a property. As soon as I open curly braces, okay, getter and setter all done for me, great. Except we are kind of just automating the wrong things. So we have all these tools that automate what we do manually,
but unless we change what we're doing manually, if we're doing the wrong things manually, then your tools are just gonna make doing the wrong things faster and easier, which is probably not where you wanna end up at. And that's where I think language default is so important. Where it is in the imperative first languages, such as C sharp or Java, mutability is the default.
But in functional first languages, such as F sharp or Scala, I think they got it right by choosing having immutability as default instead. So where you have the record, all the properties are immutable by default. So where I've made a conscious decision on what can change,
then I have to then do additional typing to use the mutable keywords. And every time I type the mutable keyword, it's a chance for me to ask myself again, is it really necessary for this thing to change? That plus the mental resistance that I have towards, well, because of my love for immutability, for me at least has been sufficient
to really force me to think carefully and make very conscious decisions on which part of application can change and which ones can't. And finally, we have an uncohesive test. And this is a habit that I have and I see a lot of people have as well where we write a lot of tests,
but all of which targets just a single method. And it's good at getting a nice code coverage and keep your managers happy, but you're really just testing the surface area of your code because when you need to implement a feature, you have to call all these different methods and different orders. And a lot of the complexity and bugs
actually comes from the way they work together, especially where states and the currency is concerned because the order in which you process something could be significant, especially if you're updating state as you go. And where people talk about test-driven development, most of the focus is on the words test and development.
And not enough people are considering what driven implies. Whereas for tests to drive your development, they must do more than just test your code, it's doing what it's supposed to. They must also clearly express the required functionality to the reader. And that is they must be clear specification
for the requires functionality. And this book by, I'm gonna fail really bad if I pronounce his name, Gojko Asic. It's one of my favorite books on testing. And in this book, he talked about how this concept of living documentation and how you can use your test
as a form of a specification for your application that is executable and always up to date. But even as we improve on what it is that we are testing there's still this question of how many tests do we need to write? If you take a simple function
that takes the integer as the argument, to do an exhaustive testing, you need to generate 2.14 million test cases to be exhaustive. Of course, we don't always need to generate, we don't always need to be exhaustive to get a reasonable degree of confidence about our code. But still even writing and maintaining
a really relatively large set of tests can be quite expensive and time consuming. And we can't be trusted because we're humans to always think of all the different edge cases all the time. Which is why in addition to writing unit tests the FSHAR community is also has been moving towards using adopting property-based testing with FSHEK which is a port of QuickCheck from Haskell and Erlang.
So in this world where you have your unit test to cover special cases that you have in your code but for everything else or as much as you can you use property-based testing and you look for properties that will hold for either all or at least some subset of all potential inputs
to your application. A bit of a trivial example but if you take list.reverse as example these three properties will hold for any argument any input to my method. So if you reverse and reverse the list you're gonna get back the original list, right? And if you reverse something then the length of the list should not change ever.
And if you append and reverse the list it should get the same result as if you reverse list first and then prepend the element. So once you've identified these properties which is probably the more difficult thing to do and again, Scott has got really nice series blocks and some hints and advices
on how to identify the different properties that you may have. You can then express them as very simple functions that ultimately returns a Boolean and then just allow the system to generate tests for you. And by default, whenever you do check.quick with the property that you're testing against the system will generate 100 test cases.
You can change that to generate 1,000, 10,000, a million as many as you want. And the system could then also try to cover different edge cases and you can do the same thing for the other properties. And if you wanna have a look and have a peek under the cover and see what are actually test cases that have been generated
you can use check over both to see that in this case we're generating all kind of interesting test cases that I probably wouldn't have thought of myself but then it also covers the common edge cases such as the null as well as the empty list with a list of different types for example. And when a test fails it also does this very interesting nice thing
of simplifying the test case that fails and shrink it down to the simplest case that can cause this particular property to fail. The idea here is that you let the machine do the groundwork, do the not interesting things
and for me this is the most scalable way to write tests. It leaves you to do the interesting things that the machines are not very good at doing yet. Otherwise you end up having to write all these tests by hand and often I see people copy and pasting changing one tiny bit of your code, maybe the method name and the name of the test
and maybe some other tiny bits and then they forgot to change one other thing and then the test will pass but they're not testing what they're supposed to. So in those cases you end up with this area where okay, I can't fully trust my test so I need to have a test to test my test which is where you end up with mutation testing where you have mutation tests that changes your test, tiny bits of your code in your test
to see whether or not your test is succeeding or failing and if it's not failing then you have a problem with your test. So then you then also ask okay, so we've got someone who washes their washman, but then who washes their washman. Mathias is actually gonna be talking a bit more about property-based testing later on today
and again, Scott, I love your work. He also did a talk at the skills matter in London while back on the property-based testing. So besides unit tests and property-based tests you also have another tool in your toolbox, that is your types and given a type system that allows you
to have a rich dialogue with the compiler it means then you can have a better way to express your intention as well as a constraint that you have in mind for your application to a compiler and to help make more of the problem of ensuring that your application is gonna do what it's supposed to, the compiler's problem rather than your problem.
So you hopefully end up with a fewer tests that you have to write versus what compiler can do for you. So this is something that I keep going back to when I'm working in dynamic languages like Erlang or Ruby, I'm sorry, not Ruby, Python versus say C sharp and F sharp, whereby I, okay, I have to write a lot more tests
when I'm doing stuff in Python because a lot of the guarantees that I have when I'm working in a static type language is not there. So some of the work that I've outsourced to the compiler is now mine, so I have to write more tests to cover the different cases. And of all the bugs that you ever have, some of which you can think of ahead of time so you can do something about them, but others you just can't think of
and your best chance would be to catch them at production when they manifest themselves. But for the things that you can think of, you should try to, you should aim to make as much of them as possible the compiler's problem using your type system and that's where this whole thing we talked about earlier of making illegal states unrepresentable in your code
comes in. Granted, in F sharp, our type system is not, it doesn't get us there yet and I think the closest I've seen on actually reaching that dream is with Idris. But even then, with F sharp, we have some very nice, a very expressive type system and there are lots of interesting tools that I don't have in other languages
such as you need a measure and something that everybody misses in F sharp when they go back to writing code in C sharp, which is discriminate unions because again, it's about what can you express through your type system and the discriminate unions give me something that I badly miss when I'm working in C sharp. Another thing that I found very interesting
when I think about testing is that the three different approaches that we talked about here actually also mirrors what I see in distributed system testing. So you've got your normal things where you write some script perhaps to set up your cluster, you run some automated testing against them to make sure that it's doing what it's supposed to. So that'd be the equivalent for unit tests
where you've got specific test case in mind, you try to automate it when you're testing your system. And then there's also Jepson, which is a tool by Kyle Kingsbury who goes to the name of Aifer on the Twitter. He's got some really interesting series of blogs all started with call me maybe followed by the name of the database
that he's been testing. So what Jepson does is that he applies the same approach as the property based testing where you generate random test cases and then randomly induce network splits as you have different nodes, you're reading and writing data to different nodes and then after the network split hills,
check if the consistency that the database providers claims to have actually holds at the end of it. And it's actually been used quite widely now by database vendors to test whether or not the claims that they have around consistency actually holds after Kyle Kingsbury wrote a series
of blog posts which shines unflattery light on a number of different databases. Seriously, go check it out. It's very interesting reading. A lot of things have been improved partially because he's been doing this work and identify all these things that people say are true but are not. And the equivalent to using types
as a form of proof that the application is supposed to do what it's supposed to, is a TLA+, which is a language to describe, a language for describing formal methods to prove the correctness of your system and it's something that has been used that came out of Microsoft Research by Leslie Lambert
and it's been used very heavily by Amazon Web Services in S3 and in the design of S3 and DynamoDB. So with the DynamoDB case, they did loads of very intense pair reviews on the system design as implementation
and they did the exhaustive work on creating formal proof that, okay, the system is supposed to do what it's supposed to, it's gonna do what it's supposed to but even then, they were not able to cover all the different cases and it's only when they started using TLA+, to break down what DynamoDB is doing into 75 different steps
and allow the system to randomly generate the pseudo test cases against the design of a system, not implementation, had then found actually they had some flaws in the design whereby there was different edge cases where you can result in data loss for your customers.
So those are the seven ineffective coding habits that Kevin pointed out and through practice, we all pick up good and bad habits over time and Larry Gelwix, who's a very famous American rugby coach in the 50s said that practice doesn't make perfect, practice makes permanent
to which Vince Lombardi later on added that practice does not make perfect, only perfect practice makes perfect and that perfection is not attainable but if we chase perfection, hopefully we can catch excellence and going back to the influence programming languages on the way on our coding habits,
language defaults give you affordance towards the right behaviors and habits, for example, mutability affords the habit of being conscious about change so that you don't always add a setters whenever you have a getter and don't expose your states to the, uncaptured state to the outside world and since programming language and the paradigm
specifically have a huge impact on how we think and how we problem solve, none more so than the first language that we ever come across which I think personally that we should spend a lot of our effort on learning new language and more importantly, new paradigms because every paradigm forces you to think in a particular way and if all you know is one paradigm or one language,
then you are not in control, your language or your paradigm is the master of you, it forces you to think the way that it's designed to so for you to actually get your control back of your mind of how you think, you have to break free of that constraint that the language and the paradigm has placed around you
by learning new things and then a new way to look at a problem and having to try loads of different language and paradigms is amazing, the different ways you can come up with solutions, different solutions for the same problem and a book that I've been reading recently and I've been converting examples to F-sharp is called the Exercises in Programming Style
where the author takes a very simple term frequency problem and wrote 35 different styles to solve that problem, some of which are very distinct and very different from anything that you might have think of in say C-sharp or F-sharp, it's definitely worth checking out and of course, we all wanna be great programmers,
I think that goes without saying so let's all help us get better coding habits in order to do so by learning F-sharp as a start. So I've been training about F-sharp for a long time how great it is but what about some of the ineffective coding habits that some F-sharp programmers and functional programmers in general do have? Well, one thing I noticed
and quite a few people have mentioned this as well including John Harrop who's quite possibly one of the smartest guy I've ever met. In his post on the core here, he noted that some people, sometimes people are too puritanical about purity even when it comes to forfeiting performance in the performance critical part of the application
and I'm sure everyone's seen this quote that premature optimization is the root of all evil but I'm dismayed by how almost never, I've never seen anyone show the second part of this quote which is just as important that yet we should not pass up our opportunities in that critical 3%.
So the message is not don't optimize ever, the premature part is the key. You want to optimize once you have learned about your application, learn about which are the 3% of your code that's very performance critical and once you identify that, focus your optimization efforts on that. If it means you can use
all the functional programming goodness or immutability and whatnot for 97% of your code where performance is not as important, great but when you're in that 3% of your code, do whatever you can to get your performance back and especially when it comes to using data structures, immutability has a cost, sometimes amazing.
So if you're adding a million items to a FSHAR map, it's 244 times slower, it's two order of magnitude slower than if you used a mutable dictionary. Of course, it wouldn't matter if all you're doing is creating a map of 10 elements and all you're doing is doing is get
so that would be while within your 97% of your code base, then don't worry, it doesn't matter if it's a thousand times slower, it just wouldn't make any change to your code or to your overall performance of your application if you decide to use a dictionary instead but once you've identified the core part of your code where you're doing a lot of mutation, where you're updating dictionaries a lot,
try using a dictionary instead and then the trick that you can also do in FSHAR is if you encapsulate it, remember immutability is to the outside, coming to the outside world, you can still have mutable state as much as you want so long as encapsulated within say a function or within a mailbox processor which is a FSHAR way of defining an actor,
then you can mutate all the way, all as much as you want because it's all encapsulated to the outside world, everything's immutable, it's still good. So prefer simplicity and pragmatism over purity and use imperative paradigm where it's best for the job and with that, I would like to leave you
with a few more passages from the Zen or Python. The explicit is better than implicit and the simple is better than complex and complex is better than complicated. Special cases aren't special enough to break the rules but practicality builds purity all the time and if something is difficult, it's hard to explain,
it's probably a bad idea to begin with and with that, I'd like to thank you for your time and I thank my employers that give me time off to do this and we're hiring. Oh yeah, right, Mathias. So after lunch, which is in four minutes time, there's a function programming labs in the workshop
which I think just two doors down that way. Yes, it's down that way is where you can come and speak to what most of the guys on a functional track and if you've got questions about FSHAR or other functional programming languages or just wanna do some hands-on coding, some kata, I think Mathias has got some really nice ideas
to do some hands-on workshops with you guys. Just come and speak to us and I've got some stickers courtesy of Mathias again to give out FSHAR stickers. So yeah, thank you very much.