问题 将Perl CGI迁移到Template Toolkit的策略?


我有一个相对较大的传统Perl / CGI / DBI Web应用程序,它可以一个接一个地生成HTML。我们正在重新制作正在生成的HTML,以符合HTML 5 / CSS 3.这是转移到某种模板系统的好时机。我们不想进行完全重写,因此不希望迁移到Catalyst等框架。

我认为Perl模板工具包可能是我们影响最小的手段。我正在重新阅读古老的Badger Book来研究可行性。

我的问题是这个。有没有人在这里将“旧学校”Perl Web代码迁移到Template Toolkit?是否有任何技巧可以分享,以尽量减少重写/返工?我们还没有100%决定使用Template Toolkit。如果有替代方案我们应该考虑?

具体来说,我们试图解决什么问题?我们正在生成无效的HTML并需要清理它。由于我们正在清理,我们希望生成完全有效的HTML 5,并在可行的范围内生成有效的CSS3和Javascript。我们通过jQuery使用jQuery,jQuery UI小部件和AJAX。我们有典型的页面控制器MVC架构,除了没有View层。我们想去某种模板系统,但不想重写所有东西(或许多东西!)进行迁移。

谢谢! Ed Barnard,Cannon Falls MN


7529
2017-11-23 23:47


起源

我建议第一步的东西是创建一个测试套件。您可能希望在外包的第一步中对旧文档和新文档进行某种解析和比较,以确保您不会破坏任何内容,以及功能测试(这里会想到Selenium)。您重写HTML后可以保留的第二部分,反过来您也可以对HTML有效性/合规性进行单元测试。 - simbabque


答案:


这是我发现的,因为我已经将我的练习从CGI.pm转移到了TT,以及我在使用HTML :: Mason,HTML :: Template,Text :: Template和使用的方式中学到了什么。 Rails中的ERB和HAML。

  1. 您在显示器中使用的逻辑越多,特别是如果它以显示特定语言编写,您将获得的乐趣就越少。
  2. 我更喜欢HAML减少模板内容的大小[在HAML中,缩进隐含了结束标签]
  3. 在使用应用程序的本机语言放入模板之前,执行尽可能多的逻辑来计算页面的各种动态位。 [调用视图方法,在进行渲染之前]。
  4. 关于(3),通过使用方法而不是内联显示/呈现逻辑,您可以使模板具有声明性,因此当您在渲染过程中执行逻辑时,您的模板没有一堆IF / THEN / ELSE逻辑导致混乱。

让我们想象一个由标题,页脚和正文组成的相当小的,人为的网页。让我们假设页脚是完全静态的,每次加载新页面时主体都会更改,但标题只会在用户登录/注销时更改。

你可以想象包含这样的代码的标题:

<header>
[% IF $user.is_logged_in THEN %]
   Hello [% $user.name %] - <a href="/logout/user/[% $user.id %]">Log Out</a>
[% ELSE %]
   Please <a href="/user/login">Log In</a>
[% END %]
</header>

但是你最好在header.tt中做这件事:

<header>
  [% user_info($user) |html %]
</header>

这在View :: Helpers :: Header.pm中:

sub user_info {
   my $user = shift;
   if ($user->{is_logged_in} ) {
     return "Hello $user->{name} - " . logout_link($user->{id});
   }
   else {
     return "Please " . login_link();
   }
}

sub logout_link {
  my $userid = shift;
  return qq(<a href="/logout/user/[% $userid %]">Log Out</a>)
}

当然,您可以在TT而不是纯Perl中实现视图助手,我没有任何类型的数字,但如果您已经在Perl中完成了所有逻辑,则可以将Perl重构为模块(如果它不存在),而不是在TT中重新编码。


10
2017-11-24 00:23



谢谢你,Len!我非常同意你的四个要点(除了我从未使用过HAML)。大多数域逻辑都在.pm模块中。我们宁愿在纯Perl中尽可能多地实现。这是一个UI(用户界面)刷新而不是重写!这就是为什么我认为TT是一个很好的选择,因为我们仍然允许使用纯Perl。您在模板下使用Perl的示例正是我所需要的。我希望它(相对)那么容易。 Ed(现在我知道Return发表评论) - Edward Barnard
所以评论条目是一个严厉的情妇:-) - Len Jaffe
我有一段时间是HAML nay-sayer。我避免使用python和ruby来使用语义空格。我已经转换了,并且对HAML非常满意,并且可能会在我从头开始的下一个项目中使用它。我现在使用它的那个从ERB开始,我一直在转换,因为时间允许。 - Len Jaffe
我喜欢你在减少模板中的逻辑方面所说的话。但是,如果你去限制模板,为什么不使用纯HTML文档作为模板呢?您可以通过解析页面并修改DOM来修改“模板”。所以 <header> <div id='user_info'><a>Joe Sample</a></div> 可以使用HTML :: TreeBuilder之类的东西替换 my $u_info = $doc->look_down( 'id', 'user_info' ); $u_info->push_content( '...' );  现在,我只在小项目中使用过这种技术,但它在那里运行良好。 - daotoad
因为模板通常不具有HTML解析的开销,所以只有正则表达式搜索必须遵循特定规则的分隔符以防止需要解析HTML。简短的回答是,你必须在某处画一条线。大多数情况下,我们使用模板,因为它们暗示了围绕所有HTML的print语句。我们可以很容易地使用一堆打印语句,并且根据组件分解的程度,无论如何它通常都是这样。我猜模板只是感觉正确的抽象级别。 - Len Jaffe


作为测试套件的一部分,请考虑HTML验证器,如HTML :: Lint或HTML :: Tidy。


3
2017-11-26 16:02



Andy,问题:HTML :: Lint会被html 5 doctype“!DOCTYPE HTML”搞砸吗?我们实际上并没有使用任何特定于html5的东西,因此Lint / Tidy应该非常有用。我看到你有Test :: More包装器。我们可以运行我们的CGI脚本命令行,因此对当前输出运行lint有望提供对当前情况的良好调查。并将转换保持在正确的轨道上,即测试驱动开发。感谢您的建议。 - Edward Barnard
HTML :: Lint不知道HTML 5.此外,不是从命令行运行CGI脚本,而是使用类似的工具 WWW::Mechanize 通过Web服务器获取页面,就像浏览器一样,然后您可以将该页面提供给HTML :: Lint。这样你就可以测试更接近实物的东西了。 - Andy Lester
谢谢安迪!对于我们来说,机械化可能是一个问题,因为不希望在测试工具中构建身份验证。但我肯定会看看那个选项。 - Edward Barnard
使用的另一个好处 WWW::Mechanize 就是它也有 Test::WWW::Mechanize 这可以让你轻松编写测试程序。 Mech程序可能有的地方 $mech->get($url),你把它放在测试程序中并将其更改为 $mech->get_ok($url)瞧,它做了GET然后验证它是正确的。加, Test::WWW::Mechanize 可以自动在每个页面上运行HTML :: Lint,甚至无需考虑它。 - Andy Lester
WWW :: Mechanize,Test :: WWW :: Mechanize,HTML :: Lint和Test :: HTML :: Lint现在列在清单上。再次感谢安迪! - Edward Barnard