TL;DR - When designing classes for MVC use, is there "best practice" for how classes should be structured to eliminate property duplication and/or redundancy? I'm trying to avoid large (one-size-fits-all) classes with many (redundant) properties, but am also concerned about having too many isolated classes.

I've been searching for guidelines/examples all day with this, and I assuming that the answer is either too subjective, or is explicitly answered on a case-by-case basis. If so, please comment and I'll close the question.

Suppose I have an MVC app that displays to-do list items, e.g.:

public class ToDoItem {
   public datetime Deadline {get;set;}
   public string Summary {get;set;}
   public string Detail {get;set;}
   public double EstimatedCost {get;set;}
}

I can easily create a list/array of items and display them. However, what if a different view requires a summary of all items for all people? For example:

public class ToDoItemDeadlineSummary {
   public string PersonName {get;set;}
   public string Summary {get;set;}
   public datetime Deadline {get;set;}
}

Elsewhere, someone requests a view that displays cost summaries:

public class ToDoItemCostSummary {
   public string PersonName {get;set;}
   public string Summary {get;set;}
   public double EstimatedCost {get;set;}
}

Then maybe later new views need to compare cost vs. deadlines, etc. In time, there could be potentially many classes with properties repeated across them.

Is it best to just use a separate (isolated) class for each requirement, or can inheritance/interfaces solve this problem in its entirety when future requirements are not known? Or, is there a completely different approach that future-proofs things in a better way?

有帮助吗?

解决方案

TL;DR
If you duplicate too much, you violate DRY/YAGNI. If you reuse too much, you (may) end up having to rewrite core parts of your domain logic later on.

Never abstract for abstraction's sake, never duplicate just for duplication's sake. Always look at your situation and pick the approach that fits your situation.


I assuming that the answer is either too subjective, or is explicitly answered on a case-by-case basis. If so, please comment and I'll close the question.

It's both (developer preference and project context), but I don't think this is a reason for closing. Finding the balance between reuse and duplication is a key skill for any experienced developer, and it's an incredibly hard balance to strike. That is, in my opinion, very much on topic for software engineering.


Minimizing development effort

There are boundaries to what is reasonable, but this is otherwise a "pick your poison" type of scenario.

When you have two things that are currently structurally the same (and not just coincidentally), you can either reuse the same structure or duplicate it. The question is whether you're going to have to change one (but not the other) in the future.

  • If you reused the same structure and did not need to change one of the structures later on, you chose wisely.
  • If you duplicated the same structure and needed to change one of the structures later on, you chose wisely.

Those two are obvious. But what happens when you choose wrongly?

  • If you reused the same structure and did need to change one of the structures later on, you have to now duplicate it. This entails having to revisit all of the old structure's references and evaluating whether they should reference the new structure or not. This can lead to further duplications for classes that e.g. consume this structure.
  • If you duplicated the same structure and did not need to change one of the structures later on, you will have wasted the effort that was required to create a second structure. Also, for any changes that need to be applied to both structures, you will have to implement the same changes twice, and are liable to introduce bugs if you forget to change one of them.

Comparing the two bullet points by themselves, the former has a bigger impact on effort than the latter. This is exactly why most senior developers I work with err on the side of duplication. It's such an ingrained choice that they don't even reconsider this anymore and blindly favor duplication because they've experienced issues when they forgot to duplicate something in the past.


However...

There is one more thing to consider: how many things are you going to need to change in the future? Because right now, we've been comparing one set of structures. But if you're building an enterprise grade codebase from scratch, and you always choose duplication, then you're going to end up with hundreds of duplicates.

If it turns out that you never needed to change 99% of these structures, even though you did save time on the 1% that did need changes further down the line (by pre-emptively duplicating all 100% of the structures), you wasted the effort of duplicating the other 99%. This is a different numbers game, and here the answer can swing the other direction. Maybe it's better to have to duplicate one structure after the fact than it is to pointlessly duplicate 99 structures which you never needed to change afterwards.


I can't give you a universally applicable objective answer. If you duplicate too much, you violate DRY/YAGNI. If you reuse too much, you (may) end up having to rewrite core parts of your domain logic later on.

How do you know where the line of "too much" is? Well, that's very situational.

It all depends on how liable your codebase is to change over time. If you're making a calculator app, I can tell you with reasonable certainty that the core principles of math are not going to change any time soon; so you can rest assured that there won't be much reworking.
Compare this to e.g. a government project involving legislature (e.g. tax calculations), and you'll realize that the business logic is incredibly volatile (as laws change or get tweaked often), and there'll be a high amount of changes to the existing codebase in the future.

Whichever option you pick, you're going to end up wasting effort if you end up having picked the wrong one. It's not always possible to gauge beforehand whether a significant amount of changes will or will not be required.
Furthermore, this can be situational. Some business logic may be volatile (e.g. data validation), whereas other components may be relatively set in stone (e.g. based on your company culture).

As much as abstraction and loose coupling is generally advocated so you can avoid/minimize future maintenance roadblocks, when you overdo it, you're going to have wasted effort as well.

Never abstract for abstraction's sake, never duplicate just for duplication's sake. Always look at your situation and pick the approach that fits your situation.

其他提示

Make sure you don't blur the responsibilities between views and models. You're talking about inheritance but a view has a totally different responsibility to a TodoItem and changes for different reasons.

If you just want to show for example PersonName in your view without duplicating it then simply creates a proxy property to the property on the TodoItem Object.

许可以下: CC-BY-SA归因
scroll top