论坛首页 Java企业应用论坛

代码擂台,特别有请buaawhl

浏览 69603 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-07-16  
庄表伟 写道
to:buaawhl

你没有理解我的意思,第一个题,关键在于rowspan="n",这个n要等于该学生的选修科目数。

第二个题,关键在于子服务的数目不一定能被4整除,剩下的空位,要用 补足。

更加根本的问题在于,你的模板,有没有对逻辑判断的支持,支持程度如何?


对不起,我的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>&amp;</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}", "&amp;");;
                    }
                    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++,都不能直接支持中文。
0 请登录后投票
   发表时间:2004-07-16  
引用
我的模板绝对不支持逻辑判断。一点都不支持。
我千辛万苦,呕心沥血才好容易把“logic pollution”从模板中驱逐出去。
这是fastm模板的最关键亮点之一。这是fastm模板“所见即所得”的根本原因。

所有逻辑由代码来做,是吗?

buaawhl大大回答一下potian大大的问题
引用
该框架是属于模版技术(例如velocity)还是属于MVC(例如是struts或者webwork)框架,如果是纯粹的模版,那么应该可以和Xwork等Action框架结合,甚至是作为Webwork的一种页面展示技术
如果是完整的MVC框架,那么该框架如何处理与服务层的交互,譬如是否可以注入,框架是否支持interceptor,准备如何与其他的验证框架结合,资源和文本i18n如何考虑,如何处理模版的缓存,一个成功的框架应该具备这方面的东东。当然目前完全可以只有核心,如果作者能把总体的设计思路解释一下,应该可以吸引很多的志愿者在这方面帮助。
0 请登录后投票
   发表时间:2004-07-16  
dhj1 写道
庄表伟 写道
这就更不对了,如果在数据部分,还要考虑到显示的逻辑,那不是乱了?


我在这个论坛上有一个专栏的, STRUTS+DAO+HIBERNATE 程序模板设计笔记,照着用就可以了


由于fastm本身是作为一种DOM结构而存在。
操作方法也都是按照DOM的操作方法。
这和操作HTML DOM的方法是一样的。
总是需要直接把 数据 直接放到 模板的节点上。
在fastm中,需要操作ValueSet DOM。当然要把显示的数据放到节点里面。
对于XML DOM程序员来说,这是最自然的思路了。

而把逻辑放在模板中。那些和HTML纠结在一起的逻辑是无法分离为 独立的方法或 类的。也就是,那些逻辑根本不具有可重用性。
页面逻辑越复杂,这个问题就越明显。

所以,非常感谢你的例子。能够很清楚地体现这个问题。
对于DOM或者fastm来说,任何一部分的逻辑代码都具有可重用性。
因为逻辑就存在于Java Code中。
0 请登录后投票
   发表时间: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是一样的。
0 请登录后投票
   发表时间: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认为,既然是页面,就不应该包括任何逻辑。
0 请登录后投票
   发表时间: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中,因为它是显示的逻辑,而不是业务的逻辑。
0 请登录后投票
   发表时间:2004-07-16  
我用过的server端脚本来说,我觉得Velocity已经足够好,无论从设计思路、使用的方便程度、语法的简练都比JSP强很多。
我不知道fastm是什么,或者为什么需要要去重新发明一个轮子。
我不知道没有逻辑语句的View模板能做什么。
把显示逻辑放到后台的Java代码中,在后台写200行的代码,只是为了在前台节约10行逻辑代码?哦,多么美妙的想法。
0 请登录后投票
   发表时间: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结构中的任何位置。
0 请登录后投票
   发表时间:2004-07-17  
to:buaawhl
给你一个提示,如果你一时还没有想通,我明后天再详细写出来。

你现在的fastm结构主要分为两个部分,Template+ValueSet,Template是面向显示的,ValueSet是面向后台数据的,而你应该再加一个部分,可以称之为ViewLogic是从数据到显示的转换。是Template和ValueSet之间的桥梁。而不是向你现在这样,将ValueSet的填充与显示逻辑中的rowspan之类的数据混为一体。

先写到这里,提示你一下...
0 请登录后投票
   发表时间:2004-07-17  
庄表伟 写道
to:buaawhl
给你一个提示,如果你一时还没有想通,我明后天再详细写出来。

你现在的fastm结构主要分为两个部分,Template+ValueSet,Template是面向显示的,ValueSet是面向后台数据的,而你应该再加一个部分,可以称之为ViewLogic是从数据到显示的转换。是Template和ValueSet之间的桥梁。而不是向你现在这样,将ValueSet的填充与显示逻辑中的rowspan之类的数据混为一体。

先写到这里,提示你一下...


多谢提示。
我希望能够多听取到你的意见和思路。
如果百忙之余有时间,请详细写出来。
将是对我的很大帮助。多谢。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics