From c615f5b99ffe106249c749969ee450b2ed224882 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Tue, 10 Mar 2015 19:41:18 -0500 Subject: [PATCH] Document the use and reasoning of goto in step-26. --- examples/step-26/step-26.cc | 84 ++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/examples/step-26/step-26.cc b/examples/step-26/step-26.cc index 452d39dcf1..2ba5c01932 100644 --- a/examples/step-26/step-26.cc +++ b/examples/step-26/step-26.cc @@ -370,7 +370,14 @@ namespace Step26 cell = triangulation.begin_active(min_grid_level); cell != triangulation.end_active(min_grid_level); ++cell) cell->clear_coarsen_flag (); - + // These two loops above are slightly different but this is easily + // explained. In the first loop, instead of calling + // triangulation.end() we may as well have called + // triangulation.end_active(max_grid_level). The two + // calls should yield the same iterator since iterators are sorted + // by level and there should not be any cells on levels higher than + // on level max_grid_level. In fact, this very piece + // of code makes sure that this is the case. // As part of mesh refinement we need to transfer the solution vectors // from the old mesh to the new one. To this end we use the @@ -419,6 +426,22 @@ namespace Step26 // out mesh (we choose the zero function here, which of course we could // do in a simpler way by just setting the solution vector to zero). We // also output the initial time step once. + // + // @note If you're an experienced programmer, you may be surprised + // that we use a goto statement in this piece of code! + // goto statements are not particularly well liked any + // more since Edsgar Dijkstra, one of the greats of computer science, + // wrote a letter in 1968 called "Go To Statement considered harmful" + // (see here). + // The author of this code subscribes to this notion whole-heartedly: + // goto is hard to understand. In fact, deal.II contains + // virtually no occurrences: excluding code that was essentially + // transcribed from books and not counting duplicated code pieces, + // there are 3 locations in about 600,000 lines of code; we also + // use it in 4 tutorial programs, in exactly the same context + // as here. Instead of trying to justify the occurrence here, + // let's first look at the code and we'll come back to the issue + // at the end of function. template void HeatEquation::run() { @@ -570,6 +593,65 @@ start_time_iteration: } } } +// Now that you have seen what the function does, let us come back to the issue +// of the goto. In essence, what the code does is +// something like this: +// @code +// void run () +// { +// initialize; +// start_time_iteration: +// for (timestep=1...) +// { +// solve timestep; +// if (timestep==1 && not happy with the result) +// { +// adjust some data structures; +// goto start_time_iteration; // simply try again +// } +// postprocess; +// } +// } +// @endcode +// Here, the condition "happy with the result" is whether we'd like to keep +// the current mesh or would rather refine the mesh and start over on the +// new mesh. We could of course replace the use of the goto +// by the following: +// @code +// void run () +// { +// initialize; +// while (true) +// { +// solve timestep; +// if (not happy with the result) +// adjust some data structures; +// else +// break; +// } +// postprocess; +// +// for (timestep=2...) +// { +// solve timestep; +// postprocess; +// } +// } +// @endcode +// This has the advantage of getting rid of the goto +// but the disadvantage of having to duplicate the code that implements +// the "solve timestep" and "postprocess" operations in two different +// places. This could be countered by putting these parts of the code +// (sizable chunks in the actual implementation above) into their +// own functions, but a while(true) loop with a +// break statement is not really all that much easier +// to read or understand than a goto. +// +// In the end, one might simply agree that in general +// goto statements are a bad idea but be pragmatic +// and state that there may be occasions where they can help avoid +// code duplication and awkward control flow. This may be one of these +// places. // @sect3{The main function} -- 2.39.5