解惑

解己之惑,解人之惑

标签:API

开始习惯MSDN格式的API文档了

最开始很不习惯MSDN格式的api文档,感觉很分散,原理性介绍、快速入门、API的说明以及常量定义都不知道怎么弄的。
经过对CDO的文档的摸索,发现这些东西都是存在的,只是和JAVA的那些习惯不一样,java的组件的文档一般比较全面,而且把这些东西组织得很好,开始就是quick start,然后是developement guide,最后就是API reference,链接也做得比较好。虽然MSDN的文档不缺少这些内容,在内容之间的引用做得似乎弱一些。

SandCastle使用入门

看了网上的SandCastle入门,但是我使用的时候还是遇到很多问题。
秉承我的一贯作风写个我的入门指南:

  • 下载SandCastle并安装
  • 设置系统环境变量DXROOT指向SandCastle安装的目录,默认是C:\Program Files\Sandcastle\
  • 把SandCastle的productiontools加到系统环境变量PATH里面%DXROOT%\productiontools;
  • 把SandCastle的example的bat文件拷贝出来备用:C:\Program Files\Sandcastle\Examples\sandcastle\build_Sandcastle.bat,建议把bat重命名为generate_chm.bat
  • 如果你使用Visual Studio,那么修改工程的属性,把Build的Output中的XML Documentation File勾中,如果没有使用Visual Studio,那么可以使用csc命令生成这个XML文件 csc /doc:Xxx.xml Xxx.cs,如果编译依赖其他的东西,也需要在命令行中提供。
  • Build工程,把Build生成的bin下的所有内容(debug或者release),注意是所有内容拷贝到其他的新建的目录下,然后把generate_chm.bat也拷贝过去,然后在DOS下进入那个目录: generate_chm vs2005 Xxx。不要直接在Visual Studio的工程下面运行,一个是生成很多中间的目录和文件,二是好像影响正常生成(我开始都是在Visual Studio下弄的,总是不成功)。

得到当前方法

在写代码的时候我们可能会需要当前的方法名,特别是在输出一些调试信息的时候,但是如果使用字符串硬写的话不太好,API好像也不带对应的功能,如果细心的话,异常信息里面是带出错的方法名的,我们可以dump stack trace并分析得到当前方法的方法名,实际上有更好的方法,和dump stack trace类似:
public static String getCurrentMethodName() {
    StackTraceElement element=Thread.currentThread().getStackTrace()[3];
    return element.getClassName()+"."+element.getMethodName();
}
为什么是3呢?从0到2分别是:
java.lang.Thread.dumpThreads
java.lang.Thread.getStackTrace
xxx.Xxxx.getCurrentMethodName:也就是你定义这个工具方法的类

如何设计API?

每个人设计API的思路可能都不一样,而我们公司的一些代码的API的设计很有意思,一个例子:
    public AppGroupConfigValueObj get(UserSession _userSession, AppGroupConfigValueObj invo) throws DataException
    {
        long start = System.currentTimeMillis();
        try
        {
            Long id = (Long) invo.getId();
            if (isDebug() )
                SessionLogManager.getInstance().getLogger(this.getClass()).debug("get group" + id);
            AppGroupConfig eb = this.appGroupHome().findByPrimaryKey(id);
            if (isDebug() )
                SessionLogManager.getInstance().getLogger( this.getClass() ).debug("Get( UserSession _userSession, AppGroupConfigValueObj invo) elapsed time = "+ (System.currentTimeMillis()-start));
            return get(eb, invo);
        }
        catch (Exception e)
        {
            throwException(e);
        }
        return null;
    }

    private AppGroupConfigValueObj get(AppGroupConfig eb, AppGroupConfigValueObj invo)
            throws Exception
    {
        AppGroupConfigValueObj vo = (AppGroupConfigValueObj) ServerUtil.getValueObj(eb);

        if (invo.getApps() != null)
        {
            Collection collection = eb.getApplications();
            if (invo.getApps().getCount() == 0)
                vo.setApps(new ValueObjList(collection.size()));
            else
            {
                Iterator it = collection.iterator();
                while (it.hasNext())
                {
                    AppConfig a = (AppConfig) it.next();
                    vo.addApp((AppConfigValueObj) ServerUtil.getValueObj(a));
                }
            }
        }
        return vo;
    }

解释一下,这个API的功能是这样的,主要参数AppGroupConfigValueObj 是一个Map结构的对象,另外包含一些父子关系,如果你需要的是一个轻量级的结果,那么传入的对象只需要设置ID就可以,典型的用法是这样的:
get(cuSession, new AppGroupConfigValueObj(appGroupId))
如果你需要一个重量级的结果,也就是需要它的一些子表的数据,那么就要设置子表的关系,并添加一个空的对象:
                    AppGroupConfigValueObj appVo = new AppGroupConfigValueObj(appGroupId);
                    appVo.addApp(new AppConfigValueObj());
                    get(cuSession,appVo);
还有第三种用法,就是你希望那些子表数据不填充,但是需要知道子表数据有几个,那么你的调用代码就是:
                    AppGroupConfigValueObj appVo = new AppGroupConfigValueObj(appGroupId);
                    appVo.setApps(new ValueObjList());
                    get(cuSession,appVo);

我不知道这种做法源自何处,但是很明显是原来的某位高人,而比我资历更老的一些同事沿用了这个做法并且没有在文档中记录这种方法,当我苦苦寻找一个简单的get(cuSession, appGroupId)方法时没有任何结果,最后看其它部分的代码才知道了这个诀窍。

© 2024 解惑

本主题由Anders Noren提供向上 ↑