不要重新发明轮子
This is the story about how I created my own schema validation library: Schemy. I was writing a tiny API for a small app with a few friends. The packaged application weighted around 9 KB. I know, right? I told you. It was small.
这是关于我如何创建自己的模式验证库Schemy的故事。 我正在和几个朋友一起为小型应用程序编写一个小型API。 打包的应用程序权重约9 KB。 我知道,对吧? 我告诉你了。 它很小。
Eventually, we needed to validate user input in the backend, so naturally, we came out with a few common validation library names we could use, such as Joi or AJV. The problem was their package size. The first one weighs around 500 KB, and the second one almost 1 MB!
最终,我们需要在后端验证用户输入,因此自然而然地,我们产生了一些可以使用的常见验证库名称,例如Joi或AJV 。 问题是它们的包装尺寸。 第一个重约500 KB,第二个重约1 MB !
This made us think, do we really need a library for just a few validations that weigh like 110x times our app?
这使我们思考,我们是否真的需要一个库来进行几次验证,这些验证的权重约为应用程序的110倍?
We want to validate an object. Something composed of keys and values. To validate what the value should be, we can assign to that key some properties to check for later. We wanted something simple, like mongoose’s schemas, but you know, without all the DB stuff. Something like this:
我们要验证一个对象。 由键和值组成的东西。 为了验证值是什么,我们可以为该键分配一些属性以供以后检查。 我们想要简单的东西,例如猫鼬的模式,但是要知道,没有所有的数据库内容。 像这样:
Our desired schema definition 我们期望的模式定义Now that we know what we want, we can start coding it. We basically want a function that validates an input against this schema. In my case, I decided to write a class to keep the references more easily:
现在我们知道了我们想要什么,我们可以开始对其进行编码。 我们基本上想要一个函数来根据该模式验证输入。 就我而言,我决定编写一个类来更轻松地保留引用:
Schema constructor 模式构造器Let’s think about that schema programmatically: We need to iterate over the schema keys and check if the input has all (and only) the declared keys and that their values match the configured types. Since we saved the schema in the instance, this can be done pretty easily by comparing each key of the input against that same key in the schema:
让我们以编程方式考虑一下该模式:我们需要遍历模式键,并检查输入是否具有所有(且仅)声明的键以及它们的值是否与配置的类型匹配。 由于我们将模式保存在实例中,因此可以通过将输入的每个键与模式中的相同键进行比较来轻松完成此操作:
Our validate method 我们的验证方法This is where the magic happens. We iterate over the schema using for…of and Object.entries() which allows us to get the keys and properties we configured when we first called our constructor. Then for each key, we check the type and finally if the one in the input matches that type. Of course, we save every error in an array, so we can return every validation error if there is more than one.
这就是魔术发生的地方。 我们使用for…of和Object.entries()遍历模式,这使我们可以获得在初次调用构造函数时配置的键和属性。 然后针对每个键,检查类型,最后检查输入中的那个是否与该类型匹配。 当然,我们将每个错误保存在一个数组中,因此,如果存在多个错误,则可以返回每个验证错误。
Our little library is alive! 我们的小图书馆还活着!The basic functionality is done. We only support strings for now, but adding other native types is easy: just add more if blocks.
基本功能已完成。 我们现在仅支持字符串,但是添加其他本机类型很容易:只需添加更多if块即可。
Well, having a lot of if blocks doesn’t look as sexy as we’d want. So there’s a trick we can use. Native types words like String, Number, or Boolean are actually functions. They return a value of that type. So you can take advantage of it combining typeof and these functions:
好吧,拥有很多if块看起来并不像我们想要的那样性感。 因此,我们可以使用一个技巧。 诸如String , Number或Boolean之类的本机类型单词实际上是函数。 它们返回该类型的值。 因此,您可以结合使用typeof和以下功能来利用它:
Implementation of typeof 实现typeofIf you remember in our basic schema, we set some properties for each key including the type, which can be either String, Number, Object, or Boolean. Since we passed actually a function, we can just call it and get the type of their return value. This allows us to improve our code and making it a lot smaller and smarter.
如果您还记得我们的基本架构,我们会为每个键设置一些属性,包括类型,可以是String , Number , Object或Boolean 。 由于我们实际上传递了一个函数,因此我们可以调用它并获取其返回值的类型。 这使我们可以改进代码,并使代码更小巧,更智能。
You can check by yourself in any javascript console to see how it works:
您可以在任何JavaScript控制台中自行检查其工作方式:
Example return of typeof with native constructor 使用本机构造函数返回typeof的示例Instead of automatically putting a library or framework in your project, try to check if you really need it first. There’s no need to grow your project with libraries that overkills your needs.
与其自动在您的项目中放置一个库或框架,不如先检查您是否真的需要它。 无需使用过分需求的库来扩展您的项目。
Try to find out what the dependency you’re adding does and what it does not. If it doesn’t do what you need, you’ll discard it for sure. But if it does hundreds of other things, maybe you should discard it as well and search for a smaller alternative, or why not, just do it yourself!
尝试找出要添加的依赖项有哪些功能,没有做什么。 如果它不能满足您的需求,则将其丢弃。 但是,如果它做其他数百件事,也许您也应该将其丢弃,并寻找更小的选择,或者为什么不做,那就自己动手!
If you go for the DIY path, is a good idea to make it as generic as possible, and even open source! That way, you will receive help from the open-source community.
如果您选择DIY的方法,最好使其尽可能通用,甚至是开源! 这样,您将获得开源社区的帮助。
If you ever need a small validation library, you already know which one I recommend 😉
如果您需要一个小型验证库,那么您已经知道我推荐哪个库了。
翻译自: https://medium.com/weekly-webtips/you-dont-always-need-to-not-reinvent-the-wheel-7a9ceaa82fb9
不要重新发明轮子
