锁定老帖子 主题:代码擂台,特别有请buaawhl
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-07-16
庄表伟 写道 to:buaawhl
你没有理解我的意思,第一个题,关键在于rowspan="n",这个n要等于该学生的选修科目数。 第二个题,关键在于子服务的数目不一定能被4整除,剩下的空位,要用&nbsp;补足。 更加根本的问题在于,你的模板,有没有对逻辑判断的支持,支持程度如何? 对不起,我的HTML功底很差。开始我都不知道rowSpan和colSpan的意思。理解起来比较困难。现在我明白了。 先回答你的问题。 我的模板绝对不支持逻辑判断。一点都不支持。 我千辛万苦,呕心沥血才好容易把“logic pollution”从模板中驱逐出去。 这是fastm模板的最关键亮点之一。这是fastm模板“所见即所得”的根本原因。 下面是我的HTML文件和代码。 运行环境需要fastm.jar. http://sourceforge.net/projects/fastm score.html <table> <tr> <td>name</td> <td>average score</td> <td>suject</td> <td>score</td> </tr> <!-- BEGIN INGNORED: sample_data --> <tr> <td rowspan="2">Li Si</td> <td rowspan="2">85</td> <td>Chinese</td> <td>80</td> </tr> <tr> <td>math</td> <td>90</td> </tr> <!-- END INGNORED: sample_data --> <!-- BEGIN DYNAMIC: tr --> <tr> <td rowspan="{nSubject}">{name}</td> <td rowspan="{nSubject}">{average_score}</td> <td>{subject}</td> <td>{score}</td> </tr> <!-- BEGIN DYNAMIC: subject--> <tr> <td>{subject}</td> <td>{score}</td> </tr> <!-- END DYNAMIC: subject --> <!-- END DYNAMIC: tr --> </table> service.html <table> <!-- BEGIN DYNAMIC: service_class --> <tr> <td colspan="4">{service_class}</td> </tr> <!-- BEGIN DYNAMIC: tr --> <tr> <!-- BEGIN DYNAMIC: td --> <td>{service}</td> <!-- END DYNAMIC: td --> <!-- BEGIN IGNORED: sample_data --> <td>A1 Service</td> <td>A2 Service</td> <td>&</td> <!-- END IGNORED: sample_data --> </tr> <!-- END DYNAMIC: tr --> <!-- END DYNAMIC: service_class --> </table> 注意,上面的两个模板中都包括了sample数据。 被IGNORED包括,所以不成为fastm Template DOM的一个部分。 只是为了“所见即所得”的显示作用。 java code: package fastmtest; import java.util.*; import net.sf.fastm.*; import java.io.*; /** * <p>Title: Fast Template</p> * <p>Description: Fast Template For XML File (Using XML Comment as Tag);</p> * <p>Copyright: Copyright (c); 2004</p> * <p>Company: </p> * @author Wang Hailong * @version 1.0 */ class TestTable { /** * set the parameter tree * * @return IValueSet */ public static IValueSet makeScore();{ Object[][] data = { {"Zhang San", "Chinese", new Integer(80);}, {"Li Si", "Chinese", new Integer(80);, "math", new Integer(90);} }; IValueSet topValueSet = new ValueSet();; // the whole document List trs = new ArrayList(data.length);; for(int i = 0; i < data.length; i++);{ IValueSet tr = new ValueSet();; Object[] info = data[i]; int nSubject = (info.length - 1); / 2; tr.setVariable("{nSubject}", new Integer(nSubject););; tr.setVariable("{name}", info[0]);; tr.setVariable("{subject}", info[1]);; tr.setVariable("{score}", info[2]);; // calculate the average score int totalScore = 0; List subjects = new ArrayList(nSubject - 1);; for(int j = 2; j < info.length; j += 2);{ totalScore += ((Integer);info[j]);.intValue();; if(j < 4); continue; IValueSet subject = new ValueSet();; subject.setVariable("{subject}", info[j - 1]);; subject.setVariable("{score}", info[j]);; subjects.add(subject);; } int averageScore = totalScore / nSubject; tr.setVariable("{average_score}", new Integer(averageScore););; tr.setDynamicValueSets("subject", subjects);; trs.add(tr);; } topValueSet.setDynamicValueSets("tr", trs);; return topValueSet; } /** * set the parameter tree * * @return IValueSet */ public static IValueSet makeService();{ Object[][] data = { {"Service Class A", "A1 Service", "A2 Service", "A3 Service", "A4 Service"}, {"Service Class B", "B1 Service", "B2 Service", "B3 Service", "B4 Service", "B5 Service", "B6 Service"}, }; IValueSet topValueSet = new ValueSet();; // the whole document List serviceClasses = new ArrayList(data.length);; for(int i = 0; i < data.length; i++);{ IValueSet serviceClass = new ValueSet();; Object[] info = data[i]; serviceClass.setVariable("{service_class}", info[0]);; int nServices = info.length - 1; int nTR = nServices / 4; if(nServices % 4 > 0); nTR++; int count = 1; List trs = new ArrayList(nServices);; for(int j = 0; j < nTR; j++);{ List tds = new ArrayList(4);; for(int k = 0; k < 4; k++);{ IValueSet td = new ValueSet();; if(count < info.length);{ td.setVariable("{service}", info[count]);; }else{ td.setVariable("{service}", "&");; } tds.add(td);; count++; } IValueSet tr = new ValueSet();; tr.setDynamicValueSets("td", tds);; trs.add(tr);; } serviceClass.setDynamicValueSets("tr", trs);; serviceClasses.add(serviceClass);; } topValueSet.setDynamicValueSets("service_class", serviceClasses);; return topValueSet; } /** * * @param args String[] * @throws Exception */ public static void main(String[] args); throws Exception{ TemplateLoader scoreTemplate = new TemplateLoader("score.html");; FileWriter fw = null; fw = new FileWriter("score.result.html");; IValueSet valueSet = makeScore();; // get value set fw.write(scoreTemplate.toString(valueSet););;// assign the value set to the template fw.close();; TemplateLoader serviceTemplate = new TemplateLoader("service.html");; fw = new FileWriter("service.result.html");; valueSet = makeService();; // get value set fw.write(serviceTemplate.toString(valueSet););; // assign the value set to the template fw.close();; } } 其中生成ValueSet DOM的代码完全是可以重用的。 假设换一种显示风格或布局风格。比如用List,DIV等。 只要把模板一换(所见即所得),这段代码的输出自动换成另一种风格。 比XML/XSLT还要方便。XSLT很难,更别想“所见即所得”了。 想象一下,如何用Velocity为相同的数据实现不同的HTML显示风格或者布局风格。:-) 非常感谢楼主 特别邀请我。还请多多交流。 另外,我写的HTML和Java Code没有用中文。 因为我的计算机的Default Locale是英文。 我用的都是开源的编辑器gVim和notepad++,都不能直接支持中文。 |
|
返回顶楼 | |
发表时间:2004-07-16
引用 我的模板绝对不支持逻辑判断。一点都不支持。
我千辛万苦,呕心沥血才好容易把“logic pollution”从模板中驱逐出去。 这是fastm模板的最关键亮点之一。这是fastm模板“所见即所得”的根本原因。 所有逻辑由代码来做,是吗? buaawhl大大回答一下potian大大的问题 引用 该框架是属于模版技术(例如velocity)还是属于MVC(例如是struts或者webwork)框架,如果是纯粹的模版,那么应该可以和Xwork等Action框架结合,甚至是作为Webwork的一种页面展示技术
如果是完整的MVC框架,那么该框架如何处理与服务层的交互,譬如是否可以注入,框架是否支持interceptor,准备如何与其他的验证框架结合,资源和文本i18n如何考虑,如何处理模版的缓存,一个成功的框架应该具备这方面的东东。当然目前完全可以只有核心,如果作者能把总体的设计思路解释一下,应该可以吸引很多的志愿者在这方面帮助。 |
|
返回顶楼 | |
发表时间:2004-07-16
dhj1 写道 庄表伟 写道 这就更不对了,如果在数据部分,还要考虑到显示的逻辑,那不是乱了?
我在这个论坛上有一个专栏的, STRUTS+DAO+HIBERNATE 程序模板设计笔记,照着用就可以了 由于fastm本身是作为一种DOM结构而存在。 操作方法也都是按照DOM的操作方法。 这和操作HTML DOM的方法是一样的。 总是需要直接把 数据 直接放到 模板的节点上。 在fastm中,需要操作ValueSet DOM。当然要把显示的数据放到节点里面。 对于XML DOM程序员来说,这是最自然的思路了。 而把逻辑放在模板中。那些和HTML纠结在一起的逻辑是无法分离为 独立的方法或 类的。也就是,那些逻辑根本不具有可重用性。 页面逻辑越复杂,这个问题就越明显。 所以,非常感谢你的例子。能够很清楚地体现这个问题。 对于DOM或者fastm来说,任何一部分的逻辑代码都具有可重用性。 因为逻辑就存在于Java Code中。 |
|
返回顶楼 | |
发表时间:2004-07-16
我的做法可能和很多人不一样,我是DAO+iBatis
有VO,没有PO,我所有的数据交互都是XML,IE取到Servlet返回的XML在显示,Servlet读XML调用DAO做处理。 我这样做有另外一个考虑,在实际中B/S 以及C/S要一起存在,也就是说,有B/S还有C/S,使用XML做数据交互,B/S C/S很多代码可以重用至少Server是一样的。 |
|
返回顶楼 | |
发表时间:2004-07-16
ziyi 写道 所有逻辑由代码来做,是吗? potian的问题 引用 该框架是属于模版技术(例如velocity)还是属于MVC(例如是struts或者webwork)框架,如果是纯粹的模版,那么应该可以和Xwork等Action框架结合,甚至是作为Webwork的一种页面展示技术
如果是完整的MVC框架,那么该框架如何处理与服务层的交互,譬如是否可以注入,框架是否支持interceptor,准备如何与其他的验证框架结合,资源和文本i18n如何考虑,如何处理模版的缓存,一个成功的框架应该具备这方面的东东。当然目前完全可以只有核心,如果作者能把总体的设计思路解释一下,应该可以吸引很多的志愿者在这方面帮助。 没错,所有的逻辑代码来做。 fastm只是属于模版技术(例如velocity)。 lightweb是Web Framework。但lightweb非常简单,不属于MVC。 另外,感谢ziyi的例子。可见ziyi对fastm的理解程度和支持程度。 那段代码看起来很长,但实际的应用中,很多部分都可以用公用方法来实现。 代码的重用性非常强。结果在整个页面逻辑范围内,造成整体代码的结构化和重用化。 比如,把一个bean的属性设到IValueSet中,完全可以用一个通用方法实现。 在比如,那段切分ValueSet DOM的代码,或者 任何操作IValueSet的代码都可以分离出来,成为通用方法。 你可以比较一下Velocity代码的可读性,和可理解性。 而且,你可以看到,所有的Velocity代码都避免在模板中作平均值计算。 Velocity要把 显示逻辑 和 计算逻辑 分开。 这种分开其实是 人为的概念(为了支持MVC结构)造成的。 于是大家都理所当然地认为,既然是页面,就应该只包含显示的逻辑。不应该包含数据计算的逻辑。 而fastm认为,既然是页面,就不应该包括任何逻辑。 |
|
返回顶楼 | |
发表时间:2004-07-16
引用 而fastm认为,既然是页面,就不应该包括任何逻辑。
如果能那样的话,Velocity的下一个版本就可以只保留#foreach和#set了,没有必要#if #else #end这样的语句了,可能吗?纯粹只是理想。 我想庄的例子是要说明:制作稍微复杂的页面,即使是使用已经很MVC的模板脚本语言(Velocity已经很淡化了脚本的逻辑控制功能,例如它只提供#foreach,甚至都没有#for和#while),也需要自己来写显示逻辑。 你可以将业务逻辑尽量的封装,这看你OO的功底了,如果你OO的功底很不错,你就可以提供封装得足够好的简单的几个对象到Velocity中,但是--------但是--------因为Velocity, JSP与HTML的天生的关系,碰到诸如动态决定rowspan, colspan的值的时候,你没有办法不去借助Velocity或JSP提供的逻辑控制语句。 而这些,你是不可能封装在Java Object中,因为它是显示的逻辑,而不是业务的逻辑。 |
|
返回顶楼 | |
发表时间:2004-07-16
我用过的server端脚本来说,我觉得Velocity已经足够好,无论从设计思路、使用的方便程度、语法的简练都比JSP强很多。
我不知道fastm是什么,或者为什么需要要去重新发明一个轮子。 我不知道没有逻辑语句的View模板能做什么。 把显示逻辑放到后台的Java代码中,在后台写200行的代码,只是为了在前台节约10行逻辑代码?哦,多么美妙的想法。 |
|
返回顶楼 | |
发表时间:2004-07-17
derbysoft 写道 我用过的server端脚本来说,我觉得Velocity已经足够好,无论从设计思路、使用的方便程度、语法的简练都比JSP强很多。
我不知道fastm是什么,或者为什么需要要去重新发明一个轮子。 我不知道没有逻辑语句的View模板能做什么。 把显示逻辑放到后台的Java代码中,在后台写200行的代码,只是为了在前台节约10行逻辑代码?哦,多么美妙的想法。 关于代码长度的问题。我这里解释一下(我以为不用解释:-))。 仔细观察一下两种代码。 (1) 我写的代码是按照Java风格。 为了可读性。换行,空行,注释很多。 并且为了效率,声明了很多局部变量。并用了比较长的变量名。 你仔细观察一下Velocity的代码。声明的局部变量很少。 你会发现,service.get(1).size() 用了很多次。 有些if else 写在一行。基本没有空行。 我如果把我的Java代码也换成这样的风格。代码长度几乎一样。 而且,如果是中间夹杂的HTML Text和Tag很多的情况下。 Velocity的代码长度看起来如何? 实际的项目应用中,本例这种简单的HTML几乎是不可能的。中间总是夹杂了很多背景图片、风格、字体的定义,虽然,CSS能够帮助解决一点这个问题。 (2) 而且,你可以看到,Velocity代码中避免了计算平均值的过程。 如果加上那部分,Velocity代码的复杂度将会大幅增加。 所以,这里的假设是,服务端已经计算好了平均值,放到request.attribute里面。Velocity把这些东西取出来显示。 那么,想想看,Velocity服务端的代码:计算平均值,把所有需要的数据组织为List,放到request.attribute里面。这段代码的长度如何? Velocity的逻辑代码分布在模板 和 Server Java Code两个部分。 而fastm的逻辑代码在存在于 Server Java Code部分。 要比较代码长度,fastm的总代码通常更短。 (3) 据说,“既然是页面处理逻辑,就应该放在模板中。” 我来问一个格式化的问题。 比如,我们要把当前的时间,根据不同情况,显示不同的时间格式。 这段根据不同情况“格式化时间”的代码,应该放在Velocity模板中,还是放在Server端代码中? (4) “我不知道没有逻辑语句的View模板能做什么。” fastm是没有逻辑语句的模板。 fastm只能做一件事情,定义页面的DOM层次关系,和动态数据占位符。 所有的逻辑,不管是计算,还是动态数据的组织,都在Java Code中作。 所以,fastm能够做到任何事情。 至于View,是MVC结构的概念。 而MVC结构是为了支持JSP等模板技术而出现的结构。 fastm当然可以支持MVC。就象Velocity做的那样(velocity-tools)。 有兴趣请阅读org.apache.velocity.tools.view.servlet的 VelocityViewServlet类的代码。 你可以看到,Velocity是如何支持MVC的,付出了如何的代价。 Servlet规范又付出了怎样的代价。 参见VelocityViewServlet类的一段代码。 * @return Velocity Template object or null */ protected Template handleRequest(HttpServletRequest request, HttpServletResponse response, Context ctx); throws Exception { // If we get here from RequestDispatcher.include();, getServletPath(); // will return the original (wrong); URI requested. The following special // attribute holds the correct path. See section 8.3 of the Servlet // 2.3 specification. String path = (String);request.getAttribute("javax.servlet.include.servlet_path");; if (path == null); { path = request.getServletPath();; } return getTemplate(path);; } 没有逻辑语句的View模板。 还有Barracuda的XMLC。直接操作HTML DOM结构。 http://xmlc.enhydra.org/ fastm模板也是DOM结构。 至于DOM结构能做到什么。 DOM结构能够做到任何你能想到的组装方式。 把任意一个DOM结构的任何一个节点,修改,复制, 加入到任何一个DOM结构中的任何位置。 |
|
返回顶楼 | |
发表时间:2004-07-17
to:buaawhl
给你一个提示,如果你一时还没有想通,我明后天再详细写出来。 你现在的fastm结构主要分为两个部分,Template+ValueSet,Template是面向显示的,ValueSet是面向后台数据的,而你应该再加一个部分,可以称之为ViewLogic是从数据到显示的转换。是Template和ValueSet之间的桥梁。而不是向你现在这样,将ValueSet的填充与显示逻辑中的rowspan之类的数据混为一体。 先写到这里,提示你一下... |
|
返回顶楼 | |
发表时间:2004-07-17
庄表伟 写道 to:buaawhl
给你一个提示,如果你一时还没有想通,我明后天再详细写出来。 你现在的fastm结构主要分为两个部分,Template+ValueSet,Template是面向显示的,ValueSet是面向后台数据的,而你应该再加一个部分,可以称之为ViewLogic是从数据到显示的转换。是Template和ValueSet之间的桥梁。而不是向你现在这样,将ValueSet的填充与显示逻辑中的rowspan之类的数据混为一体。 先写到这里,提示你一下... 多谢提示。 我希望能够多听取到你的意见和思路。 如果百忙之余有时间,请详细写出来。 将是对我的很大帮助。多谢。 |
|
返回顶楼 | |