September 2007 Entries

RE: Presentation Model Question

 

I've been working on an end to end example using MonoRail (I know, just get it posted Joey!) that can demonstrate one way this can be implemented and JP has given me the green light to get it posted even though he's working in some sample code as well.  (I'm sure his example will be much better than mine)  :) 

But I wanted to respond quickly to Liam's questions on JP's latest update on screen-specific DTOs.

Here was Liam's first question:

"Firstly, isn't this a violation of the DRY principle?"

Well... it depends.  :)

It certainly is not right for every situation.  But one of my motivations for using screen-specific DTOs is SRP.  Having a set of task specific/screen specific DTOs can sometimes give you the loose coupling you need to protect your domain model from being polluted (most of the time, unintentionally) by UI and/or infrastructure concerns. 

If I have to work within a complex domain, I typically like for the responsibilities of the domain model to be narrowly focused on object interactions and relationships to make it easier to understand and maintain.

Now, if your DTOs are nothing more than mirror images of your domain model, then that is definitely a smell and is most likely not very DRY.  I've been on a couple projects like this and, at that point, maintenance of the mapping layer becomes very tedious and generally makes developers unhappy.  Not a good thing.

Liam's second question is something I've been looking for/working towards myself:

"Secondly, is there a nice way to handle the mapping between the domain model and the presentation model?"

This is a very good question.  So, of course, all of this does come with a price.  Maintaining a mapping layer is usually a necessary evil if you choose to go this route.  I try to start out with simple hand-rolled mappers and let it evolve from there.  Most likely, through continuous refactoring you could arrive at a fairly robust and somewhat easy to maintain mapping layer.  I feel like I'm getting close to that point on my current project now that I have a dozen or so mappers implemented. 

Unfortunately, I don't know of any decent frameworks out there that can tackle this problem of domain-presentation mapping the same way, say NHibernate, solves the object-relational mapping problem.  If you know of any, please let me know.  Otherwise, I suppose it wouldn't be too hard to "harvest" one from an existing application.  In fact, I may try to do just that on my current project if I can see any value in it.

You're probably saying, "Just post some code Joey!".  I know, I know.  Well, I'm pretty close.  I just like to make sure the quality of the samples I provide are close to, if not the same, as the code I churn out every day.  So, thanks for your patience.  :)

Quick Tip: Enabling WordPress Tagging In WLW

 

I've been playing with WordPress a little over the past couple days (for our new family site we're trying to start) and it's a pretty sweet product.  In their latest version 2.3 they have full tagging support but at first glance the only thing Windows Live Writer would allow me to do is set up categories for WordPress which are not the same.  I prefer tagging for its simplicity. 

So after some searching I found that WLW looks for a file named "wlwmanifest.xml" to discover what features are available for the particular blog engine your using.  So all you have to do is download this WLW manifest file designed for WordPress, and then upload it to the root of your blog.

This allows you to use a nice little box in WLW to enter "keywords" which get translated into "tags" when posting to WordPress.

wlw_keywords

:D 

My First Interview (that I have given)

 

Today I was asked to give a technical interview to a candidate which is kind of a new thing for me.  He had already been screened on the "what's an abstract class and how do you do <insert something here /> in ASP.NET" kind of questions.  So I got to have fun and go through some more interesting topics.

Some of the topics I was bringing up, I see as fundamental to being a good developer.  I didn't realize it until afterwards, but not one question I asked him was technology-specific.  Which is usually the kinds of topics I prefer to focus my own time on.

I started out with some OOD principles like SRP, OCP, LSP, DIP, etc.  Unfortunately he had never heard of any of them.  So I went into explaining each one for him because, if nothing else, I figured at least I could test my own self in my explanations and maybe he could even learn a little something too. 

Then I started talking about just some basic unit testing, which he didn't currently practice.  So I really didn't even bother to get into TDD/Mock Objects.  It was probably a mistake for me to try and go over IoC/DI and xDD practices after that, but I wanted to give him the benefit of the doubt.  No dice. 

So, I guess this is my first time experiencing for myself the challenge that many of my fellow bloggers talk about when they say how hard it can be to find great hackers

My final question (which probably should've been my first) was "So, who's your favorite bloggers?".  :D

Seriously though, whether or not a developer is involved with the community I think says a lot about them.  There is certainly nothing wrong with not being involved in the developer community, but I think it can be a good distinguisher.  (I think that's a word...  :P )

Speaking of jobs, if you are looking for some short-term work, Joe is looking for a few good developers.

NBehave + NSpec

 

So, quickly, I decided to go ahead and throw NSpec into the mix on top of NBehave.  Why not!  :)

Here is what the example from my previous post would look like using NSpec:

[Test, Story]
        public void Load_checkout_information()
        {
            CheckoutOrderDTO checkoutOrderDTO = new CheckoutOrderDTO();
            ShoppingCartDTO shoppingCartDTO = new ShoppingCartDTO();
            IList<LookupDTO> listOfCreditCards = new List<LookupDTO>();

            Story story = new Story("Load checkout information");

            story
                .AsA("controller that is responsible for performing the checkout process")
                .IWant("to load the checkout information based on the current user's pending order")
                .SoThat("I can edit the customer's information before submitting the order");

            story
                .WithScenario("Order is ready to be checked out")

                    .Given("controller is prepared", delegate { PrepareController(controller, "checkout", "index"); })
                        .And("pending order is retrieved from checkout service",
                            delegate { Expect.Call(mockCheckoutService.GetOrderForCheckout()).Return(checkoutOrderDTO); })
                        .And("shopping cart is retrieved from shopping cart service",
                            delegate { Expect.Call(mockBasketService.GetShoppingCart()).Return(shoppingCartDTO); })
                        .And("list of acceptable credit card types are retrieved from credit card lookup service",
                            delegate { Expect.Call(mockCreditCardLookupService.GetAllCreditCardTypes()).Return(listOfCreditCards); })
                        .And("mock object framework has stopped recording", delegate { mockery.ReplayAll(); })

                    .When("the index action is executed", delegate { controller.Index(); })

                    .Then("the pending order should exist in the property bag with key of", PB.CheckoutOrder,
                            delegate(string key) { Specify.That(controller.PropertyBag[key]).ShouldEqual(checkoutOrderDTO); })
                        .And("the shopping cart should exist in the property bag with key of", PB.ShoppingCart,
                            delegate(string key) { Specify.That(controller.PropertyBag[key]).ShouldEqual(shoppingCartDTO); })
                        .And("the list of accepted credit card types should exist in the property bag with key of", PB.AllCreditCardTypes,
                            delegate(string key) { Specify.That(controller.PropertyBag[key]).ShouldEqual(listOfCreditCards); });
        }

 

Of course I know that the use of NSpec here is basically just syntactic sugar over the Assert statement, but it definitely reads better.

NBehave Experiment: MonoRail Controllers & Rhino Mocks

 

...whoever keeps His word, truly the love of God is perfected in him. By this we know that we are in Him. -- 1 John 2:5

Well I decided it was finally time I took a look at NBehave as another one of those tools to have in my toolbox.  NBehave's primary use seems to be in the domain model for implementing stories from the user's perspective, which obviously sounds very powerful. 

But I specifically wanted to see how NBehave would "behave" (sorry...) for driving out my MonoRail controllers along with mock objects for mocking out the back-end services as I do now.  In other words, making the controller itself, the "person" interacting with the system using controller-specific terminology.

So I thought I would take one of my existing controller tests and convert it to a NBehave-type story/scenario.  Here is my original old-school test:

   1: [Test]
   2: public void Should_load_pending_order_and_shopping_cart_and_list_of_acceptable_credit_card_types()
   3: {
   4:     CheckoutOrderDTO checkoutOrderDTO = new CheckoutOrderDTO();
   5:     ShoppingCartDTO shoppingCartDTO = new ShoppingCartDTO();
   6:     IList<LookupDTO> listOfCreditCards = new List<LookupDTO>();
   7:  
   8:     using (mockery.Record())
   9:     {
  10:         PrepareController(controller, "checkout", "index");
  11:         Expect.Call(mockCheckoutService.GetOrderForCheckout()).Return(checkoutOrderDTO);
  12:         Expect.Call(mockBasketService.GetShoppingCart()).Return(shoppingCartDTO);
  13:         Expect.Call(mockCreditCardLookupService.GetAllCreditCardTypes()).Return(listOfCreditCards);
  14:     }
  15:  
  16:     using (mockery.Playback())
  17:     {
  18:         controller.Index();
  19:         Assert.AreEqual(checkoutOrderDTO, controller.PropertyBag[PB.CheckoutOrder]);
  20:         Assert.AreEqual(shoppingCartDTO, controller.PropertyBag[PB.ShoppingCart]);
  21:         Assert.AreEqual(listOfCreditCards, controller.PropertyBag[PB.AllCreditCardTypes]);
  22:     }
  23: }

 

Since I tend to be very verbose in my test naming, sometimes they can become unwieldy.  Of course every time my test names get too long, I start questioning whether the unit of code I'm testing is trying to do too much, thus violating SRP.  But in this case, I'm simply loading up 3 pieces of data from various services.  (Yes, I realize the service communication here is becoming a bit chatty, and a refactoring task is definitely on the radar, but that's not really the focus for this post).  :)

Anyway, I wanted to see what this test would look like as a NBehave story.  Here goes...

(sorry for the code wrappage)

   1: [Test, Story]
   2: public void Load_checkout_information()
   3: {
   4:     CheckoutOrderDTO checkoutOrderDTO = new CheckoutOrderDTO();
   5:     ShoppingCartDTO shoppingCartDTO = new ShoppingCartDTO();
   6:     IList<LookupDTO> listOfCreditCards = new List<LookupDTO>();
   7:  
   8:     Story story = new Story("Load checkout information");
   9:  
  10:     story
  11:         .AsA("controller that is responsible for performing the checkout process")
  12:         .IWant("to load the checkout information based on the current user's pending order")
  13:         .SoThat("I can edit the customer's information before submitting the order");
  14:  
  15:     story
  16:         .WithScenario("Order is ready to be checked out")
  17:  
  18:             .Given("controller is prepared", delegate { PrepareController(controller, "checkout", "index"); })
  19:                 .And("pending order is retrieved from checkout service",
  20:                     delegate { Expect.Call(mockCheckoutService.GetOrderForCheckout()).Return(checkoutOrderDTO); })
  21:                 .And("shopping cart is retrieved from shopping cart service",
  22:                     delegate { Expect.Call(mockBasketService.GetShoppingCart()).Return(shoppingCartDTO); })
  23:                 .And("list of acceptable credit card types are retrieved from credit card lookup service",
  24:                     delegate { Expect.Call(mockCreditCardLookupService.GetAllCreditCardTypes()).Return(listOfCreditCards); mockery.ReplayAll(); })
  25:  
  26:             .When("the index action is executed", delegate { controller.Index(); })
  27:  
  28:             .Then("the pending order should exist in the property bag with key of", PB.CheckoutOrder,
  29:                     delegate(string key) { Assert.AreEqual(checkoutOrderDTO, controller.PropertyBag[key]); })
  30:                 .And("the shopping cart should exist in the property bag with key of", PB.ShoppingCart,
  31:                     delegate(string key) { Assert.AreEqual(shoppingCartDTO, controller.PropertyBag[key]); })
  32:                 .And("the list of accepted credit card types should exist in the property bag with key of", PB.AllCreditCardTypes,
  33:                     delegate(string key) { Assert.AreEqual(listOfCreditCards, controller.PropertyBag[key]); });
  34: }

 

But the real beauty is the generated output:

 

Theme: Checkout Process

    Story: Load checkout information
    
    Narrative:
        As a controller that is responsible for performing the checkout process
        I want to load the checkout information based on the current user's pending order
        So that I can edit the customer's information before submitting the order
    
        Scenario 1: Order is ready to be checked out
            Given controller is prepared
                And pending order is retrieved from checkout service
                And shopping cart is retrieved from shopping cart service
                And list of acceptable credit card types are retrieved from credit card lookup service
            When the index action is executed
            Then the pending order should exist in the property bag with key of: order
                And the shopping cart should exist in the property bag with key of: shoppingCart
                And the list of accepted credit card types should exist in the property bag with key of: allCreditCardTypes

 

As the title of this post states, this is merely an experiment at this point.  But I do think it better expresses exactly what the controller is doing vs the non-NBehave test above. 

One extension I would like to add to the NBehave framework is some built-in support for mock object frameworks.  I don't necessarily think a specific mock object framework should be integrated into NBehave, but for my own purposes, I'm thinking about adding support for the Given scope to implicitly signal to Rhino Mocks to stop recording.  As you can see, for now I had to include it in my last Given block like this:

.And("list of acceptable credit card types are retrieved from credit card lookup service",
                            delegate { Expect.Call(mockCreditCardLookupService.GetAllCreditCardTypes()).Return(listOfCreditCards); mockery.ReplayAll(); })

 

I suppose I could do something silly like this:

.And("mock object framework has stopped recording", delegate { mockery.ReplayAll(); })

 

But that would litter the nicely generated output with "test" specific terminology which I'm not very cool with.  This extension could probably be achieved using a simple decorator/interceptor, but won't know for sure until I peek at the source.  :)

What do you think?  Is this over-complicating things? Or could it be an elegant way for expressing what is actually going on in the controllers?

Agile Web Development with Rails - Chapter 5

 

What!  You tease me with code in Chapter 4 and now there is none in this chapter?!?  Oh wait, I guess we should at least figure out what we want to build moving forward.  :)

Chapter 5

Well this chapter is all about doing some very high level use cases, page flows and a quick data diagram.  It's just scribbled on a piece of paper, so it's nowhere near as scary as a "dysfunctional requirement" or UML diagram.  It's your basic e-commerce application.  Which is fitting since I'm actually right in the middle of an e-commerce project at my "day job" which I'm building with MonoRail. 

<side_note>

Speaking of MonoRail, was chatting with a friend earlier and he mentioned that it would be nice to see some comparisons of MonoRail and RoR during this whole process.  I figured some of those comparisons would naturally make there way as I move through the book.  So I'll try and make a more concerted effort to point out the important differences as I come across them.

</side_note>

So that's really all that's in this chapter.  Dave does point out how RoR fits in perfectly with agile because of the ability to make such quick on-the-fly type of changes and the customers can be involved more often.

Alright, next I get to write some code again!

Agile Web Development with Rails - Chapter 4

 

Cool!  Now I get to start building stuff.

Chapter 4 

I just pop open my kermit green command line window and type "rails demo".  And BAM!  We've got ourselves an application!  Ok, so it might not do much yet.  But it's given me a nice "filing cabinet" to keep everything organized.  Everything from the controllers source code, views, database scripts, test fixtures, configuration files, log files, scripts, images, etc.  All in a nicely organized tree.  Very nice.

Now I just fire up a the built-in web server using "ruby script\server", open up browser and there we go.  We have a full working application.  That entire process, from generating the application, starting the server and browsing to the application literally took about 5 seconds. 

At this point it takes me through the obligatory Hello World implementation.  I can just use the rails generator to create a controller named "Say" with a method named "Hello", then create a quick rhtml view named "hello.rhtml" in the appropriate app\views\say directory and that's it.  What's really great about all of this style of development is that I never have to restart the internal web server because in development mode, automatically detects file changes and reloads them instantly.  Try that in C#.

Then it just takes me through adding some controller code and I get to discover some more of the elegance of the Ruby language.  Stuff like "3.times" and "1.hour.from_now".  How cool is that!  Some basic ERb (Embedded Ruby) commands are then shown for linking to other actions.  I'm pretty familiar with this kind of thing in MonoRail already.  The way you can use hashes in Ruby is very nice, and is very similar to how Ayende implemented then in Brail. 

Well that's about it for now.  This was just a demo app.  Looks like next I get to start building a "real" application.  Woohoo!  :)

Ruby, so easy a wife can do it

 

I just have to share this.  So my wife asks me why I'm learning this new thing called Ruby.  She's usually not interested in the specifics of the programming languages I use.  (A few years ago, she asked me, "what's that C-Pound book you're reading?"  :)

So I broke out a pen and paper and wrote these 2 lines:

  • DateTime.Now.AddHours(1)
  • 1.hour.from_now

I asked her which one did she think was easier to understand.  She said "obviously, the 2nd one".  Bingo!

Then I wrote her another couple of lines:

  • for (int i=0; i<=3; i++) { // do something }
  • 3.times.do //something

Same question and she pointed at the first one in disgust and again said the 2nd was much easier to write.  Then she asked me why I'm not doing everything using the 2nd one.  Sadly, I couldn't really come with a good answer to that one except to say that it's just now gaining traction (even though it's been around for long time), it's open source, it doesn't come from Microsoft, blah blah.

Needless to say, the fact that my wife is telling me I need to start using Ruby more is definitely a sign.  Just not sure of what it's a sign of...

Agile Web Development with Rails - Chapter 3

 

Hmm, well I've already zoomed through to chapter 8 in my actual reading/coding.  Better start getting these notes cranked out.  Oh, and why not purchase the book yourself and follow along.  It'd be interesting to get comments from other folks who are currently going through the RoR learning experience.

Chapter 3

This chapter mainly deals with the infrastructure of getting Ruby and the Rails framework installed, along with MySQL.  Luckily us 'softies on Windows can just use the very cool InstantRails package, which is a 100% self-contained package of Ruby, Rails, MySQL and even an Apache web server with no actual installation required.  Yep, this got added to my portable app library very quickly.  Installation on Mac and Linux are also covered, which may come in handy one day when I'm able to get one of these.  (I am accepting donations...)  :)

Using the command-line, a blip on version control and editors are covered next.  It's interesting to me that so far I have NOT missed my fancy VS 2005 IDE when coding Ruby.  Dave points this out and offers a quick plug for TextMate, which is pretty much everyone's favorite editor for coding in the Ruby community, and from what I've seen, I can understand.  But alas, us Windows users are left out in the cold again.  Although I have been using what might be the next best thing to TextMate for Windows which is the e text editor.  It seems to have a lot of the features of TextMate and can even use the exact same bundles, which is where most of the editing power comes from.

Database support is pretty good in Rails as well, with all the major ones supported.  Most folks seem to stick with MySQL which is fine by me.  But SQL Server is supported for all of you who feel like you just *have* to keep one foot in the Microsoft camp.  ;)

And finally, we get a little taste of something called RubyGems.  This is one of the really cool things that seems to be missing from every other framework I've worked with.  The ability to issue a simple command at a command-line and have the entire framework and plugins downloaded and/or updated, including all of its dependencies is extremely useful.  It even keeps a history of the previous versions.  Genius, I say!  In .NET, imagine how much time has been wasted by having to open a browser, finding the framework/plugin update you're looking for, downloading it, unzipping it and copying the assemblies to your project folder.  Oh, and don't forget that you have to update your project "references", blah, blah. 

<side_note>

As I'm starting to build my first RoR application (even though it's the sample from the book), I'm starting to realize just how much time is wasted on non-business related "things" when coding in .NET with VS 2005. 

NOT ONCE have I had to:

  • Add New Project
  • Add Project References
  • Even Compile!

Of course, tools like ReSharper definitely help speed things up, coding-wise.  But you still have to muck around all of the "features" of VS 2005 like projects and references.  I'm starting to imagine how much faster I could deliver more business value if I didn't have to worry about stuff like this.

</side_note>

Agile Web Development with Rails - Chapter 2

 

Got.  To.  Learn.  Ruby.  On.  Rails.

Chapter 2

Chapter 1 was mainly a high-level introduction to Ruby and the Rails framework.  Chapter 2 starts off with some of the history behind the MVC pattern and how it was originally intended for "fat" client applications.  It's interesting that when developers first started building web applications, they seemed to largely ignore patterns like MVC and just shoved everything together.  We developers soon wised up and came up with various frameworks like Struts and ASP.NET WebForms (which is a very poor implementation of MVC, IMHO). 

It then goes into the basics of how MVC works, which I won't bother to repeat here, since most folks who read my blog are probably already familiar with it.  But they do a fine job of introducing how the MVC pattern works in Chapter 2 which is obviously essential in order to use an MVC framework like Rails.

And now we come to the touchy subject of the Active Record pattern.  I have a love/hate relationship with the Active Record pattern.  While I love its simplicity and ability to get something running very quickly, I'm also a huge proponent of Domain-Driven Design and rich domain models with persistent ignorant (PI) domain objects.  Castle's ActiveRecord implementation is quite nice, however, especially since it allows you to use an ActiveRecordMediator instead of having to subclass your domain objects.  Many folks have talked about DDD within the context of the Active Record pattern.  Nelson shares his thoughts on Castle's ActiveRecord from a DDD perspective on his blog.

At this point, Active Record in Rails is starting to grow on me, because I understand that the Rails framework is an "opinionated framework" and should only be used when it's a good fit for your particular project.  Although, if you haven't watched it yet, I would highly recommend you watch this keynote from DHH at RailsConf 2006.  David makes some very interesting points about how often you may think something is not CRUD, when in fact it really could be.  Then we get to see some more Ruby code, this time dealing with retrieving and saving objects using Active Record.  Again, the elegance of the code just blows me away. 

And finally is what they call Action Pack.  This pretty much encompasses the "V" & "C" parts of MVC.  View and Controller. 

The 3 main view template types are explained a little, rhtml, rjs and rxml.  Views using rhtml are basically the same as brail views (.brail) if you're familiar with MonoRail.  They are just html files with ruby code sprinkled in to make the pages dynamic.  Rjs views are similar to brailjs views in MonoRail and are primarily used for javascript fragments and AJAX.  Rxml views sound very interesting.  Being that I'm not a fan of hand-writing XML files, I'm excited to see how I can use the ruby language to generate XML documents.

The Controller is where everything starts.  It's responsible for things like routing, caching and session management.  It's also where most of the interaction with your Model will take place. 

This chapter is wrapped up by telling you that now it's time to start building some stuff.  Schweet!  :)

Another Quick Tip: Asserting view renders in a MonoRail controller test

 

This is another one of those "blog it so I can remember it" posts.

My last post about a similar tip was relating to asserting redirects in a MonoRail controller.  This one deals with asserting which view is being rendered in your controller when only RenderView is called.

Controller Code
   1: public class CheckoutController : BaseController
   2: {
   3:     public void ValidateOrder(CheckoutOrderDTO orderToValidate)
   4:     {
   5:         // code to validate order
   6:  
   7:         RenderView("review");
   8:     }
   9: }
Controller Test Code
   1: Assert.AreEqual(@"checkout\review", controller.SelectedViewName);

 

It's a subtle difference from asserting redirects, because it doesn't require the leading "/" or the ".rails" extension to be included.

Agile Web Development with Rails - Chapter 1

 

As I mentioned previously, I'm starting to dig into the Ruby language for its elegance and the Rails framework in search of better, more efficient ways to develop web applications.  As part of this learning process, I figured it was essential that I pick up and read Agile Web Development with Rails (PDF edition for me).  I'm going to take some brief notes on each chapter and figured I'd use my blog for storing them.  :)  (To basically act as chapter reviews)

Chapter 1

This is just a basic introduction to the Ruby language and Rails as an MVC framework.  I like the fact that they throw some Ruby code right in your face from the start, because it immediately shows the elegance of the Ruby language and makes you want to start writing code like that now.  The two main concepts that Rails embraces is the DRY principle and "convention over configuration".  I gave an example of refactoring towards DRY code in a recent post, so I'm not going to elaborate on DRY too much here, because really, it just makes sense.  I'm a huge fan of "convention over configuration" and it's something that I've been practicing more and more in the .NET world.  If nothing else, just a common source tree structure.  Someone I was listening to put it like this. 

"It's like a big filing cabinet with labels that tell you where to put stuff".   -- ??

I'm really not a fan of XML configuration files.  In fact, I need to get off my tail and replace our growing Windsor XML configuration file with Binsor which uses my new favorite .NET language, Boo (Note to self: start here).  So, I'm very interested to see how this plays out with the Rails framework.

Ajax and RESTful interfaces are briefly mentioned as well, both of which have built-in support in Rails.  Deployment and rollbacks are touted as "easy", so of course I'm very interested in that as well.  Having built some crazy deployment scenarios by hand using NAnt in the past, I'm looking forward to some of this being "out of the box".

Maybe one of the best things about Rails framework that already gets a lot of points in my book is that it was harvested from an existing commercial application.  Hopefully by now, most of us know that the best frameworks are extracted from existing, tried and true applications.  I've been forced to use "pre-built application frameworks" in the past, and they have been so painful to work with.

Since the title of the book has a focus on agile development, it gives a quick introduction as to why the Rails framework enables a team to be agile.  It seems the core of the reason is that you can really crank out working features and respond to changes very quickly using Rails, which tends to be a fundamental to the success of agile projects.

Oh and they point out how fun writing code is when using Ruby on the Rails framework.  Since I'm already a bit of a geek, I actually enjoy coding most of the time already.  If you see me start drumming on my desk or keyboard, that's usually a sign that I'm "in the zone" and am actually getting stuff done.  :)

Anyway, the rest of the first chapter is just a brief guideline on how to read the book (I'm assuming one line after another, hehe).

That's it for now.  Since I have already started some Ruby coding, the appetite is already there to keep digging in more. 

Until next time...

Courage-Driven Blogging

 

When wisdom enters your heart, And knowledge is pleasant to your soul, Discretion will preserve you; Understanding will keep you, -- Proverbs 2:10-11

One of the reasons I blog and specifically, post code to my blog, is that I really learn a lot from other folks in the community.  It's like we're all one big team, sitting in a "virtual" collaborative environment, constantly striving for perfection (which will never happen, of course).

An interesting thing about this, is that it requires one of the core values of XP, Courage.  I truly never know how what I post is going to be received.  A lot of times it's just some crazy idea that I'm experimenting with or more often it's applying and/or extending something I've picked up from someone else.  Either way, sometimes it's good to hear "you're crazy" or "well, I would've done it like this", because it allows me to learn different/better ways of doing things.  Even if it sometimes stings.  Though I've noticed that as I progress into more of an agile developer,  the sting lessens.  Because after all, "there are no smart guys, there's only us".

Of course this is beneficial to me, but more importantly, it will hopefully benefit the teams and clients that I work with.

Building the often needed anti-corruption layer

 

The fear of the LORD is the beginning of knowledge, But fools despise wisdom and instruction.  -- Proverbs 1:7

"Agile Joe" and I were chatting about the challenges of building on top of existing application platforms, specifically ones like Microsoft CRM (which Ayende is painfully dealing with) and Commerce Server 2007, which is what I'm dealing with on my current project.  Joe pointed out the importance of building an anti-corrruption layer.  And I couldn't agree more.  In fact, since I'm using DDD as much as I can on this project, we've been able to deliver early customer demos showing working features, end to end, using stubbed repositories. 

To get a better picture, this is basically how the design of the system is shaping up so far:

MVC Web UI MonoRail of course.  :)
DTOs (Screen-specific) 2 way databound using MonoRail's most excellent DataBinder
Thin Service Layer To simply act as a facade to expose business operations and to handle the DTO => Domain Object mappings
Domain Model With all the entities, value objects, factories, specifications, etc. that you would expect.  I also keep the public interfaces to my Repositories in my domain model, but the specific implementations of them in a Persistence layer.
Persistence Layer - Stubbed These are just some in-memory repository implementations which have allowed us to demonstrate working features to the customer very early in the project.
Persistence Layer - CS 2007? This one is yet to be, but is what I have in mind when we start integrating with CS 2007 soon.  This would basically act as our "anti-corruption layer" between CS 2007 and our domain model.

 

It seems the recommended approach for implementing an anti-corruption layer is to treat is as another Service Layer.  From our perspective, I don't see much of a difference in using Repository implementations in the same way.  Especially since in our case, most of our integration with Commerce Server will be dealing with persisting/retrieving data.  On a related note, I'm starting to realize that MS application platforms like Commerce Server are nothing more than a pre-built legacy database for your application.  Hence the need to localize the nastiness involved with extending and integrating with it, in an anti-corruption layer.

The one advantage I do see by treating this integration layer as another Service Layer, is in the fact that in reality there will be a lot more going on behind the scenes besides just a bunch of persistence method calls.  Since Commerce Server has its own wannabe entities in the form of weakly-typed datasets (yes! you heard that right) and untestable classes, we're going to have to build another set of mappers that can translate between our domain model and our extended CS 2007 "entities".  Along with things dealing with the CS 2007 context, etc. 

We've already identified the need to have an extensive set of automated integration tests to drive out this anti-corruption layer.  So I'm sure I'll have a lot more to say on that as we progress.  Unfortunately it looks like it's going to require some fairly complex test set up logic to get a test instance of CS 2007 configured in an automated fashion.

Like most instances where you have to extend and integrate with an existing platform such as Commerce Server, I keep wondering if all this time we're having to spend will be worth it vs. "rolling our own" as they say.  Guess we'll see.

Any thoughts on this approach?  Am I just completely mad?  :)

The importance of tools to a software craftsman

 

And I have filled him with the spirit of God, in wisdom, and in understanding, and in knowledge, and in all manner of workmanship -- Exodus 31:3

Folks often wonder why I carry my keyboard around with me everywhere there is a chance I need to write some code.  Bringing it home every night from work, carrying it with me to client sites, etc.  Here's my (possibly feeble) attempt to try and give an answer as to why.

I like the term software craftsman very much.  For example, I'm sure folks who do carpentry for a living have their favorite tool(s) that they have mastered.  This allows them to produce some beautiful work with great attention to detail.  And the fact that they have learned to use their tool(s) effectively probably means they can work very efficiently.

This is exactly how I see the tools I use to build software.  Let's face it, you're not going to get very far building software without a good keyboard.  And I'd go one step further and say you're not going to build software very efficiently if you're not using your keyboard effectively.  And that applies to more than just your keyboard of course.  For all of you other 'softies out there that have to use Visual Studio, if you're not using a productivity add-in like CodeRush, or my long-time favorite, ReSharper, then you're not working anywhere near as efficiently as you could/should be working.  And frankly, it's not that hard to point out the overwhelming value that such tools can bring vs. their cost.

So I guess I would just encourage folks to acquire and learn to master the tools necessary to be as productive as you possibly can as a software craftsman. 

Fresh simplistic look

 

Trust in the LORD with all your heart, And lean not on your own understanding; In all your ways acknowledge Him, And He shall direct your paths. -- Proverbs 3:5-6

The origami skin, while very nice looking, was just getting too busy for me.  So I decided to port over one of my favorite simplistic skins, Scribbish, to Subtext.  I still have a couple minor tweaks to do, but I'm pretty happy with it.

Let me know what you think!

Quick Tip: Asserting response redirects in a MonoRail controller test

 

Reading this post by Sean reminded me of when I first started using the trunk's BaseControllerTest.  One nifty little property on the base test controller's mock Response object is RedirectedTo.  So you can do something like this:

   1: // some call on the controller that should do the redirect
   2: Assert.AreEqual("/productSearch/performSearch.rails", Response.RedirectedTo);

In previous MonoRail projects, I used the very nice base class from the guys at Eleutian and it worked great.  But I've been using the trunk's BaseControllerTest exclusively on my current project since it started a few months ago and it rocks as well.  Nice to have it "out of the box" now.

Refactoring towards a DRY, fluent interface

 

But I (Jesus) say to you, love your enemies, bless those who curse you, do good to those who hate you, and pray for those who spitefully use you and persecute you -- Matthew 5:44

Problem

In my current project, I have an application service that is used to make various modifications to a shopping cart, like adding cart items, applying discounts, changing quantities, etc.  Well as this service class evolved, the methods were starting to look like this...

   1: public void ApplyDiscountToShoppingCart(decimal discount)
   2: {
   3:     IShoppingCart shoppingCart = shoppingCartRepository.GetCurrentShoppingCart();
   4:     shoppingCart.ApplyDiscountOf(discount);
   5:  
   6:     shoppingCartRepository.Save(shoppingCart);
   7: }
   8:  
   9: public void AddToCartUsing(string productId, int quantityToAdd)
  10: {