Four user interface design
The design of the user interface is very simple. It is to draw in the BCB control, as shown below:
Figure 3 File Split User Interface
Since most people are familiar with Winzip, they use its icon and imitate its interface, so that users don't need too much learning, so I can use this software.
I divide the entire software into a functional processing layer (previously designed) and the user interface layer (as shown above), the user interface layer does not need to know the details of the underlying flow operation, it only needs to publish commands to the FilecutMerge object. .
Writing code in the user interface to centralize processing user operations, there is the following points:
1. About the relationship between the user's main interface and the functional Filecutmerge:
The original consideration is a packet corresponding to a filecutmerge object. When you want to open a package, create one, then open another file package, and create a new one. But later found that if you create a FileCutMerge object for the user for the first time or new package, then multiplex it, complete the new and open package work through the newPackage () and openpackage () method until the program is turned off, then deleted It avoids constantly creating and destroying the FileCutMerge object, which is obviously more reasonable, which is also the scheme I used.
2. User interface encoding hierarchical principle:
My opinion is that excessive functional code is not added in the event handler of the form control, but extract it as defined as a private function of a form level.
For example, click the "Open Pack" button, I only write the following code:
Void __fastcall tMainform :: btnopenpackageClick (Tobject * Sender)
{
Openpackage ();
}
The OpenPackage () is designed as a private function of the main form TMAINFORM:
Void __fastcall tMainform :: openpackage ()
{
// ......
/ / Open the package command to the FilecutMerge object
Pfilecutmerge-> openpackage (...);
// ......
}
The advantage of this is that I can easily change the interface design without rewrite the code on a large scale, and the implementation of the File Interface Code is separated from the implementation of the function code (FileCutMerge class), and it is more easier to implement maintainability.
Five improving the robustness of the software
I mainly take the following methods:
1. When the program is basically completed, start from the bottom of the class, gradually find the pre-control (prerequisite) and post-conditionation (results) of each external interface, and then determine whether or the error should be handled.
2. Each function is guaranteed as far as possible, safe.
See the following code:
Bool __fastcall filestreamopt :: ExtractStream (TSTREAM * PSTREAM, STRING NewFileName, Int Begin, Int Size, BOOL overcover)
{
// Pick a portion from a ready-to-stream PStream to become a new stream, a new stream, and the specified file newfilename.
//
//premise:
//1. BEGIN should be less than the size of the stream
// 2. When the file exists, according to the overcover decision, if it is replaced, when it cannot be replaced (such as file read only)
/ / Give a prompt to give up the operation //
//result:
// Successfully returns true
//
//note:
// Possible causes: memory allocation and operation failure
IF (Fileexists (NewFileName) && overcover)
{
Bool ret = deletefile (newfilename);
if (RET == FALSE) / / may be read-only file
{
ShowMessage ("File: NewFileName " already exists, and cannot be deleted ");
Return False;
}
}
/ / Have the same name file and don't delete it.
IF (FileExists (NewFileName) &&! overcover)
{
ShowMessage ("File:" NewFileName "already exists");
Return False;
}
TFileStream * pnewfile;
// Call another function OpenFileStream in the same class creates stream, which will return null when it fails
Pnewfile = OpenFileStream (NewFileName, "CREATEWRITE");
// Is it successful to determine whether the call to the OpenFileStream () is successful?
IF (pnewfile == null) / / cannot create a file
Return False;
IF (pstream-> size Return False; Try { // Move to a suitable location PStream-> Seek (Begin, Sofrombeginning); //Allocate memory Void * buf = new char [size]; IF (buf == NULL) { ShowMessage ("Insufficient memory"); Return False; } Pstream-> read (buf, size); // read the contents of the buffer PNewFile-> Seek (0, Sofrombeginning); PNewFile-> Write (buf, size); // Write new flow Pnewfile-> free (); // Write file } Catch (...) { Return False; } Return True; } From this example we can see that if you join a clear and specified annotation when you write a code, you have to watch this code or debug this function. In the above example, simply use a simple try and catch statement processing error. In the big project, the type of error is more, and a complete set of error classes is generally designed. When the corresponding error occurs, "Throw error class objects;" Method to handle errors. About the error handling, in Tyson Gill, "Visual Basic 6 Advanced Programming Policy and Example - Error Coding and Terrace Technology" book is a good, although it is for VB, but it is actually suitable for any software development. Language, he thinks that a robust software should: l Prevention of all errors that can be pre-affected and prevented; such as processing that has existed in the above example l Handling all errors that can be pre-priced but not prevent; such as the processing of memory allocation failure l Capture all unpredictable errors. For example, the catch (...) statement in the previous example. 3. Ensure that the function class is called in the correct order of the user interface: People are mainly used by user interfaces such as the software, and a reasonable software is a system that receives user commands by the form, then calls the corresponding functional module to complete data processing. If a program will take the interface code and function code, it is the worst programming style. I think most software errors are caused by the operations other than programmers. These erroneous operations have triggered error calls for software modules, destroying the relationship between modules. Programmers are afraid to fall into the endless cycle of the procedure. In fact, the most effective way is to ensure its correctness in writing the underlying module, and then ensure that the user interface layer is called under the correct order. Module, if an error is often found to be due to the error of the underlying code, it will be sorrowful. For a complex user interface (form), there are multiple controls that receive user input, such as 8 buttons and a ListView control in this example, and the possibility of user operations is 9! Amount (assuming that the ListView only has an operation of selecting the object), to ensure that the software is not wrong in so many cases, the key is to ensure that you must call the function class in the correct order. For example, in this case, if the file object is not selected, delete a file is meaningless. At this time, the deleteafile command should not be issued to the FileCutmerge object in the code. See example: Void __fastcall tMainform :: btndeletefileclick (TOBJECT * SENDER) { // User does not select file objects to exit IF (ListView1-> SELCOUNT == 0) Return; // Get the selected file TITEMSTATES SELECTED = TITEMSTATES () << isselected; TLISTITEM * ITEM = listview1-> success; Int Num; / / Change the shape of the cursor telling the user that the computer is working Screen-> Cursor = CRHOURGLASS; While (item) { Num = Item-> index; / / Really delete a file Pfilecutmerge-> deleteafile (NUM); // Read the next selected file Item = listview1-> getNextItem (item, sdall, self); // Delete the file icon Listview1-> items-> delete (num); } Screen-> Cursor = crdefault; } It is not necessary to determine if the FileCutMerge object has been established (pfilecutmerge == null?), Because if the file is empty or not open the file package, then there will be no object existing in the ListView. Of course, it is possible to happen, and the write code guarantees that the correct implementation of this work is the programmer's responsibility. So, it is best to join two sentences at the beginning of the function: / / Is there a valid file package to open IF (pfilecutmerge == null) Return; In addition, this code has a shortcomings, no processing of the return value for the PfileCutmege-> deleteafile (NUM); statement. Of course, because all the code of deleteafile () is I wrote, I have handled the possible error inside this function. If it is called other people write functions, then the code to call the error handled for these functions is a must Indispensable. So, we see how important it is to hide unnecessary internal operation information to the outside world, the more functions that an object provides the outside world, the more ways to work with other objects, the more likely, the possibility of errors Big. Summary During modern software development, object-oriented technology has become a mainstream development method, which requires our programmers to constantly improve our thinking methods to keep up with the pace of the times. For now, I think an excellent programmer must establish the following ideas: 1. Design is over-encoding: Take a dog nest, you can do it immediately, and the building can not design the drawing; 2. A small procedure should also pay attention to normative: more write comments = less spend time to see code playing patch 3. Try to use the idea of software multiplexing: "Never Reinvent the Wheel." (Prades the C Bjarne Stroustrup "The C Programming Language"); 4. Specific programming techniques and technologies are important, software development ideas and methods are more important! Attachment: The examples of this article are attached to all source code and Rose 2001 modeling files, interested readers can contact me: Jinxuliang@263.net