'cpan'에 해당되는 글 5건

  1. 2010/12/13 카페 방문자 정보 긁어오기
  2. 2008/08/29 DBD::mysql 모듈 설치
  3. 2008/06/05 GeoIP (1)
  4. 2008/05/09 perl의 Net::FTP 모듈을 이용한 ftp 전송
  5. 2008/03/17 perlmodstyle
다음카페 같은데 보면 방문자 정보를 10개씩 뿌려주는데 그거 긁어오는거..
스크립트를 cron 에 등록시키고 매 1분마다 실행시킨다.
데이터를 긁어와 특정한 곳에 파일 또는 DB로 저장한다.
url 정보가 바뀌진 않지만 만약, 디자인 레이아웃이 바뀌면 말짱 도루묵.. 고로 그때그때 맞게 수정해야 된다.
charset도 시스템에 맞게 적절히 수정..


#!/usr/bin/perl -w

#####################################################################################
# author : gogisnim (gogisnim@gmail.com)
# file   : getCafe.pl
# date   : 2009.10.05
# desc   : LWP 모듈 테스트용, perl 감각익히기
#         : 다음카페의 방문자 목록을 얻는 perl script
#         : 단, cron으로 돌릴땐 local::lib 모듈을 지정해 주어야 한다.
#          : perl -I$HOME/perl5/lib/perl5 -Mlocal::lib ~/perl/getCafe.pl 이런식으로...
#####################################################################################

use strict;
use warnings;
use LWP::Simple;    # LWP 모듈

# 변수선언
my ($url, $html, $html2, $div1, $div2, $dir, $prev_txt, $old_txt, $new_txt, $data, $file_name) = ();
my (@nick,@tmp) = ();

$dir = "/home/xxx/perl/fun";
$url = "html긁어올url";
$html = get($url);

# html을 얻어오지 못하면 종료한다.
exit if ( !$html );

# $div1으로 나눈 2번째 요소를 취하고 $div2로 나눈 첫번째 요소를 취한다.
$div1 = "<div class=\"component_list group\">";
$div2 = "</div>";
($html2) = ( split $div2, (split $div1,$html)[1] )[0];

# 필요한 html을 \n 으로 분리해서 @tmp 배열에 넣는다.
@tmp = split("\n", $html2);

open (FH, $dir."/curr") or die("curr file error");
#binmode FH, ':encoding(UTF-8)';
binmode FH, ':encoding(euc-kr)';

# 문자열 초기화
$prev_txt = $old_txt = $new_txt = "";


# curr 파일의 내용을 읽어서 $prev_txt에 저장
# 주의. UTF-8로 인코딩 해야한다.
while ( <FH> ) {
   $prev_txt .= $_;
}
close(FH);


# 얻은 html 정보를 라인별로 읽어 정규표현식 <li title=\"(.+)\"> 에 만족하는 부분의 괄호부분($1)을 $old_txt에 저장
# 그중에서 이전 데이터($prev_txt)에 없는 정보(새로운 닉네임)은 $new_txt에 저장한다.
foreach ( @tmp ) {
   if ( /<li title=\"(.+)\">/ ) {
       $old_txt .= $1.",";
       if ( index($prev_txt,$1) == -1 ) {
           $new_txt .= $1.",";
       }
   }    
}

# curr 파일을 쓰기모드로 열고 UTF-8로 인코딩한다음 $old_txt 내용을 저장한다.
open (FH, ">".$dir."/curr") or die("curr file error");
#binmode FH, ':encoding(UTF-8)';
binmode FH, ':encoding(euc-kr)';
print FH $old_txt;
close(FH);


# 하루에 해당하는 파일 "년월일" $file_name 을 구한다.  예) 20091006
my ( $sec, $min, $hour, $mday, $mon, $year ) = ();
($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
$year = $year + 1900;
$mon = $mon + 1;
if(length($mon)==1)     { $mon  = '0'.$mon; }
if(length($mday)==1)    { $mday = '0'.$mday; }
if(length($hour)==1)    { $hour = '0'.$hour; }
if(length($min)==1)     { $min  = '0'.$min; }
$file_name = $year.$mon.$mday;


# 새로운 닉네임($new_txt) 내용을 $file_name에 저장한다.
open (FH, ">>".$dir."/$file_name") or die("data file error");
$data = "\n".$hour.":".$min." ==> ".$new_txt;
#binmode FH, ':encoding(UTF-8)';
binmode FH, ':encoding(euc-kr)';
print FH $data;
close(FH);

perl에서 데이터베이스 접근을 위한 모듈을 설치한다.
사용자는 DBI모듈 불러오고 이 DBI모듈이 DBD::mysql 모듈을 불러와 DB에 접근할 수 있다.

모듈정보를 확인한다.

# perl -MDBI -e 'print "$DBI::VERSION\n"'
Can't locate DBI.pm in @INC (@INC contains: /usr/local/lib/perl5/site_perl/5.8.6/mach /usr/local/lib/perl5/site_perl/5.8.6 /usr/local/lib/perl5/site_perl /usr/local/lib/perl5/5.8.6/BSDPAN /usr/local/lib/perl5/5.8.6/mach /usr/local/lib/perl5/5.8.6 .).
BEGIN failed--compilation aborted.

# perl -MDBD::mysql -e 'print "$DBD::mysql::VERSION\n"'
Can't locate DBD/mysql.pm in @INC (@INC contains: /usr/local/lib/perl5/site_perl/5.8.6/mach /usr/local/lib/perl5/site_perl/5.8.6 /usr/local/lib/perl5/site_perl /usr/local/lib/perl5/5.8.6/BSDPAN /usr/local/lib/perl5/5.8.6/mach /usr/local/lib/perl5/5.8.6 .).
BEGIN failed--compilation aborted.

# cpan
cpan> i /DBI/
cpan> install DBI
cpan> exit
# perl -MDBI -e 'print "$DBI::VERSION\n"'
1.607

DBI 모듈이 설치되었다.

DBD::mysql 모듈을 설치한다.

# cpan
cpan> install DBD::mysql
...
mysql_config 를 찾지못한다고 오류가나면서 종료된다.
$PATH를 추가하고 다시 한다.

이번에는 DB 테스트하는 과정에서 오류가 난다.
테스트를 건너뛰고 모듈을 설치할 수도 있겠지만 어떻게 하는지는 모르겠다.
기본 DB가 test인데 내가 가지고 있는 mysql 서버에는 test DB조차 없다.
root 계정도 비밀번호가 있어서 어쨌든 DB 테스트는 실패로 끝났다.

$HOME/.cpan/ 디렉토리의 설치문서를 본다.

$ vi /root/.cpan/build/DBD-mysql-4.008/INSTALL.html

이런 부분이 있다.

CPAN installation

.....
If you cannot get the CPAN module working, you might try manual installation. If installation with CPAN fails because the your local settings have been guessed wrong, you need to ensure MySQL's mysql_config is on your path (see SOURCE INSTALLATION) or alternatively create a script called mysql_config. This is described in more details later. Configuration.
....

또 이런 부분도 있다.

Configuration

The install script ``Makefile.PL'' can be configured via a lot of switches. All switches can be used on the command line. For example, the test database:

  perl Makefile.PL --testdb=<db>

If you do not like configuring these switches on the command line, you may alternatively create a script called mysql_config. This is described later on.

Available switches are:

testdb

   Name of the test database, defaults to test.

testuser

   Name of the test user, defaults to empty. If the name is empty, then the currently logged in users name will be used.

testpassword

   Password of the test user, defaults to empty.

testhost

   Host name or IP number of the test database; defaults to localhost.

testport

   Port number of the test database

ps-protcol=1 or 0

   Whether to run the test suite using server prepared statements or driver emulated prepared statemetns. ps-protocol=1 means use server prepare, ps-protocol=0 means driver emulated.

cflags

   This is a list of flags that you want to give to the C compiler. The most important flag is the location of the MySQL header files. For example, on Red Hat Linux the header files are in /usr/include/mysql and you might try

     -I/usr/include/mysql

   On Windows the header files may be in C:\mysql\include and you might try

     -IC:\mysql\include

   The default flags are determined by running

     mysql_config --cflags

   More details on the C compiler flags can be found in the following section. Compiler flags.

libs

   This is a list of flags that you want to give to the linker or loader. The most important flags are the locations and names of additional libraries. For example, on Red Hat Linux your MySQL client libraries are in /usr/lib/mysql and you might try

     -L/usr/lib/mysql -lmysqlclient -lz

   On Windows the libraries may be in C:\mysql\lib and

     -LC:\mysql\lib -lmysqlclient

   might be a good choice. The default flags are determined by running

     mysql_config --libs

   More details on the linker flags can be found in a separate section. Linker flags.

If a switch is not present on the command line, then the script mysql_config will be executed. This script comes as part of the MySQL distribution. For example, to determine the C compiler flags, we are executing

  mysql_config --cflags
  mysql_config --libs

If you want to configure your own settings for database name, database user and so on, then you have to create a script with the same name, that replies

 
=head2 Compiler flags

Note: the folling info about compiler and linker flags, you shouldn't have to use these options because Makefile.PL is pretty good at utilising mysql_config to get the flags that you need for a successful compile.

It is typically not so difficult to determine the appropriate flags for the C compiler. The linker flags, which you find in the next section, are another story.

The determination of the C compiler flags is usually left to a configuration script called mysql_config, which can be invoked with

  mysql_config --cflags

When doing so, it will emit a line with suggested C compiler flags, for example like this:

  -L/usr/include/mysql

The C compiler must find some header files. Header files have the extension .h. MySQL header files are, for example, mysql.h and mysql_version.h. In most cases the header files are not installed by default. For example, on Windows it is an installation option of the MySQL setup program (Custom installation), whether the header files are installed or not. On Red Hat Linux, you need to install an RPM archive mysql-devel or MySQL-devel.

If you know the location of the header files, then you will need to add an option

  -L<header directory>

to the C compiler flags, for example -L/usr/include/mysql.


# cd ~/.cpan/build/DBD-mysql-4.008
# perl Makefile.PL --testdb=xxxx --testuser=xxxx --testpassword=xxxx --testhost=localost
# make
# make test
테스트할때 중간쯤 오래걸릴때가 있다. 그럴땐 가볍게 Ctrl-C..

# make install
# perl -MDBD::mysql -e 'print "$DBD::mysql::VERSION\n"'
4.008

운영체제는 FreeBSD 5.4 이고 perl 버전은 5.8.6, mysql 버전은 4.1.18 이다.

GeoIP

컴퓨터/Programming 2008/06/05 13:38

ip나 host로 해당 지역이 어딘지 알 수 있다.

maxmind 에서 C,perl,php,java,python,ruby,vb 등 여러 언어로(심지어 자바스크립트로도 제공) GeoIP 기능을 사용할 수 있는 Geo API 를 제공한다.

perl의 Geo::IP::PurePerl 모듈을 제외하고는 모든 언어의 API에 GeoIP C Library가 설치되어 있어야 한다.

perl 같은 경우,
Geo::IP 는 C Library가 설치되어 있어야 하지만 속도가 빠른반면 Geo::IP::PurePerl 모듈은 속도는 느리지만 C Library가 설치되지 않아도 사용할 수 있다는 장점이 있다.

LGPL 라이센스를 따르는 GeoLite Country는 해당 데이터베이스 파일(GeoIP.dat)을 매달 1일 마다 업데이트해 무상으로 제공한다.

GeoIP.dat 파일 다운로드


젠투에서 GeoIP C Library 설치
# emerge dev-libs/geoip

CPAN에서 Geo::IP 모듈 설치
# cpan
cpan> install Geo::IP
cpan> quit



Geo::IP에 대한 내용은 perldoc 이나 CPAN 에서 참조한다.

#!/usr/bin/perl -w

#############################################################
# 파일명 : E:\perl\test\daum\daum_ftp.pl
# 작성자 : 고기스님 (gogisnim@gmail.com)
# 작성일 : 2008.05.09
# 사용법 : perl E:\perl\test\daum_ftp.pl [all|new|del]
# 설명    : daum 검색 데이터를 ftp로 제공한다.
#             스케줄에 등록하고 매일 새벽 자동실행된다.
# 주의    : new 일때 실행후 관련 파일은 자동 삭제된다.
#             따라서 del 옵션은 실제로는 필요가 없다.
#############################################################

use strict;
use warnings;
use Net::FTP;

my $ftp;
my $host = "myhost.test.com";
my $port = "2121";
my $user = "someuser";
my $pwd = "somepassword";
my $local_dir = "E:\\inetpub\\test\\daum\\";
my $target_dir;
my $fh;

my @real_files;


##### 파라미터 갯수를 체크하고 옵션(all, new, del) 값을 저장 #####
die "ARGV failed !!!" unless $#ARGV == 0;
my ( $opt ) = @ARGV;

##### all 일 경우 #####
if ( $opt eq "all" ) {
# 업로드할 파일 목록을 배열에 저장한다.
push @real_files, $local_dir.$opt."\\static.source.0";

##### new 또는 del 일 경우 #####
} else {
$target_dir = $local_dir.$opt;
opendir $fh, $target_dir
or die "file handle failed: $! \n";
while ( my $tmp_f = readdir $fh ) {
if ( ! -d $tmp_f ) { # 디렉토리는 포함하지 않는다.
  # 업로드할 파일 목록을 배열에 저장한다.
  push @real_files, $local_dir.$opt."\\".$tmp_f;
}
}
closedir $fh;
}

##### ftp 커넥션 #####
$ftp = Net::FTP->new($host, Port=>$port, Debug=>0)
or die "Cannot connect host $host : $@";


##### ftp 사용자 로그인 #####
$ftp->login($user, $pwd)
or die "cannot login ", $ftp->message;


##### 윈도우즈에서는 텍스트파일의 라인 마지막 1 byte가 짤렸다. #####
##### 이를 해결하기위해 binary 메소드를 호출한다.    #####
##### 리눅스/유닉스에서는 없어도 정상 작동한다.     #####
$ftp->binary;


##### 파일 전송 #####
foreach my $f ( @real_files ) {
$ftp->put($f)
or die "put failed ", $ftp->message;
}


##### ftp 커넥션 종료 #####
$ftp->quit;


##### new 또는 del 일 경우 로컬파일을 삭제한다 #####
if ( $opt ne "all" ) {
foreach my $del_f ( @real_files ) {
unlink($del_f);
}
}


binary

Transfer file in binary mode. No transformation will be done.

Hint: If both server and client machines use the same line ending for text files, then it will be faster to transfer all files in binary mode.


http://search.cpan.org/~gbarr/libnet-1.22/Net/FTP.pm

perlmodstyle

perlmodstyle 문서을 나름대로(?) 번역했습니다.
Perl을 배우는 입장에서 잘 이해되지 않는부분도 있었고 아예 해석이 불가능한 부분은 원문 그대로 두었습니다.

INTRODUCTION

이 문서는 펄 모듈작성을 위한 펄 커뮤니티의 "best practice"에 대해 설명할 것이다. 이는 perlstyle에서 권장되는 여러 사항들을 확장한 문서이다. perlstyle 문서를 미리 읽어두면 좋다. 이 문서는 모든 모듈개발자 특히, CPAN에서 모듈이 발표되기를 원하는 사람들에게 유용할 것이다. 중요한것은 모듈개발자에게만 보여질게 아니라 그 모듈의 사용자 관점에서의 스타일이라는 것이다. 이 문서에서 제공하는 가이드라인의 많은 부분은 모듈내부로의 적용 및 추정을 할수 있게 한다.

이 문서는 CPAN 모듈의 튜토리얼이라기 보단 스타일가이드인 perlnewmod 와는 다르다. It provides a checklist against which modules can be compared to determine whether they conform to best practice, without necessarily describing in detail how to achieve this. (it이 무엇을 말하는지 모르겠군요 ㅠ)

이 문서의 모든 권고사항들은 경험많은 CPAN 개발자와 사용자의 수많은 이야기들을 포함하고 있다. 각각의 권고사항은 이전에 했던 실수의 결과로 부터 얻어졌다. 이런 정보는 당신이 똑같은 실수나 불가피하게 그런 실수가 일어날수 있는 경우들을 피할 수 있게한다.

이 문서의 첫번째 섹션은 체크해야할 항목리스트를 제공한다. 그 다음 섹션은 각각의 항목에 대한 상세한 주제를 다루며 마지막 섹션 "Common Pitfalls"에서는 CPAN 저자들의 가장 잘 알려진 실수들을 설명한다.

QUICK CHECKLIST

체크리스트에 있는 각각의 아이템에 대한 자세한 설명이 아래에 있다.

시작하기전에

- 헛수고하지 마라(있는 모듈을 만들지 마라)

- 가능하면 존재하는 모듈을 패치하거나 하위클래스로 확장해라.

- 하나의 모듈은 자기자신의 역할에 충실히

- 어울리는 이름을 골라라

API

- API는 대부분의 프로그래머에게 이해하기 쉽게 만들어져야 한다

- 단순한 작업에 단순한 메소드

- 결과물로부터 기능적으로 분리해라

- 서브루틴 또는 메소드는 일관된 네이밍룰에 따라라

- 2개이상의 파라미터일때 해시 또는 해시레퍼런스를 사용해라

안정성

- 당신의 모듈을 use strict 와 -w 플래그를 이용해 안전하게 작성해라

- 안정적인 모듈은 이전버전과의 호환성을 유지하게 한다.

문서작업

- POD에 문서작업을 해라

- 목적, 범위 그리고 해당되는 프로그램을 기술해라.

- public하게 access 할 수있는 메소드나 서브루틴을 기술하고 파라미터와 리턴값을 포함해라.

- 문서에 사용예제를 제공해라.

- README 파일과 가능하다면 릴리즈노트,체인지로그 등등을 제공해라.

- 더많은 정보(URL,email)에 대한 링크를 제공해라.

릴리즈시 고려해야 할 것

- Makefile.PL 이나 Build.PL의 필요조건을 명시해라.

- use 와 함께 사용되는 펄 버전을 명시해라.

- 당신의 모듈로 한 테스트를 포함시켜라.

- 적당하고 일관된 버전번호를 선택해라(X.YY는 대부분 펄모듈의 넘버링 방식이다)

- 작은 수정에도 버전을 증가시켜라. 번호가 작은것은 문제가 되지 않는다.

- 패키지모듈을 만들때 "make dist" 를 사용해라.

- 적당한 라이센스를 골라라(GPL/Artistic이 좋다)

모듈 작성하기 전

모듈을 만들때 생각없이 무모하게 진행하지 마라. 약간의 신중함이 나중에 많은 수고를 덜어줄 수 있다.

모듈이 이미 존재하는가?

당신이 모듈을 만들 필요가 없을수도 있다. 펄에서 이미 만들어진게 있는지 체크부터해라. 만약 당신이 기가막힌 아이디어가 아니라면 다시 개발하는 헛수고는 하지마라. 이미 존재하는 모듈을 찾는 좋은 곳은 http://search.cpan.org/ 이다. modules@perl.org에 문의하라. 당신이 원하는 어떠한 모듈이 거의 대부분 존재한다면 재작성보다는 패치, subclass 그렇지 않으면 모듈확장을 고려해라.

각각의 모듈은 자신의 역할에 충실하자

명백히 위험성이 있음에도 불구하고 모듈들은 좀더 모듈화 되어왔다. 펄 개발자들은 그들의 프로그램의 일관적인 방향으로 만들기위해 모듈을 사용할 수 있다. 하지만, 중요한것은 그러한 부분(코드)이 올바른 형태여야 한다는 것이다. 개발자들은 작은 부분이 필요할때 큰 부분을 사용해서는 안된다.

당신의 모듈은 하나의 문장도 채 되지않는 명백히 정의된 유효범위를 가져야 한다. 당신의 모듈이 연관된 모듈의 구성원이 될 수있는가?

나쁜 예:
"FooBar.pm 은 FOO 프로토콜을 구현하고 연관된 BAR 표준을 제공하는 기능을 한다."

좋은 예:
"Foo.pm은 FOO 프로토콜의 구현한다. Bar.pm은 연관된 BAR 프로토콜을 구현한다."

이는 개발자가 단지 BAR 표준을 위한 하나의 모듈만 필요하다면, FOO와 같은 라이브러리들은 절대 설치되지 않게해야 함을 의미한다.

이름을 어떻게 지을것인가?

초기에 당신의 모듈을 위한 적당한 이름을 고려해라. 이는 사람들이 당신이 만든 모듈을 찾고 기억하는데 도움을 줄것이다. 당신의 모듈로 더욱 더 직관적으로 프로그램을 짤 수있게 할것이다.

모듈이름 정할때 아래사항들을 고려해라.

- 사실적으로 기술(모듈의 목적에 맞게 자세히 설명되는)

- 이미 존재하는 모듈과 일관된 네이밍룰을 가져라.

- 모듈의 구현이 아닌 기능성을 반영해라.

- 특히, 당신의 모듈이 위치할 곳에 이미 적당한 계층이 존재한다면 최상위 계층에 모듈명이 시작되는것을 피해라.

당신의 모듈을 publishing 하기전에 모듈이름에 대해서 modules@perl.org 에 문의해야 한다. 모듈 어플리케이션 도메인과 CPAN 네이밍 시스템을 잘 아는 사람들에게 문의해야 한다. 유사한 모듈 또는 유사한 이름의 모듈 저자에게 문의하는것도 좋은 방법이다.

모듈 디자인 및 작성

모듈을 디자인하고 코딩할때의 고려사항들

객체지향과 비객체지향

당신의 모듈은 객체지향일수도 있고 비객체지향적일 수 있고 두가지 방식 모두 가능할 수도 있다. API를 디자인할때 고려되는 각각의 테크닉에 대한 찬반양론이 있다. Damian Conway에 따르면, 당신은 객체지향 방식을 고려해야 한다.

- 시스템이 거대하거나 또는 그리 될 가능성이 많을때

- 객체가 될 명백한 구조에서 데이터가 모아질때

- 상속받아 사용할 수있는 일반적인 계층형 데이터 타입일때

- 데이터 타입에 따른 많은 연산이 필요할 때 (적당한 메소드로 다형성 구현)

- 새로운 데이터타입이 나중에 시스템으로 전달되거나 존재하는 코드에 의해 핸들링 될 필요가 있을때

- 데이터의 상호작용으로 오버로드된 연산자에 의해 재작성될때

- 시스템 컴포넌트의 구현이 시간이 지남에 따라 변할수 있을때 (따라서 캡슐화 시켜야 한다)

- 시스템 디자인이 원래 객체지향적으로 되어 있을때

- 클라이언트 코드의 상당부분이 소프트웨어에 사용될때 (구현시 수정된것으로부터 분리되어야 한다)

- When many separate operations will need to be applied to the same set of data (?)

당신의 모듈이 객체지향에 적합한지는 많은 고찰이 필요하다. 아무런 이유없이 객체지향기법을 사용하면 API는 복잡해지고 그 모듈을 사용하거나 이해하려는 일반적인 사용자는 상당한 어려움을 겪게된다.

API 디자인

당신의 interface는 일반적인 펄 프로그래머가 이해할 수 있어야 한다. 아래의 가이드라인은 당신의 API가 제대로된건지 그렇지 않은지 판단하는데 도움을 줄것이다.

간단한 기능에 간단한 루틴을 작성하라. 수많은 간단한 루틴이 몇개의 복잡한 루틴보다 더 좋다. 만약 당신의 루틴이 인자때문에 상당한 기능의 수정이 있다면 2개(그 이상으로) 분리된 루틴을 작성하는것이 그 이유이다.

결과물로부터 기능적으로 분리해라. 가능한 가장 일반적인 형태에서 결과를 리턴해라. 그리고 사용자가 그것들을 사용하는 방법을 선택할 수 있게 만들어라. 가능한 가장 일반적인 형태란 텍스트, HTML, XML, DB 쿼리 또는 사용자가 요구하는 다른 어떤 포맷에 익숙한 펄 데이터 구조이다. 만약 당신의 루틴이 어떠한 리스트(파일리스트, 데이터베이스 레코드 등)를 반복하는 것이라면 리스트 각각의 요소를 차례로 컨트롤할 수있게 하기위해 callback을 제공하는것을 고려해야 할 것이다. 그러한 예로 File::Find 모듈은 find(\&wanted, $dir)를 제공한다.

적당한 단축과 default를 제공해라. 간단한 결과를 이루기위해 남들이 하는 그대로 똑같이 모듈사용자에게 요청하지마라. 당신은 선택적으로 파라미터를 포함하거나 더욱 복잡한 루틴을 포함하거나 표준적이지 않은 기능 역시 포함할 수 있다. 만약 그들이 당신의 모듈을 사용하기 시작했을때 거의 대부분 동일한 코드라인을 가진다면 당신은 기본적인 기능을 만들었다는 것을 의미한다. 당신이 기본적인것을 사용해야하는 또 다른 좋은 지표는 대부분의 사용자들이 당신의 루틴을 같은 파라미터로 호출하는 것이다.

네이밍 관례 네이밍은 일관되어야 한다. 예를들면

display_day();
display_week();
display_year();

이 코드가

display_day();
week_display();
show_year();

이 코드보다 더 좋다. 이것은 메소드명, 파라미터명 그리고 사용자에게 보여지는 어떤 이름에도 그대로 적용된다.(대부분 그렇지 못하다)

Parameter passing 네이밍된 파라미터를 사용해라.

$obj->do_something(
    name => "wibble",
    type => "text",
    size => 1024,
);

위 처럼 해시를 사용하는게 아래처럼 네이밍되지 않은 하나의 긴 리스트보다 훨씬 코드가 쉽다.

$obj->do_something("wibble", "text", 1024);

인자가 하나라면 괜찮지만 둘,셋 또는 그 이상이되면 모듈사용자가 기억하기 어렵고 모듈제작자가 관리하기 어렵다. 만약 당신이 새로운 파라미터를 추가하고 싶다면 이전 버전과의 호환성 유지를 위해 리스트의 끝에 그것을 추가해야한다. 이는 리스트가 직관적이지 못하게 될 가능성이 크다. 또한, 많은 요소들이 undefined 이라면 메소드 호출하는 코드가 아래처럼 아름답지 못할 것이다.

$obj->do_something(undef, undef, undef, undef, undef, undef, 1024);

적당한 디폴트 파라미터를 제공해라. 사용자에게 거의 대부분 동일한 파라미터를 지정하게 만들지 마라. 해시나 해시레퍼런스로 인수를 통과할 것인지 그렇지 않을것인지의 이슈는 개인 스타일의 문제이다. 해시키의 사용은 하이픈(-)으로 시작하거나 전체를 대문자로 하는것은 소문자가 => 연산자에 의해서 정확하게 핸들링할 수 없었던 오래된 펄버전의 잔재이다. 어떤 모듈은 역사적인 이유 또는 개인적인 스타일 문제등으로 하이픈붙은 키 또는 대문자 스타일을 그대로 유지하기도 한다. 대부분의 새로운 모듈들은 간단하게 소문자 키를 사용한다. 당신이 어떠한 선택을 하던 일관성을 유지해라!

Strictness and warnings

당신의 모듈은 strict 환경에서 어떠한 경고없이 성공적으로 작동을 해야 한다. 또한 수많은 조건에서 갖가지 돌출사항이 있더라도 적절한 오류체크를 할 수 있어야 한다.

이전버전과 호환성

"stable"한 모듈들은 적어도 아주 오래된 문법을 사용한다던지 버전의 큰 변화가 없는한 이전버전과의 호환성을 깨뜨려서는 안된다.

에러처리 메시지

당신의 모듈에서 에러가 발생했을때 다음과 같이 해라.

- undefined 값을 리턴

- $Module::errstr을 세팅하거나 또는 그와 유사한 것을 세팅(errstr은 DBI 또는 다른 유명한 모듈에 사용되는 일반적인 이름; 당신이 그외 다른 어떤것을 선택할 경우 문서를 확인해라)

- warn() 또는 carp() 메시지를 STDERR로 보내라

- croak()은 당신의 모듈이 무슨일을 하는지 알 수 없을때에만 사용해라.(모듈내에서 사용할때 die()보다 croak()이 좋다. croak()은 호출자의 관점에서 그것의 에러를 리포트한다. croak(),carp() 그리고 다른 유용한 루틴을 참조하려면 Carp 모듈을 참조해라)

- 위의 대안으로는, 당신은 Error 모듈을 사용해서 exception이 떨어지게 하는걸 좋아할지도 모르겠다.

에러 핸들링을 설정하는것은 사용자에게 굉장히 유용하다. 경고메시지와 디버거메시지의 레벨을 선택하거나, 메시지 내용을 파일로 보낸다거나, 에러핸들링 루틴을 지정하는 다른 방법이나 그 밖의 다른 특징들에 대해 고려해라. 가장 일반적으로 사용되는 이러한 선택들은 기본적으로 갖추어져야 한다.

모듈 문서작업

POD (plain old documentation)

당신의 모듈은 펄개발자들을 위한 문서를 제공해야 한다. 펄에서 일반적인 기술문서를 위한 POD를 사용한다. 다른포맷에서의 추가적인 문서작업(white paper, 튜토리얼 등)을 할 때에도 POD를 사용한다. 아래 이슈들을 파악해야 한다.

- 모듈의 일반적인 개요

- 당신의 모듈이 사용될 프로그램, 범위, 목적

- public하게 access 할 수있는 메소드나 서브루틴을 기술하고 파라미터와 리턴값을 포함해라.

- 사용 예

- 더 많은 소스정보

- 저자/관리자의 메일주소

펄모듈 문서작업의 상세레벨은 일반적으로 작은 분량에서 많은 분량으로 늘어간다. SYNOPSIS 섹션은 작은 예를 포함해야 한다.(한 라인이 안될정도의 코드; 대부분 사용자에게 필요없거나 일반적이지 않은 경우는 생략) DESCRIPTION 은 일반적으로 몇개의 단락으로 나눠 모듈에 대한 전체적인 설명을 한다. 모듈의 루틴,메소드,예제 또는 보다 심오하고 중요한 내용은 하위절에서 다룬다.

당신의 모듈에 대해 좀 알고있는 사람은 "page down"키 없이도 자신의 기억을 새롭게 할 수있으면 더할나위 없이 좋을것이다. 당신의 독자들이 문서를 통해서 익혀나갈때 그들의 지식은 점차적으로 늘어갈 것이다.

펄모듈 문서의 섹션순서는 다음처럼 한다.

- 이름

- 개요

- 설명

- 관련된 더욱 자세한 내용

- 버그/경고/기타

- 저자

- 다른 참조

- 라이센스

Keep your documentation near the code it documents ("inline" documentation). Include POD for a given method right above that method's subroutine.

README, INSTALL, release notes, changelogs

당신은 모듈을 설명하는 README 파일을 포함할 수 있고 더 많은 정보를 제공할 수 있다(웹사이트,이메일을 통해서) INSTALL파일은 간단한 설치명령을 포함하고 있다. ExtUtils::MakeMaker? 모듈을 사용할 때, 다음과 같이 한다.

perl Makefile.PL
make
make test
make install

Module::Build 모듈을 사용할 때, 다음과 같이 한다.

perl Build.PL
perl Build
perl Build test
perl Build install

release note 나 changelog는 사용자에게 보여지는 모듈의 변화를 보여준다. 사용자에게 유용하다.

릴리즈시 고려해야 할 것

버전 번호

버전번호는 메이저릴리즈, 마이너릴리즈를 가리킨다. 서브 마이너 릴리즈를 가리킬 수도 있다. 메이저 릴리즈는 기능면에서 중요한 변화가 있거나 새로운 기능이 추가되었을때 적용한다. 마이너 릴리즈는 작은 기능이 추가되거나 바뀌었을때, 서브마이너 릴리즈는 기능적인 변화는 없고 문서패치와 같은 경우 적용된다.

가장 중요한 CPAN 버전의 번호부여는 다음과 같다.

1.00, 1.10, 1.11, 1.20, 1.30, 1.31, 1.32

올바른 CPAN 버전 번호는 소숫점 2자리로 표시한다. CPAN에 따르는지 그렇지않은지는 아래와 같이 확인해 볼수있다.

perl -MExtUtils::MakeMaker -le 'print MM->parse_version(shift)' 'Foo.pm'

만약, 모듈버전에 alpha나 beta를 추가는 하지만 CPAN에 리스트되지 않게 하려면 최신 정규버전 뒤에 '_'를 붙이고 숫자2개로 표시한다.(이를테면 1.20_01) 아래와 같이 하는것을 권장한다.

$VERSION = "1.12_01";
$XS_VERSION = $VERSION; # only needed if you have XS code
$VERSION = eval $VERSION;

MakeMaker?가 첫라인과 언더라인만 읽는다는 트릭을 이용해서 펄 인터프리터가 $VERSION 변수를 해석하고 문자열을 숫자로 변환한다. $VERSION을 숫자로 취급하는 이후의 연산에서 $VERSION이 숫자가 아니라는 경고 없이 사용할 수 있다.

숫자 증가없이 어떠한 릴리즈도 하지마라!(단지, 문서의 한 단어를 수정하는 것일지라도) 한 단어 문서패치라도 서브 마이너 레벨의 버전 변화를 주어야 한다.

모듈 요구사항

모듈제작자는 다른 모듈에 의존되는지 주의깊게 살펴봐야 한다. 가장 중요한것은 가능하면 안정적인 모듈을 선택하라는 것이다. 아래의 순서를 따라라.

- Core Perl 모듈

- Stable CPAN 모듈

- Unstable CPAN 모듈

- CPAN으로 부터 사용하지 않는 모듈

당신의 Makefile.PL 이나 Build.PL 에서 사전에 요구되는 다른 펄 모듈 요구버전을 명시해라. Makefile.PL 이나 Build.PL, 그리고 펄 버전 5.6.1 또는 이와 유사한 버전 모두 요구되는것을 명시해야 한다. 보다 상세한 내용은 "require" in perlfunc 의 use VERSION 섹션을 참조.

테스트

모든 모듈을 배포되기전에(make disttest를 사용해서) 테스트 되어야 한다. 테스트는 모듈을 설치하려는 사람들에게 유용해야 한다.(make test) 당신은 perl Build test와 동등한 make test를 사용하는 Module::Build를 사용한다.

이런 테스트의 중요성은 모듈의 안정성을 증가시켜준다는 것이다. 안정적이거나 광범위하게 쓰이길 원하는 모듈을 가능하면 엄격하고 꼼꼼하게 테스트를 수행해야 한다. 당신의 테스트에 많은 도움을 주는 유용한 모듈(Test::Simple, Carp::Assert, Test::Inline를 포함하는)은 당신이 작업하는 시간이나 개발 프로세스 중간에 충돌을 최소화 한다. 보다 정교한 테스트를 위한 모듈은 Test::More, Test::MockObject? 등이 있다.

패키징

모듈은 표준 패키징 툴들중 하나를 사용해서 패키징 한다. 현재 당신은 ExtUtils::MakeMaker? 와 플랫폼 독립적인 Module::Build 를 선택할 수 있다. 이들은 일관성있게 모듈을 설치하게 해준다. ExtUtils::MakeMaker? 를 사용할때 당신은 패키지를 생성하기 위해 "make dist" 를 한다. MakeMaker? 스타일의 당신의 모듈을 빌드하는데 도움을 주는 툴들이 존재한다. ExtUtils::ModuleMaker? 과 h2xs 같은게 그것들이다. perlnewmod를 참조하라.

라이센스

당신의 모듈은 라이센스를 가져야 한다. 전체 내용은 배포판에 포함된다.(라이센스의 기간이나 일반적인 것들이 없으면 당신이 그것을 포함하는것을 요구하지 마라) 만약, 당신이 라이센스 사용을 잘 모른다면 GPL과 Artistic 라이센스하에(perl 처럼) 두는것이 좋다. perlgpl과 perlartistic를 참조하라.

일반적인 함정

불필요한 일

CPAN에 이미 많은 프로그램들이 존재한다. templating 시스템을 예로 들어보자. 다른 많은 날짜와 시간 모듈이 있다. 마치 통과의례처럼 자신만의 코드를 만드는 동안 과연 내가 이것을 만들 필요가 있을지, 그렇지 않을지를 신중히 고려해라.

해야할게 너무 많은 거

당신의 모듈을 개발자들의 툴킷의 일부분이 될 수있다. 아니면 그 자체로 하나의 완성된 툴킷이 될수도 있을 것이다. 당신의 코드는 어떠한 특정 모듈보다는 하나의 단일 시스템이 될때까지 여타 가능을 추가하는 것도 괜찮다.

잘못된 문서

불량(?) 사용자를 위한 문서작업을 하는 함정에 빠지지 마라. 주 사용자는 적어도 당신의 모듈을 이해하는 개발경험이 있는 사람들이다. 그들은 당신의 모듈을 다운로드 받아 가능한 빨리 사용해보기를 원한다.

Tutorials, end-user documentation, research papers, FAQ 따위는 모듈의 메인문서로 적당하지 않다. 만약, 당신이 이런 문서작업을 하길 원한다면 My::Module::Tutorial 이나 My::Module::FAQ, 메인문서의 SEE ALSO 섹션에 링크를 제공하는 sub document에 포함시켜라.

SEE ALSO perlstyle General Perl style guide

perlnewmod How to create a new module

perlpod POD documentation

podchecker Verifies your POD's correctness

Packaging Tools ExtUtils::MakeMaker?, Module::Build

Testing tools Test::Simple, Test::Inline, Carp::Assert, Test::More, Test::MockObject?

http://pause.perl.org/ Perl Authors Upload Server. Contains links to information for module authors.

Any good book on software engineering AUTHOR Kirrily "Skud" Robert <skud@cpan.org>