精华内容
下载资源
问答
  • 下面关于采用Java EE架构的描述,不正确的是 ( ) 。A、Java EE定义了分布式环境中多层应用系统的架构,是多种Java技术的混合体B、具有典型的三层结构:表现层,业务逻辑层和基础设施层C、不同的应用系统底层支持...

    旺财管理软件(cnitpm.com) 17:16:31

    Java EE是Java领域内企业级应用开发的框架与标准。下面关于采用Java EE架构的描述,不正确的是 ( ) 。

    A、Java EE定义了分布式环境中多层应用系统的架构,是多种Java技术的混合体

    B、具有典型的三层结构:表现层,业务逻辑层和基础设施层

    C、不同的应用系统对底层支持系统的要求可能不同,因此每次开发时应该针对不同的应用需求对底层系统进行二次开发,提供支持接口

    D、要严格区分业务逻辑层和表现层,尤其应该注意不要在表现层中混杂业务代码

    秋水长天(cnitpm.com) 17:18:28

    3???

    旺财管理软件(cnitpm.com) 17:18:32

    这是专业人来答的。

    旺财管理软件(cnitpm.com) 17:19:10

    不过,我也搞笑了。  这题的B明显是不对的。

    鱼♂≮余江波≯(cnitpm.com) 17:20:00

    信息发布是项目监控内容不是执行的内容吗?

    309627378(cnitpm.com) 17:20:46

    还剩下不到一个月了

    旺财管理软件(cnitpm.com) 17:22:12

    恩。加油。

    直心眼(cnitpm.com) 17:22:50

    这题选B?

    旺财管理软件(cnitpm.com) 17:22:53

    最后5天,基本不能计算的,可能心都飞了。

    旺财管理软件(cnitpm.com) 17:23:09

    答案是C,不会,B是错的。

    旺财管理软件(cnitpm.com) 17:23:20

    百度一下,你就知道。什么是三层。

    雨巷(cnitpm.com) 17:23:33

    题目问的就是不正确的啊

    秋水长天(cnitpm.com) 17:23:42

    好像java忽略系统的

    煜┷传说(cnitpm.com) 17:23:42

    c

    煜┷传说(cnitpm.com) 17:24:14

    Java是跨平台的

    可人(cnitpm.com) 17:24:16

    第2题,感觉不对呢

    直心眼(cnitpm.com) 17:24:50

    对头,C是错的

    直心眼(cnitpm.com) 17:25:07

    B哪里错了呀

    旺财管理软件(cnitpm.com) 17:25:18

    没有基础设施

    尊(cnitpm.com) 17:26:14

    B

    尊(cnitpm.com) 17:26:17

    我是专业人士啊

    可人(cnitpm.com) 17:26:20

    没有基础设施

    尊(cnitpm.com) 17:26:39

    模型层

    尊(cnitpm.com) 17:27:01

    MVC

    直心眼(cnitpm.com) 17:27:40

    有没有解析看看呢

    旺财管理软件(cnitpm.com) 17:27:43

    B是错的,所以,不选B就不对的。

    旺财管理软件(cnitpm.com) 17:28:02

    @尊 B是错误的吧。

    可人(cnitpm.com) 17:28:30

    标准答案是多少?

    旺财管理软件(cnitpm.com) 17:28:53

    答案是C

    直心眼(cnitpm.com) 17:29:08

    答案是C~

    旺财管理软件(cnitpm.com) 17:29:27

    B确定是错的,专业人士。

    雨巷(cnitpm.com) 17:30:20

    题目问的是不正确

    雄楚墨(cnitpm.com) 17:31:33

    系统分析师的题目怪不得这么专业

    可人(cnitpm.com) 17:32:01

    C好象也不对

    可人(cnitpm.com) 17:32:19

    不可能每次都专门开发一个接口来提供,有些是可以共用一个接口的

    雄楚墨(cnitpm.com) 17:32:52

    不同的要求才二次开发

    可人(cnitpm.com) 17:33:07

    是的

    可人(cnitpm.com) 17:33:09

    所以C也不错

    可人(cnitpm.com) 17:33:22

    也不对

    可人(cnitpm.com) 17:33:25

    C也是错的

    煜┷传说(cnitpm.com) 17:36:42

    java 三层架构是对的,MVC,不过我们不说基础设施层,不知道她的基础设施层和M是不是一致

    菲(cnitpm.com).。o♡(cnitpm.com) 17:39:12

    所以答案是c?

    煜┷传说(cnitpm.com) 17:39:31

    我看看书

    煜┷传说(cnitpm.com) 17:40:41

    高级的没有,谁有中级的书看下

    菲(cnitpm.com).。o♡(cnitpm.com) 17:41:15

    这是中级的题目吗

    煜┷传说(cnitpm.com) 17:41:34

    java,中级书里比较详细

    菲(cnitpm.com).。o♡(cnitpm.com) 17:41:37

    刷了那么久的题目 觉得中级跟高级的选择都差不多

    尊(cnitpm.com) 17:42:22

    @旺财管理软件 c也错

    尊(cnitpm.com) 17:43:54

    但是b答案有点模拟量可

    LIKai(cnitpm.com) 17:44:51

    模棱两可

    尊(cnitpm.com) 17:44:59

    是啊

    尊(cnitpm.com) 17:45:48

    整体技术架构分为基础设施层 数据层 业务层 展现层

    小萝卜头(cnitpm.com) 18:07:45

    我只知道MVP

    旺财管理软件(cnitpm.com) 18:16:37

    技术上也有MVP的说法

    尊(cnitpm.com) 18:26:32

    @旺财管理软件 J2ee有MVc,

    展开全文
  • 背景描述 说明:singleton有各式各样翻译,因人口味而异,所以,本文中singleton就直接用英文了。 singleton实现方式也多多,以下只是做一种非侵入使用double-checked locking方式进行描述,有错误地方...

    背景描述

    说明:singleton有各式各样的翻译,因人口味而异,所以,本文中对singleton就直接用英文了。

    singleton的实现方式也多多,以下只是做一种非侵入的使用double-checked locking方式进行描述,有错误的地方尽情拍砖。

        在整个软件开发中,singleton应该是使用最广泛的一种设计模式,也几乎每个人都写过若个版本的单例实现,在这些singleton实现中,很大一部分实现均是有问题的,甚至是错误。以下从两个方面进行说明为什么,第一:singleton的生命周期问题,如:有A、B两个singleton,初始化顺序为A、B,析构顺序当然为B、A,但是在A析构时调用了B,这时候将会产生什么结果? 第二:C++11以前语言本身没有提供内存边界(memory barrier)这个东西(其他语言也会有这个问题),C++的内存模型就不支持内存边界,导致在编译器优化或者cpu乱序(out-of-order)执行时,产生了非预期的结果,且该现象很难复现。

    如果您已经熟练使用singleton我建议您直接跳到singleton高级版,查看最后c++11带来的memory barrier给C++程序猿带来的福利。

    singleton初级版

    Foo* GetFooInstance() {  
        static Foo foo;  
        return &foo;  
    }

    或者

    Foo& GetFooInstance() {  
        static Foo foo;  
        return foo;  
    }

    这种实现是最原始的版本,有时在项目中也是见的最多的一个版本,在单线程程序,甚至在许多单核设备上问题都不是很大,但是遇到多核多线程时,也许就会跪了,是否会有问题还与Foo在构造函数中是否有额外的初始化有关,额外初始化就会花费时间,这样多线程访问到`GetFooInstance`时,也许会有可能会构造两次foo。这样就有了下面一个升级版。

    singleton升级版

    Foo* GetFooInstance() {  
        static Foo* foo = NULL;  
        if (NULL == foo) {  
            foo = new Foo;   // (1)
        }  
        return foo;  
    }

    这次升级后与上次相差不大,但是可以在(1)后面干点额外的东西了,如二段初始化等,但是还是没避免多线程问题。再次升级一下。

    template <typename T>
    class DefaultAllocatorTraits
    {
    public:
        static T* Allocate()
        {
            return new T;
        }
        static void Delete(T* t)
        {
            typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
            delete t;
        }
    };
    
    
    template <class T, class allocator = DefaultAllocatorTraits<T> >
    class Singleton    {
    public:
        Singleton()
            : singleton_(NULL) {
            InitializeCriticalSection(&wait_event_);
        }
        ~Singleton() {
            DeleteCriticalSection(&wait_event_);
            allocator::Delete(singleton_);
        }
        T* GetInstance() {
            // (1)
            if (NULL == singleton_)    {
                // (2)
                EnterCriticalSection(&wait_event_);
                // (3)
                if (NULL == singleton_)    {
                    singleton_ = allocator::Allocate();
                }
                LeaveCriticalSection(&wait_event_);
            }
            return singleton_;
        }
    private:
        CRITICAL_SECTION wait_event_;
        T*  singleton_;
    };

     

    以上代码使用方式为

    static Singleton<Foo> foo;  
    foo.GetInstance();

     

    代码看似很长,只是想看清所有内容而已,全部内容都在GetInstance中了,这里面的代码是以windows为例的,为了示例就没有封装锁了,意思一下即可,锁的位置可以放到(1)处,这时候呢每次进入到这个函数里面都得加一次锁,虽然没什么问题,但是消耗挺大的,所以放到(2)处,当获取到临界区的使用权限后,在对singleton_ 进行一次检查,并申请内存内存初始化等,这里进行二段初始化、三段初始化都已经没有问题了,这就是所谓的“Double-Checked Locking”。以下简称DCL。
    DCL解决了大部分情况下遇到的多数问题,如碰到多线程,即使两个线程都进入到二的位置,A线程获得临界区,进入到(3)然后执行完毕后退出临界区,B线程再进入,这时候由于检查了singleton_的有效性,所以不会再次初始化,以后都将不会进入到(2),所以这个版本的singleton基本能够投入使用了。
    但是这也不是没问题的,这里的singleton只负责了申请内存,没有释放,当然整个程序都有效的,有无释放都无所谓了。不过没释放总感觉少点啥,不是吗?

    singleton高级版

    传说中,C提供了一个高端的API`[atexit](http://www.cplusplus.com/reference/cstdlib/atexit/)`,这个东西呢能让我们注册一个在程序退出时调用函数的方法,在析构之前,也挺好,如果看着不爽或者不太想用这个时,可以自行实现,chrome的base库里面提供了一个实现[AtExit](http://src.chromium.org/viewvc/chrome/trunk/src/base/at_exit.h?revision=148405),这个都是小事,问题是这个能够辅助我们解决内存释放问题了,修改上面的单例,在申请内存的地方注册一下退出接口。我这里就使用的是`AtExitManager`因为C库那玩意儿不带参数,不能满足我的这个需求。
    修改如下

     

    T* GetInstance()
    {
        if (NULL == singleton_)
        {
            EnterCriticalSection(&wait_event_);
            if (NULL == singleton_)
            {
                singleton_ = memory_traits::Allocate();
                AtExitManager::RegisterCallback(Singleton::OnExit, this);
            }
            LeaveCriticalSection(&wait_event_);
        }
        return singleton_;
    }
    static void OnExit(void* singleton) {
        Singleton<T, allocator>* me =
            reinterpret_cast<Singleton<T, allocator>*>(singleton);
            allocator::Delete(me->singleton_);
    }

    实现还是比较粗糙的,但是至少能够初始化,能够释放了,不考他自身自灭了。
    到了现在,还是没能解决我的目的,重新初始化及[乱序执行](http://en.wikipedia.org/wiki/Out-of-order_execution)的问题。甚至有时候编译器优化的recorder等一系列的问题,都有可能导致代码并不是按照人想的一样执行

    T* GetInstance()
    {
        // (1)
        if (NULL == singleton_)
        {
            // (2)
            EnterCriticalSection(&wait_event_);
            // (3)
            if (NULL == singleton_)
            {
                // (4)
                singleton_ = allocator::Allocate();
            }
            LeaveCriticalSection(&wait_event_);
        }
        return singleton_;
    }

    这段代码中,(3)、(4)处的内容被out-of-order执行的cpu弄到前面去执行的话,产生的问题将不可预料,当然这种情况也极少。
    在C++11修改过多线程的内存模型后,添加了memory barrier的东西,使指令在指定的一段内存中不会被使用乱序执行,当然memory barrier这个东西不是所有平台都支持的。有了这个之后修改上面的内容,(注:在java5.1以前的内存模型也会有这个问题,至于现在是否有修改不知道。。。求答案)。

    T* GetInstance()
    {
        std::atomic_thread_fence(std::memory_order_acquire);
        if (NULL == singleton_)
        {
            EnterCriticalSection(&wait_event_);
            if (NULL == singleton_)
            {
                singleton_ = allocator::Allocate();
            }
            LeaveCriticalSection(&wait_event_);
        }
        std::atomic_thread_fence(std::memory_order_release);
        return singleton_;
    }

    至于`memory_order_release`放到`singleton_ = allocator::Allocate()`后面也没太大关系。
    有了这么一玩意儿,在fence之间的代码就不会乱序执行了,当然需要编译器支持才能编译的过,详情参见[cplusplus.com](http://www.cplusplus.com/reference/atomic/atomic_thread_fence/?kw=atomic_thread_fence).
    注:linux平台提供了一些barrier可以使用,也能解决该问题。
    最后一个问题,单例牺牲后的恢复,这个问题,在前面提供析构函数的地方基本已经得到解决,有了析构函数之后,对原有变量稍加改动即可。
    因为,使用AtExitManager来控制生命周期后,按如下方式使用:

     

    int main() {
        AtExitManager exit_manager;
        // other operations.
        return 0;
    }

    exit_manager的生命周期受main控制,所以呢,肯定先于其他静态变量析构,在`exit_manager`退出时就会一一将单例析构,即使出现A B B A,A在调用B的情况,也会重新初始化单例B,因为静态变量还没析构,继续注册,继续析构,所以这种问题得以解决。
    到这里实现的单例,应该来说还是比较完善了。可以尽情的happy了。
    ### lock free ###

    前面的所有实现中均采用了锁的机制,现在应用的也挺多,但是编程难度挺高的一个lock free,可以让减少锁的使用,同时还可以提高性能,由于这个话题没能具体衡量,所以只好简要一笔带过。留作以后完善。

    直接参考chrome的源码也就是讲前面的锁换成一个spin lock,采用原子操作,减少整体线程切换及切换到内核状态等一系列的开销。

    参考:

    http://src.chromium.org/viewvc/chrome/trunk/src/base/lazy_instance.h?revision=204953

    这里面的lazy_instance就可以稍加修改拿来使用。

    结论


    最终我们使用DCL的方式实现了一个近乎完善的singleton,但是这只是其中的一种方法,如:c++11提供了一个方法[call_once](http://en.cppreference.com/w/cpp/thread/call_once),这个一看名字,对于单例来说太爽了。方法多多。

    ### 参考 ###


    - Double-Checked Locking is Broken
    - C++ and the Perils of Double-Checked Locking by scott meyers and andrei alexandrescu
    - Double-Checked Locking Is Fixed In C++11
    - chrome lazy_instance
    - [api design for c++ 第三章]

    转载于:https://www.cnblogs.com/linclee/p/3388587.html

    展开全文
  • 对软件测试理解

    2015-03-15 18:08:00
    软件测试(英语:software testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。 软件测试[1-2]是使用人工操作或者软件自动运行的方式来检验它是否满足规定的需求或弄清预期结果与实际结果...

    软件测试(英语:software testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。

    软件测试[1-2]   是使用人工操作或者软件自动运行的方式来检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别的过程。
    它是帮助识别开发完成(中间或最终的版本)的计算机软件(整体或部分)的
    正确度(correctness) 、完全度(completeness)和质量(quality)的软件过程;是SQA(software quality assurance)的重要子域。

    它是一种活动,用来评估一个软件的属性和质量。

    软件测试的历史大致分为以下几个阶段

    -1956 通过debug来进行测试,人工的进行测试

    1956-1978 为演示阶段

    1978-1982 面向构建的软件测试

    1982-1987 面向评估的软件测试

    1988-2000 以预防为主的软件测试

    2001-....   软件测试从艺术和经验上升到理论高度

    那么,我们为什么要进行软件测试呢,主要因为:

    1、我们的编程能力不是足够的强

    2、在编程过程中,我们的注意力不是总在如何预防错误上

    3、顾客的表达和他的实际所需可能有差异,因而对需求理解存在不同

    4、测试允许我们存在一定的失误(容错)

    同时,测试目标有以下几个方面:

    1.发现一些可以通过测试避免的开发风险。
    2.实施测试来降低所发现的风险。
    3.确定测试何时可以结束。
    4.在开发项目的过程中将测试看作是一个标准项目。

    同时,软件测试不是仅仅在代码写完之后才进行,反而,为了使测试更加的有效,

    软件测试的过程往往是一个一直伴随进行的过程。软件测试的方法也有很多种,

    最直接的就是人工的检查代码,高级的有回归测试等。

    转载于:https://www.cnblogs.com/lushengli1234/p/4340142.html

    展开全文
  • 如:对软件的认识 1、直观理解 (1)无颜色、无味道、无重量、永不磨损。 (2)是活着的人的灵魂验证,实现了灵魂的神话。 2、科学的定义 (1)、在运行中提供所希望的功能和性能的指令集(即程序)。 (2)使程序...
  • 图1:软件系统中耦合的对象如果我们打开机械式手表的后盖,就会看到与上面类似的情形,各个齿轮分别带动时针、分针和秒针顺时针旋转,从而在表盘上产生正确的时间。图1中描述的就是这样的一个齿轮组,它拥有多个独立...

    1 IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑。

    图1:软件系统中耦合的对象

    如果我们打开机械式手表的后盖,就会看到与上面类似的情形,各个齿轮分别带动时针、分针和秒针顺时针旋转,从而在表盘上产生正确的时间。图1中描述的就是这样的一个齿轮组,它拥有多个独立的齿轮,这些齿轮相互啮合在一起,协同工作,共同完成某项任务。我们可以看到,在这样的齿轮组中,如果有一个齿轮出了问题,就可能会影响到整个齿轮组的正常运转。 齿轮组中齿轮之间的啮合关系,与软件系统中对象之间的耦合关系非常相似。对象之间的耦合关系是无法避免的,也是必要的,这是协同工作的基础。现在,伴随着工业级应用的规模越来越庞大,对象之间的依赖关系也越来越复杂,经常会出现对象之间的多重依赖性关系,因此,架构师和设计师对于系统的分析和设计,将面临更大的挑战。对象之间耦合度过高的系统,必然会出现牵一发而动全身的情形。

    图2:对象之间复杂的依赖关系

    耦合关系不仅会出现在对象与对象之间,也会出现在软件系统的各模块之间,以及软件系统和硬件系统之间。如何降低系统之间、模块之间和对象之间的耦合度,是软件工程永远追求的目标之一。为了解决对象之间的耦合度过高的问题,软件专家Michael Mattson提出了IOC理论,用来实现对象之间的“解耦”,目前这个理论已经被成功地应用到实践当中,很多的J2EE项目均采用了IOC框架产品Spring。

    2 什么是控制反转(IoC) IOC是Inversion of Control的缩写,多数书籍翻译成“控制反转”,还有些书籍翻译成为“控制反向”或者“控制倒置”。 1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中,首先提出了IOC 这个概念。对于面向对象设计及编程的基本思想,前面我们已经讲了很多了,不再赘述,简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度,而且可以灵活地被重用和扩展。IOC理论提出的观点大体是这样的:借助于“第三方”实现具有依赖关系的对象之间的解耦,如下图:

    图3:IOC解耦过程

    大家看到了吧,由于引进了中间位置的“第三方”,也就是IOC容器,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠“第三方”了,全部对象的控制权全部上缴给“第三方”IOC容器,所以,IOC容器成了整个系统的关键核心,它起到了一种类似“粘合剂”的作用,把系统中的所有对象粘合在一起发挥作用,如果没有这个“粘合剂”,对象与对象之间会彼此失去联系,这就是有人把IOC容器比喻成“粘合剂”的由来。 我们再来做个试验:把上图中间的IOC容器拿掉,然后再来看看这套系统:

    图4:拿掉IoC容器后的系统

    我们现在看到的画面,就是我们要实现整个系统所需要完成的全部内容。这时候,A、B、C、D这4个对象之间已经没有了耦合关系,彼此毫无联系,这样的话,当你在实现A的时候,根本无须再去考虑B、C和D了,对象之间的依赖关系已经降低到了最低程度。所以,如果真能实现IOC容器,对于系统开发而言,这将是一件多么美好的事情,参与开发的每一成员只要实现自己的类就可以了,跟别人没有任何关系! 我们再来看看,控制反转(IOC)到底为什么要起这么个名字?我们来对比一下: 软件系统在没有引入IOC容器之前,如图1所示,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。 软件系统在引入IOC容器之后,这种情形就完全改变了,如图3所示,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。 通过前后的对比,我们不难看出来:对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。

    3 IOC的别名:依赖注入(DI) 2004年,Martin Fowler探讨了同一个问题,既然IOC是控制反转,那么到底是“哪些方面的控制被反转了呢?”,经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IOC容器主动注入。于是,他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现IOC的方法:注入。所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。

    所以,依赖注入(DI)和控制反转(IOC)是从不同的角度的描述的同一件事情,就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。 我们举一个生活中的例子,来帮助理解依赖注入的过程。大家对USB接口和USB设备应该都很熟悉吧,USB为我们使用电脑提供了很大的方便,现在有很多的外部设备都支持USB接口。

    图5:USB接口和USB设备

    现在,我们利用电脑主机和USB接口来实现一个任务:从外部USB设备读取一个文件。 电脑主机读取文件的时候,它一点也不会关心USB接口上连接的是什么外部设备,而且它确实也无须知道。它的任务就是读取USB接口,挂接的外部设备只要符合USB接口标准即可。所以,如果我给电脑主机连接上一个U盘,那么主机就从U盘上读取文件;如果我给电脑主机连接上一个外置硬盘,那么电脑主机就从外置硬盘上读取文件。挂接外部设备的权力由我作主,即控制权归我,至于USB接口挂接的是什么设备,电脑主机是决定不了,它只能被动的接受。电脑主机需要外部设备的时候,根本不用它告诉我,我就会主动帮它挂上它想要的外部设备,你看我的服务是多么的到位。这就是我们生活中常见的一个依赖注入的例子。在这个过程中,我就起到了IOC容器的作用。 通过这个例子,依赖注入的思路已经非常清楚:当电脑主机读取文件的时候,我就把它所要依赖的外部设备,帮他挂接上。整个外部设备注入的过程和一个被依赖的对象在系统运行时被注入另外一个对象内部的过程完全一样。 我们把依赖注入应用到软件系统中,再来描述一下这个过程: 对象A依赖于对象B,当对象 A需要用到对象B的时候,IOC容器就会立即创建一个对象B送给对象A。IOC容器就是一个对象制造工厂,你需要什么,它会给你送去,你直接使用就行了,而再也不用去关心你所用的东西是如何制成的,也不用关心最后是怎么被销毁的,这一切全部由IOC容器包办。 在传统的实现中,由程序内部代码来控制组件之间的关系。我们经常使用new关键字来实现两个组件之间关系的组合,这种实现方式会造成组件之间耦合。IOC很好地解决了该问题,它将实现组件间关系从程序内部提到外部容器,也就是说由容器在运行期将组件间的某种依赖关系动态注入组件中。

    4 IOC为我们带来了什么好处

    我们还是从USB的例子说起,使用USB外部设备比使用内置硬盘,到底带来什么好处? 第一、USB设备作为电脑主机的外部设备,在插入主机之前,与电脑主机没有任何的关系,只有被我们连接在一起之后,两者才发生联系,具有相关性。所以,无论两者中的任何一方出现什么的问题,都不会影响另一方的运行。这种特性体现在软件工程中,就是可维护性比较好,非常便于进行单元测试,便于调试程序和诊断故障。代码中的每一个Class都可以单独测试,彼此之间互不影响,只要保证自身的功能无误即可,这就是组件之间低耦合或者无耦合带来的好处。 第二、USB设备和电脑主机的之间无关性,还带来了另外一个好处,生产USB设备的厂商和生产电脑主机的厂商完全可以是互不相干的人,各干各事,他们之间唯一需要遵守的就是USB接口标准。这种特性体现在软件开发过程中,好处可是太大了。每个开发团队的成员都只需要关心实现自身的业务逻辑,完全不用去关心其它的人工作进展,因为你的任务跟别人没有任何关系,你的任务可以单独测试,你的任务也不用依赖于别人的组件,再也不用扯不清责任了。所以,在一个大中型项目中,团队成员分工明确、责任明晰,很容易将一个大的任务划分为细小的任务,开发效率和产品质量必将得到大幅度的提高。 第三、同一个USB外部设备可以插接到任何支持USB的设备,可以插接到电脑主机,也可以插接到DV机,USB外部设备可以被反复利用。在软件工程中,这种特性就是可复用性好,我们可以把具有普遍性的常用组件独立出来,反复利用到项目中的其它部分,或者是其它项目,当然这也是面向对象的基本特征。显然,IOC不仅更好地贯彻了这个原则,提高了模块的可复用性。符合接口标准的实现,都可以插接到支持此标准的模块中。 第四、同USB外部设备一样,模块具有热插拔特性。IOC生成对象的方式转为外置方式,也就是把对象生成放在配置文件里进行定义,这样,当我们更换一个实现子类将会变得很简单,只要修改配置文件就可以了,完全具有热插拨的特性。 以上几点好处,难道还不足以打动我们,让我们在项目开发过程中使用IOC框架吗?

    5 IOC容器的技术剖析 IOC中最基本的技术就是“反射(Reflection)”编程,目前.Net C#、Java和PHP5等语言均支持,其中PHP5的技术书籍中,有时候也被翻译成“映射”。有关反射的概念和用法,大家应该都很清楚,通俗来讲就是根据给出的类名(字符串方式)来动态地生成对象。这种编程方式可以让对象在生成时才决定到底是哪一种对象。反射的应用是很广泛的,很多的成熟的框架,比如象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做为最基本的技术手段。 反射技术其实很早就出现了,但一直被忽略,没有被进一步的利用。当时的反射编程方式相对于正常的对象生成方式要慢至少得10倍。现在的反射技术经过改良优化,已经非常成熟,反射方式生成对象和通常对象生成方式,速度已经相差不大了,大约为1-2倍的差距。 我们可以把IOC容器的工作模式看做是工厂模式的升华,可以把IOC容器看作是一个工厂,这个工厂里要生产的对象都在配置文件中给出定义,然后利用编程语言的的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IOC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立分隔开来,目的就是提高灵活性和可维护性。 6 IOC容器的一些产品 Sun ONE技术体系下的IOC容器有:轻量级的有Spring、Guice、Pico Container、Avalon、HiveMind;重量级的有EJB;不轻不重的有JBoss,Jdon等等。Spring框架作为Java开发中SSH(Struts、Spring、Hibernate)三剑客之一,大中小项目中都有使用,非常成熟,应用广泛,EJB在关键性的工业级项目中也被使用,比如某些电信业务。 .Net技术体系下的IOC容器有:Spring.Net、Castle等等。Spring.Net是从Java的Spring移植过来的IOC容器,Castle的IOC容器就是Windsor部分。它们均是轻量级的框架,比较成熟,其中Spring.Net已经被逐渐应用于各种项目中。 7 使用IOC框架应该注意什么 使用IOC框架产品能够给我们的开发过程带来很大的好处,但是也要充分认识引入IOC框架的缺点,做到心中有数,杜绝滥用框架。 第一、软件系统中由于引入了第三方IOC容器,生成对象的步骤变得有些复杂,本来是两者之间的事情,又凭空多出一道手续,所以,我们在刚开始使用IOC框架的时候,会感觉系统变得不太直观。所以,引入了一个全新的框架,就会增加团队成员学习和认识的培训成本,并且在以后的运行维护中,还得让新加入者具备同样的知识体系。 第二、由于IOC容器生成对象是通过反射方式,在运行效率上有一定的损耗。如果你要追求运行效率的话,就必须对此进行权衡。 第三、具体到IOC框架产品(比如:Spring)来讲,需要进行大量的配制工作,比较繁琐,对于一些小的项目而言,客观上也可能加大一些工作成本。 第四、IOC框架产品本身的成熟度需要进行评估,如果引入一个不成熟的IOC框架产品,那么会影响到整个项目,所以这也是一个隐性的风险。 我们大体可以得出这样的结论:一些工作量不大的项目或者产品,不太适合使用IOC框架产品。另外,如果团队成员的知识能力欠缺,对于IOC框架产品缺乏深入的理解,也不要贸然引入。最后,特别强调运行效率的项目或者产品,也不太适合引入IOC框架产品,象WEB2.0网站就是这种情况。

    展开全文
  • 本课件是一个动态演示数据结构算法执行过程辅助教学软件, 它可适应读者算法输入数据和过程执行控制方式不同需求, 在计算机屏幕上显示算法执行过程中数据逻辑结构或存储结构变化状况或递归算法执行...
  • 软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。对于很多人(甚至是软件项目组的技术人员)还存在对软件测试的认识误区。这进一步影响了软件测试活动的开展和...
  • 实例化需求是一组方法,它以一种开发团队有所帮助方式(理想情况下表现为可执行测试)描述计算机系统功能和行为,让不懂技术利益相关者也可以理解,即使客户需求在不断变化,它也...
  • 动人的故事就像美女一样,很容易让人忽略其真实性,多数人似乎很容易就相信了文章作者关于开源软件,关于隐私安全技术的描述。本文是一篇辟谣+科普文章,并不是针对那篇文章的作者,而是开源和安全都是IT技术的热点...
  • 首先,形式化软件开发的核心要求,就是保证软件的正确性、规范性。因此,形式化方法适用于安全性、可靠性、保密性要求极高的系统开发。 形式化方法是指将数学的方法用于解决软件工程领域的问题,主要包括建立精确...
  • 百科描述: 软件测试(英语:Software Testing), 描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出间的审核或者比较过程。 软件测试的经典定义是:在...
  • 覆盖测试是验证软件功能结构正确性...本文着重描述这类工具工作机理,以及嵌入式软件测试特殊要求,并以自主知识产权嵌入式操作系统测试为例进行说明。  关键词:嵌入式操作系统覆盖测试软件测试工具  1概
  • 软件的本质

    千次阅读 2013-07-25 10:30:57
    软件的本质我觉得有非常多的理解方法。我们可以说软件是一种秩序,是一种从混沌的真实世界中抽象出的秩序的本质。软件描述了一种正确的规律,一系列必要的约束,指导着其他软件以及大众如何正确地行动。软件是一组...
  • (1)软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出比较过程。软件测试的经典定义是:在规定的条件下程序...
  • 嵌入式软件的覆盖测试(一)软件测试摘要:覆盖测试是验证软件功能结构正确性以及查找问题的非常重要的方法和手段,它要借助一定的工具才能取得较好的效果,满足软件在质量和时间上的双重要求(纯粹的人工测试工作量大...
  •  单元测试:单元测试是对软件基本组成单位进行测试。目的是检验软件基本组成单位的正确性。  集成测试:集成测试是在软件系统集成过程中所进行测试。目的是检查软件单位之间接口是否正确。  系统测试...
  • 软件测试理解

    2020-03-20 11:53:44
    **百度百科定义:**软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出间的审核或者比较过程。 软件测试的经典定义...
  • 软件测试认识

    2019-03-23 23:33:00
    定义:软件测试(英语:software testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出间的审核或者比较过程。软件测试的经典定义是:在规定的条件下...
  • 什么是软件测试?

    2020-12-18 19:34:14
    软件测试(英语:Software Testing),描述一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程。换句话说,软件测试是一种实际输出与预期输出之间的审核或者比较过程。软件测试的经典定义是:在规定的条件下...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,257
精华内容 502
关键字:

对软件的描述正确的是