软件构造实验一记录

软件构造实验一记录,第1张

语言:Java

开发工具:IntelliJ IDEA 2022.1社区版

1.实验目标

本次实验通过求解选自MIT和CMU三个问题,训练基本 Java 编程技能,能够利用 Java OO 开发基本的功能模块,能够阅读理解已有代码框架并根据功能需求补全代码,能够为所开发的代码编写基本的测试程序并完成测试,初步保证所开发代码的正确性。 另一方面,利用 Git 作为代码配置管理的工具,学会 Git 的基本使用方法。

 基本的 Java OO 编程

 基于 Eclipse IDE 进行 Java 编程

 基于 JUnit 的测试

 基于 Git 的代码配置管理

2.环境配置

配置过程:下载IDEA—配置JDK11—新建项目—Module中添加JUnit4

3.实验过程 3.1Magic Squares

3.1.1isLegalMagicSquare()

编写isLegalMagicSquare()函数,判断以txt形式输入的矩阵是否满足幻方要求,同时需要考虑程序应对非法输入的健壮性; 

新建MagicSquare类 

  1. 读取txt文件:
    1. 使用bufferReader按行读取,读取到temp;
    2. 使用temp.split(“\t”)将字符串分开;
    3. 使用Integer.valueOf()函数将字符串转化为数字;
  2. 读取时对输入进行判断:
    1. 非数字字符输入;
    2. 数字重复输入;
    3. 输入负数;
    4. 输入不满足幻方要求的形状
  3. 判断行列元素之和、对角线元素之和是否相等:
    1. 计算两条对角线元素之和并比较,相等则作为基值参与后面比较,否则返回false;
    2. 计算每一行列的元素和,与基值比较,相等则为幻方,否则不是; 
public static boolean isLegalMagicSquare(String fileName) throws IOException {
        File file = new File(fileName);
        FileReader Freader = new FileReader(file);
        BufferedReader buf = new BufferedReader(Freader);
        int[][] numbers = new int[Max][Max];
        boolean[] judge_repeat = new boolean[Max*Max+1];//判断是否有重复元素
        Arrays.fill(judge_repeat,false);
        String temp = null;
        String[] line = null;
        int m = 0,n = 0;
        temp = buf.readLine();
        line = temp.split("\t");
        n = line.length;
        int old_n = n;
        while(temp!=null){
            for(int i=0;i

 3.1.2generateMagicSquare()

理解并修改generateMagicSquare()的代码,使之能够把生成的幻方写到txt文件里

        1.原函数流程图

         2.异常分析​​​​​

                1.当输入为偶数时,出现数组越界异常,以输入2为例:

                第一次引用右上角元素,第二次引用左下角元素,此时i为2,恰好是阶数2的倍数,

                使得第三次引用第三行的元素,发生越界访问;

               2. 当输入为负数时,由于不允许数组大小是负数,所以出现数组大小为负数的异常

        3.函数扩展

                1.引入PrintWriter将产生的幻方数组写到txt文件中;

                2.在函数开始,对输入的阶数n进行合法化检查

public static boolean generateMagicSquare(int n) throws IOException {
        if(n<0||n%2==0){
            System.out.println("输入阶数为负数或为偶数!");
            return false;
        }
        int magic[][] = new int[n][n];
        int row = 0, col = n / 2, i, j, square = n * n;//起始为第一行中间位置
        for (i = 1; i <= square; i++) {
            magic[row][col] = i;//给元素依次赋值1,2,。。。,n*n
            if (i % n == 0)//如果i是阶的倍数,下一个元素填充在下一行
                row++;
            else {
                if (row == 0)//如果当前在第0行,下一个元素填充在最后一行
                    row = n - 1;
                else
                    row--;//其他情况下,下一个元素填充在往上一行
                if (col == (n - 1))//如果当前在最右那一列,下一个元素填充在最左那一列
                    col = 0;
                else
                    col++;//其他情况下,下一个元素填充在往右一列
            }
        }
        File file = new File("src/P1/txt/6.txt");
        PrintWriter output = new PrintWriter(file);
        for (i = 0; i < n; i++) {
            for (j = 0; j < n; j++)
                output.print(magic[i][j] + "\t");
            output.println();
        }
        output.close();
        return true;
    }

 main函数:

public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        for(int i=1;i<=5;i++){
            System.out.println(isLegalMagicSquare("src/P1/txt/"+i+".txt"));
        }
        System.out.println("输入幻方的阶数");
        int n = sc.nextInt();
    if(generateMagicSquare(n)){
        System.out.println("generateMagicSquare函数生成的幻方是否满足要求:"+isLegalMagicSquare("src/P1/txt/6.txt"));
    }
    }
3.2​​​​​​Turtle Graphics

在给定的Turtle程序中实现几个方法,然后通过这些方法,实现凸包算法、绘制图像等,并利用JUnit进行测试

注:以下方法在TurtleSoup类下

        Problem 1: Clone and import

        从GitHub上下载代码到自己的项目里,需要注意,由于目录结构变化,下载的每个class文件开头的package需要在前面添加P2.

        Problem 3: Turtle graphics and drawSquare

        实现:通过调用forward和turn函数,分别控制每次前进sideLength的距离、顺时针转动90度,重复四次即可

        Problem 5: Drawing polygons

        实现:首先实现calculateRegularPolygonAngle方法,计算正n边形的内角大小,然后类比drawSquare方法,控制每次前进距离和转动方向即可,需要注意的是,转动方向是180-内角大小

        Problem 6: Calculating Bearings

        calculateBearingToPoint实现:利用反正切函数获取两点间连线与y轴夹角,但是反正切函数返回的是-pi/2到pi/2的值,而题目要求返回沿顺时针转动的角度,所以要根据两点的位置关系对结果进行处理;

        calculateBearings实现:不断调用calculateBearingToPoint方法,记录当前点和偏转角度即可

​​​​​​​​​​​​​​        Problem 7: Convex Hulls

        实现:选择最左下方的顶点作为基准点,然后扫描其余顶点,通过calculateBearingToPoint方法选取从基准点到该点,所需转动角度最小的点,如果存在两个点,从基准点到达它们所需的转动角度一样小,则选取离基准点较远的那一个,即确保求得的凸包是最小的,将新选取的点作为基准点,重复上述过程,直到选取的点为开始的顶点为止。

​​​​​​​​​​​​​​        Problem 8: Personal art

        实现:利用上面的函数绘制正五边形,然后通过forward和turn绘制螺旋线

TurtleSoup类代码 

package P2.turtle;

import java.util.*;

public class TurtleSoup {

    /**
     * Draw a square.
     * @param turtle     the turtle context
     * @param sideLength length of each side
     */
    public static void drawSquare(Turtle turtle, int sideLength) {
        float angle = 90;
        for (int i = 0; i < 4; i++) {
            turtle.forward(sideLength);
            turtle.turn(angle);
        }
    }

    /**
     * Determine inside angles of a regular polygon.
     */
    public static double calculateRegularPolygonAngle(int sides) {
        double angle = 1.0 * (180 * sides - 360) / sides;
        return angle;
    }

    /**
     * Determine number of sides given the size of interior angles of a regular polygon.
     */
    public static void drawRegularPolygon(Turtle turtle, int sides, int sideLength) {
        double angle = 180.0 - calculateRegularPolygonAngle(sides);
        for (int i = 0; i < sides; i++) {
            turtle.forward(sideLength);
            turtle.turn(angle);
        }
    }

    /**
     * Given the current direction, current location, and a target location, calculate the Bearing
     */
    public static double calculateBearingToPoint(double currentBearing, int currentX, int currentY,
                                                 int targetX, int targetY) {
        if(currentBearing < 0||currentBearing >= 360){
            throw new IllegalArgumentException("input out of bound!");
        }
        double tan = 1.0 * (targetX - currentX) / (targetY - currentY);
        double rawBearing = Math.toDegrees(Math.atan(tan));
        if (targetX - currentX > 0 && targetY - currentY < 0)
            rawBearing += 180;
        else if (targetX - currentX < 0 && targetY - currentY >= 0)
            rawBearing += 360;
        else if (targetX - currentX <= 0 && targetY - currentY < 0)
            rawBearing += 180;
        if (rawBearing < currentBearing)
            return rawBearing - currentBearing + 360;
        return rawBearing - currentBearing;
    }

    /**
     * Given a sequence of points, calculate the Bearing adjustments needed to get from each point
     */
    public static List calculateBearings(List xCoords, List yCoords) {
        List angles = new ArrayList<>();
        double cb = 0;
        int x0 = xCoords.get(0);
        int y0 = yCoords.get(0);
        int x, y;
        for (int i = 1; i < xCoords.size(); i++) {
            x = xCoords.get(i);
            y = yCoords.get(i);
            angles.add(calculateBearingToPoint(cb, x0, y0, x, y));
            cb = (cb + angles.get(i - 1)) % 360;
            x0 = x;
            y0 = y;
        }
        return angles;
    }

    /**
     * Given 2 points, compute the distance of the points
     */
    public static double getDistance(Point a, Point b) {
        double X = Math.abs(b.x() - a.x());
        double Y = Math.abs(b.y() - a.y());
        return Math.sqrt(X * X + Y * Y);
    }

    /**
     * Given a set of points, compute the convex hull, the smallest convex set that contains all the points
     */
    public static Set convexHull(Set points) {
        if (points.size() <= 2)
            return points;
        Set ConvexHull = new HashSet();
        Iterator it = points.iterator();
        Point start = it.next();
        Point current = start;
        double angle = 0, current_angle = 0;
        for (Point p : points) {
            if (p.x() < start.x() || (p.x() == start.x() && p.y() < start.y()))
                start = p;
        }
        ConvexHull.add(start);
        Point base = start;
        while (true) {
            double min_angle = Double.MAX_VALUE;
            for (Point p : points) {
                if (p == base)
                    continue;
                angle = calculateBearingToPoint(current_angle, (int) base.x(), (int) base.y(), (int) p.x(), (int) p.y());
                if (angle < min_angle) {
                    current = p;
                    min_angle = angle;
                } else if (angle == min_angle) {
                    double dis1 = getDistance(base, p);
                    double dis2 = getDistance(base, current);
                    if (dis1 > dis2) {
                        current = p;
                    }
                }
            }
            if (current == start)
                break;
            else {
                ConvexHull.add(current);
                current_angle = min_angle;
                base = current;
            }
        }
        return ConvexHull;
    }

    /**
     * Draw your personal, custom art.
     */
    public static void drawPersonalArt(Turtle turtle) {
        int Size = 400, Step = 1, Densi = 1, ColorNum = 6,sideLength = 100;
        for(int i=0;i<3;i++){
            for(int j=1;j<=Size;j++){
                switch (j % ColorNum) {
                    case 0:
                        turtle.color(PenColor.BLUE);
                        break;
                    case 1:
                        turtle.color(PenColor.CYAN);
                        break;
                    case 2:
                        turtle.color(PenColor.GREEN);
                        break;
                    case 3:
                        turtle.color(PenColor.YELLOW);
                        break;
                    case 4:
                        turtle.color(PenColor.RED);
                        break;
                    case 5:
                        turtle.color(PenColor.MAGENTA);
                        break;
                }
                drawRegularPolygon(turtle,5,sideLength);
                turtle.turn(9);
            }
            sideLength += 100;
        }
        for (int i = 1; i <= Size; i++) {
            switch (i % ColorNum) {
                case 0:
                    turtle.color(PenColor.BLUE);
                    break;
                case 1:
                    turtle.color(PenColor.CYAN);
                    break;
                case 2:
                    turtle.color(PenColor.GREEN);
                    break;
                case 3:
                    turtle.color(PenColor.YELLOW);
                    break;
                case 4:
                    turtle.color(PenColor.RED);
                    break;
                case 5:
                    turtle.color(PenColor.MAGENTA);
                    break;
            }
            turtle.forward(Step * i);
            turtle.turn(360 / ColorNum + Densi);
        }
    }

        /**
         * Main method.
         */
        public static void main (String[] args){
            DrawableTurtle turtle = new DrawableTurtle();
            drawPersonalArt(turtle);
            turtle.draw();
        }
}

​​​​​​​​​​​​​​        Submitting

        如何通过Git提交当前版本到GitHub上你的Lab1仓库:通过git status查看改变的文件,将改变的文件add到原有git仓库中,再用git commit提交,最后git push到GitHub的远程仓库上。

​​​​​​​3.3Social Network

设计Person类存储人的信息,设计FriendshipGraph类实现简单的社交网络,包括添加顶点、添加边和求任意两顶点的距离

        1.设计/实现FriendshipGraph类

        成员变量:顶点序号num、顶点表verTable和邻接表adjTable。顶点序号为int类型,在新增顶点之后自动加一;顶点表是HashMap类型,即每个Person对象对应一个顶点序号;邻接表是HashMap>类型,对每一个顶点保存与其邻接的顶点

        主要方法:

       public void addVertex(Person person):

        将person加入顶点表中,如果出现重名则抛出异常,终止程序

      public void addEdge(Person startPerson,Person endPerson):

        在图中加入边:startPerson->endPerson,即在startPerson对应顶点的链表中加入endPerson对应的定点序号,如果已存在则不加入,如果参数对应的顶点不在图中则抛出异常;

        public int getDistance(Person startPerson,Person targetPerson):

        计算图中两个顶点间距离,两顶点相同返回0,两顶点之间没有路径返回-1。使用广度优先搜索算法,维护一个队列存放待搜索的顶点,取出队列第一个元素,遍历它的邻接表,如果出现目标顶点则停止,不出现则把遍历到的顶点加入队列,重复上述过程,直至队列为空。需要注意的是,需要记录队列中每个元素距离开始顶点的距离,这里使用node内部类定义一个新的数据类型,类似于C语言结构体的用法。

FriendshipGraph类代码: 

package P3;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;

import static java.lang.System.exit;

public class FriendshipGraph {

    private class node{
        int vertex;
        int distance;

        public node(int vertex,int distance) {
            this.vertex = vertex;
            this.distance = distance;
        }
    }
    private int num;
    private HashMap verTable;
    private HashMap> adjTable;

    public FriendshipGraph() {
        this.num = 1;
        this.verTable = new HashMap<>();
        this.adjTable = new HashMap<>();
    }
    public void addVertex(Person person){
        for(Person p: verTable.keySet()){
            if(p.getName() == person.getName()){
                throw new IllegalArgumentException("The graph already exists a identical name");
            }
        }
        verTable.put(person,this.num);
        adjTable.put(this.num,new LinkedList<>());
        this.num++;
    }
    public void addEdge(Person startPerson,Person endPerson){
        if(!verTable.containsKey(startPerson)||!verTable.containsKey(endPerson)){
            throw new IllegalArgumentException("The graph doesn't exist such vertex please add first");
        }
        int startNum = verTable.get(startPerson);
        int endNum = verTable.get(endPerson);
        LinkedList listOfStart = adjTable.get(startNum);
        for(Integer i:listOfStart){
            if(i == endNum){
                System.out.println("不需要重复添加边");
                return;
            }
        }
        listOfStart.add(endNum);
    }
    public int getDistance(Person startPerson,Person targetPerson){
        if(!verTable.containsKey(startPerson)||!verTable.containsKey(targetPerson)){
            throw new IllegalArgumentException("The start vertex or target vertex doesn't exist");
        }
        int start = verTable.get(startPerson);
        int target = verTable.get(targetPerson);
        if(start == target)
            return 0;
        int distance = 0;
        boolean[] visited = new boolean[verTable.size()+1];
        Queue Q = new LinkedList<>();
        LinkedList curList;
        Q.offer(new node(start,distance));
        while(!Q.isEmpty()){
            node current = Q.poll();
            visited[current.vertex] = true;
            curList = adjTable.get(current.vertex);
            if(!curList.isEmpty()){
                for(int i:curList){
                    if(i == target){
                        return current.distance+1;
                    }
                    else if(!visited[i]){
                        Q.offer(new node(i,distance+1));
                    }
                }
            }
        }
        return -1;
    }

    public HashMap getVerTable() {
        return verTable;
    }

    public HashMap> getAdjTable() {
        return adjTable;
    }

    public static void main(String[] args){
        FriendshipGraph graph = new FriendshipGraph();
        Person rachel = new Person("Rachel");
        Person ross = new Person("Ross");
        Person ben = new Person("Ben");
        Person kramer = new Person("Kramer");
        graph.addVertex(rachel);
        graph.addVertex(ross);
        graph.addVertex(ben);
        graph.addVertex(kramer);
        graph.addEdge(rachel, ross);
        graph.addEdge(ross, rachel);
        graph.addEdge(ross, ben);
        graph.addEdge(ben, ross);
        //should print 1
        System.out.println(graph.getDistance(rachel, ross));
        //should print 2
        System.out.println(graph.getDistance(rachel, ben));
        //should print 0
        System.out.println(graph.getDistance(rachel, rachel));
        //should print -1
        System.out.println(graph.getDistance(rachel, kramer));
    }
}

        2.设计/实现Person类​​​​​​​

        Person类包括name一个成员变量、getName方法来获取实例的name属性。

package P3;

public class Person {
    private String name;
    public Person(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

         3.设计/实现客户端代码main()

                借鉴实验指导书上的客户端代码

​​​​​​​        4.设计/实现测试用例

                主要对三个方法进行测试:

                public void addVertex(Person person):

                1.加入重复顶点,测试是否抛出异常

                2.加入10000个顶点,测试程序对大量数据的适用性

                public void addEdge(Person startPerson,Person endPerson):

                1.输入不存在的顶点,测试是否抛出异常

                2.加入10000条边,测试程序对大量数据的适用性

                public int getDistance(Person startPerson,Person targetPerson):

                1.输入不存在的顶点,测试是否抛出异常

                2.输入每个顶点至多一条边的图

                3.输入存在顶点有多条边的图

                JUnit测试代码(test.P3目录下):

package P3;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.util.*;

import static org.junit.Assert.*;

public class FriendshipGraphTest {
    /**
     * Testing Strategy:
     * addVertex:
     * 两个顶点人名相同
     * 添加大量顶点
     * addEdge:
     * 为不存在的定点添加边
     * 添加大量的边
     * getDistance:
     * 输入中含有不存在的顶点
     * 每个顶点至多一条边
     * 存在顶点有多条边
     */

    @Rule
    public ExpectedException expectedEx = ExpectedException.none();

    //covers 违反“ Each person has a unique name ”的约束条件
    @Test
    public void testAddDuplicatedVertex() throws IllegalArgumentException{
        expectedEx.expect(IllegalArgumentException.class);
        expectedEx.expectMessage("The graph already exists a identical name");
        FriendshipGraph graph = new FriendshipGraph();
        Person rachel = new Person("Rachel");
        Person ross = new Person("Rachel");
        Person ben = new Person("Ben");
        Person kramer = new Person("Kramer");
        graph.addVertex(rachel);
        graph.addVertex(ross);
        graph.addVertex(ben);
        graph.addVertex(kramer);
    }
    //covers 添加10000个顶点
    @Test
    public void testAddManyVertex(){
        FriendshipGraph graph = new FriendshipGraph();
        for(int i=0;i<9999;i++){
            Person test = new Person("test"+ i);
            graph.addVertex(test);
        }
        Person test = new Person("test9999");
        graph.addVertex(test);
        HashMap result = graph.getVerTable();
        assertEquals(Integer.valueOf(10000),result.get(test));
    }
    //covers 给不存在的顶点添加边
    @Test
    public void testAddEdgeForNonExistVertex() throws IllegalArgumentException{
        expectedEx.expect(IllegalArgumentException.class);
        expectedEx.expectMessage("The graph doesn't exist such vertex please add first");
        FriendshipGraph graph = new FriendshipGraph();
        Person rachel = new Person("Rachel");
        Person ross = new Person("Ross");
        Person ben = new Person("Ben");
        Person kramer = new Person("Kramer");
        graph.addVertex(rachel);
        graph.addVertex(ross);
        graph.addVertex(ben);
        graph.addEdge(rachel,kramer);
    }
    //covers 给一个顶点添加10000条边
    @Test
    public void testAddManyEdge(){
        FriendshipGraph graph = new FriendshipGraph();
        Person base = new Person("Base");
        graph.addVertex(base);
        for(int i=1;i<10001;i++){
            Person test = new Person("test"+ i);
            graph.addVertex(test);
            graph.addEdge(base,test);
        }
        LinkedList test = new LinkedList<>();
        for(int i=2;i<10002;i++){
            test.add(Integer.valueOf(i));
        }
        HashMap> res = graph.getAdjTable();
        LinkedList result = res.get(Integer.valueOf(1));
        assertEquals(test,result);
    }
    //covers 待搜索的人名不存在
    @Test
    public void testGetNonExistDistance() throws IllegalArgumentException{
        expectedEx.expect(IllegalArgumentException.class);
        expectedEx.expectMessage("The start vertex or target vertex doesn't exist");
        FriendshipGraph graph = new FriendshipGraph();
        Person rachel = new Person("Rachel");
        Person ross = new Person("Ross");
        Person ben = new Person("Ben");
        Person kramer = new Person("Kramer");
        Person johnson = new Person("Johnson");
        graph.addVertex(rachel);
        graph.addVertex(ross);
        graph.addVertex(ben);
        graph.addVertex(kramer);
        graph.addEdge(rachel,kramer);
        graph.getDistance(rachel,johnson);
    }
    //covers 所有的边都是单向的
    @Test
    public void testGetDistance(){
        FriendshipGraph graph = new FriendshipGraph();
        Person rachel = new Person("Rachel");
        Person ross = new Person("Ross");
        Person ben = new Person("Ben");
        Person kramer = new Person("Kramer");
        Person johnson = new Person("Johnson");
        graph.addVertex(rachel);
        graph.addVertex(ross);
        graph.addVertex(ben);
        graph.addVertex(kramer);
        graph.addVertex(johnson);
        graph.addEdge(rachel,ross);
        graph.addEdge(ross,ben);
        graph.addEdge(ben,kramer);
        assertEquals(1,graph.getDistance(rachel,ross));
        assertEquals(3,graph.getDistance(rachel,kramer));
        assertEquals(-1,graph.getDistance(kramer,rachel));
        assertEquals(-1,graph.getDistance(johnson,ben));
    }
    //covers 每个顶点至多一条边
    @Test
    public void testGetDistance2(){
        FriendshipGraph graph = new FriendshipGraph();
        Person rachel = new Person("Rachel");
        Person ross = new Person("Ross");
        Person ben = new Person("Ben");
        Person kramer = new Person("Kramer");
        Person johnson = new Person("Johnson");
        graph.addVertex(rachel);
        graph.addVertex(ross);
        graph.addVertex(ben);
        graph.addVertex(kramer);
        graph.addVertex(johnson);
        graph.addEdge(rachel,ross);
        graph.addEdge(rachel,ben);
        graph.addEdge(rachel,kramer);
        graph.addEdge(kramer,johnson);
        assertEquals(1,graph.getDistance(rachel,ross));
        assertEquals(2,graph.getDistance(rachel,johnson));
        assertEquals(-1,graph.getDistance(kramer,rachel));
        assertEquals(-1,graph.getDistance(johnson,ben));
    }
}
 4.实验过程中收获的经验、教训、感想          4.1.实验过程中收获的经验和教训

        通过这次实验,我对Java编程的基础知识有了更深刻的理解,对面向对象的编程思想有了更深刻的认识,同时,我学会了对Java数据类型如HashMap、LinkedList的使用,初步了解了JUnit单元测试、git版本控制等新知识。与此同时,我通过本次实验清晰认识到对程序进行单元测试的重要性,比如编写问题3的getDistance时,一开始的实现过程是:每从队列中取一个元素就把距离+1,这样对于一个顶点有多条边的情况,计算错误,而这个错误正是通过编写测试用例发现的,在今后的实验过程中,要提前想好测试用例,及时对程序进行测试,做到防患于未然。

        4.2.针对以下方面的感受

        1.Java编程语言是否对你的口味?与你熟悉的其他编程语言相比,Java有何优势和不足?

        刚接触Java语言有些许的不习惯,对面向对象的编程思想认识不足。个人认为,与C语言相比,Java语言的优点在于取消复杂的指针 *** 作,提供了许多方便快捷的数据类型,不足在于编译运行速度稍慢。

        2.关于Eclipse或IntelliJ IDEA,它们作为IDE的优势和不足;

IDE

优势

不足

Eclipse

开源、免费、占用内存较少、一个页面可以打开多个项目

界面较为传统、代码提示不够智能

IntelliJ IDEA

界面美观、代码提示智能

专业版需要付费、占用内存较多、一个页面只能打开一个项目

        3.关于Git和GitHub,是否感受到了它在版本控制方面的价值;

        使用git可以轻松实现版本控制,修改过的程序git会自动检查、提交新版本时只需处理修改过的程序即可;使用GitHub托管平台可以轻松实现代码获取和提交,便于多人协作。

        4.关于CMU和MIT的作业,你有何感受;

        内容很新颖、很有新意,在锻炼编程能力的同时解决了实际问题。

        5.关于本实验的工作量、难度、deadline;

        工作量适中,deadline也合适,不过对于自己这样基础较薄弱的同学,难度稍大, 自己会课下多加练习,以满足课程要求。

        6.关于初接触“软件构造”课程;

        接触这门课之前,认为它是关于如何开发软件的,即教会我们写软件,但上了两堂课之后,发现这门课并不仅仅涵盖写软件这样浅层次的知识,更多的是在试图传授思维,让我们对软件开发进行具体实践的同时,能在宏观上把握一个软件的整体。

水平有限,欢迎批评指正~ 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/794871.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)