Monday, October 24, 2011

Composition Root

I'm reading Dependency Injection in .Net by Mark Seemann

In response to http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx

I'm only up to reading mid-way through your chapter on doing it right (and jumped to the asp.net webforms composition root after reading this blog post), but here is more of my reasoning.

The catch comes when you look at the behavior, and you realize that there is hardly any behavior on these objects, making them little more than bags of getters and setters. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. AnemicDomain Models - Martin Fowler


It becomes a 'real' domain model when it contains all (or most) of the behaviour that makes up the business domain (note I'm emphasising business logic, not UI or other orthogonal concerns). Anemic Domain Models - Stack overflow

I don't feel that this is headed into an Anemic domain model as the domain model assembly would contain all behaviors specific to the domain.

  Designs that share very little state or, even better, have no state at all tend to be less prone to hard to analyze bugs and easier to repurpose when requirements change. Blog article - makes sense but i could be missing multiple boats here.

The domain would have zero state, and would depend on interfaces not DTOs. This would make test-ability and analysis simple.

 Motivation for DTOs in the interfaces layer: presentation and persistence could all share the DTOs rather than having them duplicated in either place.
Barring that perceived gain, then the shared layer across all would just be interfaces.

 The UI could depend on interfaces only, but the same assembly would contain DTOs that the presentation layer and any persistence could share without having to be duplicated/rewritten. So the domain is completely persistence and presentation ignorant.

Wednesday, October 19, 2011

Routing except webforms requests

I have a legacy webforms (.aspx) project that I'm sliding routing and MVC3 into. I needed a route that would not prevent the default page from being handled by IIS, but would allow all other controller style routing.  How do you make a regex that only fails uri's that have .aspx or .axd in them?

Then I thought well I still don't want anything that doesn't look like an mvc route (things that end in .foo or .fooo)  Sounds like a crazy negative regex.
Here's the regular expression:

^(.(?!\.[a-zA-Z0-9]{3,}))*$


Match anything that doesn't look like a file extension 


And here's the routeAdd in global.asax


static void RegisterRoutes(RouteCollection routes)
  {

     routes.MapRoute("mvc", "{controller}/{action}/{id}",defaults: new{action="index",id=""}, constraints:new{controller=@"^(.(?!\.[a-zA-Z0-9]{3,}))*$"});

  }

Thursday, September 29, 2011

Microsoft is embracing extensibility... using Stackoverflow.com for forums, and uservoice for VS feedback!


Where are the MSDN forums?
We have decided to migrate our forums to stackoverflow.com in order to better build a community around Pex and Moles. Questions about Pex should be tagged with 'Pex' and Moles with 'Moles'...

Monday, September 19, 2011

Some F# early learning and reference

I'm translating my bulk code detector from c# to f#, to learn f#. It's a linqpad c# program that recurses a directory tree organizing code

  • by
    • highest line count 
    • highest line count by directory 
    • highest line count by base filename (the stuff before the .) 
  • includes 
    • non-whitespace count 
    • potential magic numbers count 
    • " count


//path returns string
let path :string= 
  let userPath=Util.ReadLine("SourceDirectory?",@"D:\projects\")
  let exists=System.IO.Directory.Exists(userPath)
  if not(exists) then //guard clause
    raise(DirectoryNotFoundException(userPath))
  userPath
  
let doTestFileExclude = false

//fileExclude= Func<string,bool> a=>
let fileExclude  (a:string):bool = 
  a.EndsWith("designer.cs",StringComparison.CurrentCultureIgnoreCase)||
  a.StartsWith("jquery-",StringComparison.CurrentCultureIgnoreCase)||
  a.StartsWith("AssemblyInfo");
  
let pathExclude (a:string) :bool =
  a.Contains(@"\Database\")||
  a.Contains("Service References")||
  a.Contains("Web References") ||
  a.Contains("PackageTmp") ||
  a.StartsWith(@"~\Web\Scripts\Mvc3")

//record, class, struct, or discriminated union?  
type  CountSettings = {
  Path: string
  Patterns: IEnumerable<string>
  FileExclude: string -> bool
  PathExclude: string-> bool
  }
//instance of above type
let currentSettings:CountSettings=  {
  Path=path
  Patterns=["*.cs";"*.js"]
  FileExclude=fileExclude
  PathExclude=pathExclude
  }

//demonstrating access modifier  
let private testFileExclude() =
  let testCases = ["test";"test.designer.cs";"test.Designer.cs"]
  let mapped = testCases |>
    List.map(fun (fn:string) ->
      (fn,currentSettings.FileExclude(fn))
    )
  mapped.Dump("testFileExclude done")
  
if doTestFileExclude then
  do testFileExclude()

//set cwd (not a functional call, imperative?)
System.Environment.CurrentDirectory=currentSettings.Path
//public ~IEnumerable<T> visitDir(string dir,T1 dirFilter, T2 patterns, T3 fileFilter)
let rec visitAll (dir:string) patterns=seq{
  for pattern in patterns do
    yield! Directory.EnumerateFiles(dir,pattern)
  for subdir in Directory.EnumerateDirectories(dir) do
    yield! visitAll subdir patterns
  }
  
visitAll currentSettings.Path currentSettings.Patterns 
  |> Seq.length 
  |> fun x->x.Dump("LengthAll")


let rec visitDir (dir:string) dirFilter patterns fileFilter=
  seq{
  for pattern in patterns do
    for file in Directory.EnumerateFiles(dir,pattern) do
      if not(fileFilter(file)) then
        yield file
  for subdir in Directory.EnumerateDirectories(dir) do
    if not(dirFilter(subdir)) then
      yield! visitDir subdir dirFilter patterns fileFilter
  }
  
let visitDirResult= 
  visitDir currentSettings.Path currentSettings.PathExclude
    currentSettings.Patterns
      currentSettings.FileExclude
visitDirResult |> Seq.length |> fun x->x.Dump("visitDirLength")
visitDirResult |> fun x ->x.Dump("visitDirResult")

//Extension method on string
type System.String with
  member x.Right(index) = x.Substring(x.Length - index)

Tuesday, September 6, 2011

Local NuGet Feed on network drive

This was so much simpler than I imagined. I followed this article from Hanselman.


  1. Get the NuGet.exe command line here. Put it in the %path% or somewhere.
  2. Create a directory for your package - I created mine on the network share directly
  3. on the command line in your new folder nuget.exe spec
    1. Depends on your nuget.exe being in the %path%
  4. edit any fields in the new Package.nuspec file.
  5. If you have assemblies
    1. Add a lib folder
      1. Add assemblies inside
  6. If you have other content
    1. Add a content folder
      1. Add files inside
  7. If you have transforms
    1. Add filename.transform inside the content folder
      1. For example web.config.transform
  8. nuget.exe pack package.nuspec
Package created!

Now add that location in your Vs2010  Tools->LibraryPackageManager->PackageManagerSettings
In Package sources add the source, and name it. TADA!