悠然乱弹:从一段代码讲开去

序言

今天偶然看到一框架,在框架的里面有一段这样的描述:

?


1

2

xxx并不愿意其他人来直接修改YYY框架的代码,因为XXX致力于将它打造为完美的作品,其他人写的代码,实在没有加入进来的意义。

但是您可以当小白鼠,提意见,提bug,好的idea我还是愿意接受的。

这里解释一下,其中xxx是作者名字,YYY是框架名称,这么OSC上牛人众多,牛到这个程度的还是第一次见到,于是就想去速度学习一下。其实框架好不好,看例子代码就可以看出一二,去找了找,果然找到了示例代码,我摘了两个方法:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

/**

   * 发布文章

   *

   * @return

   */

  public Object add(){

    Request r = Context.get(Statics.REQUEST);

    String title = r.get("title");

    String desc = r.get("desc");

    String content = r.get("content");

    String cats = r.get("cats");

    String pic = r.get("pic");

    String keywords = r.get("keywords");

    List<String> l = new ArrayList<String>();

    String[] cs = cats.split(",");

    for(String s:cs){

      s = s.trim();

      if(!s.equals("")){

        l.add(s);

      }

    }

    Validator.check(title,new RuleNotEmpty("标题"));

    HttpSession session = r.find(WebExecute.TAG_SESSION);

    User user = (User)session.getAttribute(Global.SESSION_USER);

    ITrans t = TransFactory.getTrans();

    String id = ID.next()+"";

    IInserter ins = t.getInserter().table("T_ARTICLE");

    ins.set("C_ID",id);

    ins.set("C_TITLE",title);

    ins.set("C_DESC",desc);

    ins.set("C_USER_ID",user.getId());

    ins.set("C_CONTENT",content);

    ins.set("C_TIME",Dater.ymdhms(Dater.now()));

    ins.set("C_DAY",Dater.ymd(Dater.now()));

    ins.set("C_PIC",pic);

    ins.set("C_KEYWORDS",keywords);

    ins.insert();

    if(l.size()>0){

      for(String cat:l){

        t.getInserter().table("T_ARTICLE_CAT").set("C_ID",ID.next()).set("C_ARTICLE_ID",id).set("C_CAT_ID",cat).insert();

      }

    }else{

      t.getInserter().table("T_ARTICLE_CAT").set("C_ID",ID.next()).set("C_ARTICLE_ID",id).set("C_CAT_ID",1).insert();

    }

    t.commit();

    t.close();

    return new Tip("发布成功");

  }

 

  /**

   * 修改文章

   *

   * @return

   */

  public Object modify(){

    Request r = Context.get(Statics.REQUEST);

    long id = r.getLong("id");

    String title = r.get("title");

    String desc = r.get("desc");

    String content = r.get("content");

    String cats = r.get("cats");

    String pic = r.get("pic");

    String keywords = r.get("keywords");

    List<String> l = new ArrayList<String>();

    String[] cs = cats.split(",");

    for(String s:cs){

      s = s.trim();

      if(!s.equals("")){

        l.add(s);

      }

    }

    Validator.check(title,new RuleNotEmpty("标题"));

    HttpSession session = r.find(WebExecute.TAG_SESSION);

    User user = (User)session.getAttribute(Global.SESSION_USER);

    Logger.getLog().info(desc);

    ITrans t = TransFactory.getTrans();

    IUpdater iup = t.getUpdater().table("T_ARTICLE");

    iup.where("C_ID",id);

    iup.set("C_TITLE",title);

    iup.set("C_DESC",desc);

    iup.set("C_USER_ID",user.getId());

    iup.set("C_CONTENT",content);

    iup.set("C_PIC",pic);

    iup.set("C_KEYWORDS",keywords);

    iup.update();

    t.getDeleter().table("T_ARTICLE_CAT").where("C_ARTICLE_ID",id).delete();

    if(l.size()>0){

      for(String cat:l){

        t.getInserter().table("T_ARTICLE_CAT").set("C_ID",ID.next()).set("C_ARTICLE_ID",id).set("C_CAT_ID",cat).insert();

      }

    }else{

      t.getInserter().table("T_ARTICLE_CAT").set("C_ID",ID.next()).set("C_ARTICLE_ID",id).set("C_CAT_ID",1).insert();

    }

    t.commit();

    t.close();

    return new Tip("修改成功");

  }

今天在某著名群里贴了一个方法,结果下面有同学说:“不是挺清楚的?我觉得就不错。”

当时正在忙,没有时间详细介绍,于是决定晚上抽个时间给分析讲解一下,不能保证全部是对的,也不能保证全部能够被人接受,但是一定可以促进大家思考一些框架开发中的问题:

  1. 什么是框架?
  2. 到底设计的时候应该考虑哪些问题?
  3. 怎样才是一个及格的框架?

问题的解答

上面提出了三个问题,这三个问题说复杂也非常复杂,三天两天说不清楚;说简单也简单,一句话就说清楚了。

什么是框架?这个问题实际上许多“做框架”的人也不明白。

框架和库的本质不同在于:

  • 框架考虑的是机制的复用,而库主要考虑的是代码的复用
  • 框架考虑的是在机制不变的情况下进行扩展,而库则基本不考虑扩展方面的问题
  • 框架本身是不完整的,在大多数的情况下它自己是干不了啥事情的,而库自身是完整的,可以解决某个领域的问题。
  • 框架是活的,通过不断的扩展与衍生,它就更加强大,而库而是死的,发布时是怎样,就是怎样。

当然,关于这两货之间的比较,还有许多个角度,但我个人觉得本质是我上面举的这些。

设计的时候应该考虑哪些问题?这个问题的答案,如果用一句话来解符号,那答案就是:要仔细考虑使用这个框架的人感受,要考虑如何让使用者感觉爽的问题。当然如果是三天两天说不清楚的方式,那就得从方法论,问题领域,设计原则等待进行阐述了。

怎样才是一个及格的框架?这个问题,用一句话解释,就是在满足上一个问题的情况下不违背基本设计原则,那么就可以算是一个及格的框架。如果用三天两天说明,那就要把所有的基本设计原则拿出来,一个个讲讲清楚,一个个说说明白。 

如果满足了第一个条件,使用者是满意的,从使用来说是不错的;如果满足了第二个条件来说,从设计及实现来说是不错的。如果两个都满足了那说明,最起码是可用的及格的框架,当然也可能得分更多。

代码分析

好的,上面大致讲了一个框架设计过程中要考虑的一些问题,下面就实质性的考虑一下上面的代码,我承认,我没有看里面“框架中具体的实现”,下面的全部“结论”其实都是我的一种判断或猜测,如有不对,欢迎指正:

  1. 这两个方法看起来是那么那么的相像,怎么看都不太协调
  2. Context看起来是个静态类,说明他一定有个ThreadLocal之类的东西在进行一些数据的存储,如果使用的是ThreadLocal其实还是有许多要注意的内容的,个人一般不太推荐采用这种方式进行数据传输。
  3. 数据获取:居然是通过request对象来直接读取值的,当然看得出来这个request作者已经进行了一些封装,但是显然,开发人员会对这个极度反感的。
  4. 事务处理:所有的处理都是自己在代码中写的,好吧,如果所有的业务都在一个方法中编写,那么是OK的,如果不是的话,就麻烦大了。
  5. 数据校验:也是在这个方法内部创建校验对象进行校验的,所以看到在两个方法中都有同样的代码来做同样的事情。
  6. 异常处理:没有看到异常处理方面的内容,因此不知道如果要操作的表不存时发生异常的时候,前台看到一个什么结果,是一大堆异常栈么?
  7. 函数声明:从函数的声明处是看不到传入和传出参数的,因此就决定了所有的处理都是要从上下文中获取Request,Session啥的自己把数据搞出来的。它的返回值是Object,这说明啥意思呢?说明在Jsp展现里应该是进行类型强转的。
  8. 代码重复:由于事务都是写在方法里的,也就说明这些方法不能重用,许多代码都要重复编写。
  9. 处理能力扩展:由于数据库处理与业务展现放在一起,说明是一个典型的B/S架构,也就是说处理能力是非常容易估算的,而且进行水平扩展的能力也比较有限。也说明 系统的安全性比较弱(数据库与应用服务器在同一层上,如果攻破了应用服务器,就会有倒库行为的发生)
  10. 事务对象:有一个疑问:t.commit中为什么还要执行一个t.close?如果commit的时候发生一个异常,到底是close上没有?如果没有close上,外面异常处理怎么处理?

再来分析一下它里面违反一些常见现象对象设计原则的点:

单一原则:在一个方法里做了太多的事情,这种代码以后改的时候有多累呀

抽象原则:没有独立的Dao及Pojo,没有把Dao层,业务层进行剥离,从而导致数据的验证要重复的进行,这块的处理也不能进行复用。可以想想,如果想让这两方法提供的添加和修改功能通过Json或WebService对外提供服务,程序员唯一可行的办法就是再写两方法。

DRY原则:不要做重复的工作,代码中的重复实在太多了,这一点有可能是笔都只是为了说明意思或者随意了。

自动原则:如果能程序化自动完成的,不要让程序员手动完成。

总结

只看这两段代码总结出来的内容不一定全部正确,如果有不正确的地方,欢迎海涵并批评指正。

其实之所以对这两段代码进行分析,是经过作者同意的,一来这两段代码比较典型,可遇而不可求,另外也希望代码作者能够高调做事,低调做人,扎扎实实做出一个别人无法进行再优化改良的框架来。

时间: 2024-12-31 03:12:04

悠然乱弹:从一段代码讲开去的相关文章

悠然乱弹:从几个方法的重构讲开去--性能大优化

现在还存在多次扫描处理的问题,也就是说虽然代码结构性重构是成功的,但是性能问题还是没有根本解决. 在给出解决方案之前,需要对这个处理方式缕一缕: 处理方式1:每次遍历全路径找到待处理文件,文件然后批量进行处理.优点是处理起来比较简单,但是会重复扫描. 处理方式2:一次遍历所有文件,然后对每个文件进行注解检测.扫描全路径只有一次,然后要把每个文件与过滤器进行比较如果比较成功那就做,比较不成功就不做. 稍加分析就会发现,两种方式的比较次数是一样的,但是第二种方案遍历文件的次数就少到极限了,还能比1次

悠然乱弹:从几个方法的重构讲开去--注解相关的处理

有时候它们的处理没有关联性,有些时候,它们的处理又是有关联性的. 我们用伪代码来示意一下. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if(includeAnnotation(testClass,Abc.class)){   doSomething... }   if(includeAnnotation(testClass,Abc.class)){   for(Field field:testClass.getFields){     if(include

悠然乱弹:从几个方法的重构讲开去--文件相关的处理

简单看看吧,确实没有什么好的解决方案,那我们就抽丝剥茧,看看这三个方法里都涉及到哪些个领域? 涉及到注解方面的处理 涉及到多种注解方面的处理 涉及到文件查找方面的问题 涉及到多种资源文件查找方面的问题-file,jar 涉及到对查找到资源文件之后的后续处理的问题 好吧,可能还有别的问题,我们先利用上面分析出来的问题,看看有没有着手之处?? 仔细分析下来,暂时有三种要遍历的文件了,file,jar,自定义ClassLoader,那我们简单抽象一下: ? 1 2 3 4 5 6 7 8 9 10 1

悠然乱弹:从几个方法的重构讲开去--引言

引言: 在学习代码的过程中,看到如下几个工具方法: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

悠然乱弹:一段SQL引发的性能危机及其背后隐藏的设计缺陷

故事发生的背景是,在文件上传的时候,有时间会有人上传了文件,但是最后没有使用上传的文件,这样就会产生一些垃圾文件. 原来软件作者就想写一个后台定时任务程序,来清除这些垃圾文件? 由于作者坚定的不让我发她的SQL语句(这个我也理解,这么丑陋的SQL),所以这里就不发源代码了,发伪代码. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void deleteMissLinkFile{   List fileList=getFileList();   List delete

url-求解释下这段代码,拜托了,各位大神,可怜可怜我这个新手吧,

问题描述 求解释下这段代码,拜托了,各位大神,可怜可怜我这个新手吧, 求解释下这段代码,最主要的是详细解释下最后编辑的那个地方,那个好像是各种嵌套吧,所以我希望大神们能一个点一个点的讲~拜托了,各位大神,可怜可怜我这个新手吧, <s:iterator value="gongWenLeiBieList" status="st" var="cil"> <TR> <TD class="tdStyle"

javascript-求解释下这段代码,可怜可怜我这个新手吧,拜托了,各位大神

问题描述 求解释下这段代码,可怜可怜我这个新手吧,拜托了,各位大神 求解释下这段代码,最主要的是详细解释下条件语句和 onclick,那个好像是各种嵌套吧,所以我希望大神们能一个点一个点的讲~拜托了,各位大神,可怜可怜我这个新手吧, <s:form action="Save" id="form1" theme="simple" > <div class="buttonDiv"> <s:submit

printf-为什么这一小段代码总是运行时错误 求大家帮帮忙

问题描述 为什么这一小段代码总是运行时错误 求大家帮帮忙 #include<stdio.h>#include<string.h>int main(){ int t; scanf(""%d""&t); while(t--) { int n; scanf(""%d""&n); while(n--) { char a[]="">+""; char

当程序员说“这代码写的可真烂”,他们的意思是“这烂代码不是我写的”。而当他们说这段代码有些“小问题”时,很可能这代码是他们自己写的

英文原文:What Programmers Say vs. What They Mean 你是否听到过同事说"这段代码不言自明"?你的同事的这句话的实际意思是这段代码不需要写注释. 你也许注意到了,很多时候,程序员所说的话的字面意思和其真实的意思是完全不同的.不用惊异,下面你将很快知道这些暧昧的短语和其深层次的意思都是什么. 最近 Imgur 上出现了一张图片,里面列举的程序员的一些专业术语和其含义,它能很好的帮助你理解这些话的真实意思.这里是对其中的精华进行的总结. 典型的程序员之间