Hungarian notation (and any derivation thereof) has its cons and pros. I understand that there are people who like it, and that there are people opposed to it. Some would argue that Perl code doesn't need any kind of Hungarian notation, because we already have our sigils that mark $variable as a scalar, @variable as an array, and %variable as a hash.
However, a scalar is a flexible thing. I don't have to tell you it doesn't just hold strings and numbers, it can also hold a multitude of different kind of references. In my experience, in can be helpful to make it obvious what sort of data you expect to be in a scalar, so that you can see at all times what you're dealing with. I usually do that by adding a short two or three letter suffix to a variable name (and in rare occasions, just one or even four letters).
a) Non-object references
$child_nodes_ar ar: Array Reference $attributes_hr hr: Hash Reference $callback_cr cr: Code (or Callback) reference $next_node_it it: Iterator $report_fhi fhi: File Handle for Input *1 $summary_fho fho: File Handle for Output *1 $time_re re: Regexp
*1: it could be argued that file handles are object references, but there aren't many situations I use them that way, hence I list them as non-object references.
b) Object references
In applications where you have only one database, you could easily store the database handle in $dbh, but what if your application has to talk to multiple databases, for instance when you have to write code to glue a Wordpress webshop to an external bookkeeping system. Names such as $wordpress_dbh and $bookkeeping_dbh clearly indicate which database each dbh refers to.
It doesn't end just there. I like to use suffixes for many kinds of object types:
$yesterday_dt dt: Date::Time $website_ht ht: HTML::Template $website_tt tt: Template Toolkit $sessions_slct: slct: IO::Select $www_sck sck: a socket of kinds (most likely IO::Socket)
b.1) GUI components
Some conventions I find myself using when programming a GUI around a program:$settings_mw mw: Tk Main Window $login_tl tl: Tk TopLevel window $process_but: but: button $trim_chk: chk: checkbox $markup_frm: frm: frame $encode_opt: opt: radio button
c) Non-reference variables
Even plain non-reference scalars could do with some kind of clarifications as to what they're supposed to contain, or how they're used:
$input_buf buf: a buffer $valid_b b: used as a boolean $entities_cnt cnt: count, or ammount $log_f f: a format for sprintf() or printf() $article_id id: a unique identifier $element_idx idx: an index $session_ser ser: a serialized object $long_name_out out: output value for the current subroutine
c.1) Content format
$report_html html: content in html format $report_json json: content in json format $report_txt txt: content in plain text format $report_yaml yaml: content in yaml format $report_xml xml: content in xml format
c.2) Different kind of arrays
There are also cases where I like to suffix my arrays to indicate their use:
@nodes_s s: stack (so I should only use push, pop, and $nod +e_s[-1] on it) @nodes_q q: a queue (so I should only use push, shift, and +$node_q on it) @nodes_out out: output value for the current subroutine
I find sticking to such suffixes greatly improve readability of my code. When I come back to a piece of code because I discovered a bug or want to improve the way something works, I can dive straight into some relevant subroutine and see what each variable is supposed to be. Note that none of these suffixes tell me whether a scalar is a string or an int or what-have-you: those details should be clear by the main name of the variable, if they're not obvious by the suffix (for example, a $..._idx will hardly ever be a string ;) ).
Another thing, which is only tangentially relevant, is that I always use underscores_to_separate words and suffixes in a variable name, and never camelCasing. That saves me from wondering, "what was it again? $myAwesomeScalar, $MyAwesomeScalar, or $my_awesome_scalar?" It will always be the latter.