Previous Page
Next Page

10.16. Progress Indicators

Always convey the progress of long non-interactive operations within interactive applications.

As annoying as it is to sit like a mushroom whilst some mute program waits for your unprompted input, it's even more frustrating to tentatively start typing something into an interactive program, only to discover that the program is still busy initializing, or calculating, or connecting to a remote device:

    
    # Initialize from any config files...
    for my $possible_config ( @CONFIG_PATHS ) {
        init_from($possible_config);
    }

    # Connect to remote server...
    my $connection;
    TRY:
    for my $try (1..$MAX_TRIES) {
        # Retry connection with increasingly tolerant timeout intervals...
        $connection = connect_to($REMOTE_SERVER, { timeout => fibonacci($try) });
        last TRY if $connection;
    }
    croak "Can't contact server ($REMOTE_SERVER)"
        if !$connection;

    # Interactive portion of the program starts here...
    while (my $cmd = prompt($prompt_str, -fail_if=>$QUIT)) {
        remote_execute($connection, $cmd)
            or carp "Unknown command: $cmd";
    }

It's much betterand not much more onerousto give an active indication that an interactive program is busy doing something non-interactive:


    

    # Initialize from any config files...
print {*STDERR} 'Initializing...'; for my $possible_config ( @CONFIG_PATHS ) { print {*STDERR} '.'; init_from($possible_config); } print {*STDERR} "done\n";
# Connect to remote server...
print {*STDERR} 'Connecting to server...'; my $connection; TRY: for my $try (1..$MAX_TRIES) { print {*STDERR} '.'; $connection = connect_to($REMOTE_SERVER, { timeout => fibonacci($try) }); last TRY if $connection; } croak "Can't contact server ($REMOTE_SERVER)" if not $connection; print {*STDERR} "done\n";
# Interactive portion of the program starts here...

Better still, factor those messages out into a set of utility subroutines:


    

    # Utility subs to provide progress reporting...
sub _begin_phase { my ($phase) = @_; print {*STDERR} "$phase..."; return; } sub _continue_phase { print {*STDERR} '.'; return; } sub _end_phase { print {*STDERR} "done\n"; return; } _begin_phase('Initializing'); for my $possible_config ( @CONFIG_PATHS ) { _continue_phase( ); init_from($possible_config); } _end_phase( ); _begin_phase('Connecting to server'); my $connection; TRY: for my $try (1..$MAX_TRIES) { _continue_phase( ); $connection = connect_to($REMOTE_SERVER, { timeout => fibonacci($try) }); last TRY if $connection; } croak "Can't contact server ($REMOTE_SERVER)" if not $connection; _end_phase( );
# Interactive portion of the program starts here...

Note that some of the comments have been dispensed with, as the _begin_phase( ) calls adequately document each non-interactive code paragraph.

    Previous Page
    Next Page