Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Wednesday, 16 May 2012
( Patterns | TekPub )

Singleton: A class which only allows a single instance

Very controversial in general.

NodaTime – Jons open source library, which implements good practices

namespace Sandbox
{
    public class Singleton
    {
        public void DoSomething()
        {
        }
    }

    public class SingletonClient
    {
        public void UseSingleton()
        {
            Singleton s1 = new Singleton();
            s1.DoSomething();
            Singleton s2 = new Singleton();
            s2.DoSomething();
        }
    }
}

Ahh – can make 2 of the singleton class!

public static class Singleton
    {
        public static void DoSomething()
        {
        }
    }

    public class SingletonClient
    {
        public void UseSingleton()
        {
            //Singleton s1 = new Singleton();
            //s1.DoSomething();
            //Singleton s2 = new Singleton();
            //s2.DoSomething();
            Singleton.DoSomething();
        }
    }

but want to instantiate class.. just not have 2 possible

public class Singleton
{
    //global state - bad
    private static Singleton instance;

    private Singleton()
    {
    }

    public static Singleton CreateInstance()
    {
        if (instance == null)
        {
            instance = new Singleton();
        }
        return instance;
    }

    //raison d'etre for the class
    public void DoSomething()
    {
    }
}

[TestFixture]
public class SingletonClient
{
    [Test]
    public void UseSingleton()
    {
        Singleton s1 = Singleton.CreateInstance();
        Singleton s2 = Singleton.CreateInstance();
        Assert.AreSame(s1,s2);
    }
}

However if on multiple threads this could be bad as both could get to the new Singleton() line at the same time.

mutex locks..complex

public class Singleton
{
    //clr manages locking, mutex and volatile stuff
    private static readonly Singleton instance = new Singleton();

    //empty static constructor - chaanges when the clr is allowed to initialise this...
    //will only initialise before it is first used.
    static Singleton() {}

    private Singleton()
    {
        //stuff that must only happen once
        Console.WriteLine("Singleton constructor");
    }

    public static Singleton Instance { get { return instance; } }

    public static void SayHi()
    {
        Console.WriteLine("hi");
    }

    //raison d'etre for the class
    public void DoSomething()
    {
        // This must be thread-safe... it can be got at from multiple threads... thats its purpose
    }
}

[TestFixture]
public class SingletonClient
{
    [Test]
    public void UseSingleton()
    {
        Singleton.SayHi();
        Console.WriteLine("Start of test");
        Singleton s1 = Singleton.Instance;
        Singleton s2 = Singleton.Instance;
        Assert.AreSame(s1,s2);
    }
}

asdf

image

but say we wanted real laziness ie only creating the singleton when needed:

public class Singleton
    {
        //nested class
        private static class SingletonHolder
        {
            internal static readonly Singleton instance = new Singleton();
            //empty static constructor - forces laziness!
            static SingletonHolder() {}
        }

        private Singleton()
        {
            //stuff that must only happen once
            Console.WriteLine("Singleton constructor");
        }

        public static Singleton Instance { get { return SingletonHolder.instance; } }

        public static void SayHi()
        {
            Console.WriteLine("hi");
        }

        //raison d'etre for the class
        public void DoSomething()
        {
            // This must be thread-safe... it can be got at from multiple threads... thats its purpose
        }
    }

    [TestFixture]
    public class SingletonClient
    {
        [Test]
        public void UseSingleton()
        {
            Singleton.SayHi();
            Console.WriteLine("Start of test");
            Singleton s1 = Singleton.Instance;
            Singleton s2 = Singleton.Instance;
            Assert.AreSame(s1,s2);
        }
    }

.NET4 could use Lazy<T>

| | # 
# Tuesday, 13 March 2012
  • A Data Access Pattern
  • Separate persistence responsibility from business logic classes

talks about unit of work..

In DDD the most coarsely grained items will each have a repository.

Data Access Evolution

Interesting:

image

To test this app, you need to run the UI.

image

2 tier.  ADO.NET code pushed into the helper.  Hard to test business logic as its still in the UI.

image

eg ICustomerRepository.. and CustomerRepository

Commonly Strategy Pattern is used in Repository

mvcmusicstore.codeplex.com

http://mvcmusicstore.codeplex.com/SourceControl/network/forks/ssmith/MvcMusicStoreRepositoryPattern

Original Code:

public class HomeController : Controller
    {
        //
        // GET: /Home/
        MusicStoreEntities storeDB = new MusicStoreEntities();

        public ActionResult Index()
        {
            // Get most popular albums
            var albums = GetTopSellingAlbums(5);

            return View(albums);
        }

        private List<Album> GetTopSellingAlbums(int count)
        {
            // Group the order details by album and return
            // the albums with the highest count

            return storeDB.Albums
                .OrderByDescending(a => a.OrderDetails.Count())
                .Take(count)
                .ToList();
        }
    }

image

where DbContext is in System.Data.Entity (EF) – this uses a unit of work and repository pattern (need to clarify).

image

So looks like we’re using code first.

In global.asax there is a line which will seed the db if need be.

In web.config there is a connection string to a SQL CE DB.

Applying Repository Pattern

image

    public class HomeController : Controller
    {
        private readonly IAlbumRepository _albumRepository;

        //poor mans dependency injection
        //can put in a fake repository here
        public HomeController(IAlbumRepository albumRepository)
        {
            _albumRepository = albumRepository;
        }

        //as mvc3 calls constructor without parameter
        //can assume that all testing will call the above
        //so can hard code in the actual db calls here
        //uses a constructor initializer
        public HomeController() : this(new EfAlbumRepository()) { }

        public ActionResult Index()
        {
            var albums = _albumRepository.GetTopSellingAlbums(5);
            return View(albums);
        }
    }
Where to put stuff:

image

he uses structuremap for IoC

| | # 

Intent:

  • Way to decouple things which are dependant on one another

SRP – Single Responsibility

OCP – Open to extension (can change its behaviour), but closed to modification (change the source code and recompile) eg a plugin structure.. paramaters.. pass in different parameters to change the behaviour

Commonly used for Dependency Injection.

| | # 

Notes from Steve Smith’s Commonly Used Design patterns dnrtv show.

http://dnrtv.com/dnrtvplayer/player.aspx?ShowNum=0194

http://csharpindepth.com/Articles/General/Singleton.aspx – Jon Skeets article on this

http://ardalis.com/ Steves blog (running Orchard)

Intent:

  • Ensure a class has only 1 instance
  • Make the class itself responsible for keeping track of its sole instance
  • “There can be only 1”

Not thread-safe

class Program
    {
        static void Main(string[] args)
        {
            //Call singleton's DoStuff() method
            Singleton.Instance.DoStuff();

            //Assign to another variable
            var myObject = Singleton.Instance;
            myObject.DoStuff();

            //Pas as a paramater
            SomeOtherMethod(Singleton.Instance);
        }

        private static void SomeOtherMethod(Singleton singleton)
        {
            singleton.DoStuff();
        }
    }

    //warning - not thread safe eg aspnet
    public class Singleton
    {
        private static Singleton _instance;

        private Singleton() { }

        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new Singleton();
                return _instance;
            }
        }

        public void DoStuff()
        {
        }
    }

Thread-safe and fast

 

default pattern is Not thread safe and should

Tight coupling

Notoriously difficult to test – commonly regarded as an anti-pattern..

 

Using an IoC Container is a way to avoid coupling eg ninject, unity

 

“Singletons allow you to reuse code and control object state much easier. This improves code-sharing, and can result in a far cleaner body of code. With less code, your programs will usually have fewer bugs and will be easier to maintain.”

Steve doesn’t use singletons. Violates SRP – because it does 2 things:  eg if you want all file management to go through 1 instance of a class ie a singleton

  • Class has to mange its own lifetime (IoC containers job)
  • Deal with the filesystem
| | # 
# Friday, 30 December 2011
( Patterns | TDD | TekPub )

“An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.”

eg every time we call Add, we want a notification to clients (logger) that something interesting happened.

  • publisher
  • subscriber

Action<string>

- if we were in .NET2 then public event would have to be of some delegate type.

-  Would have to declare a delegate type of function that would return a string

3.5  Action<T>

public class StringCalculator
    {
        //declare and assign it at the same time (so don't have to check it is null every time)
        public event Action<string> OnAdd = delegate { };

        private readonly ILogger logger;
        public ILogger SecondaryLogger { get; set; }

        public StringCalculator(ILogger logger)
        {
            this.logger = logger;
        }

        public int Add(string numbers)
        {
            OnAdd.Invoke(numbers);
            LogNumbers(numbers);
            if (IsEmpty(numbers))
            {
                return DefaultEmptyResult();
            }
            return AllOtherValues(numbers);
        }

declaring the event, and invoking when add is pressed:

[Test]
        public void Add_Always_TriggersOnAddEvent()
        {
            //bool wasTriggered = false;
            string eventParam = null;

            StringCalculator sc = GetDefaultCalc();
            //lambda way
            //sc.OnAdd += s => wasTriggered = true;

            //so whenever someone invokes the event, wasTriggered will turn to true
            //sc.OnAdd += delegate(string s) { wasTriggered = true; };
            
            //register for event
            sc.OnAdd += delegate(string s) { eventParam = s; };

            sc.Add("1");

            //Assert.IsTrue(wasTriggered);
            Assert.AreEqual("1", eventParam);
        }

subscribing to event, passing in a delegate

Extract and Override

very powerful as can break dependencies easily without interfaces

| | # 
# Monday, 16 May 2011

http://jamescbender.com/bendersblog/archive/2010/08/09/devlink-2010-slides-and-demo.aspx

from devlink 2010

Slideshow (look in notes) and code.

Adapter

Decorator

Factory

Command

| | # 
# Monday, 22 February 2010

The Hands on MVC set of videos:  www.learnvisualstudio.net

Routing

In global.asax

 routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "Index", id = ""} // Parameter defaults
);

This means eg http://localhost:3203/Home/About
will come to the controller called HomeController and run the method called About
 
public ActionResult About()
{
return View();
}

which in this case will call the view with the same name called About.aspx

What about http://localhost:3203/ which is the same as /Home and /Home/Index

In this case the defaults are being used eg Home, Index , null… as shown above in //Parameter defaults.

It even passes a message from the Home controller, Index method.

ViewData["Message"] = "Welcome to ASP.NET MVC!";
 
Hardcode /Home to mean something
// for hardcoded /home goto home/member
routes.MapRoute(
"MemberHome",
"home",
new {controller = "Home", action = "Member"}
);

Building UI Form

get is putting in query string

post is putting in the http request body

utility methods for not directly specifying URL


<%Html.BeginForm(); %>






<% Html.EndForm(); %>

Useful to see the Request coming back from /home/member into the HomeController, Member method.

image

asdf

image

Yuk!

Post redirect get pattern.

Basically stops the above resend message by getting the browser to do a redirect after the post page, to a nice get page.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Member(string status) // this will match up the name status in the forms collection
{
//return View();
return RedirectToAction("Member");
}

The Model using LinqToSQL

Added a simple table with a FK to the aspnet_users UserId column.

 

image


The UserId FK is a guid.

The Timestamp has a default value of GETUTCDATE() so that the db writes in the timestamp.

LinqToSQL has:

readonly – shouldn’t allow app to change it

auto Generated Value = true   - hmm to do with:

Auto_Sync – so it will auto get the timestamp property back into the model whenever it does an insert.

 

Can see the class generated that represents our StatusUpdate table:

image

The View

In the controller:

List updates = db.GetUserUpdates(User.Identity.Name);
return View(updates);

and in the view:

System.Web.Mvc.ViewPage>

we now get a strongly typed object

 

View Models

Have simply created another class called MemberViewModel in Models:

public class MemberViewModel
{
public List Updates { get; set; }
}
 
so can pass in more complex stuff than just a list into my view (can’t pass in multiple lists)
 
So the view now has:
 
System.Web.Mvc.ViewPage

and we can access data like:
 
foreach (var update in Model.Updates)

 

Lazy Loading and Eager Loading.

However we’ve hit an interesting issue:

image

this is because of in the view we’ve called:

Html.Encode(update.User.UserName)

And in the actual query, it returns only the StatusUpdate object and not the User object (even though it does a join).

var updates = from update in this.StatusUpdates
where update.User.UserName == userName
orderby update.Timestamp descending
select update;
 
in the controller after query is ran and the result put into the ViewModel, then passed to the View… the datacontext is destroyed.
 
using (var db = new TwixDataContext())
{
ViewData["Stuff"] = "Blah this is a generic object with no intellisense";

MemberViewModel model = new MemberViewModel
{
Updates = db.GetUserUpdates(User.Identity.Name)
};
//List updates = db.GetUserUpdates(User.Identity.Name);
return View(model);
}


So when the view tries to call the User.UserName.. LinqToSQL tries to go and get this data, as it hasn’t been needed yet.  This is lazy loading.

We want LinqToSQL to load the User object at the same time as loading the StatusUpdates.. this is Eager Loading.

CSS

Making things look good:

#timeline { list-style: none; padding: 0;}
#timeline li {border-top:dashed 1px #888; padding: 5px 0; }
#timeline li:hover { background-color: #eee; }
#timeline li div.message { font-size: 10pt; }
#timeline li div.message span { font-weight: bold; }
#timeline li div.time { font-size: 8pt; font-style: italic }

for:

    "timeline">
    <%foreach (var update in Model.Updates) {%>


  • class="message">
    <%= Html.Encode(update.User.UserName) %>:
    <%=Html.Encode(update.Message) %>

    class="time">
    <%=update.Timestamp.ToLocalTime().ToString() %>


  • <%} %>
Creating a Home/Profile

coppied the get from index, however instead of passing in the current logged in user to GetUserUpdates, am passing in the string ie it will be localhost/nameofperson or localhost/home/profile/nameofperson

Also created a new viewmodel for profile that has username in it (as we’ll need this).  Strongly typed as well.

public class ProfileViewModel
{
public string UserName { get; set; }
public List Updates { get; set; }
}

Partial View (#7)

create a viewmodel just for the timeline ie this partial view.

changing MemberViewModel and ProfileViewModel to have a TimeliveViewModel (abstracting it away to get rid of duplication)

public class MemberViewModel
{
public TimelineViewModel TimelineModel { get; set; }
}

public class TimelineViewModel
{
public List Updates { get; set; }

So we reference it in the controller like this:

ProfileViewModel model = new ProfileViewModel
{
UserName = userName,
TimelineModel = new TimelineViewModel{
Updates = db.GetUserUpdates(userName)
}
};
and then in the view:
<%foreach (var update in Model.TimelineModel.Updates) {%>

Hyperlinks, Anonymous Type - create new view as Timeline.ascx

<%Html.RenderPartial("Timeline", Model.TimelineModel); %>
 
<%Html.ActionLink(update.User.UserName, "profile", new {userName = update.User.UserName}) %>

First property is the text to be displayed, second is the action to be called when they click this link (method on this controller),

We’re not specifying the controller here, so it is going to user the current (home) controller.

The third is a generic object which represents the extra route values that we want.. as the method takes a parameter called userName, we need to pass it. We use an anonymous type

 

image

The crowd goes wild :-)

Seeing Other Peoples Tweets

A common technique when we need a Many to Many relationship. 

each user can follow many other users

each user can be followed by many other users

image

The primary key is both on the FollowerMappings table.

Then in the Mappings:

image

We have renamed the child and parent properties for clarity.

The first FK relationship is the FollowerId being held constant.  So the Child Property is the Followee (all the people the user is following)

The second FK relationship is the FoloweeId being held contact.  So the Child Property is the Follower (all people who are following the user).

**TODO refactor and come up with better names.

Adding Methods to The Model DataContext

GetAllUpdates – gets all status update records including those psoted by user that this user is following

IsFollowing – checks if a specific user name is following another user name… so we know whether to display a button

DeleteFollowerMapping

Adding Methods to the HomeController

Changed the get method on Home/Profile to GetUserUpdates.. and to do logic for displaying the Follow/Stop Following button.

Added a post method for Follow (which is called from Profile as a form post), and redirects back to Profile.

 

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Follow(string userName)
{
if (!string.IsNullOrEmpty(userName) && !userName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase))
{
using (var db = new TwixDataContext())
{
if (!db.IsFollowing(User.Identity.Name, userName)) // double check they are not already being followed
{
var followerMapping = new FollowerMapping
{
FollowerId = db.GetUserIdForUserName(User.Identity.Name),
FolloweeId = db.GetUserIdForUserName(userName)
};

db.FollowerMappings.InsertOnSubmit(followerMapping);
db.SubmitChanges();
}
}
}
return RedirectToAction("Profile", new {userName = userName});
}

Added a post method for StopFollowing.. same as above.

Adding Properties to the ProfileViewModel

public class ProfileViewModel
{
public string FollowText { get; set; }
public string FollowAction { get; set; }
public bool IsSelf { get; set; }
public string UserName { get; set; }
public TimelineViewModel TimelineModel { get; set; }
}
So when we pass this object to the view, we’ve got lots of strongly typed goodness.

Using in the View

using (Html.BeginForm(Model.FollowAction, "home")) {
%>
<%=Html.Hidden("userName", Model.UserName) %>

<%
}

where the brace ends, is just the same as doing an Html.EndForm.

 

Best Practise

Use a form post instead of a link if doing database stuff to prevent hacking.

Summary so Far

Why do we have so much business logic in the controller?

DSCN1403

next video is #9

why is this line sometimes giving Http Exception in home controller.

var isSelf = userName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase);

#9 – is jQuery.. thats all folks or more stuff.

#10 – is account settings.. name, email, timezone.. form field validation… combo box (dropdown)… nice fade out jquery front end.

#11 – is upload photo

#12 – is search.. ?q=learnvisualstudio… not a post… stuff in his source code that isn’t in video. icon/link delete a post.

| | # 
# Wednesday, 21 October 2009
Customer tests confirm how the feature is supposed to work as experienced by the end user.

Because customers generally don't want to use nUnit.. we're going to use Fitnesse, which is more user friendly:

The goal is to have the customer write their own tests.

To setup Fitnesse.  Download the .jar and run it like this:

c:\apps\fitnesse -jar fitness.jar -p 8080

Then go and get slim for .net.  I installed it to c:\apps\slim



Here is how it works for the Divider example:

!define TEST_SYSTEM {slim}
!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\apps\slim\fitsharp.dll %p}
!define TEST_RUNNER {c:\apps\slim\Runner.exe}
 
!path C:\code\slimexample\slimexample\bin\Debug\slimexample.dll

|import      |
|slim_example|

!|Divider|
|Numerator|Denominator|Quotient?|
|10       |2          |5      |
|12.6     |3          |4.2      |
|22       |7          |~=3.14   |
|9        |3          |<5       |
|11       |2          |4<_<6    |
|100      |4          |33       |

Here is the C# code, I compiled to slimexample.dll
using System;

namespace slim_example
{
    public class Divider
    {
        public double  Numerator { get; set; }
        public double Denominator { get; set; }
        double _quotient;

        public void Execute()
        {
            _quotient = Numerator / Denominator;
        }

        public double Quotient()
        {
            return _quotient;
        }
    }
}
Run the tests.. and we'll see that when 2 numbers are sent... then then ? in the Fitnesse means that something should be checked.


Then we wire up to our code and test CatalogAdapter:

From this test we can see that I've a bug.. something wrong with the Duration.



Debugging

Have been working through why we are not getting the duration through.  The unit tests on the DAL are passing fine.. in CatalogFixture, have added in 2 tracks of different lengths.  They get pushed into the db, then pulled out using Catalog.. looks ok.



The next step is to look at the Service layer and see if the Duration is being written.  Interestingly, the webservice is passing back all the correct tracks, but nothing to do with reviewers etc..




Very interesting bug.. if I didn't specify this in my RecordingAssembler.WriteTotalRunTime:

dto.totalRunTimeSpecified = true;

then nothing would be passing back.  Same for WriteAverageRating.


Came across another issue with the webservice, and couldn't get it to autogen.. easiest way was to create it again.  Using source control so it if all went to custard, could go back.

Been getting bogged down in detail, so have decided to push to the end of the project, and get a front end up and running asap.



| | # 
# Tuesday, 20 October 2009
Task:  create a WebService that returns a recording and all its entities when specifying the id of the recording. Return type of XML (ie not a .net dataset).

The DAL.Catalog returns a RecordingDataSet.Recording.

We need to write a DTO that takes an input and transforms(munges) it into something else

Using a Service Interface Pattern.

Build a stub, map it into a DTO, and verify each field.
First thing I did was to create a stub, to hide how the RecordingDataSet is retrieved..so am not relying on the DAL at this point.

Here is the test the Stub code:
[TestFixture]
  public class CatalogServiceStubFixture
     {
         RecordingDataSet.Recording recording;
         RecordingDataSet.Recording actual;
         CatalogServiceStub service;
 
         [SetUp]
         public void SetUp()
         {
             // create a test recording in memory
             recording = CreateRecording();
             service = new CatalogServiceStub(recording);
             actual = service.FindByRecordingId(recording.Id);
         }
 
         private RecordingDataSet.Recording CreateRecording() 
         {
             RecordingDataSet dataSet = new RecordingDataSet();
             RecordingDataSet.Recording recording = dataSet.Recordings.NewRecording();
             recording.Id = 1;
            // more code needed here to fill in the rest of the recording.
             return recording;
         }
 
         [Test]
         public void CheckId()
         {
             Assert.AreEqual(recording.Id, actual.Id);
         }

Next we want a dto to transform our dataset, into something else:



To specify in platform independant, we use XML.  This is still quite bulky, perhaps JSON would be lighter now.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://nunit.org/webservices" elementFormDefault="qualified" targetNamespace="http://nunit.org/webservices" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Recording" type="tns:RecordingDto" />
  <xs:complexType name="RecordingDto">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="id" type="xs:long" />
      <xs:element minOccurs="1" maxOccurs="1" name="title" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="artistName" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="releaseDate" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="labelName" type="xs:string" />
      <xs:element minOccurs="0" maxOccurs="unbounded" name="tracks" type="tns:TrackDto" />
      <xs:element minOccurs="0" maxOccurs="unbounded" name="reviews" type="tns:ReviewDto" />
      <xs:element minOccurs="0" maxOccurs="1" name="totalRunTime" type="xs:int" />
      <xs:element minOccurs="0" maxOccurs="1" name="averageRating" type="xs:int" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="TrackDto">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="id" type="xs:long" />
      <xs:element minOccurs="1" maxOccurs="1" name="title" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="artistName" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="duration" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="genreName" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ReviewDto">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="1" name="id" type="xs:long" />
      <xs:element minOccurs="1" maxOccurs="1" name="reviewerName" type="xs:string" />
      <xs:element minOccurs="1" maxOccurs="1" name="rating" type="xs:int" />
      <xs:element minOccurs="1" maxOccurs="1" name="reviewContent" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>


A benefit is that we can create C# from this:.. but really just getters and setters.  See below.. this led to an interesting bug.

http://www.codingday.com/xml-c-class-generator-for-c-using-xsd-for-deserialization/

xsd asdf.xml - create an xsd
xsd asdf.xsd /CLASSES  - creates a .cs

Then just creating an 'Assembler', which writes out the DTO...(from http://martinfowler.com/eaaCatalog/dataTransferObject.html)

The Assembler has business logic in it to flatten the structure (as in the similar example above)

The webservice is setup by adding it into IISAdmin.

As the default ASP.NET user does not have access to my local database
connection = new SqlConnection("Data Source=DAVEXPLAPTOP;Initial Catalog=catalog;Integrated Security=True");

The easiest way to get running on dev was to add the DAVEXPLAPTOP\ASPNET user into my SQL database.  This didn't show up under objects when adding, but I went ahead anyway and it worked.







So this is what we have so far:


| | # 
From the nbdn course, I had some interesting code I'd like to test.  Just the business logic really, no DAL nor UI.  As I wanted to make a full application, the first though was to make a DAL which talked to a text file, or just some dummy data.  How to do this well?  De-coupled.  Tried to use poor mans dependency injection, and got confused.  So I had a coffee, and bought this book.  Because it had an end to end example of a testable application.  It uses .net1.1 mostly (which is good as there are no language constructs to learn)



Some good introduction to refactorings, and unit testing.  The main meat of the book is an example called MediaLibrary (music recordings).  Chapter 5 started with testing the DAL.

Here are the first tests.  Am showing nunit test runner.. mostly I use testdriven.net, and have setup ctrl alt shft t to run tests.



for source control I'm using  git, and have coupled up with gvim as text editor.  And linked in beyond compare for a merge tool.

The book uses Strongly Typed Datasets, which were the 'star of the show' in the .net1.0 release.  By writing the sql, and having intellisense have autoproperties, this saves writing boiler plate code.

I learned about DataSets.. here is my edit (from wikipedia)..http://en.wikipedia.org/wiki/ADO.NET#DataSets

ADO.NET consists of two primary parts:

Data provider

These classes provide access to a data source, such as a Microsoft SQL Server.  Each data source has its own set of provider objects, but they each have a common set of utility classes:

  • Connection: Provides a connection used to communicate with the data source.
  • Command: Used to perform some action on the data source, such as reading, updating, or deleting relational data.
  • Parameter: Describes a single parameter to a command. A common example is a parameter to a stored procedure.
  • DataAdapter: A bridge used to transfer data between a Data source and a DataSet object (see below).
  • DataReader: Used to efficiently process a large list of results one record at a time. It allows records to be accessed in a read-only, forward-only mode, i.e., records have to be accessed in sequential order; they can neither be randomly accessed nor can a record which has been processed previously be accessed again.

DataSets

DataSet objects, a group of classes describing a simple in-memory relational database,

  • A DataSet object represents a schema (either an entire database or a subset of one). It can contain tables and relationships between those tables.
    • A DataTable object represents a single table in the database. It has a name, rows, and columns.
      • A DataView object overlays a DataTable and sorts the data (much like an SQL "order by" clause) and filters the records (much like an SQL "where" clause) if a filter is set. An in-memory index is used to facilitate these operations. All DataTables have a default filter, while any number of additional DataViews can be defined, reducing interaction with the underlying database and thus improving performance.
        • A DataColumn represents a column of the table, including its name and type.
        • A DataRow object represents a single row in the table; it allows reading and updating of values in that row, likewise retrieving any rows that are related to it through a primary-key foreign-key relationship.
VS has a nice editor:



Once I spiked up what datasets were (in simpleDatabaseTests.cs).. used this for reference: http://www.csharp-station.com/Tutorials/AdoDotNet/Lesson05.asp
 [Test]
        public void put_data_into_a_dataset()
        {
            DataSet dataset = new DataSet();
            SqlDataAdapter data_adapter = new SqlDataAdapter("select id, name from Artist", connection);
            SqlCommandBuilder sql_command_builder = new SqlCommandBuilder(data_adapter);
            data_adapter.Fill(dataset, "Artist");
            Assert.IsNotNull(dataset);

            DataTable data_table = dataset.Tables[0];
            for (int i = 0; i < data_table.Rows.Count; i++)
            {
                DataRow data_row = data_table.Rows[i];
                Console.Out.Write(data_row["id"] + " ");
                Console.Out.WriteLine(data_row["name"]);
            }
        }

The example I'm working through uses a Table Data Gateway Pattern for the DAL. 

http://martinfowler.com/eaaCatalog/tableDataGateway.html
"A Table Data Gateway holds all the SQL for accessing a single table or view: selects, inserts, updates, and deletes. Other code calls its methods for all interaction with the database."

Lets take an example of ArtistFixture.cs which tests ArtistGateway.cs

[TestFixture]
    public class ArtistFixture
    {
        static readonly string artistName = "Artist";
        SqlConnection connection;
        ArtistGateway gateway;
        RecordingDataSet recordingDataSet;
        long artistId;

        [SetUp]
        public void setup_and_open_connection_pass_to_gateway_setup_data_set()
        {
            connection = new SqlConnection(ConfigurationSettings.AppSettings.Get("Catalog.Connection"));
            connection.Open();

            recordingDataSet = new RecordingDataSet();
            gateway = new ArtistGateway(connection);
            // insert a new artist getting its ID from the database
            artistId = gateway.Insert(recordingDataSet, artistName);
        }

        [Test]
        public void RetrieveArtistFromDatabase()
        {
            // create new RDS, use same gateway.
            RecordingDataSet loadedFromDB = new RecordingDataSet();
            RecordingDataSet.Artist loadedArtist = gateway.FindById(artistId, loadedFromDB);

            Assert.AreEqual(artistId, loadedArtist.Id);
            Assert.AreEqual(artistName, loadedArtist.Name);
        }
Here is part of ArtistGateway.cs.. gateway is newed up with a connection passed in.. then only in Insert is it passed in a strongly typed RecordingDataSet, which has all the SQL in it which has been auto-genned.
public class ArtistGateway
{
SqlDataAdapter adapter;
SqlConnection connection;
SqlCommand command;
SqlCommandBuilder builder;

public ArtistGateway(SqlConnection connection)
{
this.connection = connection;

command = new SqlCommand("select id, name from artist where id = @id",connection);
command.Parameters.Add("@id", SqlDbType.BigInt);

adapter = new SqlDataAdapter(command);
builder = new SqlCommandBuilder(adapter);
}


public RecordingDataSet.Artist FindById(long artistId, RecordingDataSet recordingDataSet)
{
command.Parameters["@id"].Value = artistId;
adapter.Fill(recordingDataSet, recordingDataSet.Artists.TableName);
DataRow[] rows = recordingDataSet.Artists.Select(String.Format("id={0}", artistId));

if (rows.Length < 1) return null;
return (RecordingDataSet.Artist) rows[0];
}
Class Diagram done in VS2008 with the Class Designer Powertoy http://www.codeplex.com/modeling
To get the blue lines go to Class Diagram, Filter Lines, Show All Associations.

Sequence diagram done in Visio: (hmm - this is a bit complex... I prefer the class diagram above with notes)


Genre was next, then the rest.  Then relationships between objects eg ReviewReviewer.. just testing the test data we create comes back:  Have abstracted out some of the setup code into ConnectionFixture.
 [TestFixture]
 public class ReviewReviewerFixture : ConnectionFixture
 {
     [Test]
     public void ReviewerId()
     {
         RecordingDataSet recordingDataSet = new RecordingDataSet();

         ReviewGateway reviewGateway = new ReviewGateway(Connection);
         long reviewId = reviewGateway.Insert(recordingDataSet, 1, "Review Content");

         ReviewerGateway reviewerGateway = new ReviewerGateway(Connection);
         long reviewerId = reviewerGateway.Insert(recordingDataSet, "Reviewer Name");

         RecordingDataSet.Review review = reviewGateway.FindById(reviewId, recordingDataSet);

         review.ReviewerId = reviewerId;
         reviewGateway.Update(recordingDataSet);

         Assert.AreEqual(reviewerId, review.Reviewer.Id);

         reviewGateway.Delete(recordingDataSet, reviewId);
         reviewerGateway.Delete(recordingDataSet, reviewerId);
     }
 }
The hardest test is RecordingGateway, as it depends on all the other 'tables'.  To simplify, we abstract out the insert/del of test data to RecordingBuilder.cs.

The last class is Catalog, which is the only class that will be called from the Service layer.  In Catalog we have FindByRecordingId, which returns a RecordingDataSet.Recording (so all the data associated with this recordingId).




In summary we have done this of the overall structure of the APP:

| | # 
# Friday, 17 July 2009
A simple MVC (Model View Controller) implementation..code by Jimmy Chandra
http://stackoverflow.com/questions/1107720/mvc-c-simplest-possible-implementation

Why use MVC?  Similar reasons to MVP - testability and seperation of concerns

Simple.MVC.zip (167.25 KB)



1. Program.cs runs, running Main.. as is standard in a Win Forms app.  Difference from MVP is that main here is instantiating and running a controller class first of all, instead of newing up the view, which calls the controller/presenter.
static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            
            TopEmployeeController controller = new TopEmployeeController();
            Application.Run(controller.View as Form);
        }
2. Controller is instantiated and constructor called:
        private ITopEmployeeView _view;
        private Employee _employee;

        private bool _monitoring;

        public TopEmployeeController()
        {
            _employee = new Employee();
            _view = new TopEmployeeForm(this, _employee);
        }
3. Controller news up an employee (dumb).. then a view of type TopEmployeeForm, passing its self (the controller) and employee to it.

4. View (the observer) subscribes to the model (the subject) so that when model.OnPropertyChange is called, view.UpdateView is called.  This is the observer pattern, made easier in C# using events.. which is using a delegate.
// view
public TopEmployeeForm(ITopEmployeeController controller, Employee model)
        {
            _controller = controller;
            _model = model;

            //Let the model know that this view is interested if the model change
            _model.OnPropertyChange += new Action(UpdateView);

            InitializeComponent();
}
6. When Button is pressed on the view.  The controller.GetTopEmplyee method is called.  This calls model.MontorChanges:
// controller
public void GetTopEmployee()
{
if (!_monitoring)
{
_monitoring = true;
_employee.MonitorChanges();
}
}



7. MonitorChanges does some waiting code, then every second calls FirePropertyChange(). Which calls model.OnPropertyChange.
Which is really a delegate to View.UpdateView
// model
public event Action OnPropertyChange;

private void FirePropertyChange()
        {
            var propChange = OnPropertyChange;
            if (propChange != null)
            {
                OnPropertyChange();
            }
        }

8. The view method which runs every second and displays the name on the form.
// view
        public void UpdateView()
        {
            // to do with threading
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(UpdateView));
            }
            else
            {
                TopEmployeeName = _model.FullName;
            }
        }




| | # 
# Thursday, 16 July 2009
( MVP | Patterns | Testing )
Easy to understand, working example WinForms app using MVP (Model View Presenter) pattern.

Why use this pattern?  Testability and maintainability (ie loosely coupled so less likely to break!)

Download noddy.zip (106.62 KB) (VS2008)

Notes:
View is dumb and does render logic
View never talks to the model (or any business entity eg customer) directly
Presenter retries data and manipulates
Model is the data and business rules

usually MVP sits on top of an ORM or Database Abstraction / Business Logic layer:


How it works:

1) Application comes to Program.cs which calls Form1.cs.. no MVP code here.
static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// Standard code.. nothing MVP
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

2) Form1 (which is the view in MVP) which implements IView interface (**why**).. instantiates a new MainPresenter calling it presenter.
public partial class Form1 : Form, IView
    {
        private MainPresenter presenter;

        public Form1()
        {
            InitializeComponent();
             presenter = new MainPresenter(this);
        }

        private void btnPostCustomer_Click(object sender, EventArgs e)
        {
            presenter.PostCustomer();
        }

        // IView members
        public string FirstName
        {
            get { return txtFirstName.Text; }
            set { txtFirstName.Text = value; }
        }

        public string LastName
        {
            get { return txtLastName.Text; }
            set { txtLastName.Text = value; }
        }

        public void DisplayResult(string result)
        {
            MessageBox.Show(result);
        }
    }
3) MainPresenter constructor runs, and is passed in the view object of type IView. (**could we have just passed it in as a Form object?**)

public class MainPresenter
    {
        private IView view;
        private MainModel model = new MainModel();

        public MainPresenter(IView view)
        {
            this.view = view;    
        }

        public void PostCustomer()
        {
            Debug.Assert(view != null);

            try
            {
                Customer customer = new Customer(view.FirstName, view.LastName);
                model.PostCustomer(customer);
                view.DisplayResult(customer.ToString() + " posted");
            }
            catch(Exception ex)
            {
                view.DisplayResult(ex.Message);
            }
        }
    }
4) App is run, names are filled in, and Post button is submitted.



5) View code (form1.cs) runs presenter.PostCustomer
private void btnPostCustomer_Click(object sender, EventArgs e)
        {
            presenter.PostCustomer();
        }
6) presenter creates a new customer (which could be seen as being outside of MVP, and more in an entity later, as the model layer is usually light, and only relating the modelviews) and passes in the names.  Nothing special on the constructor of customer. 

public void PostCustomer()
        {
            Debug.Assert(view != null);

            try
            {
                Customer customer = new Customer(view.FirstName, view.LastName);
                model.PostCustomer(customer);
                view.DisplayResult(customer.FullName() + " posted");
            }
            catch(Exception ex)
            {
                view.DisplayResult(ex.Message);
            }
        }
7) Presenter calls the main model to PostCustomer which writes out to disk the Customer which has just been entered.
public void PostCustomer(Customer customer)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Customer));

            if (File.Exists("Customer.xml"))
            {
                using (FileStream stream = new FileStream("Customer.xml", FileMode.Append, FileAccess.Write))
                {
                    serializer.Serialize(stream, customer);
                }
            }
            else
            {
                using (FileStream stream = new FileStream("Customer.xml", FileMode.Create, FileAccess.Write))
                {
                    serializer.Serialize(stream, customer);
                }
            }
        }



8) Presenter calls the view to DisplayResult, passing in the customer data as a string.
public void DisplayResult(string result)
        {
            MessageBox.Show(result);
        }


Included in the download are simple tests on the ViewModel and Domain model.  Also Form2 which has a Form2Presenter.  Uses same ViewModel (hmm probably should have a seperate one), and the same domain model (customer.cs).  Next step for me is to get tests working on the Presenters.




| | #