DynamicModule[decl, body, opts] evaluates to another DynamicModule[] with the body evaluated and values for the variables declared saved in the output. One key to understanding the behavior of the output is how the module's variables are localized. This is complicated. A second key is to realized what is left in the (new) DynamicModule[] when the body has evaluated.
How variables are localized. People who look into Module[{t},...] versus DynamicModule[{t},...] first notice the ordinary Module[] variables have the form t$nnn, where the nnn represents a module serial number (given by $ModuleNumber); and DynamicModule[] variables have the form t$$nnn where the number nnn is another serial number (not given by $ModuleNumber). But of course, it's not that simple.
Module[] variables generally are created Global`t$nnn by Module[] in the kernel. DynamicModule[] variables generally are created FE`t$$nnn by the Front End when instantiating the DynamicModule[] — though, again (!), it's not that simple.
Let inDM represent the DynamicModule[] input code, and let outDM represent the DynamicModule[] code returned by the kernel, outDM = inDM. This may be inspected by InputForm[outDM], the body of which you will note below differs from the input.
outDM =
(* inDM= *)
DynamicModule[{t = 0},
{t, Unevaluated@t, SymbolName@Unevaluated@t, Dynamic@Unevaluated@t}
];
InputForm[outDM]
(*
DynamicModule[{t = 0},
{0, Unevaluated[t], "t$24845620", Dynamic[Unevaluated[t]]},
DynamicModuleValues :> {}]
*)
outDM
(* {0, Unevaluated[t$$], "t$24845620", FE`t$$25450} *)
outDM // MakeBoxes[#, StandardForm] &
(*
DynamicModuleBox[{t$$ = 0},
RowBox[{"{", (* begin List *)
RowBox[{
"0", ",", (* 1st element *)
RowBox[{"Unevaluated", "[", "t$$", "]"}], ",", (* 2nd element *)
"\"t$24845620\"", ",", (* 3rd element *)
DynamicBox[ToBoxes[Unevaluated[t$$], StandardForm]] (* 4th element *)
}],
"}"}], (* end List *)
DynamicModuleValues :> {}]
*)
Here is what happens in effect: The body is evaluated with t being replaced with an ordinary Module[] variable t$24845620 (cf. 3rd element of list). This is set to 0, and that's the value in the output in the 1st element of the list: it's the static number 0 and not a dynamic value of a t. The two ts that remain, which are both t$24845620, in the output are replaced by t$$ (cf. 2nd, 4th elements of list). Finally, when the Front End instantiates an active dynamic module, the ts inside a Dynamic[] (4th element only) are replaced by the variable t$$25450 created for that instance. (If you copy the output and paste in a new cell, you will get a new instance and a new variable in the 4th element.)
Beware global versus local. The difference between global and local variables is usually not hard to understand. The consequences sometimes are. The symbol created in the OP for stepOnce is Global`stepOnce. The value (or definition) created lasts until the symbol is cleared or the kernel quits. In the OP's code, the definition is created when the input is evaluated, and the definition is not in the output. If the DynamicModule[] output is present in the notebook when it first opens, then the Front End will run the DynamicModule[] with stepOnce undefined. In a more complicated example, this could lead to many error messages.
Now suppose the definition of a global stepOnce were included in the dynamic module (see the Initialization option further down). Then if the output were pasted in a new cell, and a new DynamicModule were instantiated, a new definition of stepOnce would overwrite the old one. The new definition would refer to the new variable for t, and the old dynamic module would stop working properly.
OK, I think that was complicated. There are four, fairly long tech notes in the documentation, two on Dynamic[] and two on Manipulate[]. At least this was shorter. :)
Here is the OP's code with some extras and comments above snippets of code. Lines of the form (***<optional code>***) indicate variations that might be included or omitted in different combinations.
DynamicModule[
(*" Symbols initialized with ownvalues are stored
in the DynamicModule output in a list of assignments
in the first argument
"*)
{t = 0, slider = 0
(*" Local symbols initialized with downvalues are stored in
the DynamicModule output in the DynamicModuleValues
option to DynamicModule
"*)
(***, stepOnce***) (* localizes stepOnce if included *)
},
(*" If stepOnce is a Global` symbol, then its values is
not stored in the DynamicModule output
"*)
(***stepOnce[]:=(t++;);***) (* include here or in the Initialization below *)
Column[{
Grid[
(*" Dynamic@output:
slider is given a DynamicModule localization
Instantiated by the Front End
"*)
{{"Slider", Slider[Dynamic[slider], {0, 1}, ContinuousAction -> False],
Dynamic@NumberForm[slider, {4, 2}]}}, Alignment -> Left,
Spacings -> {2, 1}],
(*" not Dynamic@output:
Unevaluated t is given a Module localization
"*)
SymbolName@Unevaluated@t,
(*" not Dynamic@output:
Evaluated t becomes the current value 0
"*)
t,
Dynamic[
Refresh[
(*" Dynamic@output:
Literally present symbols t given a
DynamicModule localization; instantiated by
the Front End; symbol t does not literally
appear in `Downvalues@stepOnce`, and the t in
the downvalues is as it was when stepOnce[]
was constructed.
"*)
stepOnce[];
Row[{"t = ", t
, ", ", SymbolName@Unevaluated@t
, ", ", DownValues@stepOnce}]
, UpdateInterval -> 2, TrackedSymbols :> {}]]
}
]
(*" Executed when DynamicModule is instantiated
by the Front End; all symbols t in D.M.
instantiated with the same D.M. localization
"*)
(***, Initialization:>(stepOnce[]:=(t++;);)***) (* alternative place to defined things *)
]
Ways that work. The first two are best. The second has a global stepOnce[] defined in a way that works for all dynamic modules. The lines marked (* OMIT *) were included to illustrate what variables are being used for t.
Best (local stepOnce[]):
DynamicModule[{t = 0, slider = 0, stepOnce},
stepOnce[] := (t++;);
Column[{
Grid[{{"Slider",
Slider[Dynamic[slider], {0, 1}, ContinuousAction -> False],
Dynamic@NumberForm[slider, {4, 2}]}}, Alignment -> Left,
Spacings -> {2, 1}],
SymbolName@Unevaluated@t, (* OMIT *)
t, (* OMIT *)
Dynamic[
Refresh[stepOnce[];
Row[{"t = ", t
, ", ", SymbolName@Unevaluated@t (* OMIT *)
, ", ", DownValues@stepOnce (* OMIT *)
}]
, UpdateInterval -> 2, TrackedSymbols :> {}]]
}
]
]
Best (global stepOnce[]):
DynamicModule[{t = 0, slider = 0},
Column[{
Grid[{{"Slider",
Slider[Dynamic[slider], {0, 1}, ContinuousAction -> False],
Dynamic@NumberForm[slider, {4, 2}]}}, Alignment -> Left,
Spacings -> {2, 1}],
SymbolName@Unevaluated@t, (* OMIT *)
t, (* OMIT *)
Dynamic[
Refresh[stepOnce[t];
Row[{"t = ", t
, ", ", SymbolName@Unevaluated@t (* OMIT *)
, ", ", DownValues@stepOnce (* OMIT *)
}]
, UpdateInterval -> 2, TrackedSymbols :> {}]]
}
],
Initialization :> (ClearAll[stepOnce];
SetAttributes[stepOnce, HoldAll]; stepOnce[var_] := (var++;);)
]