• 结对编程(前后端分离)


    成员:

      巫培杰:3117004669

      易俊楷:3117004677

     一、Github项目地址

     前端代码:https://github.com/JakeYi/Paring-project

    后端代码:https://github.com/blanche789/softpairing

    二、PSP表格

    PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
    Planning 计划 20 20
    · Estimate · 估计这个任务需要多少时间 30 30
    Development 开发 1520 1550
    · Analysis · 需求分析  90 85
    · Design Spec · 生成设计文档 60 50
    · Design Review · 设计复审  35 45
    · Coding Standard · 代码规范 90 80
    · Design · 具体设计 60 60
    · Coding · 具体编码 1000 1100
    · Code Review · 代码复审 100 120
    · Test · 测试(自我测试,修改代码,提交修改) 90 110
    Reporting 报告 110 150
    · Test Report · 测试报告 60 50
    · Size Measurement · 计算工作量 40 30
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 60 70
    Total  总计 1720 1760

    三、效能分析

      生成一万道题目用的时间是766ms

            

    四、设计实现过程

      本项目是前后端分离的项目,我是负责前端的技术,前端采用的技术栈是jquery框架,简化了开发流程。前端与后端的交互是通过接口进行的,实现了真正的分工合作。

      主要流程是编写静态页面,然后逐一实现功能。

      关键函数通过四个主要的对象编写

      1. Paging类 切换分页面

      2. Subject类 获取题目和答案并放置到dom节点上

      3. Match类 进行题目的校队

      4.Download类 进行题目的下载和答案的下载

      

    五、代码说明

    1.Subject对象 获取题目和答案并放置到dom节点上

    var Subject = {
        init: function () {
            var _this = this
            this.$main = $(".content")
            this.$input = this.$main.find(".operate input")
            this.$confirm = this.$main.find(".operate a")
            this.$second = $('.second')
            this.$subject = $('#subject')
            this.$answer = $('#answer')
            this.$tTbody = this.$subject.find('.chart .manifest tbody')
            this.$aTbody = this.$answer.find('.chart .manifest tbody')
    
            this.bind()
    
        },
        bind: function () {
            var _this = this
            var string = new Array()
            this.$confirm.click(function (e) {
    
                _this.$inputValue = _this.$input[0].value
                if ((_this.$inputValue.match(/^[0-9]+,[0-9]+$/g)) == null) {
                    console.log('输入了错误的数据')
                    e.preventDefault();
                } else {
                    _this.$main.addClass('hide')
                    _this.$second.removeClass('hide')
                    _this.strs = new Array()
                    strs = _this.$inputValue.split(",")
                    _this.questionNum = parseInt(strs[0])
                    _this.numericalRange = parseInt(strs[1])
                    console.log(_this.$input)
                    console.log(_this.$inputValue)
                    console.log(_this.questionNum)
                    console.log(_this.numericalRange)
                    console.log(typeof _this.questionNum)
                    console.log(typeof _this.numericalRange)
                    _this.getData(function (result) {
                        _this.renderData(result)
    
                    })
                }
    
            })
    
            this.$tTbody.click(function () {
                // console.log('click title_tbody')
            })
            this.$aTbody.click(function () {
                // console.log('click answers_tbody')
            })
        },
        getData: function (callback) {
            var _this = this
            var allData = {
                questionNum: _this.questionNum,
                numericalRange: _this.numericalRange
            };
            $.ajax({
                    url: '/generate',
                    type: 'POST',
                    contentType: "application/json",
                    dataType: "json",
                    data: JSON.stringify(allData)
                })
                .done(function (ret) {
                    // console.log(ret)
                    callback(ret)
                })
                .fail(function (err) {
                    console.log("出错了")
                })
                .always(function () {
                    console.log("end...")
                })
        },
        renderData: function (data) {
            var _this = this
            data.forEach(function (item) {
                // console.log(item);
                var $nodeTit = _this.createTitle(item)
                var $nodeAns = _this.creatAnswer(item)
                _this.$tTbody.append($nodeTit)
                _this.$aTbody.append($nodeAns)
            })
        },
        creatAnswer: function (node) {
            var $node = $(`
            <tr>
            <td >${node.qid+1}</td>
            <td>${node.exercise}</td>
            <td class="answer">${node.answer} </td>
            </tr> `)
            return $node
        },
        createTitle: function (node) {
            var $node = $(`
            <tr class="title${node.qid+1}">
            <td >${node.qid+1}</td>
            <td>${node.exercise}</td>
            <td>
            <input type="text">
            </td>
             <td class="check_answer"></td>
            </tr>
            `)
            return $node
        }
    
    }

    2. Match类 进行题目的校队

    var Match = {
        init: function () {
            var _this = this
            this.$main = $('#subject')
            this.$second = $('#answer')
            this.$mainTbody = this.$main.find('.chart .manifest tbody')
            this.$secondTbody = this.$second.find('.chart .manifest tbody')
    
            this.$check = this.$main.find('.chart .check')
            this.bind()
        },
        bind: function () {
            var _this = this
            _this.$check.click(function () {
                _this.$text = _this.$mainTbody.find('input')
                _this.$answer = _this.$secondTbody.find('.answer')
                _this.$checkAnswer = _this.$mainTbody.find('.check_answer')
                _this.check()
                console.log('check')
            })
    
        },
        check: function () {
            var _this = this
            for (let i = 0; i < _this.$answer.length; i++) {
                console.log( _this.$answer[i].innerText)
                console.log( _this.$text[i].value)
                if (_this.$answer[i].innerText == _this.$text[i].value + ' ') {
                    _this.$checkAnswer.eq(i).html('true')
                    console.log("right")
                } else {
                    _this.$checkAnswer.eq(i).html('false')
                    console.log("error")
    
                }
            }
        }
    }

    3.Download类 进行题目的下载和答案的下载

    var Download = {
        init: function(){
            var _this = this
            this.$third = $('#function')
            this.$file = this.$third.find('.file')
            this.$answer = this.$third.find('.answer')
            this.bind()
        },
        bind: function(){
            var _this = this
            _this.$file.click(function(){
                console.log('click file')
                var xhr = new XMLHttpRequest()
                xhr.open('POST', "/download", true)
                xhr.responseType = 'blob'
    
                xhr.onload function() {
                    if (this.status === 200) {
                        var responseHeaders = xhr.getAllResponseHeaders().toLowerCase();
                        var fileName = responseHeaders.match(/w+.txt/g)
                        var blob = this.response
                        var a = document.createElement('a')
                        a.download = `${fileName}`
                        a.href = window.URL.createObjectURL(blob)
                        a.click()
                    }
                }
                xhr.send("0")
            })
            _this.$answer.click(function(){
                console.log('click answer')
                var xhr = new XMLHttpRequest()
                xhr.open('POST', "/download", true)
                xhr.responseType = 'blob'
    
                xhr.onload function() {
                    if (this.status === 200) {
                        var responseHeaders = xhr.getAllResponseHeaders().toLowerCase();
                        var fileName = responseHeaders.match(/w+.txt/g)
                        var blob = this.response
                        var a = document.createElement('a')
                        a.download = `${fileName}`
                        a.href = window.URL.createObjectURL(blob)
                        a.click()
                    }
                }
                xhr.send("1")
            })
        }
    }

    4.Paging类 切换分页面

    var Paging = {
        init: function () {
            this.$tab = $('footer>div')
            this.$page = $('main>section')
            this.bind()
            console.log("123")
        },
        bind: function () {
            var _this = this
            _this.$tab.on('click', function () {
                console.log('tab click...')
                var $this = $(this)
                var index = $this.index()
                $this.addClass('active').siblings().removeClass('active')
                _this.$page.eq(index).fadeIn().siblings().hide()
            })
        }
    }

    六、测试运行

    1.初始界面

     2. 题目

     3. 答案

     4.下载功能

     5. 校队功能

     6.下载题目

     7.下载答案

    七、项目小结

    本次项目通过真正的前后端分离,体验到实际开发中的感觉,结对开发的时候更多的是需要迁就与包容,当出现BUG的时候需要耐心的应对,不要因为一些很困难的问题就选择放弃。

    开发过程中搭档提供的接口需要很多的耦合代码,下了比较大的功夫,获取数据的时候出现了差错,跳转404页面的次数比较多,一度产生奔溃情绪,实际编码过程中也因为获取数据的时候测试使用的是假数据所以出现了和结果的偏差。

    我觉得在下次的开发过程中,如果按照产品,设计,后端,前端这样的开发路线来说,无论对于产品的质量,还是对于开发者来说,会是一个不错的选择。

    本次项目比较匆忙,如有未发现的漏洞,请大家谅解。

  • 相关阅读:
    Entity Framework6 with Oracle(可实现code first)
    ORACLE官方全托管驱动 Oracle.ManagedDataAccess 12.1.0.1.0
    C#连接Oracle数据库的四种方法
    WPF的TextBox产生内存泄露的情况
    ArcGIS客户端API中加载大量数据的几种解决办法(以Silverlight API为例)
    ArcGISDynamicMapServiceLayer 和 ArcGISTiledMapServiceLayer 区别
    ArcGIS客户端API中加载大量数据的几种解决办法
    MVVM中间接使用事件(命令)
    Tornaod框架
    跨站请求伪造CSRF
  • 原文地址:https://www.cnblogs.com/frankyi/p/11689570.html
Copyright © 2020-2023  润新知