简体   繁体   English

用自定义库包装jQuery,dojo?

[英]Wrap jQuery, dojo with custom library?

Coming from Java, I'm wondering if a Java best practice applies to JavaScript. 来自Java,我想知道Java最佳实践是否适用于JavaScript。

In Java, there's a separation of interface and implementation, and mixing them up is considered a bad practice. 在Java中,接口和实现是分离的,将它们混合起来被认为是一种不好的做法。 By the same token, it is recommended to hide implementation details of your library from end developers. 出于同样的原因,建议从最终开发人员隐藏库的实现细节。

For example, log4J is one of the most popular logging libraries out there but it is recommended to write code to the slf4j library or the Commons Logging library that "wraps" log4j. 例如,log4J是最受欢迎的日志库之一,但建议将代码写入slf4j库或“包装”log4j的Commons Logging库。 This way, if you choose to switch to another logging framework such as logback, you can do so without changing your code. 这样,如果您选择切换到另一个日志记录框架(如logback),则可以在不更改代码的情况下执行此操作。 Another reason is that you, as a user of a logging library, how logging is done is none of your concern, as long as you know what logging does. 另一个原因是,作为日志库的用户,只要您知道日志记录的作用,您就不会担心如何进行日志记录。

So back to JavaScript, most non-trivial web applications have their own custom JavaScript libraries, many of which use open source libraries such as jQuery and dojo. 回到JavaScript,大多数非平凡的Web应用程序都有自己的自定义JavaScript库,其中许多使用开源库,如jQuery和dojo。 If a custom library depends on, say jQuery, not as an extension, but as implementation, do you see the need to add another layer that wraps jQuery and makes it transparent to the rest of JavaScript code? 如果自定义库依赖于jQuery,而不是作为扩展,而是作为实现,您是否认为需要添加另一个包装jQuery的层并使其对其余JavaScript代码透明?

For example, if you have the foo library that contains all your custom, front-end logic, you'd introduce the bar library that just wraps jQuery. 例如,如果你有包含所有自定义前端逻辑的foo库,你将引入刚刚包装jQuery的bar库。 This way, your foo library would use the bar library for jQuery functions, but it is totally oblivious to jQuery. 这样,你的foo库就会使用bar库来实现jQuery函数,但它完全没有jQuery。 In theory, you could switch to other libraries such as dojo and google web toolkit without having a big impact on the foo library. 从理论上讲,您可以切换到其他库,如dojo和google web toolkit,而不会对foo库产生太大影响。

Do you see any practical value in this? 你觉得这有什么实际价值吗? Overkill? 矫枉过正?

Although it makes sense from a theoretical standpoint, in practice I'd say it's overkill. 虽然从理论的角度来看它是有道理的,但在实践中我会说它太过分了。 If nothing else for these two reasons: 如果出于以下两个原因,没有别的:

  1. Anything that adds to the size of the request (or adds more requests) is bad - in web world, less is more. 任何增加请求大小(或添加更多请求)的东西都是不好的 - 在网络世界中,少即是多。
  2. If you're using say jQuery, the chances of you switching to something like Mootools is (imho) slim to none. 如果你正在使用说jQuery,那么你切换到Mootools这样的东西的机会很小(imho)。 From what I've seen, the top libraries each aim to solve different problems (at least in the case of Mootools and jQuery - see this great doc for more info on that). 从我所看到的,顶级库每个都旨在解决不同的问题(至少在Mootools和jQuery的情况下 - 请参阅这个伟大的文档获取更多信息)。 I'd assume that you'd incur a tremendous amount of headache if you were to try to implement a middleware library that could easily switch between the two. 如果你试图实现一个可以在两者之间轻松切换的中间件库,我认为你会遇到很大的麻烦。

In my experience and being a Java developer myself, sometimes we tend to take the whole "abstraction" layer pattern too far, I've seen implementations where someone decided to completely abstract a certain framework just for the sake of "flexibility" but it ends up making things more complicated and creating more code to maintain. 根据我的经验,我自己也是一名Java开发人员,有时候我们倾向于把整个“抽象”层模式放得太远,我已经看到有人为了“灵活性”而决定完全抽象某个框架的实现,但它结束了使事情变得更复杂并创建更多代码来维护。

Bottom line is you should look at it on a case by case basis, for example you wouldn't try to create an abstraction layer on top of struts, or on top of JPA, just in case you then go to a different framework (which I've rarely seen done). 底线是您应该根据具体情况来看待它,例如,您不会尝试在struts之上或JPA之上创建一个抽象层,以防万一然后转到另一个框架(我很少见过。)

My suggestion is, regardless of the framework you are using, create objects and components that use the framework internally, they should model your problem and be able to interact between them without the need of any specific framework. 我的建议是,无论您使用何种框架,创建在内部使用框架的对象和组件,他们都应该为您的问题建模并能够在不需要任何特定框架的情况下进行交互。

Hope this helps. 希望这可以帮助。

There are a lot of good answers here, but one thing I don't see mentioned is feature sets. 这里有很多好的答案,但我没有看到的一件事就是功能集。 If you try to write a library to wrap the functionality provided by, say, jQuery, but you want to be able to easily swap out for something like prototype, you have a problem. 如果您尝试编写一个库来包装jQuery提供的功能,但是您希望能够轻松换出类似原型的东西,则会遇到问题。 The jQuery library doesn't provide all the features prototype provides, and prototype doesn't provide all the features jQuery provides. jQuery库没有提供原型提供的所有功能,而原型也没有提供jQuery提供的所有功能。 On top of that, they both provide their features in radically different ways (prototype extends base objects -- that's damn near impossible to wrap). 最重要的是,它们都以完全不同的方式提供它们的功能(原型扩展了基础对象 - 这几乎不可能包装)。

In the end, if you tried to wrap these libraries in some code that adds 'abstraction' to try to make them more flexible, you're going to lose 80% of what the frameworks provided. 最后,如果您尝试将这些库包装在一些代码中,这些代码添加了“抽象”以试图使它们更加灵活,那么您将失去80%的框架所提供的内容。 You'll lose the fancy interfaces they provide (jQuery provides an awesome $('selector') function, prototype extends base objects), and you'll also have to decide if you want to leave out features. 你会失去他们提供的花哨界面(jQuery提供了一个很棒的$('选择器')函数,原型扩展了基础对象),你还必须决定是否要省略功能。 If a given feature is not provided by both frameworks, you have to either ditch it or reimplement it for the other framework. 如果两个框架都没有提供给定的功能,您必须抛弃它或为其他框架重新实现它。 This is a big can of worms. 这是一大堆蠕虫。

The whole problem stems from the fact that Java is a very inflexible language. 整个问题源于Java是一种非常不灵活的语言。 A library provides functionality, and that's it. 库提供了功能,就是这样。 In JavaScript, the language itself is insanely flexible, and lets you do lots of crazy things (like writing a library, and assigning it to the $ variable). 在JavaScript中,语言本身非常灵活,可以让你做很多疯狂的事情(比如编写一个库,然后将它分配给$变量)。 The ability to do crazy things lets developers of javascript libraries provide some really creative functionality, but it means you can't just find commonalities in libraries and write an abstraction. 做疯狂事情的​​能力让javascript库的开发人员提供了一些非常有创意的功能,但这意味着你不仅可以在库中找到共性并编写抽象。 I think writing javascript well requires a significant change in perspective for a Java developer. 我认为编写好的JavaScript需要对Java开发人员进行重大改进。

Someone wise once said "premature optimization is the root of all evil." 有人明智地说“过早优化是所有邪恶的根源”。 I believe that applies in this case. 我相信这适用于这种情况。

As others have expressed, you don't want to abstract for the sake of flexibility until you have an actual need for the abstraction. 正如其他人所表达的那样,在你真正需要抽象之前,你不想为了灵活性而抽象。 Otherwise you end up doing more work than necessary, and introducing unnecessary complexity before it is required. 否则,您最终会做更多不必要的工作,并在需要之前引入不必要的复杂性。 This costs money and actually makes your code more brittle. 这需要花钱,实际上会使您的代码更加脆弱。

Also, if your code is well organized and well tested, you should not be afraid of major changes. 此外,如果您的代码组织良好且经过充分测试,您不应该害怕重大变化。 Code is always changing, and trying to anticipate and optimize for a change that may or may not come will almost always get you in more trouble than it saves you. 代码总是在变化,尝试预测和优化可能会或可能不会发生的变化几乎总会让您遇到麻烦而不是拯救您。

Acknowledgement: I should give credit to Agile programming and my practice and readings on the topic. 致谢:我应该赞扬敏捷编程以及我对该主题的实践和阅读。 What I've said comes directly from my understanding of Agile, and I've found it to be an extremely good razor to cut out the extra fat of my work and get lots done. 我所说的直接来自于我对敏捷的理解,我发现它是一个非常好的剃刀,可以减少我工作的额外成本并完成很多工作。 Also none of what I've said is actually JavaScript specific... I'd apply those principles in any language. 此外,我所说的一切都不是JavaScript特定的...我会用任何语言应用这些原则。

There are good arguments calling this development practice - wrapping in order to switch later - into question in any language. 有很好的论据称这种开发实践 - 包装以便以后切换 - 用任何语言提出质疑。

A good quote by Oren Eini, from his writeup on wrapping ORMs : Oren Eini在他关于包装ORM的文章中引用了一句好话

Trying to encapsulate to make things easier to work with, great. 尝试封装以使事情更容易使用,很棒。 Trying to encapsulate so that you can switch OR/Ms? 试图封装,以便您可以切换OR / Ms? Won't work, will be costly and painful. 不会工作,将是昂贵和痛苦的。

This is definitely something that is done in enterprise environments. 这绝对是在企业环境中完成的事情。

Take for example a company that has their own custom javascript framework that is used on all of their projects. 以一家公司为例,该公司拥有自己的自定义javascript框架,用于所有项目。 Each of the projects decide to use their own framework (jQuery, Dojo, Prototype) to add functionality to the underlying modules of the company framework. 每个项目都决定使用自己的框架(jQuery,Dojo,Prototype)来为公司框架的底层模块添加功能。 Employees that move between projects can now easily do so because their API with working the project's codebase is still the same, even though the underlying implementation could be different for each project. 在项目之间移动的员工现在可以很容易地这样做,因为他们使用项目代码库的API仍然是相同的,即使每个项目的底层实现可能不同。 Abstraction is helpful in these situations. 在这些情况下,抽象是有帮助的。

It is overkill. 这太过分了。 Javascript is not Java and is not in any way related to Java. Javascript不是Java,与Java没有任何关系。 It is a completely different language that got Java in the name for marketing reasons. 这是一种完全不同的语言,出于营销原因,它将Java作为名称。

If you are concerned with availability of add-on libraries, then choose a framework with a large ecosystem. 如果您关心附加库的可用性,那么选择具有大型生态系统的框架。 In an enterprise environment you will be further ahead by standardising on a vanilla off-the-shelf uncustomised web framework that you can upgrade every year or so tracking the rest of the world. 在企业环境中,您将通过标准化现成的非自定义Web框架来进一步领先,您可以每年升级,跟踪世界其他地方。 And then supplement that with a SMALL in-house add-on library which you will, of course, have to maintain yourself, not to mention training any new programmers that you hire. 然后用一个SMALL内部附加库来补充它,当然,你必须自己维护,更不用说训练你雇用的任何新程序员了。

Since you are talking about Javascript in the client (web browser) it is more important that you limit the complexity of the things that people do with it. 由于您在客户端(Web浏览器)中讨论Javascript,因此限制人们使用它的事情的复杂性更为重要。 Don't build huge amounts of client side code, and don't make stuff that is so brittle that another programmer can't maintain it. 不要构建大量的客户端代码,也不要制造那么脆弱的东西,而另一个程序员则无法维护它。 A web framework helps you both keep the linecount down, and keep your own code reasonably simple. Web框架可以帮助您降低行数,并使您自己的代码保持相当简单。

It is not a question of Javascript best practice, because that would be different for server-side JS such as Rhino or node.js. 这不是Javascript最佳实践的问题,因为对于服务器端的JS,例如Rhino或node.js,这会有所不同。

Adapter pattern is not a common solution in this case. 在这种情况下,适配器模式不是常见的解决方案。 The only example I know to use this pattern is extjs . 我知道使用这种模式的唯一例子是extjs Javascript projects are usually too small and they aren't worth the effort you would make by creating such an abstraction layer. Javascript项目通常太小,并且通过创建这样的抽象层不值得你做的努力。 The common solution for this problem is that you try to use multiple frameworks together for example with jquery.noConflict . 此问题的常见解决方案是您尝试将多个框架一起使用,例如使用jquery.noConflict

I've done this before, and can talk a bit about the experience of writing a library/toolkit wrapper. 我以前做过这个,可以谈谈编写库/工具包包装的经验。

The plan was to move from Prototype to some other library. 计划是从Prototype转移到其他一些图书馆。 Dojo was the first choice, but at the time I wasn't sure whether that's the library to move everything to (and by everything I mean ~5MB of Prototype-happy JS). Dojo是第一选择,但当时我不确定这是否是将所有内容移动到的库(以及我所说的所有内容~5MB的Prototype-happy JS)。 So coming from a world of clean interfaces, I was set to write one around Prototype and Dojo; 所以来自一个干净的界面世界,我准备在Prototype和Dojo周围写一个; an awesome interface that would make switching out from dojo a breeze, if that was in fact necessary. 一个令人敬畏的界面,如果事实上是必要的话,这将使得从dojo切换出来是一件轻而易举的事。

That was a mistake that cost a lot of time and effort for a few reasons. 这是一个错误,由于一些原因需要花费大量的时间和精力。 The first one is that although two libraries can provide the same functionality, (a) their API will almost always be different, and most importantly (b) the way you program with one library will be different. 第一个是虽然两个库可以提供相同的功能,但是(a)它们的API几乎总是不同的,最重要的是(b)你用一个库编程的方式会有所不同。

To demonstrate, let's take something as common as adding a class-name: 为了演示,让我们采取像添加类名一样常见的东西:

// Prototype
$("target").addClassName('highlighted');

// Dojo
dojo.addClass("target", "highlighted");

// jQuery
$("target").addClass("highlighted");

// MooTools
$('target').set('class', 'highlighted');

Pretty straight-forward so far. 到目前为止非常直截了当。 Let's complicate it a bit: 让我们复杂一点:

// Prototype
Element.addClassName('target', 'highlighted selected');

// Dojo
dojo.addClass("target", ["highlighted", "selected"]);

// jQuery
$("target").addClass(function() {
   return 'highlighted selected';
});

// MooTools
$("target").set({
    "class": "highlighted selected"
});

Now after choosing an interface for your version of the addClass you have two options: (1) code to the lowest common denominator, or (2) implement all of the non-intersecting features of the libraries. 现在,为您的addClass版本选择一个接口后,您有两个选择:(1)代码到最小公分母,或(2)实现库的所有非交叉功能。

If you go with the 1st -- you'll loose the "personality" / best qualities of each of the library. 如果你选择第一名 - 你将失去每个图书馆的“个性”/最佳品质。 If you go with #2 -- your addClass' code will be at 4 times larger than the ones provided by any of the libraries, since for example when Dojo is included, you'll have to write the code for the function as the first param (jQuery) and the Object as the first param (MooTools). 如果你选择#2 - 你的addClass代码将比任何库提供的代码大4倍,因为例如当包含Dojo时,你必须编写函数的代码作为第一个param(jQuery)和Object作为第一个参数(MooTools)。

Therefore, although it is theoretically possible, it isn't practical, but is a very nice way to understand the intricacies of the libraries out there. 因此,虽然它在理论上是可行的,但它不实用,但却是理解那些库的复杂性的一种非常好的方法。

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

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