重构"包含文件地狱"
真正使ASP经典项目的代码库上步伐困难的一件事是,包含文件的情况有点混乱。我有时会发现我一直在寻找的功能被包含在一个完全不相关的包含文件中。是否有人对如何重构它有任何建议,以便他们可以在需要的地方更轻松地判断一个函数在哪里?
编辑:我忘了问一件事:vbscript是否具有防止某种文件被两次包含的任何机制?像#ifndef来自C的排序方式?
解决方案
我认为我们应该考虑将代码从ASP VBScript移到Visual Basic COM DLL。这将减轻我们包含过多内容的麻烦。
接管经典ASP应用程序时,我们可以做一些基本的事情,但是我们最终可能会后悔这样做。
- 消除重复的包含文件。我见过的每个经典的ASP应用程序都有5个" login.asp"页面和7个" datepicker.js"文件,依此类推。搜寻并删除所有重复项,然后根据需要在应用程序的其余部分中更改引用。删除文件时,请务必对它们进行差异检查-通常,重复的文件会有细微的差异,因为原始作者复制了该文件,然后仅更改了副本。对于Evolution而言,这是一件了不起的事情,但对于代码而言却不是那么重要。
- 创建一个合理的文件夹结构并将所有文件移入其中。这很明显,但这是我们最后悔的事情。无论应用程序中的链接是相对的还是绝对的,我们都必须更改大多数链接。
- 将所有包含文件合并为一个大文件。然后,我们可以按逻辑对所有功能进行重新排序,并将它们分解为单独的,命名合理的文件。然后,我们必须逐页浏览应用程序,弄清楚每页上的include语句需要是什么(或者坚持使用一个文件,仅在每个页面上包含它-我不记得是否这在ASP中是个好主意)。我无法理解这里涉及的痛苦程度,并且假设现有的包含文件没有大量使用同名的全局变量。
我什么都不会做。用史蒂夫·耶格(Steve Yegge)来解释一下:"经典的ASP应用程序没有任何问题,而该应用程序无法通过完全重写来解决"。我对此非常认真,我认为在这个世界上程序员的时间不会比维护ASP应用程序浪费更多,而且随着ASP的过时越来越多,问题变得更加严重。
@MusiGenisis的要点列表是一个很好的建议,但我不同意-
"我不会做任何事情。用史蒂夫·耶格(Steve Yegge)来解释(我认为),"经典的ASP应用程序没什么问题,无法完全重写而修复。"认为在这个世界上,程序员的时间比维护一个ASP应用程序要浪费更多的时间,而且随着ASP越来越过时,问题变得更加严重。"
一切都很好,但是如果它是一个相当大的遗留应用程序,则由于缺乏开发人员时间/资源,通常不可能进行完全重写。
我们有一个相当大的经典ASP应用程序,这些应用程序已经发展了很多年,虽然不漂亮,但确实可以满足业务需求。在接下来的六个月中,我们没有时间进行完全的重写,这很好,但是不可能。我们的方法是-
- 在需要新功能的地方,可以在ASP.NET中实现。 95%的时间会发生这种情况。 5%的极端情况通常是,新应用程序代码与旧应用程序有很多接触,这要求我们进行大量经典的ASP重做工作,从而可能使该应用程序更脆弱。
- 在功能发生变化的地方,我们评估是否可以以最小的影响重构到ASP.NET。如果无法做到这一点,那么我们将在经典的ASP中进行更改并整理现有的代码,例如简化包括文件嵌套,用更多的跨浏览器友好的代码替换javascript,这有点。
回答我们有关#ifndef的问题时,恐怕没有对等的答案。
哇。不断让我感到惊讶的是,有多少人讨厌ASP。在体面的手中,它是设计Web应用程序的完美能力的语言。
但是,我承认,在ASP中管理包含文件的方式可能有些麻烦-因为(取决于我们使用它们的方式)它们必须被加载和解析,即使我们没有使用其中包含的功能的一半。
我倾向于有一个包含文件(" initialise.asp"或者类似文件),它本身包含指向多个函数库(" lib_http.asp"," lib_mssql.asp"或者类似文件)的链接,并且所有库函数都是自包含的,因此不用担心交叉变量。任何全局变量都在主文件中声明和设置。这意味着我可以在任何地方,任何时间使用函数,而不必担心它的定义位置,因为它就在这里使用。当我们发现对我们不认识的函数的调用时,Visual Studio和Primalscript之类的IDE可以"跳转到定义"。
然后,在对该主包含文件的调用之后,脚本中将包含任何特定于脚本的包含。
我承认这是一种内存消耗大的方法,因为所有库中的所有函数都是针对每个脚本调用进行编译的,因此该方法需要针对我们开发的每个站点进行完善-决定通过master include调用什么以及还有更多页面-具体的。能够只加载所需的东西会很好-但这是DLL方法,不适用于大多数实际开发,而且我们还必须权衡编译小脚本与加载的处理器成本成分。
简洁的目录结构是必需的,并且易于开发,但是要遍历现有站点中的所有代码并更改任何链接或者mappath调用,可能会很麻烦。另外,请注意,某些IIS管理员禁止通过VBScript遍历目录的'.. '方法,因此所有文件引用都必须是绝对路径。
- 使用一个文件作为全局标题,并包含(将其命名为t-head.asp)。此文件包含在所有asp文件中。
- 使用一个文件使站点具有可见的全局标题(徽标,菜单等),并将其包含在后面。让我们称之为t-begin.asp
- 使用一个文件使站点可视化全局页脚(版权,Google Analytics等),并关闭在t-begin.asp中打开的所有div或者表。让我们将此文件称为t-end.asp
- 使用一个文件夹放置称为BUS的业务逻辑文件。该文件夹中的文件不能包含。文件中的每个函数都必须以逻辑单元的名称开头(即:product.asp中的所有函数都必须以product_ *开头)
- 使用一个文件夹放置一些重用的UI代码,称为UI。该文件夹中的文件不能包含。
例子:
<%@ Language=VBScript %> <% Option Explicit %> <% Response.Buffer = true%> <html> <head> <!--#include file="../general/t-head.asp"--> <!--#include file="../bus/product.asp"--> <title>Products page</title> </head> <body> <!--#include file="../general/t-begin.asp"--> <% 'all your code %> <!--#include file="../general/t-end.asp"--> </body> </html>
我不知道一种防止重复包含的方法,只能得到一条错误消息。我们是否看到包含在整个页面中的附件,这使得它们很难被发现?
顺便说一句,我们是否在开发服务器上使用代码和数据库的副本?根据我的经验,第一件事就是尽快将自己从实时站点中分离出来。最初虽然很麻烦,但它使我们可以自由进行更改,而不会破坏实时站点。在include和BAM中轻松进行微小更改很容易!整个站点都关闭了。
我已经完成了一些像我们描述的项目,并且使用了以下策略:
有时间/金钱的情况下可以完全重写,但是通常在出现问题并尽快需要结果时才能接到电话。
较小的项目我会在IDE中打开所有内容,然后才开始在所有项目文件中搜索功能/子项,以增强对include逻辑的了解。几乎每次都将所有内容散布到各处,因此我开始重建由业务逻辑组织的包含项。我还遇到了内联代码(原始代码,而不是子代码或者函数),这些代码都包含在其中,因此我通常只将代码拉回到页面中,以便以后进行重构。
较大的项目,我将使用一些代码来解析包含子/函数标题的行的包含,并将其转储到文本文件中,以建立例程所在位置的列表并引用该例程。当我们在每个页面上都有大量包含并且无法理解代码库时,这会派上用场。