本文共 12560 字,大约阅读时间需要 41 分钟。
c# api返回后执行代码
Once upon a time, a young girl observed her mother, who was unwrapping a freshly bought piece of beef for roasting. The mother cut the extremities of the meat out.
曾几何时,一个年轻的女孩观察她的母亲,母亲正在包装新鲜购买的一块牛肉进行烧烤。 母亲把四肢切开。
“Mommy, why do you do that?” the young girl asked.
“妈妈,你为什么要这么做?” 小女孩问。
“It gives a better taste,” the mother replied, as she put the meal in the oven.
母亲把饭放在烤箱里时回答说:“味道更好。”
“How is it so?”
“怎么样?”
“I don’t remember, go ask your grand-mother, she taught me all these kinds of tips and tricks.”
“我不记得了,去问问你的祖母,她教了我所有这些技巧和窍门。”
The child was curious, and ran to the nearby house of her grandmother.
这个孩子很好奇,跑到她祖母附近的房子里。
“Grand-mommy, do you know why cutting the sides of roast beef makes it better?”
“祖母,你知道为什么减少烤牛肉的面使它更好吗?”
“It has to be with the flow of the juice,” the grandmother replied.
奶奶回答说:“必须随果汁的流动而变化。”
“Can’t we just punch holes with a fork instead?”
“我们不能只用叉子打Kong吗?”
“My mother has always prepared them so, and for sure she was a great cook.”
“我的母亲总是为他们做准备,可以肯定的是,她是一位出色的厨师。”
The child was not only curious but also perseverant, and ran to the home where her elder lived. She narrated what her mother and grandmother had told her, and repeated her question.
这个孩子不仅好奇,而且毅力十足,跑到长者居住的家中。 她叙述了母亲和祖母告诉她的内容,并重复了她的问题。
The elder burst in laughter.
老人大笑起来。
“I did always cut the ends of my roast beef, but only because my oven was waaaayyy too small for a whole one.”
“我确实切过烤牛肉的末端,但这只是因为我的烤箱太小了,整个烤箱都太小了。”
This little tale, which exists in, makes an important point about human life. Old habits die hard, even when they haven’t made sense for decades (if ever). And computer science, though evolving at a fast pace, is quite prone to this type of harmful tradition.
这个故事 ,它是人类生活的重要方面。 即使数十年来没有任何意义(即使有),古老的习惯也很难消亡。 尽管计算机科学发展Swift,但很容易受到这种有害传统的影响。
Take error handling, for example. We are deeply used to HTTP status codes, to small unix “errnos”, to lengthy windows error codes… and our APIs are filled with custom numbers, indicating problems with inputs, or with SQL operational errors, or with access permissions…
以错误处理为例。 我们非常熟悉HTTP状态代码,小型unix“ errnos”,冗长的Windows错误代码……并且我们的API充满了自定义数字,表示输入问题,SQL操作错误或访问权限……
The first, low level, programming languages — including C and Fortran — had very rudimentary data types. That’s why they handled errors as mere integers, that they could compare, switch-case, lookup as array indices, and transmit painlessly. And that’s why they ended up using 0 (boolean False) to indicate all successes, and non-zero integers (boolean True) to indicate errors — something not deeply intuitive to ordinary mortals.
第一种底层编程语言(包括C和Fortran)具有非常基本的数据类型。 这就是为什么他们将错误仅作为整数来处理,以便可以进行比较,切换大小写,查找为数组索引并进行轻松传输的原因。 这就是为什么它们最终使用0(布尔False)来表示所有成功,而使用非零整数(布尔True)来表示错误的原因-对于普通凡人来说,这是不那么直观的。
But what do we expect from errors in our everyday modern, high level languages ? That they be:
但是,我们对日常的现代高级语言中的错误有何期待? 他们是:
explicit, so we know what they mean without asking the whole web everytime
明确的 ,因此我们无需每次询问整个网络就知道它们的含义。
deeply hierarchical, so that we can refine error cases without breaking current software, and fallback to generic treatments when too specific errors are encountered
深入的层次结构 ,因此我们可以在不破坏当前软件的情况下优化错误情况,并在遇到过于具体的错误时退回通用处理
contextualized, so that additional data may accompany the error, and detail what exactly went wrong and why
上下文相关 ,以便其他数据可能伴随错误,并详细说明错误的原因和原因
This is the way exceptions are implemented in many modern languages. There are hierarchies of classes with (hopefully) clear meanings. Each has different instance attributes in different branches in these hierarchies, for example filenames, field names, and origin OS errors. And those instances drag with them tons of information, including tracebacks and their per-frame local variables.
这是在许多现代语言中实现异常的方式。 存在具有(希望)具有清晰含义的类层次结构。 每个人在这些层次结构的不同分支中具有不同的实例属性,例如文件名,字段名称和原始OS错误。 这些实例会拖累大量信息,包括回溯及其每帧局部变量。
But when it’s time for the error to cross the boundaries of this specific process, of this specific language? Error codes are amongst the worst supports for this.
但是何时应该让错误越过这种特定过程,这种特定语言的界限呢? 错误代码是对此的最差支持。
What does “Error 0x29273363833” mean? You have no idea. You can’t subdivide this error into more precise cases. If you want more context information, you’ll have to fetch it somewhere else.
“错误0x29273363833”是什么意思? 你不知道。 您无法将此错误细分为更精确的情况。 如果需要更多上下文信息,则必须在其他地方获取它。
And you have little clue what the closest parent error code could be. True, some systems advocate rudimentary fallback behaviours — for example if you encounter an unknown HTTP 478 error, you’re supposed to handle it as an HTTP 400. But it is still a bit too coarse-grained for lots of cases, and once you have used all the numbers of an error class, you’re out-of-luck.
而且您几乎不知道最接近的父错误代码是什么。 的确,某些系统提倡基本的回退行为-例如,如果遇到未知的HTTP 478错误,则应将其作为HTTP 400进行处理。但是对于许多情况而言,它仍然有点过于粗略,一旦您已经使用了错误类别的所有数字,那么您真不走运。
Just map exception types to their closest JSON-compatible representations. Which happen to be… sequences of identifiers.
只需将异常类型映射到它们最接近的JSON兼容表示即可。 碰巧是……标识符序列。
Ladies and gentlemen, I present to you, a bunch of status slugs:
女士们,先生们,我向您介绍一些身份sl :
As you can see, whether we use lists or strings doesn’t matter much ; even the term “slug” must not be taken too rigidly, having underscores or capital letters in them is harmless.
如您所见,我们使用列表还是字符串都没关系; 即使“子弹”一词也不能太刻板,因为其中带有下划线或大写字母是无害的。
The important take-away messages are that these slugs are:
重要的外卖 消息是这些弹头是:
Dots should be reserved to qualify, and thus differentiate, same-name exceptions provided by different packages. An example here is “cuteforms.Invalid” vs “validator.Invalid”.
应该保留点以限定并区分不同程序包提供的同名异常。 这里的一个示例是“ cuteforms.Invalid”与“ validator.Invalid”。
The cherry on the cake is that status slugs may be used to distinguish success cases too, like the “HTTP 2XX” family advocated it for the web.
可喜的是,状态标记也可以用来区分成功案例,例如“ HTTP 2XX”家族在网络上倡导它。
So here is the first point I wanted to make: use status slugs to announce operation results.
因此,这是我要说明的第一点: 使用状态块来宣布操作结果 。
Error handling is at the very core of software robustness and a pleasant user experience, so it deserves more than assembly-level data types. Let’s just stop using poor error dispatching based on integers, on single slugs, or — worst of all — on booleans.
错误处理是软件健壮性和令人愉悦的用户体验的核心,因此,它比程序集级数据类型更有价值 。 让我们停止使用基于整数,单个子块或布尔值(最糟糕的是)的差错错误分配。
The second point I wanted to make about error handling is: be ambitious.
关于错误处理,我想说的第二点是: 有野心 。
Lots of protocols define castrated error structures — “if it’s enough for me, it’s enough for others”. And developers end up adding their own error handling system. Sometimes SUCCESS responses of initial protocol are stuffed with their own error structures, when ERROR responses leave no room for customization (looking at you, XML-RPC).
许多协议定义了cast割的错误结构-“如果对我足够,对其他人也足够”。 开发人员最终添加了自己的错误处理系统。 有时,初始协议的SUCCESS响应会填充自己的错误结构,而ERROR响应则没有自定义的余地(看着您,XML-RPC)。
So if you end up, one day, having to specify your own error format — which is always a pity, but sometimes unavoidable — think big.
因此,如果最终有一天,您必须指定自己的错误格式(这总是很遗憾,但有时是不可避免的),请考虑大事 。
What do we expect from a response format?
我们对响应格式有什么期望?
Here is an example of an (almost) one-size-fits-all StatusPack structure:
这是一个(几乎)千篇一律的StatusPack结构的示例:
{
{
status_slugs : list of slugs for success/error dispatching, mandatory field
status_slugs:成功/错误调度的段列表,必填字段
data: data tree with contextual information (results, invalid input fields...)
数据:具有上下文信息的数据树(结果,无效的输入字段...)
traceback : for dev mode only, might include frames with local variables
traceback:仅适用于开发模式,可能包含带有局部变量的框架
nested_statuses: optional list of StatusPack structures
nested_statuses:StatusPack结构的可选列表
message_translated: displayable string
message_translated:可显示的字符串
message_untranslated: string or [string template, parameters] pair
message_untranslated:字符串或[字符串模板,参数]对
This structure should cover the use cases mentioned above, thanks to the malleability provided by the “nested_statuses” field.
由于“ nested_statuses”字段提供的可扩展性,该结构应涵盖上述用例。
If you deal with microservices, chaining these status packs, and displaying them properly user-side — especially the traceback — might save you days of logs investigations.
如果您处理微服务 ,则将这些状态包链接起来,并在用户端( 尤其是回溯)正确显示它们,可能会节省几天的日志调查时间。
And if you want to obfuscate your errors, then fine. But there is no need to specify error codes yourself. Just create hashes of your “status_slugs” and automatically generate the whole listing of available errors by introspecting your codebase.
如果您想掩盖错误,那很好。 但是无需自己指定错误代码。 只需创建“ status_slugs”的哈希值 ,然后通过内省代码库自动生成可用错误的完整清单。
The last point I am emphasizing is: be kind to API consumers.
我要强调的最后一点是: 对API使用者要友善。
Ensure that your consumers know when an error occurs. Ensure that your consumers also know what to do, especially programmatically, in this case.
确保您的消费者知道何时发生错误。 在这种情况下,请确保您的消费者也知道该怎么做,尤其是通过编程。
Silent errors are Hell’s antechamber. Deleting a non-existing account must return an error. But provide a gentle “strict=False” parameter to such operations, so that users may issue unimportant calls without embarrassing themselves with errors.
无声的错误是地狱的前厅。 删除不存在的帐户必须返回错误。 但是请为此类操作提供一个温和的“ strict = False”参数,以便用户可以发出不重要的呼叫而不会因错误而尴尬。
These two ideas — status slugs and StatusPack structures — are certainly not the epitome of error handling, but they represent a sure step forward in terms of precision and evolvability.
这两个想法- 状态段和StatusPack结构 - 绝对不是错误处理的缩影,但它们在准确性和可扩展性方面代表了肯定的进步。
I’d like to hear the other error fields, or other handling strategies, that API developers around here might have come up with. Please share your innovations and hard-earned lessons!
我想听听附近的API开发人员可能想出的其他错误字段或其他处理策略。 请分享您的创新和来之不易的教训!
Edited on 2018/09/07: Fix typos, and precise the idea behind the “slug” term.
于2018年9月7日编辑:修正了拼写错误,并完善了“弹头”一词背后的想法。
Edited on 2019/06/22: Precise the StatusPack "data" field
于2019/06/22编辑:精确的StatusPack“数据”字段
翻译自:
c# api返回后执行代码
转载地址:http://uckzd.baihongyu.com/