2017秋高级软件工程学习总结-冯涛

学习心得

        在这个秋季学期内,我有幸选到了孟宁老师的高级软件工程,通过一个学习的学习后,我感受颇深。在这门课的学期计划里,分为线上和线下两个课程。
        线上部分除了真实课堂上老师讲授的软件工程思想外,还有一门老师自己录制的网易云课程《C编码实践》,虽然我在本科阶段已经学过C编码,但是这门课还是给我一种别样的体验。这门课并不是简单的教习C语言编程,而是通过一个个小实例将软件工程的架构思想融入到代码中,让参与者可以有更深的体验,比如后期的callback函数的设计方法,利与弊,线程安全的重要性,封装抽象的利弊等等,都给学习者一种别样的感受。在学习的过程中老师要求我们必须使用类linux的开发环境,我是相当认同的,因为开发者需要对这个开源系统有一定了解,未来在涉及后端开发时可以如鱼得水,另外,系统的开源特性也使得它十分灵活,而熟练终端也是开发者的必备技能之一。我认为这种学习方式非常的高效,也没有传统C课程那般无聊,因为它的重心根本就不是对语法的纠结,而是上升到了架构的层次。
        线下课堂主要是深入理解Vue.js及其应用开发,老师通过几次线下实验带我们体验了vue.js的生态环境和核心实现,当然,对于有些没有基础的同学,学习起来可能十分困难,但是老师也提供了很多学习资料,这只能依赖于平时多多练习了。我本人曾在本科阶段使用过vue.js1.0版本开发过网站前端,当时的使用体验不是很好,但是通过老师的这次课程后,我发现主要还是由于自己对于vue.js的理解不够透彻,对最新标准的js不熟悉,老师的深入双向绑定实验使我对于vue.js的核心实现有了很深的体会,通过自己实现一个微缩版本的vue,我们对于vue的技术细节了然于心,以后在使用vue的过程中也会有不一样的体验。
        以下是令我收获颇丰的几个实验内容:

  • Vue背后如何实现的双向数据绑定?
  • 基于vue的技术栈范例,包括vuex、axios、RESTful API (express和express-rest)、mongoose和mongoDB
  • 可重用模块的接口设计(callback函数)
  • 函数的可重入性(reentrant)及线程安全浅析
  • 子系统的可重用设计
  • 代码背后的设计思想

收获颇丰代码部分(配有我自己做的注释)

C实验部分代码:

/*
 * C实验关键代码,指针转型,搜寻节点
 * Search a LinkTableNode from LinkTable
 * int Conditon(tLinkTableNode * pNode,void * args);
 */
tLinkTableNode * SearchLinkTableNode(tLinkTable *pLinkTable, int Conditon(tLinkTableNode * pNode,void * args),void * args)
{
    if(pLinkTable == NULL || Conditon == NULL)
    {
        return NULL;
    }
    tLinkTableNode * pNode = pLinkTable->pHead;
    while(pNode != NULL)
    {    
        if(Conditon(pNode,args) == SUCCESS)
        {
            return pNode;                   
        }
        pNode = pNode->pNext;
    }
    return NULL;
}

/*
 * C实验关键代码,比较节点,配合上面函数使用
 */
int SearchCondition(tLinkTableNode * pLinkTableNode, void * args)
{
    char * cmd = (char*) args;
    tDataNode * pNode = (tDataNode *)pLinkTableNode;
    if(strcmp(pNode->cmd, cmd) == 0)
    {
        return  SUCCESS;  
    }
    return FAILURE;        
}

Vue.js实验部分代码:

// Observer.js
// 在Observer原型上增加defineReactive方法
Observer.prototype.defineReactive = function (data, key, value) {
    // dep.subs为当前元素的监听列表
    var dep = new Dep();
    Object.defineProperty(data, key, {
        enumerable: true,
        configurable: false,
        get: function () {
            console.log("intercept get:" + key);
            // 挂载监听器
            if (Dep.target) {
                //JS的浏览器单线程特性,保证这个全局变量在同一时间内,只会有同一个监听器使用
                dep.addSub(Dep.target);
            }
            return value;
        },
        set: function (newVal) {
            console.log("intercept set:" + key);
            if (newVal == value) {
                return;
            }
            //利用闭包的特性,修改value,get取值时也会变化
            //不能使用data[key]=newVal
            //因为在set中继续调用set赋值,引起递归调用
            value = newVal;
            //监视新值,此处与下方的observer(value)并不冲突
            observer(newVal);
            //通知所有监听该数据的Watcher对象
            dep.notify(newVal);
        }
    });

    //递归处理
    observer(value);
};

// Watcher.js
Watcher.prototype = {
    get: function () {
        Dep.target = this;
        /*
        this.getter是parseExpression根据exp生成的差不多这样的一个函数
        function anonymous(scope) {
            return  scope.b.c+1+scope.message;
        }

        个人理解: this.vm作为scope传入anonymous后执行的过程中会触发元素的get拦截从而将当前Dep.target绑定到元素的监听器列表中
        而每次调用update中的Watcher的get()操作时都会重新逐级访问触发元素的get操作从而完成重新注册

        这里的访问会逐级触发get,有两个作用
        1.在Watcher初始化时调用get,会逐级将自己添加到对象的监听列表中,如要监听a.b.c,则a、a.b、a.b.c的监听列表中都会添加这个Watcher
         这样做的目的是,在上级数据被修改时,也能接收到通知,如a.b = {c:1}时,原c元素被覆盖,不会发出变动通知,而b则会;
        2.同样是上述情况,新添加的c元素,需要添加监听原来c元素的Watcher到自己的监听列表中,在这个Watcher接收到b过来的通知时,会去取a.b.c的值
        与原值比较是否发生变动,
         这个取的过程中,触发新的c的get,就会添加到c的监听队列
        */
        var value = this.getter ? this.getter(this.vm) : ''; 
        Dep.target = null;
        return value;
    },
    update: function () {
        var newVal = this.get();
        if (this.value != newVal) {
            this.cb && this.cb(newVal, this.value);
            this.value = newVal;
        }
    }
};

// Compiler.js
// 视图层的直接关联处,此对象包含的方法能够将在watcher中监听到的数据层变化同步到对应的DOM节点中,真正的双向绑定实现处
var CompileUtil = {
    textUpdater: function (node, newVal, oldVal) {
        node.textContent = newVal;
    },
    handleEvent: function (node, vm, event, exp) {
        var fn = parseExpression(exp).get;
        node.addEventListener(event, function () {
            if (fn) {
                fn(vm);
            }
        });
    },
    valueUpdater: function (node, newVal, oldVal) {
        node.value = newVal ? newVal : '';
    }
};

实验报告作业链接


总结部分

        在学完整个秋高软件工程后,我个人感觉收获还是颇丰的,从上面我列举的每次实验报告和实验内容上基本可以看出。每次实验我都是非常认真完成的,并没有枯燥烦人的点,多是些有趣的挑战和体验,而具体的收获内容我已在上面的学习体验中讲述了,这里就不再赘述。
        不过我个人认为还是有些许遗憾的,上学期由于个人原因,需要备考托福,花费了大量精力在英语上的我没有太多的时间去深究高软这门课,老实说高软这门课学到多少东西取决于自己,老师只是一个引路人,孟老师给的课程范围非常之光,每个细节都可以深究,而没有太多时间去也是我唯一的遗憾吧。

                                                                                                                      软设1班 SA17225078 冯涛

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值