Showing posts with label Sprint Planner Helper. Show all posts
Showing posts with label Sprint Planner Helper. Show all posts

Thursday, May 14, 2009

Sprint Planner Helper – final

I have had some real problems to get going with the Sprint Planner Helper Project after the trip to Ethiopia. I am not sure why – but it made me think about the project, the scope and purpose.

First and foremost – I am not working, i am on parental leave. That means this is my spare time project and I promised myself that I would end it if I didn’t feel up to it for some reason. Since I have found it hard to restart I conclude that I have reached that point.

Secondly – the main reason and purpose of the project was to learn, not to produce a wonder-application (although that would have been nice :)). I think that I have learned quite a lot during this project and that I am at a junction right now. You cannot pursue at depth in all directions.

OK – what was my learning goals and where have they taken me?

DDD

The main purpose was to look into Domain Driven Design. I feel that I have got a nice grasp around that subject – and I most certainly want to learn more. I’ll write a separate post about my thoughts on DDD and it’s implications on your project.

[UPDATED]

Here is my post on DDD

TDD

When I started the Sprint Planner Helper project I liked test. Now they are a part of the way I code. Over and over again you are struck by the fact that doing test first actually improves your code quality and helps you find flaws in your code early. I like that. Might be a post on these findings also.

ASP.NET MVC

Finally a web framework from Microsoft that I understand! I’ve been doing WebForms on and off during several years and still don’t get it. Actually I don’t think many do (how many developers does fully understand the implication of this…)

After doing ASP.NET MVC during this project I can honestly say that I will surely continue and never look back. Also the community is exploding with examples, code and projects that will assist you in creating great code. And of course the introduction Nerd Dinner chapter.

I am ridiculous proud of being the number one hit on this search. Before the actual book it self!!!

Extreme OOP

Eeeh – you can’t win them all, now can you? Actually this was the one thing that I pretty soon abandoned. Not that I don’t like the rules and the way they improve your code quality but it was one thing to much to think about.

I think that if you want to learn this you’ll need to do a separate project that solely focus on extreme OOP. And that would be quite fun.

Actually, in the PDF i am linking to above, you find an exercise that’ll get you started.

Where to go now

Some other reasons for me to stop is that I have found some great resources that is much more ambitious than my feeble tries. Here are a short list of them. Be sure to check them out, I know I will:

So I hope that anyone who has read this has enjoyed it for as long as it lasted. I know that I have learned a lot and that doing this project has made me a better developer.

The code will still be available at http://sprintplannerhelper.codeplex.com/, if not contact me to get it. I might even re-start the project later.

Saturday, April 11, 2009

Sprint Planner Helper - Vaccation halt

I am going to Ethiopia for two weeks and the project comes to a natural (and needed) halt during that period.

I had hoped that I would have got further than this but I must stay content with what I've got.

The visit to Ethopia will be something very different and exciting. Especially with Albert who right now is 14 months and have just started to walk...

Get back to you on the trip at www.marcusoft.net

Tuesday, April 07, 2009

Sprint Planner Helper – Session 26

I have come to realize that I am not working… Not very flattering that I has taken me about 2,5 months to come to that conclusion but here I am.

So I will probably slow down the pace for this project. I have not done loads so far but I felt a bit pressured to “produce” and that not the kind of feeling I would like to have on my parental leave. So a bit slow – and still only when it’s fun!

OK – the thing today is to find aggregates and create repositories for the Sprint domain object.

When it’s comes to aggregates I still find them quite hard to grasp. The mainstream definition seems to be “things that must exists together” and the most common example is the Order-OrderLine relationship.

But for my Sprint I have a list of SprintItems each with a list of ActionItems. And if feels quite strange to get the complete thing each time I bring up a sprint. Feels to heavy. So I’ll start with the aggregate being the Sprint, Team and SprintItems and then another aggregate for SprintItem and ActionItems.

I am not sure that this is good DDD but I’ll start of like this. My modeling is done in PowerPoint, and if you follow my code (on this project @ CodePlex) you’ll find it in the modelling.pptx-file.

[PowerPointing in progress]

aggregates

OK – that was the thinking part. Now I need to add repositories for these aggregates. That is mostly inheritance and tests. Simple tests… :)

[Coding in progress]

Ok – that took some time. But now I have the tests in place and everything is dandy to get started on the UI for the sprint-part of my domain.

Thursday, April 02, 2009

Sprint Planner Helper – Session 25

Today I will continue working on the model, surrounding Sprints, and of course drive it forward with tests.

I came to realize today that I am now converted. I am now a TDD guy. I will do tests even if it’s not required of me. And the reason is security and speed.

I have gone from coding along with no worries – the tester will find (any) bugs for me… Then I heard of unit-testing and started to write some – just for fun in the start (yeah – pretty sick). After a while I didn’t dare to check in any code that I couldn’t prove with some test – but a wrote the code first. And after a while of doing that, I was so feed up with running behind with the tests that thought I’ll give true TDD a chance.

What I pretty soon came to realize is that not only was the code easier to test that way (doing the test first) – but I often spotted bad design and code even as I was writing the test. Before the code was even written, if you like.

That’s my reason for doing TDD.

OK – on to the code.

More test are written – more knowledge about the domain is acquired. I really like this way to get about the model.

Monday, March 30, 2009

Sprint Planner Helper – Session 24

My detour for learning ASP.NET MVC is coming to an end. I cannot say that I fully know the framework but I have a much better understanding of it now and that will hopefully help me keep the tempo up.

I have a few things left (such as editing product backlog items) surrounding the product. But I will leave them for later. I am so long back to the DDD that this project also is aiming to learn me.

The third item of my user stories is a biggie and it concerns Sprints – the main object of my domain model.

3. As user I can create a sprint that represent a sprint in which some items of the product backlog is to be realized.

The sprint has a goal description and a start, stop and demo-date and the team members with availability (in %), absent hours and focus factor (in %).

The sprint also contains a sprint backlog which initially contains a sprint backlog item for each product backlog item selected. 

The sprint backlog contains summarized values for total number of hours and story points.

I’ll start by making some simple tests to get to know the model. That’s probably what I have time for today

Unleash the code-fingers!

OK – I’m getting quite used to not managing the things that I think I will… I have now TDD’ed all the parts of an sprint (Team Members, Actions, SprintBacklogItems etc) – but not the actual SprintObject. I’ll get to that next.

Very good progress today. Doing TDD is such a good way to “get to know” your objects. I would love to do it in pairs in a real project – or even in a group to get the whole team to know the core of the domain object.

Sunday, March 29, 2009

UpdateModel, FormCollection and unit test

I ran into some problems with a Action Controller method that accepted an FormCollection. Inside the method I use UpdateModel to get the values from the form into the model-class.

Here is a skeleton implementation of the method:

[UPDATED]
Some insightful comments by Steve made me do some changes to this code. I have now updated it. The tip had to do with if the ValueProvider should be set on the Controller in the test or in the actual Action-method. I finally opted for the latter and changed it into this (significant code in bold).

[AcceptVerbs(HttpVerbs.Post)]       

        public ActionResult Create(FormCollection form)       

        {           

            // Create ViewData           

            ProductForm viewData = new ProductForm(new Product(), productOwnerRepository.Find().ToList());

 

            try           

            {               

                UpdateModel(viewData, form.ToValueProvider());               

 

                // Get the productowner for the selected product-owner id

                viewData.Product.Owner = productOwnerRepository.GetById(viewData.SelectedOwnerID);               

 

                // add new product to the repository               

                productRepository.Add(viewData.Product);               

                productRepository.Save();               

 

                // Go back to the list               

                return RedirectToAction("Index");           

            }           

            catch

            {

                ModelState.AddRuleViolations(viewData.Product.GetRuleViolations());

                return View(viewData);

            }       

        }

This works great but when I call this from my unit test the the values of my form (created in the unit test) is lost. I was very puzzled by this until I found this post in the asp.net mvc forum.

So what that means is that you’ll, in the unit test case, need set the ValueProvider, for the controller you’re testing, to the test form collection you’re sending to the method. Otherwise the Action Controller method will check the Request-property and that will be empty in the test case. Not obvious maybe but understandable when you think about it.

[UPDATED]
Just to be sure – note that the Action-method is using an overloaded version of the UpdateModel that makes sure that the sent-in form is used. I haven’t used the recommendation from the link above since I think it’s less readable/understandable.
The main point are still valid though.

Here is a short sample that test the action method above.

        [TestMethod]

        public void createControllerActionCanTakeAFormCollectionWithProductDataAndAddItToTheRepository()

        {

            var numberOfProductsBefore = productRepository.Find().Count();

            var form = CreateProductTestFormCollection();

 

            

            var result = productController.Create(form);

 

            Assert.IsNotNull(result);

            Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));

            var redirectResult = (RedirectToRouteResult)result;

            Assert.AreEqual("Index", redirectResult.RouteValues["action"]);

 

            Assert.AreEqual(numberOfProductsBefore + 1, productRepository.Find().Count());

        }

 

        private static FormCollection CreateProductTestFormCollection()

        {

            FormCollection form = new FormCollection();

            form.Add("Product.Name", TESTFORM_NAME);

            form.Add("Product.Description", TESTFORM_DESCRIPTION);

            form.Add("SelectedOwnerID", TestData.TEST_PRODUCTOWNER_ID2.ToString());

 

            return form;

        }

Saturday, March 28, 2009

Sprint Planner Helper – Session 23

This has been the longest of my sessions so far and by far. It has actually stretched over 4 separate “hours” and almost a week since my schedule has been busy with other stuff.

It had to do with me getting stuck on a thing the ASP.NET MVC framework that I didn’t get. This was related to the way the framework binds the data in the view to the values posted, and the UpdateModel method etc.

To make a long story short I have posted an item in the MVC-forum, and got some truly great feedback from Alberto. I recommend you reading it. Go on. Do it now.

Ok – from all this I learned some very useful lessons;

  • the most important was to use a separate ViewModel. That is – create classes that are streamlined to fit the view that the controller is exposing.
  • you can do some pretty funky stuff with the naming conventions in the view. For example: if you do this in the view:
    Html.TextBox("Product.Name", Model.Product.Name) will
    and then call UpdateModel(), the Product-property will get new-ed and the Name-value set.

My goal with this session was to continue the use of the IsValid/GetRuleViolations-pattern from Session 22.

But that broke down pretty fast – and I got to learn this pattern instead. I’ll take that any day! Much better knowledge. But I’ll get back to it – shortly.

[UPDATED]
I managed to nail the ValidationSummary-stuff… Here is a picture of it:

ruleviolations

I have also pondered over me spending to much time in the MVC-trenches. If I re-read my initial intentions this is a DDD-learning project (as well as TDD and ASP.NET MVC). But I feel that the DDD-ing has been sidestepped for a while.

I guess that it has to do with that the ASP.NET MVC is a framework that you need to learn how to get your way around. These thing takes time and can stop you in your tracks.

DDD on the other hand is a bunch of design patterns and a mindset – that can take considerable time to master but is often quite easy to get up and running with. 

I’ll try to get back to the DDD-part of this in next session. I had to leave to test that doesn’t work so I’ll have to fix that first. but then…

Sunday, March 22, 2009

Sprint Planner Helper – Session 22

I have had some serious thoughts on what to do next in my project. On one hand I want to update the way I am doing the GUI for the product and product backlog. Right now I am warm and learning a lot about ASP.NET MVC so it feels quite good to continue there.

And on the other hand this is first and foremost a DDD-learning experience and I have got stuck for a while in the ASP.NET MVC trench.

And finally since I only have one hour a either way will take me on a detour from the other track. What to do?

After some serious consideration I decided to spend today’s session on a DDD-thingy that I ran into in the walkthrough. I want to implement the “IsValid and GetRuleValidations”-pattern. And include it in my BaseRepository Save-method.

That will be enough for today – I think.

[Coding with lots of simple tests takes place here]

Yeah – I liked that. Now I have a foundation for validation in place. I even added the validation rules for the Product, ProductOwner and ProductBacklogItem.

Good progress today.

Friday, March 20, 2009

Sprint Planner Helper – Session 21

I’m back! After doing a detour through the sample chapter of the upcoming ASP.NET MVC book (lovingly called “The four faces”, i heard…) I now feel ready to go on.

And I learned a few things by that sample chapter; about ASP.NET MVC, yes but also I saw some flaws of my DDD-ing, especially in the use of the Repository pattern.

The main thing is that I have a separate Update-method that feels a bit strange. Another thing I learned and finally understood was the IQueryable-interface.

By using it you can defer the execution of the actual database query until the client calls. Which means that the query will be fine tuned with all the parameters that the client has includes (such as Take, Sort etc.). (For a much better explanation see this.)

So I’ll update my IRepository to something like this:

    public interface IRepository<T>  where T :IBaseEntity

    {

        T GetById(int id);

        IQueryable<T> Find();

        void Add(T entity);

        void Delete(T entity);

        void Save();

    }

And then I’ll face the consequences of that… I expect loads of tests and code to fix.

[Coding, coding, coding…]

The first thing I needed to do was to move the fakes from the Repository-project into the Test-project where they belong (again a tip from the sample chapter). OK – that made me re-invent the InMemory-Repository. But when I was done the code quality was much better. Clean code!

But I also feel that I might ditch the InMemory solution altogether and go to a database-solution… It starts to feel quite strange…

Then the connection to CodePlex was lost… Took about ten minutes to restart…

With my new repository I also introduced a pattern, called Unit Of Work. Its from Fowlers book Patterns of Enterprise Architecture, which on my bedside table. In this example is basically means that I need to be sure to call the Save-method of the IRepository-interface after each add or delete.

Finally I once again got the opportunity to praise TDD. Did refactoring for about 50 minutes with minor changes all over the place. Ran the tests… 5 failing. Corrected them in 5 minutes! Show me that without any test and I will be very impressed.

Next session will start to implement some “implementation patterns” from the sample chapter, such as the Details-views, the two-phase Delete etc.

Friday, March 13, 2009

Sprint Planner Helper – Session 20

Today I plan to finish up the last part of the prioritizing of Product Backlog Items (see Session 19). That is TDD the controller and then wrap the GUI.

Let’s go!

Whooa – I ran into some problems with routing. Some problems that took me about two sessions (read: hours) to solve. To not to bore you with details or meaningless posts on me scratching my head, I’ll sum it up in this post.

Here is the layout of the “problem"; I have an Action-method with two parameters:

public ActionResult PrioUp(int productID, int productBacklogItemID)

OK – but how do I create a link to that method? Well by using the Html-helper ActionLink-method of course. You define an anonymous object with the route values. Here is my example:

Html.ActionLink("Prio up",  "PrioUp", "ProductBacklogItem", new {productID = Model.ID, productBacklogItemID = item.ID}, null);

OK – but here comes the problems. I have no routing-table entry for sending two parameters. And here I was hanging around, trying stuff out, screaming loud, hammering the keyboard. I just don’t get the routing-stuff yet…

So finally I added this routing-table entry, first of the entries:

            // http://localhost/ProductBacklogItem/PrioUp/productId/productBacklogItemID

            // http://localhost/ProductBacklogItem/PrioUp/1001/2

            routes.MapRoute(

                "ProductBacklogPrio",                                       // Name

                "{controller}/{action}/{productId}/{productBacklogItemID}", // Url with parameters

                new {controller = "ProductBacklogItem"},                    // Parameter defaults

                new { productId = @"\d+", productBacklogItemID = @"\d+" }

            );

That worked! I cannot say that I fully understand why since I thought that I tried it… but naming issues and not concentrating well enough.

A few things to note:

  • It has been very helpful to specify an example on how I wanted the URL to look.
  • I had to specify the full URL ({controller}/{action}/{productId}/{productBacklogItemID} to get it to work
  • I skipped default values for productID and productBacklogItemID since that make no sense
  • The final row is a constaint that states that productID and productBacklogItemID should be numeric

These problems and a tip from Christer made me decide to pause this project for a while. There is a new book on ASP.NET MVC coming out soon which contain a tutorial chapter that looks very nice. You can download it here.

I will run through that chapter and hope that it wont take me to long and also that I’ll learn a lot of stuff that come in handy in the Sprint Planner Helper project.

In fact (and this is a secret) I love doing these walkthroughs – feels like I know something very well…

Alright – but now I have a way to prioritize product backlog items up and and down.

See ya in a while.

Tuesday, March 10, 2009

Sprint Planner Helper – Session 19

After my refactoring yesterday the function that re-prioritize product backlog items was reduced to swapping priority points on two items.

So that’s what I’ll do today. TDD through a function that swap priority points for an product backlog item and the item before (prioritize up) of after (prioritize down) it.

[Coding in progress]

That really was an old-time programming problem. Fun! But now I have TDD’ed a priority swap algorithm. That was all I managed to get through today. Some progress I think.

Now all that is left is to reach this functionality from the GUI and reload the list after it’s done

Sunday, March 08, 2009

Sprint Planner Helper – Session 18

I haven’t done to much on the Sprint Planner Helper project during this week. A lot of Salvation Army activities has taken up my time.

But I have read the blog post (in form of a PDF-book) from DDD Step By Step. I have read much of it before but sometimes other word clear things up for you. This book did it for me.

OK – what to do tonight (Abbe is sound asleep and Elin has gone to work). I have most of the stuff from my first two user stories in place. But I need a way to easy move product backlog item up and down in the list. This will come in handy when the product backlog items are estimated.

So I’ll introduce some methods to move the in the product backlog list. And some arrows in the GUI for the list.

Let’s write some lovely simple tests and see where it takes me.

[tap, tap, tap… Marcus is typing]

Oh my good – this was really to open a can of worms. I have to rework the product backlog class from a List<ProductBacklogItem> to class of it’s own. This is also to follow Extreme OOP rule #8 – Use first-class collections, so it feel quite alright.
Took me about 40 minutes to figure out though, my tests broke down…

The solution was quite simple. After I had reworked the ProductBacklog to not inherit List<ProductBacklogItem> I created a property that return the list in sorted order. The sorting was taken care of with this simple LINQ-statment:

public List<ProductBacklogItem> ProductBacklogItems

        {

get

            {

var listToReturn = from item in productBacklogItems

orderby item.Priority

select item;

return listToReturn.ToList();

            }

        }

After adding an AddProductBacklogItem-method I was back on track with all green lights…

I was then at the edge of blowing my 1 hour rule. So I stopped. Tomorrow I’ll get back to my reprioritizing of item.

Thursday, March 05, 2009

Sprint Planner Helper – Session 17

When you learning something new you’ll expect some progress and the occasional setback. If you are on your own, as I am in this project, that is even more likely to be the other way around.

My approach to learning this is very much like the way we played with the chemistry box when we were small – try something you believe will work and expect the whole thing to blow up, possibly with a stinging sensation to your eye…

So… I guess that you see where this is going. I have to redo something. Actually it’s two. And actually I am not that worried; the whole idea of agile TDD, DDD and all this is that it should be easy to change.

The first thing is not biggie; my Entities has a Guid as ID right now. It’s mega-ugly when I am passing it around on the querystring etc. I’ll change that into an integer. The nice thing about Guid’s is that they are guaranteed to be unique. But not very human friendly…

The second thing is a more delicate matter in DDD. It has to do with aggregates and something called aggregate boundaries (which I understand as: “where do I stop, the whole database is knitted together…”).  This post, by Casey Charlton, explains the background in a nice, compact way. Actually the whole site rocks, with a the relevant posts as a book even.

For me Jimmy Nilsson summed it up in a nice way:

The parts of an aggregate have no reason to exists without their parent.

In my case I have the Product-class that contains a ProductBacklog which is a list of ProductBacklogItems. The ProductBacklogItems have no reason to exists without being attached to the Product. So the Product is my aggregate root.

And as far as I understand (here comes the chemistry box part :)) it should be no ProductBacklogItem-repository. Add how to add a ProductBacklogItem to the ProductBacklog should be an operation on the ProductBacklog.

When the whole Product (aggregate root) is saved the repository will have to save all parts of the aggregate. Which can be quite tricky in the update-case I presume, if the aggregate is big…

Seems like I will be learning how tricky in a while. On to the code!

[Some time passes by while Marcus is coding…]

Eeeh – that took much longer than anticipated and I will stretch this session over two sessions. The main reason for that is that was forced to invent some kind of auto-increment functionality for my fake repository. It was quite simple when I had it figured out. I simply rewrote the add method into this:

public void Add(T entity)

        {

            if (entity.ID == BaseEntity.NEWID)

            {

                // get the new highest id

                entity.ID = FindAll().Max(x => x.ID) + 1;

            }

 

            dictionary.Add(entity.ID, entity);

        }

But I still have the Update-functionality for my Product aggregate to figure out. More simple tests, please. 

[Again some typing, head scratching and thinking takes place…]

Ok – that was much easier than I thought – which of course have to do with that I have a in-memory implementation of the repository right now… So the very simple Update-method:

public void Update(T entity)

        {

            dictionary[entity.ID] = entity;

        }

… took care of it for me. It will probably be a bit more advanced when I have to map this to a relational database.

OK – but now I can create new product backlog items.

Great progress today – I’ve learned a lot about DDD today.

Tuesday, March 03, 2009

Sprint Planner Helper – Session 16

I am now almost ready with the first user story of my own backlog.

1. As user I can create a product that describes the product and the product owner so that the purpose of the product is known.

Each product has a product backlog that describes what is left to do.

Each product backlog item requires at least an Number(1.2.1), description, initial priority.

Other properties are story points (how big is this compared to other) and a document with additional business rules.

The one thing that is left is to be able to create new backlog items.

My GUI for editing a product right now looks like this:

edit a product

and as I said before I will not put to much effort into the design of the GUI, but I have noticed that the MVC-pattern opens up for GUI-design decisions to be change later on. I mean – there is a product backlog item create action that can be outputted as a pop-dialog or on a own page or via AJAX/Flash or …

That is a really nice feature.

Come to think of it – this is one of the main thing of DDD. You are given the freedom to choose (and change) how to solve when the time is right. This goes for all the ends of the application design; the database and the GUI for example.
The important stuff (ie. the model) is what you need to worry about.

OK – on to the code! Lets write some simple test…

I brushed on some extension methods today. They are cool but a bit messy since they don’t belong in the class they are extending… I am not sure if I like them or not.

I came as far as I could create the form for creating new product backlog items. Tomorrow I will save them.

PS. Passed 100 unit tests today. Yeah!

Sunday, March 01, 2009

Sprint Planner Helper – Session 15

I don’t think I ever been doing system development in a nicer place – I am right now in Hyppeln in the Gothenburg archipelago. The weather is most wonderful and we have actually been sitting out for coffee and even managed to do some barbecue…

OK – I am pressing on with the Edit controller action for the Product. Ran into a bug of the ASP.NET MVC framework I think. The first one I see – pretty good for a RC…

I think that I have missed some part of the TDD-ing with that I haven’t been good at “testing my boundaries” (a Code Smell from Clean Code by Robert C. Martin). When I read it I didn’t fully understand it but as I am beginning to understand the TDD-ways I realized that for most cases that is to write tests for the NULL-values also. I guess that you could go to the other extreme and write test for the highest possible value but I cannot see the great use of that. NULL values are always good to test for so I think I will incorporate that into my TDD rhythm, and maybe even start with it.

Today I have worked with the Edit (update) and Delete-actions. I have implemented them in the view and the controller, still with a very simple UI.

I actually got the Product Backlog Items in a usercontrol also. Found the really nice RenderPartial-method that renders a user control in a view.

I have a great feeling of “i have done this before” when doing the UI. It feel likes good old ASP.OLD done right. And a bit like Web Classes (IIS Applications in VB6 back in the days). I like it!

Tuesday, February 24, 2009

Sprint Planner Helper – Session 14

Ok – today I’ll start by making a factory for the product class. I have some issues with the factory patterns and here is my reasoning; another class is the creator and must hence have access to the NEW-method of the class to create. Since that forces at least protected-level on the constructor it means that I cannot be sure that the clients uses the factory and not the constructor.

If I however place the factory method on the class I am creating – I can. But then I am violating the Single Responsibility Principle.  What to do, what to do…

For now – in TDD/XP-fashion – I’ll do the simplest. A static Create-method on the class I am creating. I don’t have several different Products so it’s the same factory for all products, possible with overloads.

Flame away – ye flamers… and give me some insight in how I should have done.

Anyhow – that should give me some work...

Another problem that I was faced with yesterday was that the product I added to my repository did not show up in the list of all products in the repository on the next page. That puzzled me for a while until I realized that; Even though I am using the fake in-memory repository version I am recreating it on each request.

So I need some sort of Singleton-version of the Repository to use for my application until I add support for SQL. I don’t want to do that just yet…

That turned out to be quite tricky but I am happy with the result – that was only a few lines of code… And now I have a repository, in-memory that remembers actions, until I close the application.

Monday, February 23, 2009

Sprint Planner Helper – Session 13

After some consideration I have decided to follow the ASP.NET MVC best practices quite closely – and do the listing of the products as a separate page, the Index-method on the Product Controller.

I’ll focus on this before the actual adding is fleshed out. This is because the Create-method of the ProductController do a redirect to the Index-action.

Also I will keep the GUI very simple. If I do the MVC-ing right it will be easy for anyone who knows this.

[Wait one hour – Marcus is coding :)]

I actually got a product added today! And the more I work with TDD, DDD and ASP.NET MVC the more right it feels. Read this and you’ll see what I mean.

I will have to create a factory for products… but my hour is up.

Sprint Planner Helper – Session 12

Today I started off with some refactoring of the things I did yesterday. It was some pretty ugly code in the aspx-page which now is improved with some properties in the domain model.

I also started the actual adding functionality of the Product and the product backlog. This immediately got me into trouble since I need a list of product owners in order to fill out the form… More test data and repositories.

TDD is great – but it doesn’t solve the problem with testdata. It’s hard work – even with the great repository pattern. I hope (and guess) that this pays off.

Since I am alone and Abbe is sound asleep I’ll break the 1 hour rule and continue a bit further.

There are some great help in the way that ASP.NET MVC integrates into Visual Studio 2008. Most notably the way you can generate typed views (for list, edit and details!) and controller classes via a dialog. Me likey!

Got me to realize that the list of products probably lives best on a view of it’s own and not directly on the first page.
Hmmm – more work. This is learning…

I was quite happy when I could produce this non-working form. Now sleep!

product

Saturday, February 21, 2009

Sprint Planner Helper – Session 11

It’s been a while since I did some code on the project. Abbe has been quite sickly and I have not had the time. No worries – it’s all a hobby ;)

OK – what I have done since last time (2 x 15 min I think) is to produce a list of Product on my web page. With this fancy layout…

sprintplannerhelpergui1

That made me realize that I could have added some disclaimer when it comes to the UI. I made a certain css-class for the productlist, so someone can help me out later. I will make it functional now – not pretty.

I also came to realize that my model may be enhanced with some status for the product items and aggregated values for how much that is done for a product. I TDD’ed them out and added them to the GUI. Which took me forever since I got stuck on LINQ-issues. Here is a excellent site for help in these matters.

Tuesday, February 17, 2009

DDD – the coin drops for Marcus

I have now tried to grasp the DDD-concept without fully “getting it”. I must confess that I have thought: “What is the deal with this… I have done it before”.

But today we had a most prominent guest at Elevate (the education initiative at Avega) – Jimmy Nilsson.  And what he said got the coin to drop for me.

The heading of his presentation was something like “A new era for data access”. And the things he said that got me to understand was something like this – not a quote but rather his reasoning:

Traditionally we focus on the database design in application development. So very early we want to get the database design in place. “We need it to start to do code”. Since we did that design early in the process we often got it wrong and inherited those error through the process. And we are reluctant to change the database later on because its hard to test and overview what the change may break.

In DDD we do the opposite – we start with the domain model, as far as we know. We prepare for change – we want it to change when we get more knowledge about it. We will not even use a database for quite some time in the project, when we have got to “know” the model through test and code.

Ok – that was my interpretation of Jimmy’s reasoning. But I got it – when starting with the pure domain model you don’t need to worry how it’s stored.
And also I understand why I liked the DDD-concept from the start. It goes perfectly with SCRUM – you don’t strive to do it correct from the start but rather expect and prepare for change. I like it!

I also learned some other stuff that I will need to incorporate into my design:

  • Aggregate – use aggregate to logically divide and group your model. An aggregate root is the only way into the other objects in the aggregate. They cannot be accessed from the outside.
  • Start modeling with what you know – I have started out with the first user story and find out what I can about the model in that story, preparing for changing it down the road.
  • Behaviors – I have not put the behaviors on my entities yet. Need to do that.
  • TDD is the way to go – with DDD and TDD together you get to “feel” the model in a more direct way than to write about it.

So that was quite a lot of information to me and to the Sprint Planner Project. No code today – but quite a lot of nice input.

Here’s a last one: since I only code one hour a day I often find it hard to remember what to start with. Leave a RED test – was the very simple and resolute tip from Jimmy.

Thank you Jimmy – for everything I take with me from your presentation.