Archive for the 'Training' Category

Enterprise MVC Apps course – redux

Last year, Adam Stephensen and I ran a number of “Enterprise MVC” courses.  These courses were hugely popular, not only selling out in Brisbane, Melbourne, and Sydney, but receiving positive feedback from each session nationwide.

Well, due to popular demand, they’re back, but in a slightly different format – it’s gone from a 2 part course to a course of 4 relatively independent days.  Day 1 will be useful if you’re new to MVC, while the other three days will take your skills to the next level by teaching how to make enterprise-quality MVC applications.

There are a few reasons for the change, all of which based on feedback from the participants.

The volume of important content was the primary reason for the change.  Adam and I really wanted to spend more time on important topics like Inversion of Control, Dependency Injection, logging, and testing.  With a 4 day course, we can really give these topics the attention they deserve.

We also think that getting your hands dirty is really important for understanding a lot of concepts.  By extending the course to 4 days, we can ensure there’s plenty of time for participants to try things rather than just hearing about them.

Finally, we found that attendees came to the course with differing levels of MVC experience.  For some, the introductory subjects were invaluable, but not for everyone.  By adding an extra day for MVC Foundations, we can confidently start at a higher level for the subsequent days.

If you’re writing MVC applications (or want to start) and you want to go beyond the demos so you can write enterprise-quality, maintainable, scalable, and robust applications in MVC, I’d highly recommend attending our new and improved courses.

For more details:

P.S. Telerik has once again jumped on board offering licenses for some of their awesome products when you register.  Check out the course pages for more info!

A Generic Repository and Unit of Work Implementation for Entity Framework

You may be familiar with my previous posts describing the implementation of design patterns for Entity Framework.  It started with using generics for lookup tables, and followed with a generic CRUD repository.  This strategy follows along with our SSW rule, Do you use the Repository Pattern for data access.

In the lead up to SSW’s recent Enterprise MVC course, I had lots of discussions with Adam Stephensen and Eric Phan about whether we could do a better job with this pattern.  We’ve come up with what we think is a great solution that includes the Unit of Work pattern as well.

We felt it was really important to separate the domain models, the repositories, and the context; a separation that’s not made by Entity Framework. Doing so gave us some really important benefits.  Testing is made much easier.  For one, we can mock our context enabling us to test our repositories without going back to the database.  We can also mock the repositories to test the code that calls it.

A quick shout-out to Adrian Clark who suggested this separation in the comments last time.

We also used Inversion of Control to inject a context into the repository.  We could have had a reference to each of our repositories in our context, but inverting this relationship meant that we only needed to instantiate those repositories we were actually using.  It means less overhead and a looser coupling between the context and each repository.

First, we create our IUnitOfWork and our IGenericRepository.

public interface IUnitOfWork : IDisposable
{
    DbSet<TEntity> Set<TEntity>() where TEntity : class;

    int SaveChanges();
}
public interface IGenericRepository<TEntity>
  where TEntity : class
{
    IQueryable<TEntity> Select();

    IEnumerable<TEntity> GetAll();

    IEnumerable<TEntity> Where(Func<TEntity, bool> predicate);

    TEntity GetSingle(Func<TEntity, bool> predicate);

    TEntity GetFirst(Func<TEntity, bool> predicate);

    void Add(TEntity entity);

    void Delete(TEntity entity);

    void Attach(TEntity entity);

    void Dispose(bool disposing);

    void Dispose();
}

Then, we create an interface for our specific context. In this example, we have a context with a set of customers. This context is essentially a unit of work, so we’ll inherit that interface.

public interface ICustomerContext : IUnitOfWork
{
    DbSet<Customer> Customers { get; set; }
}

Next, we’ll create a concrete GenericRepository instance. This is very similar to the version in my previous post, but take note of the repository that takes a context. We use this to inject our Unit of Work.

public class GenericRepository<TContext, TEntity> : IGenericRepository<TEntity>
    where TContext : IUnitOfWork
    where TEntity : class
{
    protected TContext _context;
    /// <summary>
    /// Constructor that takes a context
    /// </summary>
    /// <param name="context">An established data context</param>
    public GenericRepository(TContext context)
    {
        _context = context;
    }

    public IQueryable<TEntity> Select()
    {
        return _context.Set<TEntity>().AsQueryable();
    }

    public IEnumerable<TEntity> GetAll()
    {
        return _context.Set<TEntity>().AsEnumerable();
    }

    public IEnumerable<TEntity> Where(Func<TEntity, bool> predicate)
    {
        return _context.Set<TEntity>().Where(predicate);
    }

    public TEntity GetSingle(Func<TEntity, bool> predicate)
    {
        return _context.Set<TEntity>().Single(predicate);
    }

    public TEntity GetFirst(Func<TEntity, bool> predicate)
    {
        return _context.Set<TEntity>().First(predicate);
    }

    public void Add(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentException("Cannot add a null entity");

        _context.Set<TEntity>().Add(entity);
    }

    public void Delete(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentException("Cannot delete a null entity");

        _context.Set<TEntity>().Remove(entity);
    }

    public void Attach(TEntity entity)
    {
        if (entity == null)
            throw new ArgumentException("Cannot attach a null entity");

        _context.Set<TEntity>().Attach(entity);
    }

    #region IDisposable implementation
    private bool disposedValue;

    public void Dispose(bool disposing)
    {
        if (!this.disposedValue)
        {
            if (disposing)
            {
                // dispose managed state here if required
            }
            // dispose unmanaged objects and set large fields to null
        }
        this.disposedValue = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    #endregion
}

Next, we’ll create a concretion for our context using Entity Framework. We’ll inherit DbContext as well as implementing ICustomerContext, and we’ll create both an empty constructor and one that takes a connection string so we can connect to a specific database.

public class CustomerContext : System.Data.Entity.DbContext, ICustomerContext
{
    public CustomerContext() { }

    public CustomerContext(string connectionString) : base(connectionString) { }
}

And that’s all we really need to do.

When we use it, we have to make sure we refer only to our interfaces so we can replace them later if need be.

private ICustomerContext _context;
private IGenericRepository<Customer> _customerRepository;

Ideally, we’d be using Dependency Injection to inject our concretions at runtime, but here’s an example of how you would do it.

_context = new CustomerContext();
_customerRepository = new GenericRepository<ICustomerContext,Customer>(_context);

From there, we can do whatever we need to do with the objects in our repository, and just call SaveChanges() on our context when we’re done. For example:

public ResetCustomerLastLoginDate(int customerId) {
    var customer = _customerRepository.GetSingle(c => c.CustomerId == customerId);
    customer.LastLoginDate = DateTime.Now;
    _context.SaveChanges();
}

Speaking at QMSDNUG on Tuesday 21st Feb

Just a quick post to let you know I’ll be presenting my “Building Mobile Websites with ASP.NET MVC 3 and 4″ talk at the Qld MSDN User Group meeting on Tuesday the 21st.

Previous versions of this talk have focused mainly on MVC 3 with a nod towards MVC 4. Now that the ASP.Net team have officially launched the beta of ASP.NET MVC 4, I’ll be shifting the focus to the new version.  Out with the old and in with the new!

If you saw the version of this talk I gave at DDD Brisbane last year, don’t be scared off – it’s gone through many, many iterations since then based on the feedback I’ve received.

So if you’re in Brisbane, I’d love for you to come along.  Just RSVP on EventBrite and I’ll see you there!

Professional Scrum Developer Course – New Delhi Day 1

scrumdevlogoI’m in India at the moment with Adam Cogan and Adam Stephensen helping out on a Professional Scrum Developer course. The training is with a group of 24 guys with varying roles – developers, testers, architects, and managers. At the end of the course, they will all have the opportunity to sit an online exam to become “Professional Scrum Developers”.

It was such a fun day, we decided to sit down and write a blog post together.

Pre-day one

We decided to catch a couple of tuk-tuks to the venue.  Adam Cogan somehow managed to send emails on his iPad while cramped in the back.

Setting off on our way…. little did we know that the driver had no idea where he was going

Setting off on our way…. little did we know that the driver had no idea where he was going

One of the important things you learn about in Scrum is an Impediment.  Even before day 1 started, we had our first one.

Impediment 1: The distance from our hotel to the training venue was about 2km.  The 1.5 hour journey (yes, one and a half hours) to this venue on the first day included three lost taxis (two independently finding their way to the same wrong address) and several near-death experiences.

Tip: Don’t think about complaining to your tuk-tuk driver or else you will find him try to make you happy by driving the wrong way down a busy main road.

Our tuk-tuk driver saving time – you have no idea how we felt.

Our tuk-tuk driver saving time – you have no idea how we felt.

Getting Started with “Scrumdementals”

Impediment 2: Day 1 officially started with Adam C noticing that only one of the 24 students had read the Scrum guide. To bring everyone up to speed, he was able to give a succinct rundown of the Scrum user guide with the help of a few SSW rules (The importance of a team, Reading the Scrum Guide, and Physical Task Boards) and the awesome “Scrum Master in Under 10 Minutes” video by Hameed Shojaee.

The “guts” of Scrum was covered, with particular reference to short iterations, multi-skilled teams and timeboxing.  Adam C also told a story about his years in the army, and pressed  the point about the “inspect and adapt” tenet of Scrum which got a laugh.  The army tends to plan a mission, watch it all go very differently, and then debrief so they can adapt.

Adam C telling the team what they "said", but what the Product Owner really "heard"

Adam C telling the team what they "said", but what the Product Owner really "heard"

Adam C talked about the burndown and asked which time fields in a User Story mattered for the burndown.  Two of the 24 students already knew that the only time field that Scrum cares about is the “remaining time”.  He went on to explain why this was, and why the “original estimate” and “actual time” spent fields aren’t as important.

User Stories

After a morning break, Adam Cogan spoke to the group about User Stories. Everybody loved his quintessential example with accompanying story:

As a marketing manager
I want to search for customers
So that I can call them up

He followed this up with a discussion about Acceptance Criteria and why they were so important.  Referencing the SSW rule on Acceptance Criteria, it was pointed out that you should never assume “gold plating” for a User Story.  The group appreciated the clarification on acceptance criteria and agreed that it was important for clarity.

Adam C’s next instruction was for each student to write one of their current working items in the form of an SSW story card.  Some were good, and some were not so good.  I reviewed my favourite ones and shared them with the class.

Rohit Arora’s great Story Card

Rohit Arora’s great Story Card

Manish Yadav’s great Story Card

Manish Yadav’s great Story Card

Sanjay Saini’s great Story Card

Sanjay Saini’s great Story Card

Amit Choudhary’s great Story Card

Amit Choudhary’s great Story Card

Sprint One

After lunch, the group was asked to self-organise into four teams of six.  Initially, the groupings weren’t ideal (all the developers with MVC experience were in the same team), maybe the ‘multi-skilled’ point was forgotten… a quick bit of shuffling was required.

The teams really worked well together

The teams really worked well together

Bonus 1: Even though team members were being split up, the new teams worked really well together.

Next, the Product Owner entered the room and scared everyone with his tough requirements. He is a Product Owner you don’t want to mess with.

The Product Owner giving his requirements

The Product Owner giving his requirements

He spent 10 minutes (timeboxed) giving out requirements for the first one hour sprint. The task was to create a poster for his boardroom.  The sprint was split into four 15min “days”, after which the teams presented the results in the review meeting.

Impediment 3: Every half hour or so, a “black room event” occurred.  No, not a “black swan event” :-).  Apparently power outages are fairly common in Delhi, but every time it happened, the laptops switched to battery and all network connections were lost.

Adam C saw this message pop up on his PC quite a lot:

The all-too-common Battery Monitor message

The all-too-common Battery Monitor message

The post-sprint Review meetings were fun with the teams presenting some different results in their work.  The Product Owner was hard to please, but we think under that tough skin, he was generally pleased with the work.  The same can’t be said about the process.  In the end, he chose his favourite diagram to hang on his boardroom wall.

The Product Owner’s favourite diagram had some excellent artwork

The Product Owner’s favourite diagram had some excellent artwork

The Retrospective meeting was even more fun and the teams learnt some very valuable lessons.  However, Adam C explained that every one of the teams was naughty:

  1. Only 1 of 4 teams took up the invitation to speak to the Product Owner about what he wanted
  2. 2 teams did a User Story for the task (despite Adam C giving several “Printed Story Cards” to each team)
  3. None of the teams kept a Backlog
  4. None of the teams did a Daily Standup, and
  5. Only 2 teams followed the brief and included pretty pictures (this was very important to the Product Owner)

Later on, Adam C presented his ideal Scrum diagram and spoke about how it clearly shows the Scrum process from start to finish.

Adam Cogan’s ideal Scrum diagram

Adam Cogan’s ideal Scrum diagram

Retrospective

The day ended with a retrospective where each student talked about what they liked and disliked about the day.

The top two highlights of the day – repeated multiple times – were:

  1. Writing User Stories and learning about why the wording was important
  2. Learning about effective acceptance criteria

The students said they were very happy with the course so far. They wanted 2 things improved for the next day:

  1. There weren’t enough videos (we’ll fix that on day 2!)
  2. Lunch was too early

Can’t wait for Day 2.