Design Discussion

Coordinator
Aug 17, 2008 at 7:49 AM
  1. Change from provider pattern to repository + IoC?
  2. Extract logic from objects into services w/ interfaces?
  3. Utilize routing or URL rewriting?
  4. Move away from WCF to a HttpHandler + IRouteHandler?
  5. Use Guids, Tags, or Urls for ID?
  6. How should the resources be located?
  7. Authentication/Authorization?
  8. What is our test methodology?
Developer
Aug 17, 2008 at 10:49 AM
for 8) The only choice that I like are:
- MbUnit (http://www.mbunit.com/) which has lots of nice features
- The Microsoft testing tools, which are quite decent in the 2008 release. This may win just because it's already there.
Developer
Aug 17, 2008 at 12:07 PM
4) I would not move away from WCF lightly. It has a lot going for it, and the System.Web.Routing stuff like IRouteHandler is new and not well known. I don't know it, for one.
Coordinator
Aug 17, 2008 at 5:02 PM
Edited Aug 17, 2008 at 5:17 PM
8) I've been using the Microsoft testing tools for a couple years so I'd prefer to stick with that.  But I'm open to change if there are compelling reasons.  As for the tests, I'd like to see APE as our own collection of tests. BTW, last time a ran APE there were 0 errors.  This shouldn't be too hard to whip up as you can export sessions from Fiddler into the Test project. I'd also like to see other tests to exercise the business logic/data storage.
Coordinator
Aug 17, 2008 at 5:23 PM
Edited Aug 17, 2008 at 5:52 PM
4) The usage of WCF has so far been a love hate relationship.  In general, I like WCF.  One of my original goals was to allow BlogSvc to function without needing IIS.  I accomplished this goal but with limitations.  The interface became "unpure" due to the media support (must accept and return stream rather than strongly typed AtomEntry). Also, the UriTemplate is not the most flexible way to handle URLs.  Specifically, if you want to support multi-folder or multi-subdomain workspaces it can be difficult to alter the UriTemplates for these scenarios.  It requires some complex URL rewriting to get it done.  Finally, security has been another thorn in my side.  Unless you use a hack (like the current implementation of WSSE auth) then it is impossible to support annonymous and secure connections to the same EndPoint, which means you'd need to split the ServiceContract and thus the interface becomes even more "unpure".  As it becomes less and less pure, then exposing a Soap enpoint becomes impossible (or dirty) without rewriting with a separate contract and implemenation.  All this keeps nagging at my mind if it is worth all the trouble of sticking with WCF.  See first link here.

The main question here is: Do we need to keep service independence from ASP.NET?
Coordinator
Aug 17, 2008 at 6:01 PM
Edited Aug 17, 2008 at 7:10 PM
3, 5 & 6) I've spent a lot of time and effort working towards "ideal" urls and uris.  To me, ideal coincides with Jacob Nielson
  • a domain name that is easy to remember and easy to spell
  • short URLs
  • easy-to-type URLs
  • URLs that visualize the site structure
  • URLs that are "hackable" to allow users to move to higher levels of the information architecture by hacking off the end of the URL
  • persistent URLs that don't change
  • (also) file extension that corresponds to content type
Although, I've not completely settled on this, I've documented what I think they should look like here: http://blogsvc.net/info/URIsAndURLs.xhtml

Those pretty urls are currently accomplished using url-rewriting but that involves complex Regex and also lots of supporting logic for building them.  With Routing, it would simplify things and reduce the amount of code since you can use Routing to build and parse urls.  Also, in the future, if you decide to tweak the non-persistent locations, the links could possibly auto-update or you could keep the old routes in place but use a 301 or 302.

There are two types of collections: dated="yes" or dated="no" where if dated="yes" then dates are an important part of the id and location of a resource.

Note, that by using a combination of the tag scheme and allowing the provider to find an unused id allows for global unique ids.  For example, here is the code in the FileAtomPubProvider to find a unique file name, it just increments a number until it is unique:
Id id = entry.Id;
int i = 1;
while (File.Exists(path)) {
  id = new Id(id.Owner, id.Date, id.Collection, entry.Id.EntryPath + i);
  path = GetEntryPath(id);
  i++;
}
entry.Id = id;

Developer
Aug 19, 2008 at 10:03 PM
Have you seen this? http://diveintomark.org/archives/2004/05/28/howto-atom-id
I'm starting to think that the SQL DB tables will need integer primary keys. Varchar primary keys make DBAs break out in a rash.
Coordinator
Aug 20, 2008 at 3:32 AM
Nice link.  I followed the Tag Spec so all the id's I've been generating are extremely similar to what Mark is suggesting.  For BlogSvc, the design can support integer primary keys if that is what the database needs to have. The repository can alter the Id of an entry when it gets created (doesn't ever change after that).  Therefore, you could potentially have something similar to what Mark suggests for the timestamp:

Example: tag:blogsvc.net,2008-08-19:blog,20080819110347

This would make a composite key of workspace, date, collection, entryNum.  However, it wouldn't translate well into a pretty url.  You could also do something like:

tag:blogsvc.net,2008-08-19:blog,101-MyEntry

where you could extract the integer id and it would look better translated to a permalink.  The other two options are
  1. Allow permalinks to change (disconnect id from permalink)
  2. Use urn:uid:guid syntax which is fairly popular but not human friendly.
For 1, BlogSvc currently translates Urls (both permalinks and atom links) into Ids for talking to the repository.  If the permalinks were to differ from the id, we must use the link to lookup the id to lookup the post.  This isn't much of a problem for a database but for the file system repository you'd need to build some sort of index or restructure based on permalink.  The goal with the usage of the tag scheme is to create an internally dereferencable value that we can use build logic around the workspace, collection, and entry.  We could create an implementation of the following interface to support non-dereferencable ids.
public interface IRouteService
{
  AppService AppService { get; set; }
  Id IdFromNames(string workspace, string collection, string date, string entryPath);
  Id IdFromNames(string workspace, string collection, string entryPath);
  Id IdFromNames(string workspace, string collection);
  Id IdFromPath(string path);
  Id IdFromPath(string workspace, string path);
  Id IdFromPath(string workspace, string collection, string path);
  Uri IdToAtomHref(Id id);
  Uri IdToMediaHref(Id id);
  Uri IdToWebHref(Id id);
  Uri ServiceHref();
}


Developer
Aug 22, 2008 at 10:06 AM
- Change from provider pattern to repository + IoC?

I'd be happy with repositories behind interfaces. IOC can then be added as and when needed.

- Extract logic from objects into services w/ interfaces?

Currently I'm thinking that it's going to be hard to populate these objects with data from a relational database - they're "XML inside", and one way to do it would be to whip up some XML from the database records and give that to the object model. This doesn't seem right.

Or store XML on the database. This doesn't seem right either.

The model presented in the MVC strorefront suggests a simpler, dumber object model, and services that can transform it to/from XML. Which seems like open-heart surgery on the code.


I'd like to see what direction you had in mind.
Coordinator
Aug 25, 2008 at 1:54 AM
> I'd be happy with repositories behind interfaces. IOC can then be added as and when needed.
I'm on the same page here.  The solution is ready for IOC.

>Currently I'm thinking that it's going to be hard to populate these objects with data from a relational database - they're "XML inside", and one way to do it would be to whip up some XML from the database records and give that to the object model. This doesn't seem right. Or store XML on the database. This doesn't seem right either.
The objects can be treated as POCOs.  The database should not care that they are XML based objects.  This does have one catch: any xml extension elements not supported by the object model will be lost.  However, I'm ok with that.

The other option still on the table (especially now that .NET 3.5SP1 is out) is to use the built in object model in the framework.  It has support for ServiceDoc, Workspaces, Categories, Collections, Feeds, and Entries which is all of our main objects.  When I tried using their model in the past I was not happy.  The naming is horrible and inconsistent and the extension API is extremely cumbersome.  It takes 10 times more (ugly and bug ridden) code to add an extension if you go with the built in model.  I do plan to take another look at the feasibility of this if I ever get some free time.

I have a Linq presentation coming up that I'll probably take a look at the schema you came up with and do a spike on some repository code.