您将如何组织大型复杂的 Web 应用程序(参见基本示例)? [英] How would you organize a large complex web application (see basic example)?

查看:21
本文介绍了您将如何组织大型复杂的 Web 应用程序(参见基本示例)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了让事情变得有趣并结束我的最后一个悬而未决的问题,以组织良好的方式和体面的架构实现以下功能的解决方案获得了丰厚的回报.完整代码在 jsfiddle 上,有任何问题可以随时提问:)

Just to keep things interesting and close my final open question, the solution that implements the below functionality in a nicely organized manner with a decent architecture gets a good bounty. The full code is on jsfiddle, and feel free to ask any questions :)

您通常如何组织在客户端极其丰富的复杂 Web 应用程序.我创建了一个人为的示例,以表明如果大型应用程序的管理不善,很容易陷入混乱.随意修改/扩展此示例 - http://jsfiddle.net/NHyLC/1/

How do you usually organize complex web applications that are extremely rich on the client side. I have created a contrived example to indicate the kind of mess it's easy to get into if things are not managed well for big apps. Feel free to modify/extend this example as you wish - http://jsfiddle.net/NHyLC/1/

该示例基本上反映了 SO 上的部分评论,并遵循以下规则:

The example basically mirrors part of the comment posting on SO, and follows the following rules:

  1. 必须至少有 15 个字符,修剪多个空格后一分为二.
  2. 如果 Add Comment 被点击,但是删除后尺寸小于15多个空格,然后显示一个弹出窗口错误.
  3. 指出剩余的字符数和用颜色编码总结.灰色表示一个小注释,棕色表示中等评论,橙色大评论,红色评论溢出.
  4. 一条评论只能提交每 15 秒.如果评论是提交过早,显示弹出窗口带有适当的错误消息.
  1. Must have 15 characters minimum, after multiple spaces are trimmed out to one.
  2. If Add Comment is clicked, but the size is less than 15 after removing multiple spaces, then show a popup with the error.
  3. Indicate amount of characters remaining and summarize with color coding. Gray indicates a small comment, brown indicates a medium comment, orange a large comment, and red a comment overflow.
  4. One comment can only be submitted every 15 seconds. If comment is submitted too soon, show a popup with appropriate error message.

我注意到这个例子的几个问题.

A couple of issues I noticed with this example.

  • 理想情况下,这应该是一个小部件或某种打包的功能.
  • 诸如每 15 秒的评论和最少 15 个字符的评论之类的内容属于某些应用程序范围的政策,而不是嵌入到每个小部件中.
  • 硬编码值过多.
  • 没有代码组织.模型、视图、控制器都捆绑在一起.并不是说 MVC 是组织富客户端 Web 应用程序的唯一方法,但在本示例中没有.

你会如何清理这个?在此过程中应用了一点 MVC/MVP?

How would you go about cleaning this up? Applying a little MVC/MVP along the way?

这里有一些相关的函数,但如果你在 jsfiddle 上看到完整的代码会更有意义:

Here's some of the relevant functions, but it will make more sense if you saw the entire code on jsfiddle:

/**
 * Handle comment change.
 * Update character count. 
 * Indicate progress
 */
function handleCommentUpdate(comment) {
    var status = $('.comment-status');

    status.text(getStatusText(comment));
    status.removeClass('mild spicy hot sizzling');
    status.addClass(getStatusClass(comment));
}

/**
 * Is the comment valid for submission
 * But first, check if it's all good.
 */
function commentSubmittable(comment) {
    var notTooSoon = !isTooSoon();
    var notEmpty = !isEmpty(comment);
    var hasEnoughCharacters = !isTooShort(comment);

    return notTooSoon && notEmpty && hasEnoughCharacters;
}

/**
 * Submit comment.
 * But first, check if it's all good!
 */
$('.add-comment').click(function() {
    var comment = $('.comment-box').val();

    // submit comment, fake ajax call
    if(commentSubmittable(comment)) {
        .. 
    }

    // show a popup if comment is mostly spaces
    if(isTooShort(comment)) {
        if(comment.length < 15) {
            // blink status message
        }
        else {
           popup("Comment must be at least 15 characters in length.");
        }
    }
    // show a popup is comment submitted too soon
    else if(isTooSoon()) {
        popup("Only 1 comment allowed per 15 seconds.");
    }

});

编辑 1:

@matpol 感谢您对包装对象和插件的建议.这将是对现有混乱局面的重大改进.但是,该插件不是独立的,正如我所提到的,它将成为更大的复杂应用程序的一部分.客户端/服务器端的应用程序范围的策略会规定诸如评论的最小/最大长度、用户评论的频率等.当然,插件可以将此信息作为参数提供.

@matpol Thanks for the suggestion for a wrapper object and plugin. That will really be a big improvement over the existing mess. However, the plugin is not independent and as I mentioned, it would be part of a larger complex application. Application wide policies on client/server side would dictate things like minimum/maximum length of a comment, how often can a user comment, etc. Surely the plugin can be fed this information as parameters.

此外,对于富客户端应用程序,数据必须与其 html 表示分离,因为可以保存许多服务器往返,因为应用程序具有数据感知能力,并且可以将内容存储在本地,并定期更新在服务器上,或应用程序本身内的有趣事件(例如窗口关闭时).这就是为什么我真的不喜欢插件方法的原因.它会像提供打包的表示一样工作,但它仍然会以 DOM 为中心,当您在应用程序中有 20 个这样的插件时,这将是有问题的,无论如何这都不是一个荒谬的数字.

Also, for a rich client side application, the data would have to be separated from its html representation, as many server round-trips can be saved since the application is data-aware and things could be stored locally, and periodically updated on the server, or upon interesting events within the application itself (such as when the window is closed). Here's why I don't really like a plugin approach. It would work as in provide a packaged representation, but it would still be centered around the DOM, which is going to be problematic when you have 20 such plugins in the application, which is not an absurd number by any means.

推荐答案

我的做法是三折.

  1. 将 javascript 封装在命名空间内定义良好的小型类中
  2. Javascript 类应该具有它们需要注入"的 HTML 作为依赖项,允许 浏览器外单元测试
  3. 将尽可能多的客户端功能移至服务器,并使用称为 AHAH 的概念

Javascript 名称间距

这很容易实现,并且已经在其他帖子中进行了介绍,例如 是否有简明"?在 JavaScript 中如何进行命名空间?

This can be achieved easily and has been covered in other posts such as this Is there a "concise" way to do namespacing in JavaScript?

小封装类

Javascript 代码,就像服务器端代码一样,应该用小的内聚类和方法很好地封装.每个类都位于一个单独的文件中,并与其所在的命名空间一起命名,例如:MyCompany.SomePackage.MyClass.js.通过合并和缩小 这些在构建时的类文件.

Javascript code, just like server-side code should be well encapsulated with small cohesive classes and methods. Each class lives in a separate file, named along with the namespace it is in, eg: MyCompany.SomePackage.MyClass.js. Excessive HTTP requests to each file can be saved via combining and minifying these class files at build time.

Javascript 中的依赖倒置

如此有效,而不是选择您需要在类中使用的元素,如下所示:

So effectively instead of selecting the elements you require to work with inside your class, like this:

var MyNamespace.MyClass = function() {
  var elementINeed = $('#IdOfElementINeed');
}

你会像这样注入它:

var foo = new MyNamspace.MyClass($('#IdOfElementINeed'));

var MyNamespace.MyClass = function(incomingDependency) {
  var elementINeed = incomingDependency;
}

这种技术非常适合通过 MVC 风格进行可测试的 javscript 和关注点分离 代码分层.

This technique lends itself well to testable javscript and seperation of concerns through MVC style layering of your code.

AHAH 和客户端简化

AHAH 是一种相当古老的技术,在网络开发,虽然它纯粹的简单性正在网络爱好者中复兴.然而,哲学必须在架构技术层面之外被接受,它必须被用作所有客户端 javascript 的替代品,例如:验证、显示/隐藏动态内容、计算等

AHAH is quite an old technique that has been around for quite some time in web-development, although is making a resurgence amongst web aficionados for its pure simplicity. However, the philosophy must be bought into at more than the architectural technique level and it must be used as a replacement for all your client side javascript eg: validation, showing/hiding dynamic content, calculations etc

您可能曾经在何处附加具有客户端复杂性的 onClick 事件:

Where you may used to have attached an onClick event with client-side complexity:

$('#someElement').click(function(){
  // insert complex client-side functionality here, such as validating input
  // eg var isValid = $(this).val() < minimumCommentLength;
  // update page based on result of javascript code
  // eg $('#commentTooLong').show();
})

现在您只需触发一个 ajax 请求返回服务器以获取新的 HTML 并简单地替换您感兴趣的全部或部分元素:

Now you would simply trigger an ajax request back to the server to get the new HTML and simply replace all or some of the elements you are interested in as such:

$('#addCommentButton').click(function(){
  $.ajax({ 
    url: "/comment/add", 
    context: document.body, success: 
    function(responseHTML){
        $('body').html(reponseHTML);
      }});
})

显然这是一个微不足道的例子,但是当有效地使用时,页面上的任何 javascript 事件都会触发相同的 ajax 请求和 HTML 替换,大大减少了所需的客户端代码量.将其移至可以进行有效测试的服务器.

Obviously this is a trivial example, but when used effectively, ANY javascript event on the page, simply fires off the identical ajax request and HTML replacement, greatly reducing the amount of client-side code required. Moving it to the server where it can be effectively tested.

AHAH 反对者,会争辩说这不是运行网站的一种高效方式,但是我已经在具有 56k 调制解调器访问权限的网站和大规模公共网站上使用并看到了这种技术.结果当然更慢,但你仍然可以产生低于 100 毫秒的往返行程,这对人类来说几乎是即时的.

AHAH nay-sayers, will argue that this is not a performant way to run a web-site, however I have used and seen this technique on sites with 56k modem access and also massively scaled public web-sites. The result is of course slower, but you can still produce sub 100 millisecond round trips, which is practically instant to humans.

这篇关于您将如何组织大型复杂的 Web 应用程序(参见基本示例)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆