Question

Let's say you're implementing your own version of stackoverflow (once again, yes)

You have a service that provides all the required functionality like this:

class Question { ... } // EF entity
class Answer { ... } // EF entity

interface IStackoverflowService
{
    void PostQuestion(Question question);
    void PostAnswer(Answer answer);
    void UpdateQuestion(Question question);
    ...
}

That seems to be pretty simple and generally I believe it's a good idea. The only thing that I don't like here is that client code (ASP.NET MVC controllers) has direct access to Questions and Answers. Pretend we have some tough BL related with posting questions and answers. It's good idea to have this logic concentrated in a "single place" - on a service layer. In case your client code has access to Questions, it's possible that someday somebody will decide to add "just a little bit of logic" to one of your controllers which is basically bad idea.

I'm thinking about defining a number of DTOs which will be the part of service interface, so the client code will only be able to work with these DTOs that contain "just the right amount of details".

Let's say your question entity is defined like this:

interface Question
{
    int Id { get; set; }
    User Poster { get; set; }
    DateTime Posted { get; set; }
    DateTime? Edited { get; set; }
    string Title { get; set; }
    string Text { get; set; }
    IQueryable<Answer> Answers { get; set; }
    ...
}

When posting the question, the request should only contain Title, Text and Poster. So, I'll define a PostQuestionDTO:

class PostQuestionDTO
{
    User Poster { get; set; }
    string Title { get; set; }
    string Text { get; set; }
}

When somebody opens the page to check the question, there's a little bit more details like Posted and Edited:

class QuestionDetailsDTO
{
    User Poster { get; set; }
    string Title { get; set; }
    string Text { get; set; }
    DateTime Posted { get; set; }
    DateTime? Edited { get; set; }
}

And so on. Is it a good practice or do you think it's overengineering? What are the common approaches here?

Was it helpful?

Solution

I've recently implemented pretty much exactly what you're talking about, using a lot of Ninject and AutoMapper. My logical structure is like this:

    MyCompany.Data // Data layer namespace containing EF EDMX file / Codefirst / ADO.Net, whatever you want.
    class User { } // EF Entity

MyCompany.Business // Business layer namespace containing business level factory interfaces and classes that expose their own business objects (some are directly mapped to the DB, most are not). All members expose POCO objects

class NewUser { } // POCO class RegisteredUser { } // POCO interface IAccountFactory {
    void AddUser(NewUser user);
    RegisteredUser GetUser(int id); } // factory interface class AccountFactory : IAccountFactory // Service provider

MyCompany.MVC // Presentation layer containing controllers and views. Controllers expose POCO objects from the business layer to the Views.

I don't think it's overkill at all - yes, it takes a little longer to write, but AutoMapper basically removes most of the donkey work for you.

A colleague of mine is very keen on Inversion of Control, which apparently solves this problem... though I'm not completely sold on it yet :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top