[Work] soft twinning project work

project content
Course work belongs Spring 2020 Computer Software Engineering Institute (Roger Ren Jian)
Job requirements Twinning project work
My goal of this course is Design ideas and learn to use methods of software engineering, to design a high efficiency and availability, maintainability, scalability higher software.
This job helped me achieve the goals in what areas Pair programming experience, the students learn knot design ideas and coding habits, learn to communicate and adapt.
Reference material "Building of the law: modern software engineering (with Zou Yan)" and so on.
Teaching classes 005
project address https://github.com/CookieLau/intersection.git

PSP form to record

PSP2.1 Personal Software Process Stages Estimated time consuming (minutes) The actual time-consuming (minutes)
Planning plan
· Estimate • Estimate how much time this task requires 40 40
Development Develop
· Analysis · Needs analysis (including learning new technologies) 300 360
· Design Spec Generate design documents 100 100
· Design Review · Design Review (and his colleagues reviewed the design documents) 60 60
· Coding Standard · Code specifications (development of appropriate norms for the current development) 30 30
· Design · Specific design 180 200
· Coding · Specific coding 300 320
· Code Review · Code Review 180 180
· Test · Test (self-test, modify the code, submit modifications) 180 180
Reporting report
· Test Report · testing report 100 80
· Size Measurement · Computing workload 30 20
· Postmortem & Process Improvement Plan · Hindsight, and propose process improvement plan 20 10
total 1620 1680

In addition to the code, conducting needs analysis time learning new technology has also spent a lot of time, especially because before no GUI programming experience, consider using methods and modules are spending a lot of time on the search. At the same time because it is pair programming in the code review also spent a lot of time, my co-twinning partners in the conception and encoding capabilities are stronger than I am much better, so initially expand basic is based colorectal code partners for Some understand the design idea to spend some time.

Information Hiding、Interface Design与Loose Coupling

Information hiding is part of the foundation of both structured design and object-oriented design. In structured design, the notion of “black boxes” comes from information hiding. In object-oriented design, it gives rise to the concepts of encapsulation and modularity, and it is associated with the concept of abstraction.

Selected Code Complete Section 5.3

The so-called Information Hiding i.e. in different functional module package, and provides an interface used for other modules to call, so that other modules when calling to shield off the details of its internal implementation, but also to limit the caller to be modified inside the caller and improve their security. We conducted a package of core parts of the program, the various graphic Shape class is not visible to the caller. This avoids direct the caller to the operation of the Shape class, will be able to carry out its operations were limited to ensure the security implementation of the inner core.

Meanwhile, the core module for the external interface, i.e. Interaction class, which provides a series of methods to use for the call, e.g. point file is read, the number of intersections and so solving function. The main function of the command line and GUI interfaces through to complete a series of calls this function.

Loose Coupling for loose decoupled refers to the interface as possible through each module of the calls between the different modules, a module while avoiding dependence on other functions inside the other modules, so that when performing the expansion or reconstruction, modification can be prevented due to the coupling between the module and the difficulties caused by the interaction. In our project, provides an interface by using the Interaction while the shield down pattern class specific implementation details, the main function to achieve a reduction in the command line and a GUI coupled to the core module.

Calculation module interface design and implementation

Calculation module includes three classes, namely, class two graphics (vector class, class circle) Interaction and a class, which is used to calculate the interface module outward, and provide data read method of solution. On the overall relationship, create vector class and object instance of the circle class by reading files in Interaction class, while calling its related methods in solving.

  • Shape

    • Point(Vector)
      • Construction method
      • Override operator: <+ - * / ==
      • Solving the vector length: double Length (Vector A)
      • Solving inner product: double Dot (Vector A, Vector B)
      • Solving outer product: double Cross (Vector A, Vector B)
      • Seeking the angle between vectors: double Angle (Vector A, Vector B)
      • Other related functions
    • Circle
      • Construction method
      • Solving circle that coordinates: Point Circle :: point (double angle)
    • Other functions when solving for calculating an intersection of the relevant edge length
  • Interaction

    • Read the file: int Intersection :: (ifstream & in) getAllPoints

      • For lines, the stored coordinates of the first point, the first point to a second point of the point vector, and its type (line, ray, linear)
      • For round, stored center coordinates and the radius length
    • Solving the intersection of two lines: void Intersection :: solveLineLineIntersection ()

    • Solving the intersection of lines and circles: void Intersection :: solveLineCircleIntersection ()

    • Solution of circle and circle intersection: void Intersection :: solveCircleCircleIntersection ()

    • The above-described three methods similar to the overall idea of ​​the previous ideas of the individual events, except that the line and increased radiation, thus solving lines and lines, lines and circles, the intersections solved, if it is determined to be in two graphics on. According to our above for the save format presentation graphics, a calculated design point is M, the first point to determine a line, ray, a straight line is P, the second point Q, denoted t = PM · P q / PQ · PQ, so that, for a straight line, the intersection of this straight line in a certain, for radiation, requires t> = 0, for the line, requires 0 <= t <= 1. No need to code before too many changes in this way, as long as may be solved intersection about the legality of the judgment can be. It did code before largely reuse.

      bool LineIsValid(char type, double t) {
      	switch (type)
      	{
      	case 'L':
      		return true;
      	case 'R':
      		return dcmp(t) >= 0;
      	case 'S':
      		return dcmp(t - 1.0) <= 0 && dcmp(t) >= 0;
      	default:
      		return false;
      	}
      }
      

UML 图

Performance calculation module interface section Improvement

When the pair started on the other side of the students is the code first, before personal projects, I use a set of calculated intersection of de-heavy, but during the performance analysis is shown below, the main cost of in that the time set is in progress insert operation. Because when you use set inside a red-black tree maintenance, which will take time to maintain it when inserting every time, so this efficiency is relatively low.

Use code twinning students are vector, upon insertion time of consumption is very small, but just go in heavy. Finally, the time spent on the red-black tree every time performing maintenance much less. which is:

sort(intersects.begin(), intersects.end());
auto new_end = unique(intersects.begin(), intersects.end());
intersects.erase(new_end, intersects.end()); // Real Delete Duplicates

Thus, when using the same size were tested in the original program for the data length 40000 in terms of execution time exceeds one minute, while the use of Vector, and finally to re-time use about 37 seconds. As shown below:

This maximum time to time consuming method of using the above-described sort operation, and for the time occupied by the vector operation push_back rarely.

Display module calculating unit test

We calculate for parts, prepared more than 10 integrated test cases, and every method to prepare the corresponding unit test cases.

Calculating portion exception handling module described

Exception processing is divided into two parts, exception processing for reading an input and an abnormality processing when the graphics to be processed.

  • It includes the abnormal input

    • Value error, can not read: including the emergence of illegal characters, etc.

    • Two segments overlap configuration, radiation or linear

    • Ultra-wide data appear

    • Radius of the circle should be larger than 0

  • There is an overlap led to the emergence of numerous cases before the intersection of the multi-processing abnormalities include linear, rays and segments. Specific determination method and the code is as follows. In the collinear case:

    • As long as there straight line, we will be the case there will be an infinite number of intersections

    • If two rays, to carry out its direction vector dot product

      • If it is positive, it certainly has an infinite number of intersection
      • Otherwise, according to the ray origin and composition of the ray direction vector product of vectors determined, the specific code comments see below
      // 对方向向量进行点乘,如果同向则error
      double judge = Dot(vectors[i], vectors[j]);
      if (dcmp(judge) > 0) {
      	throw string("射线与射线重合");
      }
      // 不同向,用射线起点组成的向量与其中一个方向向量点乘
      Point ppv = points[j] - points[i]; // 从i指向j
      judge = Dot(ppv, vectors[i]);
      // ppv 与i的方向向量内积
      if (dcmp(judge) > 0) {
      	throw string("射线与射线重合");
      }
      else if (dcmp(judge) == 0) {
      	// 有一个交点,即射线起点
      	intersects.push_back(points[i]);
      }
      else {
      	continue;
      }
      
    • If this is the case and the straight rays, it needs to be determined in accordance with vector consisting of two end points and the starting point of the line segment rays, see below codes. Of these, we use a point and the point line represents a vector whose direction vector.

      Point rsv0 = points[j] - points[i];
      Point rsv1 = vectors[j] + points[j] - points[i];
      double judge0 = Dot(vectors[i], rsv0);
      double judge1 = Dot(vectors[i], rsv1);
      if (dcmp(judge0) < 0 && dcmp(judge1) < 0) {
      	continue;
      }
      else if ((dcmp(judge0) < 0 && dcmp(judge1) == 0) || (dcmp(judge0) == 0 && dcmp(judge1) < 0)) {
      	// 此时有唯一焦点为射线起点
      	intersects.push_back(points[i]);
      }
      else {
      	throw string("射线与线段重合");
      }
      
    • If the two segments, because we are at the determination of collinear known, so the use of this condition, which we can use the x-axis coordinates of the projected point of the determination (if parallel to the y axis, using the coordinate point in the projection of the y-axis).

      Point iSmall = (dcmp(vectors[i].x) > 0) ? points[i] : (points[i] + vectors[i]);
      Point iLarge = (dcmp(vectors[i].x) > 0) ? (points[i] + vectors[i]) : points[i];
      Point jSmall = (dcmp(vectors[j].x) > 0) ? points[j] : (points[j] + vectors[j]);
      Point jLarge = (dcmp(vectors[j].x) > 0) ? (points[j] + vectors[j]) : points[j];
      if (dcmp(vectors[i].x) == 0) {
      	// 与y轴平行,用纵坐标
      	// ...
      }
      else {
      	// 用横坐标
      	if (iSmall.x > jLarge.x || jSmall.x > iLarge.x) {
      		continue;
      	}
      	else if (iSmall.x == jLarge.x || jSmall.x == iLarge.x) {
      		// 一个的小等于另一个的大,有一个重合的点
      		if (iSmall.x == jLarge.x) {
      			intersects.push_back(iSmall);
      		}
      		else {
      			intersects.push_back(jSmall);
      		}
      	}
      	else {
      		throw string("线段与线段重合");
      	}
      }
      

When the error processing unit for testing, in a basic embodiment by writing a file, and then load the file, it is determined whether the specified error thrown. For errors introduced above, each of which give you an example:

TEST_METHOD(INPUT_0)
		{
			try {
				ifstream in("../test/errortestcase/0.txt");
				Intersection* intersect = new Intersection();
				intersect->getAllPoints(in);
				Assert::IsTrue(false);
			}
			catch (string msg) {
				Assert::AreEqual(string("在第2行,出现未识别符号"), msg);
			}
		}
2
L 1 1 1 0
P 1 2 3 4
TEST_METHOD(LL_0)
		{
			try {
				ifstream in("../test/errortestcase/5.txt");
				Intersection* intersect = new Intersection();
				intersect->getAllPoints(in);
				intersect->solveIntersection();
				Assert::IsTrue(false);
			}
			catch (string msg) {
				Assert::AreEqual(string("直线与直线或线段重合"), msg);
			}
		}
2
L 1 1 2 2
L -1 -1 0 0
TEST_METHOD(LR_0)
		{
			try {
				ifstream in("../test/errortestcase/6.txt");
				Intersection* intersect = new Intersection();
				intersect->getAllPoints(in);
				intersect->solveIntersection();
				Assert::IsTrue(false);
			}
			catch (string msg) {
				Assert::AreEqual(string("直线与直线或线段重合"), msg);
			}
		}
2
L 1 1 2 2
R -1 -1 0 0
TEST_METHOD(RR_0)
		{
			try {
				ifstream in("../test/errortestcase/7.txt");
				Intersection* intersect = new Intersection();
				intersect->getAllPoints(in);
				int ret = intersect->solveIntersection();
				Assert::AreEqual(ret, 0);
			}
			catch (string msg) {
				Assert::IsTrue(false);
				Assert::AreEqual(string("直线与直线或线段重合"), msg);
			}
		}
2
R 1 1 2 2
R 0 0 -1 -1

We each case for error handling, prepared a total of about 20 use cases for testing.

Interface module detailed design process

  • UI

    • Graphics rendering and display, using the QWidget, using QPainter plotted thereon.
    • Some buttons, such as opening a file, to solve the like, using the PushButton, which is clicked () function signals associated groove binding.
    • All graphics and display coordinates introduced using ListWidget.
    • It is shown as follows:

  • Related functions

    Open the file on solving other functions, the design content to interact with the core, it is introduced into the next section, this is mainly introduce the function associated with the drawing. The main drawing is the paintEvent () function. The main idea is to traverse for each graphic to draw specific details, see the code comments.

    void ShowPic::paintEvent(QPaintEvent *event) {
    
        QPainter painter(this);
        //painter.setPen(Qt::blue);
        QPen pp;
        pp.setWidth(2);
        pp.setColor(Qt::blue);
        pp.setStyle(Qt::DotLine);
        painter.setPen(pp);
    
        QLineF axis_X(0, y_offset, x_offset*2, y_offset);
        QLineF axis_Y(x_offset, 0, x_offset, y_offset*2);
    
        painter.drawLine(axis_X);
        painter.drawLine(axis_Y);
    
        pp.setColor(Qt::black);
        pp.setStyle(Qt::SolidLine);
        painter.setPen(pp);
        // 因为是左上角为基准点,所以要加上偏移量
        double multipleSize = 1e9;
        double x1, y1; // x1, y1 point
        double v1, v2;
        double radius;
        QLineF line;
        QRectF circle;
    
        // 画基本图形
        int type;
    
        // 遍历基本图形
        if (intersection == nullptr) {
            return;
        }
        std::vector<Point> linePoints = intersection->getPoints();
        std::vector<Vector> vectors = intersection->getVectors();
        for (int i = 0; i < linePoints.size(); ++i) {
            if (!linePoints[i].isExist) {
                continue;
            }
            type = linePoints[i].type;
            x1 = linePoints[i].x;
            y1 = linePoints[i].y;
            v1 = vectors[i].x;
            v2 = vectors[i].y;
    
            switch (type) {
            case 'L':
                // get x1, x2, v1, x2
                line.setLine(x_offset + (x1 + multipleSize * v1)*zoom, y_offset - (y1 + multipleSize * v2)*zoom, x_offset + (x1 - multipleSize * v1)*zoom, y_offset - (y1 - multipleSize * v1)*zoom);
                painter.drawLine(line);
                break;
            case 'R':
                // get x1, x2, v1, x2
                line.setLine(x_offset + (x1 + multipleSize * v1)*zoom, y_offset - (y1 + multipleSize * v2)*zoom, x_offset + x1*zoom, y_offset - y1*zoom);
                painter.drawLine(line);
                break;
            case 'S':
                // get x1, x2, v1, x2
                line.setLine(x_offset + (x1 + v1)*zoom, y_offset - (y1 + v2)*zoom, x_offset + x1*zoom, y_offset - y1*zoom);
                painter.drawLine(line);
                break;
            default:
                break;
            }
        }
        for (Circle item : intersection->getCircles()) {
            if (!item.isExist) {
                continue;
            }
            x1 = item.center.x;
            y1 = item.center.y;
            radius = item.radius;
            circle.setRect(x_offset + (x1 - radius)*zoom, y_offset - (y1 + radius)*zoom, 2*radius*zoom, 2*radius*zoom);
            painter.drawEllipse(circle);
        }
    
        // 画交点
        QPen dotPen;
        dotPen.setWidth(4);
        dotPen.setColor(Qt::red);
        painter.setPen(dotPen);
    
        // 遍历交点
        for (Point p : intersection->getIntersects()) {
            x1 = p.x;
            y1 = p.y;
            QPointF  point(x_offset + x1*zoom, y_offset - y1*zoom);
            painter.drawPoint(point);
        }
    }
    
  • function display

    Our GUI support importing from a file, delete solving and graphics, and also supports zooming the display window, you can click the + - button to zoom in and zoom out, reset can restore the default ratio.

Docking module and the computing module interface

As mentioned above, our entire project can be divided into three main sections:

  • Intersection: This section encapsulates the core core.
  • IntersectionCLI: The command core and binding, provides a command line input and output.
  • IntersectionGUI: The core combined with GUI, that provides a GUI to use.

In the GUI, an object instance of a first configuration Intersection class, then the relevant functions by calling its various methods.

ui.setupUi(this);
Intersection* intersection = new Intersection();

Then when you open the file, we use that getAllPoint()approach that combines QFileDialogpop-up window for file reads:

void IntersectionGUI::openFile(void) {
	QString filePath = QFileDialog::getOpenFileName(this, "Open File to Load", "./");
	QFileInfo fileInfo = QFileInfo(filePath);
	string file_path = fileInfo.absoluteFilePath().toStdString();
	ifstream in(file_path);
	intersection->getAllPoints(in);
	QStringList strList;
	loadShape(strList);
	ui.allShapes->addItems(strList);
}

Similarly, the acquisition result is the same, call the solveIntersection()method.

void IntersectionGUI::getResult(void) {
	int res = intersection->solveIntersection();
	ui.pointNumResult->setText(QString::number(res, 10));
}

We used directly in the drawing QPainter, and the QWconnection control. Wherein during use the display Intersection class get method, and obtain the respective set of graphics rendering.

After completion of the above, each control signal is connected to the slot function.

connect(ui.openFileButton, SIGNAL(clicked()), this, SLOT(openFile()));
connect(ui.getResult, SIGNAL(clicked()), this, SLOT(getResult()));
connect(ui.deleteShape, SIGNAL(clicked()), this, SLOT(deleteItem()));
connect(ui.draw, SIGNAL(clicked()), this, SLOT(paintItems(ui.canvas)));

Describe the process of twinning

We mainly use the Live Share and micro-channel voice VS will be pair programming.

Pair programming advantages and disadvantages

  • advantage
    • Pair programming, the two sides can conduct real-time code review, bug chance to appear in the debugging program or cooperative programming probability is lower than single people. And because we are co-designed, so the situation a person only know part of the code does not exist, two people are more clear to code for the entire program, when looking bug can be much faster.
    • Pair programming is a good opportunity to learn. When this pair, I also learned taking design ideas for each other, to learn how to improve operational efficiency through improved design, but also learned some GUI design.
  • Shortcoming
    • Because even if a person does not encode do "navigator" should always check the "driver" of the code, so it may take more time for everyone.
    • If you encounter a junction for people to find information in time, it may cause other waste of time. So, we need efficient pair programming, two people should be thinking more clearly on an issue, but for its implementation should generally be able to grasp. partner

Pair of both the advantages and disadvantages

  • Twinning partners
    • advantage
      • Design, coding capabilities are strong
      • High efficiency
      • It enables more effective communication
    • Shortcoming
      • Sometimes liver quite late (Wulian)
  • I
    • advantage
      • You can find information needed
      • Like to learn something new
      • It enables more effective communication
    • Shortcoming
      • Lack of mobility
      • Write code more slowly

Guess you like

Origin www.cnblogs.com/yjy2019/p/12557500.html