Carpool Project: Part #3

My first question was “where do I put the POCOs?” I can put them in the Models folder in the MVC solution – there is already a ChangePassword, Logon, and Register Model there. They are all POCOs with some validation attributes added.

However, those Models only exist in context of the MVC application – they are not in the Domain. Therefore, I am leaning to putting the Domain POCOs in the Domain Layer (as recommended in DDD). I then realized I could use the Layering diagram in VS2010 – Yippie!

Carpool11

I note that the data layer is not abstract enough – rather it is the implementation. I just didn’t know what to call it

My next big thought – do I add validation attributes to POCOs? Without actually trying anything, I learned towards yes – so I can get the built in features of MVC validation.

I then went back and removed the class name from the properties (CarPoolId is now Id, etc…) to make the code more readable.

My next dilemma has to do with dependency properties. Consider this class:

1 public class SwimmerSummary 2 { 3 public int SwimmerId { get; set; } 4 public string SwimmerName { get; set; } 5 public int SwimGroupId { get; set; } 6 public string SwimGroupName { get; set; } 7 public int SwimTeamId { get; set; } 8 public string SwimTeamName { get; set; } 9 } 10  

I want to assign the Swimmer Group on the UI, perhaps change the name, perhaps assign a new team. The problem is that I run the risk of changing the Swim Team and Swim Group to an invalid state. I can limit the Update to group and put the swim team name into the swim group name, but that is not what I want. Do I need to check the group and team on each update and make sure that it is valid? I think yes – that is what the factory can do…

I then thought about how I want to signal that the ViewModels are valid. I realized the pattern that Rob and I used on another project will work well. I inherit from a base class that has 2 properties: IsValid and List<Errors> that can be traversed.

I wondered then if I needed two validation mechanisms: using attributes on the properties and then using this IsValid pattern. I think the answer is yes – you can signal to the UI the required length and IsNull validation via the attributes, but then you also can have a return on every CRUD to say if the class is OK.

Note that I have not tested anything yet – there is nothing to test. Testing getters and setters without any custom logic is testing the .NET framework – which is a waste of time. My code coverage is 0, but that is fine.

I now have enough of my Domain Model conceptualized to set up a backing store.  In this case, a SQL Server 2008 database.  Since a picture can say a thousand words:

Carpool12

Once the database was done, I set up my Entity Framework Model:

Carpool13

My data layer was then setup well enough to continue into the business layer…

Carpool Project: Part #2

The next section in DDD is about factories – where you create classes that control the creation and updating of these . These classes are not part of the domain model but are part of the domain design. That would be easy enough to do right now and I have taken that approach on several projects, but I want to take a different approach using POCOs and ViewModels. The problem with DDD is that only have 1 representation of an entity/value object. In most applications, there are different flavors of a given value object and depending on the circumstances, different behaviors from the objects.

I then thought of soft drinks. You have a base class – Coke – for example. From that, you have Cherry Coke, Vanilla Coke, etc… Each one of these specialty flavors start with the base Coke and then add something new to it. In addition, some other flavors of Coke (Diet Coke) actually DON’T start with the base Coke. This distinction points directly to Evan’s notion of ubiquitous language.

Going back to the Coke example, you can either use 1 factory that can spit out any flavor of Coke (G0f4 Factory/Builder pattern) or 2 Factories. Factory #1 takes in raw materials and spits out base Coke. This base code can then be used directly by the Consumer(UI). The base Coke can then also be used by Factory #2 that takes in base Coke and some flavoring and spits out Cherry Coke. From a design point of view – does it make sense to have a factory for each variety of Coke? In addition, what happens when a new flavor is invented? Is it better to make a new factory or just add a new loading/unloading bay to an existing factory?

I suspect, like most things, that the answer is not clear-cut. Given the choice of 1 uber-class with lots of methods (or 1 method with multiple inputs via dependency injection) or many classes (like a plant – many factories in 1 place), I lean toward the later. Creating classes are cheap and as long as they use an interface (or a base abstract class) you can enforce some rigor in its construction. In addition, if you have some business logic around Cherry Coke, the code has to written somewhere. Using DI, many classes, or any other technique does not magically remove the need to write fewer lines of code (assuming all are following DRY principles). So if the code needs to be written somewhere – where is it better to be placed? My answer follows Martin and Fowler – more classes with functions that do only 1 thing. Organizing projects via namespaces and VS2010 is a snap and the benefit of having clear-cut responsibilities is clear.

Side note, the problem is that if you have a Brownfield app that many developers have touched over the years. Some might believe in 1 factory using DI, others might believe in 1 factory using extension methods, still others might believe in a plant concept. What happens when all do what they want on the project? You get a mess. That is why having readable code, ubiquitous language, and a standard domain design is so important.

I then launched into DDD’s section on specification – specifically predicates. An example shows better than a textual explanation. Is it better to have a Trip.IsInvalid() method with a collection of invalid reasons, a Trip.HasNoDiver() method + Trip.DoesNotCoverPractice() method, etc.., or an InvalidTrip Class() with a property that gives the collection of invalid, or an TripHasNoDriver() class? I can see the merits of all 4 possible solutions – I generally use the 1st option – but just because I used it before does not mean it is the right way. DDD recommends the 4th option – having a class for every violation of business rules. Depending on the number of business rules, this solution can get pretty unwieldy. Since I am doing this exercise as a chance to learn, I will try option 4 and see where it gets me…

I wanted to start building factories but I wanted to do it in context of the POCOs that the Presentation Layer will consume. I am using a ViewModel pattern so I started listing POCOs that tie directly to the User Stories. Here is my strategy:

· Build a View Model (using an interface or an abstract class)

· Build a Factory – input is the Domain Model, output is the View Model

· Wire it up

My 1st stop is the Car Pool Class (renamed from Trip to have ubiquitous language). Taking the Domain Model’s Car Pool, I stubbed out what the 1st Car Pool View Model would look like:

Carpool07

Notice that the ViewModel Car Pool takes all references and makes them the description of the reference – effectively taking classes and making the strings. My first question – what do I call the Car Pool View Model? Since there can be an infinite number of CarPool-based View Models, I need something that is descriptive enough but still allow for additional View Models – CarPool1 won’t cut it. My typical naming is to call it CarPoolSummary but that locks me in because what if I need two different types of summaries? I then thought that if the summary class covers all of the Car Pool class, I can always subtract fields in the View. I then thought – but if I do that, I am getting away from 1 ViewModel per View. I then decided to tie my class to the actual view that it is supporting – the CarPoolSummary ViewModel will tie to the Summary View. Not great, but I will work though the permutations to see how well this holds up.

My model now looks like:

Carpool08

I then went to add another View Model based on the next Use Case when I realized I really need a description field for each car pool. This string needs to be a combination of Dates/Times/Teams/SwimmerGroups – something to show the user. I then added the next View Model like so:

Carpool09

Calling two points a trend, I then finished the rest of the view models. Note that I made the following changes:

· The car pool description changes depending on if the driver has been assigned, the swim team/groups, and the time leaving.

· Most of the time, there is only 1 swim group per practice. Occasionally, practices are combined with groups (but never teams).

· I removed calculated fields from the Domain model -> practice start and end times are in the domain model, practice length is in the view model

Here is the resulting View Model:

Carpool10

I think this enough to go with, so I then went to write my POCOs.

Carpool Project: Part #1

There are some kids in the neighborhood that need to get a lift over to a local swim center for swim team practice. The swim team practices year-round.

Currently, there is an Excel spreadsheet on a Live Account. I went to add functionality to the Excel spreadsheet and learned that you cannot do conditional filtering in an on-line copy.

I checked out some on-line carpool sites and realized they were a bit of an overkill

I then thought I can build a car pool site and in the process, work through using the Architectural features of VS2010 and apply what I am learning in Domain Driven Design.

Carpool01

Step #1: Set Up the Infrastructure

I set up the needed infrastructure on WinHost and locally for the new solution. I won’t go into the details here.

Step #2: Set Up the Domain Model and Use Cases/User Stories

I opened VS2010 and set up a basic class diagram that captures the data elements that are included in the current Excel workbook. I added multiple swim teams in case there are some people in the neighborhood that want to jump in…

Carpool02

Based on this class diagram, I started entering some user stories into TFS (I am using the Agile template). Here is the 1st one:

Carpool03

Here are the user stories:
Notification

· The carpool that my child is in now has a driver

· Your child is in a carpool without a driver and the practice is less than 24 hours away

· Admin notified on an error

Action – Standard User

· Need to sign up for a day

· Need to cancel for a day

· Need to add a child to a car pool

· Need to remove a child from a car pool

· Need to see the weekly schedule of carpools

Action – Administrator

· Need to add a new swimmer

· Need to add a new driver

· Need to change a swimmer to a new Swim Group

Non-Functional

· Person signs into the site

· Person changes their password

· Person updates their contact info

· All errors and logins are logged

I then thought about the POCOs that would be part of the ViewModel so I went back to my stories to identify the data elements that each story includes. I created my 1st query of all of the work items that I put into TFS. As you can see, I screwed up – I mistakenly made all of my User Stories Work Items:

Carpool04

Also, with the multiple practices, I realized that I needed to add the ability for the standard user to add new practices to a day, and then determine if 1 or 2 car pools are needed. Also, looking at the class diagram and reading DDD, I see that I need to add more stories. For example, does swimmer have an entry point? If so, then who can add/remove swimmers?

I looked at the class diagram again and realized I had to add for some more changes -> cars might have a max capacity, but the actual capacity changes for each trip – depending if there are siblings along for the ride. Also, the notion of the car is not needed, the trip can tell you who is the driver and the capacity allowed for the trip. My model changed to this.

Carpool05

I then went through Domain Driven Design – Chapters 5 & 6 – and tried to identify the Entity, Value, and Aggregate objects. Below is my initial thought.

Carpool06

The Root Entity is Trip and Practice. However, this is not right because the Root Entity has a global identity and the entities inside the aggregate are unique only within the aggregate. That is not the case – for example, the swim team is unique for the entire graph. The fact that the driver is not associated with the swim team doesn’t mean they are in different aggregates. Also, since nothing outside of the aggregate can hold a ref to the inside entities and Swimmers clearly need to be associated with a Swim Group/Team, this separation is not going to work.

After reading some more on aggregates and the canonical example of purchase order/line items, I think that I don’t have any aggregates.

Win Phone 7

I went to a Win7 conf last week:

http://www.msdnevents.com/Default.aspx?keyword=windows+phone+7+developer+launch

And will be going to another this week.  I will be trying to win7-ify my carpool project next.

TFS

I installed TFS on my local machine for version control and build services.  I got the version control working fine – using a MAIN/DEV/PROD branching strategy.  The problem is setting up the builds.  I installed the Build Server and Agent no problem on the local machine.  Then wanted to associate current Team Project Collection to the Build Controller:

 

However, when I went to the Build Controllers – there is no button to add it to the available list.

 

 

I decided to stop – b/c I really don’t need CI for my local workstation but I was getting excited to alter the build steps using WF4.0 – just to see it in action.

 

Looks like you need to install the Build Controller BEFORE you create a Team Collection – there is no way to retro-add a collection to a controller?  I Binged the error and no one has answered it (yet).  I also tried to alter the properties of the Build Server in TFS Explorer and cannot alter the url:

Humm, perhaps an enhancement for later…

Moving SQL Server between 2 Hosting Companies

I am moving a site from Host4Life to WinHost.  There were 2 high-level tasks:

Publish the website

Move the database

 

Publishing the website was easy.   All I had to do was to change the ftp address in Visual Studio 2010 Publish Website wizard

Moving the database was more complicated.  I tried 3 different ways using SQL Server Management Studio 2008 (SSMS):

1)      Backup/restore.  The backup failed on the default file location.  However, when I backed it  up not specifying the path, the backup worked.  Somewhere on Host4Life’s data servers is a file named Test.  In any event, the fact that I could not back up to my local file system in SSMS killed this idea.  I then tried to look for test but they have a new interface (tinyhost) and my SQL Server password did not work and there was no way I am interacting with those clowns at H4L’s help desk

2)      Copy Database.  I tried this next.  It failed when trying to copy from H4L to WinHost and H4L to my local file system.  I went through a couple of iterations with my local system – I made more progress once I enabled all of the SQL Server Services, but it ultimately failed and the log did not tell me why easily

3)      Scripting.  Ultimately, this is what worked for me.  I don’t know what version you can add scripting the data (shown here) but that made all the difference.  I scripted the tables, functions, views, and stored procs (fortunately, I don’t have any recursive dependencies in my objects) in order and the database came up as expected

CSS gotcha when using VS2010 and IE

I ran into a frustrating gotcha when using VS2010 and updating my .css.

I created the following .css entry:

/* Hidden Column

———————————————————*/

 

.noDisplay

{

    display:none;

}

 

I then implemented it in a basic MVC View:

    <table>

        <tr>

            <th class="noDisplay">

                RegionID

            </th>

            <th>

                RegionDescription

            </th>

        </tr>

 

    <% foreach (var item in Model) { %>

   

        <tr>

            <td class="noDisplay">

                <%: item.RegionID %>

            </td>

            <td>

                <%: item.RegionDescription %>

            </td>

        </tr>

   

    <% } %>

 

    </table>

 

I then spun up my site and started changing some things.  Interesting, every time I change a value in the .css, it was not reflected on the next spin up of the site.  Even if I closed the instance of Cassani running on the desktop, I was getting the same mysterious behavior.  After some frustrating experimenting (that you fiddler), I deduced that IE is caching the .css so as long as I was using the same url (localhost/xxx), the cached .css was being used – IE was not recognizing changes to the .css.  Ugh.

To get around IE’s limitation (perhaps there is also a setting – I haven’t checked yet), I changed the site address everytime.  How, you might ask?  Under Project Properities-> Web in VS:

 

Once I specified a different port for each run – IE would dedect a change in the address and re-load all of the filed – including the new .css.

For the record, this code

    <script type="text/javascript">

        function DisplayColumnIds() {

 

            $(".noDisplay:gt(0)").each(function () {

                var regionId = $(this).html();

                alert(regionId);

            });

 

        }   

    </script>

 

Detected the hidden field like a champ

 

VS2010, JQuery and Intellisense

I installed VS2010 this week.  I am not sure what took longer – installing 2010 or uninstalling 2008.  In any event, I am working on a JQuery project.  I was all hot to get JQuery intellisense on a Hello World MVC2 Project.  I did file-> New , carved out a Script block, and went to town:

 

 I was immediately confused -> only Javascript intellise.  After poking at the problem with Tinu for a couple of minutes, we realized that we need to add in the JQuery Script to get its intellisense

Did the trick

Another problem with JQuery was that some of the selectors were not working.  Consider this code block:

        $(function () {

            $("#sourceTable tr:gt(0)").draggable({

                revert: ‘invalid’,

                cursor: ‘move’

            });

 

When I fired up IE to see this working, nothing was draggable.  I then changed the selector to this:

$("#sourceTable").draggable({

And I had draggability (warning: new word alert) in IE.  After banging my head for an hour or so, I accidently clicked on compatibility mode on IE.  Low and Behold – it worked!  Lesson to the wise – if something doesn’t work as expected, blame IE….

Finally, just so you know – forgot to reference Ajax library, the message box you get is o so helpful:

Finally, really, is a quick reminder to myself about Fiddler:

 

 

JQuery and Caching

I ran into a problem this morning that is turning into something that is more than a little annoying.  I am cooking up some JQuery to allow drag and drop between two data tables.  Building slowly, I wrote the following JQuery: 

 

    <script type="text/javascript">

        $(function() {

            $("#sourceTable").draggable();

            $("#destinationTable").draggable();

        }

 

        );

      </script>

I then added an additional qualifier on the source table to only select the data rows

$("#sourceTable tr:gt(1)").draggable();

The problem is that it is not working.  Any other qualifier than TR does work – which makes no sense.

I then took these methods and put them into a seperate file.  I first tested with an alert – which worked fine

function jamie() {

    alert("setupDragDrop called");

}

However, once I renamed the target function to something more meaningful, it failed

function setupDragDrop() {

    alert("setupDragDrop called");

}

And the reason why is that I had a function with the same name (but different signature) created earlier.  The kicker is that the original function is commented out – but the browser is still calling it. 

I recompiled the solution and stopped the instance of Cassani running, to no avail.  I am wondering if I have to clear my IE cache.  If so, this is nutz.  There is no way I should need to go though all of those steps just to update a java script file.

–As an update, I noticed that the relative path in debugging mode was localhost\scripts\JQueryExtender.js.  I deleted all of the debugging symbols out of the /bin folder (both working and test) and it stuck.  I wonder why the debug symbols were not getting updated even when I recompiled…

 

 

Blog Engine and SQL Server

I spent my free time over the weekend doing taxes and family stuff, so I did not get to any code.  I did start working with BlogEngine to see if I can incorporate it into our website.  I ran into an interesting problem.  I wanted to change the data provider from an XML file in the app_data folder to a SQL Server database.  I ran the scripts no problem on a local instance of SQL Server.  I then created a SQL Server Login using SQL Server Authentication:

 
I then verified the login’s roles in the database. 

I then went to create a connection to the database via Visual Studio using a SQL Server Data Provider in a basic ASP.NET application:

And I get an error:

I then went out to SQL Server Management Studio and I also cannot login using those credentials.  I don’t know if there is something about Vista and SQL Server Authentication – I will continuing researching it.

I then changed the server role to sysadmin:

Changing the network library didn’t work:

 

I then tried starting all of the SQL Server related services – still no dice

Still failed

Finally, I then made sure that Sql Server Configuration allowed TCP and Shared Memory – it did

Then, in the words of Charlie Brown “There is no problem so large that you cannot run away from it”, I figured I would just use integrated security.

I changed the connection string in my web.config to this:

<add name="BlogEngine" connectionString="Server=.;Database=BlogEngine;Trusted_Connection=True;" providerName="System.Data.SqlClient"/>

And I added this line:

<identity impersonate="true" userName="xxx" password="yyy" />

I still got a login error regarding NT AUTHORITY\NETWORK SERVICE.  I then decided that if I couldn’t beat them, make my solution less secure.  I added NT AUTHORITY\NETWORK SERVICE to the server and database as sysadmin server role and datawriter and datareader database role.

It worked.  I am not happy, but it worked…