dotNet 代码检查标准v1.0 发布

by Richard 28. October 2009 12:59

昨天下午的Common Library的讨论,主要是再次评审代码检查的标准。 现在把评审通过的代码检查标准v1.0 的文件发布出来。

APJ Code Review Checklist v1.0.xls (49.00 kb)

大家可以依照这个check list中的内容检查一下,看看自己开发的代码是否符合标准,有不符合的要配合项目组想办法改进。

如果大家对这个代码检查的标准有什么问题和意见,可以在此留言,或直接给我反馈。

Tags:

Common Library | Standard

关于Common Library的一些想法

by Richard 20. October 2009 23:39

目的:

建立和维护一个公司级的可复用公共库,主要为了3个目的:

  1. 提高开发效率,让开发人员从系统级功能的开发中解放出来,把工作重点放在业务级功能的开发。
  2. 提高代码质量,开发人员写的代码越少了,问题就越少。
  3. 改善不同团队,不同项目之间代码风格的一致性,促进团队之间的交流与合作。

 

内容:

主要包含这几种类型:组件、控件、函数库、工具、示例,以及从项目中抽象出的可复用模块。

其实可以考虑把公司的开发规范,代码检查标准也纳入Common Library中一起管理。

 

开发:

当识别出有新的可复用的item,Common Library管理小组要进行讨论,确定基本方案;然后指定负责人,按照要求完成开发,并对验收检查后才能入库。

  

测试:

Common Library中的每一项都是要经过严格的测试后才能发布出来的,测试用例和测试报告都要保留存档,方便检查和以后参考。

可以借助一些单元测试工具,使得测试用例可复用,并自动执行大部分测试,提高测试效率。

 

文档:

主要包含4个文档:

  1. 功能文档:实现了那些功能和特性(feature),还有哪些没有完成的功能(to do list),还有哪些bug没有修复(bug list),版本历史记录(history)。
  2. 使用手册:什么情况可以使用(when to use),从哪里获取最新版本(where to use),如何使用(how to use),和一些注意事项(tip)。
  3. 设计文档:包括Class Diagram,Class Reference,Database ER Diagram。
  4. 测试文档:主要包含测试用例和测试报告。

   
维护:   

配置管理方面也应该分开两个代码库:开发库和产品库。 开发库只有参与Common Library开发的人员可以访问,而产品库是公开只读权限给所有人。只有测试通过的代码,而且相应的文档也同时更新了,经过管理组的同意才能更新到产品库。更新产品库后要发布消息给大家,并告知更新的内容。
要建立一个查询系统,让大家可以方便的查找想要的内容。
定期检查,了解使用情况,收集新需求:在Code Review Checklist中加入对Common Library使用的检查,在项目总结中加入对Common Library使用情况的总结、改进意见、以及推荐项目中可被纳入Common Library的新内容。

 

风险:

执行前需要一个深远的考虑和计划。否则不易执行或不能长久坚持下去。
如果Common Library有更新或发布了新版本,要考虑是否对已经在运行的系统有影响,再决定各个系统是否应用更新。

 

职责:

从上面看下来,要把Common Library建设好,需要做很多的工作。公司应该有专门的人员来做这个工作,建立起相关的组织来管理和维护它。

公司越大,Common Library的意义就越重要,同时也越难管理。如果公司真的要扩大3倍,安排一两个人专门做这个应该不过分。       
   

 

其实Common Library的关键不是建立一个代码库,而是需要相应的管理流程和公司气氛才能使Common Library变得有生命力和发挥更大的效力。

Tags:

Common Library

Common Library 进展

by Richard 17. September 2009 12:32

昨天的Common Library讨论中,主要还是说了权限控制的实现细节,

  • 设置权限的方法放在 override OnPreRender 中,不利于分清楚事件前后的关系,建议放在 override OnPreRenderCompleted,或注册事件的方式。
  • 在control级的控制,现在是使用简单的case判断,给控件的属性赋值,建议使用反射,提高可扩展性。
  • 在control级的控制,当两个角色对某个控件的控制权限矛盾时,如何确定优先级。第一阶段先按照简单的方式做:肯定优先的并集。
  • 对Page和Function级别,要提供一个维护页面的例子。
  • 找控件时,现在使用的是递归的方式,建议改用asp.net 2.0中的新特性,$连接符。


另外,还讨论了大家比较关心的基础数据维护的例子,

  • 确定了三种操作方式

         1,弹出div,做新增,查看,修改。
         2,对于字段比较少的,在Grid中实现新增,修改。
         3,多条数据同时编辑,最后批量更新。

  • 数据访问方式,使用Towngas Team的Lamda表达式解析的方式。
  • 和数据库操作完了后,把相应的用户消息处理放到统一的事件处理程序中做。
  • 排序的 Sort Expression 使用 viewstate 保持。
  • 使用Common Lib中的分页控件。


每次讨论,大家都会提出很多需求和新的想法, 虽然有一些是由于时间有限和技术问题无法在短期内实现。但我觉得这些 new idea 都是很有价值的,所以决定把他们都记录下来,经常的review一下,在合适的时机把它们一一搞定。 也方便后面写文档和测试用。 看附件

Common Lib 备忘录.xls (26.50 kb)


还要提醒一下,后面即将开始的MTR新项目会要求使用我们的新Common Lib,新项目的同事请注意以下附件中的开发进度,如果你们觉得哪些内容是你们要求比较紧迫的,可以告诉我,我们可以适当调整开发进度,尽量满足你们项目的需求。

Common Lib Schedule.xls (23.50 kb)

Tags:

Common Library

Common Library 之 ResourceProvider 多语言实现

by Daniel 19. August 2009 13:33

这个功能相信大家都早已知道。

1. 在在web.config定义特定的culture和uiCulture, 如果应用自定义resource prodiver的话, 加上resourceProviderFactoryType的设置:

如:

<globalization culture="en-us" uiCulture="en-us" resourceProviderFactoryType="MTRC.IRMIS.Common.ResourceProvider.DBResourceProviderFactory, IRMIS.Common "/>

culture和uiCulture也可以设置成auto, 这样就会取浏览器首选区域设定, MTRC.IRMIS.Common.ResourceProvider.DBResourceProviderFactory为provider factory类的命名空间加上类名, IRMIS.Common 则为dll的名字。

2. 运行中更改语言类别。对浏览器首选语言区域的检测是在页面什么周期早期, 可以在basepage基类中overirde InitializeCulture, 并且修改Thread.CurrentThread.CurrentUICulture和Thread.CurrentThread.CurrentCulture。 如:

 

protected override void InitializeCulture()

    {

        string language = string.Empty;

        if (Session["lang"] != null)

        {

            language = Session["lang"].ToString();

        }

        if (!String.IsNullOrEmpty(language) && (language != "Auto"))

        {

            Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);

            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language);

        }

    }

3. 可以在后台也可以在页面上直接调用资源

- 后台方法调用: GetLocalResourceObject 或 GetGlobalResourceObject, 不多说, 相信大家都知道

- 直接在页面有两种方法: 隐式和显式, 下面简单说说他们俩的区别。

a. 调用方法不同(废话, 真是的)

显示表达式:

调用全局资源 <asp:Literal id="Literal1" Text="<%$ Resources:riskCommon, ltrRiskStatus %>" runat="server"></asp:Literal>, 其中riskCommon是resource type字段, ltrRiskStatus是resource key

调用本地资源<asp:Literal ID="ltrUserName" runat="server" Text="<%$ Resources:ltrUserName %>"></asp:Literal>

隐式表达式:

调用本地资源<asp:Localize runat="server" Text="Deafult value" meta:resourcekey="lblProviderType"></asp:Localize>

b. 隐式表达式只可以调用本地资源

c. 隐式表达式存储值方式不一样, 在database里面如lblProviderType.text是Text属性的resource key。当然也可以配置其他属性, 如Visible的resource key 是lblProviderType.Visible

d. 隐式表达式是通过resourcereader去取资源的, 也就是说会一次把该resource type下的所有资源一次拿出来, 更有利于性能。而显式表达式是一条一条取的。(通过验证, 隐式表达式还是会一个一个跑一次)

e. 隐式表达式通过resource provider取不到值时会用默认值, 如上例中的Text="Default value", 而显式表达式会有编译错误(有点烦)。

注意:如果只是为了显示值,请使用控件<asp:Localize .., 上面有例子。

请大家指出不同意见和补充不全的。

 

Tags:

Common Library

Common Library - Demo project 布局

by Daniel 17. August 2009 16:59

要求:

1. 跨浏览器

2. 代码简单,样式结构分离

3.使用div+css布局,自适应高度, 有min-heigh, min-width

最后效果如下(menu css和部分图片来源于towngas,有些同事会有似曾相识的感觉): 

 

masterpage 代码如下: 

 

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Main.master.cs" Inherits="CommonLibrary.Demo.Module.Common.Main" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title></title>

    <asp:ContentPlaceHolder ID="cphHead" runat="server">

    </asp:ContentPlaceHolder>

</head>

<body>

    <form id="form1" runat="server">

    <div id="main">

        <asp:ScriptManager ID="ScriptManager1" runat="server" />

        <div id="header">

            <div id="logo"><br/></div>

            <div id="sysName">VS.NET 2008 Common Library Demo Project</div>

            <div id="language">

                <ul>

                    <li>

                        <asp:LinkButton ID="lbtnEn" runat="server" CommandArgument="en-us" OnCommand="ltbnChgLang_Click">ENGLISH</asp:LinkButton>

                    </li>

                    <li>

                        <asp:LinkButton ID="lbtnZhCn" runat="server" CommandArgument="zh-cn" OnCommand="ltbnChgLang_Click">简体中文</asp:LinkButton>

                    </li>

                </ul>

            </div>

        </div>

        <div id="menu">          

            <asp:Menu ID="menuMain" runat="server" DataSourceID="smdsMain"></asp:Menu>

            <asp:sitemapdatasource runat="server" id="smdsMain" />

        </div>       

        <div id="nav">

            <div id="path"><asp:SiteMapPath runat="server" id="smpWeb" /></div>

            <div id="logonOut">

                <asp:ImageButton ID="ibtn" runat="server" ImageUrl="~/App_Themes/Default/img/frame/nav_exit.png" Text="Logon Out" OnClick="ibtnLogonOut_OnClick"></asp:ImageButton>

            </div>

            <div id="logonUser"><asp:Label ID="lblUserName" runat="server" Style="color: #0033CC;"></asp:Label></div>

        </div>

        <div id="content">       

            <asp:ContentPlaceHolder ID="cphContent" runat="server"></asp:ContentPlaceHolder>

        </div>

        <div id="footer">@copyright 2009 AiPuJing Software Technology Co. Ltd</div> 

    </div>

    </form>

</body>

</html>

 css 代码如下:

 

body { margin: 0; padding: 0; font-family: "Arial", "Helvetica", "sans-serif"; font-size: 12px;text-align:center; background: url(../img/frame/form_bg.gif) repeat-x; background-color:#EDEDED;}

 

div#main { height: auto; width:985px; margin:0 auto; padding-bottom:5px; text-align:left;background-color:#ffffff; }

 

div#header {height: 70px; background: url(../img/frame/header_bg.jpg) repeat-x;}

div#header div#logo{float: left;padding-left: 180px; background: url(../img/frame/header_logo.gif) no-repeat;}

div#header div#sysName { float: left; padding-top: 18px; font-family:"Times New Roman", "Times", "serif";font-size: 28px; font-weight:bold; color:#FFFFFF;}

div#header div#language { float: right; padding: 10px 15px 0 0; font-weight:bold;}

div#language ul li {list-style-type: none;}

div#language a:link,

div#language a:visited,

div#language a:focus,

div#language a:hover,

div#language a:active { color: #ccc; text-decoration: none;}

 

div#menu { background: url(../img/frame/menu_bg.gif) repeat-x; text-align: left; height: 30px;}

div#nav { height: 19px; padding:2px 0 0 15px; background: url(../img/frame/nav_bg.gif) repeat-x; /*background-color:#e6f0fa;*/}

 

div#path { float: left;}

div#logonUser { float:right; padding-left:18px;background: url(../img/frame/nav_user.png) no-repeat;}

div#logonOut { float:right; padding:0 10px 0 10px;}

 

div#content {height: auto !important; height:440px; min-height:440px; margin-top:1px; text-align:center; color:#004499;} 

div#footer { height:30px; line-height:28px;background:#3C7FAF; text-align:center; color:#ffffff;}

 

供参考和学习, 望大家提意见和真正


Tags:

Common Library

Common Library - Menu之数据库设计篇

by Daniel 6. August 2009 15:56

综合大家的讨论,晓冰在其博客Common Library 菜单控件提出了9点基本需求和实现方式, 另结合实际应用,我加上下面两点:

10. 支持一个User多个Role

11. 实现基于11.的Function级别的权限控制

下面是数据库设计图:

上述6个表说明如下:

 

1. tbl_ComLib_Menu 

该表在上次讨论中已经和大家见面了, 不多唠叨。需要注意的是:指定Active为false的时候,请确保其所有孩子都是false。

2. tbl_ComLib_User

很显然, 这是一个用户信息表,没什么需要说的。只列出了几个常用字段,大家可以扩展。

3. tbl_ComLib_UserRole

存储用户角色基本信息,有两个新鲜的字段:‘HomePage' 和’Priority'。‘HomePage'指的是用户角色在登录系统的时候的默认页面,由于我们实现了一个用户可以有多个Role,所以这里的’Prilrity‘就有用了, 指定那个Role优先级别高。比如登录的时候,进入优先级别高的Role的‘HomePage'.

4. tbl_ComLib_UserRoleUserAssignment

用户和Role的关联表。很简单,就两个字段,存储用户和Role的映射关系。

5. tbl_ComLib_UserRolePermissionFunction

 Role和Menu的关联表。(也就是MTR项目里常用到的tbl_RoleRight表, 只是换了个马甲而已)

需要说明的是:

1. 数据除了可以继续像之前MTR项目一样,所有的Menu item都必须关联到Role, 也就是说如果menu中有10条数据,有2role, 则该表有10*2 = 20条数据,如果有访问权限的话, Active设置为true, 否则设为false(这是之前MTR项目的做法). 如果要新加menu, 则该表也为每个role添加相应的menu。

2. 也可以只存储有访问权限的数据, 也就是说该表中只存储有访问权限的数据(当然Active字段也可以去掉了)。我想这种方法存储过程会复杂点, 要找出该记录的所有父亲节点(好的是SQL2005之后可以用WITH temptbl 递归找父亲)。

现在Demo用的是第二种方法,只给Role指定有权限访问的数据, 且只要指定叶子节点即可。 如果所有的Role都有访问权限的叶子节点则不需要在该表中配置记录,默认所有Role都是有访问权限的(用*表示). 也就是说如果该表中一条记录也没有, 默认所有Role对所有Menu都有访问权限。但是现在有一个问题:如果新加一个menu, 且没有配置任何权限在permission function表, 但是该menu的parent 配置了权限, 比如配置了SYS-ADMIN, 但是没有配置给GENERAL, 这个时候, 用GENERAL登陆, 则是给GENERAL添加parent menu的权限?还是不给呢?如果不给的话, 新加的menu会找不到parent而抛出异常。从功能上好像应该给GENERAL添加parent menu的权限, 但是从权限控制的角度, 也就是说用户信息保密的角度,应该不添加该parent menu.  大家认为该怎么处理呢?

6. tbl_ComLib_Resource

Common Library示例menu的title和description存储在resource file

如果有需要将Menu的多语言数据存储在数据库中,则可以存放于该表中, 可以通过简单修改存储过程实现, 其他多语言数据也可存储于该表,如label等, 然后用ResourceProvider事先多语言, 这是下一个Common Library工作项。实例数据如下:

不确定的地方,请留下您的宝贵意见:

1. 数据库表,字段命名规范

2. tbl_ComLib_UserRolePermissionFunction有提到两种数据方案,如果有其他更好的当然更好。

3. Menu的多语言数据是放在数据库还是resource file?

如果有不一样的想法希望您能留下宝贵想法和意见。这只是个初稿, 且有些想法也没有确定,Common Library的建设需要您的一份力量。

另提点意见: 我们的博客真的不太好用1. 太慢了, 图片加载要等。 2. upload图片很不爽, 要刷新页面,也要等。 3. 最不爽的是编辑不太好使。可能是我发帖太少,还没习惯吧。也或者大家都是先在word写好再paste到这里发布, 也或者用email发布, 所以感觉不到这些问题。

Tags:

Common Library

Common Library 菜单控件

by Richard 27. July 2009 22:51

经过前面两次的Common Library讨论会,基本确定了菜单控件的需求和实现方式,记录下来以便后续的讨论和测试。

  1. 使用微软提供的 ASP.NET Menu + SiteMapDataSource 来实现。
  2. 要同时支持XML和数据库存放菜单数据,为数据库存放方式提供一个自定义的Provider,可以在这两种方式间很方便的切换。
  3. 支持菜单内容多语言显示。
  4. 要同时支持横向显示和纵向显示,并可以很方便的切换。
  5. 跨浏览器支持,要支持IE(v6和以上版本), FireFox, Chrome, Opear, Safari。
  6. 使用符合web HTML 语义标准的 ul + li 标签,而不是微软Menu控件的默认 table + td 标签。
  7. 当前页对应的菜单项能高亮显示。
  8. 将菜单项集合缓存起来以提高性能,并提供强行更新缓存的方法。
  9. 尽量少使用图片和图标,减少网络传输的负担。

欢迎大家在此留言,发表大家对Common Library的菜单控件的不同意见和要求,谢谢!

 

 

listry 同事说得有道理,把第9点改一下:

9. 支持在没给Menu Item前显示不同的图标, 也可以配置为不显示以适应网络带宽不是很好的环境。

Tags:

Common Library

Copyright © 2009 APJ Software

最新评论

Comment RSS

公告

欢迎使用APJ Blog!

日历

<<  May 2012  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar