Carpool Project: Part #7

I am now moving into the site navigation of the carpool site. It was my 1st real foray into routing and after a couple of minutes, I realized it is straightforward. I had 2 controllers:

1 for the main page that shows 2 grids (current carpools and uncovered practices)

1 for the carpool update, insert, and delete pages

Here is an example of the Update method (so far):

1 public ActionResult Edit(int carpoolId) 2 { 3 Carpool.Domain.Carpool carpool = CarpoolFactory.GetCarpool(carpoolId); 4 return View(carpool); 5 } 6 7 [HttpPost] 8 public ActionResult Edit(int carpoolId, FormCollection collection) 9 { 10 try 11 { 12 Carpool.Domain.Carpool carpool = CarpoolFactory.GetCarpool(carpoolId); 13 UpdateModel(carpool); 14 CarpoolFactory.UpdateCarpool(carpool); 15 return RedirectToAction("Index"); 16 } 17 catch 18 { 19 return View(); 20 } 21 } 22  

 

I had to do some redirecting – there is no Index controller/page for the carpool as it is all handled out of Main.Index. I created the follwoign routes to allow me to redirect from one controller to the next:

1 routes.MapRoute( 2 "EditCarpool", 3 "Home/Edit", 4 new { controller = "Carpool", action = "Edit" } 5 ); 6 7 routes.MapRoute( 8 "CreateCarpool", 9 "Home/Create", 10 new { controller = "Carpool", action = "Create" } 11 ); 12 13 routes.MapRoute( 14 "DeleteCarpool", 15 "Home/Delete", 16 new { controller = "Carpool", action = "Delete" } 17 ); 18 19 routes.MapRoute( 20 "ReturnHome", 21 "Carpool", 22 new { controller = "Home", action = "Index", id = UrlParameter.Optional } 23 ); 24 25 routes.MapRoute( 26 "Default", // Route name 27   "{controller}/{action}/{id}", // URL with parameters 28 new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 29 ); 30

My only question is how to add in the parameter so it looks like Carpool/Update/2 and not Carpool/Update?carpoolId = 2

Carpool Project: Part #6

I finished the factories and the POCOs. I made some changes that simplified the model some – I set up 7 factories for the non-flattened POCOs and 1 factory for a flattened POCO:

carpool21

I will see if the other flattened POCOs are needed. With enough factories to make me dangerous, I then thought about how to organize the UI. Since this exercise is to help me work though the Architectual features of VS2010, I created an activity diagram based on some of the Use Cases:

carpool22

Note how I started documenting business rules. I went back to the Task list for each activity and added both the data elements and the business rules:

carpool23 

I then have enough to launch a tracer bullet that matches how I want the home page to be. The challenge is that the home page will actually show 2 independent grids that use different data elements:

· A list of all practices without a carpool

· A list of all carpools

I don’t know the best way to implement this in MVC. In prior projects, I had 1 controller for the page that handles the “primary” data elements and then some AJAX calls to dynamically populate the remaining grids. Another possible way is to have the page be a composite of 2 independent User Controls. A final way is to have the page controller’s model collection just include both data element sets and refer to each in the collection.

I had already tried Option #1 on a different project and found that it requires too much JavaScript code. I then explored Option #2. I set up my MVC’s project controllers to match the domain model like so:

carpool24

I then tried to wire up some User Controls for each of the controllers that I could then combine on the Default page. I quickly learned that MVC2 User Controls Are not well supported in the MVC community (30 minutes of Bing/Google/MSDN searches did not give me a specific example of MVC2 User Controls tied together in 1 page). I also realized that I was taking a “bottom-up” approach.

I then revamped my project to take a “top-down” approach. Incidentally, this option seems to be the “happy path” for MVC2. I removed all of the POCO controllers:

carpool25

And then added the POCOs that I want on the main page to the ViewModel Collection:

1 public ActionResult Index() 2 { 3 ViewData["Message"] = "Welcome to ASP.NET MVC!"; 4 ViewData["CurrentCarpoolSummaries"] = CarpoolSummaryFactory.GetCurrentWeekCarpoolSummaries(); 5 ViewData["UncoveredPraciceSummaries"] = PracticeSummaryFactory.GetCurrentWekUncoveredPracticeSummaries(); 6 7 return View(); 8 } 9  

And then wired up the UI:

1 <table> 2 <tr> 3 <th> 4 Id 5 </th> 6 <th> 7 Day 8 </th> 9 <th> 10 Date 11 </th> 12 <th> 13 Description 14 </th> 15 <th> 16 Pracitce(s) 17 </th> 18 <th> 19 Driver 20 </th> 21 <th> 22 Swimmer(s) 23 </th> 24 <th> 25 Remaining Seats 26 </th> 27 </tr> 28 29 <% foreach (Com.Tff.Carpool.Domain.CarpoolSummary carpoolSummary in ViewData["CurrentCarpoolSummaries"]) 30 { %> 31 32 <tr> 33 <td> 34 <%: carpoolSummary.Id%> 35 </td> 36 <td> 37 <%: carpoolSummary.DayDescription%> 38 </td> 39 <td> 40 <%: carpoolSummary.CarpoolDate%> 41 </td> 42 <td> 43 <%: carpoolSummary.CarpoolDescription%> 44 </td> 45 <td> 46 <%: carpoolSummary.PracticeDescription%> 47 </td> 48 <td> 49 <%: carpoolSummary.DriverDescription%> 50 </td> 51 <td> 52 <%: carpoolSummary.SwimmerDescription%> 53 </td> 54 <td> 55 <%: carpoolSummary.RemainingSeats%> 56 </td> 57 </tr> 58 59 <% } %> 60 </table> 61  

I ran into this problem:

carpool26

It looks like I need to cast it via the page Inherits method – but I have multiple datasets. I tried ignoring the error – hoping that the object resolves at run time. No such luck:

carpool27

So I went back and casted the model into the proper type:

1 <% foreach (Com.Tff.Carpool.Domain.CarpoolSummary carpoolSummary in (System.Collections.Generic.List<Com.Tff.Carpool.Domain.CarpoolSummary>)ViewData["CurrentCarpoolSummaries"])

And

1 <% foreach (Com.Tff.Carpool.Domain.PracticeSummary uncoveredPracticeSummaries in (System.Collections.Generic.List<Com.Tff.Carpool.Domain.PracticeSummary>)ViewData["UncoveredPraciceSummaries"])

And boom goes the dynamite…

carpool28

Carpool Project: Part #5

I am now building factories for my POCOs. I have a design question. Should POCOs hold the key to another object or an actual reference? DDD says that I should a reference and EF does that, but POCOs do not seem to pattern that way.

The choice is this:

1 public class Swimmer : ValidationBase 2 { 3 public int Id { get; set; } 4 public string Name { get; set; } 5 public SwimGroup SwimGroup { get; set; } 6 } 7  

or this (flattened class):

1 public class Swimmer : ValidationBase 2 { 3 public int Id { get; set; } 4 public string Name { get; set; } 5 public int SwimGroupId { get; set; } 6 public string SwimGroupName { get; set; } 7 } 8  

I see the benefits to both sides. On one hand, the flattened class (option #2) makes it very easy to code up the UI. On the other hand, option #2 is much more rigid and brittle – you can have lots of properties and a change to 1 entity class means that every value object that depends on the entity object has to change. You can add interfaces for each of the permutations of the flattened classes to account for change, but that becomes unwieldy.

After going back and forth a couple of times, I settled on doing both. I left my base class (Swimmer) as option #1 and then build a SwimmerSummary class that is option #2. With both, I will see what is easier to work with on the UI.

Starting on Option #1, I created a Swimmer Factory with a mapper function like this:

Carpool17

The problem is that the SwimGroup reference is expected my Domain-Defined class, not the EF class. I need to wire up a factory for the SwimGroup and pass a Domain-Driven class like this:

1 Swimmer swimmer = new Swimmer { 2 Id = carpool_swimmer.SwimmerId, 3 Name = carpool_swimmer.SwimmerName}; 4 5 SwimGroupFactory swimGroupFactory = new SwimGroupFactory(); 6 swimmer.SwimGroup = swimGroupFactory.GetSwimGroup(carpool_swimmer.Carpool_SwimGroup.SwimGroupId); 7 8 return swimmer; 9  

Which leads me to my next problem – how to get both the Swimmer and the SwimGroup in the same database call? As this is written, each factory has a unique reference to the EF class, so getting the swimmer and his/her SwimGroup means 2 round trips. I can put them all into a single call (Unit of work) by using the include statement, but then I will need to change the factory to do the mapping WITHOUT the database call.

I started implanting this, but then I ran into references two deep – Swimmer needs SwimGroup which needs SwimTeam – so the SwimmerFactory has to know to call for SwimGroup and SwimTeam in it’s EF call. I wonder if there are guidelines about how deep to make the references?

So I have this:

1 public static SwimGroup MapSwimGroup(Carpool_SwimGroup carpool_swimgroup) 2 { 3 SwimGroup swimGroup = new SwimGroup { 4 Id = carpool_swimgroup.SwimGroupId, 5 Name = carpool_swimgroup.SwimGroupName, 6 SwimTeam = SwimTeamFactory.MapSwimTeam(carpool_swimgroup.Carpool_SwimTeam) }; 7 8 return swimGroup; 9 } 10  

and this:

1 public static Swimmer MapSwimmer(Carpool_Swimmer carpool_swimmer) 2 { 3 Swimmer swimmer = new Swimmer { 4 Id = carpool_swimmer.SwimmerId, 5 Name = carpool_swimmer.SwimmerName, 6 SwimGroup = SwimGroupFactory.MapSwimGroup(carpool_swimmer.Carpool_SwimGroup) }; 7 8 return swimmer; 9  

and then a EF call that does this:

1 public Swimmer GetSwimmer(int swimmerId) 2 { 3 var selectedSwimmer = (from swimmer in carpoolEntity.Carpool_Swimmer 4 .Include("Carpool_SwimGroup") 5 .Include("Carpool_SwimGroup.Carpool_SwimTeam") 6 where swimmer.SwimmerId == swimmerId 7 select swimmer).First(); 8 9 return MapSwimmer(selectedSwimmer); 10 } 11  

The 2 things I need to be mindful of are:

· No intellisense on the include statement – so the name has to match

· I need to check for null in the mapping in case the calling function forgets the include statement. My mapping cannot handle lazy loading.

This got me thinking about the Factory pattern in general. My Factory class is actually a plant with 2 factories. Factory 1 maps EF classes to POCO classes. Factory 2 class calls EF and returns POCOs. I wonder if I need to divide these 2 functions into separate classes? The examples of the repository pattern that I have seen keep them together – but I have only seen them in a “hello nerd dinner” context.

I then thought harder about the subject and realized that I missing the point of the factory. Conceptually, I picture a window with Alot behind it. I can either hand him an int or a EF class. No matter what I pass in, I get a POCO class out. In this sense, the factory spits out POCOs and I can use overloaded parameters to handle the different permutations that come in. The factory class then looks like this:

1 public class SwimGroupFactory 2 { 3 CarpoolEntities carpoolEntity = null; 4 5 public SwimGroupFactory() 6 { 7 carpoolEntity = new CarpoolEntities(); 8 } 9 10 public SwimGroup GetSwimGroup(int swimGroupId) 11 { 12 var selectedSwimGroup = (from swimGroup in carpoolEntity.Carpool_SwimGroup 13 where swimGroup.SwimGroupId == swimGroupId 14 select swimGroup).First(); 15 return MapSwimGroup(selectedSwimGroup); 16 } 17 18 public SwimGroup GetSwimGroup(Carpool_SwimGroup carpool_swimgroup) 19 { 20 return MapSwimGroup(carpool_swimgroup); 21 } 22 23 24 private static SwimGroup MapSwimGroup(Carpool_SwimGroup carpool_swimgroup) 25 { 26 SwimGroup swimGroup = new SwimGroup { 27 Id = carpool_swimgroup.SwimGroupId, 28 Name = carpool_swimgroup.SwimGroupName, 29 SwimTeam = SwimTeamFactory.MapSwimTeam(carpool_swimgroup.Carpool_SwimTeam) }; 30 31 return swimGroup; 32 } 33 } 34  

Which is great – but then the new class uses a new EF. I have 2 EF classes, though only 1 is used for an active connection. Perhaps the EF class should be moved from the constructor and placed in the methods that actually use it…

So I refactored and got all green – making my factories static and overloaded methods passing in ints or EF classes. For ints, the methods created a new EF context and queries the db. For EF classes, it just maps and send back…

For example:

1 public static SwimGroup GetSwimGroup(int swimGroupId) 2 { 3 using (CarpoolEntities carpoolEntity = new CarpoolEntities()) 4 { 5 var selectedSwimGroup = (from swimGroup in carpoolEntity.Carpool_SwimGroup 6 where swimGroup.SwimGroupId == swimGroupId 7 select swimGroup).First(); 8 return MapSwimGroup(selectedSwimGroup); 9 } 10 } 11 12 public static SwimGroup GetSwimGroup(Carpool_SwimGroup carpool_swimgroup) 13 { 14 return MapSwimGroup(carpool_swimgroup); 15 } 16 17 private static SwimGroup MapSwimGroup(Carpool_SwimGroup carpool_swimgroup) 18 { 19 SwimGroup swimGroup = new SwimGroup { 20 Id = carpool_swimgroup.SwimGroupId, 21 Name = carpool_swimgroup.SwimGroupName, 22 SwimTeam = SwimTeamFactory.GetSwimTeam(carpool_swimgroup.Carpool_SwimTeam) }; 23 24 return swimGroup; 25 } 26 } 27  

I then used this pattern for the rest of my factories…

Carpool Project: Part #4

I wrote this factory code:

1 public SwimTeam GetSwimTeam(int swimTeamId) 2 { 3 var selectedSwimTeam = (from swimTeam in carpoolEntity.Carpool_SwimTeam 4 where swimTeam.SwimTeamId == swimTeamId 5 select swimTeam).First(); 6 7 return MapSwimTeam(selectedSwimTeam); 8 9 } 10 11 public List<SwimTeam> GetAllSwimTeams() 12 { 13 List<SwimTeam> swimTeams = new List<SwimTeam>(); 14 15 var swimTeamsQuery = (from swimTeam in carpoolEntity.Carpool_SwimTeam 16 select swimTeam); 17 18 foreach(Carpool_SwimTeam carpool_Swimteam in swimTeamsQuery) 19 { 20 swimTeams.Add(MapSwimTeam(carpool_Swimteam)); 21 } 22 23 return swimTeams; 24 } 25  

How do I know that I wrote it right?

Unit Test? Integration Test? I don’t care what you call it – I want to make sure it is right BEFORE I use this as a pattern for the rest of the project.

So I created a couple of unit tests (and remembering to add the app.config to my unit test project)

1 [TestMethod()] 2 public void GetSwimTeamTest() 3 { 4 string expected = "RSA"; 5 string actual = SwimTeamFactory.GetSwimTeam(1).Name; 6 Assert.AreEqual(expected, actual); 7 } 8 9 /// <summary> 10 ///A test for GetAllSwimTeams 11 ///</summary> 12   [TestMethod()] 13 public void GetAllSwimTeamsTest() 14 { 15 int expected = 3; 16 int actual = SwimTeamFactory.GetAllSwimTeams().Count; 17 Assert.AreEqual(expected, actual); 18 } 19  

And got green:

Carpool14

I then wired up the UI

I added a controller to my MVC application

1 public class SwimTeamController : Controller 2 { 3 SwimTeamFactory swimTeamFactory = null; 4 5 public SwimTeamController() 6 { 7 swimTeamFactory = new SwimTeamFactory(); 8 } 9 10 public ActionResult Index() 11 { 12 return View(swimTeamFactory.GetAllSwimTeams()); 13 } 14 15 } 16

Added the connection string to the Web.Config

Added an auto generated View

Carpool15

 

And boom goes the dynamite…

Carpool16

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.

Eating the IT Elephant

I started reading Eating the IT Elephant two weeks ago based on its subtitle: “Moving from Greenfield Development to Brownfield.”

 

I am interested in anything regarding Brownfield development after reading Brownfield Application Development and finding it to be a great book.  Unfortunately, the word ‘Brownfield’ is the only similarity between the two books. 

Eating was written by a couple of IBM folks – and I have a pretty dim view of IBM’s products after being forced to use them on my day job (the fact that IBM’s growth strategy is in product development next year makes me laugh – they better keep feeding that Mainframe/Consulting Service monster…).  Undaunted about IBM black mark, I cracked it open.  I quickly became lost in their dense prose (almost academic paper-like quality), obscure points, and convoluted connective rational.  The authors might have some great things to say, but I could find any. They identify the common problems of why software projects fail (pretty much the same as all of the other software development books out there) and then devise some solutions (Views, Hilbert Space, buy more IBM products?) that I can’t understand. 

If you need to get something done, don’t read this book.  If you want to expand your mind in some kind of academic gymnastic exercise and have already done the crossword this morning, then have a go.