关注点分离; MVC;为什么?

时间:2009-03-12 17:23:52

标签: php model-view-controller user-interface oop

在我开始下一个重大项目之前,我正在阅读OO。为了给你一些快速的背景知识,我是一名PHP开发人员,致力于Web应用程序。

我特别感兴趣的一个领域是用户界面;具体如何构建它并将其连接到我的OO“模型”。

我一直在读这个领域。我最喜欢的一个是: Building user interfaces for object-oriented systems

  

“所有对象都必须提供自己的用户界面”

考虑到我的问题,我可以看到它运作良好。例如,我构建了我的“用户”对象来代表登录我网站的人。我的一种方法是“display_yourself”或类似方法。我可以在整个代码中使用它。也许从这开始就是他们的名字。之后,如果我需要调整以显示他们的名字+小头像,我可以更新这个方法,嘿-presto,我的应用程序更新。或者如果我需要将他们的名字作为他们个人资料的链接,嘿-presto我可以从一个地方轻松更新。

就OO系统而言;我认为这种方法效果很好。看看其他StackOverflow线程,我在“Separation of Concerns”下找到了这个: Soc

  

“在计算机科学中,分离   关注点(SoC)就是这个过程   打破计算机程序   重叠的不同特征   功能尽可能少。一个   关注是任何利益或   专注于一个计划。通常情况下,   问题是功能的同义词   或行为。 SoC的进展是   传统上通过实现   模块化和封装,与   信息隐藏的帮助。“

在我看来,我已经实现了这一点。我的用户对象隐藏了它的所有信息。在我显示它之前,我在代码中没有任何地方我说$ user-> get_user_name()。

然而,这似乎违背了其他人似乎认为的“最佳实践”。

引用同一问题中的“选定”(绿色)答案:

  

“关注点的分离仍在继续   每个问题的代码   分离。更改界面   不应该要求改变   业务逻辑代码,反之亦然。   模型 - 视图 - 控制器(MVC)设计   模式是一个很好的例子   将这些问题分开来更好   软件可维护性。“

为什么这会带来更好的软件可维护性?当然,对于MVC,我的View必须对模型有很多了解吗?阅读JavaWorld文章,了解有关这一点的详细讨论: Building user interfaces for object-oriented systems

无论如何......最后到达实际点!

1。任何人都可以推荐任何详细讨论此内容的书籍吗?我不想要一本MVC书;我不是在MVC上卖的。我想要一本讨论OO / UI,潜在问题,潜在解决方案等的书。(可能包括MVC) 亚瑟瑞尔的Object-Oriented Design Heuristics

触及它(也是一本优秀的书!),但我想要更详细的内容。

2。任何人都可以提出一个与Allen Holub的JavaWorld文章一样好解释的论点,该文章解释了为什么MVC是一个好主意?

非常感谢能够帮助我就此做出结论的任何人。

8 个答案:

答案 0 :(得分:32)

这是如何经常教授OOP的失败,使用像rectangle.draw()和dinosaur.show()这样的例子,这些都是毫无意义的。

当你谈论有一个显示自己的用户类时,你几乎回答了自己的问题。

“稍后,如果我需要调整以显示他们的名字+小头像,我可以更新这个方法并嘿-presto,我的应用程序更新。”

暂时想想那件小事。现在看看Stack Overflow并注意您的用户名出现的所有地方。在每种情况下看起来都一样吗?不,在顶部,您的用户名旁边有一个信封,后跟您的声誉和徽章。在一个问题主题中,你已经获得了你的头像,然后是你的用户名,下面是你的声誉和徽章。你认为有一个用户对象有像getUserNameWithAvatarInFrontOfItAndReputationAndBadgesUnderneath()这样的方法吗?全息

对象关注它所代表的数据以及对该数据起作用的方法。您的用户对象可能具有firstName和lastName成员,以及检索这些部分所需的getter。它也可能有一个方便的方法,比如toString()(用Java术语),它会以通用格式返回用户的名字,比如第一个名字后跟一个空格,然后是姓氏。除此之外,用户对象不应该做太多其他事情。由客户决定它想要对象做什么。

以您向我们提供用户对象的示例为例,如果您在其中构建了“UI”,请考虑如何执行以下操作:

  1. 创建一个CSV导出,显示按姓氏排序的所有用户。例如。姓氏,名字。
  2. 提供重量级GUI和基于Web的界面以使用用户对象。
  3. 在一个地方显示用户名旁边的头像,但只在另一个地方显示用户名。
  4. 提供RSS用户列表。
  5. 在一个地方显示粗体用户名,在另一个地方显示斜体,在另一个地方显示超链接。
  6. 在适当的位置显示用户的中间名。
  7. 如果你考虑这些要求,它们都归结为提供一个只关注它应该关注的数据的用户对象。它不应该试图成为所有人的所有事情,它应该只是提供获取用户数据的手段。您将创建每个许多视图,以决定如何显示用户数据。

    您想在一个地方更新代码以在许多地方更新您的观点是一个很好的想法。这仍然是可能的,不会在太低的水平上捣乱。您当然可以创建类似于小部件的类,它们将封装各种常见的“东西”视图,并在整个视图代码中使用它们。

答案 1 :(得分:25)

答案 2 :(得分:3)

我不确定我是否可以带你到你喝的水,但我想我可以回答你的一些问题。

首先,在MVC中,模型和视图确实有一些相互作用,但视图实际上与合同相关,而不是实现。您可以转移到符合相同合同但仍能使用该视图的其他模型。并且,如果你考虑它,它是有道理的。用户具有名字和姓氏。他可能还有登录名和密码,尽管您可能会或可能不会将此与用户的“合同”联系起来。关键是,一旦确定用户是什么,就不太可能发生太大变化。你可能会添加一些东西,但你不太可能经常拿走它。

在视图中,您有指向符合该合同的模型的指针,但我可以使用一个简单的对象:

 public class User
 {
    public string FirstName;
    public string LastName;
 }

是的,我意识到公共领域很糟糕。 :-)我也可以使用DataTable作为模型,只要它公开FirstName和LastName。这可能不是最好的例子,但重点是模型与视图无关。该视图与合同相关联,特定模型遵守该合同。

我没有听说过每个对象都必须有自己的UI。基本上有两种类型的对象:状态和行为。我已经看到了具有状态和行为的示例,但它们通常位于不太可测试的系统中,这是我不喜欢的。最终,每个状态对象都应该暴露给某种形式的UI,以避免迫使IT人员直接在数据存储中处理所有更新,但是有自己的UI?我必须看到在解释中写的,试图了解用户正在做什么。

对于SoC来说,明确打包事物的方法是能够在不重写整个系统的情况下切换层/层。通常,应用程序实际上位于业务层中,因此该部分不能轻易切换。在设计良好的系统中,数据和UI应该相当容易切换。

关于理解OOP的书籍,我倾向于喜欢关于模式的书籍,因为它们是理解概念的更实用的方法。您可以在网上找到底漆材料。如果你想要一本与语言无关的模式书,并且认为有点怪异,那么四人帮书就是一个很好的起点。对于更具创意的类型,我会说Heads Up Design Patterns。

答案 3 :(得分:2)

所有对象都知道如何显示自己的想法的问题是每个对象只能以一种方式显示。如果要提供用户的详细视图和摘要视图,会发生什么。如果要显示合并多个对象(例如用户及其关联地址)的视图,会发生什么。如果你将业务对象(用户)与知道如何显示它们的东西分开,那么你就没有更多的代码可以编写,只需将它分隔到不同的地方。

这使得软件更易于维护,因为如果用户对象的行为不正确,您知道它是用户,如果它没有正确显示,您就知道它是视图。在您需要为应用程序提供新界面的情况下(假设您决定为移动浏览器提供新的外观),那么您根本不需要更改用户对象,添加一个知道如何的新对象为移动浏览器呈现用户对象。

SOLID原则提供了一些很好的理由,here对这些原则进行了相对简洁的研究。我担心我没有完整的书,但经验告诉我,编写新代码比更新旧代码更容易,所以设计有利于插入到一起的小模块类。从长远来看,实现所需的功能虽然更难设计,但更容易维护。很高兴能够为用户对象编写新的渲染器,而无需深入研究该对象的内部。

答案 4 :(得分:2)

  

任何人都可以提出一个论证,解释为什么MVC是一个好主意?

通过帮助您记住代码的作用,让您保持理智,因为它们彼此隔离。

答案 5 :(得分:1)

  • 考虑一下代码量 如果是的话会进入那个单一的课程 你想要公开相同的信息 仅作为UI上的Html,但作为一部分 RSS,JSON,休息服务 使用XML,[插入其他内容]。
  • 这是一个漏洞的抽象,意味着它试图让你感觉它将是唯一能够知道数据的部分,但这不是完全真实的。假设您希望提供与多个外部第三方集成的服务。您将很难迫使他们使用您的特定语言与您的服务集成(因为它是该类唯一可以使用它的数据的部分),或者如果另一方面您暴露了一些数据您没有隐藏这些第三方系统的数据。

更新1:我全面了解了整篇文章,并且作为一篇旧文章(99),它并不是关于我们今天所知的MVC与面向对象的关系,也不是有反对SRP的论据。

你完全可以与他所说的完全一致,并处理我提到的上述场景,负责将对象的公共合同转换为不同格式的特定类:主要关注的是我们没有一个明确的地方处理变更,我们也不希望信息全部重复。所以,在html的情况下,你可以完美地拥有一个呈现信息的控件,或者一个将它转换为html或[在此处插入重用机制]的类。

不过,我的RMI位闪回。无论如何,在那个例子中,你可以看到他与沟通机制有关。也就是说,每个方法调用都是远程处理的。我认为他也非常担心开发人员有代码而不是获得单个对象并对返回的信息进行操作,有大量小的Get调用来获取大量不同的信息。

聚苯乙烯。我建议你阅读关于DDD和Solid的信息,就像我对SRP说的那样,我不会说这是作者抱怨的事情类型

答案 6 :(得分:1)

我不知道有关MVC主题的任何好书,但根据我自己的经验。例如,在Web开发中,很多时候您与设计师合作,有时甚至是dbas。将逻辑与演示文稿分开可以让您更好地与不同技能组合的人合作,因为设计人员不需要太多编码,反之亦然。此外,对于DRY的概念,您可以使代码重复性更低,更易于维护。您的代码将更加可重用,使您的工作变得更加轻松。它还将使您成为更好的开发人员,因为您将变得更有条理,并以不同的方式思考编程。因此,即使您必须处理非MVC的事情,您也可能采用不同的方法来构建项目,因为您了解MVC概念。

我想与大型网站的许多MVC框架进行权衡是因为它可能不够快,无法处理负载。

答案 7 :(得分:0)

我的2c ..除了所说的之外,你可以做的另一件事是使用你的User对象的装饰器。这样,您可以根据上下文以不同方式装饰用户。所以你最终会得到WebUser.class,CVSUser.class,RSSUser.class等。

我不是真的这样做,它可能会变得混乱,但它有助于避免客户端代码不得不从用户那里获取大量信息。这可能是一件有趣的事情; - )