如何避免在ASP.NET Core Web应用程序中创建许多相似的类?

huangapple go评论62阅读模式
英文:

How to avoid creating many similar classes in ASP.NET Core web application?

问题

我迄今为止一直在开发多个基于ASP.NET Core的Web应用程序,总是会遇到一个问题。例如:我想创建一个控制器,用于提供关于资源(例如“产品”)的简单CRUD操作。在实现创建资源的端点时,我需要一个包含资源属性的类,我希望从调用者那里收到这些属性。在这种情况下,我不需要获得ID,因为在创建新实体时,ID由数据库确定。

在实现更新端点时,从技术上讲,我需要相同的类,但这次需要一个ID,以便应用程序知道必须在数据库中更新哪个实体。在实现获取单个或所有现有资源的端点时,从技术上讲,我也需要相同的类,其中包括ID(因为我希望将ID返回给调用者,以便它可以唯一标识每个实体)。

我的选择如下:

  1. 为我需要不同“口味”的每个端点创建单独的类。这种方式会导致我拥有多个看起来非常相似的类,随着项目变得越来越复杂,管理起来可能会变得困难。
  2. 使用一个单一的类,并使不是每个端点都需要的属性都可为空。这样,整体上减少了冗余,但在不需要额外属性的端点上会有一些开销。当使用Swagger时,我也会遇到问题,因为Swagger会在端点文档中列出那些实际上在该端点中根本不需要的属性。
  3. 从类中删除不总是需要的所有属性,并在需要时单独提供它们。这在许多情况下都有效,但在GET端点中特别难看,例如,我想将ID作为返回对象的属性。
  4. 使用继承,并创建某种“基类”,其中只包含所需的属性。对于需要ID或其他属性的端点,创建和使用子类,如“ProductWithId”。在简单情况下,这对我来说似乎是一个不错的解决方案,但一旦变得更加复杂,这些子类的名称可能会变得非常难以阅读(例如,“ProductWithIDAndWithoutFieldXYZ”)。

我知道这可能有点主观,但是否有任何通用方法可以解决这个问题,在许多情况下甚至在所有情况下都适用?是否有我迄今为止没有考虑到的其他选项可以解决这个问题?

英文:

I have been working on multiple ASP.NET Core based web applications so far and there is always this one issue I come across. Example:
I want to create a controller that provides simple CRUD operations for a ressource (e.g. a "Product"). When implementing an endpoint to create the ressource, I need a class containing the properties of that ressource which I expect to receive from the caller. In this case, I do not need to get an ID because the ID is determined by the database when the new entity is created.

When implementing an update endpoint, I technically need the same class but this time with an ID, so the application knows which entity must be updated in the database. When implementing an endpoint to get a single or a list of all existing ressources, I also need technically the same class with the ID included (since I want to return the ID to the caller so it can uniquely identify each entity).

My options are as follows:

  1. Create a separate class for each endpoint where I need a different "flavor" of it. This way, I end up with multiple classes that look extremely similar and can become difficult to manage sooner or later the more complex the project becomes.
  2. Use a single class and make all properties nullable which are not always needed in every endpoint. This way, I have less redundancy overall but I have some overhead in the endpoints where do not need the additional properties. I also have problems when using swagger because it would list those properties in the endpoint documentation while they are in fact not needed at all in that endpoint.
  3. Remove all properties from the class which are not always needed and provide them separately when needed. This works in many cases, but is especially ugly in GET-endpoints, e.g. where I would like to return the ID as property of the returned objects.
  4. Use inheritance and create some sort of "base" class which contains only the required properties. For endpoints that need an ID or other property, sub-classes like "ProductWithId" are created and used. In simple scenarios, this seems like a good solution to me but as soon as it gets more complex, the names of those sub-classes can become pretty unreadable (e.g. "ProductWithIDAndWithoutFieldXYZ").

I know that this might be a bit opinionated, but is there any common approach to this problem that works in many or even in all cases? Are there any other options which I did not consider so far that would solve this problem?

答案1

得分: 1

是的,这是有主观观点的。我会在这里表达我的观点。

你提到将属性保持为null并使用相同的类可能会在你的系统中引起开销。如果你只是担心ID属性,那么**不用再担心了。对于你的端点来说,这不会增加开销**(考虑到这一代的服务器)。我见过很多企业应用程序同时将相同的类用于命令和查询操作。

如果你有超过几个这样的属性,我仍然认为在不使用时将这些属性保持为null是可以接受的。就我个人而言,我见过很多我们正在构建和使用的微服务也是这样做的。如果这些属性的数量很多,而且你正在使用基于SQL的数据库,你可能需要使用规范化技术来正确建模数据。

如果你仍然寻求除你列出的解决方案之外的其他选项,使用GraphQL可以帮助你保持相同的类并精确返回客户端所需的内容。我知道为了避免ID属性的开销而实现GraphQL可能有些过度,这是在软件架构方面需要做出的重要决策。只有在你理解它除了上面提到的内容之外还带来了什么优势,并且符合你的需求时,才能考虑使用GraphQL。GraphQL可以解决你的带宽问题,但它也有自己的缺点

如果有任何涉及问题的代码层面的技巧,我将很高兴看到。

英文:

Yes, it's opinionated. I'll put my opinion here.

You mentioned that keeping properties as null and using the same classes may cause overhead in your system. If it is just the ID property that you are worried about then Worry no more. It is Not Overhead to your endponint (Considering servers of this generation). I've seen many enterprise applications use the same classes for both command and query operations.

If you have more than a couple of such properties, still I think it is fine to use same class by keeping those properties as null when not in use. Personally, I've seen many microservices that we are building and consuming that does the same. If the number of such properties are huge and you're using SQL based database, you may need to work on modelling the data properly using Normalization Techniques.

If you still seek other options other than solutions you listed, using GraphQL can help you to keep the same class and return exactly what's required to the client. I know it's an over-over-kill implementing graphql just so that you can avoid overhead with the ID property. It's a big decision to take in the software architecture matters. You can only go for it once you understand what advantage it brings over REST other than what's mentioned above and suits to your requirements. GraphQL may solve your bandwithdth concerns but it has its own drawbacks as well.

Happy to see if there is any code level tricks that address the question.

huangapple
  • 本文由 发表于 2023年6月1日 18:44:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381081.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定