Continue to dig
In the previous article, the robustness also exists. Now it's time to handle some practical things, but we still won't go to the end. Let's take a look.
Abstract action again)
Let's ignore the spaces, asterisks, and other details. What do we see?
We only seeOne lineWhen 3 is passed in, there are 3 rows, and 4 rows when 4 is passed in. We use the getlinecontent method to represent such an abstraction. The Code is as follows:
Public String getpattern (INT linecount) {If (linecount <1) {Throw new illegalargumentexception ("the number of rows cannot be less than 1! ");} If (linecount> 20) {Throw new illegalargumentexception (" the number of rows cannot exceed 20! ");} Stringbuilder pattern = new stringbuilder (); For (INT linenumber = 0; linenumber <linecount; linenumber ++) {pattern. append (getlinecontent (linenumber);} return pattern. tostring ();}
Black box, input and output (black box, input & output)
Let's not rush to let ide generate code first. Now let's focus on this layer. Let's just think about getlinecontent as a black box with some inputs and outputs like a circuit:
Is the returned value what we want?
Is the input parameter enough for "getlinecontent" to complete its work?
The first point is certain, but is the input parameter enough?
If you use the preceding code, getlinecontent (0) is called when you obtain the content of the first row, regardless of the three or five rowsInput decides outputThe results will be the same.
However, we know that there must be more than three spaces in front of the first line in five rows, for example:
Therefore, it is clear that it is not enough to pass in only one linenumber, and the total number of linecount rows must also be passed in.
Top-down)
Now let's change the code, pass in one more parameter, and let ide generate the getlinecontent code for us, and make some simple modifications. The final result is as follows:
Public String getpattern (INT linecount) {If (linecount <1) {Throw new illegalargumentexception ("the number of rows cannot be less than 1! ");} If (linecount> 20) {Throw new illegalargumentexception (" the number of rows cannot exceed 20! ");} Stringbuilder pattern = new stringbuilder (); For (INT linenumber = 0; linenumber <linecount; linenumber ++) {pattern. append (getlinecontent (linecount, linenumber);} return pattern. tostring ();} private string getlinecontent (INT linecount, int linenumber) {// todo auto-generated method stub return NULL ;}
So, this is the first way to consider from the top, that is, the so-called top-down, next we will continue to complete this small program in this way.
Top-down is a very important way to think about and handle problems. If you are not used to this way (including writing code), it is time to try it out.
Project Progress)
In addition, the todo mark in the getpattern method can be removed. This method is complete. If the sun is about to go down, you can submit it, your project manager is also happy to see that "The amount of code is growing every day", which gives him confidence that "the project is progressing steadily ", when reporting to the project director or customer, he can show them some "progress.
When managers do not see the progress, they will feel the pressure, the pressure will be transferred to you, and you will even "volunteer to work overtime ". This kind of stress is not good except for harming our health, so you should be smart. When managers ask you, you will say to them loudly: "Today, I submitted XXX lines of code. ", Then you pat your ass and get off work on time.
The abstraction (aggregate action, again and again)
Now let's look at the getlinecontent method. After observation, we can see that the content of a row is composed of three parts, and we ignore the details again.
As shown in the preceding figure, three colors represent three parts. We use abstraction again, so we do not need to consider what parameters are passed.Pseudo Code)So quickly put the programSkeleton (skeleton)Write it out:
Private string getlinecontent (INT linecount, int linenumber) {// todo auto-generated method stub stringbuilder content = new stringbuilder (); // 1. space content. append (getfirstpart (); // 2. asterisk part content. append (getsecondpart (); // 3. content. append (getthirdpart (); Return content. tostring ();}
Now let's take a closer look at the problem of passing parameters in it:
The first method, getfirstpart, is actually about the leading space of the output, which has already been analyzed as"In the case of five rows, there must be more than three spaces in front of the first row.", So it requires two parameters.
The second method, getsecondpart, is about the output Asterisk. It can be seen that the first row is one star, and the second row is three stars, whether it is three or five rows, therefore, this is irrelevant to the total number of linecount rows. It is only related to the number of linenumbers. Therefore, you only need to input a parameter.
The third method, getthirdpart, is actually a line break, so no parameter is required.
Some people may have some questions: Is it too detailed? To what extent is abstraction and encapsulation necessary?
Overengineer)
In particular, let's take a look at the third method: getthirdpart. We know that this is actually a line feed, and a statement can be used for compaction, so there is no need to encapsulate it.
Excessive abstraction and encapsulation sometimes make the program bloated and difficult to read. If you cannot find the specific "working" Statement for half a day, the performance will also be compromised.
The syntax of line feed can be directly expressed in Java. The final result is as follows:
Private string getlinecontent (INT linecount, int linenumber) {stringbuilder content = new stringbuilder (); // 1. space content. append (getfirstpart (linecount, linenumber); // 2. asterisk part content. append (getsecondpart (linenumber); // 3. content. append (system. lineseparator (); Return content. tostring ();} private string getfirstpart (INT linecount, int linenumber) {// todo auto-generated method stub return NULL;} private string getsecondpart (INT linenumber) {// todo auto-generated method stub return NULL ;}
Lack of abstraction action)
On the other hand, we also need to be cautious about the lack of necessary encapsulation layers. Unfortunately, in many cases, we lack necessary abstraction and encapsulation.
Those who have done maintenance may have seen that super-long and super-horrible method. Some of the statements in it may even contain thousands of lines, even if they are looking for a variable definition in the method, it also reminds you of the song Jay Chou and Fei zhengqing sang, "thousands of miles away". It is not a pleasant experience to maintain such a method.
I want to tell you that even a small program is abstracted to this point, at the semantic level, there is still no excessive tendency.
Generally, if the program language can directly express the semantics we want, the encapsulation will end. Let's take a look at the first two methods. Obviously, they cannot be expressed directly, so the encapsulation can continue.
Generally, when a statement can be expressed, the abstraction and encapsulation are basically at the beginning.
At the same time, you do not have to follow these rules in a rigid manner. Sometimes, when three or two statements can be expressed, it is normal to not encapsulate them;
Sometimes, to provide clearer semantics, You can encapsulate a statement.
Of course, for this small program, you may think that it has been over-encapsulated, but we will see later that it has not yet reached the most abstract stage. Now let's not argue about this point. We will understand it later.
Divide and conquer)
What are the benefits of abstraction and encapsulation? That is what we will discuss here.
Let's review the program's writing to the present. Have we ever encountered any "obstacles?
The answer is no. You can look at the previous code, which is a simple for loop, append, and so on.
Some people may say unconvinced:
"The difficulties are all delayed by the abstraction and encapsulation of another layer, and the Code has not been written for a long time ."
Is this true? Indeed, through abstractionSuppressionThe expressions of those details are constantlyPostponedProcessing.
Imagine there was a room where clothes and items were piled up in a mess. At this time someone brought a big box and stuffed them in. Put these things"Encapsulation"After we got up, the room was naturally neat, but we knew it was still a mess in the box.
However, this metaphor is not suitable for this situation. Our abstraction is not simply to solve the problem.TransferBy means of abstraction, a major problem is constantly being solved.DecompositionSmall issues.
1. Some small problems are clear enough, and we have fixed them in this process.
For example, a line feed is output.
2. Small issues that are not clear enough have been abstracted by us.Isolated (isolate,OrIsolation)Some have seen the dawn of solutions.
For example, in the previous step, we still have two parameters passed in, but by further dividing them into new subproblems, we can see that some subproblems can be solved with only one parameter.
Therefore, abstraction does not do anything. On the contrary, abstraction does very important things.
Through abstraction, the problem is being broken down and simplified; through abstraction, we have constructed the skeleton of the program.
In this process, big problems are broken down into small problems and arranged to a proper place. They are isolated from other small problems. What can we say, "The gods return to the throne"? this is probably the meaning.
How do you deal with it? If they all stay in their positions, we can pick them up one by one.
The abstraction does not contain "event 3" (no limits for each action)
Let's continue. Can we continue to abstract it? The answer is yes. Whether it is the getfirstpart with more parameters or the getsecondpart with fewer parameters, they can be divided into two parts:
How can you calculate the number n)
Output n spaces or asterisks
The Code is as follows:
private String getFirstPart(int lineCount, int lineNumber) { int count = getElementCountOfFirstPart(lineCount, lineNumber); StringBuilder part = new StringBuilder(); for (int i = 0; i < count; i++) { part.append(" "); } return part.toString(); } private String getSecondPart(int lineNumber) { int count = getElementCountOfSecondPart(lineNumber); StringBuilder part = new StringBuilder(); for (int i = 0; i < count; i++) { part.append("*"); } return part.toString(); } private int getElementCountOfFirstPart(int lineCount, int lineNumber) { // TODO Auto-generated method stub return 0; } private int getElementCountOfSecondPart(int lineNumber) { // TODO Auto-generated method stub return 0; }
Now let's take a look at how to implement the last two methods, taking a four-row pattern as an example:
The rule in the figure is obvious. The final result is as follows:
/*** Get the number of elements in the first part of each line * @ Param linecount total number of rows * @ Param linenumber row number, starting from 0 * @ return */Public int getelementcountoffirstpart (INT linecount, int linenumber) {return linecount-linenumber-1;}/*** get the number of elements in the second part of each line * @ Param linenumber row, start from 0 * @ return */Public int getelementcountofsecondpart (INT linenumber) {return linenumber * 2 + 1 ;}
Here, I added comments to the last two methods and changed them to public. Why? The following are some explanations.
ABSTRACT To number
Some people may not quite understand why we need to abstract it so deeply. Here, there is only one statement in the last two methods. It is not enough to write it directly at the previous layer?
We can see that the last two methods return the int type, that is, a number. As we all know, numbers are a very pure and abstract concept that cannot be abstracted any more. For example, taking a single "1" is very abstract:
1 can be a potato, 1 can be a sweet potato;
1 can be a Yuan Dynasty horse, 1 can be a programmer.
Abstract: As a verb, its original meaning has the following meanings... "Extracted" means to extract and strip things.
We say that numbers are pure. Why do we need to pursue such purity? What did we remove from this process?
Coupling, decoupling, and pride (coupling, decoupling, $ % #&...)
We have all heard of a saying that "words do not show up" or "words do not show up", indicating that we use "Words" to express "meaning ", of course, "reaching" is another thing; on the other hand:
"The Speaker cares so much and forgets his words ." -- Chuang Tzu's foreign things
In the "Jin Shu · Ruan Ji Chuan", there is a description of Ruan Ji:
"You can drink and play well. ."
This is the initial meaning of the so-called "ecstasy:
It refers to its meaning, that is, the essence of its thoughts, without worrying about the form, that is, the form of expression.
The "form-to-meaning interaction" indicates that the form and meaning are often mixed, and the "meaning" must be transmitted to us through the "form.
The close relationship between the meaning to be expressed and its carrier is called "coupling" in our software field ".
This can be regarded as a type of coupling, and coupling can be understood in many other aspects.
This kind of blending of form and meaning is sometimes not a good thing, Tao Yuanming said in his "returning to death:
FromHeart serves,Sorrow and sorrow.
Back to our problem, we have been dealing with such a pattern. So what is the "shape" of this pattern? What is its "meaning?
Obviously, the asterisks (and spaces) are called "shapes", and "meaning?
It is actually the "abstract to the ultimate number" mentioned above, which is the "meaning" of the pattern ".
By detaching a "shape" from a pattern, or extracting "meaning" from the pattern, we will be "proud" to achieve the goal of decoupling.
By grasping the meaning, we don't have to stick to spaces or asterisks. We can use various shapes to see the shadows of triangles.
If you already know something about the so-called MVC (Model-View-control, Model-View-control), do you see the shadows of model and view here?
Once again, because the length is too long, this time it is still not possible to "dig to the end". The legs are a little long, and the remaining half is cut. Hold down. We will see you next time for the remaining topics.
2nd principle in Applet