简体   繁体   English

什么是适合我的案例的基于 MVC 的 OOP 设计?

[英]What is an appropriate MVC-based OOP design for my case?

Suppose the following baseline design: I have a class CarElement which holds properties and methods related to both visual representation and data model/logic representation of a car:假设以下基线设计:我有一个CarElement类,它包含与汽车的视觉表示和数据模型/逻辑表示相关的属性和方法:

class carElement
{

    // UI related properties and methods:
    public Size DrawSize { get; set; }
    public Point Location { get; set; }

    public void Draw()
    {
        // do something...
    }

    // data model / logic related properties and methods:
    public double weight { get; set; }
    public string manufacturer { get; set; }

    public double CalculatePrice()
    {
        // do something...
        return 0;
    }
}

The usage of this class is as follows: Multiple instances of carElement are drawn to some canvas.这个类的用法如下: carElement多个实例被绘制到某个画布上。 Clicking each drawn car shows the properties of that car in a property grid by using propertygrid.SelectedObject = InstanceOfcarElement .单击每个绘制的汽车会使用propertygrid.SelectedObject = InstanceOfcarElement在属性网格中显示该汽车的属性。

In my opinion, this design is flawed because data model and visual representation are not separated in the class design.在我看来,这种设计是有缺陷的,因为数据模型和可视化表示在类设计中没有分开。 I would like to improve the design towards MVC and I am seeking advice on good design decisions.我想改进面向 MVC 的设计,我正在寻求有关良好设计决策的建议。

My current take on this would be to separate above class carElement into something like the following two classes.我目前对此的carElement是将上面的carElement类分成以下两个类。

class carUIElement // organizes visual representation of a car
{
    public Size DrawSize { get; set; }
    public Point Location { get; set; }

    private carDataElement linkedCarDataElement;

    public void Draw()
    {
        // do something...
    }

}

class carDataElement // organizes data model organization of a car
{   

    public double weight { get; set; }
    public string manufacturer { get; set; }

    private carUIElement linkedCarUIElement;

    public double CalculatePrice()
    {
        // do something...
        return 0;
    }
}

With that approach, the following are unclear to me:使用这种方法,我不清楚以下几点:

  • carUIElement should know the carDataElement it is linked to, and vice versa. carUIElement应该知道它链接到的carDataElement ,反之亦然。 Are there better design approaches to this than the simple linking in above Code?有没有比上面代码中的简单链接更好的设计方法?
  • How would I best show both the UI and data model properties on the property Grid, when the drawn UIElement is clicked?单击绘制的 UIElement 时,如何最好地在属性 Grid 上同时显示 UI 和数据模型属性?

Is the overall approach viable?整体方法是否可行? What about the above open points?以上开放点呢? I am missing the experience to judge that, so I would be grateful for your comments.我错过了判断这一点的经验,所以我会很感激你的评论。 Thank you.谢谢你。

Well while we should always be careful not to over intellectualize stuff, after all we as programmers are more masons than artist and even if Notre Dame church is just a construction and not art, no always will be required exorbitant decoration and acoustic chambers, suppose the next version will be as grand as the previous :)好吧,虽然我们应该始终小心不要过度智能化,毕竟我们作为程序员比艺术家更像是泥瓦匠,即使圣母教堂只是一个建筑而不是艺术,也不总是需要过高的装饰和隔音室,假设下一个版本会和上一个一样盛大:)

What do i mean?我是什么意思? I propose pragmatism with MVC, so if and if in early infancy of the program, it can have the ui model, also sometimes called the data transfer object, be identical to the logical model, that is not in itself an anti-pattern imo.我建议 MVC 实用主义,所以如果在程序的早期阶段,它可以有 ui 模型,有时也称为数据传输对象,与逻辑模型相同,这本身不是反模式 imo。 Obviously once bulding ui, we begin to have released instances with presumed constructs and when it starts to limit development of the product, how it is presented, typically when you need more info than is relevant to ui, stored on the entity, then you can lock the interface by inventing the DTO model objects and party on with the initial model.显然,一旦构建了 ui,我们就开始发布具有假定构造的实例,当它开始限制产品的开发时,它是如何呈现的,通常是当您需要更多与 ui 相关的信息时,存储在实体中,然后您可以通过创建 DTO 模型对象并使用初始模型来锁定接口。 So I get where you're going with what's behind why you might want to separate it.所以我知道你要去哪里以及为什么你可能想要将它分开。

Then again often we have web frontends, especially with mvc and then mostly it will be no longer a databound view, but a MVVM thingy like like Angular, React, Vue or even Blazor if for some reason you might want that, or the tradition Razor pages, really?再说一次,我们经常有 Web 前端,尤其是使用 mvc,然后大多数情况下它将不再是数据绑定视图,而是像 Angular、React、Vue 甚至 Blazor 之类的 MVVM 之类的东西,如果出于某种原因你可能想要它,或者传统的 Razor页,真的吗? in new development??在新的发展?? I try not to put anything in the DTO classes that would be lost if only the serialized JSON version is available to your view engine.如果只有序列化的 JSON 版本可用于您的视图引擎,我尽量不将任何内容放入 DTO 类中。 So that when modernization happens, your controller/ api doesn't have to principally change.因此,当现代化发生时,您的控制器/api 不必主要更改。

So seperate classes for seperate concerns an no logic in data access or transfer classes, my suggestion would be something along the lines below, but to end up with your questions:因此,单独的单独类与数据访问或传输类中的逻辑无关,我的建议将是以下几行,但最终会提出您的问题:

a) Linking with a navigation property in your data model makes sense if you use it to load for instance using entity framework, it is required. a) 如果您使用它来加载数据模型中的导航属性,例如使用实体框架,则它是必需的。 In Your UI type the frequency is key, typically we like to push all data into the points so that they need nothing else to perform, but this makes sense if the class is being serialized and deserialized and you use a tool like AutoMapper to move to and from, if You're in a windows client like WPF hey your model is already on the client and already loaded up for MVVM, you're in such a much better place that you may not honestly care for front-end types, until they need to vary.在您的 UI 类型中,频率是关键,通常我们喜欢将所有数据推送到点中,这样它们就不需要执行任何其他操作,但是如果类正在被序列化和反序列化并且您使用 AutoMapper 之类的工具移动到从,如果您在像 WPF 这样的 Windows 客户端中,嘿您的模型已经在客户端上并且已经为 MVVM 加载,那么您处于一个更好的位置,您可能不会诚实地关心前端类型,直到他们需要改变。

b) the question is do you always want to show both or can you hide the cardata element until they ask for it, that would dictate the choice to either let a DTO include the data from the relation or just the foreign key and have an extra lookup method available imo. b) 问题是你是否总是想同时显示这两个元素,或者你可以隐藏 cardata 元素直到他们要求它,这将决定让 DTO 包含来自关系的数据或只包含外键的选择,并有一个额外的可用的查找方法imo。

So suggestion brief:所以建议简短:

/// <summary>
/// Drawing is a separate concern of the application
/// </summary>
class DrawManager
{
    public void DrawCar(CarBase car) { }
}

/// <summary>
/// So is calculating prices
/// </summary>
class PriceManager
{
    decimal CalculateCarPrice(CarBase car) { throw new NotImplementedException(); }
}

/// <summary>
/// The 2 classes share properties, invent a base class to abide by the DRY principle
/// </summary>
class CarBase
{
    public Size DrawSize { get; set; }
    public Point Location { get; set; }
}

/// <summary>
/// Now they are identical
/// </summary>
class carElement : CarBase
{
    carDataElement CarData { get; set; }
}

/// <summary>
/// Now they are identical
/// </summary>
class carUIElement : CarBase
{
    carDataElement linkedCarDataElement;
}

/// <summary>
/// The data about a car, in RDBMS typically normalized into a seperate entity like you have,
/// does UI really need any of them? Is it always needed when other members are accessed? 
/// </summary>
/// <remarks>
/// we could choose to have the data model have a navigation property and then let the ui member not have it and give it a method to ackquire it,
/// but then that shouldn't get done to early and well if it always needs it, it is not yet a seperate datatype justification for the ui aspect
/// </remarks>
class carDataElement
{
    public double weight { get; set; }
    public string manufacturer { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM