From ed5c1a3c1b1e14d9aff843fe7ef8cc99e1ea0c07 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Fri, 8 Mar 2019 12:15:41 +1100 Subject: [PATCH] converted http:// urls to relative fixes https://github.com/ploeh/ploeh.github.com/issues/430 --- .../LivingInInterestingTimes.aspx/index.html | 8 +- 2009/01/28/ZeroFrictionTDD.aspx/index.html | 8 +- 2009/02/13/SUTFactory.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../ConstrainedNonDeterminism.aspx/index.html | 8 +- .../index.html | 8 +- .../11/ExplicitExpectations.aspx/index.html | 8 +- 2009/03/16/FixtureObject.aspx/index.html | 8 +- .../22/AnnouncingAutoFixture.aspx/index.html | 8 +- 2009/03/23/JoiningSafewhere.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../AutoFixture.8.1Released.aspx/index.html | 8 +- .../17/AutoFixture81Released.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../26/TheAutoFixtureBuilder.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../04/AutoFixtureCheatSheet.aspx/index.html | 8 +- .../index.html | 8 +- 2009/06/05/Tweet.aspx/index.html | 8 +- .../index.html | 8 +- .../AutoFixture.8.2Released.aspx/index.html | 8 +- .../18/AutoFixture82Released.aspx/index.html | 8 +- .../AutoFixture.8.3Released.aspx/index.html | 8 +- .../20/AutoFixture83Released.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../AutoFixture.8.4AndRoadmap.aspx/index.html | 8 +- .../AutoFixture84AndRoadmap.aspx/index.html | 8 +- .../index.html | 8 +- .../DataTemplatingInASPNETMVC.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2009/08/25/DoRedux.aspx/index.html | 8 +- .../AutoFixture.8.5Released.aspx/index.html | 8 +- .../02/AutoFixture85Released.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../AutoFixture.8.6Released.aspx/index.html | 8 +- .../21/AutoFixture86Released.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2009/09/29/SOLIDOrCOLDS.aspx/index.html | 8 +- 2009/10/05/WritingABook.aspx/index.html | 8 +- 2009/10/24/WCFPodcastWithMe.aspx/index.html | 8 +- 2009/10/26/AnonymousWith.aspx/index.html | 8 +- 2009/10/31/AutoFixtureBeta1.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2009/11/26/AnonymousDo.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../07/LoggingExceptionFilter.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2009/12/20/MEFTechTalkWithMe.aspx/index.html | 8 +- 2010/01/04/AnonymousGet.aspx/index.html | 8 +- 2010/01/13/AutoFixture1.0RC1.aspx/index.html | 8 +- 2010/01/13/AutoFixture10RC1.aspx/index.html | 8 +- 2010/01/20/AutoFixture1.0RC2.aspx/index.html | 8 +- 2010/01/20/AutoFixture10RC2.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2010/01/26/IWindsorInstaller.aspx/index.html | 8 +- 2010/01/27/AutoFixture1.0.aspx/index.html | 8 +- 2010/01/27/AutoFixture10.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2010/02/08/CNUGTDDTalk.aspx/index.html | 8 +- 2010/03/17/AutoFixtureFreeze.aspx/index.html | 8 +- .../26/MoreAboutFrozenPizza.aspx/index.html | 8 +- 2010/03/27/FreezingMocks.aspx/index.html | 8 +- 2010/04/02/AutoFixture1.1RC1.aspx/index.html | 8 +- 2010/04/02/AutoFixture11RC1.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2010/04/10/AutoFixture1.1.aspx/index.html | 8 +- 2010/04/10/AutoFixture11.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../UpcomingTalksSpring2010.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../08/09/AutoFixture2.0Beta1.aspx/index.html | 8 +- 2010/08/09/AutoFixture20Beta1.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2010/09/13/MyFutureIsAzure.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../10/AutoFixture2.0Released.aspx/index.html | 8 +- .../10/AutoFixture20Released.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../TowardsBetterAbstractions.aspx/index.html | 8 +- .../index.html | 8 +- 2010/12/22/TheTDDApostate.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../24/ScalableDoesntMeanFast.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../22/CommandsAreComposable.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../04/19/AutoFixture2.1Beta1.aspx/index.html | 8 +- 2011/04/19/AutoFixture21Beta1.aspx/index.html | 8 +- .../index.html | 8 +- .../27/ProviderIsNotAPattern.aspx/index.html | 8 +- .../index.html | 8 +- 2011/05/02/AutoFixture2.1.aspx/index.html | 8 +- 2011/05/02/AutoFixture21.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2011/06/07/SOLIDCodeIsnt.aspx/index.html | 8 +- 2011/07/28/CompositionRoot.aspx/index.html | 8 +- 2011/08/01/JoiningAppHarbor.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2011/10/25/SOLIDConcrete.aspx/index.html | 8 +- 2011/11/08/Independency.aspx/index.html | 8 +- .../10/TDDImprovesReusability.aspx/index.html | 8 +- .../07/PolymorphicConsistency.aspx/index.html | 8 +- 2011/12/19/FactoryOverload.aspx/index.html | 8 +- .../index.html | 8 +- 2012/01/03/SOLIDIsAppendonly.aspx/index.html | 8 +- .../index.html | 8 +- .../IsLayeringWorthTheMapping.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../BankOCRKataInF#UserStory1.aspx/index.html | 8 +- .../BankOCRKataInFUserStory1.aspx/index.html | 8 +- .../BankOCRKataInF#UserStory2.aspx/index.html | 8 +- .../BankOCRKataInFUserStory2.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../06/21/TheResemblanceIdiom.aspx/index.html | 8 +- .../22/ResemblanceAndLikeness.aspx/index.html | 8 +- .../index.html | 8 +- 2012/06/27/FacadeTest.aspx/index.html | 8 +- .../02/PrimitiveDependencies.aspx/index.html | 8 +- 2012/07/18/Hyprlinkr.aspx/index.html | 8 +- .../20/FizzBuzzKataInF#Stage1.aspx/index.html | 8 +- .../20/FizzBuzzKataInFStage1.aspx/index.html | 8 +- .../25/FizzBuzzKataInF#Stage2.aspx/index.html | 8 +- .../25/FizzBuzzKataInFStage2.aspx/index.html | 8 +- .../index.html | 8 +- .../31/ConcreteDependencies.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../06/WhenToUseADIContainer.aspx/index.html | 8 +- .../index.html | 8 +- .../EncapsulationOfProperties.aspx/index.html | 8 +- .../18/RangersAndZookeepers.aspx/index.html | 8 +- .../index.html | 8 +- 2013/01/07/RoleHints.aspx/index.html | 8 +- 2013/01/07/TypeNameRoleHints.aspx/index.html | 8 +- .../08/ArgumentNameRoleHint.aspx/index.html | 8 +- 2013/01/09/MetadataRoleHint.aspx/index.html | 8 +- .../index.html | 8 +- .../10/RoleInterfaceRoleHint.aspx/index.html | 8 +- .../PartialTypeNameRoleHint.aspx/index.html | 8 +- .../index.html | 8 +- .../BewareOfProductivityTools.aspx/index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- .../index.html | 8 +- 2013/03/01/AutoFixture3.aspx/index.html | 8 +- README.md | 4 +- _includes/themes/ploeh/contact_sidebar.html | 4 +- _posts/2009-01-28-Zero-FrictionTDD.html | 14 +- _posts/2009-02-13-SUTFactory.html | 6 +- ...edValuesEnsureExecutableSpecification.html | 4 +- ...2009-03-05-ConstrainedNon-Determinism.html | 10 +- ...03-10-Specification-DrivenDevelopment.html | 6 +- _posts/2009-03-11-ExplicitExpectations.html | 4 +- _posts/2009-03-16-FixtureObject.html | 4 +- _posts/2009-03-22-AnnouncingAutoFixture.html | 10 +- _posts/2009-03-23-JoiningSafewhere.html | 2 +- ...09-03-24-HowAutoFixtureCreatesObjects.html | 8 +- ...-04-02-CreatingStringsWithAutoFixture.html | 6 +- ...-04-03-CreatingNumbersWithAutoFixture.html | 6 +- ...04-19-CreatingBooleansWithAutoFixture.html | 2 +- ...ingWithTypesWithoutPublicConstructors.html | 4 +- ...eplacingAutoFixturesDefaultAlgorithms.html | 6 +- ...009-05-01-DealingWithConstrainedInput.html | 10 +- ...-05-05-ManagingLooselyCoupledProjects.html | 2 +- ...-11-AnonymousSequencesWithAutoFixture.html | 2 +- ...2009-05-15-AutoFixtureAsFixtureObject.html | 6 +- ...ze()ThrowsCOMExceptionWhenUnitTesting.html | 2 +- ...dingAnonymousVariablesWithAutoFixture.html | 6 +- ...abilityIsReallyTheOpenClosedPrinciple.html | 2 +- ...dingAnonymousVariablesWithAutoFixture.html | 2 +- ...09-07-01-AutoFixtureAsTestDataBuilder.html | 2 +- ...2009-07-16-DataTemplatingInASP.NETMVC.html | 6 +- ...-DisablingAutoPropertiesInAutoFixture.html | 8 +- ...rfaceForTestingINotifyPropertyChanged.html | 2 +- ...gOnlyCertainPropertiesWithAutoFixture.html | 2 +- _posts/2009-08-25-DoRedux.html | 14 +- .../2009-09-02-AutoFixture.8.5Released.html | 2 +- ...-Self-updatingAJAXlinkswithASP.NETMVC.html | 4 +- ...tomizingAType'sBuilderWithAutoFixture.html | 4 +- _posts/2009-10-05-Writingabook.html | 6 +- _posts/2009-10-26-AnonymousWith.html | 4 +- ...gth-constrainedstringswithAutoFixture.html | 4 +- ...bRequestlifestylewithASP.NETMVConIIS7.html | 2 +- ...12-01-GlobalErrorHandlinginASP.NETMVC.html | 6 +- ...dingandassigningarrayswithAutoFixture.html | 8 +- _posts/2009-12-07-LoggingExceptionFilter.html | 2 +- ....NETMVCErrorHandlingwithCastleWindsor.html | 2 +- _posts/2010-01-04-AnonymousGet.html | 4 +- ...010-01-20-EnablingDIforLazyComponents.html | 18 +-- ...Constructorover-injectionanti-pattern.html | 8 +- ...25-DependencyInjectionInversionin.NET.html | 10 +- _posts/2010-01-26-IWindsorInstaller.html | 20 +-- _posts/2010-01-27-AutoFixture1.0.html | 4 +- ...27-What'ssodangerousaboutaDIattribute.html | 6 +- ...-02-02-RefactoringtoAggregateServices.html | 10 +- ...-02-03-ServiceLocatorisanAnti-Pattern.html | 74 +++++----- _posts/2010-03-17-AutoFixtureFreeze.html | 8 +- _posts/2010-03-26-Moreaboutfrozenpizza.html | 8 +- _posts/2010-03-27-Freezingmocks.html | 8 +- ...010-04-06-MappingtypeswithAutoFixture.html | 4 +- ...07-DependencyInjectionisLooseCoupling.html | 12 +- ...6-WhyImmigratingfromMSTesttoxUnit.net.html | 6 +- ...0-05-18-SneakviewatCastlesWCFFacility.html | 6 +- ...-06-29-IntroducingAutoFixtureLikeness.html | 4 +- ...-07-12-DomainObjectsandIDataErrorInfo.html | 10 +- _posts/2010-08-09-AutoFixture2.0beta1.html | 4 +- ...-AutoFixtureasanauto-mockingcontainer.html | 14 +- ...aviorofAutoFixtureauto-mockingwithMoq.html | 2 +- ...8-30-Dontcallthecontainer;itllcallyou.html | 6 +- _posts/2010-09-13-MyfutureisAzure.html | 2 +- ...entationwithDecoratorsandInterceptors.html | 6 +- ...9-29-TheRegisterResolveReleasepattern.html | 4 +- ...10-08-AutoDataTheorieswithAutoFixture.html | 10 +- _posts/2010-10-10-AutoFixture2.0Released.html | 2 +- ...on-basedCustomizationswithAutoFixture.html | 12 +- ...nitionAbstractFactoryorServiceLocator.html | 6 +- ...ctoringfromAbstractFactorytoDecorator.html | 14 +- ...ngfromServiceLocatortoAbstractFactory.html | 6 +- ...ocks-basedauto-mockingwithAutoFixture.html | 2 +- ...egratingAutoFixturewithObjectHydrator.html | 2 +- ...10-12-02-Interfacesarenotabstractions.html | 28 ++-- .../2010-12-03-Towardsbetterabstractions.html | 12 +- ...stractionsPrincipleandServiceLocators.html | 4 +- _posts/2010-12-22-TheTDDApostate.html | 14 +- ...24-ChallengeResolveclosedtypeswithMEF.html | 2 +- ...-01-01-MyChristmaschallengehasawinner.html | 2 +- _posts/2011-01-24-Scalabledoesntmeanfast.html | 2 +- ...011-02-04-TheBCLalreadyhasaMaybemonad.html | 8 +- ...specificpopulatedlistswithAutoFixture.html | 6 +- ...ggeneralpopulatedlistswithAutoFixture.html | 6 +- ...11-02-28-Interfacesareaccessmodifiers.html | 8 +- ...3-InjectionConstructorsshouldbesimple.html | 6 +- ...-04-Composeobjectgraphswithconfidence.html | 18 +-- ...011-03-14-ResolvingclosedtypeswithMEF.html | 2 +- ...ncapsulatingAutoFixtureCustomizations.html | 4 +- _posts/2011-03-22-CommandsareComposable.html | 8 +- ...agazinearticleaboutCQRSonWindowsAzure.html | 2 +- ...numerablesaredynamicalsoinAutoFixture.html | 10 +- ...9-ConstructorstrategiesforAutoFixture.html | 6 +- _posts/2011-04-27-Providerisnotapattern.html | 14 +- ...-04-29-Feedbackmechanismsandtradeoffs.html | 6 +- ...grationsmellSQLServerover-utilization.html | 2 +- ...05-09-GenericunittestingwithxUnit.net.html | 2 +- ...tabletypesandacyclomaticcomplexityof1.html | 4 +- ...011-05-24-DesignSmellTemporalCoupling.html | 30 ++-- ...4-Poka-yokeDesignFromSmelltoFragrance.html | 28 ++-- ...1-05-25-DesignSmellPrimitiveObsession.html | 14 +- ...2011-05-26-CodeSmellAutomaticProperty.html | 24 ++-- ...DesignSmellRedundantRequiredAttribute.html | 14 +- ...1-05-30-DesignSmellDefaultConstructor.html | 14 +- ...ies,ApplicationsareNotObject-Oriented.html | 34 ++--- _posts/2011-06-07-SOLIDCodeisnt.html | 2 +- _posts/2011-07-28-CompositionRoot.html | 68 +++++----- ...08-25-ServiceLocatorrolesvs.mechanics.html | 14 +- ...tinuousDeliverywithSemanticVersioning.html | 2 +- ...sageDispatchingwithoutServiceLocation.html | 36 ++--- ...edversusStrongly-typedMessageChannels.html | 6 +- _posts/2011-10-25-SOLIDconcrete.html | 6 +- _posts/2011-11-08-Independency.html | 2 +- _posts/2011-11-10-TDDimprovesreusability.html | 2 +- _posts/2011-12-07-PolymorphicConsistency.html | 4 +- _posts/2011-12-19-FactoryOverload.html | 4 +- ...-12-21-TestingContainerConfigurations.html | 12 +- _posts/2012-01-03-SOLIDisAppend-only.html | 16 +-- ...2-02-02-LooseCouplingandtheBigPicture.html | 6 +- .../2012-02-09-IsLayeringWorththeMapping.html | 38 +++--- ...2-03-15-ImplementinganAbstractFactory.html | 34 ++--- ...MigratingfromWCFWebAPItoASP.NETWebAPI.html | 4 +- ...12-03-20-RobustDIWiththeASP.NETWebAPI.html | 16 +-- ...2012-03-26-IQueryableTisTightCoupling.html | 8 +- ...ControllerContextWiththeASP.NETWebAPI.html | 18 +-- ...ttpControllerContextWithCastleWindsor.html | 12 +- ...-VendorMediaTypesWiththeASP.NETWebAPI.html | 4 +- ...Dtestsuitesshouldrunin10secondsorless.html | 4 +- ...2-05-25-Designpatternsacrossparadigms.html | 6 +- .../2012-05-29-BankOCRkatainF#userstory1.html | 4 +- .../2012-06-01-BankOCRkatainF#userstory2.html | 6 +- ...06-04-BankOCRkatainF#userstories3and4.html | 12 +- _posts/2012-06-21-TheResemblanceidiom.html | 10 +- _posts/2012-06-22-ResemblanceandLikeness.html | 6 +- ...-specificEqualityversusDomainEquality.html | 6 +- _posts/2012-06-27-FacadeTest.html | 2 +- _posts/2012-07-02-PrimitiveDependencies.html | 8 +- _posts/2012-07-18-Hyprlinkr.html | 4 +- _posts/2012-07-20-FizzBuzzkatainF#stage1.html | 4 +- _posts/2012-07-25-FizzBuzzkatainF#stage2.html | 6 +- ...rderofAutoFixtureCustomizationsmatter.html | 6 +- _posts/2012-08-31-ConcreteDependencies.html | 6 +- ...ndLifetimeManagementwithASP.NETWebAPI.html | 18 +-- ...ctioninASP.NETWebAPIwithCastleWindsor.html | 32 ++--- _posts/2012-11-06-WhentouseaDIContainer.html | 22 +-- ...AppSettingsconventionforCastleWindsor.html | 8 +- .../2012-11-27-Encapsulationofproperties.html | 10 +- ...012-12-18-ZookeepersmustbecomeRangers.html | 12 +- _posts/2013-01-07-RoleHints.html | 10 +- _posts/2013-01-07-TypeNameRoleHints.html | 2 +- _posts/2013-01-08-ArgumentNameRoleHint.html | 4 +- _posts/2013-01-09-MetadataRoleHint.html | 12 +- ...SubstituteAuto-mockingwithAutoFixture.html | 2 +- _posts/2013-01-10-RoleInterfaceRoleHint.html | 8 +- .../2013-01-11-PartialTypeNameRoleHint.html | 4 +- ...st-DrivenDevelopmentPluralsightcourse.html | 2 +- ...6-StringCalculatorkatawithAutoFixture.html | 6 +- ...alculatorkatawithAutoFixtureexercise1.html | 8 +- ...alculatorkatawithAutofixtureexercise2.html | 4 +- ...alculatorkatawithAutofixtureexercise3.html | 4 +- ...alculatorkatawithAutofixtureexercise4.html | 6 +- ...alculatorkatawithAutofixtureexercise5.html | 8 +- ...alculatorkatawithAutofixtureexercise6.html | 4 +- ...alculatorkatawithAutofixtureexercise7.html | 4 +- ...alculatorkatawithAutofixtureexercise8.html | 2 +- _posts/2013-03-01-AutoFixture3.html | 2 +- .../2013-03-03-moving-the-blog-to-jekyll.html | 4 +- ...013-03-04-code-readability-hypotheses.html | 6 +- .../2013-03-04-outside-in-tdd-versus-ddd.html | 6 +- _posts/2013-03-08-test-trivial-code.html | 4 +- _posts/2013-03-11-auto-mocking-container.html | 4 +- .../2013-03-11-listen-to-trivial-tests.html | 10 +- _posts/2013-04-04-structural-inspection.html | 14 +- ...gure-automoq-to-set-up-all-properties.html | 2 +- ...ally-populate-properties-with-automoq.html | 2 +- ...ploeh-blog-syndication-feed-addresses.html | 6 +- .../2013-04-11-fizzbuzz-kata-in-clojure.html | 2 +- ...id-user-supplied-data-in-uri-segments.html | 2 +- _posts/2013-04-29-rest-lessons-learned.html | 10 +- ...st-lesson-learned-avoid-204-responses.html | 6 +- _posts/2013-05-01-herding-code-podcast.html | 2 +- ...st-lesson-learned-avoid-hackable-urls.html | 26 ++-- ...consider-a-home-link-on-all-resources.html | 6 +- ...consider-a-self-link-on-all-resources.html | 6 +- .../2013-06-17-where-to-put-unit-tests.html | 6 +- _posts/2013-07-08-defensive-coding.html | 8 +- _posts/2013-07-20-linq-versus-the-lsp.html | 6 +- ...reate-a-pure-f-aspnet-web-api-project.html | 4 +- ...g-a-pure-f-web-api-on-azure-web-sites.html | 2 +- ...09-06-dependency-injection-and-events.html | 10 +- ...i-and-events-constructor-subscription.html | 12 +- ...-09-di-and-events-third-party-connect.html | 10 +- ...-11-di-and-events-reactive-extensions.html | 12 +- .../2013-09-12-di-and-events-composition.html | 14 +- ...g-every-single-commit-in-a-git-branch.html | 4 +- ...eb-api-dtos-with-f-climutable-records.html | 12 +- ...-mocks-for-commands-stubs-for-queries.html | 2 +- ...versioning-with-continuous-deployment.html | 22 +-- _posts/2013-12-11-zerotonine.html | 4 +- _posts/2014-01-20-rest-efficiency.html | 2 +- ...et-package-restore-considered-harmful.html | 2 +- ...ng-nuget-with-autonomous-repositories.html | 8 +- ...-10-solid-the-next-step-is-functional.html | 16 +-- ...itrary-version-instances-with-fscheck.html | 2 +- ...3-21-composed-assertions-with-unquote.html | 2 +- ...1-autofixture-conventions-with-albedo.html | 4 +- ...-05-15-service-locator-violates-solid.html | 16 +-- ...2014-05-16-configuring-azure-web-jobs.html | 4 +- _posts/2014-05-19-conforming-container.html | 18 +-- _posts/2014-05-19-di-friendly-framework.html | 50 +++---- _posts/2014-05-19-di-friendly-library.html | 16 +-- ...-on-aspnet-vnext-dependency-injection.html | 6 +- _posts/2014-06-02-captive-dependency.html | 10 +- ...-06-03-compile-time-lifetime-matching.html | 28 ++-- _posts/2014-06-10-pure-di.html | 6 +- ...14-06-12-web-api-raygun-error-handler.html | 2 +- _posts/2014-06-13-passive-attributes.html | 28 ++-- _posts/2014-07-22-hire-me.html | 2 +- _posts/2014-07-23-drain.html | 6 +- ...sulation-and-solid-pluralsight-course.html | 6 +- _posts/2014-08-07-why-dry.html | 2 +- ...08-11-cqs-versus-server-generated-ids.html | 18 +-- _posts/2014-08-24-decoraptor.html | 10 +- ...014-08-25-decommissioning-decoraptors.html | 10 +- ...polling-consumer-with-scheduled-tasks.html | 6 +- ...g-methods-with-the-same-implemenation.html | 4 +- _posts/2014-12-16-name-this-operation.html | 4 +- _posts/2014-12-17-good-times-with-f.html | 2 +- ...xception-messages-are-for-programmers.html | 4 +- ...12-24-placement-of-abstract-factories.html | 18 +-- _posts/2015-01-06-composition-root-reuse.html | 24 ++-- .../2015-01-10-diamond-kata-with-fscheck.html | 2 +- ...imitive-obsession-to-domain-modelling.html | 24 ++-- _posts/2015-01-21-library-bundle-facade.html | 18 +-- ...impler-arbitrary-for-the-diamond-kata.html | 4 +- ...ut-a-property-based-testing-framework.html | 2 +- ...15-03-19-posting-json-to-an-f-web-api.html | 4 +- ...-04-13-less-is-more-language-features.html | 12 +- ...l-eventually-get-all-f-features-right.html | 6 +- ...onal-design-is-intrinsically-testable.html | 4 +- ...6-22-rest-implies-content-negotiation.html | 6 +- ...2015-08-03-idiomatic-or-idiosyncratic.html | 2 +- .../2015-08-10-type-driven-development.html | 10 +- ...n-development-implementing-shouldidle.html | 8 +- ...2-type-driven-development-composition.html | 16 +-- ...en-x-y-and-z-are-great-variable-names.html | 10 +- ...-ad-hoc-arbitraries-with-fscheckxunit.html | 2 +- ...2015-09-18-temporary-field-code-smell.html | 2 +- ...21-public-types-hidden-in-plain-sight.html | 20 +-- _posts/2015-09-22-unit-testing-internals.html | 14 +- ...3-applications-and-their-side-effects.html | 4 +- ...when-queries-should-have-side-effects.html | 14 +- .../2015-10-19-visual-value-verification.html | 2 +- ...ervice-locator-violates-encapsulation.html | 12 +- ...-11-13-null-has-no-type-but-maybe-has.html | 2 +- _posts/2015-11-30-to-log-or-not-to-log.html | 6 +- _posts/2015-12-01-recurse.html | 2 +- ...2-04-the-rules-of-attraction-location.html | 2 +- ...ntegration-testing-composed-functions.html | 4 +- _posts/2015-12-22-tail-recurse.html | 8 +- ...erties--software-designing-with-types.html | 4 +- ...016-02-10-types--properties--software.html | 20 +-- ...-software-state-transition-properties.html | 8 +- ...re-properties-for-the-advantage-state.html | 8 +- ...--software-properties-for-the-forties.html | 10 +- ...pes--properties--software-composition.html | 12 +- ...s--properties--software-initial-state.html | 6 +- ...erties--software-finite-state-machine.html | 6 +- ...properties--software-other-properties.html | 2 +- ...1-ad-hoc-arbitraries---now-with-pipes.html | 4 +- ...al-architecture-is-ports-and-adapters.html | 36 ++--- ...with-an-either-computation-expression.html | 6 +- _posts/2016-04-11-async-as-surrogate-io.html | 12 +- ...6-cqs-and-server-generated-entity-ids.html | 14 +- ...-05-17-tie-fighter-fscheck-properties.html | 4 +- _posts/2016-06-15-sut-double.html | 4 +- ...roman-numerals-via-property-based-tdd.html | 6 +- ...-conditional-composition-of-functions.html | 8 +- ...ttp-route-defaults-for-aspnet-web-api.html | 2 +- ...-26-decoupling-decisions-from-effects.html | 4 +- ...25-when-variable-names-are-in-the-way.html | 8 +- ...1-28-easy-domain-modelling-with-types.html | 10 +- ...2016-12-07-domain-modelling-with-rest.html | 14 +- ...016-12-16-from-rest-to-algebraic-data.html | 6 +- ...application-errors-from-domain-models.html | 8 +- ...ency-injection-is-passing-an-argument.html | 6 +- ...ncy-injection-to-dependency-rejection.html | 10 +- ...l-application-is-dependency-injection.html | 12 +- _posts/2017-02-02-dependency-rejection.html | 18 +-- ...3-30-a-reusable-apicontroller-adapter.html | 6 +- _posts/2017-04-24-simple-holidays.html | 8 +- ...30-using-polly-with-f-async-workflows.html | 2 +- _posts/2017-06-27-pure-times.html | 10 +- _posts/2017-06-28-pure-times-in-haskell.html | 14 +- _posts/2017-07-04-pure-times-in-f.html | 12 +- _posts/2017-07-10-pure-interactions.html | 18 +-- ...1-hello-pure-command-line-interaction.html | 10 +- ...2017-07-17-a-pure-command-line-wizard.html | 10 +- ...7-24-combining-free-monads-in-haskell.html | 10 +- ...2017-07-31-combining-free-monads-in-f.html | 24 ++-- _posts/2017-08-07-f-free-monad-recipe.html | 28 ++-- ...data-builders-to-the-identity-functor.html | 16 +-- .../2017-08-15-test-data-builders-in-c.html | 18 +-- ...7-08-21-generalised-test-data-builder.html | 8 +- _posts/2017-08-28-the-builder-functor.html | 10 +- _posts/2017-09-04-builder-as-identity.html | 6 +- ...2017-09-11-test-data-without-builders.html | 6 +- ...09-18-the-test-data-generator-functor.html | 6 +- ...-09-25-interception-vis-a-vis-pure-di.html | 8 +- ...-10-05-monoids-semigroups-and-friends.html | 44 +++--- _posts/2017-10-06-monoids.html | 32 ++--- ...rings-lists-and-sequences-as-a-monoid.html | 12 +- _posts/2017-10-16-money-monoid.html | 12 +- _posts/2017-10-23-convex-hull-monoid.html | 10 +- _posts/2017-10-30-tuple-monoids.html | 16 +-- ...om-design-patterns-to-category-theory.html | 128 +++++++++--------- _posts/2017-11-06-function-monoids.html | 8 +- _posts/2017-11-13-endomorphism-monoid.html | 14 +- _posts/2017-11-20-monoids-accumulate.html | 6 +- _posts/2017-11-27-semigroups.html | 6 +- _posts/2017-12-04-bounding-box-semigroup.html | 14 +- _posts/2017-12-11-semigroups-accumulate.html | 8 +- _posts/2017-12-18-quasigroups.html | 6 +- _posts/2017-12-27-magmas.html | 8 +- .../2017-12-28-rock-paper-scissors-magma.html | 8 +- _posts/2018-01-02-colour-mixing-magma.html | 10 +- ...18-01-08-software-design-isomorphisms.html | 28 ++-- _posts/2018-01-15-unit-isomorphisms.html | 8 +- _posts/2018-01-22-function-isomorphisms.html | 10 +- ...2018-01-29-argument-list-isomorphisms.html | 8 +- _posts/2018-02-05-uncurry-isomorphisms.html | 10 +- _posts/2018-02-12-object-isomorphisms.html | 10 +- ...2018-02-19-abstract-class-isomorphism.html | 34 ++--- ...6-inheritance-composition-isomorphism.html | 8 +- ...gn-patterns-as-universal-abstractions.html | 20 +-- _posts/2018-03-12-composite-as-a-monoid.html | 28 ++-- ...-19-functors-applicatives-and-friends.html | 48 +++---- _posts/2018-03-22-functors.html | 28 ++-- _posts/2018-03-26-the-maybe-functor.html | 12 +- _posts/2018-04-03-maybe-monoids.html | 12 +- ...4-09-coalescing-composite-as-a-monoid.html | 16 +-- ...-16-endomorphic-composite-as-a-monoid.html | 12 +- .../2018-04-23-null-object-as-identity.html | 28 ++-- ...30-parametrised-unit-tests-in-haskell.html | 6 +- .../2018-05-07-inlined-hunit-test-lists.html | 2 +- ...roject-arbitraries-with-view-patterns.html | 6 +- ...s-a-monoid---a-business-rules-example.html | 14 +- _posts/2018-05-22-church-encoding.html | 18 +-- ...8-05-24-church-encoded-boolean-values.html | 10 +- ...-05-28-church-encoded-natural-numbers.html | 10 +- _posts/2018-06-04-church-encoded-maybe.html | 12 +- _posts/2018-06-11-church-encoded-either.html | 18 +-- ...18-06-18-church-encoded-payment-types.html | 8 +- _posts/2018-06-25-visitor-as-a-sum-type.html | 16 +-- ...tors-make-business-code-more-readable.html | 2 +- ...8-07-09-typing-and-testing-problem-23.html | 6 +- .../2018-07-16-angular-addition-monoid.html | 6 +- ...-07-24-dependency-injection-revisited.html | 26 ++-- ...ng-arrow-code-using-a-stack-of-monads.html | 6 +- _posts/2018-08-06-a-tree-functor.html | 6 +- _posts/2018-08-13-a-visitor-functor.html | 14 +- _posts/2018-08-20-reactive-functor.html | 6 +- ...8-08-27-on-constructor-over-injection.html | 2 +- _posts/2018-09-03-the-identity-functor.html | 6 +- _posts/2018-09-10-the-lazy-functor.html | 6 +- ...yping-is-not-a-programming-bottleneck.html | 10 +- _posts/2018-09-24-asynchronous-functors.html | 10 +- _posts/2018-10-01-applicative-functors.html | 22 +-- _posts/2018-10-08-full-deck.html | 6 +- ...18-10-15-an-applicative-password-list.html | 6 +- ...applicative-combinations-of-functions.html | 8 +- ...8-10-29-the-maybe-applicative-functor.html | 22 +-- _posts/2018-11-05-applicative-validation.html | 6 +- ...18-11-12-what-to-test-and-not-to-test.html | 14 +- ...-functional-architecture-a-definition.html | 22 +-- ...st-data-generator-applicative-functor.html | 8 +- _posts/2018-12-03-set-is-not-a-functor.html | 8 +- .../2018-12-10-danish-cpr-numbers-in-f.html | 20 +-- ...18-12-17-the-lazy-applicative-functor.html | 14 +- _posts/2018-12-24-bifunctors.html | 10 +- _posts/2018-12-31-tuple-bifunctor.html | 6 +- _posts/2019-01-07-either-bifunctor.html | 6 +- _posts/2019-01-14-an-either-functor.html | 6 +- ...-01-21-some-thoughts-on-anti-patterns.html | 4 +- ...9-01-28-better-abstractions-revisited.html | 30 ++-- ...how-to-get-the-value-out-of-the-monad.html | 20 +-- _posts/2019-02-11-asynchronous-injection.html | 40 +++--- ...eraction-based-to-state-based-testing.html | 8 +- ...ple-of-interaction-based-testing-in-c.html | 12 +- about.html | 2 +- hire-me.html | 10 +- support.html | 2 +- 639 files changed, 2962 insertions(+), 2962 deletions(-) diff --git a/2009/01/28/LivingInInterestingTimes.aspx/index.html b/2009/01/28/LivingInInterestingTimes.aspx/index.html index 28951c461..5758beff1 100644 --- a/2009/01/28/LivingInInterestingTimes.aspx/index.html +++ b/2009/01/28/LivingInInterestingTimes.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/01/28/LivingInInterestingTimes. + This page has moved to /2009/01/28/LivingInInterestingTimes. \ No newline at end of file diff --git a/2009/01/28/ZeroFrictionTDD.aspx/index.html b/2009/01/28/ZeroFrictionTDD.aspx/index.html index 82b7aac5e..c5a1072ab 100644 --- a/2009/01/28/ZeroFrictionTDD.aspx/index.html +++ b/2009/01/28/ZeroFrictionTDD.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/01/28/Zero-FrictionTDD. + This page has moved to /2009/01/28/Zero-FrictionTDD. \ No newline at end of file diff --git a/2009/02/13/SUTFactory.aspx/index.html b/2009/02/13/SUTFactory.aspx/index.html index 80dd0104d..c5deade99 100644 --- a/2009/02/13/SUTFactory.aspx/index.html +++ b/2009/02/13/SUTFactory.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/02/13/SUTFactory. + This page has moved to /2009/02/13/SUTFactory. \ No newline at end of file diff --git a/2009/02/22/UpdatingDetachedEntitiesWithLINQToEntities.aspx/index.html b/2009/02/22/UpdatingDetachedEntitiesWithLINQToEntities.aspx/index.html index 17e0dcb24..d14f93d12 100644 --- a/2009/02/22/UpdatingDetachedEntitiesWithLINQToEntities.aspx/index.html +++ b/2009/02/22/UpdatingDetachedEntitiesWithLINQToEntities.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/02/22/UpdatingDetachedEntitiesWithLINQToEntities. + This page has moved to /2009/02/22/UpdatingDetachedEntitiesWithLINQToEntities. \ No newline at end of file diff --git a/2009/03/03/DerivedValuesEnsureExecutableSpecification.aspx/index.html b/2009/03/03/DerivedValuesEnsureExecutableSpecification.aspx/index.html index d8c8f49ee..1f10ad6ac 100644 --- a/2009/03/03/DerivedValuesEnsureExecutableSpecification.aspx/index.html +++ b/2009/03/03/DerivedValuesEnsureExecutableSpecification.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/03/DerivedValuesEnsureExecutableSpecification. + This page has moved to /2009/03/03/DerivedValuesEnsureExecutableSpecification. \ No newline at end of file diff --git a/2009/03/05/ConstrainedNonDeterminism.aspx/index.html b/2009/03/05/ConstrainedNonDeterminism.aspx/index.html index 11378e49d..2d3d6238e 100644 --- a/2009/03/05/ConstrainedNonDeterminism.aspx/index.html +++ b/2009/03/05/ConstrainedNonDeterminism.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/05/ConstrainedNon-Determinism. + This page has moved to /2009/03/05/ConstrainedNon-Determinism. \ No newline at end of file diff --git a/2009/03/10/SpecificationDrivenDevelopment.aspx/index.html b/2009/03/10/SpecificationDrivenDevelopment.aspx/index.html index 6a9debce0..90f1e8d30 100644 --- a/2009/03/10/SpecificationDrivenDevelopment.aspx/index.html +++ b/2009/03/10/SpecificationDrivenDevelopment.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/10/Specification-DrivenDevelopment. + This page has moved to /2009/03/10/Specification-DrivenDevelopment. \ No newline at end of file diff --git a/2009/03/11/ExplicitExpectations.aspx/index.html b/2009/03/11/ExplicitExpectations.aspx/index.html index 68f907733..59728d4ad 100644 --- a/2009/03/11/ExplicitExpectations.aspx/index.html +++ b/2009/03/11/ExplicitExpectations.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/11/ExplicitExpectations. + This page has moved to /2009/03/11/ExplicitExpectations. \ No newline at end of file diff --git a/2009/03/16/FixtureObject.aspx/index.html b/2009/03/16/FixtureObject.aspx/index.html index 2a1b4e2d3..2dd41ba5c 100644 --- a/2009/03/16/FixtureObject.aspx/index.html +++ b/2009/03/16/FixtureObject.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/16/FixtureObject. + This page has moved to /2009/03/16/FixtureObject. \ No newline at end of file diff --git a/2009/03/22/AnnouncingAutoFixture.aspx/index.html b/2009/03/22/AnnouncingAutoFixture.aspx/index.html index 1849a38ad..7119275c0 100644 --- a/2009/03/22/AnnouncingAutoFixture.aspx/index.html +++ b/2009/03/22/AnnouncingAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/22/AnnouncingAutoFixture. + This page has moved to /2009/03/22/AnnouncingAutoFixture. \ No newline at end of file diff --git a/2009/03/23/JoiningSafewhere.aspx/index.html b/2009/03/23/JoiningSafewhere.aspx/index.html index 66ed599e0..c414813a4 100644 --- a/2009/03/23/JoiningSafewhere.aspx/index.html +++ b/2009/03/23/JoiningSafewhere.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/23/JoiningSafewhere. + This page has moved to /2009/03/23/JoiningSafewhere. \ No newline at end of file diff --git a/2009/03/24/HowAutoFixtureCreatesObjects.aspx/index.html b/2009/03/24/HowAutoFixtureCreatesObjects.aspx/index.html index 6acdb893c..8875f2873 100644 --- a/2009/03/24/HowAutoFixtureCreatesObjects.aspx/index.html +++ b/2009/03/24/HowAutoFixtureCreatesObjects.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/03/24/HowAutoFixtureCreatesObjects. + This page has moved to /2009/03/24/HowAutoFixtureCreatesObjects. \ No newline at end of file diff --git a/2009/04/02/CreatingStringsWithAutoFixture.aspx/index.html b/2009/04/02/CreatingStringsWithAutoFixture.aspx/index.html index c4bc94256..eec3803e3 100644 --- a/2009/04/02/CreatingStringsWithAutoFixture.aspx/index.html +++ b/2009/04/02/CreatingStringsWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/04/02/CreatingStringsWithAutoFixture. + This page has moved to /2009/04/02/CreatingStringsWithAutoFixture. \ No newline at end of file diff --git a/2009/04/03/CreatingNumbersWithAutoFixture.aspx/index.html b/2009/04/03/CreatingNumbersWithAutoFixture.aspx/index.html index 87b6b95be..072279980 100644 --- a/2009/04/03/CreatingNumbersWithAutoFixture.aspx/index.html +++ b/2009/04/03/CreatingNumbersWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/04/03/CreatingNumbersWithAutoFixture. + This page has moved to /2009/04/03/CreatingNumbersWithAutoFixture. \ No newline at end of file diff --git a/2009/04/19/CreatingBooleansWithAutoFixture.aspx/index.html b/2009/04/19/CreatingBooleansWithAutoFixture.aspx/index.html index 50c0b3527..56c3a9477 100644 --- a/2009/04/19/CreatingBooleansWithAutoFixture.aspx/index.html +++ b/2009/04/19/CreatingBooleansWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/04/19/CreatingBooleansWithAutoFixture. + This page has moved to /2009/04/19/CreatingBooleansWithAutoFixture. \ No newline at end of file diff --git a/2009/04/23/DealingWithTypesWithoutPublicConstructors.aspx/index.html b/2009/04/23/DealingWithTypesWithoutPublicConstructors.aspx/index.html index 872bfa9dc..75632abf2 100644 --- a/2009/04/23/DealingWithTypesWithoutPublicConstructors.aspx/index.html +++ b/2009/04/23/DealingWithTypesWithoutPublicConstructors.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/04/23/DealingWithTypesWithoutPublicConstructors. + This page has moved to /2009/04/23/DealingWithTypesWithoutPublicConstructors. \ No newline at end of file diff --git a/2009/04/27/ReplacingAutoFixturesDefaultAlgorithms.aspx/index.html b/2009/04/27/ReplacingAutoFixturesDefaultAlgorithms.aspx/index.html index ce828822f..f213727fa 100644 --- a/2009/04/27/ReplacingAutoFixturesDefaultAlgorithms.aspx/index.html +++ b/2009/04/27/ReplacingAutoFixturesDefaultAlgorithms.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/04/27/ReplacingAutoFixturesDefaultAlgorithms. + This page has moved to /2009/04/27/ReplacingAutoFixturesDefaultAlgorithms. \ No newline at end of file diff --git a/2009/04/28/SpeakingAt7NITConference2009.aspx/index.html b/2009/04/28/SpeakingAt7NITConference2009.aspx/index.html index 9fac3c463..523a0bdc7 100644 --- a/2009/04/28/SpeakingAt7NITConference2009.aspx/index.html +++ b/2009/04/28/SpeakingAt7NITConference2009.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/04/28/Speakingat7NITConference2009. + This page has moved to /2009/04/28/Speakingat7NITConference2009. \ No newline at end of file diff --git a/2009/05/01/DealingWithConstrainedInput.aspx/index.html b/2009/05/01/DealingWithConstrainedInput.aspx/index.html index e9fe29a1c..351f25737 100644 --- a/2009/05/01/DealingWithConstrainedInput.aspx/index.html +++ b/2009/05/01/DealingWithConstrainedInput.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/01/DealingWithConstrainedInput. + This page has moved to /2009/05/01/DealingWithConstrainedInput. \ No newline at end of file diff --git a/2009/05/05/ManagingLooselyCoupledProjects.aspx/index.html b/2009/05/05/ManagingLooselyCoupledProjects.aspx/index.html index c0d725862..c5b4601f4 100644 --- a/2009/05/05/ManagingLooselyCoupledProjects.aspx/index.html +++ b/2009/05/05/ManagingLooselyCoupledProjects.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/05/ManagingLooselyCoupledProjects. + This page has moved to /2009/05/05/ManagingLooselyCoupledProjects. \ No newline at end of file diff --git a/2009/05/11/AnonymousSequencesWithAutoFixture.aspx/index.html b/2009/05/11/AnonymousSequencesWithAutoFixture.aspx/index.html index c09d31828..5a24653a3 100644 --- a/2009/05/11/AnonymousSequencesWithAutoFixture.aspx/index.html +++ b/2009/05/11/AnonymousSequencesWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/11/AnonymousSequencesWithAutoFixture. + This page has moved to /2009/05/11/AnonymousSequencesWithAutoFixture. \ No newline at end of file diff --git a/2009/05/15/AutoFixtureAsFixtureObject.aspx/index.html b/2009/05/15/AutoFixtureAsFixtureObject.aspx/index.html index 588cb4137..2e82a61c0 100644 --- a/2009/05/15/AutoFixtureAsFixtureObject.aspx/index.html +++ b/2009/05/15/AutoFixtureAsFixtureObject.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/15/AutoFixtureAsFixtureObject. + This page has moved to /2009/05/15/AutoFixtureAsFixtureObject. \ No newline at end of file diff --git a/2009/05/17/AutoFixture.8.1Released.aspx/index.html b/2009/05/17/AutoFixture.8.1Released.aspx/index.html index 8274fb127..fa9f9ff15 100644 --- a/2009/05/17/AutoFixture.8.1Released.aspx/index.html +++ b/2009/05/17/AutoFixture.8.1Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/17/AutoFixture.8.1Released. + This page has moved to /2009/05/17/AutoFixture.8.1Released. \ No newline at end of file diff --git a/2009/05/17/AutoFixture81Released.aspx/index.html b/2009/05/17/AutoFixture81Released.aspx/index.html index 8274fb127..fa9f9ff15 100644 --- a/2009/05/17/AutoFixture81Released.aspx/index.html +++ b/2009/05/17/AutoFixture81Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/17/AutoFixture.8.1Released. + This page has moved to /2009/05/17/AutoFixture.8.1Released. \ No newline at end of file diff --git a/2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html b/2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html index c2df25e67..a4cb7edd1 100644 --- a/2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html +++ b/2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting. + This page has moved to /2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting. \ No newline at end of file diff --git a/2009/05/21/SyncOrchestratorSynchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html b/2009/05/21/SyncOrchestratorSynchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html index c2df25e67..a4cb7edd1 100644 --- a/2009/05/21/SyncOrchestratorSynchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html +++ b/2009/05/21/SyncOrchestratorSynchronize()ThrowsCOMExceptionWhenUnitTesting.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting. + This page has moved to /2009/05/21/SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting. \ No newline at end of file diff --git a/2009/05/26/TheAutoFixtureBuilder.aspx/index.html b/2009/05/26/TheAutoFixtureBuilder.aspx/index.html index bfe80f47a..48659e87f 100644 --- a/2009/05/26/TheAutoFixtureBuilder.aspx/index.html +++ b/2009/05/26/TheAutoFixtureBuilder.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/26/TheAutoFixtureBuilder. + This page has moved to /2009/05/26/TheAutoFixtureBuilder. \ No newline at end of file diff --git a/2009/05/28/DelegatesAreAnonymousInterfaces.aspx/index.html b/2009/05/28/DelegatesAreAnonymousInterfaces.aspx/index.html index 207f6b2a6..19a127c71 100644 --- a/2009/05/28/DelegatesAreAnonymousInterfaces.aspx/index.html +++ b/2009/05/28/DelegatesAreAnonymousInterfaces.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/05/28/DelegatesAreAnonymousInterfaces. + This page has moved to /2009/05/28/DelegatesAreAnonymousInterfaces. \ No newline at end of file diff --git a/2009/06/01/SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html b/2009/06/01/SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html index 047c838fc..b79b7ee63 100644 --- a/2009/06/01/SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html +++ b/2009/06/01/SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/01/SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture. + This page has moved to /2009/06/01/SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture. \ No newline at end of file diff --git a/2009/06/04/AutoFixtureCheatSheet.aspx/index.html b/2009/06/04/AutoFixtureCheatSheet.aspx/index.html index b6a30d6c0..d04d51467 100644 --- a/2009/06/04/AutoFixtureCheatSheet.aspx/index.html +++ b/2009/06/04/AutoFixtureCheatSheet.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/04/AutoFixtureCheatSheet. + This page has moved to /2009/06/04/AutoFixtureCheatSheet. \ No newline at end of file diff --git a/2009/06/05/TestabilityIsReallyTheOpenClosedPrinciple.aspx/index.html b/2009/06/05/TestabilityIsReallyTheOpenClosedPrinciple.aspx/index.html index 94579bf49..1e18dfd1c 100644 --- a/2009/06/05/TestabilityIsReallyTheOpenClosedPrinciple.aspx/index.html +++ b/2009/06/05/TestabilityIsReallyTheOpenClosedPrinciple.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/05/TestabilityIsReallyTheOpenClosedPrinciple. + This page has moved to /2009/06/05/TestabilityIsReallyTheOpenClosedPrinciple. \ No newline at end of file diff --git a/2009/06/05/Tweet.aspx/index.html b/2009/06/05/Tweet.aspx/index.html index 192799a96..3a80d469b 100644 --- a/2009/06/05/Tweet.aspx/index.html +++ b/2009/06/05/Tweet.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/05/Tweet. + This page has moved to /2009/06/05/Tweet. \ No newline at end of file diff --git a/2009/06/09/CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html b/2009/06/09/CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html index f8160a3dd..d975f37ce 100644 --- a/2009/06/09/CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html +++ b/2009/06/09/CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/09/CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture. + This page has moved to /2009/06/09/CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture. \ No newline at end of file diff --git a/2009/06/18/AutoFixture.8.2Released.aspx/index.html b/2009/06/18/AutoFixture.8.2Released.aspx/index.html index a2058cc7b..1cc56d467 100644 --- a/2009/06/18/AutoFixture.8.2Released.aspx/index.html +++ b/2009/06/18/AutoFixture.8.2Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/18/AutoFixture.8.2Released. + This page has moved to /2009/06/18/AutoFixture.8.2Released. \ No newline at end of file diff --git a/2009/06/18/AutoFixture82Released.aspx/index.html b/2009/06/18/AutoFixture82Released.aspx/index.html index a2058cc7b..1cc56d467 100644 --- a/2009/06/18/AutoFixture82Released.aspx/index.html +++ b/2009/06/18/AutoFixture82Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/18/AutoFixture.8.2Released. + This page has moved to /2009/06/18/AutoFixture.8.2Released. \ No newline at end of file diff --git a/2009/06/20/AutoFixture.8.3Released.aspx/index.html b/2009/06/20/AutoFixture.8.3Released.aspx/index.html index d9ac7b9e8..5a94e06c6 100644 --- a/2009/06/20/AutoFixture.8.3Released.aspx/index.html +++ b/2009/06/20/AutoFixture.8.3Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/20/AutoFixture.8.3Released. + This page has moved to /2009/06/20/AutoFixture.8.3Released. \ No newline at end of file diff --git a/2009/06/20/AutoFixture83Released.aspx/index.html b/2009/06/20/AutoFixture83Released.aspx/index.html index d9ac7b9e8..5a94e06c6 100644 --- a/2009/06/20/AutoFixture83Released.aspx/index.html +++ b/2009/06/20/AutoFixture83Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/20/AutoFixture.8.3Released. + This page has moved to /2009/06/20/AutoFixture.8.3Released. \ No newline at end of file diff --git a/2009/06/22/CustomTokensOverNonHTTPTransports.aspx/index.html b/2009/06/22/CustomTokensOverNonHTTPTransports.aspx/index.html index 50f0d1f39..81ec9fe7e 100644 --- a/2009/06/22/CustomTokensOverNonHTTPTransports.aspx/index.html +++ b/2009/06/22/CustomTokensOverNonHTTPTransports.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/06/22/CustomTokensOverNon-HTTPTransports. + This page has moved to /2009/06/22/CustomTokensOverNon-HTTPTransports. \ No newline at end of file diff --git a/2009/07/01/AutoFixtureAsTestDataBuilder.aspx/index.html b/2009/07/01/AutoFixtureAsTestDataBuilder.aspx/index.html index b99d44cbf..078037a4a 100644 --- a/2009/07/01/AutoFixtureAsTestDataBuilder.aspx/index.html +++ b/2009/07/01/AutoFixtureAsTestDataBuilder.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/07/01/AutoFixtureAsTestDataBuilder. + This page has moved to /2009/07/01/AutoFixtureAsTestDataBuilder. \ No newline at end of file diff --git a/2009/07/11/AutoFixture.8.4AndRoadmap.aspx/index.html b/2009/07/11/AutoFixture.8.4AndRoadmap.aspx/index.html index bcf15292e..f4fdb0b08 100644 --- a/2009/07/11/AutoFixture.8.4AndRoadmap.aspx/index.html +++ b/2009/07/11/AutoFixture.8.4AndRoadmap.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/07/11/AutoFixture.8.4AndRoadmap. + This page has moved to /2009/07/11/AutoFixture.8.4AndRoadmap. \ No newline at end of file diff --git a/2009/07/11/AutoFixture84AndRoadmap.aspx/index.html b/2009/07/11/AutoFixture84AndRoadmap.aspx/index.html index bcf15292e..f4fdb0b08 100644 --- a/2009/07/11/AutoFixture84AndRoadmap.aspx/index.html +++ b/2009/07/11/AutoFixture84AndRoadmap.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/07/11/AutoFixture.8.4AndRoadmap. + This page has moved to /2009/07/11/AutoFixture.8.4AndRoadmap. \ No newline at end of file diff --git a/2009/07/16/DataTemplatingInASP.NETMVC.aspx/index.html b/2009/07/16/DataTemplatingInASP.NETMVC.aspx/index.html index ce3ff807b..34894e417 100644 --- a/2009/07/16/DataTemplatingInASP.NETMVC.aspx/index.html +++ b/2009/07/16/DataTemplatingInASP.NETMVC.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/07/16/DataTemplatingInASP.NETMVC. + This page has moved to /2009/07/16/DataTemplatingInASP.NETMVC. \ No newline at end of file diff --git a/2009/07/16/DataTemplatingInASPNETMVC.aspx/index.html b/2009/07/16/DataTemplatingInASPNETMVC.aspx/index.html index ce3ff807b..34894e417 100644 --- a/2009/07/16/DataTemplatingInASPNETMVC.aspx/index.html +++ b/2009/07/16/DataTemplatingInASPNETMVC.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/07/16/DataTemplatingInASP.NETMVC. + This page has moved to /2009/07/16/DataTemplatingInASP.NETMVC. \ No newline at end of file diff --git a/2009/07/23/DisablingAutoPropertiesInAutoFixture.aspx/index.html b/2009/07/23/DisablingAutoPropertiesInAutoFixture.aspx/index.html index c918a2750..0d16803b7 100644 --- a/2009/07/23/DisablingAutoPropertiesInAutoFixture.aspx/index.html +++ b/2009/07/23/DisablingAutoPropertiesInAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/07/23/DisablingAutoPropertiesInAutoFixture. + This page has moved to /2009/07/23/DisablingAutoPropertiesInAutoFixture. \ No newline at end of file diff --git a/2009/08/06/AFluentInterfaceForTestingINotifyPropertyChanged.aspx/index.html b/2009/08/06/AFluentInterfaceForTestingINotifyPropertyChanged.aspx/index.html index 19d3ec1c7..98273e021 100644 --- a/2009/08/06/AFluentInterfaceForTestingINotifyPropertyChanged.aspx/index.html +++ b/2009/08/06/AFluentInterfaceForTestingINotifyPropertyChanged.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/08/06/AFluentInterfaceForTestingINotifyPropertyChanged. + This page has moved to /2009/08/06/AFluentInterfaceForTestingINotifyPropertyChanged. \ No newline at end of file diff --git a/2009/08/17/OmittingOnlyCertainPropertiesWithAutoFixture.aspx/index.html b/2009/08/17/OmittingOnlyCertainPropertiesWithAutoFixture.aspx/index.html index ec0f079a9..264d873f6 100644 --- a/2009/08/17/OmittingOnlyCertainPropertiesWithAutoFixture.aspx/index.html +++ b/2009/08/17/OmittingOnlyCertainPropertiesWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/08/17/OmittingOnlyCertainPropertiesWithAutoFixture. + This page has moved to /2009/08/17/OmittingOnlyCertainPropertiesWithAutoFixture. \ No newline at end of file diff --git a/2009/08/25/DoRedux.aspx/index.html b/2009/08/25/DoRedux.aspx/index.html index f73b8a7ba..a94b163e4 100644 --- a/2009/08/25/DoRedux.aspx/index.html +++ b/2009/08/25/DoRedux.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/08/25/DoRedux. + This page has moved to /2009/08/25/DoRedux. \ No newline at end of file diff --git a/2009/09/02/AutoFixture.8.5Released.aspx/index.html b/2009/09/02/AutoFixture.8.5Released.aspx/index.html index b401eef9a..7cce8fb8e 100644 --- a/2009/09/02/AutoFixture.8.5Released.aspx/index.html +++ b/2009/09/02/AutoFixture.8.5Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/02/AutoFixture.8.5Released. + This page has moved to /2009/09/02/AutoFixture.8.5Released. \ No newline at end of file diff --git a/2009/09/02/AutoFixture85Released.aspx/index.html b/2009/09/02/AutoFixture85Released.aspx/index.html index b401eef9a..7cce8fb8e 100644 --- a/2009/09/02/AutoFixture85Released.aspx/index.html +++ b/2009/09/02/AutoFixture85Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/02/AutoFixture.8.5Released. + This page has moved to /2009/09/02/AutoFixture.8.5Released. \ No newline at end of file diff --git a/2009/09/07/SelfupdatingAJAXLinksWithASP.NETMVC.aspx/index.html b/2009/09/07/SelfupdatingAJAXLinksWithASP.NETMVC.aspx/index.html index 597480a3b..7aa45e913 100644 --- a/2009/09/07/SelfupdatingAJAXLinksWithASP.NETMVC.aspx/index.html +++ b/2009/09/07/SelfupdatingAJAXLinksWithASP.NETMVC.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/07/Self-updatingAJAXlinkswithASP.NETMVC. + This page has moved to /2009/09/07/Self-updatingAJAXlinkswithASP.NETMVC. \ No newline at end of file diff --git a/2009/09/07/SelfupdatingAJAXLinksWithASPNETMVC.aspx/index.html b/2009/09/07/SelfupdatingAJAXLinksWithASPNETMVC.aspx/index.html index 597480a3b..7aa45e913 100644 --- a/2009/09/07/SelfupdatingAJAXLinksWithASPNETMVC.aspx/index.html +++ b/2009/09/07/SelfupdatingAJAXLinksWithASPNETMVC.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/07/Self-updatingAJAXlinkswithASP.NETMVC. + This page has moved to /2009/09/07/Self-updatingAJAXlinkswithASP.NETMVC. \ No newline at end of file diff --git a/2009/09/21/AutoFixture.8.6Released.aspx/index.html b/2009/09/21/AutoFixture.8.6Released.aspx/index.html index 10e45f5af..a8a4c09d9 100644 --- a/2009/09/21/AutoFixture.8.6Released.aspx/index.html +++ b/2009/09/21/AutoFixture.8.6Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/21/AutoFixture.8.6Released. + This page has moved to /2009/09/21/AutoFixture.8.6Released. \ No newline at end of file diff --git a/2009/09/21/AutoFixture86Released.aspx/index.html b/2009/09/21/AutoFixture86Released.aspx/index.html index 10e45f5af..a8a4c09d9 100644 --- a/2009/09/21/AutoFixture86Released.aspx/index.html +++ b/2009/09/21/AutoFixture86Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/21/AutoFixture.8.6Released. + This page has moved to /2009/09/21/AutoFixture.8.6Released. \ No newline at end of file diff --git a/2009/09/22/CustomizingAType'sBuilderWithAutoFixture.aspx/index.html b/2009/09/22/CustomizingAType'sBuilderWithAutoFixture.aspx/index.html index c3bc20d5e..8467978c5 100644 --- a/2009/09/22/CustomizingAType'sBuilderWithAutoFixture.aspx/index.html +++ b/2009/09/22/CustomizingAType'sBuilderWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/22/CustomizingATypesBuilderWithAutoFixture. + This page has moved to /2009/09/22/CustomizingATypesBuilderWithAutoFixture. \ No newline at end of file diff --git a/2009/09/22/CustomizingATypesBuilderWithAutoFixture.aspx/index.html b/2009/09/22/CustomizingATypesBuilderWithAutoFixture.aspx/index.html index 00aa217f4..72f837b10 100644 --- a/2009/09/22/CustomizingATypesBuilderWithAutoFixture.aspx/index.html +++ b/2009/09/22/CustomizingATypesBuilderWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/22/CustomizingAType'sBuilderWithAutoFixture. + This page has moved to /2009/09/22/CustomizingAType'sBuilderWithAutoFixture. \ No newline at end of file diff --git a/2009/09/29/SOLIDOrCOLDS.aspx/index.html b/2009/09/29/SOLIDOrCOLDS.aspx/index.html index 281f1515f..f5ded6c6a 100644 --- a/2009/09/29/SOLIDOrCOLDS.aspx/index.html +++ b/2009/09/29/SOLIDOrCOLDS.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/09/29/SOLIDorCOLDS. + This page has moved to /2009/09/29/SOLIDorCOLDS. \ No newline at end of file diff --git a/2009/10/05/WritingABook.aspx/index.html b/2009/10/05/WritingABook.aspx/index.html index fc77971a3..6cfc1a78e 100644 --- a/2009/10/05/WritingABook.aspx/index.html +++ b/2009/10/05/WritingABook.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/10/05/Writingabook. + This page has moved to /2009/10/05/Writingabook. \ No newline at end of file diff --git a/2009/10/24/WCFPodcastWithMe.aspx/index.html b/2009/10/24/WCFPodcastWithMe.aspx/index.html index 0e46dafa6..fd5fa014b 100644 --- a/2009/10/24/WCFPodcastWithMe.aspx/index.html +++ b/2009/10/24/WCFPodcastWithMe.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/10/24/WCFPodcastwithme. + This page has moved to /2009/10/24/WCFPodcastwithme. \ No newline at end of file diff --git a/2009/10/26/AnonymousWith.aspx/index.html b/2009/10/26/AnonymousWith.aspx/index.html index d520f609e..9c1e9245e 100644 --- a/2009/10/26/AnonymousWith.aspx/index.html +++ b/2009/10/26/AnonymousWith.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/10/26/AnonymousWith. + This page has moved to /2009/10/26/AnonymousWith. \ No newline at end of file diff --git a/2009/10/31/AutoFixtureBeta1.aspx/index.html b/2009/10/31/AutoFixtureBeta1.aspx/index.html index 984e5e03c..22624546c 100644 --- a/2009/10/31/AutoFixtureBeta1.aspx/index.html +++ b/2009/10/31/AutoFixtureBeta1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/10/31/AutoFixturebeta1. + This page has moved to /2009/10/31/AutoFixturebeta1. \ No newline at end of file diff --git a/2009/11/07/CreatingLengthconstrainedStringsWithAutoFixture.aspx/index.html b/2009/11/07/CreatingLengthconstrainedStringsWithAutoFixture.aspx/index.html index ca466993d..6175a71b9 100644 --- a/2009/11/07/CreatingLengthconstrainedStringsWithAutoFixture.aspx/index.html +++ b/2009/11/07/CreatingLengthconstrainedStringsWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/11/07/Creatinglength-constrainedstringswithAutoFixture. + This page has moved to /2009/11/07/Creatinglength-constrainedstringswithAutoFixture. \ No newline at end of file diff --git a/2009/11/17/DependencyInjectionPodcastWithMe.aspx/index.html b/2009/11/17/DependencyInjectionPodcastWithMe.aspx/index.html index b011f0705..76425177a 100644 --- a/2009/11/17/DependencyInjectionPodcastWithMe.aspx/index.html +++ b/2009/11/17/DependencyInjectionPodcastWithMe.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/11/17/DependencyInjectionPodcastwithme. + This page has moved to /2009/11/17/DependencyInjectionPodcastwithme. \ No newline at end of file diff --git a/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASP.NETMVCOnIIS7.aspx/index.html b/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASP.NETMVCOnIIS7.aspx/index.html index d942f937b..d098f1383 100644 --- a/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASP.NETMVCOnIIS7.aspx/index.html +++ b/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASP.NETMVCOnIIS7.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/11/17/UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7. + This page has moved to /2009/11/17/UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7. \ No newline at end of file diff --git a/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html b/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html index ab0e8a673..12e61e2e9 100644 --- a/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html +++ b/2009/11/17/UsingCastleWindsor'sPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/11/17/UsingCastleWindsorsPerWebRequestlifestylewithASP.NETMVConIIS7. + This page has moved to /2009/11/17/UsingCastleWindsorsPerWebRequestlifestylewithASP.NETMVConIIS7. \ No newline at end of file diff --git a/2009/11/17/UsingCastleWindsorsPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html b/2009/11/17/UsingCastleWindsorsPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html index d942f937b..d098f1383 100644 --- a/2009/11/17/UsingCastleWindsorsPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html +++ b/2009/11/17/UsingCastleWindsorsPerWebRequestLifestyleWithASPNETMVCOnIIS7.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/11/17/UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7. + This page has moved to /2009/11/17/UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7. \ No newline at end of file diff --git a/2009/11/26/AnonymousDo.aspx/index.html b/2009/11/26/AnonymousDo.aspx/index.html index 8a7278058..4c9a2f502 100644 --- a/2009/11/26/AnonymousDo.aspx/index.html +++ b/2009/11/26/AnonymousDo.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/11/26/AnonymousDo. + This page has moved to /2009/11/26/AnonymousDo. \ No newline at end of file diff --git a/2009/12/01/GlobalErrorHandlingInASP.NETMVC.aspx/index.html b/2009/12/01/GlobalErrorHandlingInASP.NETMVC.aspx/index.html index 74d08f224..42d1fef0e 100644 --- a/2009/12/01/GlobalErrorHandlingInASP.NETMVC.aspx/index.html +++ b/2009/12/01/GlobalErrorHandlingInASP.NETMVC.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/12/01/GlobalErrorHandlinginASP.NETMVC. + This page has moved to /2009/12/01/GlobalErrorHandlinginASP.NETMVC. \ No newline at end of file diff --git a/2009/12/01/GlobalErrorHandlingInASPNETMVC.aspx/index.html b/2009/12/01/GlobalErrorHandlingInASPNETMVC.aspx/index.html index 74d08f224..42d1fef0e 100644 --- a/2009/12/01/GlobalErrorHandlingInASPNETMVC.aspx/index.html +++ b/2009/12/01/GlobalErrorHandlingInASPNETMVC.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/12/01/GlobalErrorHandlinginASP.NETMVC. + This page has moved to /2009/12/01/GlobalErrorHandlinginASP.NETMVC. \ No newline at end of file diff --git a/2009/12/05/BuildingAndAssigningArraysWithAutoFixture.aspx/index.html b/2009/12/05/BuildingAndAssigningArraysWithAutoFixture.aspx/index.html index d308f53b5..8f95b6892 100644 --- a/2009/12/05/BuildingAndAssigningArraysWithAutoFixture.aspx/index.html +++ b/2009/12/05/BuildingAndAssigningArraysWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/12/05/BuildingandassigningarrayswithAutoFixture. + This page has moved to /2009/12/05/BuildingandassigningarrayswithAutoFixture. \ No newline at end of file diff --git a/2009/12/07/LoggingExceptionFilter.aspx/index.html b/2009/12/07/LoggingExceptionFilter.aspx/index.html index 80de16fe8..6dc30067c 100644 --- a/2009/12/07/LoggingExceptionFilter.aspx/index.html +++ b/2009/12/07/LoggingExceptionFilter.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/12/07/LoggingExceptionFilter. + This page has moved to /2009/12/07/LoggingExceptionFilter. \ No newline at end of file diff --git a/2009/12/14/WiringASP.NETMVCErrorHandlingWithCastleWindsor.aspx/index.html b/2009/12/14/WiringASP.NETMVCErrorHandlingWithCastleWindsor.aspx/index.html index 29076592e..e6b1e4c6d 100644 --- a/2009/12/14/WiringASP.NETMVCErrorHandlingWithCastleWindsor.aspx/index.html +++ b/2009/12/14/WiringASP.NETMVCErrorHandlingWithCastleWindsor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/12/14/WiringASP.NETMVCErrorHandlingwithCastleWindsor. + This page has moved to /2009/12/14/WiringASP.NETMVCErrorHandlingwithCastleWindsor. \ No newline at end of file diff --git a/2009/12/14/WiringASPNETMVCErrorHandlingWithCastleWindsor.aspx/index.html b/2009/12/14/WiringASPNETMVCErrorHandlingWithCastleWindsor.aspx/index.html index 29076592e..e6b1e4c6d 100644 --- a/2009/12/14/WiringASPNETMVCErrorHandlingWithCastleWindsor.aspx/index.html +++ b/2009/12/14/WiringASPNETMVCErrorHandlingWithCastleWindsor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/12/14/WiringASP.NETMVCErrorHandlingwithCastleWindsor. + This page has moved to /2009/12/14/WiringASP.NETMVCErrorHandlingwithCastleWindsor. \ No newline at end of file diff --git a/2009/12/20/MEFTechTalkWithMe.aspx/index.html b/2009/12/20/MEFTechTalkWithMe.aspx/index.html index a36b7d459..845372fd0 100644 --- a/2009/12/20/MEFTechTalkWithMe.aspx/index.html +++ b/2009/12/20/MEFTechTalkWithMe.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2009/12/20/MEFTechTalkwithme. + This page has moved to /2009/12/20/MEFTechTalkwithme. \ No newline at end of file diff --git a/2010/01/04/AnonymousGet.aspx/index.html b/2010/01/04/AnonymousGet.aspx/index.html index 68e01ce2f..208af30a5 100644 --- a/2010/01/04/AnonymousGet.aspx/index.html +++ b/2010/01/04/AnonymousGet.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/04/AnonymousGet. + This page has moved to /2010/01/04/AnonymousGet. \ No newline at end of file diff --git a/2010/01/13/AutoFixture1.0RC1.aspx/index.html b/2010/01/13/AutoFixture1.0RC1.aspx/index.html index 8110a09a3..4a679cd94 100644 --- a/2010/01/13/AutoFixture1.0RC1.aspx/index.html +++ b/2010/01/13/AutoFixture1.0RC1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/13/AutoFixture1.0RC1. + This page has moved to /2010/01/13/AutoFixture1.0RC1. \ No newline at end of file diff --git a/2010/01/13/AutoFixture10RC1.aspx/index.html b/2010/01/13/AutoFixture10RC1.aspx/index.html index 8110a09a3..4a679cd94 100644 --- a/2010/01/13/AutoFixture10RC1.aspx/index.html +++ b/2010/01/13/AutoFixture10RC1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/13/AutoFixture1.0RC1. + This page has moved to /2010/01/13/AutoFixture1.0RC1. \ No newline at end of file diff --git a/2010/01/20/AutoFixture1.0RC2.aspx/index.html b/2010/01/20/AutoFixture1.0RC2.aspx/index.html index 06de1f2a2..d20ab66a5 100644 --- a/2010/01/20/AutoFixture1.0RC2.aspx/index.html +++ b/2010/01/20/AutoFixture1.0RC2.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/20/AutoFixture1.0RC2. + This page has moved to /2010/01/20/AutoFixture1.0RC2. \ No newline at end of file diff --git a/2010/01/20/AutoFixture10RC2.aspx/index.html b/2010/01/20/AutoFixture10RC2.aspx/index.html index 06de1f2a2..d20ab66a5 100644 --- a/2010/01/20/AutoFixture10RC2.aspx/index.html +++ b/2010/01/20/AutoFixture10RC2.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/20/AutoFixture1.0RC2. + This page has moved to /2010/01/20/AutoFixture1.0RC2. \ No newline at end of file diff --git a/2010/01/20/EnablingDIForLazyComponents.aspx/index.html b/2010/01/20/EnablingDIForLazyComponents.aspx/index.html index 3148d9b65..ea7688d79 100644 --- a/2010/01/20/EnablingDIForLazyComponents.aspx/index.html +++ b/2010/01/20/EnablingDIForLazyComponents.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/20/EnablingDIforLazyComponents. + This page has moved to /2010/01/20/EnablingDIforLazyComponents. \ No newline at end of file diff --git a/2010/01/20/RebuttalConstructorOverinjectionAntipattern.aspx/index.html b/2010/01/20/RebuttalConstructorOverinjectionAntipattern.aspx/index.html index b29736c5b..b54448b03 100644 --- a/2010/01/20/RebuttalConstructorOverinjectionAntipattern.aspx/index.html +++ b/2010/01/20/RebuttalConstructorOverinjectionAntipattern.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/20/RebuttalConstructorover-injectionanti-pattern. + This page has moved to /2010/01/20/RebuttalConstructorover-injectionanti-pattern. \ No newline at end of file diff --git a/2010/01/25/DependencyInjectionInversionIn.NET.aspx/index.html b/2010/01/25/DependencyInjectionInversionIn.NET.aspx/index.html index d25e2b617..4a31acee3 100644 --- a/2010/01/25/DependencyInjectionInversionIn.NET.aspx/index.html +++ b/2010/01/25/DependencyInjectionInversionIn.NET.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/25/DependencyInjectionInversionin.NET. + This page has moved to /2010/01/25/DependencyInjectionInversionin.NET. \ No newline at end of file diff --git a/2010/01/25/DependencyInjectionInversionInNET.aspx/index.html b/2010/01/25/DependencyInjectionInversionInNET.aspx/index.html index d25e2b617..4a31acee3 100644 --- a/2010/01/25/DependencyInjectionInversionInNET.aspx/index.html +++ b/2010/01/25/DependencyInjectionInversionInNET.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/25/DependencyInjectionInversionin.NET. + This page has moved to /2010/01/25/DependencyInjectionInversionin.NET. \ No newline at end of file diff --git a/2010/01/26/IWindsorInstaller.aspx/index.html b/2010/01/26/IWindsorInstaller.aspx/index.html index b2881ac90..b6c0e2739 100644 --- a/2010/01/26/IWindsorInstaller.aspx/index.html +++ b/2010/01/26/IWindsorInstaller.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/26/IWindsorInstaller. + This page has moved to /2010/01/26/IWindsorInstaller. \ No newline at end of file diff --git a/2010/01/27/AutoFixture1.0.aspx/index.html b/2010/01/27/AutoFixture1.0.aspx/index.html index 527149e1d..3f5c80281 100644 --- a/2010/01/27/AutoFixture1.0.aspx/index.html +++ b/2010/01/27/AutoFixture1.0.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/27/AutoFixture1.0. + This page has moved to /2010/01/27/AutoFixture1.0. \ No newline at end of file diff --git a/2010/01/27/AutoFixture10.aspx/index.html b/2010/01/27/AutoFixture10.aspx/index.html index 527149e1d..3f5c80281 100644 --- a/2010/01/27/AutoFixture10.aspx/index.html +++ b/2010/01/27/AutoFixture10.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/27/AutoFixture1.0. + This page has moved to /2010/01/27/AutoFixture1.0. \ No newline at end of file diff --git a/2010/01/27/What'sSoDangerousAboutADIAttribute.aspx/index.html b/2010/01/27/What'sSoDangerousAboutADIAttribute.aspx/index.html index 508b361d6..fc57fc283 100644 --- a/2010/01/27/What'sSoDangerousAboutADIAttribute.aspx/index.html +++ b/2010/01/27/What'sSoDangerousAboutADIAttribute.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/27/WhatssodangerousaboutaDIattribute. + This page has moved to /2010/01/27/WhatssodangerousaboutaDIattribute. \ No newline at end of file diff --git a/2010/01/27/WhatsSoDangerousAboutADIAttribute.aspx/index.html b/2010/01/27/WhatsSoDangerousAboutADIAttribute.aspx/index.html index 5cdb36cfb..333f6eb10 100644 --- a/2010/01/27/WhatsSoDangerousAboutADIAttribute.aspx/index.html +++ b/2010/01/27/WhatsSoDangerousAboutADIAttribute.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/01/27/What'ssodangerousaboutaDIattribute. + This page has moved to /2010/01/27/What'ssodangerousaboutaDIattribute. \ No newline at end of file diff --git a/2010/02/02/RefactoringToAggregateServices.aspx/index.html b/2010/02/02/RefactoringToAggregateServices.aspx/index.html index 23559b03e..b085f1307 100644 --- a/2010/02/02/RefactoringToAggregateServices.aspx/index.html +++ b/2010/02/02/RefactoringToAggregateServices.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices. + This page has moved to /2010/02/02/RefactoringtoAggregateServices. \ No newline at end of file diff --git a/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx/index.html b/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx/index.html index 64acd6c6a..49fba5220 100644 --- a/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx/index.html +++ b/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern. + This page has moved to /2010/02/03/ServiceLocatorisanAnti-Pattern. \ No newline at end of file diff --git a/2010/02/08/CNUGTDDTalk.aspx/index.html b/2010/02/08/CNUGTDDTalk.aspx/index.html index bfc7e6ced..3e85659ec 100644 --- a/2010/02/08/CNUGTDDTalk.aspx/index.html +++ b/2010/02/08/CNUGTDDTalk.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/02/08/CNUGTDDtalk. + This page has moved to /2010/02/08/CNUGTDDtalk. \ No newline at end of file diff --git a/2010/03/17/AutoFixtureFreeze.aspx/index.html b/2010/03/17/AutoFixtureFreeze.aspx/index.html index ca809f9da..b3d7c79ee 100644 --- a/2010/03/17/AutoFixtureFreeze.aspx/index.html +++ b/2010/03/17/AutoFixtureFreeze.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/03/17/AutoFixtureFreeze. + This page has moved to /2010/03/17/AutoFixtureFreeze. \ No newline at end of file diff --git a/2010/03/26/MoreAboutFrozenPizza.aspx/index.html b/2010/03/26/MoreAboutFrozenPizza.aspx/index.html index fa8d26549..ad97e4144 100644 --- a/2010/03/26/MoreAboutFrozenPizza.aspx/index.html +++ b/2010/03/26/MoreAboutFrozenPizza.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/03/26/Moreaboutfrozenpizza. + This page has moved to /2010/03/26/Moreaboutfrozenpizza. \ No newline at end of file diff --git a/2010/03/27/FreezingMocks.aspx/index.html b/2010/03/27/FreezingMocks.aspx/index.html index 9957e5762..b04d0b980 100644 --- a/2010/03/27/FreezingMocks.aspx/index.html +++ b/2010/03/27/FreezingMocks.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/03/27/Freezingmocks. + This page has moved to /2010/03/27/Freezingmocks. \ No newline at end of file diff --git a/2010/04/02/AutoFixture1.1RC1.aspx/index.html b/2010/04/02/AutoFixture1.1RC1.aspx/index.html index 7fc7bef81..09720a844 100644 --- a/2010/04/02/AutoFixture1.1RC1.aspx/index.html +++ b/2010/04/02/AutoFixture1.1RC1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/02/AutoFixture1.1RC1. + This page has moved to /2010/04/02/AutoFixture1.1RC1. \ No newline at end of file diff --git a/2010/04/02/AutoFixture11RC1.aspx/index.html b/2010/04/02/AutoFixture11RC1.aspx/index.html index 7fc7bef81..09720a844 100644 --- a/2010/04/02/AutoFixture11RC1.aspx/index.html +++ b/2010/04/02/AutoFixture11RC1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/02/AutoFixture1.1RC1. + This page has moved to /2010/04/02/AutoFixture1.1RC1. \ No newline at end of file diff --git a/2010/04/06/MappingTypesWithAutoFixture.aspx/index.html b/2010/04/06/MappingTypesWithAutoFixture.aspx/index.html index 281456062..8a4933e96 100644 --- a/2010/04/06/MappingTypesWithAutoFixture.aspx/index.html +++ b/2010/04/06/MappingTypesWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/06/MappingtypeswithAutoFixture. + This page has moved to /2010/04/06/MappingtypeswithAutoFixture. \ No newline at end of file diff --git a/2010/04/07/DependencyInjectionIsLooseCoupling.aspx/index.html b/2010/04/07/DependencyInjectionIsLooseCoupling.aspx/index.html index d13591076..ece3ab341 100644 --- a/2010/04/07/DependencyInjectionIsLooseCoupling.aspx/index.html +++ b/2010/04/07/DependencyInjectionIsLooseCoupling.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/07/DependencyInjectionisLooseCoupling. + This page has moved to /2010/04/07/DependencyInjectionisLooseCoupling. \ No newline at end of file diff --git a/2010/04/10/AutoFixture1.1.aspx/index.html b/2010/04/10/AutoFixture1.1.aspx/index.html index 903cb460b..37df64456 100644 --- a/2010/04/10/AutoFixture1.1.aspx/index.html +++ b/2010/04/10/AutoFixture1.1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/10/AutoFixture1.1. + This page has moved to /2010/04/10/AutoFixture1.1. \ No newline at end of file diff --git a/2010/04/10/AutoFixture11.aspx/index.html b/2010/04/10/AutoFixture11.aspx/index.html index 903cb460b..37df64456 100644 --- a/2010/04/10/AutoFixture11.aspx/index.html +++ b/2010/04/10/AutoFixture11.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/10/AutoFixture1.1. + This page has moved to /2010/04/10/AutoFixture1.1. \ No newline at end of file diff --git a/2010/04/26/ChangingWindsorLifestylesAfterTheFact.aspx/index.html b/2010/04/26/ChangingWindsorLifestylesAfterTheFact.aspx/index.html index eeb0e767b..eeeee29bc 100644 --- a/2010/04/26/ChangingWindsorLifestylesAfterTheFact.aspx/index.html +++ b/2010/04/26/ChangingWindsorLifestylesAfterTheFact.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/26/ChangingWindsorlifestylesafterthefact. + This page has moved to /2010/04/26/ChangingWindsorlifestylesafterthefact. \ No newline at end of file diff --git a/2010/04/26/WhyImMigratingFromMSTestToXUnit.net.aspx/index.html b/2010/04/26/WhyImMigratingFromMSTestToXUnit.net.aspx/index.html index 22a796d8e..72e6d3629 100644 --- a/2010/04/26/WhyImMigratingFromMSTestToXUnit.net.aspx/index.html +++ b/2010/04/26/WhyImMigratingFromMSTestToXUnit.net.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/26/WhyI'mmigratingfromMSTesttoxUnit.net. + This page has moved to /2010/04/26/WhyI'mmigratingfromMSTesttoxUnit.net. \ No newline at end of file diff --git a/2010/04/26/WhyImMigratingFromMSTestToXUnitnet.aspx/index.html b/2010/04/26/WhyImMigratingFromMSTestToXUnitnet.aspx/index.html index 95a67e8f2..a702cbd33 100644 --- a/2010/04/26/WhyImMigratingFromMSTestToXUnitnet.aspx/index.html +++ b/2010/04/26/WhyImMigratingFromMSTestToXUnitnet.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/26/WhyImmigratingfromMSTesttoxUnit.net. + This page has moved to /2010/04/26/WhyImmigratingfromMSTesttoxUnit.net. \ No newline at end of file diff --git a/2010/04/27/FunWithLiteralExtensionsAndAmbientContext.aspx/index.html b/2010/04/27/FunWithLiteralExtensionsAndAmbientContext.aspx/index.html index afc3428bd..47ac89008 100644 --- a/2010/04/27/FunWithLiteralExtensionsAndAmbientContext.aspx/index.html +++ b/2010/04/27/FunWithLiteralExtensionsAndAmbientContext.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/04/27/FunwithliteralextensionsandAmbientContext. + This page has moved to /2010/04/27/FunwithliteralextensionsandAmbientContext. \ No newline at end of file diff --git a/2010/05/17/ServiceHostFactoryLifetime.aspx/index.html b/2010/05/17/ServiceHostFactoryLifetime.aspx/index.html index 0db3776f6..e9b190ce2 100644 --- a/2010/05/17/ServiceHostFactoryLifetime.aspx/index.html +++ b/2010/05/17/ServiceHostFactoryLifetime.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/05/17/ServiceHostFactorylifetime. + This page has moved to /2010/05/17/ServiceHostFactorylifetime. \ No newline at end of file diff --git a/2010/05/18/SneakViewAtCastlesWCFFacility.aspx/index.html b/2010/05/18/SneakViewAtCastlesWCFFacility.aspx/index.html index b477b7b45..86481de37 100644 --- a/2010/05/18/SneakViewAtCastlesWCFFacility.aspx/index.html +++ b/2010/05/18/SneakViewAtCastlesWCFFacility.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/05/18/SneakviewatCastlesWCFFacility. + This page has moved to /2010/05/18/SneakviewatCastlesWCFFacility. \ No newline at end of file diff --git a/2010/05/23/UpcomingTalksSpring2010.aspx/index.html b/2010/05/23/UpcomingTalksSpring2010.aspx/index.html index 7c54efa24..11b2172eb 100644 --- a/2010/05/23/UpcomingTalksSpring2010.aspx/index.html +++ b/2010/05/23/UpcomingTalksSpring2010.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/05/23/Upcomingtalksspring2010. + This page has moved to /2010/05/23/Upcomingtalksspring2010. \ No newline at end of file diff --git a/2010/06/29/IntroducingAutoFixtureLikeness.aspx/index.html b/2010/06/29/IntroducingAutoFixtureLikeness.aspx/index.html index 97dc066a1..9aedda72c 100644 --- a/2010/06/29/IntroducingAutoFixtureLikeness.aspx/index.html +++ b/2010/06/29/IntroducingAutoFixtureLikeness.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/06/29/IntroducingAutoFixtureLikeness. + This page has moved to /2010/06/29/IntroducingAutoFixtureLikeness. \ No newline at end of file diff --git a/2010/07/12/DomainObjectsAndIDataErrorInfo.aspx/index.html b/2010/07/12/DomainObjectsAndIDataErrorInfo.aspx/index.html index 1b425e347..793fd02d3 100644 --- a/2010/07/12/DomainObjectsAndIDataErrorInfo.aspx/index.html +++ b/2010/07/12/DomainObjectsAndIDataErrorInfo.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/07/12/DomainObjectsandIDataErrorInfo. + This page has moved to /2010/07/12/DomainObjectsandIDataErrorInfo. \ No newline at end of file diff --git a/2010/07/20/StructureMapPerRequestVs.UniqueLifetimes.aspx/index.html b/2010/07/20/StructureMapPerRequestVs.UniqueLifetimes.aspx/index.html index a534b8560..d3fdb9a54 100644 --- a/2010/07/20/StructureMapPerRequestVs.UniqueLifetimes.aspx/index.html +++ b/2010/07/20/StructureMapPerRequestVs.UniqueLifetimes.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/07/20/StructureMapPerRequestvs.Uniquelifetimes. + This page has moved to /2010/07/20/StructureMapPerRequestvs.Uniquelifetimes. \ No newline at end of file diff --git a/2010/07/20/StructureMapPerRequestVsUniqueLifetimes.aspx/index.html b/2010/07/20/StructureMapPerRequestVsUniqueLifetimes.aspx/index.html index a534b8560..d3fdb9a54 100644 --- a/2010/07/20/StructureMapPerRequestVsUniqueLifetimes.aspx/index.html +++ b/2010/07/20/StructureMapPerRequestVsUniqueLifetimes.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/07/20/StructureMapPerRequestvs.Uniquelifetimes. + This page has moved to /2010/07/20/StructureMapPerRequestvs.Uniquelifetimes. \ No newline at end of file diff --git a/2010/08/09/AutoFixture2.0Beta1.aspx/index.html b/2010/08/09/AutoFixture2.0Beta1.aspx/index.html index 2ef92d29b..62956f912 100644 --- a/2010/08/09/AutoFixture2.0Beta1.aspx/index.html +++ b/2010/08/09/AutoFixture2.0Beta1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/08/09/AutoFixture2.0beta1. + This page has moved to /2010/08/09/AutoFixture2.0beta1. \ No newline at end of file diff --git a/2010/08/09/AutoFixture20Beta1.aspx/index.html b/2010/08/09/AutoFixture20Beta1.aspx/index.html index 2ef92d29b..62956f912 100644 --- a/2010/08/09/AutoFixture20Beta1.aspx/index.html +++ b/2010/08/09/AutoFixture20Beta1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/08/09/AutoFixture2.0beta1. + This page has moved to /2010/08/09/AutoFixture2.0beta1. \ No newline at end of file diff --git a/2010/08/19/AutoFixtureAsAnAutomockingContainer.aspx/index.html b/2010/08/19/AutoFixtureAsAnAutomockingContainer.aspx/index.html index a9fdd0c73..776435f9e 100644 --- a/2010/08/19/AutoFixtureAsAnAutomockingContainer.aspx/index.html +++ b/2010/08/19/AutoFixtureAsAnAutomockingContainer.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/08/19/AutoFixtureasanauto-mockingcontainer. + This page has moved to /2010/08/19/AutoFixtureasanauto-mockingcontainer. \ No newline at end of file diff --git a/2010/08/25/ChangingTheBehaviorOfAutoFixtureAutomockingWithMoq.aspx/index.html b/2010/08/25/ChangingTheBehaviorOfAutoFixtureAutomockingWithMoq.aspx/index.html index 65b15cded..336713ec4 100644 --- a/2010/08/25/ChangingTheBehaviorOfAutoFixtureAutomockingWithMoq.aspx/index.html +++ b/2010/08/25/ChangingTheBehaviorOfAutoFixtureAutomockingWithMoq.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/08/25/ChangingthebehaviorofAutoFixtureauto-mockingwithMoq. + This page has moved to /2010/08/25/ChangingthebehaviorofAutoFixtureauto-mockingwithMoq. \ No newline at end of file diff --git a/2010/08/30/DontCallTheContainer;ItllCallYou.aspx/index.html b/2010/08/30/DontCallTheContainer;ItllCallYou.aspx/index.html index 27d0f45c0..6a2788f85 100644 --- a/2010/08/30/DontCallTheContainer;ItllCallYou.aspx/index.html +++ b/2010/08/30/DontCallTheContainer;ItllCallYou.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/08/30/Dontcallthecontainer;itllcallyou. + This page has moved to /2010/08/30/Dontcallthecontainer;itllcallyou. \ No newline at end of file diff --git a/2010/08/30/DontCallTheContainerItllCallYou.aspx/index.html b/2010/08/30/DontCallTheContainerItllCallYou.aspx/index.html index 27d0f45c0..6a2788f85 100644 --- a/2010/08/30/DontCallTheContainerItllCallYou.aspx/index.html +++ b/2010/08/30/DontCallTheContainerItllCallYou.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/08/30/Dontcallthecontainer;itllcallyou. + This page has moved to /2010/08/30/Dontcallthecontainer;itllcallyou. \ No newline at end of file diff --git a/2010/09/13/MyFutureIsAzure.aspx/index.html b/2010/09/13/MyFutureIsAzure.aspx/index.html index 5ad4a3c5b..32c7a54d8 100644 --- a/2010/09/13/MyFutureIsAzure.aspx/index.html +++ b/2010/09/13/MyFutureIsAzure.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/09/13/MyfutureisAzure. + This page has moved to /2010/09/13/MyfutureisAzure. \ No newline at end of file diff --git a/2010/09/20/InstrumentationWithDecoratorsAndInterceptors.aspx/index.html b/2010/09/20/InstrumentationWithDecoratorsAndInterceptors.aspx/index.html index 4e3d3fa58..01ff1da78 100644 --- a/2010/09/20/InstrumentationWithDecoratorsAndInterceptors.aspx/index.html +++ b/2010/09/20/InstrumentationWithDecoratorsAndInterceptors.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/09/20/InstrumentationwithDecoratorsandInterceptors. + This page has moved to /2010/09/20/InstrumentationwithDecoratorsandInterceptors. \ No newline at end of file diff --git a/2010/09/29/TheRegisterResolveReleasePattern.aspx/index.html b/2010/09/29/TheRegisterResolveReleasePattern.aspx/index.html index f19cfb4de..0da9b66c4 100644 --- a/2010/09/29/TheRegisterResolveReleasePattern.aspx/index.html +++ b/2010/09/29/TheRegisterResolveReleasePattern.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/09/29/TheRegisterResolveReleasepattern. + This page has moved to /2010/09/29/TheRegisterResolveReleasepattern. \ No newline at end of file diff --git a/2010/10/08/AutoDataTheoriesWithAutoFixture.aspx/index.html b/2010/10/08/AutoDataTheoriesWithAutoFixture.aspx/index.html index 186855f4d..9c1ade635 100644 --- a/2010/10/08/AutoDataTheoriesWithAutoFixture.aspx/index.html +++ b/2010/10/08/AutoDataTheoriesWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/10/08/AutoDataTheorieswithAutoFixture. + This page has moved to /2010/10/08/AutoDataTheorieswithAutoFixture. \ No newline at end of file diff --git a/2010/10/10/AutoFixture2.0Released.aspx/index.html b/2010/10/10/AutoFixture2.0Released.aspx/index.html index 3bc8879fd..f4fc46123 100644 --- a/2010/10/10/AutoFixture2.0Released.aspx/index.html +++ b/2010/10/10/AutoFixture2.0Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/10/10/AutoFixture2.0Released. + This page has moved to /2010/10/10/AutoFixture2.0Released. \ No newline at end of file diff --git a/2010/10/10/AutoFixture20Released.aspx/index.html b/2010/10/10/AutoFixture20Released.aspx/index.html index 3bc8879fd..f4fc46123 100644 --- a/2010/10/10/AutoFixture20Released.aspx/index.html +++ b/2010/10/10/AutoFixture20Released.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/10/10/AutoFixture2.0Released. + This page has moved to /2010/10/10/AutoFixture2.0Released. \ No newline at end of file diff --git a/2010/10/14/WindowsAzureMigrationSanityCheck.aspx/index.html b/2010/10/14/WindowsAzureMigrationSanityCheck.aspx/index.html index 8b65e7173..417f36375 100644 --- a/2010/10/14/WindowsAzureMigrationSanityCheck.aspx/index.html +++ b/2010/10/14/WindowsAzureMigrationSanityCheck.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/10/14/WindowsAzureMigrationSanityCheck. + This page has moved to /2010/10/14/WindowsAzureMigrationSanityCheck. \ No newline at end of file diff --git a/2010/10/19/ConventionbasedCustomizationsWithAutoFixture.aspx/index.html b/2010/10/19/ConventionbasedCustomizationsWithAutoFixture.aspx/index.html index 300ec0d61..307a84a6b 100644 --- a/2010/10/19/ConventionbasedCustomizationsWithAutoFixture.aspx/index.html +++ b/2010/10/19/ConventionbasedCustomizationsWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/10/19/Convention-basedCustomizationswithAutoFixture. + This page has moved to /2010/10/19/Convention-basedCustomizationswithAutoFixture. \ No newline at end of file diff --git a/2010/11/01/PatternRecognitionAbstractFactoryOrServiceLocator.aspx/index.html b/2010/11/01/PatternRecognitionAbstractFactoryOrServiceLocator.aspx/index.html index 708c1586c..e4abba71a 100644 --- a/2010/11/01/PatternRecognitionAbstractFactoryOrServiceLocator.aspx/index.html +++ b/2010/11/01/PatternRecognitionAbstractFactoryOrServiceLocator.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/11/01/PatternRecognitionAbstractFactoryorServiceLocator. + This page has moved to /2010/11/01/PatternRecognitionAbstractFactoryorServiceLocator. \ No newline at end of file diff --git a/2010/11/01/RefactoringFromAbstractFactoryToDecorator.aspx/index.html b/2010/11/01/RefactoringFromAbstractFactoryToDecorator.aspx/index.html index 7133c177f..ee23b8f41 100644 --- a/2010/11/01/RefactoringFromAbstractFactoryToDecorator.aspx/index.html +++ b/2010/11/01/RefactoringFromAbstractFactoryToDecorator.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/11/01/RefactoringfromAbstractFactorytoDecorator. + This page has moved to /2010/11/01/RefactoringfromAbstractFactorytoDecorator. \ No newline at end of file diff --git a/2010/11/01/RefactoringFromServiceLocatorToAbstractFactory.aspx/index.html b/2010/11/01/RefactoringFromServiceLocatorToAbstractFactory.aspx/index.html index 4af278b06..a6f8041b6 100644 --- a/2010/11/01/RefactoringFromServiceLocatorToAbstractFactory.aspx/index.html +++ b/2010/11/01/RefactoringFromServiceLocatorToAbstractFactory.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/11/01/RefactoringfromServiceLocatortoAbstractFactory. + This page has moved to /2010/11/01/RefactoringfromServiceLocatortoAbstractFactory. \ No newline at end of file diff --git a/2010/11/13/RhinoMocksbasedAutomockingWithAutoFixture.aspx/index.html b/2010/11/13/RhinoMocksbasedAutomockingWithAutoFixture.aspx/index.html index ade377286..f9104a7aa 100644 --- a/2010/11/13/RhinoMocksbasedAutomockingWithAutoFixture.aspx/index.html +++ b/2010/11/13/RhinoMocksbasedAutomockingWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/11/13/RhinoMocks-basedauto-mockingwithAutoFixture. + This page has moved to /2010/11/13/RhinoMocks-basedauto-mockingwithAutoFixture. \ No newline at end of file diff --git a/2010/11/22/IntegratingAutoFixtureWithObjectHydrator.aspx/index.html b/2010/11/22/IntegratingAutoFixtureWithObjectHydrator.aspx/index.html index 3fdec0cda..31e4278bd 100644 --- a/2010/11/22/IntegratingAutoFixtureWithObjectHydrator.aspx/index.html +++ b/2010/11/22/IntegratingAutoFixtureWithObjectHydrator.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/11/22/IntegratingAutoFixturewithObjectHydrator. + This page has moved to /2010/11/22/IntegratingAutoFixturewithObjectHydrator. \ No newline at end of file diff --git a/2010/12/02/InterfacesAreNotAbstractions.aspx/index.html b/2010/12/02/InterfacesAreNotAbstractions.aspx/index.html index 0b6d58d73..fe9a440b8 100644 --- a/2010/12/02/InterfacesAreNotAbstractions.aspx/index.html +++ b/2010/12/02/InterfacesAreNotAbstractions.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/12/02/Interfacesarenotabstractions. + This page has moved to /2010/12/02/Interfacesarenotabstractions. \ No newline at end of file diff --git a/2010/12/03/TowardsBetterAbstractions.aspx/index.html b/2010/12/03/TowardsBetterAbstractions.aspx/index.html index 8bb17e87b..3c915e95e 100644 --- a/2010/12/03/TowardsBetterAbstractions.aspx/index.html +++ b/2010/12/03/TowardsBetterAbstractions.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/12/03/Towardsbetterabstractions. + This page has moved to /2010/12/03/Towardsbetterabstractions. \ No newline at end of file diff --git a/2010/12/18/OnRoleInterfaces,TheReusedAbstractionsPrincipleAndServiceLocators.aspx/index.html b/2010/12/18/OnRoleInterfaces,TheReusedAbstractionsPrincipleAndServiceLocators.aspx/index.html index af1b2a829..45e5ca259 100644 --- a/2010/12/18/OnRoleInterfaces,TheReusedAbstractionsPrincipleAndServiceLocators.aspx/index.html +++ b/2010/12/18/OnRoleInterfaces,TheReusedAbstractionsPrincipleAndServiceLocators.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/12/18/OnRoleInterfaces,theReusedAbstractionsPrincipleandServiceLocators. + This page has moved to /2010/12/18/OnRoleInterfaces,theReusedAbstractionsPrincipleandServiceLocators. \ No newline at end of file diff --git a/2010/12/22/TheTDDApostate.aspx/index.html b/2010/12/22/TheTDDApostate.aspx/index.html index 0a102a99e..0fdc13c9e 100644 --- a/2010/12/22/TheTDDApostate.aspx/index.html +++ b/2010/12/22/TheTDDApostate.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/12/22/TheTDDApostate. + This page has moved to /2010/12/22/TheTDDApostate. \ No newline at end of file diff --git a/2010/12/24/ChallengeResolveClosedTypesWithMEF.aspx/index.html b/2010/12/24/ChallengeResolveClosedTypesWithMEF.aspx/index.html index 9a24a78b1..10fc4d6c7 100644 --- a/2010/12/24/ChallengeResolveClosedTypesWithMEF.aspx/index.html +++ b/2010/12/24/ChallengeResolveClosedTypesWithMEF.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2010/12/24/ChallengeResolveclosedtypeswithMEF. + This page has moved to /2010/12/24/ChallengeResolveclosedtypeswithMEF. \ No newline at end of file diff --git a/2011/01/01/MyChristmasChallengeHasAWinner.aspx/index.html b/2011/01/01/MyChristmasChallengeHasAWinner.aspx/index.html index fa453867c..41622c4e9 100644 --- a/2011/01/01/MyChristmasChallengeHasAWinner.aspx/index.html +++ b/2011/01/01/MyChristmasChallengeHasAWinner.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/01/01/MyChristmaschallengehasawinner. + This page has moved to /2011/01/01/MyChristmaschallengehasawinner. \ No newline at end of file diff --git a/2011/01/24/ScalableDoesntMeanFast.aspx/index.html b/2011/01/24/ScalableDoesntMeanFast.aspx/index.html index 7f52723f2..9bf278f44 100644 --- a/2011/01/24/ScalableDoesntMeanFast.aspx/index.html +++ b/2011/01/24/ScalableDoesntMeanFast.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/01/24/Scalabledoesntmeanfast. + This page has moved to /2011/01/24/Scalabledoesntmeanfast. \ No newline at end of file diff --git a/2011/02/04/TheBCLAlreadyHasAMaybeMonad.aspx/index.html b/2011/02/04/TheBCLAlreadyHasAMaybeMonad.aspx/index.html index b672afb59..75beae849 100644 --- a/2011/02/04/TheBCLAlreadyHasAMaybeMonad.aspx/index.html +++ b/2011/02/04/TheBCLAlreadyHasAMaybeMonad.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/02/04/TheBCLalreadyhasaMaybemonad. + This page has moved to /2011/02/04/TheBCLalreadyhasaMaybemonad. \ No newline at end of file diff --git a/2011/02/07/CreatingSpecificPopulatedListsWithAutoFixture.aspx/index.html b/2011/02/07/CreatingSpecificPopulatedListsWithAutoFixture.aspx/index.html index 41a810375..f65574bb0 100644 --- a/2011/02/07/CreatingSpecificPopulatedListsWithAutoFixture.aspx/index.html +++ b/2011/02/07/CreatingSpecificPopulatedListsWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/02/07/CreatingspecificpopulatedlistswithAutoFixture. + This page has moved to /2011/02/07/CreatingspecificpopulatedlistswithAutoFixture. \ No newline at end of file diff --git a/2011/02/08/CreatingGeneralPopulatedListsWithAutoFixture.aspx/index.html b/2011/02/08/CreatingGeneralPopulatedListsWithAutoFixture.aspx/index.html index 093edbabf..36dac4c03 100644 --- a/2011/02/08/CreatingGeneralPopulatedListsWithAutoFixture.aspx/index.html +++ b/2011/02/08/CreatingGeneralPopulatedListsWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/02/08/CreatinggeneralpopulatedlistswithAutoFixture. + This page has moved to /2011/02/08/CreatinggeneralpopulatedlistswithAutoFixture. \ No newline at end of file diff --git a/2011/02/28/InterfacesAreAccessModifiers.aspx/index.html b/2011/02/28/InterfacesAreAccessModifiers.aspx/index.html index ddebfa555..07a185d3d 100644 --- a/2011/02/28/InterfacesAreAccessModifiers.aspx/index.html +++ b/2011/02/28/InterfacesAreAccessModifiers.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/02/28/Interfacesareaccessmodifiers. + This page has moved to /2011/02/28/Interfacesareaccessmodifiers. \ No newline at end of file diff --git a/2011/03/03/InjectionConstructorsShouldBeSimple.aspx/index.html b/2011/03/03/InjectionConstructorsShouldBeSimple.aspx/index.html index beb3baa92..bbce8bc52 100644 --- a/2011/03/03/InjectionConstructorsShouldBeSimple.aspx/index.html +++ b/2011/03/03/InjectionConstructorsShouldBeSimple.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple. + This page has moved to /2011/03/03/InjectionConstructorsshouldbesimple. \ No newline at end of file diff --git a/2011/03/04/ComposeObjectGraphsWithConfidence.aspx/index.html b/2011/03/04/ComposeObjectGraphsWithConfidence.aspx/index.html index 79884b021..37416ffe1 100644 --- a/2011/03/04/ComposeObjectGraphsWithConfidence.aspx/index.html +++ b/2011/03/04/ComposeObjectGraphsWithConfidence.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence. + This page has moved to /2011/03/04/Composeobjectgraphswithconfidence. \ No newline at end of file diff --git a/2011/03/14/ResolvingClosedTypesWithMEF.aspx/index.html b/2011/03/14/ResolvingClosedTypesWithMEF.aspx/index.html index e8a61b4fd..388c4929c 100644 --- a/2011/03/14/ResolvingClosedTypesWithMEF.aspx/index.html +++ b/2011/03/14/ResolvingClosedTypesWithMEF.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/03/14/ResolvingclosedtypeswithMEF. + This page has moved to /2011/03/14/ResolvingclosedtypeswithMEF. \ No newline at end of file diff --git a/2011/03/18/EncapsulatingAutoFixtureCustomizations.aspx/index.html b/2011/03/18/EncapsulatingAutoFixtureCustomizations.aspx/index.html index 52d3c1ce9..53c69c44f 100644 --- a/2011/03/18/EncapsulatingAutoFixtureCustomizations.aspx/index.html +++ b/2011/03/18/EncapsulatingAutoFixtureCustomizations.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/03/18/EncapsulatingAutoFixtureCustomizations. + This page has moved to /2011/03/18/EncapsulatingAutoFixtureCustomizations. \ No newline at end of file diff --git a/2011/03/22/CommandsAreComposable.aspx/index.html b/2011/03/22/CommandsAreComposable.aspx/index.html index 036754183..eb149ca82 100644 --- a/2011/03/22/CommandsAreComposable.aspx/index.html +++ b/2011/03/22/CommandsAreComposable.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/03/22/CommandsareComposable. + This page has moved to /2011/03/22/CommandsareComposable. \ No newline at end of file diff --git a/2011/04/05/MSDNMagazineArticleAboutCQRSOnWindowsAzure.aspx/index.html b/2011/04/05/MSDNMagazineArticleAboutCQRSOnWindowsAzure.aspx/index.html index a6ac8f983..7d77ddc25 100644 --- a/2011/04/05/MSDNMagazineArticleAboutCQRSOnWindowsAzure.aspx/index.html +++ b/2011/04/05/MSDNMagazineArticleAboutCQRSOnWindowsAzure.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/04/05/MSDNMagazinearticleaboutCQRSonWindowsAzure. + This page has moved to /2011/04/05/MSDNMagazinearticleaboutCQRSonWindowsAzure. \ No newline at end of file diff --git a/2011/04/18/EnumerablesAreDynamicalsoInAutoFixture.aspx/index.html b/2011/04/18/EnumerablesAreDynamicalsoInAutoFixture.aspx/index.html index 86895ca7d..2d5347ef3 100644 --- a/2011/04/18/EnumerablesAreDynamicalsoInAutoFixture.aspx/index.html +++ b/2011/04/18/EnumerablesAreDynamicalsoInAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/04/18/Enumerablesaredynamic-alsoinAutoFixture. + This page has moved to /2011/04/18/Enumerablesaredynamic-alsoinAutoFixture. \ No newline at end of file diff --git a/2011/04/19/AutoFixture2.1Beta1.aspx/index.html b/2011/04/19/AutoFixture2.1Beta1.aspx/index.html index fb6e5d5bb..8c902a3af 100644 --- a/2011/04/19/AutoFixture2.1Beta1.aspx/index.html +++ b/2011/04/19/AutoFixture2.1Beta1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/04/19/AutoFixture2.1beta1. + This page has moved to /2011/04/19/AutoFixture2.1beta1. \ No newline at end of file diff --git a/2011/04/19/AutoFixture21Beta1.aspx/index.html b/2011/04/19/AutoFixture21Beta1.aspx/index.html index fb6e5d5bb..8c902a3af 100644 --- a/2011/04/19/AutoFixture21Beta1.aspx/index.html +++ b/2011/04/19/AutoFixture21Beta1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/04/19/AutoFixture2.1beta1. + This page has moved to /2011/04/19/AutoFixture2.1beta1. \ No newline at end of file diff --git a/2011/04/19/ConstructorStrategiesForAutoFixture.aspx/index.html b/2011/04/19/ConstructorStrategiesForAutoFixture.aspx/index.html index f0d207638..38c378394 100644 --- a/2011/04/19/ConstructorStrategiesForAutoFixture.aspx/index.html +++ b/2011/04/19/ConstructorStrategiesForAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/04/19/ConstructorstrategiesforAutoFixture. + This page has moved to /2011/04/19/ConstructorstrategiesforAutoFixture. \ No newline at end of file diff --git a/2011/04/27/ProviderIsNotAPattern.aspx/index.html b/2011/04/27/ProviderIsNotAPattern.aspx/index.html index 96a70ed27..9a49be30c 100644 --- a/2011/04/27/ProviderIsNotAPattern.aspx/index.html +++ b/2011/04/27/ProviderIsNotAPattern.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/04/27/Providerisnotapattern. + This page has moved to /2011/04/27/Providerisnotapattern. \ No newline at end of file diff --git a/2011/04/29/FeedbackMechanismsAndTradeoffs.aspx/index.html b/2011/04/29/FeedbackMechanismsAndTradeoffs.aspx/index.html index c713d9e11..6fa54c1f0 100644 --- a/2011/04/29/FeedbackMechanismsAndTradeoffs.aspx/index.html +++ b/2011/04/29/FeedbackMechanismsAndTradeoffs.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/04/29/Feedbackmechanismsandtradeoffs. + This page has moved to /2011/04/29/Feedbackmechanismsandtradeoffs. \ No newline at end of file diff --git a/2011/05/02/AutoFixture2.1.aspx/index.html b/2011/05/02/AutoFixture2.1.aspx/index.html index 2a1b841e2..3bdddb4a0 100644 --- a/2011/05/02/AutoFixture2.1.aspx/index.html +++ b/2011/05/02/AutoFixture2.1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/02/AutoFixture2.1. + This page has moved to /2011/05/02/AutoFixture2.1. \ No newline at end of file diff --git a/2011/05/02/AutoFixture21.aspx/index.html b/2011/05/02/AutoFixture21.aspx/index.html index 2a1b841e2..3bdddb4a0 100644 --- a/2011/05/02/AutoFixture21.aspx/index.html +++ b/2011/05/02/AutoFixture21.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/02/AutoFixture2.1. + This page has moved to /2011/05/02/AutoFixture2.1. \ No newline at end of file diff --git a/2011/05/02/WindowsAzureMigrationSmellSQLServerOverutilization.aspx/index.html b/2011/05/02/WindowsAzureMigrationSmellSQLServerOverutilization.aspx/index.html index 5ddcef4ec..358fe447c 100644 --- a/2011/05/02/WindowsAzureMigrationSmellSQLServerOverutilization.aspx/index.html +++ b/2011/05/02/WindowsAzureMigrationSmellSQLServerOverutilization.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/02/WindowsAzuremigrationsmellSQLServerover-utilization. + This page has moved to /2011/05/02/WindowsAzuremigrationsmellSQLServerover-utilization. \ No newline at end of file diff --git a/2011/05/09/GenericUnitTestingWithXUnit.net.aspx/index.html b/2011/05/09/GenericUnitTestingWithXUnit.net.aspx/index.html index 037d0974a..933636f0e 100644 --- a/2011/05/09/GenericUnitTestingWithXUnit.net.aspx/index.html +++ b/2011/05/09/GenericUnitTestingWithXUnit.net.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/09/GenericunittestingwithxUnit.net. + This page has moved to /2011/05/09/GenericunittestingwithxUnit.net. \ No newline at end of file diff --git a/2011/05/09/GenericUnitTestingWithXUnitnet.aspx/index.html b/2011/05/09/GenericUnitTestingWithXUnitnet.aspx/index.html index 037d0974a..933636f0e 100644 --- a/2011/05/09/GenericUnitTestingWithXUnitnet.aspx/index.html +++ b/2011/05/09/GenericUnitTestingWithXUnitnet.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/09/GenericunittestingwithxUnit.net. + This page has moved to /2011/05/09/GenericunittestingwithxUnit.net. \ No newline at end of file diff --git a/2011/05/16/TennisKataWithImmutableTypesAndACyclomaticComplexityOf1.aspx/index.html b/2011/05/16/TennisKataWithImmutableTypesAndACyclomaticComplexityOf1.aspx/index.html index 86b92c2ab..30e152d3b 100644 --- a/2011/05/16/TennisKataWithImmutableTypesAndACyclomaticComplexityOf1.aspx/index.html +++ b/2011/05/16/TennisKataWithImmutableTypesAndACyclomaticComplexityOf1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/16/TennisKatawithimmutabletypesandacyclomaticcomplexityof1. + This page has moved to /2011/05/16/TennisKatawithimmutabletypesandacyclomaticcomplexityof1. \ No newline at end of file diff --git a/2011/05/24/DesignSmellTemporalCoupling.aspx/index.html b/2011/05/24/DesignSmellTemporalCoupling.aspx/index.html index a57229447..48cc7187d 100644 --- a/2011/05/24/DesignSmellTemporalCoupling.aspx/index.html +++ b/2011/05/24/DesignSmellTemporalCoupling.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/24/DesignSmellTemporalCoupling. + This page has moved to /2011/05/24/DesignSmellTemporalCoupling. \ No newline at end of file diff --git a/2011/05/24/PokayokeDesignFromSmellToFragrance.aspx/index.html b/2011/05/24/PokayokeDesignFromSmellToFragrance.aspx/index.html index 982c2af56..07c3d62d8 100644 --- a/2011/05/24/PokayokeDesignFromSmellToFragrance.aspx/index.html +++ b/2011/05/24/PokayokeDesignFromSmellToFragrance.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/24/Poka-yokeDesignFromSmelltoFragrance. + This page has moved to /2011/05/24/Poka-yokeDesignFromSmelltoFragrance. \ No newline at end of file diff --git a/2011/05/25/DesignSmellPrimitiveObsession.aspx/index.html b/2011/05/25/DesignSmellPrimitiveObsession.aspx/index.html index 92d85c956..fa1a6300c 100644 --- a/2011/05/25/DesignSmellPrimitiveObsession.aspx/index.html +++ b/2011/05/25/DesignSmellPrimitiveObsession.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/25/DesignSmellPrimitiveObsession. + This page has moved to /2011/05/25/DesignSmellPrimitiveObsession. \ No newline at end of file diff --git a/2011/05/26/CodeSmellAutomaticProperty.aspx/index.html b/2011/05/26/CodeSmellAutomaticProperty.aspx/index.html index 425d9b02b..1624d87da 100644 --- a/2011/05/26/CodeSmellAutomaticProperty.aspx/index.html +++ b/2011/05/26/CodeSmellAutomaticProperty.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/26/CodeSmellAutomaticProperty. + This page has moved to /2011/05/26/CodeSmellAutomaticProperty. \ No newline at end of file diff --git a/2011/05/27/DesignSmellRedundantRequiredAttribute.aspx/index.html b/2011/05/27/DesignSmellRedundantRequiredAttribute.aspx/index.html index c5c28b62c..33db543e7 100644 --- a/2011/05/27/DesignSmellRedundantRequiredAttribute.aspx/index.html +++ b/2011/05/27/DesignSmellRedundantRequiredAttribute.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/27/DesignSmellRedundantRequiredAttribute. + This page has moved to /2011/05/27/DesignSmellRedundantRequiredAttribute. \ No newline at end of file diff --git a/2011/05/30/DesignSmellDefaultConstructor.aspx/index.html b/2011/05/30/DesignSmellDefaultConstructor.aspx/index.html index 131e0085a..7a1bdb817 100644 --- a/2011/05/30/DesignSmellDefaultConstructor.aspx/index.html +++ b/2011/05/30/DesignSmellDefaultConstructor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/30/DesignSmellDefaultConstructor. + This page has moved to /2011/05/30/DesignSmellDefaultConstructor. \ No newline at end of file diff --git a/2011/05/31/AtTheBoundaries,ApplicationsAreNotObjectOriented.aspx/index.html b/2011/05/31/AtTheBoundaries,ApplicationsAreNotObjectOriented.aspx/index.html index 28cc30525..f6c8d0565 100644 --- a/2011/05/31/AtTheBoundaries,ApplicationsAreNotObjectOriented.aspx/index.html +++ b/2011/05/31/AtTheBoundaries,ApplicationsAreNotObjectOriented.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/31/AttheBoundaries,ApplicationsareNotObject-Oriented. + This page has moved to /2011/05/31/AttheBoundaries,ApplicationsareNotObject-Oriented. \ No newline at end of file diff --git a/2011/05/31/AtTheBoundariesApplicationsAreNotObjectOriented.aspx/index.html b/2011/05/31/AtTheBoundariesApplicationsAreNotObjectOriented.aspx/index.html index 28cc30525..f6c8d0565 100644 --- a/2011/05/31/AtTheBoundariesApplicationsAreNotObjectOriented.aspx/index.html +++ b/2011/05/31/AtTheBoundariesApplicationsAreNotObjectOriented.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/05/31/AttheBoundaries,ApplicationsareNotObject-Oriented. + This page has moved to /2011/05/31/AttheBoundaries,ApplicationsareNotObject-Oriented. \ No newline at end of file diff --git a/2011/06/07/SOLIDCodeIsnt.aspx/index.html b/2011/06/07/SOLIDCodeIsnt.aspx/index.html index a4ca9cf34..b1bd6559b 100644 --- a/2011/06/07/SOLIDCodeIsnt.aspx/index.html +++ b/2011/06/07/SOLIDCodeIsnt.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/06/07/SOLIDCodeisnt. + This page has moved to /2011/06/07/SOLIDCodeisnt. \ No newline at end of file diff --git a/2011/07/28/CompositionRoot.aspx/index.html b/2011/07/28/CompositionRoot.aspx/index.html index 6ec43f0ad..c37dfd623 100644 --- a/2011/07/28/CompositionRoot.aspx/index.html +++ b/2011/07/28/CompositionRoot.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/07/28/CompositionRoot. + This page has moved to /2011/07/28/CompositionRoot. \ No newline at end of file diff --git a/2011/08/01/JoiningAppHarbor.aspx/index.html b/2011/08/01/JoiningAppHarbor.aspx/index.html index 9e33d7da9..8d5a55935 100644 --- a/2011/08/01/JoiningAppHarbor.aspx/index.html +++ b/2011/08/01/JoiningAppHarbor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/08/01/JoiningAppHarbor. + This page has moved to /2011/08/01/JoiningAppHarbor. \ No newline at end of file diff --git a/2011/08/25/ServiceLocatorRolesVs.Mechanics.aspx/index.html b/2011/08/25/ServiceLocatorRolesVs.Mechanics.aspx/index.html index 76220c644..fc95f188a 100644 --- a/2011/08/25/ServiceLocatorRolesVs.Mechanics.aspx/index.html +++ b/2011/08/25/ServiceLocatorRolesVs.Mechanics.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics. + This page has moved to /2011/08/25/ServiceLocatorrolesvs.mechanics. \ No newline at end of file diff --git a/2011/08/25/ServiceLocatorRolesVsMechanics.aspx/index.html b/2011/08/25/ServiceLocatorRolesVsMechanics.aspx/index.html index 76220c644..fc95f188a 100644 --- a/2011/08/25/ServiceLocatorRolesVsMechanics.aspx/index.html +++ b/2011/08/25/ServiceLocatorRolesVsMechanics.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics. + This page has moved to /2011/08/25/ServiceLocatorrolesvs.mechanics. \ No newline at end of file diff --git a/2011/09/06/AutoFixtureGoesContinuousDeliveryWithSemanticVersioning.aspx/index.html b/2011/09/06/AutoFixtureGoesContinuousDeliveryWithSemanticVersioning.aspx/index.html index d6f3cacfc..2ff96237b 100644 --- a/2011/09/06/AutoFixtureGoesContinuousDeliveryWithSemanticVersioning.aspx/index.html +++ b/2011/09/06/AutoFixtureGoesContinuousDeliveryWithSemanticVersioning.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/09/06/AutoFixturegoesContinuousDeliverywithSemanticVersioning. + This page has moved to /2011/09/06/AutoFixturegoesContinuousDeliverywithSemanticVersioning. \ No newline at end of file diff --git a/2011/09/19/MessageDispatchingWithoutServiceLocation.aspx/index.html b/2011/09/19/MessageDispatchingWithoutServiceLocation.aspx/index.html index 6f9562e2c..4fc3fb068 100644 --- a/2011/09/19/MessageDispatchingWithoutServiceLocation.aspx/index.html +++ b/2011/09/19/MessageDispatchingWithoutServiceLocation.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/09/19/MessageDispatchingwithoutServiceLocation. + This page has moved to /2011/09/19/MessageDispatchingwithoutServiceLocation. \ No newline at end of file diff --git a/2011/09/23/WeaklytypedVersusStronglytypedMessageChannels.aspx/index.html b/2011/09/23/WeaklytypedVersusStronglytypedMessageChannels.aspx/index.html index cce56125d..98523ea3c 100644 --- a/2011/09/23/WeaklytypedVersusStronglytypedMessageChannels.aspx/index.html +++ b/2011/09/23/WeaklytypedVersusStronglytypedMessageChannels.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/09/23/Weakly-typedversusStrongly-typedMessageChannels. + This page has moved to /2011/09/23/Weakly-typedversusStrongly-typedMessageChannels. \ No newline at end of file diff --git a/2011/10/11/CheckingForExactlyOneItemInASequenceUsingC#AndF#.aspx/index.html b/2011/10/11/CheckingForExactlyOneItemInASequenceUsingC#AndF#.aspx/index.html index 99fd933f5..7caa94939 100644 --- a/2011/10/11/CheckingForExactlyOneItemInASequenceUsingC#AndF#.aspx/index.html +++ b/2011/10/11/CheckingForExactlyOneItemInASequenceUsingC#AndF#.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/10/11/CheckingforexactlyoneiteminasequenceusingC#andF#. + This page has moved to /2011/10/11/CheckingforexactlyoneiteminasequenceusingC#andF#. \ No newline at end of file diff --git a/2011/10/11/CheckingForExactlyOneItemInASequenceUsingCAndF.aspx/index.html b/2011/10/11/CheckingForExactlyOneItemInASequenceUsingCAndF.aspx/index.html index a90d251b5..667a1e750 100644 --- a/2011/10/11/CheckingForExactlyOneItemInASequenceUsingCAndF.aspx/index.html +++ b/2011/10/11/CheckingForExactlyOneItemInASequenceUsingCAndF.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/10/11/CheckingforexactlyoneiteminasequenceusingCandF. + This page has moved to /2011/10/11/CheckingforexactlyoneiteminasequenceusingCandF. \ No newline at end of file diff --git a/2011/10/25/SOLIDConcrete.aspx/index.html b/2011/10/25/SOLIDConcrete.aspx/index.html index 1e528767b..08944b317 100644 --- a/2011/10/25/SOLIDConcrete.aspx/index.html +++ b/2011/10/25/SOLIDConcrete.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/10/25/SOLIDconcrete. + This page has moved to /2011/10/25/SOLIDconcrete. \ No newline at end of file diff --git a/2011/11/08/Independency.aspx/index.html b/2011/11/08/Independency.aspx/index.html index 21643194e..b64dde131 100644 --- a/2011/11/08/Independency.aspx/index.html +++ b/2011/11/08/Independency.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/11/08/Independency. + This page has moved to /2011/11/08/Independency. \ No newline at end of file diff --git a/2011/11/10/TDDImprovesReusability.aspx/index.html b/2011/11/10/TDDImprovesReusability.aspx/index.html index f36cb736f..584a6a0dd 100644 --- a/2011/11/10/TDDImprovesReusability.aspx/index.html +++ b/2011/11/10/TDDImprovesReusability.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/11/10/TDDimprovesreusability. + This page has moved to /2011/11/10/TDDimprovesreusability. \ No newline at end of file diff --git a/2011/12/07/PolymorphicConsistency.aspx/index.html b/2011/12/07/PolymorphicConsistency.aspx/index.html index 60a4611a0..a93080c04 100644 --- a/2011/12/07/PolymorphicConsistency.aspx/index.html +++ b/2011/12/07/PolymorphicConsistency.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/12/07/PolymorphicConsistency. + This page has moved to /2011/12/07/PolymorphicConsistency. \ No newline at end of file diff --git a/2011/12/19/FactoryOverload.aspx/index.html b/2011/12/19/FactoryOverload.aspx/index.html index 4dd8a4853..3af0b6f21 100644 --- a/2011/12/19/FactoryOverload.aspx/index.html +++ b/2011/12/19/FactoryOverload.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/12/19/FactoryOverload. + This page has moved to /2011/12/19/FactoryOverload. \ No newline at end of file diff --git a/2011/12/21/TestingContainerConfigurations.aspx/index.html b/2011/12/21/TestingContainerConfigurations.aspx/index.html index 2d5093d79..2f249ce9e 100644 --- a/2011/12/21/TestingContainerConfigurations.aspx/index.html +++ b/2011/12/21/TestingContainerConfigurations.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2011/12/21/TestingContainerConfigurations. + This page has moved to /2011/12/21/TestingContainerConfigurations. \ No newline at end of file diff --git a/2012/01/03/SOLIDIsAppendonly.aspx/index.html b/2012/01/03/SOLIDIsAppendonly.aspx/index.html index 34d80aeec..3c3197be0 100644 --- a/2012/01/03/SOLIDIsAppendonly.aspx/index.html +++ b/2012/01/03/SOLIDIsAppendonly.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/01/03/SOLIDisAppend-only. + This page has moved to /2012/01/03/SOLIDisAppend-only. \ No newline at end of file diff --git a/2012/02/02/LooseCouplingAndTheBigPicture.aspx/index.html b/2012/02/02/LooseCouplingAndTheBigPicture.aspx/index.html index fbd87ff92..5022d0f1f 100644 --- a/2012/02/02/LooseCouplingAndTheBigPicture.aspx/index.html +++ b/2012/02/02/LooseCouplingAndTheBigPicture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/02/02/LooseCouplingandtheBigPicture. + This page has moved to /2012/02/02/LooseCouplingandtheBigPicture. \ No newline at end of file diff --git a/2012/02/09/IsLayeringWorthTheMapping.aspx/index.html b/2012/02/09/IsLayeringWorthTheMapping.aspx/index.html index 399348e20..3428e0d33 100644 --- a/2012/02/09/IsLayeringWorthTheMapping.aspx/index.html +++ b/2012/02/09/IsLayeringWorthTheMapping.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/02/09/IsLayeringWorththeMapping. + This page has moved to /2012/02/09/IsLayeringWorththeMapping. \ No newline at end of file diff --git a/2012/03/15/ImplementingAnAbstractFactory.aspx/index.html b/2012/03/15/ImplementingAnAbstractFactory.aspx/index.html index cdb07205d..4304033a9 100644 --- a/2012/03/15/ImplementingAnAbstractFactory.aspx/index.html +++ b/2012/03/15/ImplementingAnAbstractFactory.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory. + This page has moved to /2012/03/15/ImplementinganAbstractFactory. \ No newline at end of file diff --git a/2012/03/19/MigratingFromWCFWebAPIToASP.NETWebAPI.aspx/index.html b/2012/03/19/MigratingFromWCFWebAPIToASP.NETWebAPI.aspx/index.html index 776772cae..96076ea52 100644 --- a/2012/03/19/MigratingFromWCFWebAPIToASP.NETWebAPI.aspx/index.html +++ b/2012/03/19/MigratingFromWCFWebAPIToASP.NETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/03/19/MigratingfromWCFWebAPItoASP.NETWebAPI. + This page has moved to /2012/03/19/MigratingfromWCFWebAPItoASP.NETWebAPI. \ No newline at end of file diff --git a/2012/03/19/MigratingFromWCFWebAPIToASPNETWebAPI.aspx/index.html b/2012/03/19/MigratingFromWCFWebAPIToASPNETWebAPI.aspx/index.html index 776772cae..96076ea52 100644 --- a/2012/03/19/MigratingFromWCFWebAPIToASPNETWebAPI.aspx/index.html +++ b/2012/03/19/MigratingFromWCFWebAPIToASPNETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/03/19/MigratingfromWCFWebAPItoASP.NETWebAPI. + This page has moved to /2012/03/19/MigratingfromWCFWebAPItoASP.NETWebAPI. \ No newline at end of file diff --git a/2012/03/20/RobustDIWithTheASP.NETWebAPI.aspx/index.html b/2012/03/20/RobustDIWithTheASP.NETWebAPI.aspx/index.html index c1bc49c82..adaf2abff 100644 --- a/2012/03/20/RobustDIWithTheASP.NETWebAPI.aspx/index.html +++ b/2012/03/20/RobustDIWithTheASP.NETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/03/20/RobustDIWiththeASP.NETWebAPI. + This page has moved to /2012/03/20/RobustDIWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx/index.html b/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx/index.html index c1bc49c82..adaf2abff 100644 --- a/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx/index.html +++ b/2012/03/20/RobustDIWithTheASPNETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/03/20/RobustDIWiththeASP.NETWebAPI. + This page has moved to /2012/03/20/RobustDIWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/03/26/IQueryableTIsTightCoupling.aspx/index.html b/2012/03/26/IQueryableTIsTightCoupling.aspx/index.html index 56094a982..b32fd2251 100644 --- a/2012/03/26/IQueryableTIsTightCoupling.aspx/index.html +++ b/2012/03/26/IQueryableTIsTightCoupling.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/03/26/IQueryableTisTightCoupling. + This page has moved to /2012/03/26/IQueryableTisTightCoupling. \ No newline at end of file diff --git a/2012/04/17/HyperlinkingWithTheASP.NETWebAPI.aspx/index.html b/2012/04/17/HyperlinkingWithTheASP.NETWebAPI.aspx/index.html index 34581a90b..f5c1e9551 100644 --- a/2012/04/17/HyperlinkingWithTheASP.NETWebAPI.aspx/index.html +++ b/2012/04/17/HyperlinkingWithTheASP.NETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/04/17/HyperlinkingWiththeASP.NETWebAPI. + This page has moved to /2012/04/17/HyperlinkingWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/04/17/HyperlinkingWithTheASPNETWebAPI.aspx/index.html b/2012/04/17/HyperlinkingWithTheASPNETWebAPI.aspx/index.html index 34581a90b..f5c1e9551 100644 --- a/2012/04/17/HyperlinkingWithTheASPNETWebAPI.aspx/index.html +++ b/2012/04/17/HyperlinkingWithTheASPNETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/04/17/HyperlinkingWiththeASP.NETWebAPI. + This page has moved to /2012/04/17/HyperlinkingWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/04/17/InjectingHttpControllerContextWithTheASP.NETWebAPI.aspx/index.html b/2012/04/17/InjectingHttpControllerContextWithTheASP.NETWebAPI.aspx/index.html index 453bbc0de..0209f90e1 100644 --- a/2012/04/17/InjectingHttpControllerContextWithTheASP.NETWebAPI.aspx/index.html +++ b/2012/04/17/InjectingHttpControllerContextWithTheASP.NETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/04/17/InjectingHttpControllerContextWiththeASP.NETWebAPI. + This page has moved to /2012/04/17/InjectingHttpControllerContextWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/04/17/InjectingHttpControllerContextWithTheASPNETWebAPI.aspx/index.html b/2012/04/17/InjectingHttpControllerContextWithTheASPNETWebAPI.aspx/index.html index 453bbc0de..0209f90e1 100644 --- a/2012/04/17/InjectingHttpControllerContextWithTheASPNETWebAPI.aspx/index.html +++ b/2012/04/17/InjectingHttpControllerContextWithTheASPNETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/04/17/InjectingHttpControllerContextWiththeASP.NETWebAPI. + This page has moved to /2012/04/17/InjectingHttpControllerContextWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx/index.html b/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx/index.html index 9bb270848..3ab7c4f9a 100644 --- a/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx/index.html +++ b/2012/04/19/WiringHttpControllerContextWithCastleWindsor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/04/19/WiringHttpControllerContextWithCastleWindsor. + This page has moved to /2012/04/19/WiringHttpControllerContextWithCastleWindsor. \ No newline at end of file diff --git a/2012/04/24/VendorMediaTypesWithTheASP.NETWebAPI.aspx/index.html b/2012/04/24/VendorMediaTypesWithTheASP.NETWebAPI.aspx/index.html index 897f549c4..f6a4e0a6a 100644 --- a/2012/04/24/VendorMediaTypesWithTheASP.NETWebAPI.aspx/index.html +++ b/2012/04/24/VendorMediaTypesWithTheASP.NETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/04/24/VendorMediaTypesWiththeASP.NETWebAPI. + This page has moved to /2012/04/24/VendorMediaTypesWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/04/24/VendorMediaTypesWithTheASPNETWebAPI.aspx/index.html b/2012/04/24/VendorMediaTypesWithTheASPNETWebAPI.aspx/index.html index 897f549c4..f6a4e0a6a 100644 --- a/2012/04/24/VendorMediaTypesWithTheASPNETWebAPI.aspx/index.html +++ b/2012/04/24/VendorMediaTypesWithTheASPNETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/04/24/VendorMediaTypesWiththeASP.NETWebAPI. + This page has moved to /2012/04/24/VendorMediaTypesWiththeASP.NETWebAPI. \ No newline at end of file diff --git a/2012/05/24/TDDTestSuitesShouldRunIn10SecondsOrLess.aspx/index.html b/2012/05/24/TDDTestSuitesShouldRunIn10SecondsOrLess.aspx/index.html index 3fc0c39af..a97ff1df0 100644 --- a/2012/05/24/TDDTestSuitesShouldRunIn10SecondsOrLess.aspx/index.html +++ b/2012/05/24/TDDTestSuitesShouldRunIn10SecondsOrLess.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/05/24/TDDtestsuitesshouldrunin10secondsorless. + This page has moved to /2012/05/24/TDDtestsuitesshouldrunin10secondsorless. \ No newline at end of file diff --git a/2012/05/25/DesignPatternsAcrossParadigms.aspx/index.html b/2012/05/25/DesignPatternsAcrossParadigms.aspx/index.html index 0a42cd348..c134a2c68 100644 --- a/2012/05/25/DesignPatternsAcrossParadigms.aspx/index.html +++ b/2012/05/25/DesignPatternsAcrossParadigms.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/05/25/Designpatternsacrossparadigms. + This page has moved to /2012/05/25/Designpatternsacrossparadigms. \ No newline at end of file diff --git a/2012/05/29/BankOCRKataInF#UserStory1.aspx/index.html b/2012/05/29/BankOCRKataInF#UserStory1.aspx/index.html index 6220151c2..d75daba9d 100644 --- a/2012/05/29/BankOCRKataInF#UserStory1.aspx/index.html +++ b/2012/05/29/BankOCRKataInF#UserStory1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/05/29/BankOCRkatainF#userstory1. + This page has moved to /2012/05/29/BankOCRkatainF#userstory1. \ No newline at end of file diff --git a/2012/05/29/BankOCRKataInFUserStory1.aspx/index.html b/2012/05/29/BankOCRKataInFUserStory1.aspx/index.html index e171ca44b..108b6b374 100644 --- a/2012/05/29/BankOCRKataInFUserStory1.aspx/index.html +++ b/2012/05/29/BankOCRKataInFUserStory1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/05/29/BankOCRkatainFuserstory1. + This page has moved to /2012/05/29/BankOCRkatainFuserstory1. \ No newline at end of file diff --git a/2012/06/01/BankOCRKataInF#UserStory2.aspx/index.html b/2012/06/01/BankOCRKataInF#UserStory2.aspx/index.html index 10661f75a..1aa5e0e03 100644 --- a/2012/06/01/BankOCRKataInF#UserStory2.aspx/index.html +++ b/2012/06/01/BankOCRKataInF#UserStory2.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/01/BankOCRkatainF#userstory2. + This page has moved to /2012/06/01/BankOCRkatainF#userstory2. \ No newline at end of file diff --git a/2012/06/01/BankOCRKataInFUserStory2.aspx/index.html b/2012/06/01/BankOCRKataInFUserStory2.aspx/index.html index 5d32dd959..28f289319 100644 --- a/2012/06/01/BankOCRKataInFUserStory2.aspx/index.html +++ b/2012/06/01/BankOCRKataInFUserStory2.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/01/BankOCRkatainFuserstory2. + This page has moved to /2012/06/01/BankOCRkatainFuserstory2. \ No newline at end of file diff --git a/2012/06/04/BankOCRKataInF#UserStories3And4.aspx/index.html b/2012/06/04/BankOCRKataInF#UserStories3And4.aspx/index.html index 2d2a4945a..04bf5faa8 100644 --- a/2012/06/04/BankOCRKataInF#UserStories3And4.aspx/index.html +++ b/2012/06/04/BankOCRKataInF#UserStories3And4.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/04/BankOCRkatainF#userstories3and4. + This page has moved to /2012/06/04/BankOCRkatainF#userstories3and4. \ No newline at end of file diff --git a/2012/06/04/BankOCRKataInFUserStories3And4.aspx/index.html b/2012/06/04/BankOCRKataInFUserStories3And4.aspx/index.html index 9793cae7d..5a9b00017 100644 --- a/2012/06/04/BankOCRKataInFUserStories3And4.aspx/index.html +++ b/2012/06/04/BankOCRKataInFUserStories3And4.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/04/BankOCRkatainFuserstories3and4. + This page has moved to /2012/06/04/BankOCRkatainFuserstories3and4. \ No newline at end of file diff --git a/2012/06/21/TheResemblanceIdiom.aspx/index.html b/2012/06/21/TheResemblanceIdiom.aspx/index.html index eb5b5f698..cb9ca310a 100644 --- a/2012/06/21/TheResemblanceIdiom.aspx/index.html +++ b/2012/06/21/TheResemblanceIdiom.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/21/TheResemblanceidiom. + This page has moved to /2012/06/21/TheResemblanceidiom. \ No newline at end of file diff --git a/2012/06/22/ResemblanceAndLikeness.aspx/index.html b/2012/06/22/ResemblanceAndLikeness.aspx/index.html index 085819673..2c4a38c36 100644 --- a/2012/06/22/ResemblanceAndLikeness.aspx/index.html +++ b/2012/06/22/ResemblanceAndLikeness.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/22/ResemblanceandLikeness. + This page has moved to /2012/06/22/ResemblanceandLikeness. \ No newline at end of file diff --git a/2012/06/22/TestspecificEqualityVersusDomainEquality.aspx/index.html b/2012/06/22/TestspecificEqualityVersusDomainEquality.aspx/index.html index 094930652..a12bdf22e 100644 --- a/2012/06/22/TestspecificEqualityVersusDomainEquality.aspx/index.html +++ b/2012/06/22/TestspecificEqualityVersusDomainEquality.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/22/Test-specificEqualityversusDomainEquality. + This page has moved to /2012/06/22/Test-specificEqualityversusDomainEquality. \ No newline at end of file diff --git a/2012/06/27/FacadeTest.aspx/index.html b/2012/06/27/FacadeTest.aspx/index.html index e018f4b62..fb8867ca6 100644 --- a/2012/06/27/FacadeTest.aspx/index.html +++ b/2012/06/27/FacadeTest.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/06/27/FacadeTest. + This page has moved to /2012/06/27/FacadeTest. \ No newline at end of file diff --git a/2012/07/02/PrimitiveDependencies.aspx/index.html b/2012/07/02/PrimitiveDependencies.aspx/index.html index 52914b769..a352e94c9 100644 --- a/2012/07/02/PrimitiveDependencies.aspx/index.html +++ b/2012/07/02/PrimitiveDependencies.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/07/02/PrimitiveDependencies. + This page has moved to /2012/07/02/PrimitiveDependencies. \ No newline at end of file diff --git a/2012/07/18/Hyprlinkr.aspx/index.html b/2012/07/18/Hyprlinkr.aspx/index.html index 97f7ff5f8..5bed088d3 100644 --- a/2012/07/18/Hyprlinkr.aspx/index.html +++ b/2012/07/18/Hyprlinkr.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/07/18/Hyprlinkr. + This page has moved to /2012/07/18/Hyprlinkr. \ No newline at end of file diff --git a/2012/07/20/FizzBuzzKataInF#Stage1.aspx/index.html b/2012/07/20/FizzBuzzKataInF#Stage1.aspx/index.html index 607d73f4f..4b66bf856 100644 --- a/2012/07/20/FizzBuzzKataInF#Stage1.aspx/index.html +++ b/2012/07/20/FizzBuzzKataInF#Stage1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/07/20/FizzBuzzkatainF#stage1. + This page has moved to /2012/07/20/FizzBuzzkatainF#stage1. \ No newline at end of file diff --git a/2012/07/20/FizzBuzzKataInFStage1.aspx/index.html b/2012/07/20/FizzBuzzKataInFStage1.aspx/index.html index 2fcc68de3..98d31fdb5 100644 --- a/2012/07/20/FizzBuzzKataInFStage1.aspx/index.html +++ b/2012/07/20/FizzBuzzKataInFStage1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/07/20/FizzBuzzkatainFstage1. + This page has moved to /2012/07/20/FizzBuzzkatainFstage1. \ No newline at end of file diff --git a/2012/07/25/FizzBuzzKataInF#Stage2.aspx/index.html b/2012/07/25/FizzBuzzKataInF#Stage2.aspx/index.html index 2c903345b..d89380e79 100644 --- a/2012/07/25/FizzBuzzKataInF#Stage2.aspx/index.html +++ b/2012/07/25/FizzBuzzKataInF#Stage2.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/07/25/FizzBuzzkatainF#stage2. + This page has moved to /2012/07/25/FizzBuzzkatainF#stage2. \ No newline at end of file diff --git a/2012/07/25/FizzBuzzKataInFStage2.aspx/index.html b/2012/07/25/FizzBuzzKataInFStage2.aspx/index.html index 1e28e7c52..7d70ea7a6 100644 --- a/2012/07/25/FizzBuzzKataInFStage2.aspx/index.html +++ b/2012/07/25/FizzBuzzKataInFStage2.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/07/25/FizzBuzzkatainFstage2. + This page has moved to /2012/07/25/FizzBuzzkatainFstage2. \ No newline at end of file diff --git a/2012/07/31/TheOrderOfAutoFixtureCustomizationsMatter.aspx/index.html b/2012/07/31/TheOrderOfAutoFixtureCustomizationsMatter.aspx/index.html index 260df9a68..b85ffbca7 100644 --- a/2012/07/31/TheOrderOfAutoFixtureCustomizationsMatter.aspx/index.html +++ b/2012/07/31/TheOrderOfAutoFixtureCustomizationsMatter.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/07/31/TheorderofAutoFixtureCustomizationsmatter. + This page has moved to /2012/07/31/TheorderofAutoFixtureCustomizationsmatter. \ No newline at end of file diff --git a/2012/08/31/ConcreteDependencies.aspx/index.html b/2012/08/31/ConcreteDependencies.aspx/index.html index 30f7a3860..9ee385283 100644 --- a/2012/08/31/ConcreteDependencies.aspx/index.html +++ b/2012/08/31/ConcreteDependencies.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/08/31/ConcreteDependencies. + This page has moved to /2012/08/31/ConcreteDependencies. \ No newline at end of file diff --git a/2012/09/28/DependencyInjectionAndLifetimeManagementWithASP.NETWebAPI.aspx/index.html b/2012/09/28/DependencyInjectionAndLifetimeManagementWithASP.NETWebAPI.aspx/index.html index 56ee4c964..c76283c78 100644 --- a/2012/09/28/DependencyInjectionAndLifetimeManagementWithASP.NETWebAPI.aspx/index.html +++ b/2012/09/28/DependencyInjectionAndLifetimeManagementWithASP.NETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/09/28/DependencyInjectionandLifetimeManagementwithASP.NETWebAPI. + This page has moved to /2012/09/28/DependencyInjectionandLifetimeManagementwithASP.NETWebAPI. \ No newline at end of file diff --git a/2012/09/28/DependencyInjectionAndLifetimeManagementWithASPNETWebAPI.aspx/index.html b/2012/09/28/DependencyInjectionAndLifetimeManagementWithASPNETWebAPI.aspx/index.html index 56ee4c964..c76283c78 100644 --- a/2012/09/28/DependencyInjectionAndLifetimeManagementWithASPNETWebAPI.aspx/index.html +++ b/2012/09/28/DependencyInjectionAndLifetimeManagementWithASPNETWebAPI.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/09/28/DependencyInjectionandLifetimeManagementwithASP.NETWebAPI. + This page has moved to /2012/09/28/DependencyInjectionandLifetimeManagementwithASP.NETWebAPI. \ No newline at end of file diff --git a/2012/10/03/DependencyInjectionInASP.NETWebAPIWithCastleWindsor.aspx/index.html b/2012/10/03/DependencyInjectionInASP.NETWebAPIWithCastleWindsor.aspx/index.html index 0d0c95e48..769efa4ac 100644 --- a/2012/10/03/DependencyInjectionInASP.NETWebAPIWithCastleWindsor.aspx/index.html +++ b/2012/10/03/DependencyInjectionInASP.NETWebAPIWithCastleWindsor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor. + This page has moved to /2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor. \ No newline at end of file diff --git a/2012/10/03/DependencyInjectionInASPNETWebAPIWithCastleWindsor.aspx/index.html b/2012/10/03/DependencyInjectionInASPNETWebAPIWithCastleWindsor.aspx/index.html index 0d0c95e48..769efa4ac 100644 --- a/2012/10/03/DependencyInjectionInASPNETWebAPIWithCastleWindsor.aspx/index.html +++ b/2012/10/03/DependencyInjectionInASPNETWebAPIWithCastleWindsor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor. + This page has moved to /2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor. \ No newline at end of file diff --git a/2012/11/06/WhenToUseADIContainer.aspx/index.html b/2012/11/06/WhenToUseADIContainer.aspx/index.html index 46515014e..56c427257 100644 --- a/2012/11/06/WhenToUseADIContainer.aspx/index.html +++ b/2012/11/06/WhenToUseADIContainer.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/11/06/WhentouseaDIContainer. + This page has moved to /2012/11/06/WhentouseaDIContainer. \ No newline at end of file diff --git a/2012/11/07/AppSettingsConventionForCastleWindsor.aspx/index.html b/2012/11/07/AppSettingsConventionForCastleWindsor.aspx/index.html index 058096630..eacf2607a 100644 --- a/2012/11/07/AppSettingsConventionForCastleWindsor.aspx/index.html +++ b/2012/11/07/AppSettingsConventionForCastleWindsor.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/11/07/AppSettingsconventionforCastleWindsor. + This page has moved to /2012/11/07/AppSettingsconventionforCastleWindsor. \ No newline at end of file diff --git a/2012/11/27/EncapsulationOfProperties.aspx/index.html b/2012/11/27/EncapsulationOfProperties.aspx/index.html index e366b8fad..3de3ed28f 100644 --- a/2012/11/27/EncapsulationOfProperties.aspx/index.html +++ b/2012/11/27/EncapsulationOfProperties.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/11/27/Encapsulationofproperties. + This page has moved to /2012/11/27/Encapsulationofproperties. \ No newline at end of file diff --git a/2012/12/18/RangersAndZookeepers.aspx/index.html b/2012/12/18/RangersAndZookeepers.aspx/index.html index d85acc098..328c32b83 100644 --- a/2012/12/18/RangersAndZookeepers.aspx/index.html +++ b/2012/12/18/RangersAndZookeepers.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/12/18/RangersandZookeepers. + This page has moved to /2012/12/18/RangersandZookeepers. \ No newline at end of file diff --git a/2012/12/18/ZookeepersMustBecomeRangers.aspx/index.html b/2012/12/18/ZookeepersMustBecomeRangers.aspx/index.html index 62133a4ed..912384e35 100644 --- a/2012/12/18/ZookeepersMustBecomeRangers.aspx/index.html +++ b/2012/12/18/ZookeepersMustBecomeRangers.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2012/12/18/ZookeepersmustbecomeRangers. + This page has moved to /2012/12/18/ZookeepersmustbecomeRangers. \ No newline at end of file diff --git a/2013/01/07/RoleHints.aspx/index.html b/2013/01/07/RoleHints.aspx/index.html index dafe4deda..d780f8108 100644 --- a/2013/01/07/RoleHints.aspx/index.html +++ b/2013/01/07/RoleHints.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/07/RoleHints. + This page has moved to /2013/01/07/RoleHints. \ No newline at end of file diff --git a/2013/01/07/TypeNameRoleHints.aspx/index.html b/2013/01/07/TypeNameRoleHints.aspx/index.html index 609239d5b..c68bb186f 100644 --- a/2013/01/07/TypeNameRoleHints.aspx/index.html +++ b/2013/01/07/TypeNameRoleHints.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/07/TypeNameRoleHints. + This page has moved to /2013/01/07/TypeNameRoleHints. \ No newline at end of file diff --git a/2013/01/08/ArgumentNameRoleHint.aspx/index.html b/2013/01/08/ArgumentNameRoleHint.aspx/index.html index 5fdd88288..2fca6abee 100644 --- a/2013/01/08/ArgumentNameRoleHint.aspx/index.html +++ b/2013/01/08/ArgumentNameRoleHint.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/08/ArgumentNameRoleHint. + This page has moved to /2013/01/08/ArgumentNameRoleHint. \ No newline at end of file diff --git a/2013/01/09/MetadataRoleHint.aspx/index.html b/2013/01/09/MetadataRoleHint.aspx/index.html index 59ecc8040..abedbaa81 100644 --- a/2013/01/09/MetadataRoleHint.aspx/index.html +++ b/2013/01/09/MetadataRoleHint.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/09/MetadataRoleHint. + This page has moved to /2013/01/09/MetadataRoleHint. \ No newline at end of file diff --git a/2013/01/09/NSubstituteAutomockingWithAutoFixture.aspx/index.html b/2013/01/09/NSubstituteAutomockingWithAutoFixture.aspx/index.html index 896332b19..6c7316372 100644 --- a/2013/01/09/NSubstituteAutomockingWithAutoFixture.aspx/index.html +++ b/2013/01/09/NSubstituteAutomockingWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/09/NSubstituteAuto-mockingwithAutoFixture. + This page has moved to /2013/01/09/NSubstituteAuto-mockingwithAutoFixture. \ No newline at end of file diff --git a/2013/01/10/RoleInterfaceRoleHint.aspx/index.html b/2013/01/10/RoleInterfaceRoleHint.aspx/index.html index 1eae46543..bbae92917 100644 --- a/2013/01/10/RoleInterfaceRoleHint.aspx/index.html +++ b/2013/01/10/RoleInterfaceRoleHint.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/10/RoleInterfaceRoleHint. + This page has moved to /2013/01/10/RoleInterfaceRoleHint. \ No newline at end of file diff --git a/2013/01/11/PartialTypeNameRoleHint.aspx/index.html b/2013/01/11/PartialTypeNameRoleHint.aspx/index.html index 675325000..02a1a3f76 100644 --- a/2013/01/11/PartialTypeNameRoleHint.aspx/index.html +++ b/2013/01/11/PartialTypeNameRoleHint.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/11/PartialTypeNameRoleHint. + This page has moved to /2013/01/11/PartialTypeNameRoleHint. \ No newline at end of file diff --git a/2013/01/16/OutsideInTestDrivenDevelopmentPluralsightCourse.aspx/index.html b/2013/01/16/OutsideInTestDrivenDevelopmentPluralsightCourse.aspx/index.html index f49bcff27..5a5208c5f 100644 --- a/2013/01/16/OutsideInTestDrivenDevelopmentPluralsightCourse.aspx/index.html +++ b/2013/01/16/OutsideInTestDrivenDevelopmentPluralsightCourse.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/01/16/Outside-InTest-DrivenDevelopmentPluralsightcourse. + This page has moved to /2013/01/16/Outside-InTest-DrivenDevelopmentPluralsightcourse. \ No newline at end of file diff --git a/2013/02/04/BewareOfProductivityTools.aspx/index.html b/2013/02/04/BewareOfProductivityTools.aspx/index.html index 8bc9c5e30..16bfc6535 100644 --- a/2013/02/04/BewareOfProductivityTools.aspx/index.html +++ b/2013/02/04/BewareOfProductivityTools.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/04/BewareofProductivityTools. + This page has moved to /2013/02/04/BewareofProductivityTools. \ No newline at end of file diff --git a/2013/02/06/StringCalculatorKataWithAutoFixture.aspx/index.html b/2013/02/06/StringCalculatorKataWithAutoFixture.aspx/index.html index 8c6c34028..44b505875 100644 --- a/2013/02/06/StringCalculatorKataWithAutoFixture.aspx/index.html +++ b/2013/02/06/StringCalculatorKataWithAutoFixture.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/06/StringCalculatorkatawithAutoFixture. + This page has moved to /2013/02/06/StringCalculatorkatawithAutoFixture. \ No newline at end of file diff --git a/2013/02/06/StringCalculatorKataWithAutoFixtureExercise1.aspx/index.html b/2013/02/06/StringCalculatorKataWithAutoFixtureExercise1.aspx/index.html index 6df0593a7..c6f6fa51b 100644 --- a/2013/02/06/StringCalculatorKataWithAutoFixtureExercise1.aspx/index.html +++ b/2013/02/06/StringCalculatorKataWithAutoFixtureExercise1.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/06/StringCalculatorkatawithAutoFixtureexercise1. + This page has moved to /2013/02/06/StringCalculatorkatawithAutoFixtureexercise1. \ No newline at end of file diff --git a/2013/02/07/StringCalculatorKataWithAutofixtureExercise2.aspx/index.html b/2013/02/07/StringCalculatorKataWithAutofixtureExercise2.aspx/index.html index 2f37fa9df..e9abf6788 100644 --- a/2013/02/07/StringCalculatorKataWithAutofixtureExercise2.aspx/index.html +++ b/2013/02/07/StringCalculatorKataWithAutofixtureExercise2.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/07/StringCalculatorkatawithAutofixtureexercise2. + This page has moved to /2013/02/07/StringCalculatorkatawithAutofixtureexercise2. \ No newline at end of file diff --git a/2013/02/11/StringCalculatorKataWithAutofixtureExercise3.aspx/index.html b/2013/02/11/StringCalculatorKataWithAutofixtureExercise3.aspx/index.html index f579c4fe3..2ec7ca350 100644 --- a/2013/02/11/StringCalculatorKataWithAutofixtureExercise3.aspx/index.html +++ b/2013/02/11/StringCalculatorKataWithAutofixtureExercise3.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/11/StringCalculatorkatawithAutofixtureexercise3. + This page has moved to /2013/02/11/StringCalculatorkatawithAutofixtureexercise3. \ No newline at end of file diff --git a/2013/02/12/StringCalculatorKataWithAutofixtureExercise4.aspx/index.html b/2013/02/12/StringCalculatorKataWithAutofixtureExercise4.aspx/index.html index 232356c3c..d447a5270 100644 --- a/2013/02/12/StringCalculatorKataWithAutofixtureExercise4.aspx/index.html +++ b/2013/02/12/StringCalculatorKataWithAutofixtureExercise4.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/12/StringCalculatorkatawithAutofixtureexercise4. + This page has moved to /2013/02/12/StringCalculatorkatawithAutofixtureexercise4. \ No newline at end of file diff --git a/2013/02/13/StringCalculatorKataWithAutofixtureExercise5.aspx/index.html b/2013/02/13/StringCalculatorKataWithAutofixtureExercise5.aspx/index.html index 94ff651fc..d74ff82a2 100644 --- a/2013/02/13/StringCalculatorKataWithAutofixtureExercise5.aspx/index.html +++ b/2013/02/13/StringCalculatorKataWithAutofixtureExercise5.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/13/StringCalculatorkatawithAutofixtureexercise5. + This page has moved to /2013/02/13/StringCalculatorkatawithAutofixtureexercise5. \ No newline at end of file diff --git a/2013/02/14/StringCalculatorKataWithAutofixtureExercise6.aspx/index.html b/2013/02/14/StringCalculatorKataWithAutofixtureExercise6.aspx/index.html index 2c9ded2c3..59141599b 100644 --- a/2013/02/14/StringCalculatorKataWithAutofixtureExercise6.aspx/index.html +++ b/2013/02/14/StringCalculatorKataWithAutofixtureExercise6.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/14/StringCalculatorkatawithAutofixtureexercise6. + This page has moved to /2013/02/14/StringCalculatorkatawithAutofixtureexercise6. \ No newline at end of file diff --git a/2013/02/15/StringCalculatorKataWithAutofixtureExercise7.aspx/index.html b/2013/02/15/StringCalculatorKataWithAutofixtureExercise7.aspx/index.html index d0b7ad93f..7e6d06f44 100644 --- a/2013/02/15/StringCalculatorKataWithAutofixtureExercise7.aspx/index.html +++ b/2013/02/15/StringCalculatorKataWithAutofixtureExercise7.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/15/StringCalculatorkatawithAutofixtureexercise7. + This page has moved to /2013/02/15/StringCalculatorkatawithAutofixtureexercise7. \ No newline at end of file diff --git a/2013/02/18/StringCalculatorKataWithAutofixtureExercise8.aspx/index.html b/2013/02/18/StringCalculatorKataWithAutofixtureExercise8.aspx/index.html index 2ae703320..d8dada143 100644 --- a/2013/02/18/StringCalculatorKataWithAutofixtureExercise8.aspx/index.html +++ b/2013/02/18/StringCalculatorKataWithAutofixtureExercise8.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/02/18/StringCalculatorkatawithAutofixtureexercise8. + This page has moved to /2013/02/18/StringCalculatorkatawithAutofixtureexercise8. \ No newline at end of file diff --git a/2013/03/01/AutoFixture3.aspx/index.html b/2013/03/01/AutoFixture3.aspx/index.html index 487f7867d..0ff0fe6fb 100644 --- a/2013/03/01/AutoFixture3.aspx/index.html +++ b/2013/03/01/AutoFixture3.aspx/index.html @@ -3,11 +3,11 @@ Content moved - + - This page has moved to http://blog.ploeh.dk/2013/03/01/AutoFixture3. + This page has moved to /2013/03/01/AutoFixture3. \ No newline at end of file diff --git a/README.md b/README.md index 740f319a1..f59435919 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # ploeh blog -This repository contains the templates and data for my blog at . It is powered by [Jekyll-Bootstrap](http://jekyllbootstrap.com). +This repository contains the templates and data for my blog at <>. It is powered by [Jekyll-Bootstrap](http://jekyllbootstrap.com). ## Comments As an experiment, all comments for a particular post are kept as part of the post itself. -If you wish to comment on a particular post, send me a pull request for that post. If you're in doubt about the format, just look at how previous comments are formatted. For an example of a post with comments, see e.g. [the very first post on this blog](http://blog.ploeh.dk/2009/01/28/LivingInInterestingTimes). +If you wish to comment on a particular post, send me a pull request for that post. If you're in doubt about the format, just look at how previous comments are formatted. For an example of a post with comments, see e.g. [the very first post on this blog](/2009/01/28/LivingInInterestingTimes). ## Contributions diff --git a/_includes/themes/ploeh/contact_sidebar.html b/_includes/themes/ploeh/contact_sidebar.html index 465bf97b7..2f2d01c59 100644 --- a/_includes/themes/ploeh/contact_sidebar.html +++ b/_includes/themes/ploeh/contact_sidebar.html @@ -14,7 +14,7 @@ Watch my Clean Coders videos
@@ -25,5 +25,5 @@
"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
- Hire me! + Hire me!
\ No newline at end of file diff --git a/_posts/2009-01-28-Zero-FrictionTDD.html b/_posts/2009-01-28-Zero-FrictionTDD.html index f0aebfec0..11308bb6a 100644 --- a/_posts/2009-01-28-Zero-FrictionTDD.html +++ b/_posts/2009-01-28-Zero-FrictionTDD.html @@ -12,7 +12,7 @@ In my original post on Zero-Friction TDD, I continually updated the list of posts in the series, so that there would always be a central 'table of contents' for this topic.

- Since I'll lose the ability to keep editing any of my previous postings on the old ploeh blog, the present post now contains the most updated list of Zero-Friction TDD articles: + Since I'll lose the ability to keep editing any of my previous postings on the old ploeh blog, the present post now contains the most updated list of Zero-Friction TDD articles:

\ No newline at end of file diff --git a/_posts/2009-02-13-SUTFactory.html b/_posts/2009-02-13-SUTFactory.html index 36ce60125..eda64db9b 100644 --- a/_posts/2009-02-13-SUTFactory.html +++ b/_posts/2009-02-13-SUTFactory.html @@ -9,7 +9,7 @@

- In my Zero-Friction TDD series, I focus on establishing a set of good habits that can potentially make you more productive while writing tests TDD style. While being able to quickly write good tests is important, this is not the only quality on which you should focus. + In my Zero-Friction TDD series, I focus on establishing a set of good habits that can potentially make you more productive while writing tests TDD style. While being able to quickly write good tests is important, this is not the only quality on which you should focus.

Maintainability, not only of your production code, but also of your test code, is important, and the DRY principle is just as applicable here. @@ -111,7 +111,7 @@

2009-02-16 19:20 UTC

- +
Hi Martin

Thank you for your comment.
@@ -129,7 +129,7 @@

2011-05-24 10:54 UTC

- +
Raj, the problem with this approach is that in order to be maintainable you would need to adopt the Testcase Class per Fixture pattern, because if you don't the test class will eventually suffer from low cohesion. However, most people (myself included) tend to find this pattern counter-intuitive and rather prefer Testcase Class per Class.
2011-05-24 19:07 UTC
diff --git a/_posts/2009-03-03-DerivedValuesEnsureExecutableSpecification.html b/_posts/2009-03-03-DerivedValuesEnsureExecutableSpecification.html index e4657920b..e32c9923f 100644 --- a/_posts/2009-03-03-DerivedValuesEnsureExecutableSpecification.html +++ b/_posts/2009-03-03-DerivedValuesEnsureExecutableSpecification.html @@ -9,7 +9,7 @@

- In this Zero-Friction TDD post, I'd like to take a detour around the concept of tests as Executable Specification. + In this Zero-Friction TDD post, I'd like to take a detour around the concept of tests as Executable Specification.

An important aspect of test maintainability is readability. Tests should act both as Executable Specification as well as documentation, which puts a lot of responsibility on the test. @@ -124,7 +124,7 @@ While such tests more clearly provide both specification and documentation, it requires discipline to write tests in this way. Particularly when the algorithm is so simple as is the case here, it's very tempting to just hard-code the values directly into the assertion.

- In a future post, I'll explain how we can force ourselves to do the right thing per default. + In a future post, I'll explain how we can force ourselves to do the right thing per default.

\ No newline at end of file diff --git a/_posts/2009-03-05-ConstrainedNon-Determinism.html b/_posts/2009-03-05-ConstrainedNon-Determinism.html index dd0803365..0c9d994b4 100644 --- a/_posts/2009-03-05-ConstrainedNon-Determinism.html +++ b/_posts/2009-03-05-ConstrainedNon-Determinism.html @@ -9,10 +9,10 @@

- This may turn out to be the most controversial of my Zero-Friction TDD posts so far, as it supposedly goes against conventional wisdom. However, I have found this approach to be really powerful since I began using it about a year ago. + This may turn out to be the most controversial of my Zero-Friction TDD posts so far, as it supposedly goes against conventional wisdom. However, I have found this approach to be really powerful since I began using it about a year ago.

- In my previous post, I explained how Derived Values help ensure that tests act as Executable Specification. In short, a test should clearly specify the relationship between input and outcome, as this test does: + In my previous post, I explained how Derived Values help ensure that tests act as Executable Specification. In short, a test should clearly specify the relationship between input and outcome, as this test does:

[TestMethod]
@@ -32,7 +32,7 @@
 }

- However, it is very tempting to just hardcode the expected value. Consistently using Derived Values to establish the relationship between input and outcome requires discipline. + However, it is very tempting to just hardcode the expected value. Consistently using Derived Values to establish the relationship between input and outcome requires discipline.

To help myself enforce this discipline, I use well-defined, but essentially random, input, because when the input is random, I don't know the value at design time, and hence, it is impossible for me to accidentally hard-code any assertions. @@ -58,7 +58,7 @@ For strings, I prefer Guids, as the above example demonstrates. For numbers, I often just use the sequence of natural numbers (i.e. 1, 2, 3, 4, 5...). For booleans, I often use an alternating sequence (i.e. true, false, true, false...).

- While this technique causes input to become non-deterministic, I always pick the non-deterministic value-generating algorithm in such a way that it creates 'nice' values; I call this principle Constrained Non-Determinism. Values are carefully generated to stay far away from any boundary conditions that may cause the SUT to behave differently in each test run. + While this technique causes input to become non-deterministic, I always pick the non-deterministic value-generating algorithm in such a way that it creates 'nice' values; I call this principle Constrained Non-Determinism. Values are carefully generated to stay far away from any boundary conditions that may cause the SUT to behave differently in each test run.

Conventional unit testing wisdom dictates that unit tests should be deterministic, so how can I possibly endorse this technique? @@ -109,7 +109,7 @@

2010-10-08 14:52 UTC

- +
It sounds to me like Pex would fit your scenario very well. Basically, that would allow you to write a Pex test that creates deterministic test cases for each and every code path through the SUT. I do realize that data comes from the database, but it's still input. In testing terminology, we call that Indirect Input.

If you can't inject a Test Double that provides all the different data combinations, you should be able to use Moles for that part of the task.
diff --git a/_posts/2009-03-10-Specification-DrivenDevelopment.html b/_posts/2009-03-10-Specification-DrivenDevelopment.html index 1b863aae8..0a0fc57d5 100644 --- a/_posts/2009-03-10-Specification-DrivenDevelopment.html +++ b/_posts/2009-03-10-Specification-DrivenDevelopment.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

In the last couple of years, there's been a lot of debate in the community on the philosophy behind TDD and where to put the emphasis - even to the point of debating whether the acronym stands for Test-Driven Development or Test-Driven Design.

Other people don't like the emphasis on tests, since that makes TDD sound like a Testing discipline, and not a Development discipline. Instead, they prefer terms like Example-Driven Design/Development (EDD) or even Design by Example (DbE).

This view seems to me to be particularly prevalent in Microsoft, where there's a rather sharp distinction between developers and testers (job titles to the contrary) - I guess that's one of the reasons why xUnit.net (a project initiated by Microsoft employees) uses the attribute Fact instead of Test or TestMethod.

For people used to SCRUM or other agile methodologies, this distinction is more blurred, and they also seem to accept the T in TDD more willingly.

However, the adherents of EDD claim that the mere presence of the word test make some developers block any further input and stop listening. They may be right in that.

They also claim that the tests in TDD/EDD are nothing more than accidental artifacts of the development process, and hence argue that we shouldn't call them tests at all. However, if that's true, this little story related by Ayende must be an example of EDD in its purest form :)

To me, the tests are also important. Since 2003 I've been practicing TDD, and while I love how it helps me arrive at better design, I also savor the safety net that my suite of tests gives me. The tests that I write during TDD define the behavior of the software. In many cases, I'd even claim that such a regression test suite is more valuable than a Quality Assurance (QA) regression test suite - after all, a QA suite may catch some edge cases, but they don't focus on the intended behavior of the system, but often more on how to break it - but I digress…

My recent posts on Executable Specification and Constrained Non-Determinism help explain my current stance in this debate: In my opinion, EDD fails to establish a relationship by not providing Derived Values. After all, what does a test like the following specify?

+

In the last couple of years, there's been a lot of debate in the community on the philosophy behind TDD and where to put the emphasis - even to the point of debating whether the acronym stands for Test-Driven Development or Test-Driven Design.

Other people don't like the emphasis on tests, since that makes TDD sound like a Testing discipline, and not a Development discipline. Instead, they prefer terms like Example-Driven Design/Development (EDD) or even Design by Example (DbE).

This view seems to me to be particularly prevalent in Microsoft, where there's a rather sharp distinction between developers and testers (job titles to the contrary) - I guess that's one of the reasons why xUnit.net (a project initiated by Microsoft employees) uses the attribute Fact instead of Test or TestMethod.

For people used to SCRUM or other agile methodologies, this distinction is more blurred, and they also seem to accept the T in TDD more willingly.

However, the adherents of EDD claim that the mere presence of the word test make some developers block any further input and stop listening. They may be right in that.

They also claim that the tests in TDD/EDD are nothing more than accidental artifacts of the development process, and hence argue that we shouldn't call them tests at all. However, if that's true, this little story related by Ayende must be an example of EDD in its purest form :)

To me, the tests are also important. Since 2003 I've been practicing TDD, and while I love how it helps me arrive at better design, I also savor the safety net that my suite of tests gives me. The tests that I write during TDD define the behavior of the software. In many cases, I'd even claim that such a regression test suite is more valuable than a Quality Assurance (QA) regression test suite - after all, a QA suite may catch some edge cases, but they don't focus on the intended behavior of the system, but often more on how to break it - but I digress…

My recent posts on Executable Specification and Constrained Non-Determinism help explain my current stance in this debate: In my opinion, EDD fails to establish a relationship by not providing Derived Values. After all, what does a test like the following specify?

[TestMethod]
 public void InvertWillReverseText_Naïve()
@@ -42,7 +42,7 @@ 

2009-03-28 12:28 UTC

- +
Hi Torbjørn

Thank you for your comment.
@@ -68,7 +68,7 @@

2009-03-28 18:01 UTC

- +
Hi Torbjørn

Thanks again. You point was valid and well taken.
diff --git a/_posts/2009-03-11-ExplicitExpectations.html b/_posts/2009-03-11-ExplicitExpectations.html index 6a19a1dfe..d9b06e83a 100644 --- a/_posts/2009-03-11-ExplicitExpectations.html +++ b/_posts/2009-03-11-ExplicitExpectations.html @@ -8,7 +8,7 @@ {% include JB/setup %}
-

In previous Zero-Friction TDD posts, I've discussed naming SUT and Direct Output variables, as well as the importance of explicitly describing the relationship between input and expected results.

Everything you can do to help the Test Reader understand what's going on increases the quality of the test. Having a naming convention for expectations help in that regard, and it also helps coming up with variable names, thus saving yourself a bit of mental context switching.

My naming convention is to always prefix my expectation variables with the term expected.

+

In previous Zero-Friction TDD posts, I've discussed naming SUT and Direct Output variables, as well as the importance of explicitly describing the relationship between input and expected results.

Everything you can do to help the Test Reader understand what's going on increases the quality of the test. Having a naming convention for expectations help in that regard, and it also helps coming up with variable names, thus saving yourself a bit of mental context switching.

My naming convention is to always prefix my expectation variables with the term expected.

[TestMethod]
 public void DoStuffWillReturnMessage()
@@ -97,7 +97,7 @@ 

2015-02-3 15:33 UTC

- +

Like this? diff --git a/_posts/2009-03-16-FixtureObject.html b/_posts/2009-03-16-FixtureObject.html index a9561cfcd..9858bb8af 100644 --- a/_posts/2009-03-16-FixtureObject.html +++ b/_posts/2009-03-16-FixtureObject.html @@ -8,7 +8,7 @@ {% include JB/setup %}

-

(A Zero-Friction TDD post)

For a simple API, setting up the Fixture may be as simple as creating a new instance of the SUT, and possibly any Expected or Anonymous Variables. On the other hand, for a complex API, setting up the fixture may require quite a bit of (potentially repetitive) code.

Since the DRY principle also applies to test code, it quickly becomes necessary to create test-specific helper methods and other SUT API Encapsulation, and I've found that instead of creating a more or less unplanned set of disconnected helper methods, it's much cleaner (and, not to mention, much more object-oriented) to create a single object that represents the Fixture, and attach the helper methods to this object.

Let's look at an example.

Here's a unit test with a complex Fixture Setup:

+

(A Zero-Friction TDD post)

For a simple API, setting up the Fixture may be as simple as creating a new instance of the SUT, and possibly any Expected or Anonymous Variables. On the other hand, for a complex API, setting up the fixture may require quite a bit of (potentially repetitive) code.

Since the DRY principle also applies to test code, it quickly becomes necessary to create test-specific helper methods and other SUT API Encapsulation, and I've found that instead of creating a more or less unplanned set of disconnected helper methods, it's much cleaner (and, not to mention, much more object-oriented) to create a single object that represents the Fixture, and attach the helper methods to this object.

Let's look at an example.

Here's a unit test with a complex Fixture Setup:

[TestMethod]
 public void NumberSumIsCorrect_Naïve()
@@ -133,7 +133,7 @@
     }
 }

-

The CreateAnonymousThing method uses Constrained Non-Determinism to create unique Thing instances. The AddAnonymousThings method uses 3 as an equivalence of many, and the CreateSut method acts as a SUT Factory.

+

The CreateAnonymousThing method uses Constrained Non-Determinism to create unique Thing instances. The AddAnonymousThings method uses 3 as an equivalence of many, and the CreateSut method acts as a SUT Factory.

This is both more reusable and more expressive than a collection of disjointed static helper methods.

Whenever I begin to feel that setting up a Test Fixture is becoming too cumbersome, Fixture Object is the first pattern I consider.

diff --git a/_posts/2009-03-22-AnnouncingAutoFixture.html b/_posts/2009-03-22-AnnouncingAutoFixture.html index c0697f4db..eebef94d3 100644 --- a/_posts/2009-03-22-AnnouncingAutoFixture.html +++ b/_posts/2009-03-22-AnnouncingAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

It gives me great pleasure to announce my latest project: AutoFixture!

What is AutoFixture?

In essence, AutoFixture is a library that creates Anonymous Variables for you when you write unit tests. The intention is that it should enhance your productivity when you do Test-Driven Development - as it has done mine.

Instead of using mental resources on creating Anonymous Variables, AutoFixture can do it for you. By default, it uses Constrained Non-Determinism, but you can configure it to behave differently if you wish.

Here's a very basic example:

+

It gives me great pleasure to announce my latest project: AutoFixture!

What is AutoFixture?

In essence, AutoFixture is a library that creates Anonymous Variables for you when you write unit tests. The intention is that it should enhance your productivity when you do Test-Driven Development - as it has done mine.

Instead of using mental resources on creating Anonymous Variables, AutoFixture can do it for you. By default, it uses Constrained Non-Determinism, but you can configure it to behave differently if you wish.

Here's a very basic example:

[TestMethod]
 public void IntroductoryTest()
@@ -24,10 +24,10 @@
     // Teardown
 }

-

The Fixture class is your main entry point to AutoFixture. You can use it as is, customize it, or derive from it as you please; it makes a great base class for a Fixture Object.

-

The expectedNumber variable may be an Explicit Expectation, but its value is Anonymous, so instead of coming up with a number ourselves, we can let the CreateAnonymous<T> method do it for us.

+

The Fixture class is your main entry point to AutoFixture. You can use it as is, customize it, or derive from it as you please; it makes a great base class for a Fixture Object.

+

The expectedNumber variable may be an Explicit Expectation, but its value is Anonymous, so instead of coming up with a number ourselves, we can let the CreateAnonymous<T> method do it for us.

This method can create instances of most CLR types as long as they have a public constructor (it uses Reflection), but for many primitive types (like Int32), it has specific, customizable algorithms for creating values using Constrained Non-Determinism.

-

When creating the SUT, we can also use Fixture as an excellent SUT Factory. Since it will do whatever it can to create an instance of the type you ask for, it is pretty robust if you decide to refactor the SUT's constructor.

+

When creating the SUT, we can also use Fixture as an excellent SUT Factory. Since it will do whatever it can to create an instance of the type you ask for, it is pretty robust if you decide to refactor the SUT's constructor.

The above example only hints at what AutoFixture can do. Since the example is very simple, it may be hard to immediately understand its value, so in future posts I will expand on specific AutoFixture features and principles.

Getting started with AutoFixture is as simple as downloading it from CodePlex and referencing the assembly in Visual Studio.

@@ -48,7 +48,7 @@

2009-05-01 15:53 UTC

- +
Hi Peli

Thank you for your comment.
diff --git a/_posts/2009-03-23-JoiningSafewhere.html b/_posts/2009-03-23-JoiningSafewhere.html index 47ec45362..ccfc27d04 100644 --- a/_posts/2009-03-23-JoiningSafewhere.html +++ b/_posts/2009-03-23-JoiningSafewhere.html @@ -21,7 +21,7 @@

2009-03-24 15:14 UTC

- +
Thanks :)
2009-03-25 07:32 UTC
diff --git a/_posts/2009-03-24-HowAutoFixtureCreatesObjects.html b/_posts/2009-03-24-HowAutoFixtureCreatesObjects.html index 484a00e25..4b2e7bace 100644 --- a/_posts/2009-03-24-HowAutoFixtureCreatesObjects.html +++ b/_posts/2009-03-24-HowAutoFixtureCreatesObjects.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

AutoFixture creates Anonymous Variables, but you'd probably like to know how it does it. This post explains how.

As we previously saw, the CreateAnonymous method can create a new instance of a type known to it only from its type parameter:

+

AutoFixture creates Anonymous Variables, but you'd probably like to know how it does it. This post explains how.

As we previously saw, the CreateAnonymous method can create a new instance of a type known to it only from its type parameter:

MyClass sut = fixture.CreateAnonymous<MyClass>();

@@ -28,7 +28,7 @@

So what happens when we ask AutoFixture to create an instance of ComplexParent?

ComplexParent only has a single public constructor, so AutoFixture doesn't have any other choice than picking that. This means that it must now create an anonymous instance of ComplexChild.

Fortunately, AutoFixture's raison d'être is creating objects, so creating an instance of ComplexChild isn't a big deal; the only thing it needs to figure out is which constructor to pick. When multiple public constructors are available, it always picks the one with the fewest number of arguments - in this case ComplexChild(string).

-

Obviously, it then needs to create an anonymous string value. For primitive types like strings, numbers and booleans, AutoFixture has custom algorithms for value creation. Since I'll cover those mechanisms later, suffice it to say that Constrained Non-Determinism is used to create an anonymous string.

+

Obviously, it then needs to create an anonymous string value. For primitive types like strings, numbers and booleans, AutoFixture has custom algorithms for value creation. Since I'll cover those mechanisms later, suffice it to say that Constrained Non-Determinism is used to create an anonymous string.

At this point, AutoFixture has all the information it needs, and it can now return a properly initialized instance of ComplexParent.

This ability to create instances of almost arbitrarily complex types is a real time-saver: That, more than the ability to create single strings or numbers, was the reason I originally created AutoFixture, since I got tired of initializing complex object graphs just to satisfy some API that the Test Fixture requires.

It also has the additional advantage that it hides all the irrelevant object creation code that the Test Fixture needs, but which isn't relevant for the test at hand.

@@ -45,7 +45,7 @@

2009-03-25 09:17 UTC

- +
Hi Klaus

Thank you for your question! It is an excellent question, particularly because it gives me the opportunity to touch on both some of the more advanced features of AutoFixture, as well as to demonstrate how TDD drives good design.
@@ -59,7 +59,7 @@

2010-05-21 10:51 UTC

- +
It doesn't, so this is a situation best avoided. Essentially AutoFixture orders the constructors according to length, but in case of equal lengths it just picks the first one. Which constructor is the first is up to Reflection to decide, so this is not specified.

This sounds like a serious limitation on AutoFixture's part, but in practice I've found that it rarely matters. In the few cases where a SUT has overloaded constructors, it is essential to the design that none of them puts the SUT into an invalid state, so when you need an anonymous instance it shouldn't matter which constructor is used. This is really what AutoFixture is all about.
diff --git a/_posts/2009-04-02-CreatingStringsWithAutoFixture.html b/_posts/2009-04-02-CreatingStringsWithAutoFixture.html index 0d1418e90..821fb73c1 100644 --- a/_posts/2009-04-02-CreatingStringsWithAutoFixture.html +++ b/_posts/2009-04-02-CreatingStringsWithAutoFixture.html @@ -7,13 +7,13 @@ {% include JB/setup %}
-

As previously hinted, AutoFixture creates primitive types like strings, numbers, etc. using special algorithms.

In this post, I'll describe the default algorithm for strings. If you don't like this particular algorithm, you can replace it with your own.

If you don't care about the created string at all, you can just create it like this:

+

As previously hinted, AutoFixture creates primitive types like strings, numbers, etc. using special algorithms.

In this post, I'll describe the default algorithm for strings. If you don't like this particular algorithm, you can replace it with your own.

If you don't care about the created string at all, you can just create it like this:

string anonymousText = 
     fixture.CreateAnonymous<string>();

-

The algorithm is simply to create a new Guid and convert it to a string, so that anonymousText will have a value like “f5cdf6b1-a473-410f-95f3-f427f7abb0c7”. Obviously, you don't know exactly which value will be returned, but that's the whole point of Constrained Non-Determinism.

-

When I create string values as Explicit Expectations, I prefer that the Assert failure message contains some sort of hint for me, so I can instead provide a hint to the CreateAnonymous method:

+

The algorithm is simply to create a new Guid and convert it to a string, so that anonymousText will have a value like “f5cdf6b1-a473-410f-95f3-f427f7abb0c7”. Obviously, you don't know exactly which value will be returned, but that's the whole point of Constrained Non-Determinism.

+

When I create string values as Explicit Expectations, I prefer that the Assert failure message contains some sort of hint for me, so I can instead provide a hint to the CreateAnonymous method:

string anonymousName = fixture.CreateAnonymous("Name");

diff --git a/_posts/2009-04-03-CreatingNumbersWithAutoFixture.html b/_posts/2009-04-03-CreatingNumbersWithAutoFixture.html index a0a1389b6..b96cd6f57 100644 --- a/_posts/2009-04-03-CreatingNumbersWithAutoFixture.html +++ b/_posts/2009-04-03-CreatingNumbersWithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

Previously, we saw how AutoFixture creates strings. In this post, I'll explain how it creates numbers. Once again, the algorithm that I'll explain here is the default algorithm, but if you don't like it, you can replace it with something else.

It's very simple: Numbers are returned in the ordered sequence of natural numbers (1, 2, 3, 4, 5, …). The first time you call

+

Previously, we saw how AutoFixture creates strings. In this post, I'll explain how it creates numbers. Once again, the algorithm that I'll explain here is the default algorithm, but if you don't like it, you can replace it with something else.

It's very simple: Numbers are returned in the ordered sequence of natural numbers (1, 2, 3, 4, 5, …). The first time you call

fixture.CreateAnonymous<int>();

@@ -51,7 +51,7 @@

2010-05-21 10:29 UTC

- +
The idea about constrained non-determinism is that although test values are essentially unknown, two consecutive test runs must traverse the same branch of source code each time. In some SUTs different integer values may cause different branches to be exectured for each test run, so I found it safer to use a deterministic sequence.

For complex objects (say: a class with two writable properties of the same number type) the ordering of assignment is undefined even though the sequence of numbers is deterministic. In other words, if you have the properties Number1 and Number2, you know one gets the value 1 and the other gets the value 2, but you don't know which one gets what (it's probably deterministic anyway because Reflection is likely to always return properties in the same order, but AutoFixture does nothing to explicitly order properties and fields).
@@ -69,7 +69,7 @@

2011-03-05 23:16 UTC

- +
Let's say that you want to change the integer algorithm to return the seed. This can be done like this:

fixture.Customize<int>(c => c.FromSeed(i => i));
diff --git a/_posts/2009-04-19-CreatingBooleansWithAutoFixture.html b/_posts/2009-04-19-CreatingBooleansWithAutoFixture.html index 90a8a7e28..63752e29d 100644 --- a/_posts/2009-04-19-CreatingBooleansWithAutoFixture.html +++ b/_posts/2009-04-19-CreatingBooleansWithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

(Just back after 14 days in Morocco, I'll pick up where I left…)

The last group of built-in special creation algorithms for AutoFixture, besides strings and numbers, concerns Booleans.

The default algorithm is to alternate between true and false, starting with true; i.e. the first time you invoke

+

(Just back after 14 days in Morocco, I'll pick up where I left…)

The last group of built-in special creation algorithms for AutoFixture, besides strings and numbers, concerns Booleans.

The default algorithm is to alternate between true and false, starting with true; i.e. the first time you invoke

fixture.CreateAnonymous<bool>();

diff --git a/_posts/2009-04-23-DealingWithTypesWithoutPublicConstructors.html b/_posts/2009-04-23-DealingWithTypesWithoutPublicConstructors.html index 7e64db7f6..ea11475e8 100644 --- a/_posts/2009-04-23-DealingWithTypesWithoutPublicConstructors.html +++ b/_posts/2009-04-23-DealingWithTypesWithoutPublicConstructors.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

Now that I've described how AutoFixture creates objects, it's time to look at a bit more advanced scenario. As you may recall, AutoFixture creates an object graph based on the public constructors of the types contained in that object graph.

That's all well and good when all involved types have public constructors, but what happens when this is not the case?

Imagine that the MyClass constructor has this signature:

+

Now that I've described how AutoFixture creates objects, it's time to look at a bit more advanced scenario. As you may recall, AutoFixture creates an object graph based on the public constructors of the types contained in that object graph.

That's all well and good when all involved types have public constructors, but what happens when this is not the case?

Imagine that the MyClass constructor has this signature:

public MyClass(IMyInterface mi)

@@ -48,6 +48,6 @@

Compared to the previous example, I save a line of code. The drawback is that I have to explicitly specify the type parameters to the Register method. In my book, that's a pretty good tradeoff, as it removes a line of irrelevant code, and allows the test to focus on the relevant parts.

Notice that this Register overload creates both an anonymous integer and an anonymous string, but since I don't want to use the anonymous string (s), I just ignore it and use the knownText variable instead.

-

*Edit (2009-09-02): Changed the name of the Exception type to correctly reflect a breaking change introduced in AutoFixture .8.5.

+

*Edit (2009-09-02): Changed the name of the Exception type to correctly reflect a breaking change introduced in AutoFixture .8.5.

\ No newline at end of file diff --git a/_posts/2009-04-27-ReplacingAutoFixturesDefaultAlgorithms.html b/_posts/2009-04-27-ReplacingAutoFixturesDefaultAlgorithms.html index 9c9ce9a08..4571d2bf7 100644 --- a/_posts/2009-04-27-ReplacingAutoFixturesDefaultAlgorithms.html +++ b/_posts/2009-04-27-ReplacingAutoFixturesDefaultAlgorithms.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

Several times in my previous AutoFixture posts, I've insinuated that you can change the algorithms used for creating strings, numbers and so on, if you don't like the defaults.

One way you can do this is by simply using the Register method that I introduced in my previous post. Let's say that you want to replace the string algorithm to simply return a specific string:

+

Several times in my previous AutoFixture posts, I've insinuated that you can change the algorithms used for creating strings, numbers and so on, if you don't like the defaults.

One way you can do this is by simply using the Register method that I introduced in my previous post. Let's say that you want to replace the string algorithm to simply return a specific string:

fixture.Register<string>(() => "ploeh");

@@ -43,8 +43,8 @@

2012-07-25 07:05 UTC

- -
Yes, TypeMappings were removed in AutoFixture 2.0, which has a much more flexible extensibility model. Ultimately, a custom ISpecimenBuilder can do everything you may want to do.
+ +
Yes, TypeMappings were removed in AutoFixture 2.0, which has a much more flexible extensibility model. Ultimately, a custom ISpecimenBuilder can do everything you may want to do.
2012-07-25 08:37 UTC
\ No newline at end of file diff --git a/_posts/2009-05-01-DealingWithConstrainedInput.html b/_posts/2009-05-01-DealingWithConstrainedInput.html index e6468c58e..1b128ae2d 100644 --- a/_posts/2009-05-01-DealingWithConstrainedInput.html +++ b/_posts/2009-05-01-DealingWithConstrainedInput.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

As a response to my description of how AutoFixture creates objects, Klaus asked:

“[What] if the constructor of ComplexChild imposes some kind of restriction on its parameter? If, for example, instead of the "name" parameter, it would take a "phoneNumber" parameter (as a string), and do some format checking?”

Now that we have covered some of the basic features of AutoFixture, it's time to properly answer this excellent question.

For simplicity's sake, let's assume that the phone number in question is a Danish phone number: This is pretty good for example code, since a Danish phone number is essentially just an 8-digit number. It can have white space and an optional country code (+45), but strip that away, and it's just an 8-digit number. However, there are exceptions, since the emergency number is 112 (equivalent to the American 911), and other 3-digit special numbers exist as well.

With that in mind, let's look at a simple Contact class that contains a contact's name and Danish phone number. The constructor might look like this:

+

As a response to my description of how AutoFixture creates objects, Klaus asked:

“[What] if the constructor of ComplexChild imposes some kind of restriction on its parameter? If, for example, instead of the "name" parameter, it would take a "phoneNumber" parameter (as a string), and do some format checking?”

Now that we have covered some of the basic features of AutoFixture, it's time to properly answer this excellent question.

For simplicity's sake, let's assume that the phone number in question is a Danish phone number: This is pretty good for example code, since a Danish phone number is essentially just an 8-digit number. It can have white space and an optional country code (+45), but strip that away, and it's just an 8-digit number. However, there are exceptions, since the emergency number is 112 (equivalent to the American 911), and other 3-digit special numbers exist as well.

With that in mind, let's look at a simple Contact class that contains a contact's name and Danish phone number. The constructor might look like this:

public Contact(string name, string phoneNumber)
 {
@@ -17,9 +17,9 @@
 }

The static ParsePhoneNumber method strips away white space and optional country code and parses the normalized string to a number. This fits the scenario laid out in Klaus' question.

-

So what happens when we ask AutoFixture to create an instance of Contact? It will Reflect over Contact's constructor and create two new anonymous string instances - one for name, and one for phoneNumber. As previously described, each string will be created as a Guid prepended with a named hint - in this case the argument name. Thus, the phoneNumber argument will get a value like "phoneNumberfa432351-1563-4769-842c-7588af32a056", which will cause the ParsePhoneNumber method to throw an exception.

+

So what happens when we ask AutoFixture to create an instance of Contact? It will Reflect over Contact's constructor and create two new anonymous string instances - one for name, and one for phoneNumber. As previously described, each string will be created as a Guid prepended with a named hint - in this case the argument name. Thus, the phoneNumber argument will get a value like "phoneNumberfa432351-1563-4769-842c-7588af32a056", which will cause the ParsePhoneNumber method to throw an exception.

How do we deal with that?

-

The most obvious fix is to modify AutoFixture's algorithm for generating strings. Here an initial attempt:

+

The most obvious fix is to modify AutoFixture's algorithm for generating strings. Here an initial attempt:

fixture.Register<string>(() => "112");

@@ -37,7 +37,7 @@ }

If we still need to parse strings (e.g. from user input), we could add a static Parse, or even a TryParse, method and test that method in isolation without involving the Contact class.

This neatly solves our original issue with AutoFixture, since it will now create a new instance of DanishPhoneNumber as part of the creation process when we ask for an anonymous Contact instance.

-

The only remaining issue is that by default, the number fed into the DanishPhoneNumber instance is likely to be considerably less than 112 - actually, if no other Int32 instances are created, it will be 1.

+

The only remaining issue is that by default, the number fed into the DanishPhoneNumber instance is likely to be considerably less than 112 - actually, if no other Int32 instances are created, it will be 1.

This will be a problem if we modify the DanishPhoneNumber constructor to look like this:

public DanishPhoneNumber(int number)
@@ -56,7 +56,7 @@
     
fixture.Register<int>(() => 12345678);

However, this will cause that particular instance of Fixture to return 12345678 every time you ask it to create an anonymous integer. Depending on the scenario, this may or may not be a problem.

-

A more targeted solution is to specifically address the algorithm for generating DanishPhoneNumber instances:

+

A more targeted solution is to specifically address the algorithm for generating DanishPhoneNumber instances:

fixture.Register<int, DanishPhoneNumber>(i => 
     new DanishPhoneNumber(i + 112));
diff --git a/_posts/2009-05-05-ManagingLooselyCoupledProjects.html b/_posts/2009-05-05-ManagingLooselyCoupledProjects.html index 6ed8c252c..d13f0aaaa 100644 --- a/_posts/2009-05-05-ManagingLooselyCoupledProjects.html +++ b/_posts/2009-05-05-ManagingLooselyCoupledProjects.html @@ -7,6 +7,6 @@ {% include JB/setup %}
-

Udi recently posted an article on managing loose coupling in Visual Studio. While I completely agree, this is a topic that deserves more detailed treatment. In particular, I'd like to expand on this statement:

"In fact, each component could theoretically have its own solution"

This is really the crux of the matter, although in practical terms, you'd typically need at least a couple of projects per component. In special cases, a component may truly be a stand-alone component, requiring no other dependencies than what is already in the BCL (in fact, AutoFixture is just such a component), but most components of more complex software have dependencies.

Even when you are programming against interfaces (which you should be), these interfaces will normally be defined in other projects.

PragmaticMinimalSolution

A component may even use multiple interfaces, since it may be implementing some, but consuming others, and these interfaces may be defined in different projects. This is particularly the case with Adapters.

Finally, you should have at least one unit test project that targets your component.

In essence, while the exact number of projects you need will vary, it should stay small. In the figure above, we end up with five projects, but there's also quite a few abstractions being pulled in.

As a rule of thumb I'd say that if you can't create an .sln file that contains less than ten projects to work on any component, you should seriously consider your decoupling strategy.

You may choose to work with more than ten projects in a solution, but it should always be possible to create a solution to work with a single component, and it should drag only few dependencies along.

+

Udi recently posted an article on managing loose coupling in Visual Studio. While I completely agree, this is a topic that deserves more detailed treatment. In particular, I'd like to expand on this statement:

"In fact, each component could theoretically have its own solution"

This is really the crux of the matter, although in practical terms, you'd typically need at least a couple of projects per component. In special cases, a component may truly be a stand-alone component, requiring no other dependencies than what is already in the BCL (in fact, AutoFixture is just such a component), but most components of more complex software have dependencies.

Even when you are programming against interfaces (which you should be), these interfaces will normally be defined in other projects.

PragmaticMinimalSolution

A component may even use multiple interfaces, since it may be implementing some, but consuming others, and these interfaces may be defined in different projects. This is particularly the case with Adapters.

Finally, you should have at least one unit test project that targets your component.

In essence, while the exact number of projects you need will vary, it should stay small. In the figure above, we end up with five projects, but there's also quite a few abstractions being pulled in.

As a rule of thumb I'd say that if you can't create an .sln file that contains less than ten projects to work on any component, you should seriously consider your decoupling strategy.

You may choose to work with more than ten projects in a solution, but it should always be possible to create a solution to work with a single component, and it should drag only few dependencies along.

\ No newline at end of file diff --git a/_posts/2009-05-11-AnonymousSequencesWithAutoFixture.html b/_posts/2009-05-11-AnonymousSequencesWithAutoFixture.html index 97ca7aad6..f63f8e3cf 100644 --- a/_posts/2009-05-11-AnonymousSequencesWithAutoFixture.html +++ b/_posts/2009-05-11-AnonymousSequencesWithAutoFixture.html @@ -12,7 +12,7 @@
Fixture fixture = new Fixture();
 var strings = fixture.CreateMany<string>();

-

Obviously, you can create sequences of whatever type you want, as long as AutoFixture can figure out how to create instances of the type:

+

Obviously, you can create sequences of whatever type you want, as long as AutoFixture can figure out how to create instances of the type:

var myInstances = fixture.CreateMany<MyClass>();

diff --git a/_posts/2009-05-15-AutoFixtureAsFixtureObject.html b/_posts/2009-05-15-AutoFixtureAsFixtureObject.html index f30789327..51d43c9b9 100644 --- a/_posts/2009-05-15-AutoFixtureAsFixtureObject.html +++ b/_posts/2009-05-15-AutoFixtureAsFixtureObject.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

Dear reader, I hope you are still with me!

After eight posts of AutoFixture feature walkthroughs, I can't blame you for wondering why this tool might even be relevant to you. In this post, we'll finally begin to look at how AutoFixture can help you towards Zero-Friction TDD!

In an earlier post, I described how the Fixture Object pattern can help you greatly reduce the amount of test code that you have to write. Since AutoFixture was designed to act as a general-purpose Fixture Object, it can help you reduce the amount of test code even further, letting you focus on specifying the behavior of your SUT.

In that former post, the original example was this complex test that I will repeat in it's entirety for your benefit (or horror):

+

Dear reader, I hope you are still with me!

After eight posts of AutoFixture feature walkthroughs, I can't blame you for wondering why this tool might even be relevant to you. In this post, we'll finally begin to look at how AutoFixture can help you towards Zero-Friction TDD!

In an earlier post, I described how the Fixture Object pattern can help you greatly reduce the amount of test code that you have to write. Since AutoFixture was designed to act as a general-purpose Fixture Object, it can help you reduce the amount of test code even further, letting you focus on specifying the behavior of your SUT.

In that former post, the original example was this complex test that I will repeat in it's entirety for your benefit (or horror):

[TestMethod]
 public void NumberSumIsCorrect_Naïve()
@@ -47,7 +47,7 @@
 }

This test consists of 18 lines of code.

-

Using the Fixture Object pattern, I was able to cut that down to 7 lines of code, which is a 61% improvement (however, the downside was an additional 19 lines of (reusable) code for MyClassFixture, so the benefit can only be reaped when you have multiple tests leveraged by the same Fixture Object. This was all covered in the former post, to which I will refer you).

+

Using the Fixture Object pattern, I was able to cut that down to 7 lines of code, which is a 61% improvement (however, the downside was an additional 19 lines of (reusable) code for MyClassFixture, so the benefit can only be reaped when you have multiple tests leveraged by the same Fixture Object. This was all covered in the former post, to which I will refer you).

With AutoFixture, we can do much better. Here's a one-off rewrite of the unit test using AutoFixture:

[TestMethod]
@@ -71,7 +71,7 @@
     // Teardown
 }

-

In this test, I map the concrete fake instance to the IMyInterface type in the fixture object, and then use its ability to create many anonymous instances with one method call. Before exercising the SUT, I also use the fixture instance as a SUT Factory.

+

In this test, I map the concrete fake instance to the IMyInterface type in the fixture object, and then use its ability to create many anonymous instances with one method call. Before exercising the SUT, I also use the fixture instance as a SUT Factory.

Apart from AutoFixture (and FakeMyInterface, which is invariant for all variations, and thus kept out of the comparison), this test stands alone, but still manages to reduce the number of code lines to 10 lines - a 44% improvement! In my book, that's already a significant gain in productivity and maintainability, but we can do better!

If we need to test MyClass repeatedly in similar ways, we can move the common code to a Fixture Object based on AutoFixture, and the test can be refactored to this:

diff --git a/_posts/2009-05-21-SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.html b/_posts/2009-05-21-SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.html index adc4e434b..9535746d7 100644 --- a/_posts/2009-05-21-SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.html +++ b/_posts/2009-05-21-SyncOrchestrator.Synchronize()ThrowsCOMExceptionWhenUnitTesting.html @@ -21,7 +21,7 @@

2009-07-10 12:46 UTC

- +
Hi Reginal

Thank you for your message - I am happy that my post was helpful to you.
diff --git a/_posts/2009-06-01-SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.html b/_posts/2009-06-01-SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.html index a2a2ed8a8..3d2f890e5 100644 --- a/_posts/2009-06-01-SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.html +++ b/_posts/2009-06-01-SettingPropertyValuesWhileBuildingAnonymousVariablesWithAutoFixture.html @@ -7,13 +7,13 @@ {% include JB/setup %}
-

In my previous post I described how the Build method can be used to customize how a single anonymous variable is created.

A common customization is to set a property value during creation. In most cases, this can simply be done after the anonymous variable has been created (so the following is not an AutoFixture customization):

+

In my previous post I described how the Build method can be used to customize how a single anonymous variable is created.

A common customization is to set a property value during creation. In most cases, this can simply be done after the anonymous variable has been created (so the following is not an AutoFixture customization):

var mc = fixture.CreateAnonymous<MyClass>();
 mc.MyText = "Ploeh";

By default, AutoFixture assigns anonymous values to all writable properties, but since they are writable, you can always explicitly give them different values if you care.

-

However, there are situations when a property is writable, but can't take just any value of its type. Sometimes this is a sign that you should reconsider your API, as I've previously described, but it may also be a legitimate situation.

+

However, there are situations when a property is writable, but can't take just any value of its type. Sometimes this is a sign that you should reconsider your API, as I've previously described, but it may also be a legitimate situation.

Consider a Filter class that has Min and Max properties. To be semantically correct, the Min property must be less than or equal to the Max property. Each property is implemented like this:

public int Min
@@ -29,7 +29,7 @@
     }
 }

-

When you ask AutoFixture to create an instance of the Filter class, it will throw an exception because it's attempting to set the Min property after the Max property, and the default algorithm for numbers is to return numbers in an increasing sequence. (In this example, the Min property is being assigned a value after the Max property, but AutoFixture has no contract that states that the order in which properties are assigned is guaranteed.) In other words, this throws an exception:

+

When you ask AutoFixture to create an instance of the Filter class, it will throw an exception because it's attempting to set the Min property after the Max property, and the default algorithm for numbers is to return numbers in an increasing sequence. (In this example, the Min property is being assigned a value after the Max property, but AutoFixture has no contract that states that the order in which properties are assigned is guaranteed.) In other words, this throws an exception:

var f = fixture.CreateAnonymous<Filter>();

diff --git a/_posts/2009-06-05-TestabilityIsReallyTheOpenClosedPrinciple.html b/_posts/2009-06-05-TestabilityIsReallyTheOpenClosedPrinciple.html index 13826f0fc..c5459f4b1 100644 --- a/_posts/2009-06-05-TestabilityIsReallyTheOpenClosedPrinciple.html +++ b/_posts/2009-06-05-TestabilityIsReallyTheOpenClosedPrinciple.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

When I talk with people about TDD and unit testing, the discussion often moves into the area of Testability - that is, the software's susceptibility to unit testing. A couple of years back, Roy even discussed the seemingly opposable forces of Object-Oriented Design and Testability.

Lately, it has been occurring to me that there really isn't any conflict. Encapsulation is important because it manifests expert knowledge so that other developers can effectively leverage that knowledge, and it does so in a way that minimizes misuse.

However, too much encapsulation goes against the Open/Closed Principle (that states that objects should be open for extension, but closed for modification). From a Testability perspective, the Open/Closed Principle pulls object-oriented design in the desired direction. Equivalently, done correctly, making your API Testable is simply opening it up for extensibility.

As an example, consider a simple WPF ViewModel class called MainWindowViewModel. This class has an ICommand property that, when invoked, should show a message box. Showing a message box is good example of breaking testability, because if the SUT were to show a message box, it would be very hard to automatically verify and we wouldn't have fully automated tests.

For this reason, we need to introduce an abstraction that basically models an action with a string as input. Although we could define an interface for that, an Action<string> fits the bill perfectly.

To enable that feature, I decide to use Constructor Injection to inject that abstraction into the MainWindowViewModel class:

+

When I talk with people about TDD and unit testing, the discussion often moves into the area of Testability - that is, the software's susceptibility to unit testing. A couple of years back, Roy even discussed the seemingly opposable forces of Object-Oriented Design and Testability.

Lately, it has been occurring to me that there really isn't any conflict. Encapsulation is important because it manifests expert knowledge so that other developers can effectively leverage that knowledge, and it does so in a way that minimizes misuse.

However, too much encapsulation goes against the Open/Closed Principle (that states that objects should be open for extension, but closed for modification). From a Testability perspective, the Open/Closed Principle pulls object-oriented design in the desired direction. Equivalently, done correctly, making your API Testable is simply opening it up for extensibility.

As an example, consider a simple WPF ViewModel class called MainWindowViewModel. This class has an ICommand property that, when invoked, should show a message box. Showing a message box is good example of breaking testability, because if the SUT were to show a message box, it would be very hard to automatically verify and we wouldn't have fully automated tests.

For this reason, we need to introduce an abstraction that basically models an action with a string as input. Although we could define an interface for that, an Action<string> fits the bill perfectly.

To enable that feature, I decide to use Constructor Injection to inject that abstraction into the MainWindowViewModel class:

public MainWindowViewModel(Action<string> notify)
 {
diff --git a/_posts/2009-06-09-CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.html b/_posts/2009-06-09-CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.html
index 3101c08cd..4a46dce8c 100644
--- a/_posts/2009-06-09-CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.html
+++ b/_posts/2009-06-09-CallingMethodsWhileBuildingAnonymousVariablesWithAutoFixture.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

Previously, we saw how you can set property values while building anonymous variables with AutoFixture. While I insinuated that I consider this a somewhat atypical scenario, we can now safely venture forth to the truly exotic :)

Imagine that you want to build an anonymous instance of a type that requires you to call a certain method before you can start assigning properties. It's difficult to come up with a reasonable example of this, but although I consider it quite bad design, I've seen interfaces that include an Initialize method that must be called before any other member. In our example, let's call this interface IBadDesign.

Let's say that we have a class called SomeImp that implements IBadDesign. Here's the relevant part of the class:

+

Previously, we saw how you can set property values while building anonymous variables with AutoFixture. While I insinuated that I consider this a somewhat atypical scenario, we can now safely venture forth to the truly exotic :)

Imagine that you want to build an anonymous instance of a type that requires you to call a certain method before you can start assigning properties. It's difficult to come up with a reasonable example of this, but although I consider it quite bad design, I've seen interfaces that include an Initialize method that must be called before any other member. In our example, let's call this interface IBadDesign.

Let's say that we have a class called SomeImp that implements IBadDesign. Here's the relevant part of the class:

#region IBadDesign Members
  
diff --git a/_posts/2009-07-01-AutoFixtureAsTestDataBuilder.html b/_posts/2009-07-01-AutoFixtureAsTestDataBuilder.html
index 48c2a262a..eff2b4a85 100644
--- a/_posts/2009-07-01-AutoFixtureAsTestDataBuilder.html
+++ b/_posts/2009-07-01-AutoFixtureAsTestDataBuilder.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

Some time ago, my good friend Martin Gildenpfennig from Ative made me aware that AutoFixture (among other things) is an generic implementation of the Test Data Builder pattern, and indeed it is.

In the original Gang of Four definition of a Design Pattern, several people must independently have arrived at the same general solution to a given problem before we can call a coding idiom a true Pattern. In this spirit, the Test Data Builder pattern is on the verge of becoming a true Design Pattern, since I came up with AutoFixture without having heard about Test Data Builder :)

The problem is the same: How do we create semantically correct test objects in a manner that is flexible and yet hides away irrelevant complexity?

Like others before me, I tried the Object Mother (anti?)pattern and found it lacking. To me the answer was AutoFixture, a library that heuristically builds object graphs using Reflection and built-in rules for specific types.

Although my original approach was different, you can certainly use AutoFixture as a generic Test Data Builder.

To demonstrate this, let's work with this (oversimplified) Order object model:

image

Assuming that we have an instance of the Fixture class (called fixture), we can create a new instance of the Order class with a ShippingAddress in Denmark:

+

Some time ago, my good friend Martin Gildenpfennig from Ative made me aware that AutoFixture (among other things) is an generic implementation of the Test Data Builder pattern, and indeed it is.

In the original Gang of Four definition of a Design Pattern, several people must independently have arrived at the same general solution to a given problem before we can call a coding idiom a true Pattern. In this spirit, the Test Data Builder pattern is on the verge of becoming a true Design Pattern, since I came up with AutoFixture without having heard about Test Data Builder :)

The problem is the same: How do we create semantically correct test objects in a manner that is flexible and yet hides away irrelevant complexity?

Like others before me, I tried the Object Mother (anti?)pattern and found it lacking. To me the answer was AutoFixture, a library that heuristically builds object graphs using Reflection and built-in rules for specific types.

Although my original approach was different, you can certainly use AutoFixture as a generic Test Data Builder.

To demonstrate this, let's work with this (oversimplified) Order object model:

image

Assuming that we have an instance of the Fixture class (called fixture), we can create a new instance of the Order class with a ShippingAddress in Denmark:

var order = fixture.Build<Order>()
     .With(o => o.ShippingAddress, 
diff --git a/_posts/2009-07-16-DataTemplatingInASP.NETMVC.html b/_posts/2009-07-16-DataTemplatingInASP.NETMVC.html
index 3ed266dd8..b36602742 100644
--- a/_posts/2009-07-16-DataTemplatingInASP.NETMVC.html
+++ b/_posts/2009-07-16-DataTemplatingInASP.NETMVC.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

The expressiveness of WPF is amazing. I particularly like the databinding and templating features. The ability to selectively render an object based on its type is very strong.

When I recently began working with ASP.NET MVC (which I like so far), I quickly ran into a scenario where I would have liked to have WPF's DataTemplates at my disposal. Maybe it's just because I've become used to WPF, but I missed the feature and set out to find out if something similar is possible in ASP.NET MVC.

Before we dive into that, I'd like to present the 'problem' in WPF terms, but the underlying View Model that I want to expose will be shared between both solutions.

PresentationModel

The main point is that the Items property exposes a polymorphic list. While all items in this list share a common property (Name), they are otherwise different; one contains a piece of Text, one contains a Color, and one is a complex item that contains child items.

When I render this list, I want each item to render according to its type.

In WPF, this is fairly easy to accomplish with DataTemplates:

+

The expressiveness of WPF is amazing. I particularly like the databinding and templating features. The ability to selectively render an object based on its type is very strong.

When I recently began working with ASP.NET MVC (which I like so far), I quickly ran into a scenario where I would have liked to have WPF's DataTemplates at my disposal. Maybe it's just because I've become used to WPF, but I missed the feature and set out to find out if something similar is possible in ASP.NET MVC.

Before we dive into that, I'd like to present the 'problem' in WPF terms, but the underlying View Model that I want to expose will be shared between both solutions.

PresentationModel

The main point is that the Items property exposes a polymorphic list. While all items in this list share a common property (Name), they are otherwise different; one contains a piece of Text, one contains a Color, and one is a complex item that contains child items.

When I render this list, I want each item to render according to its type.

In WPF, this is fairly easy to accomplish with DataTemplates:

<ListBox.Resources>
     <DataTemplate DataType="{x:Type pm:NamedTextItem}">
@@ -47,7 +47,7 @@
 

Each DataTemplate is contained within a ListBox. When the ListBox binds to each item in the Items list, it automatically picks the correct template for the item.

The result is something like this:

-

WpfApp

+

WpfApp

The NamedTextItem is rendered as a box containing the Name and the Text on two separate lines; the NamedColorItem is rendered as a box containing the Name and a circle filled with the Color defined by the item; and the NamedComplexItem is rendered as a box with the Name and each child of the Children list.

This is all implemented declaratively without a single line of imperative UI code.

Is it possible to do the same in ASP.NET MVC?

@@ -95,7 +95,7 @@

This is definitely less pretty than with WPF, but if you overlook the aesthetics and focus on the structure of the code, it's darn close to markup. The Cyclomatic Complexity of the page is only 2, and that's even because of the foreach statement that we need in any case.

The resulting page looks like this:

-

AspNetMvcApp

+

AspNetMvcApp

My HTML skills aren't good enough to draw circles with markup, so I had to replace them with blocks, but apart from that, the result is pretty much the same.

A potential improvement on this technique could be to embed the knowledge of the UserControl into each item. ASP.NET MVC Controllers already know of Views in an abstract sense, so letting the View Model know about a UserControl (identified as a string) may be conceptually sound.

The advantage would be that we could get rid of the Dictionary in the ViewPage and instead let the item itself tell us the name of the UserControl that should be used to render it.

diff --git a/_posts/2009-07-23-DisablingAutoPropertiesInAutoFixture.html b/_posts/2009-07-23-DisablingAutoPropertiesInAutoFixture.html index 0c7396b4a..c217ec0fd 100644 --- a/_posts/2009-07-23-DisablingAutoPropertiesInAutoFixture.html +++ b/_posts/2009-07-23-DisablingAutoPropertiesInAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

Since AutoFixture is a Test Data Builder, one of its most important tasks is to build up graphs of fully populated, yet semantically correct, strongly typed objects. As such, its default behavior is to assign a value to every writable property in the object graph.

While this is sometimes the desired behavior, at other times it is not.

This is particularly the case when you want to test that a newly created object has a property of a particular value. When you want to test the default value of a writable property, AutoFixture's AutoProperty feature is very much in the way.

Let's consider as an example a piece of software that deals with vehicle registration. By default, a vehicle should have four wheels, since this is the most common occurrence. Although I always practice TDD, I'll start by showing you the Vehicle class to illustrate what I mean.

+

Since AutoFixture is a Test Data Builder, one of its most important tasks is to build up graphs of fully populated, yet semantically correct, strongly typed objects. As such, its default behavior is to assign a value to every writable property in the object graph.

While this is sometimes the desired behavior, at other times it is not.

This is particularly the case when you want to test that a newly created object has a property of a particular value. When you want to test the default value of a writable property, AutoFixture's AutoProperty feature is very much in the way.

Let's consider as an example a piece of software that deals with vehicle registration. By default, a vehicle should have four wheels, since this is the most common occurrence. Although I always practice TDD, I'll start by showing you the Vehicle class to illustrate what I mean.

public class Vehicle
 {
@@ -35,8 +35,8 @@
     // Teardown
 }

-

Why does the test fail when the value of Wheels is set to 4 in the constructor? It fails because AutoFixture is designed to create populated test data, so it assigns a value to every writable property. Wheels is a writable property, so AutoFixture assigns an integer value to it using its default algorithm for creating anonymous numbers. Since no other numbers are being created during this test, the number assigned to Wheels is 1. This is AutoFixture's AutoProperties feature in effect.

-

When you want to test constructor logic, or otherwise wish to disable the AutoProperties feature, you can use a customized Builder with the OmitAutoProperties method:

+

Why does the test fail when the value of Wheels is set to 4 in the constructor? It fails because AutoFixture is designed to create populated test data, so it assigns a value to every writable property. Wheels is a writable property, so AutoFixture assigns an integer value to it using its default algorithm for creating anonymous numbers. Since no other numbers are being created during this test, the number assigned to Wheels is 1. This is AutoFixture's AutoProperties feature in effect.

+

When you want to test constructor logic, or otherwise wish to disable the AutoProperties feature, you can use a customized Builder with the OmitAutoProperties method:

[TestMethod]
 public void VehicleWithoutAutoPropertiesWillHaveFourWheels()
@@ -53,7 +53,7 @@
     // Teardown
 }

-

The OmitAutoProperties method instructs AutoFixture to skip assigning automatic Anonymous Values to all writable properties in the object graph. Any properties specifically assigned by the With method will still be assigned.

+

The OmitAutoProperties method instructs AutoFixture to skip assigning automatic Anonymous Values to all writable properties in the object graph. Any properties specifically assigned by the With method will still be assigned.

The test using OmitAutoProperties succeeds.

\ No newline at end of file diff --git a/_posts/2009-08-06-AFluentInterfaceForTestingINotifyPropertyChanged.html b/_posts/2009-08-06-AFluentInterfaceForTestingINotifyPropertyChanged.html index 29fe5cb47..166e4687e 100644 --- a/_posts/2009-08-06-AFluentInterfaceForTestingINotifyPropertyChanged.html +++ b/_posts/2009-08-06-AFluentInterfaceForTestingINotifyPropertyChanged.html @@ -147,7 +147,7 @@

2012-08-06 11:39 UTC

- +
Would that add more value than three individual tests?
2012-08-06 11:52 UTC
diff --git a/_posts/2009-08-17-OmittingOnlyCertainPropertiesWithAutoFixture.html b/_posts/2009-08-17-OmittingOnlyCertainPropertiesWithAutoFixture.html index 2bc60ea64..b85811f46 100644 --- a/_posts/2009-08-17-OmittingOnlyCertainPropertiesWithAutoFixture.html +++ b/_posts/2009-08-17-OmittingOnlyCertainPropertiesWithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

The default behavior of AutoFixture is to create an Anonymous Variable by assigning a value to all writable properties of the created instance. This is great in many scenarios, but not so much in others. You can disable this behavior by using the OmitAutoProperties method, but sometimes, you would like most of the writable properties set, except one or two.

Consider this simple Person class:

+

The default behavior of AutoFixture is to create an Anonymous Variable by assigning a value to all writable properties of the created instance. This is great in many scenarios, but not so much in others. You can disable this behavior by using the OmitAutoProperties method, but sometimes, you would like most of the writable properties set, except one or two.

Consider this simple Person class:

public class Person
 {
diff --git a/_posts/2009-08-25-DoRedux.html b/_posts/2009-08-25-DoRedux.html
index ee3ada562..80489f756 100644
--- a/_posts/2009-08-25-DoRedux.html
+++ b/_posts/2009-08-25-DoRedux.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

Soon after I posted my post on the AutoFixture Custom Builder's Do method, a much better example occurred to me, so let's revisit this feature in light of a more reasonable context.

When I write WPF code, I always use the MVVM pattern. When I need to create a Master/Detail View, I usually model it so that my View Model has a list of available items, and a property that returns the currently selected item. In this way, I can bind the current Detail View to the currently selected item purely through the View Model.

Such a View Model might look like this:

+

Soon after I posted my post on the AutoFixture Custom Builder's Do method, a much better example occurred to me, so let's revisit this feature in light of a more reasonable context.

When I write WPF code, I always use the MVVM pattern. When I need to create a Master/Detail View, I usually model it so that my View Model has a list of available items, and a property that returns the currently selected item. In this way, I can bind the current Detail View to the currently selected item purely through the View Model.

Such a View Model might look like this:

public class MyViewModel
 {
@@ -52,14 +52,14 @@
     .CreateAnonymous();

This first creates an anonymous instance of MyClass, adds it to AvailableItems as part of a customized Builder pipeline and subsequently assigns it to SelectedItem.

-

Another option is to skip assigning only the SelectedItem property. This is a good option if you don't need that value in a particular test. You can use the Without method to do that:

+

Another option is to skip assigning only the SelectedItem property. This is a good option if you don't need that value in a particular test. You can use the Without method to do that:

var mvm = fixture.Build<MyViewModel>()
     .Without(s => s.SelectedItem)
     .CreateAnonymous();

This will assign a value to all other writable properties of MyViewModel (if it had had any), except the SelectedItem property. In this case, the value of SelectedItem will be null, since it is being ignored.

-

Finally you can simply choose to omit all AutoProperties using the OmitAutoProperties method:

+

Finally you can simply choose to omit all AutoProperties using the OmitAutoProperties method:

var mvm = fixture.Build<MyViewModel>()
     .OmitAutoProperties()
@@ -105,10 +105,10 @@ 

2009-12-04 22:00 UTC

- +
Hi Murali

-Thank you for your question! It prompted me to write a new blog post that provides possible solutions to your question: Building and assigning arrays with AutoFixture.
+Thank you for your question! It prompted me to write a new blog post that provides possible solutions to your question: Building and assigning arrays with AutoFixture.

I hope it answers your question. If not then please write again.
2009-12-05 00:45 UTC
@@ -121,7 +121,7 @@

2012-05-10 13:22 UTC

- +
FWIW, I've found Knockout.js pretty decent so far, but that's probably not what you had in mind?

For WPF, I don't think an additional framework is warranted for MVVM; for Silverlight, I have no opinion.
@@ -144,7 +144,7 @@

2012-05-14 07:09 UTC

- +
2012-05-14 08:23 UTC
diff --git a/_posts/2009-09-02-AutoFixture.8.5Released.html b/_posts/2009-09-02-AutoFixture.8.5Released.html index 32c83e5d7..0521c22c4 100644 --- a/_posts/2009-09-02-AutoFixture.8.5Released.html +++ b/_posts/2009-09-02-AutoFixture.8.5Released.html @@ -7,6 +7,6 @@ {% include JB/setup %}
-

It gives me great pleasure to announce that I have just release version .8.5 of AutoFixture. It is a minor release (hence the numbering) that mainly contains a lot of convenience overloads to already existing methods. There is also a single bug fix.

There are two breaking changes (documented on the release page), but they are minor and I do not expect them to cause problems. Only one of these even remotely affects any part of the API I have already discussed here, and that relates to what kind of exception is being thrown when AutoFixture is unable to create an instance of the requested type.

Please go ahead and download it and use it heavily :) As always, comments and questions are welcome.

+

It gives me great pleasure to announce that I have just release version .8.5 of AutoFixture. It is a minor release (hence the numbering) that mainly contains a lot of convenience overloads to already existing methods. There is also a single bug fix.

There are two breaking changes (documented on the release page), but they are minor and I do not expect them to cause problems. Only one of these even remotely affects any part of the API I have already discussed here, and that relates to what kind of exception is being thrown when AutoFixture is unable to create an instance of the requested type.

Please go ahead and download it and use it heavily :) As always, comments and questions are welcome.

\ No newline at end of file diff --git a/_posts/2009-09-07-Self-updatingAJAXlinkswithASP.NETMVC.html b/_posts/2009-09-07-Self-updatingAJAXlinkswithASP.NETMVC.html index bd0ce2637..8bce210ec 100644 --- a/_posts/2009-09-07-Self-updatingAJAXlinkswithASP.NETMVC.html +++ b/_posts/2009-09-07-Self-updatingAJAXlinkswithASP.NETMVC.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

How can you make an AJAX link that updates itself in ASP.NET MVC? My colleague Mikkel and I recently had that problem and we couldn't find any guidance on this topic, so now that we have a solution, I thought I'd share it.

The problem is simple: We needed a link that invoked some server side code and updated the text of the link itself based on the result of the operation. Here is a simplified example:

image

Each time you click the link, it should invoke a Controller Action and return a new number that should appear as the link text.

This is pretty simple to implement once you know how. The first thing to realize is that the link and all the AJAX stuff must be placed in a user control. The only thing that needs to go into the containing page is the containing element itself:

+

How can you make an AJAX link that updates itself in ASP.NET MVC? My colleague Mikkel and I recently had that problem and we couldn't find any guidance on this topic, so now that we have a solution, I thought I'd share it.

The problem is simple: We needed a link that invoked some server side code and updated the text of the link itself based on the result of the operation. Here is a simplified example:

image

Each time you click the link, it should invoke a Controller Action and return a new number that should appear as the link text.

This is pretty simple to implement once you know how. The first thing to realize is that the link and all the AJAX stuff must be placed in a user control. The only thing that needs to go into the containing page is the containing element itself:

<h2>Self-updating AJAX link</h2>
 Click the link to update the number:
@@ -65,7 +65,7 @@ 

2009-09-08 07:00 UTC

- +
Thank you for your comment

It looks pretty simple. The following questions are entirely based on my total (and very deplorable) lack of JQuery knowledge:
diff --git a/_posts/2009-09-22-CustomizingAType'sBuilderWithAutoFixture.html b/_posts/2009-09-22-CustomizingAType'sBuilderWithAutoFixture.html index ba617932f..1420c3065 100644 --- a/_posts/2009-09-22-CustomizingAType'sBuilderWithAutoFixture.html +++ b/_posts/2009-09-22-CustomizingAType'sBuilderWithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

In the previous post on AutoFixture, I demonstrated how it's possible to use a customized Builder to perform complex initialization when requesting an instance of a particular type. To recap, this was the solution I described:

+

In the previous post on AutoFixture, I demonstrated how it's possible to use a customized Builder to perform complex initialization when requesting an instance of a particular type. To recap, this was the solution I described:

var mc = fixture.CreateAnonymous<MyClass>();
 var mvm = fixture.Build<MyViewModel>()
@@ -98,7 +98,7 @@ 

2015-02-26 21:39 UTC

- +

Scott, thank you for writing. In your expression b.DatePurchased == DateTime.Now.AddMonths(-7), what would you say the == does? diff --git a/_posts/2009-10-05-Writingabook.html b/_posts/2009-10-05-Writingabook.html index 195f45b46..f9c3ceb78 100644 --- a/_posts/2009-10-05-Writingabook.html +++ b/_posts/2009-10-05-Writingabook.html @@ -23,7 +23,7 @@

2009-10-07 03:01 UTC

- +
I hope that you get a lot out of it! If parts of the contents strike you as odd or you think that something is missing, please let me know. The Author Online forum is the preferred place, but you can drop me a line in any way you prefer.
2009-10-13 11:00 UTC
@@ -38,7 +38,7 @@

2009-10-21 12:32 UTC

- +
Yes, that is definitely the plan. Manning does have the code, but I don't know when they plan on making it available. It's still a little rough around the edges, but if you would like to get it now, send me an email (use the small envelope icon in the Contact section area) and I'll zip it up for you.
2009-10-21 12:55 UTC
@@ -56,7 +56,7 @@

2013-05-23 18:31 UTC

- +

Scott, thanks for writing. The Visual Studio behaviour you describe fits my own experience: stepping into something Decorated with a dynamic interceptor doesn't really work. While I'm no expert in how the Visual Studio debugger works, I think it's because there's some auto-generated code (the dynamic interceptor(s)) between the call site and your code on the other side. Visual Studio doesn't have the source code for the dynamic interceptor, so it generally gives up when you try to do that. diff --git a/_posts/2009-10-26-AnonymousWith.html b/_posts/2009-10-26-AnonymousWith.html index bed8a5171..71108d96f 100644 --- a/_posts/2009-10-26-AnonymousWith.html +++ b/_posts/2009-10-26-AnonymousWith.html @@ -7,7 +7,7 @@ {% include JB/setup %}

-

A few months ago I described how you can use AutoFixture's With method to assign property values as part of building up an anonymous variable. In that scenario, the With method is used to explicitly assign a particular, pre-defined value to a property.

There's another overload of the With method that doesn't take an explicit value, but rather uses AutoFixture to create an anonymous value for the property. So what's the deal with that if AutoFixture's default behavior is to assign anonymous values to all writable properties?

In short it's an opt-in mechanism that only makes sense if you decide to opt out of the AutoProperties features.

As always, let's look at an example. This time, I've decided to show you a slightly more realistic example so that you can get an idea of how AutoFixture can be used to aid in unit testing. This also means that the example is going to be a little more complex than usual, but it's still simple.

Imagine that we wish to test that an ASP.NET MVC Controller Action returns the correct result. More specifically, we wish to test that the Profile method on MyController returns a ViewResult with the correct Model (the current user's name, to make things interesing).

Here's the entire test. It may look more complicated than it is - it's really only 10 lines of code, but I had to break them up to prevent unpleasant wrapping if your screen is narrow.

+

A few months ago I described how you can use AutoFixture's With method to assign property values as part of building up an anonymous variable. In that scenario, the With method is used to explicitly assign a particular, pre-defined value to a property.

There's another overload of the With method that doesn't take an explicit value, but rather uses AutoFixture to create an anonymous value for the property. So what's the deal with that if AutoFixture's default behavior is to assign anonymous values to all writable properties?

In short it's an opt-in mechanism that only makes sense if you decide to opt out of the AutoProperties features.

As always, let's look at an example. This time, I've decided to show you a slightly more realistic example so that you can get an idea of how AutoFixture can be used to aid in unit testing. This also means that the example is going to be a little more complex than usual, but it's still simple.

Imagine that we wish to test that an ASP.NET MVC Controller Action returns the correct result. More specifically, we wish to test that the Profile method on MyController returns a ViewResult with the correct Model (the current user's name, to make things interesing).

Here's the entire test. It may look more complicated than it is - it's really only 10 lines of code, but I had to break them up to prevent unpleasant wrapping if your screen is narrow.

[TestMethod]
 public void ProfileWillReturnResultWithCorrectUserName()
@@ -40,7 +40,7 @@
 }

Apart from AutoFixture, I'm also making use of Moq to stub out HttpContextBase.

-

You can see the Anonymous With method in two different places: in the call to Customize and when the SUT is being built. In both cases you can see that the call to With follows a call to OmitAutoProperties. In other words: we are telling AutoFixture that we don't want any of the writable properties to be assigned a value except the one we identify.

+

You can see the Anonymous With method in two different places: in the call to Customize and when the SUT is being built. In both cases you can see that the call to With follows a call to OmitAutoProperties. In other words: we are telling AutoFixture that we don't want any of the writable properties to be assigned a value except the one we identify.

Let me highlight some parts of the test.

fixture.Customize<ControllerContext>(ob => ob
diff --git a/_posts/2009-11-07-Creatinglength-constrainedstringswithAutoFixture.html b/_posts/2009-11-07-Creatinglength-constrainedstringswithAutoFixture.html
index 60f61431e..b00a95870 100644
--- a/_posts/2009-11-07-Creatinglength-constrainedstringswithAutoFixture.html
+++ b/_posts/2009-11-07-Creatinglength-constrainedstringswithAutoFixture.html
@@ -97,12 +97,12 @@ 

2012-04-26 14:32 UTC

- +
IIRC the ConstrainedStringGenerator class was added to support the [StringLength] attribute. Does this do what you'd like it to do?

There's also a recent discussion about the subject on Stack Overflow.

-Finally, perhaps you'll find this post helpful.
+Finally, perhaps you'll find this post helpful.

If none of these links answer your question, please feel free to ask again. However, Stack Overflow or the AutoFixture discussion list might be better forums, as they are better targeted at Q&A.

diff --git a/_posts/2009-11-17-UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7.html b/_posts/2009-11-17-UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7.html index ca8915d6e..7c6840d0a 100644 --- a/_posts/2009-11-17-UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7.html +++ b/_posts/2009-11-17-UsingCastleWindsor'sPerWebRequestlifestylewithASP.NETMVConIIS7.html @@ -30,7 +30,7 @@

2010-01-14 22:04 UTC

- +
Thanks for the explanation :)
2010-01-14 22:23 UTC
diff --git a/_posts/2009-12-01-GlobalErrorHandlinginASP.NETMVC.html b/_posts/2009-12-01-GlobalErrorHandlinginASP.NETMVC.html index d9b8d5e5e..ece984ac2 100644 --- a/_posts/2009-12-01-GlobalErrorHandlinginASP.NETMVC.html +++ b/_posts/2009-12-01-GlobalErrorHandlinginASP.NETMVC.html @@ -104,10 +104,10 @@

2010-01-30 00:23 UTC

- +
You are correct that in our production applications, we don't manually request the ErrorHandlingActionInvoker from the container and assign it to the property. Rather, we simply configure the container to automatically set the ActionInvoker property as part of wiring up any Controller.

-This follow-up post provides an example.
+This follow-up post provides an example.
2010-01-30 09:27 UTC
@@ -116,7 +116,7 @@

2010-03-15 21:42 UTC

- +
I'm not sure I understand how your question relates particularly to this blog post, so I'll need more details than that to be able to say anything meaningful.

May I suggest asking your question on Stack Overflow? That site has good facilities for asking development-related questions, including syntax highlighting. You are welcome to point me to any questions you may have, and I'll take a look and answer if I have anything to add.
diff --git a/_posts/2009-12-05-BuildingandassigningarrayswithAutoFixture.html b/_posts/2009-12-05-BuildingandassigningarrayswithAutoFixture.html index 678616a6c..5f64dcf88 100644 --- a/_posts/2009-12-05-BuildingandassigningarrayswithAutoFixture.html +++ b/_posts/2009-12-05-BuildingandassigningarrayswithAutoFixture.html @@ -16,14 +16,14 @@     public MyClassD D; }

-

Ignoring the bad practice of publicly exposing fields, the main problem is that AutoFixture has no inherent understanding of arrays, so if we try to create a new instance of MyClassA by invoking the CreateAnonymous method, we would end up with Items being an array of nulls.

+

Ignoring the bad practice of publicly exposing fields, the main problem is that AutoFixture has no inherent understanding of arrays, so if we try to create a new instance of MyClassA by invoking the CreateAnonymous method, we would end up with Items being an array of nulls.

Obviously we want a populated array instead. There are at least a couple of ways to reach this goal.

The simplest is just to create it and modify it afterwards:

var mc = fixture.CreateAnonymous<MyClassA>();
 mc.Items = fixture.CreateMany<MyClassB>().ToArray();

-

Although the CreateAnomymous method will assign an unitialized array, we immediately overwrite the value with an initialized array. The CreateMany method returns an IEnumerable<MyClassB> on which we can use the ToArray extension method to create an array.

+

Although the CreateAnomymous method will assign an unitialized array, we immediately overwrite the value with an initialized array. The CreateMany method returns an IEnumerable<MyClassB> on which we can use the ToArray extension method to create an array.

The next option is to do almost the same thing, but as a single operation:

var mc = fixture.Build<MyClassA>()
@@ -31,8 +31,8 @@
         fixture.CreateMany<MyClassB>().ToArray())
     .CreateAnonymous();

-

Besides the different syntax and the lower semicolon count, the biggest difference is that in this case the Items field is never assigned an unitialized array because the With method ensures that the specified value is assigned immediately.

-

If you get tired of writing this Builder sequence every time you want to create a new MyClassA instance, you can Customize the Fixture:

+

Besides the different syntax and the lower semicolon count, the biggest difference is that in this case the Items field is never assigned an unitialized array because the With method ensures that the specified value is assigned immediately.

+

If you get tired of writing this Builder sequence every time you want to create a new MyClassA instance, you can Customize the Fixture:

fixture.Customize<MyClassA>(ob =>
     ob.With(x => x.Items, 
diff --git a/_posts/2009-12-07-LoggingExceptionFilter.html b/_posts/2009-12-07-LoggingExceptionFilter.html
index df2467476..74c43abbf 100644
--- a/_posts/2009-12-07-LoggingExceptionFilter.html
+++ b/_posts/2009-12-07-LoggingExceptionFilter.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

In a previous post I described how to enable global error handling in ASP.NET MVC applications. Although I spent some time talking about the importance of DRY, another major motivation for me was to enable Dependency Injection (DI) with exception handling so that I could log stack traces before letting ASP.NET MVC handle the exception.

With the ErrorHandlingControllerActionInvoker I described, we can inject any IExceptionFilter implementation. As an example I used HandleErrorAttribute, but obviously that doesn't log anything. Once again, it would be tempting to derive from HandleErrorAttribute and override its OnException method, but staying true to the Single Responsibility Principle as well as the Open/Closed Principle I rather prefer a Decorator:

+

In a previous post I described how to enable global error handling in ASP.NET MVC applications. Although I spent some time talking about the importance of DRY, another major motivation for me was to enable Dependency Injection (DI) with exception handling so that I could log stack traces before letting ASP.NET MVC handle the exception.

With the ErrorHandlingControllerActionInvoker I described, we can inject any IExceptionFilter implementation. As an example I used HandleErrorAttribute, but obviously that doesn't log anything. Once again, it would be tempting to derive from HandleErrorAttribute and override its OnException method, but staying true to the Single Responsibility Principle as well as the Open/Closed Principle I rather prefer a Decorator:

public class LoggingExceptionFilter : IExceptionFilter
 {
diff --git a/_posts/2009-12-14-WiringASP.NETMVCErrorHandlingwithCastleWindsor.html b/_posts/2009-12-14-WiringASP.NETMVCErrorHandlingwithCastleWindsor.html
index 7337fde0d..33015c64e 100644
--- a/_posts/2009-12-14-WiringASP.NETMVCErrorHandlingwithCastleWindsor.html
+++ b/_posts/2009-12-14-WiringASP.NETMVCErrorHandlingwithCastleWindsor.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

In my previous posts I discussed how to enable global error handling in ASP.NET MVC and how to inject a logging interface into the error handler. In these posts, I simplified things a bit to get my points across.

In production we don't use a custom ErrorHandlingControllerFactory to configure all Controllers with error handling, nor do we instantiate IExceptionFilters manually. What I described was the Poor Man's Dependency Injection (DI) approach, which I find most appropriate when describing DI concepts.

However, we really use Castle Windsor currently, so the wiring looks a bit different although it's still exactly the same thing that's going on. Neither ErrorHandlingActionInvoker nor LoggingExceptionFilter are any different than I have already described, but for completeness I wanted to share a bit of our Windsor code.

This is how we really wire our Controllers:

+

In my previous posts I discussed how to enable global error handling in ASP.NET MVC and how to inject a logging interface into the error handler. In these posts, I simplified things a bit to get my points across.

In production we don't use a custom ErrorHandlingControllerFactory to configure all Controllers with error handling, nor do we instantiate IExceptionFilters manually. What I described was the Poor Man's Dependency Injection (DI) approach, which I find most appropriate when describing DI concepts.

However, we really use Castle Windsor currently, so the wiring looks a bit different although it's still exactly the same thing that's going on. Neither ErrorHandlingActionInvoker nor LoggingExceptionFilter are any different than I have already described, but for completeness I wanted to share a bit of our Windsor code.

This is how we really wire our Controllers:

container.Register(AllTypes
     .FromAssemblyContaining(representativeControllerType)
diff --git a/_posts/2010-01-04-AnonymousGet.html b/_posts/2010-01-04-AnonymousGet.html
index d3f0c4f09..53a7d6fa3 100644
--- a/_posts/2010-01-04-AnonymousGet.html
+++ b/_posts/2010-01-04-AnonymousGet.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

In a previous post I described how AutoFixture's Do method can let you invoke commands on your SUT with Dummy values for the parameters you don't care about.

The Get method is the equivalent method you can use when the member you are invoking returns a value. In other words: if you want to call a method on your SUT to get a value, but you don't want the hassle of coming up with values you don't care about, you can let the Get method supply those values for you.

In today's example I will demonstrate a unit test that verifies the behavior of a custom ASP.NET MVC ModelBinder. If you don't know anything about ASP.NET MVC it doesn't really matter. The point is that a ModelBinder must implement the IModelBinder interface that defines a single method:

+

In a previous post I described how AutoFixture's Do method can let you invoke commands on your SUT with Dummy values for the parameters you don't care about.

The Get method is the equivalent method you can use when the member you are invoking returns a value. In other words: if you want to call a method on your SUT to get a value, but you don't want the hassle of coming up with values you don't care about, you can let the Get method supply those values for you.

In today's example I will demonstrate a unit test that verifies the behavior of a custom ASP.NET MVC ModelBinder. If you don't know anything about ASP.NET MVC it doesn't really matter. The point is that a ModelBinder must implement the IModelBinder interface that defines a single method:

object BindModel(ControllerContext controllerContext,
     ModelBindingContext bindingContext);
@@ -41,7 +41,7 @@     // Teardown }

-

The first part simply creates the Fixture object and customizes it to disable AutoProperties for all ControllerContext instances (otherwise we would have to set up a lot of Test Doubles for such properties as HttpContext, RequestContext etc.).

The next part of the test sets up a ModelBindingContext instance that will be used to exercise the SUT. In this test case, the bindingContext parameter of the BindModel method is important, so I explicitly set that up. On the other hand, I don't care about the controllerContext parameter in this test case, so I ask the Get method to take care of that for me:

+

The first part simply creates the Fixture object and customizes it to disable AutoProperties for all ControllerContext instances (otherwise we would have to set up a lot of Test Doubles for such properties as HttpContext, RequestContext etc.).

The next part of the test sets up a ModelBindingContext instance that will be used to exercise the SUT. In this test case, the bindingContext parameter of the BindModel method is important, so I explicitly set that up. On the other hand, I don't care about the controllerContext parameter in this test case, so I ask the Get method to take care of that for me:

var result = fixture.Get((ControllerContext cc) =>
     sut.BindModel(cc, bindingContext));
diff --git a/_posts/2010-01-20-EnablingDIforLazyComponents.html b/_posts/2010-01-20-EnablingDIforLazyComponents.html index 788e7cb87..e80635cfb 100644 --- a/_posts/2010-01-20-EnablingDIforLazyComponents.html +++ b/_posts/2010-01-20-EnablingDIforLazyComponents.html @@ -8,7 +8,7 @@ {% include JB/setup %}
-

My previous post led to this comment by Phil Haack:

Your LazyOrderShipper directly instantiates an OrderShipper. What about the dependencies that OrderShipper might require? What if those dependencies are costly?

I didn't want to make my original example more complex than necessary to get the point across, so I admit that I made it a bit simpler than I might have liked. However, the issue is easily solved by enabling DI for the LazyOrderShipper itself.

As always, when the dependency's lifetime may be shorter than the consumer, the solution is to inject (via the constructor!) an Abstract Factory, as this modification of LazyOrderShipper shows:

+

My previous post led to this comment by Phil Haack:

Your LazyOrderShipper directly instantiates an OrderShipper. What about the dependencies that OrderShipper might require? What if those dependencies are costly?

I didn't want to make my original example more complex than necessary to get the point across, so I admit that I made it a bit simpler than I might have liked. However, the issue is easily solved by enabling DI for the LazyOrderShipper itself.

As always, when the dependency's lifetime may be shorter than the consumer, the solution is to inject (via the constructor!) an Abstract Factory, as this modification of LazyOrderShipper shows:

public class LazyOrderShipper2 : IOrderShipper
 {
@@ -60,8 +60,8 @@ 

2010-01-20 20:44 UTC

- -
Yes, Func<T> is sometimes a viable option. In general, I consider delegates to be anonymous interfaces, so Func<T> is really just an Abstract Factory. In other words, IOrderShipperFactory is functionally equivalent to Func<IOrderShipper>.
+ +
Yes, Func<T> is sometimes a viable option. In general, I consider delegates to be anonymous interfaces, so Func<T> is really just an Abstract Factory. In other words, IOrderShipperFactory is functionally equivalent to Func<IOrderShipper>.

I had a period where I used a lot of delegates as injected dependencies, but I have more or less abandonded that approach again. While it technically works fine, it makes unit testing a bit harder because it's harder to test that a given object contains a specific type of Strategy if it's just a Func<T> or similar.

@@ -108,7 +108,7 @@

2010-01-21 10:59 UTC

- +
To be fair, Alwin mentioned it over on Jeffrey Palermo's original post before I posted my response.

That would definitely be an option as well, but I rather wanted to show the route involving absolutely no redesign of the original OrderProcess, and I couldn't do that purely with Lazy<IOrderShipper>. The most important point I wanted to make is that you can solve this problem using basic tools available since .NET 1.0.
@@ -122,7 +122,7 @@

2010-01-22 15:25 UTC

- +
@Derek Greer: Aggreed, and that was also my initial point in my previous post.
2010-01-22 23:54 UTC
@@ -143,7 +143,7 @@

2012-03-14 21:52 UTC

- +
Thomas, who said anything about a DI Container or Castle Windsor for that matter?
2012-03-15 06:47 UTC
@@ -159,7 +159,7 @@

2012-03-15 08:50 UTC

- +
Ah, sorry... I'm not sure I entirely understand the question. With Windsor's Typed Factory Facility, you'd reqister the IOrderShipperFactory as being auto-generated by Windsor. I can't recall the exact syntax for this right now, but that registration would happen as part of the Registration phase of RRR.
2012-03-15 09:26 UTC
@@ -181,8 +181,8 @@

2012-03-15 10:04 UTC

- -
Thomas, I wrote a new blog post to answer your question.
+ +
Thomas, I wrote a new blog post to answer your question.

HTH
2012-03-15 21:04 UTC
diff --git a/_posts/2010-01-20-RebuttalConstructorover-injectionanti-pattern.html b/_posts/2010-01-20-RebuttalConstructorover-injectionanti-pattern.html index 9985bab12..baf15be11 100644 --- a/_posts/2010-01-20-RebuttalConstructorover-injectionanti-pattern.html +++ b/_posts/2010-01-20-RebuttalConstructorover-injectionanti-pattern.html @@ -108,10 +108,10 @@

2010-01-20 17:20 UTC

- +
Thank you all for your comments.

-The point raised by Phil Haack is valid, so I've addressed it in a second blog post.
+The point raised by Phil Haack is valid, so I've addressed it in a second blog post.
2010-01-20 18:09 UTC
@@ -120,7 +120,7 @@

2010-01-20 18:44 UTC

- +
Why isn't LazyOrderShipper thread-safe as it is?

When I wrote that, my thinking was that if the Ship method is hit by two or more threads simultaneously, more than one thread may evaluate the member field to null and start creating a new instance of OrderShipper. At least one of those instance will created, but never permanently assigned, since another thread may overwrite the value.
@@ -154,7 +154,7 @@

2010-01-22 21:52 UTC

- +
I agree, but I just couldn't let the claim that Constructor Injection is an anti-pattern go by without reacting.
2010-01-22 23:56 UTC
diff --git a/_posts/2010-01-25-DependencyInjectionInversionin.NET.html b/_posts/2010-01-25-DependencyInjectionInversionin.NET.html index ea0282500..5ddc2f781 100644 --- a/_posts/2010-01-25-DependencyInjectionInversionin.NET.html +++ b/_posts/2010-01-25-DependencyInjectionInversionin.NET.html @@ -85,12 +85,12 @@

2010-01-26 22:18 UTC

- +
Thanks for your comment.

If my previous post left the impression that I find Uncle Bob's views justified in the context of Java's DI Containers, that was accidental: I have no opinion on whether or not this is the case as I know too little about the detailed mechanics of Java and the DI Containers available there to have an opinion either for or against.

-Whether or not a single annotation constitutes a problem or not ended up warranting an entire new blog post in response :)
+Whether or not a single annotation constitutes a problem or not ended up warranting an entire new blog post in response :)
2010-01-27 19:49 UTC
@@ -105,19 +105,19 @@

2010-02-01 02:24 UTC

- +
That is actually a different issue, but I agree that if we need to take a dependency on WindsorContainer or any other particular DI Container, we haven't solved the problem.

However, explaining how to deal with that will require another blog post - watch this space the next couple of days.
2010-02-01 05:47 UTC
- +
How do we deal with the issue if we need BillingService deep in the bowels of the application?

Well, take a dependency on BillingService using standard Constructor Injection. Does this mean that we should have to pass an instance of BillingService through all constructors on the way down? No, rather not.

-The answer lies in Aggregate Services. Instead of taking dependencies with the only purpose of passing them on to other dependencies, we can define a more coarse-grained service that encapsulates the desired behavior. This is exactly the kind of scenario where DI Containers excel, because they are able to auto-wire complex object graphs based entirely on their knowledge of which dependencies are required by each concrete type. They can do that when you use Constructor Injection because this knowledge is statically encoded in the type.
+The answer lies in Aggregate Services. Instead of taking dependencies with the only purpose of passing them on to other dependencies, we can define a more coarse-grained service that encapsulates the desired behavior. This is exactly the kind of scenario where DI Containers excel, because they are able to auto-wire complex object graphs based entirely on their knowledge of which dependencies are required by each concrete type. They can do that when you use Constructor Injection because this knowledge is statically encoded in the type.

Then what if you need BillingService both deep in the bowels of the application as well as near the surface? In most cases I would say that this is a design smell that indicates that the granularity of BillingService is poorly defined. A dependency should be either a fine-grained 'leaf' dependency, or an Aggregate Service - not both.
2010-02-03 10:03 UTC
diff --git a/_posts/2010-01-26-IWindsorInstaller.html b/_posts/2010-01-26-IWindsorInstaller.html index eb6f07f58..09ec14d42 100644 --- a/_posts/2010-01-26-IWindsorInstaller.html +++ b/_posts/2010-01-26-IWindsorInstaller.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

Reacting to my previous post, Krzysztof Koźmic was so kind to point out to me that I really should be using an IWindsorInstaller instead of writing the registration code in a static helper method (it did make me cringe a bit).

As it turns out, IWindsorInstaller is not a particularly well-described feature of Castle Windsor, so here's a quick introduction. Fortunately, it is very easy to understand.

The idea is simply to package configuration code in reusable modules (just like the Guice modules from Uncle Bob's post).

Refactoring the bootstrap code from my previous post, I can now move all the container configuration code into a reusable module:

+

Reacting to my previous post, Krzysztof Koźmic was so kind to point out to me that I really should be using an IWindsorInstaller instead of writing the registration code in a static helper method (it did make me cringe a bit).

As it turns out, IWindsorInstaller is not a particularly well-described feature of Castle Windsor, so here's a quick introduction. Fortunately, it is very easy to understand.

The idea is simply to package configuration code in reusable modules (just like the Guice modules from Uncle Bob's post).

Refactoring the bootstrap code from my previous post, I can now move all the container configuration code into a reusable module:

public class BillingContainerInstaller : IWindsorInstaller
 {
     #region IWindsorInstaller Members
@@ -41,7 +41,7 @@ 

2010-01-26 21:35 UTC

- +
I have to admit that I'm not yet entirely up to speed on all the different DI Containers out there, but it's a common feature that several DI Containers have.
2010-01-26 22:04 UTC
@@ -51,14 +51,14 @@

2010-01-27 07:14 UTC

- +
Thanks for pointing that out - did you have this particular blog post in mind?

I'll have to investigate whether that still holds true. If so, I would be inclined to consider it a bug on Windsor's part, but it may be by design, influenced by considerations I simply have yet to realize.
2010-01-27 08:17 UTC
- +
Windsor committer Krzysztof Koźmic was so kind to investigate this, and he left a comment at the blog post to the effect that this was a bug in Windsor. It is now fixed in Windsor 2.1, so having dependencies implement IDisposable should be enough.
2010-01-27 09:02 UTC
@@ -70,7 +70,7 @@

2010-04-04 09:52 UTC

- +
Hi urkurk

Thank you for writing. Unfortunately, I'm not aware of such a sample application. Have you tried asking on the Castle Windsor forum?
@@ -84,7 +84,7 @@

2010-09-22 09:25 UTC

- +
AFAIR the new version of Castle Windsor (2.5) enables you to specify installers in app.config.
2010-09-22 09:47 UTC
@@ -100,7 +100,7 @@

2011-08-11 09:39 UTC

- +
AFAIK AddComponent is a legacy method and will be removed in future versions of Castle Windsor, but that I didn't know when I wrote that specific example :$
2011-08-11 09:44 UTC
@@ -114,10 +114,10 @@

2011-08-12 05:34 UTC

- +
The same advantage as any other DI Container.

-In addition to that, Castle Windsor (and Unity and Spring.NET) also supports interception.
+In addition to that, Castle Windsor (and Unity and Spring.NET) also supports interception.
2011-08-12 06:44 UTC
@@ -135,7 +135,7 @@

2011-09-19 09:43 UTC

- +
I can't recall off the top of my head - may I suggest that you ask on Stack Overflow?
2011-09-19 10:12 UTC
diff --git a/_posts/2010-01-27-AutoFixture1.0.html b/_posts/2010-01-27-AutoFixture1.0.html index 2598cc944..cb54f6441 100644 --- a/_posts/2010-01-27-AutoFixture1.0.html +++ b/_posts/2010-01-27-AutoFixture1.0.html @@ -23,7 +23,7 @@

2010-02-08 10:39 UTC

- +
Thanks for those kind words. They are much appreciated :)
2010-02-08 14:31 UTC
@@ -39,7 +39,7 @@

2010-03-07 02:51 UTC

- +
Currently, the best place to learn about AutoFixture is this very blog. Apart from that, trying it out on some small, but real software project is always always the best way to truly learn a new technology.

If you have specific questions about AutoFixture, the best place to ask them would be in the AutoFixture discussion forum.
diff --git a/_posts/2010-01-27-What'ssodangerousaboutaDIattribute.html b/_posts/2010-01-27-What'ssodangerousaboutaDIattribute.html index 4c2970f66..70236aad5 100644 --- a/_posts/2010-01-27-What'ssodangerousaboutaDIattribute.html +++ b/_posts/2010-01-27-What'ssodangerousaboutaDIattribute.html @@ -71,7 +71,7 @@

2010-02-04 15:09 UTC

- +
I'm no expert in Ninject, but last time I checked, the [Inject] attribute was optional.
2010-02-04 15:41 UTC
@@ -81,10 +81,10 @@

2018-09-03 5:48 UTC

- +

- babakks, thank you for writing. While I'm aware of TypeScript and the overall design philosphy behind it, I've never written any TypeScript code, so I'm not really the right person to ask. As a general observation, though, I recommend Pure DI. Unless you have some rare and exotic requirements, a DI Container is almost never the best choice. DI Containers tend to create more problems than they solve. + babakks, thank you for writing. While I'm aware of TypeScript and the overall design philosphy behind it, I've never written any TypeScript code, so I'm not really the right person to ask. As a general observation, though, I recommend Pure DI. Unless you have some rare and exotic requirements, a DI Container is almost never the best choice. DI Containers tend to create more problems than they solve.

In TypeScript, can't you compose object graphs by simply writing the necessary code? That's what I do in C#, at least... diff --git a/_posts/2010-02-02-RefactoringtoAggregateServices.html b/_posts/2010-02-02-RefactoringtoAggregateServices.html index 606591c75..4b91ee249 100644 --- a/_posts/2010-02-02-RefactoringtoAggregateServices.html +++ b/_posts/2010-02-02-RefactoringtoAggregateServices.html @@ -16,7 +16,7 @@                       IRateExchange exchange,                       IUserContext userContext)

-

In this version, I even added IOrderShipper back in as I described in my earlier post. Surely, five constructor parameters are too many.

+

In this version, I even added IOrderShipper back in as I described in my earlier post. Surely, five constructor parameters are too many.

Constructor Injection makes SRP violations glaringly obvious.

What's not to like? My personal threshold lies somewhere around 3-4 constructor parameters, so whenever I hit three, I start to consider if I could perhaps aggregate some of the dependencies into a new type.

I call such a type a Facade Service. It's closely related to Parameter Objects, but the main difference is that a Parameter Object only moves the parameters to a common root, while a Facade Service hides the aggregate behavior behind a new abstraction. While the Facade Service may start its life as a result of a pure mechanistic refactoring, it often turns out that the extracted behavior represents a Domain Concept in its own right. Congratulations: you've just move a little closer to adhering to the SRP!

@@ -142,12 +142,12 @@

2011-07-29 14:14 UTC

- +
The Reused Abstractions Principle says that we should strive towards having more than one implementation of the same interface, and that we should consider 1:1 interfaces as code smells. That doesn't mean that 1:1 interfaces suddenly have become illegal - only that they warrant more investigation.

Even though I find the RAP extremely useful as a guide it doesn't mean that I ferociously stamp out every occurrence of 1:1 interfaces I find in my code bases. For example, when refactoring to Facade Services, I still think that this refactoring alone improves a code base. If that means that we (perhaps temporarily) end up with a 1:1 interface, I wouldn't be that concerned.

-Still, in this blog post I outline what really is a ranking of composability patterns. More blog posts are going to follow on that topic, but I can already now reveal that the most composable (and thus most reusable) pattern is the Command pattern. Thus, the more Commands you have, the easier it will become to adhere to the RAP.
+Still, in this blog post I outline what really is a ranking of composability patterns. More blog posts are going to follow on that topic, but I can already now reveal that the most composable (and thus most reusable) pattern is the Command pattern. Thus, the more Commands you have, the easier it will become to adhere to the RAP.

I believe that this is the underlying reason why so many people are reporting that CQRS are helping them to effectively deal with complexity.

@@ -198,7 +198,7 @@

2013-02-24 18:55 UTC

- +
You and your team are probably the only people who know what the SiteMap class and its dependencies do, so I can't tell you how to group them better. Could the SiteMap be taking on too many responsibilities?
2013-02-24 20:21 UTC
@@ -214,7 +214,7 @@

2013-02-24 22:45 UTC

- +
If "accessor methods rely on services, but none of them rely on 2 or more services" it sounds like the SiteMap class has poor cohesion, which again is a sign that it should be split into multiple smaller classes.
2013-02-25 07:20 UTC
diff --git a/_posts/2010-02-03-ServiceLocatorisanAnti-Pattern.html b/_posts/2010-02-03-ServiceLocatorisanAnti-Pattern.html index 2047b8231..67b16a949 100644 --- a/_posts/2010-02-03-ServiceLocatorisanAnti-Pattern.html +++ b/_posts/2010-02-03-ServiceLocatorisanAnti-Pattern.html @@ -82,7 +82,7 @@

This is what we get from IntelliSense in Visual Studio:

- image + image

Okay, so the class has a default constructor. That means I can simply create a new instance of it and invoke the Process method right away: @@ -119,7 +119,7 @@

While this use of Service Locator is problematic from the consumer's point of view, what seems easy soon becomes an issue for the maintenance developer as well.

- Let's say that we need to expand the behavior of OrderProcessor to also invoke the IOrderCollector.Collect method. This is easily done, or is it? + Let's say that we need to expand the behavior of OrderProcessor to also invoke the IOrderCollector.Collect method. This is easily done, or is it?

public void Process(Order order)
@@ -265,7 +265,7 @@ 

From a developer perspective, we now get a bit of help from IntelliSense:

- image + image

What does this tell us? Nothing much, really. Okay, so OrderProcessor needs a ServiceLocator - that's a bit more information than before, but it still doesn't tell us which services are needed. The following code compiles, but crashes with the same KeyNotFoundException as before: @@ -292,10 +292,10 @@

You can read more about DI patterns and anti-patterns in my book.

- Update 2014-05-20: Another way to explain the negative aspects of Service Locator is that it violates SOLID. + Update 2014-05-20: Another way to explain the negative aspects of Service Locator is that it violates SOLID.

- Update 2015-10-26: The fundamental problem with Service Locator is that it violates encapsulation. + Update 2015-10-26: The fundamental problem with Service Locator is that it violates encapsulation.

@@ -337,7 +337,7 @@

2010-02-04 10:00 UTC

- +
It's true that frameworks such as ASP.NET, PowerShell and the MMC SDK (but not WCF) are inherently DI-unfriendly because they insist on managing the lifetime of important objects. ASP.NET Page objects are the most well-known example.

In such cases you really have no recourse but to move the Composition Root into each object (e.g. Page) and let your DI Container wire up your dependencies from there. This may look like the Service Locator anti-pattern, but it isn't because you still keep container usage at an absolute minimum. The difference is that the 'absolute minimum' in this case is inside the constructor or Initialize method of each and every object (e.g. Page) created by the framework (e.g. ASP.NET).
@@ -350,12 +350,12 @@

2010-02-04 10:18 UTC

- +
@FZelle: I don't agree that Service Locator is ever appropriate. The standard solution if you need short-lived or dynamically created objects is to use an injected Abstract Factory.
2010-02-04 10:32 UTC
- +
@Will: Autofac is just one among several DI Containers. I'm not yet that familiar with it, but if Delegate Factories are comparable to Windsor's Typed Factory Facility, it sounds like a good approach. In general Constructor Injection is preferrable, but there are many cases where you need a short-lived object.

This is where Abstract Factories bridge the gap. What is better about an Abstract Factory compared to a Service Locator is that it is strongly typed: you can't just ask it for any dependency, but only for instances of specific types.
@@ -367,7 +367,7 @@

2010-02-05 04:03 UTC

- +
Huy Nguyen

Thank you for your comment.
@@ -399,7 +399,7 @@

2010-02-06 21:19 UTC

- +
Arnis L.

Thank you for writing.
@@ -421,7 +421,7 @@

2010-02-06 23:11 UTC

- +
To be fair, I must admit that I'm puposefully being rigid and unrelenting in my tone to get the point across :)

Here's an interesting confession: There are a few places in Safewhere's production code where we call Resolve() pretty deep within the bowels of the application. You could well argue that we apply Service Locator there. The point, however, is that I still don't consider those few applications valid, but rather as failures on my part to correctly model our abstractions. One day, I still hope to get them right so I can get rid of those last pieces, and I actually managed to remove one dirty part of that particular API just this week.
@@ -438,7 +438,7 @@

2010-02-08 09:27 UTC

- +
@FZelle: The Abstract Factory needs no dependencies since it's an abstraction (interface/abstract base class).

Concrete implementations of an Abstract Factory may very well need specific dependencies, which it can request via Constructor Injection - just like any other service.
@@ -484,7 +484,7 @@

2010-07-21 23:54 UTC

- +
What do you mean by running "inside or outside of a container environment"? If you design your software appropriately, the presence of a DI container has no impact on the overall dependency usage. A DI container should resolve the appropriate object graph and get out of the way. This is what I call the Hollywood Principle for DI Containers: Don't call the container - it will call you.

In my opinion the SOA discussion is completely orthogonal to the discussion about the Service Locator (anti-)pattern. We shouldn't be misled by the similarity of names. The services located by a Service Locator are object services that may or may not encapsulate or represent an external resource. That external resource may be a web service, but could be something entirely different. When we discuss the Service Locator (anti-)pattern, we discuss it in the context of object-oriented design. Whether or not the underlying implementation is a web service is irrelevant at that level.
@@ -559,8 +559,8 @@

2011-05-28 01:03 UTC

- -
With DI, all "new" keywords are being pushed to the entry point of the application. This is what is called the Composition Root. In this example I use Poor Man's DI towards the end of the post.
+ +
With DI, all "new" keywords are being pushed to the entry point of the application. This is what is called the Composition Root. In this example I use Poor Man's DI towards the end of the post.

FWIW the first nine chapters of my book discuss DI mainly in the context of Poor Man's DI (that is, without containers).
2011-05-28 21:20 UTC
@@ -576,8 +576,8 @@

2011-06-01 15:35 UTC

- -
DI doesn't go against encapsulation, which is one of the most misunderstood concepts in OOP.
+ +
DI doesn't go against encapsulation, which is one of the most misunderstood concepts in OOP.
2011-06-01 18:49 UTC
@@ -605,7 +605,7 @@

2011-07-13 08:03 UTC

- +
Yes, the software hosting this blog is crap, and migration is on my to-do list. The error usually has something to do with the use of angle brackets.

Sorry about the inconvenience.
@@ -623,8 +623,8 @@

2011-10-05 00:20 UTC

@@ -751,7 +751,7 @@

2012-02-20 16:23 UTC

- +
In my opinion, there's no such thing as a "DI-enabled Service Locator". Service Locator and DI are two mutually exclusive concepts.
2012-02-22 15:56 UTC
@@ -790,12 +790,12 @@

2012-05-10 22:09 UTC

- +
Yes, logging is a cross-cutting concern, which is why I'd strongly recommend not injecting it all. AOP is much preferred. It addresses fine-grained instrumentation too, with the caveat that (as you imply) you can only log at method boundaries. However, before you dismiss this as a solution, consider this: why is that not enough? If you need to log from within a single method, it most like means that this method is too big.
2012-05-11 03:55 UTC
- +
BTW, even if you're not convinced by the arguments above, or if you have legacy code with long methods, Service Locator is not a good solution. If you don't like to inject an Abstract Factory, you could instead use an Ambient Context. That's not my first choice, but still way better than a Service Locator.
2012-05-11 04:04 UTC
@@ -808,7 +808,7 @@

2012-05-14 18:24 UTC

- +
Which post?

Did you read the Ambient Context pattern description in my book?
@@ -830,7 +830,7 @@

2012-05-14 19:28 UTC

- +
Oh, that blog post... I'd completely forgotten about that one.

I agree that injecting an ILoggerFactory could be considered as parameter pollution of the constructor, but remember that (IMO) we are only talking about this as a solution when dealing with legacy code. Properly factored code should have methods that are short enough that a Decorator or Around Advice should be more than enough for logging and instrumentation purposes.
@@ -854,7 +854,7 @@

2012-07-28 10:13 UTC

- +
That's section 7.5, but to be fair, it's only 6 pages, so it's not a major part of the book in any way.
2012-07-28 10:24 UTC
@@ -903,7 +903,7 @@

2012-11-26 09:54 UTC

- +
It's no so much the SRP as it's the ISP which is in play here. I'd strongly recommend building a Role Interface for each query or command instead of the sort of Header Interface you seem to prefer.
2012-11-26 10:01 UTC
@@ -1024,7 +1024,7 @@

2013-01-24 08:19 UTC

- +
Mansoor, what you describe is already covered in the original post under the heading Abstract Service Locator.
2013-01-27 10:55 UTC
@@ -1052,16 +1052,16 @@

2013-01-30 20:10 UTC

- +
Mansoor, in which way does your proposed amendment of Service Locator change the feedback mechanism? While you propose a more explicit API for querying a Service Locator, it doesn't change the fundamental situation. Even without an explicit query mechanism, you could wrap your Service Locator calls in a try/catch block or check for null return values... so even without an explicit query mechanism, you can get the exact same information. Now you have that information at run-time. What will you do with it?

-One major problem with Service Locator is that it doesn't provide feedback until at run-time. It's much better if we can get feedback already at compile time, and that's possible with Dependency Injection. It 'reports' on its requirements at compile time. It also enables tools (such as DI Containers) to walk up to the type information and start querying about its dependencies.
+One major problem with Service Locator is that it doesn't provide feedback until at run-time. It's much better if we can get feedback already at compile time, and that's possible with Dependency Injection. It 'reports' on its requirements at compile time. It also enables tools (such as DI Containers) to walk up to the type information and start querying about its dependencies.

The proposed fix for Service Locator doesn't change any of that. What benefits does it provide?
2013-02-04 15:38 UTC
- +
Buddy, I think my opinion about passing the container around is sufficiently covered in the subsection of this post entitled Variation: Abstract Service Locator. That's exactly what it describes :)
2013-02-04 15:43 UTC
@@ -1144,7 +1144,7 @@

2013-02-15 08:40 UTC

- +
Buddy, thanks for clarifying. While I've never looked at Prism, I think I understand how it works from what you've described. It's not that uncommon a 'pattern', but I can't particularly endorse it, as I think that it tightly couples a framework to a particular container (in this case Unity), and in any case there are better, less invasive alternatives.

The way MEF works comes to mind, but you can do the same as MEF does with convention-based wiring with any DI Container worth its salt. However, I think I need to do a write-up of this one day...
@@ -1163,13 +1163,13 @@

2015-10-07 14:54 UTC

- +

- Danyil, thank you for writing. Context IoC, as described in that article, isn't service location, because each context injected is only a limited, well-known interface. A Service Locator, on the other hand, exposes an infinite set of services. + Danyil, thank you for writing. Context IoC, as described in that article, isn't service location, because each context injected is only a limited, well-known interface. A Service Locator, on the other hand, exposes an infinite set of services.

- That said, how does Context IoC solve anything that Pure DI doesn't solve in a simpler way? + That said, how does Context IoC solve anything that Pure DI doesn't solve in a simpler way?

2015-10-07 15:37 UTC
@@ -1183,7 +1183,7 @@

2015-10-07 16:55 UTC

- +

Danyil, thank you for writing. That Pure DI link may not give you the most succinct picture of what I had in mind. Using the blue/red example from the Context IoC article, you can rewrite MyService much simpler using Constructor Injection: @@ -1225,7 +1225,7 @@

}

- You can compose desired object graphs in your Composition Root: + You can compose desired object graphs in your Composition Root:

public ISomeService Main()
diff --git a/_posts/2010-03-17-AutoFixtureFreeze.html b/_posts/2010-03-17-AutoFixtureFreeze.html
index 6bedb33aa..30bca52ab 100644
--- a/_posts/2010-03-17-AutoFixtureFreeze.html
+++ b/_posts/2010-03-17-AutoFixtureFreeze.html
@@ -7,7 +7,7 @@
 {% include JB/setup %}
 
 
-

One of the important points of AutoFixture is to hide away all the boring details that you don't care about when you are writing a unit test, but that the compiler seems to insist upon. One of these details is how you create a new instance of your SUT.

Every time you create an instance of your SUT using its constructor, you make it more difficult to refactor that constructor. This is particularly true when it comes to Constructor Injection because you often need to define a Test Double in each unit test, but even for primitive types, it's more maintenance-friendly to use a SUT Factory.

AutoFixture is a SUT Factory, so we can use it to create instances of our SUTs. However, how do we correlate constructor parameters with variables in the test when we will not use the constructor directly?

This is where the Freeze method comes in handy, but let's first examine how to do it with the core API methods CreateAnonymous and Register.

Imagine that we want to write a unit test for a Pizza class that takes a name in its constructor and exposes that name as a property. We can write this test like this:

+

One of the important points of AutoFixture is to hide away all the boring details that you don't care about when you are writing a unit test, but that the compiler seems to insist upon. One of these details is how you create a new instance of your SUT.

Every time you create an instance of your SUT using its constructor, you make it more difficult to refactor that constructor. This is particularly true when it comes to Constructor Injection because you often need to define a Test Double in each unit test, but even for primitive types, it's more maintenance-friendly to use a SUT Factory.

AutoFixture is a SUT Factory, so we can use it to create instances of our SUTs. However, how do we correlate constructor parameters with variables in the test when we will not use the constructor directly?

This is where the Freeze method comes in handy, but let's first examine how to do it with the core API methods CreateAnonymous and Register.

Imagine that we want to write a unit test for a Pizza class that takes a name in its constructor and exposes that name as a property. We can write this test like this:

[TestMethod]
 public void NameIsCorrect()
@@ -95,7 +95,7 @@ 

2012-12-05 22:51 UTC

- +
The CreateAnonymous method reflects over the constructor to figure out which arguments are required. If you add a decimal to the constructor, it's just going to pick that up and supply an anonymous value of decimal. No update of the test is required.

Try it out :)
@@ -121,10 +121,10 @@

- +

- WesM, thank you for writing. Perhaps you'll find this article helpful. + WesM, thank you for writing. Perhaps you'll find this article helpful.

2014-03-18 07:33 UTC
diff --git a/_posts/2010-03-26-Moreaboutfrozenpizza.html b/_posts/2010-03-26-Moreaboutfrozenpizza.html index a9b620b5b..0a12bab24 100644 --- a/_posts/2010-03-26-Moreaboutfrozenpizza.html +++ b/_posts/2010-03-26-Moreaboutfrozenpizza.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

In my previous blog post, I introduced AutoFixture's Freeze feature, but the example didn't fully demonstrate the power of the concept. In this blog post, we will turn up the heat on the frozen pizza a notch.

The following unit test exercises the BasketPresenter class, which is simply a wrapper around a Basket instance (we're doing a pizza online shop, if you were wondering). In true TDD style, I'll start with the unit test, but I'll post the BasketPresenter class later for reference.

+

In my previous blog post, I introduced AutoFixture's Freeze feature, but the example didn't fully demonstrate the power of the concept. In this blog post, we will turn up the heat on the frozen pizza a notch.

The following unit test exercises the BasketPresenter class, which is simply a wrapper around a Basket instance (we're doing a pizza online shop, if you were wondering). In true TDD style, I'll start with the unit test, but I'll post the BasketPresenter class later for reference.

[TestMethod]
 public void AddWillPipeMapCorrectly()
@@ -62,8 +62,8 @@
     }
 }

-

If you are wondering about why this is interesting at all, and why we don't just pass in a Basket through the BasketPresenter's constructor, it's because we are using AutoFixture as a SUT Factory. We want to be able to refactor BasketPresenter (and in this case particularly its constructor) without breaking a lot of existing tests. The level of indirection provided by AutoFixture gives us just that ability because we never directly invoke the constructor.

-

Coming up: more fun with the Freeze concept!

+

If you are wondering about why this is interesting at all, and why we don't just pass in a Basket through the BasketPresenter's constructor, it's because we are using AutoFixture as a SUT Factory. We want to be able to refactor BasketPresenter (and in this case particularly its constructor) without breaking a lot of existing tests. The level of indirection provided by AutoFixture gives us just that ability because we never directly invoke the constructor.

+

Coming up: more fun with the Freeze concept!

@@ -80,7 +80,7 @@

2012-09-04 15:26 UTC

- +
I have an upcoming article on how to decouple tests from constructor signatures, so stay tuned.
2012-09-04 19:05 UTC
diff --git a/_posts/2010-03-27-Freezingmocks.html b/_posts/2010-03-27-Freezingmocks.html index 7c78f7759..a2cd869ed 100644 --- a/_posts/2010-03-27-Freezingmocks.html +++ b/_posts/2010-03-27-Freezingmocks.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

My previous post about AutoFixture's Freeze functionality included this little piece of code that I didn't discuss:

+

My previous post about AutoFixture's Freeze functionality included this little piece of code that I didn't discuss:

var mapMock = new Mock<IPizzaMap>();
 fixture.Register(mapMock.Object);
@@ -64,7 +64,7 @@

2010-03-27 20:24 UTC

- +
Wim, thank you for writing.

Setting up your Test Fixture by populating fields on the test class is a common approach. However, I prefer not to do this, as it binds us very hard to the Testcase Class per Fixture pattern. Although it may make sense in some cases, it requires us to add new test classes every time we need to vary the Test Fixture even the slightest, or we will end up with a General Fixture, which again leads to Obscure Tests.
@@ -96,7 +96,7 @@

- +

Wes, thank you for writing. You are indeed correct that this particular overload of the Register method no longer exists, and Inject is the correct method to use. See this Stack Overflow answer for more details. @@ -109,7 +109,7 @@

Tommy Vernieri

- This article is out of date. Readers wishing to use AutoFixture with Moq should read AutoFixture as an auto-mocking container. + This article is out of date. Readers wishing to use AutoFixture with Moq should read AutoFixture as an auto-mocking container.

2018-08-27 02:21 UTC
diff --git a/_posts/2010-04-06-MappingtypeswithAutoFixture.html b/_posts/2010-04-06-MappingtypeswithAutoFixture.html index 3072bfacf..239b8d84a 100644 --- a/_posts/2010-04-06-MappingtypeswithAutoFixture.html +++ b/_posts/2010-04-06-MappingtypeswithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

In my previous posts I demonstrated interaction-based unit tests that verify that a pizza is correctly being added to a shopping basket. An alternative is a state-based test where we examine the contents of the shopping basket after exercising the SUT. Here's an initial attempt:

+

In my previous posts I demonstrated interaction-based unit tests that verify that a pizza is correctly being added to a shopping basket. An alternative is a state-based test where we examine the contents of the shopping basket after exercising the SUT. Here's an initial attempt:

[TestMethod]
 public void AddWillAddToBasket()
@@ -30,7 +30,7 @@
     // Teardown
 }

-

In this case the assertion examines the Pizze collection (you did know that the plural of pizza is pizze, right?) of the frozen Basket to verify that it contains the added pizza.

+

In this case the assertion examines the Pizze collection (you did know that the plural of pizza is pizze, right?) of the frozen Basket to verify that it contains the added pizza.

The tricky part is that the Pizze property is a collection of Pizza instances, and not PizzaPresenter instances. The injected IPizzaMap instance is responsible for mapping from PizzaPresenter to Pizza, but since we are rewriting this as a state-based test, I thought it would also be interesting to write the test without using Moq. Instead, we can use the real implementation of IPizzaMap, but this means that we must instruct AutoFixture to map from the abstract IPizzaMap to the concrete PizzaMap.

We see that happening in this line of code:

diff --git a/_posts/2010-04-07-DependencyInjectionisLooseCoupling.html b/_posts/2010-04-07-DependencyInjectionisLooseCoupling.html index bfba3604a..1f91cf9d0 100644 --- a/_posts/2010-04-07-DependencyInjectionisLooseCoupling.html +++ b/_posts/2010-04-07-DependencyInjectionisLooseCoupling.html @@ -142,7 +142,7 @@

Once again, we modified neither SqlProductRepository nor CachingProductRepository to introduce this new feature. We can implement security and auditing features by following the same principle.

To me, this is what loose coupling (and DI) is all about. That we can also replace data access components and unit test using dynamic mocks are very fortunate side effects, but the loose coupling is valuable in itself because it enables us to write more maintainable code.

-

We don't even need a DI Container to wire up all these repositories (although it sure would could be helpful). Here's how we can do it with Pure DI:

+

We don't even need a DI Container to wire up all these repositories (although it sure would could be helpful). Here's how we can do it with Pure DI:

IProductRepository repository =
     new PerformanceMeasuringProductRepository(
@@ -169,7 +169,7 @@ 

2010-04-08 11:27 UTC

- +
Thanks :)

I'm not sure I understand your comment regarding Service Locator. It is an anti-pattern :)
@@ -195,7 +195,7 @@

2010-04-26 21:20 UTC

- +
He he, no, normally I don't, but sometimes when writing sample code I like taking advantage of the fact that C# is based on Unicode. Somewhere here, I also have a sample that uses Danish characters (æ, ø or å), but I can't remember which post it was :)
2010-04-26 21:30 UTC
@@ -206,7 +206,7 @@

2010-10-08 22:17 UTC

- +
Yes, you are right. Perhaps it will just cache the query - it actually depends on what the concrete implementation is. It may be an array or List<T>, in which case there is no issue.

However, we could always specialize the implementation of the cache so that if T was IEnumerable, we'd invoke ToList() on it before caching the result.
@@ -226,7 +226,7 @@

2012-01-15 19:04 UTC

- +
Thanks, Tom. No new book scheduled right now :)
2012-01-15 19:33 UTC
@@ -240,7 +240,7 @@

2012-09-12 11:46 UTC

- +
If you have 15 methods and only one should be cached, you can still cache the one method with a Decorator. The remaining 14 methods on that Decorator can be implemented as pure delegation.

However, if you have this scenario, could it be that the interface violates the Interface Segregation Principle?
diff --git a/_posts/2010-04-26-WhyImmigratingfromMSTesttoxUnit.net.html b/_posts/2010-04-26-WhyImmigratingfromMSTesttoxUnit.net.html index 5710e315d..39fb45bf7 100644 --- a/_posts/2010-04-26-WhyImmigratingfromMSTesttoxUnit.net.html +++ b/_posts/2010-04-26-WhyImmigratingfromMSTesttoxUnit.net.html @@ -28,7 +28,7 @@

2010-04-26 13:59 UTC

- +
Personally, I also use Hg for SCM.

In Safewhere, we are currenlty trying out AgileZen for work item tracking. For AutoFixture, I just use the tools provided with CodePlex.
@@ -40,7 +40,7 @@

2010-04-26 21:15 UTC

- +
There are two main reasons that I prefer xUnit.net over NUnit, but both may be due to ignorance about NUnit on my part. The last time I did serious work with NUnit must have been back in 2005.

One reason is that xUnit.net has a pretty good extensibility story, and as I do have some plans in that direction, that's a pretty big issue for me. Last time I checked, the extensibility story for NUnit didn't match xUnit.net.
@@ -61,7 +61,7 @@

2010-06-19 16:46 UTC

- +
I'm not sure exactly to which MSTest code you are referring, but in general I don't plan to change the existing MSTest code I've posted here on the blog. However, new tests are likely to appear with xUnit.net. In any case, when it comes to unit testing examples I don't think the differences are all that important. In most cases it's just a question of differently named attributes and slightly different Assert syntax...
2010-06-20 06:39 UTC
diff --git a/_posts/2010-05-18-SneakviewatCastlesWCFFacility.html b/_posts/2010-05-18-SneakviewatCastlesWCFFacility.html index 93f59944f..b23ebc56f 100644 --- a/_posts/2010-05-18-SneakviewatCastlesWCFFacility.html +++ b/_posts/2010-05-18-SneakviewatCastlesWCFFacility.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

One of Castle Windsor's facilities addresses wiring up of WCF services. So far, the sparse documentation for the WCF Facility seems to indicate that you have to configure your container in a global.asax. That's not much to my liking. First of all, it reeks of ASP.NET, and secondly, it's not going to work if you expose WCF over protocols other than HTTP.

However, now that we know that a custom ServiceHostFactory is effectively a Singleton, a much better alternative is to derive from the WCF Facility's DefaultServiceHost class:

+

One of Castle Windsor's facilities addresses wiring up of WCF services. So far, the sparse documentation for the WCF Facility seems to indicate that you have to configure your container in a global.asax. That's not much to my liking. First of all, it reeks of ASP.NET, and secondly, it's not going to work if you expose WCF over protocols other than HTTP.

However, now that we know that a custom ServiceHostFactory is effectively a Singleton, a much better alternative is to derive from the WCF Facility's DefaultServiceHost class:

public class FooServiceHostFactory : 
     DefaultServiceHostFactory
@@ -85,7 +85,7 @@ 

2010-05-18 08:24 UTC

- +
That would definitely address most cases, including the one I'm currently looking at, although I'm not sure I understand your last sentence. Did you mean that I can implement a custom IWindsorInstaller? If so, that makes a lot of sense.

For the edge cases where adding an Installer isn't enough, I'd still prefer a Factory Method hook in DefaultServiceHostFactory, but being able to specify an Installer in web.config will likely address 90 percent (or more) of scenarios.
@@ -107,7 +107,7 @@

2010-05-18 08:47 UTC

- +
Thanks for your explanation. I think that sounds very promising. As far as I can tell, this is still in the future, right? I don't see any GetInstallers() on DefaultServiceHostFactory right now (based on the code I downloaded and compiled last week).

Don't get me wrong on the Factory Method thing. I don't expect to need it often (if at all), but I just think it would be a good OCP thing to do... Off the top of my head, I can't remember whether there are things you can do to a container that you can't do from an Installer. Maybe there aren't...
diff --git a/_posts/2010-06-29-IntroducingAutoFixtureLikeness.html b/_posts/2010-06-29-IntroducingAutoFixtureLikeness.html index e63d10bb5..bbaf9a69e 100644 --- a/_posts/2010-06-29-IntroducingAutoFixtureLikeness.html +++ b/_posts/2010-06-29-IntroducingAutoFixtureLikeness.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

The last time I presented a sample of an AutoFixture-based unit test, I purposely glossed over the state-based verification that asserted that the resulting state of the basket variable was that the appropriate Pizza was added:

+

The last time I presented a sample of an AutoFixture-based unit test, I purposely glossed over the state-based verification that asserted that the resulting state of the basket variable was that the appropriate Pizza was added:

Assert.IsTrue(basket.Pizze.Any(p =>
     p.Name == pizza.Name), "Basket has added pizza.");
@@ -75,7 +75,7 @@

Comments

- +

David, if you want to get more detailed feedback on which properties don't match, you can use expected.ShouldEqual(actual); diff --git a/_posts/2010-07-12-DomainObjectsandIDataErrorInfo.html b/_posts/2010-07-12-DomainObjectsandIDataErrorInfo.html index b102a60c9..f26b8e2a1 100644 --- a/_posts/2010-07-12-DomainObjectsandIDataErrorInfo.html +++ b/_posts/2010-07-12-DomainObjectsandIDataErrorInfo.html @@ -7,7 +7,7 @@ {% include JB/setup %}

-

Occasionally I get a question about whether it is reasonable or advisable to let domain objects implement IDataErrorInfo. In summary, my answer is that it's not so much a question about whether it's a leaky abstraction or not, but rather whether it makes sense at all. To me, it doesn't.

Let us first consider the essence of the concept underlying IDataErrorInfo: It provides information about the validity of an object. More specifically, it provides error information when an object is in an invalid state.

This is really the crux of the matter. Domain Objects should be designed so that they cannot be put into invalid states. They should guarantee their invariants.

Let us return to the good old DanishPhoneNumber example. Instead of accepting or representing a Danish phone number as a string or integer, we model it as a Value Object that encapsulates the appropriate domain logic.

More specifically, the class' constructor guarantees that you can't create an invalid instance:

+

Occasionally I get a question about whether it is reasonable or advisable to let domain objects implement IDataErrorInfo. In summary, my answer is that it's not so much a question about whether it's a leaky abstraction or not, but rather whether it makes sense at all. To me, it doesn't.

Let us first consider the essence of the concept underlying IDataErrorInfo: It provides information about the validity of an object. More specifically, it provides error information when an object is in an invalid state.

This is really the crux of the matter. Domain Objects should be designed so that they cannot be put into invalid states. They should guarantee their invariants.

Let us return to the good old DanishPhoneNumber example. Instead of accepting or representing a Danish phone number as a string or integer, we model it as a Value Object that encapsulates the appropriate domain logic.

More specifically, the class' constructor guarantees that you can't create an invalid instance:

private readonly int number;
  
@@ -70,7 +70,7 @@ 

2010-07-13 13:44 UTC

- +
I would prefer to disagree :)

We must keep in mind that we are not modeling the real world, but rather the business logic that addresses the real world. In your example, that would be represented by a proper domain object that models that a shipment is still in the planning stage. Let's call this object PlannedShipment.
@@ -86,7 +86,7 @@

2010-07-13 20:08 UTC

- +
I never said that all Domain Objects should be immutable - I'm using the terminology from Domain-Driven Design that distinguishes between Entities and Value Objects.

A Value Object benefits very much from being immutable, so I always design them that way, but that doesn't mean that I make Entities immutable as well. I usually don't, although I'm sometimes toying with that idea.
@@ -103,7 +103,7 @@

2010-07-15 20:28 UTC

- +
You'll have to define the range check somewhere. If you put it in an external class, I could repeat your argument there: "your DanishPhoneNumberRangeValidator isn't open for extensibility." Value Objects are intrinsically rather atomic, and not particularly composable, in scope.

However, consumers of those Value Objects need not be. While I didn't show it, DanishPhoneNumber could implement IPhoneNumber and all clients consume the interface. That would make DanishPhoneNumber a leaf of a composition while still keeping the architecture open for extensibility.
@@ -121,7 +121,7 @@

2010-07-20 08:51 UTC

- +
I think we can often construct examples where the opposite of our current stance makes sense. Still, I like all rules like the above because they should first and foremost make us stop and think about what we are doing. Once we've done that, we can forge ahead knowing that we made a conscious decision - no matter what we chose.

To me, internal consistency and the SRP is so important that I would feel more comfortable having IDataErrorInfo outside of domain objects, but there are no absolutes :)
diff --git a/_posts/2010-08-09-AutoFixture2.0beta1.html b/_posts/2010-08-09-AutoFixture2.0beta1.html index d2481def1..e2ae6af5e 100644 --- a/_posts/2010-08-09-AutoFixture2.0beta1.html +++ b/_posts/2010-08-09-AutoFixture2.0beta1.html @@ -80,10 +80,10 @@

2010-08-13 19:00 UTC

- +
That's a reasonable question. The short answer is provided by AutoFixture's tag line: Write maintainable unit tests, faster.

-For a more elaborate answer, you may want to read this, this and this. Also: stay tuned for more content.
+For a more elaborate answer, you may want to read this, this and this. Also: stay tuned for more content.
2010-08-15 19:32 UTC
diff --git a/_posts/2010-08-19-AutoFixtureasanauto-mockingcontainer.html b/_posts/2010-08-19-AutoFixtureasanauto-mockingcontainer.html index 737f9e008..44405571d 100644 --- a/_posts/2010-08-19-AutoFixtureasanauto-mockingcontainer.html +++ b/_posts/2010-08-19-AutoFixtureasanauto-mockingcontainer.html @@ -7,15 +7,15 @@ {% include JB/setup %}
-

The new internal architecture of AutoFixture 2.0 enables some interesting features. One of these is that it becomes easy to extend AutoFixture to become an auto-mocking container.

Since I personally use Moq, the AutoFixture 2.0 .zip file includes a new assembly called Ploeh.AutoFixture.AutoMoq that includes an auto-mocking extension that uses Moq for Test Doubles.

Please note that AutoFixture in itself has no dependency on Moq. If you don't want to use Moq, you can just ignore the Ploeh.AutoFixture.AutoMoq assembly.

Auto-mocking with AutoFixture does not have to use Moq. Although it only ships with Moq support, it is possible to write an auto-mocking extension for a different dynamic mock library.

To use it, you must first add a reference to Ploeh.AutoFixture.AutoMoq. You can now create your Fixture instance like this:

+

The new internal architecture of AutoFixture 2.0 enables some interesting features. One of these is that it becomes easy to extend AutoFixture to become an auto-mocking container.

Since I personally use Moq, the AutoFixture 2.0 .zip file includes a new assembly called Ploeh.AutoFixture.AutoMoq that includes an auto-mocking extension that uses Moq for Test Doubles.

Please note that AutoFixture in itself has no dependency on Moq. If you don't want to use Moq, you can just ignore the Ploeh.AutoFixture.AutoMoq assembly.

Auto-mocking with AutoFixture does not have to use Moq. Although it only ships with Moq support, it is possible to write an auto-mocking extension for a different dynamic mock library.

To use it, you must first add a reference to Ploeh.AutoFixture.AutoMoq. You can now create your Fixture instance like this:

var fixture = new Fixture()
     .Customize(new AutoMoqCustomization());

What this does is that it adds a fallback mechanism to the fixture. If a type falls through the normal engine without being handled, the auto-mocking extension will check whether it is a request for an interface or abstract class. If this is so, it will relay the request to a request for a Mock of the same type.

A different part of the extension handles requests for Mocks, which ensures that the Mock will be created and returned.

-

Splitting up auto-mocking into a relay and a creational strategy for Mock objects proper also means that we can directly request a Mock if we would like that. Even better, we can use the built-in Freeze support to freeze a Mock, and it will also automatically freeze the auto-mocked instance as well (because the relay will ask for a Mock that turns out to be frozen).

-

Returning to the original frozen pizza example, we can now rewrite it like this:

+

Splitting up auto-mocking into a relay and a creational strategy for Mock objects proper also means that we can directly request a Mock if we would like that. Even better, we can use the built-in Freeze support to freeze a Mock, and it will also automatically freeze the auto-mocked instance as well (because the relay will ask for a Mock that turns out to be frozen).

+

Returning to the original frozen pizza example, we can now rewrite it like this:

[Fact]
 public void AddWillPipeMapCorrectly()
@@ -38,7 +38,7 @@
 }

Notice that we can simply freeze Mock<IPizzaMap> which also automatically freeze the IPizzaMap instance as well. When we later create the SUT by requesting an anonymous BasketPresenter, IPizzaMap is already frozen in the fixture, so the correct instance will be injected into the SUT.

-

This is similar to the behavior of the custom FreezeMoq extension method I previously described, but now this feature is baked in.

+

This is similar to the behavior of the custom FreezeMoq extension method I previously described, but now this feature is baked in.

@@ -61,7 +61,7 @@

2010-09-09 10:34 UTC

- +
Hi David

Thanks for writing.
@@ -115,7 +115,7 @@

2011-09-08 09:57 UTC

- +
Yes, this is mostly intentional - mostly because even if AutoFixture would attempt to assign data to properties, you wouldn't get any result out of it. As an illustration, try using Moq without AutoFixture to create a new instance of IComplexParent and assign a property to it. It's not going to remember the property value!

This is, in my opinion, the correct design choice made by the Moq designers: an interface specifies only the shape of members - not behavior.
@@ -148,7 +148,7 @@

2011-09-08 14:19 UTC

- +
Yes, I agree that consistency is desirable :)

As I mentioned, it's not something I've ever given a great deal of thought because I almost never define properties on interfaces, but I agree that it might be more consistent, so I've created a work item for it - you could go and vote for it if you'd like :)
diff --git a/_posts/2010-08-25-ChangingthebehaviorofAutoFixtureauto-mockingwithMoq.html b/_posts/2010-08-25-ChangingthebehaviorofAutoFixtureauto-mockingwithMoq.html index 3ef6f28e0..881bbe424 100644 --- a/_posts/2010-08-25-ChangingthebehaviorofAutoFixtureauto-mockingwithMoq.html +++ b/_posts/2010-08-25-ChangingthebehaviorofAutoFixtureauto-mockingwithMoq.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

One of my Twitter followers who appears to be using AutoFixture recently asked me this:

So with the AutoMoqCustomization I feel like I should get Mocks with concrete types too (except the sut) - why am I wrong?

AutoFixture's extention for auto-mocking with Moq was never meant as a general modification of behavior. Customizations extend the behavior of AutoFixture; they don't change it. There's a subtle difference. In any case, the auto-mocking customization was always meant as a fallback mechanism that would create Mocks for interfaces and abstract types because AutoFixture doesn't know how to deal with those.

Apparently @ZeroBugBounce also want concrete classes to be issued as Mock instances, which is not quite the same thing; AutoFixture already has a strategy for that (it's called ConstructorInvoker).

Nevertheless I decided to spike a little on this to see if I could get it working. It turns out I needed to open some of the auto-mocking classes a bit for extensibility (always a good thing), so the following doesn't work with AutoFixture 2.0 beta 1, but will probably work with the RTW. Also please not that I'm reporting on a spike; I haven't thoroughly tested all edge cases.

That said, the first thing we need to do is to remove AutoFixture's default ConstructorInvoker that invokes the constructor of concrete classes. This is possible with this constructor overload:

+

One of my Twitter followers who appears to be using AutoFixture recently asked me this:

So with the AutoMoqCustomization I feel like I should get Mocks with concrete types too (except the sut) - why am I wrong?

AutoFixture's extention for auto-mocking with Moq was never meant as a general modification of behavior. Customizations extend the behavior of AutoFixture; they don't change it. There's a subtle difference. In any case, the auto-mocking customization was always meant as a fallback mechanism that would create Mocks for interfaces and abstract types because AutoFixture doesn't know how to deal with those.

Apparently @ZeroBugBounce also want concrete classes to be issued as Mock instances, which is not quite the same thing; AutoFixture already has a strategy for that (it's called ConstructorInvoker).

Nevertheless I decided to spike a little on this to see if I could get it working. It turns out I needed to open some of the auto-mocking classes a bit for extensibility (always a good thing), so the following doesn't work with AutoFixture 2.0 beta 1, but will probably work with the RTW. Also please not that I'm reporting on a spike; I haven't thoroughly tested all edge cases.

That said, the first thing we need to do is to remove AutoFixture's default ConstructorInvoker that invokes the constructor of concrete classes. This is possible with this constructor overload:

public Fixture(DefaultRelays engineParts)

diff --git a/_posts/2010-08-30-Dontcallthecontainer;itllcallyou.html b/_posts/2010-08-30-Dontcallthecontainer;itllcallyou.html index 951ff0cbd..7eaf2784c 100644 --- a/_posts/2010-08-30-Dontcallthecontainer;itllcallyou.html +++ b/_posts/2010-08-30-Dontcallthecontainer;itllcallyou.html @@ -8,7 +8,7 @@ {% include JB/setup %}
-

There still seems to be some confusion about what is Dependency Injection (DI) and what is a DI Container, so in this post I will try to sort it out as explicitly as possible.

DI is a set of principles and patterns that enable loose coupling.

That's it; nothing else. Remember that old quote from p. 18 of Design Patterns?

Program to an interface; not an implementation.

This is the concern that DI addresses. The most useful DI pattern is Constructor Injection where we inject dependencies into consumers via their constructors. No container is required to do this.

The easiest way to build a DI-friendly application is to just use Constructor Injection all the way. Conversely, an application does not automatically become loosely coupled when we use a DI Container. Every time application code queries a container we have an instance of the Service Locator anti-pattern. The corollary leads to this variation of the Hollywood Principle:

Don't call the container; it'll call you.

A DI Container is a fantastic tool. It's like a (motorized) mixer: you can whip cream by hand, but it's easier with a mixer. On the other hand, without the cream the mixer is nothing. The same is true for a DI Container: to really be valuable, your code must employ Constructor Injection so that the container can auto-wire dependencies.

A well-designed application adheres to the Hollywood Principle for DI Containers: it doesn't call the container. On the other hand, we can use the container to compose the application - or we can do it the hard way; this is called Poor Man's DI. Here's an example that uses Poor Man's DI to compose a complete application graph in a console application:

+

There still seems to be some confusion about what is Dependency Injection (DI) and what is a DI Container, so in this post I will try to sort it out as explicitly as possible.

DI is a set of principles and patterns that enable loose coupling.

That's it; nothing else. Remember that old quote from p. 18 of Design Patterns?

Program to an interface; not an implementation.

This is the concern that DI addresses. The most useful DI pattern is Constructor Injection where we inject dependencies into consumers via their constructors. No container is required to do this.

The easiest way to build a DI-friendly application is to just use Constructor Injection all the way. Conversely, an application does not automatically become loosely coupled when we use a DI Container. Every time application code queries a container we have an instance of the Service Locator anti-pattern. The corollary leads to this variation of the Hollywood Principle:

Don't call the container; it'll call you.

A DI Container is a fantastic tool. It's like a (motorized) mixer: you can whip cream by hand, but it's easier with a mixer. On the other hand, without the cream the mixer is nothing. The same is true for a DI Container: to really be valuable, your code must employ Constructor Injection so that the container can auto-wire dependencies.

A well-designed application adheres to the Hollywood Principle for DI Containers: it doesn't call the container. On the other hand, we can use the container to compose the application - or we can do it the hard way; this is called Poor Man's DI. Here's an example that uses Poor Man's DI to compose a complete application graph in a console application:

private static void Main(string[] args)
 {
@@ -55,7 +55,7 @@
 

The main part of the application's execution time will be spent within the Execute method, which is where all the real application code runs.

In this example I wire up a console application, but it just as well might be any other type of application. In a web application we just do a resolve per web request instead.

But wait! does that mean that we have to resolve the entire object graph of the application, even if we have dependencies that cannot be resolved at run-time? No, but that does not mean that you should pull from the container. Pull from an Abstract Factory instead.

-

Another question that is likely to arise is: what if I have dependencies that I rarely use? Must I wire these prematurely, even if they are expensive? No, you don't have to do that either.

+

Another question that is likely to arise is: what if I have dependencies that I rarely use? Must I wire these prematurely, even if they are expensive? No, you don't have to do that either.

In conclusion: there is never any reason to query the container. Use a container to compose your object graph, but don't rely on it by querying from it. Constructor Injection all the way enables most containers to auto-wire your application, and an Abstract Factory can be a dependency too.

@@ -70,7 +70,7 @@

2010-09-01 16:29 UTC

- +
Yes, MEF supports it, but I chose my words pretty carefully. Any container that needs a special attribute to handle Constructor Injection can hardly be said to understand the pattern. I can't point MEF to a class that uses Constructor Injection and expect it to natively recognize it as such. MEF understands the [ImportingConstructor] attribute, but that's a different thing altogether.
2010-09-01 17:34 UTC
diff --git a/_posts/2010-09-13-MyfutureisAzure.html b/_posts/2010-09-13-MyfutureisAzure.html index 9505837f6..6354c08d1 100644 --- a/_posts/2010-09-13-MyfutureisAzure.html +++ b/_posts/2010-09-13-MyfutureisAzure.html @@ -31,7 +31,7 @@

2010-09-14 08:57 UTC

- +
Thanks. You know where to find me :)
2010-09-14 09:23 UTC
diff --git a/_posts/2010-09-20-InstrumentationwithDecoratorsandInterceptors.html b/_posts/2010-09-20-InstrumentationwithDecoratorsandInterceptors.html index 879c3fb89..f9c8130f1 100644 --- a/_posts/2010-09-20-InstrumentationwithDecoratorsandInterceptors.html +++ b/_posts/2010-09-20-InstrumentationwithDecoratorsandInterceptors.html @@ -8,7 +8,7 @@ {% include JB/setup %}
-

One of my readers recently asked me an interesting question. It relates to my book's chapter about Interception (chapter 9) and Decorators and how they can be used for instrumentation-like purposes.

In an earlier blog post we saw how we can use Decorators to implement Cross-Cutting Concerns, but the question relates to how a set of Decorators can be used to log additional information about code execution, such as the time before and after a method is called, the name of the method and so on.

A Decorator can excellently address such a concern as well, as we will see here. Let us first define an IRegistrar interface and create an implementation like this:

+

One of my readers recently asked me an interesting question. It relates to my book's chapter about Interception (chapter 9) and Decorators and how they can be used for instrumentation-like purposes.

In an earlier blog post we saw how we can use Decorators to implement Cross-Cutting Concerns, but the question relates to how a set of Decorators can be used to log additional information about code execution, such as the time before and after a method is called, the name of the method and so on.

A Decorator can excellently address such a concern as well, as we will see here. Let us first define an IRegistrar interface and create an implementation like this:

public class ConsoleRegistrar : IRegistrar
 {
@@ -21,8 +21,8 @@
 }

Although this implementation ‘logs' to the Console, I'm sure you can imagine other implementations. The point is that given this interface, we can add all sorts of ambient information such as the thread ID, the name of the current principal, the current culture and whatnot, while the text string variable still gives us an option to log more information. If we want a more detailed API, we can just make it more detailed - after all, the IRegistrar interface is just an example.

-

We now know how to register events, but are seemingly no nearer to instrumenting an application. How do we do that? Let us see how we can instrument the OrderProcessor class that I have described several times in past posts.

-

At the place I left off, the OrderProcessor class uses Constructor Injection all the way down. Although I would normally prefer using a DI Container to auto-wire it, here's a manual composition using Pure DI just to remind you of the general structure of the class and its dependencies:

+

We now know how to register events, but are seemingly no nearer to instrumenting an application. How do we do that? Let us see how we can instrument the OrderProcessor class that I have described several times in past posts.

+

At the place I left off, the OrderProcessor class uses Constructor Injection all the way down. Although I would normally prefer using a DI Container to auto-wire it, here's a manual composition using Pure DI just to remind you of the general structure of the class and its dependencies:

var sut = new OrderProcessor(
     new OrderValidator(), 
diff --git a/_posts/2010-09-29-TheRegisterResolveReleasepattern.html b/_posts/2010-09-29-TheRegisterResolveReleasepattern.html
index 1e125006a..8a438a06e 100644
--- a/_posts/2010-09-29-TheRegisterResolveReleasepattern.html
+++ b/_posts/2010-09-29-TheRegisterResolveReleasepattern.html
@@ -8,7 +8,7 @@
 {% include JB/setup %}
 
 
-

The subject of Dependency Injection (DI) in general, and DI Containers specifically, suffers from horrible terminology that seems to confuse a lot of people. Newcomers to DI often think about DI Containers as a sort of Abstract Factory on steroids. It's not. Nicholas Blumhardt already realized and described this phenomenon a couple of years ago.

The core of the matter is that as developers, we are extremely accustomed to thinking about components and services in terms of queries instead of commands. However, the Hollywood Principle insists that we should embrace a tell, don't ask philosophy. We can apply this principles to DI Containers as well: Don't call the container; it'l call you.

This leads us to what Krzysztof Koźmic calls the three calls pattern. Basically it states that we should only do three things with a DI Container:

  1. Bootstrap the container
  2. Resolve root components
  3. Dispose this container

This is very sound advice and independently of Krzysztof I've been doing something similar for years - so perhaps the pattern label is actually in order here.

However, I think that the pattern deserves a more catchy name, so in the spirit of the Arrange Act Assert (AAA) pattern for unit testing I propose that we name it the Register Resolve Release (RRR) pattern. The names originate with Castle Windsor terminology, where we:

  1. Register components with the container
  2. Resolve root components
  3. Release components from the container

Other containers also support the RRR pattern, but if we were to pick their terminology, it would rather be the Configure GetInstance Dispose (CGD) pattern (or something similar), and that's just not as catchy.

We can rewrite a previous example with Castle Windsor and annotate it with comments to call out where the three container phases occur:

+

The subject of Dependency Injection (DI) in general, and DI Containers specifically, suffers from horrible terminology that seems to confuse a lot of people. Newcomers to DI often think about DI Containers as a sort of Abstract Factory on steroids. It's not. Nicholas Blumhardt already realized and described this phenomenon a couple of years ago.

The core of the matter is that as developers, we are extremely accustomed to thinking about components and services in terms of queries instead of commands. However, the Hollywood Principle insists that we should embrace a tell, don't ask philosophy. We can apply this principles to DI Containers as well: Don't call the container; it'l call you.

This leads us to what Krzysztof Koźmic calls the three calls pattern. Basically it states that we should only do three things with a DI Container:

  1. Bootstrap the container
  2. Resolve root components
  3. Dispose this container

This is very sound advice and independently of Krzysztof I've been doing something similar for years - so perhaps the pattern label is actually in order here.

However, I think that the pattern deserves a more catchy name, so in the spirit of the Arrange Act Assert (AAA) pattern for unit testing I propose that we name it the Register Resolve Release (RRR) pattern. The names originate with Castle Windsor terminology, where we:

  1. Register components with the container
  2. Resolve root components
  3. Release components from the container

Other containers also support the RRR pattern, but if we were to pick their terminology, it would rather be the Configure GetInstance Dispose (CGD) pattern (or something similar), and that's just not as catchy.

We can rewrite a previous example with Castle Windsor and annotate it with comments to call out where the three container phases occur:

private static void Main(string[] args)
 {
@@ -68,7 +68,7 @@ 

2010-10-07 17:03 UTC

- +
Yes, although the general pattern is a bit more subtle than this. In the example given, the call to the Release method is largely redundant. If we assume that this is the case, a using block disposes the container as well.

However, a using block invokes Dispose, but not Release. Releasing an object graph is conceptually very different from disposing the container. However, in the degenerate case shown here, there's not a lot of difference, but in a server scenario where we use the container to resolve an object graph per request, we resolve and release many object graphs all the time. In such scenarios we only dispose the container when the application itself recycles, and even then, we may never be given notice that this happens.
diff --git a/_posts/2010-10-08-AutoDataTheorieswithAutoFixture.html b/_posts/2010-10-08-AutoDataTheorieswithAutoFixture.html index dbe12d61e..1e8d1430f 100644 --- a/_posts/2010-10-08-AutoDataTheorieswithAutoFixture.html +++ b/_posts/2010-10-08-AutoDataTheorieswithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

AutoFixture 2.0 comes with a new extension for xUnit.net data theories. For those of us using xUnit.net, it can help make our unit tests more succinct and declarative.

AutoFixture's support for xUnit.net is implemented in a separate assembly. AutoFixture itself has no dependency on xUnit.net, and if you use another unit testing framework, you can just ignore the existence of the Ploeh.AutoFixture.Xunit assembly.

Let's go back and revisit the previous test we wrote using AutoFixture and its auto-mocking extension:

+

AutoFixture 2.0 comes with a new extension for xUnit.net data theories. For those of us using xUnit.net, it can help make our unit tests more succinct and declarative.

AutoFixture's support for xUnit.net is implemented in a separate assembly. AutoFixture itself has no dependency on xUnit.net, and if you use another unit testing framework, you can just ignore the existence of the Ploeh.AutoFixture.Xunit assembly.

Let's go back and revisit the previous test we wrote using AutoFixture and its auto-mocking extension:

[Fact]
 public void AddWillPipeMapCorrectly()
@@ -77,7 +77,7 @@ 

2012-02-27 02:49 UTC

- +
I just copied in the code from your gist and added the appropriate NuGet packages, followed by an Add-BindingRedirect, and everything works as intended. In other words, I can't reproduce the problem based on the information given here. I'd love to help, but I don't think this is the correct forum. Could you ask on Stack Overflow instead? If so, I'll take a look.
2012-02-27 06:57 UTC
@@ -87,7 +87,7 @@

2012-03-02 17:00 UTC

- +
Absolutely, that's what the [Frozen] attribute is for. Here's an example (second test).
2012-03-03 19:42 UTC
@@ -113,13 +113,13 @@

2013-08-22 23:00 UTC

- +

Jeff, thank you for your comment. As you have discovered, the order of test parameters matter when you apply those 'hint' attributes, like [Frozen]. This is by design, because it enables you to generate one or more unique values of a data type before you freeze it. This could sometimes be important, although it's not something I do a lot. Keep in mind that the [Frozen] attribute wasn't designed exclusively with mocks in mind; it doesn't know anything about mocks - it just freeze a Type.

- In general, all of those 'hint' attributes apply an ICustomization, and they apply each ICustomization in the order of the arguments to which they are applied. The order of AutoFixture Customizations matter. + In general, all of those 'hint' attributes apply an ICustomization, and they apply each ICustomization in the order of the arguments to which they are applied. The order of AutoFixture Customizations matter.

2013-08-24 12:39 UTC
diff --git a/_posts/2010-10-10-AutoFixture2.0Released.html b/_posts/2010-10-10-AutoFixture2.0Released.html index ff76a4f46..3599ac0b3 100644 --- a/_posts/2010-10-10-AutoFixture2.0Released.html +++ b/_posts/2010-10-10-AutoFixture2.0Released.html @@ -7,6 +7,6 @@ {% include JB/setup %}
-

It gives me great pleasure to announce the release of AutoFixture 2.0. This release fixes a few minor issues since beta 1, but apart from that there are no significant changes.

This is a major release compared to AutoFixture 1.1, featuring a completely new kernel, as well as new features and extensibility points. The beta 1 announcement sums up the changes. Get it here.

+

It gives me great pleasure to announce the release of AutoFixture 2.0. This release fixes a few minor issues since beta 1, but apart from that there are no significant changes.

This is a major release compared to AutoFixture 1.1, featuring a completely new kernel, as well as new features and extensibility points. The beta 1 announcement sums up the changes. Get it here.

\ No newline at end of file diff --git a/_posts/2010-10-19-Convention-basedCustomizationswithAutoFixture.html b/_posts/2010-10-19-Convention-basedCustomizationswithAutoFixture.html index 5ca7acfd1..c9f100f80 100644 --- a/_posts/2010-10-19-Convention-basedCustomizationswithAutoFixture.html +++ b/_posts/2010-10-19-Convention-basedCustomizationswithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

As previous posts have described, AutoFixture creates Anonymous Variables based on the notion of being able to always hit within a well-behaved Equivalence Class for a given type. This works well a lot of the time because AutoFixture has some sensible defaults: numbers are positive integers and strings are GUIDs.

This last part only works as long as strings are nothing but opaque blobs to the consuming class. This is, however, not an unreasonable assumption. Consider classes that implement Entities such as Person or Address. Strings will often take the form of FirstName, LastName, Street, etc. In all such cases, the value of the string usually doesn't matter.

However, there will always be cases where the value of a string has a special meaning of its own. It will often be best to let AutoFixture guide us towards a better API design, but this is not always possible. Sometimes there are rules that constrain the formatting of a string.

As an example, consider a Money class with this constructor:

+

As previous posts have described, AutoFixture creates Anonymous Variables based on the notion of being able to always hit within a well-behaved Equivalence Class for a given type. This works well a lot of the time because AutoFixture has some sensible defaults: numbers are positive integers and strings are GUIDs.

This last part only works as long as strings are nothing but opaque blobs to the consuming class. This is, however, not an unreasonable assumption. Consider classes that implement Entities such as Person or Address. Strings will often take the form of FirstName, LastName, Street, etc. In all such cases, the value of the string usually doesn't matter.

However, there will always be cases where the value of a string has a special meaning of its own. It will often be best to let AutoFixture guide us towards a better API design, but this is not always possible. Sometimes there are rules that constrain the formatting of a string.

As an example, consider a Money class with this constructor:

public Money(decimal amount, string currencyCode)
{
    if (currencyCode == null)
    {
        throw new ArgumentNullException("...");
    }
    if (!CurrencyCodes.IsValid(currencyCode))
    {
        throw new ArgumentException("...");
    }

    this.amount = amount;
    this.currencyCode = currencyCode;
}

@@ -51,7 +51,7 @@

2012-11-28 20:28 UTC

- +
Jon, thanks for your comment.

The reason why the CurrencyCodeSpecimenBuilder is looking for a ParameterInfo instance is because the thing it's looking for is exactly the constructor parameter to the Money class.
@@ -68,7 +68,7 @@

- +

A request can be anything, but will often by a Type, ParameterInfo, or PropertyInfo. @@ -83,7 +83,7 @@

- +

You can use the context argument passed to the Create method to resolve other values; you only need to watch out for infinite recursions: you can't ask for an unconditional string if the Specimen Builder you're writing handles unconditional strings. @@ -106,10 +106,10 @@

- +

- Jeff, thank you for writing. Your question warranted a new blog post; it may not answer all of your concerns, but hopefully some of them. Read it and let me know if you still have questions. + Jeff, thank you for writing. Your question warranted a new blog post; it may not answer all of your concerns, but hopefully some of them. Read it and let me know if you still have questions.

2014-05-02 8:23 UTC
diff --git a/_posts/2010-11-01-PatternRecognitionAbstractFactoryorServiceLocator.html b/_posts/2010-11-01-PatternRecognitionAbstractFactoryorServiceLocator.html index fdc0772c0..af20797f8 100644 --- a/_posts/2010-11-01-PatternRecognitionAbstractFactoryorServiceLocator.html +++ b/_posts/2010-11-01-PatternRecognitionAbstractFactoryorServiceLocator.html @@ -8,7 +8,7 @@ {% include JB/setup %}
-

It's easy to confuse the Abstract Factory pattern with the Service Locator anti-pattern - particularly so when generics or contextual information is involved. However, it's really easy to distinguish between there two, and here's how!

Here are both (anti-)patterns in condensed form opposite each other:

+

It's easy to confuse the Abstract Factory pattern with the Service Locator anti-pattern - particularly so when generics or contextual information is involved. However, it's really easy to distinguish between there two, and here's how!

Here are both (anti-)patterns in condensed form opposite each other:

Abstract Factory Service Locator
public interface IFactory<T>
{
    T Create(object context);
}
Abstract Factory Service Locator
public interface IFactory<T>
{
    T Create(object context);
}
public interface IServiceLocator
{
    T Create<T>(object context);
}

For these examples I chose to demonstrate both as generic interfaces that take some kind of contextual information (context) as input.

@@ -39,7 +39,7 @@

2010-11-01 13:08 UTC

- +
Good point about design patterns not always being identifiable by implementation details. That's not quite what I said, either... We can distinguish between the two from differences in the structure of their public APIs. That's not the implementation, but rather the shape, of the type. Still, point taken.

However, the whole point is that there are fundamental differences between Abstract Factory and Service Locator. One is good, the other is evil. Learning to tell them apart is important.
@@ -52,7 +52,7 @@

2010-11-14 04:08 UTC

- +
True, but I'm sure you understand what is meant :)
2010-11-14 08:10 UTC
diff --git a/_posts/2010-11-01-RefactoringfromAbstractFactorytoDecorator.html b/_posts/2010-11-01-RefactoringfromAbstractFactorytoDecorator.html index 794d359df..1d931ba63 100644 --- a/_posts/2010-11-01-RefactoringfromAbstractFactorytoDecorator.html +++ b/_posts/2010-11-01-RefactoringfromAbstractFactorytoDecorator.html @@ -8,7 +8,7 @@ {% include JB/setup %}
-

Garth Kidd was so nice to point out to me that I hadn't needed stop where I did in my previous post, and he is, of course, correct. Taking a dependency on an Abstract Factory that doesn't take any contextual information (i.e. has no method parameters) is often an indication of a Leaky Abstraction. It indicates that the consumer has knowledge about the dependency's lifetime that it shouldn't have.

We can remove this flaw by introducing a Decorator of the IRepository<T> interface. Something like this should suffice:

+

Garth Kidd was so nice to point out to me that I hadn't needed stop where I did in my previous post, and he is, of course, correct. Taking a dependency on an Abstract Factory that doesn't take any contextual information (i.e. has no method parameters) is often an indication of a Leaky Abstraction. It indicates that the consumer has knowledge about the dependency's lifetime that it shouldn't have.

We can remove this flaw by introducing a Decorator of the IRepository<T> interface. Something like this should suffice:

public class FoundRepository<T> : IRepository<T>
 {
@@ -69,12 +69,12 @@ 

2011-08-10 16:36 UTC

- +
Agreed, but this is just one step in a refactoring process. What I would subsequently tend to do would be to refactor once more and let the Composition Root invoke the factory, which means that the consumer can now take only the result of invoking the factory as a single dependency.

You could also go the other way and perform a lazy evaluation of the dependency, but this is far more complicated to implement because it means that you'd be changing the state of the consumer. This again means that if you want to share the consumer as another dependency, you'll also need to think about thread safety.

-In most cases I'd regard lazy evaluation as a premature optimization. As I have explained in another blog post, we shouldn't worry about the cost of composing an object graph.
+In most cases I'd regard lazy evaluation as a premature optimization. As I have explained in another blog post, we shouldn't worry about the cost of composing an object graph.

In your example, IConfigService isn't really a dependency because the ConfiguredCache class doesn't depend on it - it only use it to get an instance of ExpiringCache. Change the constructor by removing the IConfigService and instead require an ExpiringCache (or the interface it implements). Some third party can take care of wiring up the IConfigService for you.

@@ -93,7 +93,7 @@

2011-08-15 13:33 UTC

- +
Why not perform the complex configuration in the Composition Root?
2011-08-15 13:39 UTC
@@ -105,7 +105,7 @@

2011-08-16 07:26 UTC

- +
Why would it make it impossible?

The code that reads configuration etc. needs to go somewhere. The Composition Root is the correct place because it makes the rest of your application code decoupled from your configuration source(s).
@@ -119,7 +119,7 @@

2011-08-16 09:25 UTC

- +
Would the configuration code be longer if you put it in the Composition Root? If that's the case, I can't for the life of me imagine why this would be, so please explain.
2011-08-16 09:39 UTC
@@ -133,7 +133,7 @@

2011-08-16 10:05 UTC

- +
The Composition Root doesn't have to be a single class. It's an architectural concept. It can have as many classes as you need as long as the stay together. Usually we implement the Composition Root in the same project as the application's entry point. This is where we wire everything together, so this particular place tends to not be (unit) testable. As such, we should go to great lengths to ensure that the entry point is a Humble Executable.

Thus it follows that the Composition Root can be as large as necessary, but it must contain no logic. My personal rule of thumb is that all members must have a cyclomatic complexity of 1.
diff --git a/_posts/2010-11-01-RefactoringfromServiceLocatortoAbstractFactory.html b/_posts/2010-11-01-RefactoringfromServiceLocatortoAbstractFactory.html index 83afe2d75..4a92931c5 100644 --- a/_posts/2010-11-01-RefactoringfromServiceLocatortoAbstractFactory.html +++ b/_posts/2010-11-01-RefactoringfromServiceLocatortoAbstractFactory.html @@ -9,7 +9,7 @@

- One of the readers of my book recently asked me an interesting question that relates to the disadvantages of the Service Locator anti-pattern. I found both the question and the potential solution so interesting that I would like to share it. + One of the readers of my book recently asked me an interesting question that relates to the disadvantages of the Service Locator anti-pattern. I found both the question and the potential solution so interesting that I would like to share it.

In short, the reader's organization currently uses Service Locator in their code, but don't really see a way out of it. This post demonstrates how we can refactor from Service Locator to Abstract Factory. Here's the original question: @@ -32,7 +32,7 @@

- When we look at the FindRepository method we quickly find that it's a Service Locator. There are many problems with Service Locator, but the general issue is that the generic argument can be one of an unbounded set of types. + When we look at the FindRepository method we quickly find that it's a Service Locator. There are many problems with Service Locator, but the general issue is that the generic argument can be one of an unbounded set of types.

The problem is that seen from the outside, the consuming type (MyService in the example) doesn't advertise its dependencies. In the example the dependency is a CustomerRepository, but you could later go into the implementation of MyServiceOperation and change the call to context.FindRepository<Qux>(context.EnterpriseId) and everything would still compile. However, at run-time, you'd likely get an exception. @@ -113,7 +113,7 @@

Step 3 #

- At this point, we're actually already done, since ICustomerRepositoryFinder is an Abstract Factory, but we can make the API even better. When we consider the implementation of MyServiceOperation, it should quickly become clear that there's a sort of local Feature Envy in play. Why do we need to access finder.EnterpriseId to invoke finder.FindCustomerRepository? Shouldn't it rather be the finder's own responsibility to figure that out for us? + At this point, we're actually already done, since ICustomerRepositoryFinder is an Abstract Factory, but we can make the API even better. When we consider the implementation of MyServiceOperation, it should quickly become clear that there's a sort of local Feature Envy in play. Why do we need to access finder.EnterpriseId to invoke finder.FindCustomerRepository? Shouldn't it rather be the finder's own responsibility to figure that out for us?

Instead, let us change the implementation so that the method does not need the enterpriseId parameter: diff --git a/_posts/2010-11-13-RhinoMocks-basedauto-mockingwithAutoFixture.html b/_posts/2010-11-13-RhinoMocks-basedauto-mockingwithAutoFixture.html index 8324b127a..e4b726e31 100644 --- a/_posts/2010-11-13-RhinoMocks-basedauto-mockingwithAutoFixture.html +++ b/_posts/2010-11-13-RhinoMocks-basedauto-mockingwithAutoFixture.html @@ -8,7 +8,7 @@

- AutoFixture now includes a Rhino Mocks-based auto-mocking feature similar to the Moq-based auto-mocking customization previously described. + AutoFixture now includes a Rhino Mocks-based auto-mocking feature similar to the Moq-based auto-mocking customization previously described.

The developer of this great optional feature, the talented but discreet Mikkel has this to say: diff --git a/_posts/2010-11-22-IntegratingAutoFixturewithObjectHydrator.html b/_posts/2010-11-22-IntegratingAutoFixturewithObjectHydrator.html index 23b275bf0..cb2fee1c7 100644 --- a/_posts/2010-11-22-IntegratingAutoFixturewithObjectHydrator.html +++ b/_posts/2010-11-22-IntegratingAutoFixturewithObjectHydrator.html @@ -7,7 +7,7 @@ {% include JB/setup %}

-

Back in the days of AutoFixture 1.0 I occasionally got the feedback that although people liked the engine and its features, they didn't like the data it generated. I think they particularly didn't like all the Guids, but Håkon Forss suggested combining Object Hydrator's data generator with AutoFixture.

In fact, this suggestion made me realize that AutoFixture 1.0's engine wasn't extensible enough, which again prompted me to build AutoFixture 2.0. Now that AutoFixture 2.0 is out, what would be more fitting than to examine whether we can do what Håkon suggested?

It turns out to be pretty easy to customize AutoFixture to use Object Hydrator's data generator. The main part is creating a custom ISpecimenBuilder that acts as an Adapter of Object Hydrator:

+

Back in the days of AutoFixture 1.0 I occasionally got the feedback that although people liked the engine and its features, they didn't like the data it generated. I think they particularly didn't like all the Guids, but Håkon Forss suggested combining Object Hydrator's data generator with AutoFixture.

In fact, this suggestion made me realize that AutoFixture 1.0's engine wasn't extensible enough, which again prompted me to build AutoFixture 2.0. Now that AutoFixture 2.0 is out, what would be more fitting than to examine whether we can do what Håkon suggested?

It turns out to be pretty easy to customize AutoFixture to use Object Hydrator's data generator. The main part is creating a custom ISpecimenBuilder that acts as an Adapter of Object Hydrator:

public class HydratorAdapter : ISpecimenBuilder
 {
diff --git a/_posts/2010-12-02-Interfacesarenotabstractions.html b/_posts/2010-12-02-Interfacesarenotabstractions.html
index c7f4a88c1..686ddeb4b 100644
--- a/_posts/2010-12-02-Interfacesarenotabstractions.html
+++ b/_posts/2010-12-02-Interfacesarenotabstractions.html
@@ -42,10 +42,10 @@
 		Interfaces can be used as abstractions, but using an interface is in itself no guarantee that we are dealing with an abstraction. Rather, we have the following relationship between interfaces and abstractions:
 	

- Abstractions, interfaces and their intersection + Abstractions, interfaces and their intersection

- There are basically two sets: a set of abstractions and a set of interfaces. In the following we will discuss the set of interfaces that does not intersect the set of abstractions, saving the intersection for another blog post. + There are basically two sets: a set of abstractions and a set of interfaces. In the following we will discuss the set of interfaces that does not intersect the set of abstractions, saving the intersection for another blog post.

There are many ways an interface can turn out to be a poor abstraction. The following is an incomplete list: @@ -149,7 +149,7 @@

In short, using interfaces in no way guarantees that we operate with appropriate abstractions. Thus, the proliferation of interfaces that typically follow from TDD or use of DI may not be the pure goodness we tend to believe.

- Creating good abstractions is difficult and requires skill. In a future post, I'll look at some principles that we can use as guides. + Creating good abstractions is difficult and requires skill. In a future post, I'll look at some principles that we can use as guides.

@@ -164,7 +164,7 @@

2010-12-02 16:21 UTC

- +
Good abstractions will still be interfaces (or base classes), so replacement with Test Doubles will still be possible.
2010-12-02 16:24 UTC
@@ -174,7 +174,7 @@

2010-12-02 16:28 UTC

- +
The whole discussion about abstract base classes versus interfaces is orthogonal to the point I'm trying to make, so I'm not going to go into that discussion in my next post.

The reason why the Framework Design Guidelines favor abstract classes is related to keeping options open for future extensions to abstractions without breaking backwards compatibility. It makes tons of sense when you just have to respect backwards compatibility when adding new features. This is the case for big, commercial frameworks like the BCL. However, I'm beginning to suspect that this is kind of a pseudo-argument; it's really more an excuse for creating abstractions that don't adhere to the Open/Closed Principle.
@@ -193,7 +193,7 @@

2010-12-02 20:53 UTC

- +
Yes, the only thing I say is that an interface doesn't guarantee that you are using a good abstraction, but you can certainly use interfaces to model good abstractions - hence the Venn diagram.
2010-12-02 20:59 UTC
@@ -214,12 +214,12 @@

2010-12-17 20:02 UTC

- +
Hi Danny

-Thanks for your comments. If you manage to read your way through my follow-up post you'll notice that I already discuss Role Interfaces there :)
+Thanks for your comments. If you manage to read your way through my follow-up post you'll notice that I already discuss Role Interfaces there :)

-I actually prefer Role Interfaces over Header Interfaces, but I can understand why you ask the questions you do. In fact, I went ahead and wrote a new blog post to answer them. HTH :)
+I actually prefer Role Interfaces over Header Interfaces, but I can understand why you ask the questions you do. In fact, I went ahead and wrote a new blog post to answer them. HTH :)
2010-12-18 14:27 UTC
@@ -232,7 +232,7 @@

2010-12-24 11:23 UTC

- +
I recently wrote an Azure application where I used these abstractions on top of Azure Queues:

public interface IChannel { void Send(object message); }
@@ -258,7 +258,7 @@

2010-12-29 08:14 UTC

- +
No, I meant exactly the same as the RAP post. Not implementing all members would indicate that an interface has more than one members. That would smell of a Header Interface, and I prefer Role Interface.

What gave you that other impression?
@@ -273,7 +273,7 @@

2010-12-29 12:43 UTC

- +
Yes, that's right, but a Decorator is also an implementation of an interface. As soon as you define your first Decorator, by implication you already have two implementations of the same type.

With an interface like IChannel, a Composite also becomes possible, in the case that you would like to broadcast a message on multiple channels.
@@ -292,7 +292,7 @@

2012-04-21 12:57 UTC

- +
For a framework example, see AutoFixture, which contains some 3000 unit tests - many of them with Test Doubles. Most (if not all) of the interfaces have several implementations, e.g. ISpecimenBuilder.

For a more complete application, see the Booking sample CQRS application. It uses Moq for Test Doubles, and I very consciously wrote that code base with the RAP in mind.
@@ -311,7 +311,7 @@

2012-04-23 17:42 UTC

- +
Currently, I don't have any concrete plans for new books, but it's not unlikely that I'll write another book in the future.
2012-04-23 18:12 UTC
diff --git a/_posts/2010-12-03-Towardsbetterabstractions.html b/_posts/2010-12-03-Towardsbetterabstractions.html index 18b46d592..050dd79f3 100644 --- a/_posts/2010-12-03-Towardsbetterabstractions.html +++ b/_posts/2010-12-03-Towardsbetterabstractions.html @@ -9,16 +9,16 @@

- In my previous post I discussed why the use of interfaces doesn't guarantee that we work against good abstractions. In this post I will look at some guidelines that might be helpful in defining better abstractions. + In my previous post I discussed why the use of interfaces doesn't guarantee that we work against good abstractions. In this post I will look at some guidelines that might be helpful in defining better abstractions.

- One important trait of a useful abstraction is that we can create many different implementations of it. This is the Reused Abstractions Principle (RAP). This is particularly important because composition and separation of concerns often result in such reuse. Every time we use Null Objects, Decorators or Composites, we reuse the same abstraction to compose an application from separate classes that all adhere to the Single Responsibility Principle. For example, Decorators are an excellent way to implement Cross-Cutting Concerns. + One important trait of a useful abstraction is that we can create many different implementations of it. This is the Reused Abstractions Principle (RAP). This is particularly important because composition and separation of concerns often result in such reuse. Every time we use Null Objects, Decorators or Composites, we reuse the same abstraction to compose an application from separate classes that all adhere to the Single Responsibility Principle. For example, Decorators are an excellent way to implement Cross-Cutting Concerns.

The RAP gives us a way to identify good abstractions after the fact, but doesn't say much about the traits that make up a good, composable interface.

- On the other hand, I find that the composability of an interface is a pretty good indicator of its potential for reuse. While we can create Decorators from just about any interface, creating meaningful Null Objects or Composites are much harder. As we previously saw, bad abstractions often prevent us from implementing a meaningful Composite. + On the other hand, I find that the composability of an interface is a pretty good indicator of its potential for reuse. While we can create Decorators from just about any interface, creating meaningful Null Objects or Composites are much harder. As we previously saw, bad abstractions often prevent us from implementing a meaningful Composite.

@@ -142,7 +142,7 @@

Keeping interfaces small and focused makes this possible in the first place.

- P.S. (added 2019-01-28) See my retrospective article on the topic. + P.S. (added 2019-01-28) See my retrospective article on the topic.

@@ -183,10 +183,10 @@

- +

- Orchun, thank you for writing. I intend to write a retrospective on this article, in the light of what I've subsequently figured out. I briefly discuss that connection in another article, but I've yet to make a formal treatment out of it. Shortly told, all the 'shapes' identified here form monoids, and the Composite design pattern itself forms a monoid. + Orchun, thank you for writing. I intend to write a retrospective on this article, in the light of what I've subsequently figured out. I briefly discuss that connection in another article, but I've yet to make a formal treatment out of it. Shortly told, all the 'shapes' identified here form monoids, and the Composite design pattern itself forms a monoid.

Stay tuned for a more detailed treatment of each of the above 'shapes'. diff --git a/_posts/2010-12-18-OnRoleInterfaces,theReusedAbstractionsPrincipleandServiceLocators.html b/_posts/2010-12-18-OnRoleInterfaces,theReusedAbstractionsPrincipleandServiceLocators.html index c6bd38aad..23ed070b7 100644 --- a/_posts/2010-12-18-OnRoleInterfaces,theReusedAbstractionsPrincipleandServiceLocators.html +++ b/_posts/2010-12-18-OnRoleInterfaces,theReusedAbstractionsPrincipleandServiceLocators.html @@ -8,7 +8,7 @@ {% include JB/setup %}

-

As a comment to my previous post about interfaces being no guarantee for abstractions, Danny asks some interesting questions. In particular, his questions relate to Udi Dahan's presentation Intentions & Interfaces: Making patterns concrete (also known as Making Roles Explicit). Danny writes:

it would seem that Udi recommends creating interfaces for each "role" the domain object plays and using a Service Locator to find the concrete implementation ... or in his case the concrete FetchingStrategy used to pull data back from his ORM. This sounds like his application would have many 1:1 abstractions.

Can this be true, or can we consolidate Role Interfaces with the Reused Abstractions Principle (RAP) - preferably without resorting to a Service Locator? Yes, of course we can.

In Udi Dahan's talks, we see various examples where he queries a Service Locator for a Role Interface. If the Service Locator returns an instance he uses it; otherwise, he falls back to some sort of default behavior. Here is my interpretation of Udi Dahan's slides:

+

As a comment to my previous post about interfaces being no guarantee for abstractions, Danny asks some interesting questions. In particular, his questions relate to Udi Dahan's presentation Intentions & Interfaces: Making patterns concrete (also known as Making Roles Explicit). Danny writes:

it would seem that Udi recommends creating interfaces for each "role" the domain object plays and using a Service Locator to find the concrete implementation ... or in his case the concrete FetchingStrategy used to pull data back from his ORM. This sounds like his application would have many 1:1 abstractions.

Can this be true, or can we consolidate Role Interfaces with the Reused Abstractions Principle (RAP) - preferably without resorting to a Service Locator? Yes, of course we can.

In Udi Dahan's talks, we see various examples where he queries a Service Locator for a Role Interface. If the Service Locator returns an instance he uses it; otherwise, he falls back to some sort of default behavior. Here is my interpretation of Udi Dahan's slides:

public void Persist(Customer entity)
 {
@@ -78,7 +78,7 @@ 

2011-02-10 00:50 UTC

- +
Use Constructor Injection all the way and defer composition until the application's entry point. In my book I call this the Composition Root.
2011-02-10 06:04 UTC
diff --git a/_posts/2010-12-22-TheTDDApostate.html b/_posts/2010-12-22-TheTDDApostate.html index 818ec9479..cf1c105e6 100644 --- a/_posts/2010-12-22-TheTDDApostate.html +++ b/_posts/2010-12-22-TheTDDApostate.html @@ -20,7 +20,7 @@ Over the years I've written tons of code with TDD. I've written code where tests blindly drove the design, and I've written code where the design was the result of a long period of deliberation, and the tests were only the manifestations of already well-formed ideas.

- I can safely say that the code where tests alone drove the design never turned out particularly well. Although it was testable and, after a fashion, ‘loosely coupled', it was still Spaghetti Code in the sense that it lacked overall consistency and good abstractions. + I can safely say that the code where tests alone drove the design never turned out particularly well. Although it was testable and, after a fashion, ‘loosely coupled', it was still Spaghetti Code in the sense that it lacked overall consistency and good abstractions.

On the other hand, I'm immensely pleased with code like AutoFixture 2.0, which was mostly the result of hours of careful contemplation riding my bike to and from work. It was still written test-first, but the design was well thought out in advance. @@ -38,7 +38,7 @@

Does TDD ensure the application of the Single Responsibility Principle (SRP)? This question is easy to answer and the answer is a resounding NO! Nothing prevents us from test-driving a God Class. I've seen many examples, and I've been guilty of it myself.

- Constructor Injection is a much better help because it makes SRP violations so painful. + Constructor Injection is a much better help because it makes SRP violations so painful.

The score so far: 0 points to TDD. @@ -47,7 +47,7 @@

TDD versus the Open/Closed Principle #

- Does TDD ensure that we follow the Open/Closed Principle (OCP)? This is a bit harder to answer. I've previously argued that Testability is just another name for OCP, so that would in itself imply that TDD drives OCP. However, the issue is more complex than that, because there are several different ways we can address the OCP: + Does TDD ensure that we follow the Open/Closed Principle (OCP)? This is a bit harder to answer. I've previously argued that Testability is just another name for OCP, so that would in itself imply that TDD drives OCP. However, the issue is more complex than that, because there are several different ways we can address the OCP:

  • Inheritance
  • @@ -60,7 +60,7 @@

    However, we all know that we should favor composition over inheritance, so does TDD drive us in that direction? As I alluded to previously, TDD does tend to drive us towards the use of Test Doubles, which we can view as one way to achieve OCP via composition.

    - However, another favorite composition technique of mine is to add functionality with a Decorator. This is only possible if the original type implements an interface that can be decorated. It's possible to write a test that forces a SUT to implement an interface, but TDD as a technique in itself does not drive us in that direction. + However, another favorite composition technique of mine is to add functionality with a Decorator. This is only possible if the original type implements an interface that can be decorated. It's possible to write a test that forces a SUT to implement an interface, but TDD as a technique in itself does not drive us in that direction.

    Grudgingly, however, I must admit that TDD still scores half a point against OCP, for a total score so far of ½ point. @@ -75,7 +75,7 @@

    Black box testing can't protect us against the SUT attempting to downcast its dependencies, but at least it doesn't particularly pull us in that direction either. When it comes to the SUT's treatment of a dependency, TDD pulls in neither direction.

    - Can we test-drive interface implementations that inadvertently violate the LSP? Yes, easily. As I discussed in a previous post, the use of Header Interfaces pulls us towards LSP violations. The more members an interface has, the more likely are LSP violations. + Can we test-drive interface implementations that inadvertently violate the LSP? Yes, easily. As I discussed in a previous post, the use of Header Interfaces pulls us towards LSP violations. The more members an interface has, the more likely are LSP violations.

    TDD can definitely drive us towards Header Interfaces (although they tend to hurt in the long run). I've seen this happen numerous times, and I've been there myself. TDD doesn't properly encourage LSP adherence. @@ -102,7 +102,7 @@

    The whole drive towards Testability - the ability to replace dependencies with Test Doubles - drives us exactly in the same direction as the DIP.

    - Since we tend to mistake such mechanistic loose coupling with proper application design, this probably explains why we, for so long, have confused TDD with good design. However, although I view loose coupling as a prerequisite for good design, it is by no means enough. + Since we tend to mistake such mechanistic loose coupling with proper application design, this probably explains why we, for so long, have confused TDD with good design. However, although I view loose coupling as a prerequisite for good design, it is by no means enough.

    For those that still keep score, TDD scores 1 point against DIP, for a total of 1½ points. @@ -170,7 +170,7 @@

    2010-12-23 15:14 UTC

- +
That article seems reasonable (and interesting), but I don't see it as being adverse to what I wrote. Uncle Bob writes about how you evolve an implementation of an API as an interaction between progressively complex tests and the code itself. As far as I can tell, at no point during that blog post does he change the API. In other words, the API design is given a priori.

What I'm discussing here is whether or not you can use tests to blindly design APIs. That's a different perspective.
diff --git a/_posts/2010-12-24-ChallengeResolveclosedtypeswithMEF.html b/_posts/2010-12-24-ChallengeResolveclosedtypeswithMEF.html index 741f27465..5bd252add 100644 --- a/_posts/2010-12-24-ChallengeResolveclosedtypeswithMEF.html +++ b/_posts/2010-12-24-ChallengeResolveclosedtypeswithMEF.html @@ -261,7 +261,7 @@

ContainerBuilder is the class you must implement, so the unit tests don't compile until you make them. Meffy xmas!

- clip_image002 + clip_image002

\ No newline at end of file diff --git a/_posts/2011-01-01-MyChristmaschallengehasawinner.html b/_posts/2011-01-01-MyChristmaschallengehasawinner.html index da87b65c1..923d1c044 100644 --- a/_posts/2011-01-01-MyChristmaschallengehasawinner.html +++ b/_posts/2011-01-01-MyChristmaschallengehasawinner.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

A week ago I concluded Microsoft Denmark's 2010 .NET Community Christmas Calendar with a challenge about resolving closed types with MEF. As 2011 came around, the deadline ended, so it's now time to pick the winner.

I didn't get a lot of entries, which can be interpreted in at least one (or more) of the following ways:

  • The challenge was too difficult
  • The challenge wasn't interesting
  • The prize wasn't attractive
  • People had other things to do during the holidays

Whatever the reason, it made my task of picking a winner that much easier. The best Danish entry came from Daniel Volder Guarnieri who cheated a bit by partially hard-coding the composition of Mayonnaise into the ContainerBuilder. As I wrote in the original challenge, there are many ways to tackle the challenge, and one was to take the unit tests very literally :)

However, honorable mention must go to Boyan Mihaylov who participated just for the honor. He took a more general approach similar to Fluent MEF. This involves implementing a completely new ComposablePartCatalog with associated ComposablePartDefinition and ComposablePart implementations - not a trivial undertaking.

Kudos to Boyan and congratulations to Daniel. My thanks for your submissions, and a happy new year to all my readers!

+

A week ago I concluded Microsoft Denmark's 2010 .NET Community Christmas Calendar with a challenge about resolving closed types with MEF. As 2011 came around, the deadline ended, so it's now time to pick the winner.

I didn't get a lot of entries, which can be interpreted in at least one (or more) of the following ways:

  • The challenge was too difficult
  • The challenge wasn't interesting
  • The prize wasn't attractive
  • People had other things to do during the holidays

Whatever the reason, it made my task of picking a winner that much easier. The best Danish entry came from Daniel Volder Guarnieri who cheated a bit by partially hard-coding the composition of Mayonnaise into the ContainerBuilder. As I wrote in the original challenge, there are many ways to tackle the challenge, and one was to take the unit tests very literally :)

However, honorable mention must go to Boyan Mihaylov who participated just for the honor. He took a more general approach similar to Fluent MEF. This involves implementing a completely new ComposablePartCatalog with associated ComposablePartDefinition and ComposablePart implementations - not a trivial undertaking.

Kudos to Boyan and congratulations to Daniel. My thanks for your submissions, and a happy new year to all my readers!

diff --git a/_posts/2011-01-24-Scalabledoesntmeanfast.html b/_posts/2011-01-24-Scalabledoesntmeanfast.html index 958d5391e..4c88a10f8 100644 --- a/_posts/2011-01-24-Scalabledoesntmeanfast.html +++ b/_posts/2011-01-24-Scalabledoesntmeanfast.html @@ -24,7 +24,7 @@

2011-01-24 20:35 UTC

- +
Jakob, if you already knew all of those things, then this blog post wasn't meant for you. I knew them too, but apparently many people don't, so I wrote for their benefit. Trust me: for many developers, this is far from obvious.

The same goes for the ACID comment. People don't seem to have too big of a problem with in-memory caches because somehow they know that these can't possibly be consistent. However, as soon as you start writing to a persistent store, you encounter knee-jerk reactions that all persisted data must be written and updated within transactions.
diff --git a/_posts/2011-02-04-TheBCLalreadyhasaMaybemonad.html b/_posts/2011-02-04-TheBCLalreadyhasaMaybemonad.html index bb32829d4..7a9fc1d58 100644 --- a/_posts/2011-02-04-TheBCLalreadyhasaMaybemonad.html +++ b/_posts/2011-02-04-TheBCLalreadyhasaMaybemonad.html @@ -78,7 +78,7 @@

2011-02-04 20:38 UTC

- +
Yes, I believe the concept of a Maybe monad originates from Haskell or a similar language (but I can't remember the specific details).

Using Enumerable.Single(value) will not work because it takes an IEnumerable<T> and returns a T. We want the exact opposite: take a T and return IEnumerable<T>.
@@ -92,7 +92,7 @@

2011-02-04 23:29 UTC

- +
Yes, you are right - Single() is enough. My mistake :)

It's true that there are many ways to create an IEnumerable with a single element.
@@ -123,7 +123,7 @@

2011-02-05 09:07 UTC

- +
Did you test that code? I'm pretty sure it has defects.

If you call GetGenericTypeDefinition() on a type which is not generic, an exception will be thrown. This could happen if, for instance, I were to invoke the method with request = typeof(object).
@@ -137,7 +137,7 @@

2011-02-05 22:50 UTC

- +
Yes, but the point is that it's those little things that end up making a more procedural refactoring less than readable. In any case, 'readability' of code is highly subjective so obviously YMMV.
2011-02-06 09:35 UTC
diff --git a/_posts/2011-02-07-CreatingspecificpopulatedlistswithAutoFixture.html b/_posts/2011-02-07-CreatingspecificpopulatedlistswithAutoFixture.html index 729623b29..d6959aa60 100644 --- a/_posts/2011-02-07-CreatingspecificpopulatedlistswithAutoFixture.html +++ b/_posts/2011-02-07-CreatingspecificpopulatedlistswithAutoFixture.html @@ -16,11 +16,11 @@

fixture.AddManyTo(list);

-

However, you may instead prefer getting a populated list right away. This is also possible, but before we look at how to get there, I'd like to point out a feature that surprisingly few users notice. You can create many anonymous specimens at once:

+

However, you may instead prefer getting a populated list right away. This is also possible, but before we look at how to get there, I'd like to point out a feature that surprisingly few users notice. You can create many anonymous specimens at once:

var integers = fixture.CreateMany<int>();

-

Armed with this knowledge, as well as the knowledge of how to map types, we can now create this customization to map IEnumerable<int> to CreateMany<int>:

+

Armed with this knowledge, as well as the knowledge of how to map types, we can now create this customization to map IEnumerable<int> to CreateMany<int>:

fixture.Register(() => fixture.CreateMany<int>());

@@ -45,6 +45,6 @@

When we use the Register method to map types we can no longer rely on type inference. Instead, we must explicitly register IList<int> against a delegate that creates a populated List<int>. Because List<int> implements IList<int> this compiles. Whenever this fixture instance resolves IList<int> it will create a populated List<int>.

All of this describes what you can do with the strongly typed API available in AutoFixture 2.0. It's easy and very flexible, but the only important drawback is that it's not general. All of the customizations in this post specifically address lists and sequences of integers, but not lists of any other type. What if you would like to expand this sort of behavior to any List<T>, IEnumerable<T> etc?

-

Stay tuned, because in the next post I will describe how to do that.

+

Stay tuned, because in the next post I will describe how to do that.

\ No newline at end of file diff --git a/_posts/2011-02-08-CreatinggeneralpopulatedlistswithAutoFixture.html b/_posts/2011-02-08-CreatinggeneralpopulatedlistswithAutoFixture.html index 8433acf28..738ea1cb5 100644 --- a/_posts/2011-02-08-CreatinggeneralpopulatedlistswithAutoFixture.html +++ b/_posts/2011-02-08-CreatinggeneralpopulatedlistswithAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}
-

In my previous post I described how to customize a Fixture instance to populate lists with items instead of returning empty lists. While it's pretty easy to do so, the drawback is that you have to do it explicitly for every type you want to influence. In this post I will follow up by describing how to enable some general conventions that simply populates all collections that the Fixture resolves.

This post describes a feature that will be available in AutoFixture 2.1. It's not available in AutoFixture 2.0, but is already available in the code repository. Thus, if you can't wait for AutoFixture 2.1 you can download the source and built it.

Instead of having to create multiple customizations for IEnumerable<int>, IList<int>, List<int>, IEnumerable<string>, IList<string>, etc. you can simply enable these general conventions as easy as this:

+

In my previous post I described how to customize a Fixture instance to populate lists with items instead of returning empty lists. While it's pretty easy to do so, the drawback is that you have to do it explicitly for every type you want to influence. In this post I will follow up by describing how to enable some general conventions that simply populates all collections that the Fixture resolves.

This post describes a feature that will be available in AutoFixture 2.1. It's not available in AutoFixture 2.0, but is already available in the code repository. Thus, if you can't wait for AutoFixture 2.1 you can download the source and built it.

Instead of having to create multiple customizations for IEnumerable<int>, IList<int>, List<int>, IEnumerable<string>, IList<string>, etc. you can simply enable these general conventions as easy as this:

var fixture = new Fixture()
     .Customize(new MultipleCustomization());
@@ -17,7 +17,7 @@

This feature must be explicitly enabled. There are several reasons for that:

  • It would be a breaking change if AutoFixture suddenly started to behave like this by default. -
  • The MultipleCustomization targets not only concrete types such as List<T> and Collection<T>, but also interfaces such as IEnumerable<T>, IList<T> etc. Thus, if you also use AutoFixture as an Auto-Mocking container, I wanted to provide the ability to define which customization takes precedence.
+
  • The MultipleCustomization targets not only concrete types such as List<T> and Collection<T>, but also interfaces such as IEnumerable<T>, IList<T> etc. Thus, if you also use AutoFixture as an Auto-Mocking container, I wanted to provide the ability to define which customization takes precedence.
  • With that simple customization enabled, all requested IEnumerable<T> are now populated. The following will give us a finite, but populated list of integers:

    var integers = 
    @@ -36,7 +36,7 @@
     

    var list = fixture.CreateAnonymous<IList<int>>();

    -

    The exact number of ‘many' is as always determined by the Fixture's RepeatCount.

    +

    The exact number of ‘many' is as always determined by the Fixture's RepeatCount.

    As this code is still (at the time of publishing) in preview, I would love to get feedback on this feature.

    \ No newline at end of file diff --git a/_posts/2011-02-28-Interfacesareaccessmodifiers.html b/_posts/2011-02-28-Interfacesareaccessmodifiers.html index ca3a65825..67486159f 100644 --- a/_posts/2011-02-28-Interfacesareaccessmodifiers.html +++ b/_posts/2011-02-28-Interfacesareaccessmodifiers.html @@ -92,7 +92,7 @@

    2011-02-28 16:32 UTC

    - +
    I must admit that I haven't fully thought through whether or not interfaces ought to be explicit or implicit, but my gut feeling is that implicit implementations (as shown in the example) are fine.

    The thing is: when I unit test the concrete implementations I often tend to declare the System Under Test (SUT) as the concrete type because I want to exercise an interface member, but verify against a concrete member. If I were to use an explicit implementation this would require a cast in each test. If there was an indisputable benefit to be derived from explicit implementations I wouldn't consider this a valid argument, but in the absence of such, I'd tend towards making unit testing as easy as possible.
    @@ -101,7 +101,7 @@

    2011-02-28 20:49 UTC

    - +
    Gael

    Thank you for your comment.
    @@ -121,7 +121,7 @@

    2011-03-01 01:15 UTC

    - +
    Ruben

    Thank you for writing.
    @@ -139,7 +139,7 @@

    2011-03-02 09:51 UTC

    - +
    First and foremost I consider the InternalsVisibleTo feature an abomination. We should only unit test the public members of our code.

    As I wrote in another answer on this page, the Builder property is most certainly part of the public API of the concrete SpecimenContext class. It doesn't pollute the class in any way because it's an integral part of what the SpecimenContext class does.
    diff --git a/_posts/2011-03-03-InjectionConstructorsshouldbesimple.html b/_posts/2011-03-03-InjectionConstructorsshouldbesimple.html index f6e02feed..a6f257359 100644 --- a/_posts/2011-03-03-InjectionConstructorsshouldbesimple.html +++ b/_posts/2011-03-03-InjectionConstructorsshouldbesimple.html @@ -31,7 +31,7 @@
  • When we compose applications with Constructor Injection we often create substantial object graphs, and we want to be able to create these graphs as efficiently as possible. This is Nikola's original argument.
  • In the odd (and not recommended) cases where you have circular dependencies, the injected dependencies may not yet be fully initialized, so an attempt to invoke their members at that time may result in an exception. This issue is similar to the issue of invoking virtual members from the constructor. Conceptually, an injected dependency is equivalent to a virtual member.
  • With Constructor Injection, the constructor's responsibility is to demand and receive the dependencies. Thus, according to the Single Responsibility Principle (SRP), it should not try to do something else as well. Some readers might argue that I'm misusing the SRP here, but I think I'm simply applying the underlying principle in a more granular context.
  • -

    There's no reason to feel constrained by this rule, as in any case the constructor is an implementation detail. In loosely coupled code, the constructor is not part of the overall application API. When we consider the API at that level, we are still free to design the API as we'd like.

    +

    There's no reason to feel constrained by this rule, as in any case the constructor is an implementation detail. In loosely coupled code, the constructor is not part of the overall application API. When we consider the API at that level, we are still free to design the API as we'd like.

    Please notice that this rule is contextual: it applies to Services that use Constructor Injection. Entities and Value Objects tend not to use DI, so their constructors are covered by other rules.

    @@ -46,7 +46,7 @@

    2011-03-03 15:01 UTC

    - +
    That's very rarely a good idea. The problem with an Initialize method is the same as with Property Injection (A.K.A. Setter Injection): it creates a temporal coupling between the Initialize method and all other members of the class. Unless you truly can invoke any other member of the class without first invoking the Initialize method, such API design is deceitful and will lead to run-time exceptions. It also becomes much harder to ensure that the object is always in a consistent state.

    Constructor Injection is a far superior pattern because is enforces that required dependencies will be present. Property Injection on the other hand implies that the dependency is optional, which is rarely the case.
    @@ -61,7 +61,7 @@

    2011-03-03 19:28 UTC

    - +
    When you look at what happens on the IL level, subscribing to an event is just another method call, so the same arguments as above still apply.

    Keep in mind, however, that the above constitutes a guideline. It's not an absolute truth. I rarely use events, but it happens from time to time, and I can think of at least one case where I've done just what you suggest. I also occasionally break the above rule in other ways, but I always pause and consider the implications and whether there's a better alternative - often there is.
    diff --git a/_posts/2011-03-04-Composeobjectgraphswithconfidence.html b/_posts/2011-03-04-Composeobjectgraphswithconfidence.html index 14461b9c5..1d6c09db4 100644 --- a/_posts/2011-03-04-Composeobjectgraphswithconfidence.html +++ b/_posts/2011-03-04-Composeobjectgraphswithconfidence.html @@ -11,7 +11,7 @@

    - The main principle behind the Register Resolve Release pattern is that loosely coupled object graphs should be composed as a single action in the entry point of the application (the Composition Root). For request-based applications (web sites and services), we use a variation where we compose once per request. + The main principle behind the Register Resolve Release pattern is that loosely coupled object graphs should be composed as a single action in the entry point of the application (the Composition Root). For request-based applications (web sites and services), we use a variation where we compose once per request.

    It seems to me that a lot of people are apprehensive when they first hear about this concept. It may sound reasonable from an architectural point of view, but isn't it horribly inefficient? A well-known example of such a concern is Jeffrey Palermo's blog post Constructor over-injection anti-pattern. Is it really a good idea to compose a complete object graph in one go? What if we don't need part of the graph, or only need it later? Doesn't it adversely affect response times? @@ -26,7 +26,7 @@ Consider a simple tree composed of classes from three different assemblies:

    - Tree + Tree

    All the A classes (blue) are defined in the A assembly, B classes (green) in the B assembly, and the C1 class (red) in the C assembly. In code we create the tree with Constructor Injection like this: @@ -48,7 +48,7 @@

    Will it be slow? #

    - Most likely not. Keep in mind that Injection Constructors should be very simple, so not a lot of work is going on during composition. Obviously just creating new object instances takes a bit of time in itself, but we create objects instances all the time in .NET code, and it's often a very fast operation. + Most likely not. Keep in mind that Injection Constructors should be very simple, so not a lot of work is going on during composition. Obviously just creating new object instances takes a bit of time in itself, but we create objects instances all the time in .NET code, and it's often a very fast operation.

    Even when using DI Containers, which perform a lot of (necessary) extra work when creating objects, we can create tens of thousand trees per second. Creation of objects simply isn't that big a deal. @@ -96,7 +96,7 @@

    Imagine that we wish to defer creation of the C1 branch of the above tree. It will prevent the C assembly from being loaded because that assembly is not used in any other place in the tree. However, it will not prevent the B assembly from being loaded, since that assembly is also being used by the A2 node.

    - Still, in those rare situations where it makes sense to defer creation of a branch, we can make that cut into a part of the infrastructure of the tree. I originally described this technique as a reaction to the above mentioned post by Jeffrey Palermo, but here's a restatement in the current context. + Still, in those rare situations where it makes sense to defer creation of a branch, we can make that cut into a part of the infrastructure of the tree. I originally described this technique as a reaction to the above mentioned post by Jeffrey Palermo, but here's a restatement in the current context.

    We can defer creating the C1 node by wrapping it in a lazy implementation of the same interface. The C1 node implements an interface called ISolo<IMarker>, so we can wrap it in a Virtual Proxy that defers creation of C1 until it's needed: @@ -167,7 +167,7 @@


    The main premise here is that in a rich-client app the trees you mention above should ALWAYS be lazily loaded, since the "branches" of the component tree are usually screens or their various sub-components (a dialog in some sub-screen for example). The branches are also more like "chains" as screens can have multiple follow-on screens that slowly load more content as you dive in deeper (while content you have visited higher up the chain may get unloaded - "lazy unloading" shall we say?). You never want to load screens that are not yet visible at app startup. In a desktop, fully-local app this results in a chuggy-performing or needlessly resource-wasteful app; in mobile it is simply impossible within the memory constraints. And of course... a majority of rich-client screens are hydrated with data pulled from the Internet and that data depends on either user input or server state (think accessing a venue listing on Yelp - you need the user to say which venue they want to view and the venue data is stored and updated server-side in a crowd-sourced manner not locally available to the user). So even if you had unlimited client-side memory you still couldn't pre-load the whole component object graph for the application up front.

    -I completely agree with your Composition Root article (http://blog.ploeh.dk/2011/07/28/CompositionRoot) and I think it describes things very beautifully. But what it also blissfully points out is that rich-client apps are poorly suited to a Composition Root and thus Dependency Injection approach.
    +I completely agree with your Composition Root article (/2011/07/28/CompositionRoot) and I think it describes things very beautifully. But what it also blissfully points out is that rich-client apps are poorly suited to a Composition Root and thus Dependency Injection approach.

    DI does lazy-loading very poorly (just look at the amount of wrapper/plumbing you have to write for one component above). Now picture doing that for every screen in a mobile app (ours has ~30 screens and it's quite a trivial, minimal app for our problem domain). That's not to even mention whether you actually WANT to pull all the lifetime management into a single component - what could easily be seen as a break in Cohesion for logic belonging to the various sub-components. In web this doesn't really matter as the lifetime is usually all or nothing - it's either a singleton/per-request or per-instance. The request provides the full scoping needed for most processing. But in rich-client the lifetimes need to be finely managed based on screen navigation, user action and caching or memory constraints. Sub-components need to get loaded in and out dynamically in a lot more complex a manner than singletons or per-user-session. Again pulling this fine-tuned logic into a shared, centralized component is highly questionable - even if it was easily doable, which it's not.

    @@ -179,7 +179,7 @@

    2012-10-18 05:11 UTC

    - +
    Hi Marcel

    Thank you for your insightful comment. When it comes to the analysis of the needs of desktop and mobile applications, I completely agree that many nodes of the object graph would need to be lazy for exactly the reasons you so clearly explain.
    @@ -212,13 +212,13 @@

    - +

    - Vasiliy, thank you for writing. That statement sounds reasonable. FWIW, objects that do too much work during construction violate Nikola Malovic's 4th law of IoC. Unfortunately, the original links to Nikola Malovic laws of IoC no longer point at the original material, but I described the fourth law in an article called Injection Constructors should be simple. + Vasiliy, thank you for writing. That statement sounds reasonable. FWIW, objects that do too much work during construction violate Nikola Malovic's 4th law of IoC. Unfortunately, the original links to Nikola Malovic laws of IoC no longer point at the original material, but I described the fourth law in an article called Injection Constructors should be simple.

    - If you want to give some examples of possible refactorings, you may want to take a look at the Decoraptor pattern. Additionally, if you're dealing with a third-party component, you can often create an Adapter that behaves nicely during construction. + If you want to give some examples of possible refactorings, you may want to take a look at the Decoraptor pattern. Additionally, if you're dealing with a third-party component, you can often create an Adapter that behaves nicely during construction.

    2017-03-19 11:53 UTC
    diff --git a/_posts/2011-03-14-ResolvingclosedtypeswithMEF.html b/_posts/2011-03-14-ResolvingclosedtypeswithMEF.html index 78750c067..0482b5217 100644 --- a/_posts/2011-03-14-ResolvingclosedtypeswithMEF.html +++ b/_posts/2011-03-14-ResolvingclosedtypeswithMEF.html @@ -7,7 +7,7 @@ {% include JB/setup %}
    -

    A while back I posed the challenge of resolving closed types with MEF. I received some responses, but I also wanted to provide an alternative outline for a solution. In case you don't remember the problem statement, it revolved around using the Managed Extensibility Framework (MEF) to compose classes in those cases where it's impossible to annotate those classes with the MEF attributes. In the given example I want to compose the Mayonnaise class from EggYolk and OliveOil, but all three classes are sealed and cannot be recompiled.

    As I describe in my book, a general solution to this type of problem is to create a sort of adapter the exports the closed type via a read-only attribute, like these EggYolkAdapter and MayonnaiseAdapter classes (the OliveOilAdapter looks just like the EggYolkAdapter):

    +

    A while back I posed the challenge of resolving closed types with MEF. I received some responses, but I also wanted to provide an alternative outline for a solution. In case you don't remember the problem statement, it revolved around using the Managed Extensibility Framework (MEF) to compose classes in those cases where it's impossible to annotate those classes with the MEF attributes. In the given example I want to compose the Mayonnaise class from EggYolk and OliveOil, but all three classes are sealed and cannot be recompiled.

    As I describe in my book, a general solution to this type of problem is to create a sort of adapter the exports the closed type via a read-only attribute, like these EggYolkAdapter and MayonnaiseAdapter classes (the OliveOilAdapter looks just like the EggYolkAdapter):

    public class EggYolkAdapter
     {
    diff --git a/_posts/2011-03-18-EncapsulatingAutoFixtureCustomizations.html b/_posts/2011-03-18-EncapsulatingAutoFixtureCustomizations.html
    index 492ccf6ec..1daaf2dd7 100644
    --- a/_posts/2011-03-18-EncapsulatingAutoFixtureCustomizations.html
    +++ b/_posts/2011-03-18-EncapsulatingAutoFixtureCustomizations.html
    @@ -7,7 +7,7 @@
     {% include JB/setup %}
     
     
    -

    AutoFixture is designed around the 80-20 principle. If your code is well-designed I'd expect a default instance of Fixture to be able to create specimens of your classes without too much trouble. There are cases where AutoFixture needs extra help:

    • If a class consumes interfaces a default Fixture will not be able to create it. However, this is easily fixed through one of the AutoMocking Customizations.
    • If an API has circular references, Fixture might enter an infinite recursion, but you can easily customize it to cut off one the references.
    • Some constructors may only accept arguments that don't fit with the default specimens created by Fixture. There are ways to deal with that as well.

    I could keep on listing examples, but let's keep it at that. The key assumption underlying AutoFixture is that these special cases are a relatively small part of the overall API you want to test - preferably much less than 20 percent.

    Still, to address those special cases you'll need to customize a Fixture instance in some way, but you also want to keep your test code DRY.

    As the popularity of AutoFixture grows, I'm getting more and more glimpses of how people address this challenge: Some derive from Fixture, others create extension methods or other static methods, while others again wrap creation of Fixture instances in Factories or Builders.

    There really is no need to do that. AutoFixture has an idiomatic way to encapsulate Customizations. It's called… well… a Customization, which is just another way to say that there's an ICustomization interface that you can implement. This concept corresponds closely to the modularization APIs for several well-known DI Containers. Castle Windsor has Installers, StructureMap has Registries and Autofac has Modules.

    The ICustomization interface is simple and has a very gentle learning curve:

    +

    AutoFixture is designed around the 80-20 principle. If your code is well-designed I'd expect a default instance of Fixture to be able to create specimens of your classes without too much trouble. There are cases where AutoFixture needs extra help:

    • If a class consumes interfaces a default Fixture will not be able to create it. However, this is easily fixed through one of the AutoMocking Customizations.
    • If an API has circular references, Fixture might enter an infinite recursion, but you can easily customize it to cut off one the references.
    • Some constructors may only accept arguments that don't fit with the default specimens created by Fixture. There are ways to deal with that as well.

    I could keep on listing examples, but let's keep it at that. The key assumption underlying AutoFixture is that these special cases are a relatively small part of the overall API you want to test - preferably much less than 20 percent.

    Still, to address those special cases you'll need to customize a Fixture instance in some way, but you also want to keep your test code DRY.

    As the popularity of AutoFixture grows, I'm getting more and more glimpses of how people address this challenge: Some derive from Fixture, others create extension methods or other static methods, while others again wrap creation of Fixture instances in Factories or Builders.

    There really is no need to do that. AutoFixture has an idiomatic way to encapsulate Customizations. It's called… well… a Customization, which is just another way to say that there's an ICustomization interface that you can implement. This concept corresponds closely to the modularization APIs for several well-known DI Containers. Castle Windsor has Installers, StructureMap has Registries and Autofac has Modules.

    The ICustomization interface is simple and has a very gentle learning curve:

    public interface ICustomization
     {
    @@ -45,7 +45,7 @@
         }
     }

    -

    This means that I can reuse the DomainCustomization across normal, imperative unit tests as well as the declarative, xUnit.net-powered data theories I normally prefer:

    +

    This means that I can reuse the DomainCustomization across normal, imperative unit tests as well as the declarative, xUnit.net-powered data theories I normally prefer:

    [Theory, AutoDomainData]
     public void CanReserveReturnsTrueWhenQuantityIsEqualToRemaining(
    diff --git a/_posts/2011-03-22-CommandsareComposable.html b/_posts/2011-03-22-CommandsareComposable.html
    index 23c7c9271..75031ddb5 100644
    --- a/_posts/2011-03-22-CommandsareComposable.html
    +++ b/_posts/2011-03-22-CommandsareComposable.html
    @@ -9,7 +9,7 @@
     
     

    - A few months back I wrote a (somewhat theoretical) post on composable interfaces. A major point of that post was that Role Interfaces  with a single Command method (i.e. a method that returns no value) is a very versatile category of abstraction. + A few months back I wrote a (somewhat theoretical) post on composable interfaces. A major point of that post was that Role Interfaces  with a single Command method (i.e. a method that returns no value) is a very versatile category of abstraction.

    Some of my readers asked for examples, so in this post I will provide a few. Consider this interface that fits the above description: @@ -30,7 +30,7 @@

    Decorator #

    - Can we create a meaningful Decorator around the IMessageConsumer<T> interface? Yes, that's easy - I've earlier provided various detailed examples of Decorators, so I'm not going to repeat them here. + Can we create a meaningful Decorator around the IMessageConsumer<T> interface? Yes, that's easy - I've earlier provided various detailed examples of Decorators, so I'm not going to repeat them here.

    @@ -191,14 +191,14 @@

    Each of the design pattern implementations (Null Object, Composite - even Conditional) are generic. This is a strong testament to the power of this particular abstraction.
  • - The dynamic mocks I'm familiar with (Moq, Rhino Mocks) will by default try to create Null Object implementations for interfaces without explicit setups. Since it's trivial to implement a Null Command, they just emit them by default. If you use an Auto-mocking Container with your unit tests, you can refactor to your heart's content, adding and removing dependencies as long as they are Command interfaces, and your testing infrastructure will just take care of things for you. It'll just work. + The dynamic mocks I'm familiar with (Moq, Rhino Mocks) will by default try to create Null Object implementations for interfaces without explicit setups. Since it's trivial to implement a Null Command, they just emit them by default. If you use an Auto-mocking Container with your unit tests, you can refactor to your heart's content, adding and removing dependencies as long as they are Command interfaces, and your testing infrastructure will just take care of things for you. It'll just work.
  • Did you notice that even with these few building blocks we have implemented a large part of a sequential workflow engine? We can execute consumers in sequence as well as branch between different sequences. Obviously, more building blocks are needed to make a full-blown workflow engine, but not that many. I'll leave the rest as an exercise to the reader :)
  • - As I originally sketched, a Command interface is the ultimate in composability. To illustrate, the application from where I took the above examples is a small application with 48 types (classes and interfaces) in the production code base (that is, excluding unit tests). Of these, 9 are implementations of the IMessageConsumer<T> interface. If we also count the interface itself, it accounts for more than 20 percent of the code base. According to the Reused Abstractions Principle (RAP) I consider this a very successful abstraction. + As I originally sketched, a Command interface is the ultimate in composability. To illustrate, the application from where I took the above examples is a small application with 48 types (classes and interfaces) in the production code base (that is, excluding unit tests). Of these, 9 are implementations of the IMessageConsumer<T> interface. If we also count the interface itself, it accounts for more than 20 percent of the code base. According to the Reused Abstractions Principle (RAP) I consider this a very successful abstraction.

    \ No newline at end of file diff --git a/_posts/2011-04-05-MSDNMagazinearticleaboutCQRSonWindowsAzure.html b/_posts/2011-04-05-MSDNMagazinearticleaboutCQRSonWindowsAzure.html index 1c7ae2a45..f50d5df58 100644 --- a/_posts/2011-04-05-MSDNMagazinearticleaboutCQRSonWindowsAzure.html +++ b/_posts/2011-04-05-MSDNMagazinearticleaboutCQRSonWindowsAzure.html @@ -7,7 +7,7 @@ {% include JB/setup %}
    -

    My latest MSDN Magazine article, this time about CQRS on Windows Azure, is now available at the April MSDN Magazine web site.

    It's mostly meant as an introduction to CQRS as well as containing some tips and tricks that are specific to applying CQRS on Windows Azure.

    As an added bonus the code sample download contains lots of idiomatic unit tests written with AutoFixture's xUnit.net extensions, so if you'd like to see the result of my TDD work with AutoFixture, there's a complete code base to look at there.

    +

    My latest MSDN Magazine article, this time about CQRS on Windows Azure, is now available at the April MSDN Magazine web site.

    It's mostly meant as an introduction to CQRS as well as containing some tips and tricks that are specific to applying CQRS on Windows Azure.

    As an added bonus the code sample download contains lots of idiomatic unit tests written with AutoFixture's xUnit.net extensions, so if you'd like to see the result of my TDD work with AutoFixture, there's a complete code base to look at there.

    diff --git a/_posts/2011-04-18-EnumerablesaredynamicalsoinAutoFixture.html b/_posts/2011-04-18-EnumerablesaredynamicalsoinAutoFixture.html index 0036c6977..b09132159 100644 --- a/_posts/2011-04-18-EnumerablesaredynamicalsoinAutoFixture.html +++ b/_posts/2011-04-18-EnumerablesaredynamicalsoinAutoFixture.html @@ -16,8 +16,8 @@

    If this doesn't surprise you, then read the assertion again. The sequence is expected to not equal itself!

    This behavior is by design.

    (I've always wanted to write that.) The reason is that the return type of the CreateMany method is IEnumerable<T>, and that interface makes no guarantee that it will return the same sequence every time you iterate over it. The implementation may be a Generator.

    -

    According to its principle of Constrained Non-determinism, AutoFixture goes to great lengths to ensure that since IEnumerable<T> might be non-deterministic, it will be. This can be very useful in flushing out incorrect assumptions made by the SUT.

    -

    This behavior is carried forward by the MultipleCustomization. This unit test also succeeds:

    +

    According to its principle of Constrained Non-determinism, AutoFixture goes to great lengths to ensure that since IEnumerable<T> might be non-deterministic, it will be. This can be very useful in flushing out incorrect assumptions made by the SUT.

    +

    This behavior is carried forward by the MultipleCustomization. This unit test also succeeds:

    var fixture = new Fixture()
         .Customize(new MultipleCustomization());
    @@ -39,7 +39,7 @@
     

    The above unit test succeeds. Notice that the assertion now verifies that the sequence of strings is equal to itself.

    Just like MultipleCustomization the StableFiniteSequenceRelay class will be available in AutoFixture 2.1, but is not availale in 2.0.

    -

    As always, it's best to encapsulate this behavior change into a Customization:

    +

    As always, it's best to encapsulate this behavior change into a Customization:

    public class StableFiniteSequenceCustomization :
         ICustomization
    @@ -90,7 +90,7 @@ 

    2012-02-27 18:18 UTC

    - +
    Circular references are, IMO, a design smell, but since you are attempting to work with relational data, I guess you can't change the design.

    The easiest way to get around an issue like that is to customize the types to not fill in the properties in question. Something like this:
    @@ -115,7 +115,7 @@

    2015-01-15 17:32 UTC

    - +

    Diogo, thank you for writing. The reason for the changed behaviour was that the old behaviour caused too much confusion. Essentially, you can boild down the problem to the fact that if you compare 'two' IEnumerable<T> instances with ReferenceEquals, it could evaluate to true, and still contain different values when you start enumerating over them. diff --git a/_posts/2011-04-19-ConstructorstrategiesforAutoFixture.html b/_posts/2011-04-19-ConstructorstrategiesforAutoFixture.html index 13fbba4e0..6a305b072 100644 --- a/_posts/2011-04-19-ConstructorstrategiesforAutoFixture.html +++ b/_posts/2011-04-19-ConstructorstrategiesforAutoFixture.html @@ -7,7 +7,7 @@ {% include JB/setup %}

    -

    When AutoFixture creates complex objects it invokes the constructors of the types in question. When a class exposes more than one constructor, the default behavior is to pick the constructor with the fewest number  of arguments. This is the exact opposite of most DI Containers that select the greediest constructor.

    For a DI Container it makes more sense to select the greediest constructor because that maximizes the chance that all dependencies are properly being auto-wired.

    The reason that AutoFixture's default behavior is different is that it maximizes the chance that an object graph can be created at all. If a convenience overload is available, this gives AutoFixture a better chance to compose the object graph.

    This works well until a class comes along and introduces the wrong kind of ambiguity. Consider this case of Bastard Injection (Dependency Injection in .NET, section 5.2):

    +

    When AutoFixture creates complex objects it invokes the constructors of the types in question. When a class exposes more than one constructor, the default behavior is to pick the constructor with the fewest number  of arguments. This is the exact opposite of most DI Containers that select the greediest constructor.

    For a DI Container it makes more sense to select the greediest constructor because that maximizes the chance that all dependencies are properly being auto-wired.

    The reason that AutoFixture's default behavior is different is that it maximizes the chance that an object graph can be created at all. If a convenience overload is available, this gives AutoFixture a better chance to compose the object graph.

    This works well until a class comes along and introduces the wrong kind of ambiguity. Consider this case of Bastard Injection (Dependency Injection in .NET, section 5.2):

    public class Bastard
     {
    @@ -34,7 +34,7 @@
         }
     }

    -

    By default AutoFixture will use the default constructor which means that the Foo will always be the instance of DefaultFoo owned by the Bastard class itself. This is problematic if we wish to inject and freeze a Test Double because even if we freeze an IFoo instance, it will never be injected because the default constructor is being invoked.

    +

    By default AutoFixture will use the default constructor which means that the Foo will always be the instance of DefaultFoo owned by the Bastard class itself. This is problematic if we wish to inject and freeze a Test Double because even if we freeze an IFoo instance, it will never be injected because the default constructor is being invoked.

    var fixture = new Fixture();
     fixture.Register<IFoo>(
    @@ -87,7 +87,7 @@ 

    2014-10-17 6:48 UTC

    - +

    Wes, thank you for writing. Let's continue the discussion over at that GitHub issue. diff --git a/_posts/2011-04-27-Providerisnotapattern.html b/_posts/2011-04-27-Providerisnotapattern.html index b4c364429..9578c3a74 100644 --- a/_posts/2011-04-27-Providerisnotapattern.html +++ b/_posts/2011-04-27-Providerisnotapattern.html @@ -18,7 +18,7 @@ No, it has nothing to do with DI, but as it tries to mimic loose coupling I can understand the confusion.

    - First things first. Let's start with the name. Is it a pattern at all? Regular readers of this blog may get the impression that I'm fond of calling everything and the kitchen sink an anti-pattern. That's not true because I only make that claim when I'm certain I can hold that position, so I'm not going to denounce Provider as an anti-pattern. On the contrary I will make the claim that Provider is not a pattern at all. + First things first. Let's start with the name. Is it a pattern at all? Regular readers of this blog may get the impression that I'm fond of calling everything and the kitchen sink an anti-pattern. That's not true because I only make that claim when I'm certain I can hold that position, so I'm not going to denounce Provider as an anti-pattern. On the contrary I will make the claim that Provider is not a pattern at all.

    A design pattern is not invented - it's discovered as a repeated solution to a commonly recurring problem. Providers, on the other hand, were invented by Microsoft, and I've rarely seen them used outside their original scope. Secondly I'd also dispute that they solve anything. @@ -33,7 +33,7 @@

  • It's not testable
  • - In the rest of this post I will explain each point in detail, but before I do that we need an example to look at. The old OrderProcessor example suffices, but instead of injecting IOrderValidator, IOrderCollector, and IOrderShipper this variation uses Providers to provide instances of the Services: + In the rest of this post I will explain each point in detail, but before I do that we need an example to look at. The old OrderProcessor example suffices, but instead of injecting IOrderValidator, IOrderCollector, and IOrderShipper this variation uses Providers to provide instances of the Services:

    public SuccessResult Process(Order order)
    @@ -120,7 +120,7 @@ 

  • The appropriate configuration section is not available in the app.config file.
  • The ValidatorTypeName is not provided, or is null, or is malformed.
  • The ValidatorTypeName is correctly formed, but the type in question cannot be located by Fusion.
  • -
  • The Type doesn't have a default constructor. This is one of the other problems of Constrained Construction: it can't be statically enforced because a constructor is not part of an abstraction's API.
  • +
  • The Type doesn't have a default constructor. This is one of the other problems of Constrained Construction: it can't be statically enforced because a constructor is not part of an abstraction's API.
  • The created type doesn't implement IOrderValidator.
  • @@ -168,7 +168,7 @@

    It is possible to use hard-coded Test Doubles such as Stubs or Fakes because we can configure the XML with their type names, but even a Spy is problematic because we'll rarely have an object reference to the Test Double.

    - In short, the Provider idiom is not a good approach to loose coupling. Although Microsoft uses it in some of their products, it only leads to problems, so there's no reason to mimic it. Instead, use Constructor Injection to create loosely coupled components and wire them in the application's Composition Root using the Register Resolve Release pattern. + In short, the Provider idiom is not a good approach to loose coupling. Although Microsoft uses it in some of their products, it only leads to problems, so there's no reason to mimic it. Instead, use Constructor Injection to create loosely coupled components and wire them in the application's Composition Root using the Register Resolve Release pattern.

    @@ -187,7 +187,7 @@

    2011-06-27 16:43 UTC

    - +
    I just reread the Bridge pattern and while I agree that Provider is a specialization of Bridge, I don't agree that this relationship goes the other way. If you read the description of Provider provided in the link above, you'll notice that it goes into very specific details on how a Provider should be implemented, including how it should be backed by the configuration system and that it must be created by clients by a static factory.

    This goes way beyond what the Bridge pattern describes, so I hardly think you can equate the two.
    @@ -231,7 +231,7 @@

    - +

    Luke, thank you for writing. Obviously, you are free to have your own opinions, and interpretation of various words. However, if we want to be able to discuss our trade in a concise manner, we need as precise a vocabulary as possible. @@ -323,7 +323,7 @@

    - +

    At the risk of coming across as a pedant, did you mean Provider when you wrote "Service Pattern"? At least, I'm not aware of any Service Pattern in the most commonly accepted pattern literature, but perhaps there's a book I should read. diff --git a/_posts/2011-04-29-Feedbackmechanismsandtradeoffs.html b/_posts/2011-04-29-Feedbackmechanismsandtradeoffs.html index cb4fc69be..eab426d5a 100644 --- a/_posts/2011-04-29-Feedbackmechanismsandtradeoffs.html +++ b/_posts/2011-04-29-Feedbackmechanismsandtradeoffs.html @@ -107,7 +107,7 @@

    2011-05-04 20:46 UTC

    - +
    I totally agree, and I was (and am still) planning on writing something about that in a later post. This is essentially the Fail Fast principle, but as for feedback mechanisms, we don't discover these Guard Clauses before we invoke them.

    My strong preference is for writing unit tests that invoke these Guard Clauses to verify that they work, and that means that as far as feedback mechanisms go, they fall into the unit testing 'bucket'.
    @@ -123,7 +123,7 @@

    2012-06-25 09:20 UTC

    - +
    IntelliSense is, I think, more of a learning tool. It's not really feedback about what you did - it's more information about what you can do. It's certainly a productivity feature, although there are some people who argue that it does more harm than good.
    2012-06-25 10:50 UTC
    @@ -136,7 +136,7 @@

    - +

    David, thank you for making these feedback cases explicit. When I originally wrote this article, I implicitly had such alternative, common-place feedback mechanisms in mind, but I never explicitly spelled them out. While I should have done that, I can now thank you for doing it; your comment is a good addition to the original article. diff --git a/_posts/2011-05-02-WindowsAzuremigrationsmellSQLServerover-utilization.html b/_posts/2011-05-02-WindowsAzuremigrationsmellSQLServerover-utilization.html index 31d028bda..22cd96030 100644 --- a/_posts/2011-05-02-WindowsAzuremigrationsmellSQLServerover-utilization.html +++ b/_posts/2011-05-02-WindowsAzuremigrationsmellSQLServerover-utilization.html @@ -8,6 +8,6 @@ {% include JB/setup %}

    -

    Recently I partook in a Windows Azure migration workshop, helping developers from existing development organizations port their applications to Windows Azure. Once more an old design smell popped up: SQL Server over-utilization. This ought to be old news to anyone with experience designing software on the Wintel stack, but apparently it bears repetition:

    Don't put logic in your database. SQL Server should be used only for persistent storage of data.

    (Yes: this post is written in 2011…)

    Many years ago I heard that role described as a ‘bit bucket' - you put in data and pull it out again, and that's all you do. No fancy stored procedures or functions or triggers.

    Why wouldn't we want to use the database if we have one? Scalability is the answer. SQL Server doesn't scale horizontally. You can't add more servers to take the load off a database server (well, some of my old colleagues will argue that this is possible with Oracle, and that may be true, but with SQL Server it's impossible).

    Yes, we can jump through hoops like partitioning and splitting the database up into several smaller databases, but it still doesn't give us horizontal scalability. SQL Server is a bottleneck in any system in which it takes part.

    How is this relevant to Windows Azure? It's relevant for two important reasons:

    • There's an upper size limit on SQL Azure. Currently that size limit is 50 GB, and while it's likely to grow in the future, there's going to be a ceiling for a long time.
    • You can't fine tune the hardware for performance. The server runs on virtual hardware.

    Development organizations that rely heavily on the database for execution of logic often need expensive hardware and experienced DBAs to squeeze extra performance out of the database servers. Such people know that write-intensive/append-only tables work best with one type of RAID, while read-intensive tables are better hosted on other file groups on different disks with different RAID configurations.

    With SQL Azure you can just forget about all that.

    The bottom line is that there are fundamental rules for software development that you must follow if you want to be able to successfully migrate to Windows Azure. I previously described an even simpler sanity check you should perform, but after that you should take a good look at your database.

    The best solution is if you can completely replace SQL Server with Azure's very scalable storage services, but those come with their own set of challenges.

    +

    Recently I partook in a Windows Azure migration workshop, helping developers from existing development organizations port their applications to Windows Azure. Once more an old design smell popped up: SQL Server over-utilization. This ought to be old news to anyone with experience designing software on the Wintel stack, but apparently it bears repetition:

    Don't put logic in your database. SQL Server should be used only for persistent storage of data.

    (Yes: this post is written in 2011…)

    Many years ago I heard that role described as a ‘bit bucket' - you put in data and pull it out again, and that's all you do. No fancy stored procedures or functions or triggers.

    Why wouldn't we want to use the database if we have one? Scalability is the answer. SQL Server doesn't scale horizontally. You can't add more servers to take the load off a database server (well, some of my old colleagues will argue that this is possible with Oracle, and that may be true, but with SQL Server it's impossible).

    Yes, we can jump through hoops like partitioning and splitting the database up into several smaller databases, but it still doesn't give us horizontal scalability. SQL Server is a bottleneck in any system in which it takes part.

    How is this relevant to Windows Azure? It's relevant for two important reasons:

    • There's an upper size limit on SQL Azure. Currently that size limit is 50 GB, and while it's likely to grow in the future, there's going to be a ceiling for a long time.
    • You can't fine tune the hardware for performance. The server runs on virtual hardware.

    Development organizations that rely heavily on the database for execution of logic often need expensive hardware and experienced DBAs to squeeze extra performance out of the database servers. Such people know that write-intensive/append-only tables work best with one type of RAID, while read-intensive tables are better hosted on other file groups on different disks with different RAID configurations.

    With SQL Azure you can just forget about all that.

    The bottom line is that there are fundamental rules for software development that you must follow if you want to be able to successfully migrate to Windows Azure. I previously described an even simpler sanity check you should perform, but after that you should take a good look at your database.

    The best solution is if you can completely replace SQL Server with Azure's very scalable storage services, but those come with their own set of challenges.

    \ No newline at end of file diff --git a/_posts/2011-05-09-GenericunittestingwithxUnit.net.html b/_posts/2011-05-09-GenericunittestingwithxUnit.net.html index 3071b37e4..59e8af273 100644 --- a/_posts/2011-05-09-GenericunittestingwithxUnit.net.html +++ b/_posts/2011-05-09-GenericunittestingwithxUnit.net.html @@ -27,7 +27,7 @@     Assert.Equal(result, first); }

    -

    In this test, I also use AutoFixture's xUnit.net extension, but that's completely optional. You might as well just write an old-fashioned unit test, but then you'll need a SUT Factory that can resolve generics. If you don't use AutoFixture any other (auto-mocking) container will do, and if you don't use one of those, you can define a Factory Method that creates appropriate instances of T (and, in this particular case, instances of IComparable<T>).

    +

    In this test, I also use AutoFixture's xUnit.net extension, but that's completely optional. You might as well just write an old-fashioned unit test, but then you'll need a SUT Factory that can resolve generics. If you don't use AutoFixture any other (auto-mocking) container will do, and if you don't use one of those, you can define a Factory Method that creates appropriate instances of T (and, in this particular case, instances of IComparable<T>).

    In the above example I used a [Theory], but I might as well have been using a [Fact] as long as I had a container or a Factory Method to create the appropriate instances.

    The above test doesn't execute in itself because the owning class is abstract. I needed to declare an appropriate set of constructed types for which I wanted the test to run. To do that, I defined the following test classes:

    diff --git a/_posts/2011-05-16-TennisKatawithimmutabletypesandacyclomaticcomplexityof1.html b/_posts/2011-05-16-TennisKatawithimmutabletypesandacyclomaticcomplexityof1.html index 1117dbc65..a9de1cca7 100644 --- a/_posts/2011-05-16-TennisKatawithimmutabletypesandacyclomaticcomplexityof1.html +++ b/_posts/2011-05-16-TennisKatawithimmutabletypesandacyclomaticcomplexityof1.html @@ -97,7 +97,7 @@     Assert.Equal(new FortyPoints(), game.PlayerTwoScore); }

    -

    In case you'd like to take a closer look at the code I'm attaching it to this post. It was driven completely by using the AutoFixture.Xunit extension, so if you are interested in idiomatic AutoFixture code it's also a good example of that.

    TennisKata.zip (3.09 MB) +

    In case you'd like to take a closer look at the code I'm attaching it to this post. It was driven completely by using the AutoFixture.Xunit extension, so if you are interested in idiomatic AutoFixture code it's also a good example of that.

    TennisKata.zip (3.09 MB)
    @@ -111,7 +111,7 @@

    2011-05-17 14:59 UTC

    - +
    Thanks :)
    2011-05-17 15:02 UTC
    diff --git a/_posts/2011-05-24-DesignSmellTemporalCoupling.html b/_posts/2011-05-24-DesignSmellTemporalCoupling.html index c91812fe3..8b31d0d4e 100644 --- a/_posts/2011-05-24-DesignSmellTemporalCoupling.html +++ b/_posts/2011-05-24-DesignSmellTemporalCoupling.html @@ -9,7 +9,7 @@

    - This post is the first in a series about Poka-yoke Design - also known as encapsulation. + This post is the first in a series about Poka-yoke Design - also known as encapsulation.

    A common problem in API design is temporal coupling, which occurs when there's an implicit relationship between two, or more, members of a class requiring clients to invoke one member before the other. This tightly couples the members in the temporal dimension. @@ -68,7 +68,7 @@

    var n = sut.Spread();

    - While it's possible to write unit tests that explore the behavior of the Smell class, it would be better if the design was improved to enable the compiler to provide feedback. + While it's possible to write unit tests that explore the behavior of the Smell class, it would be better if the design was improved to enable the compiler to provide feedback.

    Improvement: Constructor Injection # @@ -116,7 +116,7 @@

    }

    - In many cases the injected value (name) is unknown until run-time, in which case straight use of the constructor seems prohibitive - after all, the constructor is an implementation detail and not part of the loosely coupled API. When programming against an interface it's not possible to invoke the constructor. + In many cases the injected value (name) is unknown until run-time, in which case straight use of the constructor seems prohibitive - after all, the constructor is an implementation detail and not part of the loosely coupled API. When programming against an interface it's not possible to invoke the constructor.

    There's a solution for that as well. @@ -192,7 +192,7 @@

    2011-05-25 17:27 UTC

    - +
    Simon, exactly the opposite is true. With the Fragrance API you wouldn't have to deal with any runtime problems, because as soon as you can compile, the design of the code makes it very likely that it's also going to work at run-time (except for null values, which you can't escape no matter what you do).

    Getting feedback sooner is betting than getting feedback later. I much prefer getting a compiler error over a run-time exception.
    @@ -203,7 +203,7 @@

    2011-05-25 18:19 UTC

    - +
    Patrick, yes, that might be a possible variation, although perhaps a bit exotic... In which scenario would that be the case?
    2011-05-25 18:21 UTC
    @@ -217,7 +217,7 @@

    2011-05-26 07:08 UTC

    - +
    This blog post discusses two scenarios. The first scenario is that you have only the Smell class. In that scenario, you can replace the Smell class with the Fragrance class (minus the IFragrance interface). No new types are necessary, so you start out with one type and end up with one type.

    The second scenarios is when you have a Smell class implementing an ISmell interface. In that case you'd need to go from two to four types.
    @@ -235,7 +235,7 @@

    2011-05-27 10:49 UTC

    - +
    Use of a DI Container is IMO orthogonal to the issue.

    Conceptually it's best to think about any such factories as concrete classes. If they need to pass dependencies to the objects they create, they can do so by requesting them by Constructor Injection. In other words you are correct that "any dependencies that the concrete class needs will have to be passed to the factory class" (excluding those that are passed as parameters to the Create method).
    @@ -265,7 +265,7 @@

    2011-07-21 12:34 UTC

    - +
    Daniel, thank you for your insightful comment - you are completely correct.

    I just added the Guard Clause out of habit, but your arguments are valid and I will in the future be more careful with my Guard Clauses. It only makes sense that one should only have a Guard Clause if one uses the argument in question. That's not the case when it's just being passed on, so it should not be there.
    @@ -279,7 +279,7 @@

    2011-07-21 15:25 UTC

    - +
    Not at all - I'm happy that you pointed out something I hadn't properly considered. I learned something from it :)
    2011-07-21 15:28 UTC
    @@ -294,10 +294,10 @@

    2011-08-02 17:50 UTC

    - +
    Not at all (to both statements). A Fluent Interface doesn't rely on Temporal Coupling at all - I frequently implement Fluent APIs with immutable types.

    -See this blog post for a very simple example. For a very complex example, see AutoFixture's Ploeh.AutoFixture.Dsl namespace, which is kicked off by the fixture.Build<T>() method.
    +See this blog post for a very simple example. For a very complex example, see AutoFixture's Ploeh.AutoFixture.Dsl namespace, which is kicked off by the fixture.Build<T>() method.

    In any case, Temporal Coupling doesn't disallow mutability - it just states that if you have mutating methods, the order in which they are invoked (if at all) mustn't matter.
    2011-08-02 18:23 UTC
    @@ -309,7 +309,7 @@

    2011-09-16 14:32 UTC

    - +
    The most common approach is certainly to model Entities as mutable objects while Value Objects are kept immutable.

    When you use 'classic' CRUD-style Repositories or Unit of Work, that may also be the best match to that style of architecture. However, my more recent experience with CQRS and Event Sourcing seems to indicate to me that an immutable domain model begins to make a lot more sense. However, I've still to gain more experience with this before I can say anything with confidence.
    @@ -323,10 +323,10 @@

    2012-09-11 14:12 UTC

    - +
    An IFragranceFactory instance can be injected into any client that needs it, freeing it from having to create the tightly coupled instance itself.

    -The IFragranceFactory instance can be created in the Composition Root, potentially far removed from any clients. At this point it could be created with the 'new' keyword, or by a DI Container.
    +The IFragranceFactory instance can be created in the Composition Root, potentially far removed from any clients. At this point it could be created with the 'new' keyword, or by a DI Container.
    2012-09-11 15:43 UTC
    @@ -335,7 +335,7 @@

    2012-09-21 12:45 UTC

    - +
    Sorry, I didn't mean to confuse you...
    2012-09-21 13:15 UTC
    diff --git a/_posts/2011-05-24-Poka-yokeDesignFromSmelltoFragrance.html b/_posts/2011-05-24-Poka-yokeDesignFromSmelltoFragrance.html index 2c13dc595..2f7be6834 100644 --- a/_posts/2011-05-24-Poka-yokeDesignFromSmelltoFragrance.html +++ b/_posts/2011-05-24-Poka-yokeDesignFromSmelltoFragrance.html @@ -35,20 +35,20 @@

    Keep in mind that users are expected to not fully understand the internal implementation of a class. This makes it obvious what encapsulation is really about:

    Encapsulation is a fail-safe mechanism.

    -

    By corollary, encapsulation does not mean hiding complexity. Whenever complexity is hidden (as is the case for Providers) feedback time increases. Rapid feedback is much preferred, so delaying feedback is not desirable if it can be avoided.

    +

    By corollary, encapsulation does not mean hiding complexity. Whenever complexity is hidden (as is the case for Providers) feedback time increases. Rapid feedback is much preferred, so delaying feedback is not desirable if it can be avoided.

    Encapsulation is not about hiding complexity, but conversely exposing complexity in a fail-safe manner.

    -

    In Lean this is known as Poka-yoke, so I find it only fitting to think about encapsulation as Poka-yoke Design: APIs that make it as hard as possible to do the wrong thing. Considering that compilation is the cheapest feedback mechanism, it's preferable to design APIs so that the code can only compile when classes are used correctly.

    +

    In Lean this is known as Poka-yoke, so I find it only fitting to think about encapsulation as Poka-yoke Design: APIs that make it as hard as possible to do the wrong thing. Considering that compilation is the cheapest feedback mechanism, it's preferable to design APIs so that the code can only compile when classes are used correctly.

    In a series of blog posts I will look at various design smells that break encapsulation, as well as provide guidance on how to improve the design to make it safer, thus going from smell to fragrance.

      -
    1. Design Smell: Temporal Coupling -
    2. Design Smell: Primitive Obsession -
    3. Code Smell: Automatic Property -
    4. Design Smell: Redundant Required Attribute -
    5. Design Smell: Default Constructor
    6. -
    7. DI Container smell: Captive Dependency
    8. +
    9. Design Smell: Temporal Coupling +
    10. Design Smell: Primitive Obsession +
    11. Code Smell: Automatic Property +
    12. Design Smell: Redundant Required Attribute +
    13. Design Smell: Default Constructor
    14. +
    15. DI Container smell: Captive Dependency
    -

    Postscript: At the Boundaries, Applications are Not Object-Oriented

    +

    Postscript: At the Boundaries, Applications are Not Object-Oriented

    @@ -64,8 +64,8 @@

    2011-05-30 15:03 UTC

    @@ -80,7 +80,7 @@

    2011-06-01 16:22 UTC

    - +
    One thing at a time... There's a reason I themed this series of blog posts around fail-safing. I agree that encapsulation involves more than just that, but I don't think I ever said anything else.
    2011-06-01 18:52 UTC
    @@ -93,7 +93,7 @@

    2011-06-16 08:12 UTC

    - +
    Florian, I agree with your statement about Law of Demeter, although Fowler calls it 'the occasionally useful suggestion of Demeter' (or some such thing).

    I don't have any comment on the C++ const qualifier, as I have no idea what it does...
    @@ -116,7 +116,7 @@

    2011-06-21 11:30 UTC

    - +
    Sounds useful. Currently, Microsoft is making an effort along the same lines with Code Contracts, but although it's actually a released technology it still seems a bit immature to me.

    As I've been using TDD since 2003 I usually just codify my assumptions about invariants in the tests I write. A framework like Greg Young's Grensesnitt might also come in handy there.
    diff --git a/_posts/2011-05-25-DesignSmellPrimitiveObsession.html b/_posts/2011-05-25-DesignSmellPrimitiveObsession.html index 0d0389361..0cf353f04 100644 --- a/_posts/2011-05-25-DesignSmellPrimitiveObsession.html +++ b/_posts/2011-05-25-DesignSmellPrimitiveObsession.html @@ -9,13 +9,13 @@

    - This post is the second in a series about Poka-yoke Design - also known as encapsulation. + This post is the second in a series about Poka-yoke Design - also known as encapsulation.

    Many classes have a tendency to consume or expose primitive values like integers and strings. While such primitive types exist on any platform, they tend to lead to procedural code. Furthermore they often break encapsulation by allowing invalid values to be assigned.

    - This problem has been addressed many times before. Years ago Jimmy Bogard provided an excellent treatment of the issue, as well as guidance on how to resolve it. In relation to AutoFixture I also touched upon the subject some time ago. As such, the current post is mostly a placeholder. + This problem has been addressed many times before. Years ago Jimmy Bogard provided an excellent treatment of the issue, as well as guidance on how to resolve it. In relation to AutoFixture I also touched upon the subject some time ago. As such, the current post is mostly a placeholder.

    However, it's worth noting that both Jimmy's and my own post address the concern that strings and integers do not sufficiently encapsulate the concepts of Zip codes and phone numbers. @@ -40,7 +40,7 @@

    Improved Design #

    - Encapsulate the primitive value in a Value Object that contains appropriate Guard Clauses etc. to guarantee that only valid instances are possible. + Encapsulate the primitive value in a Value Object that contains appropriate Guard Clauses etc. to guarantee that only valid instances are possible.

    Primitives tend to not be fail-safe, but encapsulated Value Objects are. @@ -62,7 +62,7 @@

    2011-05-25 15:52 UTC

    - +
    I would very much like to be able to represent a quantity as a specialized class. Unfortunately uint is not a CLS-compliant type - otherwise I would use that one a lot.

    Keep in mind that I'm talking about a code smell. This means that whenever you encounter the smell it should make you stop and think. I'm not saying that using a primitive type is always wrong.
    @@ -82,8 +82,8 @@

    2011-05-31 22:38 UTC

    - -
    Thomas, did you see my post on application boundaries? I think it ought to answer your question :)
    + +
    Thomas, did you see my post on application boundaries? I think it ought to answer your question :)
    2011-06-01 05:45 UTC
    @@ -103,7 +103,7 @@

    - +

    Scott, thank you for writing. A Value Object can contain more than a single primitive value. The canonical Value Object example is Money, and you often see Money examples where a Money value is composed of an amount and a currency; one example in the literature is Kent Beck's implementation in Test Driven Development: By Example, which contains amount and currency. diff --git a/_posts/2011-05-26-CodeSmellAutomaticProperty.html b/_posts/2011-05-26-CodeSmellAutomaticProperty.html index 2222bb7f0..bc94dccc0 100644 --- a/_posts/2011-05-26-CodeSmellAutomaticProperty.html +++ b/_posts/2011-05-26-CodeSmellAutomaticProperty.html @@ -9,7 +9,7 @@

    - This post is the third in a series about Poka-yoke Design - also known as encapsulation. + This post is the third in a series about Poka-yoke Design - also known as encapsulation.

    Automatic properties are one of the most redundant features of C#. I know that some people really love them, but they address a problem you shouldn't have in the first place. @@ -98,7 +98,7 @@

    Code Smell: Automatic Value Type Property #

    - If the type of the property is a value type, the case is less clear-cut because value types can't be null. This means that a Null Guard is never appropriate. However, directly consuming a value type may still be inappropriate. In fact, it's only appropriate if the class can meaningfully accept and handle any value of that type. + If the type of the property is a value type, the case is less clear-cut because value types can't be null. This means that a Null Guard is never appropriate. However, directly consuming a value type may still be inappropriate. In fact, it's only appropriate if the class can meaningfully accept and handle any value of that type.

    If, for example, the class can really only handle a certain subset of all possible values, a Guard Clause must be introduced. Consider this example: @@ -202,19 +202,19 @@

    2011-05-26 14:25 UTC

    - +
    James, thanks for pointing that out. I've now corrected the error.
    2011-05-26 18:31 UTC
    - +
    Omer, a boolean property falls into that rare case described during the discussion of value type properties. If the class exposing the property truly can accept any value that the type can possibly take, an automatic property is in order. A boolean value can only take one of two values, and both are legal. Thus, no Guard Clause is required. However, please notice that this scenario is not (or at least should not be) representative.

    Regarding ORMs you are now jumping ahead of me :) I'll come to that in a later blog post, but yes, I genuinely believe that the whole concept of an ORM (at least in any incarnations I've seen so far) is a fallacy.
    2011-05-26 18:39 UTC
    - +
    Ben, you are correct that the issue is at least most prevalent when the setter is public. However, keep in mind that we should always treat protected as public, as anyone can always come by and derive from a class.

    For private setters it's not so clear-cut. In most cases when I have read-only properties it tends to be because the property is being supplied through the constructor and subsequently treated as immutable. When that is the case, I much prefer a backing field because it can be declared as readonly.
    @@ -225,7 +225,7 @@

    2011-05-26 18:50 UTC

    - +
    Alex, see my previous comment regarding { get; private set; }

    Regarding { get; readonly set; } I would probably use something like this assuming this was something that could only be used from the constructor, because I'd still be able to add the appropriate Guard Clause in the constructor before invoking the setter.
    @@ -239,7 +239,7 @@

    2011-05-27 07:52 UTC

    - +
    If the value is optional a public setter is in order. However, allowing the field to be null is not, as it would require the rest of the class to have to check for null every time it uses the field. A Null Object is a better alternative, which again leads to the rule that a Null Guard is always appropriate for reference types. However, in certain cases, that Null Guard might not throw an exception, but rather replace the null with a Null Object.
    2011-05-29 08:55 UTC
    @@ -257,8 +257,8 @@

    2011-05-30 09:18 UTC

    - -
    Theo, please see my latest post that touches on exactly that point.
    + +
    Theo, please see my latest post that touches on exactly that point.
    2011-05-31 18:11 UTC
    @@ -279,8 +279,8 @@

    2012-01-10 17:04 UTC

    - - + +
    2012-01-15 16:40 UTC
    @@ -289,7 +289,7 @@

    2018-03-20 14:15 UTC

    - +

    Juliano, thank you for writing. You're right that after the publication of this post, C# got more features, at least one of which seems to relate to this article. When I write C# code today, I often use automatic read-only properties, combined with appropriate Guard Clauses in the constructor. I find that a useful language feature. diff --git a/_posts/2011-05-27-DesignSmellRedundantRequiredAttribute.html b/_posts/2011-05-27-DesignSmellRedundantRequiredAttribute.html index bfdc31961..1c2af46de 100644 --- a/_posts/2011-05-27-DesignSmellRedundantRequiredAttribute.html +++ b/_posts/2011-05-27-DesignSmellRedundantRequiredAttribute.html @@ -9,7 +9,7 @@

    - This post is the fourth in a series about Poka-yoke Design - also known as encapsulation. + This post is the fourth in a series about Poka-yoke Design - also known as encapsulation.

    Recently I saw this apparently enthusiastic tweet reporting from some Microsoft technology event: @@ -30,7 +30,7 @@ }

    - Every time I see something like this I die a little inside. If you already read my previous posts it should by now be painfully clear why this breaks encapsulation. Despite the [Required] attribute there's no guarantee that the Id property will ever be assigned a value. The attribute is just a piece of garbage making a claim it can't back up. + Every time I see something like this I die a little inside. If you already read my previous posts it should by now be painfully clear why this breaks encapsulation. Despite the [Required] attribute there's no guarantee that the Id property will ever be assigned a value. The attribute is just a piece of garbage making a claim it can't back up.

    Code like that is not fail-safe. @@ -61,7 +61,7 @@

    }

    - This simple structural design ensures that the ID truly is required (and if the ID can only be positive a Guard Clause can be added). An instance of Fragrance can only be created with an ID. Since this is a structural construction, the compiler can enforce the requirement, giving us rapid feedback. + This simple structural design ensures that the ID truly is required (and if the ID can only be positive a Guard Clause can be added). An instance of Fragrance can only be created with an ID. Since this is a structural construction, the compiler can enforce the requirement, giving us rapid feedback.

    I do realize that the [Required] attribute mentioned above is intended to address the challenge of mapping objects to relational data and rendering, but instead of closing the impedance mismatch gap, it widens it. Instead of introducing yet another redundant attribute the team should have made their tool understand simple idioms for encapsulation like the one above. @@ -107,14 +107,14 @@

    2011-05-27 15:19 UTC

    - +
    Ben, if all you have "is a piece of data that you want to display on a web page" you're most likely in the CRUD application scenario. There are cases where this is indeed the correct solution to a business problem. It's perfectly fine, but it has nothing to do with object-orientation.

    This whole series of posts about Poka-yoke Design are about encapsulation, which is an object-oriented principle. And yes: when it comes to OOD I'd never use EF (or any other ORM) if it requires me to break encapsulation.
    2011-05-28 21:29 UTC
    - +
    Craig, I agree that when it comes to user input validation, using an attribute on one or more properties with very loose invariants is the best solution. In general, when at the boundary of an application, it's always best to assume that input can be invalid in all sorts of ways. This is true for UI input as well as automated input (XML, CSV, JSON, etc.). Thus, any 'object' modeling an application boundary data structure is essentially not encapsulated.

    However, it would be a grave mistake if we let UI concerns drive the design of our domain models. Thus, as soon as we know that we have a case of valid input data on our hands, we must translate it to a proper encapsulated object. From that point on (including db schema design) an attribute would certainly be redundant.
    @@ -130,7 +130,7 @@

    2011-05-31 14:56 UTC

    - +
    When you say 'BO', do you mean 'Boundary Object' or 'Business Object'? It seems to me that you might use both abbreviations in the same sentence... or I'm totally missing something :)
    2011-05-31 18:19 UTC
    @@ -140,7 +140,7 @@

    2011-05-31 20:39 UTC

    - +
    Gotcha! Agreed :)
    2011-05-31 20:40 UTC
    diff --git a/_posts/2011-05-30-DesignSmellDefaultConstructor.html b/_posts/2011-05-30-DesignSmellDefaultConstructor.html index 35d5993ee..f3d4065de 100644 --- a/_posts/2011-05-30-DesignSmellDefaultConstructor.html +++ b/_posts/2011-05-30-DesignSmellDefaultConstructor.html @@ -9,7 +9,7 @@

    - This post is the fifth in a series about Poka-yoke Design - also known as encapsulation. + This post is the fifth in a series about Poka-yoke Design - also known as encapsulation.

    Default constructors are code smells. There you have it. That probably sounds outrageous, but consider this: object-orientation is about encapsulating behavior and data into cohesive pieces of code (classes). Encapsulation means that the class should protect the integrity of the data it encapsulates. When data is required, it must often be supplied through a constructor. Conversely, a default constructor implies that no external data is required. That's a rather weak statement about the invariants of the class. @@ -23,10 +23,10 @@

    - If you have read my book you will know that Constructor Injection is the dominating DI pattern exactly because it statically advertises dependencies and protects the integrity of those dependencies by guaranteeing that an initialized consumer is always in a consistent state. This is fail-safe design because the compiler can enforce the relationship, thus providing rapid feedback. + If you have read my book you will know that Constructor Injection is the dominating DI pattern exactly because it statically advertises dependencies and protects the integrity of those dependencies by guaranteeing that an initialized consumer is always in a consistent state. This is fail-safe design because the compiler can enforce the relationship, thus providing rapid feedback.

    - This principle extends far beyond DI. In a previous post I described how a constructor with arguments statically advertises that the argument is required: + This principle extends far beyond DI. In a previous post I described how a constructor with arguments statically advertises that the argument is required:

    public class Fragrance : IFragrance
    @@ -50,7 +50,7 @@
     }

    - The Fragrance class protects the integrity of the name by requiring it through the constructor. Since this class requires the name to implement its behavior, requesting it through the constructor is the correct thing to do. A default constructor would not have been fail-safe, since it would introduce a temporal coupling. + The Fragrance class protects the integrity of the name by requiring it through the constructor. Since this class requires the name to implement its behavior, requesting it through the constructor is the correct thing to do. A default constructor would not have been fail-safe, since it would introduce a temporal coupling.

    Consider that objects are supposed to be containers of behavior and data. Whenever an object contains data, the data must be encapsulated. In the (very common) case where no meaningful default value can be defined, the data must be provided via the constructor. Thus, default constructors might indicate that encapsulation is broken. @@ -127,8 +127,8 @@

    2011-05-31 15:29 UTC

    - -
    Martin, Bob, Ken, I wrote this postscript that essentially explains why such boundary code isn't object-oriented code. At the boundaries, encapsulation doesn't apply.
    + +
    Martin, Bob, Ken, I wrote this postscript that essentially explains why such boundary code isn't object-oriented code. At the boundaries, encapsulation doesn't apply.
    2011-05-31 18:17 UTC
    @@ -144,7 +144,7 @@

    2011-06-05 07:39 UTC

    - +
    structs aren't evil - as with most other language constructs, it's a matter of understanding when and how to apply them. Basically, a struct is (or should be) a specialized representation of a number. Int32, Decimal, DateTime, TimeSpan etc. all fall into this category, and if you have a similar domain-specific concept in you code base, a struct could be a good representation as long as 0 is a valid value. A hypothetical Temperature type would be an excellent candidate.

    An example where a struct was inappropriately applied would by Guid, whose default value is Guid.Empty. Making Guid a struct adds no value because you'd always conceptually have to check whether you just received Guid.Empty. Had Guid been a reference type we could just have checked for null, but with this design choice we need to have special cases for handling exactly Guids. This means that we have to write special code that deals only with Guids, instead of code that just deals with any reference type.
    diff --git a/_posts/2011-05-31-AttheBoundaries,ApplicationsareNotObject-Oriented.html b/_posts/2011-05-31-AttheBoundaries,ApplicationsareNotObject-Oriented.html index 7b9e74ede..b98b02ec4 100644 --- a/_posts/2011-05-31-AttheBoundaries,ApplicationsareNotObject-Oriented.html +++ b/_posts/2011-05-31-AttheBoundaries,ApplicationsareNotObject-Oriented.html @@ -9,7 +9,7 @@

    - My recent series of blog posts about Poka-yoke Design generated a few responses (I would have been disappointed had this not been the case). Quite a few of these reactions relate to various serialization or translation technologies usually employed at application boundaries: Serialization, XML (de)hydration, UI validation, etc. Note that such translation happens not only at the perimeter of the application, but also at the persistence layer. ORMs are also a translation mechanism. + My recent series of blog posts about Poka-yoke Design generated a few responses (I would have been disappointed had this not been the case). Quite a few of these reactions relate to various serialization or translation technologies usually employed at application boundaries: Serialization, XML (de)hydration, UI validation, etc. Note that such translation happens not only at the perimeter of the application, but also at the persistence layer. ORMs are also a translation mechanism.

    Common to most of the comments is that lots of serialization technologies require the presence of a default constructor. As an example, the XmlSerializer requires a default constructor and public writable properties. Most ORMs I've investigated seem to have the same kind of requirements. Windows Forms and WPF Controls (UI is also an application boundary) also must have default constructors. Doesn't that break encapsulation? Yes and no. @@ -49,7 +49,7 @@

    Yes, and that means they are not objects. A DTO is a representation of such a piece of data mapped into an object-oriented language. That still doesn't make them objects in the sense of encapsulation. It would be impossible. Since all input is suspect, we can hardly enforce any invariants at all.

    - Often, as Craig Stuntz points out in a comment to one of my previous posts, even if the input is invalid, we want to capture what we did receive in order to present a proper error message (this argument also applies on machine-to-machine boundaries). This means that any DTO must have very weak invariants (if any at all). + Often, as Craig Stuntz points out in a comment to one of my previous posts, even if the input is invalid, we want to capture what we did receive in order to present a proper error message (this argument also applies on machine-to-machine boundaries). This means that any DTO must have very weak invariants (if any at all).

    @@ -60,7 +60,7 @@

    Don't be fooled by your tooling. The .NET framework very, very much wants you to treat DTOs as objects. Code generation ensues.

    - However, the strong typing provided by such auto-generated classes gives a false sense of security. You may think that you get rapid feedback from the compiler, but there are many possible ways you can get run-time errors (most notably when you forget to update the auto-generated code based on new schema versions). + However, the strong typing provided by such auto-generated classes gives a false sense of security. You may think that you get rapid feedback from the compiler, but there are many possible ways you can get run-time errors (most notably when you forget to update the auto-generated code based on new schema versions).

    An even more problematic result of representing input and output as objects is that it tricks lots of developers into dealing with them as though they represent the real object model. The result is invariably an anemic domain model. @@ -81,7 +81,7 @@

    Another option is to stop treating data as objects and start treating it as the structured data that it really is. It would be really nice if our programming language had a separate concept of structured data… Interestingly, while C# has nothing of the kind, F# has tons of ways to model data structures without behavior. Perhaps that's a more honest approach to dealing with data… I will need to experiment more with this…

    - A third option is to look towards dynamic types. In his article Cutting Edge: Expando Objects in C# 4.0, Dino Esposito outlines a dynamic approach towards consuming structured data that shortcuts auto-generated code and provides a lightweight API to structured data. This also looks like a promising approach… It doesn't provide compile-time feedback, but that's only a false sense of security anyway. We must resort to unit tests to get rapid feedback, but we're all using TDD already, right? + A third option is to look towards dynamic types. In his article Cutting Edge: Expando Objects in C# 4.0, Dino Esposito outlines a dynamic approach towards consuming structured data that shortcuts auto-generated code and provides a lightweight API to structured data. This also looks like a promising approach… It doesn't provide compile-time feedback, but that's only a false sense of security anyway. We must resort to unit tests to get rapid feedback, but we're all using TDD already, right?

    In summary, my entire series about encapsulation relates to object-oriented programming. Although there are lots of technologies available to represent boundary data as ‘objects', they are false objects. Even if we use an object-oriented language at the boundary, the code has nothing to do with object orientation. Thus, the Poka-yoke Design rules don't apply there. @@ -109,7 +109,7 @@

    2011-05-31 16:37 UTC

    - +
    Phil, when you write 'Entity' I immediately think about the definition provided in "Domain-Driven Design". Those Entities are definitely Domain Objects which should have lots of behavior, but I'm getting the feeling that you're thinking about something else?
    2011-05-31 18:22 UTC
    @@ -121,7 +121,7 @@

    2011-05-31 22:09 UTC

    - +
    Yes, we might compose real domain objects from DTOs, but I'm not sure that is the best solution. When we map non-object-oriented structures to objects, they tend to drag along a lot of baggage which hurts OO modeling.

    For instance, generating DTOs from a database schema provides an entire static structure (relationships, etc.) that tend to constrain us when we subsequently attempt to define an object model. I rather prefer being able to work unconstrained and then subsequently figure out how to persist it.
    @@ -133,7 +133,7 @@

    2011-06-01 08:29 UTC

    - +
    Yes, that's what I've been doing for the last couple of years, but the downside is the maintenance overhead. That's why I, in the last part of the post, discuss alternatives. Currently I think that using dynamic types looks most promising.

    Keep in mind that in most cases, a DTO is not an end-goal in itself. Rather, the end-goal is often the wire-representation of the DTO (XML, JSON, etc.). Wouldn't it be better if we could just skip the DTO altogether and use a bit of convention-based (and testable) dynamic code to make that translation directly?
    @@ -159,12 +159,12 @@

    2011-06-01 14:34 UTC

    - +
    Florian, in WCF it is possible to drop down to the message-level and write directly to the message. Even so, I'm not sure I'd go that route, but it's good to know that the option exists.
    2011-06-01 18:43 UTC
    - +
    Boyan, I was specifically thinking about dropping down to IDataReader. For one example, please refer to Tomas Petricek's article Dynamic in F#: Reading data from SQL database.
    2011-06-01 18:46 UTC
    @@ -187,7 +187,7 @@

    2011-06-02 02:37 UTC

    - +
    Makes sense. I mainly used the term 'translation layer' as I assumed that most people would then immediately know what I meant :)
    2011-06-02 06:51 UTC
    @@ -197,7 +197,7 @@

    2011-06-02 09:50 UTC

    - +
    Sorry about that. This blog is running on dasBlog which was last updated two years ago. Migrating the blog to a better engine is on my to-do list, but it'll be a couple of months at least before I get there.
    2011-06-02 10:07 UTC
    @@ -213,7 +213,7 @@

    2011-06-04 15:51 UTC

    - +
    I agree on the rule of never putting any behavior on an EF entity (although, still, I used to put a translation method on most of them: ToDomainObject(), but still...).

    My personal experience with EF was that even with code generation, it was far from frictionless, but YMMV...
    @@ -234,7 +234,7 @@

    2011-06-05 11:18 UTC

    - +
    The point being made here is that despite the name, DTOs aren't 'objects'. It's certainly possible to create a complex application entirely with DTOs - it's just not object-oriented.

    There may be nothing wrong with that, but if you decide that you need object-orientation to solve a business problem, you must transform DTOs into proper objects, because it's impossible to make OOD with DTOs.
    @@ -265,12 +265,12 @@

    2011-06-08 14:14 UTC

    - +
    Yes, we can take it further, but I don't believe that one approach necessarily rules out the other. However, it depends on how you decide to pass around structured data.

    If you do it in a request/response style (even mapped into internal code), I'd say that you'd be doing procedural programming.

    -However, if you do it as Commands, passing structured data to void methods, you'd basically be heading in the direction of Pipes and Filters architecture. That's actually a very good place to be.
    +However, if you do it as Commands, passing structured data to void methods, you'd basically be heading in the direction of Pipes and Filters architecture. That's actually a very good place to be.
    2011-06-09 09:47 UTC
    @@ -291,7 +291,7 @@

    - +

    The "different matter" of interpretation is that you need to be able to interpret and validate the incoming data, before you turn it into a Domain Object. An encapsulated Domain Object should throw exceptions if you attempt to create invalid instances, so unless you want to catch exceptions and surface them at the boundary, you'll need to be able to validate the input before you create the Domain Object. @@ -340,7 +340,7 @@

    2015-12-19 1:40 UTC

    - +

    Dmitry, thank you for writing. This purpose of this post is mostly to help people realise that, as the title says, at the boundaries, applications aren't Object-Oriented (and neither are they Functional). Beyond that, the article is hardly prescriptive. While the What Should Happen at the Boundary section muses on ways to deal with input and output, I hope it doesn't suggest that there are any silver bullets that address these problems. diff --git a/_posts/2011-06-07-SOLIDCodeisnt.html b/_posts/2011-06-07-SOLIDCodeisnt.html index e0dcbbcd6..e580a8fc7 100644 --- a/_posts/2011-06-07-SOLIDCodeisnt.html +++ b/_posts/2011-06-07-SOLIDCodeisnt.html @@ -14,7 +14,7 @@ Recently I had an interesting conversation with a developer at my current client, about how the SOLID principles would impact their code base. The client wants to write SOLID code - who doesn't? It's a beautiful acronym that fully demonstrates the power of catchy terminology.

    - However, when you start to outline what it actually means people become uneasy. At the point where the discussion became interesting, I had already sketched my view on encapsulation. However, the client's current code base is designed around validation at the perimeter. Most of the classes in the Domain Model are actually internal and implicitly trust input. + However, when you start to outline what it actually means people become uneasy. At the point where the discussion became interesting, I had already sketched my view on encapsulation. However, the client's current code base is designed around validation at the perimeter. Most of the classes in the Domain Model are actually internal and implicitly trust input.

    We were actually discussing Test-Driven Development, and I had already told them that they should only test against the public API of their code base. The discussion went something like this (I'm hoping I'm not making my ‘opponent' sound dumb, because the real developer I talked to was anything but): diff --git a/_posts/2011-07-28-CompositionRoot.html b/_posts/2011-07-28-CompositionRoot.html index 4e45caaf2..c33d2c6b5 100644 --- a/_posts/2011-07-28-CompositionRoot.html +++ b/_posts/2011-07-28-CompositionRoot.html @@ -39,7 +39,7 @@

    - This means that all the application code relies solely on Constructor Injection (or other injection patterns), but is never composed. Only at the entry point of the application is the entire object graph finally composed. + This means that all the application code relies solely on Constructor Injection (or other injection patterns), but is never composed. Only at the entry point of the application is the entire object graph finally composed.

    The appropriate entry point depends on the framework: @@ -63,7 +63,7 @@

    - The Composition Root can be implemented with Poor Man's DI Pure DI, but is also the (only) appropriate place to use a DI Container. + The Composition Root can be implemented with Poor Man's DI Pure DI, but is also the (only) appropriate place to use a DI Container.

    @@ -71,7 +71,7 @@

    - Using a DI Container is often a good choice. In that case it should be applied using the Register Resolve Release pattern entirely from within the Composition Root. + Using a DI Container is often a good choice. In that case it should be applied using the Register Resolve Release pattern entirely from within the Composition Root.

    Read more in Dependency Injection in .NET. @@ -89,12 +89,12 @@

    2011-08-02 03:24 UTC

    - +
    Each application/process requires only a single Composition Root. It doesn't matter how complex the application is.

    The earlier you compose, the more you limit your options, and there's simply no reason to do that.

    -You may or may not find this article helpful - otherwise, please write again :)
    +You may or may not find this article helpful - otherwise, please write again :)
    2011-08-02 07:56 UTC
    @@ -114,7 +114,7 @@

    2011-09-29 11:57 UTC

    - +
    The problem with letting each module register their own types to any sort of container is that it tightly couples the modules (and any application in which you might want to use them) to a specific container. Even worse, if you ever need to consume a service provided by one module from another module, you'd have to couple these two to each other. Pretty soon, you'll end up with a tightly coupled mess.

    One option is to use whichever DI Container you'd like from the Composition Root, and use its XML capabilities to configure the modules into each particular application that needs them. That's always possible, but adds some overhead, and is rarely required.
    @@ -133,8 +133,8 @@

    2011-10-21 16:09 UTC

    - -
    Why would your UI depend on DTOs? A Data Transfer Object plays the role of a boundary data carrier, just like View Model might do - they fit architecturally at the same place of application architecture: at the boundary. If you base your inner architecture upon DTOs you'll be headed in the direction of an Anemic Domain Model, so that doesn't sound a particularly good idea to me...
    + +
    Why would your UI depend on DTOs? A Data Transfer Object plays the role of a boundary data carrier, just like View Model might do - they fit architecturally at the same place of application architecture: at the boundary. If you base your inner architecture upon DTOs you'll be headed in the direction of an Anemic Domain Model, so that doesn't sound a particularly good idea to me...
    2011-10-23 09:05 UTC
    @@ -159,7 +159,7 @@

    2011-10-25 00:17 UTC

    - +
    It may just be that we use the terminology different, but according to Patterns of Enterprise Application Architecture "a Data Transfer Object is one of those objects our mothers told us never to write. It's often little more than a bunch of fields and the getters and setters for them."

    The purpose of a DTO is "to transfer multiple items of data between two processes in a single method call." That is (I take it) not what you are attempting to do here.
    @@ -177,10 +177,10 @@

    2013-01-12 10:09 UTC

    - -
    Jordan, would the Virtual Proxy pattern be of help here?
    + +
    Jordan, would the Virtual Proxy pattern be of help here?

    -You can use one of the solutions outlined in my recent series on Role Hints to avoid referencing a container outside of the Composition Root.
    +You can use one of the solutions outlined in my recent series on Role Hints to avoid referencing a container outside of the Composition Root.
    2013-01-12 21:17 UTC
    @@ -188,7 +188,7 @@

    Hi Mark

    I wanted to post the following comment on your linked page, here
    -http://blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence
    +/2011/03/04/Composeobjectgraphswithconfidence
    but I am encountering a page error on submission.

    The above article suggests a great framework for delayed construction of resources, however I have a different reason for wanting this than loading an assembly.
    @@ -207,7 +207,7 @@

    2013-01-13 23:07 UTC

    - +
    I'll refer you to section 6.2 in my book regarding lifetime management and the closing of resources. However, if things aren't disposable, you can also just let them go out of scope again and let the garbage collector take care of cleaning up.

    I can't help you with Ninject.
    @@ -235,19 +235,19 @@

    - +

    - Allan, thank you for writing. In the end, you'll need to do what makes sense to you, and based on what you write, it may make sense to do what you do. Still, my first reaction is that I would probably tend to worry less about duplication than you seem to do. However, I don't know your particular project: neither how big your Composition Roots are, or how often they change. In other words, it's easy enough for me to say that a bit of duplication is okay, but that may not fit your reality at all. + Allan, thank you for writing. In the end, you'll need to do what makes sense to you, and based on what you write, it may make sense to do what you do. Still, my first reaction is that I would probably tend to worry less about duplication than you seem to do. However, I don't know your particular project: neither how big your Composition Roots are, or how often they change. In other words, it's easy enough for me to say that a bit of duplication is okay, but that may not fit your reality at all.

    - Another point is that, in my experience at least, even if you have different applications (web sites, services, console applications, etc.) as part of the same overall system, and they share code, the way they should be composed tend to diverge the longer they live. This is reminiscent of Mathias Verraes' point that duplication may be coincidental, but that the duplicated code may deviate from each other in the future. This could also happen for such applications; e.g. at one point, you may wish to instrument some of your web site's dependencies, but not your batch job. + Another point is that, in my experience at least, even if you have different applications (web sites, services, console applications, etc.) as part of the same overall system, and they share code, the way they should be composed tend to diverge the longer they live. This is reminiscent of Mathias Verraes' point that duplication may be coincidental, but that the duplicated code may deviate from each other in the future. This could also happen for such applications; e.g. at one point, you may wish to instrument some of your web site's dependencies, but not your batch job.

    My best advice is to build smaller systems, in order to keep complexity down, and then build more of them, rather than building big systems. Again, that advice may not be useful in your case...

    - Another option, since you mention component-based design, is to move towards a convention-based approach, so that you don't have to maintain those Composition Roots at all: just drop in the binaries, and let your DI Container take care of the rest. Take a look at the Managed Extensibility Framework (MEF) for inspiration. Still, while MEF exposes some nice ideas, and is a good source of inspiration, I would personally chose to do something like this with a proper DI Container that also supports run-time Interception and programmable Pointcuts. + Another option, since you mention component-based design, is to move towards a convention-based approach, so that you don't have to maintain those Composition Roots at all: just drop in the binaries, and let your DI Container take care of the rest. Take a look at the Managed Extensibility Framework (MEF) for inspiration. Still, while MEF exposes some nice ideas, and is a good source of inspiration, I would personally chose to do something like this with a proper DI Container that also supports run-time Interception and programmable Pointcuts.

    In the end, I think I understand your problem, but my overall reaction is that you seem to have a problem you shouldn't have, so my priority would be: @@ -264,7 +264,7 @@

    - It seems that I have a certan inclination for reopening "old" posts. + It seems that I have a certan inclination for reopening "old" posts. Still the may be considered evergreens! :) Now back on topic.

    @@ -306,10 +306,10 @@

    2014-09-18 07:17 UTC

    - +

    - Mario, thank you for writing. If you're writing an SDK, you are writing either a library or a framework, so the Composition Root pattern isn't appropriate (as stated above). Instead, consider the guidelines for writing DI friendly libraries or DI friendly frameworks. + Mario, thank you for writing. If you're writing an SDK, you are writing either a library or a framework, so the Composition Root pattern isn't appropriate (as stated above). Instead, consider the guidelines for writing DI friendly libraries or DI friendly frameworks.

    So, in order to answer your specific questions: @@ -318,13 +318,13 @@

    1: Conceptually, there should only be a single Composition Root, but it belongs to the application, so as a library developer, then no: 'you' can't have any Composition Root.

    - 2: A library shouldn't trigger any composition, but as I explain in my guidelines for writing DI friendly libraries, you can provide Facades to make the learning curve gentle. For frameworks, you may need to provide appropriate Abstract Factories. + 2: A library shouldn't trigger any composition, but as I explain in my guidelines for writing DI friendly libraries, you can provide Facades to make the learning curve gentle. For frameworks, you may need to provide appropriate Abstract Factories.

    - 3: The performance impact of Composition shouldn't be a major concern. However, the real problem of attempting to apply the Composition Root pattern where it doesn't apply is that it increases coupling and takes away options that the client developer may want to utilize; e.g. how can a client developer instrument a sub-graph with Decorators if that sub-graph isn't available? + 3: The performance impact of Composition shouldn't be a major concern. However, the real problem of attempting to apply the Composition Root pattern where it doesn't apply is that it increases coupling and takes away options that the client developer may want to utilize; e.g. how can a client developer instrument a sub-graph with Decorators if that sub-graph isn't available?

    - 4: There are better ways to design DI friendly libraries and DI friendly frameworks. + 4: There are better ways to design DI friendly libraries and DI friendly frameworks.

    2014-09-18 08:12 UTC
    @@ -361,7 +361,7 @@

    2014-09-18 12:57 UTC

    - +

    Mario, thank you for writing again. As far as I understand, you basically have this scenario: @@ -407,7 +407,7 @@

    }

    - If you want the best of both worlds, the solution is the Facade pattern I already described in my DI Friendly library article. + If you want the best of both worlds, the solution is the Facade pattern I already described in my DI Friendly library article.

    2014-09-19 19:56 UTC
    @@ -488,10 +488,10 @@

    2014-09-22 10:07 UTC

    - +

    - Mario, you don't want the user of your library to know about the dependencies, in order to make it easy to use the SDK. That's fine: this goal is easily achieved with one of those Facade patterns I've already described. With either Constructor Chaining, or use of the Fluent Builder pattern, you can make it as easy to get started with FancyCalculator as possible: just invoke its parameterless constructor. + Mario, you don't want the user of your library to know about the dependencies, in order to make it easy to use the SDK. That's fine: this goal is easily achieved with one of those Facade patterns I've already described. With either Constructor Chaining, or use of the Fluent Builder pattern, you can make it as easy to get started with FancyCalculator as possible: just invoke its parameterless constructor.

    What then, is your motivation for wanting to make the other constructors internal? What do you gain from doing that? @@ -520,7 +520,7 @@

    2014-09-25 20:10 UTC

    - +

    Robert, thank you for writing. Your guess sounds reasonable. Even assuming that this is the case, I find it important to preface my answer with the caution that since I don't know the entire context, my answer is, at best, based on mainstream scenarios I can think of. There may be contexts where this approach is, indeed, the best solution, but in my experience, this tends not to be the case. @@ -535,13 +535,13 @@

    .NET has suffered from a combination of fear of breaking backwards compatibility, combined with Big Design Up-Front (BDUF). The fact that (after all) it's still quite useful is a testament to the people who originally designed it; these people were (or are) some of most skilled people in the industry. Unless you're Anders Hejlsberg, Krzysztof Cwalina, Brad Abrams, or on a similar level, you can't expect to produce a useful and stable API if you take the conservative BDUF approach.

    - Instead, what you can do is to use TDD to explore the design of your API. This doesn't guarantee that you'll end up with a stable API, but it does help to make the API as useful as possible. + Instead, what you can do is to use TDD to explore the design of your API. This doesn't guarantee that you'll end up with a stable API, but it does help to make the API as useful as possible.

    - How do you ensure stability, then? One option is to realise that you can use interfaces as access modifiers. Thus, you can publish a library that mostly contains interfaces and a few high-level classes, and then add the public implementations of those interfaces in other libraries, and clearly document that these types are not guaranteed to remain stable. This option may be useful in some contexts, but if you're really exposing an API to the wild, you probably need a more robust strategy. + How do you ensure stability, then? One option is to realise that you can use interfaces as access modifiers. Thus, you can publish a library that mostly contains interfaces and a few high-level classes, and then add the public implementations of those interfaces in other libraries, and clearly document that these types are not guaranteed to remain stable. This option may be useful in some contexts, but if you're really exposing an API to the wild, you probably need a more robust strategy.

    - The best strategy I've been able to identify so far is to realise that you can't design a stable API up front. You will make mistakes, and you will need to deal with these design mistakes. One really effective strategy is to apply the Strangler pattern: leave the design mistakes in, but add new, better APIs as you learn; SOLID is append-only. In my Encapsulation and SOLID Pluralsight course, I discuss this particular problem and approach in the Append-Only section of the Liskov Substitution Principle module. + The best strategy I've been able to identify so far is to realise that you can't design a stable API up front. You will make mistakes, and you will need to deal with these design mistakes. One really effective strategy is to apply the Strangler pattern: leave the design mistakes in, but add new, better APIs as you learn; SOLID is append-only. In my Encapsulation and SOLID Pluralsight course, I discuss this particular problem and approach in the Append-Only section of the Liskov Substitution Principle module.

    2014-09-28 13:40 UTC
    @@ -568,7 +568,7 @@

    2014-09-28 18:12 UTC

    - +

    Please note that I'm not saying that internal or private classes are always bad; all I'm saying is that unit testing internal classes (presumably using the [InternalsVisibleTo] attribute) is, in my opinion, not a good idea. @@ -616,7 +616,7 @@

    - Thank to Mark Seemann for his very inspiring write about Composition Root design pattern, http://blog.ploeh.dk/2011/07/28/CompositionRoot/ + Thank to Mark Seemann for his very inspiring write about Composition Root design pattern, /2011/07/28/CompositionRoot/

    I wrote my own JavaScript Dependency Injection Framework called Di-Ninja with these principles in mind https://github.com/di-ninja/di-ninja diff --git a/_posts/2011-08-25-ServiceLocatorrolesvs.mechanics.html b/_posts/2011-08-25-ServiceLocatorrolesvs.mechanics.html index 7ae21d486..788527fa6 100644 --- a/_posts/2011-08-25-ServiceLocatorrolesvs.mechanics.html +++ b/_posts/2011-08-25-ServiceLocatorrolesvs.mechanics.html @@ -7,7 +7,7 @@ {% include JB/setup %}

    -

    It's time to take a step back from the whole debate about whether or not Service Locator is, or isn't, an anti-pattern. It remains my strong belief that it's an anti-pattern, while others disagree. Although everyone is welcome to think differently than me, I've noticed that some of the arguments being put forth in defense of Service Locator seem very convincing. However, I believe that in those cases we no longer talk about Service Locator, but something that looks an awful lot like it.

    Some APIs are easy to confuse with a ‘real' Service Locator. It probably doesn't help that last year I published an article on how to tell the difference between a Service Locator and an Abstract Factory. In this article I may have focused too much on the mechanics of Service Locator, but as Derick Bailey was so kind to point out, this hides the role the API might play.

    To repeat that earlier post, a Service Locator looks like this:

    +

    It's time to take a step back from the whole debate about whether or not Service Locator is, or isn't, an anti-pattern. It remains my strong belief that it's an anti-pattern, while others disagree. Although everyone is welcome to think differently than me, I've noticed that some of the arguments being put forth in defense of Service Locator seem very convincing. However, I believe that in those cases we no longer talk about Service Locator, but something that looks an awful lot like it.

    Some APIs are easy to confuse with a ‘real' Service Locator. It probably doesn't help that last year I published an article on how to tell the difference between a Service Locator and an Abstract Factory. In this article I may have focused too much on the mechanics of Service Locator, but as Derick Bailey was so kind to point out, this hides the role the API might play.

    To repeat that earlier post, a Service Locator looks like this:

    public interface IServiceLocator
     {
    @@ -21,7 +21,7 @@
     

    Even AutoFixture has an API like that:

    MyClass sut = fixture.CreateAnonymous<MyClass>();

    It has never been my intention to denounce every single DI container available, as well as my own open source framework. Service Locator is ultimately not identified by the mechanics of its API, but by the role it plays.

    -

    A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.

    +

    A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.

    It becomes a Service Locator if used incorrectly: when application code (as opposed to infrastructure code) actively queries a service in order to be provided with required dependencies, then it has become a Service Locator.

    Service Locators are spread thinly and pervasively throughout a code base - that is just as much a defining characteristic.

    @@ -38,10 +38,10 @@

    2011-08-26 08:53 UTC

    - +
    Service Locator is, in my opinion, always an anti-pattern. However, a class with a Service Locator-like signature does not in itself constitute a Service Locator - it has to be used like a Service Locator to be one.

    -A DI Container is not, in itself, a Service Locator, but it can be used like one. If you do that, it's an anti-pattern, but that doesn't mean that any use of a container constitutes an anti-pattern. When a container is used according to the Register Resolve Release pattern from within a Composition Root it's all good.
    +A DI Container is not, in itself, a Service Locator, but it can be used like one. If you do that, it's an anti-pattern, but that doesn't mean that any use of a container constitutes an anti-pattern. When a container is used according to the Register Resolve Release pattern from within a Composition Root it's all good.
    2011-08-26 09:22 UTC

    @@ -50,7 +50,7 @@

    2011-08-26 15:34 UTC

    - +
    Yes, well, nobody's perfect :/ Thanks for pointing that out. My mistake. 'Symmetric' is the correct term - I'll see if I can manage to include that correction in the book. It's close, but I think it'll be possible to correct it.
    2011-08-28 19:41 UTC
    @@ -77,7 +77,7 @@

    2011-12-04 18:28 UTC

    - +
    Composing an object graph in WPF is no different than in any other application. In WPF, using the MVVM pattern, you shouldn't compose Windows but rather ViewModels. In the case where the ViewModels rely on run-time values, you can use an Abstract Factory.
    2011-12-05 10:46 UTC
    @@ -137,7 +137,7 @@

    2011-12-07 18:06 UTC

    - +
    Does the code download for the book work for you?
    2011-12-07 18:21 UTC
    diff --git a/_posts/2011-09-06-AutoFixturegoesContinuousDeliverywithSemanticVersioning.html b/_posts/2011-09-06-AutoFixturegoesContinuousDeliverywithSemanticVersioning.html index 50bbf5d0d..ba6ecd12a 100644 --- a/_posts/2011-09-06-AutoFixturegoesContinuousDeliverywithSemanticVersioning.html +++ b/_posts/2011-09-06-AutoFixturegoesContinuousDeliverywithSemanticVersioning.html @@ -7,6 +7,6 @@ {% include JB/setup %}
    -

    For the last couple of months I've been working on setting up AutoFixture for Continuous Delivery (thanks to the nice people at http://teamcity.codebetter.com/ for supplying the CI service) and I think I've finally succeeded. I've just pushed some code from my local Mercurial repository, and 5 minutes later the release is live on both the CodePlex site as well as on the NuGet Gallery.

    The plan for AutoFixture going forward is to maintain Continuous Delivery and switch the versioning scheme from ad hoc to Semantic Versioning. This means that obviously you'll see releases much more often, and versions are going to be incremented much more often. Since the previous release the current release incidentally ended at version 2.2.44, but since the versioning scheme has now changed, you can expect to see 2.3, 2.4 etc. in rapid succession.

    While I've been mostly focused on setting up Continuous Delivery, Nikos Baxevanis and Enrico Campidoglio have been busy writing new features:

    Apart from these excellent contributions, other new features are

    • Added StableFiniteSequenceCustomization
    • Added [FavorArrays], [FavorEnumerables] and [FavorLists] attributes to xUnit.net extension
    • Added a Generator<T> class
    • Added a completely new project/package called Idioms, which contains convention-based tests (more about this later)
    • Probably some other things I've forgotten about…

    While you can expect to see version numbers to increase more rapidly and releases to occur more frequently, I'm also beginning to think about AutoFixture 3.0. This release will streamline some of the API in the root namespace, which, I'll admit, was always a bit haphazard. For those people who care, I have no plans to touch the API in the Ploeh.AutoFixture.Kernel namespace. AutoFixture 3.0 will mainly target the API contained in the Ploeh.AutoFixture namespace itself.

    Some of the changes I have in mind will hopefully make the default experience with AutoFixture more pleasant - I'm unofficially thinking about AutoFixture 3.0 as the ‘pit of success' release. It will also enable some of the various outstanding feature requests.

    Feedback is, as usual, appreciated.

    +

    For the last couple of months I've been working on setting up AutoFixture for Continuous Delivery (thanks to the nice people at http://teamcity.codebetter.com/ for supplying the CI service) and I think I've finally succeeded. I've just pushed some code from my local Mercurial repository, and 5 minutes later the release is live on both the CodePlex site as well as on the NuGet Gallery.

    The plan for AutoFixture going forward is to maintain Continuous Delivery and switch the versioning scheme from ad hoc to Semantic Versioning. This means that obviously you'll see releases much more often, and versions are going to be incremented much more often. Since the previous release the current release incidentally ended at version 2.2.44, but since the versioning scheme has now changed, you can expect to see 2.3, 2.4 etc. in rapid succession.

    While I've been mostly focused on setting up Continuous Delivery, Nikos Baxevanis and Enrico Campidoglio have been busy writing new features:

    Apart from these excellent contributions, other new features are

    • Added StableFiniteSequenceCustomization
    • Added [FavorArrays], [FavorEnumerables] and [FavorLists] attributes to xUnit.net extension
    • Added a Generator<T> class
    • Added a completely new project/package called Idioms, which contains convention-based tests (more about this later)
    • Probably some other things I've forgotten about…

    While you can expect to see version numbers to increase more rapidly and releases to occur more frequently, I'm also beginning to think about AutoFixture 3.0. This release will streamline some of the API in the root namespace, which, I'll admit, was always a bit haphazard. For those people who care, I have no plans to touch the API in the Ploeh.AutoFixture.Kernel namespace. AutoFixture 3.0 will mainly target the API contained in the Ploeh.AutoFixture namespace itself.

    Some of the changes I have in mind will hopefully make the default experience with AutoFixture more pleasant - I'm unofficially thinking about AutoFixture 3.0 as the ‘pit of success' release. It will also enable some of the various outstanding feature requests.

    Feedback is, as usual, appreciated.

    \ No newline at end of file diff --git a/_posts/2011-09-19-MessageDispatchingwithoutServiceLocation.html b/_posts/2011-09-19-MessageDispatchingwithoutServiceLocation.html index 21b281603..9b7efe019 100644 --- a/_posts/2011-09-19-MessageDispatchingwithoutServiceLocation.html +++ b/_posts/2011-09-19-MessageDispatchingwithoutServiceLocation.html @@ -9,10 +9,10 @@

    - Once upon a time I wrote a blog post about why Service Locator is an anti-pattern, and ever since then, I occasionally receive rebuffs from people who agree with me in principle, but think that, still: in various special cases (the argument goes), Service Locator does have its uses. + Once upon a time I wrote a blog post about why Service Locator is an anti-pattern, and ever since then, I occasionally receive rebuffs from people who agree with me in principle, but think that, still: in various special cases (the argument goes), Service Locator does have its uses.

    - Most of these arguments actually stem from mistaking the mechanics for the role of a Service Locator. Still, once in a while a compelling argument seems to come my way. One of the most insistent arguments concerns message dispatching - a pattern which is currently gaining in prominence due to the increasing popularity of CQRS, Domain Events and kindred architectural styles. + Most of these arguments actually stem from mistaking the mechanics for the role of a Service Locator. Still, once in a while a compelling argument seems to come my way. One of the most insistent arguments concerns message dispatching - a pattern which is currently gaining in prominence due to the increasing popularity of CQRS, Domain Events and kindred architectural styles.

    In this article I'll first provide a quick sketch of the scenario, followed by a typical implementation based on a ‘Service Locator', and then conclude by demonstrating why a Service Locator isn't necessary. @@ -30,7 +30,7 @@

    }

    - Personally, I find that the generic typing of the Send method is entirely redundant (not to mention heavily reminiscent of the shape of a Service Locator), but it's very common and not particularly important right now (but more about that later). + Personally, I find that the generic typing of the Send method is entirely redundant (not to mention heavily reminiscent of the shape of a Service Locator), but it's very common and not particularly important right now (but more about that later).

    An application might use the IChannel interface like this: @@ -119,7 +119,7 @@

  • Does it use a Service Locator? No.
  • - While AutofacChannel uses Autofac (a DI Container) to implement the functionality, it's not (necessarily) a Service Locator in action. This was the point I already tried to get across in my previous post about the subject: just because its mechanics look like Service Locator it doesn't mean that it is one. In my implementation, the AutofacChannel class is a piece of pure infrastructure code. I even made it a private nested class in my Composition Root to underscore the point. The container is still not available to the application code, so is never used in the Service Locator role. + While AutofacChannel uses Autofac (a DI Container) to implement the functionality, it's not (necessarily) a Service Locator in action. This was the point I already tried to get across in my previous post about the subject: just because its mechanics look like Service Locator it doesn't mean that it is one. In my implementation, the AutofacChannel class is a piece of pure infrastructure code. I even made it a private nested class in my Composition Root to underscore the point. The container is still not available to the application code, so is never used in the Service Locator role.

    One of the shortcomings about the above implementations is that it provides no fallback mechanism. What happens if the container can't resolve the matching consumer? Perhaps there isn't a consumer for the message. That's entirely possible because there are no safeguards in place to ensure that there's a consumer for every possibly message. @@ -233,7 +233,7 @@

    My claim still stands #

    - In conclusion, I find that I can still defend my original claim: Service Locator is an anti-pattern. + In conclusion, I find that I can still defend my original claim: Service Locator is an anti-pattern.

    That claim, by the way, is falsifiable, so I do appreciate that people take it seriously enough by attempting to disprove it. However, until now, I've yet to be presented with a scenario where I couldn't come up with a better solution that didn't involve a Service Locator. @@ -254,7 +254,7 @@

    2011-09-19 19:37 UTC

    - +
    AutofacChannel (and PoorMansChannel) is a private class that implements a public interface (IChannel). Since IChannel is a public interface, it can be consumed by any class that needs it.
    2011-09-19 19:46 UTC
    @@ -271,7 +271,7 @@

    2011-09-19 20:03 UTC

    - +
    Thanks for contacting me about this. Yes, I'd like to discuss this further, but I think we should take this via e-mail so as to not tire all my other readers :) You can email me at mark(guess which sign goes here)seemann.ms.
    2011-09-19 20:10 UTC
    @@ -295,7 +295,7 @@

    2011-09-19 20:48 UTC

    - +
    Phil

    Thanks for writing.
    @@ -314,7 +314,7 @@

    2011-09-20 14:41 UTC

    - +
    Martin

    I had that problem previously, but I thought I fixed it months ago. From where I'm sitting, the code looks OK both in Google Reader on the Web, Google Reader on Android as well as FeedDemon. Can you share exactly where and how it looks unreadable?
    @@ -330,19 +330,19 @@

    2011-09-25 15:06 UTC

    - +
    Martin, I agree that the screen shot looks strange, but across multiple machines and browsers I've been unable to reproduce it, so it's quite difficult for me to troubleshoot. Do you have any idea what might cause this problem?
    2011-09-26 10:48 UTC
    Martin
    -
    Update: I found the reason for the problem: it seems I was subscribed to the Atom feed (http://blog.ploeh.dk/SyndicationService.asmx/GetAtom). After unsubscribing and resubscribing to the Rss feed (http://blog.ploeh.dk/SyndicationService.asmx/GetRss), the code snippets look OK.
    +
    Update: I found the reason for the problem: it seems I was subscribed to the Atom feed (/SyndicationService.asmx/GetAtom). After unsubscribing and resubscribing to the Rss feed (/SyndicationService.asmx/GetRss), the code snippets look OK.

    Thanks.
    2011-09-26 13:15 UTC
    - +
    Good :) Thanks for the update.
    2011-09-26 14:20 UTC
    @@ -360,7 +360,7 @@

    2011-10-09 10:14 UTC

    - +
    Daniel, I think you reached the correct conclusion already. As you say, you could always create a Poor Man's implementation of that factory.

    It'd be particularly clean if you could inject an Abstract Factory into your NHibernate infrastructure and keep the container itself isolated to the Composition Root. In any case I agree that this sounds like pure infrastructure code, so it doesn't sound like Service Location.
    @@ -380,7 +380,7 @@

    2012-05-04 08:29 UTC

    - +
    The way we tend to think about messaging-based applications today (e.g. with CQRS, or Udi Dahan-style SOA), messages are only related to the domain models. Thus, any messaging gateway (like an IBus interface or similar) is only required by the domain model.

    It's not too hard to implement a message bus on top of a queue system, but it might be worth taking a look at NServiceBus or Rebus.
    @@ -402,10 +402,10 @@

    - +

    - Kenneth, thank you for writing. Your question reminded my of my series about Role Hints, particularly Metadata, Role Interface, and Partial Type Name Role Hints. The examples in those posts aren't generically typed, but I wonder if you might still find those patterns useful? + Kenneth, thank you for writing. Your question reminded my of my series about Role Hints, particularly Metadata, Role Interface, and Partial Type Name Role Hints. The examples in those posts aren't generically typed, but I wonder if you might still find those patterns useful?

    2014-02-23 08:11 UTC
    @@ -430,13 +430,13 @@

    - +

    Martijn, thank you for writing. The golden rule for decommissioning is that the object responsible for composing the object graph should also be responsible for releasing it. That's what some DI Containers (Castle Windsor, Autofac, MEF) do - typically using a Release method. The reason for that is that only the Composer knows if there are any nodes in the object graph that should be disposed of, so only the Composer can properly decommission an object graph.

    - You can also implement that Resolve/Release pattern using Pure DI. If you're writing a framework, you may need to define an Abstract Factory with an associated Release method, but otherwise, you can just release the graph when you're done with it. + You can also implement that Resolve/Release pattern using Pure DI. If you're writing a framework, you may need to define an Abstract Factory with an associated Release method, but otherwise, you can just release the graph when you're done with it.

    In the present article, you're correct that I haven't addressed the lifetime management aspect. The Composer here is the last code snippet that composes the PoorMansChannel object. As shown here, the entire object graph has the same lifetime as the PoorMansChannel object, but I don't describe whether or not it's a Singleton, Per Graph, Transient, or something else. However, the code that creates the PoorMansChannel object should also be the code that releases it, if that's required. diff --git a/_posts/2011-09-23-Weakly-typedversusStrongly-typedMessageChannels.html b/_posts/2011-09-23-Weakly-typedversusStrongly-typedMessageChannels.html index f4211f2b8..9be078bc6 100644 --- a/_posts/2011-09-23-Weakly-typedversusStrongly-typedMessageChannels.html +++ b/_posts/2011-09-23-Weakly-typedversusStrongly-typedMessageChannels.html @@ -7,14 +7,14 @@ {% include JB/setup %}

    -

    Soon after I posted my previous blog post on message dispatching without Service Location I received an email from Jeff Saunders with some great observations. Jeff has been so kind to allow me to quote his email here on the blog, so here it is:

    “I enjoyed your latest blog post about message dispatching. I have to ask, though: why do we want weakly-typed messages? Why can't we just inject an appropriate IConsumer<T> into our services - they know which messages they're going to send or receive.

    “A really good example of this is ISubject<T> from Rx. It implements both IObserver<T> (a message consumer) and IObservable<T> (a message producer) and the default implementation Subject<T> routes messages directly from its IObserver side to its IObservable side.

    “We can use this with DI quite nicely - I have written an example in .NET Pad: http://dotnetpad.net/ViewPaste/woTkGk6_GEq3P9xTVEJYZg#c9,c26,

    “The good thing about this is that we now have access to all of the standard LINQ query operators and the new ones added in Rx, so we can use a select query to map messages between layers, for instance.

    “This way we get all the benefits of a weakly-typed IChannel interface, with the added advantages of strong typing for our messages and composability using Rx.

    “One potential benefit of weak typing that could be raised is that we can have just a single implementation for IChannel, instead of an ISubject<T> for each message type. I don't think this is really a benefit, though, as we may want different propagation behaviour for each message type - there are other implementations of ISubject<T> that call consumers asynchronously, and we could pass any IObservable<T> or IObserver<T> into a service for testing purposes.”

    These are great observations and I think that Rx holds much promise in this space. Basically you can say that in CQRS-style architectures we're already pushing events (and commands) around, so why not build upon what the framework offers?

    Even if you find the IObserver<T> interface a bit too clunky with its OnNext, OnError and OnCompleted methods compared to the strongly typed IConsumer<T> interface, the question still remains: why do we want weakly-typed messages?

    We don't, necessarily. My previous post wasn't meant as a particular endorsement of a weakly typed messaging channel. It was more an observation that I've seen many variations of this IChannel interface:

    +

    Soon after I posted my previous blog post on message dispatching without Service Location I received an email from Jeff Saunders with some great observations. Jeff has been so kind to allow me to quote his email here on the blog, so here it is:

    “I enjoyed your latest blog post about message dispatching. I have to ask, though: why do we want weakly-typed messages? Why can't we just inject an appropriate IConsumer<T> into our services - they know which messages they're going to send or receive.

    “A really good example of this is ISubject<T> from Rx. It implements both IObserver<T> (a message consumer) and IObservable<T> (a message producer) and the default implementation Subject<T> routes messages directly from its IObserver side to its IObservable side.

    “We can use this with DI quite nicely - I have written an example in .NET Pad: http://dotnetpad.net/ViewPaste/woTkGk6_GEq3P9xTVEJYZg#c9,c26,

    “The good thing about this is that we now have access to all of the standard LINQ query operators and the new ones added in Rx, so we can use a select query to map messages between layers, for instance.

    “This way we get all the benefits of a weakly-typed IChannel interface, with the added advantages of strong typing for our messages and composability using Rx.

    “One potential benefit of weak typing that could be raised is that we can have just a single implementation for IChannel, instead of an ISubject<T> for each message type. I don't think this is really a benefit, though, as we may want different propagation behaviour for each message type - there are other implementations of ISubject<T> that call consumers asynchronously, and we could pass any IObservable<T> or IObserver<T> into a service for testing purposes.”

    These are great observations and I think that Rx holds much promise in this space. Basically you can say that in CQRS-style architectures we're already pushing events (and commands) around, so why not build upon what the framework offers?

    Even if you find the IObserver<T> interface a bit too clunky with its OnNext, OnError and OnCompleted methods compared to the strongly typed IConsumer<T> interface, the question still remains: why do we want weakly-typed messages?

    We don't, necessarily. My previous post wasn't meant as a particular endorsement of a weakly typed messaging channel. It was more an observation that I've seen many variations of this IChannel interface:

    public interface IChannel
     {
         void Send<T>(T message);
     }

    -

    The most important thing I wanted to point out was that while the generic type argument may create the illusion that this is a strongly typed method, this is all it is: an illusion. IChannel isn't strongly typed because you can invoke the Send method with any type of message - and the code will still compile. This is no different than the mechanical distinction between a Service Locator and an Abstract Factory.

    +

    The most important thing I wanted to point out was that while the generic type argument may create the illusion that this is a strongly typed method, this is all it is: an illusion. IChannel isn't strongly typed because you can invoke the Send method with any type of message - and the code will still compile. This is no different than the mechanical distinction between a Service Locator and an Abstract Factory.

    Thus, when defining a channel interface I normally prefer to make this explicit and instead model it like this:

    public interface IChannel
    @@ -24,7 +24,7 @@
     

    This achieves exactly the same and is more honest.

    Still, this doesn't really answer Jeff's question: is this preferable to one or more strongly typed IConsumer<T> dependencies?

    -

    Any high-level application entry point that relies on a weakly typed IChannel can get by with a single IChannel dependency. This is flexible, but (just like with Service Locator), it might hide that the client may have (or (d)evolve) too many responsibilities.

    +

    Any high-level application entry point that relies on a weakly typed IChannel can get by with a single IChannel dependency. This is flexible, but (just like with Service Locator), it might hide that the client may have (or (d)evolve) too many responsibilities.

    If, instead, the client would rely on strongly typed dependencies it becomes much easier to see if/when it violates the Single Responsibility Principle.

    In conclusion, I'd tend to prefer strongly typed Datatype Channels instead of a single weakly typed channel, but one shouldn't underestimate the flexibility of a general-purpose channel either.

    diff --git a/_posts/2011-10-25-SOLIDconcrete.html b/_posts/2011-10-25-SOLIDconcrete.html index 4c0f26187..169ca8154 100644 --- a/_posts/2011-10-25-SOLIDconcrete.html +++ b/_posts/2011-10-25-SOLIDconcrete.html @@ -52,7 +52,7 @@

    2011-10-25 18:15 UTC

    - +
    The RAP fills the same type of role as unit testing/TDD: theoretically, it's possible to write testable code without writing a single unit test against it, but how do you know?

    It's the same thing with the RAP: how can you know that it's possible to exchange one implementation of an interface with another if you've never tried it? Keep in mind that Test Doubles don't count because you can always create a bogus implementation of any interface. You could have an interface that's one big leaky abstraction: even though it's an interface, you can never meaningfully replace that single implementation with any other meaningful production implementation.
    @@ -73,10 +73,10 @@

    2011-10-26 04:16 UTC

    - +
    Nelson, I think we agree :) To me, the RAP is not an absolute rule, but just another guideline/metric. If none of my interfaces have multiple implementations, I start to worry about the quality of my abstractions, but I don't find it problematic if some of my interfaces have only a single implementation.

    -Your discussion about interfaces fit well with the Interface Segregation Principle and the concept of Role Interfaces, and I've also previously described how interfaces act as access modifiers.
    +Your discussion about interfaces fit well with the Interface Segregation Principle and the concept of Role Interfaces, and I've also previously described how interfaces act as access modifiers.
    2011-10-26 08:37 UTC
    \ No newline at end of file diff --git a/_posts/2011-11-08-Independency.html b/_posts/2011-11-08-Independency.html index 25d1db5c4..00465bbf7 100644 --- a/_posts/2011-11-08-Independency.html +++ b/_posts/2011-11-08-Independency.html @@ -8,7 +8,7 @@ {% include JB/setup %}
    -

    Now that my book about Dependency Injection is out, it's only fitting that I also invert my own dependencies by striking out as an independent consultant/advisor. In the future I'm hoping to combine my writing and speaking efforts, as well as my open source interests, with helping out clients write better code.

    If you'd like to get help with Dependency Injection or Test-Driven Development, SOLID, API design, application architecture or one of the other topics I regularly cover here on my blog, I'm available as a consultant worldwide.

    When it comes to Windows Azure, I'll be renewing my alliance with my penultimate employer Commentor, so you can also hire me as part of larger deal with Commentor.

    In case you are wondering what happened to my employment with AppHarbor, I resigned from my position there because I couldn't make it work with all the other things I also would like to do. I still think AppHarbor is a very interesting project, and I wish my former employers the best of luck with their endeavor.

    This has been a message from the blog's sponsor (myself). Soon, regular content will resume.

    +

    Now that my book about Dependency Injection is out, it's only fitting that I also invert my own dependencies by striking out as an independent consultant/advisor. In the future I'm hoping to combine my writing and speaking efforts, as well as my open source interests, with helping out clients write better code.

    If you'd like to get help with Dependency Injection or Test-Driven Development, SOLID, API design, application architecture or one of the other topics I regularly cover here on my blog, I'm available as a consultant worldwide.

    When it comes to Windows Azure, I'll be renewing my alliance with my penultimate employer Commentor, so you can also hire me as part of larger deal with Commentor.

    In case you are wondering what happened to my employment with AppHarbor, I resigned from my position there because I couldn't make it work with all the other things I also would like to do. I still think AppHarbor is a very interesting project, and I wish my former employers the best of luck with their endeavor.

    This has been a message from the blog's sponsor (myself). Soon, regular content will resume.

    diff --git a/_posts/2011-11-10-TDDimprovesreusability.html b/_posts/2011-11-10-TDDimprovesreusability.html index 49c79de83..20c7ba938 100644 --- a/_posts/2011-11-10-TDDimprovesreusability.html +++ b/_posts/2011-11-10-TDDimprovesreusability.html @@ -56,7 +56,7 @@

    2012-05-11 09:13 UTC

    - +
    I rarely use code coverage tools. Since I develop code almost exclusively with TDD, I know my coverage is good.

    I still occasionally use code coverage tools when I work in a team environment, so I have nothing against them. When I do, I just use the coverage tool which is built into Visual Studio. When used with the TestDriven.NET Visual Studio add-in it's quite friction-less.
    diff --git a/_posts/2011-12-07-PolymorphicConsistency.html b/_posts/2011-12-07-PolymorphicConsistency.html index 5ae6c89bd..04dea2093 100644 --- a/_posts/2011-12-07-PolymorphicConsistency.html +++ b/_posts/2011-12-07-PolymorphicConsistency.html @@ -236,7 +236,7 @@

    2011-12-08 13:38 UTC

    - +
    Why not? You can combine the async functionality with the approach described above. It could make the application more efficient, since it would free up a thread while the first transaction is being completed.

    However, while the async CTP makes it easier to write asynchronous code, it doesn't help with blocking calls. It may be more efficient, but not necessarily faster. You can't know whether or not a transaction has committed until it actually happens, so you still need to wait for that before you decide whether or not to proceed.
    @@ -256,7 +256,7 @@

    2011-12-14 21:23 UTC

    - +
    A HUD is exactly the sort of scenario that a must be implemented by a synchronous write. If you want to be sure that the persisted data is ACID consistent, it must be written as a synchronous, blocking operation. This means that once the query side comes along, it can simply read from the same persistent store because it's always up to date. That sort of persisted data isn't eventually consistent - it's atomically consistent.
    2011-12-21 08:08 UTC
    diff --git a/_posts/2011-12-19-FactoryOverload.html b/_posts/2011-12-19-FactoryOverload.html index c59a8c956..7942d3c1c 100644 --- a/_posts/2011-12-19-FactoryOverload.html +++ b/_posts/2011-12-19-FactoryOverload.html @@ -235,7 +235,7 @@

    }

    - Now it's entirely up to the Composition Root to compose SomeConsumer with the correct modifiers, and while this can be done manually, it's an excellent case for a DI Container and a bit of Convention over Configuration. + Now it's entirely up to the Composition Root to compose SomeConsumer with the correct modifiers, and while this can be done manually, it's an excellent case for a DI Container and a bit of Convention over Configuration.

    Conclusion # @@ -320,7 +320,7 @@

    2012-01-09 06:48 UTC

    - +
    Eber, let me quoute myself from this particular post: "I think the easiest way to address these variations would be to algorithmically build the strings from a couple of templates". A lookup table falls into that category, so I agree that such a thing would be easier if at all possible.

    The whole premise of the rest of the post is that for some reason, it's more complicated than that...
    diff --git a/_posts/2011-12-21-TestingContainerConfigurations.html b/_posts/2011-12-21-TestingContainerConfigurations.html index 8f3f09aa1..fb553584f 100644 --- a/_posts/2011-12-21-TestingContainerConfigurations.html +++ b/_posts/2011-12-21-TestingContainerConfigurations.html @@ -50,7 +50,7 @@

    To understand the answer, consider the set of all components contained in the container in this figure:

    - +

    The container contains the set of components IFoo, IBar, IBaz, Foo, Bar, Baz, and Qux so a self-test will try to create a single instance of each of these seven types. If all seven instances can be created, the test succeeds. @@ -157,7 +157,7 @@

    2011-12-28 19:23 UTC

    - +
    That sounds like a brittle test, because instead of testing the 'what' you'd be testing the 'how'.
    2011-12-29 07:50 UTC
    @@ -188,7 +188,7 @@

    2012-02-03 18:16 UTC

    - +
    Thomas, the point of IQux is that, in the example, the container doesn't know about the IQux interface. A container self-test is only going to walk through all components to see if they can be resolved. However, such a test will never attempt to resolve IQux, since the container doesn't know about it.

    So, if an application code base requires IQux, the application is going to fail even when the container self-test succeeds.
    @@ -200,7 +200,7 @@

    2012-02-05 11:10 UTC

    - +
    Yes - that's why a container self-test is worthless. The container doesn't know about the requirements of you application. All it can do is to test whether or not it's internally consistent. It doesn't tell you anything about its ability to resolve the object graphs your application is going to need.
    2012-02-05 12:02 UTC
    @@ -210,7 +210,7 @@

    2012-06-05 09:10 UTC

    - +
    I'm not sure I can agree with that - that sounds a bit like Cargo Culting to me... The point of the RAP is that it tells us something about the degree of abstraction of our interfaces. If the sole purpose of adding a Null Object implementation is to adhere to the RAP, it may address the mechanics of the RAP, but not the spirit</i>.
    2012-06-05 09:18 UTC
    @@ -222,7 +222,7 @@

    such a method is close to worthless

    and without a working example of a better way you explain why you are right. I am an avid reader of your posts and often reference them but IMO this particular argument is not well reasoned.

    -

    Your opening argument explains why you may have an issue when using the Service Locator anti-pattern:

    +

    Your opening argument explains why you may have an issue when using the Service Locator anti-pattern:

    an application could require instances of the ICorge, Corge or Grault types which are completely external to the configuration, in which case resolution would fail.

    diff --git a/_posts/2012-01-03-SOLIDisAppend-only.html b/_posts/2012-01-03-SOLIDisAppend-only.html index 927e930ac..922654684 100644 --- a/_posts/2012-01-03-SOLIDisAppend-only.html +++ b/_posts/2012-01-03-SOLIDisAppend-only.html @@ -9,7 +9,7 @@

    - SOLID is a set of principles that, if applied consistently, has some surprising effect on code. In a previous post I provided a sketch of what it means to meticulously apply the Single Responsibility Principle. In this article I will describe what happens when you follow the Open/Closed Principle (OCP) to its logical conclusion. + SOLID is a set of principles that, if applied consistently, has some surprising effect on code. In a previous post I provided a sketch of what it means to meticulously apply the Single Responsibility Principle. In this article I will describe what happens when you follow the Open/Closed Principle (OCP) to its logical conclusion.

    In case a refresher is required, the OCP states that a class should be open for extension, but closed for modification. It seems to me that people often forget the second part. What does it mean? @@ -18,7 +18,7 @@ It means that once implemented, you shouldn't touch that piece of code ever again (unless you need to correct a bug).

    - Then how can new functionality be added to a code base? This is still possible through either inheritance or polymorphic recomposition. Since the L in SOLID signifies the Liskov Substitution Principle, SOLID code tends to be based on loosely coupled code composed into an application through copious use of interfaces - basically, Strategies injected into other Strategies and so on (also due to Dependency Inversion Principle). In order to add functionality, you can create new implementations of these interfaces and redefine the application's Composition Root. Perhaps you'd be wrapping existing functionality in a Decorator or adding it to a Composite. + Then how can new functionality be added to a code base? This is still possible through either inheritance or polymorphic recomposition. Since the L in SOLID signifies the Liskov Substitution Principle, SOLID code tends to be based on loosely coupled code composed into an application through copious use of interfaces - basically, Strategies injected into other Strategies and so on (also due to Dependency Inversion Principle). In order to add functionality, you can create new implementations of these interfaces and redefine the application's Composition Root. Perhaps you'd be wrapping existing functionality in a Decorator or adding it to a Composite.

    Once in a while, you'll stop using an old implementation of an interface. Should you then delete this implementation? What would be the point? At a certain point in time, this implementation was valuable. Maybe it will become valuable again. Leaving it as an potential building block seems a better choice. @@ -183,12 +183,12 @@

    2012-01-03 16:09 UTC

    - +
    Agreed, OCP is hard.

    However, adhering to OCP doesn't indicate that you have to do BDUF. What it means is that once you get a 'rush of insight' (as Domain-Driven Design puts it) you don't modify existing classes. Instead, you introduce new classes to follow the new model.

    -This may seem wasteful, but due to the very fine-grained nature of SOLID code, it means that those classes that follow the old model (that you've just realized can be improved) are basically 'wrong' because they model the domain in the 'wrong' way. Re-implementing that part of the application's behavior while leaving the old code in place is typically more efficient because it's only going to be a very small part of the code base (again due to the granularity) and because you can do it in micro-iterations since you're not changing anything. Thus, dangerous 'big-bang' refactorings are avoided.
    +This may seem wasteful, but due to the very fine-grained nature of SOLID code, it means that those classes that follow the old model (that you've just realized can be improved) are basically 'wrong' because they model the domain in the 'wrong' way. Re-implementing that part of the application's behavior while leaving the old code in place is typically more efficient because it's only going to be a very small part of the code base (again due to the granularity) and because you can do it in micro-iterations since you're not changing anything. Thus, dangerous 'big-bang' refactorings are avoided.

    In any case, I never said that SOLID is easy. What I'm saying is that SOLID code has certain characteristics, and if a code base doesn't exhibit those characteristics, it's not (perfectly) SOLID. In reality, I expect that there are very few code bases that can live up to what is essentially an ideal more than a practically attainable goal.
    2012-01-03 16:42 UTC
    @@ -211,14 +211,14 @@

    2012-01-03 17:55 UTC

    - +
    Jon, that's well put.

    When it comes to fixing bugs, the OCP specifically states that it's OK to modify existing code, so you shouldn't be uneasy about that.
    2012-01-03 19:32 UTC
    - +
    Hadi, I'd never claim that it's possible to get things right on the first attempt. Looking at AutoFixture (again), I had to do a lot of refactoring and redesign to arrive at version 2.0, which is 'fairly' SOLID. Still, I have more changes in store for version 3.0, which indicates to me that it's still not SOLID - although it's vastly better than before.

    Still, instead of refactoring, sometimes it makes more sense to leave the old stuff to atrophy and build the new, better API up around it. That's basically the Strangler pattern applied at the code level.
    @@ -254,7 +254,7 @@

    2012-01-04 10:15 UTC

    - +
    Jeff, I think that the use of a DI Container and application of the OCP are perpendicular concerns.

    Andreas, the 'old' definition of OCP (Meyer's) is to use inheritance to extend an existing class. However, when we favor composition over inheritance, the default way to extend a class is to apply a Decorator to it.
    @@ -276,7 +276,7 @@

    2012-03-17 08:51 UTC

    - +
    Payman, I do practice TDD, and I do refactor regularly as part of the Red/Green/Refactor cycle.

    What I meant (but perhaps did not explicitly state) was that once a piece of code is released to production, it changes status. That kind of code I don't often refactor.
    diff --git a/_posts/2012-02-02-LooseCouplingandtheBigPicture.html b/_posts/2012-02-02-LooseCouplingandtheBigPicture.html index b5dda06fe..0989deef4 100644 --- a/_posts/2012-02-02-LooseCouplingandtheBigPicture.html +++ b/_posts/2012-02-02-LooseCouplingandtheBigPicture.html @@ -295,7 +295,7 @@

    2012-02-03 16:30 UTC

    - +
    Thomas, Javi

    I'm a big proponent of the concept that, with TDD, unit tests are actually the first consumer of your code, and the final application only a close second. As such, it may seem compelling to state that you're never breaking the RAP if you do TDD. However, as a knee-jerk reaction, I just don't buy that argument, which made me think why that is the case...
    @@ -317,7 +317,7 @@

    2012-02-05 09:33 UTC

    - +
    I'm not saying that you can't program to interfaces, but I'm saying that if you can't reuse those interfaces, it's time to take a good hard look at them. So if you know there's only ever going to be one implementation of ISmthRepository, what does that tell you about that interface?

    In any case, please refer back to the original definition of the RAP. It doesn't say that you aren't allowed to program against 1:1 interfaces - it just states that as long as it remains a 1:1 interface, you haven't proved that it's a generalization. Until that happens, it should be treated as suspect.
    @@ -338,7 +338,7 @@

    2012-02-05 19:11 UTC

    - +
    Justin

    Remember that with TDD we should move through the three phases of Red, Green and Refactor. During the Refactoring phase we typically look towards eliminating duplication. We are (or at least should be) used to do this for code duplication. The only thing the RAP states is that we should extend that effort towards our interface designs.
    diff --git a/_posts/2012-02-09-IsLayeringWorththeMapping.html b/_posts/2012-02-09-IsLayeringWorththeMapping.html index 0c57c2ea7..9402a9a02 100644 --- a/_posts/2012-02-09-IsLayeringWorththeMapping.html +++ b/_posts/2012-02-09-IsLayeringWorththeMapping.html @@ -28,7 +28,7 @@

    To understand the problem with layering, I'll describe a fairly simple example. Assume that you are building a music service and you've been asked to render a top 10 list for the day. It would have to look something like this in a web page:

    - Top10Tracks + Top10Tracks

    As part of rendering the list, you must color the Movement values accordingly using CSS. @@ -142,7 +142,7 @@

    }

    - You may be wondering about the translation from DbTrack to Track. In this case you can assume that the DbTrack class is a class representation of a database table, modeled along the lines of your favorite ORM. The Track class, on the other hand, is a proper object-oriented class which protects its invariants: + You may be wondering about the translation from DbTrack to Track. In this case you can assume that the DbTrack class is a class representation of a database table, modeled along the lines of your favorite ORM. The Track class, on the other hand, is a proper object-oriented class which protects its invariants:

    public class Track
    @@ -220,7 +220,7 @@ 

    Such an architecture is often drawn like this:

    - CrossCuttingEntities + CrossCuttingEntities

    Now, a single Track class is allowed to travel from layer to layer in order to avoid mapping. The controller code hasn't really changed, although the model returned to the View is no longer a sequence of TopTrackViewModel, but simply a sequence of Track instances: @@ -334,7 +334,7 @@

    }

    - It also looks simpler than before, but this is actually not particularly beneficial, as it doesn't protect its invariants. In order to play nice with the ORM of your choice, it must have a default constructor. It also has automatic properties. However, most insidiously, it also somehow gained the Position and CssClass properties. + It also looks simpler than before, but this is actually not particularly beneficial, as it doesn't protect its invariants. In order to play nice with the ORM of your choice, it must have a default constructor. It also has automatic properties. However, most insidiously, it also somehow gained the Position and CssClass properties.

    What does the Position property imply outside of the context of a top 10 list? A position in relation to what? @@ -450,14 +450,14 @@

    2012-02-10 16:44 UTC

    - +
    bitbonk, that wasn't what I said at all. On the contrary, the point of the post is that as soon as you soften separation of concerns just a bit, it becomes impossible to maintain that separation. It's an all-or-nothing proposition. Either you maintain strict separation, or you'd be building a monolithic application whether you know it or not.

    The only thing I'm saying is that it's better to build a monolithic application when you know and understand that this is what you are doing, than it is to be building a monolithic application while under the illusion that you are building a decoupled application.
    2012-02-10 16:46 UTC
    - +
    Jonty: I don't know... How does protected or private constructors or properties help protect invariants?
    2012-02-10 16:48 UTC
    @@ -509,7 +509,7 @@

    2012-02-10 18:40 UTC

    - +
    nelson, I never claimed the code in this post was supposed to represent good code :) Agreed that the Enrich method violates CQS.

    While your suggested, inheritance-based solution seems cleaner, please note that it also introduces a mapping (in the copy constructor). Once you start doing this, there's almost always a composition-based solution which is at least as good as the inheritance-based solution.
    @@ -525,7 +525,7 @@

    2012-02-10 19:22 UTC

    - +
    Well, I was mainly attempting to address the perception that a lot of people have that decoupling creates a lot of mapping and therefore isn't worth the effort (their sentiment, not mine). Unfortunately, I have too little experience with technology stacks outside of .NET to be able to say something authoritative about them, but that particular positioning of Rails matches what I've previously heard.
    2012-02-10 19:30 UTC
    @@ -607,31 +607,31 @@

    2012-02-18 17:03 UTC

    - -
    Anders, I've been down the road of modeling Entities or Value Objects as interfaces, and it rarely leads to anywhere productive. The problem is that you end up with a lot of interfaces that mainly consists of properties (instead of methods). One day I'll attempt to write a long and formal exposition on why this is problematic, but for now I'll just hint that it violates the Law of Demeter and leads to interface coupling as I quoted Jim Cooper for explaining in my previous blog post. Basically the problem is that such interfaces tend to be Header Interfaces.
    + +
    Anders, I've been down the road of modeling Entities or Value Objects as interfaces, and it rarely leads to anywhere productive. The problem is that you end up with a lot of interfaces that mainly consists of properties (instead of methods). One day I'll attempt to write a long and formal exposition on why this is problematic, but for now I'll just hint that it violates the Law of Demeter and leads to interface coupling as I quoted Jim Cooper for explaining in my previous blog post. Basically the problem is that such interfaces tend to be Header Interfaces.
    2012-02-20 00:23 UTC
    - +
    Daniel, it's really hard to answer that question without knowing why that web service exists in the first place. If the only reason it exists is to facilitate communication between client and server, you may not need a translation layer. That's basically how WCF RIA services work. However, that tightly couples the client to the service, and you can't deploy or version each independently of the other.

    -If the service layer exists in order to decouple the service from the client, you must translate from the internal model to a service API. However, if this is the case, keep in mind that at the service boundary, you are no longer dealing with objects at all, so translation or mapping is conceptually very important. If you have .NET on both sides it's easy to lose sight of this, but imagine that either service or client is implemented in COBOL and you may begin to understand the importance of translation.
    +If the service layer exists in order to decouple the service from the client, you must translate from the internal model to a service API. However, if this is the case, keep in mind that at the service boundary, you are no longer dealing with objects at all, so translation or mapping is conceptually very important. If you have .NET on both sides it's easy to lose sight of this, but imagine that either service or client is implemented in COBOL and you may begin to understand the importance of translation.

    So as always, it's a question of evaluating the advantages and disadvantages of each alternative in the concrete situation. There's no one correct answer.
    2012-02-20 00:37 UTC
    - +
    Dave, well, yes, you are correct that the service in the code is actually part of the UI API. An error on my part, but I hope I still got the point of the blog post across. It doesn't change the conclusion in any way.
    2012-02-20 00:40 UTC
    - +
    Ilias, you can write me at mark at seemann dot (my initials).
    2012-02-20 00:42 UTC
    - +
    Moss, that's one of the reason I find NoSQL (particularly Event Sourcing) very attractive. There need be no mapping at the data access level - only serialization.

    Personally, I'm beginning to consider ORMs the right solution to the wrong problem. A relational database is rarely the correct data store for a LoB application or your typical web site.
    @@ -654,7 +654,7 @@

    2012-03-02 15:22 UTC

    - +
    Amy, while I think you're describing a dynamic approach with that Proxy class, it sounds actually rather close to normal inheritance to me. Basically, in C#, when you inherit from another class, all the base class' members are carried forward into the derived class. From C# 4 and onward, we also have dynamic typing, which would enable us to forego compilation and type safety for dynamic dispatching.

    No matter how you'd achieve such things, I'm not to happy about doing this, as most of the variability axes we get from a multi-paradigmatic language such as C# is additive - it means that while it's fairly easy to add new capabilities to objects, it's actually rather hard to remove capabilities.
    @@ -667,8 +667,8 @@

    2012-03-12 20:41 UTC

    - -
    Justin, if you pass JSON or any other type of untyped data up and down the layers, it would certainly remove the class coupling. The question is whether or not it would remove coupling in general. If you take a look at the Jim Cooper quote here, he's talking about semantic coupling, and you'd still have that because each layer would be coupled to a specific structure of the data that travels up and down.
    + +
    Justin, if you pass JSON or any other type of untyped data up and down the layers, it would certainly remove the class coupling. The question is whether or not it would remove coupling in general. If you take a look at the Jim Cooper quote here, he's talking about semantic coupling, and you'd still have that because each layer would be coupled to a specific structure of the data that travels up and down.

    You might also want to refer to my answer to Amy immediately above. The data structures the UI requires may be entirely different from the Domain Model, which again could be different from the data access model. The UI will often be an aggregate of data from many different data sources.

    @@ -690,7 +690,7 @@

    2012-04-16 16:31 UTC

    - +
    Matt, I don't think there's any hard rule for that. Consider all the unknowns that are before you when you embark on a new project: this is one of those unknowns. In part, I base such decisions on gut feeling - you may call it experience...

    What I think would be the correct thing, on the other hand, would be to make a conscious decision as a team on which way to go. If the team agrees that the project is most likely a CRUD application, then it can save itself the trouble of having all those layers. However, it's very important to stress to non-technical team members and stake holders (project managers etc.) that there's a trade-off here: We've decided to go with RAD development. This will enables us to go fast as long as our assumption about a minimum of business logic holds true. On the other hand, if that assumption fails, we'll be going very slowly. Put it in writing and make sure those people understand this.
    diff --git a/_posts/2012-03-15-ImplementinganAbstractFactory.html b/_posts/2012-03-15-ImplementinganAbstractFactory.html index 3579069ac..c6202135f 100644 --- a/_posts/2012-03-15-ImplementinganAbstractFactory.html +++ b/_posts/2012-03-15-ImplementinganAbstractFactory.html @@ -8,10 +8,10 @@

    - Abstract Factory is a tremendously useful pattern when used with Dependency Injection (DI). While I've repeatedly described how it can be used to solve various problems in DI, apparently I've never described how to implement one. As a comment to an older blog post of mine, Thomas Jaskula asks how I'd implement the IOrderShipperFactory. + Abstract Factory is a tremendously useful pattern when used with Dependency Injection (DI). While I've repeatedly described how it can be used to solve various problems in DI, apparently I've never described how to implement one. As a comment to an older blog post of mine, Thomas Jaskula asks how I'd implement the IOrderShipperFactory.

    - To stay consistent with the old order shipper scenario, this blog post outlines three alternative ways to implement the IOrderShipperFactory interface. + To stay consistent with the old order shipper scenario, this blog post outlines three alternative ways to implement the IOrderShipperFactory interface.

    To make it a bit more challenging, the implementation should create instances of the OrderShipper2 class, which itself has a dependency: @@ -97,13 +97,13 @@

    }

    - But wait! Isn't this an application of the Service Locator anti-pattern? Not if this class is part of the Composition Root. + But wait! Isn't this an application of the Service Locator anti-pattern? Not if this class is part of the Composition Root.

    If this implementation was placed in the same library as OrderShipper2 itself, it would mean that the library would have a hard dependency on the container. In such a case, it would certainly be a Service Locator.

    - However, when a Composition Root already references a container, it makes sense to place the ContainerFactory class there. This changes its role to the pure infrastructure component it really ought to be. This seems more SOLID, but the disadvantage is that there's no longer a ready-to-use implementation packaged together with the LazyOrderShipper2 class. All new clients must supply their own implementation. + However, when a Composition Root already references a container, it makes sense to place the ContainerFactory class there. This changes its role to the pure infrastructure component it really ought to be. This seems more SOLID, but the disadvantage is that there's no longer a ready-to-use implementation packaged together with the LazyOrderShipper2 class. All new clients must supply their own implementation.

    Dynamic Proxy # @@ -144,7 +144,7 @@

    2012-03-16 00:35 UTC

    - +
    Patrick, I just explained what the advantages (and disadvantages) are...
    2012-03-16 04:47 UTC
    @@ -168,7 +168,7 @@

    2012-03-16 10:30 UTC

    - +
    About disposal, I can only think of two options - both of which are leaky abstractions: Either let the returned interface also implement IDisposable, or add a Release method to the Abstract Factory.

    You can read more about this in chapter 6 in my book.
    @@ -207,7 +207,7 @@

    var googleSearchHighlight = function () {
    if (!document.createElement) return;
    ref = document.referrer;
    - if (ref.indexOf('?') == -1 || ref.indexOf('http://blog.ploeh.dk/') != -1) {
    + if (ref.indexOf('?') == -1 || ref.indexOf('/') != -1) {
    if (document.location.href.indexOf('PermaLink') != -1) {
    if (ref.indexOf('SearchView.aspx') == -1) return;
    }
    @@ -302,12 +302,12 @@

    2012-03-16 19:03 UTC

    - +
    Good point, Steve. You're right... I hadn't thought it all the way through :)
    2012-03-18 14:03 UTC
    - +
    Dmitriy, if we let only the concrete factory implement IDisposable, then when should it be disposed? How can we deterministically signal that we are 'done' with it?

    (Thank you very much for your assistance with the javascript - I didn't even know which particular script was causing all that trouble. Unfortunately, the script itself is compiled into the dasBlog engine which hosts this blog, so I can't change it. However, I think I managed to switch it off... Yet another reason to find myself a new blog platform...)
    @@ -322,7 +322,7 @@

    2012-03-18 21:54 UTC

    - +
    Implicit scopes like an HTTP request can work pretty well when we can hook into the lifetime cycle of the scope itself. This is possible with HTTP requests, which is why many DI Containers can implicitly clean up when the HTTP request has been handled.

    However, what if we have a desktop application or a long-running batch job? How do we define an implicit scope then? One option might me to employ a timeout, but I'll have to think more about this... Not a bad idea, though :)
    @@ -339,7 +339,7 @@

    2012-03-19 12:02 UTC

    - +
    Dmitriy, I still need to think more about this, but AFACT in order to use a scope for decommissioning, there must be some hook that we can attach to in order to clean up when the scope ends. I'm not aware of such a hook on a Thread, but I must admit that I rarely do low-level work with Threads.

    A Task<T>, on the other, provides us with the ability to attach a continuation, so that seems to me to be an appropriate candidate...
    @@ -351,7 +351,7 @@

    2012-12-23 14:31 UTC

    - +
    You could create each factory instance using the "new" keyword and register the instances with the container.

    Or you could register the container with itself, enabling it to auto-wire itself.
    @@ -365,16 +365,16 @@

    2014-02-28 22:58 UTC

    - +

    - Julien, thank you for your question. Using a Dynamic Proxy is an implementation detail. The consumer (in this case LazyOrderShipper2) depends only on IOrderShipperFactory. + Julien, thank you for your question. Using a Dynamic Proxy is an implementation detail. The consumer (in this case LazyOrderShipper2) depends only on IOrderShipperFactory.

    Does using a Dynamic Proxy make it harder to swap containers? Yes, it does, because I'm only aware of one .NET DI Container that has this capability (although it's a couple of years ago since I last surveyed the .NET DI Container landscape). Therefore, if you start out with Castle Windsor, and then later on decide to exchange it for another DI Container, you would have to supply a manually coded implementation of IOrderShipperFactory. You could choose to implement either a Manually Coded Factory, or a Container-based Factory, as described in this article. It's rather trivial to do, so I would hardly call it blocking issue.

    - The more you rely on specific features of a particular DI Container, the more work you'll have to perform to migrate. This is why I always recommend that you design your classes following normal, good design practices first, without any regard to how you'd use them with any particular DI Container. Only when you've designed your API should you figure out how to compose it with a DI Container (if at all). + The more you rely on specific features of a particular DI Container, the more work you'll have to perform to migrate. This is why I always recommend that you design your classes following normal, good design practices first, without any regard to how you'd use them with any particular DI Container. Only when you've designed your API should you figure out how to compose it with a DI Container (if at all).

    2014-03-01 14:47 UTC
    @@ -385,10 +385,10 @@

    2014-12-31 20:57 UTC

    - +

    - Personally, I don't find container verification particularly valuable, but then again, I mostly use Pure DI anyway. + Personally, I don't find container verification particularly valuable, but then again, I mostly use Pure DI anyway.

    2014-12-31 21:33 UTC
    diff --git a/_posts/2012-03-19-MigratingfromWCFWebAPItoASP.NETWebAPI.html b/_posts/2012-03-19-MigratingfromWCFWebAPItoASP.NETWebAPI.html index 9046bf234..af5c6fb34 100644 --- a/_posts/2012-03-19-MigratingfromWCFWebAPItoASP.NETWebAPI.html +++ b/_posts/2012-03-19-MigratingfromWCFWebAPItoASP.NETWebAPI.html @@ -120,8 +120,8 @@

    2012-03-20 10:48 UTC

    - -
    Jonty, here's why.
    + +
    Jonty, here's why.
    2012-03-20 16:07 UTC
    diff --git a/_posts/2012-03-20-RobustDIWiththeASP.NETWebAPI.html b/_posts/2012-03-20-RobustDIWiththeASP.NETWebAPI.html index db8eeb3d5..9b731ca40 100644 --- a/_posts/2012-03-20-RobustDIWiththeASP.NETWebAPI.html +++ b/_posts/2012-03-20-RobustDIWiththeASP.NETWebAPI.html @@ -8,7 +8,7 @@
    - Note 2014-04-03 19:46 UTC: This post describes how to address various Dependency Injection issues with a Community Technical Preview (CTP) of ASP.NET Web API 1. Unless you're still using that 2012 CTP, it's no longer relevant. Instead, refer to my article about Dependency Injection with the final version of Web API 1 (which is also relevant for Web API 2). + Note 2014-04-03 19:46 UTC: This post describes how to address various Dependency Injection issues with a Community Technical Preview (CTP) of ASP.NET Web API 1. Unless you're still using that 2012 CTP, it's no longer relevant. Instead, refer to my article about Dependency Injection with the final version of Web API 1 (which is also relevant for Web API 2).

    Like the WCF Web API, the new ASP.NET Web API supports Dependency Injection (DI), but the approach is different and the resulting code you'll have to write is likely to be more complex. This post describes how to enable robust DI with the new Web API. Since this is based on the beta release, I hope that it will become easier in the final release. @@ -102,7 +102,7 @@

    - It's a fundamental rule of DI that you must Release what you Resolve. That's not possible with the DependencyResolver API. The result may be memory leaks. + It's a fundamental rule of DI that you must Release what you Resolve. That's not possible with the DependencyResolver API. The result may be memory leaks.

    @@ -138,7 +138,7 @@

    There's also a DefaultControllerFactory in the Web API, but unfortunately no Template Methods to override. While I could write an algorithm that maps from the controllerName parameter to a type which can be passed to a DI Container, I'd rather prefer to be able to reuse the implementation which the DefaultControllerFactory contains.

    - In ASP.NET MVC, this is possible by overriding the GetControllerInstance method, but it turns out that the Web API (beta) does this slightly differently. It favors composition over inheritance (which is actually a good thing, so kudos for that), so after mapping controllerName to a Type instance, it invokes an instance of the IHttpControllerActivator interface (did I hear anyone say "FactoryFactory?"). Very loosely coupled (good), but not very discoverable (not so good). It would have been more discoverable if DefaultControllerFactory had used Constructor Injection to get its dependency, rather than relying on the Service Locator which DependencyResolver really is. + In ASP.NET MVC, this is possible by overriding the GetControllerInstance method, but it turns out that the Web API (beta) does this slightly differently. It favors composition over inheritance (which is actually a good thing, so kudos for that), so after mapping controllerName to a Type instance, it invokes an instance of the IHttpControllerActivator interface (did I hear anyone say "FactoryFactory?"). Very loosely coupled (good), but not very discoverable (not so good). It would have been more discoverable if DefaultControllerFactory had used Constructor Injection to get its dependency, rather than relying on the Service Locator which DependencyResolver really is.

    However, this is only an issue if you need to hook into the Controller creation process, e.g. in order to capture the HttpControllerContext for further use. In normal scenarios, despite what Nikos Baxevanis describes in his blog post, you don't have to override or implement IHttpControllerFactory.CreateController. The DependencyResolver infrastructure will automatically invoke your GetService implementation (or the corresponding code block) whenever a Controller instance is required. @@ -226,7 +226,7 @@

    2012-03-21 14:29 UTC

    - +
    Why not?
    2012-03-21 14:46 UTC
    @@ -241,7 +241,7 @@

    2012-03-21 15:34 UTC

    - +
    Jaime, yes, I'm aware of FubuMVC, but have never tried it for a couple of reasons.

    First of all, right now I need a framework for building REST services, and not a web framework. FubuMVC might have gained REST features (such as conneg) since last I looked, but the ASP.NET Web API does have quite an attractive feature set for building REST APIs.
    @@ -274,7 +274,7 @@

    2012-03-21 16:42 UTC

    - +
    Jaime, it's good feedback - I'm receiving it in the most positive way :)
    2012-03-21 16:45 UTC
    @@ -289,7 +289,7 @@

    2012-03-23 08:05 UTC

    - +
    Anders, no I don't know, but I would be slightly surprised if it does. Unity (2.0) has several issues related to proper decommissioning. In section 14.2 in my book I describe those issues and how to overcome them.
    2012-03-23 08:34 UTC
    @@ -341,7 +341,7 @@

    2012-08-07 10:02 UTC

    - +
    The class may very well have changed since the beta.

    In the future, I may add an update to this article, unless someone else beats me to it.
    diff --git a/_posts/2012-03-26-IQueryableTisTightCoupling.html b/_posts/2012-03-26-IQueryableTisTightCoupling.html index 4133e435a..b71f9c0e7 100644 --- a/_posts/2012-03-26-IQueryableTisTightCoupling.html +++ b/_posts/2012-03-26-IQueryableTisTightCoupling.html @@ -185,7 +185,7 @@

    2012-03-27 19:42 UTC

    - +
    Amir, that sounds correct. IQueryable is a useful tool, but it can be somewhat misleading as part of an API (interfaces or base classes). On concrete classes it's less misleading.
    2012-03-28 05:03 UTC
    @@ -293,7 +293,7 @@

    2012-03-30 13:29 UTC

    - +
    Looks good, Daniel. I'd love to hear your experience with this once you've tried it on for some time :)
    2012-03-30 14:15 UTC
    @@ -366,7 +366,7 @@

    2014-08-06 17:46 UTC

    - +

    Mario, thank you for writing. It occasionally happens that I change my mind, as I learn new skills and gain more experience, but in this case, I haven't changed my mind. I indirectly use IQueryable<T> when I occasionally have to query a relational database with the Entity Framework or LINQ to SQL (which happens extremely rarely these days), but I never design my own interfaces around IQueryable<T>; my reasons for introducing an interface is normally to reduce coupling, but introducing any interface that exposes or depends on IQueryable<T> doesn't reduce coupling. @@ -378,7 +378,7 @@

    The same argument also goes against designing interfaces around Expression<Func<T, bool>>. It may seem flexible, but the fact is that such an expression can be arbitrarily complex, so in practice, it's impossible to guarantee that you can translate every expression to all SQL dialects; and what about OData? Or queries against MongoDB?

    - Still, I rarely use ORMs at all. Instead, I increasingly rely on simple abstractions like Drain when designing my systems. + Still, I rarely use ORMs at all. Instead, I increasingly rely on simple abstractions like Drain when designing my systems.

    2014-08-09 12:22 UTC
    diff --git a/_posts/2012-04-17-InjectingHttpControllerContextWiththeASP.NETWebAPI.html b/_posts/2012-04-17-InjectingHttpControllerContextWiththeASP.NETWebAPI.html index f0fe00a41..ea34152e5 100644 --- a/_posts/2012-04-17-InjectingHttpControllerContextWiththeASP.NETWebAPI.html +++ b/_posts/2012-04-17-InjectingHttpControllerContextWiththeASP.NETWebAPI.html @@ -14,13 +14,13 @@

    The Problem #

    - A Service may need an instance of the HttpControllerContext class. For an example, see the RouteLinker class in my previous post. A Controller, on the other hand, may depend on such a Service: + A Service may need an instance of the HttpControllerContext class. For an example, see the RouteLinker class in my previous post. A Controller, on the other hand, may depend on such a Service:

    public CatalogController(IResourceLinker resourceLinker)

    - How can a CatalogController instance be wired up with an instance of RouteLinker, which again requires an instance of HttpControllerContext? In contrast to the existing ASP.NET MVC API, there's no easy way to read the current context. There's no HttpControllerContext.Current method or any other easy way (that I have found) to refer to an HttpControllerContext as part of the Composition Root. + How can a CatalogController instance be wired up with an instance of RouteLinker, which again requires an instance of HttpControllerContext? In contrast to the existing ASP.NET MVC API, there's no easy way to read the current context. There's no HttpControllerContext.Current method or any other easy way (that I have found) to refer to an HttpControllerContext as part of the Composition Root.

    True: it's easily available as a property on a Controller, but at the time of composition, there's no Controller instance (yet). A Controller instance is exactly what the Composition Root is attempting to create. This sounds like a circular reference problem. Fortunately, it's not. @@ -29,7 +29,7 @@

    The Solution #

    - For Poor Man's DI, the solution is relatively simple. As I've previously described, by default the responsibility of creating Controller instances is handled by an instance of IHttpControllerActivator. This is, essentially, the Composition Root (at least for all Controllers). + For Poor Man's DI, the solution is relatively simple. As I've previously described, by default the responsibility of creating Controller instances is handled by an instance of IHttpControllerActivator. This is, essentially, the Composition Root (at least for all Controllers).

    The Create method of that interface takes exactly the HttpControllerContext required by RouteLinker - or, put differently: the framework will supply an instance every time it invokes the Create method. Thus, a custom IHttpControllerActivator solves the problem: @@ -64,7 +64,7 @@

    The controllerContext parameter is simply passed on to the RouteLinker constructor.

    - The only thing left is to register the PoorMansCompositionRoot with the ASP.NET Web API. This can be done in Global.asax by using the GlobalConfiguration.Configuration.ServiceResolver.SetResolver method, as described in my previous post. Just resolve IHttpControllerActivator to an instance of PoorMansCompositionRoot. + The only thing left is to register the PoorMansCompositionRoot with the ASP.NET Web API. This can be done in Global.asax by using the GlobalConfiguration.Configuration.ServiceResolver.SetResolver method, as described in my previous post. Just resolve IHttpControllerActivator to an instance of PoorMansCompositionRoot.

    @@ -88,7 +88,7 @@

    2012-04-20 09:35 UTC

    - +
    Yes, please go ahead :)
    2012-04-20 09:58 UTC
    @@ -112,8 +112,8 @@

    2012-04-23 09:09 UTC

    - -
    Ali, that's not an approach I like. First of all because an Initialize method would introduce a Temporal Coupling, but also because it would mean that one would potentially need to pass the HttpControllerContext through a lot of intermediary layers in order to invoke that Initialize method on a very low-level dependency. That's API pollution.
    + +
    Ali, that's not an approach I like. First of all because an Initialize method would introduce a Temporal Coupling, but also because it would mean that one would potentially need to pass the HttpControllerContext through a lot of intermediary layers in order to invoke that Initialize method on a very low-level dependency. That's API pollution.
    2012-04-23 09:24 UTC
    @@ -122,12 +122,12 @@

    2012-04-23 16:32 UTC

    - +
    I realize that this article is more general, but specifically for IResourceLinker, would it make more sense to just pass HttpControllerContext as a second parameter from controller action. What would be the downside of this approach?
    2012-05-02 14:03 UTC
    - +
    Dmitry, that would mean that you'd need to pass the parameter through each and every method through all intermediary layers (see also my answer above). This would seriously pollute the API.
    2012-05-02 14:10 UTC
    diff --git a/_posts/2012-04-19-WiringHttpControllerContextWithCastleWindsor.html b/_posts/2012-04-19-WiringHttpControllerContextWithCastleWindsor.html index 0d9dd835f..67e35d4e4 100644 --- a/_posts/2012-04-19-WiringHttpControllerContextWithCastleWindsor.html +++ b/_posts/2012-04-19-WiringHttpControllerContextWithCastleWindsor.html @@ -8,7 +8,7 @@

    - In a previous post I demonstrated how to wire up HttpControllerContext with Poor Man's DI. In this article I'll show how to wire up HttpControllerContext with Castle Windsor. + In a previous post I demonstrated how to wire up HttpControllerContext with Poor Man's DI. In this article I'll show how to wire up HttpControllerContext with Castle Windsor.

    This turns out to be remarkably difficult, at least with the constraints I tend to set for myself: @@ -27,7 +27,7 @@ If possible, the solution should be thread-safe.

  • - The overall solution should still adhere to the Register Resolve Release pattern, so registering a captured HttpControllerContext is a no-go. It's also unlikely to work, since you'd need to somehow scope each registered instance to its source request. + The overall solution should still adhere to the Register Resolve Release pattern, so registering a captured HttpControllerContext is a no-go. It's also unlikely to work, since you'd need to somehow scope each registered instance to its source request.
  • That also rules out nested containers. @@ -61,7 +61,7 @@

    Creating a custom IHttpControllerActivator with an injected TaskCompletionSource<HttpControllerContext> sounds like a good approach. If the custom IHttpControllerActivator can be scoped to a specific request, that would be the solution then and there.

    - However, as I've previously described, the current incarnation of the ASP.NET Web API has the unfortunate behavior that all framework Services (such as IHttpControllerActivator) are resolved once and cached forever (effectively turning them into having the Singleton lifestyle, despite what you may attempt to configure in your container). + However, as I've previously described, the current incarnation of the ASP.NET Web API has the unfortunate behavior that all framework Services (such as IHttpControllerActivator) are resolved once and cached forever (effectively turning them into having the Singleton lifestyle, despite what you may attempt to configure in your container).

    @@ -182,7 +182,7 @@

    2012-04-24 14:24 UTC

  • - +
    Thomas, I haven't investigated that yet. Sorry.
    2012-04-25 06:23 UTC
    @@ -197,8 +197,8 @@

    2012-10-19 15:44 UTC

    - -
    The current blog post describes how to use Castle Windsor with a preview of the Web API. Since there were breaking changes between the preview and the RTM version, the approach described here no longer works. Please refer to this blog post for a description of how to make DI work with Castle Windsor in Web API RTM.
    + +
    The current blog post describes how to use Castle Windsor with a preview of the Web API. Since there were breaking changes between the preview and the RTM version, the approach described here no longer works. Please refer to this blog post for a description of how to make DI work with Castle Windsor in Web API RTM.
    2012-10-19 16:57 UTC
    \ No newline at end of file diff --git a/_posts/2012-04-24-VendorMediaTypesWiththeASP.NETWebAPI.html b/_posts/2012-04-24-VendorMediaTypesWiththeASP.NETWebAPI.html index 392f50e23..6d8793fe3 100644 --- a/_posts/2012-04-24-VendorMediaTypesWiththeASP.NETWebAPI.html +++ b/_posts/2012-04-24-VendorMediaTypesWiththeASP.NETWebAPI.html @@ -210,7 +210,7 @@

    Comments

    - +
    For those who are interested in returning 406 depending on client Accept header, there is an article about it and the my attempt to improve the code in it:

    http://pedroreys.com/2012/02/17/extending-asp-net-web-api-content-negotiation/
    @@ -218,7 +218,7 @@

    2012-05-03 02:10 UTC

    diff --git a/_posts/2012-05-24-TDDtestsuitesshouldrunin10secondsorless.html b/_posts/2012-05-24-TDDtestsuitesshouldrunin10secondsorless.html index 4c87ea6b7..5e4db8179 100644 --- a/_posts/2012-05-24-TDDtestsuitesshouldrunin10secondsorless.html +++ b/_posts/2012-05-24-TDDtestsuitesshouldrunin10secondsorless.html @@ -102,7 +102,7 @@

    2012-05-24 17:52 UTC

    - +
    In Agile we have this concept of rapid feedback. That a test runner runs in the background doesn't address the problem of Slow Tests. It's no good if you start writing more code and then five minutes later, your continuous test runner comes back and tells you that something you did five minutes ago caused the test suite to fail. That's not timely feedback.

    Some of that can be alleviated with a DVCS, but rapid feedback just makes things a lot easier.
    @@ -137,7 +137,7 @@

    - +

    Peter, thank you for writing. I recall reading about the 10 second rule some months before I wrote the article, but that, when writing the article, I had trouble finding public reference material. Thank you for making the effort of researching this and sharing your findings. I don't dispute what you wrote, but here are some further thoughts on the topic: diff --git a/_posts/2012-05-25-Designpatternsacrossparadigms.html b/_posts/2012-05-25-Designpatternsacrossparadigms.html index 7380e4363..5da430f97 100644 --- a/_posts/2012-05-25-Designpatternsacrossparadigms.html +++ b/_posts/2012-05-25-Designpatternsacrossparadigms.html @@ -106,7 +106,7 @@

    It means that given a variable, we can often just enter ".", and our IDE is going to give us a list of methods we can call on the object:

    - IntelliSense + IntelliSense

    Since behavior is contained by each type, we can use patterns such as Fluent Interface to make it easy to learn a new API. While we can laugh at the term 'dot-driven development' it's hard to deny that it makes it very easy to learn. @@ -135,7 +135,7 @@

    There might be a slight overlap, but I'd expect most patterns to be tightly coupled to the paradigm in which they were originally stated.

    - +

    There might be a few patterns that are generally applicable. @@ -162,7 +162,7 @@

    2012-05-25 12:42 UTC

    - +
    Martin, I agree that often the FP view is superior because it contains more information. What I said was that mutation is often more intuitive. Consider a kettle of boiling water: over time, the water in the kettle mutates - it becomes steam.

    While we are programmers, we are still human, and unless you get involved in pretty advanced theoretical physics, a practical and very precise world view is that objects change state over time.
    diff --git a/_posts/2012-05-29-BankOCRkatainF#userstory1.html b/_posts/2012-05-29-BankOCRkatainF#userstory1.html index b99020b28..24ee9bd41 100644 --- a/_posts/2012-05-29-BankOCRkatainF#userstory1.html +++ b/_posts/2012-05-29-BankOCRkatainF#userstory1.html @@ -10,7 +10,7 @@

    - In case my previous post left readers in doubt about whether or not I like Functional Programming (FP), this post should make it clear that I (also) love FP. + In case my previous post left readers in doubt about whether or not I like Functional Programming (FP), this post should make it clear that I (also) love FP.

    A couple of years ago I had the pleasure of performing a technical review of Real World Functional Programming, which caused me to significantly shift my C# coding style towards a more functional style. @@ -224,7 +224,7 @@

    That's it. The code is actually quite compact, but I just took a long time explaining it all in some detail.

    - In a future post I'll walk through the other use cases of the Bank OCR kata.
    + In a future post I'll walk through the other use cases of the Bank OCR kata.

    diff --git a/_posts/2012-06-01-BankOCRkatainF#userstory2.html b/_posts/2012-06-01-BankOCRkatainF#userstory2.html index 752f0ae7d..d60610509 100644 --- a/_posts/2012-06-01-BankOCRkatainF#userstory2.html +++ b/_posts/2012-06-01-BankOCRkatainF#userstory2.html @@ -10,7 +10,7 @@

    - Following up on my initial post about the Bank OCR kata, this post walks through the code required to implement user story 2, which is about calculating a checksum. + Following up on my initial post about the Bank OCR kata, this post walks through the code required to implement user story 2, which is about calculating a checksum.

    The code I previously described already contains a function called ParseToDigits which returns a sequence of digits, so it seems reasonable to express the validation function as based on a sequence of digits as input. @@ -80,7 +80,7 @@

        |> should equal false

    - In a future post I will walk you through user stories 3 and 4. + In a future post I will walk you through user stories 3 and 4.

    @@ -95,7 +95,7 @@

    2012-06-01 23:45 UTC

    - +
    That's a TDD artifact more than an actual requirement. I wrote the test first, and wanted it to specify that the IsValid function should be able to take any sequence, and not only a list.

    Because of F# powerful type inference, that's what the function ends up doing anyway, but with TDD, it's the test that specifies the shape of the API, not the other way around.
    diff --git a/_posts/2012-06-04-BankOCRkatainF#userstories3and4.html b/_posts/2012-06-04-BankOCRkatainF#userstories3and4.html index 3b834f9d4..b8ddf8576 100644 --- a/_posts/2012-06-04-BankOCRkatainF#userstories3and4.html +++ b/_posts/2012-06-04-BankOCRkatainF#userstories3and4.html @@ -10,7 +10,7 @@

    - In previous posts, I've walked through the first two user stories of the Bank OCR kata in F#. In this post I'll walk through my implementation of user stories 3 and 4. + In previous posts, I've walked through the first two user stories of the Bank OCR kata in F#. In this post I'll walk through my implementation of user stories 3 and 4.

    The reason I'm collecting both user stories in a single blog post is that the requirements of user story 4 represent a change from user story 3, and since I didn't use a DVCS for this kata, I no longer have my implementation for user story 3. @@ -204,13 +204,13 @@

    That part of the if/then branch should be fairly easy to understand. If the entry is valid (according to the checksum function from user story 2) and legible, the result is formatted and returned.

    - The isValidAndLegible function determines whether the entry is... well... valid and legible. The first thing it does is to pipe the string into the ParseToDigits function, which, you'll recall, returns a sequence of integer options. + The isValidAndLegible function determines whether the entry is... well... valid and legible. The first thing it does is to pipe the string into the ParseToDigits function, which, you'll recall, returns a sequence of integer options.

    To figure out whether those potential digits are legible it invokes the isLegible function, which I'll return to shortly.

    - In order to figure out whether the potential digits are valid, it invokes the IsValid method from user story 2. However, in order to do so, it needs to convert the sequence of integer options to a sequence of integers. It does that by invoking the skipNones helper method, that I defined in a helper module: + In order to figure out whether the potential digits are valid, it invokes the IsValid method from user story 2. However, in order to do so, it needs to convert the sequence of integer options to a sequence of integers. It does that by invoking the skipNones helper method, that I defined in a helper module:

    let skipNones sequence = Seq.collect Option.toArray sequence
    @@ -346,7 +346,7 @@

    Finally, if there are multiple candidates, each is formatted and appended as ambiguous alternatives to the original (invalid) input.

    - In case you'd like to take an even closer look at the code, I've attached the entire solution as a zip file: KataBankOCR.zip (299.62 KB) + In case you'd like to take an even closer look at the code, I've attached the entire solution as a zip file: KataBankOCR.zip (299.62 KB)

    @@ -361,7 +361,7 @@

    2012-06-21 11:16 UTC

    - +
    FWIW, I found the book Real World Functional Programming: With Examples in F# and C# an excellent introduction to functional concepts for object-oriented programmers.

    Soon, I'll write a small blog post on one way in which SOLID relates to Functional Programming.
    @@ -382,7 +382,7 @@

    2012-07-04 19:35 UTC

    - +
    I use TestDriven.net to run the xUnit.net tests.

    Thanks for the alternatives for the ReplaceElementAt function. I was never happy with the readability of my implementation. I like the seq { } alternative best, so I've updated my own source code :)
    diff --git a/_posts/2012-06-21-TheResemblanceidiom.html b/_posts/2012-06-21-TheResemblanceidiom.html index d55c9151d..2f41e97a7 100644 --- a/_posts/2012-06-21-TheResemblanceidiom.html +++ b/_posts/2012-06-21-TheResemblanceidiom.html @@ -161,7 +161,7 @@

    channelMock.Verify(c => c.Send(expected));

    - You may still feel that the overhead of creating a new test-specific class just for this purpose doesn't quite justify the increased readability and composability, but stay tuned - I have more tricks to show you. + You may still feel that the overhead of creating a new test-specific class just for this purpose doesn't quite justify the increased readability and composability, but stay tuned - I have more tricks to show you.

    @@ -180,7 +180,7 @@

    2012-06-21 13:05 UTC

    - +
    There's that, but none of the options presented here solve that problem - all of them are going to throw an exception by the Verify method if the correct method call wasn't made.

    In GOOS they are better off because they use Hamcrest, and their mocking library understands Hamcrest matchers. That's not the situation in .NET (yet).
    @@ -209,7 +209,7 @@

    2012-06-21 17:22 UTC

    - +
    As I wrote: stay tuned :)

    (and yes: the comment engine here is really crappy - sorry about that)
    @@ -222,14 +222,14 @@

    2012-10-01 15:18 UTC

    - +
    I don't have a direct solution for that particular issue, but I find the Resemblance idiom most useful when dealing with Indirect Input and Output, as in the example above. In other words, it's mostly useful when dealing with Mock objects, because the have to deal exclusively with equality.

    When it comes to direct assertions, like Assert.Equal, I'd love it if we had something like Hamcrest Matchers in .NET (actually, there is a .NET port, but last time I looked, it seemed abandonded). The next best thing is often a custom IEqualityComparer, but that doesn't necessarily solve the pretty print error reporting need.

    Sometimes, it's nice to have both, so one can implement a custom IEqualityComparer and then use that class to also implement a Resemblance.

    -FWIW, the Likeness class described in the next blog post is built that way. It also includes a ShouldEqual method as a very concrete way of providing more readable error reporting...
    +FWIW, the Likeness class described in the next blog post is built that way. It also includes a ShouldEqual method as a very concrete way of providing more readable error reporting...
    2012-10-01 19:28 UTC
    diff --git a/_posts/2012-06-22-ResemblanceandLikeness.html b/_posts/2012-06-22-ResemblanceandLikeness.html index 4d3ee1fc9..533086dda 100644 --- a/_posts/2012-06-22-ResemblanceandLikeness.html +++ b/_posts/2012-06-22-ResemblanceandLikeness.html @@ -9,7 +9,7 @@

    - In a previous post I described the Resemblance idiom. In this post I present a class that can be used to automate the process of creating a Resemblance. + In a previous post I described the Resemblance idiom. In this post I present a class that can be used to automate the process of creating a Resemblance.

    The Resemblance idiom enables you to write readable unit tests, but the disadvantage is that you will have to write (and maintain) quite a few test-specific Resemblance classes. If you're a Coding Neat Freak like me, you'll also have to override GetHashCode in every Resemblance, just because you're overriding Equals. If you're still looking for ways to torment yourself, you'll realize that the typical Resemblance implementation of Equals contains branching logic, so ideally, it should be unit tested too. (Yes, I do occasionally unit test my unit testing helper classes. AutoFixture, which is essentially one big unit test helper, is currently covered by some three thousand tests.) @@ -21,7 +21,7 @@

    Likeness #

    - Before I show you how to turn a Likeness into a Resemblance, I think a very short introduction to Likeness is in order. A couple of years ago I introduced Likeness on my blog, but I think a re-introduction is in order. In the context of the unit test from the previous blog post, instead of manually writing a test like this: + Before I show you how to turn a Likeness into a Resemblance, I think a very short introduction to Likeness is in order. A couple of years ago I introduced Likeness on my blog, but I think a re-introduction is in order. In the context of the unit test from the previous blog post, instead of manually writing a test like this:

    [Theory, AutoWebData]
    @@ -147,7 +147,7 @@ 

    2012-07-05 07:43 UTC

    - +
    Nah, I don't have any insights on that. Nikos Baxevanis wrote that, and I trust that he got it right (as he did with so much other crazy stuff). However, perhaps I can coax him to provide an answer here :)
    2012-07-05 08:03 UTC
    diff --git a/_posts/2012-06-22-Test-specificEqualityversusDomainEquality.html b/_posts/2012-06-22-Test-specificEqualityversusDomainEquality.html index fa9ac57e0..8c17b214a 100644 --- a/_posts/2012-06-22-Test-specificEqualityversusDomainEquality.html +++ b/_posts/2012-06-22-Test-specificEqualityversusDomainEquality.html @@ -8,7 +8,7 @@

    - As a reaction to my two previous blog posts, Joe Miller asks on Twitter: + As a reaction to my two previous blog posts, Joe Miller asks on Twitter:

    If a test needs to check a "special" type of equality, isn't that special equality actually part of the domain? @@ -36,7 +36,7 @@ If we were to rely on the domain object's built-in equality, we would only be testing that the identity of the Entity is as expected, but not whether or not the mapping code properly maps all the other data. In such cases we need Test-specific Equality, and that's exactly what Resemblances and Likenesses provide.

    - In the previous example, this is exactly what happens. The SUT produces a new instance of the RequestReservationCommand: + In the previous example, this is exactly what happens. The SUT produces a new instance of the RequestReservationCommand:

    @@ -77,7 +77,7 @@

    2012-06-26 13:33 UTC

    - +
    Well, that's an Ambient Context (Dependency Injection in .NET, p. 118), and while it enables you to assign an expected Guid value from a unit test, from a conceptual perspective I don't think it's the correct solution for a test like this one.

    From a behavioral point of view, we don't really care about the value of the ID (the Guid). From other tests we know that a new instance of a command will always have a unique ID. It's part of the command's invariants. Thus, we know that the ID is going to be unique, so having to configure an Ambient Context is only going to add noise to a unit test.
    diff --git a/_posts/2012-06-27-FacadeTest.html b/_posts/2012-06-27-FacadeTest.html index b0d91f728..ddd88484f 100644 --- a/_posts/2012-06-27-FacadeTest.html +++ b/_posts/2012-06-27-FacadeTest.html @@ -92,7 +92,7 @@

    2012-07-03 21:02 UTC

    - +
    The purpose is to have a pattern language for automated tests - just as with every other pattern language.

    "Let's drive this through Facade Tests" now means something else than "Let's drive this through Unit Tests".
    diff --git a/_posts/2012-07-02-PrimitiveDependencies.html b/_posts/2012-07-02-PrimitiveDependencies.html index 0bf173d02..07b845327 100644 --- a/_posts/2012-07-02-PrimitiveDependencies.html +++ b/_posts/2012-07-02-PrimitiveDependencies.html @@ -18,7 +18,7 @@ Primitives are dependencies, too. It doesn't really matter whether or not they are polymorphic. In the end, a dependency is something that the client depends on - hence the name. It doesn't really matter whether the dependency is an interface, a class or a primitive type. In most object-oriented languages, everything is an object - even integers and booleans (although boxing occurs).

    - There are several ways to inject dependencies into clients. My book describes a set of patterns including Constructor Injection and Property Injection. It's important to keep in mind that ultimately, the reason why Constructor Injection should be your preferred DI pattern has nothing to do with polymorphism. It has to do with protecting the invariants of the class. + There are several ways to inject dependencies into clients. My book describes a set of patterns including Constructor Injection and Property Injection. It's important to keep in mind that ultimately, the reason why Constructor Injection should be your preferred DI pattern has nothing to do with polymorphism. It has to do with protecting the invariants of the class.

    Therefore, if the class in question requires a primitive value in order to work, that is a dependency too. Primitive constructor arguments can be mixed with polymorphic arguments. There's really no difference. @@ -108,7 +108,7 @@

            chartConnectionString: "foo"));

    - This code is part of the application's Composition Root. + This code is part of the application's Composition Root.

    Configuration-based composition # @@ -152,7 +152,7 @@

                    .ConnectionString)));

    - This configures the ChartController type exactly like the previous example, but it's actually more complicated now, and you even lost the feedback from the compiler. That's not good, but you can do better. + This configures the ChartController type exactly like the previous example, but it's actually more complicated now, and you even lost the feedback from the compiler. That's not good, but you can do better.

    Conventions for primitives # @@ -266,7 +266,7 @@

    2012-07-05 20:29 UTC

    - +
    It's been almost two years since I last worked with Unity, so I don't know - I can't remember all the details of its API. However, I remember Unity as being quite extensible, actually, so I wouldn't be surprised if you could do something like this.

    Basically, Unity has very little in terms of Fluent APIs, convention over configuration, etc. but what it does have is a very open architecture. This means it's almost always possible to write a bit of Reflection code to configure Unity by convention.
    diff --git a/_posts/2012-07-18-Hyprlinkr.html b/_posts/2012-07-18-Hyprlinkr.html index 5d9d5c487..fb208264f 100644 --- a/_posts/2012-07-18-Hyprlinkr.html +++ b/_posts/2012-07-18-Hyprlinkr.html @@ -7,7 +7,7 @@ {% include JB/setup %}
    -

    This post serves as an announcement that my latest open source project Hyprlinkr is available. It's a very sharply focused helper library for the ASP.NET Web API, enabling you to create type-safe hyperlinks between resources in a RESTful API.

    It's basically a reusable package of the RouteLinker class I previously presented as a spike. The original idea wasn't mine, but José F. Romaniello's - I just took the idea and created a project out of it.

    The library is mostly useful if you build level 3 RESTful APIs with the ASP.NET Web API.

    It's available as a NuGet package.

    Apart from that, I'll refer you to the project site for more information.

    +

    This post serves as an announcement that my latest open source project Hyprlinkr is available. It's a very sharply focused helper library for the ASP.NET Web API, enabling you to create type-safe hyperlinks between resources in a RESTful API.

    It's basically a reusable package of the RouteLinker class I previously presented as a spike. The original idea wasn't mine, but José F. Romaniello's - I just took the idea and created a project out of it.

    The library is mostly useful if you build level 3 RESTful APIs with the ASP.NET Web API.

    It's available as a NuGet package.

    Apart from that, I'll refer you to the project site for more information.

    @@ -25,7 +25,7 @@

    2012-07-18 11:23 UTC

    - +
    In the cases I can think about right now, I'd say that the Controller (or one of its dependencies) must have the responsibility of adding the hyperlinks. It's an application concern to define what can be linked to. This isn't any different than adding "<a href" links to HTML in a 'normal' web application.
    2012-07-18 11:45 UTC
    diff --git a/_posts/2012-07-20-FizzBuzzkatainF#stage1.html b/_posts/2012-07-20-FizzBuzzkatainF#stage1.html index 7515fe15b..4fc955af2 100644 --- a/_posts/2012-07-20-FizzBuzzkatainF#stage1.html +++ b/_posts/2012-07-20-FizzBuzzkatainF#stage1.html @@ -10,7 +10,7 @@

    - In previous posts I've walked through the Bank OCR kata in F#. In this post, I will do the same for the first stage of the very simple FizzBuzz kata. This is a very simple kata, so if you already know F#, there will be nothing new to see here. On the other hand, if you've yet to be exposed to F#, this is a good place to start - I'll attempt to walk you through the code assuming that you don't know F# yet. + In previous posts I've walked through the Bank OCR kata in F#. In this post, I will do the same for the first stage of the very simple FizzBuzz kata. This is a very simple kata, so if you already know F#, there will be nothing new to see here. On the other hand, if you've yet to be exposed to F#, this is a good place to start - I'll attempt to walk you through the code assuming that you don't know F# yet.

    Unit test # @@ -122,7 +122,7 @@

    It now takes this string and the next value ("4") and applies the sprintf function once more, etc. This is how the final list is being printed.

    - In a future post I'll walk you through stage 2 of the kata. + In a future post I'll walk you through stage 2 of the kata.

    diff --git a/_posts/2012-07-25-FizzBuzzkatainF#stage2.html b/_posts/2012-07-25-FizzBuzzkatainF#stage2.html index 76ab6eb8a..d843f806c 100644 --- a/_posts/2012-07-25-FizzBuzzkatainF#stage2.html +++ b/_posts/2012-07-25-FizzBuzzkatainF#stage2.html @@ -10,7 +10,7 @@

    - In my previous post I walked you through stage 1 of the FizzBuzz kata. In this post I'll walk you through stage 2 of the kata, where new requirements are introduced (see the kata itself for details). This makes the implementation much more complex. + In my previous post I walked you through stage 1 of the FizzBuzz kata. In this post I'll walk you through stage 2 of the kata, where new requirements are introduced (see the kata itself for details). This makes the implementation much more complex.

    Unit test # @@ -67,7 +67,7 @@

        |> should equal expected

    - This is the same test code as before, only with new or modified test data. + This is the same test code as before, only with new or modified test data.

    Implementation # @@ -238,7 +238,7 @@

    else fizzOrBuzz

    - To print the FizzBuzz list for numbers from 1 to 100 the same solution as before can be used. + To print the FizzBuzz list for numbers from 1 to 100 the same solution as before can be used.

    What I like about Functional Programming is that data just flows through the function. There's not state and no mutation - only operations on sequences of data. diff --git a/_posts/2012-07-31-TheorderofAutoFixtureCustomizationsmatter.html b/_posts/2012-07-31-TheorderofAutoFixtureCustomizationsmatter.html index 27e270f0d..7fb98cfb7 100644 --- a/_posts/2012-07-31-TheorderofAutoFixtureCustomizationsmatter.html +++ b/_posts/2012-07-31-TheorderofAutoFixtureCustomizationsmatter.html @@ -12,13 +12,13 @@ {{ page.description }}

    - With AutoFixture you can encapsulate common Customizations using the Customize method and the ICustomization interface. However, customizations may 'compete' for the same requests in the sense that more than one customization is able to handle a request. + With AutoFixture you can encapsulate common Customizations using the Customize method and the ICustomization interface. However, customizations may 'compete' for the same requests in the sense that more than one customization is able to handle a request.

    As an example, consider a request for something as basic as IEnumerable<T>. By default, AutoFixture can't create instances of IEnumerable<T>, but more than one customization can.

    - As previously described the MultipleCustomization handles requests for sequences just fine: + As previously described the MultipleCustomization handles requests for sequences just fine:

    @@ -26,7 +26,7 @@ var seq = fixture.CreateAnonymous<IEnumerable<int>>();

    - However, the AutoMoqCustomization can also (sort of) create sequences: + However, the AutoMoqCustomization can also (sort of) create sequences:

    diff --git a/_posts/2012-08-31-ConcreteDependencies.html b/_posts/2012-08-31-ConcreteDependencies.html index 9a56e65df..06c3349dc 100644 --- a/_posts/2012-08-31-ConcreteDependencies.html +++ b/_posts/2012-08-31-ConcreteDependencies.html @@ -12,7 +12,7 @@ {{ page.description }}

    - Usually, when we think about Dependency Injection (DI), we tend to consider that only polymorphic types (interfaces or (abstract) base classes) can act as dependencies. However, in a previous blog post I described how primitives can be used as dependencies. A primitive is about as far removed from polymorphism as it can be, but there's a middle ground too. Sometimes 'normal' concrete classes with non-virtual members can be used as dependencies with to great effect. + Usually, when we think about Dependency Injection (DI), we tend to consider that only polymorphic types (interfaces or (abstract) base classes) can act as dependencies. However, in a previous blog post I described how primitives can be used as dependencies. A primitive is about as far removed from polymorphism as it can be, but there's a middle ground too. Sometimes 'normal' concrete classes with non-virtual members can be used as dependencies with to great effect.

    While the Liskov Substitution Principle is voided by injecting a concrete type, there can be other good reasons to occasionaly do something like this. Consider how many times you've written an extension method to perform some recurring task. Sometimes it turns out that an extension method isn't the best way to encapsulate a common algorithm. It might start out simple enough, but then you realize that you need to provide the extension method with a control parameter in order to 'configure' it. This causes you to add more arguments to the extension method, or to add more overloads. Soon, you have something like the Object Mother (anti-)pattern on your hand. @@ -171,13 +171,13 @@

    }

    - In this test, you Freeze the RouteLinker instance, which means that the linker variable is the same instance as the RouteLinker injected into the SUT. Next, you ask that RouteLinker instance what it would produce when invoked in a particular way, and since AtomLinkModel doesn't override Equals, you produce a Likeness from the AtomLinkModel and verify that the actual collection of links contains the expected link. + In this test, you Freeze the RouteLinker instance, which means that the linker variable is the same instance as the RouteLinker injected into the SUT. Next, you ask that RouteLinker instance what it would produce when invoked in a particular way, and since AtomLinkModel doesn't override Equals, you produce a Likeness from the AtomLinkModel and verify that the actual collection of links contains the expected link.

    That's much more precise than those horribly forgiving It.IsAny constraints. The other advantage is also that you don't have to care about Setups of methods you don't care about in a particular test case. The SUT can invoke the GetUri method as many times as it wants, with as many different arguments as it likes, and the test is never going to break because of that. Since the real implementation is injected, it always works without further Setup.

    - Granted, strictly speaking these aren't unit tests any longer, but rather Facade Tests. + Granted, strictly speaking these aren't unit tests any longer, but rather Facade Tests.

    This technique works because the GetUri method is deterministic and has no side-effects. Thus, it's very similar to Function Composition in Functional languages. diff --git a/_posts/2012-09-28-DependencyInjectionandLifetimeManagementwithASP.NETWebAPI.html b/_posts/2012-09-28-DependencyInjectionandLifetimeManagementwithASP.NETWebAPI.html index a1e6f3d2a..06146ca31 100644 --- a/_posts/2012-09-28-DependencyInjectionandLifetimeManagementwithASP.NETWebAPI.html +++ b/_posts/2012-09-28-DependencyInjectionandLifetimeManagementwithASP.NETWebAPI.html @@ -18,7 +18,7 @@

    The problem with IDependencyResolver #

    - The main problem with IDependencyResolver is that it's essentially a Service Locator. There are many problems with the Service Locator anti-pattern, but most of them I've already described elsewhere on this blog (and in my book). One disadvantage of Service Locator that I haven't yet written so much about is that within each call to GetService there's no context at all. This is a general problem with the Service Locator anti-pattern, not just with IDependencyResolver. Glenn Block originally pointed this out to me. The problem is that in an implementation, all you're given is a Type instance and asked to return an object, but you're not informed about the context. You don't know how deep in a dependency graph you are, and if you're being asked to provide an instance of the same service multiple times, you don't know whether it's within the same HTTP request, or whether it's for multiple concurrent HTTP requests. + The main problem with IDependencyResolver is that it's essentially a Service Locator. There are many problems with the Service Locator anti-pattern, but most of them I've already described elsewhere on this blog (and in my book). One disadvantage of Service Locator that I haven't yet written so much about is that within each call to GetService there's no context at all. This is a general problem with the Service Locator anti-pattern, not just with IDependencyResolver. Glenn Block originally pointed this out to me. The problem is that in an implementation, all you're given is a Type instance and asked to return an object, but you're not informed about the context. You don't know how deep in a dependency graph you are, and if you're being asked to provide an instance of the same service multiple times, you don't know whether it's within the same HTTP request, or whether it's for multiple concurrent HTTP requests.

    In the ASP.NET Web API this issue is exacerbated by another design decision that the team made. Contrary to the IDependencyResolver design, I find this other decision highly appropriate. It's how context is modeled. In previous incarnations of web frameworks from Microsoft, we've had such abominations as HttpContext.Current, HttpContextBase and HttpContextWrapper. If you've ever tried to work with these interfaces, and particularly if you've tried to do TDD against any of these types, you know just how painful they are. That they are built around the Singleton pattern certainly doesn't help. @@ -147,7 +147,7 @@

    Stay away from the IDependencyResolver interface, which is close to useless. Instead, implement IHttpControllerActivator and use the RegisterForDispose method for decommissioning.

    - In a future post I will demonstrate how to use a DI Container instead of Poor Man's DI. + In a future post I will demonstrate how to use a DI Container instead of Poor Man's DI.

    @@ -162,7 +162,7 @@

    2012-09-28 12:24 UTC

    - +
    Yes, that's what I wrote. The problem is that it doesn't provide any context.
    2012-09-28 12:30 UTC
    @@ -178,12 +178,12 @@

    2012-09-28 20:40 UTC

    - +
    Dave, the IHttpControllerActivator/RegisterForDispose is a workable combo, but I'd preferred a release method on it, just like MVC's IControllerFactory.
    2012-09-28 21:26 UTC
    - +
    Jonas, let's assume that you have a deeper dependency graph. Let's say that you have this Controller constructor: public MyController(IService1, IService2). Imagine, moreover, that you have implementations of each of these interfaces, with these constructors: public Service1(IFoo) and public Service2(IFoo).

    You have one implementation of IFoo, namely Foo, and for efficiency reasons, or perhaps because Foo is a Mediator, you'd like to share the same instance of Foo between Service1 and Service2. However, Foo isn't thread-safe, so you can only share the Foo instance within a single request. For each request, you want to use a single instance of Foo.
    @@ -220,7 +220,7 @@

    2012-09-29 08:39 UTC

    - +
    Well, whether or not it's a necessity depends on who you ask.

    StructureMap, for example, has no decommissioning capability, and when you ask Jeremy Miller, it's by design. The reason for this is that if you don't have any disposable dependencies at all, it's just an overhead keeping track of all the instances created by the container. Garbage collection will ensure that resources are properly reclaimed.
    @@ -238,7 +238,7 @@

    2012-10-19 09:02 UTC

    - +
    Yes, this is described in detail in section 7.2 in my book.
    2012-10-19 12:39 UTC
    @@ -265,10 +265,10 @@

    2014-08-28 14:52 UTC

    - +

    - In general, I don't like attributes with behaviour, but prefer passive attributes. Still, that just moves the implementation to the Filter's ExecuteActionFilterAsync method, so that doesn't really address your question. + In general, I don't like attributes with behaviour, but prefer passive attributes. Still, that just moves the implementation to the Filter's ExecuteActionFilterAsync method, so that doesn't really address your question.

    If you need access to the actual objects created from the incoming request, you probably could pull it out of the HttpActionContext passed into ExecuteActionFilterAsync, but why bother? You can access the object from the Controller. diff --git a/_posts/2012-10-03-DependencyInjectioninASP.NETWebAPIwithCastleWindsor.html b/_posts/2012-10-03-DependencyInjectioninASP.NETWebAPIwithCastleWindsor.html index cebce5e16..6fa10400b 100644 --- a/_posts/2012-10-03-DependencyInjectioninASP.NETWebAPIwithCastleWindsor.html +++ b/_posts/2012-10-03-DependencyInjectioninASP.NETWebAPIwithCastleWindsor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my previous post I described how to use Dependency Injection (DI) in the ASP.NET Web API using Poor Man's DI. It explained the basic building blocks, including the relevant extensibility points in the Web API. Poor Man's DI can be an easy way to get started with DI and may be sufficient for a small code base, but for larger code bases you may want to adopt a more convention-based approach. Some DI Containers provide excellent support for Convention over Configuration. One of these is Castle Windsor. + In my previous post I described how to use Dependency Injection (DI) in the ASP.NET Web API using Poor Man's DI. It explained the basic building blocks, including the relevant extensibility points in the Web API. Poor Man's DI can be an easy way to get started with DI and may be sufficient for a small code base, but for larger code bases you may want to adopt a more convention-based approach. Some DI Containers provide excellent support for Convention over Configuration. One of these is Castle Windsor.

    Composition Root # @@ -66,7 +66,7 @@

    That's pretty much all there is to it, but there are a few points of interest here. First of all, the class implements IHttpControllerActivator just like the previous PoorMansCompositionRoot. That's the extensibility point you need to implement in order to create Controller instances. However, instead of hard-coding knowledge of concrete Controller classes into the Create method, you delegate creation of the instance to an injected IWindsorContainer instance. However, before returning the IHttpController instance created by calling container.Resolve, you register that object graph for disposal.

    - With Castle Windsor decommissioning is done by invoking the Release method on IWindsorContainer. The input into the Release method is the object graph originally created by IWindsorContainer.Resolve. That's the rule from the Register Resolve Release pattern: What you Resolve you must also Release. This ensures that if the Resolve method created a disposable instance (even deep in the object graph), the Release method signals to the container that it can now safely dispose of it. You can read more about this subject in my book. + With Castle Windsor decommissioning is done by invoking the Release method on IWindsorContainer. The input into the Release method is the object graph originally created by IWindsorContainer.Resolve. That's the rule from the Register Resolve Release pattern: What you Resolve you must also Release. This ensures that if the Resolve method created a disposable instance (even deep in the object graph), the Release method signals to the container that it can now safely dispose of it. You can read more about this subject in my book.

    The RegisterForDispose method takes as a parameter an IDisposable instance, and not a Release method, so you must wrap the call to the Release method in an IDisposable implementation. That's the little private Release class in the code example. It adapts an Action delegate into a class which implements IDisposable, invoking the code block when Dispose is invoked. The code block you pass into the constructor of the Release class is a closure around the outer variables this.container and controller so when the Dispose method is called, the container releases the controller (and the entire object graph beneath it). @@ -147,7 +147,7 @@

    2012-10-16 08:15 UTC

    - +
    Thank you. Have you read my CQRS article? For examples on using DI with CQRS, I'd like to suggest the updated example code.
    2012-10-16 11:59 UTC
    @@ -160,7 +160,7 @@

    2012-10-17 08:12 UTC

    - +
    IHttpControllerActivator is a special Web API interface, as is IHttpController. MVC Controllers are not resolved with this API, but it's very similar to the approach outlined in my book.
    2012-10-17 12:30 UTC
    @@ -174,7 +174,7 @@

    2012-10-20 12:58 UTC

    - +
    You can't use the above technique for injecting anything into MVC 4 attributes, since they aren't Controllers. The only way to inject dependencies into MVC attributes is by Property Injection, and if you read section 4.2 of my book you'll see that there are many issues with this pattern.

    A better approach is to use global filters with behaviour, and use only passive attributes.
    @@ -223,7 +223,7 @@

    What do you think about this?

    2012-11-20 02:32 UTC
    - +
    I've never experienced it to be a problem, so my guess is that in reality the documentation is off and there's only one instance of HttpApplication. Otherwise, the container should be disposed, and I've never seen that happen.
    2012-11-20 08:07 UTC
    @@ -254,7 +254,7 @@

    - +
    See previous comments.
    2012-12-09 19:36 UTC
    @@ -267,8 +267,8 @@

    - -
    Will, DependencyConventions is just a Windsor Installer. I just called it DependencyConventions because I prefer Convention over Configuration when using DI Containers. In your own project, you'll need to define your own Windsor Installer. Alternatively, you can configure the container directly in the WebApiApplication constructor.
    + +
    Will, DependencyConventions is just a Windsor Installer. I just called it DependencyConventions because I prefer Convention over Configuration when using DI Containers. In your own project, you'll need to define your own Windsor Installer. Alternatively, you can configure the container directly in the WebApiApplication constructor.
    2013-04-12 16:00 UTC
    @@ -286,16 +286,16 @@

    - +

    - Jeff, thank you for writing. You are indeed correct that one of the many problems with the Service Locator anti-pattern (and therefore also IDependencyResolver) is that the overall context is hidden. Glenn Block originally pointed that particular problem out to me. + Jeff, thank you for writing. You are indeed correct that one of the many problems with the Service Locator anti-pattern (and therefore also IDependencyResolver) is that the overall context is hidden. Glenn Block originally pointed that particular problem out to me.

    This is also the case with IDependencyResolver, because when GetService(Type) or GetServices(Type) is invoked, the only information the composition engine knows, is the requested type. Thus, resolving something that requires access to the HttpRequestMessage or one of its properties, is impossible with IDependencyResolver, but perfectly possible with IHttpControllerActivator.

    - So, yes, I would definitely say that any DI Container that provides 'ASP.NET Web API integration' by implementing IDependencyResolver is missing out. In any case, these days I rarely use a DI Container, so I don't consider it a big deal - and if I need to use a DI Container, I just need to add those few lines of code listed above in this blog post. + So, yes, I would definitely say that any DI Container that provides 'ASP.NET Web API integration' by implementing IDependencyResolver is missing out. In any case, these days I rarely use a DI Container, so I don't consider it a big deal - and if I need to use a DI Container, I just need to add those few lines of code listed above in this blog post.

    2014-03-15 18:28 UTC
    @@ -318,10 +318,10 @@

    - +

    - Dmitry, thank you for writing. Does this or this help? + Dmitry, thank you for writing. Does this or this help?

    2015-12-07 17:05 UTC
    @@ -341,13 +341,13 @@

    - +

    Andrew, thank you for writing. In general, I don't recall that this has ever been an issue, but see previous threads in the comments for this post. The question's come up before.

    - I do, however, admit that I've never formally studied the question like I did with WCF, so it's possible that I'm wrong on this particular issue. Also, details of the framework could have changed in the five years that's gone by since I wrote the article. + I do, however, admit that I've never formally studied the question like I did with WCF, so it's possible that I'm wrong on this particular issue. Also, details of the framework could have changed in the five years that's gone by since I wrote the article.

    2017-09-02 15:33 UTC
    diff --git a/_posts/2012-11-06-WhentouseaDIContainer.html b/_posts/2012-11-06-WhentouseaDIContainer.html index 97bbffab2..2cecccbd6 100644 --- a/_posts/2012-11-06-WhentouseaDIContainer.html +++ b/_posts/2012-11-06-WhentouseaDIContainer.html @@ -14,7 +14,7 @@ {{ page.description }}

    - Note (2018-07-18): Since I wrote this article, I've retired the term Poor Man's DI in favour of Pure DI. + Note (2018-07-18): Since I wrote this article, I've retired the term Poor Man's DI in favour of Pure DI.

    It seems to me that lately there's been a backlash against DI Containers among alpha geeks. Many of the software leaders that I myself learn from seem to dismiss the entire concept of a DI Container, claiming that it's too complex, too 'magical', that it isn't a good architectural pattern, or that the derived value doesn't warrant the 'cost' (most, if not all, DI Containers are open source, so they are free in a monetary sense, but there's always a cost in learning curve etc.). @@ -91,10 +91,10 @@

    - The major advantage of Poor Man's DI is that it's easy to learn. You don't have to learn the API of any DI Container (Unity, Autofac, Ninject, StructureMap, Castle Windsor, etc.) and while individual classes still use DI, once you find the Composition Root it'll be evident what's going on and how object graphs are constructed. No 'magic' is involved. + The major advantage of Poor Man's DI is that it's easy to learn. You don't have to learn the API of any DI Container (Unity, Autofac, Ninject, StructureMap, Castle Windsor, etc.) and while individual classes still use DI, once you find the Composition Root it'll be evident what's going on and how object graphs are constructed. No 'magic' is involved.

    - The second big advantage of Poor Man's DI is often overlooked: it's strongly typed. This is an advantage because it provides the fastest feedback about correctness that you can get. However, strong typing cuts both ways because it also means that every time you refactor a constructor, you will break the Composition Root. If you are sharing a library (Domain Model, Utility, Data Access component, etc.) between more than one application (unit of deployment), you may have more than one Composition Root to maintain. How much of a burden this is depends on how often you refactor constructors, but I've seen projects where this happens several times each day (keep in mind that constructor are implementation details). + The second big advantage of Poor Man's DI is often overlooked: it's strongly typed. This is an advantage because it provides the fastest feedback about correctness that you can get. However, strong typing cuts both ways because it also means that every time you refactor a constructor, you will break the Composition Root. If you are sharing a library (Domain Model, Utility, Data Access component, etc.) between more than one application (unit of deployment), you may have more than one Composition Root to maintain. How much of a burden this is depends on how often you refactor constructors, but I've seen projects where this happens several times each day (keep in mind that constructor are implementation details).

    If you use a DI Container, but explicitly Register each and every component using the container's API, you lose the rapid feedback from strong typing. On the other hand, the maintenance burden is also likely to drop because of Auto-wiring. Still, you'll need to register each new class or interface when you introduce them, and you (and your team) still has to learn the specific API of that container. In my opinion, you lose more advantages than you gain. @@ -393,7 +393,7 @@

    2012-11-06 19:53 UTC

    - +
    Darren, thank you for your comment. How do you think TDD fits into this discussion? Which overloaded constructors? If you examine the git repo behind these samples, you should find that I didn't change the production code between the three examples. It's the same production code - the same classes, the same constructors, etc. - just wired in three different ways.
    2012-11-06 20:52 UTC
    @@ -413,7 +413,7 @@

    2012-11-07 01:02 UTC

    - +
    Darren, I'll refer you to this answer for further details on the terminology choice. You do have a point, but I'm sticking to the terminology from my book.
    2012-11-07 08:17 UTC
    @@ -436,7 +436,7 @@

    2012-11-09 18:51 UTC

    - +
    Bill, thanks for your comment.

    When it comes to lifetime management, there are answers on more than one level.
    @@ -445,7 +445,7 @@


    On a more explicit level, it would be possible to define a convention that picks up a hint about the desired lifetime from the type itself. You could for example call a service "ThreadSafeFoo" to hint that Singleton would be appropriate - or perhaps you could adorn it with a [ThreadSafe] attribute...

    - Testing the container itself I don't find particularly useful, but a set of smoke tests of the entire app can be helpful.

    + Testing the container itself I don't find particularly useful, but a set of smoke tests of the entire app can be helpful.
    2012-11-11 18:03 UTC
    @@ -472,20 +472,20 @@

    2015-08-18 7:06 UTC

    - +

    Arialdo, thank you for writing.

    Like you, I used to think that lifetime management was an strong motivation to use a DI Container; there's an entire chapter about lifetime management in my book.

    - There may be cases where that's true, but these days I prefer the the explicit lifetime matching I get from Pure DI. + There may be cases where that's true, but these days I prefer the the explicit lifetime matching I get from Pure DI.

    - While you can make lifetime management quite complicated, I prefer to keep it simple, so in practice, I only use the Singleton and Transient lifetime styles. Additionally, I prefer to design my components so that they aren't disposable. If I must use a disposable third-party object, my next priority would be to use a Decoraptor, and add decommissioning support if necessary. Only if none of that is possible will I begin to look at disposal from the Composition Root. + While you can make lifetime management quite complicated, I prefer to keep it simple, so in practice, I only use the Singleton and Transient lifetime styles. Additionally, I prefer to design my components so that they aren't disposable. If I must use a disposable third-party object, my next priority would be to use a Decoraptor, and add decommissioning support if necessary. Only if none of that is possible will I begin to look at disposal from the Composition Root.

    - Usually, when you only use Singleton and Transient, manual disposal from the Composition Root is easy. There's no practical reason to dispose of the Singletons, so you only need to dispose of the Transient objects. How you do that varies from framework to framework, but in ASP.NET Web API, for example, it's easy. + Usually, when you only use Singleton and Transient, manual disposal from the Composition Root is easy. There's no practical reason to dispose of the Singletons, so you only need to dispose of the Transient objects. How you do that varies from framework to framework, but in ASP.NET Web API, for example, it's easy.

    2015-08-18 08:41 UTC
    diff --git a/_posts/2012-11-07-AppSettingsconventionforCastleWindsor.html b/_posts/2012-11-07-AppSettingsconventionforCastleWindsor.html index e52b29f49..9d84921cc 100644 --- a/_posts/2012-11-07-AppSettingsconventionforCastleWindsor.html +++ b/_posts/2012-11-07-AppSettingsconventionforCastleWindsor.html @@ -12,13 +12,13 @@ {{ page.description }}

    - In my previous post I explained how Convention over Configuration is the preferred way to use a DI Container. Some readers asked to see some actual convention implementations (although I actually linked to them in the post). In fact, I've previously showcased some simple conventions expressed with Castle Windsor's API.. In this post I'm going to show you another convention, which is completely reusable. Feel free to copy and paste :) + In my previous post I explained how Convention over Configuration is the preferred way to use a DI Container. Some readers asked to see some actual convention implementations (although I actually linked to them in the post). In fact, I've previously showcased some simple conventions expressed with Castle Windsor's API.. In this post I'm going to show you another convention, which is completely reusable. Feel free to copy and paste :)

    Most conventions are really easy to implement. Actually, sometimes it takes more effort to express the specification than it actually takes to implement it.

    - This convention deals with Primitive Dependencies. In my original post on the topic I included an AppSettingsConvention class as part of the code listing, but that implementation was hard-coded to only deal with integers. This narrow convention can be generalized: + This convention deals with Primitive Dependencies. In my original post on the topic I included an AppSettingsConvention class as part of the code listing, but that implementation was hard-coded to only deal with integers. This narrow convention can be generalized:

    @@ -154,7 +154,7 @@

    2012-11-07 21:19 UTC

    - +
    Krzysztof, if I try to implement an interface called "IComponentModelContributor" IntelliSense gives me nothing. Where is that interface defined? (I'm drawing a blank on Google too...)
    2012-11-07 21:29 UTC
    @@ -164,7 +164,7 @@

    2012-11-07 21:31 UTC

    - +
    How would you implement the above convention with that interface?
    2012-11-07 21:49 UTC
    diff --git a/_posts/2012-11-27-Encapsulationofproperties.html b/_posts/2012-11-27-Encapsulationofproperties.html index a63ada277..59e027879 100644 --- a/_posts/2012-11-27-Encapsulationofproperties.html +++ b/_posts/2012-11-27-Encapsulationofproperties.html @@ -18,7 +18,7 @@ (As an aside, even in languages without formal properties, such as e.g. Java, you often see property-like constructs. In Java, for example, a pair of a getter and a setter method is sometimes informally referred to as a property. In the end, that's also how .NET properties are implemented. Thus, the present article can also be applied to Java and other 'property-less' languages.)

    - In my experience, the two most important aspects of encapsulation are Protection of Invariants and Information Hiding. Earlier, I have had much to say about Protection of Invariants, including the invariants of properties. In this post, I will instead focus on Information Hiding. + In my experience, the two most important aspects of encapsulation are Protection of Invariants and Information Hiding. Earlier, I have had much to say about Protection of Invariants, including the invariants of properties. In this post, I will instead focus on Information Hiding.

    With all that confusion (which I will get back to), you would think that Information Hiding is really hard to grasp. It's not - it's really simple, but I think that the name erects an effective psychological barrier to understanding. If instead we were to call it Implementation Hiding, I think most people would immediately grasp what it's all about. @@ -27,7 +27,7 @@ However, since Information Hiding has this misleading name, it becomes really difficult to understand what it means. Does it mean that all information in an object should be hidden from clients? How can we reconcile such a viewpoint with the fundamental concept that object-orientation is about data and behavior? Some people take the misunderstanding so far that they begin to evangelize against properties as a design principle. Granted, too heavy a reliance on properties leads to violations of the Law of Demeter as well as Feature Envy, but without properties, how can a client ever know the state of a system?

    - Direct field access isn't the solution, as this discloses data to an even larger degree than properties. Still, in the lack of better guidance, the question of Encapsulation often degenerates to the choice between fields and properties. Perhaps the most widely known and accepted .NET design guideline is that data should be exposed via properties. This again leads to the redundant 'Automatic Property' language feature. + Direct field access isn't the solution, as this discloses data to an even larger degree than properties. Still, in the lack of better guidance, the question of Encapsulation often degenerates to the choice between fields and properties. Perhaps the most widely known and accepted .NET design guideline is that data should be exposed via properties. This again leads to the redundant 'Automatic Property' language feature.

    Tell me again: how is this @@ -53,7 +53,7 @@

    Example: a tennis game #

    - The Tennis kata is one of my favorite TDD katas. Previously, I posted my own, very specific take on it, but I've also, when teaching, asked groups to do it as an exercise. Often participants arrive at a solution not too far removed from this example: + The Tennis kata is one of my favorite TDD katas. Previously, I posted my own, very specific take on it, but I've also, when teaching, asked groups to do it as an exercise. Often participants arrive at a solution not too far removed from this example:

    @@ -256,12 +256,12 @@

    2012-11-28 07:33 UTC

    - +
    Steven, thank you for your thoughtful comment. There are definitely many ways to think about encapsulation, and I don't think I have the only true definition. Basically I'm just trying to make sense of a lot of things that I know, from experience and intuition, are correct.

    The main purpose of this post is to drive a big stake through the notion that properties = Encapsulation.

    -The lambda trick you describe is an additional way to scope a method - another is to realize that interfaces can also be used for scoping.
    +The lambda trick you describe is an additional way to scope a method - another is to realize that interfaces can also be used for scoping.
    2012-11-28 07:46 UTC
    diff --git a/_posts/2012-12-18-ZookeepersmustbecomeRangers.html b/_posts/2012-12-18-ZookeepersmustbecomeRangers.html index fa16516e5..05b8edbf6 100644 --- a/_posts/2012-12-18-ZookeepersmustbecomeRangers.html +++ b/_posts/2012-12-18-ZookeepersmustbecomeRangers.html @@ -13,7 +13,7 @@ {{ page.description }}

    - In a previous article I wrote about Ranger and Zookeper developers. The current article is going to make no sense to you if you haven't read the previous, but in brief, Rangers explicitly deal with versioning and forwards and backwards compatibility (henceforth called temporal compatibility) in order to produce workable code. + In a previous article I wrote about Ranger and Zookeper developers. The current article is going to make no sense to you if you haven't read the previous, but in brief, Rangers explicitly deal with versioning and forwards and backwards compatibility (henceforth called temporal compatibility) in order to produce workable code.

    While reading the previous article, you may have thought that you'd rather like to be a Ranger than a Zookeeper, simply because it sounds cooler. Well, I didn't pick those names by accident :) You don't want to be a Zookeeper developer. @@ -102,19 +102,19 @@

    However, the service was made to support other systems, so this change must be coordinated with all the known clients. It turns out that three systems depend on the music catalog service.

    - +

    Each of these systems are being worked on by separate teams, each with individual deadlines. These teams are not planning to deploy new versions of their applications all on the same day. Their immediate schedules are already set, and they aren't aligned.

    - +

    The Architecture team must negotiate future iterations with teams A, B, and C to line them up so that the music catalog team can release their new version on the same day.

    - +

    This alignment may be months into the future - perhaps a significant fraction of a year. The music catalog team can't sit still while they wait for this date to arrive, so they work on other new features, most likely introducing other breaking changes along the way. @@ -132,7 +132,7 @@

    So far, the analysis has been unrealistically simplified. It turns out that the A, B, and C applications have other dependencies besides the music catalog service.

    - +

    Each of these dependencies are also moving, producing new features. Some of those new features also involve breaking changes. Once again, the Enterprise Architecture team must negotiate a coordinated deployment date to make sure nothing breaks. However, the organization have more applications than A, B, and C. Application D, for instance, doesn't depend on the music catalog service, but it shares a dependency with application A. Thus, Team D must take part in the coordination effort, making sure that they deploy their new version on the same day as everyone else. Meanwhile, they'll need yet another one of those expensive testing environments. @@ -212,7 +212,7 @@

    2012-12-19 14:28 UTC

    - +
    Markus Zywitza, the dictionary definition of "professional" simply mean that one gets paid to do a particular task. There are lots of professional programmers that don't use testing, etc. While I agree that it often seems ignorant or short-sighted to neglect to follow what you call "agile practices", you can hardly say that it's unprofessional if the team gets paid to do it. Thus, we need a different terminology.

    However, the other Markus is spot on. The message of this article isn't that you should use TDD, Continuous Integration, etc. Lot's of people have already said that before me. The message is that even if you are an 'internal' developer, you must think explicitly about versioning and backwards compatibility.
    diff --git a/_posts/2013-01-07-RoleHints.html b/_posts/2013-01-07-RoleHints.html index 5c8216a34..40a197e44 100644 --- a/_posts/2013-01-07-RoleHints.html +++ b/_posts/2013-01-07-RoleHints.html @@ -25,11 +25,11 @@

      -
    • Type Name. Use the name of the type (such as the class name) to hint at the role played by instances of the class. This seems to be mostly relevant for objects that can play only a single role.
    • -
    • Argument Name. Use the name of an argument (or variable) to hint at the role played by an instance.
    • -
    • Metadata. Use data about code (such as attributes or marker interfaces) to hint at the role played by instances of the class.
    • -
    • Role Interfaces. A class can implement several Role Interfaces; clients can treat instances as the roles they require.
    • -
    • Partial Type Name. Use part of the type name to hint at a role played by objects. This can be used to enable Convention over Configuration.
    • +
    • Type Name. Use the name of the type (such as the class name) to hint at the role played by instances of the class. This seems to be mostly relevant for objects that can play only a single role.
    • +
    • Argument Name. Use the name of an argument (or variable) to hint at the role played by an instance.
    • +
    • Metadata. Use data about code (such as attributes or marker interfaces) to hint at the role played by instances of the class.
    • +
    • Role Interfaces. A class can implement several Role Interfaces; clients can treat instances as the roles they require.
    • +
    • Partial Type Name. Use part of the type name to hint at a role played by objects. This can be used to enable Convention over Configuration.

    diff --git a/_posts/2013-01-07-TypeNameRoleHints.html b/_posts/2013-01-07-TypeNameRoleHints.html index 87bc0bd7b..d667169bd 100644 --- a/_posts/2013-01-07-TypeNameRoleHints.html +++ b/_posts/2013-01-07-TypeNameRoleHints.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. When first hearing about the concept of object roles, a typical reaction is: How is that different from the class name? Doesn't the class name communicate the purpose of the class? + In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. When first hearing about the concept of object roles, a typical reaction is: How is that different from the class name? Doesn't the class name communicate the purpose of the class?

    Sometimes it does, so this is a fair question. However, there are certainly other situations where this isn't the case at all. diff --git a/_posts/2013-01-08-ArgumentNameRoleHint.html b/_posts/2013-01-08-ArgumentNameRoleHint.html index 7cb4647e8..da1902e2c 100644 --- a/_posts/2013-01-08-ArgumentNameRoleHint.html +++ b/_posts/2013-01-08-ArgumentNameRoleHint.html @@ -13,7 +13,7 @@ {{ page.description }}

    - In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is by proper naming of variables and method arguments. In many ways, this is the converse view of a Type Name Role Hint. + In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is by proper naming of variables and method arguments. In many ways, this is the converse view of a Type Name Role Hint.

    To reiterate, the Design Guidelines for Developing Class Libraries provides this rule: @@ -24,7 +24,7 @@

    - As described in the post about Type Name Role Hints, this rule makes sense when the argument type is too generic to provide enough information about role played by an object. + As described in the post about Type Name Role Hints, this rule makes sense when the argument type is too generic to provide enough information about role played by an object.

    Example: unit test variables # diff --git a/_posts/2013-01-09-MetadataRoleHint.html b/_posts/2013-01-09-MetadataRoleHint.html index 66efd0bf1..c159c5128 100644 --- a/_posts/2013-01-09-MetadataRoleHint.html +++ b/_posts/2013-01-09-MetadataRoleHint.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is by leveraging metadata. In .NET that would often take the form of attributes, but you can also maintain the metadata in a separate data structure, such as a dictionary. + In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is by leveraging metadata. In .NET that would often take the form of attributes, but you can also maintain the metadata in a separate data structure, such as a dictionary.

    Metadata can provide useful Role Hints when there are many potential objects to choose from. @@ -78,13 +78,13 @@

    }

    - Now, before you pull Refactoring at me and tell me to replace the enum with a polymorphic type, I must remind you that at the boundaries, applications aren't object-oriented. At some place, close to the application boundary, the application must translate an incoming primitive to a polymorphic type. That's the responsibility of something like the ShippingCostCalculatorFactory. + Now, before you pull Refactoring at me and tell me to replace the enum with a polymorphic type, I must remind you that at the boundaries, applications aren't object-oriented. At some place, close to the application boundary, the application must translate an incoming primitive to a polymorphic type. That's the responsibility of something like the ShippingCostCalculatorFactory.

    There are several problems with the above implementation of IShippingCostCalculatorFactory. In the simplified example code, all three implementations of IBasketCalculator have default constructors, but that's not likely to be the case. Recall that calculating shipping cost involves complicated business rules. Not only are those classes likely to need all sorts of configuration data to determine price per weight range, etc. but they might even need to perform lookups against external system - such as getting a qoute from an external carrier. In other words, the ExpressShippingCostCalculator, PriceSaverShippingCostCalculator, and StandardShippingCostCalculator are unlikely to have default constructors.

    - There are various ways to implement such an Abstract Factory, but none of them may fit perfectly. Another option is to associate metadata with each implementation. Using attributes for such purpose is the classic .NET solution: + There are various ways to implement such an Abstract Factory, but none of them may fit perfectly. Another option is to associate metadata with each implementation. Using attributes for such purpose is the classic .NET solution:

    @@ -154,13 +154,13 @@

    This implementation is created with a sequence of IBasketCalculator candidates and then selects the matching candidate upon each GetCalculator method call. (Notice that I decided that candidates was a better Role Hint than e.g. calculators.) To find a match, the method looks through the candidates and examines each candidate's [HandlesShippingMethod] attribute.

    - You may think that this is horribly inefficient because it virtually guarantees that the majority of the injected candidates are never going to be used in this method call, but that's not a concern. + You may think that this is horribly inefficient because it virtually guarantees that the majority of the injected candidates are never going to be used in this method call, but that's not a concern.

    Example: detached metadata #

    - The use of attributes has been a long-standing design principle in .NET, but seems to me to offer a poor combination of tight coupling and Primitive Obsession. To be fair, it looks like even in the BCL, the more modern APIs are less based on attributes, and more based on other alternatives. In other posts in this series on Role Hints I'll describe other ways to match objects, but even when working with metadata there are other alternatives. + The use of attributes has been a long-standing design principle in .NET, but seems to me to offer a poor combination of tight coupling and Primitive Obsession. To be fair, it looks like even in the BCL, the more modern APIs are less based on attributes, and more based on other alternatives. In other posts in this series on Role Hints I'll describe other ways to match objects, but even when working with metadata there are other alternatives.

    One alternative is to decouple the metadata from the type itself. There's no particular reason the metadata should be compiled into each type (and sometimes, if you don't own the type in question, you may not be able to do this). Instead, you can define the metadata in a simple map. Remember, 'metadata' simply means 'data about data'. @@ -184,7 +184,7 @@

    }

    - That's a much simpler implementation than before, and only requires that you supply the appropriately populated dictionary in the application's Composition Root. + That's a much simpler implementation than before, and only requires that you supply the appropriately populated dictionary in the application's Composition Root.

    Summary # diff --git a/_posts/2013-01-09-NSubstituteAuto-mockingwithAutoFixture.html b/_posts/2013-01-09-NSubstituteAuto-mockingwithAutoFixture.html index 245ab10a0..3c8b18a3d 100644 --- a/_posts/2013-01-09-NSubstituteAuto-mockingwithAutoFixture.html +++ b/_posts/2013-01-09-NSubstituteAuto-mockingwithAutoFixture.html @@ -12,7 +12,7 @@ {{ page.description }}

    - Almost two and a half years ago I added an Auto-mocking extension to AutoFixture, using Moq. Since then, a couple of other Auto-mocking extensions have been added, and this Sunday I accepted a pull request for Auto-mocking with NSubstitute, bringing the total number of Auto-mocking extensions for AutoFixture up to four: + Almost two and a half years ago I added an Auto-mocking extension to AutoFixture, using Moq. Since then, a couple of other Auto-mocking extensions have been added, and this Sunday I accepted a pull request for Auto-mocking with NSubstitute, bringing the total number of Auto-mocking extensions for AutoFixture up to four:

    • AutoFixture.AutoMoq
    • AutoFixture.AutoRhinoMocks
    • diff --git a/_posts/2013-01-10-RoleInterfaceRoleHint.html b/_posts/2013-01-10-RoleInterfaceRoleHint.html index 9b72c14bd..b48e74748 100644 --- a/_posts/2013-01-10-RoleInterfaceRoleHint.html +++ b/_posts/2013-01-10-RoleInterfaceRoleHint.html @@ -12,13 +12,13 @@ {{ page.description }}

      - In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is by implementing one or more Role Interfaces. As the name implies, a Role Interface describes a role an object can play. Classes can implement more than one Role Interface. + In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is by implementing one or more Role Interfaces. As the name implies, a Role Interface describes a role an object can play. Classes can implement more than one Role Interface.

      Example: Selecting a shipping Strategy #

      - As an example, consider the shipping Strategy selection problem from the previous post. That example seemed to suffer from the Feature Envy smell because the attribute had to expose the handled shipping method as a property in order to enable the selection mechanism to pick the right Strategy. + As an example, consider the shipping Strategy selection problem from the previous post. That example seemed to suffer from the Feature Envy smell because the attribute had to expose the handled shipping method as a property in order to enable the selection mechanism to pick the right Strategy.

      Another alternative is to define a Role Interface for matching objects to shipping methods: @@ -83,7 +83,7 @@

      Notice that because the implementation of CanHandle can be more sophisticated and conditional on the context, more than one of the candidates may be able to handle a given shipping method. This means that the order of the candidates matters. Instead of selecting a Single item from the candidates, the implementation now selects the First. This provides a fall-through mechanism where a preferred, but specialized candidate is asked before less preferred, general-purpose candidates.

      - This particular definition of the IHandleShippingMethod interface suffers from the same tight coupling to the ShippingMethod enum as the previous example. One fix may be to define the shipping method as a string, but you could still successfully argue that even implementing an interface such as IHandleShippingMethod in a Domain Model object mixes architectural concerns. Detached metadata might still be a better option. + This particular definition of the IHandleShippingMethod interface suffers from the same tight coupling to the ShippingMethod enum as the previous example. One fix may be to define the shipping method as a string, but you could still successfully argue that even implementing an interface such as IHandleShippingMethod in a Domain Model object mixes architectural concerns. Detached metadata might still be a better option.

      Summary # @@ -115,7 +115,7 @@

    - +

    You could have super-specialized IBasketCalculator implementations, that (e.g.) are only active certain times of day, and you could have the ones I've shown here, and then you could have a fallback that implements IHandleShippingMethod.CanHandle by simply returning true no matter what the input is. If you put this fallback implementations last in the injected candidates, it's only going to picked up by the First method if no other candidate (before it) returns true from CanHandle. diff --git a/_posts/2013-01-11-PartialTypeNameRoleHint.html b/_posts/2013-01-11-PartialTypeNameRoleHint.html index 24f5a876b..64afc1abb 100644 --- a/_posts/2013-01-11-PartialTypeNameRoleHint.html +++ b/_posts/2013-01-11-PartialTypeNameRoleHint.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is to let a part of a class' name convey that information. This is often very useful when using Convention over Configuration. + In my overview article on Role Hints I described how making object roles explicit can help making code more object-oriented. One way code can convey information about the role played by an object is to let a part of a class' name convey that information. This is often very useful when using Convention over Configuration.

    While a class can have an elaborate and concise name, a part of that name can communicate a particular role. If the name is complex enough, it can hint at multiple roles. @@ -21,7 +21,7 @@

    Example: Selecting a shipping Strategy #

    - As an example, consider the shipping Strategy selection problem from a previous post. Does attribute-based metadata like this really add any value? + As an example, consider the shipping Strategy selection problem from a previous post. Does attribute-based metadata like this really add any value?

    diff --git a/_posts/2013-01-16-Outside-InTest-DrivenDevelopmentPluralsightcourse.html b/_posts/2013-01-16-Outside-InTest-DrivenDevelopmentPluralsightcourse.html index 6e5dc5b3d..193f437c4 100644 --- a/_posts/2013-01-16-Outside-InTest-DrivenDevelopmentPluralsightcourse.html +++ b/_posts/2013-01-16-Outside-InTest-DrivenDevelopmentPluralsightcourse.html @@ -29,7 +29,7 @@

    2013-02-03 17:47 UTC

    - +
    Currently I don't have more information about the Skills Matter course than what's on their web site, but as it's a course about Dependency Injection, it's not going to cover TDD in particular. That's a different subject.
    2013-02-04 15:27 UTC
    diff --git a/_posts/2013-02-06-StringCalculatorkatawithAutoFixture.html b/_posts/2013-02-06-StringCalculatorkatawithAutoFixture.html index 77d50e4a7..56e6f7da9 100644 --- a/_posts/2013-02-06-StringCalculatorkatawithAutoFixture.html +++ b/_posts/2013-02-06-StringCalculatorkatawithAutoFixture.html @@ -15,12 +15,12 @@ A couple of weeks ago, at the Warm Crocodile conference in Copenhagen, Roy Osherove and I talked about AutoFixture and his String Calculator kata, and I decided to do the kata with AutoFixture 3 and make a series of screencasts out of it.

    - This series makes no particular attempt at explaining what AutoFixture is, so you might want to first acquaint yourself with some basics, such as the theory of Anonymous Variables, Derived Values, Equivalence Classes, and Constrained Non-Determinism. It might also be a good idea to understand how AutoFixture integrates with xUnit.net. + This series makes no particular attempt at explaining what AutoFixture is, so you might want to first acquaint yourself with some basics, such as the theory of Anonymous Variables, Derived Values, Equivalence Classes, and Constrained Non-Determinism. It might also be a good idea to understand how AutoFixture integrates with xUnit.net.

    The following screencasts are available:

      -
    1. Exercise 1
    2. Exercise 2
    3. Exercise 3
    4. Exercise 4
    5. Exercise 5
    6. Exercise 6
    7. Exercise 7
    8. Exercise 8
    9. +
    10. Exercise 1
    11. Exercise 2
    12. Exercise 3
    13. Exercise 4
    14. Exercise 5
    15. Exercise 6
    16. Exercise 7
    17. Exercise 8

    @@ -40,7 +40,7 @@

    2013-07-31 14:43 UTC

    - +
    Hi Cristian, thank you for writing. The way I use TestDriven.Net is that I have a keyboard shortcut (Shift+Alt+q, simply because that combination was available, and adequately fits my hand) assigned to TestDriven.NET.RunAllTestsInSolution, which Jamie Cansdale courteously added upon my request; I don't exactly remember at which version that command was added, but I'm currently running TestDriven.Net 3.4 Professional build 2808.
    diff --git a/_posts/2013-02-06-StringCalculatorkatawithAutoFixtureexercise1.html b/_posts/2013-02-06-StringCalculatorkatawithAutoFixtureexercise1.html index 0dab4bebb..1b6e650c0 100644 --- a/_posts/2013-02-06-StringCalculatorkatawithAutoFixtureexercise1.html +++ b/_posts/2013-02-06-StringCalculatorkatawithAutoFixtureexercise1.html @@ -8,7 +8,7 @@

    - This is the first post in a series of posts about the String Calculator kata done with AutoFixture. + This is the first post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast sets up the Visual Studio projects and completes the first exercise of the kata. @@ -17,7 +17,7 @@

    - Next exercise + Next exercise

    If you liked this screencast, you may also like my Pluralsight course Outside-In Test-Driven Development. @@ -35,8 +35,8 @@

    2013-02-15 21:37 UTC

    - -
    Gary, does this help?
    + +
    Gary, does this help?
    2013-02-16 08:31 UTC
    \ No newline at end of file diff --git a/_posts/2013-02-07-StringCalculatorkatawithAutofixtureexercise2.html b/_posts/2013-02-07-StringCalculatorkatawithAutofixtureexercise2.html index c797cd58d..b6880907d 100644 --- a/_posts/2013-02-07-StringCalculatorkatawithAutofixtureexercise2.html +++ b/_posts/2013-02-07-StringCalculatorkatawithAutofixtureexercise2.html @@ -8,7 +8,7 @@

    - This is the second post in a series of posts about the String Calculator kata done with AutoFixture. + This is the second post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast implements the requirement of the kata's exercise 2. @@ -17,7 +17,7 @@

    - Next exercise + Next exercise

    If you liked this screencast, you may also like my Pluralsight course Outside-In Test-Driven Development. diff --git a/_posts/2013-02-11-StringCalculatorkatawithAutofixtureexercise3.html b/_posts/2013-02-11-StringCalculatorkatawithAutofixtureexercise3.html index c088e6c9a..3b6f1dcfd 100644 --- a/_posts/2013-02-11-StringCalculatorkatawithAutofixtureexercise3.html +++ b/_posts/2013-02-11-StringCalculatorkatawithAutofixtureexercise3.html @@ -8,7 +8,7 @@

    - This is the third post in a series of posts about the String Calculator kata done with AutoFixture. + This is the third post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast implements the requirement of the kata's exercise 3. @@ -17,7 +17,7 @@

    - Next exercise + Next exercise

    If you liked this screencast, you may also like my Pluralsight course Outside-In Test-Driven Development. diff --git a/_posts/2013-02-12-StringCalculatorkatawithAutofixtureexercise4.html b/_posts/2013-02-12-StringCalculatorkatawithAutofixtureexercise4.html index dc9e6ff2a..f2757617b 100644 --- a/_posts/2013-02-12-StringCalculatorkatawithAutofixtureexercise4.html +++ b/_posts/2013-02-12-StringCalculatorkatawithAutofixtureexercise4.html @@ -8,7 +8,7 @@

    - This is the fourth post in a series of posts about the String Calculator kata done with AutoFixture. + This is the fourth post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast implements the requirement of the kata's exercise 4. @@ -17,7 +17,7 @@

    - Next exercise + Next exercise

    If you liked this screencast, you may also like my Pluralsight course Outside-In Test-Driven Development. @@ -36,7 +36,7 @@

    2013-02-12 18:22 UTC

    - +
    Undreadable? Well, my mother and my wife both find C# unreadable, while I don't (and I suspect you don't either). Other people find F# unreadable, while it's beginning to grow on me. Personally, I find Clojure unreadable, but I'm certain it's only a matter of time.

    Unit tests that leverage AutoFixture tends to be terser and more declarative in nature than more traditional unit tests, which tend to look more imperative. Like every other new thing, it takes some time getting used to.
    diff --git a/_posts/2013-02-13-StringCalculatorkatawithAutofixtureexercise5.html b/_posts/2013-02-13-StringCalculatorkatawithAutofixtureexercise5.html index 77a1e700c..f1fd10d3c 100644 --- a/_posts/2013-02-13-StringCalculatorkatawithAutofixtureexercise5.html +++ b/_posts/2013-02-13-StringCalculatorkatawithAutofixtureexercise5.html @@ -8,7 +8,7 @@

    - This is the fifth post in a series of posts about the String Calculator kata done with AutoFixture. + This is the fifth post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast implements the requirement of the kata's exercise 5. @@ -17,7 +17,7 @@

    - Next exercise + Next exercise

    If you liked this screencast, you may also like my Pluralsight course Outside-In Test-Driven Development. @@ -38,14 +38,14 @@

    2013-02-19 09:25 UTC

    - +
    Integers generated by AutoFixture have, by design, always been positive, although the algorithm has changed during the years.

    In AutoFixture 3, numbers are random.

    In AutoFixture 2.2+, all numbers are generated by a strictly monotonically increasing sequence.

    -In AutoFixture prior to 2.2, numbers were also generated as a rising sequence, but one sequence per number type.
    +In AutoFixture prior to 2.2, numbers were also generated as a rising sequence, but one sequence per number type.

    Common for all is that they are 'small, positive integers'.
    2013-02-19 19:46 UTC
    diff --git a/_posts/2013-02-14-StringCalculatorkatawithAutofixtureexercise6.html b/_posts/2013-02-14-StringCalculatorkatawithAutofixtureexercise6.html index 30c189632..f2bbbe668 100644 --- a/_posts/2013-02-14-StringCalculatorkatawithAutofixtureexercise6.html +++ b/_posts/2013-02-14-StringCalculatorkatawithAutofixtureexercise6.html @@ -8,7 +8,7 @@

    - This is the sixth post in a series of posts about the String Calculator kata done with AutoFixture. + This is the sixth post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast implements the requirement of the kata's exercise 6. @@ -17,7 +17,7 @@

    - Next exercise + Next exercise

    If you liked this screencast, you may also like my Pluralsight course Outside-In Test-Driven Development. diff --git a/_posts/2013-02-15-StringCalculatorkatawithAutofixtureexercise7.html b/_posts/2013-02-15-StringCalculatorkatawithAutofixtureexercise7.html index d8348e70a..6e0bfe15d 100644 --- a/_posts/2013-02-15-StringCalculatorkatawithAutofixtureexercise7.html +++ b/_posts/2013-02-15-StringCalculatorkatawithAutofixtureexercise7.html @@ -8,7 +8,7 @@

    - This is the seventh post in a series of posts about the String Calculator kata done with AutoFixture. + This is the seventh post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast implements the requirement of the kata's exercise 7. @@ -17,7 +17,7 @@

    - Next exercise + Next exercise

    If you liked this screencast, you may also like my Pluralsight course Outside-In Test-Driven Development. diff --git a/_posts/2013-02-18-StringCalculatorkatawithAutofixtureexercise8.html b/_posts/2013-02-18-StringCalculatorkatawithAutofixtureexercise8.html index 4274f6b02..ee37a82c3 100644 --- a/_posts/2013-02-18-StringCalculatorkatawithAutofixtureexercise8.html +++ b/_posts/2013-02-18-StringCalculatorkatawithAutofixtureexercise8.html @@ -8,7 +8,7 @@

    - This is the eighth post in a series of posts about the String Calculator kata done with AutoFixture. + This is the eighth post in a series of posts about the String Calculator kata done with AutoFixture.

    This screencast implements the requirement of the kata's exercise 8 and 9. Although the kata has nine steps, it turned out that I slightly misinterpreted the requirements of exercise 8 and ended up implementing the requirements of exercise 9 as well as those of exercise 8 - or perhaps I was just gold plating. diff --git a/_posts/2013-03-01-AutoFixture3.html b/_posts/2013-03-01-AutoFixture3.html index 5543ca748..0d53e5327 100644 --- a/_posts/2013-03-01-AutoFixture3.html +++ b/_posts/2013-03-01-AutoFixture3.html @@ -36,7 +36,7 @@

    The AutoFixture 3 kernel makes it possible to take away functionality, as well as add new functionality. At the moment, you have to understand the underlying kernel to figure out how to do that, but in the future I plan to surface an API for that as well.

    - In any case, I find it interesting that using real SOLID principles, I was able to develop the new kernel in parallel with the version 2 kernel. Partly because I was very conscious of not introducing breaking changes, but also because I follow the Open/Closed Principle, I rarely had to touch existing code, but could build the new parts of the kernel in parallel. Even more interestingly, I think, is the fact that once that work was done, replacing the kernel turned out to be a point release. This happened late November 2012 - more than three months ago. If you've been using AutoFixture 2.14.1 or a more recent version, you've already been using the AutoFixture 3 kernel for some time. + In any case, I find it interesting that using real SOLID principles, I was able to develop the new kernel in parallel with the version 2 kernel. Partly because I was very conscious of not introducing breaking changes, but also because I follow the Open/Closed Principle, I rarely had to touch existing code, but could build the new parts of the kernel in parallel. Even more interestingly, I think, is the fact that once that work was done, replacing the kernel turned out to be a point release. This happened late November 2012 - more than three months ago. If you've been using AutoFixture 2.14.1 or a more recent version, you've already been using the AutoFixture 3 kernel for some time.

    The reason I find this interesting is that sometimes casual readers of my blog express skepticism over whether the principles I talk about can be applied in 'realistic' settings. According to Ohloh, AutoFixture has a total of 197,935 lines of code, and I consider that a fair sized code base. I practice what I preach. QED. diff --git a/_posts/2013-03-03-moving-the-blog-to-jekyll.html b/_posts/2013-03-03-moving-the-blog-to-jekyll.html index 70ee6971b..655dedaf3 100644 --- a/_posts/2013-03-03-moving-the-blog-to-jekyll.html +++ b/_posts/2013-03-03-moving-the-blog-to-jekyll.html @@ -12,7 +12,7 @@ ploeh blog is sorta moving

    - For more than four years ploeh blog has been driven by dasBlog, since I originally had to move away from my original MSDN blog. At the time, dasBlog seemed like a good choice for a variety of reasons, but not too long after, development seemed to stop. + For more than four years ploeh blog has been driven by dasBlog, since I originally had to move away from my original MSDN blog. At the time, dasBlog seemed like a good choice for a variety of reasons, but not too long after, development seemed to stop.

    It's my hope that, as a reader, you haven't been too inconvenienced about that choice of blogging engine, but as the owner and author, I've grown increasingly frustrated with dasBlog. Yesterday, ploeh blog moved to a new platform and a new host. @@ -24,7 +24,7 @@

    The new platform for ploeh blog is Jekyll-Bootstrap hosted on GitHub pages. If you don't know what Jekyll-Bootstrap is, it's a parsing engine that creates a complete static web site from templates and data. This means that when you read this on the internet, you are reading a static HTML page served directly from a file. There's no application server involved.

    - Since ploeh blog is now a static web site, I had to make a few shortcuts here and there. One example is that I can't have any forms on the web site, so I can't have a contact me form - but I didn't have that before either, so that's not really a problem. There are still plenty of ways in which you can contact me. + Since ploeh blog is now a static web site, I had to make a few shortcuts here and there. One example is that I can't have any forms on the web site, so I can't have a contact me form - but I didn't have that before either, so that's not really a problem. There are still plenty of ways in which you can contact me.

    Another example is that the blog can't have a server-driven comment engine. As an alternative, Jekyll provides several options for including a third-party commenting service, such as Disqus, Livefyre, IntenseDebate, etc. I could have done that too, but have chosen to try another alternative. diff --git a/_posts/2013-03-04-code-readability-hypotheses.html b/_posts/2013-03-04-code-readability-hypotheses.html index 9a8d1ad71..a98a96da2 100644 --- a/_posts/2013-03-04-code-readability-hypotheses.html +++ b/_posts/2013-03-04-code-readability-hypotheses.html @@ -31,7 +31,7 @@ There are lots of circumstances when code is read. Often, programmers read code from inside their IDE. This has been used as an argument against Hungarian notation. However, at other times, you may be reading code as part of a review process - e.g. on GitHub or CodePlex. Or you may be reading code on a blog post, or in a book.

    - Often I feel that the this keyword helps me because it provides information about the scope of a variable. However, I also preach that code should consist of small classes with small methods, and if you follow that principle, variable scoping should be easily visible on a single screen. + Often I feel that the this keyword helps me because it provides information about the scope of a variable. However, I also preach that code should consist of small classes with small methods, and if you follow that principle, variable scoping should be easily visible on a single screen.

    Another argument against using the this keyword is that it's simply noise and that it makes it harder to read the program, simply because there's more text to read. Such a statement is impossible to refute with logic, because it depends on the person reading the code. @@ -53,7 +53,7 @@

  • Measure how quickly members of each group arrives at a correct conclusion.
  • Compare results against original hypothesis.
  • - Creative Commons License
    Code readability hypotheses by Mark Seemann is licensed under a Creative Commons Attribution 3.0 Unported License. + Creative Commons License
    Code readability hypotheses by Mark Seemann is licensed under a Creative Commons Attribution 3.0 Unported License.

    @@ -125,7 +125,7 @@

    Comments

    - +

    Karsten, I think you're reading practical issues into my proposal. Would you agree that all but the last of your reservations could be addressed if one were to pick large enough groups of test subjects, without selection bias? diff --git a/_posts/2013-03-04-outside-in-tdd-versus-ddd.html b/_posts/2013-03-04-outside-in-tdd-versus-ddd.html index 2070166cf..4bf597e4e 100644 --- a/_posts/2013-03-04-outside-in-tdd-versus-ddd.html +++ b/_posts/2013-03-04-outside-in-tdd-versus-ddd.html @@ -49,7 +49,7 @@

    Outside-In TDD #

    - Outside-In TDD, as I describe it in my Pluralsight course, isn't a design technique. TDD isn't a design technique. Granted, TDD provides fast feedback about the design you are implementing, but it's not a blind design technique. + Outside-In TDD, as I describe it in my Pluralsight course, isn't a design technique. TDD isn't a design technique. Granted, TDD provides fast feedback about the design you are implementing, but it's not a blind design technique.

    Outside-In TDD and DDD # @@ -84,10 +84,10 @@

    Comments

    2013-03-15 12:22 MST
    - +

    - Lev, thank you for your comment. While I've considered Disqus and other alternatives, I don't want to go in that direction. Free services have a tendendcy to not remain free forever - Google Reader being a current case in point. + Lev, thank you for your comment. While I've considered Disqus and other alternatives, I don't want to go in that direction. Free services have a tendendcy to not remain free forever - Google Reader being a current case in point.

    2013-03-16 08:36 GMT
    diff --git a/_posts/2013-03-08-test-trivial-code.html b/_posts/2013-03-08-test-trivial-code.html index 831a8309c..d090d6638 100644 --- a/_posts/2013-03-08-test-trivial-code.html +++ b/_posts/2013-03-08-test-trivial-code.html @@ -51,7 +51,7 @@

    Robert C. Martin's exception about getters and setters is particularly confounding. If you consider a getter/setter (or .NET property) trivial, why even have it? Why not expose a public class field instead?

    - There are good reasons why you shouldn't expose public class fields, and they are all releated to encapsulation. Data should be exposed via getters and setters because it gives you the option of changing the implementation in the future. + There are good reasons why you shouldn't expose public class fields, and they are all releated to encapsulation. Data should be exposed via getters and setters because it gives you the option of changing the implementation in the future.

    What do we call the process of changing the implementation code without changing the behavior? @@ -165,7 +165,7 @@

    Update 2014.01.07: As a follow-up to this article, Jon Galloway interviewed me about this, and other subject, for a Herding Code podcast.

    - Update, 2018.11.12: A new article reflects on this one, and gives a more nuanced picture of my current thinking. + Update, 2018.11.12: A new article reflects on this one, and gives a more nuanced picture of my current thinking.

    diff --git a/_posts/2013-03-11-auto-mocking-container.html b/_posts/2013-03-11-auto-mocking-container.html index e90b58a95..706053338 100644 --- a/_posts/2013-03-11-auto-mocking-container.html +++ b/_posts/2013-03-11-auto-mocking-container.html @@ -50,7 +50,7 @@

    When to use it #

    - Use an Auto-mocking Container when you are unit testing classes which utilize DI (particularly Constructor Injection). In a fully loosely coupled system, constructors are implementation details, which means that you may decide to change constructor signatures as part of refactoring. + Use an Auto-mocking Container when you are unit testing classes which utilize DI (particularly Constructor Injection). In a fully loosely coupled system, constructors are implementation details, which means that you may decide to change constructor signatures as part of refactoring.

    Particularly early in a code base's lifetime, the system and its internal design may be in flux. In order to enable refactoring, it's important to be able to change constructor signatures without worrying about breaking tests. In such cases, an Auto-mocking Container can be of great help. @@ -377,7 +377,7 @@

    This example demonstrated how to repurpose Castle Windsor as an Auto-mocking Container. It's important to realize that this is still a pure unit testing concern. It doesn't require you to use Castle Windsor in your production code.

    - Other DI Containers can be repurposed as Auto-mocking Containers as well. One option is Autofac, and while not strictly a DI Container, another option is AutoFixture. + Other DI Containers can be repurposed as Auto-mocking Containers as well. One option is Autofac, and while not strictly a DI Container, another option is AutoFixture.

    This article first appeared in the Open Source Journal 2012 issue 4. It is reprinted here with kind permission. diff --git a/_posts/2013-03-11-listen-to-trivial-tests.html b/_posts/2013-03-11-listen-to-trivial-tests.html index 327e27eaf..5ab5e808f 100644 --- a/_posts/2013-03-11-listen-to-trivial-tests.html +++ b/_posts/2013-03-11-listen-to-trivial-tests.html @@ -12,7 +12,7 @@ {{ page.description }}

    - A couple of days ago I published a blog post that caused some people to react, telling me that I'm wrong. That's most certainly a possibility, but what if I'm not? In this post I'd like to provide a bit of background on why I wrote that previous post, and where it may lead us. + A couple of days ago I published a blog post that caused some people to react, telling me that I'm wrong. That's most certainly a possibility, but what if I'm not? In this post I'd like to provide a bit of background on why I wrote that previous post, and where it may lead us.

    Craftmanship # @@ -48,7 +48,7 @@

    As always, we should take to heart the advice from GOOS: Listen to your tests.

    - If you think that it's ridiculous to write tests for automatic properties, then what is the feedback really about? + If you think that it's ridiculous to write tests for automatic properties, then what is the feedback really about?

    Most of my critics present the choices like this: @@ -102,7 +102,7 @@

    I agree with both Robert C. Martin and Mark Rendle that in a lot of cases, we don't really care about anything as nitty-gritty as a single property. What we often care about is the overall behavior of a system. This is also the approach I teach in my Pluralsight course on Outside-In Test Driven Development. You don't see me write tests of properties there.

    - However, I made a mistake in that course, and another mistake in my previous post, and that was to design View Models with properties. Why are we even adding properties to View Models? The purpose of a View Model is to render in a particular way, either as UI, XML, JSON or something else. We care about the end result, not what the View Model class looks like. At the boundaries, applications aren't object-oriented. + However, I made a mistake in that course, and another mistake in my previous post, and that was to design View Models with properties. Why are we even adding properties to View Models? The purpose of a View Model is to render in a particular way, either as UI, XML, JSON or something else. We care about the end result, not what the View Model class looks like. At the boundaries, applications aren't object-oriented.

    The JournalEntryModel from my Pluralsight course should really have look like this: @@ -124,7 +124,7 @@

    Summary #

    - There may still be cases where properties are appropriate. If, for example, instead of writing an end-to-end application, you are writing a reusable library, properties provide encapsulation. In such cases, the property has a particular purpose, and it still makes sense to me to capture that behavior (yes: behavior, not data) in a regression test. + There may still be cases where properties are appropriate. If, for example, instead of writing an end-to-end application, you are writing a reusable library, properties provide encapsulation. In such cases, the property has a particular purpose, and it still makes sense to me to capture that behavior (yes: behavior, not data) in a regression test.

    However, most of the times properties aren't warranted, and you might as well use a public field - this is the YAGNI principle applied. You don't have to test public fields because they can't possibly have any behavior. @@ -184,7 +184,7 @@

    Comments

    - +
    Svick, if you change a public field into a property, it would be a breaking change, so there's a very real distinction there.
    diff --git a/_posts/2013-04-04-structural-inspection.html b/_posts/2013-04-04-structural-inspection.html index 0ef29dd39..928c2e160 100644 --- a/_posts/2013-04-04-structural-inspection.html +++ b/_posts/2013-04-04-structural-inspection.html @@ -70,7 +70,7 @@

    }

    - In the above example, the Discount class contains an amount (a decimal value), and implements the IBasketElement interface. The Accept method is the only member defined by that interface. The design philosophy of Structural Inspection is very simple: because it accepts an amount in its constructor, it should also expose that value as a public Amount property (or field). + In the above example, the Discount class contains an amount (a decimal value), and implements the IBasketElement interface. The Accept method is the only member defined by that interface. The design philosophy of Structural Inspection is very simple: because it accepts an amount in its constructor, it should also expose that value as a public Amount property (or field).

    People unused to TDD often react in one of two ways: @@ -80,13 +80,13 @@

    - Well, if you follow TDD, all production code you write, you write as a response to a test you just wrote. The unit tests are the first client of the production API. The important part is whether or not adding a member breaks encapsulation. Adding a property that exposes something that was passed into the constructor by a client, can hardly be said to break encapsulation. Exposing properties doesn't necessarily break encapsulation. Even if you believe that encapsulation is 'information hiding', it makes no sense to hide data that was passed into the object instance by a third party. The object simply isn't the exclusive owner of that data. + Well, if you follow TDD, all production code you write, you write as a response to a test you just wrote. The unit tests are the first client of the production API. The important part is whether or not adding a member breaks encapsulation. Adding a property that exposes something that was passed into the constructor by a client, can hardly be said to break encapsulation. Exposing properties doesn't necessarily break encapsulation. Even if you believe that encapsulation is 'information hiding', it makes no sense to hide data that was passed into the object instance by a third party. The object simply isn't the exclusive owner of that data.

    However, since the object (like the Discount class in the above example) already holds an instance of the data as a field, it might as well be courteous and share that information with its client. Otherwise, that would just put the onus on the client to remember the value it passed via the constructor.

    - Ultimately, adding a property to a concrete class has no impact on the exposed interface. Since a constructor is an implementation detail, by corollary Inspection Properties are also implementation details. While they don't break encapsulation, they are only part of the concrete class. At the interface level, they are invisible. Interfaces are general, but concrete types are specific. + Ultimately, adding a property to a concrete class has no impact on the exposed interface. Since a constructor is an implementation detail, by corollary Inspection Properties are also implementation details. While they don't break encapsulation, they are only part of the concrete class. At the interface level, they are invisible. Interfaces are general, but concrete types are specific.

    Unit testing # @@ -95,7 +95,7 @@

    The API design philosophy is easy to understand, but what does that mean for unit testing? The great thing is that it's possible to test each part of the whole in isolation, and then subsequently prove that parts correctly interact.

    - Consider the Discount class. It's easy to prove that the injected amount is properly exposed as a property: + Consider the Discount class. It's easy to prove that the injected amount is properly exposed as a property:

    [Theory]
    @@ -223,7 +223,7 @@ 

    Verifying the whole #

    - You can keep on working like this: establishing that the behavior of each small part follows the correct protocols. Once all fine-grained building blocks are in place, the only thing left to do is to verify that they are correctly composed. This is where Structural Inspection is very powerful. This is how you can verify that a BasketPipeline will have the correct behavior: + You can keep on working like this: establishing that the behavior of each small part follows the correct protocols. Once all fine-grained building blocks are in place, the only thing left to do is to verify that they are correctly composed. This is where Structural Inspection is very powerful. This is how you can verify that a BasketPipeline will have the correct behavior:

    [Fact]
    @@ -270,7 +270,7 @@ 

    The test verifies the structure of the API's Facade, and because the Facade has the correct structure and previous tests have proven that all the parts have the correct behavior, the Facade must have the desired higher-order behavior.

    - In order to write this article, I TDD'ed all the code presented here (and more), and I deliberately didn't try to apply the BasketPipeline to some Basket instances until I had all the structure in place. Once I had that, I wrote a few Facade Tests as sanity checks, and they all passed in the first attempt. + In order to write this article, I TDD'ed all the code presented here (and more), and I deliberately didn't try to apply the BasketPipeline to some Basket instances until I had all the structure in place. Once I had that, I wrote a few Facade Tests as sanity checks, and they all passed in the first attempt.

    Conclusion # @@ -314,7 +314,7 @@

    Comments

    2015-02-13 02:12 UTC

    - +

    Thank you for writing. With functions, I've yet to find a good alternative to Structural Inspection, so I find myself writing more Integration Tests when I write F# code. On the other hand, because the F# type system is so much stronger than e.g. C#, I've also found that I can design data structures in such a way that illegal states become unrepresentable, and that again means that I need to write fewer unit tests than I would have to with F#. diff --git a/_posts/2013-04-05-how-to-configure-automoq-to-set-up-all-properties.html b/_posts/2013-04-05-how-to-configure-automoq-to-set-up-all-properties.html index 75ef44b29..d48661c4c 100644 --- a/_posts/2013-04-05-how-to-configure-automoq-to-set-up-all-properties.html +++ b/_posts/2013-04-05-how-to-configure-automoq-to-set-up-all-properties.html @@ -12,7 +12,7 @@ {{ page.description }}

    - From time to time, people want the AutoFixture.AutoMoq Auto-Mocking Container to set up all mock instances to have 'normal' property behavior. + From time to time, people want the AutoFixture.AutoMoq Auto-Mocking Container to set up all mock instances to have 'normal' property behavior.

    By default, Moq doesn't implement any members of an interface. You have to explicitly configure the desired behavior using the Setup methods. This is also true for properties (which are really only special methods). diff --git a/_posts/2013-04-08-how-to-automatically-populate-properties-with-automoq.html b/_posts/2013-04-08-how-to-automatically-populate-properties-with-automoq.html index 5578fd29a..599133c94 100644 --- a/_posts/2013-04-08-how-to-automatically-populate-properties-with-automoq.html +++ b/_posts/2013-04-08-how-to-automatically-populate-properties-with-automoq.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In a previous blog post I described how to configure AutoFixture.AutoMoq to set up all mock instances to have 'normal' property behavior. This enables you to assign and retrieve values from properties defined by interfaces, but still doesn't fill those properties with values. + In a previous blog post I described how to configure AutoFixture.AutoMoq to set up all mock instances to have 'normal' property behavior. This enables you to assign and retrieve values from properties defined by interfaces, but still doesn't fill those properties with values.

    Apparently, people want to do that, so here's how to do it with the AutoMoq glue library. diff --git a/_posts/2013-04-09-ploeh-blog-syndication-feed-addresses.html b/_posts/2013-04-09-ploeh-blog-syndication-feed-addresses.html index a6890fd14..9b1f24fbe 100644 --- a/_posts/2013-04-09-ploeh-blog-syndication-feed-addresses.html +++ b/_posts/2013-04-09-ploeh-blog-syndication-feed-addresses.html @@ -15,7 +15,7 @@ Now that Google Reader is closing down and a lot of my readers may want to migrate their ploeh blog subscription to another service, I think it's the right time for a quick post about ploeh blog's syndication feed addresses.

    - When I migrated my blog to Jekyll I made it a priority to ensure a certain level of backwards compatibility. The permalinks for the old posts are still served, although they are now redirects. For that reason, I also left the old syndication feed addresses in place. Specifically, I left this old RSS feed address in place: http://blog.ploeh.dk/SyndicationService.asmx/GetRss. This feed address sort of works, but has issues. + When I migrated my blog to Jekyll I made it a priority to ensure a certain level of backwards compatibility. The permalinks for the old posts are still served, although they are now redirects. For that reason, I also left the old syndication feed addresses in place. Specifically, I left this old RSS feed address in place: /SyndicationService.asmx/GetRss. This feed address sort of works, but has issues.

    There are several problems with the 'legacy' feed address: @@ -32,8 +32,8 @@

    The proper syndication feed addresses for ploeh blog are:

    Both serve responses with the "text/xml" Content-Type.

    diff --git a/_posts/2013-04-11-fizzbuzz-kata-in-clojure.html b/_posts/2013-04-11-fizzbuzz-kata-in-clojure.html index 0788a2d90..63cb12dd3 100644 --- a/_posts/2013-04-11-fizzbuzz-kata-in-clojure.html +++ b/_posts/2013-04-11-fizzbuzz-kata-in-clojure.html @@ -233,6 +233,6 @@

    As you can see, the first overload takes no parameters and simply invokes the previously desribed overload with the start and end arguments.

    - FWIW, this entire solution is structurally similar to my implementation of FizzBuzz in F#. + FWIW, this entire solution is structurally similar to my implementation of FizzBuzz in F#.

    \ No newline at end of file diff --git a/_posts/2013-04-29-rest-lesson-learned-avoid-user-supplied-data-in-uri-segments.html b/_posts/2013-04-29-rest-lesson-learned-avoid-user-supplied-data-in-uri-segments.html index 008765d45..43a59fcf9 100644 --- a/_posts/2013-04-29-rest-lesson-learned-avoid-user-supplied-data-in-uri-segments.html +++ b/_posts/2013-04-29-rest-lesson-learned-avoid-user-supplied-data-in-uri-segments.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is a lesson about design of REST APIs that I learned the hard way: if you built service URIs from dynamic data, be careful with the data you allow in URI segments. + This is a lesson about design of REST APIs that I learned the hard way: if you built service URIs from dynamic data, be careful with the data you allow in URI segments.

    Some HTTP frameworks (e.g. the ASP.NET Web API) let you define URI templates or routes that handle incoming requests - e.g. diff --git a/_posts/2013-04-29-rest-lessons-learned.html b/_posts/2013-04-29-rest-lessons-learned.html index 1fd9487bd..42fb078e3 100644 --- a/_posts/2013-04-29-rest-lessons-learned.html +++ b/_posts/2013-04-29-rest-lessons-learned.html @@ -25,11 +25,11 @@

    diff --git a/_posts/2013-04-30-rest-lesson-learned-avoid-204-responses.html b/_posts/2013-04-30-rest-lesson-learned-avoid-204-responses.html index e39dc4c41..73d1b23db 100644 --- a/_posts/2013-04-30-rest-lesson-learned-avoid-204-responses.html +++ b/_posts/2013-04-30-rest-lesson-learned-avoid-204-responses.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is a lesson about REST API design that I learned while building non-trivial REST APIs. In order to be as supportive of the client as possible, a REST API should not return 204 (No Content) responses. + This is a lesson about REST API design that I learned while building non-trivial REST APIs. In order to be as supportive of the client as possible, a REST API should not return 204 (No Content) responses.

    From the service's perspective, a 204 (No Content) response may be a perfectly valid response to a POST, PUT or DELETE request. Particularly, for a DELETE request it seems very appropriate, because what else can you say? @@ -101,7 +101,7 @@

    Comments

    2015-04-02 17:24 UTC
    - +

    Xander, thank you for writing. If you read this article carefully, you may notice that it's not an exegesis of the HTTP specification, but a guideline to writing pleasant and useful RESTful services. @@ -140,7 +140,7 @@

    Comments

    2015-06-12 13:50 UTC
    - +

    Derek, thank you for writing. It's a good point that some media types like images, audio, etc. don't have a natural place to put meta-data like links. Conceivably, that might even include vendor-specific media types where, for some reason or other, links don't fit. diff --git a/_posts/2013-05-01-herding-code-podcast.html b/_posts/2013-05-01-herding-code-podcast.html index d3fc222a5..6a2c97f20 100644 --- a/_posts/2013-05-01-herding-code-podcast.html +++ b/_posts/2013-05-01-herding-code-podcast.html @@ -12,6 +12,6 @@ {{ page.description }}

    - At the Danish Developer Conference 2013 I had the pleasure of meeting Jon Galloway, who interviewed me for a Herding Code podcast. In this interview, we talk about AutoFixture, testing (or not testing) trivial code, as well as lots of the unit testing topics I also cover in my Pluralsight course on Advanced Unit Testing. + At the Danish Developer Conference 2013 I had the pleasure of meeting Jon Galloway, who interviewed me for a Herding Code podcast. In this interview, we talk about AutoFixture, testing (or not testing) trivial code, as well as lots of the unit testing topics I also cover in my Pluralsight course on Advanced Unit Testing.

    \ No newline at end of file diff --git a/_posts/2013-05-01-rest-lesson-learned-avoid-hackable-urls.html b/_posts/2013-05-01-rest-lesson-learned-avoid-hackable-urls.html index cb28a9f87..a4f27d35d 100644 --- a/_posts/2013-05-01-rest-lesson-learned-avoid-hackable-urls.html +++ b/_posts/2013-05-01-rest-lesson-learned-avoid-hackable-urls.html @@ -13,7 +13,7 @@ {{ page.description }}

    - This is a lesson about REST API design that I learned while building non-trivial REST APIs. If you provide a full-on level 3 REST API, consider avoiding hackable URLs. + This is a lesson about REST API design that I learned while building non-trivial REST APIs. If you provide a full-on level 3 REST API, consider avoiding hackable URLs.

    Hackable URLs # @@ -105,7 +105,7 @@

    Comments

    @@ -152,7 +152,7 @@

    Comments

    @@ -183,7 +183,7 @@

    Comments

    @@ -225,7 +225,7 @@

    Comments

    2014-12-23 17:40 UTC
    - +

    Kijana, thank you for writing. You suggest various good ideas that I'll have to keep in mind. Not all of them are universally applicable, but then I also don't think that my suggestion should be applied indiscriminately. @@ -267,7 +267,7 @@

    Comments

    2015-04-11 09:26 UTC
    - +

    Dan, thank you for sharing that great idea! That looks like a much better solution than my original suggestion of obscuring the URL, because the URL is still human-readable, and thus probably still easier to troubleshoot for developers. @@ -303,7 +303,7 @@

    Comments

    2015-04-11 17:58 UTC
    - +

    Dan, there are lots of interesting ideas there. What I assumed from your first comment is that you'd calculate the HMAC using asymmetric encryption, which would mean that unless clients have the server's encryption key, they wouldn't be able to recalculate the HMAC, and that would effectively prevent them from attempting to 'guess' URLs instead of following links. @@ -339,7 +339,7 @@

    Comments

    2016-02-25 11:20 UTC
    - +

    Ruben, thank you for writing. This is a commonly occuring requirement, particularly when searching for particular resources, and I usually solve it with URI templates, as outlined in the RESTful Web Services Cookbook. Essentially, it involves providing URI templates like http://foo.ploeh.dk/0D89C19343DA4ED985A492DA1A8CDC53/{term}, and making sure that each template is served like a link, with a particular relationship type. For example: @@ -372,7 +372,7 @@

    Comments

    2016-03-02 19:45 UTC
    - +

    Ruben, it's not that you can't avoid hackable URLs. URI templates are an optimisation that you can opt to apply, but you don't have to use them. As with so many other architecture decisions, it's a trade-off. @@ -428,7 +428,7 @@

    Comments

    Location: http://example.com/0D25692DE79B4AF9A73F128554A9119E

    - In both cases, though, you'll need to document the valid representations that a client can POST to the search resource, which means that you need to consider backwards compatibility if you want to change things, and so on. In other words, you can 'protect' the URL schema of the search resource, but not the payload schema. + In both cases, though, you'll need to document the valid representations that a client can POST to the search resource, which means that you need to consider backwards compatibility if you want to change things, and so on. In other words, you can 'protect' the URL schema of the search resource, but not the payload schema.

    If you're already exposing an API over HTTPS, caching is of marginal relevance anyway, so you may decide to use the first POST option outlined above. Sometimes, however, performance is more important than transport security. As an example, I once wrote (for a client) a publicly available music catalogue API. This API isn't protected, because the data isn't secret, and it has to be fast. Resources are cached for 6 hours, so if you're searching for something popular (say, Rihanna), odds are that you're going to get a response from an intermediary cache. URI templates work well in this scenario, but it's a deliberate performance optimisation. @@ -456,13 +456,13 @@

    Comments

    2016-03-10 23:50 UTC
    - +

    Ruben, my intent with this post was to highlight a problem I've experienced when publishing REST APIs, and that I've attempted to explain in the section titled Keep clients safe. I wish that problem didn't exist, but in my experience, it does. It most likely depends on a lot of factors, so if you don't have that problem, you can disregard the entire article.

    - The issue isn't that I want to make URLs opaque. The real issue at stake is that I want clients to follow links, because it gives me options to evolve the API. Consider the example in this article. If a client wants to see a user's messages, it should follow links. If, however, a client developer writes the code in such a way that it'll explicitly look for a root > users > user details > user messages route, little is gained. + The issue isn't that I want to make URLs opaque. The real issue at stake is that I want clients to follow links, because it gives me options to evolve the API. Consider the example in this article. If a client wants to see a user's messages, it should follow links. If, however, a client developer writes the code in such a way that it'll explicitly look for a root > users > user details > user messages route, little is gained.

    A client looking for user messages should be implemented with a prioritised rule set: @@ -505,7 +505,7 @@

    Comments

    2016-06-23 15:18 UTC
    - +

    Ashley, thank you for writing. In the end, as you point out, it's the client's problem if they don't adhere to the contract. In some scenarios, that's the end of the story. In other scenarios (e.g. the ones I often find myself in), there's a major client that has a lot of clout, and if those developers find that you've moved their cheese, their default reaction is that it's your fault - not theirs. In such cases, it can be political to ensure that there's no doubt about the contract. diff --git a/_posts/2013-05-02-rest-lesson-learned-consider-a-home-link-on-all-resources.html b/_posts/2013-05-02-rest-lesson-learned-consider-a-home-link-on-all-resources.html index 99265207a..112ae5cbd 100644 --- a/_posts/2013-05-02-rest-lesson-learned-consider-a-home-link-on-all-resources.html +++ b/_posts/2013-05-02-rest-lesson-learned-consider-a-home-link-on-all-resources.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This suggestion is part of my REST lessons learned series of blog posts. Contrary to the previous posts, this advice doesn't originate from a lesson learned the hard way, but is more of a gentle suggestion. + This suggestion is part of my REST lessons learned series of blog posts. Contrary to the previous posts, this advice doesn't originate from a lesson learned the hard way, but is more of a gentle suggestion.

    When designing a level 3 RESTful API, I've found that it's often helpful to think about design issues in terms of: how would you design it if it was a web site? On web sites, we don't ask users to construct URLs and enter them into the browser's address bar. On web sites, users follow links (and fill out forms). Many well-designed web sites are actually HATEOAS services, so it makes sense to learn from them when designing RESTful APIs. @@ -63,9 +63,9 @@ Notice that in addition to the two category links, the resource representation also contains a home link, enabling the client to go back to the 'home' resource.

    - Having a home link on all resources is another courtesy to the client, just like avoiding 204 responses - in fact, if you can't think of anything else to return instead of 204 (No Content), at the very least, you could return a home link. + Having a home link on all resources is another courtesy to the client, just like avoiding 204 responses - in fact, if you can't think of anything else to return instead of 204 (No Content), at the very least, you could return a home link.

    - In the above examples, I didn't obfuscate the URLs, but I would do that for a real REST API. The reason I didn't obfuscate the URLs here is to make the example easier to understand. + In the above examples, I didn't obfuscate the URLs, but I would do that for a real REST API. The reason I didn't obfuscate the URLs here is to make the example easier to understand.

    \ No newline at end of file diff --git a/_posts/2013-05-03-rest-lesson-learned-consider-a-self-link-on-all-resources.html b/_posts/2013-05-03-rest-lesson-learned-consider-a-self-link-on-all-resources.html index 517e5dcea..bd901c551 100644 --- a/_posts/2013-05-03-rest-lesson-learned-consider-a-self-link-on-all-resources.html +++ b/_posts/2013-05-03-rest-lesson-learned-consider-a-self-link-on-all-resources.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This suggestion is part of my REST lessons learned series of blog posts. Contrary to previous posts, this advice doesn't originate from a lesson learned the hard way, but is more of a gentle suggestion. + This suggestion is part of my REST lessons learned series of blog posts. Contrary to previous posts, this advice doesn't originate from a lesson learned the hard way, but is more of a gentle suggestion.

    One of the many advantages of a well-designed REST API is that it's 'web-scale'. The reason it's 'web-scale' is because it can leverage HTTP caching. @@ -55,7 +55,7 @@

    Redirected clients #

    - A level 3 RESTful API can evolve over time. As I previously described, you may start with URLs like http://foo.ploeh.dk/orders/1234 only to realize that in a later version of the API, you'd rather want it to be http://foo.ploeh.dk/customers/1234/orders. + A level 3 RESTful API can evolve over time. As I previously described, you may start with URLs like http://foo.ploeh.dk/orders/1234 only to realize that in a later version of the API, you'd rather want it to be http://foo.ploeh.dk/customers/1234/orders.

    As the RESTful Web Services Cookbook explains, you should keep URLs cool. In practice, that means that if you change the URLs of your API, you should at least leave a 301 (Moved Permanently) at the old URL. @@ -94,7 +94,7 @@

    Comments

    2014-02-13 22:45 UTC
    - +

    The primary reason I didn't mention the Content-Location header here was that, frankly, I wasn't aware of it. Now that I've read the specification, I'll have to take your word for it :) You may be right, in which case there's no particular reason to prefer a self-link over a Content-Location header. diff --git a/_posts/2013-06-17-where-to-put-unit-tests.html b/_posts/2013-06-17-where-to-put-unit-tests.html index 6a1663a55..d8353463d 100644 --- a/_posts/2013-06-17-where-to-put-unit-tests.html +++ b/_posts/2013-06-17-where-to-put-unit-tests.html @@ -47,7 +47,7 @@

    API design feedback #

    - While I find regression testing useful in itself, I find Test-Driven Development (TDD) particularly valuable because it provides feedback about the API I'm building. In the spirit of GOOS, if the test is difficult to write, it's probably because the API is difficult to use. You'll only get this feedback if you test against the public API of your code; the unit test is the first client of your API. + While I find regression testing useful in itself, I find Test-Driven Development (TDD) particularly valuable because it provides feedback about the API I'm building. In the spirit of GOOS, if the test is difficult to write, it's probably because the API is difficult to use. You'll only get this feedback if you test against the public API of your code; the unit test is the first client of your API.

    However, if your unit tests reside in the same library as your production code, you can easily invoke internal classes and members from your unit tests. You simply lose the opportunity to get valuable feedback about the usability of your code. (Note that this argument also applies to the use of the [InternalsVisibleTo] attribute, which means that you should never use it.) @@ -96,7 +96,7 @@

    Comments

    2013-12-04 09:30
    - +

    Jeff, thank you for writing. @@ -105,7 +105,7 @@

    Comments

    If I were to exaggerate a bit, I would claim that I've used Test-Driven Development (TDD) longer than I've used source control systems, so it has never occurred to me to keep tests in a separate repository. It sounds really... inconvenient, but I've never tried it, so I don't know if it's a good or bad idea. Yet, in all that time, I've never had any problems keeping tests and production code in the same version control repository.

    - With TDD, the tests are such an integral part of the code base that I wouldn't like to experiment with keeping them in a different repository. Additionally, when you use a test suite as a regression test suite, it's important that you version tests and production code together. This also means tagging them together. + With TDD, the tests are such an integral part of the code base that I wouldn't like to experiment with keeping them in a different repository. Additionally, when you use a test suite as a regression test suite, it's important that you version tests and production code together. This also means tagging them together.

    If you take a look at the various code bases I maintain on GitHub, you will also see that all of them include unit tests as part of each repository. diff --git a/_posts/2013-07-08-defensive-coding.html b/_posts/2013-07-08-defensive-coding.html index 2efe5d290..530adff2f 100644 --- a/_posts/2013-07-08-defensive-coding.html +++ b/_posts/2013-07-08-defensive-coding.html @@ -154,7 +154,7 @@

    Is it possible to balance the forces at play here? Yes it is, but in order to understand how, you need to understand the root cause of the problem. The original code example isn't particularly complicated, but even so, there are so many ways it can fail. When it comes to null references, the cause is a language design mistake, but in general, the question is whether or not you can trust input. The return values from invoking IUserRepository.Get is (indirect) input too.

    - Depending on the environment in which your program is running, you may or may not be able to trust input. Consider, for a moment, the situation where your software is running in the wild. It may be a reusable library or framework. In this case, you can't trust input at all. If fact, you may want to apply the robustness principle and make sure that, not only are you going to be very defensive about input, but you're also going to be careful and nice about the output of your program. In other words, you don't want to pass null (or other evil values) to your collaborators. + Depending on the environment in which your program is running, you may or may not be able to trust input. Consider, for a moment, the situation where your software is running in the wild. It may be a reusable library or framework. In this case, you can't trust input at all. If fact, you may want to apply the robustness principle and make sure that, not only are you going to be very defensive about input, but you're also going to be careful and nice about the output of your program. In other words, you don't want to pass null (or other evil values) to your collaborators.

    The sample code presented here may pass null to its dependencies, e.g. if userId is null, or (more subtly) if user.PreferredCurrency is null. Thus, to apply the robustness principle, you'd have to add even more defensive coding: @@ -230,7 +230,7 @@

    Protected enclosures #

    - What if your code is a zoo animal? What if your code is running in an environment, where all the collaborators are other classes also part of the same code base, written by you and your colleagues? If you can trust each other to follow some consistent rules, you could skip much of the defensive coding. + What if your code is a zoo animal? What if your code is running in an environment, where all the collaborators are other classes also part of the same code base, written by you and your colleagues? If you can trust each other to follow some consistent rules, you could skip much of the defensive coding.

    In most of the teams I work with, I always suggest that we adopt the robustness principle. In practice, that means that null is never an acceptable return value. If a class member returns null, the bug is in that class, not in the consumer. Following that team rule, the code example can be reduced to this: @@ -375,13 +375,13 @@

    }

    - Notice how the User class protects its invariants. The PreferredCurrency property can never be null. This principle is also known by another name: it's called encapsulation. + Notice how the User class protects its invariants. The PreferredCurrency property can never be null. This principle is also known by another name: it's called encapsulation.

    Summary #

    - As always, it helps to understand the forces working or your code base. You have to be much more defensive if your code is running in the wild, than if it's running in a protected environment. Still, I generally think that it's a fallacy if you believe that you can get by with writing sloppy code; we should all be Ranger programmers. + As always, it helps to understand the forces working or your code base. You have to be much more defensive if your code is running in the wild, than if it's running in a protected environment. Still, I generally think that it's a fallacy if you believe that you can get by with writing sloppy code; we should all be Ranger programmers.

    Unstructured defensive coding hurts readability; it's just another excuse for writing Spaghetti Code. Conversely, structured defensive coding is encapsulation. I know what I prefer. diff --git a/_posts/2013-07-20-linq-versus-the-lsp.html b/_posts/2013-07-20-linq-versus-the-lsp.html index 1f366d812..0b0b8fcd3 100644 --- a/_posts/2013-07-20-linq-versus-the-lsp.html +++ b/_posts/2013-07-20-linq-versus-the-lsp.html @@ -12,7 +12,7 @@ {{ page.description }}

    - As a reaction to my my previous post on Defensive Coding, one of my readers sent me this question: + As a reaction to my my previous post on Defensive Coding, one of my readers sent me this question:

    @@ -50,7 +50,7 @@

    IEnumerable<T> is one of the most misunderstood interfaces in .NET. It carries very few guarantees, and many method calls on it may actually break the Liskov Substitution Principle (LSP). ToArray is one of them, because it assumes that the sequence produced by the Iterator is finite, which it may not be. Thus, if you invoke ToArray on an infinite Iterator, you will eventually get an exception.

    - It doesn't really matter whether you call ToArray in the constructor, or in the class method(s) where you use the injected IEnumerable<T>. However, from a Fail First perspective, and in order to protect the class' invariant, if the class requires the sequence to be finite, you could argue that you should invoke ToArray (or ToList) in the constructor. However, this breaks Nikola Malovic's 4th law of IoC: constructors should do no work. This should make you stop and ponder: if you require an array, you should state that requirement up front: + It doesn't really matter whether you call ToArray in the constructor, or in the class method(s) where you use the injected IEnumerable<T>. However, from a Fail First perspective, and in order to protect the class' invariant, if the class requires the sequence to be finite, you could argue that you should invoke ToArray (or ToList) in the constructor. However, this breaks Nikola Malovic's 4th law of IoC: constructors should do no work. This should make you stop and ponder: if you require an array, you should state that requirement up front:

    public class Publisher
    @@ -79,7 +79,7 @@ 

    LINQ and the LSP #

    - In a previous post, I've talked about the conflict between IQueryable and the LSP, but even constraining the discussion to LINQ to Objects, it turns out that LINQ has lots of built-in LSP violations. + In a previous post, I've talked about the conflict between IQueryable and the LSP, but even constraining the discussion to LINQ to Objects, it turns out that LINQ has lots of built-in LSP violations.

    Recall the essence of the LSP: you should be able to pass any implementation of an interface to a client without changing the correctness of the system. While 'correctness' is application-specific, the lowest common denominator must be that if a method works for one implementation, it mustn't throw exceptions for another implementation. However, consider these two implementations of IEnumerable<string>: diff --git a/_posts/2013-08-23-how-to-create-a-pure-f-aspnet-web-api-project.html b/_posts/2013-08-23-how-to-create-a-pure-f-aspnet-web-api-project.html index 510b83cca..85c9e6d7a 100644 --- a/_posts/2013-08-23-how-to-create-a-pure-f-aspnet-web-api-project.html +++ b/_posts/2013-08-23-how-to-create-a-pure-f-aspnet-web-api-project.html @@ -189,7 +189,7 @@

    Success, of a sort!

    - This Web API now runs in IIS Express on my local machine. However, at this point, it still doesn't run in an Azure Web Site (which is something I also wanted to enable), but I'll cover how to do that in a future post. + This Web API now runs in IIS Express on my local machine. However, at this point, it still doesn't run in an Azure Web Site (which is something I also wanted to enable), but I'll cover how to do that in a future post.

    Update 2013.19.12: It turns out that it's possible to hack the registry to make it possible to add standard F# project items to the project. @@ -211,7 +211,7 @@

    Comments

    2013-08-23 17:10 UTC

    - +

    Mike, that's a great tip! Thank you. diff --git a/_posts/2013-08-26-running-a-pure-f-web-api-on-azure-web-sites.html b/_posts/2013-08-26-running-a-pure-f-web-api-on-azure-web-sites.html index 9b4b01233..8d1c44478 100644 --- a/_posts/2013-08-26-running-a-pure-f-web-api-on-azure-web-sites.html +++ b/_posts/2013-08-26-running-a-pure-f-web-api-on-azure-web-sites.html @@ -13,7 +13,7 @@ {{ page.description }}

    - In my previous post, I explained how to create an ASP.NET Web API project entirely in F#, without relying on a C# or VB host project. At the end of that article, I had a service which can be launched from Visual Studio 2012 and run in IIS Express, but it didn't run in Azure Web Sites. In this post, I'll explain how to make this possible. + In my previous post, I explained how to create an ASP.NET Web API project entirely in F#, without relying on a C# or VB host project. At the end of that article, I had a service which can be launched from Visual Studio 2012 and run in IIS Express, but it didn't run in Azure Web Sites. In this post, I'll explain how to make this possible.

    Deploying to Azure # diff --git a/_posts/2013-09-06-dependency-injection-and-events.html b/_posts/2013-09-06-dependency-injection-and-events.html index 7711102bf..60fd6d6b7 100644 --- a/_posts/2013-09-06-dependency-injection-and-events.html +++ b/_posts/2013-09-06-dependency-injection-and-events.html @@ -16,7 +16,7 @@

    - I want to register to a plain old .NET event of a dependency that is supplied via constructor injection. I read your book "DI in .NET" and in it you mention that injection constructors should be simple and not perform any other work than guarding for null values and assigning the dependencies to (read-only) fields. I also read on your blog that this is only a pattern and might be broken gently if the need would arise. + I want to register to a plain old .NET event of a dependency that is supplied via constructor injection. I read your book "DI in .NET" and in it you mention that injection constructors should be simple and not perform any other work than guarding for null values and assigning the dependencies to (read-only) fields. I also read on your blog that this is only a pattern and might be broken gently if the need would arise.

    [...] do you know and prefer any patterns to solve this "registering to events of dependencies in a constructor" problem? @@ -30,10 +30,10 @@

    diff --git a/_posts/2013-09-06-di-and-events-constructor-subscription.html b/_posts/2013-09-06-di-and-events-constructor-subscription.html index 301fc4c29..2d51ae6a9 100644 --- a/_posts/2013-09-06-di-and-events-constructor-subscription.html +++ b/_posts/2013-09-06-di-and-events-constructor-subscription.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This post is the first in a series of articles about Dependency Injection and events. + This post is the first in a series of articles about Dependency Injection and events.

    Imagine that you have an interface that defines an event: @@ -50,10 +50,10 @@ }

    - The concern is that, by subscribing to an event, the constructor violates Nikola Malovic's 4th law of IoC: Injection Constructors should perform no work. + The concern is that, by subscribing to an event, the constructor violates Nikola Malovic's 4th law of IoC: Injection Constructors should perform no work.

    - This rule about Dependency Injection explains why you can compose big object graphs with confidence. Still, the most compelling reason for conforming strictly to the rule is most likely performance considerations. So, what if you subscribe to a single event or two during construction? Will it adversely (and noticeably) affect performance of your overall system? + This rule about Dependency Injection explains why you can compose big object graphs with confidence. Still, the most compelling reason for conforming strictly to the rule is most likely performance considerations. So, what if you subscribe to a single event or two during construction? Will it adversely (and noticeably) affect performance of your overall system?

    As always, the answer to such questions is: measure. However, I'd be quite surprised if it turns out that a single event subscription has a huge impact on performance... @@ -88,13 +88,13 @@

    }

    - From the perspective of an outside observer, that's really strange. Why are we required to pass in an object that's not going to be used as is? Just like in a previous discussion about the implications of injecting IEnumerable<T>, if you're injecting an abstraction, and the constructor then starts querying, modifying, examining, or otherwise fidget with the injected object, then you're probably injecting the wrong object. + From the perspective of an outside observer, that's really strange. Why are we required to pass in an object that's not going to be used as is? Just like in a previous discussion about the implications of injecting IEnumerable<T>, if you're injecting an abstraction, and the constructor then starts querying, modifying, examining, or otherwise fidget with the injected object, then you're probably injecting the wrong object.

    Keep in mind that Constructor Injection is a declaration of requirements. It's the declaring class that advertises to the world: these are (some of) my invariants. If the class can't use the injected dependency as is, it suggests that it requested the wrong object from its clients. The class with the Injection Constructor should declare what it really needs. In this case, it needs to react to events.

    - In the next post, I'll show you a better (i.e. simpler) design for reacting to events. + In the next post, I'll show you a better (i.e. simpler) design for reacting to events.

    Unsubscription (Update, September 9, 2013, 11:48 UTC) # @@ -140,7 +140,7 @@

    While this weakens the argument that NeedyClass is requesting the wrong kind of dependency, this is a lot of work just to consume an event. Furthermore, it isn't particularly safe, because you'll have to remember to dispose of all of your NeedyClass instances.

    - Thus, a better approach is still warranted. + Thus, a better approach is still warranted.

    diff --git a/_posts/2013-09-09-di-and-events-third-party-connect.html b/_posts/2013-09-09-di-and-events-third-party-connect.html index 060ec6379..b0a7eeef5 100644 --- a/_posts/2013-09-09-di-and-events-third-party-connect.html +++ b/_posts/2013-09-09-di-and-events-third-party-connect.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In the previous article in my series about Dependency Injection and events, you saw an example of how injecting a dependency that raises events violates Nikola Malovic's 4th law of IoC: Injection Constructors should perform no work. + In the previous article in my series about Dependency Injection and events, you saw an example of how injecting a dependency that raises events violates Nikola Malovic's 4th law of IoC: Injection Constructors should perform no work.

    In this article, you'll see the first of several alternatives. @@ -24,7 +24,7 @@

    Take a step back and recall why you're using Dependency Injection in the first place. Hopefully, you use Dependency Injection because it provides the decoupling necessary to make your code more maintainable (and thus, you and your colleagues more productive). However, events are already a mechanism for decoupling. In .NET, events are simply a (limited) baked-in implementation of the Observer pattern.

    - Perhaps it's helpful if we consider alternative names for Dependency Injection. Nat Pryce prefers the term Third-party Connect, and I think that there's much sense in that name. Instead of focusing on the injection part, or even Inversion of Control, the term Third-party Connect focuses on the fact that when you decouple two objects, you need a third party to connect them with each other. In a well-designed application, this third party will often be the Composition Root. + Perhaps it's helpful if we consider alternative names for Dependency Injection. Nat Pryce prefers the term Third-party Connect, and I think that there's much sense in that name. Instead of focusing on the injection part, or even Inversion of Control, the term Third-party Connect focuses on the fact that when you decouple two objects, you need a third party to connect them with each other. In a well-designed application, this third party will often be the Composition Root.

    If you already have a third party connecting NeedyClass with IDependency, must you use Constructor Injection? @@ -33,7 +33,7 @@

    Further decoupling #

    - Apparently, if you consider the code in the previous article, NeedyClass is required to do something whenever a particular IDependency instance raises its ItHappened event. What if, instead of injecting IDependency and subscribing a private event handler, you were to expose a public method that implements the same logic as that private event handler? + Apparently, if you consider the code in the previous article, NeedyClass is required to do something whenever a particular IDependency instance raises its ItHappened event. What if, instead of injecting IDependency and subscribing a private event handler, you were to expose a public method that implements the same logic as that private event handler?

    public class NeedyClass
    @@ -48,7 +48,7 @@ 

    Notice how much simpler this implementation is, compared with the previous version. Nothing is injected, there are no interfaces in play. Such a class is very easy to unit test as well, so I think this looks very promising.

    - Doesn't this design break encapsulation? Not more than before. Remember, in the previous implementation, you could always inject an implementation of IDependency that enabled you to raise the ItHappened event, and thereby invoke the private event handler in NeedyClass. This new design just makes it a bit easier to invoke the method. Keep in mind that encapsulation isn't about public versus private members; encapsulation is about invariants. + Doesn't this design break encapsulation? Not more than before. Remember, in the previous implementation, you could always inject an implementation of IDependency that enabled you to raise the ItHappened event, and thereby invoke the private event handler in NeedyClass. This new design just makes it a bit easier to invoke the method. Keep in mind that encapsulation isn't about public versus private members; encapsulation is about invariants.

    This version of NeedyClass doesn't actually expose a public 'event handler', since the DoSomethingInteresting method doesn't match the event handler signature. Thus, if you use a static code analysis tool, it's not going to complain about a public event handler. The DoSomethingInteresting method is a method just like any other method. This design is much more decoupled than before, because NeedyClass knows nothing about IDependency. Hopefully, it makes sense as a stand-alone class with its own API. This makes it more reusable. @@ -96,6 +96,6 @@

    Conclusion #

    - Using Third-party Connect leads to a simpler, but more Fragile design. Still, I often find that the extreme simplicity of the involved classes trumps the fragility of the design; if I had to choose between Third-party Connect and Constructor Subscription, I'd select Third-party Connect. Fortunately, these aren't the only options available to you; in future articles, I'll approach a better alternative. + Using Third-party Connect leads to a simpler, but more Fragile design. Still, I often find that the extreme simplicity of the involved classes trumps the fragility of the design; if I had to choose between Third-party Connect and Constructor Subscription, I'd select Third-party Connect. Fortunately, these aren't the only options available to you; in future articles, I'll approach a better alternative.

    \ No newline at end of file diff --git a/_posts/2013-09-11-di-and-events-reactive-extensions.html b/_posts/2013-09-11-di-and-events-reactive-extensions.html index 94b62eb52..75c735710 100644 --- a/_posts/2013-09-11-di-and-events-reactive-extensions.html +++ b/_posts/2013-09-11-di-and-events-reactive-extensions.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my series about Dependency Injection and events, you previously saw how to let a third party connect publisher and subscriber. I think that approach is valuable in all those cases where you connect publishers and subscribers in a narrow and well-defined area of your application, such as in the Composition Root. However, it's not a good fit if you need to connect and disconnect publishers and subscribers throughout your application's code base. + In my series about Dependency Injection and events, you previously saw how to let a third party connect publisher and subscriber. I think that approach is valuable in all those cases where you connect publishers and subscribers in a narrow and well-defined area of your application, such as in the Composition Root. However, it's not a good fit if you need to connect and disconnect publishers and subscribers throughout your application's code base.

    This article examines alternatives based on Reactive Extensions. @@ -21,7 +21,7 @@

    Re-design #

    - For the rest of this article, I'm going to assume that you're in a position where you can change the design - particularly the design of the IDependency interface. If not, you can always convert a standard .NET event into the appropriate IObservable<T>. + For the rest of this article, I'm going to assume that you're in a position where you can change the design - particularly the design of the IDependency interface. If not, you can always convert a standard .NET event into the appropriate IObservable<T>.

    Using small iterations, you can first make IDependency implement IObservable<Unit>: @@ -71,7 +71,7 @@

    Because IObservable<T>.Subscribe returns an IDisposable, NeedyClass still needs to store that object in a field and dipose of it when it's done, which also means that it must implement IDisposable itself. Thus, you seem to be no better off than with Constructor Subscription. Actually, you're slightly worse off, because now NeedyClass gained three new public methods (OnCompleted, OnError, and OnNext), compared to a single public method with Constructor Subscription.

    - What's even worse is that you're still violating Nikola Malovic's 4th law of IoC: Injection Constructors should perform no work. + What's even worse is that you're still violating Nikola Malovic's 4th law of IoC: Injection Constructors should perform no work.

    This doesn't seem promising. @@ -129,7 +129,7 @@

    Injection disconnect #

    - If you refer back to the discussion about Constructor Subscription, you may recall an inkling that NeedyClass requests the wrong type of dependency via the constructor. If it's saving an IDisposable as its class field, then why is it requesting an IObservable<Unit>? Shouldn't it simply request an IDisposable? + If you refer back to the discussion about Constructor Subscription, you may recall an inkling that NeedyClass requests the wrong type of dependency via the constructor. If it's saving an IDisposable as its class field, then why is it requesting an IObservable<Unit>? Shouldn't it simply request an IDisposable?

    This sounds promising, but in the end turns out to be a false lead. Still, this actually compiles: @@ -210,7 +210,7 @@

    var subscription = observable.Subscribe(nc);

    - That pretty much puts you back at the Third-party Connect solution, so that didn't seem to buy you much. + That pretty much puts you back at the Third-party Connect solution, so that didn't seem to buy you much.

    (Preliminary) conclusion # @@ -222,6 +222,6 @@

    The greatest advantage gained so far is that, hopefully you've learned something. You've learned (through two refactoring attempts) that NeedyClass isn't needy at all, and should not have a dependency in order to react to events.

    - The last advantage gained by using Reactive Extensions may seem like a small thing, but actually turns out to the most important of them all: by using IObservable<T>/IObserver<T> instead of .NET events, you've converted your code to work with objects. You know, .NET events are not real objects, so they can't be passed around, but IObservable<T> and IObserver<T> instances are real objects. This means that now that you know that NeedyClass shouldn't have a dependency, perhaps some other class should. Remember what I originally said about Inversion of Inversion of Control? In the next article in the series, I'll address that issue, and arrive at a more idiomatic DI solution. + The last advantage gained by using Reactive Extensions may seem like a small thing, but actually turns out to the most important of them all: by using IObservable<T>/IObserver<T> instead of .NET events, you've converted your code to work with objects. You know, .NET events are not real objects, so they can't be passed around, but IObservable<T> and IObserver<T> instances are real objects. This means that now that you know that NeedyClass shouldn't have a dependency, perhaps some other class should. Remember what I originally said about Inversion of Inversion of Control? In the next article in the series, I'll address that issue, and arrive at a more idiomatic DI solution.

    \ No newline at end of file diff --git a/_posts/2013-09-12-di-and-events-composition.html b/_posts/2013-09-12-di-and-events-composition.html index dda0cc94d..786f5aa6c 100644 --- a/_posts/2013-09-12-di-and-events-composition.html +++ b/_posts/2013-09-12-di-and-events-composition.html @@ -12,7 +12,7 @@ {{ page.description }}

    - Previously, in my series about Dependency Injection and events, you learned how to connect a publisher and a subscriber via a third party (often the Composition Root). + Previously, in my series about Dependency Injection and events, you learned how to connect a publisher and a subscriber via a third party (often the Composition Root).

    The problem with that approach is that while it's loosely coupled, it's too easy to forget to connect the publisher and the subscriber. It's also possible to forget to unsubscribe. In neither case can the compiler help you. @@ -49,7 +49,7 @@

    From Method Injection to Constructor Injection #

    - As you learned in the last couple of articles, the subscriber should not require any dependency in order to react to events. Yet, if Method Injection via IObservable<T> isn't a good approach either, then what's left? + As you learned in the last couple of articles, the subscriber should not require any dependency in order to react to events. Yet, if Method Injection via IObservable<T> isn't a good approach either, then what's left?

    Good old Constructor Injection. @@ -58,7 +58,7 @@

    The important realization is that it's not the subscriber (NeedyClass, in previous examples) that requires a dependency - it's the publisher!

    - Imagine that until now, you've had a publisher implementing IObservable<T>. In keeping with the running example throughout this series, this was the publisher that originally implemented IDependency. Thus, it's still called RealDependency. For simplicity's sake, assume that its implementation is as simple as this: + Imagine that until now, you've had a publisher implementing IObservable<T>. In keeping with the running example throughout this series, this was the publisher that originally implemented IDependency. Thus, it's still called RealDependency. For simplicity's sake, assume that its implementation is as simple as this:

    public class RealDependency : IObservable<Unit>
    @@ -202,7 +202,7 @@ 

    2015-11-06 14:00 UTC

    - +

    Tony, thank you for writing. That's a good observation, and you're right: if you need to make substantial transformation, filtering, aggregation, and so on, on your event streams, then it would be valuable to be able to leverage Reactive Extensions. Not being able to do that would be a loss. @@ -226,16 +226,16 @@

    2016-06-09 12:58 UTC

    - +

    - Spencer, thank you for writing. Indeed, delegates are equivalent to single-method interfaces. Once you realise that, functional programming begins to look more and more attractive. + Spencer, thank you for writing. Indeed, delegates are equivalent to single-method interfaces. Once you realise that, functional programming begins to look more and more attractive.

    Actions, with their void return type, don't seem particularly functional, however, but you can build up an entire architecture on that concept.

    - Personally, in C#, I prefer to stick with interfaces for dependency injection, since I find it more idiomatic, but other people have different opinions on that. + Personally, in C#, I prefer to stick with interfaces for dependency injection, since I find it more idiomatic, but other people have different opinions on that.

    2016-06-09 16:35 UTC
    diff --git a/_posts/2013-10-07-verifying-every-single-commit-in-a-git-branch.html b/_posts/2013-10-07-verifying-every-single-commit-in-a-git-branch.html index f25e3d952..7204b18df 100644 --- a/_posts/2013-10-07-verifying-every-single-commit-in-a-git-branch.html +++ b/_posts/2013-10-07-verifying-every-single-commit-in-a-git-branch.html @@ -108,7 +108,7 @@

    2013-10-11 12:04 UTC

    - +

    Hi Steven @@ -132,7 +132,7 @@

    2014-04-12 09:36 UTC

    - +

    I didn't know about the --exec option, but I'll try it out the next time I perform a rebase. Thank you for the tip. diff --git a/_posts/2013-10-15-easy-aspnet-web-api-dtos-with-f-climutable-records.html b/_posts/2013-10-15-easy-aspnet-web-api-dtos-with-f-climutable-records.html index 34cd89795..66b860dc9 100644 --- a/_posts/2013-10-15-easy-aspnet-web-api-dtos-with-f-climutable-records.html +++ b/_posts/2013-10-15-easy-aspnet-web-api-dtos-with-f-climutable-records.html @@ -12,13 +12,13 @@ {{ page.description }}

    - When writing HTTP (or RESTful) web services with the ASP.NET Web API, the most normal approach is to define Data Transfer Objects (DTOs), which represents the data structures that go on the wire in the form of JSON or XML. While I usually call these boundary objects for renditions (a bit punny), a more normal terminology is, indeed, DTOs. + When writing HTTP (or RESTful) web services with the ASP.NET Web API, the most normal approach is to define Data Transfer Objects (DTOs), which represents the data structures that go on the wire in the form of JSON or XML. While I usually call these boundary objects for renditions (a bit punny), a more normal terminology is, indeed, DTOs.

    To enable the default .NET serializers (and particularly, deserializers) to do their magic, these DTOs must be mutable and have a default constructor. Not particularly something that seems to fit nicely with F#.

    - Until recently, I've been declaring such DTOs like this in F#: + Until recently, I've been declaring such DTOs like this in F#:

    type HomeRendition() =
    @@ -101,7 +101,7 @@ 

    2013-10-16 12:54 UTC

    - +

    Hi Patrick, thank you for writing. For JSON serialization, I usually just add this configuration: @@ -134,11 +134,11 @@

    - Nick, I haven't tried returning a Discriminated Union from a Web API Controller. Why would I want to do that? As I've previously described, at the boundaries, applications aren't object-oriented, and similarly, they aren't functional either. What would it mean to return a Discriminated Union? How would it render as JSON or XML? + Nick, I haven't tried returning a Discriminated Union from a Web API Controller. Why would I want to do that? As I've previously described, at the boundaries, applications aren't object-oriented, and similarly, they aren't functional either. What would it mean to return a Discriminated Union? How would it render as JSON or XML?

    Apart from that, I have no idea how a Discriminated Union compiles to IL... @@ -186,7 +186,7 @@

    diff --git a/_posts/2013-10-23-mocks-for-commands-stubs-for-queries.html b/_posts/2013-10-23-mocks-for-commands-stubs-for-queries.html index e71fb4463..20b0895e5 100644 --- a/_posts/2013-10-23-mocks-for-commands-stubs-for-queries.html +++ b/_posts/2013-10-23-mocks-for-commands-stubs-for-queries.html @@ -272,7 +272,7 @@

    Notice that userId was added to the returned User in the Setup for the Strict Mock.

    - Having to edit existing tests is a genuine unit test smell. Not only does it add an unproductive overhead (imagine that many tests break instead of a single one), but it also decreases the trustworthiness of your test suite. + Having to edit existing tests is a genuine unit test smell. Not only does it add an unproductive overhead (imagine that many tests break instead of a single one), but it also decreases the trustworthiness of your test suite.

    Data Flow Verification # diff --git a/_posts/2013-12-10-semantic-versioning-with-continuous-deployment.html b/_posts/2013-12-10-semantic-versioning-with-continuous-deployment.html index dd7a8c053..bbd82cba2 100644 --- a/_posts/2013-12-10-semantic-versioning-with-continuous-deployment.html +++ b/_posts/2013-12-10-semantic-versioning-with-continuous-deployment.html @@ -12,7 +12,7 @@ {{ page.description }}

    - If you aren't already using Semantic Versioning, you should. It makes it much easier to figure out how to version your releases. Even if you're 'just' building software for your internal organization, or a single customer, you should still care about versioning of the software you release. Instead of an ad-hoc versioning scheme, Semantic Versioning offers a set of easy-to-understand rules about when to increment which version number. + If you aren't already using Semantic Versioning, you should. It makes it much easier to figure out how to version your releases. Even if you're 'just' building software for your internal organization, or a single customer, you should still care about versioning of the software you release. Instead of an ad-hoc versioning scheme, Semantic Versioning offers a set of easy-to-understand rules about when to increment which version number.

    In short, you @@ -75,7 +75,7 @@

    The rules of Semantic Versioning require explicit decisions to be made. Only the development team understands what a particular commit contains. Is it a fix? Is it a new feature? Is it a breaking change? A Build Server doesn't know how to answer these questions, but you do.

    - A few years ago, I changed the delivery scheme for my open source project AutoFixture to use Semantic Versioning with Continuous Deployment. When I did that, I realised that I could no longer rely on a Build Server for controlling the version. Instead, I would have to explicitly control the versioning as part of the commit process. + A few years ago, I changed the delivery scheme for my open source project AutoFixture to use Semantic Versioning with Continuous Deployment. When I did that, I realised that I could no longer rely on a Build Server for controlling the version. Instead, I would have to explicitly control the versioning as part of the commit process.

    Because AutoFixture is a .NET project, I decided to use the version assignment mechanism already present in the framework: The [AssemblyVersion] and [AssemblyFileVersion] attributes that you typically put in AssemblyInfo files. @@ -90,7 +90,7 @@

  • I push the commits to master.
  • The Build Server picks up the new commits, and the Deployment Pipeline kicks in.
  • - This works well. You can see an example of this process if you examine the commit log for AutoFixture. The only problem is that AutoFixture has 28 AssemblyInfo files (each with two version attributes) that I must update and keep in sync. That's a lot of work, so obviously a target for automation, but that's the subject for another blog post. + This works well. You can see an example of this process if you examine the commit log for AutoFixture. The only problem is that AutoFixture has 28 AssemblyInfo files (each with two version attributes) that I must update and keep in sync. That's a lot of work, so obviously a target for automation, but that's the subject for another blog post.

    After more than two years of experience with this way of controlling software versions, I'm consistently using this approach for all my open source software, as well as the internal software we create in Grean. @@ -117,7 +117,7 @@

    2013-12-10 17:02 UTC

    - +

    Augi, it's true that you can create other approaches in order to attempt to address the issue, but the bottom line remains that a human being must make the decision about how to increment the version number. As you suggest, you can put information guiding that decision outside the source code itself, but then you'd be introducing another movable part that can break. If you do something like you suggest, you'll still need to add some machine-readable metadata to the linked issue ID. To add spite to injury, this also makes it more difficult to reproduce what the Build Server does on your local machine - particularly if you're attempting to build while offline. @@ -268,7 +268,7 @@

    - +

    Chris, thank you for your comment. That may actually be a good way to do it, too. While I did know about the add as link feature of Visual Studio, I've had bad experiences with it in the past. This may actually be a Pavlovian reaction on my part, because I must admit that I can no longer remember what those bad experiences were :$ @@ -308,7 +308,7 @@

    2013-12-11 09:54 UTC

    - +

    Laurence, Marijn, thank you for your comments. As cool as Git is (currently, I'm not aware of anything better), I don't like coupling a process unnecessarily to a particular tool. What if, some day, something better than Git arrives? @@ -317,7 +317,7 @@

    Additionally, I agree with Martin Fowler, Jez Humble, and others, that branching is essentially evil, so I don't think it's a good idea building an entire versioning scheme around branches.

    - As an alternative, I've introduced ZeroToNine, a command-line tool (and library) that works independently of any version control system. + As an alternative, I've introduced ZeroToNine, a command-line tool (and library) that works independently of any version control system.

    2013-12-11 12:55 UTC
    @@ -348,7 +348,7 @@

    - +

    Rob, thank you for writing. If I could have defined a trustworthy automated system to figure out semantic versioning, I would have done it. Is your proposed algorithm sufficiently robust? @@ -379,7 +379,7 @@

    2015-08-06 00:02 UTC

    - +

    Gus, thank you for writing. I think your suggestion could work as well, although I haven't tried it. @@ -413,7 +413,7 @@

    - +

    Jonathan, thank you for writing, and don't worry about the age of the post. It only pleases me that apparently I've managed to produce something durable enough to be of interest four years later. @@ -440,7 +440,7 @@

    I'm sure you could even write a server-side script with a Web UI that could do this, if you wanted to, but I've always preferred doing a local build as part of the verification process.

    - I don't think I've written much more about this, rather than the announcement post for ZeroToNine, as well as the documentation for it. + I don't think I've written much more about this, rather than the announcement post for ZeroToNine, as well as the documentation for it.

    2017-08-09 20:09 UTC
    diff --git a/_posts/2013-12-11-zerotonine.html b/_posts/2013-12-11-zerotonine.html index 16cfe3131..f33b6ccb6 100644 --- a/_posts/2013-12-11-zerotonine.html +++ b/_posts/2013-12-11-zerotonine.html @@ -12,7 +12,7 @@ {{ page.description }}

    - When working with Semantic Versioning in my .NET projects, I prefer to explicitly update the version information in all relevant AssemblyInfo files. However, doing that by hand is quite tedious when you have many AssemblyInfo files, so instead, I rely on an automated tool. + When working with Semantic Versioning in my .NET projects, I prefer to explicitly update the version information in all relevant AssemblyInfo files. However, doing that by hand is quite tedious when you have many AssemblyInfo files, so instead, I rely on an automated tool.

    For years, I used a PowerShell script, but recently, I decided to start over and write a 'real' tool, deployable via NuGet. It's called ZeroToNine, is free, and open source. Using it looks like this: @@ -42,7 +42,7 @@

    2014-01-23 19:26 UTC

    - +

    NuGet packages can contain executable tools as well as, or instead of, libraries. These executables can be found in the package's tools folder. This is what the Zero29 package does. It's not associated with any particular Visual Studio project. diff --git a/_posts/2014-01-20-rest-efficiency.html b/_posts/2014-01-20-rest-efficiency.html index 019306183..be0922a5a 100644 --- a/_posts/2014-01-20-rest-efficiency.html +++ b/_posts/2014-01-20-rest-efficiency.html @@ -17,7 +17,7 @@ One of my readers, Filipe Ximenes, asks the following question of me:

    - "I read you post about avoiding hackable urls and found it very interesting. I'm currently studying about REST and I'm really interested on building true RESTful API's. One thing that is bothering me is how to access resources that are not in the API root. Eg: consider the following API flow: + "I read you post about avoiding hackable urls and found it very interesting. I'm currently studying about REST and I'm really interested on building true RESTful API's. One thing that is bothering me is how to access resources that are not in the API root. Eg: consider the following API flow:

    "root > users > user details > user messages diff --git a/_posts/2014-01-29-nuget-package-restore-considered-harmful.html b/_posts/2014-01-29-nuget-package-restore-considered-harmful.html index f32df5873..cbbc0d6bd 100644 --- a/_posts/2014-01-29-nuget-package-restore-considered-harmful.html +++ b/_posts/2014-01-29-nuget-package-restore-considered-harmful.html @@ -182,7 +182,7 @@

    2015-12-03 15:36 UTC

    - +

    Blake, thank you for writing. Yes, this is still how I feel; nothing has changed. diff --git a/_posts/2014-02-03-using-nuget-with-autonomous-repositories.html b/_posts/2014-02-03-using-nuget-with-autonomous-repositories.html index 2e5ebea6c..1e85fb298 100644 --- a/_posts/2014-02-03-using-nuget-with-autonomous-repositories.html +++ b/_posts/2014-02-03-using-nuget-with-autonomous-repositories.html @@ -14,7 +14,7 @@ {{ page.description }}

    - In my recent post about NuGet, I described why the Package Restore feature is insidious. As expected, this provoked some readers, who didn't like my recommendation of adding NuGet packages to source control. That's understandable; the problem with a rant like my previous post is that while it tells you what not to do, it's not particularly constructive. While I told you to store NuGet packages in your source control system, I didn't describe patterns for doing it effectively. My impression was that it's trivial to do this, but based on the reactions I got, I realize that this may not be the case. Could it be that some readers react strongly because they don't know what else to do (than to use NuGet Package Restore)? In this post, I'll describe a way to use and organize NuGet packages that have worked well for me in several organizations. + In my recent post about NuGet, I described why the Package Restore feature is insidious. As expected, this provoked some readers, who didn't like my recommendation of adding NuGet packages to source control. That's understandable; the problem with a rant like my previous post is that while it tells you what not to do, it's not particularly constructive. While I told you to store NuGet packages in your source control system, I didn't describe patterns for doing it effectively. My impression was that it's trivial to do this, but based on the reactions I got, I realize that this may not be the case. Could it be that some readers react strongly because they don't know what else to do (than to use NuGet Package Restore)? In this post, I'll describe a way to use and organize NuGet packages that have worked well for me in several organizations.

    Publish/Subscribe # @@ -130,11 +130,11 @@

    - For AutoFixture, as well as other OSS projects I maintain, we rely almost exclusively on unit tests, keeping in mind that trustworthy tests are append-only. AutoFixture has some 4000+ unit tests, so if none of those break, I feel confident that a release doesn't contain breaking changes. + For AutoFixture, as well as other OSS projects I maintain, we rely almost exclusively on unit tests, keeping in mind that trustworthy tests are append-only. AutoFixture has some 4000+ unit tests, so if none of those break, I feel confident that a release doesn't contain breaking changes.

    For my other OSS projects, the story is the same, although the numbers differ. @@ -176,7 +176,7 @@

    diff --git a/_posts/2014-03-10-solid-the-next-step-is-functional.html b/_posts/2014-03-10-solid-the-next-step-is-functional.html index bface3cb5..6f00a34ce 100644 --- a/_posts/2014-03-10-solid-the-next-step-is-functional.html +++ b/_posts/2014-03-10-solid-the-next-step-is-functional.html @@ -35,7 +35,7 @@

    A SOLID road map #

    - In a previous article, I've described how application of the Single Responsibility Principle (SRP) leads to many small classes. Furthermore, if you rigorously apply the Interface Segregation Principle (ISP), you'll understand that you should favour Role Interfaces over Header Interfaces. + In a previous article, I've described how application of the Single Responsibility Principle (SRP) leads to many small classes. Furthermore, if you rigorously apply the Interface Segregation Principle (ISP), you'll understand that you should favour Role Interfaces over Header Interfaces.

    If you keep driving your design towards smaller and smaller interfaces, you'll eventually arrive at the ultimate Role Interface: an interface with a single method. This happens to me a lot. Here's an example: @@ -84,10 +84,10 @@

    The data (also sometimes known as the state) is the workingDirectory field. - In this example, the data is immutable and passed in via the constructor, but it could also have been a public, writeable property, or even a public field. + In this example, the data is immutable and passed in via the constructor, but it could also have been a public, writeable property, or even a public field.

    - The workingDirectory field is a Concrete Dependency, but it could also have been a primitive value or an interface or abstract base class. In the last case, we would often call the pattern Constructor Injection. + The workingDirectory field is a Concrete Dependency, but it could also have been a primitive value or an interface or abstract base class. In the last case, we would often call the pattern Constructor Injection.

    Obviously, the data could be multiple values, instead of a single value. @@ -201,7 +201,7 @@

        File.ReadAllText(path)

    - The read value is a Function with the signature 'a -> string, which means that it takes a value of the generic type 'a (in C#, it would typically have been named T) and returns a string. This is just a more general version of the IMessageQuery.Read method. When 'a is int, it's the same signature, but in F#, I only had to bother naming the Function itself. Functions are anonymous interfaces, so these are also equivalent. + The read value is a Function with the signature 'a -> string, which means that it takes a value of the generic type 'a (in C#, it would typically have been named T) and returns a string. This is just a more general version of the IMessageQuery.Read method. When 'a is int, it's the same signature, but in F#, I only had to bother naming the Function itself. Functions are anonymous interfaces, so these are also equivalent.

    Likewise, if you have a Pure Function like this: @@ -275,7 +275,7 @@

    - +

    Richard, thank you for writing. You ask "Surely your service doesn't look like this? type MyService (messageQuery: int -> string) = ..." @@ -296,7 +296,7 @@

    At the top level of your application, you may have to implement a class to fit into a framework. For an example of integrating with the ASP.NET Web API, see my A Functional Architecture with F# Pluralsight course.

    - When it comes to integrating with a DI Container, I tend to not care about that these days. I prefer composing the application with Poor Man's DI, and that works beautifully with F#. + When it comes to integrating with a DI Container, I tend to not care about that these days. I prefer composing the application with Poor Man's DI, and that works beautifully with F#.

    2014-03-11 16:57 UTC
    @@ -312,7 +312,7 @@

    - +

    Bill, you are correct! I may have gotten a little carried away at that point. The method is side-effect-free, and deterministic (unless someone comes by and changes the file), but it does depend on state on disk. Thank you for pointing that out; I stand corrected. Hopefully, that mistake of mine doesn't detract from the overall message. @@ -332,7 +332,7 @@

    - +

    Leif, thank you for writing. Is there value in adopting a functional style in C#? Yes, I think so, but not (in my opinion) from closures or partial function application. While it's possible to do this in C#, the syntax is awkward compared to F#. It also goes somewhat against the grain of C#. diff --git a/_posts/2014-03-11-arbitrary-version-instances-with-fscheck.html b/_posts/2014-03-11-arbitrary-version-instances-with-fscheck.html index 3c28864a5..e9f3c86e8 100644 --- a/_posts/2014-03-11-arbitrary-version-instances-with-fscheck.html +++ b/_posts/2014-03-11-arbitrary-version-instances-with-fscheck.html @@ -12,7 +12,7 @@ {{ page.description }}

    - When I unit test generic classes or methods, I often like to use Version as one of the type arguments. The Version class is a great test type because + When I unit test generic classes or methods, I often like to use Version as one of the type arguments. The Version class is a great test type because

    • it's readily available, as it's defined in the System namespace in mscorlib
    • it overrides Equals so that it's easy to compare two values
    • diff --git a/_posts/2014-03-21-composed-assertions-with-unquote.html b/_posts/2014-03-21-composed-assertions-with-unquote.html index 8acdc2def..31f911b74 100644 --- a/_posts/2014-03-21-composed-assertions-with-unquote.html +++ b/_posts/2014-03-21-composed-assertions-with-unquote.html @@ -39,7 +39,7 @@ There's not much to look at yet, because at that time, I was just getting started, and as always, I was using Test-Driven Development. The TasksController class is an ASP.NET Web API 2 Controller. In this incarnation, it merely accepts an HTTP POST, ignores the input, and returns 202 (Accepted).

      - The unit test uses AutoFixture.Xunit to create an instance of the SUT and a DTO record, but that's not important in this context. It also uses Unquote for assertions, although I've aliased the test function to verify. Although Unquote is an extremely versatile assertion module, I wasn't happy with the assertions I wrote. + The unit test uses AutoFixture.Xunit to create an instance of the SUT and a DTO record, but that's not important in this context. It also uses Unquote for assertions, although I've aliased the test function to verify. Although Unquote is an extremely versatile assertion module, I wasn't happy with the assertions I wrote.

      What's the problem? # diff --git a/_posts/2014-05-01-autofixture-conventions-with-albedo.html b/_posts/2014-05-01-autofixture-conventions-with-albedo.html index 3a0be056f..9fff87526 100644 --- a/_posts/2014-05-01-autofixture-conventions-with-albedo.html +++ b/_posts/2014-05-01-autofixture-conventions-with-albedo.html @@ -12,7 +12,7 @@ {{ page.description }}

      - In a question to one of my previous posts, Jeff Soper asks about using custom, string-based conventions for AutoFixture: + In a question to one of my previous posts, Jeff Soper asks about using custom, string-based conventions for AutoFixture:

      "I always wince when testing for the ParameterType.Name value [...] It seems like it makes a test that would use this implementation very brittle."
      @@ -29,7 +29,7 @@ If you often find yourself in a situation where you're writing an AutoFixture Customization based on string matching of parameters, properties or fields, you should ask yourself if you're targeting one specific class, or if you're writing a convention? If you often target individual specific classes, you probably need to rethink your strategy, but you can easily run into situations where you need to introduce true conventions in your code base. This can be beneficial, because it'll make your code more consistent.

      - Here's an example from the code base in which I'm currently working. It's a REST service written in F#. To model the JSON going in and out, I've defined some Data Transfer Records, and some of them contain dates. However, JSON doesn't deal particularly well with dates, so they're treated as strings. Here's a JSON representation of a comment: + Here's an example from the code base in which I'm currently working. It's a REST service written in F#. To model the JSON going in and out, I've defined some Data Transfer Records, and some of them contain dates. However, JSON doesn't deal particularly well with dates, so they're treated as strings. Here's a JSON representation of a comment:

      {
      diff --git a/_posts/2014-05-15-service-locator-violates-solid.html b/_posts/2014-05-15-service-locator-violates-solid.html
      index dc913763d..3f78f1bdb 100644
      --- a/_posts/2014-05-15-service-locator-violates-solid.html
      +++ b/_posts/2014-05-15-service-locator-violates-solid.html
      @@ -12,7 +12,7 @@
           {{ page.description }}
         

      - Years ago, I wrote an article about Service Locator. Regular readers of this blog may already know that I consider Service Locator an anti-pattern. That hasn't changed, but I recently realized that there's another way to explain why Service Locator is the inverse of good Object-Oriented Design (OOD). My original article didn't include that perspective at all, so perhaps this is a clearer way of explaining it. + Years ago, I wrote an article about Service Locator. Regular readers of this blog may already know that I consider Service Locator an anti-pattern. That hasn't changed, but I recently realized that there's another way to explain why Service Locator is the inverse of good Object-Oriented Design (OOD). My original article didn't include that perspective at all, so perhaps this is a clearer way of explaining it.

      In this article, I'll assume that you're familiar with the SOLID principles (also known as the Principles of OOD), and that you accept them as generally correct. It's not because I wish to argue by an appeal to authority, but rather because threre's already a large body of work that explains why these principles are beneficial to software design. @@ -31,7 +31,7 @@

      - Sometimes the method takes one or more parameters, but that doesn't change the conclusion, so I'm leaving out those input parameters to keep things simple. + Sometimes the method takes one or more parameters, but that doesn't change the conclusion, so I'm leaving out those input parameters to keep things simple.

      A common variation is the untyped, non-generic variation: @@ -96,7 +96,7 @@

      The Service Locator anti-pattern violates the ISP, and thus it also violates SOLID as a whole. SOLID is also known as the Principles of OOD. Therefore, Service Locator is bad Objected-Oriented Design.

      - Update 2015-10-26: The fundamental problem with Service Locator is that it violates encapsulation. + Update 2015-10-26: The fundamental problem with Service Locator is that it violates encapsulation.

    @@ -116,10 +116,10 @@

    - +

    - Nelson, thank you for writing. First, it's important to realize that this overall argument applies to methods with 'free' generic type parameters; that is, a method where the type in itself isn't generic, but the method is. One example of the difference I mean is that a generic Abstract Factory is benign, whereas a Server Locator isn't. + Nelson, thank you for writing. First, it's important to realize that this overall argument applies to methods with 'free' generic type parameters; that is, a method where the type in itself isn't generic, but the method is. One example of the difference I mean is that a generic Abstract Factory is benign, whereas a Server Locator isn't.

    Second, that still leaves the case where you may have a generic parameter that determines the return type of the method. The LINQ Select method is an example of such a method. These tend not to be problematic, but I had some trouble explaining why that is until James Jensen explained it to me. @@ -164,7 +164,7 @@

    - +

    Kenny, thank you for writing. The point that this post is making is mainly that Service Locator violates the Interface Segregation Principle (ISP). The appropriate perspective on ISP (and LSP and DIP as well) is from a client. The client of a Service Locator effectively sees an API with infinitely many methods. That's where the damage is done. @@ -227,7 +227,7 @@

    2016-01-08 09:40 UTC

    - +

    Kenny, thank you for writing. While I don't agree with everything you wrote, your arguments are well made, and I have no problems following them. If we disagree, I think we disagree about semantics, because the way I read your comment, I think it eventually leads you to the same conclusions that I have arrived at. @@ -239,7 +239,7 @@

    To be honest, though, I don't consider the arguments I put forth in the present article as my strongest ever. Sometimes, I write articles on topics that I've thought about for years, but I also often write articles that are half-baked ideas; I put these articles out in order to start a discussion, so I appreciate your comments.

    - I'm much happier with the article that argues that Service Locator violates Encapsulation. + I'm much happier with the article that argues that Service Locator violates Encapsulation.

    2016-01-08 10:55 UTC
    diff --git a/_posts/2014-05-16-configuring-azure-web-jobs.html b/_posts/2014-05-16-configuring-azure-web-jobs.html index 61df580ab..0903a448a 100644 --- a/_posts/2014-05-16-configuring-azure-web-jobs.html +++ b/_posts/2014-05-16-configuring-azure-web-jobs.html @@ -69,7 +69,7 @@

    - The CloudConfigurationManager class isn't part of the .NET Base Class Library, but you can easily add it from NuGet; it's called Microsoft.WindowsAzure.ConfigurationManager. The Azure SDK isn't required - it's just a stand-alone library with no dependencies, so I happily add it to my Composition Root when I know I'm going to deploy to an Azure Web Site. + The CloudConfigurationManager class isn't part of the .NET Base Class Library, but you can easily add it from NuGet; it's called Microsoft.WindowsAzure.ConfigurationManager. The Azure SDK isn't required - it's just a stand-alone library with no dependencies, so I happily add it to my Composition Root when I know I'm going to deploy to an Azure Web Site.

    Web Jobs # @@ -91,7 +91,7 @@

    - +

    Howard, thank you for writing. You should always keep your secrets out of source control. In some projects, I've used web.config transforms for that purpose. Leave your checked-in .config files empty, and have local (not checked-in) .config files on development machines, production servers, and so on. diff --git a/_posts/2014-05-19-conforming-container.html b/_posts/2014-05-19-conforming-container.html index 15661fca7..7cab80c0b 100644 --- a/_posts/2014-05-19-conforming-container.html +++ b/_posts/2014-05-19-conforming-container.html @@ -53,7 +53,7 @@

    Sometimes, the interface defines only a single of those methods; sometimes, it defines even more variations of methods to create objects based on a Type.

    - Some Conforming Containers stop at this point, so that the interface only exposes Queries, which means that they only cover the Resolve phase of the Register Resolve Release pattern. Other efforts attempt to address Register phase too: + Some Conforming Containers stop at this point, so that the interface only exposes Queries, which means that they only cover the Resolve phase of the Register Resolve Release pattern. Other efforts attempt to address Register phase too:

    public interface IContainer
    @@ -89,11 +89,11 @@ 

    such as:
    • Calls to the Conforming Container are likely to be sprinkled liberally over an entire code base.
    • -
    • It pushes novice users towards the Service Locator anti-pattern. Most people encountering Dependency Injection for the first time mistake it for the Service Locator anti-pattern, despite the entirely opposite natures of these two approaches to loose coupling.
    • -
    • It attempts to relieve symptoms of bad design, instead of addressing the underlying problem. Too many 'loosely coupled' designs attempt to rely on the Service Locator anti-pattern, which, by default, introduces a dependency to a concrete Service Locator throughout a code base. However, exclusively using the Constructor Injection and Composition Root design patterns eliminate the problem altogether, resulting in a simpler design with fewer moving parts.
    • +
    • It pushes novice users towards the Service Locator anti-pattern. Most people encountering Dependency Injection for the first time mistake it for the Service Locator anti-pattern, despite the entirely opposite natures of these two approaches to loose coupling.
    • +
    • It attempts to relieve symptoms of bad design, instead of addressing the underlying problem. Too many 'loosely coupled' designs attempt to rely on the Service Locator anti-pattern, which, by default, introduces a dependency to a concrete Service Locator throughout a code base. However, exclusively using the Constructor Injection and Composition Root design patterns eliminate the problem altogether, resulting in a simpler design with fewer moving parts.
    • It pulls in the direction of the lowest common denominator.
    • It stifles innovation, because new, creative, but radical ideas may not fit into the narrow view of the world a Conforming Container defines.
    • -
    • It makes it more difficult to avoid using a DI Container. A DI Container can be useful in certain scenarios, but often, hand-coded composition is better than using a DI Container. However, if a library or framework depends on a Conforming Container, it may be difficult to harvest the benefits of hand-coded composition.
    • +
    • It makes it more difficult to avoid using a DI Container. A DI Container can be useful in certain scenarios, but often, hand-coded composition is better than using a DI Container. However, if a library or framework depends on a Conforming Container, it may be difficult to harvest the benefits of hand-coded composition.
    • It may introduce versioning hell. Imagine that you need to use a library that depends on Confainer 1.3.7 in an application that also uses a framework that depends on Confainer 2.1.7. Since a Conforming Container is intended as an infrastructure component, this is likely to happen, and to cause much grief.
    • A Conforming Container is often a product of Speculative Generality, instead of a product of need. As such, the API is likely to be poorly suited to address real-world scenarios, be difficult to extent, and may exhibit churn in the form of frequent breaking changes.
    • If Adapters are supplied by contributors (often the DI Container maintainers themselves), the Adapters may have varying quality levels, and may not support the latest version of the Conforming Container.
    • @@ -252,7 +252,7 @@

      }

    - This leaves all options open for any code consuming the CorrectClient class. The only exception to relying on Constructor Injection is when you need to compose all these collaborating classes. The Composition Root has the single responsibility of composing all the objects into a working object graph: + This leaves all options open for any code consuming the CorrectClient class. The only exception to relying on Constructor Injection is when you need to compose all these collaborating classes. The Composition Root has the single responsibility of composing all the objects into a working object graph:

    public class CompositionRoot
    @@ -267,7 +267,7 @@ 

    }

    - In this example, the final graph is rather shallow, but it can be as complex and deep as necessary. This Composition Root uses hand-coded composition, but if you want to use a DI Container, the Composition Root is where you put it: + In this example, the final graph is rather shallow, but it can be as complex and deep as necessary. This Composition Root uses hand-coded composition, but if you want to use a DI Container, the Composition Root is where you put it:

    public class WindsorCompositionRoot
    @@ -297,13 +297,13 @@ 

    A Composition Root is only a small part of an application

    - (The above picture is meant to illustrate an arbitrary application architecture; it could be layered, onion, hexagonal, or something else - it doesn't really matter.) If you want to replace one DI Container with another DI Container, you only replace the Composition Root; the rest of the application will never notice the difference. + (The above picture is meant to illustrate an arbitrary application architecture; it could be layered, onion, hexagonal, or something else - it doesn't really matter.) If you want to replace one DI Container with another DI Container, you only replace the Composition Root; the rest of the application will never notice the difference.

    Notice that only applications should have Composition Roots. Libraries and frameworks should not.

      -
    • Library classes should be defined with Constructor Injection throughout. If the library object model is very complex, a few Facades can be supplied to make it easier for library users to get started. See my article on DI-friendly libraries for more details.
    • -
    • Frameworks should have appropriate hooks built in. These hooks should not be designed as Service Locators, but rather as Abstract Factories. See my article on DI-friendly frameworks for more details.
    • +
    • Library classes should be defined with Constructor Injection throughout. If the library object model is very complex, a few Facades can be supplied to make it easier for library users to get started. See my article on DI-friendly libraries for more details.
    • +
    • Frameworks should have appropriate hooks built in. These hooks should not be designed as Service Locators, but rather as Abstract Factories. See my article on DI-friendly frameworks for more details.
    These solutions are better than a Conforming Container because they are simpler, have fewer moving parts, are easier to understand, and easier to reason about.

    diff --git a/_posts/2014-05-19-di-friendly-framework.html b/_posts/2014-05-19-di-friendly-framework.html index 6a34e77c7..0e1d4dcc4 100644 --- a/_posts/2014-05-19-di-friendly-framework.html +++ b/_posts/2014-05-19-di-friendly-framework.html @@ -14,15 +14,15 @@ {{ page.description }}

    - It seems to me that every time a development organisation wants to add 'Dependency Injection support' to a framework, all too often, the result is a Conforming Container. In this article I wish to describe good alternatives to this anti-pattern. + It seems to me that every time a development organisation wants to add 'Dependency Injection support' to a framework, all too often, the result is a Conforming Container. In this article I wish to describe good alternatives to this anti-pattern.

    - In a previous article I covered how to design a Dependency Injection-friendly library; in this article, I will deal with frameworks. The distinction I usually make is: + In a previous article I covered how to design a Dependency Injection-friendly library; in this article, I will deal with frameworks. The distinction I usually make is:

    • A Library is a reusable set of types or functions you can use from a wide variety of applications. The application code initiates communication with the library and invokes it.
    • A Framework consists of one or more libraries, but the difference is that Inversion of Control applies. The application registers with the framework (often by implementing one or more interfaces), and the framework calls into the application, which may call back into the framework. A framework often exists to address a particular general-purpose Domain (such as web applications, mobile apps, workflows, etc.).
    - In my article about the Conforming Container anti-pattern, I already covered some general reason why attempting to create an abstraction over DI Containers is a bad idea, but when it comes to frameworks, some extra concerns arise. + In my article about the Conforming Container anti-pattern, I already covered some general reason why attempting to create an abstraction over DI Containers is a bad idea, but when it comes to frameworks, some extra concerns arise.

    The composition challenge # @@ -41,7 +41,7 @@

    Framework sequence diagram

    - Once the framework has an instance of the custom user class, it can easily start using it by invoking methods defined by the interface the class implements, etc. The difficult part is creating the instance. By default, most frameworks require that a custom class has a default (parameterless) constructor, but that may be a design smell, and doesn't fit with the Constructor Injection pattern. Such a requirement is a sensible default, but isn't Dependency Injection-friendly; in fact, it's an example of the Constrained Construction anti-pattern, which you can read about in my book. + Once the framework has an instance of the custom user class, it can easily start using it by invoking methods defined by the interface the class implements, etc. The difficult part is creating the instance. By default, most frameworks require that a custom class has a default (parameterless) constructor, but that may be a design smell, and doesn't fit with the Constructor Injection pattern. Such a requirement is a sensible default, but isn't Dependency Injection-friendly; in fact, it's an example of the Constrained Construction anti-pattern, which you can read about in my book.

    Most framework designers realize this and resolve to add Dependency Injection support to the framework. Often, in the first few iterations, they get it right! @@ -109,7 +109,7 @@

    Framework sequence diagram with release hook

    - Some framework designers attempt to introduce a 'more sophisticated' lifetime model, but there's no reason for that. This Create/Release design is simple, easy to understand, works very well, and fits perfectly into the Register Resolve Release pattern, since it provides hooks for the Resolve and Release phases. + Some framework designers attempt to introduce a 'more sophisticated' lifetime model, but there's no reason for that. This Create/Release design is simple, easy to understand, works very well, and fits perfectly into the Register Resolve Release pattern, since it provides hooks for the Resolve and Release phases.

    ASP.NET MVC 1 and 2 provided flawless examples of such Abstract Factories in the form of the IControllerFactory interface: @@ -254,10 +254,10 @@

  • Resist the urge to generalise, and define each Abstract Factory as a separate interface. That design is easy to understand, and users can implement as many or as few of these Abstract Factories as they want. In the end, frameworks are designed for the framework users, not for the framework developers.
  • If absolutely unavoidable, define a generic Abstract Factory.
  • - Under no circumstance is a Conforming Container the appropriate response. + Under no circumstance is a Conforming Container the appropriate response.

    - Many distinct, but similar Abstract Factory interfaces may be repetitive, but that's unlikely to hurt the user. A good framework provides optional extensibility points - it doesn't force users to relate to all of them at once. As an example, I'm a fairly satisfied user of the ASP.NET Web API, but while I create lots of Controllers, and the occasional Exception Filter, I've yet to write my first custom Formatter. I only add a custom IHttpControllerActivator for my Controllers. Although (unfortunately) ASP.NET Web API has had a Conforming Container in the form of the IDependencyResolver interface since version 1, I've never used it. In a properly designed framework, a Conforming Container is utterly redundant. + Many distinct, but similar Abstract Factory interfaces may be repetitive, but that's unlikely to hurt the user. A good framework provides optional extensibility points - it doesn't force users to relate to all of them at once. As an example, I'm a fairly satisfied user of the ASP.NET Web API, but while I create lots of Controllers, and the occasional Exception Filter, I've yet to write my first custom Formatter. I only add a custom IHttpControllerActivator for my Controllers. Although (unfortunately) ASP.NET Web API has had a Conforming Container in the form of the IDependencyResolver interface since version 1, I've never used it. In a properly designed framework, a Conforming Container is utterly redundant.

    If the framework must address the apparent DRY violation of multiple similar Abstract Factory definitions, an acceptable solution is a generic interface: @@ -271,7 +271,7 @@

    }

    - This type of generic Factory is generally benign, although it may hurt discoverability, because a generic type looks as though you can use anything for the type argument T, where, in fact, the framework only needs a finite set of Abstract Factories, like + This type of generic Factory is generally benign, although it may hurt discoverability, because a generic type looks as though you can use anything for the type argument T, where, in fact, the framework only needs a finite set of Abstract Factories, like

    • IFactory<IXyzController>
    • IFactory<IXyzFilter>
    • @@ -327,13 +327,13 @@

      Some frameworks provide extensibility points in the form of attributes. ASP.NET MVC, for example, defines various Filter attributes, such as [Authorize], [HandleError], [OutputCache], etc. Some of these attributes contain behaviour, because they implement interfaces such as IAuthorizationFilter, IExceptionFilter, and so on.

      - Attributes with behaviour is a bad idea. Due to compiler limitations (at least in both C# and F#), you can only provide constants and literals to an attribute. That effectively rules out Dependency Injection, but if an attribute contains behaviour, it's guaranteed that some user comes by and wants to add some custom behaviour in an attribute. The only way to add 'Dependency Injection support' to attributes is through a static Service Locator - an exceptionally toxic design. Attribute designers should avoid this. This is not Dependency Injection support; it's Service Locator support. There's no reason to bake in Service Locator support in a framework. People who deliberately want to hurt themselves can always add a static Service Locator by themselves. + Attributes with behaviour is a bad idea. Due to compiler limitations (at least in both C# and F#), you can only provide constants and literals to an attribute. That effectively rules out Dependency Injection, but if an attribute contains behaviour, it's guaranteed that some user comes by and wants to add some custom behaviour in an attribute. The only way to add 'Dependency Injection support' to attributes is through a static Service Locator - an exceptionally toxic design. Attribute designers should avoid this. This is not Dependency Injection support; it's Service Locator support. There's no reason to bake in Service Locator support in a framework. People who deliberately want to hurt themselves can always add a static Service Locator by themselves.

      Instead, attributes should be designed without behaviour. Instead of putting the behaviour in the attribute itself, a custom attribute should only provide metadata - after all, that's the original raison d'être of attributes.

      - Attributes with metadata can then be detected and handled by normal services, which enable normal Dependency Injection. See this Stack Overflow answer for an ASP.NET MVC example, or my article on Passive Attributes for a Web API example. + Attributes with metadata can then be detected and handled by normal services, which enable normal Dependency Injection. See this Stack Overflow answer for an ASP.NET MVC example, or my article on Passive Attributes for a Web API example.

      Summary # @@ -345,7 +345,7 @@

      Framework users who don't care about Dependency Injection at all can simply ignore the whole issue and use the framework with its default services. Framework users who prefer to hand-code object composition, can implement the appropriate Abstract Factories by writing custom code. Framework users who prefer to use their DI Container of choice can implement the appropriate Abstract Factories as Adapters over the container.

      - That's all. There's no reason to make it more complicated than that. There's particularly no reason to force a Conforming Container upon the users. + That's all. There's no reason to make it more complicated than that. There's particularly no reason to force a Conforming Container upon the users.

    @@ -364,7 +364,7 @@

    2014-08-10 08:54 UTC

    - +

    Shad, thank you for writing. From your questions it's a bit unclear to me whether you're writing a framework or a library. Although you write framework, your questions sound like it's a library... or at least, if you're writing a framework, it sounds like you're writing a sub-framework for another framework (MVC). Is that correct? @@ -406,7 +406,7 @@

    2015-08-14 20:27 UTC

    - +

    Shad, I don't exactly recall how DefaultControllerFactory.ReleaseController is implemented, but in general, only type-checking for IDisposable and calling Dispose may be too simplistic a view to take in the general case. As I explain in chapter 8 in my book, releasing an object graph isn't always equivalent to disposal. In the general case, you also need to take into account the extra dimension of the various lifetimes of objects in an object graph. Some object may have a longer lifetime scope, so even when you invoke Release on them, their time isn't up yet, and therefore it would be a bug to dispose of them. @@ -433,7 +433,7 @@

    2014-09-25 21:14 UTC

    - +

    Robert, thank you for writing. What advantage would a Marker Interface provide? @@ -460,7 +460,7 @@

    2014-09-26 20:48 UTC

    - +

    How does a Marker Interface lead to less framework code? It has no behaviour, so it's hard for me to imagine how it leads to less code. From a client perspective, it also sounds rather redundant to me. How can we see the possible hooks in the framework by looking for a Marker Interface? Aren't all public interfaces defined by a framework hooks? @@ -479,14 +479,14 @@

    1. To create the default implementations (that are provided with the framework) of the factories exposed in XyzConfiguration, it might be necessary to compose a complex dependency graph first, because the the default implementations of the factories themselves have dependencies. So there must be code in the framework that does this composition. At the same time this composition code should be extensible and it should be possible let the DI container of the customers choice to this composition. Can you sektch out how one would design for such a scenario or are you aware of a framework that does this well?
    2. -
    3. Once the factories in XyzConfiguration are configured and initialized, it seems that all framework classes that need one of those factories get a dependency on the XyzConfiguration, because that's the place where to get the factories from. This would be Service Locator antipattern how would I avoid this?
    4. +
    5. Once the factories in XyzConfiguration are configured and initialized, it seems that all framework classes that need one of those factories get a dependency on the XyzConfiguration, because that's the place where to get the factories from. This would be Service Locator antipattern how would I avoid this?

    2015-09-04 13:40 UTC
    - +

    bitbonk, thank you for writing. @@ -525,10 +525,10 @@

    Since the default value is only initialized if it's used, there's no cost associated with it. The XyzConfiguration class still has a public constructor, so if a framework user doesn't want to use the default, he or she can always create a new instance of the class, and pass that configuration to the framework when it's bootstrapping. The user can even use XyzConfiguration.Default as a starting point, and only tweak the properties he or she wants to tweak.

    - While XyzConfiguration.Default defines default graphs, all the constituent elements (XyzControllerFactory, Foo, Bar, Baz, etc.) are public classes with public constructors, so a framework user can always duplicate the graph him- or herself. If the framework developers want to make it easier to tweak the default graph, they can supply a facade using one of the options outlines in my companion article about DI-friendly libraries. + While XyzConfiguration.Default defines default graphs, all the constituent elements (XyzControllerFactory, Foo, Bar, Baz, etc.) are public classes with public constructors, so a framework user can always duplicate the graph him- or herself. If the framework developers want to make it easier to tweak the default graph, they can supply a facade using one of the options outlines in my companion article about DI-friendly libraries.

    - Re 2: Such an XyzConfiguration class isn't a Service Locator. It's a concrete, well-known, finite collection of Abstract Factories, whereas a Service Locator is an unknown, infinite set of Abstract Factories. + Re 2: Such an XyzConfiguration class isn't a Service Locator. It's a concrete, well-known, finite collection of Abstract Factories, whereas a Service Locator is an unknown, infinite set of Abstract Factories.

    Still, I would recommend that framework developers adhere to the Interface Segregation Principle and only take dependencies on those Abstract Factories they need. If a framework feature needs an IFactory<IXyzController>, then that's what it should take in via its constructor. The framework should pass to that constructor configuration.ControllerFactory instead of the entire configuration object. @@ -542,7 +542,7 @@

    Thanks Mark for your answer, it all makes sense to me but my first question was more geared towards the DI container. For the composition of the default dependency graphs, the (my) framework needs to provide three things at the same time:

      -
    1. Means that helps the user build default combination(s) of dependencies for common scenarios without forcing the user to use (or depend on) any DI container. I can see how this can easily be achieved by using the factory approach you mentioned or by using facade or constructor chaining as you mentioned and in your companion article about DI-friendly libraries
    2. +
    3. Means that helps the user build default combination(s) of dependencies for common scenarios without forcing the user to use (or depend on) any DI container. I can see how this can easily be achieved by using the factory approach you mentioned or by using facade or constructor chaining as you mentioned and in your companion article about DI-friendly libraries
    4. Means that helps the user build the default combination(s) of dependencies for common scenarios using the DI container of the user's choice (i.e. an existing container instance that was already created and is used for the rest of the application dependencies too). The user might want to do this because she wants to resolve some the dependencies that have been registered by the framework using the DI container of her application. I can see how this could be achieved by introducing some sort of framework-specific DI container abstraction and provide implementations for common containers (like XyzFramework.Bootstrappers.StructureMap or XyzFramework.Bootstrappers.SimpleInjector ...). It looks like this is how it is done in NancyFx.
    5. Means that helps the user modify and adapt the default combination(s) of dependencies for common scenarios using that DI container. The user might want to modify just parts of a default dependency graph or wants to intercept just some of the default dependencies. The user should be able to do this without having to reimplement the whole construction logic. Again NancyFx seems to do this by introducing a DI container abstraction.
    @@ -554,7 +554,7 @@

    2015-09-07 13:45 UTC

    - +

    Before we continue this discussion, I find myself obliged to point out that you ought have a compelling reason to create a framework. Tomas Petricek has a great article that explains why you should favour libraries over frameworks. The article uses F# for code examples, but the arguments apply equally to C# and Object-Oriented Design. @@ -563,13 +563,13 @@

    I have a hard time coming up with a single use case where a framework would be the correct design decision, but perhaps your use case is a genuine case for making a framework...

    - That said, I don't understand your second bullet point. If all the classes involved in building those default object graphs are public, a user can always register them with their DI Container of choice. Why would you need a container abstraction (which is a poor idea) for that? + That said, I don't understand your second bullet point. If all the classes involved in building those default object graphs are public, a user can always register them with their DI Container of choice. Why would you need a container abstraction (which is a poor idea) for that?

    The third bullet point makes me uneasy as well. It seems to me that the entire premise in this, and your previous, comment is that the default object graphs are deep and complex. Is that really necessary?

    - Still, if you want to make it easy for a user to modify the default factories, you can supply a Facade or Fluent Builder as already outlined. The user can use that API to tweak the defaults. Why would the user even wish to involve a DI Container in that process? + Still, if you want to make it easy for a user to modify the default factories, you can supply a Facade or Fluent Builder as already outlined. The user can use that API to tweak the defaults. Why would the user even wish to involve a DI Container in that process?

    For the sake of argument, let's assume that this is somehow necessary. The user can still hook into the provided API and combine that with a DI Container. Here's a Castle Windsor example: @@ -765,7 +765,7 @@

    - +

    John, thank you for writing. When I look at your GitHub repository, I think that it looks fine. I particularly like that if I had to work with something like this, I get to control the lifetime of all my object graphs. I just have to implement IApp and call CompositionFacade.Run with it. @@ -774,7 +774,7 @@

    This makes it more like a library than a framework, although I do understand that the intent is that Run executes for the lifetime of the application.

    - This means that if I need to implement IApp with a complex graph of objects, I can do that. In my Main method, I can compose my object graph with Pure DI, or I can leverage a DI Container if I so choose. + This means that if I need to implement IApp with a complex graph of objects, I can do that. In my Main method, I can compose my object graph with Pure DI, or I can leverage a DI Container if I so choose.

    What happens inside of CompositionFacade.Run is completely opaque to me, which implies good encapsulation. diff --git a/_posts/2014-05-19-di-friendly-library.html b/_posts/2014-05-19-di-friendly-library.html index da03a52e5..a97c35f68 100644 --- a/_posts/2014-05-19-di-friendly-library.html +++ b/_posts/2014-05-19-di-friendly-library.html @@ -14,10 +14,10 @@ {{ page.description }}

    - In my book, I go to great lengths to explain how to develop loosely coupled applications using various Dependency Injection (DI) patterns, including the Composition Root pattern. With the great emphasis on applications, I didn't particularly go into details about making DI-friendly libraries. Partly this was because I didn't think it was necessary, but since one of my highest voted Stack Overflow answers deal with this question, it may be worth expanding on. + In my book, I go to great lengths to explain how to develop loosely coupled applications using various Dependency Injection (DI) patterns, including the Composition Root pattern. With the great emphasis on applications, I didn't particularly go into details about making DI-friendly libraries. Partly this was because I didn't think it was necessary, but since one of my highest voted Stack Overflow answers deal with this question, it may be worth expanding on.

    - In this article, I will cover libraries, and in a later article I will deal with frameworks. The distinction I usually make is: + In this article, I will cover libraries, and in a later article I will deal with frameworks. The distinction I usually make is:

    • A Library is a reusable set of types or functions you can use from a wide variety of applications. The application code initiates communication with the library and invokes it.
    • A Framework consists of one or more libraries, but the difference is that Inversion of Control applies. The application registers with the framework (often by implementing one or more interfaces), and the framework calls into the application, which may call back into the framework. A framework often exists to address a particular general-purpose Domain (such as web applications, mobile apps, workflows, etc.).
    • @@ -66,7 +66,7 @@

      Use Constructor Injection #

      - Favour the Constructor Injection pattern over other injection patterns, because of its simplicity and degree of encapsulation. + Favour the Constructor Injection pattern over other injection patterns, because of its simplicity and degree of encapsulation.

      As an example, Hyprlinkr's main class, RouteLinker, has this primary constructor: @@ -94,10 +94,10 @@

      }

      - Notice that it follows Nikola Malovic's 4th law of IoC that Injection Constructors should be simple. + Notice that it follows Nikola Malovic's 4th law of IoC that Injection Constructors should be simple.

      - Although not strictly required in order to make a library DI-friendly, expose every injected dependency as an Inspection Property - it will make the library easier to use when composed in one place, but used in another place. Again, Hyprlinkr does that: + Although not strictly required in order to make a library DI-friendly, expose every injected dependency as an Inspection Property - it will make the library easier to use when composed in one place, but used in another place. Again, Hyprlinkr does that:

      public IRouteValuesQuery RouteValuesQuery
      @@ -112,7 +112,7 @@ 

      Consider an Abstract Factory for short-lived objects #

      - Sometimes, your library must create short-lived objects in order to do its work. Other times, the library can only create a required object at run-time, because only at run-time is all required information available. You can use an Abstract Factory for that. + Sometimes, your library must create short-lived objects in order to do its work. Other times, the library can only create a required object at run-time, because only at run-time is all required information available. You can use an Abstract Factory for that.

      The Abstract Factory doesn't always have to be named XyzFactory; in fact, Hyprlinkr's IRouteDispatcher interface is an Abstract Factory, although it's in disguise because it has a different name. @@ -291,10 +291,10 @@

    - +

    - Maris, thank you for writing. Hopefully, this article answers your question. + Maris, thank you for writing. Hopefully, this article answers your question.

    2014-06-03 9:20 UTC
    diff --git a/_posts/2014-05-26-feedback-on-aspnet-vnext-dependency-injection.html b/_posts/2014-05-26-feedback-on-aspnet-vnext-dependency-injection.html index f3aafda05..1383edc5c 100644 --- a/_posts/2014-05-26-feedback-on-aspnet-vnext-dependency-injection.html +++ b/_posts/2014-05-26-feedback-on-aspnet-vnext-dependency-injection.html @@ -50,17 +50,17 @@

  • Unity
  • Caste Windsor
  • - As far as I can tell, there's no web code in the ASP.NET Dependency Injection code base. In other words, this is a poster example of a Conforming Container. + As far as I can tell, there's no web code in the ASP.NET Dependency Injection code base. In other words, this is a poster example of a Conforming Container.

    My recommendations #

    - It's an excellent idea to add 'Dependency Injection support' to ASP.NET, for the few places where it's not already present. However, as I've previously explained, a Conforming Container isn't the right solution. The right solution is to put the necessary extensibility points into the framework: + It's an excellent idea to add 'Dependency Injection support' to ASP.NET, for the few places where it's not already present. However, as I've previously explained, a Conforming Container isn't the right solution. The right solution is to put the necessary extensibility points into the framework:

    • ASP.NET MVC already has a good extensibility point in the IControllerFactory interface. I recommend keeping this interface, and other interfaces in MVC that play a similar role.
    • ASP.NET Web API already has a good extensibility point in the IHttpControllerActivator interface. I recommend keeping this interface, and other interfaces in Web API that play a similar role.
    • -
    • ASP.NET Web Forms have no extensibility point that enables you to create custom Page objects. I recommend adding an IPageFactory interface, as described in my article about DI-Friendly frameworks. Other object types related to Web Forms, such as Object Data Sources, suffer from the same shortcoming, and should have similar factory interfaces.
    • +
    • ASP.NET Web Forms have no extensibility point that enables you to create custom Page objects. I recommend adding an IPageFactory interface, as described in my article about DI-Friendly frameworks. Other object types related to Web Forms, such as Object Data Sources, suffer from the same shortcoming, and should have similar factory interfaces.
    • There may be other parts of ASP.NET with which I'm not particularly familiar (SignalR?), but they should all follow the same pattern of defining Abstract Factories for user classes, in the cases where these don't already exist.
    In addition to adding these required extensibility points, I recommend completely abandoning the project of defining a Conforming Container. The extensibility points should be added where they're used - the MVC Factories as part of MVC, the Web Form Factories as part of Web Forms, etc. This will have the added benefit of making the ASP.NET Dependency Injection project redundant. Less code is better than more code. diff --git a/_posts/2014-06-02-captive-dependency.html b/_posts/2014-06-02-captive-dependency.html index 243d66486..88b7fd1fb 100644 --- a/_posts/2014-06-02-captive-dependency.html +++ b/_posts/2014-06-02-captive-dependency.html @@ -14,13 +14,13 @@ {{ page.description }}

    - This post is the sixth in a series about Poka-yoke Design. + This post is the sixth in a series about Poka-yoke Design.

    - When you use a Dependency Injection (DI) Container, you should configure it according to the Register Resolve Release pattern. One aspect of configuration is to manage the lifetime of various services. If you're not careful, though, you may misconfigure lifetimes in such a way that a longer-lived service holds a shorter-lived service captive - often with subtle, but disastrous results. You could call this misconfiguration a Captive Dependency. + When you use a Dependency Injection (DI) Container, you should configure it according to the Register Resolve Release pattern. One aspect of configuration is to manage the lifetime of various services. If you're not careful, though, you may misconfigure lifetimes in such a way that a longer-lived service holds a shorter-lived service captive - often with subtle, but disastrous results. You could call this misconfiguration a Captive Dependency.

    - A major step in applying DI is to compose object graphs, and service lifetimes in object graphs are hierarchical: + A major step in applying DI is to compose object graphs, and service lifetimes in object graphs are hierarchical:

    Hierarchical lifetime nature of object graphs @@ -194,7 +194,7 @@

    Concluding remarks #

    - You can re-create this problem with any major DI Container. The problem isn't associated with any particular DI Container, but simply the fact that there are trade-offs associated with using a DI Container, and one of the trade-offs is a reduction in compile-time feedback. The way typical DI Container registration APIs work, they can't easily detect this lifetime configuration mismatch. + You can re-create this problem with any major DI Container. The problem isn't associated with any particular DI Container, but simply the fact that there are trade-offs associated with using a DI Container, and one of the trade-offs is a reduction in compile-time feedback. The way typical DI Container registration APIs work, they can't easily detect this lifetime configuration mismatch.

    It's been a while since I last did a full survey of the .NET DI Container landscape, and back then (when I wrote my book), no containers could detect this problem. Since then, I believe Castle Windsor has got some Captive Dependency detection built in, but I admit that I'm not up to speed; other containers may have this feature as well. @@ -208,7 +208,7 @@

    Since then, I've thought of the name Captive Dependency, which may not be super-catchy, but at least accurately describes the problem. A longer-lived object (e.g. a Singleton) holds a shorter-lived object captive, past its due release time. Although the shorter-lived object should be released, it's not, because of a bureaucratic error.

    - In a follow-up post to this, I'll demonstrate why you don't have the same problem when you hand-code your object graphs. + In a follow-up post to this, I'll demonstrate why you don't have the same problem when you hand-code your object graphs.

    diff --git a/_posts/2014-06-03-compile-time-lifetime-matching.html b/_posts/2014-06-03-compile-time-lifetime-matching.html index 171d4860b..57be0df3c 100644 --- a/_posts/2014-06-03-compile-time-lifetime-matching.html +++ b/_posts/2014-06-03-compile-time-lifetime-matching.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my previous post, you learned how easy it is to accidentally misconfigure a DI Container to produce Captive Dependencies, which are dependencies that are being kept around after they should have been released. This can lead to subtle or catastrophic bugs. + In my previous post, you learned how easy it is to accidentally misconfigure a DI Container to produce Captive Dependencies, which are dependencies that are being kept around after they should have been released. This can lead to subtle or catastrophic bugs.

    This problem is associated with DI Containers, because Container registration APIs let you register services out of order, and with any particular lifestyle you'd like: @@ -29,19 +29,19 @@ In this Autofac example, CommerceContext is registered before SqlProductRepository, even though SqlProductRepository is a 'higher-level' service, but ProductService is registered first, and it's even 'higher-level' than SqlProductRepository. A DI Container doesn't care; it'll figure it out.

    - The compiler doesn't care if the various lifetime configurations make sense. As you learned in my previous article, this particular configuration combination doesn't make sense, but the compiler can't help you. + The compiler doesn't care if the various lifetime configurations make sense. As you learned in my previous article, this particular configuration combination doesn't make sense, but the compiler can't help you.

    Compiler assistance #

    - The overall message in my Poka-yoke Design article series is that you can often design your types in such a way that they are less forgiving of programming mistakes; this enables the compiler to give you feedback faster than you could otherwise have gotten feedback. + The overall message in my Poka-yoke Design article series is that you can often design your types in such a way that they are less forgiving of programming mistakes; this enables the compiler to give you feedback faster than you could otherwise have gotten feedback.

    - If, instead of using a DI Container, you'd simply hand-code the required object composition (also called Poor Man's DI in my book, but now called Pure DI), the compiler will make it much harder for you to mismatch object lifetimes. Not impossible, but more difficult. + If, instead of using a DI Container, you'd simply hand-code the required object composition (also called Poor Man's DI in my book, but now called Pure DI), the compiler will make it much harder for you to mismatch object lifetimes. Not impossible, but more difficult.

    - As an example, consider a web-based Composition Root. Here, the particular IHttpControllerActivator interface belongs to ASP.NET Web API, but it could be any Composition Root: + As an example, consider a web-based Composition Root. Here, the particular IHttpControllerActivator interface belongs to ASP.NET Web API, but it could be any Composition Root:

    public class SomeCompositionRoot : IHttpControllerActivator
    @@ -101,7 +101,7 @@ 

    Commerce example #

    - In the previous article, you saw how easy it is to misconfigure a ProductService, because you'd like it to be a Singleton. When you hand-code the composition, it becomes much easier to spot the mistake. You may start like this: + In the previous article, you saw how easy it is to misconfigure a ProductService, because you'd like it to be a Singleton. When you hand-code the composition, it becomes much easier to spot the mistake. You may start like this:

    public class CommerceCompositionRoot : IHttpControllerActivator
    @@ -176,7 +176,7 @@ 

    Concluding remarks #

    - Some time ago, I wrote an article on when to use a DI Container. In that article, I attempted to explain how going from Pure DI (hand-coded composition) to a DI Container meant loss of compile-time safety, but I may have made an insufficient job of providing enough examples of this effect. The Captive Dependency configuration error, and this article together, describe one such effect: with Pure DI, lifetime matching is compiler-assisted, but if you refactor to use a DI Container, you lose the compiler's help. + Some time ago, I wrote an article on when to use a DI Container. In that article, I attempted to explain how going from Pure DI (hand-coded composition) to a DI Container meant loss of compile-time safety, but I may have made an insufficient job of providing enough examples of this effect. The Captive Dependency configuration error, and this article together, describe one such effect: with Pure DI, lifetime matching is compiler-assisted, but if you refactor to use a DI Container, you lose the compiler's help.

    Since I wrote the article on when to use a DI Container, I've only strengthened my preference for Pure DI. Unless I'm writing a very complex code base that could benefit from Convention over Configuration, I don't use a DI Container, but since I explicitly architect my systems to be non-complex these days, I haven't used a DI Container in production code for more than 1½ years. @@ -256,13 +256,13 @@

    - +

    - Steve, thank you for writing. Indeed, you can make a DI Container detect the Captive Dependency error at run-time. I pointed that out in the defining article about the Captive Dependency problem, and as qujck points out in the comments, Simple Injector has this feature, too. + Steve, thank you for writing. Indeed, you can make a DI Container detect the Captive Dependency error at run-time. I pointed that out in the defining article about the Captive Dependency problem, and as qujck points out in the comments, Simple Injector has this feature, too.

    - The point with the present article is that, instead of waiting until run-time, you get a chance to learn about potential lifetime mismatches already at design-time. In C#, F#, and other compiled languages, you can't perform a run-time test until you've compiled. While I'm all for fail fast, I don't think it'd be failing fast enough, if you can catch the problem at compile time, but then deliberately wait until run-time. + The point with the present article is that, instead of waiting until run-time, you get a chance to learn about potential lifetime mismatches already at design-time. In C#, F#, and other compiled languages, you can't perform a run-time test until you've compiled. While I'm all for fail fast, I don't think it'd be failing fast enough, if you can catch the problem at compile time, but then deliberately wait until run-time.

    Another concern is to go for the simplest thing that could possibly work. Why use a complex piece of code like your AutofacControllerFactory above, instead of just writing the code directly? It's no secret that I'm not a big fan of the Lifetime Scope idiom, and your code provides an excellent example of how complicated it is. You may have omitted this for the sake of the example, but that code isn't thread-safe; in order to make it thread-safe, you'd need to make it even more complicated. @@ -360,10 +360,10 @@

    - +

    - Before we continue this discussion, I think it's important to establish how you use a DI Container. If you refer to my article on the benefits of using a DI Container, which approach are you using? + Before we continue this discussion, I think it's important to establish how you use a DI Container. If you refer to my article on the benefits of using a DI Container, which approach are you using?

    2014-06-05 14:22 UTC
    @@ -383,7 +383,7 @@

    - +

    That makes the discussion a little less clear-cut, because you are getting some of the benefits out of Convention over Configuration, but perhaps not as much as you could... Depending on how you put the balance between these two, I would agree with you that using a DI Container is beneficial. @@ -395,7 +395,7 @@

    Do I know of any medium-sized code bases that use Pure DI to good effect? Perhaps... I don't know what a 'medium-sized' code base is to you. In any case, while I may know of such code bases, I know of none where the source code is public.

    - 300-odd lines of code for composition sounds like a lot, but as I have previously demonstrated, using Explicit Register will only increase the line count. + 300-odd lines of code for composition sounds like a lot, but as I have previously demonstrated, using Explicit Register will only increase the line count.

    Another criticism of manual composition is that every time you change something, you'll need to edit the composition code. That's true, but this is equally as true for Explicit Register. The difference is that with manual composition, you learn about this at compile-time, while with Explicit Register, you don't learn about changes until run-time. This, in isolation, is a clear win for manual composition. diff --git a/_posts/2014-06-10-pure-di.html b/_posts/2014-06-10-pure-di.html index 9497ac08c..f2865766e 100644 --- a/_posts/2014-06-10-pure-di.html +++ b/_posts/2014-06-10-pure-di.html @@ -26,8 +26,8 @@

    Apart from my book, I've attempted to describe the trade-off involved in going from Poor Man's DI to using a DI Container in various articles:

    Based on the reactions I've received, it seems like my readers really like their DI Containers. Perhaps they're just afraid of the alternative, because it's called Poor Man's DI. @@ -39,7 +39,7 @@ P.S. 2018-04-15. Naming is hard. When I came up with the alternative name of Pure DI, I was already in the process of changing my focus to functional programming, but at that time, I'd still not realised how big a role referential transparency plays in strictly functional languages like Haskell, with its emphasis on pure functions.

    - The purity implied by Pure DI, unfortunately, has nothing to do with purity in the functional sense of the word. In fact, DI makes everything impure. + The purity implied by Pure DI, unfortunately, has nothing to do with purity in the functional sense of the word. In fact, DI makes everything impure.

    When I decided on the term Pure DI, I did it because it sounds vaguely like Poor Man's DI, so that it'd be easy to remember. Additionally, I picked the word pure because it can mean essence, and I thought that, in a sense, Pure DI can be viewed as the Platonic ideal of DI. Finally, pure sounds like something desirable, so because of those reasons, I believed that it'd be a good term. People seem to have picked it up, so in that sense I think that I chose the right word, but it can be confusing if viewed through the lens of functional programming terminology. diff --git a/_posts/2014-06-12-web-api-raygun-error-handler.html b/_posts/2014-06-12-web-api-raygun-error-handler.html index 2c8a5f169..f92d1e20e 100644 --- a/_posts/2014-06-12-web-api-raygun-error-handler.html +++ b/_posts/2014-06-12-web-api-raygun-error-handler.html @@ -28,7 +28,7 @@             fun () -> raygunClient.Send actionExecutedContext.Exception) }

    - This creates an Adapter from the ASP.NET Web API IExceptionFilter interface to a RaygunClient instance. As you can see, I use CloudConfigurationManager.GetSetting to get the Raygun API key from the configuration store. + This creates an Adapter from the ASP.NET Web API IExceptionFilter interface to a RaygunClient instance. As you can see, I use CloudConfigurationManager.GetSetting to get the Raygun API key from the configuration store.

    The only remaining step is to add the error handler to an HttpConfiguration instance: diff --git a/_posts/2014-06-13-passive-attributes.html b/_posts/2014-06-13-passive-attributes.html index 6a7d11db4..205cf3a4f 100644 --- a/_posts/2014-06-13-passive-attributes.html +++ b/_posts/2014-06-13-passive-attributes.html @@ -12,16 +12,16 @@ {{ page.description }}

    - In my article about Dependency Injection-friendly frameworks, towards the end I touched on the importance of defining attributes without behaviour, but I didn't provide a constructive example of how to do this. In this article, I'll outline how to write a Dependency Injection-friendly attribute for use with ASP.NET Web API, but as far as I recall, you can do something similar with ASP.NET MVC. + In my article about Dependency Injection-friendly frameworks, towards the end I touched on the importance of defining attributes without behaviour, but I didn't provide a constructive example of how to do this. In this article, I'll outline how to write a Dependency Injection-friendly attribute for use with ASP.NET Web API, but as far as I recall, you can do something similar with ASP.NET MVC.

    Problem statement #

    - In ASP.NET Web API, you can adorn your Controllers and their methods with various Filter attributes, which is a way to implement cross-cutting concerns, such as authorization or error handling. The problem with this approach is that attribute instances are created by the run-time, so you can't use proper Dependency Injection (DI) patterns such as Constructor Injection. If an attribute defines behaviour (which many of the Web API attributes do), the most common attempt at writing loosely coupled code is to resort to a static Service Locator (an anti-pattern). + In ASP.NET Web API, you can adorn your Controllers and their methods with various Filter attributes, which is a way to implement cross-cutting concerns, such as authorization or error handling. The problem with this approach is that attribute instances are created by the run-time, so you can't use proper Dependency Injection (DI) patterns such as Constructor Injection. If an attribute defines behaviour (which many of the Web API attributes do), the most common attempt at writing loosely coupled code is to resort to a static Service Locator (an anti-pattern).

    - This again seems to lead framework designers towards attempting to make their frameworks 'DI-friendly' by introducing a Conforming Container (another anti-pattern). + This again seems to lead framework designers towards attempting to make their frameworks 'DI-friendly' by introducing a Conforming Container (another anti-pattern).

    The solution is simple: define attributes without behaviour. @@ -121,7 +121,7 @@

  • After the continuation has completed, the MeteringFilter again records the current time and calculates the duration.
  • Finally, it publishes a MeterRecord to an injected dependency.
  • - Notice that MeteringFilter uses normal Constructor Injection, which means that it can protect its invariants. In this example, I'm using IObserver<T> as a dependency, but obviously, you could use any dependency you'd like. + Notice that MeteringFilter uses normal Constructor Injection, which means that it can protect its invariants. In this example, I'm using IObserver<T> as a dependency, but obviously, you could use any dependency you'd like.

    Configuring the service # @@ -134,10 +134,10 @@

    config.Filters.Add(filter);

    - where observer is your preferred implementation of IObserver<MeterRecord>. This example illustrates the Pure DI approach, but if you rather prefer to resolve MeteringFilter with your DI Container of choice, you can obviously do this as well. + where observer is your preferred implementation of IObserver<MeterRecord>. This example illustrates the Pure DI approach, but if you rather prefer to resolve MeteringFilter with your DI Container of choice, you can obviously do this as well.

    - The above code typically goes into your Global.asax file, or at least a class directly or indirectly invoked from Application_Start. This constitutes (part of) the Composition Root of your service. + The above code typically goes into your Global.asax file, or at least a class directly or indirectly invoked from Application_Start. This constitutes (part of) the Composition Root of your service.

    Summary # @@ -166,10 +166,10 @@

    2016-01-21 18:34 UTC

    - +

    - Jonathan, thank you for writing. Does this article on the Decoraptor pattern (and this Stack Overflow answer) answer your question? + Jonathan, thank you for writing. Does this article on the Decoraptor pattern (and this Stack Overflow answer) answer your question?

    2016-01-21 19:51 UTC
    @@ -193,7 +193,7 @@

    2016-08-21 17:20 UTC

    - +

    Valdis, thank you for writing. I haven't looked into the details of ASP.NET Core recently, but even so: on a more basic level, I don't understand the impulse to put behaviour into attributes. An attribute is an annotation. It's a declaration that a method, or type, is somehow special. Why not keep the annotation decoupled from the behaviour it 'triggers'? This would enable you to reuse the behaviour in other scenarios than by putting an attribute on a method. @@ -209,10 +209,10 @@

    2016-08-22 20:46 UTC

    - +

    - Indeed, one of the most problematic aspects of container-based DI (as opposed to Pure DI) is the loss of compile-time safety - to little advantage, I might add. + Indeed, one of the most problematic aspects of container-based DI (as opposed to Pure DI) is the loss of compile-time safety - to little advantage, I might add.

    2016-08-23 05:49 UTC
    @@ -227,7 +227,7 @@

    2016-11-16 23:10 UTC

    - +

    Tyree, thank you for writing. That's a valid concern, but I don't think it's isolated to passive attributes. The problem you outline is also present if you attempt to address cross-cutting concerns with the Decorator design pattern, or with dynamic interception as I describe in chapter 9 of my book. You also have this problem with the Composite pattern, because you can't have any compile-time guarantee that you've remembered to compose all required elements into the Composite, or that they're defined in the appropriate order (if that matters). @@ -239,7 +239,7 @@

    Even with attributes, how can you guarantee that the attributes stay there? What if another developer comes by and removes an attribute? The code is still going to compile.

    - Ultimately, code exists in order to implement some desired behaviour. There are guarantees you can get from the type system, but static typing can't provide all guarantees. If it could, you be in the situation where, 'if it compiles, it works'. No programming language I've heard of provides that guarantee, although there's a spectrum of languages with stronger or weaker type systems. Instead, we'll have to get feedback from multiple sources. Attributes often define cross-cutting concerns, and I find that these are often best verified with a set of integration tests. + Ultimately, code exists in order to implement some desired behaviour. There are guarantees you can get from the type system, but static typing can't provide all guarantees. If it could, you be in the situation where, 'if it compiles, it works'. No programming language I've heard of provides that guarantee, although there's a spectrum of languages with stronger or weaker type systems. Instead, we'll have to get feedback from multiple sources. Attributes often define cross-cutting concerns, and I find that these are often best verified with a set of integration tests.

    As always in software development, you have to find the balance that's right for a particular scenario. In some cases, it's catastrophic if something is incorrectly configured; in other cases, it's merely unfortunate. More rigorous verification is required in the first case. @@ -257,7 +257,7 @@

    2017-04-05 13:03 UTC

    - +

    Cristian, thank you for writing. The example code shown in this article only looks in the action context's ActionDescriptor, which is an object that describes the action method. If you want to look for the attribute on the class, you should look in the action context's ControllerDescriptor instead, like this: diff --git a/_posts/2014-07-22-hire-me.html b/_posts/2014-07-22-hire-me.html index 52d54ff0d..5fc851408 100644 --- a/_posts/2014-07-22-hire-me.html +++ b/_posts/2014-07-22-hire-me.html @@ -12,6 +12,6 @@ {{ page.description }}

    - Since I became self-employed in 2011, I've been as busy as always, but it looks like I have some time available in the next months. If you'd like to hire me for small or big tasks, please contact me. See here for details. + Since I became self-employed in 2011, I've been as busy as always, but it looks like I have some time available in the next months. If you'd like to hire me for small or big tasks, please contact me. See here for details.

    \ No newline at end of file diff --git a/_posts/2014-07-23-drain.html b/_posts/2014-07-23-drain.html index be6391a41..4f8b03d1a 100644 --- a/_posts/2014-07-23-drain.html +++ b/_posts/2014-07-23-drain.html @@ -32,7 +32,7 @@

    This problem should be familiar to every student of software development. Pure abstractions tend not to survive contact with reality (there are examples in both Object-Oriented, Functional, and Logical or Relational programming), but we should still strive towards keeping abstractions as pure as possible.

    - One proposed solution to the Query Problem is to use something like IQueryable, but unfortunately, IQueryable is an extremely poor abstraction (and so are F# query expressions, too). + One proposed solution to the Query Problem is to use something like IQueryable, but unfortunately, IQueryable is an extremely poor abstraction (and so are F# query expressions, too).

    In my experience, the most important feature of IQueryable is the ability to filter before loading data; normally, you can perform projections in memory, but when you read from persistent storage, you need to select your desired subset before loading it into memory. @@ -173,7 +173,7 @@

    However impure it is to introduce a third interface into the mix, I still prefer to introduce a single generic interface, instead of multiple custom interfaces, because once you and your co-workers understand the Drain abstraction, the cognitive load is still quite low. A Drain is an Iterator with a twist, so in the end, you'll have a system built on 2½ abstractions.

    - P.S. 2018-06-20. While this article is a decent attempt to generalise the query side of a fundamentally object-oriented approach to software architecture, I've later realised that dependency injection, even when disguised as partial application, isn't functional. The problem is that querying a database, reading files, and so on, is essentially non-deterministic, even when no side effects are incurred. The functional approach is to altogether reject the notion of dependencies. + P.S. 2018-06-20. While this article is a decent attempt to generalise the query side of a fundamentally object-oriented approach to software architecture, I've later realised that dependency injection, even when disguised as partial application, isn't functional. The problem is that querying a database, reading files, and so on, is essentially non-deterministic, even when no side effects are incurred. The functional approach is to altogether reject the notion of dependencies.

    @@ -183,7 +183,7 @@

    -
    A diff-output from the A Functional Architecture with F# master branch, after applying the Drain abstraction, is available here. Notice how Drain cuts the maintenance of multiple homogenous abstractions, and makes the code cleaner and easier to reason about.
    +
    A diff-output from the A Functional Architecture with F# master branch, after applying the Drain abstraction, is available here. Notice how Drain cuts the maintenance of multiple homogenous abstractions, and makes the code cleaner and easier to reason about.
    2014-07-28 09:00 UTC
    \ No newline at end of file diff --git a/_posts/2014-08-06-encapsulation-and-solid-pluralsight-course.html b/_posts/2014-08-06-encapsulation-and-solid-pluralsight-course.html index 42fde7829..6956e1279 100644 --- a/_posts/2014-08-06-encapsulation-and-solid-pluralsight-course.html +++ b/_posts/2014-08-06-encapsulation-and-solid-pluralsight-course.html @@ -35,7 +35,7 @@

    Is OOD still relevant? #

    - Functional Programming is becoming increasingly popular, and regular readers of this blog will have noticed that I, myself, write a fair amount of F# code. In light of this, is OOD still relevant? + Functional Programming is becoming increasingly popular, and regular readers of this blog will have noticed that I, myself, write a fair amount of F# code. In light of this, is OOD still relevant?

    There's a lot of Object-Oriented code out there, or at least, code written in a nominally Object-Oriented language, and it's not going to go away any time soon. Getting better at maintaining and evolving Object-Oriented code is, in my opinion, still important. @@ -55,7 +55,7 @@

    2014-08-06 06:55 UTC

    - +

    Dan, thank you for writing. You are talking about this implementation, I assume: @@ -110,7 +110,7 @@

    2014-08-13 16:43 UTC

    - +

    Bart, no, you aren't missing anything; that looks about right :) The other alternative is just a variation on your solution. diff --git a/_posts/2014-08-07-why-dry.html b/_posts/2014-08-07-why-dry.html index 16d5dd1c6..801d6baaf 100644 --- a/_posts/2014-08-07-why-dry.html +++ b/_posts/2014-08-07-why-dry.html @@ -122,7 +122,7 @@

    2014-08-20 22:03 UTC

    - +

    Markus, thank you for writing. Yes, I agree that experience is always helpful. diff --git a/_posts/2014-08-11-cqs-versus-server-generated-ids.html b/_posts/2014-08-11-cqs-versus-server-generated-ids.html index abfdaea8a..8bd53df7d 100644 --- a/_posts/2014-08-11-cqs-versus-server-generated-ids.html +++ b/_posts/2014-08-11-cqs-versus-server-generated-ids.html @@ -193,7 +193,7 @@

    2014-08-14 00:18 UTC

    - +

    Tony, thank you for writing. What you suggest is one way to model it. Essentially, if a client starts with: @@ -233,13 +233,13 @@

    Notice that this immediately creates the resource, as well as returns a representation of it in the response (consider the JSON in the example a placeholder). This should be easier on the poor UI Developers :)

    - In any case, this discussion is entirely orthogonal to CQS, because at the boundaries, applications aren't Object-Oriented - thus, CQS doesn't apply to REST API design. Both POST, PUT, and DELETE verbs imply the intention to modify a resource's state, yet the HTTP specification describes how such requests should return proper responses. These verbs violate CQS because they both involve state mutation and returning a response. + In any case, this discussion is entirely orthogonal to CQS, because at the boundaries, applications aren't Object-Oriented - thus, CQS doesn't apply to REST API design. Both POST, PUT, and DELETE verbs imply the intention to modify a resource's state, yet the HTTP specification describes how such requests should return proper responses. These verbs violate CQS because they both involve state mutation and returning a response.

    2014-08-15 17:57 UTC
    - +

    Steve, thank you for writing. Yes, raising an event from a Command is definitely valid, since a Command is all about side-effects, and an event is also a side effect. The corollary of this is that you can't raise events from Queries if you want to adhere to CQS. In my Pluralsight course on encapsulation, I briefly touch on this subject in the Encapsulation module (module 2), in the clip called Queries, at 1:52. @@ -267,7 +267,7 @@

    2014-08-25 7:55 UTC

    - +

    Kenny, thank you for writing. FWIW, I wouldn't have designed a Repository like I show in the beginning of the article either, but I've seen lots of Repositories designed like that. @@ -326,7 +326,7 @@

    2014-08-26 22:30 UTC

    - +

    Kenny, thank you for writing. Yes, you could model it like that Entity<T> class, although there are various different concerns mixed here. Whether or not you want to override Equals and GetHashCode is independent of the discussion about protecting invariants. This may already be clear to you, but I just wanted to get that out of the way. @@ -344,7 +344,7 @@

    Obviously, this makes the simplification that the ID is a GUID, which makes it easy to create a 'temporary' instance if you need to do that. You'll also note that it protects its invariants by guarding against the empty GUID.

    - (Although not particularly relevant for this discussion, you'll also notice that I made this a concrete class. In general, I favour composition over inheritance, and I see no reason to introduce an abstract base class only in order to take and expose an ID - such code is unlikely to change much. There's no behaviour here because I also don't override Equals or GetHashCode, because I've come to realise that doing so with the implementation you suggest is counter-productive... but that, again, is another discussion.) + (Although not particularly relevant for this discussion, you'll also notice that I made this a concrete class. In general, I favour composition over inheritance, and I see no reason to introduce an abstract base class only in order to take and expose an ID - such code is unlikely to change much. There's no behaviour here because I also don't override Equals or GetHashCode, because I've come to realise that doing so with the implementation you suggest is counter-productive... but that, again, is another discussion.)

    Then what if you can't use a GUID. Well, you could still resort to the solution that I outline above, and still use a GUID, and then have another Query that can give you an integer that corresponds to the GUID. @@ -380,7 +380,7 @@

    - +

    Irfan, thank you for writing. To the degree you choose to use GUIDs as described in this article, it's in order to obey the CQS principle. Thus, it's entirely a concern of the client(s). How you relate tables inside of a relational database is an implementation detail. @@ -410,13 +410,13 @@

    - +

    Ben, thank you for writing. To be clear, the Repository pattern is one of the most misunderstood and misrepresented design patterns that I can think of. It was originally described in Martin Fowler's book Patterns of Enterprise Application Architecture, but if you look up the pattern description there, it has nothing to do with how people normally use it. It's a prime example of design patterns being ambiguous and open not only to interpretation, but to semantic shift.

    - Regardless of the interpretation, I don't use the Repository design pattern. Following the Dependency Inversion Principle, "clients […] own the abstract interfaces" (APPP, chapter 11), so if I need to, say, read some data from a database, I define a data reader interface in the client library. Following other SOLID principles as well, I'd typically end up with most interfaces having only a single member. These days, though, if I do Dependency Injection at all, I mostly use partial application of higher-order functions. + Regardless of the interpretation, I don't use the Repository design pattern. Following the Dependency Inversion Principle, "clients […] own the abstract interfaces" (APPP, chapter 11), so if I need to, say, read some data from a database, I define a data reader interface in the client library. Following other SOLID principles as well, I'd typically end up with most interfaces having only a single member. These days, though, if I do Dependency Injection at all, I mostly use partial application of higher-order functions.

    2018-06-06 6:32 UTC
    diff --git a/_posts/2014-08-24-decoraptor.html b/_posts/2014-08-24-decoraptor.html index 2ef1b2964..46daa8e8c 100644 --- a/_posts/2014-08-24-decoraptor.html +++ b/_posts/2014-08-24-decoraptor.html @@ -26,7 +26,7 @@ Decoraptor

    - Sometimes, when a Client wishes to talk to a Service (Component in the figure; in practice often an interface), the Client may have a long lifetime, whereas, because of technical constraints in the implementation, the Service must only have a short lifetime. If not addressed, this may lead to a Captive Dependency: the long-lived Client holds onto the Service for too long. + Sometimes, when a Client wishes to talk to a Service (Component in the figure; in practice often an interface), the Client may have a long lifetime, whereas, because of technical constraints in the implementation, the Service must only have a short lifetime. If not addressed, this may lead to a Captive Dependency: the long-lived Client holds onto the Service for too long.

    One solution to this is a Decoraptor - a combination of a Decorator and an Adapter. A Decoraptor is a long-lived object that adapts an Abstract Factory, and uses the factory to create a short-lived instance of the interface that it, itself, implements. @@ -88,7 +88,7 @@

    Motivating example #

    - When using Passive Attributes with ASP.NET Web API, the Filter containing all the behaviour must be added to the overall collection of Filters: + When using Passive Attributes with ASP.NET Web API, the Filter containing all the behaviour must be added to the overall collection of Filters:

    var filter = new MeteringFilter(observer);
    @@ -98,7 +98,7 @@ 

    Due to the way ASP.NET Web API works, this configuration happens during Application_Start, so there's only going to be a single instance of MeteringFilter around. In other work, the MeteringFilter is a long-lived Client; it effectively has Singleton lifetime scope.

    - MeteringFilter depends on IObserver<MeterRecord> (See the article about Passive Attributes for the full code of MeteringFilter). The observer injected into the MeteringFilter object will have the same lifetime as the MeteringFilter object. The Filter will be used from concurrent threads, and while MeteringFilter itself is thread-safe (it has immutable state), the injected observer may not be. + MeteringFilter depends on IObserver<MeterRecord> (See the article about Passive Attributes for the full code of MeteringFilter). The observer injected into the MeteringFilter object will have the same lifetime as the MeteringFilter object. The Filter will be used from concurrent threads, and while MeteringFilter itself is thread-safe (it has immutable state), the injected observer may not be.

    To be more concrete, this question was recently posted on Stack Overflow: @@ -150,7 +150,7 @@

    In this case, the Abstract Factory is a generic interface, but it could also be a non-generic interface that only creates instances of IObserver<MeterRecord>. Some people prefer delegates instead, so would use e.g. Func<IObserver<MeterRecord>>. You could also define an Abstract Base Class instead of an interface, if that's more to your liking.

    - This particular example also disregards decommissioning concerns. Effectively, the Abstract Factory will create instances of SqlMeter, but since these instances simply go out of scope, the contained MeteringContext isn't being disposed of in a deterministic manner. In a future article, I will remedy this situation. + This particular example also disregards decommissioning concerns. Effectively, the Abstract Factory will create instances of SqlMeter, but since these instances simply go out of scope, the contained MeteringContext isn't being disposed of in a deterministic manner. In a future article, I will remedy this situation.

    Example: generic Decoraptor for Observers # @@ -223,6 +223,6 @@

  • Dependency Injection - new instance required in several of a classes methods
  • IOC DI Multi-Threaded Lifecycle Scoping in Background Tasks
  • - In addition, I've also previously touched upon the subject in relation to using a Virtual Proxy for lazy dependencies. + In addition, I've also previously touched upon the subject in relation to using a Virtual Proxy for lazy dependencies.

    \ No newline at end of file diff --git a/_posts/2014-08-25-decommissioning-decoraptors.html b/_posts/2014-08-25-decommissioning-decoraptors.html index 179e50787..918a483ec 100644 --- a/_posts/2014-08-25-decommissioning-decoraptors.html +++ b/_posts/2014-08-25-decommissioning-decoraptors.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my article about the Decoraptor design pattern, I deliberately ignored the question of decommissioning: what if the short-lived object created inside of the Decoraptor contains one or more disposable objects? + In my article about the Decoraptor design pattern, I deliberately ignored the question of decommissioning: what if the short-lived object created inside of the Decoraptor contains one or more disposable objects?

    A Decoraptor creates instances of object graphs, and such object graphs may contain disposable objects. These disposable objects may be deeply buried inside of the object graph, and the root object itself may not implement IDisposable. @@ -29,13 +29,13 @@ }

    - This is similar to advice I've already given in conjunction with designing DI-Friendly frameworks. + This is similar to advice I've already given in conjunction with designing DI-Friendly frameworks.

    Example: refactored Decoraptor #

    - With the new version of the IFactory<T> interface, you can refactor the Observeraptor class from the Decoraptor article: + With the new version of the IFactory<T> interface, you can refactor the Observeraptor class from the Decoraptor article:

    public class Observeraptor<T> : IObserver<T>
    @@ -161,7 +161,7 @@ 

    Yes, indeed, it should, and the only reason I didn't do that was for the sake of the example. If SqlMeter had implemented IDisposable, you'd be tempted to implement SqlMeterFactory.Release by simply attempting to downcast the incoming item from IObserver<MeterRecord> to IDisposable, and then, if the cast succeeds, invoke its Dispose method.

    - However, the only reason we know that SqlMeter ought to implement IDisposable is because it has a concrete dependency. Concrete types can implement IDisposable, but interfaces should not, since IDisposable is an implementation detail. (I do realize that some interfaces defined by the .NET Base Class Library derives from IDisposable, but I consider those Leaky Abstractions. As Nicholas Blumhardt put it: "an interface [...] generally shouldn't be disposable. There's no way for the one defining an interface to foresee all possible implementations of it - you can always come up with a disposable implementation of practically any interface.") + However, the only reason we know that SqlMeter ought to implement IDisposable is because it has a concrete dependency. Concrete types can implement IDisposable, but interfaces should not, since IDisposable is an implementation detail. (I do realize that some interfaces defined by the .NET Base Class Library derives from IDisposable, but I consider those Leaky Abstractions. As Nicholas Blumhardt put it: "an interface [...] generally shouldn't be disposable. There's no way for the one defining an interface to foresee all possible implementations of it - you can always come up with a disposable implementation of practically any interface.")

    The point of this discussion is that as soon as a class has an abstract dependency (as opposed to a concrete dependency), the class may or may not be relying on something that is disposable. That's not enough to warrant the class itself to implement the IDisposable interface. For this reason, when an Abstract Factory creates an object graph, the root object of that graph should rarely implement IDisposable, and that's the reason it's not enough to attempt a downcast. @@ -176,6 +176,6 @@

    Throwing IDisposable into the mix always makes things much more complicated, so if you can, try to implement your classes in such a way that they aren't disposable. This is often possible, but if you can't avoid it, you must add a Release method to your Abstract Factory and handle the additional complexity of decommissioning object graphs.

    - Some (but not all!) DI Containers already do this, so that may be one reason to use a DI Container. + Some (but not all!) DI Containers already do this, so that may be one reason to use a DI Container.

    \ No newline at end of file diff --git a/_posts/2014-09-25-faking-a-continuously-polling-consumer-with-scheduled-tasks.html b/_posts/2014-09-25-faking-a-continuously-polling-consumer-with-scheduled-tasks.html index 52614e6c0..9f595cd59 100644 --- a/_posts/2014-09-25-faking-a-continuously-polling-consumer-with-scheduled-tasks.html +++ b/_posts/2014-09-25-faking-a-continuously-polling-consumer-with-scheduled-tasks.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In a previous article, I described how you set up Azure Web Jobs to run only a single instance of a background process. However, the shortest time interval you can currently configure is to run a scheduled task every minute. If you want to use this trick to set up a Polling Consumer, it may seem limiting that you'll have to wait up to a minute before the scheduled task can pull new messages off the queue. + In a previous article, I described how you set up Azure Web Jobs to run only a single instance of a background process. However, the shortest time interval you can currently configure is to run a scheduled task every minute. If you want to use this trick to set up a Polling Consumer, it may seem limiting that you'll have to wait up to a minute before the scheduled task can pull new messages off the queue.

    The problem # @@ -139,7 +139,7 @@

    If you have a situation where you need to run a scheduled job (as opposed to a continuously running service or daemon), but you want it to behave like it was a continuously running service, you can make it wait until just before a new scheduled job is about to start, and then exit. This is an approach you can use anywhere you find yourself in that situation - not only on Azure.

    - Update 2015 August 11: See my article about Type Driven Development for an example of how to approach this problem in a well-designed, systematic, iterative fashion. + Update 2015 August 11: See my article about Type Driven Development for an example of how to approach this problem in a well-designed, systematic, iterative fashion.

    @@ -158,7 +158,7 @@

    Comments

    FWIW, this - talk and this + talk and this post seem to be related with the technique shown in this article.

    OTOH, in the context of Windows Services, or similar, it's possible to diff --git a/_posts/2014-10-09-unit-testing-methods-with-the-same-implemenation.html b/_posts/2014-10-09-unit-testing-methods-with-the-same-implemenation.html index 0aa733416..5d12e7570 100644 --- a/_posts/2014-10-09-unit-testing-methods-with-the-same-implemenation.html +++ b/_posts/2014-10-09-unit-testing-methods-with-the-same-implemenation.html @@ -18,7 +18,7 @@ The obvious answer is to copy and paste all the tests, but that leads to test duplication. People with a superficial knowledge of DAMP (Descriptive And Meaningful Phrases) would argue that test duplication isn't a problem, but it is, simply because it's more code that you need to maintain.

    - Another approach may be to simply ignore one of those methods, effectively not testing it, but if you're writing Wildlife Software, you have to have mechanisms in place that can protect you from introducing breaking changes. + Another approach may be to simply ignore one of those methods, effectively not testing it, but if you're writing Wildlife Software, you have to have mechanisms in place that can protect you from introducing breaking changes.

    This article outlines one approach you can use if your unit testing framework supports Parameterized Tests. @@ -170,7 +170,7 @@

    Comments

    2014-10-29 14:34 UTC
    - +

    Ricardo, thank you for writing. xUnit.net's equivalent to [TestCaseSource] is to combine the [Theory] attribute with one of the built-in [PropertyData], [ClassData], etc. attributes. However, in this particular case, there's a couple of reasons that I didn't find those attractive: diff --git a/_posts/2014-12-16-name-this-operation.html b/_posts/2014-12-16-name-this-operation.html index b42727972..778d114ae 100644 --- a/_posts/2014-12-16-name-this-operation.html +++ b/_posts/2014-12-16-name-this-operation.html @@ -108,7 +108,7 @@

    Comments

    2015-01-01 10:47 UTC
    - +

    Kenny, thank you for your suggestions. Others have pointed out the similarities with accumulation, so that looks like the most popular candidate. Junction and Consolidation are new to me, but I've added both to my list. @@ -129,7 +129,7 @@

    Comments

    2015-01-02 15:14 UTC
    - +

    It was never my intention to imply that I necessarily considered Accumulation the best option, but it has been mentioned independently multiple times. diff --git a/_posts/2014-12-17-good-times-with-f.html b/_posts/2014-12-17-good-times-with-f.html index 7a875bc5e..07b14cdfc 100644 --- a/_posts/2014-12-17-good-times-with-f.html +++ b/_posts/2014-12-17-good-times-with-f.html @@ -178,6 +178,6 @@

    This post is number 17 in the 2014 F# Advent Calendar.

    - Update 2017-05-25: A more recent treatment, including a more realistic usage scenario, is available in the article Type Driven Development. + Update 2017-05-25: A more recent treatment, including a more realistic usage scenario, is available in the article Type Driven Development.

    \ No newline at end of file diff --git a/_posts/2014-12-23-exception-messages-are-for-programmers.html b/_posts/2014-12-23-exception-messages-are-for-programmers.html index c7211231a..4091ce32c 100644 --- a/_posts/2014-12-23-exception-messages-are-for-programmers.html +++ b/_posts/2014-12-23-exception-messages-are-for-programmers.html @@ -199,13 +199,13 @@

    2015-01-08 04:02 UTC

    - +

    Mogens, thank you for writing. I know that you have a passion for well-written exception messages; in fact, you are one of the many people who inspired me to make exception messages more and more helpful.

    - How do I deal with 'deep' exceptions? First of all, I try hard to avoid them in the first place. One of the ways to do that is to validate input as close to the application boundary as possible, and transform it into something that properly protects its invariants; I recently wrote an article with a simple example of doing that (you may also want to read the comments, which contain a few gems). + How do I deal with 'deep' exceptions? First of all, I try hard to avoid them in the first place. One of the ways to do that is to validate input as close to the application boundary as possible, and transform it into something that properly protects its invariants; I recently wrote an article with a simple example of doing that (you may also want to read the comments, which contain a few gems).

    Even if you can eliminate many 'deep' exceptions, you can't get rid of all of them. Particularly if you integrate with legacy systems, it can be difficult to validate everything up front, because the 'rules' of the legacy system may not be clear or public. In such cases, I prefer to throw custom exceptions. In each place where I need to throw an exception, I create a new Exception class and throw that. This means that any client can catch that particular exception type, and convert it to a friendly user message. If you need to provide additional information to the user, the custom Exception class can have extra properties with the required information. diff --git a/_posts/2014-12-24-placement-of-abstract-factories.html b/_posts/2014-12-24-placement-of-abstract-factories.html index 0fff41499..92d9ff5e4 100644 --- a/_posts/2014-12-24-placement-of-abstract-factories.html +++ b/_posts/2014-12-24-placement-of-abstract-factories.html @@ -14,7 +14,7 @@ {{ page.description }}

    - An Abstract Factory is one of the workhorses of Dependency Injection, although it's a somewhat blunt instrument. As I've described in chapter 6 of my book, whenever you need to map a run-time value to an abstraction, you can use an Abstract Factory. However, often there are more sophisticated options available. + An Abstract Factory is one of the workhorses of Dependency Injection, although it's a somewhat blunt instrument. As I've described in chapter 6 of my book, whenever you need to map a run-time value to an abstraction, you can use an Abstract Factory. However, often there are more sophisticated options available.

    Still, it can be a useful pattern, but you have to understand where to define it, and where to implement it. One of my readers ask: @@ -23,7 +23,7 @@ "how would deal with abstract factories if a module needs to be reused across multiple hosts/agg roots?Should each root have its fact?

    - "this link http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/ talks about having the container injected only if the factory belongs in the same composition root" + "this link /2012/03/15/ImplementinganAbstractFactory/ talks about having the container injected only if the factory belongs in the same composition root"

    These are good question that deserve a more thorough treatment than a tweet in reply. @@ -44,7 +44,7 @@

    Defining the Abstract Factory #

    - Where should an Abstract Factory be defined? In order to answer this question, first you must understand what an Abstract Factory is. Essentially, it's an interface (or Abstract Base Class - it's not important) that looks like this: + Where should an Abstract Factory be defined? In order to answer this question, first you must understand what an Abstract Factory is. Essentially, it's an interface (or Abstract Base Class - it's not important) that looks like this:

    public interface IFactory<T>
    @@ -80,7 +80,7 @@ 

    It could, but what would be the purpose? The library itself doesn't need the interface, because the Foo class has a nice constructor it can use.

    - Often, the Abstract Factory pattern is most useful if you have some of the values available at composition time, but can't fully compose the object because you're waiting for one of the values to materialize at run-time. If you think this sounds abstract, my article series on Role Hints contains some realistic examples - particularly the articles Metadata Role Hint, Role Interface Role Hint, and Partial Type Name Role Hint. + Often, the Abstract Factory pattern is most useful if you have some of the values available at composition time, but can't fully compose the object because you're waiting for one of the values to materialize at run-time. If you think this sounds abstract, my article series on Role Hints contains some realistic examples - particularly the articles Metadata Role Hint, Role Interface Role Hint, and Partial Type Name Role Hint.

    A client may, for example, wait for the bar value before it can fully compose an instance of Foo. Thus, the client can define an interface like this: @@ -116,10 +116,10 @@

    Implementing the Abstract Factory #

    - While I've previously described how to implement an Abstract Factory, I may then have given short shrift to the topic of where to put the implementation. + While I've previously described how to implement an Abstract Factory, I may then have given short shrift to the topic of where to put the implementation.

    - Perhaps a bit surprising, this (at least partially) depends on the return type of the Abstract Factory's Create method. In the case of both IFooFactory definitions above, the return type of the Create methods is the concrete Foo class, defined in the shared library. This means that both Client 1 and Client 2 already depends on the shared library. In such situations, they can each implement their Abstract Factories as Manually Coded Factories. They don't have to do this, but at least it's an option. + Perhaps a bit surprising, this (at least partially) depends on the return type of the Abstract Factory's Create method. In the case of both IFooFactory definitions above, the return type of the Create methods is the concrete Foo class, defined in the shared library. This means that both Client 1 and Client 2 already depends on the shared library. In such situations, they can each implement their Abstract Factories as Manually Coded Factories. They don't have to do this, but at least it's an option.

    On the other hand, if the return type of an Abstract Factory is another interface defined by the client itself, it's a different story. Imagine, as an alternative scenario, that a client depends on an IPloeh interface that it has defined by itself. It may also define an Abstract Factory like this: @@ -134,16 +134,16 @@

    This has nothing to do with the library that defines the Foo class. However, another library, somewhere else, may implement an Adapter of IPloeh over Foo. If this is the case, that implementing third party could also implement IPloehFactory. In such cases, the library that defines IPloeh and IPloehFactory must not implement either interface, because that creates the coupling it works so hard to avoid.

    - The third party that ultimately implements these interfaces is often the Composition Root. If this is the case, other implementation options are Container-based Factories or Dynamic Proxies. + The third party that ultimately implements these interfaces is often the Composition Root. If this is the case, other implementation options are Container-based Factories or Dynamic Proxies.

    Summary #

    - In order to answer the initial question: my default approach would be to implement the Abstract Factory multiple times, favouring decoupling over DRY. These days I prefer Pure DI, so I'd tend to go with the Manually Coded Factory. + In order to answer the initial question: my default approach would be to implement the Abstract Factory multiple times, favouring decoupling over DRY. These days I prefer Pure DI, so I'd tend to go with the Manually Coded Factory.

    - Still, this answer of mine presupposes that Abstract Factory is the correct answer to a design problem. Often, it's not. It can lead to horrible interfaces like IFooManagerFactoryStrategyFactoryFactory, so I consider Abstract Factory as a last resort. Often, the Metadata, Role Interface, or Partial Type Name Role Hints are better options. In the degenerate case where there's no argument to the Abstract Factory's Create method, a Decoraptor is worth considering. + Still, this answer of mine presupposes that Abstract Factory is the correct answer to a design problem. Often, it's not. It can lead to horrible interfaces like IFooManagerFactoryStrategyFactoryFactory, so I consider Abstract Factory as a last resort. Often, the Metadata, Role Interface, or Partial Type Name Role Hints are better options. In the degenerate case where there's no argument to the Abstract Factory's Create method, a Decoraptor is worth considering.

    This article explains the matter in terms of relatively simple dependency graphs. In general, dependency graphs should be shallow, but if you want to learn about principles for composing more complex dependency graphs, Agile Principles, Patterns, and Practices contains a chapter on Principles of Package and Component Design (chapter 28) that I recommend. diff --git a/_posts/2015-01-06-composition-root-reuse.html b/_posts/2015-01-06-composition-root-reuse.html index 91485d2ab..ceb9c8be2 100644 --- a/_posts/2015-01-06-composition-root-reuse.html +++ b/_posts/2015-01-06-composition-root-reuse.html @@ -12,7 +12,7 @@ {{ page.description }}

    - At regular intervals, I get questions about how to reuse Composition Roots. The short answer is: you don't. + At regular intervals, I get questions about how to reuse Composition Roots. The short answer is: you don't.

    Since it appears to be a Frequently Asked Question, it seems that a more detailed answer is warranted. @@ -63,7 +63,7 @@

    The ReservationsContext class derives from DbContext; an instance of it is injected into a SqlReservationRepository object. From this, it's clear that this application uses SQL Server for it data persistence. This decision is hard-coded into the Composition Root. You can't change this unless you recompile the Composition Root.

    - At another boundary of this hexagonal/onion/whatever architecture is a ReservationsController, which derives from ApiController. From this, it's clear that this application is a REST API that uses ASP.NET Web API for its implementation. This decision, too, is hard-coded into the Composition Root. + At another boundary of this hexagonal/onion/whatever architecture is a ReservationsController, which derives from ApiController. From this, it's clear that this application is a REST API that uses ASP.NET Web API for its implementation. This decision, too, is hard-coded into the Composition Root.

    From this, it should be clear that the Composition Root is what defines the application. It combines all the loosely coupled components into an application: software that can be executed in an OS process. @@ -75,10 +75,10 @@

    Container-based Composition Roots #

    - The above example uses Pure DI in order to explain how a Composition Root is equivalent to an application definition. What about DI Container-based Composition Roots, then? + The above example uses Pure DI in order to explain how a Composition Root is equivalent to an application definition. What about DI Container-based Composition Roots, then?

    - It's essentially the same story, but with a twist. Imagine that you want to use Castle Windsor to compose your Web API; I've already previously explained how to do that, but here's the IHttpControllerActivator implementation repeated: + It's essentially the same story, but with a twist. Imagine that you want to use Castle Windsor to compose your Web API; I've already previously explained how to do that, but here's the IHttpControllerActivator implementation repeated:

    public class WindsorCompositionRoot : IHttpControllerActivator
    @@ -140,7 +140,7 @@ 

    What about the DRY principle, then?

    - Different applications have differing Composition Roots. Even if they start with substantial amounts of duplicated Composition Root code, in my experience, the 'common' code tends to diverge the more the applications are allowed to evolve. That duplication may be accidental, and attempting to eliminate it may increase coupling. It's better to understand why you want to avoid duplication in the first place. + Different applications have differing Composition Roots. Even if they start with substantial amounts of duplicated Composition Root code, in my experience, the 'common' code tends to diverge the more the applications are allowed to evolve. That duplication may be accidental, and attempting to eliminate it may increase coupling. It's better to understand why you want to avoid duplication in the first place.

    When it comes to Composition Roots, duplication tends to be accidental. Composition Roots aren't reusable. @@ -160,10 +160,10 @@

    Comments

    2015-01-06 13:06 UTC
    - +

    - Kenneth, thank you for writing. If you create a Facade that internally wires up a Domain Model and DAL, you've created a tightly coupled bundle. What if you later discover that you need to instrument your DAL? You can't do that if you prematurely compose object graphs. + Kenneth, thank you for writing. If you create a Facade that internally wires up a Domain Model and DAL, you've created a tightly coupled bundle. What if you later discover that you need to instrument your DAL? You can't do that if you prematurely compose object graphs.

    Clearly, there are disadvantages to doing such a thing. What are the advantages? @@ -177,7 +177,7 @@

    Comments

    Dear Mark,

    Thank you for another excellent post.

    Some of the composition roots I wrote became really large, too, especially the more complex the application got. In these cases I often introduced factories and builders that created parts of the final object graph and the imperative statements in the composition root just wired these subgraphs together. And this leads me to my actual question:

    -

    What do you think about pushing these factories and builders to a library so that they can be reused by different composition roots? This would result in much less code that wires the object graph. I know that abstract factories belong to the client, but one could provide Simple Factories / Factory Methods or, even better I think, the Builder Pattern is predestined for these situations, because it provides default dependencies that can be exchanged before the Build method is called.

    +

    What do you think about pushing these factories and builders to a library so that they can be reused by different composition roots? This would result in much less code that wires the object graph. I know that abstract factories belong to the client, but one could provide Simple Factories / Factory Methods or, even better I think, the Builder Pattern is predestined for these situations, because it provides default dependencies that can be exchanged before the Build method is called.

    If I think about automated tests, I can see that the concept I just described is already in use: every test has an arrange phase which in my opinion is the composition root for the test. To share arrange code between tests, one can use e.g. builders or fixture objects (or of course AutoFixture ;-) ). This reduces the code needed for the arrange phase and improves readability.

    What is your opinion on pushing Simple Factories / Builders to a reusable library?

    With regards,
    Kenny

    @@ -193,13 +193,13 @@

    Comments

    2015-01-06 15:05 UTC
    - +

    - Kenny, Daniel, thank you for writing. In an attempt to answer your questions, I wrote a completely new blog post on the subject; I hope it answers some of your questions, although I suppose you aren't going to like the answer. + Kenny, Daniel, thank you for writing. In an attempt to answer your questions, I wrote a completely new blog post on the subject; I hope it answers some of your questions, although I suppose you aren't going to like the answer.

    - If you truly have a big Composition Root, it may be one of the cases where you should consider adopting a DI Container with a convention-based configuration. + If you truly have a big Composition Root, it may be one of the cases where you should consider adopting a DI Container with a convention-based configuration.

    Another option is to make your 'boundary library' (e.g. your UI, or your RESTful endpoints) a library in itself, and host that library in various contexts. The Composition Root resides in that boundary library, so various hosts can 'reuse' it, as they reuse the entire application. You can see an example of this in my Outside-In Test-Driven Development Pluralsight course. @@ -219,7 +219,7 @@

    Comments

    2015-02-01 20:30 UTC
    - +

    Daniel, if I understand you correctly, that's indeed the same technique that I demonstrate in my Outside-In Test-Driven Development Pluralsight course. Although it may only be me splitting hairs, I don't consider that as reusing the Composition Root as much as it's deploying the same application to two different hosts; one of the hosts just happens to be a test harnes :) diff --git a/_posts/2015-01-10-diamond-kata-with-fscheck.html b/_posts/2015-01-10-diamond-kata-with-fscheck.html index 85ac1f6e8..43d1f487d 100644 --- a/_posts/2015-01-10-diamond-kata-with-fscheck.html +++ b/_posts/2015-01-10-diamond-kata-with-fscheck.html @@ -218,7 +218,7 @@

        |> List.reduce (fun x y -> sprintf "%s%s%s" x System.Environment.NewLine y)

    - It duplicates the test code a bit, because it reuse the algorithm that generates the desired sequence of letters. However, I'm not too concerned about the occasional DRY violation. + It duplicates the test code a bit, because it reuse the algorithm that generates the desired sequence of letters. However, I'm not too concerned about the occasional DRY violation.

    For the input 'D', this implementation produces this output: diff --git a/_posts/2015-01-19-from-primitive-obsession-to-domain-modelling.html b/_posts/2015-01-19-from-primitive-obsession-to-domain-modelling.html index 72e7a2d1f..7fd0f3afe 100644 --- a/_posts/2015-01-19-from-primitive-obsession-to-domain-modelling.html +++ b/_posts/2015-01-19-from-primitive-obsession-to-domain-modelling.html @@ -25,7 +25,7 @@ }

    - There was a few things with this that struck me as a bit odd; most notably the use of IsNullOrWhiteSpace. When I review code, IsNullOrWhiteSpace is one of the many things I look for, because most people use it incorrectly. + There was a few things with this that struck me as a bit odd; most notably the use of IsNullOrWhiteSpace. When I review code, IsNullOrWhiteSpace is one of the many things I look for, because most people use it incorrectly.

    This made me ask the author of the code why he had chosen to use IsNullOrWhiteSpace, or, more specifically, what was wrong with a string with white space in it? @@ -52,7 +52,7 @@

    This is where many programmers would start to write extension methods for strings, but that's just putting lipstick on a pig. What if you forget to call the appropriate extension method? What if a new developer on the team doesn't know about the appropriate extension method to use?

    - The root problem here is Primitive Obsession. Just because you can represent a value as a string, it doesn't mean that you always should. + The root problem here is Primitive Obsession. Just because you can represent a value as a string, it doesn't mean that you always should.

    The string data type literally can represent any text. A user name (in the example domain above) can not be any text - we've already established that. @@ -145,7 +145,7 @@

    This code has the same complexity as the original example, but now it's much clearer what's going on. You don't have to wonder about what looks like arbitrary rules; they're all nicely encapsulated in the UserName class.

    - Furthermore, as soon as you've left the not Object-Oriented boundary of your system, you can express the rest of your code in terms of the Domain Model; in this case, the UserName class. Here's the IUserRepository interface's Find method: + Furthermore, as soon as you've left the not Object-Oriented boundary of your system, you can express the rest of your code in terms of the Domain Model; in this case, the UserName class. Here's the IUserRepository interface's Find method:

    User FindUser(UserName userName);
    @@ -232,7 +232,7 @@ 

    2015-01-20 08:16 UTC

    - +

    Johannes, thank you for writing. You are right, it's possible to take the idea further in the way you describe. Again, such techniques aren't even limited to OOP; for instance, Scott Wlaschin explains how to make illegal states unrepresentable in F#. @@ -323,7 +323,7 @@

    2015-01-20 22:00 UTC

    - +

    Mike, thank you for writing. A business rule doesn't have to be complex in order to be important. The point isn't only to encapsulate complex logic, but to make sure that (any) business logic is applied consistently. @@ -335,7 +335,7 @@

    2015-01-21 12:57 UTC

    - +

    Steven, thank you for writing. You exhibit traits of critical thinking, which is always good when dealing with business logic :) In the end, it all boils down to what exactly the business rule is. As you interpret the business rule, you rephrase it as "Do not allow pre/post white-space", but that's not the business rule I had in mind. @@ -368,7 +368,7 @@

    2015-01-23 17:27 UTC

    - +

    Jeff, I attempted to run your unit tests, and the only one that fails is, as expected, if you attempt to use the constructor with "jeff"; TryParse with "jeff" works. @@ -395,7 +395,7 @@

    2015-01-28 19:42 UTC

    - +

    Jeff, I think we fundamentally agree, and I do understand why you'd find it surprising that the constructor accepts "JEFF", but not "jeff". FWIW, I follow (a lot) of rules (of thumb) when I design APIs, and one of them is that the purpose of constructors is to initialise objects. A constructor may perform validation, but must not perform work in the sense of transforming the input or producing side-effects. In other words, constructors are used to initialise objects with valid values. @@ -455,7 +455,7 @@

    2015-03-18 14:41 UTC

    - +

    Alan, thank you for writing. You're right; I'd never considered this - most likely because I never use inheritance. Therefore, my default coping strategy would most likely be to make the class sealed by default, but otherwise, explicitly comparing GetType() return values would have to do. @@ -482,7 +482,7 @@

    2015-11-21 0:51 UTC

    - +

    Rahul, thank you for writing. As a general rule, at the boundary of an application, all input must be considered evil until proven otherwise. That means that if you try to pass unvalidated input values into constructors, you should expect exceptions to be thrown on a regular basis. Since exceptions are for exceptional cases, that's most likely not the best way to go forward. @@ -509,7 +509,7 @@

    2016-05-25 14:54 UTC

    - +

    Eugene, thank you for writing. That's probably a good rule, but I admit I hadn't thought about it. One option is to convert it to an explicit conversion instead. Another option is to forgo the conversion operators all together. The conversion ability isn't the important point in this article. @@ -561,7 +561,7 @@

    - +

    Moiz, thank you for writing. Is it the right design? As usual, It Depends™. Which problem are you trying to solve? What does the input look like? What should the result be of attempting to parse various examples? diff --git a/_posts/2015-01-21-library-bundle-facade.html b/_posts/2015-01-21-library-bundle-facade.html index 314206cd1..e2526d821 100644 --- a/_posts/2015-01-21-library-bundle-facade.html +++ b/_posts/2015-01-21-library-bundle-facade.html @@ -14,7 +14,7 @@ {{ page.description }}

    - My recent article on Composition Root reuse generated some comments: + My recent article on Composition Root reuse generated some comments:

    "What do you think about pushing these factories and builders to a library so that they can be reused by different composition roots?" @@ -26,7 +26,7 @@ These comments are from two different people, but they provide a decent summary of the concerns being voiced.

    - Is it a good idea to provide one or more Facades, for example in the form of Factories or Builders, for the libraries making up a Composition Root? More specifically, is it a good idea to provide a Factory or Builder that can compose a complete object graph spanning multiple libraries? + Is it a good idea to provide one or more Facades, for example in the form of Factories or Builders, for the libraries making up a Composition Root? More specifically, is it a good idea to provide a Factory or Builder that can compose a complete object graph spanning multiple libraries?

    In this article, I will attempt to answer that question for various cases of library bundles. To make the terminology a bit more streamlined, I'll refer to any Factory or Builder that composes object graphs as a Composer. @@ -35,7 +35,7 @@

    Single library #

    - In the case of a single library, I think I've already answered the question in the affirmative. There's nothing wrong with including a Facade in the form of a Factory or Builder in order to make that single library easier to use. + In the case of a single library, I think I've already answered the question in the affirmative. There's nothing wrong with including a Facade in the form of a Factory or Builder in order to make that single library easier to use.

    Two libraries # @@ -53,7 +53,7 @@

    Domain Model and Data Access Libraries dependency graph.

    - At least, if you follow the most common architectures for loosely couple code, the Domain Model is the 'client', so it gets to define the interfaces it needs. Thus, it follows that the Data Access Library, in order to implement those interfaces, must have a compile-time dependency on the Domain Model. That's what the arrow means. + At least, if you follow the most common architectures for loosely couple code, the Domain Model is the 'client', so it gets to define the interfaces it needs. Thus, it follows that the Data Access Library, in order to implement those interfaces, must have a compile-time dependency on the Domain Model. That's what the arrow means.

    From this diagram, it should be clear that you can't put a Factory or Builder in the Domain Model library. If the Composer should compose object graphs from both libraries, it would need to reference both of those libraries, and the Domain Model can't reference the Data Access Library, since that would result in a circular reference. @@ -124,7 +124,7 @@

    The point of this analysis is to arrive at the conclusion that no matter how you twist and turn, you'll have to add a completely new library with the only purpose of composing object graphs. Is it warranted?

    - If the only motivation for doing this is to avoid duplicated code, I would argue that this looks like over-engineering. In the questions quoted above, it sounds as if the Rule of Three isn't even satisfied. It's always important to question your motivations for avoiding duplication. In this case, I'd be wary of introducing so much extra complexity only in order to avoid writing the same lines of code twice - particularly when it's likely that the duplication is accidental. + If the only motivation for doing this is to avoid duplicated code, I would argue that this looks like over-engineering. In the questions quoted above, it sounds as if the Rule of Three isn't even satisfied. It's always important to question your motivations for avoiding duplication. In this case, I'd be wary of introducing so much extra complexity only in order to avoid writing the same lines of code twice - particularly when it's likely that the duplication is accidental.

    TL;DR # @@ -141,18 +141,18 @@

    Comments

    Dear Mark,

    Thanks again for another wonderful post. I'm one of the guys you mentioned at the beginning of this text and I totally agree with you on this subject.

    -

    Maybe I wasn't specific enough in my comment that I didn't mean to introduce factories and builders handling dependencies from two or more assemblies, but only from a single one. The composition root wires the independent subgraphs from the different assemblies together.

    +

    Maybe I wasn't specific enough in my comment that I didn't mean to introduce factories and builders handling dependencies from two or more assemblies, but only from a single one. The composition root wires the independent subgraphs from the different assemblies together.

    However, I want to reemphasize the Builder Pattern in this context: it provides default dependencies for the object graph to be created and (usually) a fluent API (i.e. some sort of method chaining) to exchange these dependencies. This has the following consequences for the client programmer using the builder(s): he or she can easily create a default object graph by calling new Builder().Build() and still exchange dependencies he or she cares about. This can keep the composition root clean (at least for Arrange phases of tests this is true).

    -

    Why I'm so excited about this? Because I use this all the time in my automated tests, but haven't really used it in my production composition roots (or seen it in others). After reading this post and Composition Root Reuse, I will try to incorporate builders more often in my production code.

    +

    Why I'm so excited about this? Because I use this all the time in my automated tests, but haven't really used it in my production composition roots (or seen it in others). After reading this post and Composition Root Reuse, I will try to incorporate builders more often in my production code.

    Mark - thank you for making me think about this.

    2015-01-21 21:20 UTC
    - +
    2015-01-22 07:40 UTC
    diff --git a/_posts/2015-02-23-a-simpler-arbitrary-for-the-diamond-kata.html b/_posts/2015-02-23-a-simpler-arbitrary-for-the-diamond-kata.html index 9da3069cc..979b5419b 100644 --- a/_posts/2015-02-23-a-simpler-arbitrary-for-the-diamond-kata.html +++ b/_posts/2015-02-23-a-simpler-arbitrary-for-the-diamond-kata.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my post about the Diamond kata with FsCheck, I changed the way FsCheck generates char values, using this custom Arbitrary (essentially a random value generator): + In my post about the Diamond kata with FsCheck, I changed the way FsCheck generates char values, using this custom Arbitrary (essentially a random value generator):

    type Letters =
    @@ -34,6 +34,6 @@
         Instead of using Arb.Default.Char() and filtering the values generated by it, this implementation uses Gen.elements to create a Generator of the values 'A'-'Z', and then an Arbitrary from that Generator.
       

    - Much simpler, but now it's also clear that this custom Arbitrary will be used to generate 100 test cases (for each property) from a set of 26 values; that doesn't seem right... + Much simpler, but now it's also clear that this custom Arbitrary will be used to generate 100 test cases (for each property) from a set of 26 values; that doesn't seem right...

    \ No newline at end of file diff --git a/_posts/2015-02-23-property-based-testing-without-a-property-based-testing-framework.html b/_posts/2015-02-23-property-based-testing-without-a-property-based-testing-framework.html index 7bad92e46..148fe289a 100644 --- a/_posts/2015-02-23-property-based-testing-without-a-property-based-testing-framework.html +++ b/_posts/2015-02-23-property-based-testing-without-a-property-based-testing-framework.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my previous post, I showed you how to configure FsCheck so that it creates char values exclusively from the list of the upper-case letters A-Z. This is because the only valid input for the Diamond kata is the set of these letters. + In my previous post, I showed you how to configure FsCheck so that it creates char values exclusively from the list of the upper-case letters A-Z. This is because the only valid input for the Diamond kata is the set of these letters.

    By default, FsCheck generates 100 random values for each property, and runs each property with those 100 values. My kata code has 9 properties, so that means 900 function calls (taking just over 1 second on my Lenovo X1 Carbon). diff --git a/_posts/2015-03-19-posting-json-to-an-f-web-api.html b/_posts/2015-03-19-posting-json-to-an-f-web-api.html index 62b354354..32f7e5893 100644 --- a/_posts/2015-03-19-posting-json-to-an-f-web-api.html +++ b/_posts/2015-03-19-posting-json-to-an-f-web-api.html @@ -18,7 +18,7 @@ It's really quite easy, with one weird trick :)

    - You can follow my recipe for creating a pure F# Web API project to get started. Then, you'll need to add a Data Transfer Record and a Controller to accept your data: + You can follow my recipe for creating a pure F# Web API project to get started. Then, you'll need to add a Data Transfer Record and a Controller to accept your data:

    [<CLIMutable>]
    @@ -84,7 +84,7 @@ 

    That's all there is to it.

    - You can also receive XML instead of JSON using a similar trick. + You can also receive XML instead of JSON using a similar trick.

    diff --git a/_posts/2015-04-13-less-is-more-language-features.html b/_posts/2015-04-13-less-is-more-language-features.html index 7b3134b4c..855265816 100644 --- a/_posts/2015-04-13-less-is-more-language-features.html +++ b/_posts/2015-04-13-less-is-more-language-features.html @@ -206,10 +206,10 @@

    Interfaces #

    - Many strongly typed languages (for example Java and C#) have interfaces, which is a mechanism to implement polymorphism. In this way, you can bundle various operations together as methods on an interface. However, one of the consequences of SOLID is that you should favour Role Interfaces over Header Interfaces, and as I've previously explained, the logical conclusion is that all interfaces should only have a single member. + Many strongly typed languages (for example Java and C#) have interfaces, which is a mechanism to implement polymorphism. In this way, you can bundle various operations together as methods on an interface. However, one of the consequences of SOLID is that you should favour Role Interfaces over Header Interfaces, and as I've previously explained, the logical conclusion is that all interfaces should only have a single member.

    - When interfaces only have a single member, the interface declaration itself tends to mostly be in the way - the only thing that matters is the operation. In C#, you could just use a delegate instead, and even Java has lambdas now. + When interfaces only have a single member, the interface declaration itself tends to mostly be in the way - the only thing that matters is the operation. In C#, you could just use a delegate instead, and even Java has lambdas now.

    There's nothing new about this. Functional languages have used functions as the basic compositional unit for years. @@ -329,7 +329,7 @@

    Comments

    2015-04-14 8:07 UTC
    - +

    Chris, thank you for writing. Where in this article do I claim that there are programs you could express in JavaScript, but not in C? @@ -356,7 +356,7 @@

    Comments

    2015-04-16 6:24 UTC
    - +

    Lachlan, thank you for writing. When it comes to working without exceptions, the point is to replace them with something stronger. Scott Wlashin's post and presentation about Railway Oriented Programming is a great place to start. You can see another example in my No Mocks presentation, and in one of my up-coming Pluralsight courses. @@ -386,7 +386,7 @@

    Comments

    2015-05-15 03:09 UTC
    - +

    Shiro Kawai, thank you for writing. In this article, I deliberately left the definition of validity vague. Why do we write software? If we exclude Katas and the like (which we do for training), software is ultimately written in order to solve problems; in order to be used. A valid program is a program that's useful. @@ -419,7 +419,7 @@

    Comments

    2015-05-15 7:40 UTC
    - +

    It's a good point that a language shapes how you approach problems. In this discussion, I assume that all languages (both existing and hypothetical) are Turing complete, but even under that assumption, there will be problems that are difficult, or perhaps even impossible, to address in a particular language. diff --git a/_posts/2015-04-15-c-will-eventually-get-all-f-features-right.html b/_posts/2015-04-15-c-will-eventually-get-all-f-features-right.html index a146c4351..8806e3941 100644 --- a/_posts/2015-04-15-c-will-eventually-get-all-f-features-right.html +++ b/_posts/2015-04-15-c-will-eventually-get-all-f-features-right.html @@ -72,7 +72,7 @@

    Object Expressions. Java has had those for years, so there's no reason C# couldn't get them as well.
  • - Partial Function Application. You can already do this in C# today, but the syntax for it is really awkward. Thus, there's no technical reason C# can't have that, but the C# language designers would have to come up with a better syntax. + Partial Function Application. You can already do this in C# today, but the syntax for it is really awkward. Thus, there's no technical reason C# can't have that, but the C# language designers would have to come up with a better syntax.
  • Scripting. F# is great for scripting, but as the success of scriptcs has shown, nothing prevents C# from being a scripting language either. @@ -99,7 +99,7 @@

    These are some loved features of F# that look unlikely to be ported to C#, but there's one quality of F# that I'm absolutely convinced will never make it to C#, and this is one of the killer features of F#: it's what you can't do in the language.

    - In a recent article, I explained how less is more when it comes to language features. Many languages come with redundant features (often for historical reasons), but the fewer redundant features a language has, the better. + In a recent article, I explained how less is more when it comes to language features. Many languages come with redundant features (often for historical reasons), but the fewer redundant features a language has, the better.

    The F# compiler doesn't allow circular dependencies. You can't use a type or a function before you've defined it. This may seem like a restriction, but is perhaps the most important quality of F#. Cyclic dependencies are closely correlated with coupling, and coupling is the deadliest maintainability killer of code bases. @@ -138,7 +138,7 @@

    Comments

    2015-04-18 15:36 UTC
  • - +

    Vladimir, thank you for writing. You're probably correct. Many years ago, I overheard Anders Hejlsberg say that it wouldn't be possible to introduce non-nullable reference types into the .NET platform without massive breaking changes. I can't say I ever understood the reasoning behind this (nor was it ever explained to me), but when Anders Hejlsberg tells you that, you sort of have to accept it :) diff --git a/_posts/2015-05-07-functional-design-is-intrinsically-testable.html b/_posts/2015-05-07-functional-design-is-intrinsically-testable.html index 5f43dc0b6..900f4992f 100644 --- a/_posts/2015-05-07-functional-design-is-intrinsically-testable.html +++ b/_posts/2015-05-07-functional-design-is-intrinsically-testable.html @@ -17,7 +17,7 @@ Over the years, there's been much criticism of Test-Driven Development (TDD). Perhaps David Heinemeier Hansson best condensed this criticism by claiming that TDD leads to test-induced design damage. This isn't a criticism you can just brush away; it hits a sore point.

    - Personally, I don't believe that TDD has to lead to test-induced damage (not even in Object-Oriented Programming), but I'm the first to admit that it's not a design methodology. + Personally, I don't believe that TDD has to lead to test-induced damage (not even in Object-Oriented Programming), but I'm the first to admit that it's not a design methodology.

    In this article, though, you're going to learn about the fundamental reason that TDD with Functional Programming doesn't lead to test-induced damage. @@ -63,7 +63,7 @@

    Venn diagram showing that while there's an intersection between Encapsulation and Isolation, it's only here that Object-Oriented Programming is also testable.

    - You can do TDD with Object-Oriented Programming, and as long as you stay within the intersection of Encapsulation and Isolation, you may be able to stay clear of test-induced damage. However, that zone of testability isn't particularly big, so it's easy to stray. You have to be very careful and know what you're doing. Not surprisingly, many books and articles have been written about TDD, including quite a few on this blog. + You can do TDD with Object-Oriented Programming, and as long as you stay within the intersection of Encapsulation and Isolation, you may be able to stay clear of test-induced damage. However, that zone of testability isn't particularly big, so it's easy to stray. You have to be very careful and know what you're doing. Not surprisingly, many books and articles have been written about TDD, including quite a few on this blog.

    The best of both worlds # diff --git a/_posts/2015-06-22-rest-implies-content-negotiation.html b/_posts/2015-06-22-rest-implies-content-negotiation.html index 270cf38e2..1cd4b3728 100644 --- a/_posts/2015-06-22-rest-implies-content-negotiation.html +++ b/_posts/2015-06-22-rest-implies-content-negotiation.html @@ -237,7 +237,7 @@

    Comments

    2015-07-01 11:37 UTC
    - +

    Graham, thank you for writing. You are completely right: if it's possible to evolve the API without introducing a new version, that's always preferable. Your suggestion for doing that with my particular example demonstrates how it could be done. @@ -259,7 +259,7 @@

    Comments

    2015-07-16 4:31 UTC
    - +

    Evan, thank you for writing. As I also wrote in a comment to Jim Liddel's article, I would consider the context before making any hard rules. If you control both API and all clients, requiring specific Accept headers may make managing the entire ecosystem a little easier. @@ -286,7 +286,7 @@

    Comments

    2015-10-10 15:40 UTC
    - +

    Ben, thank you for writing. Web API has supported Content Negotiation since back when it was still a WCF Web API CTP. Out of the box it supports XML and JSON, but you can also make it support Content Negotiation-based versioning as described in this article. diff --git a/_posts/2015-08-03-idiomatic-or-idiosyncratic.html b/_posts/2015-08-03-idiomatic-or-idiosyncratic.html index 2375e2ad5..ed8215f74 100644 --- a/_posts/2015-08-03-idiomatic-or-idiosyncratic.html +++ b/_posts/2015-08-03-idiomatic-or-idiosyncratic.html @@ -342,7 +342,7 @@

    2015-08-04 06:01 UTC

    - +

    Craig, fair enough :) diff --git a/_posts/2015-08-10-type-driven-development.html b/_posts/2015-08-10-type-driven-development.html index 4d2a1e0cb..bac2a9cca 100644 --- a/_posts/2015-08-10-type-driven-development.html +++ b/_posts/2015-08-10-type-driven-development.html @@ -32,7 +32,7 @@

    Example problem: simulate a continuously running process as a series of discrete processes #

    - A couple of years ago I had a very particular problem: I needed to simulate a continuously running task using a sequence of discrete processes. + A couple of years ago I had a very particular problem: I needed to simulate a continuously running task using a sequence of discrete processes.

    In short, I needed to start a process (in reality a simple .exe file) that would act as a Polling Consumer, but with the twist that it would keep track of time. It would need to run for one minute, and then shut down so that an overall scheduler could start the process again. This was to guarantee that the process would be running on at most one server in a farm. @@ -47,7 +47,7 @@

    My problem was that I didn't know how long it took to handle a message, so the Polling Consumer would have to measure that as well, constantly updating its estimates of how long it takes to handle a message.

    - This wasn't a harder problem that I could originally solve it in a highly coupled imperative fashion. I wasn't happy with that implementation, though, so I'm happy that there's a much more incremental approach to the problem. + This wasn't a harder problem that I could originally solve it in a highly coupled imperative fashion. I wasn't happy with that implementation, though, so I'm happy that there's a much more incremental approach to the problem.

    A Finite State Machine # @@ -86,7 +86,7 @@

    It sounds like we have a time concern (do I dare say dimension?), and a concern related to doing something. Given multiple concerns, we should separate them

    - The first thing I did was to introduce a Timed<'a> generic record type. This represents the result of performing a computation, as well as the times the computation started and stopped. I changed it slightly from the linked article, so here's the updated code for that: + The first thing I did was to introduce a Timed<'a> generic record type. This represents the result of performing a computation, as well as the times the computation started and stopped. I changed it slightly from the linked article, so here's the updated code for that:

    type Timed<'a> =
    @@ -412,9 +412,9 @@ 

  • You can contemplate the inferred types to evaluate the soundness of the design.
  • The type system implicitly keeps a to-do list for you.
  • - In future articles, I'll demonstrate how to implement some of the missing functions, as well as how to compose the Polling Consumer. + In future articles, I'll demonstrate how to implement some of the missing functions, as well as how to compose the Polling Consumer.

    - Update 2017-07-10: See Pure times for a more functional design. + Update 2017-07-10: See Pure times for a more functional design.

    \ No newline at end of file diff --git a/_posts/2015-08-11-type-driven-development-implementing-shouldidle.html b/_posts/2015-08-11-type-driven-development-implementing-shouldidle.html index ba96fc66f..c7767bee3 100644 --- a/_posts/2015-08-11-type-driven-development-implementing-shouldidle.html +++ b/_posts/2015-08-11-type-driven-development-implementing-shouldidle.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In my article about Type Driven Development, I demonstrated how to approach a problem in an iterative fashion, using the F# type system to do outside-in development. With the overall behaviour in place, there's still work to be done. + In my article about Type Driven Development, I demonstrated how to approach a problem in an iterative fashion, using the F# type system to do outside-in development. With the overall behaviour in place, there's still work to be done.

    From type inference of the higher-order functions' arguments, we know that we still need to implement functions with these signatures: @@ -68,7 +68,7 @@

        nm.Stopped + idleDuration < stopBefore

    - If you paid attention to the previous article, you'll notice that this is exactly the same technique I used for the transitionFromNoMessage function. Apparently, we're not done with outside-in development yet. + If you paid attention to the previous article, you'll notice that this is exactly the same technique I used for the transitionFromNoMessage function. Apparently, we're not done with outside-in development yet.

    Type inference # @@ -89,7 +89,7 @@

    Partial application #

    - The extra arguments can be removed again with partial function application. When the Polling Consumer application starts, it can easily calculate when it ought to stop: + The extra arguments can be removed again with partial function application. When the Polling Consumer application starts, it can easily calculate when it ought to stop:

    let now' = DateTimeOffset.Now
    @@ -122,6 +122,6 @@ 

    Summary #

    - In this article, you saw how to approach the implementation of one of the functions identified with the outside-in Type Driven Development technique. If you want to see the other three functions implemented, a much more detailed discussion of the technique, as well as the entire code base with commit messages, you can watch my Type-Driven Development with F# Pluralsight course. + In this article, you saw how to approach the implementation of one of the functions identified with the outside-in Type Driven Development technique. If you want to see the other three functions implemented, a much more detailed discussion of the technique, as well as the entire code base with commit messages, you can watch my Type-Driven Development with F# Pluralsight course.

    \ No newline at end of file diff --git a/_posts/2015-08-12-type-driven-development-composition.html b/_posts/2015-08-12-type-driven-development-composition.html index c521fecab..89625734d 100644 --- a/_posts/2015-08-12-type-driven-development-composition.html +++ b/_posts/2015-08-12-type-driven-development-composition.html @@ -12,26 +12,26 @@ {{ page.description }}

    - In my article about Type Driven Development, I demonstrated how to approach a problem in an iterative fashion, using the F# type system to do outside-in development, and in a follow-up article, I showed you how to implement one of the inferred methods. In this article, you'll see how to compose all the resulting building blocks into an application. + In my article about Type Driven Development, I demonstrated how to approach a problem in an iterative fashion, using the F# type system to do outside-in development, and in a follow-up article, I showed you how to implement one of the inferred methods. In this article, you'll see how to compose all the resulting building blocks into an application.

    Building blocks #

    - In the first article, you learned that apart from the functions defined in that article itself, you'd need four other functions: + In the first article, you learned that apart from the functions defined in that article itself, you'd need four other functions:

    • ReadyData -> bool
    • unit -> Timed<MessageHandler option>
    • NoMessageData -> bool
    • unit -> Timed<'a>
    - In the article about implementation, you saw how to implement one of these functions: the shouldIdle function. + In the article about implementation, you saw how to implement one of these functions: the shouldIdle function.

    As you can see in my Type-Driven Development with F# Pluralsight course, some of the other implementations turn out to have function arguments themselves. It's not quite enough with only those four functions. Still, the final number of implementation functions is only 9.

    - Here are all the building blocks (excluding the types and functions related to Timed<'a>): + Here are all the building blocks (excluding the types and functions related to Timed<'a>):

    • run : (PollingConsumer -> PollingConsumer) -> PollingConsumer -> PollingConsumer
    • transition : (ReadyData -> bool) -> (unit -> Timed<MessageHandler option>) -> (NoMessageData -> bool) -> (unit -> Timed<'a>) -> PollingConsumer -> PollingConsumer
    • @@ -49,7 +49,7 @@

      Composition #

      - When the Polling Consumer starts, it can start by figuring out the current time, and calculate some derived values from that and some configuration values, as previously explained. + When the Polling Consumer starts, it can start by figuring out the current time, and calculate some derived values from that and some configuration values, as previously explained.

      let now' = DateTimeOffset.Now
      @@ -58,7 +58,7 @@ 

      let idleDuration' = TimeSpan.FromSeconds 5.

      - The estimatedDuration' value is a TimeSpan containing a (conservative) estimate of how long time it takes to handle a single message. It's only used if there are no already observed message handling durations, as the algorithm then has no statistics about the average execution time for each message. This value could come from a configuration system, or a command-line argument. In a recent system, I just arbitrarily set it to 2 seconds. + The estimatedDuration' value is a TimeSpan containing a (conservative) estimate of how long time it takes to handle a single message. It's only used if there are no already observed message handling durations, as the algorithm then has no statistics about the average execution time for each message. This value could come from a configuration system, or a command-line argument. In a recent system, I just arbitrarily set it to 2 seconds.

      Given these initial values, we can compose all other required functions: @@ -80,7 +80,7 @@

      let run' = run transition'

      - The composed run' function has the type PollingConsumer -> PollingConsumer. The input PollingConsumer value is the start state, and the function will return another PollingConsumer when it's done. Due to the way the run function is implemented, this return value is always going to be StoppedState. + The composed run' function has the type PollingConsumer -> PollingConsumer. The input PollingConsumer value is the start state, and the function will return another PollingConsumer when it's done. Due to the way the run function is implemented, this return value is always going to be StoppedState.

      Execution # @@ -142,7 +142,7 @@

      Summary #

      - Once you have all the appropriate building blocks, you can compose your desired system and run it. Notice how much this resembles the Composition Root pattern, only with functions instead of objects. + Once you have all the appropriate building blocks, you can compose your desired system and run it. Notice how much this resembles the Composition Root pattern, only with functions instead of objects.

      If you want to see more details about this example, or get access to the full source code, you can watch my Type-Driven Development with F# Pluralsight course. Please be aware that only certain subscription levels will give you source code access. diff --git a/_posts/2015-08-17-when-x-y-and-z-are-great-variable-names.html b/_posts/2015-08-17-when-x-y-and-z-are-great-variable-names.html index f98064f54..88cd5bc3c 100644 --- a/_posts/2015-08-17-when-x-y-and-z-are-great-variable-names.html +++ b/_posts/2015-08-17-when-x-y-and-z-are-great-variable-names.html @@ -40,7 +40,7 @@

      In statically typed Functional languages like F# or Haskell, you rarely declare the types of functions and arguments. Instead, types are inferred, based on usage or implementation. It often turns out that functions are more generic than you first thought when you started writing it.

      - Here's a simple example. When I did the Diamond kata with Property-Based Testing, I created this little helper function along the way: + Here's a simple example. When I did the Diamond kata with Property-Based Testing, I created this little helper function along the way:

      let isTwoIdenticalLetters x =
      @@ -99,7 +99,7 @@ 

          hasIdenticalElements && hasTwoElements

      - This is better, but now I'm beginning to realize that I've been thinking too much about strings and letters, and not about the more general question this function apparently answers. A more straightforward (depending on your perspective) implementation may be this: + This is better, but now I'm beginning to realize that I've been thinking too much about strings and letters, and not about the more general question this function apparently answers. A more straightforward (depending on your perspective) implementation may be this:

      let isTwoIdenticalElements x =
      @@ -108,7 +108,7 @@ 

          | _ -> false

      - This may be slightly more efficient, because it doesn't have to traverse the sequence twice, but most importantly, I think it looks more idiomatic. + This may be slightly more efficient, because it doesn't have to traverse the sequence twice, but most importantly, I think it looks more idiomatic.

      Notice the return of 'Functional' names like y and z. Although terse, these are appropriate names. Both y and z are values of the generic type argument 'a. If not y and z, then what would you call them? element1 and element2? How would those names be better? @@ -152,7 +152,7 @@

      Do you use variable names like i in for loops in C# or Java? I do, so I find it appropriate to also use short names in small functions in F# and Haskell.

      - Well-factored Functional code consists of small, concise functions, just as well-factored SOLID code consists of small classes with clear responsibilities. When functions are small, scopes are small, so it's only natural that we encounter many tersely named variables like x, y, and f. + Well-factored Functional code consists of small, concise functions, just as well-factored SOLID code consists of small classes with clear responsibilities. When functions are small, scopes are small, so it's only natural that we encounter many tersely named variables like x, y, and f.

      It's more readable that way. @@ -183,7 +183,7 @@

      2015-08-20 20:44 UTC

    - +

    Dave, thank you for writing. FWIW, I don't think there's anything wrong with longer camel-cased names when a function or a value is more explicit. As an example, I still kept the name of the example function fairly long and explicit: isTwoIdenticalElements. diff --git a/_posts/2015-09-08-ad-hoc-arbitraries-with-fscheckxunit.html b/_posts/2015-09-08-ad-hoc-arbitraries-with-fscheckxunit.html index 390c7a00e..d01a0ecc7 100644 --- a/_posts/2015-09-08-ad-hoc-arbitraries-with-fscheckxunit.html +++ b/_posts/2015-09-08-ad-hoc-arbitraries-with-fscheckxunit.html @@ -149,6 +149,6 @@

    FsCheck is a well-designed library that you can combine in lots of interesting ways. In this article you learned how to use Prop.forAll to evaluate a property with a mix of normal, arbitrarily generated values, and an ad hoc, in-line Arbitrary.

    - Addendum 2016-03-01: You can write such properties slightly better using the backward pipe operator. + Addendum 2016-03-01: You can write such properties slightly better using the backward pipe operator.

    diff --git a/_posts/2015-09-18-temporary-field-code-smell.html b/_posts/2015-09-18-temporary-field-code-smell.html index 795a7bbe5..fa7aab6ba 100644 --- a/_posts/2015-09-18-temporary-field-code-smell.html +++ b/_posts/2015-09-18-temporary-field-code-smell.html @@ -267,7 +267,7 @@

    2015-09-25 22:20 UTC

    - +

    Tom, thank you for writing. Great observation about passing arguments around instead! In this case, passing the necessary arguments around would also be a good solution. It would look like this: diff --git a/_posts/2015-09-21-public-types-hidden-in-plain-sight.html b/_posts/2015-09-21-public-types-hidden-in-plain-sight.html index 755b2f2d4..f56c52084 100644 --- a/_posts/2015-09-21-public-types-hidden-in-plain-sight.html +++ b/_posts/2015-09-21-public-types-hidden-in-plain-sight.html @@ -53,7 +53,7 @@

    My preferred approach to this problem is to make types public anyway. If my overall feeling about a type is that "it seems okay", I make it public, even if I know that there's a risk involved with this.

    - Consider, as an example, the private DurationStatistics class I extracted in a recent article. In that article, I kept the class private, because I wanted to discuss visibility in a separate article. + Consider, as an example, the private DurationStatistics class I extracted in a recent article. In that article, I kept the class private, because I wanted to discuss visibility in a separate article.

    You can easily promote the DurationStatistics class to a public class: @@ -63,7 +63,7 @@

    - Here you only see the declaration of the class, because the implementation is exactly the same as in the other article. The code is moved out of the Estimator class and put into its own file, though. + Here you only see the declaration of the class, because the implementation is exactly the same as in the other article. The code is moved out of the Estimator class and put into its own file, though.

    How can you be sure that DurationStatistics is 'done'? How can you be sure that you're not going to need to change it later? @@ -82,7 +82,7 @@

    public class DurationStatistics

    - This will cause a compiler warning in all client code using the DurationStatistics class. You should make the message as helpful and friendly as possible. + This will cause a compiler warning in all client code using the DurationStatistics class. You should make the message as helpful and friendly as possible.

    This may leave your code with compiler warnings. This is good, because you should work to remove these warnings from your own code base. The only place you should leave them in place is in your unit tests. As long as you have a deprecated type in your published code base, you should also keep it covered by unit tests. This will cause compiler warnings in your unit tests, but you can suppress such warnings explicitly there: @@ -106,7 +106,7 @@

    Keep the 'disable scope' as small as possible, and always remember to restore the warning after disabling it.

    - Perhaps you think that this approach of just making everything public and dealing with the consequences later is an unprofessional, unhygienic, and ugly way to evolve code, but it's really the logical way to produce and publish SOLID code. + Perhaps you think that this approach of just making everything public and dealing with the consequences later is an unprofessional, unhygienic, and ugly way to evolve code, but it's really the logical way to produce and publish SOLID code.

    Obsolete by default # @@ -127,7 +127,7 @@

    This is a softer way of hiding public types in plain sight, because clients get no compiler warnings if they use those 'hidden' types. Still, it can be quite effective.

    - My experience with maintaining public software (e.g. the now-more-than-six-year-old AutoFixture project) is that the most common problem is that users don't even find the public types I want them to find! If you knew how many times I've seen people reinvent a feature already available in the API... And that's even when all the interesting stuff is in the same namespace. + My experience with maintaining public software (e.g. the now-more-than-six-year-old AutoFixture project) is that the most common problem is that users don't even find the public types I want them to find! If you knew how many times I've seen people reinvent a feature already available in the API... And that's even when all the interesting stuff is in the same namespace.

    Putting types in separate namespaces is, in my experience, quite an effective way of hiding them. @@ -229,10 +229,10 @@

    2015-08-21 17:05 UTC

    - +

    - The problem with the [InternalsVisibleTo] attribute is exactly that it enables you to unit test internals, which you shouldn't. + The problem with the [InternalsVisibleTo] attribute is exactly that it enables you to unit test internals, which you shouldn't.

    2015-09-22 12:24 UTC
    @@ -261,13 +261,13 @@

    2015-10-03 04:37 UTC

    - +

    - Kenny, thank you for writing. Overall, I like that additional argument. In order to keep this discussion balanced, I think it's worth pointing out that your argument certainly applies to reusable software, but that lots of software isn't (or rather, shouldn't be) reusable. Udi Dahan has pointed out that reuse may be overrated, or even have negative consequences, and while I've been disagreeing with certain parts of that claim, in general I think there's much wisdom in that observation. + Kenny, thank you for writing. Overall, I like that additional argument. In order to keep this discussion balanced, I think it's worth pointing out that your argument certainly applies to reusable software, but that lots of software isn't (or rather, shouldn't be) reusable. Udi Dahan has pointed out that reuse may be overrated, or even have negative consequences, and while I've been disagreeing with certain parts of that claim, in general I think there's much wisdom in that observation.

    - Some software is written to be reusable, but much software shouldn't be. This is the sort of software I call Zoo software. Your argument about violation of the OCP certainly applies to Wildlife Software, but only indirectly to Zoo software. + Some software is written to be reusable, but much software shouldn't be. This is the sort of software I call Zoo software. Your argument about violation of the OCP certainly applies to Wildlife Software, but only indirectly to Zoo software.

    2015-10-03 09:30 UTC
    diff --git a/_posts/2015-09-22-unit-testing-internals.html b/_posts/2015-09-22-unit-testing-internals.html index 98ba8817a..a4c613a80 100644 --- a/_posts/2015-09-22-unit-testing-internals.html +++ b/_posts/2015-09-22-unit-testing-internals.html @@ -24,7 +24,7 @@

    Details can be interesting, but don't lose sight of the big picture. Why do you test your software with automated tests?

    - Automated testing (as opposed to manual testing) only serves a single purpose: it prevents regressions. Some would say that it demonstrates that the software works correctly, but that's inaccurate. Automated tests can only demonstrate that the software works correctly if the tests are written correctly, but that's a different discussion. + Automated testing (as opposed to manual testing) only serves a single purpose: it prevents regressions. Some would say that it demonstrates that the software works correctly, but that's inaccurate. Automated tests can only demonstrate that the software works correctly if the tests are written correctly, but that's a different discussion.

    Assuming that all automated tests are correct, then yes: automated tests also demonstrate that the software works, but it's still regression testing. The tests were written to demonstrate that the software worked correctly once. Running the tests repeatedly only demonstrates that it still works correctly. @@ -83,7 +83,7 @@

  • Members (or entire classes) are poorly encapsulated, so the developers don't want to expose these internals for fear of destabilising the system.
  • Types or members are kept hidden in order to protect the code base from backwards compatibility issues.
  • - The first issue is easy to deal with. Consider a recent example: + The first issue is easy to deal with. Consider a recent example:

    private void CalculateAverage()
    @@ -94,13 +94,13 @@ 

    }

    - This CalculateAverage method is marked private because it's unsafe to call it. this.durations can be null, in which case the method would throw an exception. It may feel like a solution to lock down the method with an access modifier, but really it only smells of poor encapsulation. Instead, refactor the code to a proper, robust design. + This CalculateAverage method is marked private because it's unsafe to call it. this.durations can be null, in which case the method would throw an exception. It may feel like a solution to lock down the method with an access modifier, but really it only smells of poor encapsulation. Instead, refactor the code to a proper, robust design.

    There are valid use cases for the private and internal access modifiers, but the majority of the time I see private and internal code, it merely smells of poor design. If you change the design, you could make types and members public, and feel good about it.

    - The other issue, concerns about compatibility, can be addressed as well. In any case, for most developers, this is essentially a theoretical issue, because most code written isn't for public consumption anyway. If you also control all consumers of your API, you may not need to worry about compatibility. If you need to change the name of a class, just let your favourite refactoring tool do this for you, and all is still good. (I'd still recommend that you should adopt a Ranger approach to your Zoo software, but that's a different topic.) + The other issue, concerns about compatibility, can be addressed as well. In any case, for most developers, this is essentially a theoretical issue, because most code written isn't for public consumption anyway. If you also control all consumers of your API, you may not need to worry about compatibility. If you need to change the name of a class, just let your favourite refactoring tool do this for you, and all is still good. (I'd still recommend that you should adopt a Ranger approach to your Zoo software, but that's a different topic.)

    The bottom line: you don't have to hide most of your code behind access modifiers. There are good alternatives that lead to better designs. @@ -127,7 +127,7 @@

    A well-designed system tends to be more stable when it comes to unit testing. A poorly designed system is often characterised by tests that are too coupled to implementation details. As soon as you decide to change something in such a system, you'll need to change the tests as well.

    - Recall that automated testing is regression testing. The only information we get from running tests is whether or not existing tests passed or failed. We don't learn if the tests are correct. How do we know that tests are correct? Essentially, we know because we review them, see them fail, and never touch them again. If you constantly have to fiddle with your tests, how do you know they still test the right behaviour? + Recall that automated testing is regression testing. The only information we get from running tests is whether or not existing tests passed or failed. We don't learn if the tests are correct. How do we know that tests are correct? Essentially, we know because we review them, see them fail, and never touch them again. If you constantly have to fiddle with your tests, how do you know they still test the right behaviour?

    Design your sub-modules well, on the other hand, and test maintenance tends to be much lower. If you have well-designed sub-modules, though, you don't have to make all types internal. Make them public. They are part of your solution. @@ -183,7 +183,7 @@

    Comments

    2015-10-03 08:14 UTC
    - +

    Kenny, thank you for writing. The answer given by Eric Lippert does, in my opinion, still paint an appropriate picture. There's always a cost to making types or members public, and I don't always wish to pay that cost. The point that I'm trying to make in the present article is that while this cost exists, it's not so high that it justifies unit testing internals via mechanisms like Reflections or [InternalsVisibleTo]. The cost of doing that is higher than making types or members public. @@ -195,7 +195,7 @@

    Comments

    Much of my code has plenty of private or internal code. An example is Hyprlinkr, which has private helper methods for one of its central features. These private helpers only exist in order to make the feature implementation more readable, but are not meant for public consumption. They're all covered by tests that exercise the various public members of the class.

    - Likewise, you can consider the private DurationStatistics class from my Temporary Field code smell article. At first, you may want to keep this class private, because you're not sure that it's stable (i.e. that it isn't going to change). Later, you may realise that you'll need that code in other parts of your code base, so you move it to an internal class. If you're still not convinced that it's stable, you may feel better keeping it internal rather than making it public. Ultimately, you may realise that it is, indeed, stable, in which case you may decide to make it public - or you may decide that no one has had the need for it, so it doesn't really matter, after all. + Likewise, you can consider the private DurationStatistics class from my Temporary Field code smell article. At first, you may want to keep this class private, because you're not sure that it's stable (i.e. that it isn't going to change). Later, you may realise that you'll need that code in other parts of your code base, so you move it to an internal class. If you're still not convinced that it's stable, you may feel better keeping it internal rather than making it public. Ultimately, you may realise that it is, indeed, stable, in which case you may decide to make it public - or you may decide that no one has had the need for it, so it doesn't really matter, after all.

    My goal with this article wasn't to advise against internal code, but only to advise against trying to directly call such code for unit testing purposes. In my experience, when people ask how to unit test internal code, it's a problem they have because they haven't used Test-Driven Development (TDD). If you do TDD, you'll have sufficient coverage, and then it doesn't matter how you choose to organise the internals of your code base. diff --git a/_posts/2015-09-23-applications-and-their-side-effects.html b/_posts/2015-09-23-applications-and-their-side-effects.html index 7a91bdf8f..bec521cf2 100644 --- a/_posts/2015-09-23-applications-and-their-side-effects.html +++ b/_posts/2015-09-23-applications-and-their-side-effects.html @@ -15,7 +15,7 @@ In my Encapsulation and SOLID Pluralsight course, I introduce Command-Query Separation (CQS) as a fundamental tool that will help you think about encapsulation. (I didn't come up with this myself, but rather picked it up from Bertrand Meyer's Object-Oriented Software Construction.)

    - Despite the age of the CQS principle, it's still news to many people, and I get lots of questions about it; I attempt to answer them as well as I can. Most questions are about specific situations where the inquirer can't see a way out of issuing a Query and at the same time producing a side-effect. + Despite the age of the CQS principle, it's still news to many people, and I get lots of questions about it; I attempt to answer them as well as I can. Most questions are about specific situations where the inquirer can't see a way out of issuing a Query and at the same time producing a side-effect.

    Perhaps the most common situation comes up when auditing comes into play. In some domains, auditing is a legal requirement. Asking any question must produce the side-effect that an audit record is created. @@ -63,7 +63,7 @@

    CQS, or referentially transparent functions, are principles we apply at the source code level to make the code easier to reason about and maintain. It's a question of separation of concerns: we separate pure computation from side-effects.

    - Applications, on the other hand, are compositions of all relevant concerns. As I've previously described, at the boundaries, applications aren't Object-Oriented. Neither are they Functional. All applications must have a boundary where Encapsulation, or FP, or CQS, doesn't apply. The trick is to keep that boundary as thin as possible. + Applications, on the other hand, are compositions of all relevant concerns. As I've previously described, at the boundaries, applications aren't Object-Oriented. Neither are they Functional. All applications must have a boundary where Encapsulation, or FP, or CQS, doesn't apply. The trick is to keep that boundary as thin as possible.

    Thus, if you must violate CQS, do it in the boundary of the application. As an example, perhaps you're creating a REST service that enables clients to create new resources with POST requests. As a response, you want to return the address of the new resource. That violates CQS, but if you keep that violation at the entry point of the request, you've isolated the violation to the boundary of the application. diff --git a/_posts/2015-10-08-command-query-separation-when-queries-should-have-side-effects.html b/_posts/2015-10-08-command-query-separation-when-queries-should-have-side-effects.html index 5442c4649..38990dfb9 100644 --- a/_posts/2015-10-08-command-query-separation-when-queries-should-have-side-effects.html +++ b/_posts/2015-10-08-command-query-separation-when-queries-should-have-side-effects.html @@ -15,7 +15,7 @@ Command Query Separation (CQS) can be difficult until you get the hang of it; then it's not so difficult - just like most other things in life :)

    - In a previous article, I covered how to retrieve server-generated IDs after Create operations. That article discussed how to prevent Commands from turning into Queries. In the present article, you'll see some examples of how to prevent Queries from turning into Commands. + In a previous article, I covered how to retrieve server-generated IDs after Create operations. That article discussed how to prevent Commands from turning into Queries. In the present article, you'll see some examples of how to prevent Queries from turning into Commands.

    Context # @@ -25,7 +25,7 @@

    "If a student has not submitted a solution to an exercise yet, when and if they look at the exercise hint for the first time, flag that hint as viewed. The points granted to a student's solution will be subtracted by 5 points, if the related hint is flagged as viewed."
    - As stated here, it sounds like a Query (reading the exercise hint) must have a side-effect. This time, we can't easily wave it away by saying that the side-effect is one that the client isn't responsible for, so it'll be OK. If the side-effect had been an audit log, we could have gotten away with that, but here the side-effect is within the Domain Model itself. + As stated here, it sounds like a Query (reading the exercise hint) must have a side-effect. This time, we can't easily wave it away by saying that the side-effect is one that the client isn't responsible for, so it'll be OK. If the side-effect had been an audit log, we could have gotten away with that, but here the side-effect is within the Domain Model itself.

    How can you implement this business requirement while still adhering to CQS? Perhaps you'd like to pause reading for a moment to reflect on this question; then you can compare your notes to mine. @@ -88,7 +88,7 @@

    }

    - The Scored<T> class enables you to carry a score value around within a computation. In order to keep the example as simple as possible, I modelled the score as an integer, but perhaps you should consider refactoring from Primitive Obsession to Domain Modelling; that's a different story, though. + The Scored<T> class enables you to carry a score value around within a computation. In order to keep the example as simple as possible, I modelled the score as an integer, but perhaps you should consider refactoring from Primitive Obsession to Domain Modelling; that's a different story, though.

    This means you can model your API in such a way that a client must supply the current score in order to retrieve a hint, and the new score is returned together with the hint: @@ -126,7 +126,7 @@

    }

    - The Read method uses an injected (lower-level) Query interface to read the answer hint, packages the result in a Scored<Hint> value, and subtracts 5 points from the score. + The Read method uses an injected (lower-level) Query interface to read the answer hint, packages the result in a Scored<Hint> value, and subtracts 5 points from the score.

    Both the score type (int) and Scored<T> are immutable. No side-effects occur while the client reads the answer hint, but the score is nonetheless adjusted. @@ -189,11 +189,11 @@

    -
    Hi Mark, don't you think that the pessimistic locking is a case of temporal coupling?
    +
    Hi Mark, don't you think that the pessimistic locking is a case of temporal coupling?
    2015-10-09 07:08 UTC
    - +

    Philippe, thank you for writing. That's a great observation, and one that I must admit that I hadn't considered myself! @@ -221,7 +221,7 @@

    2015-10-09 12:01 UTC

    - +

    Loïc, thank you for writing. I'm sure there are other alternatives than the ones I've outlined. The purpose of the article wasn't to provide an exhaustive list of options, but rather explain that it is possible to adhere to the CQS, even though sometimes it seems difficult. diff --git a/_posts/2015-10-19-visual-value-verification.html b/_posts/2015-10-19-visual-value-verification.html index 3eee7f648..6014cf242 100644 --- a/_posts/2015-10-19-visual-value-verification.html +++ b/_posts/2015-10-19-visual-value-verification.html @@ -26,7 +26,7 @@

    Return values #

    - Since I was approaching the problem with Functional Programming, it ought to be easy to unit test. After all, Functional design is intrinsically testable. My overall function to find the convex hull looks like this: + Since I was approaching the problem with Functional Programming, it ought to be easy to unit test. After all, Functional design is intrinsically testable. My overall function to find the convex hull looks like this:

    let inline hull points = // ...
    diff --git a/_posts/2015-10-26-service-locator-violates-encapsulation.html b/_posts/2015-10-26-service-locator-violates-encapsulation.html
    index 420576553..79298dad1 100644
    --- a/_posts/2015-10-26-service-locator-violates-encapsulation.html
    +++ b/_posts/2015-10-26-service-locator-violates-encapsulation.html
    @@ -12,10 +12,10 @@
     		{{ page.description }}
     	

    - The horse has been long dead, but some people still want to ride it, so I'll beat it yet again. Over the years, I've made various attempts to explain why Service Locator is an anti-pattern (e.g. that it violates SOLID), but recently it struck me that most of my arguments have been focused on symptoms without ever addressing the fundamental problem. + The horse has been long dead, but some people still want to ride it, so I'll beat it yet again. Over the years, I've made various attempts to explain why Service Locator is an anti-pattern (e.g. that it violates SOLID), but recently it struck me that most of my arguments have been focused on symptoms without ever addressing the fundamental problem.

    - As an example of discussing symptoms, in my original article, I described how IntelliSense is hurt by the use of Service Locator. In 2010, it never occurred to me that the underlying problem is that encapsulation is violated. + As an example of discussing symptoms, in my original article, I described how IntelliSense is hurt by the use of Service Locator. In 2010, it never occurred to me that the underlying problem is that encapsulation is violated.

    Consider my original example: @@ -47,7 +47,7 @@

    As Object-Oriented Software Construction explains, a contract consists of a set of pre- and postconditions for interaction. If the client satisfies the preconditions, the object promises to satisfy the postconditions.

    - In statically typed languages like C# and Java, many preconditions can be expressed with the type system itself, as I've previously demonstrated. + In statically typed languages like C# and Java, many preconditions can be expressed with the type system itself, as I've previously demonstrated.

    If you look at the public API for the above OrderProcessor class, then what would you think its preconditions are? @@ -155,7 +155,7 @@

    Service Locator is an anti-pattern in statically typed, object-oriented languages because it violates encapsulation. The reason is that it hides preconditions for proper usage.

    - If you need an accessible introduction to encapsulation, you should consider watching my Encapsulation and SOLID Pluralsight course. If you wish to learn more about Dependency Injection, you can read my award-winning book Dependency Injection in .NET. + If you need an accessible introduction to encapsulation, you should consider watching my Encapsulation and SOLID Pluralsight course. If you wish to learn more about Dependency Injection, you can read my award-winning book Dependency Injection in .NET.

    @@ -177,13 +177,13 @@

    Comments

    2015-11-19 23:21 UTC
    - +

    Jeffrey, thank you for writing. I'm not sure I fully understand, but perhaps you are considering whether the use of a DI Container as a composition engine is also an anti-pattern?

    - If so, you can use a DI Container from within your Composition Root, but personally, I still prefer Pure DI. + If so, you can use a DI Container from within your Composition Root, but personally, I still prefer Pure DI.

    2015-11-20 7:06 UTC UTC
    diff --git a/_posts/2015-11-13-null-has-no-type-but-maybe-has.html b/_posts/2015-11-13-null-has-no-type-but-maybe-has.html index 751681231..5c35da4ad 100644 --- a/_posts/2015-11-13-null-has-no-type-but-maybe-has.html +++ b/_posts/2015-11-13-null-has-no-type-but-maybe-has.html @@ -51,7 +51,7 @@ Apparently, the rules of C#'s type system is: a variable is guaranteed to be of a certain type, except when it isn't. Once again, null throws a wrench into any attempt to reason sanely about code.

    - The .NET Rocks! episode about less is more sparked a ton of comments; most of them in defence of null. People don't seem to understand just how malicious null references are. That null has no type is yet another example. + The .NET Rocks! episode about less is more sparked a ton of comments; most of them in defence of null. People don't seem to understand just how malicious null references are. That null has no type is yet another example.

    I think that the main reason that people defend null is that they have a hard time imagining other ways of modelling situations where a value may or may not be present. Even when introduced to the Maybe monad, most people remain unconvinced, because it's difficult to understand how Maybe is better than null. diff --git a/_posts/2015-11-30-to-log-or-not-to-log.html b/_posts/2015-11-30-to-log-or-not-to-log.html index 11b31f2d3..00ccb6711 100644 --- a/_posts/2015-11-30-to-log-or-not-to-log.html +++ b/_posts/2015-11-30-to-log-or-not-to-log.html @@ -239,7 +239,7 @@

    Notice the presence of the conditional compilation flag LOG. Only if the application is compiled with the LOG flag will the logging code be compiled into the application; otherwise, it runs without any logging overhead at all.

    - Personally, I've never needed to control logging at this level, so this isn't a recommendation; it's only a demonstration that it's possible. What's much more important to me is that everything you've seen here has required zero changes of the application code. The only code being modified is the Composition Root, and I regard the Composition Root as a configuration file. + Personally, I've never needed to control logging at this level, so this isn't a recommendation; it's only a demonstration that it's possible. What's much more important to me is that everything you've seen here has required zero changes of the application code. The only code being modified is the Composition Root, and I regard the Composition Root as a configuration file.

    Summary # @@ -275,13 +275,13 @@

    2018-10-04 18:31 UTC

    - +

    Ben, thank you for writing. It's not at all implicit that Singletons are involved. This article discusses a semi-functional design where there's no objects, just functions. It seems, however, that some of your concerns relate to object-oriented design.

    - In object-oriented design, I recommend modelling logging and other cross-cutting concerns as applications of the Decorator or Chain of Responsibility design patterns. As mentioned in this article, I discuss this in my book, but this blog also contains an example of this, although it's about instrumentation instead of logging. These two cross-cutting concerns are closely related in structure, though, so I hope you still find it informative. Such an approach to design eliminates the need for passing log dependencies around in business logic and other places where it doesn't belong. + In object-oriented design, I recommend modelling logging and other cross-cutting concerns as applications of the Decorator or Chain of Responsibility design patterns. As mentioned in this article, I discuss this in my book, but this blog also contains an example of this, although it's about instrumentation instead of logging. These two cross-cutting concerns are closely related in structure, though, so I hope you still find it informative. Such an approach to design eliminates the need for passing log dependencies around in business logic and other places where it doesn't belong.

    The way I've seen people address the problem with multi-threaded logging is to have a logger object per thread (or, safer this day, per HTTP request, or similar). This object simply collects all log data in memory until flushed. Some designs require client developers to explicitly call a Flush method, but typically you can automate this so that it happens automatically when the thread or HTTP context is disposed of. diff --git a/_posts/2015-12-01-recurse.html b/_posts/2015-12-01-recurse.html index 0bd5c9b1f..514f14946 100644 --- a/_posts/2015-12-01-recurse.html +++ b/_posts/2015-12-01-recurse.html @@ -87,7 +87,7 @@

    This second example is a more complex example that further illustrates how to apply the Recurse refactoring. If you already feel that you understand how to apply this refactoring, you can skip reading the following example.

    - Some time ago, I was attempting to implement the Graham Scan algorithm to find the convex hull for a set of points. As I've described before, this turned out to be quite difficult for me. One of my problems was that I was trying to implement the algorithm in Haskell, and while I understood the algorithm, I couldn't figure out how to implement it in a functional way - and when you can't do it the functional way, you can't do it at all in Haskell. + Some time ago, I was attempting to implement the Graham Scan algorithm to find the convex hull for a set of points. As I've described before, this turned out to be quite difficult for me. One of my problems was that I was trying to implement the algorithm in Haskell, and while I understood the algorithm, I couldn't figure out how to implement it in a functional way - and when you can't do it the functional way, you can't do it at all in Haskell.

    In F#, on the other hand, you can implement algorithms using procedural code if you must, so I decided to implement the algorithm in F# first, using a procedural approach, and then subsequently figure out how to refactor to immutable values. Once I had a pure F# implementation, I could always back-port it to Haskell. diff --git a/_posts/2015-12-04-the-rules-of-attraction-location.html b/_posts/2015-12-04-the-rules-of-attraction-location.html index 131eb546a..b64d71025 100644 --- a/_posts/2015-12-04-the-rules-of-attraction-location.html +++ b/_posts/2015-12-04-the-rules-of-attraction-location.html @@ -99,6 +99,6 @@

    You can claim that you're a 'world-class' organisation that hires only the best of the best (within a radius of 100 km).

    - Or you can be a world-class organisation by literally having developers working all over the world. You still need to be able to find the best, though. Perhaps you should try to let them find you instead. + Or you can be a world-class organisation by literally having developers working all over the world. You still need to be able to find the best, though. Perhaps you should try to let them find you instead.

    \ No newline at end of file diff --git a/_posts/2015-12-21-integration-testing-composed-functions.html b/_posts/2015-12-21-integration-testing-composed-functions.html index 1361ed03b..11c1db1b9 100644 --- a/_posts/2015-12-21-integration-testing-composed-functions.html +++ b/_posts/2015-12-21-integration-testing-composed-functions.html @@ -12,13 +12,13 @@ {{ page.description }}

    - Despite its reputation as a niche language for scientific or finance computing, F# is a wonderful language for 'mainstream' software development. You can compose applications from small, inherently testable functions. + Despite its reputation as a niche language for scientific or finance computing, F# is a wonderful language for 'mainstream' software development. You can compose applications from small, inherently testable functions.

    Composition #

    - Once you have your functions as building blocks, you compose them. This is best done in an application's Composition Root - no different from Dependency Injection in Object-Oriented Programming. + Once you have your functions as building blocks, you compose them. This is best done in an application's Composition Root - no different from Dependency Injection in Object-Oriented Programming.

    In my (free) Build Stuff talk on Functional TDD with F# (expanded version available on Pluralsight), I demonstrate how to compose such a function: diff --git a/_posts/2015-12-22-tail-recurse.html b/_posts/2015-12-22-tail-recurse.html index b3a5ead27..d70d54e7c 100644 --- a/_posts/2015-12-22-tail-recurse.html +++ b/_posts/2015-12-22-tail-recurse.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In a recent article, I described how to refactor an imperative loop to a recursive function. If you're coming from C# or Java, however, you may have learned to avoid recursion, since it leads to stack overflows when the recursion is too deep. + In a recent article, I described how to refactor an imperative loop to a recursive function. If you're coming from C# or Java, however, you may have learned to avoid recursion, since it leads to stack overflows when the recursion is too deep.

    In some Functional languages, like F# and Haskell, such stack overflows can be prevented with tail recursion. If the last function call being made is a recursive call to the function itself, the current stack frame can be eliminated because execution is effectively completed. This allows a tail-recursive function to keep recursing without ever overflowing. @@ -24,13 +24,13 @@

    Introduce an accumulator #

    - It seems as though the universal trick related to recursion is to introduce an accumulator argument. This is how you refactor an imperative loop to a recursive function, but it can also be used to make a non-tail-recursive function tail recursive. This will also require you to introduce an 'implementation function' that does the actual work. + It seems as though the universal trick related to recursion is to introduce an accumulator argument. This is how you refactor an imperative loop to a recursive function, but it can also be used to make a non-tail-recursive function tail recursive. This will also require you to introduce an 'implementation function' that does the actual work.

    Example: discarding candidate points when finding a convex hull #

    - In previous articles I've described various problems I had when implementing the Graham Scan algorithm to find the convex hull of a set of points. + In previous articles I've described various problems I had when implementing the Graham Scan algorithm to find the convex hull of a set of points.

    One of my functions examined the three last points in a sequence of points in order to determine if the next-to-last point is in the interior of the set, or if that point could potentially be on the hull. If the point is positively known to be in the interior of the set, it should be discarded. At one stage, the function was implemented this way: @@ -48,7 +48,7 @@

        else None

    - This function was earlier called check, which is the name used in the article about refactoring to recursion. The tryDiscard function is actually an inner function in a more complex function that's defined with the inline keyword, so the type of tryDiscard is somewhat complicated, but think of it as having the type (int * int) list -> (int * int) list option. If a point was discarded, the new, reduced list of points is returned in a Some case; otherwise, None is returned. + This function was earlier called check, which is the name used in the article about refactoring to recursion. The tryDiscard function is actually an inner function in a more complex function that's defined with the inline keyword, so the type of tryDiscard is somewhat complicated, but think of it as having the type (int * int) list -> (int * int) list option. If a point was discarded, the new, reduced list of points is returned in a Some case; otherwise, None is returned.

    The tryDiscard function already has an 'implementation function' called tryDiscardImp, but while tryDiscardImp is recursive, it isn't tail recursive. The problem is that in the p :: ps case, the recursive call to tryDiscardImp isn't the tail call. Rather, the stack frame has to wait for the recursive call tryDiscardImp ps to complete, because only then can it cons p onto its return value. diff --git a/_posts/2016-02-10-types--properties--software-designing-with-types.html b/_posts/2016-02-10-types--properties--software-designing-with-types.html index 5a683874e..821d7a7c1 100644 --- a/_posts/2016-02-10-types--properties--software-designing-with-types.html +++ b/_posts/2016-02-10-types--properties--software-designing-with-types.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the first in a series of articles that demonstrate how to develop software using types and properties. In this article, you'll see an example of how to design with algebraic data types, and in future articles, you'll see how to specify properties that must hold for the system. This example uses F#, but you can design similar types in Haskell. + This article is the first in a series of articles that demonstrate how to develop software using types and properties. In this article, you'll see an example of how to design with algebraic data types, and in future articles, you'll see how to specify properties that must hold for the system. This example uses F#, but you can design similar types in Haskell.

    The source code for this article series is available on GitHub. @@ -376,7 +376,7 @@

    You now have a model of the domain that enables you to express valid values, but that makes illegal states unrepresentable. This is half the battle won, without any moving parts. These types govern what can be stated in the domain, but they don't provide any rules for how values can transition from one state to another.

    - This is a task you can take on with Property-Based Testing. Since all values of these types are valid, it's easy to express the properties of a tennis game score. In the next article, you'll see how to start that work. + This is a task you can take on with Property-Based Testing. Since all values of these types are valid, it's easy to express the properties of a tennis game score. In the next article, you'll see how to start that work.

    If you're interested in learning more about designing with types, you can watch my Type-Driven Development with F# Pluralsight course. diff --git a/_posts/2016-02-10-types--properties--software.html b/_posts/2016-02-10-types--properties--software.html index 0d25ee373..36cb77fc5 100644 --- a/_posts/2016-02-10-types--properties--software.html +++ b/_posts/2016-02-10-types--properties--software.html @@ -17,7 +17,7 @@ When Kent Beck rediscovered Test-Driven Development (TDD) some twenty years ago, the original context was SmallTalk programming. When the concept of TDD began to catch on, it seemed to me to proliferate particularly in dynamic language communities like Python and Ruby.

    - It makes sense that if you can't get fast feedback from a compilation step, you seek another way to get feedback on your work. Unit testing is such a fast feedback mechanism. Watching the NodeJS community from the side, it always seemed to me that TDD is an integral way of working with that stack. This makes sense. + It makes sense that if you can't get fast feedback from a compilation step, you seek another way to get feedback on your work. Unit testing is such a fast feedback mechanism. Watching the NodeJS community from the side, it always seemed to me that TDD is an integral way of working with that stack. This makes sense.

    This also explains why e.g. C# programmers were more reluctant to adopt TDD. That your code compiles gives a smidgen of confidence. @@ -61,16 +61,16 @@

    In this series of articles, you'll see an example of this in F#:

    - If you're interested in learning more, my Type Driven Development article showcases another example of designing with types. My Pluralsight course Type-Driven Development with F# dives even deeper than the article. If you need an introduction to Property-based Testing with F#, that's also available. + If you're interested in learning more, my Type Driven Development article showcases another example of designing with types. My Pluralsight course Type-Driven Development with F# dives even deeper than the article. If you need an introduction to Property-based Testing with F#, that's also available.

    Summary # diff --git a/_posts/2016-02-11-types--properties--software-state-transition-properties.html b/_posts/2016-02-11-types--properties--software-state-transition-properties.html index d8ec6065e..c1faa6dc8 100644 --- a/_posts/2016-02-11-types--properties--software-state-transition-properties.html +++ b/_posts/2016-02-11-types--properties--software-state-transition-properties.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the second in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to design with types so that illegal states are unrepresentable. In this article, you'll see an example of how to express properties for transitions between legal states. + This article is the second in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to design with types so that illegal states are unrepresentable. In this article, you'll see an example of how to express properties for transitions between legal states.

    The source code for this article series is available on GitHub. @@ -61,7 +61,7 @@

    Because the Player type makes illegal states unrepresentable, you're guaranteed that only valid Player values will be passed as the winner argument.

    - (In this particular example, Player can only be the values PlayerOne and PlayerTwo. FsCheck will, because of its default settings, run the property function 100 times, which means that it will generate 100 Player values. With an even distribution, that means that it will generate approximately 50 PlayerOne values, and 50 PlayerTwo values. Wouldn't it be easier, and faster, to use a [<Theory>] that deterministically generates only those two values, without duplication? Yes, in this case it would; This sometimes happens, and it's okay. In this example, though, I'm going to keep using FsCheck, because I think this entire example is a good stand-in for a more complex business problem.) + (In this particular example, Player can only be the values PlayerOne and PlayerTwo. FsCheck will, because of its default settings, run the property function 100 times, which means that it will generate 100 Player values. With an even distribution, that means that it will generate approximately 50 PlayerOne values, and 50 PlayerTwo values. Wouldn't it be easier, and faster, to use a [<Theory>] that deterministically generates only those two values, without duplication? Yes, in this case it would; This sometimes happens, and it's okay. In this example, though, I'm going to keep using FsCheck, because I think this entire example is a good stand-in for a more complex business problem.)

    Regardless of the value of the winner argument, the property should hold that the return value of the scoreWhenDeuce function is that the winner now has the advantage. @@ -133,7 +133,7 @@

    - This would be idiomatic in Haskell, but not quite so much in F#. In my experience, many people find the point-free style less readable, so I'm not going to pursue this type of refactoring for the rest of this article series. + This would be idiomatic in Haskell, but not quite so much in F#. In my experience, many people find the point-free style less readable, so I'm not going to pursue this type of refactoring for the rest of this article series.

    To be continued... # @@ -142,7 +142,7 @@

    In this article, you've seen how to express the single property that when the score is deuce, the winner of the next ball will have the advantage. Because illegal states are unrepresentable, you can declaratively state the type of value(s) the property requires, and FsCheck will have no choice but to give you valid values.

    - In the next article, you'll see how to express properties for slightly more complex state transitions. In this article, I took care to spell out each step in the process, but in the next article, I promise to increase the pace. + In the next article, you'll see how to express properties for slightly more complex state transitions. In this article, I took care to spell out each step in the process, but in the next article, I promise to increase the pace.

    If you're interested in learning more about Property-Based Testing, you can watch my introduction to Property-based Testing with F# Pluralsight course. diff --git a/_posts/2016-02-12-types--properties--software-properties-for-the-advantage-state.html b/_posts/2016-02-12-types--properties--software-properties-for-the-advantage-state.html index 9dfea6025..3584e260d 100644 --- a/_posts/2016-02-12-types--properties--software-properties-for-the-advantage-state.html +++ b/_posts/2016-02-12-types--properties--software-properties-for-the-advantage-state.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the third in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to get started with Property-Based Testing, using a Test-Driven Development tactic. In this article, you'll see the previous Tennis Kata example continued. This time, you'll see how to express properties for the state when one of the players have the advantage. + This article is the third in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to get started with Property-Based Testing, using a Test-Driven Development tactic. In this article, you'll see the previous Tennis Kata example continued. This time, you'll see how to express properties for the state when one of the players have the advantage.

    The source code for this article series is available on GitHub. @@ -34,7 +34,7 @@

        expected =! actual

    - As explained in the previous article, FsCheck will interpret this function and discover that it'll need to generate arbitrary Player values for the advantagedPlayer argument. Because illegal states are unrepresentable, you're guaranteed valid values. + As explained in the previous article, FsCheck will interpret this function and discover that it'll need to generate arbitrary Player values for the advantagedPlayer argument. Because illegal states are unrepresentable, you're guaranteed valid values.

    This property calls the scoreWhenAdvantage function (that doesn't yet exist), passing advantagedPlayer as argument twice. The first argument is an indication of the current score. The scoreWhenAdvantage function only models how to transition out of the Advantage case. The data associated with the Advantage case is the player currently having the advantage, so passing in advantagedPlayer as the first argument describes the current state to the function. @@ -95,7 +95,7 @@

    I decided to place this function in the same module as the scoreWhenGame function, because it seemed like a generally useful function, more than a test-specific function. It turns out that the tennis score module, indeed, does need this function later.

    - Since the other function is part of the module being tested, shouldn't you test it as well? For now, I'll leave it uncovered by directed tests, because it's so simple that I'm confident that it works, just by looking at it. Later, I can return to it in order to add some properties. + Since the other function is part of the module being tested, shouldn't you test it as well? For now, I'll leave it uncovered by directed tests, because it's so simple that I'm confident that it works, just by looking at it. Later, I can return to it in order to add some properties.

    With the other function in place, the new property fails, so you need to change the implementation of scoreWhenAdvantage in order to pass all tests: @@ -119,7 +119,7 @@

    In this article, you saw how to express the properties associated with the advantage state of a tennis game. These properties were each simple. You can express each of them based on any arbitrary input of the given type, as shown here.

    - Even when all test input values are guaranteed to be valid, sometimes you need to manipulate an arbitrary test value in order to describe a particular test case. You'll see how to do this in the next article. + Even when all test input values are guaranteed to be valid, sometimes you need to manipulate an arbitrary test value in order to describe a particular test case. You'll see how to do this in the next article.

    If you're interested in learning more about Property-Based Testing, you can watch my introduction to Property-based Testing with F# Pluralsight course. diff --git a/_posts/2016-02-15-types--properties--software-properties-for-the-forties.html b/_posts/2016-02-15-types--properties--software-properties-for-the-forties.html index 37a61e8f2..4d60f3fac 100644 --- a/_posts/2016-02-15-types--properties--software-properties-for-the-forties.html +++ b/_posts/2016-02-15-types--properties--software-properties-for-the-forties.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the fourth in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to express properties for a simple state transition: finding the next tennis score when the current score is advantage to a player. These properties were simple, because they had to hold for all input of the given type (Player). In this article, you'll see how to constrain the input that FsCheck generates, in order to express properties about tennis scores where one of the players have forty points. + This article is the fourth in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to express properties for a simple state transition: finding the next tennis score when the current score is advantage to a player. These properties were simple, because they had to hold for all input of the given type (Player). In this article, you'll see how to constrain the input that FsCheck generates, in order to express properties about tennis scores where one of the players have forty points.

    The source code for this article series is available on GitHub. @@ -50,7 +50,7 @@

        expected =! actual

    - Notice that this test function takes a single function argument called current, of the type FortyData. Since illegal states are unrepresentable, FsCheck can only generate legal values of that type. + Notice that this test function takes a single function argument called current, of the type FortyData. Since illegal states are unrepresentable, FsCheck can only generate legal values of that type.

    The scoreWhenForty function is a function that explicitly models what happens when the score is in the Forty case. The first argument is the data associated with the current score: current. The second argument is the winner of the next ball. In this test case, you want to express the case where the winner is the player who already has forty points: current.Player. @@ -96,7 +96,7 @@

    The first line of code shadows the current argument by binding the result of the copy-and-update expression to a new value, also called current. Shadowing means that the original current argument is no longer available in the rest of the scope. This is exactly what you want, because the function argument isn't guaranteed to model the test case where the other player has forty points. Instead, it can be any FortyData value. You can think of the argument provided by FsCheck as a seed used to arrange the Test Fixture.

    - The property proceeds to invoke the scoreWhenForty function with the current score, and indicating that the other player wins the ball. You saw the other function in the previous article, but it's so small that it can be repeated here without taking up much space: + The property proceeds to invoke the scoreWhenForty function with the current score, and indicating that the other player wins the ball. You saw the other function in the previous article, but it's so small that it can be repeated here without taking up much space:

    let other = function PlayerOne -> PlayerTwo | PlayerTwo -> PlayerOne
    @@ -171,7 +171,7 @@ 

    In the previous article, you saw how sometimes, a test triggers the creation of a new helper function. Sometimes, such a helper function is of such general utility that it makes sense to put it in the 'production code'. Previously, it was the other function. Now, it's the incrementPoint function.

    - Before I show you the implementation of the incrementPoint function, I would like to suggest that you reflect on it. The purpose of this function is to return the point that comes after a given point. Do you remember how, in the article on designing with types, we quickly realised that love, fifteen, thirty, and forty are mere labels; that we don't need to do arithmetic on these values? + Before I show you the implementation of the incrementPoint function, I would like to suggest that you reflect on it. The purpose of this function is to return the point that comes after a given point. Do you remember how, in the article on designing with types, we quickly realised that love, fifteen, thirty, and forty are mere labels; that we don't need to do arithmetic on these values?

    There's one piece of 'arithmetic' you need to do with these values, after all: you must be able to 'add one' to a value, in order to get the next value. That's the purpose of the incrementPoint function: given Love, it'll return Fifteen, and so on - but with a twist! @@ -236,7 +236,7 @@

    While I could go on and show you how to express properties for more state transitions, you've now seen the most important techniques. If you want to see more of the tennis state transitions, you can always check out the source code accompanying this article series.

    - In the next article, instead, you'll see how to compose all these functions into a system that implements the tennis scoring rules. + In the next article, instead, you'll see how to compose all these functions into a system that implements the tennis scoring rules.

    If you're interested in learning more about Property-Based Testing, you can watch my introduction to Property-based Testing with F# Pluralsight course. diff --git a/_posts/2016-02-16-types--properties--software-composition.html b/_posts/2016-02-16-types--properties--software-composition.html index ba896540f..b737362a1 100644 --- a/_posts/2016-02-16-types--properties--software-composition.html +++ b/_posts/2016-02-16-types--properties--software-composition.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the fifth in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you witnessed the continued walk-through of the Tennis Kata done with Property-Based Test-Driven Development. In these articles, you saw how to define small, specific functions that model the transition out of particular states. In this article, you'll see how to compose these functions to a more general function. + This article is the fifth in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you witnessed the continued walk-through of the Tennis Kata done with Property-Based Test-Driven Development. In these articles, you saw how to define small, specific functions that model the transition out of particular states. In this article, you'll see how to compose these functions to a more general function.

    The source code for this article series is available on GitHub. @@ -21,7 +21,7 @@

    Composing the general function #

    - If you recall the second article in this series, what you need to implement is a state transition of the type Score -> Player -> Score. What you have so far are the following functions: + If you recall the second article in this series, what you need to implement is a state transition of the type Score -> Player -> Score. What you have so far are the following functions:

    • scoreWhenPoints : PointsData -> Player -> Score
    • scoreWhenForty : FortyData -> Player -> Score
    • @@ -29,7 +29,7 @@

    • scoreWhenAdvantage : Player -> Player -> Score
    • scoreWhenGame : Player -> Score
    - You've seen the development of scoreWhenDeuce, scoreWhenAdvantage, and scoreWhenForty in previous articles, but you haven't seen scoreWhenGame or scoreWhenPoints. The development of these remaining functions follow similar principles, and use similar techniques. If you're interested in the details, you can always peruse the source code repository. + You've seen the development of scoreWhenDeuce, scoreWhenAdvantage, and scoreWhenForty in previous articles, but you haven't seen scoreWhenGame or scoreWhenPoints. The development of these remaining functions follow similar principles, and use similar techniques. If you're interested in the details, you can always peruse the source code repository.

    These five functions are all the building blocks you need to implement the desired function of the type Score -> Player -> Score. You may recall that Score is a discriminated union defined as: @@ -43,7 +43,7 @@

    Game of Player

    - Notice how these cases align with the five functions above. That's not a coincidence. The driving factor behind the design of these five function was to match them with the five cases of the Score type. In another article series, I've previously shown this technique, applied to a different problem. + Notice how these cases align with the five functions above. That's not a coincidence. The driving factor behind the design of these five function was to match them with the five cases of the Score type. In another article series, I've previously shown this technique, applied to a different problem.

    You can implement the desired function by clicking the pieces together: @@ -100,7 +100,7 @@

        expected =! actual

    - Such a property is unlikely to be of much use, because it mostly reproduces the implementation details of the score function. Unless you're writing high-stakes software (e.g. for medical purposes), such properties are likely to have little or negative value. After all, tests are also code; do you trust the test code more than the production code? Sometimes, you may, but if you look at the source code for the score function, it's easy to review. + Such a property is unlikely to be of much use, because it mostly reproduces the implementation details of the score function. Unless you're writing high-stakes software (e.g. for medical purposes), such properties are likely to have little or negative value. After all, tests are also code; do you trust the test code more than the production code? Sometimes, you may, but if you look at the source code for the score function, it's easy to review.

    You can write four other properties, similar to the one above, but I'm going to skip them here. They are in the source code repository, though, so you're welcome to look there if you want to see them. @@ -112,7 +112,7 @@

    In this article, you saw how to compose the five specific state transition functions into an overall state transition function. This is only a single function that calculates a score based on another score. In order to turn this function into a finite state machine, you must define an initial state and a way to transition based on a sequence of events.

    - In the next article, you'll see how to define the initial state, and in the article beyond that, you'll see how to move through a sequence of transitions. + In the next article, you'll see how to define the initial state, and in the article beyond that, you'll see how to move through a sequence of transitions.

    If you're interested in learning more about designing with types, you can watch my Type-Driven Development with F# Pluralsight course. diff --git a/_posts/2016-02-17-types--properties--software-initial-state.html b/_posts/2016-02-17-types--properties--software-initial-state.html index 1164451ae..c23c97e58 100644 --- a/_posts/2016-02-17-types--properties--software-initial-state.html +++ b/_posts/2016-02-17-types--properties--software-initial-state.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the sixth in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to compose a function that returns a new score based on a previous score, and information about which player won the ball. In this article, you'll see how to define the initial state of a tennis game. + This article is the sixth in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to compose a function that returns a new score based on a previous score, and information about which player won the ball. In this article, you'll see how to define the initial state of a tennis game.

    The source code for this article series is available on GitHub. @@ -21,7 +21,7 @@

    Initial state #

    - You may recall from the article on designing with types that a Score is a discriminated union. One of the union cases is the Points case, which you can use to model the case where both players have either Love, Fifteen, or Thirty points. + You may recall from the article on designing with types that a Score is a discriminated union. One of the union cases is the Points case, which you can use to model the case where both players have either Love, Fifteen, or Thirty points.

    The game starts with both players at love. You can define this as a value: @@ -52,6 +52,6 @@

    To be continued... #

    - In this article, you saw how to define the initial state for a tennis game. There's nothing to it, but armed with this value, you now have half of the requirements needed to turn the tennis score function into a finite state machine. You'll see how to do that in the next article. + In this article, you saw how to define the initial state for a tennis game. There's nothing to it, but armed with this value, you now have half of the requirements needed to turn the tennis score function into a finite state machine. You'll see how to do that in the next article.

    \ No newline at end of file diff --git a/_posts/2016-02-18-types--properties--software-finite-state-machine.html b/_posts/2016-02-18-types--properties--software-finite-state-machine.html index 7c6a6a334..3e10f5c6f 100644 --- a/_posts/2016-02-18-types--properties--software-finite-state-machine.html +++ b/_posts/2016-02-18-types--properties--software-finite-state-machine.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the seventh in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to define the initial state of a tennis game. In this article, you'll see how to define the tennis game as a finite state machine. + This article is the seventh in a series of articles that demonstrate how to develop software using types and properties. In the previous article, you saw how to define the initial state of a tennis game. In this article, you'll see how to define the tennis game as a finite state machine.

    The source code for this article series is available on GitHub. @@ -161,7 +161,7 @@

            test <@ actual |> (not << isPoints) @>)

    - As previously explained, Prop.forAll expresses a property that must hold for all lists generated by moreThanFourBalls. + As previously explained, Prop.forAll expresses a property that must hold for all lists generated by moreThanFourBalls.

    Correspondingly, if the players have played more than five balls, the score can't be a Forty case: @@ -245,7 +245,7 @@

    In this article series, you've seen an extensive example of how to design with types and properties. You may have noticed that out of the six example articles so far, only the first one was about designing with types, and the next five articles were about Property-Based Testing. It looks as though not much is gained from designing with types.

    - On the contrary, much is gained by designing with types, but you don't see it, exactly because it's efficient. If you don't design with types in order to make illegal states unrepresentable, you'd have to write even more automated tests in order to test what happens when input is invalid. Also, if illegal states are representable, it would have been much harder to write Property-Based Tests. Instead of trusting that FsCheck generates only valid values based exclusively on the types, you'd have to write custom Generators or Arbitraries for each type of input. That would have been even more work than you've seen in this articles series. + On the contrary, much is gained by designing with types, but you don't see it, exactly because it's efficient. If you don't design with types in order to make illegal states unrepresentable, you'd have to write even more automated tests in order to test what happens when input is invalid. Also, if illegal states are representable, it would have been much harder to write Property-Based Tests. Instead of trusting that FsCheck generates only valid values based exclusively on the types, you'd have to write custom Generators or Arbitraries for each type of input. That would have been even more work than you've seen in this articles series.

    Designing with types makes Property-Based Testing a comfortable undertaking. Together, they enable you to develop software that you can trust. diff --git a/_posts/2016-02-19-types--properties--software-other-properties.html b/_posts/2016-02-19-types--properties--software-other-properties.html index 2b6d112a5..5e56a6685 100644 --- a/_posts/2016-02-19-types--properties--software-other-properties.html +++ b/_posts/2016-02-19-types--properties--software-other-properties.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is the eighth in a series of articles that demonstrate how to develop software using types and properties. In previous articles, you've seen an extensive example of how to solve the Tennis Kata with type design and Property-Based Testing. Specifically, in the third article, you saw the introduction of a function called other. In that article we didn't cover that function with automatic tests, but this article rectifies that omission. + This article is the eighth in a series of articles that demonstrate how to develop software using types and properties. In previous articles, you've seen an extensive example of how to solve the Tennis Kata with type design and Property-Based Testing. Specifically, in the third article, you saw the introduction of a function called other. In that article we didn't cover that function with automatic tests, but this article rectifies that omission.

    The source code for this article series is available on GitHub. diff --git a/_posts/2016-03-01-ad-hoc-arbitraries---now-with-pipes.html b/_posts/2016-03-01-ad-hoc-arbitraries---now-with-pipes.html index c33a34b46..94e00650c 100644 --- a/_posts/2016-03-01-ad-hoc-arbitraries---now-with-pipes.html +++ b/_posts/2016-03-01-ad-hoc-arbitraries---now-with-pipes.html @@ -12,7 +12,7 @@ {{ page.description }}

    - Last year, I described how to define and use ad-hoc, in-line Arbitraries with FsCheck.Xunit. The final example code looked like this: + Last year, I described how to define and use ad-hoc, in-line Arbitraries with FsCheck.Xunit. The final example code looked like this:

    [<Property(QuietOnSuccess = true)>]
    @@ -106,6 +106,6 @@ 

    When the last argument passed to a function is another function, you can replace the brackets with a single application of the <| operator. I only use this operator sparingly, but in the case of in-line ad-hoc FsCheck Arbitraries, I find it useful.

    - Addendum 2016-05-17: You can get rid of the nc value with TIE fighter infix notation. + Addendum 2016-05-17: You can get rid of the nc value with TIE fighter infix notation.

    \ No newline at end of file diff --git a/_posts/2016-03-18-functional-architecture-is-ports-and-adapters.html b/_posts/2016-03-18-functional-architecture-is-ports-and-adapters.html index 59067b469..a385c481e 100644 --- a/_posts/2016-03-18-functional-architecture-is-ports-and-adapters.html +++ b/_posts/2016-03-18-functional-architecture-is-ports-and-adapters.html @@ -14,7 +14,7 @@ {{ page.description }}

    - In object-oriented architecture, we often struggle towards the ideal of the Ports and Adapters architecture, although we often call it something else: layered architecture, onion architecture, hexagonal architecture, and so on. The goal is to decouple the business logic from technical implementation details, so that we can vary each independently. + In object-oriented architecture, we often struggle towards the ideal of the Ports and Adapters architecture, although we often call it something else: layered architecture, onion architecture, hexagonal architecture, and so on. The goal is to decouple the business logic from technical implementation details, so that we can vary each independently.

    This creates value because it enables us to manoeuvre nimbly, responding to changes in business or technology. @@ -32,7 +32,7 @@

    The word adapter is aptly chosen, because the role of the Adapter design pattern is exactly to translate between two different interfaces.

    - You ought to arrive at some sort of variation of Ports and Adapters if you apply Dependency Injection, as I've previously attempted to explain. + You ought to arrive at some sort of variation of Ports and Adapters if you apply Dependency Injection, as I've previously attempted to explain.

    The problem with this architecture, however, is that it seems to take a lot of explaining: @@ -121,7 +121,7 @@

    Here, SqlGateway.getReservedSeats connectionString is a partially applied function, the type of which is DateTimeOffset -> int. In F#, you can't tell by its type that it's impure, but I know that this is the case because I wrote it. It queries a database, so isn't referentially transparent.

    - This works well in F#, where it's up to you whether a particular function is pure or impure. Since that imp function is composed in the application's Composition Root, the impure functions SqlGateway.getReservedSeats and SqlGateway.saveReservation are only pulled in at the edge of the system. The rest of the system is nicely protected against side-effects. + This works well in F#, where it's up to you whether a particular function is pure or impure. Since that imp function is composed in the application's Composition Root, the impure functions SqlGateway.getReservedSeats and SqlGateway.saveReservation are only pulled in at the edge of the system. The rest of the system is nicely protected against side-effects.

    It feels Functional, but is it? @@ -248,7 +248,7 @@

    This almost looks more complicated than the Haskell function. Haskell has the advantage that you can automatically use any type that implements the Monad typeclass inside of a do block, and since (EitherT Error IO) () is a Monad instance, the do syntax is available for free.

    - You could do something similar in F#, but then you'd have to implement a custom computation expression builder for the Result type. Perhaps I'll do this in a later blog post... + You could do something similar in F#, but then you'd have to implement a custom computation expression builder for the Result type. Perhaps I'll do this in a later blog post...

    Summary # @@ -271,7 +271,7 @@

    Comments

    2016-03-18 23:00 UTC
    - +

    Arkadiusz, thank you for writing. It's the first time I see that post, but if I understand the argument correctly, it argues against the (over)use of the monad terminology when talking about IO actions that aren't intrinsically monadic in nature. As far as I can tell, it doesn't argue against the use of the IO type in Haskell. @@ -366,7 +366,7 @@

    Comments

    2016-03-24 23:30 UTC
    - +

    John, thank you for writing. I'm not sure I can answer everything to your satisfaction in single response, but we can always view this as a beginning of longer interchange. Some of the doubts you express are ambiguous, so I'm not sure how to interpret them, but I'll do my best to be as explicit as possible. @@ -454,7 +454,7 @@

    Comments

    Additionally, a kiosk may need to be able to work in off-line, or occasionally connected, mode, so perhaps you'd prefer a different data store implementation. Instead of connecting directly to a database, such an application would need to write to a message queue, and read from an off-line snapshot of reservations.

    - That's a sufficiently different application that it warrants creating applications from fine-grained building blocks instead of course-grained building blocks. Perhaps the only part you'll end up reusing is the core business logic contained in the check[Capacity] function. Composition Roots aren't reusable. + That's a sufficiently different application that it warrants creating applications from fine-grained building blocks instead of course-grained building blocks. Perhaps the only part you'll end up reusing is the core business logic contained in the check[Capacity] function. Composition Roots aren't reusable.

    (As an aside, you may think that if the check[Capacity] function is the only reusable part, then what's the point? This function is only a couple of lines long, so why even bother? That'd be a fair concern, if it wasn't for the context that all of this is only example code. Think of this example as a stand-in for much more complex business logic. Perhaps the restaurant will allow a certain percentage of over-booking, because some people never show up. Perhaps it will allow different over-booking percentages on different (week) days. Perhaps it'll need to handle reservations on per-table basis, instead of per-seat. Perhaps it'll need to handle multiple seatings on the same day. There are lots of variations you can throw into this business domain that will make it much more complex, and worthy of reuse.) @@ -463,7 +463,7 @@

    Comments

    Brittleness of composition

    - Finally, you refer to a more realistic scenario, called performOvernightCloseout, and ask if a fine-grained composition wouldn't be brittle? In my experience, it wouldn't be more brittle than any alternatives I've identified. Whether you 'inject' functions into other functions, or you compose them in the Composition Root, doesn't change the underlying forces that act on your code. If you make substantial changes to the dependencies involved, it will break your code, and you'll need to address that. This is true for any manual composition, including Pure DI. The only way to avoid compilation errors when you redefine your dependency graphs is to use a DI Container, but that only makes the feedback loop worse, because it'd change a compile-time error into a run-time error. + Finally, you refer to a more realistic scenario, called performOvernightCloseout, and ask if a fine-grained composition wouldn't be brittle? In my experience, it wouldn't be more brittle than any alternatives I've identified. Whether you 'inject' functions into other functions, or you compose them in the Composition Root, doesn't change the underlying forces that act on your code. If you make substantial changes to the dependencies involved, it will break your code, and you'll need to address that. This is true for any manual composition, including Pure DI. The only way to avoid compilation errors when you redefine your dependency graphs is to use a DI Container, but that only makes the feedback loop worse, because it'd change a compile-time error into a run-time error.

    This is a long answer, and even so, I'm not sure I've sufficiently addressed all of your concerns. If not, please write again for clarifications. @@ -515,7 +515,7 @@

    Comments

    - +

    John, thank you for writing. It's OK to reject the concept of ports and adapters; it's not a one-size-fits-all architecture. While I often use it, I don't always use it. One of my most successful customer engagements involved building a set of REST APIs on top of an existing IT infrastructure. All the business logic was already implemented elsewhere, so I deliberately chose a simpler, more coupled architecture, because there'd be no benefit from a full ports and adapters architecture. The code bases involved still run in production four years later, even though they're constantly being changed and enhanced. @@ -606,10 +606,10 @@

    Comments

    2016-06-09 10:56 UTC
    - +

    - Martin, thank you for writing. Your question prompted me to write a new article. It takes a slightly different approach to the one you suggest. + Martin, thank you for writing. Your question prompted me to write a new article. It takes a slightly different approach to the one you suggest.

    I haven't tried defining checkCapacity in the way you suggest, but that may be an exercise for another day. In general, though, I'm hesitant to introduce constraints not required by the implementation. In this case, I think it'd be a fair question to ask why the getReservedSeats argument has to have the type ZonedTime -> m Int? Nothing in its implementation seems to indicate the need for that, so it looks like a leaky abstraction to me. @@ -625,7 +625,7 @@

    Comments

    Very interesting article! I'm sorry that some Haskell details are quite difficult for me at the moment and the F# code looks a bit too simplified or maybe just incomplete

    - So I'd prefer your approach here : it better translates Haskell to F# but I still have to study its implications. Anyway the concrete benefits of Async are evident, like the ones of F# computation expressions (to wrap exceptions etc...) + So I'd prefer your approach here : it better translates Haskell to F# but I still have to study its implications. Anyway the concrete benefits of Async are evident, like the ones of F# computation expressions (to wrap exceptions etc...)

    On the other hand I fail to see the benefit of purity vs other IoC patterns. Besides async and exceptions wrapping, purity seems an unnecessarily strict enforcement of Haskell (isn't it?): original F# was testable in isolation

    @@ -635,7 +635,7 @@

    Comments

    2017-01-20 10:45 UTC
    - +
    Giulio, thank you for writing. Why do you think that the only goal of pure functions is testability?
    @@ -677,7 +677,7 @@

    Comments

    2017-01-20 20:02:00 UTC
    - +

    First, I should make it specific that when I discuss object-oriented code in general, and encapsulation specifically, I tend to draw heavily on the work of Bertrand Meyer in Object-Oriented Software Construction. Some people may regard Alan Kay as the original inventor of object-orientation, but C# and Java's interpretation of object-oriented programming seems closer to Meyer's than to Kay's. @@ -710,7 +710,7 @@

    Comments

    This is one of the many benefits of pure functions: we know, by definition, that they have no side-effects. This property holds not only for the function itself, but for all functions that that pure function calls. This follows from the definition of purity. A pure function can call other pure functions, but it can't call impure functions, because, if it did, it would become impure itself. Haskell enforces this rule, so when you're looking at a pure function, you know that that entire subgraph of your code is pure. Otherwise, it wouldn't compile.

    - Not only does that relationship force us to push impure functions to the boundary of applications, as described in the present article. It also makes functions intrinsically testable. There are other advantages of pure functions besides these, such as easy composability, but in general, pure functions are attractive because it becomes easier to figure out what a function does without having to understand all the details. In other words, pure functions are better abstractions. + Not only does that relationship force us to push impure functions to the boundary of applications, as described in the present article. It also makes functions intrinsically testable. There are other advantages of pure functions besides these, such as easy composability, but in general, pure functions are attractive because it becomes easier to figure out what a function does without having to understand all the details. In other words, pure functions are better abstractions.

    To be clear: functional programming doesn't protect you from defects, but in my experience, it helps you to avoid entire classes of bugs. I still write automated tests of my F# code, but I write fewer tests than when I wrote C# code. Despite that, I also seem to be producing fewer defects, and I rarely need to debug the functions. @@ -737,13 +737,13 @@

    Comments

    2017-03-12 20:47 UTC
    - +

    - Abel, thank you for writing. There's a discussion closely related to that question in the remarks sections of my dependency rejection article. It's the remark from 2017-02-18 19:54 UTC (I really ought to get around to add permalinks to comments...). + Abel, thank you for writing. There's a discussion closely related to that question in the remarks sections of my dependency rejection article. It's the remark from 2017-02-18 19:54 UTC (I really ought to get around to add permalinks to comments...).

    - Additionally, there's a discussion on this page that lead to a new article that goes into some further details. + Additionally, there's a discussion on this page that lead to a new article that goes into some further details.

    2017-03-13 06:42 UTC
    diff --git a/_posts/2016-03-21-composition-with-an-either-computation-expression.html b/_posts/2016-03-21-composition-with-an-either-computation-expression.html index d7844e985..da68265ba 100644 --- a/_posts/2016-03-21-composition-with-an-either-computation-expression.html +++ b/_posts/2016-03-21-composition-with-an-either-computation-expression.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In a previous article, you saw how to compose an application feature from functions: + In a previous article, you saw how to compose an application feature from functions:

    let imp =
    @@ -93,13 +93,13 @@ 

    Notice how the r value can be used by both the SqlGateway.getReservedSeats and Capacity.check functions, because they are all within the same scope.

    - This example looks more like the Haskell composition in my previous article. It even looks cleaner in F#, but to be fair to Haskell, in F# you don't have to explicitly deal with IO as a monadic context, so that in itself makes things look simpler. + This example looks more like the Haskell composition in my previous article. It even looks cleaner in F#, but to be fair to Haskell, in F# you don't have to explicitly deal with IO as a monadic context, so that in itself makes things look simpler.

    A variation using shadowing #

    - You may wonder why I chose to use return! with an expression using the map function. One reason was that I wanted to avoid having to bind a named value to the result of calling Capacity.check. Naming is always difficult, and while I find the names r and i acceptable because the scope is so small, I prefer composing functions without having to declare intermediary values. + You may wonder why I chose to use return! with an expression using the map function. One reason was that I wanted to avoid having to bind a named value to the result of calling Capacity.check. Naming is always difficult, and while I find the names r and i acceptable because the scope is so small, I prefer composing functions without having to declare intermediary values.

    Another reason was that I wanted to show you an example that resembles the previous Haskell example as closely as possible. diff --git a/_posts/2016-04-11-async-as-surrogate-io.html b/_posts/2016-04-11-async-as-surrogate-io.html index 6553521a7..571090d4a 100644 --- a/_posts/2016-04-11-async-as-surrogate-io.html +++ b/_posts/2016-04-11-async-as-surrogate-io.html @@ -12,7 +12,7 @@ {{ page.description }}

    - As a reaction to my article on the relationship between Functional architecture and Ports and Adapters, Szymon Pobiega suggested on Twitter: + As a reaction to my article on the relationship between Functional architecture and Ports and Adapters, Szymon Pobiega suggested on Twitter:

    random idea: in c# “IO Int” translates to “Task<int>”. By consistently using this we can make type system help you even in c#
    @@ -37,13 +37,13 @@

    This is similar to the distinction between pure and impure functions. You can call pure functions from impure functions, but not the other way around. If you call an impure function from a 'pure' function in F#, the caller also automatically becomes impure. In Haskell, it's not even possible; you can call a pure function from an IO context, but not the other way around.

    - In F#, Async<'a> is more idiomatic than using Task<T>. While Async<'a> doesn't translate directly to Haskell's IO either, it's worth experimenting with the analogy. + In F#, Async<'a> is more idiomatic than using Task<T>. While Async<'a> doesn't translate directly to Haskell's IO either, it's worth experimenting with the analogy.

    Async I/O #

    - In the previous Haskell example, communication with the database were implemented by functions returning IO: + In the previous Haskell example, communication with the database were implemented by functions returning IO:

    getReservedSeatsFromDB :: ConnectionString -> ZonedTime -> IO Int
    @@ -64,7 +64,7 @@ 

            // ...

    - This makes it harder to compose the desired imp function, because you need to deal with both asynchronous work-flows and the Either monad. In Haskell, the building blocks are already there in the shape of the EitherT monad transformer. F# doesn't have monad transformers, but in the spirit of the previous article, you can define a computation expression that combines Either and Async: + This makes it harder to compose the desired imp function, because you need to deal with both asynchronous work-flows and the Either monad. In Haskell, the building blocks are already there in the shape of the EitherT monad transformer. F# doesn't have monad transformers, but in the spirit of the previous article, you can define a computation expression that combines Either and Async:

    type AsyncEitherBuilder () =
    @@ -116,7 +116,7 @@ 

                |> liftAsync }

    - Notice how, in contrast with the previous example, this expression uses let! and return! throughout, but that you have to compose each line with asyncReturn or liftAsync in order to pull out the appropriate values. + Notice how, in contrast with the previous example, this expression uses let! and return! throughout, but that you have to compose each line with asyncReturn or liftAsync in order to pull out the appropriate values.

    As an example, the original, unmodified Validate.reservation function has the type ReservationRendition -> Result<Reservation, Error>. Inside an asyncEither expression, however, all let!-bound values must be of the type Async<Result<'a, 'b>>, so you need to wrap the return value Result<Reservation, Error> in Async. That's what asyncReturn does. Since this expression is let!-bound, the r value has the type Reservation. It's 'double-unwrapped', if you will. @@ -220,7 +220,7 @@

    2016-04-16 15:55 UTC

    - +

    Diogo, thank you for writing. The point about Tasks not being referentially transparent is well taken. You are, indeed, correct. diff --git a/_posts/2016-05-06-cqs-and-server-generated-entity-ids.html b/_posts/2016-05-06-cqs-and-server-generated-entity-ids.html index 1c73cd592..a1cb3c6a2 100644 --- a/_posts/2016-05-06-cqs-and-server-generated-entity-ids.html +++ b/_posts/2016-05-06-cqs-and-server-generated-entity-ids.html @@ -15,7 +15,7 @@ In my Encapsulation and SOLID course on Pluralsight, I explain how the elusive object-oriented quality encapsulation can be approximated by the actionable principles of Command Query Separation (CQS) and Postel's law.

    - One of the questions that invariably arise when people first learn about CQS is how to deal with (database) server-generated IDs. While I've already covered that question, I recently came upon a variation of the question: + One of the questions that invariably arise when people first learn about CQS is how to deal with (database) server-generated IDs. While I've already covered that question, I recently came upon a variation of the question:

    "The Create method is a command, then if the object passed to this method have some changes in their property, does it violate any rule? I mean that we can always get the new id from the object itself, so we don't need to return another integer. Is it good or bad practice?"
    @@ -96,7 +96,7 @@

    This will result in duplicated entries, because the repository can't detect whether this is a replay, or simply two new users with the same name. You may find this example contrived, but in these days of cloud-based storage, it's common to apply retry strategies to clients.

    - If you use one of the alternatives I previously outlined, you will not have this problem. + If you use one of the alternatives I previously outlined, you will not have this problem.

    Invariants # @@ -174,7 +174,7 @@

    Other methods can still use the User class as either input or output, because once the Entity has an ID, its invariants are satisfied.

    - There are other problems with this design, though, so I still prefer the alternatives I originally sketched. + There are other problems with this design, though, so I still prefer the alternatives I originally sketched.

    Conclusion # @@ -203,13 +203,13 @@

    Comments

    - +

    Vladimir, thank you for writing. Exactly how you get the ID depends on the exact requirements of your application. As an example, if you're developing a web application, you may simply be creating the user, and then that's the end of the HTTP request. Meanwhile, asynchronously, a background process is performing the actual database insertion and subsequently sends an email to the user with a link to click in order to verify the email. In that link is the generated ID, so when your server receives the next request, you already know the ID.

    - That may not always be a practical strategy, but I started to describe this technique, because my experience with CQRS and REST tells me that you have lots of options for communicating state and identity. Still, if you need an ID straight away, you can always pass a GUID as a correlation ID, so that you can later find the Entity you created. That's the technique I originally described. + That may not always be a practical strategy, but I started to describe this technique, because my experience with CQRS and REST tells me that you have lots of options for communicating state and identity. Still, if you need an ID straight away, you can always pass a GUID as a correlation ID, so that you can later find the Entity you created. That's the technique I originally described.

    2016-05-06 19:04 UTC
    @@ -259,10 +259,10 @@

    Comments

    - +

    - Ethan, thank you for your comment; I agree with 90 percent of what you wrote, which is also the reason I prefer the options I previously outlined. + Ethan, thank you for your comment; I agree with 90 percent of what you wrote, which is also the reason I prefer the options I previously outlined.

    Entities don't always have 'natural IDs', though, and even when they have, experience has taught me not to use them. Is a person's email address a natural ID? It is, but people change email addresses. diff --git a/_posts/2016-05-17-tie-fighter-fscheck-properties.html b/_posts/2016-05-17-tie-fighter-fscheck-properties.html index c4f56b563..5e5aae964 100644 --- a/_posts/2016-05-17-tie-fighter-fscheck-properties.html +++ b/_posts/2016-05-17-tie-fighter-fscheck-properties.html @@ -15,13 +15,13 @@ A doctrine of Clean Code is the Boy Scout Rule: leave the code cleaner than you found it. Attempting to live by that rule, I'm always looking for ways to improve my code.

    - Writing properties with FsCheck is enjoyable, but I've been struggling with expressing ad-hoc Arbitraries in a clean style. Although I've already twice written about this, I've recently found another improvement. + Writing properties with FsCheck is enjoyable, but I've been struggling with expressing ad-hoc Arbitraries in a clean style. Although I've already twice written about this, I've recently found another improvement.

    Cleaner, but not clean enough #

    - Previously, I've described how you can use the backward pipe operator to avoid enclosing a multi-line expression in brackets: + Previously, I've described how you can use the backward pipe operator to avoid enclosing a multi-line expression in brackets:

    [<Property(QuietOnSuccess = true)>]
    diff --git a/_posts/2016-06-15-sut-double.html b/_posts/2016-06-15-sut-double.html
    index c004d2d04..534f7ab3b 100644
    --- a/_posts/2016-06-15-sut-double.html
    +++ b/_posts/2016-06-15-sut-double.html
    @@ -148,7 +148,7 @@ 

    Since both ReadReservedSeats and SaveReservation are virtual, Moq can override them with test-specific behaviour. In this test, it defines the behaviour of ReadReservedSeats in such a way that it returns 0 when the input is a particular date.

    - While the test is simple, it has a single blemish. It ought to follow the Arrange Act Assert pattern, so it shouldn't have to configure the SaveReservation method before it calls the Post method. After all, the SaveReservation method is a Command, and you should use Mocks for Commands. In other words, the test ought to verify the interaction with the SaveReservation method in the Assert phase; not configure it in the Arrange phase. + While the test is simple, it has a single blemish. It ought to follow the Arrange Act Assert pattern, so it shouldn't have to configure the SaveReservation method before it calls the Post method. After all, the SaveReservation method is a Command, and you should use Mocks for Commands. In other words, the test ought to verify the interaction with the SaveReservation method in the Assert phase; not configure it in the Arrange phase.

    Unfortunately, if you don't configure the SaveReservation method before calling Post, Moq will use the base implementation, which will attempt to interact with the database. The database isn't available in the unit test context, so without that override, the base method will throw an exception, causing the test to fail. @@ -528,7 +528,7 @@

    You may be wondering about the potential memory leak when the SqlReservationsRepository is in use. After all, ReservationsController doesn't dispose of the injected repository.

    - You address this concern when you compose the dependency graph. This example uses ASP.NET Web API, which has an extensibility point for this exact purpose: + You address this concern when you compose the dependency graph. This example uses ASP.NET Web API, which has an extensibility point for this exact purpose:

    public class PureCompositionRoot : IHttpControllerActivator
    diff --git a/_posts/2016-06-28-roman-numerals-via-property-based-tdd.html b/_posts/2016-06-28-roman-numerals-via-property-based-tdd.html
    index eb1b72f66..c5f5e54aa 100644
    --- a/_posts/2016-06-28-roman-numerals-via-property-based-tdd.html
    +++ b/_posts/2016-06-28-roman-numerals-via-property-based-tdd.html
    @@ -273,7 +273,7 @@ 

    In this property, the function argument i can be any number, but calling abs ensures that it's positive (or zero), and the unary - operator then converts that positive value to a negative value.

    - Notice that the new i value shadows the input argument of the same name. This is a common trick when writing properties. It prevents me from accidentally using the input value provided by FsCheck. While the input argument is useful as a seed value, it isn't guaranteed to model the particular circumstances of this property. Here, you only care to assert what happens if the input is negative or zero. Specifically, you always want the return value to be None. + Notice that the new i value shadows the input argument of the same name. This is a common trick when writing properties. It prevents me from accidentally using the input value provided by FsCheck. While the input argument is useful as a seed value, it isn't guaranteed to model the particular circumstances of this property. Here, you only care to assert what happens if the input is negative or zero. Specifically, you always want the return value to be None.

    Likewise for too large input values: @@ -341,7 +341,7 @@

        else None

    - Both functions use tail-recursive inner imp functions in order to accumulate the appropriate answer. + Both functions use tail-recursive inner imp functions in order to accumulate the appropriate answer.

    One of the nice properties (that I didn't test for) of this implementation is that the tryParseRoman function is a Tolerant Reader. While toRoman would never create such a numeral, tryParseRoman correctly understands some alternative renderings: @@ -362,7 +362,7 @@

    Some problems look, at first glance, as obvious candidates for example-driven development. In my experience, this particularly happen when obvious examples abound. It's not difficult to come up with examples of Roman numerals, so it seems intuitive that you should just start writing some test cases with various examples. In my experience, though, that doesn't guarantee that you're led towards a good implementation.

    - The more a problem description is based on examples, the harder it can be to identify the underlying properties. Still, they're often there, once you start looking. As I've previously reported, using property-based test-driven development enables you to proceed in a more incremental fashion, because properties describe only parts of the desired solution. + The more a problem description is based on examples, the harder it can be to identify the underlying properties. Still, they're often there, once you start looking. As I've previously reported, using property-based test-driven development enables you to proceed in a more incremental fashion, because properties describe only parts of the desired solution.

    If you're interested in learning more about Property-Based Testing, you can watch my introduction to Property-based Testing with F# Pluralsight course. diff --git a/_posts/2016-07-04-conditional-composition-of-functions.html b/_posts/2016-07-04-conditional-composition-of-functions.html index 94119ae0d..8800ead41 100644 --- a/_posts/2016-07-04-conditional-composition-of-functions.html +++ b/_posts/2016-07-04-conditional-composition-of-functions.html @@ -12,10 +12,10 @@ {{ page.description }}

    - In my article on how Functional Architecture falls into the Ports and Adapters pit of success, I describe how Haskell forces you to separate concerns: + In my article on how Functional Architecture falls into the Ports and Adapters pit of success, I describe how Haskell forces you to separate concerns:

    • - Your Domain Model should be pure, with business decisions implemented by pure functions. Not only does it make it easier for you to reason about the business logic, it also has the side-benefit that pure functions are intrinsically testable.
    • + Your Domain Model should be pure, with business decisions implemented by pure functions. Not only does it make it easier for you to reason about the business logic, it also has the side-benefit that pure functions are intrinsically testable.
    • Side-effects, and other impure operations (such as database queries) can be isolated and implemented as humble functions.
    • @@ -32,7 +32,7 @@

      Caravans for extra space #

      - Based on my previous restaurant-booking example, Martin Rykfors suggests "a new feature request. The restaurant has struck a deal with the local caravan dealership, allowing them to rent a caravan to park outside the restaurant in order to increase the seating capacity for one evening. Of course, sometimes there are no caravans available, so we'll need to query the caravan database to see if there is a big enough caravan available that evening:" + Based on my previous restaurant-booking example, Martin Rykfors suggests "a new feature request. The restaurant has struck a deal with the local caravan dealership, allowing them to rent a caravan to park outside the restaurant in order to increase the seating capacity for one evening. Of course, sometimes there are no caravans available, so we'll need to query the caravan database to see if there is a big enough caravan available that evening:"

      findCaravan :: ServiceAddress -> Int -> ZonedTime -> IO (Maybe Caravan)
      @@ -237,7 +237,7 @@

      Comments

      2016-07-04 19:05 UTC

    - +

    Martin, I'm still experimenting with how that influences my F# code. I'd like to at least attempt to back-port something like this to F# using computation expressions, but it may turn out that it's not worth the effort. diff --git a/_posts/2016-08-09-untyped-f-http-route-defaults-for-aspnet-web-api.html b/_posts/2016-08-09-untyped-f-http-route-defaults-for-aspnet-web-api.html index 282bc29c9..15aeebb5e 100644 --- a/_posts/2016-08-09-untyped-f-http-route-defaults-for-aspnet-web-api.html +++ b/_posts/2016-08-09-untyped-f-http-route-defaults-for-aspnet-web-api.html @@ -73,7 +73,7 @@

    The API design of the MapHttpRoute method seems forged with C# in mind. I don't know how it works in Visual Basic .NET, but in F# there are no anonymous objects. How do you supply route defaults, then?

    - As I described in my article on creating an F# Web API project, you can define a record type: + As I described in my article on creating an F# Web API project, you can define a record type:

    type HttpRouteDefaults = { Controller : string; Id : obj }
    diff --git a/_posts/2016-09-26-decoupling-decisions-from-effects.html b/_posts/2016-09-26-decoupling-decisions-from-effects.html
    index 6520b6c15..56b4e9b2b 100644
    --- a/_posts/2016-09-26-decoupling-decisions-from-effects.html
    +++ b/_posts/2016-09-26-decoupling-decisions-from-effects.html
    @@ -12,7 +12,7 @@
     		{{ page.description }}
     	

    - Functional programmers love pure functions. Not only do they tend to be easy to reason about, they are also intrinsically testable. It'd be wonderful if we could build entire systems only from pure functions, but every functional programmer knows that the world is impure. Instead, we strive towards implementing as much of our code base as pure functions, so that an application is impure only at its boundaries. + Functional programmers love pure functions. Not only do they tend to be easy to reason about, they are also intrinsically testable. It'd be wonderful if we could build entire systems only from pure functions, but every functional programmer knows that the world is impure. Instead, we strive towards implementing as much of our code base as pure functions, so that an application is impure only at its boundaries.

    The more you can do this, the more testable the system becomes. One rule of thumb about unit testing that I often use is that if a particular candidate for unit testing has a cyclomatic complexity of 1, it may be acceptable to skip unit testing it. Instead, we can consider such a unit a humble unit. If you can separate decisions from effects (which is what functional programmers often call impurities), you can often make the impure functions humble. @@ -268,7 +268,7 @@

    Comments

    2016-10-14 09:06 UTC

    - +

    Grzegorz, thank you for writing. You make a good point, and in a sense you're correct. F# doesn't enforce purity, and this is both an advantage and a disadvantage. It's an advantage because it makes it easier for programmers migrating from C# to make a gradual transition to a more functional programming style. It's also an advantage exactly because it relies on the programmer's often-faulty reasoning to ensure that code is properly functional. diff --git a/_posts/2016-10-25-when-variable-names-are-in-the-way.html b/_posts/2016-10-25-when-variable-names-are-in-the-way.html index e3190c8ec..7efcad8fd 100644 --- a/_posts/2016-10-25-when-variable-names-are-in-the-way.html +++ b/_posts/2016-10-25-when-variable-names-are-in-the-way.html @@ -47,7 +47,7 @@

    A naive unit test attempt #

    - Each HTTP request is handled at the boundary of the system, and the boundary of the system is always impure - even in Haskell. This is particularly clear in the case of the above PushController, because it handles Success (). In success cases, the result is () (unit), which strongly implies a side effect. Thus, a unit test ought to care not only about what imp returns, but also the input to the function. + Each HTTP request is handled at the boundary of the system, and the boundary of the system is always impure - even in Haskell. This is particularly clear in the case of the above PushController, because it handles Success (). In success cases, the result is () (unit), which strongly implies a side effect. Thus, a unit test ought to care not only about what imp returns, but also the input to the function.

    While you could write a unit test like the following, it'd be naive. @@ -66,7 +66,7 @@

                |> Option.exists ((=msg) @>

    - This unit test uses FsCheck's integration for xUnit.net, and Unquote for assertions. Additionally, it uses a convertsTo function that I've previously described. + This unit test uses FsCheck's integration for xUnit.net, and Unquote for assertions. Additionally, it uses a convertsTo function that I've previously described.

    The imp function for PushController must have the type PushRequestDtr -> Result<unit, BoundaryFailure>. In the unit test, it uses a wild-card (_) for the input value, so its type is 'a -> Result<'b, BoundaryFailure>. That's a wider type, but it matches the required type, so the test compiles (and passes). @@ -294,10 +294,10 @@

    When talking about unit testing, I prefer the vocabulary of xUnit Test Patterns, because of its unrivalled consistent terminology. Using Gerard Meszaros' nomenclature, a Test Double with built-in verification of interaction is called a Mock.

    - Most people (including me) dislike Mocks because they tend to lead to brittle unit tests. They tend to, but sometimes you need them. Mocks are useful when you care about side-effects. + Most people (including me) dislike Mocks because they tend to lead to brittle unit tests. They tend to, but sometimes you need them. Mocks are useful when you care about side-effects.

    - Functional programming emphasises pure functions, which, by definition, are free of side-effects. In pure functional programming, you don't need Mocks. + Functional programming emphasises pure functions, which, by definition, are free of side-effects. In pure functional programming, you don't need Mocks.

    Since F# is a multi-paradigmatic language, you sometimes have to write code in a more object-oriented style. In the example you've seen here, I've shown you how to unit test that Controllers correctly work as Adapters over (impure) functions. Here, Mocks are useful, even if they have no place in the rest of the code base. diff --git a/_posts/2016-11-28-easy-domain-modelling-with-types.html b/_posts/2016-11-28-easy-domain-modelling-with-types.html index d0be791f8..0170cb512 100644 --- a/_posts/2016-11-28-easy-domain-modelling-with-types.html +++ b/_posts/2016-11-28-easy-domain-modelling-with-types.html @@ -104,7 +104,7 @@

    C# attempts #

    - Most C# developers would, I think, attempt to model a payment transaction with a class. If they aim for poka-yoke design, they might come up with a design like this: + Most C# developers would, I think, attempt to model a payment transaction with a class. If they aim for poka-yoke design, they might come up with a design like this:

    public class PaymentType
    @@ -132,7 +132,7 @@ 

    This goes a fair way towards making illegal states unrepresentable, but it doesn't communicate to a fellow programmer how it should be used.

    - Code that uses instances of this PaymentType class could attempt to read the OriginalTransactionKey, which, depending on the type of payment, could return null. That sort of design leads to defensive coding. + Code that uses instances of this PaymentType class could attempt to read the OriginalTransactionKey, which, depending on the type of payment, could return null. That sort of design leads to defensive coding.

    Other people might attempt to solve the problem by designing a class hierarchy: @@ -218,7 +218,7 @@

    There are more reasons to love F# than only its algebraic data types, but this is the foremost reason I find it a better language for mainstream development work than C#.

    - If you want to see a more complex example of modelling with types, a good next step would be the first article in my Types + Properties = Software article series. + If you want to see a more complex example of modelling with types, a good next step would be the first article in my Types + Properties = Software article series.

    Finally, I should be careful that I don't oversell the idea of making illegal states unrepresentable. Algebraic data types give you an extra dimension in which you can model domains, but there are still rules that they can't enforce. As an example, you can't state that integers must only fall in a certain range (e.g. only positive integers allowed). There are other type systems, such as dependent types, that give you even more power to embed domain rules into types, but as far as I know, there are no type systems that can fully model all rules as types. You'll still have to write some code as well. @@ -243,10 +243,10 @@

    Comments

    2016-12-03 08:38 UTC
    - +

    - Botond, thank you for writing. The major advantage is that enumeration of all possible cases is available at compile-time. One derived advantage of that is that the compiler can check whether a piece of code handles all cases. That's already, in my experience, a big deal. The sooner you can get feedback on your work, the better, and it doesn't get faster than compile-time feedback. + Botond, thank you for writing. The major advantage is that enumeration of all possible cases is available at compile-time. One derived advantage of that is that the compiler can check whether a piece of code handles all cases. That's already, in my experience, a big deal. The sooner you can get feedback on your work, the better, and it doesn't get faster than compile-time feedback.

    Another advantage of having all cases encoded in the type system is that it gives you better tool support. Imagine that you're looking at the return value of a function, and that this is the first time you're encountering that return type. If the return value is an abstract base class (or interface), you'll need to resort to either the documentation or reflection in order to figure out which subtypes exist. There can be arbitrarily many subtypes, and they can be scattered over arbitrarily many libraries (assemblies). Figuring out what to do with an abstract base class introduces a context switch that could have been avoided. diff --git a/_posts/2016-12-07-domain-modelling-with-rest.html b/_posts/2016-12-07-domain-modelling-with-rest.html index e2722eb71..5e5b65d66 100644 --- a/_posts/2016-12-07-domain-modelling-with-rest.html +++ b/_posts/2016-12-07-domain-modelling-with-rest.html @@ -17,7 +17,7 @@ Every piece of software, whether it's a web service, smart phone app, batch job, or speech recognition system, interfaces with the world in some way. Sometimes, that interface is a user interface, sometimes it's a machine-readable interface; sometimes it involves rendering pixels on a screen, and sometimes it involves writing to files, selecting records from a database, sending emails, and so on.

    - Programmers often struggle with how to model these interactions. This is particularly difficult because at the boundaries, systems no longer adhere to popular programming paradigms. Previously, I've explained why, at the boundaries, applications aren't object-oriented. By the same type of argument, neither are they functional (as in 'functional programming'). + Programmers often struggle with how to model these interactions. This is particularly difficult because at the boundaries, systems no longer adhere to popular programming paradigms. Previously, I've explained why, at the boundaries, applications aren't object-oriented. By the same type of argument, neither are they functional (as in 'functional programming').

    If that's the case, why should you even bother with 'domain modelling'? Particularly, does it even matter that, with algebraic data types, you can make illegal states unrepresentable? If you need to compromise once you hit the boundary of your application, is it worth the effort? @@ -29,7 +29,7 @@

    A payment example #

    - In my previous article, I demonstrated how to use (static) types to model an on-line payment domain. To summarise, my task was to model three types of payments: + In my previous article, I demonstrated how to use (static) types to model an on-line payment domain. To summarise, my task was to model three types of payments:

    • Individual payments, which happen only once.
    • Parent payments, which start a long-term payment relationship.
    • @@ -60,7 +60,7 @@

      The table shows that it's illegal to simultaneously provide a transaction key and set StartRecurrent to true. The other three combinations, on the other hand, are valid.

      - As I demonstrated in my previous article, you can easily model this with algebraic data types. + As I demonstrated in my previous article, you can easily model this with algebraic data types.

      At the boundary, however, there are no static types, so how could you model something like that as a web service? @@ -78,7 +78,7 @@

      If you follow those design principles, however, it's easy to model the above payment domain as a RESTful API.

      - In the following, I will show examples in XML, but it could as well have been JSON. After all, a true REST API must support content negotiation. One of the reasons that I prefer XML is that I can use XPath to point out various nodes. + In the following, I will show examples in XML, but it could as well have been JSON. After all, a true REST API must support content negotiation. One of the reasons that I prefer XML is that I can use XPath to point out various nodes.

      A client must begin at a pre-published 'home' resource, just like the home page of a web site. This resource presents affordances in the shape of hyperlinks. As recommended by the RESTful Web Services Cookbook, I always use ATOM links: @@ -166,7 +166,7 @@

      The example:pay-child link is only returned if the previous payment was a parent payment. When a client makes an individual payment, this link isn't present in the response, but when the client makes a parent payment, it is.

      - Another design principle of REST is that cool URIs don't change; once the API has shown a URL like https://example.com/recurrent/42 to a client, it should honour that URL indefinitely. The upshot of that is that a client can save that URL for later use. If a client wants to, say, renew a subscription, it can make a new HTTP POST request to that URL a month later, and that's going to be a child payment. Clients don't have to hack the URL in order to figure out what the transaction key is; they can simply store the complete URL as is and use it later. + Another design principle of REST is that cool URIs don't change; once the API has shown a URL like https://example.com/recurrent/42 to a client, it should honour that URL indefinitely. The upshot of that is that a client can save that URL for later use. If a client wants to, say, renew a subscription, it can make a new HTTP POST request to that URL a month later, and that's going to be a child payment. Clients don't have to hack the URL in order to figure out what the transaction key is; they can simply store the complete URL as is and use it later.

      A network of options # @@ -199,9 +199,9 @@

      Truly RESTful design enables you to make illegal states unrepresentable by using hypermedia as the engine of application state. This gives you a powerful design tool to ensure that clients can only perform correct operations.

      - As I also wrote in my previous article, this, too, is no silver bullet. You can turn an API into a pit of success, but there are still many fault scenarios that you can't prevent. + As I also wrote in my previous article, this, too, is no silver bullet. You can turn an API into a pit of success, but there are still many fault scenarios that you can't prevent.

      - If you were intrigued by this article, but are having trouble applying these design techniques to your own field, I'm available for hire for short or long-term engagements. + If you were intrigued by this article, but are having trouble applying these design techniques to your own field, I'm available for hire for short or long-term engagements.

    diff --git a/_posts/2016-12-16-from-rest-to-algebraic-data.html b/_posts/2016-12-16-from-rest-to-algebraic-data.html index cdbe7c7dc..16f9c2792 100644 --- a/_posts/2016-12-16-from-rest-to-algebraic-data.html +++ b/_posts/2016-12-16-from-rest-to-algebraic-data.html @@ -14,7 +14,7 @@ {{ page.description }}

    - In previous articles, you've seen how to easily model a simple domain model with algebraic data types, and how to use RESTful API design to surface such a model at the boundary of an application. In this article, you'll see how trivial it is to map incoming HTTP requests back to values of algebraic data types. + In previous articles, you've seen how to easily model a simple domain model with algebraic data types, and how to use RESTful API design to surface such a model at the boundary of an application. In this article, you'll see how trivial it is to map incoming HTTP requests back to values of algebraic data types.

    The advantage of REST is that you can make illegal states unrepresentable. Clients follow links, and while clients are supposed to treat links as opaque values, URLs still contain information your API can use. @@ -23,7 +23,7 @@

    Routing and dispatching #

    - Continuing where the previous article left off, clients can issue POST requests against a URL like https://example.com/credit-card. On the server, a well-known piece of code handles such requests. (In the example code base I've used so far, I've been using ASP.NET Web API, so the code that handles such a request is a Controller.) Since you know that URLs like that are always routed to that particular piece of code, you can create a new PaymentType value that specifically represents an individual payment with a credit card: + Continuing where the previous article left off, clients can issue POST requests against a URL like https://example.com/credit-card. On the server, a well-known piece of code handles such requests. (In the example code base I've used so far, I've been using ASP.NET Web API, so the code that handles such a request is a Controller.) Since you know that URLs like that are always routed to that particular piece of code, you can create a new PaymentType value that specifically represents an individual payment with a credit card:

    let paymentType = Individual { Name = "credit-card"; Action = "Pay" }
    @@ -53,7 +53,7 @@

    Three different URLs mapped to three different PaymentType values, which are again passed to the single pay function

    - The pay function is composed from various smaller functions, some pure and some impure. Ultimately, it transforms all the input data to the format required by the third-party payment service, and forwards the transaction information. Inside that function you'll find the pattern match that you saw in my previous article. + The pay function is composed from various smaller functions, some pure and some impure. Ultimately, it transforms all the input data to the format required by the third-party payment service, and forwards the transaction information. Inside that function you'll find the pattern match that you saw in my previous article.

    Summary # diff --git a/_posts/2017-01-03-decoupling-application-errors-from-domain-models.html b/_posts/2017-01-03-decoupling-application-errors-from-domain-models.html index 79a27b71d..d04a7910e 100644 --- a/_posts/2017-01-03-decoupling-application-errors-from-domain-models.html +++ b/_posts/2017-01-03-decoupling-application-errors-from-domain-models.html @@ -82,10 +82,10 @@

    Dependency diagram

    - Boundary and data access modules depend on the domain model, as they should, but everything depends on the Error type. This is wrong. Modules or libraries should be able to define their own error types. + Boundary and data access modules depend on the domain model, as they should, but everything depends on the Error type. This is wrong. Modules or libraries should be able to define their own error types.

    - The Error type belongs in the Composition Root, but it's impossible to put it there because F# prevents circular dependencies (a treasured language feature). + The Error type belongs in the Composition Root, but it's impossible to put it there because F# prevents circular dependencies (a treasured language feature).

    Fortunately, the fix is straightforward. @@ -173,7 +173,7 @@

        return SqlGateway.saveReservation connectionString r }

    - This composition is a variation of the composition I've previously published. The only difference is that the error cases are now mapped into the application-specific Error type. + This composition is a variation of the composition I've previously published. The only difference is that the error cases are now mapped into the application-specific Error type.

    Conclusion # @@ -202,7 +202,7 @@

    Comments

    diff --git a/_posts/2017-01-27-dependency-injection-is-passing-an-argument.html b/_posts/2017-01-27-dependency-injection-is-passing-an-argument.html index 508438f13..7a6f72515 100644 --- a/_posts/2017-01-27-dependency-injection-is-passing-an-argument.html +++ b/_posts/2017-01-27-dependency-injection-is-passing-an-argument.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is the first article in a small article series called from dependency injection to dependency rejection. + This is the first article in a small article series called from dependency injection to dependency rejection.

    In a talk at the 2012 Northeast Scala Symposium, Rúnar Bjarnason casually remarked that dependency injection is "really just a pretentious way to say 'taking an argument'". Given that I've written a 500+ pages book about dependency injection, you might expect me to disagree with that. Yet, there's some truth to that statement, although it's not quite as simple as that. @@ -129,7 +129,7 @@

    }

    - This constructor not only takes an IReservationsRepository object, but also an integer that represents the capacity of the restaurant in question. This demonstrates that dependencies can also be primitive values. + This constructor not only takes an IReservationsRepository object, but also an integer that represents the capacity of the restaurant in question. This demonstrates that dependencies can also be primitive values.

    Summary # @@ -138,6 +138,6 @@

    Dependency injection is, in a sense, only a specific way for objects to take arguments. Often, however, objects have roles defined by the interfaces they implement. Such objects may need collaborators that are not available via the APIs defined by these interfaces, so you'll have to supply dependencies via members that belong to the concrete class in question. Passing dependencies via a class' constructor is the best way to do that.

    - Next: Partial application is dependency injection. + Next: Partial application is dependency injection.

    \ No newline at end of file diff --git a/_posts/2017-01-27-from-dependency-injection-to-dependency-rejection.html b/_posts/2017-01-27-from-dependency-injection-to-dependency-rejection.html index 73d3b0455..90a974787 100644 --- a/_posts/2017-01-27-from-dependency-injection-to-dependency-rejection.html +++ b/_posts/2017-01-27-from-dependency-injection-to-dependency-rejection.html @@ -40,10 +40,10 @@

    This article series contains the following parts:

      -
    1. Dependency injection is passing an argument
    2. -
    3. Partial application is dependency injection
    4. -
    5. Dependency rejection
    6. -
    7. Pure interactions
    8. +
    9. Dependency injection is passing an argument
    10. +
    11. Partial application is dependency injection
    12. +
    13. Dependency rejection
    14. +
    15. Pure interactions
    The first three articles revolve around a common example, which is one of my favourite scenarios: on-line restaurant reservation. You can see an actual example client in my Functional Architecture with F# Pluralsight course. The (somewhat dated) client source code is available on GitHub. The server-side F# and Haskell example code for this article series is available on GitHub.

    @@ -57,6 +57,6 @@ I should point out that nowhere in this article series do I reject dependency injection as a set of object-oriented patterns. In object-oriented programming, dependency injection is a well-known and comprehensively described way to achieve decoupling and testability. In the next article, you'll see a brief review of dependency injection in C#.

    - Next: Dependency injection is passing an argument. + Next: Dependency injection is passing an argument.

    \ No newline at end of file diff --git a/_posts/2017-01-30-partial-application-is-dependency-injection.html b/_posts/2017-01-30-partial-application-is-dependency-injection.html index 74d241c5d..e3563486c 100644 --- a/_posts/2017-01-30-partial-application-is-dependency-injection.html +++ b/_posts/2017-01-30-partial-application-is-dependency-injection.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is the second article in a small article series called from dependency injection to dependency rejection. + This is the second article in a small article series called from dependency injection to dependency rejection.

    People often ask me how to do dependency injection in F#. That's only natural, since I wrote Dependency Injection in .NET some years ago, and also since I've increasingly focused my energy on F# and other functional programming languages. @@ -27,7 +27,7 @@

    Attempted dependency injection using functions #

    - Returning to the example from the previous article, you could try to rewrite MaîtreD.TryAccept as a function: + Returning to the example from the previous article, you could try to rewrite MaîtreD.TryAccept as a function:

    // int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation
    @@ -80,7 +80,7 @@ 

        let createReservation connectionString reservation = // ..

    - The readReservations function takes a connection string and a date as arguments, and returns a list of reservations for that date. The createReservation function also takes a connection string, as well as a reservation. When invoked, it creates a new record for the reservation and returns the ID of the newly created row. (This sort of API violates CQS, so you should consider alternatives.) + The readReservations function takes a connection string and a date as arguments, and returns a list of reservations for that date. The createReservation function also takes a connection string, as well as a reservation. When invoked, it creates a new record for the reservation and returns the ID of the newly created row. (This sort of API violates CQS, so you should consider alternatives.)

    If you partially apply these functions with a valid connection string, both have the type desired for their roles in tryAccept. This means that you can create a function from these elements: @@ -153,7 +153,7 @@

    Fortunately, F# and Haskell are similar enough that it's easy to port F# code to Haskell, as long as the F# code already is 'sufficiently functional'. In order to evaluate if my F# code is properly functional, I sometimes port it to Haskell. If I can get it to compile and run in Haskell, I take that as confirmation that my code is functional.

    - I've previously shown an example similar to this one, but I'll repeat the experiment here. Will porting tryAccept and tryAcceptComposition to Haskell work? + I've previously shown an example similar to this one, but I'll repeat the experiment here. Will porting tryAccept and tryAcceptComposition to Haskell work?

    It's easy to port tryAccept: @@ -221,7 +221,7 @@

    Functional programming solves the problem of decoupling (side) effects from program logic another way. That's the topic of the next article.

    - Next: Dependency rejection. + Next: Dependency rejection.

    @@ -239,7 +239,7 @@

    Comments

    - +

    Kurren, thank you for writing. Why not use Haskell in the first place? In some situations, if that's an option, I'd go for it. In most of my professional work, however, it's not. A bit of background is required, I think. I've spent most of my professional career working with Microsoft technologies. Most of my clients use .NET. The majority of my clients use C#, but some are interested in adopting functional programming. F# is a great bridge to functional programming, because it integrates so well with existing C# code. diff --git a/_posts/2017-02-02-dependency-rejection.html b/_posts/2017-02-02-dependency-rejection.html index 9ab500940..3eae24691 100644 --- a/_posts/2017-02-02-dependency-rejection.html +++ b/_posts/2017-02-02-dependency-rejection.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This is the third article in a small article series called from dependency injection to dependency rejection. In the previous article in the series, you learned that dependency injection can't be functional, because it makes everything impure. In this article, you'll see what to do instead. + This is the third article in a small article series called from dependency injection to dependency rejection. In the previous article in the series, you learned that dependency injection can't be functional, because it makes everything impure. In this article, you'll see what to do instead.

    Indirect input and output # @@ -47,10 +47,10 @@

    Such a refactoring is often problematic in mainstream object-oriented languages like C# and Java, because you wish to control the circumstances in which the indirect output must be produced. Indirect output often implies side-effects, but perhaps the side-effect must only happen when certain conditions are fulfilled. In the restaurant reservation example, the desired side-effect is to add a reservation to a database, but this must only happen when the restaurant has sufficient remaining capacity to serve the requested number of people. Since languages like C# and Java are statement-based, it can be difficult to separate the decision from the action.

    - In expression-based languages like F# and Haskell, it's trivial to decouple decisions from effects. + In expression-based languages like F# and Haskell, it's trivial to decouple decisions from effects.

    - In the previous article, you saw a version of tryAccept with this signature: + In the previous article, you saw a version of tryAccept with this signature:

    // int -> (DateTimeOffset -> Reservation list) -> (Reservation -> int) -> Reservation
    @@ -179,10 +179,10 @@ 

    Dependencies are, by nature, impure. They're either non-deterministic, have side-effects, or both. Pure functions can't call impure functions (because that would make them impure as well), so pure functions can't have dependencies. Functional programming must reject the notion of dependencies.

    - Obviously, software is only useful with impure behaviour, so instead of injecting dependencies, functional programs must be composed in impure contexts. Impure functions can call pure functions, so at the boundary, an application must gather impure data, and use it to call pure functions. This automatically leads to the ports and adapters architecture. + Obviously, software is only useful with impure behaviour, so instead of injecting dependencies, functional programs must be composed in impure contexts. Impure functions can call pure functions, so at the boundary, an application must gather impure data, and use it to call pure functions. This automatically leads to the ports and adapters architecture.

    - This style of programming is surprisingly often possible, but it's not a universal solution; other alternatives exist. + This style of programming is surprisingly often possible, but it's not a universal solution; other alternatives exist.

    @@ -225,7 +225,7 @@

    Comments

    @@ -293,7 +293,7 @@

    Testability #

    - It's true that the partial application version of tryAccept is testable, because it has isolation, but the tests are more complicated than they have to be: + It's true that the partial application version of tryAccept is testable, because it has isolation, but the tests are more complicated than they have to be:

    [<Property(QuietOnSuccess = true)>]
    @@ -401,7 +401,7 @@ 

    - +

    Benjamin, thank you for writing. The alternative you propose looks useful in Haskell, but, as you've already suggested, it doesn't translate well into F#. @@ -440,7 +440,7 @@

    - +

    Enrico, thank you for writing. There's a lot to unpack in that quote, which was one of the reasons I didn't expand it. It would have made the article too long, and wandered off compared to its main point. I don't mind going into these details here, though. diff --git a/_posts/2017-03-30-a-reusable-apicontroller-adapter.html b/_posts/2017-03-30-a-reusable-apicontroller-adapter.html index e9a98ba08..6ed46cb99 100644 --- a/_posts/2017-03-30-a-reusable-apicontroller-adapter.html +++ b/_posts/2017-03-30-a-reusable-apicontroller-adapter.html @@ -15,7 +15,7 @@ Regular readers of this blog will know that I write many RESTful APIs in F#, using ASP.NET Web API. Since I like to write functional F#, but ASP.NET Web API is an object-oriented framework, I prefer to escape the object-oriented framework as soon as possible. (In general, it makes good architectural sense to write most of your code as framework-independent as possible.)

    - (Regular readers will also have seen the above paragraph before.) + (Regular readers will also have seen the above paragraph before.)

    To bridge the gap between the object-oriented framework and my functional code, I implement Controller classes like this: @@ -33,7 +33,7 @@             this.InternalServerError (InvalidOperationException msg) :> _

    - The above example is a Controller that handles incoming payment data. It immediately delegates all work to an injected imp function, and pattern matches on the return value in order to return correct responses. + The above example is a Controller that handles incoming payment data. It immediately delegates all work to an injected imp function, and pattern matches on the return value in order to return correct responses.

    This CreditCardController extends ApiController in order to work nicely with ASP.NET Web API, while the injected imp function is written using functional programming. If you want to be charitable, you could say that the Controller is an Adapter between ASP.NET Web API and the functional F# API that actually implements the service. If you want to be cynical, you could also call it an anti-corruption layer. @@ -244,7 +244,7 @@

    Comments

    - +

    Aleksander, thank you for writing. I clearly have some scars from working with ASP.NET Web API since version 0.6 (or some value in that neighbourhood). In general, if a method is defined on ApiController, I've learned the hard way that such methods tend to be tightly coupled to the Controller. Often, such methods even look into the untyped context dictionary in the request message object, so I've gotten used to use them whenever they're present. diff --git a/_posts/2017-04-24-simple-holidays.html b/_posts/2017-04-24-simple-holidays.html index 229ca028d..b0a06b06c 100644 --- a/_posts/2017-04-24-simple-holidays.html +++ b/_posts/2017-04-24-simple-holidays.html @@ -424,7 +424,7 @@

    - +

    jadarnel27, thank you for writing. Your suggestion could be an option as well, but is hardly the simplest solution. In order to implement that, I'd need to add an administration web site for my application, program the user interface, connect the administration site and my original application (a REST API) to a persistent data source, write code for input validation, etcetera. @@ -451,7 +451,7 @@

    - +

    Alf, thank you for writing. Apart from the alternative library, how is that different from the option I covered under the heading Option: Nager.Date? @@ -471,7 +471,7 @@

    - +

    EQR, thank you for writing. The performance profile of the implementation wasn't my main concern with this article, so it's likely that it can be improved. @@ -494,7 +494,7 @@

    - +

    Thomas, thank you for writing. That just goes to show, I think, that holiday calculation is as complicated as any other 'business logic'. It should be treated as such, and not as an algorithmic calculation. diff --git a/_posts/2017-05-30-using-polly-with-f-async-workflows.html b/_posts/2017-05-30-using-polly-with-f-async-workflows.html index b36e259b6..97e17bd32 100644 --- a/_posts/2017-05-30-using-polly-with-f-async-workflows.html +++ b/_posts/2017-05-30-using-polly-with-f-async-workflows.html @@ -77,7 +77,7 @@ The isNestedCircuitBreakerException is similar to isNestedHttpException, so it'd be tempting to refactor. I decided, however, to rely on the rule of three and leave both functions as they were.

    - In my F# code I prefer to handle application errors using Either values instead of relying on exceptions, so I wanted to translate any BrokenCircuitException to a particular application error. With the above isNestedCircuitBreakerException predicate, this was now possible with a try/with expression: + In my F# code I prefer to handle application errors using Either values instead of relying on exceptions, so I wanted to translate any BrokenCircuitException to a particular application error. With the above isNestedCircuitBreakerException predicate, this was now possible with a try/with expression:

    // Policy -> ('a -> Async<'b>) -> 'a -> Async<Result<'b, BoundaryFailure>>
    diff --git a/_posts/2017-06-27-pure-times.html b/_posts/2017-06-27-pure-times.html
    index fc6f70f5c..6182797c2 100644
    --- a/_posts/2017-06-27-pure-times.html
    +++ b/_posts/2017-06-27-pure-times.html
    @@ -12,16 +12,16 @@
     		{{ page.description }}
     	

    - A couple of years ago, I published an article called Good times with F#. Unfortunately, that article never lived up to my expectations. Not that I don't have a good time with F# (I do), but the article introduced an attempt to model execution durations of operations in a functional manner. The article introduced a Timed<'a> generic type that I had high hopes for. + A couple of years ago, I published an article called Good times with F#. Unfortunately, that article never lived up to my expectations. Not that I don't have a good time with F# (I do), but the article introduced an attempt to model execution durations of operations in a functional manner. The article introduced a Timed<'a> generic type that I had high hopes for.

    - Later, I published a Pluralsight course called Type-Driven Development with F#, in which I used Timed<'a> to implement a Polling Consumer. It's a good course that teaches you how to let F#'s type system give you rapid feedback. You can read a few articles that highlight the important parts of the course. + Later, I published a Pluralsight course called Type-Driven Development with F#, in which I used Timed<'a> to implement a Polling Consumer. It's a good course that teaches you how to let F#'s type system give you rapid feedback. You can read a few articles that highlight the important parts of the course.

    There's a problem with the implementation, though. It's not functional.

    - It's nice F# code, but F# is this friendly, forgiving, multi-paradigmatic language that enables you to get real work done. If you want to do this using partial application as a replacement for Dependency Injection, it'll let you. It is, however, not functional. + It's nice F# code, but F# is this friendly, forgiving, multi-paradigmatic language that enables you to get real work done. If you want to do this using partial application as a replacement for Dependency Injection, it'll let you. It is, however, not functional.

    Consider, as an example, this function: @@ -41,9 +41,9 @@ The same argument applies, in weaker form, to the shouldIdle function. While it is possible to write more than one pure function with the type Timed<TimeSpan list> -> bool, the intent is that it should look at the time statistics and the current time, and decide whether or not it's 'safe' to poll again. Getting the current time from the system clock is a non-deterministic operation.

    - Ever since I discovered that Dependency Injection is impossible in functional programming, I knew that I had to return to the Polling Consumer example and show how to implement it in a truly functional style. In order to be sure that I don't accidentally call an impure function from a 'pure' function, I'll first rewrite the Polling Consumer in Haskell, and afterwards translate the Haskell code to F#. When reading, you can skip the Haskell article and go directly to the F# article, or vice versa, if you like. + Ever since I discovered that Dependency Injection is impossible in functional programming, I knew that I had to return to the Polling Consumer example and show how to implement it in a truly functional style. In order to be sure that I don't accidentally call an impure function from a 'pure' function, I'll first rewrite the Polling Consumer in Haskell, and afterwards translate the Haskell code to F#. When reading, you can skip the Haskell article and go directly to the F# article, or vice versa, if you like.

    - Next: Pure times in Haskell. + Next: Pure times in Haskell.

    \ No newline at end of file diff --git a/_posts/2017-06-28-pure-times-in-haskell.html b/_posts/2017-06-28-pure-times-in-haskell.html index ad72d3241..952ce8b1a 100644 --- a/_posts/2017-06-28-pure-times-in-haskell.html +++ b/_posts/2017-06-28-pure-times-in-haskell.html @@ -14,7 +14,7 @@ {{ page.description }}

    - As you can read in the introductory article, I've come to realise that the Polling Consumer that I originally wrote in F# isn't particularly functional. Being the friendly and productive language that it is, F# doesn't protect you from mixing pure and impure code, but Haskell does. For that reason, you can develop a prototype in Haskell, and later port it to F#, if you want to learn how to solve the problem in a strictly functional way. + As you can read in the introductory article, I've come to realise that the Polling Consumer that I originally wrote in F# isn't particularly functional. Being the friendly and productive language that it is, F# doesn't protect you from mixing pure and impure code, but Haskell does. For that reason, you can develop a prototype in Haskell, and later port it to F#, if you want to learn how to solve the problem in a strictly functional way.

    To recapitulate, the task is to implement a Polling Consumer that runs for a predefined duration, after which it exits (so that it can be restarted by a scheduler). @@ -23,7 +23,7 @@ Polling Consumer state machine transition diagram

    - The program is a finite state machine that moves between four states. From the ready state, it'll need to decide whether to poll for a new message or exit. Polling and handling takes time (and at compile-time we don't know how long), and the program ought to stop at a pre-defined time. If it gets too close to that time, it should exit, but otherwise, it should attempt to handle a message (and keep track of how long this takes). You can read a more elaborate description of the problem in the original article. + The program is a finite state machine that moves between four states. From the ready state, it'll need to decide whether to poll for a new message or exit. Polling and handling takes time (and at compile-time we don't know how long), and the program ought to stop at a pre-defined time. If it gets too close to that time, it should exit, but otherwise, it should attempt to handle a message (and keep track of how long this takes). You can read a more elaborate description of the problem in the original article.

    State data types # @@ -49,7 +49,7 @@

    In addition to those three types of duration, I also define a CycleDuration. This is the data that I actually need to keep track of: how long does it take to handle a single message? I'm assuming that polling for a message is an I/O-bound operation, so it may take significant time. Likewise, handling a message may take time. When deciding whether to exit or handle a new message, both durations count. Instead of defining CycleDuration as a newtype alias for NominalDiffTime, I decided to define it as a record type comprised of a PollDuration and a HandleDuration. It's not that I'm really interested in keeping track of these two values individually, but it protects me from making stupid mistakes. I can only create a CycleDuration value if I have both a PollDuration and a HandleDuration value.

    - In short, I'm trying to combat primitive obsession. + In short, I'm trying to combat primitive obsession.

    With these duration types in place, you can define the states of the finite state machine: @@ -75,7 +75,7 @@

    This is the heart of the matter. The Polling Consumer must constantly look at the clock. It's under a deadline, and it must also measure durations of poll, handle, and idle operations. All of this is non-deterministic, so not pure. The program has to interact with impure operations during its entire lifetime. In fact, its ultimate decision to exit will be based on impure data. How can you model this in a pure fashion?

    - You can model long-running (impure) interactions by defining a small instruction set for an Abstract Syntax Tree (AST). That sounds intimidating, but once you get the hang of it, it becomes routine. In later articles, I'll expand on this, but for now I'll refer you to an excellent article by Scott Wlaschin, who explains the approach in F#. + You can model long-running (impure) interactions by defining a small instruction set for an Abstract Syntax Tree (AST). That sounds intimidating, but once you get the hang of it, it becomes routine. In later articles, I'll expand on this, but for now I'll refer you to an excellent article by Scott Wlaschin, who explains the approach in F#.

    data PollingInstruction msg next =
    @@ -472,7 +472,7 @@ 

    Haskell's sophisticated type system makes this a fairly low-hanging fruit, once you understand how to do it. You can also port this type of design to F#, although, as you shall see next, more boilerplate is required.

    - Next: Pure times in F#. + Next: Pure times in F#.

    @@ -530,7 +530,7 @@

    Comments

    - +

    Benjamin, thank you for writing. It is, indeed, interesting to me, and I appreciate that you took the time to write such a helpful and concise comment. @@ -583,7 +583,7 @@

    Comments

    - +

    Benjamin, thank you once again for writing. It's amazing that not only are they isomorphic, but you can actually prove it with code. I have to admit, though, that I haven't tried compiling or running your code yet. First, I need to digest this. diff --git a/_posts/2017-07-04-pure-times-in-f.html b/_posts/2017-07-04-pure-times-in-f.html index c5577ceef..2626143b2 100644 --- a/_posts/2017-07-04-pure-times-in-f.html +++ b/_posts/2017-07-04-pure-times-in-f.html @@ -14,7 +14,7 @@ {{ page.description }}

    - Previously, you saw how to implement a Polling Consumer in Haskell. This proves that it's possible to write pure functional code modelling long-running interactions with the (impure) world. In this article, you'll see how to port the Haskell code to F#. + Previously, you saw how to implement a Polling Consumer in Haskell. This proves that it's possible to write pure functional code modelling long-running interactions with the (impure) world. In this article, you'll see how to port the Haskell code to F#.

    For reference, I'll repeat the state transition diagram here: @@ -23,7 +23,7 @@ Polling Consumer state machine transition diagram

    - For a complete description of the goals and constraints of this particular Polling Consumer implementation, see my earlier Type Driven Development article, or, even better, watch my Pluralsight course Type-Driven Development with F#. + For a complete description of the goals and constraints of this particular Polling Consumer implementation, see my earlier Type Driven Development article, or, even better, watch my Pluralsight course Type-Driven Development with F#.

    State data types # @@ -40,7 +40,7 @@

        HandleDuration : HandleDuration }

    - This is a straightforward port of the Haskell code. See the previous article for more details about the motivation for doing this. + This is a straightforward port of the Haskell code. See the previous article for more details about the motivation for doing this.

    You can now define the states of the finite state machine: @@ -90,7 +90,7 @@

    The function is named mapI, where the I stands for instruction. It's private because the next step is to package the functor in a monad. From that monad, you can define a new functor, so in order to prevent any confusion, I decided to hide the underlying functor from any consumers of the API.

    - Defining a map function for a generic type like PollingInstruction<'msg, 'next> is well-defined. Pattern-match each union case and return the same case, but with the next function composed with the input function argument f: next >> f. In later articles, you'll see more examples, and you'll see how this recipe is entirely repeatable and automatable. + Defining a map function for a generic type like PollingInstruction<'msg, 'next> is well-defined. Pattern-match each union case and return the same case, but with the next function composed with the input function argument f: next >> f. In later articles, you'll see more examples, and you'll see how this recipe is entirely repeatable and automatable.

    While a functor isn't an explicit concept in F#, this is how PollingInstruction msg next is a Functor in Haskell. Given a functor, you can produce a free monad. The reason you'd want to do this is that once you have a monad, you can get syntactic sugar. Currently, PollingInstruction<'msg, 'next> only enables you to create Abstract Syntax Trees (ASTs), but the programming experience would be cumbersome and alien. Monads give you automatic do notation in Haskell; in F#, it enables you to write a computation expression builder. @@ -175,7 +175,7 @@

    This enables you to write polling computation expressions. You'll see examples of this shortly.

    - Most of the code you've seen here is automated in Haskell. This means that while you'll have to explicitly write it in F#, it follows a recipe. Once you get the hang of it, it doesn't take much time. The maintenance overhead of the code is also minimal, because you're essentially implementing a universal abstraction. It's not going to change. + Most of the code you've seen here is automated in Haskell. This means that while you'll have to explicitly write it in F#, it follows a recipe. Once you get the hang of it, it doesn't take much time. The maintenance overhead of the code is also minimal, because you're essentially implementing a universal abstraction. It's not going to change.

    Support functions # @@ -459,6 +459,6 @@

    Haskell code with a free monad can be ported to F#, although some boilerplate code is required. That code, however, is unlikely to be much of a burden, because it follows a well-known recipe that implements a universal abstraction.

    - For more details on how to write free monads in F#, see Pure interactions. + For more details on how to write free monads in F#, see Pure interactions.

    \ No newline at end of file diff --git a/_posts/2017-07-10-pure-interactions.html b/_posts/2017-07-10-pure-interactions.html index 63f4c8fcf..97ddc7f46 100644 --- a/_posts/2017-07-10-pure-interactions.html +++ b/_posts/2017-07-10-pure-interactions.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In a previous article, you can read why Dependency Injection and (strict) functional programming are mutually exclusive. Dependency Injection makes everything impure, and if nothing is pure, then it's hardly functional. In Dependency rejection, you can see how you can often separate impure and pure code into an impure/pure/impure sandwich. + In a previous article, you can read why Dependency Injection and (strict) functional programming are mutually exclusive. Dependency Injection makes everything impure, and if nothing is pure, then it's hardly functional. In Dependency rejection, you can see how you can often separate impure and pure code into an impure/pure/impure sandwich.

    Micro-operation-based architectures # @@ -33,7 +33,7 @@

    Interactive software #

    - There is, however, another category of software. We could call it 'interactive software'. As the name implies, this includes everything with a user interface, but can also be a long-running batch job, or, as you've already seen, time-sensitive software. + There is, however, another category of software. We could call it 'interactive software'. As the name implies, this includes everything with a user interface, but can also be a long-running batch job, or, as you've already seen, time-sensitive software.

    For such software, the impure/pure/impure sandwich architecture is no longer possible. Just think of a UI-based program, like an email client. You compose and send an email, receive a response, then compose a reply, and so on. Every send and receive is impure, as is all the user interface rendering. What happens next depends on what happened before, and everything that happens in the real world is impure. @@ -44,16 +44,16 @@

    Hardly. In this series of articles, I'm going to show you how to model pure interactions:

    You can skip the Haskell article if you only want to read the F# articles.

    - This series of articles gives you a comprehensive walkthrough of pure interactions and free monads in F#. For a motivating example, see Pure times, which presents a more realistic example that, on the other hand, doesn't go to the same level of detail. + This series of articles gives you a comprehensive walkthrough of pure interactions and free monads in F#. For a motivating example, see Pure times, which presents a more realistic example that, on the other hand, doesn't go to the same level of detail.

    Summary # @@ -62,6 +62,6 @@

    The solution to the problem of continuous impure interactions is to model them as a instructions in a (domain-specific) Abstract Syntax Tree (AST), and then using an impure interpreter for the pure AST. You can model the AST as a (free) monad in order to make the required syntax nice.

    - Next: Hello, pure command-line interaction. + Next: Hello, pure command-line interaction.

    \ No newline at end of file diff --git a/_posts/2017-07-11-hello-pure-command-line-interaction.html b/_posts/2017-07-11-hello-pure-command-line-interaction.html index 23cb2fb2b..039b05022 100644 --- a/_posts/2017-07-11-hello-pure-command-line-interaction.html +++ b/_posts/2017-07-11-hello-pure-command-line-interaction.html @@ -12,7 +12,7 @@ {{ page.description }}

    - Dependency Injection is a well-described concept in object-oriented programming, but as I've explained earlier, its not functional, because it makes everything impure. In general, you should reject the notion of dependencies by instead designing your application on the concept of an impure/pure/impure sandwich. This is possible more often than you'd think, but there's still a large group of applications where this will not work. If your application needs to interact with the impure world for an extended time, you need a way to model such interactions in a pure way. + Dependency Injection is a well-described concept in object-oriented programming, but as I've explained earlier, its not functional, because it makes everything impure. In general, you should reject the notion of dependencies by instead designing your application on the concept of an impure/pure/impure sandwich. This is possible more often than you'd think, but there's still a large group of applications where this will not work. If your application needs to interact with the impure world for an extended time, you need a way to model such interactions in a pure way.

    This article introduces a way to do that. @@ -39,7 +39,7 @@

    }

    - Please note that this is clearly a toy example. In later articles, you'll see how to expand the example to cover some more complex interactions, but you could also read a more realistic example already. Initially, the example is degenerate, because there's only a single interaction. In this case, an impure/pure/impure sandwich is still possible, but such a design wouldn't scale to more complex interactions. + Please note that this is clearly a toy example. In later articles, you'll see how to expand the example to cover some more complex interactions, but you could also read a more realistic example already. Initially, the example is degenerate, because there's only a single interaction. In this case, an impure/pure/impure sandwich is still possible, but such a design wouldn't scale to more complex interactions.

    The problem with defining and injecting an interface is that it isn't functional. What's the functional equivalent, then? @@ -204,7 +204,7 @@

    Just what you need.

    - In Haskell, this happens automatically when you declare type CommandLineProgram = Free CommandLineInstruction. Thanks to Haskell's type system, Free is automatically a Monad when the underlying type is a Functor. In F#, you have to work for your monads, but the fact that Haskell can automate this means that there's a recipe that you can follow. + In Haskell, this happens automatically when you declare type CommandLineProgram = Free CommandLineInstruction. Thanks to Haskell's type system, Free is automatically a Monad when the underlying type is a Functor. In F#, you have to work for your monads, but the fact that Haskell can automate this means that there's a recipe that you can follow.

    Earlier in this article, I mentioned in passing that there are alternative ways in which you can define a 'stop' case for your instruction set. The reason I chose to separate the API into two types (an 'instruction set', and a 'program') is that the instruction set is the underlying functor. The 'program' is part of the free monad. The other part is a bind function (that obeys the monad laws). @@ -242,7 +242,7 @@

    This makes CommandLineProgram<'a> a functor as well. This is the reason I made mapI private, because mapI makes the instruction set a functor, but the API is expressed in terms of AST programs, and it should be consistent. Within the same module, map should work on the same data type as bind.

    - Notice that map can be defined as a composition of bind and Pure. This is part of the recipe. For a free monad, the map function always looks like that. The f function is a function with the type 'a -> 'b, and Pure is a case constructor with the type 'b -> CommandLineProgram<'b>. Notice that I've used 'b for the generic type argument instead of the usual 'a. Hopefully, this makes it clear that when you compose these two functions together (f >> Pure), you get a function of the type ('a -> 'b) >> ('b -> CommandLineProgram<'b>), or 'a -> CommandLineProgram<'b>. That's just the type of function needed for the bind function, so the whole composition turns out to type-check and work as intended. + Notice that map can be defined as a composition of bind and Pure. This is part of the recipe. For a free monad, the map function always looks like that. The f function is a function with the type 'a -> 'b, and Pure is a case constructor with the type 'b -> CommandLineProgram<'b>. Notice that I've used 'b for the generic type argument instead of the usual 'a. Hopefully, this makes it clear that when you compose these two functions together (f >> Pure), you get a function of the type ('a -> 'b) >> ('b -> CommandLineProgram<'b>), or 'a -> CommandLineProgram<'b>. That's just the type of function needed for the bind function, so the whole composition turns out to type-check and work as intended.

    API # @@ -324,6 +324,6 @@

    While this may seem complicated, it has the benefit of making impurities explicit in the code. Whenever you see a CommandLineProgram value, you know that, at run-time, something impure is likely to happen. It's not uncontrolled impurity, though. Inside a CommandLineProgram, only reading from, and writing to, the command line will happen. It's not going to generate random values, change global variables, send an email, or any other unpredictable operation - that is, unless the interpreter does that...

    - Next: A pure command-line wizard. + Next: A pure command-line wizard.

    \ No newline at end of file diff --git a/_posts/2017-07-17-a-pure-command-line-wizard.html b/_posts/2017-07-17-a-pure-command-line-wizard.html index 02e530eee..5e762ba43 100644 --- a/_posts/2017-07-17-a-pure-command-line-wizard.html +++ b/_posts/2017-07-17-a-pure-command-line-wizard.html @@ -12,13 +12,13 @@ {{ page.description }}

    - In the previous article, you got an introduction to a functional command-line API in F#. The example in that article, however, was too simple to highlight its composability. In this article, you'll see a fuller example. + In the previous article, you got an introduction to a functional command-line API in F#. The example in that article, however, was too simple to highlight its composability. In this article, you'll see a fuller example.

    Command-line wizard for on-line restaurant reservations #

    - In previous articles, you can see variations on an HTTP-based back-end for an on-line restaurant reservation system. In this article, on the other hand, you're going to see a first attempt at a command-line client for the API. + In previous articles, you can see variations on an HTTP-based back-end for an on-line restaurant reservation system. In this article, on the other hand, you're going to see a first attempt at a command-line client for the API.

    Normally, an on-line restaurant reservation system would have GUIs hosted in web pages or mobile apps, but with an open HTTP API, a self-respecting geek would prefer a command-line interface (CLI)... right?! @@ -50,7 +50,7 @@

    Notice that the CLI is a wizard. It leads you through a series of questions. You have to give an appropriate answer to each question before you can move on to the next question. For instance, you must type an integer for the number of guests; if you don't, the wizard will repeatedly ask you for an integer until you do.

    - You can develop such an interface with the commandLine computation expression from the previous article. + You can develop such an interface with the commandLine computation expression from the previous article.

    Reading quantities # @@ -159,7 +159,7 @@

    You may have noticed that no code so far shown define functions; they are all values. They are small program fragments, expressed as ASTs, composed into slightly larger programs that are still ASTs. So far, all the code is pure.

    - In order to run the program, you need an interpreter. You can reuse the interpreter from the previous article when composing your main function: + In order to run the program, you need an interpreter. You can reuse the interpreter from the previous article when composing your main function:

    [<EntryPoint>]
    @@ -191,6 +191,6 @@ 

    Read on.

    - Next: Combining free monads in Haskell. + Next: Combining free monads in Haskell.

    \ No newline at end of file diff --git a/_posts/2017-07-24-combining-free-monads-in-haskell.html b/_posts/2017-07-24-combining-free-monads-in-haskell.html index 3ae4c0fbd..544235e35 100644 --- a/_posts/2017-07-24-combining-free-monads-in-haskell.html +++ b/_posts/2017-07-24-combining-free-monads-in-haskell.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In the previous article in this series on pure interactions, you saw how to write a command-line wizard in F#, using a free monad to build an Abstract Syntax Tree (AST). The example collects information about a potential restaurant reservations you'd like to make. That example, however, didn't do more than that. + In the previous article in this series on pure interactions, you saw how to write a command-line wizard in F#, using a free monad to build an Abstract Syntax Tree (AST). The example collects information about a potential restaurant reservations you'd like to make. That example, however, didn't do more than that.

    For a more complete experience, you'd like your command-line interface (CLI) to not only collect data about a reservation, but actually make the reservation, using the available HTTP API. This means that you'll also need to model interaction with the HTTP API as an AST, but a different AST. Then, you'll have to figure out how to compose these two APIs into a combined API. @@ -24,7 +24,7 @@

    Command line API #

    - Let's make an easy start of it. In a previous article, you saw how to model command-line interactions as ASTs, complete with syntactic sugar provided by a computation expression. That took a fair amount of boilerplate code in F#, but in Haskell, it's declarative: + Let's make an easy start of it. In a previous article, you saw how to model command-line interactions as ASTs, complete with syntactic sugar provided by a computation expression. That took a fair amount of boilerplate code in F#, but in Haskell, it's declarative:

    import Control.Monad.Trans.Free (FreeliftF)
    @@ -43,7 +43,7 @@ 

    writeLine s = liftF (WriteLine s ())

    - This is all the code required to define your AST and make it a monad in Haskell. Contrast that with all the code you have to write in F#! + This is all the code required to define your AST and make it a monad in Haskell. Contrast that with all the code you have to write in F#!

    The CommandLineInstruction type defines the instruction set, and makes use of a language extension called DeriveFunctor, which enables Haskell to automatically create a Functor instance from the type. @@ -313,7 +313,7 @@

    This proof of concept proves that it's possible to combine separate free monads. Now that we know that it works, and the overall outline of it, it should be possible to translate this to F#. You should, however, expect more boilerplate code.

    - Next: Combining free monads in F#. + Next: Combining free monads in F#.

    @@ -391,7 +391,7 @@

    Comments

    - +

    George, thank you for writing. That alternative does, indeed, look simpler and cleaner than mine. Thank you for sharing. diff --git a/_posts/2017-07-31-combining-free-monads-in-f.html b/_posts/2017-07-31-combining-free-monads-in-f.html index a6ae40d44..a6b614a9b 100644 --- a/_posts/2017-07-31-combining-free-monads-in-f.html +++ b/_posts/2017-07-31-combining-free-monads-in-f.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is an instalment in a series of articles about modelling long-running interactions with pure, functional code. In the previous article, you saw how to combine a pure command-line API with an HTTP-client API in Haskell. In this article, you'll see how to translate the Haskell proof of concept to F#. + This article is an instalment in a series of articles about modelling long-running interactions with pure, functional code. In the previous article, you saw how to combine a pure command-line API with an HTTP-client API in Haskell. In this article, you'll see how to translate the Haskell proof of concept to F#.

    HTTP API client module #

    - You've already seen how to model command-line interactions as pure code in a previous article. You can define interactions with the online restaurant reservation HTTP API in the same way. First, define some types required for input and output to the API: + You've already seen how to model command-line interactions as pure code in a previous article. You can define interactions with the online restaurant reservation HTTP API in the same way. First, define some types required for input and output to the API:

    type Slot = { Date : DateTimeOffset; SeatsLeft : int }
    @@ -30,7 +30,7 @@ 

        Quantity : int }

    - The Slot type contains information about how many available seats are left on a particular date. The Reservation type contains the information required in order to make a reservation. It's the same Reservation F# record type you saw in a previous article, but now it's moved here. + The Slot type contains information about how many available seats are left on a particular date. The Reservation type contains the information required in order to make a reservation. It's the same Reservation F# record type you saw in a previous article, but now it's moved here.

    The online restaurant reservation HTTP API may afford more functionality than you need, but there's no reason to model more instructions than required: @@ -57,7 +57,7 @@

    This turns ReservationsApiInstruction<'a> into a functor, which is, however, not the ultimate goal. The final objective is to enable syntactic sugar, so that you can write pure ReservationsApiInstruction<'a> Abstract Syntax Trees (ASTs) in standard F# syntax. In order to fulfil that ambition, you need a computation expression builder, and to create one of those, you need a monad.

    - You can turn ReservationsApiInstruction<'a> into a monad using the free monad recipe that you've already seen. Creating a free monad, however, involves adding another type that will become both monad and functor, so I deliberately make mapI private in order to prevent confusion. This is also the reason I didn't name the function map: you'll need that name for a different type. The I in mapI stands for instruction. + You can turn ReservationsApiInstruction<'a> into a monad using the free monad recipe that you've already seen. Creating a free monad, however, involves adding another type that will become both monad and functor, so I deliberately make mapI private in order to prevent confusion. This is also the reason I didn't name the function map: you'll need that name for a different type. The I in mapI stands for instruction.

    The mapI function pattern-matches on the (implicit) ReservationsApiInstruction argument. In the GetSlots case, it returns a new GetSlots value, but composes the next continuation with f. In the PostReservation case, it returns a new PostReservation value, but pipes next to f. The reason for the difference is that PostReservation is degenerate: next isn't a function, but a value. @@ -84,7 +84,7 @@

        | Pure x -> f x

    - If you refer back to the bind implementation for CommandLineProgram<'a>, you'll see that it's the exact same code. In Haskell, creating a free monad from a functor is automatic. In F#, it's boilerplate. + If you refer back to the bind implementation for CommandLineProgram<'a>, you'll see that it's the exact same code. In Haskell, creating a free monad from a functor is automatic. In F#, it's boilerplate.

    Likewise, you can make ReservationsApiProgram<'a> a functor: @@ -124,7 +124,7 @@

    - This, in total, defines a pure API for interacting with the online restaurant reservation system, including all the syntactic sugar you'll need to stay sane. As usual, some boilerplate code is required, but I'm not too worried about its maintenance overhead, as it's unlikely to change much, once you've added it. If you've followed the recipe, the API obeys the category, functor, and monad laws, so it's not something you've invented; it's an instance of a universal abstraction. + This, in total, defines a pure API for interacting with the online restaurant reservation system, including all the syntactic sugar you'll need to stay sane. As usual, some boilerplate code is required, but I'm not too worried about its maintenance overhead, as it's unlikely to change much, once you've added it. If you've followed the recipe, the API obeys the category, functor, and monad laws, so it's not something you've invented; it's an instance of a universal abstraction.

    Monad stack # @@ -137,7 +137,7 @@

    Run of CommandLineProgram<ReservationsApiProgram<'a>>

    - This is a single-case discriminated union that stacks ReservationsApiProgram and CommandLineProgram. In this incarnation, it defines a single case called Run. The reason for this is that it enables you to follow the free monad recipe without having to do much thinking. Later, you'll see that it's possible to simplify the type. + This is a single-case discriminated union that stacks ReservationsApiProgram and CommandLineProgram. In this incarnation, it defines a single case called Run. The reason for this is that it enables you to follow the free monad recipe without having to do much thinking. Later, you'll see that it's possible to simplify the type.

    The naming is inspired by Haskell. This type is a piece of the puzzle corresponding to Haskell's FreeT type. The T in FreeT stands for transformer, because FreeT is actually something called a monad transformer. That's not terribly important in an F# context, but that's the reason I also tagged on the T in CommandLineReservationsApiT<'a>. @@ -244,7 +244,7 @@

    The behaviour is the same, but now wrap doesn't align, making it harder to discover the kinship between the two functions. My use of the backward pipe operator is motivated by readability concerns.

    - Following the free monad recipe, now create a computation expression builder: + Following the free monad recipe, now create a computation expression builder:

    type CommandLineReservationsApiBuilder () =
    @@ -267,7 +267,7 @@ 

    Simplification #

    - While there can be good reasons to introduce single-case discriminated unions in your F# code, they're isomorphic with their contained type. (This means that there's a lossless conversion between the union type and the contained type, in both directions.) Following the free monad recipe, I introduced CommandLineReservationsApiT as a discriminated union, but since it's a single-case union, you can refactor it to its contained type. + While there can be good reasons to introduce single-case discriminated unions in your F# code, they're isomorphic with their contained type. (This means that there's a lossless conversion between the union type and the contained type, in both directions.) Following the free monad recipe, I introduced CommandLineReservationsApiT as a discriminated union, but since it's a single-case union, you can refactor it to its contained type.

    If you delete the CommandLineReservationsApiT type, you'll first have to change the definition of the program type to this: @@ -333,7 +333,7 @@

    Notice that tryReserve is a value, and not a function. It's a pure value that contains an AST - a small program that describes the impure interactions that you'd like to take place. It's defined entirely within a commandLineReservationsApi computation expression.

    - It starts by using the readQuantity and readDate program values you saw in the previous F# article. Both of these values are CommandLineProgram values, so you have to use liftCL to lift them to CommandLineReservationsApiProgram values - only then can you let! bind them to an int and a DateTimeOffset, respectively. This is just like the use of lift in the previous article's Haskell example. + It starts by using the readQuantity and readDate program values you saw in the previous F# article. Both of these values are CommandLineProgram values, so you have to use liftCL to lift them to CommandLineReservationsApiProgram values - only then can you let! bind them to an int and a DateTimeOffset, respectively. This is just like the use of lift in the previous article's Haskell example.

    Once the program has collected the desired date from the user, it calls ReservationsApi.getSlots and calculates the sum over all the returned SeatsLeft labels. The ReservationsApi.getSlots function returns a ReservationsApiProgram<Slot list>, the ReservationsApi.map turns it into a ReservationsApiProgram<int> value that you must liftRA in order to be able to let! bind it to an int value. Let me stress once again: the program actually doesn't do any of that; it constructs an AST with instructions to that effect. @@ -345,7 +345,7 @@

    Interpreters #

    - The tryReserve wizard is a pure value. It contains an AST that can be interpreted in such a way that impure operations happen. You've already seen the CommandLineProgram interpreter in a previous article, so I'm not going to repeat it here. I'll only note that I renamed it to interpretCommandLine because I want to use the name interpret for the combined interpreter. + The tryReserve wizard is a pure value. It contains an AST that can be interpreted in such a way that impure operations happen. You've already seen the CommandLineProgram interpreter in a previous article, so I'm not going to repeat it here. I'll only note that I renamed it to interpretCommandLine because I want to use the name interpret for the combined interpreter.

    The interpreter for ReservationsApiProgram values is similar to the CommandLineProgram interpreter: @@ -415,6 +415,6 @@

    As expected, you can combine free monads in F#, although it requires more boilerplate code than in Haskell.

    - Next: F# free monad recipe. + Next: F# free monad recipe.

    \ No newline at end of file diff --git a/_posts/2017-08-07-f-free-monad-recipe.html b/_posts/2017-08-07-f-free-monad-recipe.html index aa9959d1d..65899dcba 100644 --- a/_posts/2017-08-07-f-free-monad-recipe.html +++ b/_posts/2017-08-07-f-free-monad-recipe.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This is not a design pattern, but it's something related. Let's call it a recipe. A design pattern should, in my opinion, be fairly language-agnostic (although hardly universally applicable). This article, on the contrary, specifically addresses a problem in F#: + This is not a design pattern, but it's something related. Let's call it a recipe. A design pattern should, in my opinion, be fairly language-agnostic (although hardly universally applicable). This article, on the contrary, specifically addresses a problem in F#:

    How do you create a free monad in F#? @@ -26,7 +26,7 @@ The recipe here is a step-by-step process, but be sure to first read the sections on motivation and when to use it. A free monads isn't a goal in itself.

    - This article doesn't attempt to explain the details of free monads, but instead serve as a reference. For an introduction to free monads, I think my article Pure times is a good place to start. See also the Motivating examples section, below. + This article doesn't attempt to explain the details of free monads, but instead serve as a reference. For an introduction to free monads, I think my article Pure times is a good place to start. See also the Motivating examples section, below.

    Motivation # @@ -35,10 +35,10 @@

    A frequently asked question about F# is: what's the F# equivalent to an interface? There's no single answer to this question, because, as always, It Depends™. Why do you need an interface in the first place? What is its intended use?

    - Sometimes, in OOP, an interface can be used for a Strategy. This enables you to dynamically replace or select between different (sub)algorithms at run-time. If the algorithm is pure, then an idiomatic F# equivalent would be a function. + Sometimes, in OOP, an interface can be used for a Strategy. This enables you to dynamically replace or select between different (sub)algorithms at run-time. If the algorithm is pure, then an idiomatic F# equivalent would be a function.

    - At other times, though, the person asking the question has Dependency Injection in mind. In OOP, dependencies are often modelled as interfaces with several members. Such dependencies are systematically impure, and thereby not part of functional design. If at all possible, prefer impure/pure/impure sandwiches over interactions. Sometimes, however, you'll need something that works like an interface or abstract base class. Free monads can address such situations. + At other times, though, the person asking the question has Dependency Injection in mind. In OOP, dependencies are often modelled as interfaces with several members. Such dependencies are systematically impure, and thereby not part of functional design. If at all possible, prefer impure/pure/impure sandwiches over interactions. Sometimes, however, you'll need something that works like an interface or abstract base class. Free monads can address such situations.

    In general, a free monad allows you to build a monad from any functor, but why would you want to do that? The most common reason I've encountered is exactly in order to model impure interactions in a pure manner; in other words: Dependency Injection. @@ -271,10 +271,10 @@

    Decision flowchart for whether or not to choose free monads as a design principle.

    - Your first consideration should be whether your context enables an impure/pure/impure sandwich. If so, there's no reason to make things more complicated than they have to be. To use Fred Brooks' terminology, this should go a long way to avoid accidental complexity. + Your first consideration should be whether your context enables an impure/pure/impure sandwich. If so, there's no reason to make things more complicated than they have to be. To use Fred Brooks' terminology, this should go a long way to avoid accidental complexity.

    - If you can't avoid long-running, impure interactions, then consider whether purity, or strictly functional design, is important to you. F# is a multi-paradigmatic language, and it's perfectly possible to write code that's impure, yet still well-structured. You can use partial application as an idiomatic alternative to Dependency Injection. + If you can't avoid long-running, impure interactions, then consider whether purity, or strictly functional design, is important to you. F# is a multi-paradigmatic language, and it's perfectly possible to write code that's impure, yet still well-structured. You can use partial application as an idiomatic alternative to Dependency Injection.

    If you prefer to keep your code functional and explicit, you may consider using free monads. In this case, I still think you should consider the maintainers of the code base in question. If everyone involved are comfortable with free monads, or willing to learn, then I believe it's a viable option. Otherwise, I'd recommend falling back to partial application, even though Dependency Injection makes everything impure. @@ -289,10 +289,10 @@

    Like most other software design considerations, the overall purpose of application architecture is to deal with (essential) complexity. Thus, any example must be complex enough to warrant the design. There's little point in a Dependency Injection hello world example in C#. Likewise, a hello world example using free monads hardly seems justified. For that reason, examples are provided in separate articles.

    - A good place to start, I believe, is with the small Pure times article series. These articles show how to address a particular, authentic problem using strictly functional programming. The focus of these articles is on problem-solving, so they sometimes omit detailed explanations in order to keep the narrative moving. + A good place to start, I believe, is with the small Pure times article series. These articles show how to address a particular, authentic problem using strictly functional programming. The focus of these articles is on problem-solving, so they sometimes omit detailed explanations in order to keep the narrative moving.

    - If you need detailed explanations about all elements of free monads in F#, the present article series offers just that, particularly the Hello, pure command-line interaction article. + If you need detailed explanations about all elements of free monads in F#, the present article series offers just that, particularly the Hello, pure command-line interaction article.

    Variations # @@ -304,7 +304,7 @@

    There are, however, various degenerate cases that deserve a few words. An interaction may return no data, or take no input. In F#, you can always model the lack of data as unit (()), so it's definitely possible to define an instruction case like Foo of (unit * Out1 -> 'a), or Bar of (In2 * unit -> 'a), but since unit doesn't contain any data, you can remove it without changing the abstraction.

    - The Hello, pure command-line interaction article contains a single type that exemplifies both degenerate cases. It defines this instruction set: + The Hello, pure command-line interaction article contains a single type that exemplifies both degenerate cases. It defines this instruction set:

    type CommandLineInstruction<'a> =
    @@ -406,7 +406,7 @@ 

    - +

    Hello Yacoub, thank you for writing. Your summary of the motivations covers most of them. The reason that purity interests me is that it forces me (and everyone else) to consider decoupling. One day, I should write a more explicit article about this, but I believe that the general problem with programming today has little to do with writing code, but with reading it. Until I get such an article written, I can only refer to my Humane Code video, and perhaps my recent appearance on .NET Rocks!. What fundamentally interests me is how to break down code into small enough chunks that they fit in our brains at all levels of abstraction. Purity, and functional programming in general, attracts me because it offers a principled way of doing that. @@ -430,7 +430,7 @@

    The only way to prevent that in F# is by diligence.

    - That's a roundabout answer to your question. The gist of it, though, is that in F#, you rarely need free monads. If you find yourself in the situation where a free monad would be required in Haskell, you could just as well use DI, or rather, partial application. My article on that approach explains how this works in F#, but also why it doesn't work in Haskell. When you inject impure behaviour into an 'otherwise' pure function, then everything becomes impure. + That's a roundabout answer to your question. The gist of it, though, is that in F#, you rarely need free monads. If you find yourself in the situation where a free monad would be required in Haskell, you could just as well use DI, or rather, partial application. My article on that approach explains how this works in F#, but also why it doesn't work in Haskell. When you inject impure behaviour into an 'otherwise' pure function, then everything becomes impure.

    This is where F# differs from Haskell. In Haskell, such an attempt simply doesn't compile. In F#, an otherwise pure function suddenly becomes impure. If you mostly care about that distinction because of, say, testability, then that's not a problem, because when you 'inject' pure behaviour, then the composed function is still pure, and thus trivial to unit test. @@ -557,7 +557,7 @@

    - +

    Yacoub, thank you for the pseudo-code. That makes it easier to discuss things. @@ -662,10 +662,10 @@

    I care about purity because it eliminates entire classes of bugs. It also means that I don't have to log what happens inside my pure code; as long as I log what happens at the impure boundary, I can always reproduce the result of a pure computation. All this makes the overall code simpler. Logging, caching, instrumentation. Many cross-cutting concerns either disappear or greatly simplify.

    - Returning to the overall discussion related to this article, free monads are one way to separate pure code from impure code. What you suggest, though, isn't pure, because all it takes to make the entire composition impure is that dep2 or dep4 are impure (or one of the 'pure' functions turning out to be impure after all). It's Dependency Injection, only you replace interfaces with delegates. + Returning to the overall discussion related to this article, free monads are one way to separate pure code from impure code. What you suggest, though, isn't pure, because all it takes to make the entire composition impure is that dep2 or dep4 are impure (or one of the 'pure' functions turning out to be impure after all). It's Dependency Injection, only you replace interfaces with delegates.

    - Does it matter? Probably not. Trying to keep things 'as pure as possible' in C# and similar languages could still provide benefits. That's how I approach F#. Ultimately, the goal is to make the code sustainable. If you can do that with Dependency Injection or partial application, then the mission is accomplished. + Does it matter? Probably not. Trying to keep things 'as pure as possible' in C# and similar languages could still provide benefits. That's how I approach F#. Ultimately, the goal is to make the code sustainable. If you can do that with Dependency Injection or partial application, then the mission is accomplished.

    In Haskell, free monads are sometimes required, but in F#, it's a specialised design I'd only reach for in niche situations. diff --git a/_posts/2017-08-14-from-test-data-builders-to-the-identity-functor.html b/_posts/2017-08-14-from-test-data-builders-to-the-identity-functor.html index 65f792768..f1dd3bf36 100644 --- a/_posts/2017-08-14-from-test-data-builders-to-the-identity-functor.html +++ b/_posts/2017-08-14-from-test-data-builders-to-the-identity-functor.html @@ -16,14 +16,14 @@

    "Abstraction is the elimination of the irrelevant and the amplification of the essential"
    - Not only are Test Data Builders great abstractions, but they're also eminently composable. You can use fine-grained Test Data Builders as building blocks for more complex Test Data Builders. This turns out to be more than a coincidence. In this series of articles, you'll learn how Test Data Builders are closely related to the identity functor. If you don't know what a functor is, then keep reading; you'll learn about functors as well. + Not only are Test Data Builders great abstractions, but they're also eminently composable. You can use fine-grained Test Data Builders as building blocks for more complex Test Data Builders. This turns out to be more than a coincidence. In this series of articles, you'll learn how Test Data Builders are closely related to the identity functor. If you don't know what a functor is, then keep reading; you'll learn about functors as well.
      -
    1. Test Data Builders in C#
    2. -
    3. Generalised Test Data Builder
    4. -
    5. The Builder functor
    6. -
    7. Builder as Identity
    8. -
    9. Test data without Builders
    10. -
    11. (The Test Data Generator functor)
    12. +
    13. Test Data Builders in C#
    14. +
    15. Generalised Test Data Builder
    16. +
    17. The Builder functor
    18. +
    19. Builder as Identity
    20. +
    21. Test data without Builders
    22. +
    23. (The Test Data Generator functor)
    By reading these articles, you'll learn the following:

    \ No newline at end of file diff --git a/_posts/2017-08-15-test-data-builders-in-c.html b/_posts/2017-08-15-test-data-builders-in-c.html index 6b00cdcd2..00b04dfdb 100644 --- a/_posts/2017-08-15-test-data-builders-in-c.html +++ b/_posts/2017-08-15-test-data-builders-in-c.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is the first in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. + This is the first in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor.

    In 2007 Nat Pryce described the Test Data Builder design pattern. The original article is easy to read, but in case you don't want to read it, here's a quick summary, with some of Nat Pryce's examples translated to C#. @@ -135,13 +135,13 @@

    Summary #

    - Test Data Builders are useful because they are good abstractions. They enable you to write unit tests that you can trust. + Test Data Builders are useful because they are good abstractions. They enable you to write unit tests that you can trust.

    The disadvantage, as you shall see, is that in languages like C# and Java, much boilerplate code is required.

    - Next: Generalised Test Data Builder. + Next: Generalised Test Data Builder.

    @@ -159,7 +159,7 @@

    - +

    Mike, thank you for writing. The fluent interface that I show in this article is the most common form you see in C#. While it's not my preferred variation, I use it in this article because it's a direct translation of the style used in Nat Pryce's Java code. @@ -205,7 +205,7 @@

    - +

    Robert, thank you for writing. I haven't seen that particular C# variation before, but it looks useful. I hope that as this article series progresses, it should become increasingly clear to the reader that the Test Data Builder pattern addresses various language deficiencies. (It has, by the way, for some time been a common criticism of design patterns in general that they are nothing but patches on language deficiencies. I don't think that I agree with that 100 percent, but I certainly understand the argument.) @@ -235,7 +235,7 @@

    - +

    Romain, do you have an example of that, that you could share? @@ -270,7 +270,7 @@

    - +

    Do I understand it correctly that you'd have an interface like the following, then? @@ -319,7 +319,7 @@

    - +

    That helps clarify things, thank you. @@ -353,7 +353,7 @@

    - +

    Now I think I get it! Thank you for taking the time to explain. diff --git a/_posts/2017-08-21-generalised-test-data-builder.html b/_posts/2017-08-21-generalised-test-data-builder.html index 1cb092661..8dca106f9 100644 --- a/_posts/2017-08-21-generalised-test-data-builder.html +++ b/_posts/2017-08-21-generalised-test-data-builder.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is the second in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. The previous article was a review of the Test Data Builder pattern. + This is the second in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. The previous article was a review of the Test Data Builder pattern.

    Boilerplate # @@ -177,7 +177,7 @@

    Perhaps you wonder about the name of the Select method, but there's a good reason for that; you'll learn about it later.

    - This example of a generic Builder class overrides Equals (and, therefore, also GetHashCode). It doesn't have to do that, but there's a good reason to do this that we'll also come back to later. + This example of a generic Builder class overrides Equals (and, therefore, also GetHashCode). It doesn't have to do that, but there's a good reason to do this that we'll also come back to later.

    It doesn't seem particularly useful, and a first attempt at using it seems to confirm such scepticism: @@ -445,7 +445,7 @@

    If you still don't find this strategy's prospects fertile, I understand. We're not done, though. In the next article, you'll see why Select is an appropriate name for the Builder's most important method, and how it relates to good abstractions.

    - Next: The Builder functor. + Next: The Builder functor.

    @@ -472,7 +472,7 @@

    - +

    Harshdeep, thank you for writing. C# object initialisers aren't the same as F# Copy and Update Record Expressions. Unless I misunderstand what you mean, when you write diff --git a/_posts/2017-08-28-the-builder-functor.html b/_posts/2017-08-28-the-builder-functor.html index 61d39dde0..6c618f493 100644 --- a/_posts/2017-08-28-the-builder-functor.html +++ b/_posts/2017-08-28-the-builder-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is the third in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. The previous article introduced this generic Builder class: + This is the third in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. The previous article introduced this generic Builder class:

    public class Builder<T>
    @@ -118,7 +118,7 @@ 

    Isn't it amazing that the C# designers were able to come up with such a generally useful language feature? It certainly is a nice piece of work, but it's based on a an existing body of knowledge.

    - A type like Builder<T> with a suitable Select method is a functor. This is a term from category theory, but I'll try to avoid turning this article into a category theory lecture. Likewise, I'm not going to talk specifically about monads here, although it's a closely related topic. A functor is a mapping between categories; it maps an object from one category into an object of another category. + A type like Builder<T> with a suitable Select method is a functor. This is a term from category theory, but I'll try to avoid turning this article into a category theory lecture. Likewise, I'm not going to talk specifically about monads here, although it's a closely related topic. A functor is a mapping between categories; it maps an object from one category into an object of another category.

    Although I've never seen Microsoft explicitly acknowledge the connection to functors and monads, it's clear that it's there. One of the principal designers of LINQ was Erik Meijer, who definitely knows his way around category theory and functional programming. A functor is a simple, but widely applicable abstraction. @@ -258,7 +258,7 @@

    This can often be beneficial, but for Test Data Builders, it turns out to be a red herring. The Builder functor is nothing but the Identity functor in disguise.

    - Next: Builder as Identity. + Next: Builder as Identity.

    @@ -284,10 +284,10 @@

    Comments

    - +

    - Andrés, thank you for writing. I hope that the next two articles in this article series will answer your question. It seems, however, that you've already predicted where this is headed. A fine display of critical thinking! + Andrés, thank you for writing. I hope that the next two articles in this article series will answer your question. It seems, however, that you've already predicted where this is headed. A fine display of critical thinking!

    2017-08-29 17:48 UTC
    diff --git a/_posts/2017-09-04-builder-as-identity.html b/_posts/2017-09-04-builder-as-identity.html index 674a9800e..7642f05f0 100644 --- a/_posts/2017-09-04-builder-as-identity.html +++ b/_posts/2017-09-04-builder-as-identity.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is the fourth in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. In the previous article, you saw how a generic Test Data Builder can be modelled as a functor. + This is the fourth in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. In the previous article, you saw how a generic Test Data Builder can be modelled as a functor.

    You may, however, be excused if you're slightly underwhelmed. Modelling a Test Data Builder as a functor doesn't seem to add much value. @@ -97,12 +97,12 @@

    Summary #

    - Neither F# nor C# comes with a built-in identity functor, but it'd be as trivial to create them as the code you've already seen. In the previous article, you saw how to define a Builder<'a> type in F#. All you have to do is to change its name to Identity<'a>, and you have the identity functor. You can perform a similar rename for the C# code in the previous articles. + Neither F# nor C# comes with a built-in identity functor, but it'd be as trivial to create them as the code you've already seen. In the previous article, you saw how to define a Builder<'a> type in F#. All you have to do is to change its name to Identity<'a>, and you have the identity functor. You can perform a similar rename for the C# code in the previous articles.

    Since the Identity functor doesn't really 'do' anything, there's no reason to use it for building test values. In the next article, you'll see how to discard the functor and in the process make your code simpler.

    - Next: Test data without Builders. + Next: Test data without Builders.

    \ No newline at end of file diff --git a/_posts/2017-09-11-test-data-without-builders.html b/_posts/2017-09-11-test-data-without-builders.html index b55b0011f..23cd67f39 100644 --- a/_posts/2017-09-11-test-data-without-builders.html +++ b/_posts/2017-09-11-test-data-without-builders.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This is the fifth and final in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. In the previous article, you learned why a Builder functor adds little value. In this article, you'll see what to do instead. + This is the fifth and final in a series of articles about the relationship between the Test Data Builder design pattern, and the identity functor. In the previous article, you learned why a Builder functor adds little value. In this article, you'll see what to do instead.

    From Identity to naked values # @@ -78,7 +78,7 @@

    Building C# objects #

    - In a previous article, you saw how to refactor your domain model to a model of Value Objects with fluent interfaces. + In a previous article, you saw how to refactor your domain model to a model of Value Objects with fluent interfaces.

    In your unit tests, you can define natural default values for testing purposes: @@ -185,7 +185,7 @@

    Still, once you've tried using a language like F# or Haskell, where 'copy and update' expressions come with the language, you realise how much redundant code you're writing in C# or Java. The Test Data Builder design pattern truly is a recipe that addresses deficiencies in particular languages.

    - Next: The Test Data Generator functor. + Next: The Test Data Generator functor.

    diff --git a/_posts/2017-09-18-the-test-data-generator-functor.html b/_posts/2017-09-18-the-test-data-generator-functor.html index 6608cec20..3abd6638a 100644 --- a/_posts/2017-09-18-the-test-data-generator-functor.html +++ b/_posts/2017-09-18-the-test-data-generator-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In a previous article series, you learned that while it's possible to model Test Data Builders as a functor, it adds little value. You shouldn't, however, dismiss the value of functors. It's an abstraction that applies broadly. + In a previous article series, you learned that while it's possible to model Test Data Builders as a functor, it adds little value. You shouldn't, however, dismiss the value of functors. It's an abstraction that applies broadly.

    Closely related to Test Data Builders is the concept of a generator of random test data. You could call it a Test Data Generator instead. Such a generator can be modelled as a functor. @@ -163,7 +163,7 @@

    Generating values #

    - You can now write tests similar to the tests shown in the article series about Test Data Builders. If, for example, you need an address in Paris, you can generate it like this: + You can now write tests similar to the tests shown in the article series about Test Data Builders. If, for example, you need an address in Paris, you can generate it like this:

    var rnd = new Random();
    @@ -323,7 +323,7 @@ 

    Comments

    - +

    Stuart, thank you for writing. Test Data Generators like the one described here are rich data structures that you can do a lot of interesting things with. As described here, the generator only generates a single value every time you invoke its Generate method. What property-based testing libraries like QuickCheck, FsCheck, and Hedgehog do is that instead of a single random value, they generate many values (the default number seems to be 100). diff --git a/_posts/2017-09-25-interception-vis-a-vis-pure-di.html b/_posts/2017-09-25-interception-vis-a-vis-pure-di.html index f8346cfcd..f753728d4 100644 --- a/_posts/2017-09-25-interception-vis-a-vis-pure-di.html +++ b/_posts/2017-09-25-interception-vis-a-vis-pure-di.html @@ -29,13 +29,13 @@

    Position #

    - I do, indeed, prefer Pure DI, but there may be cases where a DI Container is warranted. Interception, or Aspect-Oriented Programming (AOP), is one such case, but obviously that doesn't help if you can't use a DI Container. + I do, indeed, prefer Pure DI, but there may be cases where a DI Container is warranted. Interception, or Aspect-Oriented Programming (AOP), is one such case, but obviously that doesn't help if you can't use a DI Container.

    Another option for AOP is some sort of post-processor of your code. As I briefly cover in chapter 9 of my book, in .NET this is typically done by a custom tool using 'IL-weaving'. As I also outline in the book, I'm not a big fan of this approach, but perhaps that could be an option in C++ as well. In any case, I'll proceed under the assumption that you want a strictly code-based solution, involving no custom tools or build steps.

    - All that said, I doubt that this is as much of a problem than one would think. AOP is typically used for cross-cutting concerns such as logging, caching, instrumentation, authorization, metering, or auditing. As an alternative, you can also use Decorators for such cross-cutting concerns. This seems daunting if you truly need to decorate hundreds, or even thousands, of classes. In such a case, convention-based interception seems like a DRYer option. + All that said, I doubt that this is as much of a problem than one would think. AOP is typically used for cross-cutting concerns such as logging, caching, instrumentation, authorization, metering, or auditing. As an alternative, you can also use Decorators for such cross-cutting concerns. This seems daunting if you truly need to decorate hundreds, or even thousands, of classes. In such a case, convention-based interception seems like a DRYer option.

    You'd think. @@ -53,7 +53,7 @@

    If you don't have a DI Container or an AOP tool, I believe that a Decorator is the best way to address cross-cutting concerns, and I don't think there's any way around adding those Decorator classes. The aim, then, becomes to minimise the effort involved in creating and maintaining such classes.

    - As an example, I'll revisit an old blog post. In that post, the task was to instrument an OrderProcessor class. The solution shown in that article was to use Castle Windsor to define an IInterceptor. + As an example, I'll revisit an old blog post. In that post, the task was to instrument an OrderProcessor class. The solution shown in that article was to use Castle Windsor to define an IInterceptor.

    To recapitulate, the code for the Interceptor looks like this: @@ -188,7 +188,7 @@

    I called this class InstrumentedOrderProcessor2 with the 2 postfix because the previous article already contains a InstrumentedOrderProcessor class, and I wanted to make it clear that this is a new class.

    - Notice that InstrumentedOrderProcessor2 is a Decorator of IOrderProcessor. It both implements the interface, and takes one as a dependency. It also takes an Instrument object as a Concrete Dependency. This is mostly to enable reuse of a single Instrument object; no polymorphism is implied. + Notice that InstrumentedOrderProcessor2 is a Decorator of IOrderProcessor. It both implements the interface, and takes one as a dependency. It also takes an Instrument object as a Concrete Dependency. This is mostly to enable reuse of a single Instrument object; no polymorphism is implied.

    The decorated Process method simply delegates to the instrument's Intercept method, passing as parameters the name of the method, the name of the decorated class, and a lambda expression that closes over the outer order method argument. diff --git a/_posts/2017-10-05-monoids-semigroups-and-friends.html b/_posts/2017-10-05-monoids-semigroups-and-friends.html index 205a048ed..856ca6ad3 100644 --- a/_posts/2017-10-05-monoids-semigroups-and-friends.html +++ b/_posts/2017-10-05-monoids-semigroups-and-friends.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article series is part of an even larger series of articles about the relationship between design patterns and category theory. + This article series is part of an even larger series of articles about the relationship between design patterns and category theory.

    Functional programming has often been criticised for its abstruse jargon. Terminology like zygohistomorphic prepromorphism doesn't help sell the message, but before we start throwing stones, we should first exit our own glass house. In object-oriented design, we have names like Bridge, Visitor, SOLID, cohesion, and so on. The words sound familiar, but can you actually explain or implement the Visitor design pattern, or characterise cohesion? @@ -35,10 +35,10 @@

    As Evans points out, object designs with that quality begins to look like arithmetic. If you have an operation that takes two Foo and returns a Foo, what could it be? Could it be like addition? Multiplication? Another mathematical operation?

    - Some enterprise developers just 'want to get stuff done', and don't care about mathematics. To them, the value of making code more mathematical is disputable. Still, even if you 'don't like maths', you understand addition, multiplication, and so on. Arithmetic is a powerful metaphor, because all programmers understand it. + Some enterprise developers just 'want to get stuff done', and don't care about mathematics. To them, the value of making code more mathematical is disputable. Still, even if you 'don't like maths', you understand addition, multiplication, and so on. Arithmetic is a powerful metaphor, because all programmers understand it.

    - In his book Test-Driven Development: By Example, Kent Beck seems to have the same hunch, although I don't think he ever explicitly calls it out. + In his book Test-Driven Development: By Example, Kent Beck seems to have the same hunch, although I don't think he ever explicitly calls it out.

    What Evans describes are monoids, semigroups, and similar concepts from abstract algebra. To be fair, I recently had the opportunity to discuss the matter with him, and he's perfectly aware of those concepts today. Whether he was aware of them when he wrote DDD in 2003 I don't know, but I certainly wasn't; my errand isn't to point fingers, but to point out that clever people have found this design principle valuable in object-oriented design long before they gave it a distinct name. @@ -55,30 +55,30 @@

    All magmas describe binary operations of the form: an operation takes two Foo values as input and returns a Foo value as output. Both categories are governed by (intuitive) laws. The difference is that the laws governing monoids are stricter than the laws governing semigroups. Don't be put off by the terminology; 'law' may sound like you have to get involved in complicated maths, but these laws are simple and intuitive. You'll learn them as you read on.

    @@ -94,7 +94,7 @@

    Whether or not an object is a magma tells us whether Evans' Closure of Operations is possible. It might teach us other things about our code, as well.

    - Next: Monoids. + Next: Monoids.

    @@ -124,7 +124,7 @@

    Comments

    - +

    Enrico, thank you for writing. Funny you should write that, because leading with an explanation of monoid is exactly what I do in my new Clean Coders episode Composite as Universal Abstraction. In short, monoid means 'one-like'. In the video, I go into more details on why that's a useful name. diff --git a/_posts/2017-10-06-monoids.html b/_posts/2017-10-06-monoids.html index 1007d64aa..8441a9628 100644 --- a/_posts/2017-10-06-monoids.html +++ b/_posts/2017-10-06-monoids.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a larger series about monoids, semigroups, and related concepts. In this article, you'll learn what a monoid is, and what distinguishes it from a semigroup. + This article is part of a larger series about monoids, semigroups, and related concepts. In this article, you'll learn what a monoid is, and what distinguishes it from a semigroup.

    Monoids are a subset of semigroups. @@ -133,15 +133,15 @@

    I'll leave you to ponder (or look up) all and any, and instead, in the next articles, show you some slightly more interesting monoids.

    In essence, if you have a data type that 'behaves like a number', you can probably make it a monoid. Addition is often the best candidate, because it doesn't mess with the dimensions of what you're keeping track of. As an example, the .NET Base Class Library defines a TimeSpan structure with an Add method. It also comes with a == operator. On the other hand, there's no Multiply method for TimeSpan, because what does it mean to multiply two durations? What would the dimension be? Time squared?

    @@ -155,7 +155,7 @@

    (By the way, the identity element for multiplication is one (1), the all monoid is boolean and, and the any monoid is boolean or.)

    - Next: Angular addition monoid + Next: Angular addition monoid

    @@ -188,7 +188,7 @@

    Comments

    This looks like it's going to be a fantastic series - I'm really looking forwards to reading the rest!

    -

    So, as we are talking about forming a vocabulary and reducing ambiguity, I have a question about the use of the word closure, which I think has more than one common meaning in this context.

    +

    So, as we are talking about forming a vocabulary and reducing ambiguity, I have a question about the use of the word closure, which I think has more than one common meaning in this context.

    In Eric Evans' "Closure of Operations", closure refers to the fact that the operation is "closed" over it's set of possible values - in other words, the set is closed under the operation.

    @@ -200,7 +200,7 @@

    Comments

    - +

    Sean, thank you for writing. That's a great observation, and one that I frankly admit that I hadn't made myself. In an ideal world, one of those concepts would have a different name, so that we'd be able to distinguish them from each other. @@ -226,7 +226,7 @@

    Comments

    - +

    Vitrun, thank you for writing. Yes, the identity for any is false, and for all it's true. There are two other monoids over Boolean values. Can you figure out what they are? @@ -252,7 +252,7 @@

    Comments

    - +

    Vitrun, thank you for your kind words. I don't know if I have a particular way of 'bridging the gap'; I try to identify patterns in the problems I run into, and then communicate those patterns in as simple a language as I can, with as helpful examples as I can think of... @@ -309,7 +309,7 @@

    Comments

    - +

    Jeremiah, thank you for writing, and please accept my apologies that I didn't respond right away. Not only do I write technical content, but I also read a fair bit of it, and my experience is that I often have to work with the topic in question in order to fully grasp it. Reading a text more than once is one way of doing it. When it comes to Boolean monoids, another way is to draw up some truth tables. A third way would be to simply play with Boolean expressions in your programming language of choice. Whatever it takes; if you learned something, then I'm happy. diff --git a/_posts/2017-10-10-strings-lists-and-sequences-as-a-monoid.html b/_posts/2017-10-10-strings-lists-and-sequences-as-a-monoid.html index 749322123..b2e45523a 100644 --- a/_posts/2017-10-10-strings-lists-and-sequences-as-a-monoid.html +++ b/_posts/2017-10-10-strings-lists-and-sequences-as-a-monoid.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity).

    Sequences # @@ -24,7 +24,7 @@

    xs.Concat(ys);

    - Here, xs and ys are instances of IEnumerable<T>. The Concat extension method concatenates two sequences together. It has the signature IEnumerable<T> Concat<T>(IEnumerable<T>, IEnumerable<T>), so it's a binary operation. If it's also associative and has identity, then it's a monoid. + Here, xs and ys are instances of IEnumerable<T>. The Concat extension method concatenates two sequences together. It has the signature IEnumerable<T> Concat<T>(IEnumerable<T>, IEnumerable<T>), so it's a binary operation. If it's also associative and has identity, then it's a monoid.

    Sequences are associative, because the order of evaluation doesn't change the outcome. Associativity is a property of a monoid, so one way to demonstrate this is with property-based testing: @@ -200,7 +200,7 @@

    Notice how in both cases, the seed value is the identity for the monoidal operation: 0 for addition, and 1 for multiplication. Likewise, the aggregator function uses the binary operation associated with that particular monoid.

    - I think it's interesting that this is called the free monoid, similar to free monads. In both cases, you collect data without initially interpreting it, and then later you can submit the collected data to one of several evaluators. + I think it's interesting that this is called the free monoid, similar to free monads. In both cases, you collect data without initially interpreting it, and then later you can submit the collected data to one of several evaluators.

    Summary # @@ -209,10 +209,10 @@

    Various collection types, like .NET sequences, arrays, or Haskell and F# lists, are monoids over concatenation. In Haskell, strings are lists, so string concatenation is a monoid as well. In .NET, the + operator for strings is a monoid if you pretend that null strings don't exist. Still, all of these are essentially variations of the same monoid.

    - It makes sense that C# uses + for string concatenation, because, as the previous article described, addition is the most intuitive and 'natural' of all monoids. Because you know first-grade arithmetic, you can immediately grasp the concept of addition as a metaphor. A monoid, however, is more than a metaphor; it's an abstraction that describes well-behaved binary operations, where one of those operations just happen to be addition. It's a generalisation of the concept. It's an abstraction that you already understand. + It makes sense that C# uses + for string concatenation, because, as the previous article described, addition is the most intuitive and 'natural' of all monoids. Because you know first-grade arithmetic, you can immediately grasp the concept of addition as a metaphor. A monoid, however, is more than a metaphor; it's an abstraction that describes well-behaved binary operations, where one of those operations just happen to be addition. It's a generalisation of the concept. It's an abstraction that you already understand.

    - Next: Money monoid. + Next: Money monoid.

    @@ -238,7 +238,7 @@

    - +

    Manuel, thank you for writing. The confusion is entirely caused by my sloppy writing. A monoid is an associative binary operation with identity. Since the free monoid essentially elevates each number to a singleton list, the binary operation in question is list concatenation. diff --git a/_posts/2017-10-16-money-monoid.html b/_posts/2017-10-16-money-monoid.html index a45233422..c21955ebd 100644 --- a/_posts/2017-10-16-money-monoid.html +++ b/_posts/2017-10-16-money-monoid.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity).

    In the first half of Test-Driven Development By Example Kent Beck explores how to develop a simple and flexible Money API using test-driven development. Towards the end, he arrives at a design that warrants further investigation. @@ -44,7 +44,7 @@

    The Times method multiplies an IExpression with a multiplier. You'll notice that, throughout this example code base, both multiplier and amounts are modelled as integers. I think that Kent Beck did this as a simplification, but a more realistic example should use decimal values.

    - The metaphor is that you can model money as one or more expressions. A simple expression would be 5 USD, but you could also have 5 USD + 10 CHF or 5 USD + 10 CHF + 10 USD. While you can reduce some expressions, such as 5 CHF + 7 CHF, you can't reduce an expression like 5 USD + 10 CHF unless you have an exchange rate. Instead of attempting to reduce monetary values, this particular design builds an expression tree until you decide to evaluate it. (Sounds familiar?) + The metaphor is that you can model money as one or more expressions. A simple expression would be 5 USD, but you could also have 5 USD + 10 CHF or 5 USD + 10 CHF + 10 USD. While you can reduce some expressions, such as 5 CHF + 7 CHF, you can't reduce an expression like 5 USD + 10 CHF unless you have an exchange rate. Instead of attempting to reduce monetary values, this particular design builds an expression tree until you decide to evaluate it. (Sounds familiar?)

    Kent Beck implements IExpression twice: @@ -65,7 +65,7 @@

    Associativity #

    - Did you notice that Plus is a binary operation? Could it be a monoid as well? + Did you notice that Plus is a binary operation? Could it be a monoid as well?

    In order to be a monoid, it must obey the monoid laws, the first of which is that the operation must be associative. This means that for three IExpression objects, x, y, and z, x.Plus(y).Plus(z) must be equal to x.Plus(y.Plus(z)). How should you interpret equality here? The return value from Plus is another IExpression value, and interfaces don't have custom equality behaviour. Either, it's up to the individual implementations (Money and Sum) to override and implement equality, or you can use test-specific equality. @@ -340,7 +340,7 @@

    In this article, we returned to a decade-old code example in order to identify it as a monoid. In the next article, I'm going to revisit an example code base of mine from 2015.

    - Next: Convex hull monoid. + Next: Convex hull monoid.

    @@ -360,7 +360,7 @@

    Comments

    - +

    Hrvoje, thank you for writing. Yes, it's a good point that you could model the values as cents and rappen, but I think I recall that Kent Beck's text distinctly discusses dollars and francs. I am, however, currently travelling, without access to the book, so I can't check. @@ -408,7 +408,7 @@

    Comments

    - +

    Ian, thank you for writing. Much of what you write about foreign exchange matches the little I know. What interested me about Kent Beck's example was that his intuition about good programming lead him to a monoidal design. diff --git a/_posts/2017-10-23-convex-hull-monoid.html b/_posts/2017-10-23-convex-hull-monoid.html index f63d5cd62..4566c2ea8 100644 --- a/_posts/2017-10-23-convex-hull-monoid.html +++ b/_posts/2017-10-23-convex-hull-monoid.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity).

    If you're reading the series as an object-oriented programmer, I apologise for the digression, but this article exclusively contains F# code. The next article will return with more C# examples. @@ -23,7 +23,7 @@

    Convex hull #

    - In a past article I've described my adventures with finding convex hulls in F#. The convex hulls I've been looking at form the external convex boundary of a set of two-dimensional points. While you can generalise the concept of convex hulls to n dimensions, we're going to stick to two-dimensional hulls here. + In a past article I've described my adventures with finding convex hulls in F#. The convex hulls I've been looking at form the external convex boundary of a set of two-dimensional points. While you can generalise the concept of convex hulls to n dimensions, we're going to stick to two-dimensional hulls here.

    A 2D convex hull example. @@ -129,13 +129,13 @@

    Summary #

    - If you consider that the Hull type is nothing but a container for a list, it should come as no surprise that a monoid exists. After all, list concatenation is a monoid, and the + operator shown here is a combination of list concatenation (@) and a Graham Scan. + If you consider that the Hull type is nothing but a container for a list, it should come as no surprise that a monoid exists. After all, list concatenation is a monoid, and the + operator shown here is a combination of list concatenation (@) and a Graham Scan.

    The point of this article was mostly to demonstrate that monoids exist not only for primitive types, but also for (some) more complex types. The + operator shown here is really a set union operation. What about intersections of convex hulls? Is that a monoid as well? I'll leave that as an exercise.

    - Next: Tuple monoids. + Next: Tuple monoids.

    @@ -153,7 +153,7 @@

    Comments

    - +

    Mikhail, thank you for writing. You can't replace hull with any other function and expect list concatenation to remain a monoid. I'm sorry if my turn of phrase gave that impression. I can see how one could interpret my summary in that way, but it wasn't my intention to imply that this relationship holds in general. It doesn't, and it's not hard to show, because we only need to come up with a single counter-example. diff --git a/_posts/2017-10-30-tuple-monoids.html b/_posts/2017-10-30-tuple-monoids.html index b4622e5b2..22ee16625 100644 --- a/_posts/2017-10-30-tuple-monoids.html +++ b/_posts/2017-10-30-tuple-monoids.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). This article starts off with some easy-to-understand, but abstract results. Once these are established, however, you'll see how to use them in a relatable example, so keep reading! + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). This article starts off with some easy-to-understand, but abstract results. Once these are established, however, you'll see how to use them in a relatable example, so keep reading!

    Tuples # @@ -50,7 +50,7 @@

    The way to read this is that for any monoid a and any monoid b, the pair (a, b) is also a monoid.

    - Perhaps this is easiest to understand with a C# example. Consider a tuple of the type Tuple<int, string>. Integers form monoids under both addition and multiplication, and strings are monoids under concatenation. Thus, you can make Tuple<int, string> form a monoid as well. For instance, use the multiplication monoid to define this binary operation: + Perhaps this is easiest to understand with a C# example. Consider a tuple of the type Tuple<int, string>. Integers form monoids under both addition and multiplication, and strings are monoids under concatenation. Thus, you can make Tuple<int, string> form a monoid as well. For instance, use the multiplication monoid to define this binary operation:

    public static Tuple<intstring> CombinePair(
    @@ -172,7 +172,7 @@ 

    As on object-oriented developer, then why should you care that tuples of monoids are monoids?

    - The reason this is interesting in object-oriented programming is that there's a strong relationship between tuples and data objects (Value Objects or Data Transfer Objects). Consider the Customer examples that I sketched out a few paragraphs above. As you'll learn in a future article, you can refactor a tuple to a class, or a class to a tuple. + The reason this is interesting in object-oriented programming is that there's a strong relationship between tuples and data objects (Value Objects or Data Transfer Objects). Consider the Customer examples that I sketched out a few paragraphs above. As you'll learn in a future article, you can refactor a tuple to a class, or a class to a tuple.

    Example: Roster # @@ -239,7 +239,7 @@

    }

    - The Combine method is an instance method on the Roster class, taking a second Roster as input, and returning a new Roster value. It's a binary operation. Does it also have identity? + The Combine method is an instance method on the Roster class, taking a second Roster as input, and returning a new Roster value. It's a binary operation. Does it also have identity?

    Yes, it does: @@ -279,7 +279,7 @@

    Roster isomorphism #

    - In future articles, you'll learn more about isomorphisms between various representations of objects, but in this context, I think it's relevant to show how the Roster example is isomorphic to a tuple. It's trivial, really: + In future articles, you'll learn more about isomorphisms between various representations of objects, but in this context, I think it's relevant to show how the Roster example is isomorphic to a tuple. It's trivial, really:

    public Tuple<intintstring[]> ToTriple()
    @@ -320,7 +320,7 @@ 

    Tuples of monoids are also monoids. This holds for tuples of any size, but all of the elements has to be monoids. By isomorphism, this result also applies to data objects.

    - Next: Function monoids. + Next: Function monoids.

    @@ -338,7 +338,7 @@

    Comments

    - +

    Punkislamist, thank you for writing. You're entirely correct that a monoid is an associative binary operation with identity. It's a function, not a type. If this article is unclear, the fault is all mine. @@ -412,7 +412,7 @@

    Comments

    - +

    Punkislamist, thank you for those kind words. I'm happy to hear that what I wrote made sense to you; it makes sense to me, but I forgot to point out that I'm hardly an expert in category theory. Writing out the above answer helped clarify some things for me as well; as is common wisdom: you only really understand a topic when you teach it. diff --git a/_posts/2017-10-4-from-design-patterns-to-category-theory.html b/_posts/2017-10-4-from-design-patterns-to-category-theory.html index a6cbcd185..4e6e8377c 100644 --- a/_posts/2017-10-4-from-design-patterns-to-category-theory.html +++ b/_posts/2017-10-4-from-design-patterns-to-category-theory.html @@ -112,7 +112,7 @@

    Mathematics.

    - Stay with me, please. If you're a normal reader of my blog, you're most likely an 'industry programmer' or enterprise developer. You're not interested in mathematics. Perhaps mathematics even turns you off, and at the very least, you never had use for mathematics in programming. + Stay with me, please. If you're a normal reader of my blog, you're most likely an 'industry programmer' or enterprise developer. You're not interested in mathematics. Perhaps mathematics even turns you off, and at the very least, you never had use for mathematics in programming.

    You may not find n-dimensional differential topology, or stochastic calculus, intuitive, but that's not the kind of mathematics I have in mind. @@ -138,101 +138,101 @@

    The coming article series is an exploration of this space:

    @@ -274,7 +274,7 @@

    I've been thinking about these topics for years. What's a good abstraction? When do abstractions compose?

    - My first attempt at answering these questions was in 2010, but while I had the experience that certain abstractions composed better than others, I lacked the vocabulary. I've been wanting to write a better treatment of the topic ever since, but I've been constantly learning as I've grappled with the concepts. + My first attempt at answering these questions was in 2010, but while I had the experience that certain abstractions composed better than others, I lacked the vocabulary. I've been wanting to write a better treatment of the topic ever since, but I've been constantly learning as I've grappled with the concepts.

    I believe that I now have the vocabulary to take a stab at this again. This is hardly the ultimate treatment. A year from now, I hope to have learned even more, and perhaps that'll lead to further insights or refinement. Still, I can't postpone writing this article until I've stopped learning, because at that time I'll either be dead or senile. @@ -298,7 +298,7 @@

    The design patterns movement was an early attempt to create such a vocabulary. I think using category theory offers the chance of a better vocabulary, but fortunately, all the work that went into design patterns isn't wasted. It seems to me that some design patterns are essentially ad-hoc, informally specified, specialised instances of basic category theory concepts. There's quite a bit of overlap. This should further strengthen the argument that category theory is valuable in programming, because some of the concepts are equivalent to design patterns that have already proven useful.

    - Next: Monoids, semigroups, and friends. + Next: Monoids, semigroups, and friends.

    diff --git a/_posts/2017-11-06-function-monoids.html b/_posts/2017-11-06-function-monoids.html index ee3a3efc2..acf7b9e65 100644 --- a/_posts/2017-11-06-function-monoids.html +++ b/_posts/2017-11-06-function-monoids.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity).

    Functions # @@ -24,7 +24,7 @@

    public Foo Bar(Baz baz, Qux qux)

    - As you'll see in another article, however, you can refactor any method to a method that takes a single argument as input, and returns a single (possibly complex) value as output. In abstract form, we can write it like this: + As you'll see in another article, however, you can refactor any method to a method that takes a single argument as input, and returns a single (possibly complex) value as output. In abstract form, we can write it like this:

    public Out1 Op1(In1 arg)
    @@ -38,7 +38,7 @@ 

    - Another article demonstrates how this is similar to a generic function. In F#, for instance, the type of the function would be written as 'a -> 'b, whereas in Haskell it'd be written a -> b. The way to read this is that the function takes a value of the generic type T1/'a/a as input, and returns a value of the generic type T/'b/b as output. For the rest of this article, I'll favour the Haskell syntax, since it has minimal noise. + Another article demonstrates how this is similar to a generic function. In F#, for instance, the type of the function would be written as 'a -> 'b, whereas in Haskell it'd be written a -> b. The way to read this is that the function takes a value of the generic type T1/'a/a as input, and returns a value of the generic type T/'b/b as output. For the rest of this article, I'll favour the Haskell syntax, since it has minimal noise.

    To be clear, however, although I favour the Haskell syntax because of its succinctness, I don't mean to imply that the functions that I discuss are exclusively pure - think of an F# function 'a -> 'b which may or may not be pure. @@ -164,6 +164,6 @@

    A function or method with a return type that forms a monoid is itself a monoid.

    - Next: Endomorphism monoid. + Next: Endomorphism monoid.

    diff --git a/_posts/2017-11-13-endomorphism-monoid.html b/_posts/2017-11-13-endomorphism-monoid.html index a5402a541..3fca23458 100644 --- a/_posts/2017-11-13-endomorphism-monoid.html +++ b/_posts/2017-11-13-endomorphism-monoid.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). Methods that return the same type of value as their input form monoids over composition. The formal term for such an operation is an endomorphism. + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). Methods that return the same type of value as their input form monoids over composition. The formal term for such an operation is an endomorphism.

    Scheduling example #

    - Imagine that you have to develop some functionality for scheduling events in the future. As a concrete example, I recently wrote about adjusting dates while taking bank holidays into account. For instance, if you want to find the latest bank day before a given date, you could call the AdjustToLatestPrecedingDutchBankDay method. If you give it a normal bank day (say, a Thursday), it'll simply return the input date, but if you give it a Sunday, it'll return the preceding Friday. That is, unless that particular Friday is a bank holiday, in which case it'll return the Thursday before - as long as that's not also a bank holiday, and so on. + Imagine that you have to develop some functionality for scheduling events in the future. As a concrete example, I recently wrote about adjusting dates while taking bank holidays into account. For instance, if you want to find the latest bank day before a given date, you could call the AdjustToLatestPrecedingDutchBankDay method. If you give it a normal bank day (say, a Thursday), it'll simply return the input date, but if you give it a Sunday, it'll return the preceding Friday. That is, unless that particular Friday is a bank holiday, in which case it'll return the Thursday before - as long as that's not also a bank holiday, and so on.

    In that previous article, the AdjustToLatestPrecedingDutchBankDay method is an extension method, but you can also model it as an instance method, like this: @@ -202,7 +202,7 @@

    A method that returns a value of the same type as its (singular) input argument is called an endomorphism. You can compose two such unary operations together in order to get a composed operation. You simply take the output of the first method and use it as the input argument for the second method. That composition is a monoid. Endomorphisms form monoids.

    - Next: Maybe monoids. + Next: Maybe monoids.

    @@ -245,13 +245,13 @@

    Comments

    - +

    Tor, thank you for writing, and for your kind words. I suppose that the CounterExample test fails when one executes it; you don't explicitly write that, but that's what I expect would happen.

    - The Append operation is, indeed, not commutative. This is, however, not a requirement for monoids, or even for groups. Some monoids, such as addition and multiplication, are also commutative, while others, like list concatenation or, here, the endomorphism monoid, aren't. + The Append operation is, indeed, not commutative. This is, however, not a requirement for monoids, or even for groups. Some monoids, such as addition and multiplication, are also commutative, while others, like list concatenation or, here, the endomorphism monoid, aren't.

    When it comes to the FsCheck properties, I admit that I cheated slightly with the code listing in the article. I did this because the properties are a bit more complicated than what I show, and I was concerned that the extra infrastructure surrounding those tests would detract from the overall message. @@ -326,7 +326,7 @@

    Comments

    - Thank you for such a prompt and thorough reply. You are of course correct, I have been confusing associativity with commutativity. I didn't run into the same mistake during the list concatenation article, though, maybe because list concatenation more obviously is associative and not commutative. In the current article, however, I intuitively felt that the operations needed to be commutative, but your reply clears that up. + Thank you for such a prompt and thorough reply. You are of course correct, I have been confusing associativity with commutativity. I didn't run into the same mistake during the list concatenation article, though, maybe because list concatenation more obviously is associative and not commutative. In the current article, however, I intuitively felt that the operations needed to be commutative, but your reply clears that up.

    It is also helpful to see the extra scaffolding around your property based test. The article itself seemed to imply that instances of IDateTimeOffsetAdjustment could be automatically generated. Your approach to set up such a test will come in handy now that I'm convinced that I should let more of my tests be property based, even in C#! @@ -336,7 +336,7 @@

    Comments

    - +

    Tor, I made the same mistake several times when I started researching all of this. I think that there's something intuitive and fundamental about commutativity, so at a superficial glance, it seems odd that we can do without it, while at the same time requiring a less intuitive property like associativity. diff --git a/_posts/2017-11-20-monoids-accumulate.html b/_posts/2017-11-20-monoids-accumulate.html index b2b7a4520..f12f77fee 100644 --- a/_posts/2017-11-20-monoids-accumulate.html +++ b/_posts/2017-11-20-monoids-accumulate.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity).

    Recall that a binary operation is an operation involving two arguments of the same type, and returning a value of that type. @@ -84,7 +84,7 @@

    The way to read this is that there's a function called fold, and it accumulates any monoid m contained in any 'foldable' data container t. That a data container is 'foldable' means that there's a way to somehow fold, or aggregate, the element(s) in the container into a value.

    - Linked lists, arrays, and other types of sequences are foldable, as are Maybe and trees. + Linked lists, arrays, and other types of sequences are foldable, as are Maybe and trees.

    In fact, there's little difference between Haskell's Foldable type class and .NET's IEnumerable<T>, but as the names suggest, their foci are different. In Haskell, the focus is being able to fold, accumulate, or aggregate a data structure, whereas on .NET the focus is on being able to enumerate the values inside the data structure. Ultimately, though, both abstractions afford the same capabilities. @@ -105,7 +105,7 @@

    This article concludes the article series about monoids. In the next series of articles, you'll learn about a related category of operations.

    - Next: Semigroups. + Next: Semigroups.

    diff --git a/_posts/2017-11-27-semigroups.html b/_posts/2017-11-27-semigroups.html index 9d562ca04..ba4542bc4 100644 --- a/_posts/2017-11-27-semigroups.html +++ b/_posts/2017-11-27-semigroups.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll learn what a semigroup is, and what distinguishes it from a monoid. + This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll learn what a semigroup is, and what distinguishes it from a monoid.

    Monoids are a subset of semigroups. @@ -217,12 +217,12 @@

    Summary #

    - Semigroups are associative binary operations. In the previous article series about monoids you saw plenty of examples, and since all monoids are semigroups, you've already seen more than one semigroup example. In this article, however, you saw four examples of semigroups that are not monoids. + Semigroups are associative binary operations. In the previous article series about monoids you saw plenty of examples, and since all monoids are semigroups, you've already seen more than one semigroup example. In this article, however, you saw four examples of semigroups that are not monoids.

    All four examples in this article are simple, and may not seem like 'real-world' examples. In the next article, then, you'll get a more realistic example of a semigroup that's not a monoid.

    - Next: Bounding box semigroup. + Next: Bounding box semigroup.

    diff --git a/_posts/2017-12-04-bounding-box-semigroup.html b/_posts/2017-12-04-bounding-box-semigroup.html index e77d8c15d..4181757ed 100644 --- a/_posts/2017-12-04-bounding-box-semigroup.html +++ b/_posts/2017-12-04-bounding-box-semigroup.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll see a non-trivial example of a semigroup that's not a monoid. In short, a semigroup is an associative binary operation. + This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll see a non-trivial example of a semigroup that's not a monoid. In short, a semigroup is an associative binary operation.

    Shapes # @@ -87,7 +87,7 @@

    }

    - The Unite method is an instance method on the BoundingBox class, so it's a binary operation. It's also associative, because for all x, y, and z, isAssociative is true: + The Unite method is an instance method on the BoundingBox class, so it's a binary operation. It's also associative, because for all x, y, and z, isAssociative is true:

    var isAssociative = x.Unite(y).Unite(z) == x.Unite(y.Unite(z));
    @@ -99,7 +99,7 @@

    Lack of identity #

    - Is Unite also a monoid? In order to be a monoid, a binary operation must not only be associative, but also have an identity element. In a previous article, you saw how the union of two convex hulls formed a monoid. A bounding box seems to be conceptually similar to a convex hull, so you'd be excused to think that our previous experience applies here as well. + Is Unite also a monoid? In order to be a monoid, a binary operation must not only be associative, but also have an identity element. In a previous article, you saw how the union of two convex hulls formed a monoid. A bounding box seems to be conceptually similar to a convex hull, so you'd be excused to think that our previous experience applies here as well.

    It doesn't. @@ -195,7 +195,7 @@

    This article demonstrates (via an example) that non-trivial semigroups exist in normal object-oriented programming.

    - Next: Semigroups accumulate. + Next: Semigroups accumulate.

    @@ -218,7 +218,7 @@

    Comments

    - +

    Yacoub, thank you for writing. The operation used here isn't the intersection, but rather the union of two bounding boxes; that's the reason I called the method Unite. @@ -241,7 +241,7 @@

    Comments

    - +

    Yacoub, I think you're right; sorry about that! @@ -266,7 +266,7 @@

    Comments

    - +

    Yacoub, I've corrected the text in the article. Thank you for the feedback! diff --git a/_posts/2017-12-11-semigroups-accumulate.html b/_posts/2017-12-11-semigroups-accumulate.html index f54fc384f..be237cd00 100644 --- a/_posts/2017-12-11-semigroups-accumulate.html +++ b/_posts/2017-12-11-semigroups-accumulate.html @@ -12,10 +12,10 @@ {{ page.description }}

    - This article is part of a series about semigroups. In short, a semigroup is an associative binary operation. + This article is part of a series about semigroups. In short, a semigroup is an associative binary operation.

    - As you've learned in a previous article, you can accumulate an arbitrary number of monoidal values to a single value. A corresponding property holds for semigroups. + As you've learned in a previous article, you can accumulate an arbitrary number of monoidal values to a single value. A corresponding property holds for semigroups.

    Monoid accumulation # @@ -129,7 +129,7 @@

    1337

    - That's hardly the idiomatic way of getting a maximum element in Haskell, but it does show how you can 'click together' concepts in order to achieve a goal. + That's hardly the idiomatic way of getting a maximum element in Haskell, but it does show how you can 'click together' concepts in order to achieve a goal.

    Aggregate # @@ -155,6 +155,6 @@

    A semigroup operation can be used to reduce values to a single value, just like a monoid can. The only difference is that a semigroup operation can't reduce an empty collection, whereas a monoid can.

    - Next: Quasigroups + Next: Quasigroups

    \ No newline at end of file diff --git a/_posts/2017-12-18-quasigroups.html b/_posts/2017-12-18-quasigroups.html index 36484d182..943d0b660 100644 --- a/_posts/2017-12-18-quasigroups.html +++ b/_posts/2017-12-18-quasigroups.html @@ -12,10 +12,10 @@ {{ page.description }}

    - This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll get acquainted with the concept of a quasigroup. I don't think it plays that big of a role in software design, but it is a thing, and I thought that I'd cover it briefly with a well known-example. + This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll get acquainted with the concept of a quasigroup. I don't think it plays that big of a role in software design, but it is a thing, and I thought that I'd cover it briefly with a well known-example.

    - During all this talk of monoids and semigroups, you've seen that normal arithmetic operations like addition and multiplication form monoids. Perhaps you've been wondering where subtraction fits in. + During all this talk of monoids and semigroups, you've seen that normal arithmetic operations like addition and multiplication form monoids. Perhaps you've been wondering where subtraction fits in.

    Subtraction forms a quasigroup. @@ -95,6 +95,6 @@

    What if, however, you have a binary operation with no other properties?

    - Next: Magmas. + Next: Magmas.

    \ No newline at end of file diff --git a/_posts/2017-12-27-magmas.html b/_posts/2017-12-27-magmas.html index 545889710..8bce5e56f 100644 --- a/_posts/2017-12-27-magmas.html +++ b/_posts/2017-12-27-magmas.html @@ -14,7 +14,7 @@ {{ page.description }}

    - In the overall article series about group-like algebraic structures, you've so far seen examples of monoids, semigroups, and quasigroups. Common to all of these structures is that they are binary operations governed by at least one law. The laws are different for the different categories, but there are rules. + In the overall article series about group-like algebraic structures, you've so far seen examples of monoids, semigroups, and quasigroups. Common to all of these structures is that they are binary operations governed by at least one law. The laws are different for the different categories, but there are rules.

    What if you have a binary operation that follows none of those rules? @@ -31,12 +31,12 @@

    Still, it's not that hard to come up with some programming examples of magmas that aren't semi- or quasigroups. In the next articles, you'll see some examples.

    Particularly the second example is fairly realistic, which demonstrates that as programmers, we can benefit from having vocabulary that enables us to describe any binary operation that doesn't obey any particular laws. In fact, establishing a vocabulary has been my primary motivation for writing this article series.

    - Next: Rock Paper Scissors magma + Next: Rock Paper Scissors magma

    \ No newline at end of file diff --git a/_posts/2017-12-28-rock-paper-scissors-magma.html b/_posts/2017-12-28-rock-paper-scissors-magma.html index 630505b9d..697440957 100644 --- a/_posts/2017-12-28-rock-paper-scissors-magma.html +++ b/_posts/2017-12-28-rock-paper-scissors-magma.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll see an example of a magma, which is a binary operation without additional constraints. + This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll see an example of a magma, which is a binary operation without additional constraints.

    Rock Paper Scissors # @@ -82,7 +82,7 @@

    To a C# programmer, perhaps the method name Throw is bewildering, because you might expect the method to throw an exception, but I chose to use the domain language of the game.

    - Because this method takes two Rps values as input and returns an Rps value as output, it's a binary operation. Thus, you already know it's a magma, but could it, also, be another, stricter binary operations, such as a semigroup or quasigroup? + Because this method takes two Rps values as input and returns an Rps value as output, it's a binary operation. Thus, you already know it's a magma, but could it, also, be another, stricter binary operations, such as a semigroup or quasigroup?

    Lack of associativity # @@ -104,7 +104,7 @@

    This xUnit.net unit test passes, thereby demonstrating that Throw is not associative. The result of paper versus rock is paper, which, pitted against scissors yields scissors. On the other hand, paper versus the result of rock versus scissors is paper, because rock versus scissors is rock, and rock versus paper is paper.

    - Since Throw isn't associative, it's not a semigroup (and, by extension, not a monoid). Could it be a quasigroup? + Since Throw isn't associative, it's not a semigroup (and, by extension, not a monoid). Could it be a quasigroup?

    Lack of invertibility # @@ -205,6 +205,6 @@

    The Rock Paper Scissors Throw operation is a commutative magma, but while, for example, we call an associative magma a semigroup, there's no fancy word for a commutative magma.

    - Next: Colour-mixing magma. + Next: Colour-mixing magma.

    \ No newline at end of file diff --git a/_posts/2018-01-02-colour-mixing-magma.html b/_posts/2018-01-02-colour-mixing-magma.html index 33da96c99..0a490dc90 100644 --- a/_posts/2018-01-02-colour-mixing-magma.html +++ b/_posts/2018-01-02-colour-mixing-magma.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll see an example of a magma, which is a binary operation without additional constraints. + This article is part of a larger series about monoids, semigroups, and other group-like algebraic structures. In this article, you'll see an example of a magma, which is a binary operation without additional constraints.

    RGB colours #

    - The opening article about monoids, semigropus, and their friends emphasised Eric Evans' pigment mixing example from Domain-Driven Design. The following article series then promptly proceeded to ignore that example. The reason is that while the example has Closure of Operations, it exhibits precious few other properties. It's neither monoid, semigroup, quasigroup, nor any other named binary operation, apart from being a magma. + The opening article about monoids, semigropus, and their friends emphasised Eric Evans' pigment mixing example from Domain-Driven Design. The following article series then promptly proceeded to ignore that example. The reason is that while the example has Closure of Operations, it exhibits precious few other properties. It's neither monoid, semigroup, quasigroup, nor any other named binary operation, apart from being a magma.

    Instead of pigments, consider a more primitive, but well-understood colour model: that of RGB colours. In C#, you can model RGB colours using a struct that holds three byte fields. In my final code base, I ended up implementing ==, !=, Equals, and so on, but I'm not going to bore you with all of those details. Here's the RgbColor constructor, so that you can get a sense of the type: @@ -51,7 +51,7 @@

    }

    - This is a binary operation, because it's an instance method on RgbColor, taking another RgbColor as input, and returning RgbColor. Since it's a binary operation, it's a magma, but could it be another, stricter category of operation? + This is a binary operation, because it's an instance method on RgbColor, taking another RgbColor as input, and returning RgbColor. Since it's a binary operation, it's a magma, but could it be another, stricter category of operation?

    Lack of associativity # @@ -202,9 +202,9 @@

    The MixWith operation is a commutative magma, but while, for example, we call an associative magma a semigroup, there's no fancy word for a commutative magma.

    - In this article, you got another, fairly realistic, example of a binary operation. Throughout the overall article series on monoids, semigroup, and other group-like algebraic structures, you've seen many examples, and you've learned how to analyse binary operations for the presence or absence of various properties. The present article concludes the series. You can, however, continue reading the even more overall article series. + In this article, you got another, fairly realistic, example of a binary operation. Throughout the overall article series on monoids, semigroup, and other group-like algebraic structures, you've seen many examples, and you've learned how to analyse binary operations for the presence or absence of various properties. The present article concludes the series. You can, however, continue reading the even more overall article series.

    - Next: Functors, applicatives, and friends + Next: Functors, applicatives, and friends

    \ No newline at end of file diff --git a/_posts/2018-01-08-software-design-isomorphisms.html b/_posts/2018-01-08-software-design-isomorphisms.html index 745f227ae..a5227e5f5 100644 --- a/_posts/2018-01-08-software-design-isomorphisms.html +++ b/_posts/2018-01-08-software-design-isomorphisms.html @@ -14,10 +14,10 @@ {{ page.description }}

    - This article series is part of an even larger series of articles about the relationship between design patterns and category theory. + This article series is part of an even larger series of articles about the relationship between design patterns and category theory.

    - There's a school of functional programming that looks to category theory for inspiration, verification, abstraction, and cross-pollination of ideas. Perhaps you're put off by terms like zygohistomorphic prepromorphism (a joke), but you shouldn't be. There are often good reasons for using abstract naming. In any case, one term from category theory that occasionally makes the rounds is isomorphism. + There's a school of functional programming that looks to category theory for inspiration, verification, abstraction, and cross-pollination of ideas. Perhaps you're put off by terms like zygohistomorphic prepromorphism (a joke), but you shouldn't be. There are often good reasons for using abstract naming. In any case, one term from category theory that occasionally makes the rounds is isomorphism.

    Equivalence # @@ -89,18 +89,18 @@

    There are many other isomorphisms in programming. Some are morphisms in the same language, as is the case with the above C# example. This is also the case with the isomorphisms in Refactoring, because a refactoring, by definition, is a change applied to a particular code base, be it C#, Java, Ruby, or Python.

    - Other programming isomorphisms go between languages, where a concept can be modelled in one way in, say, C++, but in another way in Clojure. The present blog, for instance, contains several examples of translating between C# and F#, and between F# and Haskell. + Other programming isomorphisms go between languages, where a concept can be modelled in one way in, say, C++, but in another way in Clojure. The present blog, for instance, contains several examples of translating between C# and F#, and between F# and Haskell.

    Being aware of software design isomorphisms can make you a better programmer. It'll enable you to select the best alternative for solving a particular problem. Identifying programming isomorphisms is also important because it'll enable us to formally think about code structure by reducing many alternative representations to a canonical representation. For these reasons, this article presents a catalogue of software design isomorphisms:

    In general, I've tried to name each isomorphism after its canonical representation. For instance, by unit isomorphisms, I mean isomorphisms to the unit value. It is, however, not an entirely consistent naming strategy.

    @@ -120,7 +120,7 @@

    Understanding how code is isomorphic to other code enables us to reduce many alternatives to a canonical representation. This makes analysis easier, because we can narrow our analysis to the canonical form, and generalise from there.

    - Next: Unit isomorphisms. + Next: Unit isomorphisms.

    @@ -138,7 +138,7 @@

    - +

    Sergey, thank you for writing. Good point, you're right that viewed as a general-purpose translation, Inline Method is indeed lossy. When you look at the purpose of refactoring code, the motivation is mostly (if not always) to make the code better in some way. Particularly when the purpose is make the code more readable, a refactoring introduces clarity. Thus, going the opposite way would remove that clarity, so I think it's fair to argue that such a change would be lossy. @@ -153,7 +153,7 @@

    One quality of morphisms is that there can be several translations between two objects. One such translation could be the general-purpose refactoring that you so rightly point out is lossy. Another translation could be one that 'remembers' the name of the original method.

    - Take, as an example, the isomorphism described under the heading Roster isomorphism in my article Tuple monoids. When you consider the method ToTriple, you could, indeed, argue that it's lossy, because it 'forgets' that the label associated with the first integer is Girls, that the label associated with the second integer is Boys, and so on. The reverse translation, however, 'remembers' that information, as you can see in the implementation of FromTriple. + Take, as an example, the isomorphism described under the heading Roster isomorphism in my article Tuple monoids. When you consider the method ToTriple, you could, indeed, argue that it's lossy, because it 'forgets' that the label associated with the first integer is Girls, that the label associated with the second integer is Boys, and so on. The reverse translation, however, 'remembers' that information, as you can see in the implementation of FromTriple.

    This isn't necessarily a 'safe' translation. You could easily write a method like this: @@ -171,7 +171,7 @@

    On the other hand, the pair of translations that I do show in the article is an isomorphism. The point is that an isomorphism exists; not that it's the only possible set of morphisms.

    - The same argument can be applied to specific pairs of Extract Method and Inline Method. As a general-purpose algorithm, I still agree that Inline Method is lossy. That doesn't preclude that specific pairs of translations exist. For instance, in an article, I discuss how some people refactor Guard Clauses like this: + The same argument can be applied to specific pairs of Extract Method and Inline Method. As a general-purpose algorithm, I still agree that Inline Method is lossy. That doesn't preclude that specific pairs of translations exist. For instance, in an article, I discuss how some people refactor Guard Clauses like this:

    if (subject == null)
    diff --git a/_posts/2018-01-15-unit-isomorphisms.html b/_posts/2018-01-15-unit-isomorphisms.html
    index 5a47f8828..71f79982f 100644
    --- a/_posts/2018-01-15-unit-isomorphisms.html
    +++ b/_posts/2018-01-15-unit-isomorphisms.html
    @@ -14,7 +14,7 @@
     		{{ page.description }}
     	

    - This article is part of a series of articles about software design isomorphisms. + This article is part of a series of articles about software design isomorphisms.

    Many programming languages, such as C# and Java, distinguish between methods that return something, and methods that don't return anything. In C# and Java, a method must be declared with a return type, but if it doesn't return anything, you can use the special keyword void to indicate that this is the case: @@ -120,7 +120,7 @@

    Monoid #

    - Unit, by the way, forms a monoid. This is most evident in Haskell, where this is encoded into the type. In general, a monoid is a binary operation, and not a type, but what could the combination of two () (unit) values be, other than ()? + Unit, by the way, forms a monoid. This is most evident in Haskell, where this is encoded into the type. In general, a monoid is a binary operation, and not a type, but what could the combination of two () (unit) values be, other than ()?

    λ> mempty :: ()
    @@ -136,7 +136,7 @@ 

    Since only a single unit value exists, any binary operation is automatically associative, because, after all, it can only return unit. Likewise, unit is the identity (mempty) for the operation, because it doesn't change the output. Thus, the monoid laws hold, and unit forms a monoid.

    - This result is interesting when you start to think about composition, because a monoid can always be used to reduce (aggregate) multiple values to a single value. With this result, and unit isomorphism, we've already explained why Commands are composable. + This result is interesting when you start to think about composition, because a monoid can always be used to reduce (aggregate) multiple values to a single value. With this result, and unit isomorphism, we've already explained why Commands are composable.

    Summary # @@ -157,6 +157,6 @@

    Unit isomorphism is an example of an interlingual isomorphism, in the sense that C# void maps to F# unit, and vice versa. In the next example, you'll see an isomorphism that mostly stays within a single language, although a translation between languages is also pertinent.

    - Next: Function isomorphisms. + Next: Function isomorphisms.

    diff --git a/_posts/2018-01-22-function-isomorphisms.html b/_posts/2018-01-22-function-isomorphisms.html index 91a56706f..2eb4f6ba2 100644 --- a/_posts/2018-01-22-function-isomorphisms.html +++ b/_posts/2018-01-22-function-isomorphisms.html @@ -14,10 +14,10 @@ {{ page.description }}

    - This article is part of a series of articles about software design isomorphisms. + This article is part of a series of articles about software design isomorphisms.

    - While I have already, in an earlier article, quoted the following parable about Anton, Qc Na, objects, and closures, it's too good a fit to the current topic to pass up, so please pardon the duplication. + While I have already, in an earlier article, quoted the following parable about Anton, Qc Na, objects, and closures, it's too good a fit to the current topic to pass up, so please pardon the duplication.

    @@ -34,7 +34,7 @@

    - The point is that objects and closures are two ways of looking at a thing. In a nutshell, objects are data with behaviour, whereas closures are behaviour with data. I've already shown an elaborate C# example of this, so in this article, you'll get a slightly more formal treatment of the subject. + The point is that objects and closures are two ways of looking at a thing. In a nutshell, objects are data with behaviour, whereas closures are behaviour with data. I've already shown an elaborate C# example of this, so in this article, you'll get a slightly more formal treatment of the subject.

    Isomorphism # @@ -166,7 +166,7 @@

    };

    - In this variation, baz closes over foo. Inside the function body, you can use foo like you can use qux and corge. As I've already covered in an earlier article, the C# compiler compiles this to an IL class, making it even more obvious that objects and closures are two sides of the same coin. + In this variation, baz closes over foo. Inside the function body, you can use foo like you can use qux and corge. As I've already covered in an earlier article, the C# compiler compiles this to an IL class, making it even more obvious that objects and closures are two sides of the same coin.

    Summary # @@ -178,6 +178,6 @@

    This is another important result about the relationship between object-oriented design and functional programming, because this enables us to reduce any method to a canonical form, in the shape of a function. From a language like Haskell, we know a lot about the relationship between category theory and functional programming. With isomorphisms like the present, we can begin to extend that knowledge to object-oriented design.

    - Next: Argument list isomorphisms. + Next: Argument list isomorphisms.

    \ No newline at end of file diff --git a/_posts/2018-01-29-argument-list-isomorphisms.html b/_posts/2018-01-29-argument-list-isomorphisms.html index cd960aa95..74e4e4bae 100644 --- a/_posts/2018-01-29-argument-list-isomorphisms.html +++ b/_posts/2018-01-29-argument-list-isomorphisms.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a series of articles about software design isomorphisms. + This article is part of a series of articles about software design isomorphisms.

    Most programming languages enable you to pass arguments to operations. In C# and Java, you declare methods with a list of arguments: @@ -89,7 +89,7 @@

    You can go back and forth between a 'flat' argument list and a Parameter Object without loss of information, so these two refactorings together form an isomorphism.

    - As an example, consider the Roster example from a previous article. The Combine method on the Roster class is implemented like this: + As an example, consider the Roster example from a previous article. The Combine method on the Roster class is implemented like this:

    public Roster Combine(Roster other)
    @@ -246,12 +246,12 @@ 

    Summary #

    - Argument lists, Parameter Objects, and tuples are isomorphic. This has a few interesting implications, first of which is that because all these refactorings exist, you can employ them. If a method's argument list is inconvenient, consider introducing a Parameter Object. If your Parameter Object starts to look so generic that you have a hard time coming up with good names for its elements, perhaps a tuple is more appropriate. On the other hand, if you have a tuple, but it's unclear what role each unnamed element plays, consider refactoring to an argument list or Parameter Object. + Argument lists, Parameter Objects, and tuples are isomorphic. This has a few interesting implications, first of which is that because all these refactorings exist, you can employ them. If a method's argument list is inconvenient, consider introducing a Parameter Object. If your Parameter Object starts to look so generic that you have a hard time coming up with good names for its elements, perhaps a tuple is more appropriate. On the other hand, if you have a tuple, but it's unclear what role each unnamed element plays, consider refactoring to an argument list or Parameter Object.

    Another important result is that since these three ways to model arguments are isomorphic, we can treat them as interchangeable in analysis. For instance, from category theory we can learn about the properties of tuples. These properties, then, also apply to C# and Java argument lists.

    - Next: Uncurry isomorphisms. + Next: Uncurry isomorphisms.

    \ No newline at end of file diff --git a/_posts/2018-02-05-uncurry-isomorphisms.html b/_posts/2018-02-05-uncurry-isomorphisms.html index 35cbb5e39..fe2bb8fc2 100644 --- a/_posts/2018-02-05-uncurry-isomorphisms.html +++ b/_posts/2018-02-05-uncurry-isomorphisms.html @@ -12,10 +12,10 @@ {{ page.description }}

    - This article is part of a series of articles about software design isomorphisms. Nota bene: it's not about Curry–Howard isomorphism. In order to prevent too much confusion, I chose the title Uncurry isomorphism over Curry isomorphism. + This article is part of a series of articles about software design isomorphisms. Nota bene: it's not about Curry–Howard isomorphism. In order to prevent too much confusion, I chose the title Uncurry isomorphism over Curry isomorphism.

    - The Haskell base library includes two functions called curry and uncurry, and for anyone aware of them, it should be no surprise that they are each others' inverses. This is another important software design isomorphism, because in the previous article, you saw that all methods can be represented in tupled form. The current isomorphism then extends that result because tupled and curried forms are isomorphic. + The Haskell base library includes two functions called curry and uncurry, and for anyone aware of them, it should be no surprise that they are each others' inverses. This is another important software design isomorphism, because in the previous article, you saw that all methods can be represented in tupled form. The current isomorphism then extends that result because tupled and curried forms are isomorphic.

    An F# introduction to curry and uncurry # @@ -73,7 +73,7 @@

    - This property states that the result of combining two semigroup values is the same as first uncurrying (<>), and then 'recurry' it. It passes for various Semigroup instances: + This property states that the result of combining two semigroup values is the same as first uncurrying (<>), and then 'recurry' it. It passes for various Semigroup instances:

    testProperty "All round-trips" (semigroup2RoundTrips :: All -> All -> Bool),
    @@ -133,9 +133,9 @@ 

    From abstract algebra, and particularly its application to a language like Haskell, we have mathematical abstractions over computation - semigroups, for example! In Haskell, these abstractions are often represented in curried form. If we wish to learn about such abstractions, and see if we can use them in object-oriented programming as well, we need to translate the curried representations into something more closely related to object-oriented programming, such as C# or Java.

    - The present article describes how functions in curried form are equivalent to functions that take a single tuple as argument, and in a previous article, you saw how such functions are isomorphic to C# or Java methods. These equivalences provide a bridge that enables us to take what we've learned about abstract algebra and category theory, and bring them to object-oriented programming. + The present article describes how functions in curried form are equivalent to functions that take a single tuple as argument, and in a previous article, you saw how such functions are isomorphic to C# or Java methods. These equivalences provide a bridge that enables us to take what we've learned about abstract algebra and category theory, and bring them to object-oriented programming.

    - Next: Object isomorphisms. + Next: Object isomorphisms.

    diff --git a/_posts/2018-02-12-object-isomorphisms.html b/_posts/2018-02-12-object-isomorphisms.html index 7f0d416f2..6a6bb4738 100644 --- a/_posts/2018-02-12-object-isomorphisms.html +++ b/_posts/2018-02-12-object-isomorphisms.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about software design isomorphisms. So far, you've seen how to represent a single method or function in many different ways, but we haven't looked much at objects (in the object-oriented interpretation of the word). + This article is part of a series of articles about software design isomorphisms. So far, you've seen how to represent a single method or function in many different ways, but we haven't looked much at objects (in the object-oriented interpretation of the word).

    While this article starts by outlining the abstract concepts involved, an example is included towards the end. @@ -24,7 +24,7 @@

    I often use the phrase that objects are data with behaviour. (I'm sure I didn't come up with this myself, but the source of the phrase escapes me.) In languages like C# and Java, objects are described by classes, and these often contain class fields. These fields constitute an instance's data, whereas its methods implement its behaviour.

    - A class can contain an arbitrary number of fields, just like a method can take an arbitrary number of arguments. As demonstrated by the argument list isomorphisms, you can also represent an arbitrary number of arguments as a Parameter Object. The same argument can be applied to class fields. Instead of n fields, you can add a single 'data class' that holds all of these fields. In F# and Haskell these are called records. You could also dissolve such a record to individual fields. That would be the inverse refactoring, so these representations are isomorphic. + A class can contain an arbitrary number of fields, just like a method can take an arbitrary number of arguments. As demonstrated by the argument list isomorphisms, you can also represent an arbitrary number of arguments as a Parameter Object. The same argument can be applied to class fields. Instead of n fields, you can add a single 'data class' that holds all of these fields. In F# and Haskell these are called records. You could also dissolve such a record to individual fields. That would be the inverse refactoring, so these representations are isomorphic.

    In other words, a class looks like this: @@ -62,7 +62,7 @@

    Module #

    - From function isomorphisms we know that static methods are isomorphic to instance methods, as long as you include the original object as an extra argument. In this case, all data in Class1 is contained in a single (mutable) Data1 record, so we can eliminate Class1 from the argument list in favour of Data1: + From function isomorphisms we know that static methods are isomorphic to instance methods, as long as you include the original object as an extra argument. In this case, all data in Class1 is contained in a single (mutable) Data1 record, so we can eliminate Class1 from the argument list in favour of Data1:

    public static class Class1
    @@ -373,9 +373,9 @@ 

    To be clear, I'm not trying to convince you that it'd be great if you wrote all of your C# or Java using tuples of closures; it most likely wouldn't be. The point is that a class is isomorphic to a tuple of functions.

    - From category theory, and particular its application to Haskell, we know quite a bit about the properties of certain functions. Once we start to look at objects as tuples of functions, we may be able to say something about the properties of objects, because category theory also has something to say about the properties of tuples (for example that a tuple of monoids is itself a monoid). + From category theory, and particular its application to Haskell, we know quite a bit about the properties of certain functions. Once we start to look at objects as tuples of functions, we may be able to say something about the properties of objects, because category theory also has something to say about the properties of tuples (for example that a tuple of monoids is itself a monoid).

    - Next: Abstract class isomorphism. + Next: Abstract class isomorphism.

    \ No newline at end of file diff --git a/_posts/2018-02-19-abstract-class-isomorphism.html b/_posts/2018-02-19-abstract-class-isomorphism.html index 557fb0576..2bb3c889c 100644 --- a/_posts/2018-02-19-abstract-class-isomorphism.html +++ b/_posts/2018-02-19-abstract-class-isomorphism.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a series of articles about software design isomorphisms. + This article is part of a series of articles about software design isomorphisms.

    The introduction to Design Patterns states: @@ -90,7 +90,7 @@

    }

    - Like in the previous article, I've deliberately kept the naming abstract (but added a more concrete example towards the end). The purpose of this article series is to look at the shape of code, instead of what it does, or why. From argument list isomorphisms we know that we can represent any method as taking a single input value, and returning a single output value. + Like in the previous article, I've deliberately kept the naming abstract (but added a more concrete example towards the end). The purpose of this article series is to look at the shape of code, instead of what it does, or why. From argument list isomorphisms we know that we can represent any method as taking a single input value, and returning a single output value.

    An abstract class can have non-virtual members. In C#, this is the default, whereas in Java, you'd explicitly have to use the final keyword. In the above generalised representation, I've named these non-virtual members Op1, Op2, and so on. @@ -253,7 +253,7 @@

    When it comes to the GetMaze method, this means that the method in the book returns a null reference by default. Since this seems like poor API design, and also because the example becomes more illustrative if the class has both abstract and virtual members, I changed it to be abstract (i.e. pure virtual).

    - In general, there are various other issues with this design, the most glaring of which is the implied sequence coupling between members: you're expected to call BuildMaze before any of the other methods. A better design would be to remove that explicit step entirely, or else turn it into a factory that you have to call in order to be able to call the other methods. That's not the topic of the present article, so I'll leave the API like this. + In general, there are various other issues with this design, the most glaring of which is the implied sequence coupling between members: you're expected to call BuildMaze before any of the other methods. A better design would be to remove that explicit step entirely, or else turn it into a factory that you have to call in order to be able to call the other methods. That's not the topic of the present article, so I'll leave the API like this.

    The book also shows a simple usage example of the abstract MazeBuilder class: @@ -324,7 +324,7 @@

    }

    - An interface with a single method called BuildMaze would naturally have a name like IMazeBuilder, but unfortunately, I just used that name for the previous interface. The reason I named the above interface IMazeBuilder is because this is an interface extracted from the MazeBuilder abstract class, and I consider the pure virtual API to be the core API of the abstraction, so I think it makes most sense to keep the name for that interface. Thus, I had to come up with a smelly name like IMazeInitializer. + An interface with a single method called BuildMaze would naturally have a name like IMazeBuilder, but unfortunately, I just used that name for the previous interface. The reason I named the above interface IMazeBuilder is because this is an interface extracted from the MazeBuilder abstract class, and I consider the pure virtual API to be the core API of the abstraction, so I think it makes most sense to keep the name for that interface. Thus, I had to come up with a smelly name like IMazeInitializer.

    Fortunately, the two remaining interfaces are a little better: @@ -495,7 +495,7 @@

    The most important result of this article is that you can reinterpret the original design patterns with C# or Java interfaces and Dependency Injection, instead of using abstract classes. I've done this in C# for more than ten years, and in my experience, you never need abstract classes in a greenfield code base. There's always an equivalent representation that involves composition of interfaces.

    - Next: Inheritance-composition isomorphism. + Next: Inheritance-composition isomorphism.

    @@ -529,10 +529,10 @@

    Comments

    - +

    - Max, thank you for writing, and particularly for applying critique to this post. One of my main motivations for writing the entire article series is that I need to subject my thoughts to peer review. I've been thinking about these things for years, but in order to formalise them, I need to understand whether I'm completely wrong (I hope not), of, if I'm not, what are the limits of my findings. + Max, thank you for writing, and particularly for applying critique to this post. One of my main motivations for writing the entire article series is that I need to subject my thoughts to peer review. I've been thinking about these things for years, but in order to formalise them, I need to understand whether I'm completely wrong (I hope not), of, if I'm not, what are the limits of my findings.

    I think you've just pointed at one such limit, and for that I'm grateful. The rest of this answer, then, is not an attempt to refute your comment, but rather an effort to identify some constraints within which what I wrote may still hold. @@ -593,7 +593,7 @@

    Comments

    The result that one can write real, complex code bases in C# without inheritance is important to me, because one of my current goals is to teach people the advantages of functional programming, and one barrier I run into is that people who come from object-oriented programming run into problems when they no longer can use inheritance. Thus, this article shows an object-oriented alternative to inheritance, so that people can get used to the idea of designing without inheritance, even before they start looking at functional programming.

    - Another motivation for this article is that it's part of a much larger article series about design patterns, and how they relate to fundamental abstractions. In Design Patterns, all the (C++) patterns are described in terms of inheritance, so I wrote this article series on isomorphisms in order to be able to represent various design patterns in other forms than they appear in the book. + Another motivation for this article is that it's part of a much larger article series about design patterns, and how they relate to fundamental abstractions. In Design Patterns, all the (C++) patterns are described in terms of inheritance, so I wrote this article series on isomorphisms in order to be able to represent various design patterns in other forms than they appear in the book.

    2018-03-08 9:57 UTC
    @@ -610,7 +610,7 @@

    Comments

    (You could define Add, Subtract, Multiply and Divide methods, but to me they seem like reinventing the square wheel. They seem much less convenient than +-*/)

    - I tried creating some nice Temperature value objects, similar to the money monoid you presented and I came up with 5 classes:
    + I tried creating some nice Temperature value objects, similar to the money monoid you presented and I came up with 5 classes:
    Temperature, Kelvin, Celsius, Fahrenheit and TemperatureExpression.
    Temperature is the abstract class and its +Temperature and -Temperature operators are overloaded so that they return a TemperatureExpression, which can then be evaluated to a Maybe<TTemperature> where TTemperature : Temperature.
    A TemperatureExpression is nothing more than a lazily evaluated mathematical expression (for example: 12K + 24C - 32F).
    @@ -629,7 +629,7 @@

    Comments

    - +

    Ciprian, thank you for writing. I agree that this isn't language agnostic. It's possible that we need to add further constraints to the conjecture, but I still anticipate that, with appropriate constraints, it holds for statically typed 'mainstream' object-oriented languages (i.e. C# and Java). It may also hold for other languages, but it requires detailed knowledge of a language to claim that it does. For instance, it's been too long since I wrote C++ code, and I can't remember how its object-oriented language features work. Likewise, it'd be interesting to investigate if the conjecture holds when applied to JavaScript, Ruby, Python, etc., but I've been careful not to claim that, as I know too little about those languages. @@ -657,7 +657,7 @@

    Comments

    - +

    Ciprian, thank you for elaborating. I'd forgotten about C#'s ability to overload arithmetic operators, which is, I believe, what you're referring to. To be clear, I do believe that it's a fair enough critique, so that we'll have to once again restrict this article's conjecture to something like: @@ -691,7 +691,7 @@

    Comments

    As an aside, languages do exist where arithmetic is an abstraction instead of a language feature. The one I'm most familiar with is Haskell, where arithmetic is defined in terms of type classes. It's worth noting that the operators +, *, and - are defined in an abstraction called Num, whereas the 'fourth' arithmetic operator / is defined in a more specialised abstraction called Fractional.

    - Not that Haskell's model of arithmetic is perfect, but there's a rationale behind this distinction. Division is special, because it can translate two integers (e.g. 2 and 3) into a rational number (e.g. 2/3), while both addition and multiplication are monoids. This is where Haskell starts to fall apart itself, though, because subtraction can also translate two numbers out of the set in which they originally belonged. For example, given two natural numbers 2 and 3, 2 - 3 is no longer a natural number, since it's negative. + Not that Haskell's model of arithmetic is perfect, but there's a rationale behind this distinction. Division is special, because it can translate two integers (e.g. 2 and 3) into a rational number (e.g. 2/3), while both addition and multiplication are monoids. This is where Haskell starts to fall apart itself, though, because subtraction can also translate two numbers out of the set in which they originally belonged. For example, given two natural numbers 2 and 3, 2 - 3 is no longer a natural number, since it's negative.

    But all of that is an aside. Even in C#, one has to deal with low-level exceptional cases such as integer overflow, so even addition isn't truly monoidal, unless you use BigInteger. @@ -768,16 +768,16 @@

    Comments

    - +

    Max, thank you for writing back. That's an ingenious resolution to some of the problems you originally pointed out. Thank you!

    - As far as I can tell, this seems to strengthen the original argument, although there's still some corner cases, like the one pointed out by Ciprian. We can use Decorators as concrete dependencies as you point out, as an argument that even two (or n) identical polymorphic dependencies can be treated as though they were distinct dependencies. + As far as I can tell, this seems to strengthen the original argument, although there's still some corner cases, like the one pointed out by Ciprian. We can use Decorators as concrete dependencies as you point out, as an argument that even two (or n) identical polymorphic dependencies can be treated as though they were distinct dependencies.

    - What if we have an arbitrary number of dependencies? One example would be of a Composite, but it doesn't have to be. Consider the ShippingCostCalculatorFactory class from this example. It depends on a list of IBasketCalculator candidates. Could such a class, too, be refactored to an abstract class? + What if we have an arbitrary number of dependencies? One example would be of a Composite, but it doesn't have to be. Consider the ShippingCostCalculatorFactory class from this example. It depends on a list of IBasketCalculator candidates. Could such a class, too, be refactored to an abstract class?

    I suppose it could, since the dependency then really isn't an arbitrary number of IBasketCalculator, but rather the dependency is on a collection. Would it be enough to refactor to an abstract class with a single Factory Method that returns the candidates? @@ -882,7 +882,7 @@

    Comments

    - +

    Max, once again thank you for writing. I've never seen that article by Joel Spolsky before, but I particularly liked your enumeration of the various different roles an abstract class can have. @@ -920,7 +920,7 @@

    Comments

    - +

    Max, I agree that using a nested, private, sealed class is a good way to ensure that no-one else can add rogue implementations of an interface like IOptionVisitor<T>. diff --git a/_posts/2018-02-26-inheritance-composition-isomorphism.html b/_posts/2018-02-26-inheritance-composition-isomorphism.html index b1e6cd910..e5dcec44e 100644 --- a/_posts/2018-02-26-inheritance-composition-isomorphism.html +++ b/_posts/2018-02-26-inheritance-composition-isomorphism.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about software design isomorphisms. + This article is part of a series of articles about software design isomorphisms.

    Chapter 1 of Design Patterns admonishes: @@ -22,7 +22,7 @@ People sometimes struggle with this, because they use inheritance as a means to achieve reuse. That's not necessary, because you can use object composition instead.

    - In the previous article, you learned that an abstract class can be refactored to a concrete class with injected dependencies. + In the previous article, you learned that an abstract class can be refactored to a concrete class with injected dependencies.

    Did you notice that there was an edge case that I didn't cover? @@ -113,7 +113,7 @@

    If you already have an interface with a 'default implementation', and you want to reuse the default implementation, then you can use object composition as shown above. At its core, it's reminiscent of the Decorator design pattern, but instead of receiving the inner object via its constructor, it creates the object itself. You can, however, also use a Decorator in order to achieve the same effect. This will make your code more flexible, but possibly also more error-prone, because you no longer have any guarantee what the 'base' is. This is where the Liskov Substitution Principle becomes important, but that's a digression.

    - If you're using the previous abstract class isomorphism to refactor to Dependency Injection, you can refactor any use of base to object composition as shown here. + If you're using the previous abstract class isomorphism to refactor to Dependency Injection, you can refactor any use of base to object composition as shown here.

    This is a special case of Replace Inheritance with Delegation from Refactoring, which also describes the inverse refactoring Replace Delegation with Inheritance, thereby making these two refactorings an isomorphism. @@ -125,6 +125,6 @@

    This article focuses on a particular issue that you may run into if you try to avoid the use of abstract classes. Many programmers use inheritance in order to achieve reuse, but this is in no way necessary. Favour composition over inheritance.

    - Next: Church encoding. + Next: Church encoding.

    diff --git a/_posts/2018-03-05-some-design-patterns-as-universal-abstractions.html b/_posts/2018-03-05-some-design-patterns-as-universal-abstractions.html index 23dd24d0f..9fb13122c 100644 --- a/_posts/2018-03-05-some-design-patterns-as-universal-abstractions.html +++ b/_posts/2018-03-05-some-design-patterns-as-universal-abstractions.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article series submits results based on the work presented in an even larger series of articles about the relationship between design patterns and category theory. + This article series submits results based on the work presented in an even larger series of articles about the relationship between design patterns and category theory.

    Wouldn't it be wonderful if you could assemble software from predefined building blocks? This idea is old, and has been the driving force behind object-oriented programming (OOP). In Douglas Coupland's 1995 novel Microserfs, the characters attempt to reach that goal through a project called Oop!. Lego bricks play a role as a metaphor as well. @@ -67,13 +67,13 @@

    While we (me included) have been on an a thirty-odd year long detour around object-orientation, I don't think all is lost. I still believe that a Lego-brick-like system exists for software development, but I think that it's a system that we have to discover instead of invent.

    - As I already covered in the introductory article, category theory does, in fact, discuss 'objects'. It's not the same type of object that you know from C# or Java, but some of them do consist of data and behaviour - monoids, for example, or functors. Such object are more like types than objects in the OOP sense. + As I already covered in the introductory article, category theory does, in fact, discuss 'objects'. It's not the same type of object that you know from C# or Java, but some of them do consist of data and behaviour - monoids, for example, or functors. Such object are more like types than objects in the OOP sense.

    Another, more crucial, difference to object-oriented programming is that these objects are lawful. An object is only a monoid if it obeys the monoid laws. An object is only a functor if it obeys the functor laws.

    - Such objects are still fine-grained building blocks, but they fit into a system. You don't have to learn tens of thousands of specific objects in order to get to know a framework. You need to understand the system. You need to understand monoids, functors, applicatives, and a few other universal abstractions (yes: monads too). + Such objects are still fine-grained building blocks, but they fit into a system. You don't have to learn tens of thousands of specific objects in order to get to know a framework. You need to understand the system. You need to understand monoids, functors, applicatives, and a few other universal abstractions (yes: monads too).

    Many of these universal abstractions were almost discovered by the Gang of Four twenty years ago, but they weren't quite in place then. Much of that has to do with the fact that functional programming didn't seem like a realistic alternative back then, because of hardware limitations. This has all changed to the better. @@ -82,16 +82,16 @@

    Specific patterns #

    - In the introductory article about the relationship between design patterns and category theory, you learned that some design patterns significantly overlap concepts from category theory. In this article series, we'll explore the relationships between some of the classic patterns and category theory. I'm not sure that all the patterns from Design Patterns can be reinterpreted as universal abstractions, but the following subset seems promising: + In the introductory article about the relationship between design patterns and category theory, you learned that some design patterns significantly overlap concepts from category theory. In this article series, we'll explore the relationships between some of the classic patterns and category theory. I'm not sure that all the patterns from Design Patterns can be reinterpreted as universal abstractions, but the following subset seems promising:

    Granted, Null Object is actually not from Design Patterns, but as we shall see, it's a special case of Composite, so it fits well into that group.

    @@ -102,6 +102,6 @@

    Some design patterns closely resemble categorical objects. This article provides an overview, whereas the next articles in the series will dive into specifics.

    - Next: Composite as a monoid. + Next: Composite as a monoid.

    \ No newline at end of file diff --git a/_posts/2018-03-12-composite-as-a-monoid.html b/_posts/2018-03-12-composite-as-a-monoid.html index bf6e43792..cb3c72837 100644 --- a/_posts/2018-03-12-composite-as-a-monoid.html +++ b/_posts/2018-03-12-composite-as-a-monoid.html @@ -14,13 +14,13 @@ {{ page.description }}

    - This article is part of a series of articles about design patterns and their universal abstraction counterparts. + This article is part of a series of articles about design patterns and their universal abstraction counterparts.

    The Composite design pattern is a powerful way to structure code, but not all objects are composable. When is an object composable? This article explores that question.

    - In short, Composites are monoids. + In short, Composites are monoids.

    Composite shown as a subset of the set of monoids. @@ -32,7 +32,7 @@

    Composite #

    - First, I'll use various software design isomorphisms to put Composite in a canonical form. From unit isomorphisms, function isomorphisms, and argument list isomorphisms, we know that we can represent any method as a method or function that takes a single argument, and returns a single output value. From abstract class isomorphism we know that we can represent an abstract class with interfaces. Thus, you can represent the interface for a Composite like this: + First, I'll use various software design isomorphisms to put Composite in a canonical form. From unit isomorphisms, function isomorphisms, and argument list isomorphisms, we know that we can represent any method as a method or function that takes a single argument, and returns a single output value. From abstract class isomorphism we know that we can represent an abstract class with interfaces. Thus, you can represent the interface for a Composite like this:

    public interface IInterface1
    @@ -76,7 +76,7 @@ 

    mconcat :: Monoid a => [a] -> a

    - We also know from a previous article that a collection of monoids can be reduced to a single monoid. Notice how the above outline of a composite implementation of Op1 looks similar to the Accumulate method shown in the linked article. If IInterface1 can form a monoid, then you can make a Composite. + We also know from a previous article that a collection of monoids can be reduced to a single monoid. Notice how the above outline of a composite implementation of Op1 looks similar to the Accumulate method shown in the linked article. If IInterface1 can form a monoid, then you can make a Composite.

    Objects as monoids # @@ -85,13 +85,13 @@

    When can an object (like IInterface1) form a monoid?

    - From object isomorphisms we know that we can decompose an object with n members to n static methods. This means that instead of analysing all of IInterface1, we can consider the properties of each method in isolation. The properties of an object is the consolidation of the properties of all the methods. + From object isomorphisms we know that we can decompose an object with n members to n static methods. This means that instead of analysing all of IInterface1, we can consider the properties of each method in isolation. The properties of an object is the consolidation of the properties of all the methods.

    - Recall, still from object isomorphisms, that we can represent an object as a tuple of functions. Moreover, if you have a tuple of monoids, then the tuple also forms monoid! + Recall, still from object isomorphisms, that we can represent an object as a tuple of functions. Moreover, if you have a tuple of monoids, then the tuple also forms monoid!

    - In order to make an object a monoid, then, you have to make each method a monoid. When is a method a monoid? A method is a monoid when its return type forms a monoid. + In order to make an object a monoid, then, you have to make each method a monoid. When is a method a monoid? A method is a monoid when its return type forms a monoid.

    That's it. An interface like IInterface1 is a monoid when Out1, Out2, Out3, and so on, form monoids. If that's the case, you can make a Composite. @@ -100,7 +100,7 @@

    Examples #

    - From unit isomorphism, we know that we can represent C#'s and Java's void keywords with methods returning unit, and unit is a monoid. All methods that return void can be part of a Composite, but we already knew that Commands are composable. If you search for examples of the Composite design pattern, you'll find more than one variation involving drawing shapes on a digital canvas, with the central operation being a Draw method with a void return type. + From unit isomorphism, we know that we can represent C#'s and Java's void keywords with methods returning unit, and unit is a monoid. All methods that return void can be part of a Composite, but we already knew that Commands are composable. If you search for examples of the Composite design pattern, you'll find more than one variation involving drawing shapes on a digital canvas, with the central operation being a Draw method with a void return type.

    Another example could be calculation of the price of a shopping basket. If you have an interface method of the type decimal Calculate(Basket basket), you could have several implementations: @@ -109,7 +109,7 @@

  • Apply a discount (a negative number)
  • Calculate sales tax
  • - These could be three implementations of the same interface method, and since decimal numbers form a monoid over addition, then you can make a Composite basket calculator out of the three implementations. For a detailed example, see the coda containing a business rules example. + These could be three implementations of the same interface method, and since decimal numbers form a monoid over addition, then you can make a Composite basket calculator out of the three implementations. For a detailed example, see the coda containing a business rules example.

    Boolean values also form at least two monoids (any and all), so any method you have that returns a Boolean value can be used in a Composite. You could, for example, have a list of criteria for granting a loan. Each such business rule returns true if it evaluates that the loan should be granted, and false otherwise. If you have more than one business rule, you can create a Composite that returns true only if all the individual rules return true. @@ -127,13 +127,13 @@

    The result, then, is that you can make a Composite when all methods in your interface have monoidal return types. If only a single method has a return type that isn't a monoid, you can't aggregate that value, and you can't make a Composite.

    - Your interface can have as many methods you like, but they must all be monoids. Even one rogue method will prevent you from being able to create a Composite. This is another argument for Role Interfaces. The smaller an interface is, the more likely it is that you can make a Composite out of it. If you follow that line of reasoning to its ultimate conclusion, you'll design your interfaces with a single member each. + Your interface can have as many methods you like, but they must all be monoids. Even one rogue method will prevent you from being able to create a Composite. This is another argument for Role Interfaces. The smaller an interface is, the more likely it is that you can make a Composite out of it. If you follow that line of reasoning to its ultimate conclusion, you'll design your interfaces with a single member each.

    Relaxation #

    - There can be some exceptions to the rule that all return values must be monoids. If you have at least one implementation of your interface, then a semigroup may be enough. Recall that monoids accumulate like this: + There can be some exceptions to the rule that all return values must be monoids. If you have at least one implementation of your interface, then a semigroup may be enough. Recall that monoids accumulate like this:

    public static Foo Accumulate(IReadOnlyCollection<Foo> foos)
    @@ -145,7 +145,7 @@ 

    }

    - You only need Identity in order to start the accumulation, and to have something to return in case you have no implementations. If you have at least one implementation, you don't need the identity, and then a semigroup is enough to accumulate. Consider the bounding box example. If you have a method that returns BoundingBox values, you can still make a Composite out of such an interface, as long as you have at least one implementation. There's no 'identity' bounding box, but it makes intuitive sense that you can still compose bounding boxes into bigger bounding boxes. + You only need Identity in order to start the accumulation, and to have something to return in case you have no implementations. If you have at least one implementation, you don't need the identity, and then a semigroup is enough to accumulate. Consider the bounding box example. If you have a method that returns BoundingBox values, you can still make a Composite out of such an interface, as long as you have at least one implementation. There's no 'identity' bounding box, but it makes intuitive sense that you can still compose bounding boxes into bigger bounding boxes.

    Haskell formalises the rule for semigroups: @@ -157,7 +157,7 @@

    The sconcat function reduces any non-empty list of any semigroup a to a single a value.

    - If you have a non-empty list of implementations, then perhaps you don't even need a semigroup. Perhaps any magma will work. Be aware, however, that the lack of associativity will cause the order of implementations to matter. + If you have a non-empty list of implementations, then perhaps you don't even need a semigroup. Perhaps any magma will work. Be aware, however, that the lack of associativity will cause the order of implementations to matter.

    Technically, you may be able to program a Composite from a magma, but I'd suggest caution. The monoid and semigroup laws are intuitive. A magma without those properties may not form an intuitive Composite. While it may compile, it may have surprising, or counter-intuitive, behaviour. I'd favour sticking to monoids or semigroups. @@ -169,6 +169,6 @@

    When is an object-oriented design composable? Composition could mean more than one thing, but this article has focused exclusively on the Composite design pattern. When can you use the Composite pattern? When all method return types are monoids.

    - Next: Coalescing Composite as a monoid. + Next: Coalescing Composite as a monoid.

    \ No newline at end of file diff --git a/_posts/2018-03-19-functors-applicatives-and-friends.html b/_posts/2018-03-19-functors-applicatives-and-friends.html index 9661b045b..d05dd8791 100644 --- a/_posts/2018-03-19-functors-applicatives-and-friends.html +++ b/_posts/2018-03-19-functors-applicatives-and-friends.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article series is part of an even larger series of articles about the relationship between design patterns and category theory. + This article series is part of an even larger series of articles about the relationship between design patterns and category theory.

    If you've worked with C# or Java recently, you've most likely encountered types such as Foo<T> or Bar<T> (specifically, on .NET, e.g. List<T>). Perhaps you've also noticed that often, you can translate the type inside of the container. For example, if you have a Foo<string>, perhaps you can call some method on it that returns a Foo<int>. If so, it may be a functor. @@ -34,41 +34,41 @@

    In this article series, you'll learn about the following categories:

    You'll see plenty of examples along the way. Most examples will be in C#, but some articles will have code examples in F# or Haskell. You can read or skip those articles as you prefer.

    - Next: Functors. + Next: Functors.

    \ No newline at end of file diff --git a/_posts/2018-03-22-functors.html b/_posts/2018-03-22-functors.html index 0eb757760..3e49c712f 100644 --- a/_posts/2018-03-22-functors.html +++ b/_posts/2018-03-22-functors.html @@ -14,26 +14,26 @@ {{ page.description }}

    - This article series is part of a larger series of articles about functors, applicatives, and other mappable containers. + This article series is part of a larger series of articles about functors, applicatives, and other mappable containers.

    Programming is about abstraction, since you can't manipulate individual sub-atomic particles on your circuit boards. Some abstractions are well-known because they're rooted in mathematics. Particularly, category theory has proven to be fertile ground for functional programming. Some of the concepts from category theory apply to object-oriented programming as well; all you need is generics, which is a feature of both C# and Java.

    - In previous articles, you got an introduction to the specific Test Data Builder and Test Data Generator functors. Functors are more common than you may realise, although in programming, we usually work with a subset of functors called endofunctors. In daily speak, however, we just call them functors. + In previous articles, you got an introduction to the specific Test Data Builder and Test Data Generator functors. Functors are more common than you may realise, although in programming, we usually work with a subset of functors called endofunctors. In daily speak, however, we just call them functors.

    In the next series of articles, you'll see plenty of examples of functors, with code examples in both C#, F#, and Haskell. These articles are mostly aimed at object-oriented programmers curious about the concept.

    This list is far from exhaustive; more functors exist. Perhaps the most well-known of all functors is List, a.k.a. Sequence. C# query syntax can handle any functor, but most people only think of it as a language feature related to IEnumerable<T>. Since the combination of IEnumerable<T> and query syntax is already well-described, I'm not going to cover it explicitly here.

    @@ -91,7 +91,7 @@

    Defining a Select method isn't enough. The method must also obey the so-called functor laws. These are quite intuitive laws that govern that a functor behaves correctly.

    - The first law is that mapping the identity function returns the functor unchanged. The identity function is a function that returns all input unchanged. (It's called the identity function because it's the identity for the endomorphism monoid.) In F# and Haskell, this is simply a built-in function called id. + The first law is that mapping the identity function returns the functor unchanged. The identity function is a function that returns all input unchanged. (It's called the identity function because it's the identity for the endomorphism monoid.) In F# and Haskell, this is simply a built-in function called id.

    In C#, you can write a demonstration of the law as a unit test: @@ -151,10 +151,10 @@

    This is not a monad tutorial; it's a functor tutorial. Functors are commonplace, so it's worth keeping an eye out for them. If you already understand how LINQ (or similar concepts in Java) work, then functors should be intuitive, because they are all based on the same underlying maths.

    - While this article is an overview article, it's also a part of a larger series of articles that explore what object-oriented programmers can learn from category theory. + While this article is an overview article, it's also a part of a larger series of articles that explore what object-oriented programmers can learn from category theory.

    - Next: The Maybe functor. + Next: The Maybe functor.

    diff --git a/_posts/2018-03-26-the-maybe-functor.html b/_posts/2018-03-26-the-maybe-functor.html index aed4abd45..97cea1afb 100644 --- a/_posts/2018-03-26-the-maybe-functor.html +++ b/_posts/2018-03-26-the-maybe-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. + This article is an instalment in an article series about functors.

    One of the simplest, and easiest to understand, functors is Maybe. It's also sometimes known as the Maybe monad, but this is not a monad tutorial; it's a functor tutorial. Maybe is many things; one of them is a functor. In F#, Maybe is called option. @@ -21,13 +21,13 @@

    Motivation #

    - Maybe enables you to model a value that may or may not be present. Object-oriented programmers typically have a hard time grasping the significance of Maybe, since it essentially does the same as null in mainstream object-oriented languages. There are differences, however. In languages like C# and Java, most things can be null, which can lead to much defensive coding. What happens more frequently, though, is that programmers forget to check for null, with run-time exceptions as the result. + Maybe enables you to model a value that may or may not be present. Object-oriented programmers typically have a hard time grasping the significance of Maybe, since it essentially does the same as null in mainstream object-oriented languages. There are differences, however. In languages like C# and Java, most things can be null, which can lead to much defensive coding. What happens more frequently, though, is that programmers forget to check for null, with run-time exceptions as the result.

    A Maybe value, on the other hand, makes it explicit that a value may or may not be present. In statically typed languages, it also forces you to deal with the case where no data is present; if you don't, your code will not compile.

    - Finally, in a language like C#, null has no type, but a Maybe value always has a type. + Finally, in a language like C#, null has no type, but a Maybe value always has a type.

    If you appreciate the tenet that explicit is better than implicit, then you should favour Maybe over null. @@ -36,7 +36,7 @@

    Implementation #

    - If you've read the introduction, then you know that IEnumerable<T> is a functor. In many ways, Maybe is like IEnumerable<T>, but it's a particular type of collection that can only contain zero or one element(s). There are various ways in which you can implement Maybe in an object-oriented language like C#; here's one: + If you've read the introduction, then you know that IEnumerable<T> is a functor. In many ways, Maybe is like IEnumerable<T>, but it's a particular type of collection that can only contain zero or one element(s). There are various ways in which you can implement Maybe in an object-oriented language like C#; here's one:

    public sealed class Maybe<T>
    @@ -138,7 +138,7 @@ 

    It's up to you and your collaborators whether you prefer one or the other of those alternatives. In both examples, though, dest is a new populated Maybe<string> object containing the string "42".

    - A more realistic example could be as part of a line-of-business application. Many enterprise developers are familiar with the Repository pattern. Imagine that you'd like to query a repository for a Reservation object. If one is found in the database, you'd like to convert it to a view model, so that you can display it. + A more realistic example could be as part of a line-of-business application. Many enterprise developers are familiar with the Repository pattern. Imagine that you'd like to query a repository for a Reservation object. If one is found in the database, you'd like to convert it to a view model, so that you can display it.

    var viewModel = repository.Read(id)
    @@ -312,6 +312,6 @@ 

    In this article, I only discussed Maybe in its role of being a functor, but it's so much more than that! It's also an applicative functor, a monad, and traversable (enumerable). Not all functors are that rich.

    - Next: An Either functor. + Next: An Either functor.

    \ No newline at end of file diff --git a/_posts/2018-04-03-maybe-monoids.html b/_posts/2018-04-03-maybe-monoids.html index 1e781e232..a1db11afe 100644 --- a/_posts/2018-04-03-maybe-monoids.html +++ b/_posts/2018-04-03-maybe-monoids.html @@ -14,16 +14,16 @@ {{ page.description }}

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity).

    - You can combine Maybe objects in various ways, thereby turning them into monoids. There's at least two unconstrained monoids over Maybe values, as well as some constrained monoids. By constrained I mean that the monoid only exists for Maybe objects that contain certain values. You'll see such an example first. + You can combine Maybe objects in various ways, thereby turning them into monoids. There's at least two unconstrained monoids over Maybe values, as well as some constrained monoids. By constrained I mean that the monoid only exists for Maybe objects that contain certain values. You'll see such an example first.

    Combining Maybes over semigroups #

    - If you have two Maybe objects, and they both (potentially) contain values that form a semigroup, you can combine the Maybe values as well. Here's a few examples. + If you have two Maybe objects, and they both (potentially) contain values that form a semigroup, you can combine the Maybe values as well. Here's a few examples.

    public static Maybe<int> CombineMinimum(Maybe<int> x, Maybe<int> y)
    @@ -108,10 +108,10 @@ 

    First #

    - As you can read in the introductory article about semigroups, there's two semigroup operations called first and last. Similarly, there's two operations by the same name defined over monoids. They behave a little differently, although they're related. + As you can read in the introductory article about semigroups, there's two semigroup operations called first and last. Similarly, there's two operations by the same name defined over monoids. They behave a little differently, although they're related.

    - The first monoid operation returns the left-most non-empty value among candidates. You can view nothing as being a type-safe equivalent to null, in which case this monoid is equivalent to a null coalescing operator. + The first monoid operation returns the left-most non-empty value among candidates. You can view nothing as being a type-safe equivalent to null, in which case this monoid is equivalent to a null coalescing operator.

    public static Maybe<T> First<T>(Maybe<T> x, Maybe<T> y)
    @@ -250,6 +250,6 @@ 

    Just as there's more than one monoid over numbers, and more than one monoid over Boolean values, there's more than one monoid over Maybe values. The most useful one may be the one that elevates any semigroup to a monoid by adding nothing as the identity, but others exist. While, at first glance, the first and last monoids over Maybes look like operations in their own right, they're just applications of the general rule. They elevate the first and last semigroups to monoids by 'wrapping' them in Maybes, and using nothing as the identity.

    - Next: Monoids accumulate. + Next: Monoids accumulate.

    \ No newline at end of file diff --git a/_posts/2018-04-09-coalescing-composite-as-a-monoid.html b/_posts/2018-04-09-coalescing-composite-as-a-monoid.html index 34c6ae2e0..74f808d0f 100644 --- a/_posts/2018-04-09-coalescing-composite-as-a-monoid.html +++ b/_posts/2018-04-09-coalescing-composite-as-a-monoid.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about design patterns and their category theory counterparts. In a previous article, you learned that the Composite design pattern is simply a monoid. + This article is part of a series of articles about design patterns and their category theory counterparts. In a previous article, you learned that the Composite design pattern is simply a monoid.

    Monoidal return types # @@ -43,7 +43,7 @@

    }

    - In this case it's easy to compose multiple repositories, because void (or, rather, unit) forms a monoid. If you have methods that return numbers, you can add the numbers together (a monoid). If you have methods that return strings, you can concatenate the strings (a monoid). If you have methods that return Boolean values, you can or or and them together (more monoids). + In this case it's easy to compose multiple repositories, because void (or, rather, unit) forms a monoid. If you have methods that return numbers, you can add the numbers together (a monoid). If you have methods that return strings, you can concatenate the strings (a monoid). If you have methods that return Boolean values, you can or or and them together (more monoids).

    What about the above Read method, though? @@ -205,7 +205,7 @@

    Instead of nesting Maybe inside of First, as Haskell does, I simplified a bit and gave First<T> two constructor overloads: one that takes a value, and one that doesn't. The FindFirst method is the binary operation that corresponds to Haskell's <> or mappend.

    - This is only one of several alternative implementations of the first monoid. + This is only one of several alternative implementations of the first monoid.

    In order to make First<T> a monoid, it must also have an identity, which is just an empty value: @@ -217,7 +217,7 @@

    }

    - This enables you to accumulate an arbitrary number of First<T> values to a single value: + This enables you to accumulate an arbitrary number of First<T> values to a single value:

    public static First<T> Accumulate<T>(IReadOnlyList<First<T>> firsts)
    @@ -280,7 +280,7 @@ 

    Another Composite variation exists, but that one turns out to be a monoid as well. Read on!

    - Next: Endomorphic Composite as a monoid. + Next: Endomorphic Composite as a monoid.

    @@ -309,16 +309,16 @@

    Comments

    - +

    Nikola, thank you for writing. You're correct: it would be more correct to say that you can create a Composite from an interface when all of its methods return types that form monoids. Throughout this article series, I've been struggling to keep my language as correct and specific as possible, but I sometimes slip up.

    - This has come up before, so perhaps you'll find this answer helpful. + This has come up before, so perhaps you'll find this answer helpful.

    - By the way, there's one exception to the rule that in order to be able to create a Composite, all methods must return types that form monoids. This is when the return type is the same as the input type. The resulting Composite is still a monoid, so the overall conclusion holds. + By the way, there's one exception to the rule that in order to be able to create a Composite, all methods must return types that form monoids. This is when the return type is the same as the input type. The resulting Composite is still a monoid, so the overall conclusion holds.

    2018-08-08 6:32 UTC
    diff --git a/_posts/2018-04-16-endomorphic-composite-as-a-monoid.html b/_posts/2018-04-16-endomorphic-composite-as-a-monoid.html index 09a92e5ca..85b232b45 100644 --- a/_posts/2018-04-16-endomorphic-composite-as-a-monoid.html +++ b/_posts/2018-04-16-endomorphic-composite-as-a-monoid.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about design patterns and their category theory counterparts. In a previous article, you learned that the Composite design pattern is simply a monoid. + This article is part of a series of articles about design patterns and their category theory counterparts. In a previous article, you learned that the Composite design pattern is simply a monoid.

    There is, however, a variation of the Composite design pattern where the return value from one step can be used as the input for the next step. @@ -21,7 +21,7 @@

    Endomorphic API #

    - Imagine that you have to implement some scheduling functionality. For example, you may need to schedule something to happen a month from now, but it should happen on a bank day, during business hours, and you want to know what the resulting date and time will be, expressed in UTC. I've previously covered the various objects for performing such steps. The common behaviour is this interface: + Imagine that you have to implement some scheduling functionality. For example, you may need to schedule something to happen a month from now, but it should happen on a bank day, during business hours, and you want to know what the resulting date and time will be, expressed in UTC. I've previously covered the various objects for performing such steps. The common behaviour is this interface:

    public interface IDateTimeOffsetAdjustment
    @@ -30,7 +30,7 @@ 

    }

    - The Adjust method is an endomorphism; that is: the input type is the same as the return type, in this case DateTimeOffset. A previous article already established that that's a monoid. + The Adjust method is an endomorphism; that is: the input type is the same as the return type, in this case DateTimeOffset. A previous article already established that that's a monoid.

    Composite endomorphism # @@ -94,13 +94,13 @@

    }

    - You can see the implementation for all four composed classes in the previous article. NextMonthAdjustment adjusts a date by a month into its future, BusinessHoursAdjustment adjusts a time to business hours, DutchBankDayAdjustment takes bank holidays and weekends into account in order to return a bank day, and UtcAdjustment convert a date and time to UTC. + You can see the implementation for all four composed classes in the previous article. NextMonthAdjustment adjusts a date by a month into its future, BusinessHoursAdjustment adjusts a time to business hours, DutchBankDayAdjustment takes bank holidays and weekends into account in order to return a bank day, and UtcAdjustment convert a date and time to UTC.

    Monoidal accumulation #

    - As you've learned in that previous article that I've already referred to, an endomorphism is a monoid. In this particular example, the binary operation in question is called Append. From another article, you know that monoids accumulate: + As you've learned in that previous article that I've already referred to, an endomorphism is a monoid. In this particular example, the binary operation in question is called Append. From another article, you know that monoids accumulate:

    public static IDateTimeOffsetAdjustment Accumulate(
    @@ -201,6 +201,6 @@ 

    At first glance, then, it seems like a falsification of the original claim that Composites are monoids. As you've learned in this article, however, endomorphisms are monoids, so the claim still stands.

    - Next: Null Object as identity. + Next: Null Object as identity.

    \ No newline at end of file diff --git a/_posts/2018-04-23-null-object-as-identity.html b/_posts/2018-04-23-null-object-as-identity.html index 2be9aa78a..c39026329 100644 --- a/_posts/2018-04-23-null-object-as-identity.html +++ b/_posts/2018-04-23-null-object-as-identity.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a series of articles about design patterns and their category theory counterparts. In a previous article you learned how there's a strong relationship between the Composite design pattern and monoids. In this article you'll see that the Null Object pattern is essentially a special case of the Composite pattern. + This article is part of a series of articles about design patterns and their category theory counterparts. In a previous article you learned how there's a strong relationship between the Composite design pattern and monoids. In this article you'll see that the Null Object pattern is essentially a special case of the Composite pattern.

    I also think that there's a relationship between monoidal identity and the Null Object pattern similar to the relationship between Composite and monoids in general: @@ -86,7 +86,7 @@

    Doing nothing as identity #

    - From unit isomorphisms you know that methods without return values are isomorphic to methods that return unit. You also know that unit is a monoid. What does unit and bool have in common? They both form monoids; bool, in fact, forms four different monoids, of which all and any are the best-known. + From unit isomorphisms you know that methods without return values are isomorphic to methods that return unit. You also know that unit is a monoid. What does unit and bool have in common? They both form monoids; bool, in fact, forms four different monoids, of which all and any are the best-known.

    In my experience, you can implement the Null Object pattern by returning various 'do nothing' values, depending on their types: @@ -100,7 +100,7 @@

    What all of these have in common is that they return the identity of the monoid in question. Keep in mind that for some types, such as bool and int, more than one monoid exist, and the identity depends on which one you pick:
    • The identity for the any monoid is false.
    • -
    • The identity for string is "".
    • +
    • The identity for string is "".
    • The identity for collections is the empty collection.
    • The identity for the addition monoid is 0.
    • The identity for unit is unit.
    • @@ -167,7 +167,7 @@

      nullify = const mempty

      - Once you recall, however, that functions are monoids if their return values are monoids, you can simplify it even further: + Once you recall, however, that functions are monoids if their return values are monoids, you can simplify it even further:

      nullify :: Monoid m => a -> m
      @@ -180,7 +180,7 @@ 

      Controller identity #

      - Consider the IController interface. According to object isomorphisms, you can represent this interface as a tuple of three functions: + Consider the IController interface. According to object isomorphisms, you can represent this interface as a tuple of three functions:

      type Controller =
      @@ -193,7 +193,7 @@ 

      Notice that I've used Any as the return type for the two first tuples. As I've previously covered, Booleans form monoids like any and all. Here, we need to use Any.

      - This tuple is a monoid because all three functions are monoids, and a tuple of monoids is itself a monoid. This means that you can easily create a Null Object using mempty: + This tuple is a monoid because all three functions are monoids, and a tuple of monoids is itself a monoid. This means that you can easily create a Null Object using mempty:

      λ> nullController = mempty :: Controller
      @@ -241,7 +241,7 @@

      The question was: when can you implement the Null Object pattern? The answer is that you can do that when all involved methods return monoids.

      - Next: Visitor as a sum type. + Next: Visitor as a sum type.

    @@ -272,16 +272,16 @@

    Comments

    - +

    - Ciprian, thank you for writing. I'm not sure I understand what you man by Maybe wrapping a neutral element. I hope that's not how my introduction to Maybe comes across. Could you point to specific examples? + Ciprian, thank you for writing. I'm not sure I understand what you man by Maybe wrapping a neutral element. I hope that's not how my introduction to Maybe comes across. Could you point to specific examples?

    - If NonEmptyString is, as the name implies, a string guaranteed to be non-empty, isn't it just a specialisation of NotEmptyCollection<T>? If so, indeed, there's no identity for NonEmptyString (but it does form a Semigroup). + If NonEmptyString is, as the name implies, a string guaranteed to be non-empty, isn't it just a specialisation of NotEmptyCollection<T>? If so, indeed, there's no identity for NonEmptyString (but it does form a Semigroup).

    - Since it's a semigroup, though, you can lift it to a monoid my wrapping it in Maybe. If you do that, the identity of Maybe<NonEmptyString> would be nothing. + Since it's a semigroup, though, you can lift it to a monoid my wrapping it in Maybe. If you do that, the identity of Maybe<NonEmptyString> would be nothing.

    2018-05-08 1:53 UTC
    @@ -316,13 +316,13 @@

    Comments

    - +

    Ciprian, that's the problem with semigroups, isn't it? There's no single natural element to use in the absence of data.

    - Lifting a semigroup to a Maybe is one way to resolve that problem. Since Maybe is a functor, you can map the contents of the Maybe until you've mapped it into a value for which an identity exists. + Lifting a semigroup to a Maybe is one way to resolve that problem. Since Maybe is a functor, you can map the contents of the Maybe until you've mapped it into a value for which an identity exists.

    In some cases, you can also fold a Maybe value by supplying a default value that makes sense in the specific context. A default value can be an appropriate fall-back value in a given context, even if it isn't a general identity. @@ -361,7 +361,7 @@

    Comments

    - +

    Ciprian, thank you for the link to the code. This explains why you're running into trouble. You absolutely can address the scenario that causes you trouble in a nice functional style, but once you start having the need to keep track of error data as well as happy-path data, Maybe is no longer the data structure you need. diff --git a/_posts/2018-04-30-parametrised-unit-tests-in-haskell.html b/_posts/2018-04-30-parametrised-unit-tests-in-haskell.html index b1fa7b821..98d02f5c5 100644 --- a/_posts/2018-04-30-parametrised-unit-tests-in-haskell.html +++ b/_posts/2018-04-30-parametrised-unit-tests-in-haskell.html @@ -24,7 +24,7 @@

    Testing date and time adjustments in C# #

    - In an earlier article, I discussed how to model date and time adjustments as a monoid. The example code was written in C#, and I used a few tests to demonstrate that the composition of adjustments work as intended: + In an earlier article, I discussed how to model date and time adjustments as a monoid. The example code was written in C#, and I used a few tests to demonstrate that the composition of adjustments work as intended:

    [Theory]
    @@ -138,7 +138,7 @@ 

    This is the same test as the above C# test named AdjustReturnsCorrectResult, and it's about the same size as well. Since the test is written using do notation, you can take a list of test cases and operate on each test case at a time. Although the test creates a list of tuples, the <- arrow pulls each (ZonedTime, ZonedTime) tuple out of the list and binds it to (dt, expected).

    - This test literally consists of only three expressions, so according to my normal heuristic for test formatting, I don't even need white space to indicate the three phases of the AAA pattern. The first expression sets up the test case (dt, expected). + This test literally consists of only three expressions, so according to my normal heuristic for test formatting, I don't even need white space to indicate the three phases of the AAA pattern. The first expression sets up the test case (dt, expected).

    The next expression exercises the System Under Test - in this case the adjustToBusinessHours function. That's simply a function call. @@ -202,6 +202,6 @@

    The overall configuration of the test runner, however, leaves a bit to be desired, so that's the topic for the next article.

    - Next: Inlined HUnit test lists. + Next: Inlined HUnit test lists.

    \ No newline at end of file diff --git a/_posts/2018-05-07-inlined-hunit-test-lists.html b/_posts/2018-05-07-inlined-hunit-test-lists.html index 95089f73a..fa4bd93d0 100644 --- a/_posts/2018-05-07-inlined-hunit-test-lists.html +++ b/_posts/2018-05-07-inlined-hunit-test-lists.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In the previous article you saw how to write parametrised test with HUnit. While the tests themselves were elegant and readable (in my opinion), the composition of test lists left something to be desired. This article offers a different way to organise test lists. + In the previous article you saw how to write parametrised test with HUnit. While the tests themselves were elegant and readable (in my opinion), the composition of test lists left something to be desired. This article offers a different way to organise test lists.

    Duplication # diff --git a/_posts/2018-05-14-project-arbitraries-with-view-patterns.html b/_posts/2018-05-14-project-arbitraries-with-view-patterns.html index 6d0cc6bb9..480e7135e 100644 --- a/_posts/2018-05-14-project-arbitraries-with-view-patterns.html +++ b/_posts/2018-05-14-project-arbitraries-with-view-patterns.html @@ -43,7 +43,7 @@ Here, reservation is a Reservation value because it was pattern-matched out of ArbReservation reservation. That's just like capacity is an Int, because it was pattern-matched out of Positive capacity.

    - Incidentally, in the spirit of the previous article, I'm here using in-lined properties implemented as lambda expressions. The lambda expressions use non-idiomatic formatting in order to make the tests more readable (and to prevent horizontal scrolling), but the gist of the matter is that the entire expression has the type Positive Int -> ArbReservation -> Bool. This is a Testable property because all the input types have Arbitrary instances. + Incidentally, in the spirit of the previous article, I'm here using in-lined properties implemented as lambda expressions. The lambda expressions use non-idiomatic formatting in order to make the tests more readable (and to prevent horizontal scrolling), but the gist of the matter is that the entire expression has the type Positive Int -> ArbReservation -> Bool. This is a Testable property because all the input types have Arbitrary instances.

    Discommodity creeps in # @@ -154,7 +154,7 @@

    Comments

    - +

    Benjamin, thank you for the pattern synonyms tip; I'll have to try that next time. @@ -186,7 +186,7 @@

    Comments

    - +

    Benjamin, thank you for elaborating. That all makes sense to me. diff --git a/_posts/2018-05-17-composite-as-a-monoid---a-business-rules-example.html b/_posts/2018-05-17-composite-as-a-monoid---a-business-rules-example.html index a13e9e74f..2233168a4 100644 --- a/_posts/2018-05-17-composite-as-a-monoid---a-business-rules-example.html +++ b/_posts/2018-05-17-composite-as-a-monoid---a-business-rules-example.html @@ -15,7 +15,7 @@ Towards the end of the first decade of the third millennium, I'd been writing object-oriented code for about ten years, and I'd started to notice some patterns in my code. I'd read Design Patterns 6-7 years earlier, but I noticed that I tended to use only a small subset of the patterns from the book - particularly Composite, Decorator, Chain of Responsibility, and a few others.

    - In particular, I noticed that modelling seemed to be easier, and the code better structured, when I could apply the Composite design pattern. It was also clear, however, that I couldn't always use the Composite pattern, so I started to speculate on what could be the distinguishing factors. In 2010, I made a first attempt at identifying when a Composite is possible, and when it isn't. Unfortunately, while it was a fine attempt (which I'll return to later), it didn't lead anywhere. Ultimately, I gave up on the subject and moved on to other things. + In particular, I noticed that modelling seemed to be easier, and the code better structured, when I could apply the Composite design pattern. It was also clear, however, that I couldn't always use the Composite pattern, so I started to speculate on what could be the distinguishing factors. In 2010, I made a first attempt at identifying when a Composite is possible, and when it isn't. Unfortunately, while it was a fine attempt (which I'll return to later), it didn't lead anywhere. Ultimately, I gave up on the subject and moved on to other things.

    A revelation # @@ -36,7 +36,7 @@

    "Not really; it's the Composite pattern..."

    - A few days later, as I was doing something else, it suddenly dawned on me that not only was a few lines of F# code equivalent to the Composite design pattern, but those lines of code were also manifestations of fundamental abstractions from category theory. Originally, I thought Composite was a combination of applicative functors and monoids, but as I investigated, I discovered that Composites are simply monoids. + A few days later, as I was doing something else, it suddenly dawned on me that not only was a few lines of F# code equivalent to the Composite design pattern, but those lines of code were also manifestations of fundamental abstractions from category theory. Originally, I thought Composite was a combination of applicative functors and monoids, but as I investigated, I discovered that Composites are simply monoids.

    This article shows a concrete example of that discovery, starting with my original F# code, subsequently translating it to C# to demonstrate that it's a Composite, and concluding with a translation to Haskell in order to demonstrate that it all fits with the formalisation of Monoid there. @@ -120,7 +120,7 @@

    let handle rules good = List.collect (fun r -> r good) rules

    - This handle function takes a list of business rules (rules) and returns a new function with the type Good -> Command list (or, actually, a function with the type 'a -> 'b list - once again I've fallen into the trap of using too descriptive names). Notice that this is the same type as the individual rules. + This handle function takes a list of business rules (rules) and returns a new function with the type Good -> Command list (or, actually, a function with the type 'a -> 'b list - once again I've fallen into the trap of using too descriptive names). Notice that this is the same type as the individual rules.

    You can now compose the four specific business rules: @@ -177,7 +177,7 @@

    Other IGood 'implementations' looks similar, and there's a comparable class hierarchy for ICommand, which is another marker interface.

    - The above F# code used a shared function type of Good -> Command list as a polymorphic type for a business rule. You can translate that to a C# interface: + The above F# code used a shared function type of Good -> Command list as a polymorphic type for a business rule. You can translate that to a C# interface:

    public interface IRule
    @@ -222,7 +222,7 @@ 

    }

    - Since 'all' members of IRule return collections, which form monoids over concatenation, the interface itself gives rise to a monoid. This means that you can create a Composite: + Since 'all' members of IRule return collections, which form monoids over concatenation, the interface itself gives rise to a monoid. This means that you can create a Composite:

    public class CompositeRule : IRule
    @@ -244,7 +244,7 @@ 

    }

    - Notice how the implementation of Handle follows the template for monoid accumulation. It starts with the identity, which, for the collection concatenation monoid is the empty collection. It then loops through all the composed rules and updates the accumulator commands in each iteration. Here, I used AddRange, which mutates commands instead of returning a new value, but the result is the same. Finally, the method returns the accumulator. + Notice how the implementation of Handle follows the template for monoid accumulation. It starts with the identity, which, for the collection concatenation monoid is the empty collection. It then loops through all the composed rules and updates the accumulator commands in each iteration. Here, I used AddRange, which mutates commands instead of returning a new value, but the result is the same. Finally, the method returns the accumulator.

    You can now compose all the business rules and use the composition as though it was a single object: @@ -316,7 +316,7 @@

    Notice that all four business rules share the same type: Good -> [Command]. This is conceptually the same type as in the F# code; instead of writing Command list, which is the F# syntax, the Haskell syntax for a list of Command values is [Command].

    - All those functions are monoids because their return types form a monoid, so in Haskell, you can compose them without further ado: + All those functions are monoids because their return types form a monoid, so in Haskell, you can compose them without further ado:

    handleAll :: Good -> [Command]
    diff --git a/_posts/2018-05-22-church-encoding.html b/_posts/2018-05-22-church-encoding.html
    index ea2fd92de..95d9f0973 100644
    --- a/_posts/2018-05-22-church-encoding.html
    +++ b/_posts/2018-05-22-church-encoding.html
    @@ -12,10 +12,10 @@
     		{{ page.description }}
     	

    - This article series is part of an even larger series of articles about the relationship between design patterns and category theory. + This article series is part of an even larger series of articles about the relationship between design patterns and category theory.

    - When asked why I like functional programming so much, I often emphasise the superior modelling ability that I get from algebraic data types. Particularly, languages like F# and Haskell have sum types in addition to the product types that most statically typed languages seem to have. + When asked why I like functional programming so much, I often emphasise the superior modelling ability that I get from algebraic data types. Particularly, languages like F# and Haskell have sum types in addition to the product types that most statically typed languages seem to have.

    In short, a sum type gives you the ability to declare, as part of the type system, that a particular data type must be exactly one of a finite list of mutually exclusive options. This differs from common object-oriented sub-typing because class inheritance or interface implementation offers conceptually infinite extensibility. Sometimes, unconstrained extensibility is exactly what you need, but in other cases, the ability to define a closed set of cases can be an effective modelling tool. If you need an easy-to-read introduction to algebraic data types, I recommend Tomas Petricek's fine article Power of mathematics: Reasoning about functional types. @@ -75,7 +75,7 @@

    fun f x -> f x

    - This looks more like a function that takes two arguments, so alternatively, via uncurry isomorphisms, you can also write the C# representation like this: + This looks more like a function that takes two arguments, so alternatively, via uncurry isomorphisms, you can also write the C# representation like this:

    (f, x) => f(x)
    @@ -94,11 +94,11 @@

    @@ -114,7 +114,7 @@

    You can use lambda expressions to define all sorts of data types and computations. Because lambda calculus is a universal model of computation, you can learn about fundamental representations of computation. Particularly, lambda calculus offers a model of logical branching, which again teaches us how to model sum types.

    - Next: Church-encoded Boolean values. + Next: Church-encoded Boolean values.

    diff --git a/_posts/2018-05-24-church-encoded-boolean-values.html b/_posts/2018-05-24-church-encoded-boolean-values.html index 12336d1c0..41dc955d6 100644 --- a/_posts/2018-05-24-church-encoded-boolean-values.html +++ b/_posts/2018-05-24-church-encoded-boolean-values.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about Church encoding. + This article is part of a series of articles about Church encoding.

    Years ago, the so-called Anti-IF Campaign made the rounds on various social media (back then, IIRC, mostly known as 'the blogosphere'). The purpose of the campaign was never to eradicate every single use of if statements or expressions in source code, but rather to educate people about alternatives to the Arrow anti-pattern. @@ -36,7 +36,7 @@

    You can think of an expression like that as a function that takes a Boolean value and two potential return values: one for the true case, and one for the false case.

    - In lambda calculus, the only primitive building blocks are functions. There's no built-in Boolean values, but you can define them with functions. Boolean values are functions that take two arguments. By conventions, the first argument (the one to the left) represents the true case, whereas the second argument (to the right) signifies the false case - just like the ternary operator. In the lambda calculus, functions are curried, but we know from uncurry isomorphisms that we can also represent a two-argument function as a function that takes a two-tuple (a pair) as a single argument. Furthermore, we know from function isomorphisms that we can represent a function as an instance method. Therefore, we can declare a Boolean value in C# to be an object that implements this interface: + In lambda calculus, the only primitive building blocks are functions. There's no built-in Boolean values, but you can define them with functions. Boolean values are functions that take two arguments. By conventions, the first argument (the one to the left) represents the true case, whereas the second argument (to the right) signifies the false case - just like the ternary operator. In the lambda calculus, functions are curried, but we know from uncurry isomorphisms that we can also represent a two-argument function as a function that takes a two-tuple (a pair) as a single argument. Furthermore, we know from function isomorphisms that we can represent a function as an instance method. Therefore, we can declare a Boolean value in C# to be an object that implements this interface:

    public interface IChurchBoolean
    @@ -253,10 +253,10 @@ 

    Semigroups and monoids #

    - The strongly typed signature accentuates that the Match method is a binary operation; it takes two values of the type T and returns a single T value. Is it a monoid, then? + The strongly typed signature accentuates that the Match method is a binary operation; it takes two values of the type T and returns a single T value. Is it a monoid, then?

    - It's not a single monoid, but rather a collection of semigroups, some of which are monoids as well. The implementation of ChurchTrue corresponds to the first semigroup, and ChurchFalse to the last semigroup. You can make this explict in Haskell: + It's not a single monoid, but rather a collection of semigroups, some of which are monoids as well. The implementation of ChurchTrue corresponds to the first semigroup, and ChurchFalse to the last semigroup. You can make this explict in Haskell:

    import Data.Semigroup
    @@ -361,6 +361,6 @@ 

    This innocuous-looking question is harder to answer than you may think, so that's worthy of its own article.

    - Next: Church-encoded natural numbers. + Next: Church-encoded natural numbers.

    \ No newline at end of file diff --git a/_posts/2018-05-28-church-encoded-natural-numbers.html b/_posts/2018-05-28-church-encoded-natural-numbers.html index 96822e6af..eb58e51d1 100644 --- a/_posts/2018-05-28-church-encoded-natural-numbers.html +++ b/_posts/2018-05-28-church-encoded-natural-numbers.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about Church encoding. The previous article, about Church-encoding of Boolean values, concluded with the question: how do you determine whether an integer is even or odd? + This article is part of a series of articles about Church encoding. The previous article, about Church-encoding of Boolean values, concluded with the question: how do you determine whether an integer is even or odd?

    That sounds easy, but turns out to be more complicated that you might think at first glance. @@ -42,7 +42,7 @@

    You could implement an IsOdd method either by using the != operator instead of ==, but otherwise copy the implementation of IsEven; or, alternatively, call IsEven and negate the result.

    - This works fine in normal C# code, but in this article, the agenda is different. We're investigating how programming with the previous article's IChurchBoolean API would look. The above built-in options use Boolean language primitives, so that's not really instructive. + This works fine in normal C# code, but in this article, the agenda is different. We're investigating how programming with the previous article's IChurchBoolean API would look. The above built-in options use Boolean language primitives, so that's not really instructive.

    Boolean conversions # @@ -282,7 +282,7 @@

        | Succ p -> 1 + count p

    - This implementation, by the way, isn't tail-recursive, but you can easily refactor to a tail-recursive implementation like this: + This implementation, by the way, isn't tail-recursive, but you can easily refactor to a tail-recursive implementation like this:

    // Peano -> int
    @@ -446,7 +446,7 @@ 

    ChurchFalse { }

    - IsEven is implemented from first principles. The only language features we need are lambda expressions and recursion, although in order to make these examples slightly more idiomatic, I've also used interfaces and classes. + IsEven is implemented from first principles. The only language features we need are lambda expressions and recursion, although in order to make these examples slightly more idiomatic, I've also used interfaces and classes.

    Detecting odd numbers # @@ -482,6 +482,6 @@

    In the previous article, you saw how to model Boolean values as a set of functions with two arguments. In this article, you saw how to model natural numbers with another set of functions that take two arguments. In the next article, you'll see another data type modelled as a set of functions with two arguments. It looks like a patterns is starting to appear.

    - Next: Church-encoded Maybe. + Next: Church-encoded Maybe.

    \ No newline at end of file diff --git a/_posts/2018-06-04-church-encoded-maybe.html b/_posts/2018-06-04-church-encoded-maybe.html index 1204cc274..6dc9fdbbf 100644 --- a/_posts/2018-06-04-church-encoded-maybe.html +++ b/_posts/2018-06-04-church-encoded-maybe.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about Church encoding. In this series, you'll learn how to re-create various programming language features from first principles. In previous articles, you learned how to implement Boolean logic without Boolean primitives, as well as how to model natural numbers. Through these examples, you'll learn how to model sum types without explicit language support. + This article is part of a series of articles about Church encoding. In this series, you'll learn how to re-create various programming language features from first principles. In previous articles, you learned how to implement Boolean logic without Boolean primitives, as well as how to model natural numbers. Through these examples, you'll learn how to model sum types without explicit language support.

    The billion-dollar mistake # @@ -24,7 +24,7 @@

    Unfortunately, for fifty years, we've been immersed in environments where null references have been the dominant way to model the absence of data. This, despite the fact that even Sir Antony Hoare, the inventor of null references, has publicly called it his billion-dollar mistake.

    - You can, however, model the potential absence of data in saner ways. Haskell, for example, has no built-in null support, but it does include a built-in Maybe type. In Haskell (as well as in F#, where it's called option), Maybe is defined as a sum type: + You can, however, model the potential absence of data in saner ways. Haskell, for example, has no built-in null support, but it does include a built-in Maybe type. In Haskell (as well as in F#, where it's called option), Maybe is defined as a sum type:

    data Maybe a = Nothing | Just a deriving (EqOrd)
    @@ -71,7 +71,7 @@

    Church-encoded Maybe in C# #

    - Both lambda calculus and Haskell rely on currying and partial application to make the contract fit. In C#, as you've previously seen, you can instead define an interface and rely on class fields for the 'extra' function arguments. Since Church-encoded Maybe is represented by a function that takes two arguments, we'll once again define an interface with a single method that takes two arguments: + Both lambda calculus and Haskell rely on currying and partial application to make the contract fit. In C#, as you've previously seen, you can instead define an interface and rely on class fields for the 'extra' function arguments. Since Church-encoded Maybe is represented by a function that takes two arguments, we'll once again define an interface with a single method that takes two arguments:

    public interface IMaybe<T>
    @@ -98,7 +98,7 @@ 

    }

    - Again, the implementation unconditionally returns nothing while ignoring just. You may, though, have noticed that, as is appropriate for Maybe, Nothing<T> has a distinct type. In other words, Nothing<string> doesn't have the same type as Nothing<int>. This is not only 'by design', but is a fundamental result of how we define Maybe. The code simply wouldn't compile if you tried to remove the type argument from the class. This is in contrast to C# null, which has no type. + Again, the implementation unconditionally returns nothing while ignoring just. You may, though, have noticed that, as is appropriate for Maybe, Nothing<T> has a distinct type. In other words, Nothing<string> doesn't have the same type as Nothing<int>. This is not only 'by design', but is a fundamental result of how we define Maybe. The code simply wouldn't compile if you tried to remove the type argument from the class. This is in contrast to C# null, which has no type.

    You implement the just case like this: @@ -164,7 +164,7 @@

    Functor #

    - From Haskell (and F#) we know that Maybe is a functor. In C#, you turn a container into a functor by implementing an appropriate Select method. You can do this with IMaybe<T> as well: + From Haskell (and F#) we know that Maybe is a functor. In C#, you turn a container into a functor by implementing an appropriate Select method. You can do this with IMaybe<T> as well:

    public static IMaybe<TResult> Select<TTResult>(
    @@ -216,7 +216,7 @@ 

    Church-encoding enables you to model sum types as functions. So far in this article series, you've seen how to model Boolean values, natural numbers, and Maybe. Common to all three examples is that the data type in question consists of two mutually exclusive cases. There's at least one more interesting variation on that pattern.

    - Next: Church-encoded Either. + Next: Church-encoded Either.

    diff --git a/_posts/2018-06-11-church-encoded-either.html b/_posts/2018-06-11-church-encoded-either.html index 3f63299ed..0e01646f0 100644 --- a/_posts/2018-06-11-church-encoded-either.html +++ b/_posts/2018-06-11-church-encoded-either.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is part of a series of articles about Church encoding. In this series, you'll learn how to re-create various programming language features from first principles. In previous articles, you learned how to implement Boolean logic without Boolean primitives, how to model natural numbers, as well as how to implement Maybe (a type-safe alternative to null). Through these examples, you'll learn how to model sum types without explicit language support. + This article is part of a series of articles about Church encoding. In this series, you'll learn how to re-create various programming language features from first principles. In previous articles, you learned how to implement Boolean logic without Boolean primitives, how to model natural numbers, as well as how to implement Maybe (a type-safe alternative to null). Through these examples, you'll learn how to model sum types without explicit language support.

    @@ -20,7 +20,7 @@

    - In a previous article, I've discussed how a language doesn't need to have built-in exceptions in order to support composable and type-safe error handling. In fact, exceptions are noting but glorified GOTO statements. A better approach is to use the Either abstraction, which enables you to model values that are either one or another thing. + In a previous article, I've discussed how a language doesn't need to have built-in exceptions in order to support composable and type-safe error handling. In fact, exceptions are noting but glorified GOTO statements. A better approach is to use the Either abstraction, which enables you to model values that are either one or another thing.

    In F#, this type is known as Result<'T, 'TError>, while in Haskell it's called Either. It enables you to model an outcome that is either something (like a success) or something else (such as an error). @@ -53,7 +53,7 @@

    The right function works like the left function, with the only difference that it always returns r b.

    - The idea, as usual, is that you can partially apply left and right, by, for instance calling left three (where three is the lambda calculus representation of the number 3, as described in the article on Church-encoded natural numbers). Such a partially applied function is a function that still takes the two arguments l and r. + The idea, as usual, is that you can partially apply left and right, by, for instance calling left three (where three is the lambda calculus representation of the number 3, as described in the article on Church-encoded natural numbers). Such a partially applied function is a function that still takes the two arguments l and r.

    The same is true if you partially apply right with a value, like right one. @@ -79,7 +79,7 @@

    - Both lambda calculus and Haskell relies on currying and partial application to make the contract fit. In C#, as you've previously seen, you can instead define an interface and rely on class fields for the 'extra' function arguments. Since Church-encoded Either is represented by a function that takes two arguments, we'll once again define an interface with a single method that takes two arguments: + Both lambda calculus and Haskell relies on currying and partial application to make the contract fit. In C#, as you've previously seen, you can instead define an interface and rely on class fields for the 'extra' function arguments. Since Church-encoded Either is represented by a function that takes two arguments, we'll once again define an interface with a single method that takes two arguments:

    public interface IEither<LR>
    @@ -257,13 +257,13 @@ 

    The code shown in this article is available on GitHub.

    - Like Maybe, you can also make Either a functor. This'll enable you to compose various error-producing functions in a sane manner. + Like Maybe, you can also make Either a functor. This'll enable you to compose various error-producing functions in a sane manner.

    Church-encoding enables you to model sum types as functions. So far in this article series, you've seen how to model Boolean values, natural numbers, Maybe, and Either. Common to all four examples is that the data type in question consists of two mutually exclusive cases. This is the reason they're all modelled as methods that take two arguments. What happens if, instead of two, you have three mutually exclusive cases? Read on.

    - Next: Church-encoded payment types. + Next: Church-encoded payment types.

    @@ -288,7 +288,7 @@

    Comments

    - +

    Ciprian, thank you for writing. Either is a particular discriminated union; by definition it has two type parameters. In F# it's called Result<'T,'TError> and defined as: @@ -300,7 +300,7 @@

    Comments

    Notice that in this defintion, the 'right' result is to the left, and the error is to the right, which is opposite of the way of the either convention.

    - If you need another type with three mutually exclusive cases, then Either is a poor fit for that (although one can nest them, as you suggest). You can, however, still Church-encode such a type. The next article in this article series contains an example of a Church-encoding of a discriminated union with three, instead of two, cases. By coincidence, this type is also called payment type. The cases are, however, not the same as those you suggest, since it models a different scenario. + If you need another type with three mutually exclusive cases, then Either is a poor fit for that (although one can nest them, as you suggest). You can, however, still Church-encode such a type. The next article in this article series contains an example of a Church-encoding of a discriminated union with three, instead of two, cases. By coincidence, this type is also called payment type. The cases are, however, not the same as those you suggest, since it models a different scenario.

    The IEither<L, R> interface shown in this article is not meant to be implemented by any other classes than Left and Right. The only reason these types are public is because this article shows you how the sausage is made, so to speak. If one ever were to put such a type into a reusable library, I think an alternative implementation like the following would be more appropriate: @@ -420,7 +420,7 @@

    Comments

    }

    - Additional extension methods like the SelectBoth method described in Either bifunctor can be still implemented based on Match. + Additional extension methods like the SelectBoth method described in Either bifunctor can be still implemented based on Match.

    This API is much more locked down, so should leave little doubt about how it's supposed to be used. Apart from the methods inherited from System.Object, this Either<L, R> class only exposes one public method: Match. It's also sealed, and its constructor is marked private, so not only can't you inherit from it, you also can't derive classes from Left or Right. diff --git a/_posts/2018-06-18-church-encoded-payment-types.html b/_posts/2018-06-18-church-encoded-payment-types.html index fb6c14863..87f31c629 100644 --- a/_posts/2018-06-18-church-encoded-payment-types.html +++ b/_posts/2018-06-18-church-encoded-payment-types.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is part of a series of articles about Church encoding. In the previous articles, you've seen how to implement Boolean logic without Boolean primitives, as well as how to model natural numbers, how to implement a Maybe container, and how to implement an Either container. Common to all four examples is that they're based on sum types with exactly two mutually exclusive cases. + This article is part of a series of articles about Church encoding. In the previous articles, you've seen how to implement Boolean logic without Boolean primitives, as well as how to model natural numbers, how to implement a Maybe container, and how to implement an Either container. Common to all four examples is that they're based on sum types with exactly two mutually exclusive cases.

    Three binary sum types, and their corresponding match methods. @@ -26,7 +26,7 @@

    A payment type model in F# #

    - In a previous article I described a particular business problem that was elegantly addressed with a discriminated union (sum type) in F#: + In a previous article I described a particular business problem that was elegantly addressed with a discriminated union (sum type) in F#:

    type PaymentService = { Name : string; Action : string }
    @@ -296,9 +296,9 @@ 

    The code shown in this article is available on GitHub.

    - This article concludes the little series on how to use Church-encoding in C# to create sum types. You may, however, think that it doesn't really feel object-oriented, with its heavy reliance on function arguments (e.g. Func<PaymentService, T>). It turns out, though, that with only a few refactorings, you'll come to the realisation that what you've seen here is isomorphic to a classic design pattern. Read on! + This article concludes the little series on how to use Church-encoding in C# to create sum types. You may, however, think that it doesn't really feel object-oriented, with its heavy reliance on function arguments (e.g. Func<PaymentService, T>). It turns out, though, that with only a few refactorings, you'll come to the realisation that what you've seen here is isomorphic to a classic design pattern. Read on!

    - Next: Some design patterns as universal abstractions. + Next: Some design patterns as universal abstractions.

    \ No newline at end of file diff --git a/_posts/2018-06-25-visitor-as-a-sum-type.html b/_posts/2018-06-25-visitor-as-a-sum-type.html index a671fcc84..d2f1549c3 100644 --- a/_posts/2018-06-25-visitor-as-a-sum-type.html +++ b/_posts/2018-06-25-visitor-as-a-sum-type.html @@ -12,16 +12,16 @@ {{ page.description }}

    - This article is part of a series of articles about specific design patterns and their category theory counterparts. In it, you'll see how the Visitor design pattern is equivalent to a sum type. + This article is part of a series of articles about specific design patterns and their category theory counterparts. In it, you'll see how the Visitor design pattern is equivalent to a sum type.

    Sum types #

    - I think that the most important advantage of a statically typed programming language is that it gives you immediate feedback on your design and implementation work. Granted, that your code compiles may not be enough to instil confidence that you've done the right thing, but it's obvious that when your code doesn't compile, you still have work to do. + I think that the most important advantage of a statically typed programming language is that it gives you immediate feedback on your design and implementation work. Granted, that your code compiles may not be enough to instil confidence that you've done the right thing, but it's obvious that when your code doesn't compile, you still have work to do.

    - A static type system enables you to catch some programming errors at compile time. It prevents you from making obvious mistakes like trying to divide a GUID by a date. Some type systems don't offer much more help than that, while others are more articulate; I think that type systems inhabit a continuous spectrum of capabilities, although that, too, is a simplification. + A static type system enables you to catch some programming errors at compile time. It prevents you from making obvious mistakes like trying to divide a GUID by a date. Some type systems don't offer much more help than that, while others are more articulate; I think that type systems inhabit a continuous spectrum of capabilities, although that, too, is a simplification.

    An often-touted advantage of programming languages like F#, OCaml, and Haskell is that they, in the words of Yaron Minsky, enable you to make illegal states unrepresentable. The way these languages differ from languages like C# and Java is that they have algebraic data types. @@ -39,7 +39,7 @@

    Church-encoded payment types #

    - In a previous article, you saw how to Church-encode a domain-specific sum type. That article, again, demonstrated how to rewrite a domain-specific F# discriminated union as a C# API. The F# type was this PaymentType sum type: + In a previous article, you saw how to Church-encode a domain-specific sum type. That article, again, demonstrated how to rewrite a domain-specific F# discriminated union as a C# API. The F# type was this PaymentType sum type:

    type PaymentType =
    @@ -146,7 +146,7 @@ 

    }

    - From argument list isomorphisms we know that an argument list is isomorphic to a Parameter Object, so this step should come as no surprise. We also know that the reverse translation (from Parameter Object to argument list) is possible. + From argument list isomorphisms we know that an argument list is isomorphic to a Parameter Object, so this step should come as no surprise. We also know that the reverse translation (from Parameter Object to argument list) is possible.

    Add Run prefix # @@ -179,7 +179,7 @@

    Refactor to interface #

    - The definition of PaymentTypeParameters<T> still doesn't look object-oriented. While it's formally an object, it's an object that composes three function delegates. We've managed to move the function delegates around, but we haven't managed to get rid of them. From object isomorphisms, however, we know that tuples of functions are isomorphic to objects, and that's essentially what we have here. In this particular case, there's no implementation code in PaymentTypeParameters<T> itself - it's nothing but a group of three functions. You can refactor that class to an interface: + The definition of PaymentTypeParameters<T> still doesn't look object-oriented. While it's formally an object, it's an object that composes three function delegates. We've managed to move the function delegates around, but we haven't managed to get rid of them. From object isomorphisms, however, we know that tuples of functions are isomorphic to objects, and that's essentially what we have here. In this particular case, there's no implementation code in PaymentTypeParameters<T> itself - it's nothing but a group of three functions. You can refactor that class to an interface:

    public interface IPaymentTypeParameters<T>
    @@ -273,7 +273,7 @@ 

    }

    - In Design Patterns, the Visitor design pattern is only described in such a way that both Accept and Visit methods have void return types, but from unit isomorphisms we know that this is equivalent to returning unit. Thus, setting T in the above API to a suitable unit type (like the one defined in F#), you arrive at the canonical Visitor pattern. The generic version here is simply a generalisation. + In Design Patterns, the Visitor design pattern is only described in such a way that both Accept and Visit methods have void return types, but from unit isomorphisms we know that this is equivalent to returning unit. Thus, setting T in the above API to a suitable unit type (like the one defined in F#), you arrive at the canonical Visitor pattern. The generic version here is simply a generalisation.

    For the sake of completeness, client code now looks like this: @@ -321,7 +321,7 @@

    }

    - You can refactor all the other Church encoding examples I've shown you to Visitor implementations. It doesn't always make the code more readable, but it's possible. + You can refactor all the other Church encoding examples I've shown you to Visitor implementations. It doesn't always make the code more readable, but it's possible.

    From Visitor to sum types # diff --git a/_posts/2018-07-02-terse-operators-make-business-code-more-readable.html b/_posts/2018-07-02-terse-operators-make-business-code-more-readable.html index 0bb640a12..4861bf06a 100644 --- a/_posts/2018-07-02-terse-operators-make-business-code-more-readable.html +++ b/_posts/2018-07-02-terse-operators-make-business-code-more-readable.html @@ -15,7 +15,7 @@ The Haskell programming language has a reputation for being terse to the point of being unreadable. That reputation isn't undeserved, but to counter, other languages exist that are verbose to the point of being unreadable.

    - Particularly, idiomatic Haskell code involves abstruse operators like ., $, <$>, >>=, <*>, <>, and so on. Not only do such operators look scary, but when I started writing Haskell code, it also bothered me that I didn't know how to pronounce these operators. I don't know how you read code, but my brain often tries to 'talk' about the code, silently, inside my head, and when it encounters something like =<<, it tends to stumble. + Particularly, idiomatic Haskell code involves abstruse operators like ., $, <$>, >>=, <*>, <>, and so on. Not only do such operators look scary, but when I started writing Haskell code, it also bothered me that I didn't know how to pronounce these operators. I don't know how you read code, but my brain often tries to 'talk' about the code, silently, inside my head, and when it encounters something like =<<, it tends to stumble.

    At least, it used to. These days, my brain has accepted that in many cases, Haskell operators are a little like punctuation marks. When I read a piece of prose, my brain doesn't insist on 'saying' comma, semicolon, question mark, period, etcetera. Such symbols assist reading, and often adjust the meaning of a text, but aren't to be read explicitly as themselves. diff --git a/_posts/2018-07-09-typing-and-testing-problem-23.html b/_posts/2018-07-09-typing-and-testing-problem-23.html index ef76143f9..1291e366e 100644 --- a/_posts/2018-07-09-typing-and-testing-problem-23.html +++ b/_posts/2018-07-09-typing-and-testing-problem-23.html @@ -15,7 +15,7 @@ The debate about dynamic typing versus static typing still goes on. If it ever gets resolved, I suppose it'll be in the far future. Until then, one's position is bound to be determined mostly by experience and belief. I openly admit that I prefer statically typed languages like F# and Haskell.

    - As I've previously touched on, I can't help seeing types as a slider. The more to the right you pull it, the stronger the type system. The more to the left you pull it, the more you'll need automated tests to give you a sense of confidence in your code. + As I've previously touched on, I can't help seeing types as a slider. The more to the right you pull it, the stronger the type system. The more to the left you pull it, the more you'll need automated tests to give you a sense of confidence in your code.

    In this article, I'll share an small revelation recently given to me. @@ -96,7 +96,7 @@

    Taming randomness #

    - Before we look at automated testing, let's consider how to turn randomness into deterministic behaviour. This is (seemingly) always a problem with unit testing when the desired behaviour contains randomness, because tests should be deterministic. Once again, however, it turns out that functional design is intrinsically testable. Since Haskell design favours pure functions, the core of System.Random is deterministic. + Before we look at automated testing, let's consider how to turn randomness into deterministic behaviour. This is (seemingly) always a problem with unit testing when the desired behaviour contains randomness, because tests should be deterministic. Once again, however, it turns out that functional design is intrinsically testable. Since Haskell design favours pure functions, the core of System.Random is deterministic.

    This is, in fact, not much different from C#, where the Random class encapsulates an algorithm that computes a series of random-looking values based on an initial seed value. If you give it the same seed, it'll produce the same sequence of random-looking numbers. Haskell works the same way. @@ -218,7 +218,7 @@

    "ntfnc"

    - That looks, I suppose, random enough... What's more important is that this is completely repeatable. This means that I can write parametrised tests that protect against regressions: + That looks, I suppose, random enough... What's more important is that this is completely repeatable. This means that I can write parametrised tests that protect against regressions:

    "rndGenSelect of chars returns correct result" ~: do
    diff --git a/_posts/2018-07-16-angular-addition-monoid.html b/_posts/2018-07-16-angular-addition-monoid.html
    index a49f9f156..955fe8b12 100644
    --- a/_posts/2018-07-16-angular-addition-monoid.html
    +++ b/_posts/2018-07-16-angular-addition-monoid.html
    @@ -14,7 +14,7 @@
     		{{ page.description }}
     	

    - This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity). + This article is part of a series about monoids. In short, a monoid is an associative binary operation with a neutral element (also known as identity).

    In geometry, an angle is a measure of how two crossing lines relate to each other. In mathematics, angles are usually represented in radians, but in daily use, they're mostly measured in degrees between 0 and 360. @@ -109,7 +109,7 @@

    }

    - Notice the Add method, which is a binary operation; it's an instance method on Angle, takes another Angle as input, and returns an Angle value. + Notice the Add method, which is a binary operation; it's an instance method on Angle, takes another Angle as input, and returns an Angle value.

    Associativity # @@ -194,6 +194,6 @@

    As far as I can tell, any modulo-based addition is a monoid, but while, say, modulo 37 addition probably doesn't have any practical application, modulo 360 addition does, because it's how you do angular addition.

    - Next: Strings, lists, and sequences as a monoid. + Next: Strings, lists, and sequences as a monoid.

    \ No newline at end of file diff --git a/_posts/2018-07-24-dependency-injection-revisited.html b/_posts/2018-07-24-dependency-injection-revisited.html index 9c6dadbde..ed65025e4 100644 --- a/_posts/2018-07-24-dependency-injection-revisited.html +++ b/_posts/2018-07-24-dependency-injection-revisited.html @@ -12,13 +12,13 @@ {{ page.description }}

    - In a previous article, you saw how you can model any sum type as a Visitor. Does that mean, then, that you can model a free monad as a Visitor? + In a previous article, you saw how you can model any sum type as a Visitor. Does that mean, then, that you can model a free monad as a Visitor?

    Yes, it does.

    - In the F# free monad recipe, you saw how to refactor any injected, interface-based dependency to a free monad. Since a free monad is nothing but a recursive sum type, this means that you now have the tools at your disposal to refactor your injected dependencies to a Visitor. + In the F# free monad recipe, you saw how to refactor any injected, interface-based dependency to a free monad. Since a free monad is nothing but a recursive sum type, this means that you now have the tools at your disposal to refactor your injected dependencies to a Visitor.

    To be clear, this is an article exploring the boundaries of what's possible with a language like C#. It's not intended to be an endorsement of a particular way to organise code. A conference talk recording that covers the same example also exists. @@ -50,7 +50,7 @@

    As the code comment explains, the IsReservationInFuture method doesn't belong on this IReservationsRepository interface. A dedicated 'time provider' dependency would be more appropriate, but as you'll see when you read on, refactoring just one interface to a free monad Visitor is already complicated. Doing it twice would just repeat the process while adding little additional clarity.

    - Apart from IsReservationInFuture, the IReservationsRepository declares ReadReservations for querying the Repository for existing reservations, and Create for adding a new reservation to the Repository. Notice that the Create method violates the Command Query Separation principle. While better alternatives exist, I decided to design the present example like this because it better illustrates how data could flow through a system. + Apart from IsReservationInFuture, the IReservationsRepository declares ReadReservations for querying the Repository for existing reservations, and Create for adding a new reservation to the Repository. Notice that the Create method violates the Command Query Separation principle. While better alternatives exist, I decided to design the present example like this because it better illustrates how data could flow through a system.

    The only consumer of the interface that we're going to consider is this MaîtreD class: @@ -88,7 +88,7 @@

    This is straightforward example code. First, it queries whether the reservation is in the past, because it makes no sense accepting a reservation in the past.

    - If it gets past that hurdle, the TryAccept method then queries the injected ReservationsRepository for the reservations already recorded on that date, and calculates the sum of the quantities. This produces reservedSeats - the number of already reserved seats. If the restaurant's Capacity (a Primitive Dependency) is less than the already reserved seats, plus the requested quantity, the method again rejects the reservation. This time, the reason is that there's insufficient remaining capacity to accept it. + If it gets past that hurdle, the TryAccept method then queries the injected ReservationsRepository for the reservations already recorded on that date, and calculates the sum of the quantities. This produces reservedSeats - the number of already reserved seats. If the restaurant's Capacity (a Primitive Dependency) is less than the already reserved seats, plus the requested quantity, the method again rejects the reservation. This time, the reason is that there's insufficient remaining capacity to accept it.

    Finally, if the reservation makes it past all the guards, IsAccepted is set to true, and the reservation is added to the Repository. Recall that Create returns the ID of the new reservation (presumably a database ID), so that ID is returned from the method. In all other cases, the method returns null. The return type of TryAccept is int? (Nullable<int>), so the int value returned from Create is implicitly converted to int?; the compiler does that. @@ -228,7 +228,7 @@

    Free monad in F# #

    - In order to refactor IReservationsRepository to a free monad, it's illustrative to first see how it would look in F#. This step is by no means required, but it offers another perspective of the translation that you have to perform. According to the F# free monad recipe, you can represent the IReservationsRepository interface with a sum type that describes the instruction set of the API: + In order to refactor IReservationsRepository to a free monad, it's illustrative to first see how it would look in F#. This step is by no means required, but it offers another perspective of the translation that you have to perform. According to the F# free monad recipe, you can represent the IReservationsRepository interface with a sum type that describes the instruction set of the API:

    type ReservationsInstruction<'a> =
    @@ -249,7 +249,7 @@ 

    Church-encoded instruction set #

    - From Church encodings we know that we can represent a sum type as an interface with a single Match method. The instruction set is a functor, so it has a generic type argument: + From Church encodings we know that we can represent a sum type as an interface with a single Match method. The instruction set is a functor, so it has a generic type argument:

    public interface IReservationsInstruction<T>
    @@ -697,7 +697,7 @@

    Refactor instruction arguments to Parameter Object #

    - As you know from another article, you can refactor any Church-encoded sum type to a Visitor. If you want to do it step-wise, you start by introducing a Parameter Object, as suggested by Refactoring. There's two sum types in play in this code base, but you can arbitrarily choose to start with the instruction set. Instead of taking three method arguments, change the Match method so that it takes only a single argument: + As you know from another article, you can refactor any Church-encoded sum type to a Visitor. If you want to do it step-wise, you start by introducing a Parameter Object, as suggested by Refactoring. There's two sum types in play in this code base, but you can arbitrarily choose to start with the instruction set. Instead of taking three method arguments, change the Match method so that it takes only a single argument:

    public interface IReservationsInstruction<T>
    @@ -733,7 +733,7 @@ 

    This change clearly just moves things around, so nothing much is yet gained. You'll need to adjust other parts of the code in order to pass an instance of this Parameter Object to the Match method, but that's trivial and automatable work, so I'll skip showing it.

    - If you've noticed that the ReservationsInstructionParameters<T, TResult> Parameter Object is nothing but a container of three functions, you may not be impressed, but from Object isomorphisms we know that a tuple (or record) of functions is isomorphic to an object, thereby nicely putting everything in place for the next change. + If you've noticed that the ReservationsInstructionParameters<T, TResult> Parameter Object is nothing but a container of three functions, you may not be impressed, but from Object isomorphisms we know that a tuple (or record) of functions is isomorphic to an object, thereby nicely putting everything in place for the next change.

    Refactor instruction set Parameter Object to an interface # @@ -807,7 +807,7 @@

    Rename instruction set API #

    - You're simply following the refactoring steps outlined in Visitor as a sum type, so now you can rename the types involved with the instruction set to follow the naming conventions of the Visitor design pattern: + You're simply following the refactoring steps outlined in Visitor as a sum type, so now you can rename the types involved with the instruction set to follow the naming conventions of the Visitor design pattern:

    public interface IReservationsInstructionVisitor<TTResult>
    @@ -858,7 +858,7 @@ 

    Refactor tuple argument to argument list #

    - If you consider the current definition of IReservationsInstructionVisitor<T, TResult> (see above), you'll notice that each method takes a single argument in the shape of a tuple. From Argument list isomorphisms you know that you can refactor such a method into a method that takes a normal argument list: + If you consider the current definition of IReservationsInstructionVisitor<T, TResult> (see above), you'll notice that each method takes a single argument in the shape of a tuple. From Argument list isomorphisms you know that you can refactor such a method into a method that takes a normal argument list:

    public interface IReservationsInstructionVisitor<TTResult>
    @@ -1020,7 +1020,7 @@ 

    Testability #

    - Is this design still testable? Yes, indeed, the overall free monad design is pure, and thereby inherently testable. Instead of using a dynamic mock library like Moq, you can add a test-specific implementation of the free monad Visitor to your unit testing code base: + Is this design still testable? Yes, indeed, the overall free monad design is pure, and thereby inherently testable. Instead of using a dynamic mock library like Moq, you can add a test-specific implementation of the free monad Visitor to your unit testing code base:

    public class StubReservationsVisitor<T> :
    @@ -1142,12 +1142,12 @@ 

    As a rule of thumb, no, I don't think it's a good idea. Free monads are worth considering in Haskell where they are much closer to being 'free', in the sense that there's little programming overhead involved with defining and using them. Already when you translate a free monad to F# do you discover how much boilerplate programming is involved. Still, due to F#'s computation expressions, a free monad may occasionally be worth considering. Both in implementation and at call sites, you can make the API easy to use.

    - In C#, you run into its lack of support for branching inside monadic composition. Not only does a free monad look non-idiomatic in C#, but writing the 'programs' without good syntactic sugar for monads make this alternative even less compelling. To make matters worse, the boilerplate code you have to write in C# is positively ugly. As this article is a result of an experiment, I admit that I have no production experience with free monads as Visitors in C#. Still, due to the lack of type inference in crucial parts, I'd venture the guess that the implementation would also prove to be frustratingly refactor-resistant. + In C#, you run into its lack of support for branching inside monadic composition. Not only does a free monad look non-idiomatic in C#, but writing the 'programs' without good syntactic sugar for monads make this alternative even less compelling. To make matters worse, the boilerplate code you have to write in C# is positively ugly. As this article is a result of an experiment, I admit that I have no production experience with free monads as Visitors in C#. Still, due to the lack of type inference in crucial parts, I'd venture the guess that the implementation would also prove to be frustratingly refactor-resistant.

    Perhaps, one day, you'll run into an edge case where you have a dependency that could benefit from being refactored to a Visitor, but in general, I'd presume that Dependency Injection in C# is the lesser of two evils. Still, I think it's interesting, and illustrative, that it's possible to refactor an injected dependency to a free monad - even in C#!

    - Next: Flattening arrow code using a stack of monads. + Next: Flattening arrow code using a stack of monads.

    \ No newline at end of file diff --git a/_posts/2018-07-30-flattening-arrow-code-using-a-stack-of-monads.html b/_posts/2018-07-30-flattening-arrow-code-using-a-stack-of-monads.html index 3f1aa6f70..8a1572295 100644 --- a/_posts/2018-07-30-flattening-arrow-code-using-a-stack-of-monads.html +++ b/_posts/2018-07-30-flattening-arrow-code-using-a-stack-of-monads.html @@ -12,7 +12,7 @@ {{ page.description }}

    - In the previous article, you saw how to refactor an injected dependency to a Visitor that implements a free monad. One remaining problem is that some of the code tends towards the Arrow anti-pattern. In this article, you'll see how elegantly you can deal with this in Haskell, how it translates to slightly more verbose F# code, but how, even though it does translate all the way to C#, it stops being nice along the way. + In the previous article, you saw how to refactor an injected dependency to a Visitor that implements a free monad. One remaining problem is that some of the code tends towards the Arrow anti-pattern. In this article, you'll see how elegantly you can deal with this in Haskell, how it translates to slightly more verbose F# code, but how, even though it does translate all the way to C#, it stops being nice along the way.

    All code for this article is available on GitHub. @@ -198,7 +198,7 @@

    Can you do the same in C#? Yes, sort of, but it'll be ugly.

    - As a first step, you'll need a Maybe monad, as this isn't a built-in type in C#. While I'd typically prefer a simpler implementation, since we're already looking at Church-encoded sum types, let's take the Church-encoded Maybe implementation, and refactor it to a Visitor. The IMaybe<T> interface is simply this: + As a first step, you'll need a Maybe monad, as this isn't a built-in type in C#. While I'd typically prefer a simpler implementation, since we're already looking at Church-encoded sum types, let's take the Church-encoded Maybe implementation, and refactor it to a Visitor. The IMaybe<T> interface is simply this:

    public interface IMaybe<T>
    @@ -396,7 +396,7 @@ 

    }

    - This is simply the 'sugared' version of the previous code. It's a little more succinct, but whether it's better is subjective at best. I think you'd be challenged to find anyone who'd consider this idiomatic C# code. + This is simply the 'sugared' version of the previous code. It's a little more succinct, but whether it's better is subjective at best. I think you'd be challenged to find anyone who'd consider this idiomatic C# code.

    It gets the job done, though. It actually works! diff --git a/_posts/2018-08-06-a-tree-functor.html b/_posts/2018-08-06-a-tree-functor.html index b404d5260..08102fa11 100644 --- a/_posts/2018-08-06-a-tree-functor.html +++ b/_posts/2018-08-06-a-tree-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. In a previous article, you saw how to implement the Maybe functor in C#. In this article, you'll get another functor example: a generalised tree (also known as a rose tree). + This article is an instalment in an article series about functors. In a previous article, you saw how to implement the Maybe functor in C#. In this article, you'll get another functor example: a generalised tree (also known as a rose tree).

    As opposed to a binary tree, any node in a generalised tree can have an arbitrary number of children, including none. @@ -299,7 +299,7 @@

    }

    - Here, I chose to implement the identity function as an anonymous lambda expression. In contrast, in the previous article, I explicitly declared a function variable and called it id. Those two ways to express the identity function are equivalent. + Here, I chose to implement the identity function as an anonymous lambda expression. In contrast, in the previous article, I explicitly declared a function variable and called it id. Those two ways to express the identity function are equivalent.

    As always, I'd like to emphasise that this test doesn't prove that Tree<T> obeys the first functor law. It only demonstrates that the law holds for those five examples. @@ -336,6 +336,6 @@

    The purpose of this article series is to show enough examples of functors that you should start to see a pattern. Keep in mind, though, that a functor isn't a design pattern. It's a mathematical concept.

    - Next: A Visitor functor. + Next: A Visitor functor.

    \ No newline at end of file diff --git a/_posts/2018-08-13-a-visitor-functor.html b/_posts/2018-08-13-a-visitor-functor.html index 95767e894..a0f22dc85 100644 --- a/_posts/2018-08-13-a-visitor-functor.html +++ b/_posts/2018-08-13-a-visitor-functor.html @@ -12,10 +12,10 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. In the previous article, you saw how to implement a generalised tree as a functor. In this article, you'll see another functor example, which will also be an application of the Visitor design pattern. + This article is an instalment in an article series about functors. In the previous article, you saw how to implement a generalised tree as a functor. In this article, you'll see another functor example, which will also be an application of the Visitor design pattern.

    - The Visitor design pattern is often described in such a way that it's based on mutation; the Visit and Accept methods in those descriptions typically return void. You can, however, also implement immutable variations. This blog already contains an older example of this. + The Visitor design pattern is often described in such a way that it's based on mutation; the Visit and Accept methods in those descriptions typically return void. You can, however, also implement immutable variations. This blog already contains an older example of this.

    Visitor # @@ -30,7 +30,7 @@

    }

    - As promised, this interface implies an immutable variant where the Accept method doesn't mutate the input Visitor, but rather returns a new value. You can learn how you arrive at this particular generic method signature in my article Visitor as a sum type. + As promised, this interface implies an immutable variant where the Accept method doesn't mutate the input Visitor, but rather returns a new value. You can learn how you arrive at this particular generic method signature in my article Visitor as a sum type.

    A full binary tree is a tree where each node has either zero or two children. This means that a Visitor must have two methods, one for each case: @@ -165,7 +165,7 @@

    Since IBinaryTree<T> is a generic type, you should consider whether it's a functor. Given the overall topic of this article, you'd hardly be surprised that it is.

    - In the previous two functor examples (Maybe and Tree), the Select methods were instance methods. On the other hand, the .NET Base Class Library implements IEnumerable<T>.Select as an extension method. You can do the same with this binary tree Visitor: + In the previous two functor examples (Maybe and Tree), the Select methods were instance methods. On the other hand, the .NET Base Class Library implements IEnumerable<T>.Select as an extension method. You can do the same with this binary tree Visitor:

    public static IBinaryTree<TResult> Select<TResultT>(
    @@ -422,7 +422,7 @@ 

    }

    - Here, I chose to implement the identity function as an anonymous lambda expression. In contrast, in a previous article, I explicitly declared a function variable and called it id. Those two ways to express the identity function are equivalent. + Here, I chose to implement the identity function as an anonymous lambda expression. In contrast, in a previous article, I explicitly declared a function variable and called it id. Those two ways to express the identity function are equivalent.

    As always, I'd like to emphasise that this test doesn't prove that IBinaryTree<T> obeys the first functor law. It only demonstrates that the law holds for those five examples. @@ -453,12 +453,12 @@

    Summary #

    - Statically typed functional languages like F# and Haskell enable you to define sum types: types that encode a selection of mutually exclusive cases. Combined with pattern matching, it's easy to deal with values that can be one of several non-polymorphic cases. Object-oriented languages like C# or Java don't have good support for this type of data structure. Object-oriented programmers often resort to using type hierarchies, but this requires down-casting in order to work. It also comes with the disadvantage that with type hierarchies, the hierarchy is extensible, which means that as an implementer, you never know if you've handled all sub-types. The Visitor design pattern is a way to model sum types in object-oriented programming, although it tends to be verbose. + Statically typed functional languages like F# and Haskell enable you to define sum types: types that encode a selection of mutually exclusive cases. Combined with pattern matching, it's easy to deal with values that can be one of several non-polymorphic cases. Object-oriented languages like C# or Java don't have good support for this type of data structure. Object-oriented programmers often resort to using type hierarchies, but this requires down-casting in order to work. It also comes with the disadvantage that with type hierarchies, the hierarchy is extensible, which means that as an implementer, you never know if you've handled all sub-types. The Visitor design pattern is a way to model sum types in object-oriented programming, although it tends to be verbose.

    Nevertheless, if you have a generic type that models a set of mutually exclusive cases, it just may be a functor. In Haskell, you can make such a type a Functor with a mere declaration. In C#, you have to write considerable amounts of code.

    - Next: Reactive functor. + Next: Reactive functor.

    \ No newline at end of file diff --git a/_posts/2018-08-20-reactive-functor.html b/_posts/2018-08-20-reactive-functor.html index 5880569b3..dacb0cec5 100644 --- a/_posts/2018-08-20-reactive-functor.html +++ b/_posts/2018-08-20-reactive-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. While the previous articles showed, in great detail, how to turn various classes into functors, this article mostly serves as a place-holder. The purpose is only to point out that you don't have to create all functors yourself. Sometimes, they come as part of a reusable library. + This article is an instalment in an article series about functors. While the previous articles showed, in great detail, how to turn various classes into functors, this article mostly serves as a place-holder. The purpose is only to point out that you don't have to create all functors yourself. Sometimes, they come as part of a reusable library.

    Rx is such a library, and IObservable<T> is a functor. (It's also a monad, but this is not a monad tutorial; it's a functor tutorial.) Reactive Extensions define a Select method for IObservable<T>, so if source is an IObservable<int>, you can translate it to IObservable<string> like this: @@ -65,7 +65,7 @@

    }

    - Here, I chose to implement the identity function as an anonymous lambda expression. In contrast, in a previous article, I explicitly declared a function variable and called it id. Those two ways to express the identity function are equivalent. + Here, I chose to implement the identity function as an anonymous lambda expression. In contrast, in a previous article, I explicitly declared a function variable and called it id. Those two ways to express the identity function are equivalent.

    As always, I'd like to emphasise that this test doesn't prove that IObservable<T> obeys the first functor law. It only demonstrates that the law holds for those six examples. @@ -110,6 +110,6 @@

    The point of this article is mostly that functors are commonplace. While you may discover them in your own code, they may also come in a reusable library. If you already know C# LINQ based off IEnumerable<T>, much of Rx will be easy for you to learn. After all, it's the same abstraction, and familiar abstractions make code readable.

    - Next: The Identity functor. + Next: The Identity functor.

    \ No newline at end of file diff --git a/_posts/2018-08-27-on-constructor-over-injection.html b/_posts/2018-08-27-on-constructor-over-injection.html index 7cd15187b..7835f18ef 100644 --- a/_posts/2018-08-27-on-constructor-over-injection.html +++ b/_posts/2018-08-27-on-constructor-over-injection.html @@ -12,7 +12,7 @@ {{ page.description }}

    - Sometimes, people struggle with how to deal with the Constructor Over-injection code smell. Often, you can address it by refactoring to Facade Services. This is possible when constructor arguments fall in two or more natural clusters. Sometimes, however, that isn't possible. + Sometimes, people struggle with how to deal with the Constructor Over-injection code smell. Often, you can address it by refactoring to Facade Services. This is possible when constructor arguments fall in two or more natural clusters. Sometimes, however, that isn't possible.

    Cross-cutting concerns # diff --git a/_posts/2018-09-03-the-identity-functor.html b/_posts/2018-09-03-the-identity-functor.html index 5a9a44aad..3274fbf7b 100644 --- a/_posts/2018-09-03-the-identity-functor.html +++ b/_posts/2018-09-03-the-identity-functor.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. In previous articles, you've learned about useful functors such as Maybe. In this article, you'll learn about a (practically) useless functor called Identity. You can skip this article if you want. + This article is an instalment in an article series about functors. In previous articles, you've learned about useful functors such as Maybe. In this article, you'll learn about a (practically) useless functor called Identity. You can skip this article if you want.

    If Identity is useless, then why bother?

    - The inutility of Identity doesn't mean that it doesn't exist. The Identity functor exists, whether it's useful or not. You can ignore it, but it still exists. In C# or F# I've never had any use for it (although I've described it before), while it turns out to be occasionally useful in Haskell, where it's built-in. The value of Identity is language-dependent. + The inutility of Identity doesn't mean that it doesn't exist. The Identity functor exists, whether it's useful or not. You can ignore it, but it still exists. In C# or F# I've never had any use for it (although I've described it before), while it turns out to be occasionally useful in Haskell, where it's built-in. The value of Identity is language-dependent.

    You may still derive value from this article. My motivation for writing it is to add another example to the set of functor examples presented in this article series. By presenting a varied selection of functors, it's my hope that you, from examples, gain insight. @@ -171,6 +171,6 @@

    The point of this article was only to identify the existence of the Identity functor, and to perhaps illustrate that the concept of a functor encompasses various data structures and behaviours.

    - Next: The Lazy functor. + Next: The Lazy functor.

    \ No newline at end of file diff --git a/_posts/2018-09-10-the-lazy-functor.html b/_posts/2018-09-10-the-lazy-functor.html index 974ef22dc..0e7a99953 100644 --- a/_posts/2018-09-10-the-lazy-functor.html +++ b/_posts/2018-09-10-the-lazy-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. Previous articles have covered Maybe, rose trees, and other functors. This article provides another example. + This article is an instalment in an article series about functors. Previous articles have covered Maybe, rose trees, and other functors. This article provides another example.

    Most programming languages are eagerly evaluated. Sometimes, however, you'd like to defer execution of an expensive operation. On .NET, you can use Lazy<T> to achieve that goal. This generic type, like so many others, forms a functor. @@ -132,7 +132,7 @@

    Unlinke C#, F#, and most other programming languages, Haskell is lazily evaluated. All values, whether scalar or complex, are lazy by default. For that reason, there's no explicit Lazy type in Haskell.

    - Haskell values are, in themselves, not functors, but you can put any value into the Identity functor. Since all values are already lazy, you could view Identity as Haskell's Lazy functor. + Haskell values are, in themselves, not functors, but you can put any value into the Identity functor. Since all values are already lazy, you could view Identity as Haskell's Lazy functor.

    The equivalence is only partial, however. .NET Lazy objects are small state machines. Before you've forced evaluation, they carry around the expression to be evaluated. Once you've evaluated the value once, Lazy objects effectively replace the lazy expression with its result. Thus, the next time you access the Value property, you immediately receive the result. @@ -147,6 +147,6 @@

    In languages with eager evaluation (which is most of them), you can model deferred executation as a functor. This enables you to compose lazily evaluated expressions piecemeal.

    - Next: Asynchronous functors. + Next: Asynchronous functors.

    \ No newline at end of file diff --git a/_posts/2018-09-17-typing-is-not-a-programming-bottleneck.html b/_posts/2018-09-17-typing-is-not-a-programming-bottleneck.html index f53997a00..f82c86662 100644 --- a/_posts/2018-09-17-typing-is-not-a-programming-bottleneck.html +++ b/_posts/2018-09-17-typing-is-not-a-programming-bottleneck.html @@ -12,7 +12,7 @@ {{ page.description }}

    - I sometimes give programming advice to people. They approach me with a software design problem, and, to the best of my ability, I suggest a remedy. Despite my best intentions, my suggestions sometimes meet resistance. One common reaction is that my suggestion isn't idiomatic, but recently, another type of criticism seems to be on the rise. + I sometimes give programming advice to people. They approach me with a software design problem, and, to the best of my ability, I suggest a remedy. Despite my best intentions, my suggestions sometimes meet resistance. One common reaction is that my suggestion isn't idiomatic, but recently, another type of criticism seems to be on the rise.

    The code that I suggest is too verbose. It involves too much typing. @@ -72,13 +72,13 @@

    Is more code worse? #

    - I tend to get drawn into these discussions from time to time, but good programming has little to do with how fast you can produce lines of code. + I tend to get drawn into these discussions from time to time, but good programming has little to do with how fast you can produce lines of code.

    To be clear, I entirely accept that statement completion, refactoring support, and such are, in general, benign features. While I spend most of my programming time thinking and reading, I also tend to write code in bursts. The average count of lines per hour may not be great, but that's because averages smooth out the hills and the valleys of my activity.

    - Still, increasingly frequent objection to some of my suggestions is that what I suggest implies 'too much' code. Recently, for example, I had to defend the merits of the Fluent Builder pattern that I suggest in my DI-Friendly Library article. + Still, increasingly frequent objection to some of my suggestions is that what I suggest implies 'too much' code. Recently, for example, I had to defend the merits of the Fluent Builder pattern that I suggest in my DI-Friendly Library article.

    As another example, consider two alternatives for modelling a restaurant reservation. First, here's a terse option: @@ -180,7 +180,7 @@

    Which alternative is better? The short version is eight lines of code, including the curly brackets. The longer version is 78 lines of code. That's ten times as much.

    - I prefer the longer version. While it takes longer to type, it comes with several benefits. The main benefit is that because it's immutable, it can have structural equality. This makes it trivial to compare objects, which, for example, is something you do all the time in unit test assertions. Another benefit is that such Value Objects make better domain models. The above Reservation Value Object only shows the slightest sign of emerging domain logic in the Accept method, but once you start modelling like this, such objects seem to attract more domain behaviour. + I prefer the longer version. While it takes longer to type, it comes with several benefits. The main benefit is that because it's immutable, it can have structural equality. This makes it trivial to compare objects, which, for example, is something you do all the time in unit test assertions. Another benefit is that such Value Objects make better domain models. The above Reservation Value Object only shows the slightest sign of emerging domain logic in the Accept method, but once you start modelling like this, such objects seem to attract more domain behaviour.

    Maintenance burden # @@ -256,7 +256,7 @@

    - +

    James, thank you for writing. I agree that being able to type out your thoughts as fast as possible lowers the barrier between your brain and whatever medium you're working in. I had something similar in mind when I wrote diff --git a/_posts/2018-09-24-asynchronous-functors.html b/_posts/2018-09-24-asynchronous-functors.html index 003050917..b72903562 100644 --- a/_posts/2018-09-24-asynchronous-functors.html +++ b/_posts/2018-09-24-asynchronous-functors.html @@ -14,10 +14,10 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. The previous article covered the Lazy functor. In this article, you'll learn about closely related functors: .NET Tasks and F# asynchronous workflows. + This article is an instalment in an article series about functors. The previous article covered the Lazy functor. In this article, you'll learn about closely related functors: .NET Tasks and F# asynchronous workflows.

    - A word of warning is in order. .NET Tasks aren't referentially transparent, whereas F# asynchronous computations are. You could argue, then, that .NET Tasks aren't proper functors, but you mostly observe the difference when you perform impure operations. As a general observation, when impure operations are allowed, the conclusions of this overall article series are precarious. We can't radically change how the .NET languages work, so we'll have to soldier on, pretending that impure operations are delegated to other parts of our system. Under this undue assumption, we can pretend that Task<T> forms a functor. + A word of warning is in order. .NET Tasks aren't referentially transparent, whereas F# asynchronous computations are. You could argue, then, that .NET Tasks aren't proper functors, but you mostly observe the difference when you perform impure operations. As a general observation, when impure operations are allowed, the conclusions of this overall article series are precarious. We can't radically change how the .NET languages work, so we'll have to soldier on, pretending that impure operations are delegated to other parts of our system. Under this undue assumption, we can pretend that Task<T> forms a functor.

    Task functor # @@ -49,7 +49,7 @@

    Task<string> y = from i in x select i.ToString();

    - In both cases, you start with a Task<int> which you map into a Task<string>. Perhaps you've noticed that these two examples closely resemble the equivalent Lazy functor examples. The resemblance isn't coincidental. The same abstraction is in use in both places. This is the functor abstraction. That's what this article series is all about, after all. + In both cases, you start with a Task<int> which you map into a Task<string>. Perhaps you've noticed that these two examples closely resemble the equivalent Lazy functor examples. The resemblance isn't coincidental. The same abstraction is in use in both places. This is the functor abstraction. That's what this article series is all about, after all.

    The difference between the Task functor and the Lazy functor is that lazy computations don't run until forced. Tasks, on the other hand, typically start running in the background when created. Thus, when you finally await the value, you may actually not have to wait for it. This does, however, depend on how you created the initial task. @@ -180,7 +180,7 @@

    {{ page.image_alt }}

    - There's performance implications of going back and forth between Task<T> and Async<'a>, but there's no loss of information. You can, therefore, consider these to representations of asynchronous computations isomorphic. + There's performance implications of going back and forth between Task<T> and Async<'a>, but there's no loss of information. You can, therefore, consider these to representations of asynchronous computations isomorphic.

    Summary # @@ -189,6 +189,6 @@

    Whether you do asynchronous programming with Task<T> or Async<'a>, asynchronous computations form functors. This enables you to piecemeal compose asynchronous workflows.

    - Next: Set is not a functor. + Next: Set is not a functor.

    \ No newline at end of file diff --git a/_posts/2018-10-01-applicative-functors.html b/_posts/2018-10-01-applicative-functors.html index abe6fc46d..b5a5d4975 100644 --- a/_posts/2018-10-01-applicative-functors.html +++ b/_posts/2018-10-01-applicative-functors.html @@ -12,10 +12,10 @@ {{ page.description }}

    - This article series is part of a larger series of articles about functors, applicatives, and other mappable containers. + This article series is part of a larger series of articles about functors, applicatives, and other mappable containers.

    - In a former article series, you learned about functors, and how they also exist in object-oriented design. Perhaps the utility of this still eludes you, although, if you've ever had experience with LINQ in C#, you should realise that the abstraction is invaluable. Functors are abundant; applicative functors not quite so much. On the other hand, applicative functors enable you to do more. + In a former article series, you learned about functors, and how they also exist in object-oriented design. Perhaps the utility of this still eludes you, although, if you've ever had experience with LINQ in C#, you should realise that the abstraction is invaluable. Functors are abundant; applicative functors not quite so much. On the other hand, applicative functors enable you to do more.

    I find it helpful to think of applicative functors as an abstraction that enable you to express combinations of things. @@ -23,14 +23,14 @@

    In the functor article series, I mostly focused on the mechanics of implementation. In this article series, I think that you'll find it helpful to slightly change the perspective. In these articles, I'll show you various motivating examples of how applicative functors are useful.

    You should consider reading one or more of these articles before continuing the present article.

    @@ -111,6 +111,6 @@

    This article only attempts to provide an overview of applicative functors, while examples are given in linked articles. I find it helpful to think of applicative functors as an abstraction that enables you to model arbitrary combinations of objects. This is a core feature in Haskell, occasionally useful in F#, and somewhat alien to C#.

    - Next: Full deck. + Next: Full deck.

    \ No newline at end of file diff --git a/_posts/2018-10-08-full-deck.html b/_posts/2018-10-08-full-deck.html index 5cd2a8936..a41c771aa 100644 --- a/_posts/2018-10-08-full-deck.html +++ b/_posts/2018-10-08-full-deck.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors. While (non-applicative) functors can be translated to an object-oriented language like C# in a straightforward manner, applicative functors are more entrenched in functional languages like Haskell. This article introduces the concept with a motivating example in Haskell, and also shows a translation to F#. In the next article, you'll also see how to implement an applicative functor in C#. + This article is an instalment in an article series about applicative functors. While (non-applicative) functors can be translated to an object-oriented language like C# in a straightforward manner, applicative functors are more entrenched in functional languages like Haskell. This article introduces the concept with a motivating example in Haskell, and also shows a translation to F#. In the next article, you'll also see how to implement an applicative functor in C#.

    Deck of cards in Haskell # @@ -169,7 +169,7 @@

    While the mechanics of applicative functors translate well to F#, it leaves you with at least one problem. If you add the above operator <*>, you've now 'used up' that operator for lists. While you can define an operator of the same name for e.g. option, you'd have to put them in separate modules or namespaces in order to prevent them from colliding. This also means that you can't easily use them together.

    - For that reason, I wouldn't consider this the most idiomatic way to create a full deck of cards in F#. Normally, I'd do this instead: + For that reason, I wouldn't consider this the most idiomatic way to create a full deck of cards in F#. Normally, I'd do this instead:

    // Card list
    @@ -198,6 +198,6 @@ 

    The next article in the series shows another list example. The F# and Haskell code will be similar to the code in the present article, but the next article will also include a translation to C#.

    - Next: An applicative password list. + Next: An applicative password list.

    \ No newline at end of file diff --git a/_posts/2018-10-15-an-applicative-password-list.html b/_posts/2018-10-15-an-applicative-password-list.html index f6da02d7b..1c51bfa11 100644 --- a/_posts/2018-10-15-an-applicative-password-list.html +++ b/_posts/2018-10-15-an-applicative-password-list.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors. In the previous article, you saw how to use Haskell and F# lists as applicative functors to generate combinations of values. In this article, you'll see a similar example, but this time, there will also be a C# example. + This article is an instalment in an article series about applicative functors. In the previous article, you saw how to use Haskell and F# lists as applicative functors to generate combinations of values. In this article, you'll see a similar example, but this time, there will also be a C# example.

    Guess the password variation # @@ -222,7 +222,7 @@

    There's still an aspect of using lists and sequences as applicative functors that I've been deliberately ignoring so far. The next article covers that. After that, we'll take a break from lists and look at some other applicative functors.

    - Next: Applicative combinations of functions. + Next: Applicative combinations of functions.

    @@ -260,7 +260,7 @@

    - +

    Tyson, thank you for writing. Yes, you're right that it's the lack of default currying that makes this sort of style less than ideal in C#. This seems to be clearly demonstrated by your example. diff --git a/_posts/2018-10-22-applicative-combinations-of-functions.html b/_posts/2018-10-22-applicative-combinations-of-functions.html index 23d7d6920..11f555699 100644 --- a/_posts/2018-10-22-applicative-combinations-of-functions.html +++ b/_posts/2018-10-22-applicative-combinations-of-functions.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors. In the previous article, you saw how you can use applicative lists and sequences to generate combinations of values; specifically, the example demonstrated how to generate various password character combinations. + This article is an instalment in an article series about applicative functors. In the previous article, you saw how you can use applicative lists and sequences to generate combinations of values; specifically, the example demonstrated how to generate various password character combinations.

    People often create passwords by using a common word as basis, and then turn characters into upper- or lower case. Someone feeling particularly tech-savvy may replace certain characters with digits, in an imitation of 1337. While this isn't secure, let's look at how to create various combinations of transformations using applicative lists and sequences. @@ -95,10 +95,10 @@

        <*> ["P""p"] <*> ["a""4"] <*> ["ssw"] <*> ["o""0"] <*> ["rd"] <*> ["""!"]

    - Notice that the last list contains two options: "!" and the empty string (""). You can read about this in another article series, but character strings are monoids, and one of the characteristics of monoids is that they have an identity element - a 'neutral' element, if you will. For strings, it's ""; you can append or prepend the empty string as much as you'd like, but it's not going to change the other string. + Notice that the last list contains two options: "!" and the empty string (""). You can read about this in another article series, but character strings are monoids, and one of the characteristics of monoids is that they have an identity element - a 'neutral' element, if you will. For strings, it's ""; you can append or prepend the empty string as much as you'd like, but it's not going to change the other string.

    - If you have a set of functions of the type 'a -> 'a, then the built-in function id is the identity element. You can compose any 'a -> 'a function with id, and it's not going to change the other function. + If you have a set of functions of the type 'a -> 'a, then the built-in function id is the identity element. You can compose any 'a -> 'a function with id, and it's not going to change the other function.

    Since functions are values, then, you can create combinations of functions: @@ -244,6 +244,6 @@

    The last three articles (including the present) focus on lists as applicative functors, but lists aren't the only type of applicative functor. In the next articles, you'll encounter some other applicative functors.

    - Next: The Maybe applicative functor. + Next: The Maybe applicative functor.

    \ No newline at end of file diff --git a/_posts/2018-10-29-the-maybe-applicative-functor.html b/_posts/2018-10-29-the-maybe-applicative-functor.html index ab059c4b1..67e8e7746 100644 --- a/_posts/2018-10-29-the-maybe-applicative-functor.html +++ b/_posts/2018-10-29-the-maybe-applicative-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors. Previously, in a related series, you got an introduction to Maybe as a functor. Not all functors are applicative, but some are, and Maybe is one of them (like list). + This article is an instalment in an article series about applicative functors. Previously, in a related series, you got an introduction to Maybe as a functor. Not all functors are applicative, but some are, and Maybe is one of them (like list).

    In this article, you'll see how to make a C# Maybe class applicative. While I'm going to start with F# and Haskell, you can skip to the C# section if you'd like. @@ -21,7 +21,7 @@

    F# #

    - A few years ago, I did the Roman numerals kata in F#. This is an exercise where you have to convert between normal base 10 integers and Roman numerals. Conversions can fail in both directions, because Roman numerals don't support negative numbers, zero, or numbers greater than 3,999, and Roman numerals represented as strings could be malformed. + A few years ago, I did the Roman numerals kata in F#. This is an exercise where you have to convert between normal base 10 integers and Roman numerals. Conversions can fail in both directions, because Roman numerals don't support negative numbers, zero, or numbers greater than 3,999, and Roman numerals represented as strings could be malformed.

    Some Roman numbers are written in a subtractive style, e.g. "IV" means subtract 1 (I) from 5 (V). It's easy enough to subtract two numbers, but because parsing isn't guaranteed to succeed, I didn't have two numbers; I had two number options (recall that in F#, Maybe is called option). @@ -103,7 +103,7 @@

    - For a detailed explanation on how that works, see the previous explanation for lists; it works the same way for Maybe as it does for List. + For a detailed explanation on how that works, see the previous explanation for lists; it works the same way for Maybe as it does for List.

    In the end, however, I didn't think that this was the most readable code, so in the Roman numeral exercise, I chose to use a computation expression instead. @@ -138,7 +138,7 @@

    C# #

    - In a previous article you saw how to implement the Maybe functor in C#. You can extend it so that it also becomes an applicative functor: + In a previous article you saw how to implement the Maybe functor in C#. You can extend it so that it also becomes an applicative functor:

    public static Maybe<TResult> Apply<TTResult>(
    @@ -165,7 +165,7 @@ 

    }

    - As was the case for making sequences applicative in C#, you need overloads of the Apply method, because C#'s type inference is inadequate for this task. + As was the case for making sequences applicative in C#, you need overloads of the Apply method, because C#'s type inference is inadequate for this task.

    If you have two Maybe<int> values, minuend and subtrahend, you can now perform the subtraction: @@ -193,7 +193,7 @@

    This article demonstrates that lists or sequences aren't the only applicative functors. Maybe is also an applicative functor, but more exist. The next article will give you another example.

    - Next: Applicative validation. + Next: Applicative validation.

    @@ -206,17 +206,17 @@

    Tyson Williams
    - As was the case for making sequences applicative in C#, you need overloads of the Apply method, because C#'s type inference is inadequate for this task. + As was the case for making sequences applicative in C#, you need overloads of the Apply method, because C#'s type inference is inadequate for this task.

    - I think we agreed that the issue is not C#'s weak type inference but its lack of default function currying? My guess is that you wrote this quoted part of this article before my comment on your previous article. + I think we agreed that the issue is not C#'s weak type inference but its lack of default function currying? My guess is that you wrote this quoted part of this article before my comment on your previous article.

    2018-11-06 02:44 UTC

    - +

    Tyson, thank you for writing. @@ -251,10 +251,10 @@

    I will expand my comment a bit to give a clearer picture of my understanding.

    - First, very little is "needed"; most things are merely sufficient. In particular, we don't need to overload your Apply method to achieve your goal. As I mentioned before, it sufficies to have a single Apply method and instead create overloads of a function called curry that explicitly curries a given function. Furthermore, I think there is a sense in which this latter approach to overcome the lack of default currying is somehow minimal or most abstract or most general. + First, very little is "needed"; most things are merely sufficient. In particular, we don't need to overload your Apply method to achieve your goal. As I mentioned before, it sufficies to have a single Apply method and instead create overloads of a function called curry that explicitly curries a given function. Furthermore, I think there is a sense in which this latter approach to overcome the lack of default currying is somehow minimal or most abstract or most general.

    - Second, compared to languages like F# or Haskell, type inference is definitely weaker in C#. This issue was also present (in a subtle way) in your previous article, but I decided to largely ignore it in order to keep my comment more focused. In your previous article, you expliciltly defined the local variable concat like this + Second, compared to languages like F# or Haskell, type inference is definitely weaker in C#. This issue was also present (in a subtle way) in your previous article, but I decided to largely ignore it in order to keep my comment more focused. In your previous article, you expliciltly defined the local variable concat like this

    Func<stringstringstringstringstringstringstring> concat =
         (x, y, z, æ, ø, å) => x + y + z + æ + ø + å;
    diff --git a/_posts/2018-11-05-applicative-validation.html b/_posts/2018-11-05-applicative-validation.html index e4e6c8f0f..0fac96187 100644 --- a/_posts/2018-11-05-applicative-validation.html +++ b/_posts/2018-11-05-applicative-validation.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors. It demonstrates how applicative style can be used to compose small validation functions to a larger validation function in such a way that no validation messages are lost, and the composition remains readable. + This article is an instalment in an article series about applicative functors. It demonstrates how applicative style can be used to compose small validation functions to a larger validation function in such a way that no validation messages are lost, and the composition remains readable.

    All example code in this article is given in Haskell. No F# translation is offered, because Scott Wlaschin has an equivalent example covering input validation in F#. @@ -213,7 +213,7 @@

    For all other cases, this instance of Applicative delegates to the behaviour defined for Either. It also uses pure from Either to implement its own pure function.

    - Lists ([]) form a monoid, and since all the above validation functions return lists of errors, it means that you can compose them using this definition of Applicative: + Lists ([]) form a monoid, and since all the above validation functions return lists of errors, it means that you can compose them using this definition of Applicative:

    validateReservation :: ReservationJson -> Validation [String] Reservation
    @@ -273,6 +273,6 @@ 

    More applicative functors exist. This article series has, I think, room for more examples.

    - Next: The Test Data Generator applicative functor. + Next: The Test Data Generator applicative functor.

    \ No newline at end of file diff --git a/_posts/2018-11-12-what-to-test-and-not-to-test.html b/_posts/2018-11-12-what-to-test-and-not-to-test.html index 224f2bb5b..eb53db3ee 100644 --- a/_posts/2018-11-12-what-to-test-and-not-to-test.html +++ b/_posts/2018-11-12-what-to-test-and-not-to-test.html @@ -14,7 +14,7 @@ {{ page.description }}

    - Some years ago, I, somewhat to my own surprise, found myself on the wrong side of a controversy about whether one should test trivial code. The context was a discussion about Test-Driven Development (TDD), and for reasons that I still stand behind today, I argued that you should test all code, including trivial code, such as property getters. + Some years ago, I, somewhat to my own surprise, found myself on the wrong side of a controversy about whether one should test trivial code. The context was a discussion about Test-Driven Development (TDD), and for reasons that I still stand behind today, I argued that you should test all code, including trivial code, such as property getters.

    Most of the 'TDD community' reacted quite negatively to that article, some in not-so-nice ways. Some people reacted, I believe, based on their dislike of the conclusion, without responding to my arguments. Others, however, gave reasoned rebuttals. When people like Derick Bailey and Mark Rendle disagree with me, in a reasoned matter, even, I consider that a good reason to revisit my thinking. @@ -41,7 +41,7 @@

    Watching the wildlife #

    - My context at that time was that I had some success with AutoFixture, an open source library, which is what I consider wildlife software. Once you've released a version of the software, you have no control of where it's installed, or how it's used. + My context at that time was that I had some success with AutoFixture, an open source library, which is what I consider wildlife software. Once you've released a version of the software, you have no control of where it's installed, or how it's used.

    This means that backwards compatibility becomes important. If I broke something, I would inconvenience the users of my software. Making sure that compatibility didn't break became one of my highest priorities. I used unit tests for regression tests, and I did, indeed, test the entire public API of AutoFixture, to make sure that no breaking changes were introduced. @@ -50,7 +50,7 @@

    That was my implicit context. Read in that light, my dogmatic insistence on testing everything hopefully makes a little more sense.

    - Does that mean that my conclusion transfers to other circumstances? No, of course it doesn't. If you're developing and maintaining zoo software, breaking changes are of less concern. From that perspective, my article could easily look like the creation of an unhinged mind. + Does that mean that my conclusion transfers to other circumstances? No, of course it doesn't. If you're developing and maintaining zoo software, breaking changes are of less concern. From that perspective, my article could easily look like the creation of an unhinged mind.

    The purpose of tests # @@ -59,13 +59,13 @@

    In order to figure out what to test, and what not to test, you should ask yourself the question: what's the purpose of testing?

    - At first glance, that may seem like an inane question, but there's actually more than one purpose of a unit test. When doing TDD, the purpose of a test is to provide feedback about the API you're developing. A unit test is the first client of the production API. If a test is difficult to write, the production API is difficult to use. More on TDD later, though. + At first glance, that may seem like an inane question, but there's actually more than one purpose of a unit test. When doing TDD, the purpose of a test is to provide feedback about the API you're developing. A unit test is the first client of the production API. If a test is difficult to write, the production API is difficult to use. More on TDD later, though.

    You may say that another purpose of automated tests is that they prevent errors. That's not the case, though. Automated tests prevent regressions.

    - If you wrote the correct test, your test suite may also help to prevent errors, but a unit test is only as good as the programmer who wrote it. You could have made a mistake when you wrote the test. Or perhaps you misunderstood the specification of what you were trying to implement. Why do you even trust tests? + If you wrote the correct test, your test suite may also help to prevent errors, but a unit test is only as good as the programmer who wrote it. You could have made a mistake when you wrote the test. Or perhaps you misunderstood the specification of what you were trying to implement. Why do you even trust tests?

    The cost of regressions # @@ -116,7 +116,7 @@

    How do you know that your software works? You test it. If you want to automate your testing efforts, you write unit tests... but a unit test suite is software. How do you know that your tests work? Is it going to be turtles all the way down?

    - I think that we can trust tests for other reasons, but one of them is that each test case exercises a deterministic path through a unit that supports many paths of execution. + I think that we can trust tests for other reasons, but one of them is that each test case exercises a deterministic path through a unit that supports many paths of execution.

    Diagram that shows a unit test exercising one path through a unit. @@ -201,7 +201,7 @@

    What's the purpose of tests? Are you using TDD to get feedback on your API design ideas? Or is the main purpose of tests to prevent regressions? Your answers to such questions should guide your decisions on how much to test.

    - Recently, I've mostly been writing about topics related to computer science, such as the relationships between various branches of mathematics to computation. In such realms, laws apply, and answers tend to be either right or wrong. A piece like this article is different. + Recently, I've mostly been writing about topics related to computer science, such as the relationships between various branches of mathematics to computation. In such realms, laws apply, and answers tend to be either right or wrong. A piece like this article is different.

    This is fundamentally a deeply subjective essay. It's based on my experience with writing automated tests in various circumstances since 2003. I've tried to be as explicit about my context as possible, but I've most likely failed to identify one or more implicit assumptions or biases. I do, therefore, encourage comments. diff --git a/_posts/2018-11-19-functional-architecture-a-definition.html b/_posts/2018-11-19-functional-architecture-a-definition.html index 43b9cc92a..135977346 100644 --- a/_posts/2018-11-19-functional-architecture-a-definition.html +++ b/_posts/2018-11-19-functional-architecture-a-definition.html @@ -14,7 +14,7 @@ {{ page.description }}

    - Over the years, I've written articles on functional architecture, including Functional architecture is Ports and Adapters, given conference talks, and even produced a Pluralsight course on the topic. How should we define functional architecture, though? + Over the years, I've written articles on functional architecture, including Functional architecture is Ports and Adapters, given conference talks, and even produced a Pluralsight course on the topic. How should we define functional architecture, though?

    People sometimes ask me about their F# code: How do I know that my F# code is functional? @@ -183,7 +183,7 @@

    Clearly, you can trivially obey the functional interaction law by writing exclusively impure code. In a sense, this is what you do by default in imperative programming languages. If you're familiar with Haskell, imagine writing an entire program in IO. That would be possible, but pointless.

    - Thus, we need to add the qualifier that a significant part of the code base should consist of pure code. How much? The more, the better. Subjectively, I'd say significantly more than half the code base should be pure. I'm concerned, though, that stating a hard limit is as useful here as it is for code coverage. + Thus, we need to add the qualifier that a significant part of the code base should consist of pure code. How much? The more, the better. Subjectively, I'd say significantly more than half the code base should be pure. I'm concerned, though, that stating a hard limit is as useful here as it is for code coverage.

    Tooling # @@ -238,7 +238,7 @@

    Haskell enforces the functional interaction law via its IO type. You can't use an IO value from within a pure function (a function that doesn't return IO). If you try, your code doesn't compile.

    - I've personally used Haskell repeatedly to understand the limits of functional architecture, for example to establish that Dependency Injection isn't functional because it makes everything impure. + I've personally used Haskell repeatedly to understand the limits of functional architecture, for example to establish that Dependency Injection isn't functional because it makes everything impure.

    The overall lack of tooling, however, may make people uncomfortable, because it means that most so-called functional languages (e.g. F#, Erlang, Elixir, and Clojure) offer no support for validating or enforcing functional architecture. @@ -284,7 +284,7 @@

    Comments

    - +

    Max, thank you for writing. I'm not sure whether the assertion that it has to be some design or other is axiomatically obvious, but I suppose that we humans have an innate need to categorise things. @@ -337,10 +337,10 @@

    Comments

    - +

    - Marcin, thank you for writing. To be clear, you can perform side effects or non-deterministic behaviour in C# delegates, so delegates aren't guaranteed to be referentially transparent. In fact, delegates, and particularly closures, are isomorphic to objects. In C#, they even compile to classes. + Marcin, thank you for writing. To be clear, you can perform side effects or non-deterministic behaviour in C# delegates, so delegates aren't guaranteed to be referentially transparent. In fact, delegates, and particularly closures, are isomorphic to objects. In C#, they even compile to classes.

    I'm aware that some people think that they're doing functional programming when they use lambda expressions in C#, but I disagree. @@ -352,19 +352,19 @@

    Re: 1. #

    - Some functions are certainly ad-hoc, while others are grounded in mathematics. I agree that pure functions 'fit better in your brain', mostly because it's clear that the only stimuli that can affect the outcome of the function is the input. Granted, if we imagine a concrete, ad-hoc function that takes 23 function arguments, we might still consider it bad code. Small functions, though, tend to be easy to reason about. + Some functions are certainly ad-hoc, while others are grounded in mathematics. I agree that pure functions 'fit better in your brain', mostly because it's clear that the only stimuli that can affect the outcome of the function is the input. Granted, if we imagine a concrete, ad-hoc function that takes 23 function arguments, we might still consider it bad code. Small functions, though, tend to be easy to reason about.

    - I've previously written about the relationship between types and tests, and I believe that there's some sort of linearity in that relationship. The better the type system, the fewer tests you need. The weaker the type system, the more tests you need. It's no wonder that the unit testing culture related to languages like Ruby seems stronger than in the Haskell community. + I've previously written about the relationship between types and tests, and I believe that there's some sort of linearity in that relationship. The better the type system, the fewer tests you need. The weaker the type system, the more tests you need. It's no wonder that the unit testing culture related to languages like Ruby seems stronger than in the Haskell community.

    Re: 2. #

    - In my experience, most people make legacy code more testable by introducing some variation of Dependency Injection. This may enable you to control some otherwise non-deterministic behaviour from tests, but it doesn't make the design more functional. Those types of dependencies (e.g. on DateTime.Now) are inherently impure, and therefore they make everything that invokes them impure as well. The above functional interaction law excludes such a design from being considered functional. + In my experience, most people make legacy code more testable by introducing some variation of Dependency Injection. This may enable you to control some otherwise non-deterministic behaviour from tests, but it doesn't make the design more functional. Those types of dependencies (e.g. on DateTime.Now) are inherently impure, and therefore they make everything that invokes them impure as well. The above functional interaction law excludes such a design from being considered functional.

    - Functional code, on the other hand, is intrinsically testable. Watch out for a future series of articles that show how to move an object-oriented architecture towards something both more functional, more sustainable, and more testable. + Functional code, on the other hand, is intrinsically testable. Watch out for a future series of articles that show how to move an object-oriented architecture towards something both more functional, more sustainable, and more testable.

    Re: 3. # @@ -376,7 +376,7 @@

  • run some pure functions,
  • output the results to some impure destinations, such as files, databases, UI, email, and so on.
  • - I call this type of architecture a pure-impure-pure sandwich, and you can often, but not always, structure your application code in that way. + I call this type of architecture a pure-impure-pure sandwich, and you can often, but not always, structure your application code in that way.

    Re: 4. # diff --git a/_posts/2018-11-26-the-test-data-generator-applicative-functor.html b/_posts/2018-11-26-the-test-data-generator-applicative-functor.html index 3b7a593f4..a1e1735b7 100644 --- a/_posts/2018-11-26-the-test-data-generator-applicative-functor.html +++ b/_posts/2018-11-26-the-test-data-generator-applicative-functor.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors. It shows yet another example of an applicative functor. I tend to think of applicative functors as an abstraction of 'combinations' of values and functions, but this is most evident for lists and other collections. Even so, I think that the intuition also holds for Maybe as an applicative functor as well as validation as an applicative functor. This is also the case for the Test Data Generator functor. + This article is an instalment in an article series about applicative functors. It shows yet another example of an applicative functor. I tend to think of applicative functors as an abstraction of 'combinations' of values and functions, but this is most evident for lists and other collections. Even so, I think that the intuition also holds for Maybe as an applicative functor as well as validation as an applicative functor. This is also the case for the Test Data Generator functor.

    Applicative generator in C# #

    - In a previous article, you saw how to implement a Test Data Generator as a functor in C#. The core class is this Generator<T> class: + In a previous article, you saw how to implement a Test Data Generator as a functor in C#. The core class is this Generator<T> class:

    public class Generator<T>
    @@ -158,7 +158,7 @@ 

    }

    - You first define the three 'tainting' functions, and then create the tainters generator. Notice that this generator not only contains the three functions, but also combinations of these functions. I didn't include all possible combinations of functions, but in an earlier article, you saw how to do just that. + You first define the three 'tainting' functions, and then create the tainters generator. Notice that this generator not only contains the three functions, but also combinations of these functions. I didn't include all possible combinations of functions, but in an earlier article, you saw how to do just that.

    Gen.CprNumber is a Generator<CprNumber>, while you actually need a Generator<string>. Since Generator<T> is a functor, you can easily map Gen.CprNumber with its Select method. @@ -211,6 +211,6 @@

    While working on the Hedgehog example, I discovered another great use of option as an applicative functor. You can see this in the next article.

    - Next: Danish CPR numbers in F#. + Next: Danish CPR numbers in F#.

    \ No newline at end of file diff --git a/_posts/2018-12-03-set-is-not-a-functor.html b/_posts/2018-12-03-set-is-not-a-functor.html index bda2f3030..e039a4f8a 100644 --- a/_posts/2018-12-03-set-is-not-a-functor.html +++ b/_posts/2018-12-03-set-is-not-a-functor.html @@ -14,10 +14,10 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. The way functors are frequently presented to programmes is as a generic container (Foo<T>) equipped with a translation method, normally called map, but in C# idiomatically called Select. + This article is an instalment in an article series about functors. The way functors are frequently presented to programmes is as a generic container (Foo<T>) equipped with a translation method, normally called map, but in C# idiomatically called Select.

    - It'd be tempting to believe that any generic type with a Select method is a functor, but it takes more than that. The Select method must also obey the functor laws. This article shows an example of a translation that violates the second functor law. + It'd be tempting to believe that any generic type with a Select method is a functor, but it takes more than that. The Select method must also obey the functor laws. This article shows an example of a translation that violates the second functor law.

    Mapping sets # @@ -138,7 +138,7 @@

    This passing test provides the required counter-example. It first creates two ISO 8601 representations of the same instant. As the Guard Assertion demonstrates, the corresponding DateTimeOffset values are considered equal.

    - In the act phase, the test creates a set of these two strings. It then performs two round-trips over DateTimeOffset and back to string. The second functor law states that it shouldn't matter whether you do it in one or two steps, but it does. Assert.False passes because l is not equal to r. Q.E.D. + In the act phase, the test creates a set of these two strings. It then performs two round-trips over DateTimeOffset and back to string. The second functor law states that it shouldn't matter whether you do it in one or two steps, but it does. Assert.False passes because l is not equal to r. Q.E.D.

    An illustration # @@ -177,6 +177,6 @@

    The term functor originates from category theory, and I don't claim to be an expert on that topic. It's unclear to me if the underlying concept of equality is explicitly defined in category theory, but it wouldn't surprise me if it is. If that definition involves the substitution property, then the counter-example presented here says nothing about Set as a functor, but rather that DateTimeOffset has unlawful equality behaviour.

    - Next: Applicative functors. + Next: Applicative functors.

    \ No newline at end of file diff --git a/_posts/2018-12-10-danish-cpr-numbers-in-f.html b/_posts/2018-12-10-danish-cpr-numbers-in-f.html index ad53145d6..d762485f1 100644 --- a/_posts/2018-12-10-danish-cpr-numbers-in-f.html +++ b/_posts/2018-12-10-danish-cpr-numbers-in-f.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors, although the applicative functor example doesn't appear until towards the end. This article also serves the purpose of showing an example of Domain-Driven Design in F#. + This article is an instalment in an article series about applicative functors, although the applicative functor example doesn't appear until towards the end. This article also serves the purpose of showing an example of Domain-Driven Design in F#.

    Danish personal identification numbers #

    - As outlined in the previous article, in Denmark, everyone has a personal identification number, in Danish called CPR-nummer (CPR number). + As outlined in the previous article, in Denmark, everyone has a personal identification number, in Danish called CPR-nummer (CPR number).

    CPR numbers have a simple format: DDMMYY-SSSS, where the first six digits indicate a person's birth date, and the last four digits are a sequence number. Some information, however, is also embedded in the sequence number. An example could be 010203-1234, which indicates a woman born February 1, 1903. @@ -170,7 +170,7 @@

    Parsing CPR strings #

    - CPR numbers are often passed around as text, so you'll need to be able to parse a string representation. As described in the previous article, you should follow Postel's law. Input could include extra white space, and the middle dash could be missing. + CPR numbers are often passed around as text, so you'll need to be able to parse a string representation. As described in the previous article, you should follow Postel's law. Input could include extra white space, and the middle dash could be missing.

    The .NET Base Class Library contains enough utility methods working on string values that this isn't going to be particularly difficult. It can, however, be awkward to interoperate with object-oriented APIs, so you'll often benefit from adding a few utility functions that give you curried functions instead of objects with methods. Here's one that adapts Int32.TryParse: @@ -226,7 +226,7 @@

        |>  Option.bind id

    - The function starts by defining a private <*> operator. Readers of the applicative functor article series will recognise this as the 'apply' operator. The reason I added it as a private operator is that I don't need it anywhere else in the code base, and in F#, I'm always worried that if I add <*> at a more visible level, it could collide with other definitions of <*> - for example one for lists. This one particularly makes option an applicative functor. + The function starts by defining a private <*> operator. Readers of the applicative functor article series will recognise this as the 'apply' operator. The reason I added it as a private operator is that I don't need it anywhere else in the code base, and in F#, I'm always worried that if I add <*> at a more visible level, it could collide with other definitions of <*> - for example one for lists. This one particularly makes option an applicative functor.

    The first step in parsing candidate is to remove surrounding white space and the interior dash. @@ -238,7 +238,7 @@

    All four of these must be Some values before we can even start to attempt to turn them into a CprNumber value. If only a single value is None, tryParse should return None as well.

    - You may want to re-read the article on the List applicative functor for a detailed explanation of how the <*> operator works. In tryParse, you have four option values, so you apply them all using four <*> operators. Since four values are being applied, you'll need a function that takes four curried input arguments of the appropriate types. In this case, all four are int option values, so for the first expression in the <*> chain, you'll need an option of a function that takes four int arguments. + You may want to re-read the article on the List applicative functor for a detailed explanation of how the <*> operator works. In tryParse, you have four option values, so you apply them all using four <*> operators. Since four values are being applied, you'll need a function that takes four curried input arguments of the appropriate types. In this case, all four are int option values, so for the first expression in the <*> chain, you'll need an option of a function that takes four int arguments.

    Lo and behold! tryCreate takes four int arguments, so the only action you need to take is to make it an option by putting it in a Some case. @@ -273,7 +273,7 @@

    This article is an entry in the F# Advent Calendar in English 2018.

    - Next: The Lazy applicative functor. + Next: The Lazy applicative functor.

    @@ -296,16 +296,16 @@

    - +

    - Viktor, thank you for your kind words. The Result (or Either) type does, indeed, provide more information when things go wrong. This can be useful when client code needs to handle different error cases in different ways. Sometimes, it may also be useful, as you write, when you want to provide more helpful error messages. + Viktor, thank you for your kind words. The Result (or Either) type does, indeed, provide more information when things go wrong. This can be useful when client code needs to handle different error cases in different ways. Sometimes, it may also be useful, as you write, when you want to provide more helpful error messages.

    - Particularly when it comes to parsing or input validation, Either can be useful. + Particularly when it comes to parsing or input validation, Either can be useful.

    - The main reason I chose to model with option in this article was that I wanted to demonstrate how to use the applicative nature of option, but I suppose I could have equally done so with Result. + The main reason I chose to model with option in this article was that I wanted to demonstrate how to use the applicative nature of option, but I suppose I could have equally done so with Result.

    2018-12-18 9:09 UTC
    diff --git a/_posts/2018-12-17-the-lazy-applicative-functor.html b/_posts/2018-12-17-the-lazy-applicative-functor.html index 4f94f457d..186fa5548 100644 --- a/_posts/2018-12-17-the-lazy-applicative-functor.html +++ b/_posts/2018-12-17-the-lazy-applicative-functor.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is an instalment in an article series about applicative functors. A previous article has described how lazy computations form a functor. In this article, you'll see that lazy computations also form an applicative functor. + This article is an instalment in an article series about applicative functors. A previous article has described how lazy computations form a functor. In this article, you'll see that lazy computations also form an applicative functor.

    Apply #

    - As you have previously seen, C# isn't the best fit for the concept of applicative functors. Nevertheless, you can write an Apply extension method following the applicative 'code template': + As you have previously seen, C# isn't the best fit for the concept of applicative functors. Nevertheless, you can write an Apply extension method following the applicative 'code template':

    public static Lazy<TResult> Apply<TResultT>(
    @@ -99,7 +99,7 @@ 

        let apply (x : Lazy<_>) (f : Lazy<_>) = lazy f.Value x.Value

    - In this code listing, I've repeated the map function shown in a previous article. It's not required for the implementation of apply, but you'll see it in use shortly, so I thought it was convenient to include it in the listing. + In this code listing, I've repeated the map function shown in a previous article. It's not required for the implementation of apply, but you'll see it in use shortly, so I thought it was convenient to include it in the listing.

    If you belong to the camp of F# programmers who think that F# should emulate Haskell, you can also introduce an operator: @@ -108,7 +108,7 @@

    let (<*>) f x = Lazy.apply x f

    - Notice that this <*> operator simply flips the arguments of Lazy.apply. If you introduce such an operator, be aware that the admonition from the overview article still applies. In Haskell, the <*> operator applies to any Applicative, which makes it truly general. In F#, once you define an operator like this, it applies specifically to a particular container type, which, in this case, is Lazy<'a>. + Notice that this <*> operator simply flips the arguments of Lazy.apply. If you introduce such an operator, be aware that the admonition from the overview article still applies. In Haskell, the <*> operator applies to any Applicative, which makes it truly general. In F#, once you define an operator like this, it applies specifically to a particular container type, which, in this case, is Lazy<'a>.

    You can replicate the first of the above C# examples like this: @@ -158,13 +158,13 @@

    let s : Lazy<string> = lazy f <*> c <*> i

    - While I find operator-based syntax attractive in Haskell code, I'm more hesitant about such syntax in F#. + While I find operator-based syntax attractive in Haskell code, I'm more hesitant about such syntax in F#.

    Haskell #

    - As outlined in the previous article, Haskell is already lazily evaluated, so it makes little sense to introduce an explicit Lazy data container. While Haskell's built-in Identity isn't quite equivalent to .NET's Lazy<T> object, some similarities remain; most notably, the Identity functor is also applicative: + As outlined in the previous article, Haskell is already lazily evaluated, so it makes little sense to introduce an explicit Lazy data container. While Haskell's built-in Identity isn't quite equivalent to .NET's Lazy<T> object, some similarities remain; most notably, the Identity functor is also applicative:

    Prelude Data.Functor.Identity> :t f
    @@ -189,6 +189,6 @@ 

    The Lazy functor is also an applicative functor. This can be used to combine multiple lazily computed values into a single lazily computed value.

    - Next: Bifunctors. + Next: Bifunctors.

    \ No newline at end of file diff --git a/_posts/2018-12-24-bifunctors.html b/_posts/2018-12-24-bifunctors.html index d6cca23b0..b7f3d3078 100644 --- a/_posts/2018-12-24-bifunctors.html +++ b/_posts/2018-12-24-bifunctors.html @@ -14,7 +14,7 @@ {{ page.description }}

    - This article is a continuation of the article series about functors and about applicative functors. In this article, you'll learn about a generalisation called a bifunctor. The prefix bi typically indicates that there's two of something, and that's also the case here. + This article is a continuation of the article series about functors and about applicative functors. In this article, you'll learn about a generalisation called a bifunctor. The prefix bi typically indicates that there's two of something, and that's also the case here.

    As you've already seen in the functor articles, a functor is a mappable container of generic values, like Foo<T>, where the type of the contained value(s) can be any generic type T. A bifunctor is just a container with two independent generic types, like Bar<T, U>. If you can map each of the types independently of the other, you may have a bifunctor. @@ -52,8 +52,8 @@

    You'll see examples of how to implement and use such functions in the next articles:

    Other bifunctors exist, but those two are the most common.

    @@ -67,7 +67,7 @@

    bimap id id ≡ id

    - This just states that if you translate both axes using the endomorphic Identity, it's equivalent to applying the Identity. + This just states that if you translate both axes using the endomorphic Identity, it's equivalent to applying the Identity.

    The bifunctor law for applying id to both axes simultaneously. @@ -231,6 +231,6 @@

    Do trifunctors, quadfunctors, and so on, exist? Nothing prevents that, but they aren't particularly useful; in practice, you never run into them.

    - Next: Tuple bifunctor. + Next: Tuple bifunctor.

    \ No newline at end of file diff --git a/_posts/2018-12-31-tuple-bifunctor.html b/_posts/2018-12-31-tuple-bifunctor.html index 94e85659b..15ebfda43 100644 --- a/_posts/2018-12-31-tuple-bifunctor.html +++ b/_posts/2018-12-31-tuple-bifunctor.html @@ -12,13 +12,13 @@ {{ page.description }}

    - This article is an instalment in an article series about bifunctors. In the previous overview, you learned about the general concept of a bifunctor. In practice, there's two useful bifunctor instances: pairs (two-tuples) and Either. In this article, you'll see how a pair is a bifunctor, and in the next article, you'll see how Either fits the same abstraction. + This article is an instalment in an article series about bifunctors. In the previous overview, you learned about the general concept of a bifunctor. In practice, there's two useful bifunctor instances: pairs (two-tuples) and Either. In this article, you'll see how a pair is a bifunctor, and in the next article, you'll see how Either fits the same abstraction.

    Tuple as a functor #

    - You can treat a normal pair (two-tuple) as a functor by mapping one of the elements, while keeping the other generic type fixed. In Haskell, when you have types with multiple type arguments, you often 'fix' the types from the left, leaving the right-most type free to vary. Doing this for a pair, which in C# has the type Tuple<T, U>, this means that tuples are functors if we keep T fixed and enable translation of the second element from U1 to U2. + You can treat a normal pair (two-tuple) as a functor by mapping one of the elements, while keeping the other generic type fixed. In Haskell, when you have types with multiple type arguments, you often 'fix' the types from the left, leaving the right-most type free to vary. Doing this for a pair, which in C# has the type Tuple<T, U>, this means that tuples are functors if we keep T fixed and enable translation of the second element from U1 to U2.

    This is easy to implement with a standard Select extension method: @@ -360,6 +360,6 @@

    The other common bifunctor, Either, is complementary. While it has two dimensions, it only contains one value, which is of either the one type or the other. It's still a bifunctor, though, because mappings preserve the structure of Either, too.

    - Next: Either bifunctor. + Next: Either bifunctor.

    \ No newline at end of file diff --git a/_posts/2019-01-07-either-bifunctor.html b/_posts/2019-01-07-either-bifunctor.html index e9ca0e011..4f91c687e 100644 --- a/_posts/2019-01-07-either-bifunctor.html +++ b/_posts/2019-01-07-either-bifunctor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about bifunctors. As the overview article explains, essentially there's two practically useful bifunctors: pairs and Either. In the previous article, you saw how a pair (a two-tuple) forms a bifunctor. In this article, you'll see how Either also forms a bifunctor. + This article is an instalment in an article series about bifunctors. As the overview article explains, essentially there's two practically useful bifunctors: pairs and Either. In the previous article, you saw how a pair (a two-tuple) forms a bifunctor. In this article, you'll see how Either also forms a bifunctor.

    Mapping both dimensions # @@ -27,7 +27,7 @@

    The relationship can, however, go both ways. If you implement SelectBoth, you can derive SelectFirst and SelectSecond from it. In this article, you'll see how to do that for Either.

    - Given the Church-encoded Either, the implementation of SelectBoth can be achieved in a single expression: + Given the Church-encoded Either, the implementation of SelectBoth can be achieved in a single expression:

    public static IEither<L1R1> SelectBoth<LL1RR1>(
    @@ -282,6 +282,6 @@ 

    The other common bifunctor, pair, is complementary. Not only does it also have two dimensions, but a pair always contains both values at once.

    - Next: Software design isomorphisms + Next: Software design isomorphisms

    \ No newline at end of file diff --git a/_posts/2019-01-14-an-either-functor.html b/_posts/2019-01-14-an-either-functor.html index 1791d1050..7f4266477 100644 --- a/_posts/2019-01-14-an-either-functor.html +++ b/_posts/2019-01-14-an-either-functor.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about functors. As another article explains, Either is a bifunctor. This makes it trivially a functor. As such, this article is mostly a place-holder to fit the spot in the functor table of contents, thereby indicating that Either is a functor. + This article is an instalment in an article series about functors. As another article explains, Either is a bifunctor. This makes it trivially a functor. As such, this article is mostly a place-holder to fit the spot in the functor table of contents, thereby indicating that Either is a functor.

    Since Either is a bifunctor, it's actually not one, but two, functors. Many languages, C# included, are best equipped to deal with unambiguous functors. This is also true in Haskell, where Either l r is only a Functor over the right side. Likewise, in C#, you can make IEither<L, R> a functor by implementing Select: @@ -32,7 +32,7 @@ It would have been technically possible to instead implement a Select method by calling SelectLeft, but it seems generally more useful to enable syntactic sugar for mapping over 'happy path' scenarios. This enables you to write projections over operations that can fail.

    - Here's some C# Interactive examples that use the FindWinner helper method from the Church-encoded Either article. Imagine that you're collecting votes; you're trying to pick the highest-voted integer, but in reality, you're only interested in seeing if the number is positive or not. Since FindWinner returns IEither<VoteError, T>, and this type is a functor, you can project the right result, while any left result short-circuits the query. First, here's a successful query: + Here's some C# Interactive examples that use the FindWinner helper method from the Church-encoded Either article. Imagine that you're collecting votes; you're trying to pick the highest-voted integer, but in reality, you're only interested in seeing if the number is positive or not. Since FindWinner returns IEither<VoteError, T>, and this type is a functor, you can project the right result, while any left result short-circuits the query. First, here's a successful query:

    > from i in FindWinner(1, 2, -3, -1, 2, -1, -1) select i > 0
    @@ -65,6 +65,6 @@
     		While the Select method doesn't implement any behaviour that SelectRight doesn't already afford, it enables you to use C# query syntax, as demonstrated by the above examples.
     	

    - Next: A Tree functor. + Next: A Tree functor.

    \ No newline at end of file diff --git a/_posts/2019-01-21-some-thoughts-on-anti-patterns.html b/_posts/2019-01-21-some-thoughts-on-anti-patterns.html index 6851cc281..67823077e 100644 --- a/_posts/2019-01-21-some-thoughts-on-anti-patterns.html +++ b/_posts/2019-01-21-some-thoughts-on-anti-patterns.html @@ -49,7 +49,7 @@

    I've heard said of me that I'm one of those people who call everything I don't like an anti-pattern. I don't think that's true.

    - I think people's perception of me is skewed because even today, the most visited page (my greatest hit, if you will) is an article called Service Locator is an Anti-Pattern. (It concerns me a bit that an article from 2010 seems to be my crowning achievement. I hope I haven't peaked yet, but the numbers tell a different tale.) + I think people's perception of me is skewed because even today, the most visited page (my greatest hit, if you will) is an article called Service Locator is an Anti-Pattern. (It concerns me a bit that an article from 2010 seems to be my crowning achievement. I hope I haven't peaked yet, but the numbers tell a different tale.)

    While I've used the term anti-pattern in other connections, I prefer to be conservative with my use of the word. I tend to use it only when I feel confident that something is, indeed, an anti-pattern. @@ -158,7 +158,7 @@

    - +

    Mogens, thank you for writing. The reason I explicitly framed my treatment in a discourse related to Pareto efficiency is exactly because this view on optima is multi-dimensional. When considering whether a 'solution coordinate' is Pareto-optimal or not, the question is exactly whether or not it's possible to improve at least one dimension without exacerbating any other dimension. If you can make one dimension better without trade-offs, then you can make a Pareto improvement. If you can only make one dimension better at the cost of one or more other dimensions, then you already have a Pareto-optimal solution. diff --git a/_posts/2019-01-28-better-abstractions-revisited.html b/_posts/2019-01-28-better-abstractions-revisited.html index c1e5c7d94..af37cc0b2 100644 --- a/_posts/2019-01-28-better-abstractions-revisited.html +++ b/_posts/2019-01-28-better-abstractions-revisited.html @@ -14,13 +14,13 @@ {{ page.description }}

    - About a decade ago, I had already been doing test-driven development (TDD) and used Dependency Injection for many years, but I'd started to notice some patterns about software design. I'd noticed that interfaces aren't abstractions and that TDD isn't a design methodology. Sometimes, I'd arrive at interfaces that turned out to be good abstractions, but at other times, the interfaces I created seemed to serve no other purpose than enabling unit testing. + About a decade ago, I had already been doing test-driven development (TDD) and used Dependency Injection for many years, but I'd started to notice some patterns about software design. I'd noticed that interfaces aren't abstractions and that TDD isn't a design methodology. Sometimes, I'd arrive at interfaces that turned out to be good abstractions, but at other times, the interfaces I created seemed to serve no other purpose than enabling unit testing.

    - In 2010 I thought that I'd noticed some patterns for good abstractions, so I wrote an article called Towards better abstractions. I still consider it a decent attempt at communicating my findings, but I don't think that I succeeded. My thinking on the subject was still too immature, and I lacked a proper vocabulary. + In 2010 I thought that I'd noticed some patterns for good abstractions, so I wrote an article called Towards better abstractions. I still consider it a decent attempt at communicating my findings, but I don't think that I succeeded. My thinking on the subject was still too immature, and I lacked a proper vocabulary.

    - While I had hoped that I would be able to elaborate on such observations, and perhaps turn them into heuristics, my efforts soon after petered out. I moved on to other things, and essentially gave up on this particular research programme. Years later, while trying to learn category theory, I suddenly realised that mathematical disciplines like category theory and abstract algebra could supply the vocabulary. After some further work, I started publishing a substantial and long-running article series called From design patterns to category theory. It goes beyond my initial attempt, but it finally enabled me to crystallise those older observations. + While I had hoped that I would be able to elaborate on such observations, and perhaps turn them into heuristics, my efforts soon after petered out. I moved on to other things, and essentially gave up on this particular research programme. Years later, while trying to learn category theory, I suddenly realised that mathematical disciplines like category theory and abstract algebra could supply the vocabulary. After some further work, I started publishing a substantial and long-running article series called From design patterns to category theory. It goes beyond my initial attempt, but it finally enabled me to crystallise those older observations.

    In this article, I'll revisit that old article, Towards better abstractions, and translate the vague terminology I used then, to the terminology presented in From design patterns to category theory. @@ -29,13 +29,13 @@ The thrust of the old article is that if you can create a Composite or a Null Object from an interface, then it's likely to be a good abstraction. I still consider that a useful rule of thumb.

    - When can you create a Composite? When the abstraction gives rise to a monoid. When can you create a Null Object? When the abstraction gives rise to a monoid. + When can you create a Composite? When the abstraction gives rise to a monoid. When can you create a Null Object? When the abstraction gives rise to a monoid.

    The terms from the better abstractions article embedded in the set of monoids.

    - All the 'API shapes' I'd identified in Towards better abstractions form monoids. + All the 'API shapes' I'd identified in Towards better abstractions form monoids.

    Commands # @@ -47,13 +47,13 @@

    public void Execute()

    - From unit isomorphisms we know that methods with the void return type are isomorphic to (impure) functions that return unit, and that unit forms a monoid. + From unit isomorphisms we know that methods with the void return type are isomorphic to (impure) functions that return unit, and that unit forms a monoid.

    - Furthermore, we know from function monoids that methods that return a monoid themselves form monoids. Therefore, Commands form monoids. + Furthermore, we know from function monoids that methods that return a monoid themselves form monoids. Therefore, Commands form monoids.

    - In early 2011 I'd already explicitly noticed that Commands are composable. Now I know the deeper reason for this: they're monoids. + In early 2011 I'd already explicitly noticed that Commands are composable. Now I know the deeper reason for this: they're monoids.

    Closure of operations # @@ -65,7 +65,7 @@

    public static T DoIt(T x)

    - That's just an endomorphism, which forms a monoid. + That's just an endomorphism, which forms a monoid.

    Another variation is a method that takes two arguments: @@ -74,7 +74,7 @@

    public static T DoIt(T x, T y)

    - This is a binary operation. While it's certainly a magma, in itself it's not guaranteed to be a monoid. In fact, Evans' colour-mixing example is only a magma, but not a monoid. You can, however, also view this as a special case of the reduction of input shape, below, where the 'extra' arguments just happen to have the same type as the return type. In that interpretation, such a method still forms a monoid, but it's not guaranteed to be meaningful. (Just like modulo 31 addition forms a monoid; it's hardly useful.) + This is a binary operation. While it's certainly a magma, in itself it's not guaranteed to be a monoid. In fact, Evans' colour-mixing example is only a magma, but not a monoid. You can, however, also view this as a special case of the reduction of input shape, below, where the 'extra' arguments just happen to have the same type as the return type. In that interpretation, such a method still forms a monoid, but it's not guaranteed to be meaningful. (Just like modulo 31 addition forms a monoid; it's hardly useful.)

    The same sort of argument goes for methods with closure of operations, but more input arguments, like: @@ -89,7 +89,7 @@

    public static string DoIt(string x, string y, string z)

    - That's a different situation, though, because those strings should probably be turned into domain types that properly communicate their roles. Once you do that, you'll probably find that the method arguments have different types. + That's a different situation, though, because those strings should probably be turned into domain types that properly communicate their roles. Once you do that, you'll probably find that the method arguments have different types.

    In any case, regardless of cardinality, you can view all methods with closure of operations as special cases of the reduction of input shape below. @@ -162,7 +162,7 @@

    T1 DoIt(T3 z, T2 y, T1 x);

    - From Uncurry isomorphisms you know that a method like that is isomorphic to a function with the type 'T3 -> 'T2 -> 'T1 -> 'T1 (F# syntax). You can think of such a curried function as a function that returns a function that returns a function: 'T3 -> ('T2 -> ('T1 -> 'T1)). The rightmost function 'T1 -> 'T1 is clearly an endomorphism, and you already know that an endomorphism gives rise to a monoid. Finally, Function monoids informs us that a function that returns a monoid itself forms a monoid, so 'T2 -> ('T1 -> 'T1) forms a monoid. This argument applies recursively, because if that's a monoid, then 'T3 -> ('T2 -> ('T1 -> 'T1)) is also a monoid. + From Uncurry isomorphisms you know that a method like that is isomorphic to a function with the type 'T3 -> 'T2 -> 'T1 -> 'T1 (F# syntax). You can think of such a curried function as a function that returns a function that returns a function: 'T3 -> ('T2 -> ('T1 -> 'T1)). The rightmost function 'T1 -> 'T1 is clearly an endomorphism, and you already know that an endomorphism gives rise to a monoid. Finally, Function monoids informs us that a function that returns a monoid itself forms a monoid, so 'T2 -> ('T1 -> 'T1) forms a monoid. This argument applies recursively, because if that's a monoid, then 'T3 -> ('T2 -> ('T1 -> 'T1)) is also a monoid.

    What does that look like in C#? @@ -213,7 +213,7 @@

    }

    - This simply returns x while ignoring y and z. The Append method is associative, and the IdentityInputReducer is both left and right identity for the operation, so this is a monoid. Since monoids accumulate, you can also implement an Accumulate extension method: + This simply returns x while ignoring y and z. The Append method is associative, and the IdentityInputReducer is both left and right identity for the operation, so this is a monoid. Since monoids accumulate, you can also implement an Accumulate extension method:

    public static IInputReducer<T1T2T3> Accumulate<T1T2T3>(
    @@ -236,7 +236,7 @@ 

    Composable return types #

    - The original article finally discusses methods that in themselves don't look composable, but turn out to be so anyway, because their return types are composable. Without knowing it, I'd figured out that methods that return monoids are themselves monoids. + The original article finally discusses methods that in themselves don't look composable, but turn out to be so anyway, because their return types are composable. Without knowing it, I'd figured out that methods that return monoids are themselves monoids.

    In 2010 I didn't have the vocabulary to put this into specific language, but that's all it says. @@ -248,7 +248,7 @@

    In 2010 I apparently discovered an ad-hoc, informally specified, vaguely glimpsed, half-understood description of half of abstract algebra.

    - Riffs on Greenspun's tenth rule aside, things clicked for me once I started to investigate what category theory was about, and why it seemed so closely linked to Haskell. That's one of the reasons I started writing the From design patterns to category theory article series. + Riffs on Greenspun's tenth rule aside, things clicked for me once I started to investigate what category theory was about, and why it seemed so closely linked to Haskell. That's one of the reasons I started writing the From design patterns to category theory article series.

    The patterns I thought that I could see in 2010 all form monoids, but there are many other universal abstractions from mathematics that apply to programming as well. diff --git a/_posts/2019-02-04-how-to-get-the-value-out-of-the-monad.html b/_posts/2019-02-04-how-to-get-the-value-out-of-the-monad.html index 1fa194312..a90b98e2d 100644 --- a/_posts/2019-02-04-how-to-get-the-value-out-of-the-monad.html +++ b/_posts/2019-02-04-how-to-get-the-value-out-of-the-monad.html @@ -15,7 +15,7 @@ A frequently asked question about monads can be paraphrased as: How do I get the value out of my monad? This seems to particularly come up when the monad in question is Haskell's IO monad, from which you can't extract the value. This is by design, but then beginners are often stumped on how to write the code they have in mind.

    - You can encounter variations of the question, or at least the underlying conceptual misunderstanding, with other monads. This seems to be particularly prevalent when object-oriented or procedural programmers start working with Maybe or Either. People really want to extract 'the value' from those monads as well, despite the lack of guarantee that there will be a value. + You can encounter variations of the question, or at least the underlying conceptual misunderstanding, with other monads. This seems to be particularly prevalent when object-oriented or procedural programmers start working with Maybe or Either. People really want to extract 'the value' from those monads as well, despite the lack of guarantee that there will be a value.

    So how do you extract the value from a monad? @@ -39,7 +39,7 @@

    What happens, I think, is that when programmers first come across monads, they often encounter one of a few unit containers.

    - What's a unit container? I admit that the word is one I made up, because I couldn't detect existing terminology on this topic. The idea, though, is that it's a functor guaranteed to contain exactly one value. Since functors are containers, I call such types unit containers. Examples include Identity, Lazy, and asynchronous functors. + What's a unit container? I admit that the word is one I made up, because I couldn't detect existing terminology on this topic. The idea, though, is that it's a functor guaranteed to contain exactly one value. Since functors are containers, I call such types unit containers. Examples include Identity, Lazy, and asynchronous functors.

    You can extract 'the value' from most unit containers (with IO being the notable exception from the rule). Trivially, you can get the item contained in an Identity container: @@ -98,7 +98,7 @@

    If you set a flag that indicates that an object was empty, again, you put the burden on callers to check for the flag.

    - This leads to defensive coding, which, at best, makes the code unreadable. + This leads to defensive coding, which, at best, makes the code unreadable.

    Behaviour Injection # @@ -121,7 +121,7 @@

    Maybe<Customer> c = id.Select(x => new Customer(x));

    - A previous article offers a slightly more compelling example: + A previous article offers a slightly more compelling example:

    var viewModel = repository.Read(id).Select(r => r.ToViewModel());
    @@ -250,10 +250,10 @@

    - +

    - Sean, thank you for writing. The first example you give is quite common, and is easily addressed with using the applicative or monadic capabilities of Maybe. Often, in a language like C#, it's easiest to use monadic bind (in C# called SelectMany): + Sean, thank you for writing. The first example you give is quite common, and is easily addressed with using the applicative or monadic capabilities of Maybe. Often, in a language like C#, it's easiest to use monadic bind (in C# called SelectMany):

    Bearing = latitude
    @@ -283,7 +283,7 @@ 

    }

    - This example is based on the Church-encoded Maybe, which is currently my favourite implementation. I decided to call the method Choose, as this is also the name it has in F#. In Haskell, this function is called catMaybes. + This example is based on the Church-encoded Maybe, which is currently my favourite implementation. I decided to call the method Choose, as this is also the name it has in F#. In Haskell, this function is called catMaybes.

    2019-02-05 16:25 UTC
    @@ -300,7 +300,7 @@

    - +

    Achim, thank you for writing. The thought has crossed my mind, but my position on this question seems to be changing. @@ -340,10 +340,10 @@

    - +

    - Ralph, thank you for writing. Please see if my new article Asynchronous Injection answers your question. + Ralph, thank you for writing. Please see if my new article Asynchronous Injection answers your question.

    2019-02-11 7:56 UTC
    diff --git a/_posts/2019-02-11-asynchronous-injection.html b/_posts/2019-02-11-asynchronous-injection.html index 567fa94c8..b1f582c84 100644 --- a/_posts/2019-02-11-asynchronous-injection.html +++ b/_posts/2019-02-11-asynchronous-injection.html @@ -66,7 +66,7 @@

    The Post method simply delegates most work to an injected IMaîtreD object, and translates the return value to an HTTP response.

    - The code example is overly simplistic, to the point where you may wonder what is the point of DI, since it seems that the Post method doesn't perform any work itself. A slightly more realistic example includes some input validation and mapping between layers. + The code example is overly simplistic, to the point where you may wonder what is the point of DI, since it seems that the Post method doesn't perform any work itself. A slightly more realistic example includes some input validation and mapping between layers.

    The IMaîtreD implementation is this: @@ -97,7 +97,7 @@

    }

    - The protocol for the TryAccept method is that it returns the reservation ID if it accepts the reservation. If the restaurant has too little remaining Capacity for the requested date, it instead returns null. Regular readers of this blog will know that I'm no fan of null, but this keeps the example realistic. I'm also no fan of state mutation, but the example does that as well, by setting IsAccepted to true. + The protocol for the TryAccept method is that it returns the reservation ID if it accepts the reservation. If the restaurant has too little remaining Capacity for the requested date, it instead returns null. Regular readers of this blog will know that I'm no fan of null, but this keeps the example realistic. I'm also no fan of state mutation, but the example does that as well, by setting IsAccepted to true.

    Introducing asynchrony # @@ -205,16 +205,16 @@

    Move impure interactions to the boundary of the system #

    - We can pretend that Task<T> forms a functor. It's also a monad. Monads are those incredibly useful programming abstractions that have been propagating from their origin in statically typed functional programming languages to more mainstream languages like C#. + We can pretend that Task<T> forms a functor. It's also a monad. Monads are those incredibly useful programming abstractions that have been propagating from their origin in statically typed functional programming languages to more mainstream languages like C#.

    - In functional programming, impure interactions happen at the boundary of the system. Taking inspiration from functional programming, you can move the impure interactions to the boundary of the system. + In functional programming, impure interactions happen at the boundary of the system. Taking inspiration from functional programming, you can move the impure interactions to the boundary of the system.

    - In the interest of keeping the example simple, I'll only move the impure operations one level out: from MaîtreD to ReservationsController. The approach can be generalised, although you may have to look into how to handle pure interactions. + In the interest of keeping the example simple, I'll only move the impure operations one level out: from MaîtreD to ReservationsController. The approach can be generalised, although you may have to look into how to handle pure interactions.

    - Where are the impure interactions in MaîtreD? They are in the two interactions with IReservationsRepository. The ReadReservations method is non-deterministic, because the same input value can return different results, depending on the state of the database when you call it. The Create method causes a side effect to happen, because it creates a row in the database. This is one way in which the state of the database could change, which makes ReadReservations non-deterministic. Additionally, Create also violates Command Query Separation (CQS) by returning the ID of the row it creates. This, again, is non-deterministic, because the same input value will produce a new return value every time the method is called. (Incidentally, you should design Create methods so that they don't violate CQS.) + Where are the impure interactions in MaîtreD? They are in the two interactions with IReservationsRepository. The ReadReservations method is non-deterministic, because the same input value can return different results, depending on the state of the database when you call it. The Create method causes a side effect to happen, because it creates a row in the database. This is one way in which the state of the database could change, which makes ReadReservations non-deterministic. Additionally, Create also violates Command Query Separation (CQS) by returning the ID of the row it creates. This, again, is non-deterministic, because the same input value will produce a new return value every time the method is called. (Incidentally, you should design Create methods so that they don't violate CQS.)

    Move reservations to a method argument # @@ -290,7 +290,7 @@

    In object-oriented code, DI is the most common way to decouple decisions from effects. Imperative code reaches a decision and calls a method on an object based on that decision. The effect of calling the method can vary because of polymorphism.

    - In functional programming, you typically use a functor like Maybe or Either to separate decisions from effects. You can do the same here. + In functional programming, you typically use a functor like Maybe or Either to separate decisions from effects. You can do the same here.

    The protocol of the TryAccept method already communicates the decision reached by the method. An int value is the reservation ID; this implies that the reservation was accepted. On the other hand, null indicates that the reservation was declined. @@ -333,10 +333,10 @@

    }

    - Notice that the Post method never attempts to extract 'the value' from m. Instead, it injects the desired behaviour (Repository.Create) into the monad. The result of calling Select with an asynchronous lambda expression like that is a Maybe<Task<int>>, which is a awkward combination. You can fix that later. + Notice that the Post method never attempts to extract 'the value' from m. Instead, it injects the desired behaviour (Repository.Create) into the monad. The result of calling Select with an asynchronous lambda expression like that is a Maybe<Task<int>>, which is a awkward combination. You can fix that later.

    - The Match method is the catamorphism for Maybe. It looks exactly like the Match method on the Church-encoded Maybe. It handles both the case when m is empty, and the case when m is populated. In both cases, it returns a Task<IActionResult>. + The Match method is the catamorphism for Maybe. It looks exactly like the Match method on the Church-encoded Maybe. It handles both the case when m is empty, and the case when m is populated. In both cases, it returns a Task<IActionResult>.

    Synchronous domain logic # @@ -424,10 +424,10 @@

    return reservation.Accept().ToMaybe();

    - In any case, the method is close enough to be pure that it's testable. The interactions of TryAccept and any client code (including unit tests) is completely controllable and observable by the client. + In any case, the method is close enough to be pure that it's testable. The interactions of TryAccept and any client code (including unit tests) is completely controllable and observable by the client.

    - This means that there's no reason to Stub it out. You might as well just use the function directly in the Post method: + This means that there's no reason to Stub it out. You might as well just use the function directly in the Post method:

    public class ReservationsController : ControllerBase
    @@ -547,7 +547,7 @@ 

    - +

    Ramon, thank you for writing. Am I loading more responsibilities on the Controller? Yes, I am. Too many? I don't think so. @@ -556,7 +556,7 @@

    To be fair, however, this example is unrealistically simplified (in order to make it easily understandable). There isn't much going on, overall, so one has to imagine that more things are happening than is actually the case. For instance, at the beginning of the example, so little is going on in the Controller that I think it'd be fair to ask why it's even necessary to distinguish between a Controller and a MaîtreD class.

    - Usually, I'd say that the responsibility of a Controller object is to facilitate the translation of what goes on at the boundary of the application and what happens in the domain model. Using the terminology of the ports and adapters architecture, you could say that a Controller's responsibility is to serve as an Adapter between the technology-agnostic domain model and the technology-specific SDKs you'll need to bring into play to communicate with the 'real world'. Talking to databases fits that responsibility, I think. + Usually, I'd say that the responsibility of a Controller object is to facilitate the translation of what goes on at the boundary of the application and what happens in the domain model. Using the terminology of the ports and adapters architecture, you could say that a Controller's responsibility is to serve as an Adapter between the technology-agnostic domain model and the technology-specific SDKs you'll need to bring into play to communicate with the 'real world'. Talking to databases fits that responsibility, I think.

    The MaîtreD class didn't handle any database errors before, so I don't agree that I've moved that responsibility. @@ -597,10 +597,10 @@

    - +

    - Ramon, in general when it comes to exception handling, you either handle exceptions at the source (i.e. in the Repository) or at the boundary of the application (which is typically done by frameworks already). I'm no fan of defensive coding. + Ramon, in general when it comes to exception handling, you either handle exceptions at the source (i.e. in the Repository) or at the boundary of the application (which is typically done by frameworks already). I'm no fan of defensive coding.

    "It suddenly has to hold references to all data exchange classes that it was previously unaware of"
    @@ -669,7 +669,7 @@

    - +

    Tyson, thank you for joining the discussion. By adding a particular problem (more than one user interface) to be addressed, you make the discussion more specific. I think this helps to clarify some issues. @@ -691,7 +691,7 @@

    I do find, however, that when implementing the same sort of software capability in different user interfaces, I need to specifically design for each user interface paradigm. A web-based user interface is quite different from a command-line interface, which is again different from a native application, or a voice-based interface, and so on. A web-based interface is, for example, stateless, whereas a native smart phone application would often be stateful. You can rarely reuse the 'user interface controller layer' for one type of application in a different type of application.

    - Even a command-line interface could be stateful by interactively asking a series of questions. That's such a different user interface paradigm that an object designed for one type of interaction is rarely reusable in another context. + Even a command-line interface could be stateful by interactively asking a series of questions. That's such a different user interface paradigm that an object designed for one type of interaction is rarely reusable in another context.

    What I do find is that fine-grained building blocks still compose. When TryAccept is a pure function, it's always composable. This means that my chance of being able to reuse it becomes much higher than if it's an object injected with various dependencies. @@ -870,16 +870,16 @@

    - +

    Max, thank you for writing. I don't think that testability suffers; on the contrary, I think that it improves. Once the MaîtreD class becomes deterministic, you no longer have to hide it behind a Test Double in order to be able to control its behaviour. You can control its behaviour simply by making sure that it receives the appropriate input arguments.

    - The Facade Tests that cover ReservationsController in the repository are, in my opinion, readable and maintainable. + The Facade Tests that cover ReservationsController in the repository are, in my opinion, readable and maintainable.

    - I've started a new article series about this topic, since I knew it'd come up. I hope that these articles will help illustrate my position. + I've started a new article series about this topic, since I knew it'd come up. I hope that these articles will help illustrate my position.

    2019-02-18 8:33 UTC
    diff --git a/_posts/2019-02-18-from-interaction-based-to-state-based-testing.html b/_posts/2019-02-18-from-interaction-based-to-state-based-testing.html index bdf9fa342..e96d58e2e 100644 --- a/_posts/2019-02-18-from-interaction-based-to-state-based-testing.html +++ b/_posts/2019-02-18-from-interaction-based-to-state-based-testing.html @@ -20,7 +20,7 @@ The idea is that you can change how the code is organised, and as long as you don't break any tests, all is good. The experience that most people seem to have, though, is that when they change something in the code, tests break.

    - This is a well-known test smell. In xUnit Test Patterns this is called Fragile Test, and it's often caused by Overspecified Software. Even if you follow the proper practice of using Mocks for Commands, Stubs for Queries, you can still end up with a code base where the tests are highly coupled to implementation details of the software. + This is a well-known test smell. In xUnit Test Patterns this is called Fragile Test, and it's often caused by Overspecified Software. Even if you follow the proper practice of using Mocks for Commands, Stubs for Queries, you can still end up with a code base where the tests are highly coupled to implementation details of the software.

    The cause is often that when relying on Mocks and Stubs, test verification hinges on how the System Under Test (SUT) interacts with its dependencies. For that reason, we can call such tests interaction-based tests. For more information, watch my Pluralsight course Advanced Unit Testing. @@ -39,12 +39,12 @@

    That's an impressively perceptive observation to make in 2004. I wish I was that perspicacious, but I only reached a similar conclusion ten years later.

    - Functional programming is based on the fundamental principle of referential transparency, which, among other things, means that data must be immutable. Thus, no objects change state. Instead, functions can return data that contains immutable state. In unit tests, you can verify that return values are as expected. Functional design is intrinsically testable; we can consider it a kind of state-based testing, although the states you'd be verifying are immutable return values. + Functional programming is based on the fundamental principle of referential transparency, which, among other things, means that data must be immutable. Thus, no objects change state. Instead, functions can return data that contains immutable state. In unit tests, you can verify that return values are as expected. Functional design is intrinsically testable; we can consider it a kind of state-based testing, although the states you'd be verifying are immutable return values.

    In this article series, you'll see three different styles of testing, from interaction-based testing with Mocks and Stubs in C#, over strictly functional state-based testing in Haskell, to pragmatic state-based testing in F#, finally looping back to C# to apply the lessons from functional programming.

    \ No newline at end of file diff --git a/_posts/2019-02-25-an-example-of-interaction-based-testing-in-c.html b/_posts/2019-02-25-an-example-of-interaction-based-testing-in-c.html index 5e277f745..f8dc513f4 100644 --- a/_posts/2019-02-25-an-example-of-interaction-based-testing-in-c.html +++ b/_posts/2019-02-25-an-example-of-interaction-based-testing-in-c.html @@ -12,7 +12,7 @@ {{ page.description }}

    - This article is an instalment in an article series about how to move from interaction-based testing to state-based testing. In this series, you'll be presented with some alternatives to interaction-based testing with Mocks and Stubs. Before we reach the alternatives, however, we need to establish an example of interaction-based testing, so that you have something against which you can compare those alternatives. In this article, I'll present a simple example, in the form of C# code. + This article is an instalment in an article series about how to move from interaction-based testing to state-based testing. In this series, you'll be presented with some alternatives to interaction-based testing with Mocks and Stubs. Before we reach the alternatives, however, we need to establish an example of interaction-based testing, so that you have something against which you can compare those alternatives. In this article, I'll present a simple example, in the form of C# code.

    The code shown in this article is available on GitHub. @@ -153,7 +153,7 @@

    }

    - To be clear, as far as Overspecified Software goes, this isn't a bad test. It only has two Test Doubles, readerTD and repoTD. My current habit is to name any Test Double with the TD suffix (for Test Double), instead of explicitly naming them readerStub and repoMock. The latter would have been more correct, though, since the Mock<IUserReader> object is consistently used as a Stub, whereas the Mock<IUserRepository> object is used only as a Mock. This is as it should be, because it follows the rule that you should use Mocks for Commands, Stubs for Queries. + To be clear, as far as Overspecified Software goes, this isn't a bad test. It only has two Test Doubles, readerTD and repoTD. My current habit is to name any Test Double with the TD suffix (for Test Double), instead of explicitly naming them readerStub and repoMock. The latter would have been more correct, though, since the Mock<IUserReader> object is consistently used as a Stub, whereas the Mock<IUserRepository> object is used only as a Mock. This is as it should be, because it follows the rule that you should use Mocks for Commands, Stubs for Queries.

    IUserRepository.Update is, indeed a Command: @@ -186,7 +186,7 @@

    In C# and most other languages, you can't be sure that implementations of the Lookup method have no side effects. If, however, we assume that the code base in question obeys the Command Query Separation principle, then, by elimination, this must be a Query (since it's not a Command, because the return type isn't void).

    - For a detailed walkthrough of the IResult<S, E> interface, see my Preserved in translation video. It's just an Either with different terminology, though. Right is equivalent to SuccessResult, and Left corresponds to ErrorResult. + For a detailed walkthrough of the IResult<S, E> interface, see my Preserved in translation video. It's just an Either with different terminology, though. Right is equivalent to SuccessResult, and Left corresponds to ErrorResult.

    The test configures the IUserReader Stub twice. It's necessary to give the Stub some behaviour, but unfortunately you can't just use Moq's It.IsAny<string>() for configuration, because in order to model the test case, the reader should return two different objects for two different inputs. @@ -229,7 +229,7 @@

    }

    - This test starts with a Guard Assertion that userId isn't an integer. This is mostly an artefact of using AutoFixture. Had you used specific example values, then this wouldn't have been necessary. On the other hand, had you written the test case as a property-based test, it would have been even more important to explicitly encode such a constraint. + This test starts with a Guard Assertion that userId isn't an integer. This is mostly an artefact of using AutoFixture. Had you used specific example values, then this wouldn't have been necessary. On the other hand, had you written the test case as a property-based test, it would have been even more important to explicitly encode such a constraint.

    Perhaps a better design would have been to use a domain-specific method to check for the validity of the ID, but there's always room for improvement. @@ -416,7 +416,7 @@

    Yet, using an 'isolation framework' such as Moq, FakeItEasy, NSubstitute, and so on, will pull you towards overspecifying the interactions the SUT has with its Query dependencies.

    - How can we improve? One strategy is to move towards a more functional design, which is intrinsically testable. In the next article, you'll see how to rewrite both tests and implementation in Haskell. + How can we improve? One strategy is to move towards a more functional design, which is intrinsically testable. In the next article, you'll see how to rewrite both tests and implementation in Haskell.

    Next: An example of state-based testing in Haskell. @@ -444,7 +444,7 @@

    - +

    Rémi, thank you for writing. Hosting services as part of a test run can be a valuable addition to an overall testing or release pipeline. It's reminiscent of the approach taken in GOOS. I've also touched on this option in my Pluralsight course Outside-In Test-Driven Development. This is, however, a set of tests I would identify as belonging towards the top of a Test Pyramid. In my experience, such tests tend to run (an order of magnitude) slower than unit tests. diff --git a/about.html b/about.html index 6b6498beb..386f0b9d3 100644 --- a/about.html +++ b/about.html @@ -71,7 +71,7 @@

    Contact me #

    - There's lots of ways to contact me, and you are welcome to do so, e.g. if you want to hire me, want me to speak at a conference or user group meeting, or simply if you have a question you think I should answer here on the blog. In case of public speaking, you can also review my public speaking schedule. + There's lots of ways to contact me, and you are welcome to do so, e.g. if you want to hire me, want me to speak at a conference or user group meeting, or simply if you have a question you think I should answer here on the blog. In case of public speaking, you can also review my public speaking schedule.

    One way to contact me is via email. Here's a little test of your sentience: take each segment of the following email address, and reverse it (e.g. oof@rab.zab would become foo@bar.baz): kram@heolp.kd. diff --git a/hire-me.html b/hire-me.html index 4b5ba0ce8..35141fe3b 100644 --- a/hire-me.html +++ b/hire-me.html @@ -18,7 +18,7 @@ Software architecture. Apart from experience with nitty-gritty coding details, I also have years of experience with application architecture, including REST, SOA, batch systems, etc. If you need help with the big picture, I may be able to help as well.

  • - Functional programming migration. Get help migrating code from C# to F#, from F# to Haskell, or perhaps directly from C# to Haskell. This will include not only translation of keywords, but redesign to a more functional architecture. While I'd probably consider it unethical, I also possess the skills to help you migrate from Haskell or F# to C#. + Functional programming migration. Get help migrating code from C# to F#, from F# to Haskell, or perhaps directly from C# to Haskell. This will include not only translation of keywords, but redesign to a more functional architecture. While I'd probably consider it unethical, I also possess the skills to help you migrate from Haskell or F# to C#.
  • Sparring. If you need to improve your skills in e.g. Test-Driven Development, API design, refactoring, Unit Testing, Functional Programming, Object-Oriented Design, etc. I can pair with you, or otherwise join you with the purpose of transferring knowledge and experience while solving real problems. @@ -30,7 +30,7 @@ Code reviews. If you want me to review your code, I'll be happy to do so. Usually, I tell my customers that they should start by running a code analysis tool (like the built-in Code Analysis feature in Visual Studio), because it's free, and you get more value out of my code reviews if you already get the obvious issues out of the way before I start looking at the code. I particularly look for issues relating to readability, encapsulation, coupling, maintainability, etc.
  • - Training. I regularly talk at conferences, but I can also visit your company to deliver lectures and workshops. You are welcome to take a look at my schedule to get an idea about current and past topics, but feel free to contact me to discuss topics; I can most likely tailor something that fits your requirements. Apart from tailored training, I also have a small catalogue of off-the-shelf workshops: + Training. I regularly talk at conferences, but I can also visit your company to deliver lectures and workshops. You are welcome to take a look at my schedule to get an idea about current and past topics, but feel free to contact me to discuss topics; I can most likely tailor something that fits your requirements. Apart from tailored training, I also have a small catalogue of off-the-shelf workshops:
    • Software Craftsmanship. A full day of inspiration, controversial views on software development, and lots of hands-on exercises. @@ -53,7 +53,7 @@ Round table. Sometimes people simply want to have a meeting with me to discuss various topics - typically Test-Driven Development, software design, architecture, and the like. I'm happy to visit you for a meeting with you and your team, where we can discuss your questions, sketch together on a whiteboard, look at code examples, etc., in an ad hoc fashion.
    - This list isn't exhaustive, so if you have other ideas for how you think I may be able to help you, please contact me. + This list isn't exhaustive, so if you have other ideas for how you think I may be able to help you, please contact me.

    Testimonials

    @@ -108,8 +108,8 @@

    Testimonials

    Practical issues

    - If you are interested in hiring me, then please contact me. While I'm based in Copenhagen, Denmark, I can travel to you if necessary, as long as I don't have to stay away from my family for too long; in this case, you'll need to cover my travel expenses as well, although I sometimes include that in a fixed price offer. Collaboration over the internet is obviously a less expensive alternative. + If you are interested in hiring me, then please contact me. While I'm based in Copenhagen, Denmark, I can travel to you if necessary, as long as I don't have to stay away from my family for too long; in this case, you'll need to cover my travel expenses as well, although I sometimes include that in a fixed price offer. Collaboration over the internet is obviously a less expensive alternative.

    - Usually I charge by the hour, but sometimes (e.g. for training) I can also give you a fixed price offer. My prices are high - expect to pay more than you would normally pay for a development consultant, but slightly less than a licensed lawyer, accountant, management consultant, or similar. My price may vary with the nature and length of the assignment. Also depending on the nature of the task, I may ask for a retainer fee. Please contact me for details. + Usually I charge by the hour, but sometimes (e.g. for training) I can also give you a fixed price offer. My prices are high - expect to pay more than you would normally pay for a development consultant, but slightly less than a licensed lawyer, accountant, management consultant, or similar. My price may vary with the nature and length of the assignment. Also depending on the nature of the task, I may ask for a retainer fee. Please contact me for details.

    \ No newline at end of file diff --git a/support.html b/support.html index 83887abba..da81af91d 100644 --- a/support.html +++ b/support.html @@ -77,5 +77,5 @@

    I can send you a single invoice, or a recurring one, for any amount of your choice. I usually lose between 75 and 350 DKK in international bank transfer fees, but apart from that, I'll be grateful for any amount of support.

    - If you'd like to professionally support this blog, then please contact me. + If you'd like to professionally support this blog, then please contact me.

    \ No newline at end of file