diff --git a/about/index.html b/about/index.html index f797d82..fed346a 100644 --- a/about/index.html +++ b/about/index.html @@ -172,6 +172,10 @@

Apache Maven

Recent Posts

diff --git a/atom.xml b/atom.xml index 02bf86f..8cd5465 100644 --- a/atom.xml +++ b/atom.xml @@ -4,7 +4,7 @@ <![CDATA[Chris Eldredge]]> - 2012-07-26T14:52:10-04:00 + 2012-08-07T15:36:01-04:00 http://chriseldredge.github.com/ @@ -13,6 +13,102 @@ Octopress + + <![CDATA[How The Motley Fool uses NuGet (part 1)]]> + + 2012-08-07T14:25:00-04:00 + http://chriseldredge.github.com/blog/2012/08/07/how-the-motley-fool-uses-nuget + This post describes how we came to using binary package management. In the next part I’ll get into NuGet.

+ +

In the beginning, there was one repository and it held all the projects for The Motley Fool, and it was good. +There were around a dozen asp.net web projects, a smattering of service and console apps, and a bunch of class libraries +to hold shared code. There was one Solution (sln) to rule them all.

+ +

As time went on, we found that there are downsides to the one-giant-solution approach to .net development:

+ +
    +
  • Big Ball of Mud
  • +
  • Slow builds
  • +
  • Tight coupling
  • +
  • Configuration hell
  • +
  • Hard to release different applications on different schedules
  • +
+ + +

Typically our larger applications would be split into several projects following a typical N-tier layered architecture:

+ +
    +
  • Web
  • +
  • Service
  • +
  • Domain
  • +
  • Data Access
  • +
+ + +

Despite our attempts to encapsulate data access and domain logic behind the service project, code ended up leaking out +to the point where domain projects were using types and methods from unrelated domain projects. Cats and dogs were +sleeping together.

+ +

Around this time Steven Bohlen presented a talk +to the Washington DC Alt.NET User Group titled “Domain Driven Design Implementation Patterns in .NET”. While some of us +were already familiar with concepts of DDD, this talk lit a spark for us to try fixing our big ball of mud.

+ +

In late 2010 we started to make some changes. Instead of having one giant repository, shared code would be split out +into separate repositories. We also took this opportunity to introduce a new project organization and architecture.

+ +

We established one repository to hold utility code, broken into specific class libraries:

+ +
    +
  • Fool.Abstractions - similar in spirit to System.Web.Abstractions; adds interfaces and wrappers to various FCL types that lack them
  • +
  • Fool.Lang - similar in spirit to Jakarta Commons Lang; adds general utility classes and methods not found elsewhere
  • +
  • Other projects that extend 3rd party class libraries to make them easier for us to work with in standardized ways.
  • +
+ + +

Then we established another repository to hold Domain Driven, er, Domains. For example, many of our applications and web sites deal with +stock market data, so one of our business domains is Quotes. In the Quotes Domain we have these projects:

+ +
    +
  • Fool.Quotes - contains service interfaces and value types; serves as an API to the domain
  • +
  • Fool.Quotes.Core - contains domain logic, models, and entities; serves as a private implementation
  • +
  • Fool.Quotes.Web.Api - exposes Fool.Quotes interfaces over a RESTful web API
  • +
+ + +

The key to keeping our domains distinct and decoupled is to keep Core projects private. While Core is required at runtime, +it should never be referenced at compile time. To bridge the gap, we use Dependency Injection to provide concrete implementations.

+ +

Domains may depend on other domains provided that they consume each other through the API project. That way entities and business logic +are kept focused on their own concerns and don’t leak out to other problem areas where they don’t fit.

+ +

Gluing It Together

+ +

Having projects split into different repositories and different solutions meant that we couldn’t simply have one mega Solution +that includes everything. That’s by design, so good on us. But this introduces a problem in that we still need to reference code +from our utility projects and DDD projects in our applications. The first solution we came up with to handle this problem was +to use the AssemblyFolders registry to have our libraries +appear in the Add Reference dialog. Then to solve the runtime dependency on our private Core assemblies, we install +those to the GAC so they can be loaded using reflection by our IoC container.

+ +

This approach worked fine, mostly. But we encountered some downsides after using it for a while:

+ +
    +
  • Need to have all library code checked out and built on each development machine
  • +
  • No built-in way to manage different versions of the same dependency
  • +
  • GAC considered harmful
  • +
  • Hard to debug build errors and runtime errors
  • +
+ + +

Using Continuous Integration means we’re producing new builds dozens of times a day, so it isn’t practical for us to +manage different assembly versions for each build. Like most shops, we leave our assembly versions at 1.0.0.0 despite +injecting actual version information into the AssemblyInformationalVersion attribute.

+ +

In order to support parallel development, we needed to find a more flexible way of managing dependencies, and +at this point we started to look at binary package management.

+]]>
+
+ <![CDATA[MSBuild, Visual Studio & NuGet Hackery]]> diff --git a/blog/2012/03/29/Getting-Started-With-Relinq/index.html b/blog/2012/03/29/Getting-Started-With-Relinq/index.html index b185315..eb8cafe 100644 --- a/blog/2012/03/29/Getting-Started-With-Relinq/index.html +++ b/blog/2012/03/29/Getting-Started-With-Relinq/index.html @@ -207,6 +207,10 @@

The Bare Bones

Recent Posts

diff --git a/blog/2012/04/19/Lucene-NumericField-Gotcha/index.html b/blog/2012/04/19/Lucene-NumericField-Gotcha/index.html index 77a1565..38ab069 100644 --- a/blog/2012/04/19/Lucene-NumericField-Gotcha/index.html +++ b/blog/2012/04/19/Lucene-NumericField-Gotcha/index.html @@ -172,6 +172,10 @@

Lucene NumericField Gotcha

Recent Posts

diff --git a/blog/2012/05/08/Introducing-Linq-to-Lucene/index.html b/blog/2012/05/08/Introducing-Linq-to-Lucene/index.html index 17e02d9..5afe5f7 100644 --- a/blog/2012/05/08/Introducing-Linq-to-Lucene/index.html +++ b/blog/2012/05/08/Introducing-Linq-to-Lucene/index.html @@ -280,6 +280,10 @@

Conclusion

Recent Posts

diff --git a/blog/2012/07/03/Speeding-Up-NuGet-Server/index.html b/blog/2012/07/03/Speeding-Up-NuGet-Server/index.html index da80372..90952c5 100644 --- a/blog/2012/07/03/Speeding-Up-NuGet-Server/index.html +++ b/blog/2012/07/03/Speeding-Up-NuGet-Server/index.html @@ -239,6 +239,10 @@

Conclusion

Recent Posts

diff --git a/blog/2012/07/24/Unit-of-Work-and-Eventual-Consistency/index.html b/blog/2012/07/24/Unit-of-Work-and-Eventual-Consistency/index.html index 670fe40..73d3262 100644 --- a/blog/2012/07/24/Unit-of-Work-and-Eventual-Consistency/index.html +++ b/blog/2012/07/24/Unit-of-Work-and-Eventual-Consistency/index.html @@ -290,6 +290,10 @@

Eventual Consistency

Recent Posts

diff --git a/blog/2012/07/26/MSBuild-NuGet-Visual-Studio-Hackery/index.html b/blog/2012/07/26/MSBuild-NuGet-Visual-Studio-Hackery/index.html index 525799a..d5b2756 100644 --- a/blog/2012/07/26/MSBuild-NuGet-Visual-Studio-Hackery/index.html +++ b/blog/2012/07/26/MSBuild-NuGet-Visual-Studio-Hackery/index.html @@ -467,6 +467,8 @@

MSBuild, Visual Studio & NuGet Hackery

« Unit of Work & Eventual Consistency + How The Motley Fool uses NuGet (part 1) » +

@@ -479,6 +481,10 @@

MSBuild, Visual Studio & NuGet Hackery

Recent Posts

diff --git a/blog/2012/08/07/how-the-motley-fool-uses-nuget/index.html b/blog/2012/08/07/how-the-motley-fool-uses-nuget/index.html new file mode 100644 index 0000000..3f45518 --- /dev/null +++ b/blog/2012/08/07/how-the-motley-fool-uses-nuget/index.html @@ -0,0 +1,325 @@ + + + + + + + + How The Motley Fool uses NuGet (part 1) - Chris Eldredge + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Chris Eldredge

+ +
+ +
+ +
+
+
+
+ +
+ +

How the Motley Fool Uses NuGet (Part 1)

+ + +

+ + + + + + + + + + + + + + +

+ +
+ + +

This post describes how we came to using binary package management. In the next part I’ll get into NuGet.

+ +

In the beginning, there was one repository and it held all the projects for The Motley Fool, and it was good. +There were around a dozen asp.net web projects, a smattering of service and console apps, and a bunch of class libraries +to hold shared code. There was one Solution (sln) to rule them all.

+ +

As time went on, we found that there are downsides to the one-giant-solution approach to .net development:

+ +
    +
  • Big Ball of Mud
  • +
  • Slow builds
  • +
  • Tight coupling
  • +
  • Configuration hell
  • +
  • Hard to release different applications on different schedules
  • +
+ + +

Typically our larger applications would be split into several projects following a typical N-tier layered architecture:

+ +
    +
  • Web
  • +
  • Service
  • +
  • Domain
  • +
  • Data Access
  • +
+ + +

Despite our attempts to encapsulate data access and domain logic behind the service project, code ended up leaking out +to the point where domain projects were using types and methods from unrelated domain projects. Cats and dogs were +sleeping together.

+ +

Around this time Steven Bohlen presented a talk +to the Washington DC Alt.NET User Group titled “Domain Driven Design Implementation Patterns in .NET”. While some of us +were already familiar with concepts of DDD, this talk lit a spark for us to try fixing our big ball of mud.

+ +

In late 2010 we started to make some changes. Instead of having one giant repository, shared code would be split out +into separate repositories. We also took this opportunity to introduce a new project organization and architecture.

+ +

We established one repository to hold utility code, broken into specific class libraries:

+ +
    +
  • Fool.Abstractions - similar in spirit to System.Web.Abstractions; adds interfaces and wrappers to various FCL types that lack them
  • +
  • Fool.Lang - similar in spirit to Jakarta Commons Lang; adds general utility classes and methods not found elsewhere
  • +
  • Other projects that extend 3rd party class libraries to make them easier for us to work with in standardized ways.
  • +
+ + +

Then we established another repository to hold Domain Driven, er, Domains. For example, many of our applications and web sites deal with +stock market data, so one of our business domains is Quotes. In the Quotes Domain we have these projects:

+ +
    +
  • Fool.Quotes - contains service interfaces and value types; serves as an API to the domain
  • +
  • Fool.Quotes.Core - contains domain logic, models, and entities; serves as a private implementation
  • +
  • Fool.Quotes.Web.Api - exposes Fool.Quotes interfaces over a RESTful web API
  • +
+ + +

The key to keeping our domains distinct and decoupled is to keep Core projects private. While Core is required at runtime, +it should never be referenced at compile time. To bridge the gap, we use Dependency Injection to provide concrete implementations.

+ +

Domains may depend on other domains provided that they consume each other through the API project. That way entities and business logic +are kept focused on their own concerns and don’t leak out to other problem areas where they don’t fit.

+ +

Gluing It Together

+ +

Having projects split into different repositories and different solutions meant that we couldn’t simply have one mega Solution +that includes everything. That’s by design, so good on us. But this introduces a problem in that we still need to reference code +from our utility projects and DDD projects in our applications. The first solution we came up with to handle this problem was +to use the AssemblyFolders registry to have our libraries +appear in the Add Reference dialog. Then to solve the runtime dependency on our private Core assemblies, we install +those to the GAC so they can be loaded using reflection by our IoC container.

+ +

This approach worked fine, mostly. But we encountered some downsides after using it for a while:

+ +
    +
  • Need to have all library code checked out and built on each development machine
  • +
  • No built-in way to manage different versions of the same dependency
  • +
  • GAC considered harmful
  • +
  • Hard to debug build errors and runtime errors
  • +
+ + +

Using Continuous Integration means we’re producing new builds dozens of times a day, so it isn’t practical for us to +manage different assembly versions for each build. Like most shops, we leave our assembly versions at 1.0.0.0 despite +injecting actual version information into the AssemblyInformationalVersion attribute.

+ +

In order to support parallel development, we needed to find a more flexible way of managing dependencies, and +at this point we started to look at binary package management.

+
+ + + +
+ +
+ + + + +
+
+

+ Copyright © 2012 - Chris Eldredge - + Powered by Octopress +

+ +
+ + + + + + + + + + + + + + + + diff --git a/blog/archives/index.html b/blog/archives/index.html index 6d82c17..886f7e6 100644 --- a/blog/archives/index.html +++ b/blog/archives/index.html @@ -9,10 +9,9 @@ - + @@ -91,6 +90,16 @@

Blog Archive

2012

+ + + +

MSBuild, Visual Studio & NuGet Hackery

@@ -162,6 +171,10 @@

Getting Started with

Recent Posts

diff --git a/index.html b/index.html index 895588f..2b48218 100644 --- a/index.html +++ b/index.html @@ -9,8 +9,7 @@ - + @@ -78,6 +77,129 @@

Chris Eldredge

+
+ +
+ +

How the Motley Fool Uses NuGet (Part 1)

+ + +

+ + + + + + + + + + + + + + +

+ +
+ + +

This post describes how we came to using binary package management. In the next part I’ll get into NuGet.

+ +

In the beginning, there was one repository and it held all the projects for The Motley Fool, and it was good. +There were around a dozen asp.net web projects, a smattering of service and console apps, and a bunch of class libraries +to hold shared code. There was one Solution (sln) to rule them all.

+ +

As time went on, we found that there are downsides to the one-giant-solution approach to .net development:

+ +
    +
  • Big Ball of Mud
  • +
  • Slow builds
  • +
  • Tight coupling
  • +
  • Configuration hell
  • +
  • Hard to release different applications on different schedules
  • +
+ + +

Typically our larger applications would be split into several projects following a typical N-tier layered architecture:

+ +
    +
  • Web
  • +
  • Service
  • +
  • Domain
  • +
  • Data Access
  • +
+ + +

Despite our attempts to encapsulate data access and domain logic behind the service project, code ended up leaking out +to the point where domain projects were using types and methods from unrelated domain projects. Cats and dogs were +sleeping together.

+ +

Around this time Steven Bohlen presented a talk +to the Washington DC Alt.NET User Group titled “Domain Driven Design Implementation Patterns in .NET”. While some of us +were already familiar with concepts of DDD, this talk lit a spark for us to try fixing our big ball of mud.

+ +

In late 2010 we started to make some changes. Instead of having one giant repository, shared code would be split out +into separate repositories. We also took this opportunity to introduce a new project organization and architecture.

+ +

We established one repository to hold utility code, broken into specific class libraries:

+ +
    +
  • Fool.Abstractions - similar in spirit to System.Web.Abstractions; adds interfaces and wrappers to various FCL types that lack them
  • +
  • Fool.Lang - similar in spirit to Jakarta Commons Lang; adds general utility classes and methods not found elsewhere
  • +
  • Other projects that extend 3rd party class libraries to make them easier for us to work with in standardized ways.
  • +
+ + +

Then we established another repository to hold Domain Driven, er, Domains. For example, many of our applications and web sites deal with +stock market data, so one of our business domains is Quotes. In the Quotes Domain we have these projects:

+ +
    +
  • Fool.Quotes - contains service interfaces and value types; serves as an API to the domain
  • +
  • Fool.Quotes.Core - contains domain logic, models, and entities; serves as a private implementation
  • +
  • Fool.Quotes.Web.Api - exposes Fool.Quotes interfaces over a RESTful web API
  • +
+ + +

The key to keeping our domains distinct and decoupled is to keep Core projects private. While Core is required at runtime, +it should never be referenced at compile time. To bridge the gap, we use Dependency Injection to provide concrete implementations.

+ +

Domains may depend on other domains provided that they consume each other through the API project. That way entities and business logic +are kept focused on their own concerns and don’t leak out to other problem areas where they don’t fit.

+ +

Gluing It Together

+ +

Having projects split into different repositories and different solutions meant that we couldn’t simply have one mega Solution +that includes everything. That’s by design, so good on us. But this introduces a problem in that we still need to reference code +from our utility projects and DDD projects in our applications. The first solution we came up with to handle this problem was +to use the AssemblyFolders registry to have our libraries +appear in the Add Reference dialog. Then to solve the runtime dependency on our private Core assemblies, we install +those to the GAC so they can be loaded using reflection by our IoC container.

+ +

This approach worked fine, mostly. But we encountered some downsides after using it for a while:

+ +
    +
  • Need to have all library code checked out and built on each development machine
  • +
  • No built-in way to manage different versions of the same dependency
  • +
  • GAC considered harmful
  • +
  • Hard to debug build errors and runtime errors
  • +
+ + +

Using Continuous Integration means we’re producing new builds dozens of times a day, so it isn’t practical for us to +manage different assembly versions for each build. Like most shops, we leave our assembly versions at 1.0.0.0 despite +injecting actual version information into the AssemblyInformationalVersion attribute.

+ +

In order to support parallel development, we needed to find a more flexible way of managing dependencies, and +at this point we started to look at binary package management.

+
+ + + + +
+ +
@@ -1025,6 +1147,10 @@

The Bare Bones

Recent Posts

diff --git a/sitemap.xml b/sitemap.xml index ebf6e6a..86ec1d0 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -28,16 +28,20 @@ 2012-07-26T14:52:10-04:00 + + http://chriseldredge.github.com/blog/2012/08/07/how-the-motley-fool-uses-nuget/ + 2012-08-07T15:36:00-04:00 + http://chriseldredge.github.com/about/ 2012-07-26T14:37:00-04:00 http://chriseldredge.github.com/blog/archives/ - 2012-07-26T14:52:10-04:00 + 2012-08-07T15:36:00-04:00 http://chriseldredge.github.com/ - 2012-07-26T14:52:10-04:00 + 2012-08-07T15:36:00-04:00 \ No newline at end of file