> Programming Considerations > Developing CPLEX Applications > Tips for Successful Application Development > Program with a View toward Maintenance and Modifications

Good programming practices save development time and make an application easier to understand and modify. Tips for Successful Application Development outlines ILOG programming conventions in developing ILOG CPLEX. In addition, the following programming practices are recommended.

Comment Your Code

Comments, written in mixed upper- and lower-case, will prove useful to you at a later date when you stare at code written months ago and try to figure out what it does. They will also prove useful to ILOG staff, should you need to send ILOG your application for technical support.

Write Readable Code

Follow conventional formatting practices so that your code will be easier to read, both for you and for others. Use fewer than 80 characters per line. Put each statement on a separate line. Use white space (for example, space, blank lines, tabs) to distinguish logical blocks of code. Display compound loops with clearly indented bodies. Display if statements like combs; that is, align if and else in the same column and then indent the corresponding block. Likewise, it is a good idea to indent the body of compound statements, loops, and other structures distinctly from their corresponding headers and closing brackets. Use uniform indentation (for example, three to five spaces). Put at least one space before and after each relational operator, as well as before and after each binary plus (+) and minus (-). Use space as you do in normal English.

Avoid Side-Effects

It is good idea to minimize side-effects by avoiding expressions that produce internal effects. In C, for example, try to avoid expressions of this form:

a = c + (d =  e*f);  /* A BAD IDEA */

where the expression assigns the values of d and a.

Don't Change Argument Values

A user-defined function should not change the values of its arguments. Do not use an argument to a function on the left-hand side of an assignment statement in that function. Since C and C++ pass arguments by value, treat the arguments strictly as values; do not change them inside a function.

Declare the Type of Return Values

Always declare the return type of functions explicitly. Though C has a "historical tradition" of making the default return type of all functions int, it is a good idea to declare explicitly the return type of functions that return a value, and to use void for procedures that do not return a value.

Manage the Flow of Your Code

Use only one return statement in any function. Limit your use of break statements to the inside of switch statements. In C, do not use continue statements and limit your use of goto statements to exit conditions that branch to the end of a function. Handle error conditions in C++ with a try/catch block and in C with a goto statement that transfers control to the end of the function so that your functions have only one exit point.

In other words, control the flow of your functions so that each block has one entry point and one exit point. This "one way in, one way out" rule makes code easier to read and debug.

Localize Variables

Avoid global variables at all costs. Code that exploits global variables invariably produces side-effects which in turn make the code harder to debug. Global variables also set up peculiar reactions that make it difficult to include your code successfully within other applications. Also global variables preclude multithreading unless you invoke locking techniques. As an alternative to global variables, pass arguments down from one function to another.

Name Your Constants

Scalars - both numbers and characters - that remain constant throughout your application should be named. For example, if your application includes a value such as 1000, create a constant with the #define statement to name it. If the value ever changes in the future, its occurrences will be easy to find and modify as a named constant.

Choose Clarity First, Efficiency Later

Code first for clarity. Get your code working accurately first so that you maintain a good understanding of what it is doing. Then, once it works correctly, look for opportunities to improve performance.

Debug Effectively

Using Diagnostic Routines for Debugging, contains tips and guidelines for debugging an application that uses the ILOG CPLEX Callable Library. In that context, a symbolic debugger as well as other widely available development tools are quite helpful to produce error-free code.

Test Correctness, Test Performance

Even a program that has been carefully debugged so that it runs correctly may still contain errors or "features" that inhibit its performance with respect to execution speed, memory use, and so forth. Just as the ILOG CPLEX Interactive Optimizer can aid in your tests for correctness, it can also help you improve performance. It uses the same routines as the Component Libraries; consequently, it requires the same amount of time to solve a problem created by a callable-library application. Use CPXwriteprob, specifying a file type of SAV, to create a binary representation of the problem object of your application. Then read that representation into the Interactive Optimizer, and solve it there. If your application sets parameters, use the same settings in the Interactive Optimizer. If you find that your application takes significantly longer to solve the problem than does the Interactive Optimizer, then you can probably improve the performance of your application. In such a case, look closely at issues like memory fragmentation, unnecessary compiler options, inappropriate linker options, and programming practices that slow the application without causing incorrect results (such as operations within a loop that should be outside the loop).