简体   繁体   English

如何知道 NodeJS 中的 function 定义是否已更改?

[英]How to know if a function definition has been changed in NodeJS?

I'm trying to write a caching system for some time-intensive functions (Network requests/computation heavy) and I need to generate a fingerprint from the functions in order to invalidate the cached results once a developer changes the functions.我正在尝试为一些时间密集型功能(网络请求/计算繁重)编写缓存系统,并且我需要从功能中生成指纹,以便在开发人员更改功能后使缓存结果无效。

I have tried the following approach to generate the fingerprint:我尝试了以下方法来生成指纹:

const crypto = require('crypto')
const generateFingerprintOfFunc = (inputFunc) => {
  const cypher = crypto.createHash('sha256');

  cypher.update(inputFunc.toString());

  return cypher.digest('hex');
}

However, the problem with this approach is that the fingerprint won't be changed once the developer changes any of the functions that are called inside the function that is being fingerprinted because that function's definition hasn't really changed.但是,这种方法的问题在于,一旦开发人员更改了正在被指纹识别的 function 中调用的任何函数,指纹就不会被更改,因为该函数的定义并没有真正改变。

const foo = () => {
  return bar() + 1;
}

const bar = () => {
  return 1;
}


const fingerprintOfFoo = generateFingerprintOfFunc(foo); // 489290d22f653965a59e2e5fbb7b626535babd660f7f49501fc88c3e7fbc0176

Now I will change the bar function:现在我将更改bar function:

const foo = () => {
    return bar() + 1;
  }

const bar = () => {
    return 10;
}

const fingerprintOfFoo = generateFingerprintOfFunc(foo); // 489290d22f653965a59e2e5fbb7b626535babd660f7f49501fc88c3e7fbc0176

As you can see the fingerprint has not changed while the return value of the function has.如您所见,指纹没有改变,而 function 的返回值有。

Why do I need to do this?为什么我需要这样做?

I'm trying to generate dynamic and automatic mocks for my expensive functions during development and testing.我正在尝试在开发和测试期间为我昂贵的功能生成动态和自动模拟。 See this SO Question看到这个问题

I wanna know if there is a way that v8 would give me the path of the files making up a certain function and all of its internals.我想知道 v8 是否有办法为我提供构成某个 function 及其所有内部结构的文件的路径。

No.不。

It can't.它不能。 JavaScript is too dynamic. JavaScript 太动态了。

Consider this example:考虑这个例子:

let helper;

const foo = () => helper() + 1;

const bar = () => 1;
const baz = () => 2;

helper = bar;

So far, this does the same as your example.到目前为止,这与您的示例相同。 Now suppose someone either changed the last line to read, or added a new line that reads helper = baz .现在假设有人将最后一行更改为 read,或者添加了一个新行,内容为helper = baz In that case, no function's definition has changed, but foo 's behavior has, In fact: one can take that same idea to construct an even simpler case:在这种情况下,没有函数的定义发生变化,但foo的行为发生了变化,事实上:人们可以采用相同的想法来构造一个更简单的情况:

let global = 42;
const foo = () => global;

If someone changes global (whether statically in the source, or dynamically), foo 's return value will change, but no function definition will.如果有人更改global (无论是在源中静态还是动态), foo的返回值将会改变,但没有 function 定义会改变。 In case of dynamic assignment, not even anything in the source will change.在动态分配的情况下,甚至源中的任何内容都不会改变。 And of course such an assignment could depend on arbitrary conditions/circumstances, such as user interaction, time of day, Math.random() , whatever.当然,这样的分配可能取决于任意条件/情况,例如用户交互、一天中的时间、 Math.random()等等。

In general, the only way (for anyone, including the engine) to figure out what a function will return is to execute it.一般来说,唯一的方法(对于任何人,包括引擎)来说,弄清楚 function 将返回什么是执行它。
Memoization works if developers carefully choose functions that lend themselves to memoization.如果开发人员仔细选择适合记忆化的功能,记忆化就会起作用。
An automated system that takes any arbitrary function (without imposing any limitations on what the function does) and memoizes it, or determines whether it will the same value as last time, without actually executing it , is impossible to create in JavaScript.采用任意 function(不对 function 的功能施加任何限制)并记住它,或者确定它是否与上次相同的值而不实际执行它的自动化系统,是不可能在 Z6836155AF75A7F14D 中创建的。

What do you mean when you say "changes the function"?当您说“更改功能”时,您是什么意思? As in, you have jest in watch mode and want to only pick up changes when they make fundamental changes?例如,您在观看模式下开玩笑,并且只想在发生根本变化时才接受更改? I think the real question is why this is necessary, to begin with.我认为真正的问题是为什么这是必要的,首先。

  1. How are you generating dynamic mocks?你是如何生成动态模拟的? Does this imply that you repeatedly creating these mocks in real-time with network requests?这是否意味着您重复使用网络请求实时创建这些模拟? Then they aren't really mocks.然后他们不是真正的嘲笑。 You are just making real requests and then deciding to temporarily store it somewhere.您只是提出真正的请求,然后决定将其临时存储在某个地方。 You could just skip that data-saving step and your resulting testing process would be identical.您可以跳过该数据保存步骤,您的测试过程将是相同的。 That's a glorified integration test这是一个美化的集成测试

  2. I guess others can disagree, but your unit testing philosophy seems a little flawed.我想其他人可能不同意,但你的单元测试理念似乎有点缺陷。 Dynamic mocks imply that you have no control over what situation ends up getting tested.动态模拟意味着您无法控制最终要测试的情况。 If you are not in full control of your mocks, couldn't you end up testing the exact same case (or edge case) repeatedly?如果你不能完全控制你的模拟,你不能最终重复测试完全相同的情况(或边缘情况)吗? That's a waste of resources and can lead to flawed tests.这是对资源的浪费,并且可能导致有缺陷的测试。 Covering all of your intended cases would happen by coincidence, as opposed to explicit intent.涵盖您所有预期的情况将是巧合,而不是明确的意图。 Your unit tests should be deterministic.您的单元测试应该是确定性的。 Not stochastic.不是随机的。

It seems like you need to solve your testing methodology, as opposed to accepting that your tests are slow and developing strategies on how to work around it.看起来你需要解决你的测试方法,而不是接受你的测试很慢并制定如何解决它的策略。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM