Saving "1" in Set-hash is considered harmful
I know that using it is considered harmful is considered harmful , but it is bad; almost as bad as the rampant use of goto .
Ok, I pondered this a bit in a few comments, but I think I need a complete answer to demonstrate this problem.
Suppose we have a daemon process that provides inventory management for a store that sells widgets.
my @items = qw( widget thingy whozit whatsit ); my @items_in_stock = qw( widget thingy ); my %in_stock; my @in_stock(@items_in_stock) = (1) x @items_in_stock; #initialize all keys to 1 sub Process_Request { my $request = shift; if( $request eq REORDER ) { Reorder_Items(\@items, \%in_stock); } else { Error_Response( ILLEGAL_REQUEST ); } } sub Reorder_Items{ my $items = shift; my $in_stock = shift; # Order items we do not have in-stock. for my $item ( @$items ) { Reorder_Item( $item ) if not exists $in_stock->{$item}; } }
The tool is wonderful, it automatically stores items in stock. Very well. Now the boss requests automatically created catalogs of goods in the warehouse. Therefore, we modify Process_Request() and add directory generation.
sub Process_Request { my $request = shift; if( $request eq REORDER ) { Reorder_Items(\@items, \%in_stock); } if( $request eq CATALOG ) { Build_Catalog(\@items, \%in_stock); } else { Error_Response( ILLEGAL_REQUEST ); } } sub Build_Catalog { my $items = shift; my $in_stock = shift; my $catalog_response = ''; foreach my $item ( @$items ) { $catalog_response .= Catalog_Item($item) if $in_stock->{$item}; } return $catalog_response; }
When testing, Build_Catalog () works fine. Hooray, we go live with the app.
Unfortunately. For some reason nothing is ordered, the company runs out of everything.
The Build_Catalog() routine adds keys to %in_stock , so Reorder_Items() now sees everything as it is in stock and never makes an order.
Using Hash :: Util lock_hash can help prevent accidental hash modifications. If we blocked %in_stock before calling 'Build_Catalog () `, we would get a fatal error and never go with the error.
Thus, it is better to check for the presence of keys, rather than the truth of your set-hash values. If you use existence as a signifier, do not set your values ββto "1" because this will mask the errors and make it difficult to track them. Using lock_hash can help catch these issues.
If you must verify the validity of the values, do it in each case.