数据结构设计是静态类型语言

发布于 2024-10-03 14:51:39 字数 1127 浏览 3 评论 0原文

我使用 C# 编写一个(假设的)应用程序 - 在线商店。

我有一个产品数据库,每个产品都有以下相关信息:

  • 产品编号(必填)
  • 名称(必填)
  • 价格(必填)
  • 评级(可选)
  • 已售数量(可选) - 这是该产品的总销量

我有 4显示过滤后的产品列表的页面。页面显示每个产品的不同信息:

  • 第一页:PN、名称、价格
  • 第二页:PN、名称、价格、评级
  • 第三页:PN、名称、价格、销售数量
  • 第四页:PN、名称、价格、评级、销售数量

我的问题是,如何设计数据结构来容纳我的所有页面且几乎没有重复?

强力方法是为每个页面创建一个类型:

IList<Product>
IList<ProductWithRating>
IList<ProductWithSoldQuantity>
IList<ProductWithRatingAndSoldQuantity>

后面 3 可以从 Product 派生,但由于缺乏多重继承,ProductWithRatingAndSoldQuantity 无法同时从 Rating 和 SoldQuantity 产品派生。

在动态语言中,我只需添加我需要的任何字段即可。

因此,我可以通过在单独的字典中存储额外信息(评级、销售数量)来模拟动态语言方法,例如:

{
    IList<Product> Products;
    IDictionary<Product, Rating> ProductRatings;
    IDictionary<Product, SoldQuantity> ProductSoldQuantities;
}
// is equivalent to
IList<ProductWithRatingAndSoldQuantities>

构建包含所有内容的产品结构,然后传递部分初始化的对象我正在寻找的解决方案。

有什么建议吗?

I use C# to write a (hypothetical) application - online store.

I have a database of products, each product has following information associated with it:

  • Product Number (required)
  • Name (required)
  • Price (required)
  • Rating (optional)
  • Sold Quantity (optional) -- this is total sale of this product

I have 4 pages that show filtered list of products. Pages show different information for each product:

  • 1st page : PN, Name, Price
  • 2nd page : PN, Name, Price, Rating
  • 3d page : PN, Name, Price, Sold Quantity
  • 4th page : PN, Name, Price, Rating, Sold Quantity

My question is, how do I design data structures to accommodate all my pages with little duplication?

Brute force approach is to create a type for each page:

IList<Product>
IList<ProductWithRating>
IList<ProductWithSoldQuantity>
IList<ProductWithRatingAndSoldQuantity>

later 3 can derive from Product but due to lack of multiple inheritance ProductWithRatingAndSoldQuantity can't derive from both Rating and SoldQuantity products.

In a dynamic language I would just add whatever fields I need and be happy.

So I could simulate a dynamic-language-approach by storing extra information (rating, sold quantities) in separate dictonaries, e.g.:

{
    IList<Product> Products;
    IDictionary<Product, Rating> ProductRatings;
    IDictionary<Product, SoldQuantity> ProductSoldQuantities;
}
// is equivalent to
IList<ProductWithRatingAndSoldQuantities>

Building a Product structure that includes everything and then pass around a partially initialized object is not a solution I am looking for.

Any suggestions?

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

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

发布评论

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

评论(4

拥有 2024-10-10 14:51:39

抱歉,字符数不足,无法在评论中回复。

您应该有一个域对象 Product。它将具有不可为 null 的名称、产品编号和价格,因为您无法拥有没有这些内容的产品。

评级应该可以为空,因为产品可能没有评级。无论产品是否有评级,它始终是产品。我将保留 QuantitySold,因为我实际上不会将其存储为产品的属性,我将拥有 Orders 和 OrderLine 集合,并根据这些集合计算 QuantitySold(标准化)。但是,如果没有其他集合,您可以将其存储为产品上的字段。如果我要这样做,它将是一个不可为空的整数属性,默认值为零。

您只需要一个集合来过滤,这将是 IEnumerable 或 IQueryable 或两者的某种实现,您很可能会选择像 Entity Framework 这样的东西,并且实际上有一个 ObjectSet,但我会尝试让我的设计不知道什么存储方法我正在使用并针对这些接口进行工作。

然后,您可以查询单个集合,以确定域模型中产品的哪些属性为空。语法可能并不完美,但 Intellisense 不会识别任何内容,99% 的时间我都是 VB 人员。

var productsWithNoSales = Context.Products.Where(p=> p.QuantitySold == 0);
var productsWithNoRating = Context.Products.Where(p=> p.Rating == nothing);
var productsWithNoSalesOrRating = Context.Products.Where(p=> p.QuantitySold == 0).Where(p=> p.Rating == nothing);

这几乎是您所追求的最干净的领域模型。

如果您有具有额外属性或不同行为的 Product 的专门衍生品,则可以继承。例如,我自己的系统有一个 Product 基类,以及一个 EbayProduct 和 AmazonProduct 实体,它们都继承自 Product,并且仅包含与使用这些网站相关的额外逻辑和属性。我的 Product 类有大约 20 个属性 - 大部分可以为 null,因为当我们列出产品时,我们不一定拥有所有可用信息。在这 20 个中,我在任何一页上显示的最多大约是 15 个。我可能会做与您尝试做的类似的事情,因为我使用所描述的确切方法(即过滤)过滤掉尚未准备好列出的产品我的产品集合中缺少的字段。

Sorry not enough chars to reply in comment.

You should have a single domain object, Product. It would have non-nullable Name and ProductNumber and Price, because you cannot have products that don't have those things.

Rating should be a nullable, because it is possible to have a Product that does not have a rating. Whether or not a Product has a Rating, it is still always a Product. I'll leave QuantitySold, because I wouldn't actually store that as a property of product, I would have Orders and OrderLine collections, and calculate QuantitySold from those (normalisation). However in the absence of those other collections, you could store it as a field on Product. If I was going to do that, it would be a non-nullable integer property, the default being zero.

You only need a single collection to filter, which would be some implementation of IEnumerable or IQueryable or both, most likely you would opt for something like Entity Framework and actually have an ObjectSet but I'd try to keep my design agnostic of what storage method I'm using and work against those interfaces.

You can then query your single collection to identify which attributes are null on the Products in your domain model. Syntax might not be perfect, but nothing Intellisense won't pick up, I'm a VB guy 99% of the time.

var productsWithNoSales = Context.Products.Where(p=> p.QuantitySold == 0);
var productsWithNoRating = Context.Products.Where(p=> p.Rating == nothing);
var productsWithNoSalesOrRating = Context.Products.Where(p=> p.QuantitySold == 0).Where(p=> p.Rating == nothing);

That is pretty much the cleanest possible domain model for what you are after.

Inheritance would be if you had specialised derivatives of Product that have either extra properties or different behaviour. For example, my own system has a base Product class, and a EbayProduct and AmazonProduct entity which both inherit from Product and contain only the extra logic and properties associated with working with those sites. My Product class has about 20 properties - mostly nullable, as when we list products we don't necessarily have all the information available. Of these 20, the most I display on any one page is about 15. I probably do something similar to what you are trying to do in that I filter out Products that aren't ready to list yet using the exact method described, i.e. filtering my Products collection for missing fields.

未央 2024-10-10 14:51:39

为什么 RatingSoldQuantity 不能为空?或者始终存在但不总是显示?

Why can't Rating and SoldQuantity just be nullable? Or be always present but just not always displayed?

薆情海 2024-10-10 14:51:39

您可以将评级和销售数量存储为属性,然后存储指示它们是否存在的布尔值吗?我认为当你应该进行组合时你正在使用继承。

Can you store the rating and quantity sold as attributes, and then store booleans that indicate whether they're present? I think you're using inheritance when you should probably be doing composition.

小情绪 2024-10-10 14:51:39

您也许可以指定您正在使用什么?首先,您的“页面”是什么?你的数据存储方式是什么?

听起来您似乎在混淆显示数据和存储数据?没有义务仅仅因为数据存在就显示数据。

您的对象域几乎肯定应该只有产品。数据存储将被设置为属性可为空,并检查空值以取回数据。

如果你使用像 Linq 这样的东西,你可以简单地做一些像

var productsWithoutRating = Context.Products.Where(p => p.Rating == nothing);

字典的想法、继承和组合看起来有点奇怪的事情。存储一个单独的布尔值来告诉您某个属性是否存在是很混乱的,并且维护起来将是一场噩梦 - 只需即时检查它是否存在即可。

You could perhaps do with specifying what you're using? What are your "pages" in for a start? What is your data storage method?

It sounds like you are muddling displaying your data with storing your data? There is no obligation to show data just because it exists.

Your object domain should almost certainly just have products. The data storage would be set up such that the properties are nullable, and check for nulls to get the data back.

If you're using something like Linq, you can simply do something like

var productsWithoutRating = Context.Products.Where(p => p.Rating == nothing);

The dictionary idea, inheritance, and composition all seem a bit wierd. Storing a separate boolean telling you whether a property exists is messy, and would be a nightmare to maintain - just check whether it exists on the fly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文