OO课程第三次总结QWQ



调研,然后总结介绍规格化设计的大致发展历史和为什么得到了人们的重视



emmm为这个问题翻遍百度谷歌知乎也没有得到答案,那我就把自己认为最重要的两点简要说明一下吧,欢迎大家补充~

1、便于完成代码的重用交接。

  乌鸡老师上课说到,一个代码被重用的频率越高,说明设计的水平越高。好的代码一定是为他人提供便利的。而这种便利也包括引用时的确定性,调用者可以按照自己的需求和这份代码规格对照,因此确定自己使用这个接口的安全性可靠性。并且,代码规格也说明了调用者可视范围内变量的变化情况,否则这种重用将是非常非常危险的。因此,规格和代码的贴合性也变得很重要。

2、便于程序员按照真正的意愿做好代码实现和测试。

  编程语言毕竟是自然语言之外的第二种语言,人是按照思维生成的逻辑去构造代码实现的。而把要实现的内容完全放在脑子里没有进行仔细的分类梳理,在代码越来越复杂的情况下很容易产生疏漏,也就是实现有BUG。但测试也是按照代码逻辑产生惯性思维,所以很难找到思维漏洞的BUG。然后...然后你就变成了“我司雇来写专门BUG的程序员”,然后你就凉了。

  但规格是一种思维强制,强迫你按照你的预想去实现、去测试(有点像BUG树的作用原理)、去分类,只要规格和实现完全一致,最初有思维漏洞或许可以降低检查难度到规格层。



按照作业,针对自己所被报告的规格bug以及雷同的规格bug(限于 bug树的限制,对手无法上报),列一个表格分析


规格BUG类别 每个出现所对应方法的代码行数
modified不完整 78
modified不完整 145
   


分析自己规格bug的产生原因



这两个JSFbug都出现在第九次作业,而且错误原因基本都一样。这次作业因为一些特殊原因完成的特别仓促,也没有进行检查测试。产生的主要原因当然有时间方面的原因,更重要的是这两个方法的确也比较长。

当然,我的JSFbug水平咋样我心里还是很有笔数的,用自然语言也比较多。只是碰上的同学都比较友好,水平不高也没有被针对,但在三次作业中,我每次都对JSF进行优化,存在的问题选五个在下面介绍。



分别列举5个前置条件和5个后置条件的不好写法,并给出改进写法



前置条件部分:

参数范围描述不准确

例1

修改前:

/**
     * @REQUIRES:(\all int id;);
     *              (\all int X;);
     *           (\all int Y;);
     * @MODIFIES: cars_ID;carX;carY;carCredit;carStatus;hasTask;now_request;load_result;
     * @EFFECTS: Set these variables to their initial values;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public CarInformation(int id,int X,int Y) {
        this.carID=id;
        this.carX=X;
        this.carY=Y;
        this.carCredit=0;//信用值0
        this.carStatus=2;//等待服务状态
        this.hasTask=false;//没有任务
        this.now_request=null;
        this.load_result=false;
    //    System.out.println("出租车信息初始化成功");
    }

修改后:

/**
     * @REQUIRES:(\all int id;0<=id<100);
     *              (\all int X;0<=X<80);
     *           (\all int Y;0<=Y<80);
     * @MODIFIES: cars_ID;carX;carY;carCredit;carStatus;hasTask;now_request;load_result;
     * @EFFECTS: Set these variables to their initial values;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
        public CarInformation(int id,int X,int Y) {
        this.carID=id;
        this.carX=X;
        this.carY=Y;
        this.carCredit=0;//信用值0
        this.carStatus=2;//等待服务状态
        this.hasTask=false;//没有任务
        this.load_result=false;
    //    System.out.println("出租车信息初始化成功");
    }

例2

修改前:

/**
     * @REQUIRES:(\all int carX2;);
     *              (\all int carY2;);
     *              (\all ArrayList<Vertex> nei_Lis;);
     * @MODIFIES: None;
     * @EFFECTS: \result==new_aim;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public int Find_WhenCase2(int carX2, int carY2, ArrayList<Vertex> nei_Lis) {//在等待状态寻找一条流量最小的道路
        int min_flownum=100000000;
        int new_aim=-1;
        for(int i=0;i<nei_Lis.size();i++) {
            int ID=nei_Lis.get(i).getID();
            int index=transIndex(ID,carX*80+carY);
            //System.out.println("进入循环,CARX CARY"+carX+" "+carY);
            if((Flow_List[carX*80+carY][index].Get_open())&&(Flow_List[carX*80+carY][index].Get_Lastflow()<min_flownum)) {
                min_flownum=Flow_List[carX*80+carY][index].Get_Lastflow();
                new_aim=i;
            }
        }
        return new_aim;
    }

修改后:

/**
     * @REQUIRES:(\all int carX2;0<=carX2<80);
     *              (\all int carY2;0<=carY2<80);
     *              (\all ArrayList<Vertex> nei_Lis;);
     * @MODIFIES: None;
     * @EFFECTS: \result==new_aim;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public int Find_WhenCase2(int carX2, int carY2, ArrayList<Vertex> nei_Lis) {//在等待状态寻找一条流量最小的道路
        int min_flownum=100000000;
        int new_aim=-1;
        ArrayList<Integer> roadaim=new ArrayList<Integer>();
        for(int i=0;i<nei_Lis.size();i++) {
            int ID=nei_Lis.get(i).getID();
            int index=transIndex(ID,carX*80+carY);
            //System.out.println("进入循环,CARX CARY"+carX+" "+carY);
            if((Flow_List[carX*80+carY][index].Get_open())&&(Flow_List[carX*80+carY][index].Get_Lastflow()<min_flownum)) {
                min_flownum=Flow_List[carX*80+carY][index].Get_Lastflow();
                roadaim.clear();
                roadaim.add(i);
            }else if((Flow_List[carX*80+carY][index].Get_open())&&(Flow_List[carX*80+carY][index].Get_Lastflow()==min_flownum)) {
                roadaim.add(i);
            }
        }
        Random random=new Random();
        int begin=0;
        int end=roadaim.size()-1;
        new_aim=roadaim.get(random.nextInt(end - begin + 1) + begin);
        return new_aim;
    }

例3:

修改前:

/**
     * @REQUIRES:(\all int x;);
     * @MODIFIES: carX;
     * @EFFECTS: carX==x;
     * @THREAD_REQUIRES:\locked(this);
     * @THREAD_EFFECTS: \locked();
     */
    public synchronized void setcarX(int x) {this.carX=x;}

修改后:

/**
     * @REQUIRES:(\all int x;0<=x<80);
     * @MODIFIES: carX;
     * @EFFECTS: carX==x;
     * @THREAD_REQUIRES:\locked(this);
     * @THREAD_EFFECTS: \locked();
     */
    public synchronized void setcarX(int x) {this.carX=x;}

例4:

修改前:

/**
     * @REQUIRES:(\all int i;);
     * @MODIFIES: carStatus;
     * @EFFECTS: carStatus==i;
     * @THREAD_REQUIRES:\locked(this);
     * @THREAD_EFFECTS: \locked();
     */
    public synchronized void setcarStatus(int i) {this.carStatus=i;}

修改后:

/**
     * @REQUIRES:(\all int i;i=0/1/2/3;);
     * @MODIFIES: carStatus;
     * @EFFECTS: carStatus==i;
     * @THREAD_REQUIRES:\locked(this);
     * @THREAD_EFFECTS: \locked();
     */
    public synchronized void setcarStatus(int i) {this.carStatus=i;}

例5:

修改前:

/**
     * @REQUIRES:(\all int beginX;);
     *              (\all int beginY;);
     *           (\all int endX;);
     *           (\all int endY;);
     *           (\all long request_time;);
     * @MODIFIES: beginX;beginY;endX;endY;request_time;AreaX1 to AreaX4;AreaX1 to AreaX4;AreaY1 to AreaY4;
     * @EFFECTS: Set these variables to their initial values;Create area;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public Request(int beginX,int beginY,int endX,int endY,long request_time) {
        this.beginX=beginX;
        this.beginY=beginY;
        this.endX=endX;
        this.endY=endY;
        this.request_time=request_time;
        CreateArea();
    }

修改后:

/**
     * @REQUIRES:(\all int beginX;0<=beginX<80;);
     *              (\all int beginY;0<=beginY<80;);
     *           (\all int endX;0<=endX<80;);
     *           (\all int endY;0<=endY<80;);
     *           (\all long request_time;request_time>=0;);
     * @MODIFIES: beginX;beginY;endX;endY;request_time;AreaX1 to AreaX4;AreaX1 to AreaX4;AreaY1 to AreaY4;
     * @EFFECTS: Set these variables to their initial values;Create area;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public Request(int beginX,int beginY,int endX,int endY,long request_time) {
        this.beginX=beginX;
        this.beginY=beginY;
        this.endX=endX;
        this.endY=endY;
        this.request_time=request_time;
        CreateArea();
    }

后置条件:

主要是自然语言描述以及没有对输入非法参数的情况描述

例1:

修改前:

/**
     * @REQUIRES:(\all int id;0<=id<100);
     *              (\all int X;0<=X<80);
     *           (\all int Y;0<=Y<80);
     * @MODIFIES: cars_ID;carX;carY;carCredit;carStatus;hasTask;now_request;load_result;
     * @EFFECTS: Set these variables to their initial values;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
        public CarInformation(int id,int X,int Y) {
        this.carID=id;
        this.carX=X;
        this.carY=Y;
        this.carCredit=0;//信用值0
        this.carStatus=2;//等待服务状态
        this.hasTask=false;//没有任务
        this.load_result=false;
    //    System.out.println("出租车信息初始化成功");
    }

修改后:

/**
     * @REQUIRES:(\all int id;0<=id<100);
     *              (\all int X;0<=X<80);
     *           (\all int Y;0<=Y<80);
     * @MODIFIES: cars_ID;carX;carY;carCredit;carStatus;hasTask;now_request;load_result;
     * @EFFECTS: this.carID==id;this.carX==X;this.carY==Y;this.carCredit==0;this.carStatus==2;this.hasTask==false;this.load_result==false;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
        public CarInformation(int id,int X,int Y) {
        this.carID=id;
        this.carX=X;
        this.carY=Y;
        this.carCredit=0;//信用值0
        this.carStatus=2;//等待服务状态
        this.hasTask=false;//没有任务
        this.load_result=false;
    //    System.out.println("出租车信息初始化成功");
    }

例2:

修改前:

/**
     * @REQUIRES:(\all Flow_Count fl;);
     *              (\all CarInformation[] cars_info;);
     *           (\all Request_List list;);
     * @MODIFIES: flowlist;cars_info;list;
     * @EFFECTS: Set these variables to their initial values;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public MakeMap(Flow_Count fl,CarInformation[] cars_info,Request_List list,TaxiGUI g) {
        this.flowlist = fl;
        this.cars_info=cars_info;
        this.list=list;
        this.gui=g;
    }

修改后:

/**
     * @REQUIRES:(\all Flow_Count fl;);
     *              (\all CarInformation[] cars_info;);
     *           (\all Request_List list;);
     * @MODIFIES: flowlist;cars_info;list;
     * @EFFECTS: this.flowlist == fl;
        this.cars_info==cars_info;
        this.list==list;
        this.gui==g;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public MakeMap(Flow_Count fl,CarInformation[] cars_info,Request_List list,TaxiGUI g) {
        this.flowlist = fl;
        this.cars_info=cars_info;
        this.list=list;
        this.gui=g;
    }

例3:

修改前:

/**
     * @REQUIRES: A file with the correct format and content;
     * @MODIFIES: The neighbor‘s sequence of vertices and the value of the adjacency matrix;
     * @EFFECTS:Convert the values in a file to node connections;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public void CreateMap() {//根据文件创建地图
}

修改后:

/**
     * @REQUIRES: A file with the correct format and content;
     * @MODIFIES: The neighbor‘s sequence of vertices and the value of the adjacency matrix;
     * @EFFECTS:for(\all char c;c in file)
                     (c==‘1‘)==>road is opened;
                     (c==‘0‘)==>road is closed;
                     (!((c==‘0‘)&&(c==‘1‘)))==>system.exit(0);
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public void CreateMap() {//根据文件创建地图
}                

例4:

修改前:

/**
     * @REQUIRES: (\all int id;);
     * @MODIFIES: System.out;
     * @EFFECTS: find taxi by id;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public void checkBYcarID(int id) {// 通过汽车ID查询
        if (id >= 100) {
            System.out.println("ID越界,查询失败");
            return;
        }
        FileWriter fw;
        File printFile = new File(String.format("e://taxi3.txt",id));
        if (!printFile.exists()) {
            try {
                printFile.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try {
            fw = new FileWriter(printFile, true);
            @SuppressWarnings("resource")
            PrintWriter pw = new PrintWriter(fw);

            CarInformation info = car_list[id];
            System.out.println("查询时刻(100ms为基本单位):" + (long) System.currentTimeMillis() / (long) 100);
            pw.println("查询时刻(100ms为基本单位):" + (long) System.currentTimeMillis() / (long) 100);
            pw.flush();
            System.out.println("出租车当前坐标:(" + info.getcarX() + "," + info.getcarY() + ")");
            pw.println("出租车当前坐标:(" + info.getcarX() + "," + info.getcarY() + ")");
            pw.flush();
            String status = null;
            switch (info.getcarStatus()) {
            case 0:
                status = "服务状态";
                break;
            case 1:
                status = "接单状态";
                break;
            case 2:
                status = "等待状态";
                break;
            case 3:
                status = "停止状态";
                break;
            default:
                status = "非法未知状态";
                break;
            }
            System.out.println("出租车当前状态:" + status);
            pw.println("出租车当前状态:" + status);
            pw.flush();
        } catch (IOException e) {
        }
    }

修改后:

/**
     * @REQUIRES: (\all int id;);
     * @MODIFIES: System.out;
     * @EFFECTS: (0<=id<100)==>find taxi by id;
                              (!(0<=id<100))==>return;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public void checkBYcarID(int id) {// 通过汽车ID查询
        if (id >= 100) {
            System.out.println("ID越界,查询失败");
            return;
        }
        FileWriter fw;
        File printFile = new File(String.format("e://taxi3.txt",id));
        if (!printFile.exists()) {
            try {
                printFile.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try {
            fw = new FileWriter(printFile, true);
            @SuppressWarnings("resource")
            PrintWriter pw = new PrintWriter(fw);

            CarInformation info = car_list[id];
            System.out.println("查询时刻(100ms为基本单位):" + (long) System.currentTimeMillis() / (long) 100);
            pw.println("查询时刻(100ms为基本单位):" + (long) System.currentTimeMillis() / (long) 100);
            pw.flush();
            System.out.println("出租车当前坐标:(" + info.getcarX() + "," + info.getcarY() + ")");
            pw.println("出租车当前坐标:(" + info.getcarX() + "," + info.getcarY() + ")");
            pw.flush();
            String status = null;
            switch (info.getcarStatus()) {
            case 0:
                status = "服务状态";
                break;
            case 1:
                status = "接单状态";
                break;
            case 2:
                status = "等待状态";
                break;
            case 3:
                status = "停止状态";
                break;
            default:
                status = "非法未知状态";
                break;
            }
            System.out.println("出租车当前状态:" + status);
            pw.println("出租车当前状态:" + status);
            pw.flush();
        } catch (IOException e) {
        }
    }

例5:

修改前:

/**
     * @REQUIRES: (\all int status;);
     * @MODIFIES: System.out;
     * @EFFECTS: find taxi by status;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public void checkBYcarStatus(int status) {// 通过状态查询
        if (!((status == 0) || (status == 1) || (status == 2) || (status == 3))) {
            System.out.println("查询状态非法,查询失败");
            return;
        }
        for (int i = 0; i < 100; i++) {
            CarInformation info = car_list[i];
            if (info.getcarStatus() == status) {
                System.out.println("满足条件的出租车编号:" + info.getcarID());
            }
        }
    }

修改后:

/**
     * @REQUIRES: (\all int status;);
     * @MODIFIES: System.out;
     * @EFFECTS:
 ((status == 0) || (status == 1) || (status == 2) || (status == 3))==>find taxi by status;
(!((status == 0) || (status == 1) || (status == 2) || (status == 3))) ==>return;
     * @THREAD_REQUIRES:
     * @THREAD_EFFECTS:
     */
    public void checkBYcarStatus(int status) {// 通过状态查询
        if (!((status == 0) || (status == 1) || (status == 2) || (status == 3))) {
            System.out.println("查询状态非法,查询失败");
            return;
        }
        for (int i = 0; i < 100; i++) {
            CarInformation info = car_list[i];
            if (info.getcarStatus() == status) {
                System.out.println("满足条件的出租车编号:" + info.getcarID());
            }
        }
    }


按照作业分析被报的功能bug与规格bug在方法上的聚集关系



这里就不放表格了,因为测试的同学(虽然不知道是哪位仁兄)没有对我特别严格,而且实名承认自己是先写的代码后补的JSF,被报的JSFBUG和功能BUG没有对应关系,但不代表JSF的书写没有问题。

下面分析一下功能BUG中的问题,都截取自没有测试没有debug的第九次作业,共3个。

1、等待状态出租车走了回头路:

没有使用真正的随机,而是使用的循环break;使得每次选路都有一定规律,而且使用500ms清空一次流量的办法,数据访问一定的卡顿滞后。

2、等待服务状态20s未停止1s:

在输出和判断逻辑里使用了假时间,但初始为等待状态的出租车在假时间增加上有漏洞,不能按时增加到20s

3、测试接口没有正确实现:

这个Bug....实在是太低级了emmm  因为没有进行任何测试所以也没看出来。原因是逻辑表达式(!((status==0)||(status==1)||(status==2)||(status==3))) 写成了&&

所以,无论多忙,还是要好好测试,好好测试,好好测试!不然八成会凉。



归纳自己在设计规格和撰写规格的基本思路和体会



因为都是写好了代码才补的规格,所以谈不上什么太有价值的体会,只好把自己撰写jsf的主要方法简要谈一谈。

REQUIRES:我一般是光标点到变量上面,利用eclipse自带的阴影检查这个变量是方法内部声明的还是外部可见的。

MODIFIES:特别注意对非内部声明变量的赋值和return。

EFFECTS:一般就讲述什么条件下会得到什么样的返回结果。不要提及算法本身的过程。以及特别注意写明对非法输入参数的处理结果。

THREAD_RQUIRES\THREAD_EFFECTS:查看方法是否带锁。



总结



总之,OO课程虽然接近尾声了,一路遇到了很多很多友好的测试者感觉很幸运很感恩,但并不能因此掩盖自己的问题,我自己心里很明白作为一个预备程序猿和优秀的同学差距还是非常非常大,要学的东西还是太多,以后无论是自学还是正常学习课程都要多向身边比自己强的人谦虚请教,进步,永不止步。

原文地址:https://www.cnblogs.com/One-Is-All/p/9096702.html

时间: 2024-10-04 17:50:41

OO课程第三次总结QWQ的相关文章

IT行业卓越的目标与绩效管理高级研讨课程大纲 (三天论坛版)

IT行业卓越的目标与绩效管理高级研讨课程大纲 (三天论坛版) (如欲公开以下内容,或者需对大纲作专业化调整,请与本人联系确认) [课程关键词]绩效管理循环.工作计划.MBO\KPI\BSC.企业文化 [课程时长]3天(估计每天6.5小时) [课程对象]企业领导者,部门经理.其他各级经理和主管 [课程形式] 丰富新鲜的案例分析,深刻的问题解决建议,将与授课紧密结合. 授课现场需准备投影仪,电源拖板,如再配白板和白板水笔更好. 采用了电影剪辑和情境片断等多媒体培训技术,力求既紧紧扣住培训要点  又营

C语言基础课程 第三课 ADB(Android Debug Bridge)的使用

?? C语言基础课程 第三课 ADB(Android Debug Bridge)的使用 由于前面已经发布过Linux的博客了 基础班将Linux基础命令就不单独发表博客了,本节课主要就是利用adb连接手机进行一个Linux基本命令的复习.而且熟悉手机的底层运作,不用界面操作照样也能安装软件  卸载软件与pc传数据 目  录 1       将android设备通过USB连接到PC. 3 2       查看当前设备... 3 3       进入设备shell. 4 4       执行shel

金融行业卓越的目标与绩效管理高级研讨课程大纲(三天论坛版)

金融行业卓越的目标与绩效管理高级研讨课程大纲 (三天论坛版) (如欲公开以下内容,或者需对大纲作专业化调整,请与本人联系确认) [课程关键词]绩效管理循环.工作计划.MBO\KPI\BSC.企业文化 [课程时长]3天(估计每天6.5小时) [课程对象]企业领导者,部门经理.其他各级经理和主管 [课程形式] 丰富新鲜的案例分析,深刻的问题解决建议,将与授课紧密结合. 授课现场需准备投影仪,电源拖板,如再配白板和白板水笔更好. 采用了电影剪辑和情境片断等多媒体培训技术,力求既紧紧扣住培训要点  又营

交通行业卓越的目标与绩效管理高级研讨课程大纲(三天实战版)

交通行业卓越的目标与绩效管理高级研讨课程大纲 (三天实战版) (如欲公开以下内容,或者需对大纲作专业化调整,请与本人联系确认) [课程关键词]绩效管理循环.工作计划.MBO\KPI\BSC.企业文化 [课程时长]3天(估计每天6.5小时) [课程对象]企业领导者,部门经理.其他各级经理和主管 [课程形式] 演讲,问题讨论和个案分析. 问题讨论和个案分析将与授课紧密结合. 授课现场需准备投影仪,电源拖板,学员用胶贴纸,铅笔和练习纸,如再配白板和白板水笔更好. 采用了电影剪辑和情境片断等多媒体培训技

房地产行业卓越的目标与绩效管理高级研讨课程大纲 (三天论坛版)

房地产行业卓越的目标与绩效管理高级研讨课程大纲 (三天论坛版) (如欲公开以下内容,或者需对大纲作专业化调整,请与本人联系确认) [课程关键词]绩效管理循环.工作计划.MBO\KPI\BSC.企业文化 [课程时长]3天(估计每天6.5小时) [课程对象]企业领导者,部门经理.其他各级经理和主管 [课程形式] 丰富新鲜的案例分析,深刻的问题解决建议,将与授课紧密结合. 授课现场需准备投影仪,电源拖板,如再配白板和白板水笔更好. 采用了电影剪辑和情境片断等多媒体培训技术,力求既紧紧扣住培训要点  又

OO课程中IDEA相关插件的使用

写在前面 ??由于OO课程博客作业的需要分析代码的复杂度并绘制UML图,但是课件上推荐的分析工具(http://metrics.sourceforge.net )经过自己几个小时的折腾还是没有安装成功,于是我最终决定转移阵地,也就是使用IDEA的相关插件. IDEA安装 ??这个就不再多说了,具体方法自行百度,但是要注意,下面提到的插件需要IDEA Ultimate版本,社区版不支持自动绘制UML图. 插件1:UML Support ??UML Support是IDEA Ultimate版本中自

20135302魏静静——linux课程第三周实验及总结

实验:跟踪分析Linux内核的启动过程 使用gdb跟踪调试内核从start_kernel到init进程启动 使用实验楼的虚拟机打开shell cd LinuxKernel/ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img 内核启动完成后进入menu程序(<软件工程C编码实践篇>的课程项目),支持三个命令help.version和quit,您也可以添加更多的命令,对选修过<软件工程C编码实践篇>的童

【Python数据挖掘课程】 三.Kmeans聚类代码实现、作业及优化

这篇文章直接给出上次关于Kmeans聚类的篮球远动员数据分析案例,同时介绍这次作业同学们完成的图例,最后介绍Matplotlib包绘图的优化知识.        前文推荐:       [Python数据挖掘课程]一.安装Python及爬虫入门介绍       [Python数据挖掘课程]二.Kmeans聚类数据分析及Anaconda介绍        希望这篇文章对你有所帮助,尤其是刚刚接触数据挖掘以及大数据的同学,同时准备尝试以案例为主的方式进行讲解.如果文章中存在不足或错误的地方,还请海涵

麦子学院 — 产品进阶课程(三)

学完前面两个阶段的视频我相信大家对产品经理这个职位的职责肯定有了新的认识吧. 给大家说一个我之前培训的时候一个搞笑的事情吧,曾经培训的是平面设计和网页制作.开学的第二天开始用PS制作简单的 icon ,那时候我感觉自己好厉害,什么logo 都可以画出了我基础班上完就可以上班了,干嘛浪费时间嘛- - 后来学了越来越多的设计技能,胆子不是越来越大,反而不敢去面试了.因为学的更多才发现自己懂得很少. 所以小伙伴们千万不要像我这样子无知搞笑,认真的学习每一节课程,做好笔记,好脑子不如烂笔头呢! 这个ic