Tell me if I'm wrong

I recently came to some insights while soaking in a hot bath last night. Please tell me if I’m wrong.

The forum application that I am working on is being designed primarily to satisfy my own requirements and available software, although I plan on releasing it to the general public in some fashion once it’s done.

The software I have available includes vs2008pro and sql server. I have no plans to get licenses for other backend systems, nor do I have the funds to do so.

One of the things I’ve been trying to do that was giving me problems was developing this as if it were a large scale corporate application, and making use of various abstraction libraries and using much touted patterns and conventions that make like easier for such projects. This may have been the wrong way to approach it.

Trying to come up with a set of external libraries to accomodate such an effort has ended in turmoil since all of the RTM releases for the various things have inconsistant dependancies. I have looked into building these myself, and have made some decent progress, but in doing so, I began to wonder if all that code and effort was really affording me any true benefit.

Considering my position, it would seem that the following assertions hold true:

  1. My injection needs are simple, and unchanging enough, where using the overloaded constructor method is appropriate and efficient. Why reference a serveral thousand line code library to add support for something when adding a single function to a class does the same thing? If I used a DI library, and set some custom mappings in Global.asax, compiled the app, and later want to change a mapping, I still have to recompile the app once I edit the Global.asax file. Why not just edit the default constructor of the instancing class instead?

  2. My persistence needs are also simple, and unchanging enough, where using the DataContext designer, skipping the IRepository<T> layer and moving right into top level interfaces, concretes and a ContextFactory is appropriate and efficient.

Some other things to consider are:

  • When the project is done and offered for download, I would really like people to be able to load and build the solution without having to have knowledge of anything but the mvc framework, and that which comes with visual studio.

  • Personally, I am not really comfortable with, nor am I impressed with, NHibernate’s Criterion objects. Rather, I like the way LinqToSql syntax works.

  • I also really like the idea of distributing a single dll for my project and not a lof required dll’s to boot. I like the single project convention. While I don’t like the Models folder specifically, I do add other folders to the root to contain my namespaces. There will not be any hot-swapping of domain, service or persistence layer dll’s here.

So honestly gang, have I hit upon the “truth” about my project? Or have I just gone off on a tangent.

You’re not wrong. If anybody knows the ‘truth’ about your project, it is you.
It sounds like you have already drawn your own conclusions.

OK… I think are using the IoC containar the wrong way.

you shouldn’t be registering dependencies one by one at application startup …

 
Container.Register(Component.For<ISomeService>().ImplementedBy<SomeServiceImpl>()); 
Container.Register(Component.For<IOtherService>().ImplementedBy<OtherServiceImpl>());

The key is set/define a few conventions so that new interfaces and implementation get picked up automaticaly - ie. without requiring you to go edit the boot strapper procedure of the container to add remove dependencies.

using a marker interface … all types implementing a given interface B “marked” with the a marker interface C should be registered as implmenting the interface B.


public interface IService // The marker interface
{ 
} 
public interface ISomeService : IService // The marked interface
{ 
void DoSomethingWith(DomainObject obj); 
} 
public class SomeService : ISomeService 
{
public void DoSomethingWith(DomainObject obj)
{
// ...
}
}

how can we setup this with windsor


Container.Register(AllTypes.FromAssemblyNamed(assmeblyName)
.BasedOn<IService>()
.Unless( type => type.IsAbstract)
.WithService.FromInterface()
.Configure(c => c.LifeStyle.Is(LifestyleType.Transient)));

one could come up with other conventions…

  • regiter all types within a given name space or sub namespaces with the first interface as the service.
 
Container.Register(AllTypes.FromAssemblyNamed(assmeblyName)
.Where(type => type.Namespace.StartsWith("MyName.Services"))
.WithService.FirstInterface()
.Configure(c => c.LifeStyle.Is(LifestyleType.Transient)));

so one would define a set of these conventions and from there on would forget that the IoC container exists. You create new services or remove then without having to go edit the container registration procedure, and you defintly don’t go and edit a bunch of constructors. :stuck_out_tongue:

I find thas is key for using a Ioc container “the easy way”.

Put together with windsor facilities and you could easly swap components in your app without recompiling.
But this ability is not that appealing to me…

About persistence…

I like using NHibernate… and I’m at point that I feel confortable using it. The down side of using NHibernate is that the current linq provider is some what limited.
Next version should have a new and better linq provider implementation… I’m using a trunk version and there is also some changes to the ICriterion and ICriteria API

as an example you can do something like this…


// looks like Linq but its not :P
Session.QueryOver<Student>().Where(e => e.Code == code).SingleOrDefault();

Independent of persitence api you choose, I would make an efort to prevent it from leaking… a simple interface should be enough for abstracting it.

public interface IRepository<T>
{
public IQueriable<T> GetQuery<T>();
public Save(T entity);
}

cheers,
rui

Good points Pufa, but there’s some missunderstanding abound. When I used StructureMap for DI, the only mappings I had to do were non-conventional. Everything else was handled by the I-Something to Something, or ISomething<other> IOtherSomething mapping.

I am still wondering what the real benefit is for me in doing so because I don’t test the way you all test. I don’t do TDD. In fact, I could probably not even use interfaces at all, scrap the injector ctors, and simply use:


public class CategoryService
{
private CategoryRepository categoryRepository;
public CategoryService()
{
categoryRepository = new CategoryRepository();
}
}

Now obviously I wouldn’t go QUITE that far. I still like the concept of talking through interfaces.

The issue with IRepository is that I plan on using the data context class the designer came up with so I can use it in my repositories like this:


public class CategoryRepository : ICategoryRepository
{
 
private VenueContext venueContext;
 
public CategoryRepository()
{
venueContext = new VenueContext();
}
 
public IQueryable<Category> GetEnabled()
{
return venueContext.Categories.Where(x => x.Enabled == true);
}
 
}

Now, I do have a repository base and interface that make use of DataContext class directly, and use GetTable<T> instead, as well as a ContextFactory class.

The thing is, in my mind anyway, doing so adds a layer of complexity that just isn’t required. The amount of code saved in the long run just doesn’t outweigh the one or two methods that need to be added into top level classes otherwise.

Basically, instead of having:

Category.cs
CategoryMetadata.cs
CategoryRepository.cs
ICategoryRepository.cs
Repository.cs
IRepository.cs
ContextFactory.cs
IContextFactory.cs
ConnectionStringFactory.cs
IConnectionStringFactory.cs
MappingSourceFactory.cs
IMappingSourceFactory.cs
Persistence.map

I now have:

Category.cs
CategoryMetadata.cs
CategoryRepository.cs
ICategoryRepository.cs
Venue.dbml

Much clearer to me.

ok…

put that into the container and inject then… well not the model classes :stuck_out_tongue: