zoukankan      html  css  js  c++  java
  • 都是一样的

    我家小孩最喜欢的一句口头禅就是“都是一样的”。每当他看到两件相似的东西时,就会说“都是一样的”。其实,程序设计也是如此,不管语言的变化有多大,其基本的编程思想和设计本质,都是殊途同归。

    最近看了Jonathan Snook的作品《Javascript捷径教程》(英文书名:Accelerated DOM Scripting with Ajax, APIs, and Libraries),他带领读者构建了一个简单的动画对象。简单的例子,轻描淡写的描述,我却觉得颇有感悟,似乎展现了朴素的基本设计思想。书中这样写道:

    页面里要用到的动画对象一般都不止一个,所以应该把它定义成一个类。定义一个有5个参数的函数:要加上动画的元素、要改变的属性、属性的起始值、属性的结束值、动画的持续时间。

    function Animation(element, property, from, to, duration){}

    不管编写什么代码,都应该先把实现想透彻。每个决定都有正反两方面的后果,你应该想清楚每个决定的原因。

    这代表一个朴素的思想,那就是从实现原理来进行设计决定。注意这里的实现原理,并不是要关注实现的细节,而是要考虑影响实现的因素,并从调用者的角度思考接口或函数的输入与输出值。以本例而言,如果事先不明确动画效果的营造方式,是根据时间的变化动态变更element属性的方式来完成,就无法确定Animation函数。设计不是空中楼阁,抽象固然是重要的,但功能实现的基本原理仍然需要事先思考通透,否则,设计就可能走弯路。拿到一个功能,先要弄清楚它的目标是什么,有没有质量属性的要求,未来的变化如何,还有这一功能的实现原理。例如,我们要提供服务定制的功能,就需要实现明确“服务”的定义,如何完成服务的注册,服务的发布,服务的订阅,谁会订阅这些服务,服务的安全如何保障,如何解决服务与实现的脱耦。只有把这些问题想清楚了,设计才会靠谱。

    看看前面的代码,元素ID是作为一个字符串传递进来的,那么在动画对象中获取该元素就有两种方法:一是通过DOM方法document.getElementById();二是采用Javascript库的调用,如${}。……既然我们想让这个动画对象能适合各种情况,那还是用DOM方法比较好,保证它不依赖于任何库。

    function Animation(element, property, from, to, duration)
    {
        var el = ducument.getElementById(element);
        if (!el) return false;
    
    }

    这段话仍然体现了一种设计决策。它的实现目标是不与任何JS库耦合。这就需要保证实现的通用性。

    要是你打算执行动画的元素没有ID怎么办呢?为了让这个类更灵活,让我们把它改成既可以传入元素引用,又可以传入ID字符串。如果传入的是ID字符串而不是对象引用,程序就会通过DOM方法去获取元素。两全其美!

    function Animation(element, property, from, to, duration)
    {
        var el = element;
        if (typeof el == 'string') el = document.getElementById(element);
        if (!el) return false;
    }

    这又是一种编码修炼了。除了要在设计上保证灵活性之外,我们在编码时也需养成保证代码完整性与健壮性的习惯,并体贴地为调用者着想。有这么一条设计原理,就是伯斯塔尔法则(Postel's Law):“发送时要保守;接收时要开放。”这里的实现无疑遵循了这样一个法则。我们在编码时,考虑到这些因素了吗?

    Ok,继续我们的阅读。

    实例化一个对象要用到5个参数,但一眼看上去很难看出参数里的那些数字都代表什么含义。……为此你可以把参数改成字面量对象,键的名称看起来更直观一些。而且如此改动能使API更加灵活,因为即使今后增加了更多的参数,实例化对象的代码也不会变得更复杂。

    function Animation(options)
    {
        var el = options.element;
    }
    var options = {
        element:document.getElementById('elementId'),
        property: 'left',
        from:0,
        to:200,
        duration:1000
    };

    无疑,这体现了面向对象的“封装”思想。通过封装既保证了代码的清洁与可读性,同时还有利于未来的扩展。这与OCP(开放-封闭原则)是一脉相承的。代码是有结构的,或者体现为函数,或者体现为对象,事实上都是一种按照属性与职责进行的分类。分类是保持清洁、避免重复的唯一法门。从简朴的角度来说,所有的设计其实都是在做着分类的游戏。分类体现了定义的抽象,职责的分配,结构的划分;如果再加上类别之间的协作,就是设计的全部了。

  • 相关阅读:
    java基础部分的一些有意思的东西。
    antdvue按需加载插件babelpluginimport报错
    阿超的烦恼 javaScript篇
    .NET E F(Entity Framework)框架 DataBase First 和 Code First 简单用法。
    JQuery获得input ID相同但是type不同的方法
    gridview的删除,修改,数据绑定处理
    jgGrid数据格式
    Cannot read configuration file due to insufficient permissions
    Invoke action which type of result is JsonResult on controller from view using Ajax or geJSon
    Entity model数据库连接
  • 原文地址:https://www.cnblogs.com/wayfarer/p/2019143.html
Copyright © 2011-2022 走看看