Home SubSonic MVC-Storefront

Oxite Refactor, Take 1

I mentioned yesterday on Twitter that I’m helping out the Oxite team with some refactoring and tweaking of their codebase. I got started last night and people have been asking about it a LOT, so I thought that today I’d show you initially what I’m up to.

First – the obvious: Oxite as it stands is not acceptable as a starting point for ASP.NET MVC, and they’ve pointed that out on there project site today. I’d like the pendulum to swing in the positive direction now, If I may.

Please know – this is an initial pass and some basic thoughts. It’s very early and if you look at the source you’ll see there are precisely ZERO tests. I’m going to change that in 34 minutes from now – I needed to get my head around the model quickly, and it involved diving head first into the existing code and extracting information – that’s how I got to the point below.

Step 1: Understanding What The Client Wants
I’ve been talking to Duncan and Erik a bit of late (and others on their team) and have a good gauge of what they want (in terms of an overall guiding statement):

a highly-functional, scaleable CMS application that renders high quality and well-formatted semantic markup.

They’re initially building this for the VisitMix site – so I’ll use that as my "client" so I can try to gear what I make and have it be relevant.

Step 2: The Branch
After looking through the codebase and talking to Duncan and Erik, we thought it would be best to do a branch rather than implementing these changes directly in the trunk. So I’m putting this on my SVN server and If you want to view the source as I go, it’s here:

http://www.wekeroad.com:8080/svn/Oxite/trunk

UPDATE: you need to login with "pub" as the user and "pub" as the password.

That’s my own Subversion repo – when it comes time to move stuff over I’ll work with the team to get in place.

Step 3: The Database
In looking over the database and running the application, it seems pretty clear what’s needed here (but I’m sure I’ll have to expand on this). For now my target is the existing functionality, as opposed to what’s planned:

  • A CMS engine for posts which allow comments
  • A Tagging system
  • A "Bucketing" system which does a many/many with posts and associates the posts to an "area"
  • A versioning system that tracks Post changes

In essence (from a DB perspective), this is the everyman blog sample:

WindowClipping (5)

Again I know it’s basic – and no I’m not necessarily "starting from the database" – this is a weird situation where I have stuff right here in front of me, and I’m refactoring the existing system down – so in that sense I’m not really doing TDD here. But I promise – I will get to testing. Working on the DB first is helping me to understand the requirements and what the intent is. Please don’t flame me :) .

I’ve removed a good many things here. If you’re familiar with the Oxite DB (as it was before I started this), it had some extra tables in it that I think we can let the framework handle. In summary, here are the main ones I’ve removed:

User, Role, and Role Relationships Tables- I’m going to lean on an IAuthentication/IAuthorization service for this, and initially use ASP.NET Auth – this will help existing blog apps (on the .NET platform) merge a bit more happily. Eventually I’ll plug in Open ID.

Language, UserLanguage, StringResource Tables- these tables are basically for localization, but this is handled very nicely by the platform. I’ve removed them in favor of using Resources and System.Globalization.CultureInfo.

Subscriptions (and related tables) – Subscriptions are normally handled (these days) by RSS. I’ve removed for now simply to get the app on its feet (it wasn’t enabled in the original rev). If we need an emailer, we can add later.

Messages (and related tables) – again this is removed until the scope is figured a bit. More of a forums angle – CMS apps don’t usually provide this but again I’ll add later.

Step 4: Project Structure
I know I’ll get some sniggers on this :) , but I’ve restructured the project to lean on a bit more of a DDD approach. I’m not going full-tilt DDD here on this first pass, but hopefully I can set some goodness up that we can extend later, should the need arise (and I’m sure it will).

The solution has five main project:

  • Oxite.CMS – the domain model
  • Oxite.Infrastructure – base classes and other things that span the app
  • Oxite.Web – the MVC web app
  • Oxite.Tests – Unit Testing bits
  • Oxite.SqlRepository – the Repository implementation for SqlServer. Currently I’m using SubSonic because I want to see if I can get this thing to run on MySQL. Also I happen to like SubSonic a lot. If I do this right, it won’t matter what I use :) .

Here’s how things look currently, I’ll explain more in a second (the little dots next to the files are VisualSVN):

WindowClipping (7)  

Step 4: The initial Domain Model
I’m laying these out in a hurry, and I’m running with scissors with respect to TDD. Let’s just get this out of the way. I won’t write a stitch of logic without a test behind it (well, I’ll do my best) but right now I need to get this domain down, at least in terms of what’s a service and what’s an object. I know I’m violating things, but this is triage friends :) .

You can see from the diagram above that I’ve got (basically) two Aggregate Roots: Post and User. Well in truth User isn’t much of an Aggregate root right now – but I think it will get there soon enough :) .

Post is the main object, and it’s also abstract. The idea with the site is that a Post is a a bit of text a user can add to the site:

 

namespace Oxite.CMS {

    public abstract class Post:EntityBase {

        public Post() : base() { }

        public Post(Guid id) : base(id) { }

        public string LanguageCode { get; set; }

        public string Title { get; set; }

        public string Body { get; set; }

        public User Author { get; set; }

        public DateTime DateCreated { get; set; }

    }

}

 

Next up is Article, which inherits from Post:

 

namespace Oxite.CMS {

    public class Article : Post, IAggregateRoot,IEntity {

        public IList<Area> Areas { get; set; }

        public LazyList<Comment> Comments { get; set; }

        public DateTime DatePublished { get; set; }

        public object IEntity.Key {

            get { return this.Key; }

        }

    }

}

 

(Yes Colin, I’ve taken your advice on the IEntity stuff :)

I’ve also typed out Comment and Trackback in sort of the same way – they’re not all that interesting so I’ll save room here and keep moving.

Domain Services
Right now I have five separate domain services defined – but I think they’ll get trimmed and tweaked. This is just the start:

  • BlogService – This grabs posts from the repository, sorts comments, etc (whatever logic will be required for pulling posts and displaying). I need to dive a bit more into the Oxite bits to know what’s needed here.
  • MessagingService – Pings services like Ping-O-Matic and Google, etc. May handle spam using Akismet – not sure yet.
  • SearchService – Oxite has the notion of a pluggable search service. Good stuff – rather than make it a repository I’ve made it a service since … well that’s what it is. Not sure of the provider yet.
  • TextService – Handles scrubbing/sanitizing/formatting of post text. This will also handle XSS stuff.
  • UserService – Membership bits

Step 5: Feeds, etc
I’m going to lean on the ASP.NET MVC bits to handle this. I’m not totally sure how that will work, but I know Phil has some ideas :) . There’s some blog expertise in our group.

Love to hear your comments. Yes I know there are no tests – getting to that. This is triage.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • DotNetKicks
  • del.icio.us
  • Technorati
  • TwitThis
  • Reddit
  • Slashdot

Tags: