2

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?

3
  • Implementing the DTOs doesn't stop someone from just 'adding a little logic' to the controllers. MVC is it's own paradigm, I wish that people would realize that and stop trying to add n-tier concepts. Commented Nov 30, 2011 at 20:26
  • The question is not about MVC it's about the sign of "+" in "MVC + BL" Commented Nov 30, 2011 at 20:30
  • Controllers should contain buisness logic regarding the actions that are part of the controller, models should encapsulate the other business logic. Unless you need to connect to a WCF or other service to access your data in which case you can encapsulate that in the EF. There is no need for an n-tier BL abstraction with the PL/BL/DL in separate assemblies. The MVC pattern is pretty clear about what goes where. Commented Nov 30, 2011 at 20:35

1 Answer 1

1

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 :)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.