4D v14.3Project Methods |
||
|
4D v14.3
Project Methods
Project Methods
Project methods are aptly named. Whereas form and object methods are bound to forms and objects, a project method is available anywhere; it is not specifically attached to any particular object of the database. A project method can have one of the following roles, depending on how it is executed and used:
These terms do not distinguish project methods by what they are, but by what they do. A menu method is a project method called from a custom menu. It directs the flow of your application. The menu method takes control—branching where needed, presenting forms, generating reports, and generally managing your database. The subroutine is a project method that can be thought of as a servant. It performs those tasks that other methods request it to perform. A function is a subroutine that returns a value to the method that called it. A process method is a project method that is called when a process is started. The process lasts only as long as the process method continues to execute. For more information about processes, see the chapter Processes. Note that a menu method attached to a menu command whose property Start a New Process is selected, is also the process method for the newly started process. An event catching method runs in a separate process as the process method for catching events. Usually, you let 4D do most of the event handling for you. For example, during data entry, 4D detects keystrokes and clicks, then calls the correct object and form methods so you can respond appropriately to the events from within these methods. In other circumstances, you may want to handle events directly. For example, if you run a lengthy operation (such as For...End for loop browsing records), you may want to be able to interrupt the operation by typing Ctrl-Period (Windows) or Cmd-Period (Macintosh). In this case, you should use an event catching method to do so. For more information, see the description of the command ON EVENT CALL. An error catching method is an interrupt-based project method. Each time an error or an exception occurs, it executes within the process in which it was installed. For more information, see the description of the command ON ERR CALL. A menu method is invoked in the Application environment when you select the custom menu command to which it is attached. You assign the method to the menu command using the Menu editor. The menu executes when the menu command is chosen. This process is one of the major aspects of customizing a database. By creating custom menus with menu methods that perform specific actions, you personalize your database. Refer to the 4D Design Reference manual for more information about the Menu editor. Custom menu commands can cause one or more activities to take place. For example, a menu command for entering records might call a method that performs two tasks: displaying the appropriate input form, and calling the ADD RECORD command until the user cancels the data entry activity. Automating sequences of activities is a very powerful capability of the programming language. Using custom menus, you can automate task sequences and thus provide more guidance to users of the database. When you create a project method, it becomes part of the language of the database in which you create it. You can then call the project method in the same way that you call 4D’s built-in commands. A project method used in this way is called a subroutine. You use subroutines to:
For example, let’s say you have a database of customers. As you customize the database, you find that there are some tasks that you perform repeatedly, such as finding a customer and modifying his or her record. The code to do this might look like this: ` Look for a customer If you do not use subroutines, you will have to write the code each time you want to modify a customer’s record. If there are ten places in your custom database where you need to do this, you will have to write the code ten times. If you use subroutines, you will only have to write it once. This is the first advantage of subroutines—to reduce the amount of code. If the previously described code was a method called MODIFY CUSTOMER, you would execute it simply by using the name of the method in another method. For example, to modify a customer’s record and then print the record, you would write this method: MODIFY CUSTOMER This capability simplifies your methods dramatically. In the example, you do not need to know how the MODIFY CUSTOMER method works, just what it does. This is the second reason for using subroutines—to clarify your methods. In this way, your methods become extensions to the 4D language. If you need to change your method of finding customers in this example database, you will need to change only one method, not ten. This is the next reason to use subroutines—to facilitate changes to your methods. Using subroutines, you make your code modular. This simply means dividing your code into modules (subroutines), each of which performs a logical task. Consider the following code from a checking account database: FIND CLEARED CHECKS ` Find the cleared checks Even for someone who doesn’t know the database, it is clear what this code does. It is not necessary to examine each subroutine. Each subroutine might be many lines long and perform some complex operations, but here it is only important that it performs its task. We recommend that you divide your code into logical tasks, or modules, whenever possible. You’ll often find that you need to pass data to your methods. This is easily done with parameters. Parameters (or arguments) are pieces of data that a method needs in order to perform its task. The terms parameter and argument are used interchangeably throughout this manual. Parameters are also passed to built-in 4D commands. In this example, the string “Hello” is an argument to the ALERT command: ALERT("Hello") Parameters are passed to methods in the same way. For example, if a method named DO SOMETHING accepted three parameters, a call to the method might look like this: DO SOMETHING(WithThis;AndThat;ThisWay) The parameters are separated by semicolons (;). In the subroutine (the method that is called), the value of each parameter is automatically copied into sequentially numbered local variables: $1, $2, $3, and so on. The numbering of the local variables represents the order of the parameters. The local variables/parameters are not the actual fields, variables, or expressions passed by the calling method; they only contain the values that have been passed. Within the subroutine, you can use the parameters $1, $2... in the same way you would use any other local variable. Note: However, in the case where you use commands that modify the value of the variable passed as parameter (for example Find in field), the parameters $1, $2, and so on cannot be used directly. You must first copy them into standard local variables (for example: $myvar:=$1). Since they are local variables, they are available only within the subroutine and are cleared at the end of the subroutine. For this reason, a subroutine cannot change the value of the actual fields or variables passed as parameters at the calling method level. For example: ` Here is some code from the method MY METHOD The alert box displayed by DO SOMETHING will read “WILLIAMS” and the alert box displayed by MY METHOD will read “williams”. The method locally changed the value of the parameter $1, but this does not affect the value of the field [People]Last Name passed as parameter by the method MY METHOD. There are two ways to make the method DO SOMETHING change the value of the field: 1. Rather than passing the field to the method, you pass a pointer to it, so you would write: ` Here is some code from the method MY METHOD Here the parameter is not the field, but a pointer to it. Therefore, within the DO SOMETHING method, $1 is no longer the value of the field but a pointer to the field. The object referenced by $1 ($1-> in the code above) is the actual field. Consequently, changing the referenced object goes beyond the scope of the subroutine, and the actual field is affected. In this example, both alert boxes will read “WILLIAMS”. For more information about Pointers, see the section Field name. 2. Rather than having the method DO SOMETHING “doing something,” you can rewrite the method so it returns a value. Thus you would write: ` Here is some code from the method MY METHOD This second technique of returning a value by a subroutine is called “using a function.” This is described in the next paragraphs. Advanced note: Parameters within the subroutine are accessible through the local variables $1, $2... In addition, parameters can be optional and can be referred to using the syntax ${...}. For more information on parameters, see the description of the command Count parameters. Data can be returned from methods. A method that returns a value is called a function. 4D or 4D Plug-in commands that return a value are also called functions. For example, the following line is a statement that uses the built-in function, Length, to return the length of a string. The statement puts the value returned by Length in a variable called MyLength. Here is the statement: MyLength:=Length("How did I get here?") Any subroutine can return a value. The value to be returned is put into the local variable $0. For example, the following function, called Uppercase4, returns a string with the first four characters of the string passed to it in uppercase: The following is an example that uses the Uppercase4 function: NewPhrase:=Uppercase4("This is good.") In this example, the variable NewPhrase gets “THIS is good.” The function result, $0, is a local variable within the subroutine. It can be used as such within the subroutine. For example, in the previous DO SOMETHING example, $0 was first assigned the value of $1, then used as parameter to the ALERT command. Within the subroutine, you can use $0 in the same way you would use any other local variable. It is 4D that returns the value of $0 (as it is when the subroutine ends) to the called method. Project methods can call themselves. For example:
This is called recursion. The 4D language fully supports recursion. Here is an example. Let’s say you have a [Friends and Relatives] table composed of this extremely simplified set of fields: 1. You can build the sentence in this way: $vsName:=Request("Enter the name:";"John") 2. You can also build it this way: $vsName:=Request("Enter the name:";"John") with the recursive function Genealogy of listed here: ` Genealogy of project method Note the Genealogy of method which calls itself. The first way is an iterative algorithm. The second way is a recursive algorithm. When implementing code for cases like the previous example, it is important to note that you can always write methods using iteration or recursion. Typically, recursion provides more concise, readable, and maintainable code, but using it is not mandatory. Some typical uses of recursion in 4D are:
Important: Recursive calls should always end at some point. In the example, the method Genealogy of stops calling itself when the query returns no records. Without this condition test, the method would call itself indefinitely; eventually, 4D would return a “Stack Full” error becuase it would no longer have space to “pile up” the calls (as well as parameters and local variables used in the method). |
PROPERTIES
Product: 4D SEE ALSO
Control Flow ARTICLE USAGE
4D Language Reference ( 4D v12.4) Inherited from : Project Methods ( 4D v11 SQL Release 6) |