当版本相关时建模版本控制

发布于 2024-07-17 02:25:15 字数 1230 浏览 8 评论 0原文

我正在对类图进行建模,但我绝对遇到了这个问题:

我的新 Web 应用程序有“卡片”(有关某个主题的条目),用户可以对其进行修改,就像维基百科一样。 但与维基不同,不同的卡片保存不同的数据。 与维基百科不同的是,卡片与数据库中的其他卡片明确相关。 让我向您展示我最初是如何使用虚拟示例来设计它的:

/** Similar to strategy/bridge pattern */
class Card<T extends CardInfoVersion> is composed of T // container of versions
class CardInfoVersion // one version
class Painting extends CardInfoVersion 
class Museum extends CardInfoVersion is composed of Paintings

优雅、干净,但是错误。 使用这种方法,博物馆与绘画版本联系在一起,而不是与绘画本身联系在一起。 我想到的第一个解决方案是:

class Card<T extends CardInfoVersion> is composed of T
class CardInfoVersion
class Painting extends CardInfoVersion
class Museum extends CardInfoVersion is composed of Card<Painting>

这种方法很糟糕。 CardInfoVersion 下的类层次结构很大,因此 UML 模型将不可读,并且 Card 类将填充对 CardInfoVersion 子类的 ORM 引用。 然后我想出了这个:

class Card is composed of proposedModifications: Set<Card>
class Painting extends Card
class Museum extends Card is composed of Paintings

这也有味道。 事实上,自从版本消失后,这一切都变得一团糟。 它还要求管理员验证对卡的拟议修改。

我真的不知道如何解决这个问题。 记住:如果 CardInfoVersion 子类不相互关联,原始设计就可以。

请帮忙!

I'm modelling a class diagram and I'm absolutely stuck with this issue:

My new web application has "cards" (entries about a subject) which can be modified by the users, à là wiki. But unlike wikis, different cards hold different data. Also unlike wikis, cards are interrelated with other cards explicitly in the database. Let me show you how I initially designed it using a dummy example:

/** Similar to strategy/bridge pattern */
class Card<T extends CardInfoVersion> is composed of T // container of versions
class CardInfoVersion // one version
class Painting extends CardInfoVersion 
class Museum extends CardInfoVersion is composed of Paintings

Elegant, clean, but wrong. Using this approach, museums are tied to painting versions, not to the painting itself. The first solution that came off my head was this one:

class Card<T extends CardInfoVersion> is composed of T
class CardInfoVersion
class Painting extends CardInfoVersion
class Museum extends CardInfoVersion is composed of Card<Painting>

This approach smells. Class hierarchy under CardInfoVersion is huge, so UML model would be unreadable and Card class would be filled with ORM references to CardInfoVersion subclasses. Then I came up with this:

class Card is composed of proposedModifications: Set<Card>
class Painting extends Card
class Museum extends Card is composed of Paintings

Which also smells. In fact, this is all messed up since the version vanishes. It also requires administrators to validate proposed modifications to cards.

I don't really know how to solve this problem. Remember: original design would be OK if CardInfoVersion subclasses weren't interrelated.

Please help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月依秋水 2024-07-24 02:25:15

我会采用领域驱动的方法。 您的用户会称它们为“卡片”吗? 这似乎是一个技术问题,但您将技术问题(卡片)与领域问题(博物馆、绘画)混合在一起。

如果不了解您的域和用户,就很难猜测您的最终解决方案是什么。

也许是这样的:

class Museum extends Content is composed of Paintings
class Painting extends Content

class Card is composed of Set<Content>

这样你就可以将领域模型(博物馆、绘画)与视图模型(卡片)分开。 我什至会更进一步,不使用继承(使用普通的旧java对象)路线,但我不知道你的确切实现。

如果您想了解有关这种设计风格的更多信息,此播客是有帮助。

I would take a domain-driven approach. Would your user call them "cards"? That seems to be a technical concern, but you're mixing your technical concern (Cards) with domain concerns (Museums, Paintings).

Without knowing your domain and users it's hard to take a guess at what your final solution would be.

Perhaps this:

class Museum extends Content is composed of Paintings
class Painting extends Content

class Card is composed of Set<Content>

That way you're separating your domain model (Museum, Painting), with your view model (Cards). I would even take it one step further and not use inheritance (go with the plain-old-java-object) route, but I don't know your exact implementation.

If you want more information on this style of design, this podcast is helpful.

月牙弯弯 2024-07-24 02:25:15

@Michael 有一个很好的观点。 博物馆是一个域对象,绘画也是。 听起来你是在用“卡片”来收集不同人对画作的评论。 这表明 CardFile 就是您要建模的内容。 CardFile 将是卡片的集合。 卡片引用了相关的博物馆或绘画。

以下是一些提示:

  • 写出一些用户故事或用例。 你太早陷入程序员思维了; 首先想想你想做什么。 如果您没有最喜欢的方法,请使用此模型:“某人”“做某事”“以获得一些结果”。 例如,“我获取了所有关于 Magritte 'Ceçi n'es pas une pipe' 的卡片,以便找出哪个博物馆拥有它。”

  • 为类编写一些“用户代码”。 伪代码很好,但它确实有助于设计界面。

所以你可能会写:

cards := cardfile.getAllCards(ceciNesPas)
for each card in cards
do
    print card.getPainting().getMuseum()
od

我根本不是发誓这是最好的方法,只是一个例子。

  • 如果这里的“版本控制”是有许多卡片与同一幅画相关联,那么现在您已经设置好了。 如果卡片上的格式、方法、数据项随着时间的推移而变化,那么您需要确定卡片特有的内容,并将其设为超类。 然后,您可以使 Card 的更高版本成为 Card 的新子类:保持不变的内容位于超类中,不同的部分属于子类的事务。

@Michael has a good point. Museum is a domain object, so is Painting. It sounds like you're using the "cards" to collect various people's comments about the paintings. That suggests a CardFile is what you're trying to model. A CardFile would be a collection of Cards. A Card has a reference to the associated Museum or Painting.

Here are some hints:

  • write out some user stories or use cases. You're getting caught in programmer-thinking too early; think about what you want to do first. If you don't have a favorite way of doing this, then use this model: "Someone" "does something" "to get some result." So, for example, "I get all the cards about Magritte 'Ceçi n'es pas une pipe' in order to find out which museum has it."

  • write some "user code" for the classes. Pseudocode is fine, but it really helps come up with the interface.

So you might write:

cards := cardfile.getAllCards(ceciNesPas)
for each card in cards
do
    print card.getPainting().getMuseum()
od

I'm not at all swearing this is the best way, but an illustration.

  • If the "versioning" here is that there are many cardcs associated with the same painting, now you're set. If the format, methods, data items, on the cards are changing over time, then you need to identify what is specific to being a Card, and make that a superclass. Then you can make later versions of the Cards be new subclasses of Card: the stuff that stays the same is in the superclass, the varying parfts are the subclass's business.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文