0

I'm trying to develop an ASP.NET MVC-application with an additional Web API. To reduce code-duplication, I'd like to share as much code as possible, but with the possibility to differentiate between the two projects if needed.

My plan is to create a Shared Class Library that contains:

  • Entity-classes
  • Service-classes
  • ViewModel-classes

For example:

   class Post
    {
        public int Id { get; set; }
        public string Body { get; set; }
        public Author Author { get; set; }
    }

    class Author
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    class PostViewModel
    {
        public int PostId { get; set; }
        public string PostBody { get; set; }
        public string AuthorName { get; set; }
    }

    class BlogService
    {
        public IEnumerable<PostViewModel> GetPosts()
        {
            //retrieve entity's from DB and convert to ViewModel-objects
            return new List<PostViewModel>();
        }
    }

But with this approach, I'm affraid of the tight-coupling between the ViewModels in the MVC-application and the Web API.

A solution could be to let the Service return a DTO-object and to let the controller handle the conversion to the right ViewModel (API Controller -> API-specific, Web Controller -> Web-specific), but this seems like a lot of boilerplate-code to handle the conversions between the different layers.

Do you have any best practices regarding this scenario?

Thank you in advance!

3
  • I think my biggest question is, why does the MVC application need to use the same classes as the web API? Why isn't the MVC application delegating to the API for those operations? Nov 2, 2022 at 13:14
  • @GregBurghardt: isn't that overkill, since I can call the services/classes directly in my controller?
    – Sam
    Nov 2, 2022 at 13:18
  • If you aren't calling the web API from the MVC app, why does the web API even exist? You are introducing coupling between applications if the MVC app is directly using classes from the web API. Nov 2, 2022 at 14:12

2 Answers 2

0

ViewModels are there to service the views, so they more correctly belong in the MVC project.

There are many ways to skin a cat, but I'd be inclined to have the domain models in their own project with both the MVC & Web API projects referencing it.

You could also have an interfaces project to simplify dependency injection to be able to test each of the layers in isolation.

0

For this answer, I want to zoom in on your observation:

but this seems like a lot of boilerplate-code to handle the conversions between the different layers

That's not an argument for why it shouldn't be done, it's an argument for why it should be done as painlessly as possible.

The short answer

A mapping tool like Automapper can significantly help cut down on boilerplate fluff. You still have to map it, but it's significantly less copy/pasting between different endpoint to make sure the mapping gets executed.

The longer answer

One of the main reasons people put clean coding practices aside is "because it's too much boilerplate". That observation, however, is made by someone who is used to performing non-clean coding practices, and therefore the effort needed to clean up the code looks like it's extra work.

As someone who is very used to clean coding by now, I could call those non-clean coding practices bad "because it cuts too many corners". Same argument, but from a different side.

Notice the different observations here. The key difference is that the person in the first paragraph and me (in the second paragraph) are disagreeing on what is the "normal" amount of code that is expected.

So when you say that it's "too much boilerplate", you have to acknowledge that this is based on your own opinion on how much code should be written. This is the part where I ask you to re-evaluate your own bias - how convinced are you that your idea is the objectively and universally correct one? How can you be sure that you're not mistakenly thinking that the "normal" amount of code you expect is actually less than it should be? (This is rhetorical, discussing this is an endless back and forth)

While clean coding does force you to do some of the work upfront when you're setting things up, it pays back dividends that are multiple times the effort you invested in the long run. If it didn't, no company or experienced developer would be advocating for clean coding (nor would they call it that).

Going back to your scenario, while it's going to take additional effort to set up this additional layer, it will start saving you time once you start making changes to the shared logic. You will avoid "updated one, forgot another" kinds of bugs and regressions because there now only is one thing to update that affects both use cases.

It may not seem like much today, because today is where you have to put in the effort to make it so. However, clean coding is cumulative. Today, you will put in extra effort and avoid future trouble. Tomorrow, you will also put in extra effort in a different part of the codebase, and you will avoid future trouble.

Do this enough days in a row, and your daily developer experience will be significantly easier and lighter than if you had avoided the good practice.
The reason this may not seem apparent to you now, in the assumption that you've never really worked in a clean coding environment, is because you don't realize that the kinds of bugs and issues you have in the future, or more specifically their difficulty, was caused by some bad practice decisions you made in the distant past.

The bugs will still happen. Clean coding does not stop you from making mistakes, or from the requirements changing.

But the bugs/changes will be significantly easier to identify, locate, and fix/implement. I can attest from personal experience that between the best and worst projects I've worked on, I could either fix 6-10 bugs in a day with no stress (best) or 1 bug would take me a week of complicated tracking and getting to grips with difficult to read code, and the fix would be very liable to cause another issue somewhere else in the codebase.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.