生信码农:流程脚本编写规范

流程是介于脚本与软件的一组代码文件,所以在写流程的时候要知道脚本的基本结构以及软件开发的基本常识。前者要掌握,后者要了解。

出于掌握的需要,重温一下:

  • Name:脚本名字
  • DescripCon:对脚本简介
  • Version:作者、版本及日期
  • Usage:用法及参数说明(参数较多可以分类或者按首字母排序)
  • Note:注意事项
  • Example:使用例子
#!/usr/bin/perl -w
# 加载时间管理,参数管理,文件名和路径处理的基础包,无须安装
use POSIX qw(strftime);
use Getopt::Std;
use File::Basename;

###############################################################################
#命令行参数据的定义和获取,记录程序初始时间,设置参数默认值
#Get the parameter and provide the usage.
my $rename = "perl $Bin/rename.pl"  # 在开头一个集中的位置,记录所用程序路径
my $R = "$Bin/RScript"
###############################################################################
my %opts;
getopts( 'i:o:d:h:', \%opts );
&usage unless ( exists $opts{i} && exists $opts{o} );
my $start_time=time;
print strftime("Start time is %Y-%m-%d %H:%M:%S\n", localtime(time));
print "Input file is $opts{i}\nOutput file is $opts{o}\n";
print "Database file is $opts{d}\n" if defined($opts{d});
$opts{h}=1 unless defined($opts{h});

###############################################################################
#读入的数据或注释文件,用于与输入文件比较或注释(可选),提供三种方式
#Read the database in memory(opt)
###############################################################################
#open DATABASE,"<$opts{d}";
# 1. 散列结构数据库,要求数据文件有唯一ID并且无顺序要求
#my %database; #database in hash
#while (<DATABASE>) {
#    chomp;
#    my @tmp=split/\t/;
#    $database{$tmp[1]}=$tmp[2];
#}
# 2. 数组结构数据库,无唯一ID,但有顺序要求
#my (@tmp1,@tmp2); #database in array
#while (<DATABASE>) {
#    chomp;
#    my @tmp=split/\t/;
#    push @tmp1,$tmp[1];
#    push @tmp2,@tmp[2];
#}
#close DATABASE;
# 3. 批量数据文件,读取一批有相似结构的文件
#open a list file
#my %list;
#my @filelist=glob "$opts{i}";
#foreach $file(@filelist){
#    open DATABASE,"<$file";
#    $file=basename($file);
#    while (<DATABASE>) {
#        my @tmp=split/\t/;
#        $list{$file}{nr}++;
#    }
#    close DATABASE;
#}

###############################################################################
#Main text.
###############################################################################
# 正文部分,读取输入文件,列出输入和输入文件的三行作为示例,方便编程处理数据
open INPUT,"<$opts{i}";
#chrm0    snppos1          ref2     mat_gtyp3        pat_gtyp4        c_gtyp5  phase6   mat_all7 pat_all8 cA9  cC10   cG11   cT12   winning SymCls  SymPval BindingSite     cnv
#1       4648    C       A       C       M       PHASED  C       A       0       11      0       0       M       Asym    0.0009765625    -1      0.902113
open OUTPUT,">$opts{o}";
#chrm    snppos          ref     mat_gtyp        pat_gtyp        c_gtyp  phase   mat_all pat_all cA      cC      cG      cT      winning SymCls  SymPval BindingSite     cnv
#1       4648    C       A       C       M       PHASED  C       A       0       11      0       0       M       Asym    0.0009765625    -1      0.902113

my %count;
# h参数用于去除有文件头的行
while ($opts{h}>0) { #filter header
    <INPUT>;
    $opts{h}--;
}
# 输入和输入处理部分,常用按行读取处理并输入,默认按tab分割数据
while (<INPUT>) {
    chomp;
    my @tmp=split/\t/;
    print OUTPUT "$tmp[0]\t$tmp[1]\n";
}
close INPUT;
close OUTPUT;

###############################################################################
#Record the program running time!
# 输出程序运行时间
###############################################################################
my $duration_time=time-$start_time;
print strftime("End time is %Y-%m-%d %H:%M:%S\n", localtime(time));
print "This compute totally consumed $duration_time s\.\n";

###############################################################################
#Scripts usage and about.
# 程序的帮助文档,良好的描述是程序重用和共享的基础,也是程序升级和更新的前提
###############################################################################
sub usage {
    die(
        qq!
Usage:    template.pl -i inpute_file -o output_file -d database -h header num
Function: Template for Perl
Command:  -i inpute file name (Must)
          -o output file name (Must)
          -d database file name
          -h header line number,s default 0
Author:   Zhang San, zhangsan_bio\@163.com, QQ:1102279384
Version:  v1.0
Update:   2018/04/09
Notes:    
\n!
    )
}

为什么要规范流程的编写呢?
  • 可读
  • 流程的维护和升级
  • 提高代码复用
  • 方便调试
怎样规范流程编写?
  • 目录结构
    • README 流程发布/更新时间,版本,创建人,记录流程版本,更新信息的文件
    • bin/主流程脚本及一些重要的配置文件
    • lib/流程所使用软件库、包等等
    • database/使用的数据库,可在lib或配置文件中
    • doc/测试报告、说明书、参考文献等说明性资料
    • report/商业项目流程交付所需的文档
    • example/运行例子.包含:
      • work.sh 运行例子
      • shell文件
      • input/输入数据
      • example
      • output/输出结果展示
  • 路径引用及接口
    • 在开头一个集中的位置,记录所用程序路径
    • 对于更新较快的数据库,或者被调用的脚本涉及数据库路径问题,最好留一个用参数设置来输入路径的接口(以备以前的数据要用)
  • 使用说明

  • 注释及变量命名规则

    • 文件名称统一用英文字母(大小写)、数字和下划线的组合
    • 每个全局变量必须有注释说明其作用(命名本身就应有注释的作用)
    • 在函数的开头写函数的使用说明
    • 一个脚本中不同的功能,用注释线隔开
  • 模块化编程

    • 一个脚本完成一项简单的任务
    • 模块话编程及把算法独立写成方法,提高了代码的重用
    • 模块间连接:串行、并行。
    • 思维导图、流程图
  • 流程开发及升级规划

    • 文献调研
    • 工作量评估
    • 伪代码、流程图、框架
    • 代码编写与调试
    • 流程测试
    • 文档撰写
    • 发布
  • 执行与监督与反馈

    • 在编程中修炼自己
    • 在小修小补中优化,在质的飞跃中升级
    • 版本管理

再度重申基本代码结构:

#!/usr/bin/perl    –w
#调用库,配置环境变量
use lib/xxx/;或者BEGIN{push @INC,/xxx/;}
use    xxx包;
#==========================================
获取输入参数
使用说明
参数初始化(赋默认值)
输入文件或参数检测
获取引用软件路径
#==========================================
主程序
#==========================================
子程序

参考

生信人写程序1. Perl语言模板及配置
perl:编码规范;严格要求自己
模块化编程思想

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容