[31403] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 2655 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Wed Oct 28 14:14:22 2009

Date: Wed, 28 Oct 2009 11:14:14 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Wed, 28 Oct 2009     Volume: 11 Number: 2655

Today's topics:
        software engineering, program construction <cartercc@gmail.com>
    Re: software engineering, program construction <dannywoodz@yahoo.co.uk>
    Re: software engineering, program construction <jurgenex@hotmail.com>
    Re: software engineering, program construction <usenet@davidfilmer.com>
    Re: software engineering, program construction <cartercc@gmail.com>
    Re: software engineering, program construction <dannywoodz@yahoo.co.uk>
    Re: software engineering, program construction <douglasg.wilson@gmail.com>
    Re: software engineering, program construction <jurgenex@hotmail.com>
    Re: software engineering, program construction <jurgenex@hotmail.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Wed, 28 Oct 2009 07:00:15 -0700 (PDT)
From: ccc31807 <cartercc@gmail.com>
Subject: software engineering, program construction
Message-Id: <ba4d359d-d2e2-4d43-b02d-9987647dfa04@r5g2000yqb.googlegroups.com>

I've been writing software for about ten years, mostly Perl but also
Java, C, Python, some Lisp, Javascript, and the assorted stuff we all
pick up (SQL, HTML, XML, etc.) I've never worked on a big project, my
scripts typically running between several hundred and several thousand
LOC. I've written in a number of different styles, evolving over the
years. After reviewing some of the work I've done in the past couple
of years, rewriting a lot and revising a lot (due to changing data
requirements), I've noticed that I use a particular style.

In the past, the technology I've used seems to influence the style.
For example, at one time I was writing in C, and my Perl code
consisted of modules that acted the same as header files. When I was
writing some Lisp, my Perl code conformed a lot more to a functional
style.

Now, I don't know what I do. I've copied the guts of a program below,
and would like comments from those who might have a lot more
experience than I do.

Essentially, what I do is declare all my variables as global
variables, write the subroutines that manipulate the data, and call
the subroutines one after another. The problem domain consists of data
munging, slicing and dicing data files and preparing reports of one
kind or another.

Thoughts?

Thanks, CC.
---------------------sample of
script-----------------------------------
#declare necessary variables
my ($global1, $global2, $global3, $global4, $global5, $global6);
my (@global1, @global2, @global3);
my (%global1, %global2, %global3, %global4);

#run subroutines
&get_student_info;
&get_letter_info;
&check_site_exists;
&test_hashes;
&make_new_dir;
&create_letters;

#email to sites
my $answer = 'n';
print "Do you want to email the letters to the sites? [y|n] ";
$answer = <STDIN>;
&email_letters if $answer =~ /y/i;
exit(0);

#construct user defined functions
sub get_student_info { ...}
sub get_letter_info {... }
#etc .


------------------------------

Date: Wed, 28 Oct 2009 15:22:32 +0000
From: Danny Woods <dannywoodz@yahoo.co.uk>
Subject: Re: software engineering, program construction
Message-Id: <50bpjrpmpz.fsf@yahoo.co.uk>

ccc31807 <cartercc@gmail.com> writes:

> Essentially, what I do is declare all my variables as global
> variables, write the subroutines that manipulate the data, and call
> the subroutines one after another. The problem domain consists of data
> munging, slicing and dicing data files and preparing reports of one
> kind or another.
>
> Thoughts?

This kind of stuff is fine if it's just a script that performs a
specific task, but if it's something that you're likely to have to
revisit or modify, you'll benefit from reducing the amount of global
state you've got and instead handing required state to functions and
returning the transformed data to feed into other functions. Since
you've done some Lisp, you'll be familiar with trying to keep functions
free of side effects, which is a great thing for testing since no
function depends upon external state.  Leave the side effects (like I/O)
to tiny functions which are simple and easy to reason about.

I'm generally against cutting a script up for the sake of making it
modular unless I actually believe that I'm going to use that module
somewhere else.  If you *do* choose that route, stick the functions in a
package in a .pm file and export the interesting functions with Exporter
('perldoc Exporter' for more information).  If you want to go all object
oriented (which doesn't appear to be necessary given the size of the
script), and have a non-ancient version of Perl, have a look at Moose
rather than going down the vanilla 'perltoot' path.

Taking the additional complexity of Exporter or Moose into account,
however, and the size of the script, I'd probably just stick with the
functional refactorings.

Cheers,
Danny.


------------------------------

Date: Wed, 28 Oct 2009 08:40:22 -0700
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: software engineering, program construction
Message-Id: <v9nge5tkmsp34f0o1goa7b8ug5reaul1kf@4ax.com>

ccc31807 <cartercc@gmail.com> wrote:
>In the past, the technology I've used seems to influence the style.
>For example, at one time I was writing in C, and my Perl code
>consisted of modules that acted the same as header files. When I was
>writing some Lisp, my Perl code conformed a lot more to a functional
>style.

That is pretty typical. Most programming languages encourage a
particular programming style and if you are using that style for a while
then you will program in that style in whatever language you are using.

>Now, I don't know what I do. I've copied the guts of a program below,
>and would like comments from those who might have a lot more
>experience than I do.

Your question is not about software engineering but about good practices
and common sense  for basic programming. Software engineering deals with
how to design and modularize complex software systems and how to design
interfaces between those software components.
The difference is similar to a plumber installing a new bathroom in a
home and an engineer planning and building the water supply for a city
block or a whole city. There are rules and best practices for the
bathroom which he should follow, but it really has little to do with
engineering.

>Essentially, what I do is declare all my variables as global
>variables, 

Bad idea. Don't use globals unless you have a good reason to do so. One
principle of programming is to keep data as local as reasonable such
that code outside of your local area cannot accidently or deliberately
step on that data. This applies even to single function calls.

>write the subroutines that manipulate the data, and call
>the subroutines one after another. The problem domain consists of data
>munging, slicing and dicing data files and preparing reports of one
>kind or another.

>---------------------sample of
>script-----------------------------------
>#declare necessary variables
>my ($global1, $global2, $global3, $global4, $global5, $global6);
>my (@global1, @global2, @global3);
>my (%global1, %global2, %global3, %global4);

In addition to the comment above about use of global variables it is
very much frowned upon to use non-descriptive names like that. Large
IT-organizations even have very stringent rules how to compose variable
names (sometimes excessively so), but they always contain a descriptive
part.. 

>#run subroutines
>&get_student_info;
>&get_letter_info;
>&check_site_exists;
>&test_hashes;
>&make_new_dir;
>&create_letters;

Do you know what the '&' does? Do you really, really need that
functionality? If the answer is no to either question, then for crying
out loud drop that ampersand. Or are you stuck with Perl4 fro some odd
reason?

It appears as if your functions don't take arguments and don't return
results, either, but communicate only by side effects on global
variables. That is very poor coding style because it violates the
principle of locality.  

>#email to sites
>my $answer = 'n';
>print "Do you want to email the letters to the sites? [y|n] ";
>$answer = <STDIN>;
>&email_letters if $answer =~ /y/i;

Do you need the current @_ in 'email_letters'? If not, then why are you
passing it to the sub?

>exit(0);
>
>#construct user defined functions
>sub get_student_info { ...}
>sub get_letter_info {... }
>#etc .

If you define your subroutines at the beginning or at the end of your
code is mostly a matter of personal preference. But you should most
definitely use parameters and results to pass the necessary arguments
between sub and caller.

jue


------------------------------

Date: Wed, 28 Oct 2009 08:52:34 -0700 (PDT)
From: David Filmer <usenet@davidfilmer.com>
Subject: Re: software engineering, program construction
Message-Id: <e124660a-f7f5-43ec-86f0-ac13104fe36f@o9g2000prg.googlegroups.com>

On Oct 28, 7:00=A0am, ccc31807 <carte...@gmail.com> wrote:
> software engineering, program construction
> Thoughts?

I HIGHLY recommend the O'Reilly book, _Perl_Best_Practices_, by Dr.
Damian Conway.  Learn it, live it, love it.

FWIW, I have never used a global variable in any production program.
I always tightly scope my code (even if the variables have the same
name).  For example:

   my $dbh =3D [whatever you do to get a database handle];
   my $student_id =3D shift or die "No student ID\n";         #Not
Damian-approved, FWIW
   my %student =3D %{ get_student_info($student_id, $dbh) };

   print "The e-mail address for student $student_id is $student
{'email'}\n";

   ...

   sub get_student_info {
      my( $student_id, $dbh ) =3D @_;
      my $sql =3D qq{
         SELECT    firstname, lastname, email
         FROM      student_table
         WHERE     student_id =3D $student_id
      };
      return $dbh->selectrow_hashref( $sql );
   }

Now the sub is purely generic - you can move it to a module and call
it from any program.

Oh, and I HIGHLY recommend the O'Reilly book, _Perl_Best_Practices_,
by Damian Conway.

And, did I mention _Perl_Best_Practices_, by Damian Conway?


------------------------------

Date: Wed, 28 Oct 2009 09:08:16 -0700 (PDT)
From: ccc31807 <cartercc@gmail.com>
Subject: Re: software engineering, program construction
Message-Id: <15c47179-f797-4880-a4ba-57138be7dfb3@m20g2000vbp.googlegroups.com>

On Oct 28, 11:22=A0am, Danny Woods <dannywo...@yahoo.co.uk> wrote:
> This kind of stuff is fine if it's just a script that performs a
> specific task, but if it's something that you're likely to have to
> revisit or modify, you'll benefit from reducing the amount of global
> state you've got and instead handing required state to functions and
> returning the transformed data to feed into other functions. Since
> you've done some Lisp, you'll be familiar with trying to keep functions
> free of side effects, which is a great thing for testing since no
> function depends upon external state. =A0Leave the side effects (like I/O=
)
> to tiny functions which are simple and easy to reason about.

Many of these scripts produce standard reports that essentially are
static over long periods of time. The reason I gravitated toward
variables global to the script is because I had trouble visualizing
them when I scattered them. With all the declarations in one place, I
can see the variable names and types.

I agree with you about Lisp, but honestly, writing Perl in a
functional style was more trouble that it was worth, given the limited
scope of these kinds of scripts. FWIW, I like the fact that with Lisp
you can play with your functions on the top level and save them when
you have what you want. However, it's a different style of programming
with different kinds of tasks.

> I'm generally against cutting a script up for the sake of making it
> modular unless I actually believe that I'm going to use that module
> somewhere else. =A0If you *do* choose that route, stick the functions in =
a
> package in a .pm file and export the interesting functions with Exporter
> ('perldoc Exporter' for more information). =A0If you want to go all objec=
t
> oriented (which doesn't appear to be necessary given the size of the
> script), and have a non-ancient version of Perl, have a look at Moose
> rather than going down the vanilla 'perltoot' path.

I agree with your statement about modules. When I develop web apps, I
do indeed modularize the functions, typically writing HTML.pm, SQL.mo,
and CONSOLE.pm for the HTML, SQL, and program specific logic.

I've never written any OO Perl, although I've studied both Conway's
'OO Perl' and Schwartz's 'Learning PORM'. If I were going to write a
large OO app, I'd use Java (because Perl's lack of enforced
disciplines makes it too easy to ignore SWE practices.)

> Taking the additional complexity of Exporter or Moose into account,
> however, and the size of the script, I'd probably just stick with the
> functional refactorings.

That's one of the points of my post. Typically, I very much disfavor
cutting and pasting, but with the 'modular' subroutines, I find myself
cutting and pasting previously written subroutines between scripts. My
conscience bothers me a little bit when I do this, but for the little
bit of programming I do it's not hard to just cut and paste and it
really does lead to appropriate refactoring.

CC.


------------------------------

Date: Wed, 28 Oct 2009 16:47:54 +0000
From: Danny Woods <dannywoodz@yahoo.co.uk>
Subject: Re: software engineering, program construction
Message-Id: <507hufpirp.fsf@yahoo.co.uk>

ccc31807 <cartercc@gmail.com> writes:

> I agree with you about Lisp, but honestly, writing Perl in a
> functional style was more trouble that it was worth, given the limited
> scope of these kinds of scripts. FWIW, I like the fact that with Lisp
> you can play with your functions on the top level and save them when
> you have what you want. However, it's a different style of programming
> with different kinds of tasks.

I'm inclined to disagree here: Perl is a great language for functional
programming, as Mark Jason Dominus attests in his excellent book, Higher
Order Perl (legitimate free PDF at http://hop.perl.plover.com/#free).
Of course, you're entirely at liberty to disagree!  Some languages
(those without closures and first-class functions) make it difficult to
program functionally, but the benefits (to me) outweigh the mental
gymnastics required to think in a functional manner.

> That's one of the points of my post. Typically, I very much disfavor
> cutting and pasting, but with the 'modular' subroutines, I find myself
> cutting and pasting previously written subroutines between scripts. My
> conscience bothers me a little bit when I do this, but for the little
> bit of programming I do it's not hard to just cut and paste and it
> really does lead to appropriate refactoring.

Lots of big businesses don't like refactoring (every change to code,
however innocent, has the potential for breakage, and business-types
don't like it when the rationale is code purity).  That said, nothing
stops you from taking code that you realise you're about to cut and
paste into your script and instead paste it into a module for future
use: if you're going to re-use it once, chances are you'll think about
it again.

Cheers,
Danny.


------------------------------

Date: Wed, 28 Oct 2009 10:18:10 -0700 (PDT)
From: "DouglasG.Wilson@gmail.com" <douglasg.wilson@gmail.com>
Subject: Re: software engineering, program construction
Message-Id: <81041d46-5bc3-4d35-83ae-273e4795c61b@a31g2000yqn.googlegroups.com>

On Oct 28, 8:52=A0am, David Filmer <use...@davidfilmer.com> wrote:
>
> =A0 =A0sub get_student_info {
> =A0 =A0 =A0 my( $student_id, $dbh ) =3D @_;
> =A0 =A0 =A0 my $sql =3D qq{
> =A0 =A0 =A0 =A0 =A0SELECT =A0 =A0firstname, lastname, email
> =A0 =A0 =A0 =A0 =A0FROM =A0 =A0 =A0student_table
> =A0 =A0 =A0 =A0 =A0WHERE =A0 =A0 student_id =3D $student_id
> =A0 =A0 =A0 };
> =A0 =A0 =A0 return $dbh->selectrow_hashref( $sql );
> =A0 =A0}

I'd recommend using placeholders in that SQL (insert comment about
little Bobby Tables and security), and possibly using prepare_cached
and/or the Memoize module if that function is called a lot.

HTH,
-Doug


------------------------------

Date: Wed, 28 Oct 2009 10:27:53 -0700
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: software engineering, program construction
Message-Id: <jdvge5p8q3il9k0vbv2897tqroetc63gsp@4ax.com>

ccc31807 <cartercc@gmail.com> wrote:
>[...] The reason I gravitated toward
>variables global to the script is because I had trouble visualizing
>them when I scattered them. With all the declarations in one place, I
>can see the variable names and types.

Wrong way of thinking. Don't think in terms of variables. Instead think
in terms of information/data flow between functions.

If function f() computes a data item x, and function g() needs
information from this data item, then f() needs to return this data item
and g() needs to receive it:

	g(f(....), ....);
or
	my $thisresult = f(...);
	g($thisresult);
or 	
	f(..., $thisresult);
	g($thisresult);

jue


------------------------------

Date: Wed, 28 Oct 2009 10:30:18 -0700
From: Jürgen Exner <jurgenex@hotmail.com>
Subject: Re: software engineering, program construction
Message-Id: <qpvge51agktkj6of8c1k65euck1v443hda@4ax.com>

Danny Woods <dannywoodz@yahoo.co.uk> wrote:
>I'm inclined to disagree here: Perl is a great language for functional
>programming, as Mark Jason Dominus attests in his excellent book, Higher
>Order Perl (legitimate free PDF at http://hop.perl.plover.com/#free).
>Of course, you're entirely at liberty to disagree!  Some languages
>(those without closures and first-class functions) make it difficult to
>program functionally, but the benefits (to me) outweigh the mental
>gymnastics required to think in a functional manner.

While I agree I think the OP is nowhere near using HOFs, closures, or
functions as first-class objects. He is still struggling with the
basics.

jue


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests. 

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V11 Issue 2655
***************************************


home help back first fref pref prev next nref lref last post