﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>掌控生活，加速成长！ &#187; 技术架构</title>
	<atom:link href="http://www.zhoujingen.cn/blog/category/it/architect/feed" rel="self" type="application/rss+xml" />
	<link>http://www.zhoujingen.cn/blog</link>
	<description>平衡、快乐、高效，成为一个有自我、有目标、有结果的敏捷个人。</description>
	<lastBuildDate>Sat, 19 Oct 2024 13:10:21 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.7.1</generator>
	<item>
		<title>Cordova webapp实战开发：（5）如何写一个Andorid下自动更新的插件？</title>
		<link>http://www.zhoujingen.cn/blog/7361.html</link>
		<comments>http://www.zhoujingen.cn/blog/7361.html#comments</comments>
		<pubDate>Wed, 08 Jul 2015 03:52:35 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=7361</guid>
		<description><![CDATA[在 《Cordova webapp实战开发：（4）Android环境搭建》中我们 &#8230; <a href="http://www.zhoujingen.cn/blog/7361.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>在 《<a id="cb_post_title_url" href="http://www.zhoujingen.cn/blog/7358.html">Cordova webapp实战开发：（4）Android环境搭建</a>》中我们搭建好了开发环境，也给大家布置了调用插件的预习作业，做得如何了呢？今天我们来学一下如何自己从头建立一个Andorid下的cordova插件。</p>
<h1>本次练习你能学到的</h1>
<ol>
<li>学习如何实现自动更新功能</li>
<li>学习插件类的编写</li>
<li>学习插件的配置</li>
<li>学习插件的调用</li>
</ol>
<h1>主要内容</h1>
<ul>
<li>打开APP后检查版本更新，如果有更新则弹出更新对话框</li>
</ul>
<p><img alt="" src="http://ww3.sinaimg.cn/mw690/5381716fjw1etv41wke8vj20k00zkdhy.jpg" /></p>
<ul>
<li>APP中【检查更新】显示当前版本号，并可以点击进行版本检查更新</li>
</ul>
<p><img alt="" src="http://ww4.sinaimg.cn/mw690/5381716fjw1etv41xnyy4j21kw2t3194.jpg" /></p>
<p>&nbsp;</p>
<h1>如何实现自动更新功能</h1>
<p>你可以自己写代码，也可以网上找代码抄一下，我之前的 <strong><a href="http://www.zhoujingen.cn/agileme_app.html" target="_blank">敏捷个人APP</a> </strong>就是从网上下的一个代码片段放进我的项目中的。不过今天和大家说的不是如何编写自动更新代码，因为我们今天要做的是如何更快的用别人写好的东西来加速自己产品开发的进度和质量。</p>
<p>自动更新这个东西也不涉及到什么技术难度，一般第三方要是提供了也不会出什么质量问题，能够拿来就用岂不是很好呢？网上找了一下，发现 <strong><a href="http://www.umeng.com/component_update" target="_blank">友盟提供自动更新</a></strong></p>
<p><a href="http://www.umeng.com/component_update" target="_blank"><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201507/081019026586391.jpg" /></a></p>
<p>很好，那就直接用这个吧，Andorid和iOS都可以用。</p>
<p>如何集成到我们的产品中，看他们自己写的文档：<strong><a href="http://dev.umeng.com/auto-update/android-doc/introduction" target="_blank">自动更新android文档</a> </strong>，我就不多说了，如果遇到问题，可以在咱们群里问问大家。</p>
<h1>插件类的编写</h1>
<p>原生Andorid中如果调用，就看上面说的他们自己写的文档。如果我们现在要在APP中【设置】中增加自动检查和显示当前版本，则需要我们开始学习如何编写cordova插件了。</p>
<p>这里我们会编写一个插件，两个方法，一个方法用来检测更新，另一个方法用来获得当前APP的版本号。</p>
<p>闲话不说了，直接来代码。</p>
<div>
<pre>public class GCAppPlugin extends CordovaPlugin {

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        if ("version".equals(action)) {
            version(callbackContext);
            return true;
        }
        else if ("checkUpdate".equals(action)) {
            final Context mContext = this.cordova.getActivity();
            UmengUpdateAgent.setUpdateAutoPopup(false);
            UmengUpdateAgent.setUpdateListener(new UmengUpdateListener() {
                @Override
                public void onUpdateReturned(int updateStatus, UpdateResponse updateInfo) {
                      switch (updateStatus) {
                        case UpdateStatus.Yes: // has update
                            UmengUpdateAgent.showUpdateDialog(mContext, updateInfo);
                            break;
                        case UpdateStatus.No: // has no update
                            Toast.makeText(mContext, "现在使用的已是最新版本了", Toast.LENGTH_SHORT).show();
                            break;
                        case UpdateStatus.NoneWifi: // none wifi
                            Toast.makeText(mContext, "没有wifi连接， 只在wifi下更新", Toast.LENGTH_SHORT).show();
                            break;
                        case UpdateStatus.Timeout: // time out
                            Toast.makeText(mContext, "超时", Toast.LENGTH_SHORT).show();
                            break;
                        }                    
                }
            });
            UmengUpdateAgent.forceUpdate(mContext);
            return true;
        } 
}

private synchronized void version(CallbackContext callbackContext) {
　　PackageInfo packInfo;
　　try {
　　　　packInfo = this.cordova.getActivity().getPackageManager().getPackageInfo(this.cordova.getActivity().getPackageName(),0);
　　　　String version = packInfo.versionName +"("+packInfo.versionCode+")";
　　　　callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, version));
　　} catch (NameNotFoundException e) {
　　　　// TODO Auto-generated catch block
　　　　e.printStackTrace();
　　}
}</pre>
<div>Javascript如何得到插件调用后的返回结果？主要通过类似 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, version)); 代码返回PluginResult，失败和成功都可以触发Javascript执行对应的自定义函数</div>
</div>
<h1>插件的配置</h1>
<p>插件写完了，很多人遇到的下一个问题就是怎么配置才能在Javascript中调用呢？我们今天也不解析源码，为什么呢？因为我没看：）不过，我一定要给大家说清楚如何配置，否则就永远调用不了插件。</p>
<p>打开res/xml/config.xml文件，添加feature，必须匹配类名，因为源码中是通过这些去配对的。上面我们写了更新插件，现在就是要配置一下这个插件类到功能名称，我在配置文件中加入了下文粗体部分内容</p>
<div>
<pre>&lt;?xml version='1.0' encoding='utf-8'?&gt;
&lt;widget id="com.glodon.gcapp" version="2.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"&gt;
    &lt;name&gt;掌中广材&lt;/name&gt;
    &lt;description&gt; 随时随地查找全国最完整最及时的信息价   &lt;/description&gt;
    &lt;author email="22626496@qq.com" href="http://www.中国信息价.cn"&gt;  周金根    &lt;/author&gt;
    &lt;content src="html/scj/scj.html" /&gt;
    &lt;access origin="*" /&gt;
    &lt;access origin="tel:*" launch-external="yes"/&gt;
    &lt;access origin="geo:*" launch-external="yes"/&gt;
    &lt;access origin="mailto:*" launch-external="yes"/&gt;
    &lt;access origin="sms:*" launch-external="yes"/&gt;
    &lt;access origin="market:*" launch-external="yes"/&gt;

    &lt;preference name="SplashScreen" value="screen" /&gt;
    &lt;preference name="SplashScreenDelay" value="30000" /&gt;
    &lt;preference name="SplashMaintainAspectRatio" value="false" /&gt;    
    &lt;preference name="LoadingDialog" value="正在加载中..." /&gt;

    &lt;feature name="Device"&gt;
        &lt;param name="android-package" value="org.apache.cordova.device.Device" /&gt;
    &lt;/feature&gt;
     &lt;feature name="NetworkStatus"&gt;
        &lt;param name="android-package" value="org.apache.cordova.networkinformation.NetworkManager" /&gt;
    &lt;/feature&gt; 
    &lt;feature name="SplashScreen"&gt; 
        &lt;param name="android-package" value="org.apache.cordova.splashscreen.SplashScreen" /&gt;
    &lt;/feature&gt;    
    &lt;feature name="Camera"&gt;
        &lt;param name="android-package" value="org.apache.cordova.camera.CameraLauncher" /&gt;
    &lt;/feature&gt;    
    &lt;feature name="BarcodeScanner"&gt;
        &lt;param name="android-package" value="com.phonegap.plugins.barcodescanner.BarcodeScanner" /&gt;
    &lt;/feature&gt;
<strong>    &lt;feature name="Gcapp"&gt; 
        &lt;param name="android-package" value="com.gldjc.guangcaiclient.GCAppPlugin" /&gt;
    &lt;/feature&gt;  
</strong>&lt;/widget&gt;</pre>
<div>代码贴完了，我还是要再多说一下，</div>
</div>
<ul>
<li>
<pre><strong>com.gldjc.guangcaiclient.GCAppPlugin  是插件类的全面</strong></pre>
</li>
<li><strong>Gcapp是 feature 名称，下面大家就知道在哪里会用到了</strong></li>
</ul>
<p>以上文件就是告诉cordova，我们新增了一个Gcapp功能，这个功能会调用我们的原生插件Java对象，接下来就是Javascript如何能调用到这个类了，最重要的就是这个Gcapp功能名称。</p>
<p>我们接着就要写Javascript代码来调用这个功能了，如何写呢？继续往下看，我在assets/www/plugins/下新增目录并建立了文件gcapp.js，完整路径是 assets/www/plugins/com.gldjc.guangcaiclient/www/gcapp.js，代码如下：</p>
<div>
<pre>cordova.define('com.gldjc.guangcaiclient.gcapp', function(require, exports, module) {
        <strong>var exec = require("cordova/exec");

        </strong>function Gcapp() {};

        Gcapp.prototype.version = function (getversion) {
            exec(getversion, null, 'Gcapp', 'version', []);
        };   

   　　 Gcapp.prototype.checkUpdate = function () {
            exec(null, null, 'Gcapp', 'checkUpdate', []);
        };   

        var gcapp = new Gcapp();
        module.exports = gcapp;
});</pre>
<div>exec是cordova.js中内部的函数，当插件返回 PluginResult.Status.OK 时会执行exec的成功回调函数，如果插件返回的是错误，则会执行exec的错误回调函数。这里我们解释一下</div>
</div>
<div>
<pre> exec(null, null, 'Gcapp', 'checkUpdate', []);</pre>
</div>
<p>其中Gcapp就是我们在上一步骤加的feature名称，大小写匹配着写，通过这个名称，cordova才能找到调用那个java插件类，然后通过checkUpdate知道调用这个插件类的哪个方法，后面[]中则是参数。因为我这个插件不需要参数，所以为空。</p>
<p>Javascript插件类也配对成功了，那如何调用呢？你可以直接在html中包括这个js，不过我们一般会再配置一个js，那就是assets/www/cordova_plugins.js，这样就不用对每个插件类都去写一遍了，cordova会遍历你的配置去加载它们。</p>
<div>
<pre>cordova.define('cordova/plugin_list', function(require, exports, module) {
module.exports = [
    {
        "file": "plugins/org.apache.cordova.device/www/device.js",
        "id": "org.apache.cordova.device.device",
        "clobbers": [
            "device"
        ]
    },
    {
        "file": "plugins/org.apache.cordova.networkinformation/www/network.js",
        "id": "org.apache.cordova.networkinformation.network",
        "clobbers": [
            "navigator.connection",
            "navigator.network.connection"
        ]
    },
     {
        "file": "plugins/org.apache.cordova.networkinformation/www/Connection.js",
        "id": "org.apache.cordova.networkinformation.Connection",
        "clobbers": [
            "Connection"
        ]
    },
     {
        "file": "plugins/org.apache.cordova.splashscreen/www/splashscreen.js",
        "id": "org.apache.cordova.splashscreen",
        "clobbers": [
            "navigator.splashscreen"
        ]
    },
        {
        "file" : "plugins/org.apache.cordova.camera/www/CameraConstants.js",
        "id" : "org.apache.cordova.camera.Camera",
        "clobbers" : [ "Camera" ]
    },
    {
        "file" : "plugins/org.apache.cordova.camera/www/CameraPopoverOptions.js",
        "id" : "org.apache.cordova.camera.CameraPopoverOptions",
        "clobbers" : [ "CameraPopoverOptions" ]
    },
    {
        "file" : "plugins/org.apache.cordova.camera/www/Camera.js",
        "id" : "org.apache.cordova.camera.camera",
        "clobbers" : [ "navigator.camera" ]
    },
    {
        "file" : "plugins/org.apache.cordova.camera/www/CameraPopoverHandle.js",
        "id" : "org.apache.cordova.camera.CameraPopoverHandle",
        "clobbers" : [ "CameraPopoverHandle" ]
    },
    {
        "file" : "plugins/com.phonegap.plugins.barcodescanner/www/barcodescanner.js",
        "id" : "com.phonegap.plugins.barcodescanner.barcodescanner",
        "clobbers" : [ "barcodescanner" ]
    },
 <strong>   {
        </strong><strong>"file": "plugins/com.gldjc.guangcaiclient/www/gcapp.js",
        "id": "com.gldjc.guangcaiclient.gcapp",
        "clobbers": [
            "gcapp"</strong><strong>
        ]
    }</strong>
];
module.exports.metadata = 
// TOP OF METADATA
{
    "org.apache.cordova.device": "0.2.13"
}
// BOTTOM OF METADATA
});</pre>
<div>file表示我们去哪里找脚本插件定义js，id是之前我们在gcapp.js中开头cordova.define中写的标识，cordova通过这个标志去找到我们的Javascript插件定义，而clobbers则是我们在前端通过什么对象名来调用这个插件。这里我写的是gcapp，则后面调用则只需要写成gcapp.checkUpdate 即可</div>
</div>
<h1>插件的调用</h1>
<p>万事俱备，只欠东风，你们可以开始看到结果了，如果从头到这里一步成功，那应该还是蛮兴奋的事情吧。</p>
<p>具体前端页面如何设计我就不说了，我的页面效果就如本文最前面的图片，在js中我是这些调用version的，至于checkUpdate就是一样了，在按钮的click事件中调用 gcapp.checkUpdate(); 即可</p>
<div>
<pre>$(document).on("PG_pageinit", function(event) {
    gcapp.version(function(version){
            $("#version").html(version);
    });
});</pre>
</div>
<p>&nbsp;</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/7361.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cordova webapp实战开发：（4）Android环境搭建</title>
		<link>http://www.zhoujingen.cn/blog/7358.html</link>
		<comments>http://www.zhoujingen.cn/blog/7358.html#comments</comments>
		<pubDate>Wed, 10 Jun 2015 03:49:53 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=7358</guid>
		<description><![CDATA[在《Cordova webapp实战开发：（3）后面可能会学到的东西》中我们说了 &#8230; <a href="http://www.zhoujingen.cn/blog/7358.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>在《<a href="http://www.zhoujingen.cn/blog/7044.html" rel="bookmark">Cordova webapp实战开发：（3）后面可能会学到的东西</a>》中我们说了一下后续大致包括的内容，今天我们继续。上周我在掌中广材集成了友盟的社交分享，今天想集成iOS应该很顺利的，但是只要一加入libSocialQQ.a就错。我对iOS也不太熟，没找到原因，头晕了，写一篇博客权当休息一下。今天我们就来搭建一下Android环境，并编写一个hello world吧。准备好了吗？Web app开发旅程即将正式开始了&#8230;&#8230;.</p>
<h1>JAVA环境</h1>
<ol>
<li>安装<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">JAVA JDK</a></li>
<li>打开我的电脑&#8211;属性&#8211;高级&#8211;环境变量
<ul>
<li>新建系统变量JAVA_HOME，变量名：JAVA_HOME ，变量值：C:\Program Files\Java\jdk1.7.0</li>
<li>新建系统变量CLASSPATH，变量名：CLASSPATH ，变量值：.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;</li>
<li>选择“系统变量”中变量名为“Path”的环境变量，双击该变量，在原来变量后追加 ;%JAVA_HOME%\bin</li>
</ul>
</li>
<li>现在测试环境变量的配置成功与否。在DOS命令行窗口输入“JAVAC”，输出帮助信息即为配置正确。如图：<br />
<img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/081517126605096.jpg" /></li>
</ol>
<h1>Android环境</h1>
<div>
<p><strong>1. 下载Andorid SDK以及Eclipse</strong><br />
如果你想通过Eclipse来开发Andorid应用程序，在你配置好了JDK变量环境之后可以安装<a href="http://www.eclipse.org/downloads/">Eclipse</a>之后下载Android SDK（Software Development Kit）并在Eclipse中安装ADT插件，这个插件能让Eclipse和Android SDK关联起来。为了更加方便，在Andorid SDK下载中会包括SDK以及一个可以直接使用的Eclipse。</p>
<p>写blog，我不能保证文章的内容在以后也能使用，包括下载地址和链接，但我既然写了，就要有责任保证现在的是能用的。以前下载地址是在<a href="http://developer.android.com/sdk/index.html">Android SDK</a>，大家可以根据自己的系统选择相应的系统版本下载。不过</p>
<p>今天我写这篇文章的时，不知是我网络原因还是其他的，总之不能访问，所以我在我的百度网盘放了一个之前下载的SDK压缩包，大家可前往下载：<a href="http://pan.baidu.com/s/1gdgur2j" target="_blank">http://pan.baidu.com/s/1gdgur2j</a>。下载完后，我把这个压缩包解压到E:\dev-tools\adt-bundle-windows-x86_64-20140321（<strong>你可以自己随便放在哪个盘符</strong>）<br />
<img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/081536391912178.jpg" /></p>
<p><strong>2. 环境变量的配置</strong><br />
在JAVA环境配置中，我们做了一步环境变量的配置，对于android的开发人员来说，我们首先要做的也是环境变量的配置。<br />
打开我的电脑&#8211;属性&#8211;高级&#8211;环境变量</p>
<ul>
<li>新建系统变量ANDROID_HOME，变量名：ANDROID_HOME，变量值：E:\dev-tools\adt-bundle-windows-x86_64-20140321\sdk</li>
<li>选择“系统变量”中变量名为“Path”的环境变量，双击该变量，在原来变量后追加 ;%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools</li>
<li>现在测试环境变量的配置成功与否。在DOS命令行窗口输入“adb”，输出帮助信息即为配置正确。如图：<br />
<img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/081553590196951.jpg" /></li>
</ul>
</div>
<h1>Cordova环境</h1>
<p>在<a href="http://cordova.apache.org/" target="_blank" data-click="{<br />
			'F':'778317EA',<br />
			'F1':'9D73F3E4',<br />
			'F2':'4CA6DE6B',<br />
			'F3':'54E5243F',<br />
			'T':'1433750217',<br />
						'y':'FD74FFFB'</p>
<p>									}">Apache Cordova</a>官网上有明确的建立步骤，具体说明在 <a href="http://cordova.apache.org/docs/en/5.0.0//guide_cli_index.md.html#The%20Command-Line%20Interface" target="_blank">The Command-Line Interface</a>  中。</p>
<ol>
<li>安装<a href="http://nodejs.org/" target="_blank">NodeJS</a><br />
<a href="http://nodejs.org/"><img alt="" src="http://images.cnitblog.com/blog/14032/201311/01151200-f7f428ea1664483091ed02dcf147cc87.png" border="0" /></a></li>
<li>下载安装一个 <a href="http://git-scm.com/">git客户端</a></li>
<li>
<div>
<p>Window下行执行命令行：</p>
<div>
<div id="highlighter_45479">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>1</div>
</td>
<td>
<div>
<div><code>npm install -g cordova</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Mac下执行命令行</p>
<div>
<div id="highlighter_50319">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>1</div>
</td>
<td>
<div>
<div><code>$ sudo npm install -g cordova</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>我现在的电脑已经存在Cordova项目，但是安装环境却没有了。为了写这篇文字，我又重新安装cordova，在命令行下输入<br />
<img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/081621361446512.jpg" /><br />
同样，仍旧非常慢，别急，耐心点，不要中断执行，出去跑5公里之后再回来看看是否安装成功了。本来这篇博文是昨天发布的，只是这一步一直未完成，今天一大早又再试了试，很快就完成了。<br />
安装成功的样子是这样的：</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/090745468013068.jpg" /><br />
如果你真的很着急，就要明白下载慢的原因了。下载慢是因为源的问题，如果等不及可以使用其它源。我看在PhoneGap App开发QQ群（348192525  <a href="http://shang.qq.com/wpa/qunwpa?idkey=a926c50e786ab912159172b918eb2cc4cae6b6c194284eee70cdb80fe7d2be89" target="_blank"><img title="PhoneGap App实战开发" alt="PhoneGap App实战开发" src="http://pub.idqqimg.com/wpa/images/group.png" border="0" /></a> ）中有人介绍了通过更改下载源可以解决，如果你知道的话，可以在本文回复一下，与大家分享一下。</li>
</ol>
<h1>敏捷个人，快乐、平衡、高效</h1>
<p>下面我们来做一个Hello world示例</p>
<p>1. 新建一个项目，执行命令行 <strong>cordova create agileme cn.zhoujingen.agileme AgileMe , </strong>如果安装有问题可以后面加上 –d启动查看执行详细信息。下载类库时间有点长，我大概等了10几分钟吧，你也耐心点，不要中断执行。我第一次就是因为不想等了，然后中断，导致后面步骤失败，不得已删除下载的类库目录文件再次执行此步骤</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/090803234413010.jpg" /><strong><br />
</strong></p>
<p>error：please install android target: &#8220;android-22&#8243;.</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/102019444887616.jpg" /></p>
<p>老老实实打开Andorid SDK Manager下载最新Tools吧</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/090848533631256.jpg" /></p>
<p>不过要用代理才能下，算了，我直接用我以前做的代码做了一个Demo源码打包，使用的是Cordova3.几的版本。Andorid示例下载地址：<a href="http://pan.baidu.com/s/1kTFyjCr" target="_blank">webapptest.zip</a></p>
<p>如果你要下载，那就按这个设置，目前是可行，以后这个代理是否可用就不知道了。</p>
<p><img alt="" src="http://images.cnitblog.com/blog/491657/201501/221649322034275.png" /></p>
<p>至于如何使用Eclipse导入项目我就不说了，不知道的就网上找找，或者在群里问问大家吧</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/090824479101922.jpg" /></p>
<p>你可以在虚机上运行，</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/090800257549392.jpg" /></p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/090801237381906.jpg" />、</p>
<p>不过Andorid虚机很慢，我一般连接真机测试机</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/090850543796088.jpg" /></p>
<p>直接按运行，选择Andorid Application后，就会显示出主界面了</p>
<p><img alt="" src="http://images0.cnblogs.com/blog2015/14032/201506/102023328324789.png" width="382" height="680" /></p>
<p>&nbsp;</p>
<p>如果你看到这个界面了，恭喜你，你的成功迈进了一步。</p>
<p>如果看文字有点累，那就看看咱们群里人录制的视频吧。</p>
<p><iframe src="http://player.youku.com/embed/XMTI1OTgyMTY2NA==" height="684" width="700" frameborder="0"></iframe></p>
<p>&nbsp;</p>
<h1>预习作业</h1>
<p>第一次写一步一步的，感觉自己是不是写的太简单了</p>
<ol>
<li><strong>下载Cordova自带的notication插件，跑一跑</strong></li>
<li><strong>自己做一个获得App大小版本号的插件</strong></li>
</ol>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/7358.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MetaModelEngine：元模型引擎开发思路</title>
		<link>http://www.zhoujingen.cn/blog/2683.html</link>
		<comments>http://www.zhoujingen.cn/blog/2683.html#comments</comments>
		<pubDate>Mon, 14 Apr 2014 12:13:22 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>
		<category><![CDATA[软件产品线]]></category>
		<category><![CDATA[DSM]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=2683</guid>
		<description><![CDATA[在DSM：使用MetaEdit+编写Family Tree Modeling L &#8230; <a href="http://www.zhoujingen.cn/blog/2683.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/2687.html" rel="bookmark" title="DSM：使用MetaEdit+编写Family Tree Modeling Language">DSM：使用MetaEdit+编写Family Tree Modeling Language </a> <small>在信息系统开发平台OpenExpressApp － 总体架构的由来中说到Meta &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>在<strong><a id="homepage1_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl00_TitleUrl" href="http://www.zhoujingen.cn/blog/2687.html">DSM：使用MetaEdit+编写Family Tree Modeling Language</a></strong>中介绍了MetaEdit+的一个<em>家族树模型语言</em>应用示例，通过示例的学习掌握了基本的概念，本篇将介绍一下<strong><a href="http://openexpressapp.codeplex.com/">OpenExpressApp</a></strong>的元模型引擎<strong>MetaModelEngine</strong>的应用思路。</p>
<h1>为何借鉴MetaEdit+思想</h1>
<p>我在<a href="http://www.zhoujingen.cn/blog/1431.html"><strong>软件产品线工程方法 － 四个主要方法原则</strong></a>提到产品线带来的几个好处：减少成本，快速上市，减少风险和提高质量，这些都是我们在做软件产品时都期望达到的。在我以前blog中也有一个软件工厂的图，该图表明了模型驱动开发是支持软件产品线工程的一种方法，所以我会比较关注模型驱动开发。</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717273113.jpg" width="554" height="381" /></p>
<p>在<strong><a id="ctl03_TitleUrl" href="http://www.zhoujingen.cn/blog/2685.html">信息系统开发平台OpenExpressApp － 总体架构的由来</a></strong>中我讲到过MetaEdit+是全球DSM领域内著名的产品，它能够带来产品线中期望的几个好处：<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200910/2009101220552062.jpg" /></p>
<ul>
<li>缩短上市时间，开发生产力能够提高5-10倍</li>
<li>开发人员可以集中设计和关注业务功能，而不必用代码去写所有方面的内容</li>
<li>由于使用的是经过验证的工具，产品质量显著提高</li>
<li>可以完全控制模型和代码生成，而不像MDA方法模型和代码生成固定，不便于特定领域开发<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717294967.jpg" width="191" height="292" /></li>
</ul>
<p>通过以上说明可以看出，我借鉴MetaEdit+的思路是想采用一种模型驱动开发方法来支持产品线工程。</p>
<h1 align="left">元模型引擎对<strong><a href="http://openexpressapp.codeplex.com/">OpenExpressApp</a></strong>平台的支持</h1>
<p>知道MetaEdit+已经好多年了，之前也研究过这个工具，并查看过它的一些资料，也是在OpenExpressApp计划之中的重要组成部分。</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072810154685.jpg" /></p>
<ol>
<li>支持<strong>OpenStudio的图形化建模</strong>，让业务人员能看、能做，符合OpenExpressApp让业务人员编写软件的价值主张，通过业务人员更早更多的参与，可以更快的构建应用</li>
<li>支持OpenTool的工具：<strong>快速原型开发工具、图形化自动化测试工具</strong>等</li>
</ol>
<h3>Visual Studio的DSL架构</h3>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072811183260.png" /></p>
<ul>
<li>Microsoft.VisualStudio.Modeling:域模型框架时整个系统的核心，负责管理模型的元素和连接，也就是域类和域关系的实例。</li>
<li>Modeling.Disgrams:设计界面框架建立在域模型框架之上，它负责处理图形符号的显示，包括处理图表、图形、连接器和装饰等元素在设计界面上的显示</li>
<li>Modeling.Validation:验证框架负责执行关于模型元素和连接的验证方法，如果验证失败，它还要负责创建错误对象。它与Shell框架交互，把错误信息显示到Visual Studio的错误窗口</li>
<li>Modeling.TextTemplation:模板引擎负责执行文本模板来生成代码或其他的工件。模板引擎室一个独立的组件，用于执行来自非DSL的模板输入</li>
<li>Modeling.Shell：建模用的Shell负责管理将涉及器集成到Visual Studio中，例如处理工具窗口和菜单名利，以及文件的打开和关闭等</li>
</ul>
<h1>对MetaEdit+的技术借鉴</h1>
<ul>
<li><strong>组件架构图</strong><br />
MetaModel实现步骤：图形编辑器（Diagram Editor）-&gt; 矩阵和列表编辑器（Matrix和Table Editor）-&gt; 代码生成器</li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072717012728.png" /></p>
<ul>
<li><strong>模型架构图</strong>：GOPRR为元元模型层、领域概念为元模型层、产品规格为模型层、实例为系统应用层</li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072717191775.png" /></p>
<ul>
<li><strong>元模型概念GOPPRR：图、对象、属性、端口、关系、角色</strong><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072810540736.png" width="525" height="423" />
<ul>
<li>Graph 图：一个独立模型，通常使用图来表示</li>
<li>Objects 对象：图的主要元素，例如例子中的Person</li>
<li>Property 属性：图、对象、端口、角色和关系都可以拥有一些属性描述</li>
<li>Port 端口：定义角色如何连接对象的可能语义</li>
<li>Relationship 关系：让对象连接在一起</li>
<li>Role 角色：连接关系与对象之间</li>
</ul>
</li>
</ul>
<ul>
<li><strong>属性和非属性</strong><br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072717002784.png" /></li>
<li><strong>图的组成</strong></li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072717004847.png" /></p>
<ul>
<li><strong>绑定Binding</strong></li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072717023559.png" /></p>
<ul>
<li>
<p align="LEFT"><strong>对象引用图 Decomposition</strong></p>
</li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072810000137.png" /></p>
<h1>实现DSM步骤</h1>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072717204763.png" /></p>
<ul>
<ul>
<li><strong>设计领域概念</strong>（参考示例：<strong><a id="homepage1_HomePageDays_DaysList_ctl00_DayItem_DayList_ctl00_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/07/27/1786003.html">DSM：使用MetaEdit+编写Family Tree Modeling Language</a></strong>）
<ol>
<li>找到领域概念</li>
<li>把领域概念映射到模型概念<strong>GOPPRR：图、对象、属性、端口、关系、角色</strong></li>
</ol>
</li>
</ul>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072717053016.png" /></p>
<ul>
<li><strong>定义领域规则</strong>
<ol>
<li>定义规则</li>
<li>规则例子：【开始】状态不能直接连接到【结束】状态<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072810441540.png" />   <img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072810462793.png" /></li>
</ol>
</li>
</ul>
<ul>
<li><strong>画标记</strong><br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072810473582.png" /></li>
<li><strong>实现生成器</strong></li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072810482522.png" /></p>
<h1>主要技术及初步计划</h1>
<ul>
<li>元模型引擎</li>
<li>图形编辑器</li>
<li>代码生成器</li>
</ul>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/2687.html" rel="bookmark" title="DSM：使用MetaEdit+编写Family Tree Modeling Language">DSM：使用MetaEdit+编写Family Tree Modeling Language </a> <small>在信息系统开发平台OpenExpressApp － 总体架构的由来中说到Meta &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/2683.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DSM：使用MetaEdit+编写Family Tree Modeling Language</title>
		<link>http://www.zhoujingen.cn/blog/2687.html</link>
		<comments>http://www.zhoujingen.cn/blog/2687.html#comments</comments>
		<pubDate>Mon, 14 Apr 2014 12:12:28 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>
		<category><![CDATA[软件产品线]]></category>
		<category><![CDATA[DSM]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=2687</guid>
		<description><![CDATA[在信息系统开发平台OpenExpressApp － 总体架构的由来中说到Meta &#8230; <a href="http://www.zhoujingen.cn/blog/2687.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/2683.html" rel="bookmark" title="MetaModelEngine：元模型引擎开发思路">MetaModelEngine：元模型引擎开发思路 </a> <small>在DSM：使用MetaEdit+编写Family Tree Modeling L &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>在<strong><a id="ctl03_TitleUrl" href="http://www.zhoujingen.cn/blog/2685.html">信息系统开发平台OpenExpressApp － 总体架构的由来</a></strong>中说到MetaEdit+是全球DSM领域内著名的产品，<strong><a href="http://openexpressapp.codeplex.com/">OpenExpressApp</a></strong>将借鉴它的思想来形成自己的模型引擎，本篇介绍一下如何使用MetaEdit+来建立一个家族模型语言，这个也是MetaEdit+提供的一个示例，通过家族树语言的生产来加深对MetaEdit+的了解。如果你也想开发自己的建模工具，那么推荐你也去研究一下。</p>
<h1>MetaEdit+下载</h1>
<p>去官方网站<a href="http://www.metacase.com/">MetaCase</a>下载<a href="http://www.cnblogs.com/zhoujg/admin/Free%2031-day%20evaluation%20version%20of%20full%20MetaEdit+%20Workbench">Free 31-day evaluation version of full MetaEdit+ Workbench</a>，它自带一些示例模型，例如UML示例的一个图的界面如下：</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714175370.png" /></p>
<h1>需求</h1>
<p>对家族树进行建模，图形建模后如下：</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714185026.png" /></p>
<h1>GOPPRR 元模型语言</h1>
<p>再开始之前介绍一下GOPPRR原模型语言。对于家族树图形语言表示如下，在图中标识了多个元类型，每个类型有自己的功能和语义：</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714205150.png" /></p>
<div align="LEFT">Eachmetatype has its function and semantics as follows:</div>
<ul>
<li>Graph 图：一个独立模型，通常使用图来表示</li>
<li>Objects 对象：图的主要元素，例如例子中的Person</li>
<li>Property 属性：图、对象、端口、角色和关系都可以拥有一些属性描述</li>
<li>Port 端口：定义角色如何连接对象的可能语义</li>
<li>Relationship 关系：让对象连接在一起</li>
<li>Role 角色：连接关系与对象之间</li>
</ul>
<p>家族树例子使用这些元类型表示如下：Person为<strong>对象</strong>，Family为<strong>关系</strong>，Parent、Child为<strong>角色</strong>，First name、Family Name为<strong>属性</strong>，没有定义<strong>端口</strong>，整个显示为一张<strong>图</strong></p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714281067.png" /></p>
<h1>实现家族树模型语言</h1>
<ol>
<li>生成对象Person，对象属性如下：<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714334994.png" /></li>
<li>生成标记<br />
在上图Object Tool中点击【<b>Symbol Editor】</b>按钮，弹出标记编辑器界面，生成标记如下：<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714455340.png" /></li>
<li>生成关系Family<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714503798.png" /></li>
<li>生成角色Parent、Child<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714572585.png" /></li>
<li>生成图Family Tree<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072714585885.png" />   <img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715012064.png" /><br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715032253.png" />   <img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715051595.png" /></li>
<li>经过上面5步，Family Tree模型语言就轻易地建立起来了，这一步主要是应用模型语言生成家族树<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715102324.png" /></li>
</ol>
<h1>模型演进</h1>
<p>上面只是实现了一个简单的家族树模型，一般模型会随着要求不断演进，对于上面示例我们现在做一下演进：Person区分男性和女性</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715234092.png" /></p>
<ol>
<li>修改Person属性<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715235364.png" /></li>
<li>增加从Person继承下来两个对象：Female和Male对象<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715244679.png" /></li>
<li>增加男性和女性标记<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715242189.png" />   <img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715245987.png" /></li>
<li>修改图（Graph）定义<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715283552.png" />   <img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072715284796.png" /></li>
<li>增加端口，限制连接点<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072716323861.png" />   <img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072716324894.png" /></li>
<li>再次修改Graph定义<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072716333562.png" /></li>
<li>应用模型生成一个家族图<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201007/2010072716340067.png" /></li>
</ol>
<p>&nbsp;</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/2683.html" rel="bookmark" title="MetaModelEngine：元模型引擎开发思路">MetaModelEngine：元模型引擎开发思路 </a> <small>在DSM：使用MetaEdit+编写Family Tree Modeling L &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/2687.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>信息系统开发平台OpenExpressApp － 总体架构的由来</title>
		<link>http://www.zhoujingen.cn/blog/2685.html</link>
		<comments>http://www.zhoujingen.cn/blog/2685.html#comments</comments>
		<pubDate>Mon, 14 Apr 2014 12:09:39 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>
		<category><![CDATA[OpenExpressApp]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=2685</guid>
		<description><![CDATA[我们经常在对相同需求进行着重复的设计和编码，这使得开发效率低，而且质量也得不到保 &#8230; <a href="http://www.zhoujingen.cn/blog/2685.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>我们经常在对相同需求进行着重复的设计和编码，这使得开发效率低，而且质量也得不到保证，<a id="homepage1_HomePageDays_DaysList_ctl01_DayItem_DayList_ctl00_TitleUrl" href="http://openexpressapp.codeplex.com/">OpenExpressApp </a>就是抽取了信息系统的一些共性，用平台的方式提供大粒度的重用，提高开发效率和质量。</p>
<p>在《<a id="homepage1_HomePageDays_DaysList_ctl02_DayItem_DayList_ctl00_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2009/10/09/1579632.html">信息系统开发平台openexpressapp 1.0发布</a>》中提到过，OpenExpressApp不会带给大家创新性的技术，而是将现有技术和产品中有价值的部分引入到一起，它要做的是整合别人已经实践的方法，提高我们自身的开发能力，以求快速、高质量的开发产品。</p>
<p>下面我将通过对现有技术和产品的参考来讲解OpenExpessApp的架构，理解这些参考技术的架构是理解OpenExpressApp架构的最好办法。</p>
<p>为了提高产量和代码质量，我研究过一些产品和方法，而MetaEdit+是建立在DSM方法之上的工具，能够比较好提高产量和质量。</p>
<p>下面我先介绍一下MetaEdit+。<a href="http://www.metacase.com/"><br />
</a></p>
<h3><a href="http://www.metacase.com/">MetaEdit+</a></h3>
<p>MetaEdit+是全球DSM领域内著名的产品，它能够带来以下好处：<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200910/2009101220552062.jpg" /></p>
<ul>
<li>缩短上市时间，开发生产力能够提高5-10倍</li>
<li>开发人员可以集中设计和关注业务功能，而不必用代码去写所有方面的内容</li>
<li>由于使用的是经过验证的工具，产品质量显著提高</li>
<li>可以完全控制模型和代码生成，而不像MDA方法模型和代码生成固定，不便于特定领域开发<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717294967.jpg" width="191" height="292" /></li>
</ul>
<p>&nbsp;</p>
<p>从上图DSM方法知道模型和生成器是DSM的核心部分，而MetaEdit＋的元模型比较好，所以OpenExpressApp的建模工具中模型部分将参考MetaEdit＋。（由于现在还没有开始这部分内容，所以在这里就先不介绍了。）</p>
<p>从上图可以看到领域框架也是重要部分，所以接下来我就需要去搜索比较好的框架来参考。在我参考一些框架之后，我觉得DevExpress eXpressApp Framework比较适合，它是.Net下的一个应用框架。</p>
<h3><a href="http://www.devexpress.com/Products/NET/Application_Framework/">DevExpress eXpressApp Framwwork (XAF)</a></h3>
<p>DevExpress eXpressApp Framework是一种快速业务开发平台，它可以通过一个模型同时支持C/S和B/S应用。<img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_eXpressApp%20Framework%20Architecture.png" width="384" height="333" /><br />
它主要提供以下功能：</p>
<ul>
<li>一个架构，OpenExpressApp参考了这个架构。如有图所示。</li>
<li>XPO，一个ORM</li>
<li>对业务应用的UI进行了抽象，形成了一个UI模型，我叫它为AutoUI,就是通过类库以及模型自动生成界面，后面博文中我会单独解析AutoUI在OpenExpressApp的实现。</li>
<li> 模块化架构</li>
<li>基础类库</li>
<li>基于角色的安全实现</li>
<li>数据验证</li>
<li>本地化支持</li>
<li>报表</li>
<li>与Visual Studio IDE 继承</li>
</ul>
<p>OpenExpressApp名称中的ExpressApp词就来自这个应用框架，所以也暗示着OpenExpressApp参考了很多XAF的思想（架构、模块化、AutoUI等）。</p>
<p>XAF的基础类库建立在OO的思想上，所以我还需要一个支持OO的框架。而CSLA可以很好的支持类库开发和应用。</p>
<h3><a href="http://www.lhotka.net/">CSLA</a></h3>
<p><img alt="" src="http://www.lhotka.net/images/csla_logo1_72.png" width="250" height="72" />CSLA是Component-based, Scalable, Logical Architecture的简写，它是由Rockford Lhotka1999年开始编写的基于.Net的一套N-tier分布式框架。它还在不断更新，现在也支持Silverlight。</p>
<p>它包含如下功能：</p>
<ul>
<li>支持部署为单机、局域网和广域网</li>
<li>允许生成面向对象的业务层来封装业务逻辑和数据</li>
<li>n层撤销功能</li>
<li>跟踪违反业务规则以确定某个对象是否有效</li>
<li>跟踪某个对象的数据是否发生了改变（是否“变脏”？）</li>
<li>支持对于子对象的基于强类型的集合</li>
<li>针对UI开发人员的一种简单抽象模型</li>
<li>对于Windows Forms、WPF和Web Forms中数据绑定的支持</li>
<li>表驱动的安全机制</li>
<li>其他各种特性</li>
</ul>
<p>信息系统应用模块和功能会比较多，所以框架支持模块化就显得比较重要。第一阶段OpenExpressApp将实现基于WPF的应用，而微软模式小组编写的Composite WPF and Silverlight除了支持WPF外，也可以很好的支持模块化，所以我也使用了Composite WPF and Silverlight。</p>
<h3><a href="http://compositewpf.codeplex.com/">Composite WPF and Silverlight</a></h3>
<p><img alt="" src="http://i.msdn.microsoft.com/Dd490825.45a2c411-0ae0-496e-beb0-2704f782b872(en-us,MSDN.10).png" width="700" height="583" /></p>
<p>XAF框架中不仅有类库，还有报表支持，而报表在信息系统中是不可缺少的，所以我还需要找到一个比较好的报表系统。我几年前研究过一阵子报表，润乾报表是我觉得模型最好的一个。感兴趣的可以参考我以前写的《<a id="ctl03_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2008/03/28/1128221.html">研究润乾报表的实现</a>》，在《<a id="ctl03_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2009/08/03/1537256.html">软件工厂方法(二）：软件工厂应用</a>》中我也介绍过研究的一些方法。</p>
<h3><a href="http://www.runqian.com.cn/">润乾报表</a></h3>
<ul>
<li>类 Excel 报表设计模型<img alt="" src="http://www.runqian.com.cn/wp-content/themes/runqian2009-08/images/home_coremodel.png" width="276" height="119" /></li>
<li>非线性报表模型</li>
<li>多源填报模型</li>
<li>强关联语义模型</li>
</ul>
<p>&nbsp;</p>
<p>以上主要说的是框架主要部分参考内容，框架思路选定后还需要一个集成环境来开发，所以我又去找了几个基于模型驱动开发的软件平台，目前准备参考<a href="http://www.mendix.com/">Mendix</a> 和<a href="http://www.novulo.com/">Novulo</a></p>
<h3><a href="http://www.cnblogs.com/zhoujg/archive/2010/01/19/1651547.html">Mendix</a></h3>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_Top%20Level%20overview%20of%20the%20Mendix%20Architecture.jpg" width="576" height="480" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_multiple%20DSL%27s%20in%20one%20modeling%20space.jpg" width="605" height="480" /></p>
<h3><a href="http://www.novulo.com/Features.aspx">Novulo</a></h3>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_novulo%20architect%20MainForm.png" width="640" height="385" /><br />
依据以上参考和个人经验，确定了如下一些架构指导思想。这个在《<a id="homepage1_HomePageDays_DaysList_ctl04_DayItem_DayList_ctl00_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2009/09/15/1567353.html">OpenExpressApp架构－一个信息系统开发平台</a>》也有所介绍</p>
<h3>架构总体思想</h3>
<ul>
<li>基于单项目开发 － 基于产品线开发</li>
<li>以独立技术为中心  － 以业务集成平台为中心</li>
<li>代码 － 模型</li>
<li>面向数据库开发  －  面向对象</li>
<li>不同复用层次: 函数/类 － 模块/引擎 &#8211; 应用包/框架</li>
</ul>
<h3><a href="http://openexpressapp.codeplex.com/">OpenExpressApp架构</a></h3>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_OpenExpessApp%20Roadmap.jpg" width="555" height="453" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_OpenExpressApp%20Framework.JPG" width="640" height="421" /></p>
<p>&nbsp;</p>
<p>以上对OpenExpressApp架构的起源以及参考的现有产品进行了简单介绍，后期我会对我如何使用这些产品或者采用这些产品思想分别进行介绍。如果大家对OpenExpressApp内部比较感兴趣的话，则理解这些已有产品将会有很大帮助。</p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/2685.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何在OpenExpressApp做客户化工作</title>
		<link>http://www.zhoujingen.cn/blog/1838.html</link>
		<comments>http://www.zhoujingen.cn/blog/1838.html#comments</comments>
		<pubDate>Fri, 03 Jan 2014 13:23:55 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>
		<category><![CDATA[软件产品线]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=1838</guid>
		<description><![CDATA[很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &#8230; <a href="http://www.zhoujingen.cn/blog/1838.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/2683.html" rel="bookmark" title="MetaModelEngine：元模型引擎开发思路">MetaModelEngine：元模型引擎开发思路 </a> <small>在DSM：使用MetaEdit+编写Family Tree Modeling L &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/2687.html" rel="bookmark" title="DSM：使用MetaEdit+编写Family Tree Modeling Language">DSM：使用MetaEdit+编写Family Tree Modeling Language </a> <small>在信息系统开发平台OpenExpressApp － 总体架构的由来中说到Meta &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作，也就是处理721问题（为了简单描述这类问题，我们简单的使用721术语，7为通用功能，2为可变功能，3为个性功能，这里721只是从数字分布上表明共性和个性的大致比例，实际中并不完全就是按照721比例分配），下图表示的就是产品线的主注内容，这个在我以前blog中也介绍过多次，本篇重点是介绍如何在<a href="http://openexpressapp.codeplex.com/"><strong>OpenExpressApp</strong></a>这种面向对象框架下做客户化。</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717281697.jpg" width="390" height="251" /></p>
<h3>版本策略</h3>
<ul>
<li><strong>以往的客户化分支版本策略带来的问题</strong></li>
</ul>
<p>以往我们做客户化时，可能会专门弄出一个客户化小组，并且从SVN中弄出一个代码分支，然后进行更改，个性的东西都保存在各自的分支中，对于共性问题在开发后期再单独合并到主干中去，这样可以带来一个好处就是在进行客户化任务时可以独立于主干版本，可以较为自由的进行更改。</p>
<p>但是这会带来后期的合并版本问题：</p>
<ol>
<li>如果分支功能很多，我们以前的做法时专门用一期任务来做合并工作，这又势必<strong>带来工作的重复</strong></li>
<li>有时合并过程中说不定还会带来客户化与主干版本之间<strong>设计上的冲突</strong></li>
<li>由于没有明确采用可变性管理而是使用分支版本方式来管理客户化工作，当客户化数量增加时势必势必会带来<strong>管理的复杂性</strong></li>
</ol>
<p>我想这也就是产品线工程方法中对于代码一套性说法的原因，<strong>产品线工程认为产品所有功能（包括721）在任何时候都可以通过一套源代码库获取</strong>，然后通过可变性管理等手段来达到针对客户化发布。</p>
<ul>
<li><strong>OpenExpressApp的产品线版本策略</strong></li>
</ul>
<p>OpenExpressApp是基于产品线工程方法来做的，我画了一个图，用来说明一下我拟定项目后期对于客户化工作的总体版本策略，如下图所示：</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201009/2010090907421052.png" /></p>
<ul>
<li>只有一个主干版本，这个产品的所有功能都由同一个代码库来管理，包括通用功能、可变功能，并且还包括个性功能，这些功能通过类继承、模型动态配置、代码静态配置等方式来处理可变性</li>
<li>通用功能和可变功能由领域工程来完成，将作为产品线的核心资产；个性功能由应用工程完成</li>
<li>分支版本只在临时性的情况下发生，例如马上需要给客户演示，并且需要在短时间修复一些bug再次演示时，我们可以临时性的打出一个分支。需要明确的是，这个分支一定是抛弃型的，并且是短期存在的</li>
<li>721中的功能会随着客户的增多带来功能迁移的情况，也就是以前是个性的可能会变为可变性或共性，以前是可变性的可能会变为共性，共性的也可能会变成可变性功能，这就要求我们在产品开发过程中随时进行重构</li>
</ul>
<h3>可变性管理</h3>
<ul>
<li><strong>处理可变性的方法</strong></li>
</ul>
<p>在<strong><a id="ctl03_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2009/09/27/1575302.html">软件产品线工程方法 － 四个主要方法原则</a></strong>中介绍过产品线中的可变性管理，在技术架构上来讲，存在以下三种基本的处理可变性方式：</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201009/2010090408333888.png" /></p>
<p>上图中矩形框代表整个软件，三角矩形代表组件，圆形代表接口。下面我简单介绍一下这三种方式，后面会把我们现在常用的一些技术对应到这三种方式上。</p>
<ul>
<li>适配</li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201009/2010090714531065.png" /></p>
<p>只有一个组件实现，但是该组件提供各种接口方式来改变它的行为，例如可能采用配置文件、运行期参数或者组件源代码补丁方式。</p>
<ul>
<li>替换</li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201009/2010090714520395.png" /></p>
<p>一个组件有多种实现，每个组件都符合该组件接口规范。领域工程中可以提供多种实现，然后在应用工程中选择其中一个，或者在应用工程中遵循组件规范开发一个个性的组件</p>
<ul>
<li>扩展</li>
</ul>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/201009/2010090714522847.png" /></p>
<p>扩展需要架构提供一些允许增加新组件的扩展点，添加的组件可以是特定产品或者框架内部的。这些组建不是系统提供的功能，而是由外部插入到系统中的，这就要求系统架构必须考虑清楚有哪些扩展点。</p>
<ul>
<li><strong>具体的可变性机制</strong>
<ul>
<li>继承(适配)<br />
子类通过继承父类来改变一些默认行为，只有一个实现组件</li>
<li>补丁(适配)<br />
如果可以获得组件的源代码，通过补丁方式可以有效地更改部分行为，而不需要维护整个组件。通过这种方式，补丁由应用工程来维护，而组件本身由领域工程来维护</li>
<li>编译期配置（适配）<br />
编译器提供机制在编译期改变组件，预处理和宏就属于这种方式。Makefiles可以编译多个不同变体的组件，或者选择一个正确的组件</li>
<li>运行期配置（适配）<br />
组件内部有多种实现，运行期可以通过配置动态改变组件行为</li>
<li>代码生成 (替换)<br />
代码生成通过读取一些高级别模型或者脚本等约定来生成某些组件或者整个产品所需要的代码</li>
<li>组件替换 (替换)<br />
默认实现了多个组件，这些组建可以是领域工程实现的，也可以是应用工程特定实现的，只要符合一定接口约定都可以通过替换整个组件来改变具体功能实现方法</li>
<li>插件 (扩展)<br />
有很多插件为系统提供扩展点，插件只要找到扩展点就可以添加额外需要的功能</li>
</ul>
</li>
</ul>
<h3>考虑模型驱动</h3>
<p>在没有模型驱动时，客户化工作更多的可能是通过代码、配置、脚本来完成，如果考虑模型，则需要对可变性建模，以下是产品线工程中的一种可变性元模型图例：</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200909/2009092721420620.jpg" /></p>
<p>如果我们也支持类模型，那么类模型和可变性模型可以按照以下方式对应：</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200909/2009092721344728.jpg" /></p>
<p>如果我们采用了代码生成技术，通过这些模型后，我们可以进一步对特定产品只生成需要的代码。</p>
<h3>应用案例场景</h3>
<p>例如清单综合单价积累可以形成典型清单库，通过积累过程也可以形成图集组价库。对于这种需求来说，从用户需求以及销售角度来看，我们可以把对图集库的支持作为产品的可选附件。我们实现的理想方案可以是提供一或多个dll，当考到目录下系统则加入图集功能，这就需要我们应用上面的可变性技术来解决。</p>
<ul>
<li>采用适配和替换方式，通过从综合清单类库继承下来，增加图集相关属性</li>
<li>添加相应的一些图集相关模块</li>
<li>把图集相关的内容部署到独立于主程序的dll，以便通过简单的复制功能达到模块的配置</li>
<li>当然还有更多的一些方法，这些需要在实际工作中不断深化&#8230;&#8230;</li>
</ul>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/2683.html" rel="bookmark" title="MetaModelEngine：元模型引擎开发思路">MetaModelEngine：元模型引擎开发思路 </a> <small>在DSM：使用MetaEdit+编写Family Tree Modeling L &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/2687.html" rel="bookmark" title="DSM：使用MetaEdit+编写Family Tree Modeling Language">DSM：使用MetaEdit+编写Family Tree Modeling Language </a> <small>在信息系统开发平台OpenExpressApp － 总体架构的由来中说到Meta &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/1838.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）</title>
		<link>http://www.zhoujingen.cn/blog/1832.html</link>
		<comments>http://www.zhoujingen.cn/blog/1832.html#comments</comments>
		<pubDate>Fri, 03 Jan 2014 13:14:42 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[产品管理]]></category>
		<category><![CDATA[技术架构]]></category>
		<category><![CDATA[软件产品线]]></category>
		<category><![CDATA[产品线]]></category>
		<category><![CDATA[架构]]></category>
		<category><![CDATA[模型驱动]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=1832</guid>
		<description><![CDATA[定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &#8230; <a href="http://www.zhoujingen.cn/blog/1832.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/464.html" rel="bookmark" title="资料下载：产品架构开发方法">资料下载：产品架构开发方法 </a> <small>企业架构、业务分析、软件产品线、产品管理，这些内容如何组织在一起发挥更大的作用， &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1840.html" rel="bookmark" title="产品线架构的演进">产品线架构的演进 </a> <small>在《 Evolution in Model-Driven Software Pr &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深入研究和实施并且对外分享的并不多，今年在中国软件技术大会和软件工程大会中我拿出这个话题与大家分享一下，也希望有更多人能够一起探讨解决之道。</p>
<p>下面第一张图是我在工作中方法层面关注的主要主题，前年在一些大会上与大家分享了敏捷相关的内容，去年分享了企业架构的内容，今年分享的话题主要涉及产品线开发和模型驱动的内容。产品线工程在软件工程是一个常见的词语，实际工作中大家提到的更多是框架、平台；模型驱动也是软件工程提到的方法，实际工作中大家听到的更多是DSL、MDA等，那具体软件产品线和模型驱动的主要内容是什么，以及它们之间又有什么关系呢？如果感兴趣，那么可以看看下面的幻灯片。</p>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850459004.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850464444.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850513949.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850488706.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850499720.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850493001.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850507919.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850513949.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850519739.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850528244.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850532605.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850543063.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850554043.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850561785.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850567815.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850572209.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/20121204085058714.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/2012120408505892.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040850599470.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851005467.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851002369.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851016763.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851021157.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851029663.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851035660.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851041973.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851054938.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851063236.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851065645.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851075264.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851084085.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851091478.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851101935.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851116819.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851125325.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851128606.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851139063.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851143981.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851156390.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851161831.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851162321.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851172538.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851194848.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851207257.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851214334.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851224268.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851226677.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851233547.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851247908.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851253905.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851261331.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851272104.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851272561.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/20121204085128510.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/20121204085129444.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851302330.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851307247.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851317705.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851323461.jpg" /><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851339491.jpg" /></p>
<p>&nbsp;</p>
<p><a href="http://minjiegeren.com/home/link.php?url=http://www.minjiegeren.com/home/link.php?url=http://www.minjiegeren.com%2Fhome%2Flink.php%3Furl%3Dhttp%3A%2F%2Fwww.minjiegeren.com%252Fhome%252Flink.php%253Furl%253Dhttp%253A%252F%252Fweibo.com%25252Fu%25252F1400992111%25253Fs%25253D6uyXnP"><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/201212/201212040851337474.png" border="0" /></a></p>
<p><strong>推荐：<a href="http://minjiegeren.com/home/link.php?url=http://www.minjiegeren.com%2Fhome%2Flink.php%3Furl%3Dhttp%3A%2F%2Fwww.minjiegeren.com%252Fhome%252Flink.php%253Furl%253Dhttp%253A%252F%252Fwww.minjiegeren.com%25252Fhome%25252Flink.php%25253Furl%25253Dhttp%25253A%25252F%25252Fwww.cnblogs.com%2525252Fzhoujg%2525252Farchive%2525252F2010%2525252F01%2525252Farchive%2525252F2011%2525252F01%2525252Farchive%2525252F2010%2525252F11%2525252Farchive%2525252F2010%2525252F02%2525252F28%2525252F1675183.html" target="_blank">你可能需要的在线电子书</a></strong></p>
<p><strong>敏捷个人sina围裙：<a href="http://minjiegeren.com/home/link.php?url=http://www.minjiegeren.com%2Fhome%2Flink.php%3Furl%3Dhttp%3A%2F%2Fwww.minjiegeren.com%252Fhome%252Flink.php%253Furl%253Dhttp%253A%252F%252Fwww.minjiegeren.com%25252Fhome%25252Flink.php%25253Furl%25253Dhttp%25253A%25252F%25252Fq.t.sina.com.cn%2525252F135484" target="_blank">http://q.t.sina.com.cn/135484</a></strong></p>
<p><strong>欢迎转载，转载请注明：转载自<a href="http://minjiegeren.com/home/link.php?url=http://www.minjiegeren.com%2Fhome%2Flink.php%3Furl%3Dhttp%3A%2F%2Fwww.minjiegeren.com%252Fhome%252Flink.php%253Furl%253Dhttp%253A%252F%252Fwww.minjiegeren.com%25252F" target="_blank">敏捷个人网站</a></strong></p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/464.html" rel="bookmark" title="资料下载：产品架构开发方法">资料下载：产品架构开发方法 </a> <small>企业架构、业务分析、软件产品线、产品管理，这些内容如何组织在一起发挥更大的作用， &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1840.html" rel="bookmark" title="产品线架构的演进">产品线架构的演进 </a> <small>在《 Evolution in Model-Driven Software Pr &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/1832.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OpenExpressApp架构－信息系统开发平台</title>
		<link>http://www.zhoujingen.cn/blog/1458.html</link>
		<comments>http://www.zhoujingen.cn/blog/1458.html#comments</comments>
		<pubDate>Sun, 03 Nov 2013 13:48:06 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>
		<category><![CDATA[OEA]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=1458</guid>
		<description><![CDATA[软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &#8230; <a href="http://www.zhoujingen.cn/blog/1458.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/2683.html" rel="bookmark" title="MetaModelEngine：元模型引擎开发思路">MetaModelEngine：元模型引擎开发思路 </a> <small>在DSM：使用MetaEdit+编写Family Tree Modeling L &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这篇主要关注的是架构。</p>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_%e8%bd%af%e4%bb%b6=BAPO.jpg" width="640" height="394" /></p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717290636.jpg" width="554" height="465" /></p>
<p>作了开发多年，期间也参考了业界一些著名的软件厂商的产品，现在已经开始实现一个适合信息系统的平台，本篇将从总体上介绍一下OpenExpressApp是什么。OpenExpressApp没有创新性的技术，它更多的是将现有技术和产品中有价值的部分引入到一起。</p>
<p>在讲解现在OpenExpressApp的情况前，我先罗列一些开发的选择，这些就如同敏捷的价值观一样，决定了我开发这个框架的总体思路和方向。</p>
<ul>
<li><b>从单项目开发到基于领域工程</b></li>
</ul>
<p>信息系统存在很多共性，而领域工程是解决产品族的一个有效方法，它通过把领域工程和应用工程作为两个独立的开发流程来看待。《<a href="http://www.zhoujingen.cn/blog/1452.html">软件工厂方法</a>》和<a id="ctl03_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2009/08/03/1537256.html">软件工厂方法(二）：软件工厂应用</a>中已经介绍过了领域工程的一些知识。</p>
<p>开发架构时，从基于单项目开发到基于领域工程来开发，会考虑到如何快速方便开发，如何做定制化，因为设计的时候就会考虑应用工程时如何通过配置来实现功能。</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717283893.jpg" width="417" height="309" /></p>
<ul>
<li><b>从代码为中心到模型驱动</b></li>
</ul>
<p>基于信息系统的共性抽取，建立一系列的模型（如领域模型、报表、UI等）来表达系统，通过代码生成器生成部分代码或者直接在框架之上运行模型，开发人员更多的关注于编写业务代码，如本篇最下面的编写Command。这样可以从框架级别进行复用。</p>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_Domain-Specific%20Development.png" width="596" height="436" /></p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717300684.jpg" width="553" height="352" /></p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200901/2009010717294967.jpg" width="250" height="380" /></p>
<ul>
<li><b>从面向数据库到面向对象</b></li>
</ul>
<p>代码中遍布表和记录的操作，还有业务逻辑遍布在SQL中，在处理简单应用时，这无疑是一种快速方便的方法，但是随着系统的复杂化，这将使得可维护性 很差。而面向对象是已经验证的很好解决复杂问题的方法，而系统系统时一旦深入开发就会遇到复杂的业务，所以面向对象的使用将是一种必然。</p>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_%e9%9d%a2%e5%90%91%e6%95%b0%e6%8d%ae%e5%ba%93%e5%88%b0%e9%9d%a2%e5%90%91%e5%af%b9%e8%b1%a1.jpg" width="627" height="461" /></p>
<ul>
<li><b>软件复用层次</b></li>
</ul>
<p>大家经常在开发软件时会谈到软件复用，我认为从实现来看复用包含以下三个级别：函数/类、模块/引擎和应用包/框架。在开发过程中，我们应该尽量多考虑大粒度的复用元素，在不同层次都关注复用。</p>
<p><b><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_%e8%bd%af%e4%bb%b6%e5%a4%8d%e7%94%a8%e5%b1%82%e6%ac%a1.png" width="463" height="299" /></b></p>
<ul>
<li><b>参考</b></li>
</ul>
<p>在目前设计和实现的过程中，主要参考了ExpressApp Framework（应用框架），MetaEdit+（元模型工具），使用了CSLA作为分布式业务对象框架，Composite WPF作为UI框架，还使用了其他一些代码（如 LiteORM、Flee等）。这些参考的产品本身就含有比较多的思想和模式，建议没有看过的或者简单了解的可以再去研究一下，这样对框架的设计非常有好处。</p>
<ul>
<li><b>Roadmap</b></li>
</ul>
<p>OpenExpressApp不同于以往独立的开发工具和框架，是为业务分析人员、软件设计和开发人员提供的一种集成的开发平台，它基于业务模型驱动开发 指导思想，提供报表、流程、元数据等基础引擎，具有业务建模、领域建模和应用建模等模型，并提供权限、报表等多个通用应用模块。为了支持软件开发，还提供 基于敏捷思想的软件项目管理工具、快速原型工具和测试支持。</p>
<p>简单地说就是使用DSM方法进行模型驱动开发，作为信息系统的开发平台，支持B/S、C/S、Mobile，支持局域网和广域网。</p>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_OpenExpessApp%20Roadmap.jpg" width="555" height="453" /></p>
<p>&nbsp;</p>
<ul>
<li><b>现状</b></li>
</ul>
<p><img alt="" src="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_OpenExpressApp%20Framework.JPG" width="520" height="342" /><br />
借鉴ExpressApp的AutoUI和扩展的思想，这里的UI层也是通过模型自动生成。<br />
以下为现在的代码组织。OpenExpressApp为框架代码，GIX4开头的为项目组应用框架时写的类库和扩展Command等代码。目前只支持WPF，还不支持B/S。</p>
<p><img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200909/2009091523091160.jpg" /><br />
现状模型只是实现了通过类的属性来实现，还未实现模型编辑器。例如下面在类上定义属性可以自动在主界面生成导航项，双击后可以打开模块，模块界面也是自动生成。现在界面都只是根据模板生成，还不支持通过设计器来设计界面。<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200909/2009091523122613.jpg" /><br />
以下是一个通过在代码中WPFListViewCommand继承下来的一个命令，在命令上写上属性内容后，就可以在界面自动生成按钮，这样开发人员可以更多关注业务逻辑，而不用关注界面的变化了。<br />
<img alt="" src="http://pic002.cnblogs.com/img/zhoujg/200909/2009091523160694.jpg" /></p>
<p>关于OEA更多内容，可以看<a href="http://www.cnblogs.com/zhoujg/archive/2010/02/28/1675183.html">我的电子书 </a></p>
<p>另，现在OEA的<a id="homepage1_HomePageDays_DaysList_DayItem_2_DayList_2_TitleUrl_0" href="http://www.cnblogs.com/zhoujg/p/3357006.html">领域实体框架Rafy2 发布了</a></p>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/2683.html" rel="bookmark" title="MetaModelEngine：元模型引擎开发思路">MetaModelEngine：元模型引擎开发思路 </a> <small>在DSM：使用MetaEdit+编写Family Tree Modeling L &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/1458.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>信息系统开发平台OpenExpressApp:【OpenTest】 之 如何实现自动化测试框架</title>
		<link>http://www.zhoujingen.cn/blog/4549.html</link>
		<comments>http://www.zhoujingen.cn/blog/4549.html#comments</comments>
		<pubDate>Thu, 15 Jul 2010 03:08:29 +0000</pubDate>
		<dc:creator><![CDATA[周金根]]></dc:creator>
				<category><![CDATA[技术架构]]></category>

		<guid isPermaLink="false">http://www.zhoujingen.cn/blog/?p=4549</guid>
		<description><![CDATA[在OpenExprssApp的Roadmap图中的OpenTool中明确列出了测 &#8230; <a href="http://www.zhoujingen.cn/blog/4549.html">继续阅读 <span class="meta-nav">&#8594;</span></a><div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p>在<a href="http://openexpressapp.codeplex.com/"><b>OpenExprssApp</b></a>的<a href="http://images.cnblogs.com/cnblogs_com/zhoujg/168052/r_OpenExpessApp%20Roadmap.jpg">Roadmap</a>图中的OpenTool中明确列出了测试，自动化测试框架是<b>OpenTest</b>的一个主要组成部分，在前面blog中我也介绍了OpenTest自动化测试框架的一些内容，本篇我介绍一下为什么现在在OEA中实现自动化测试框架，以及我是如何思考的。</p>
<h1>两周内搭建自动化测试工具</h1>
<p>我现在所在项目组开发的产品都属于新产品系列，一开始连测试人员都没有，业务人员充当测试人员，做的也只能是一些操作性的点击验证，这在项目前期还没有表现出明显的问题。到产品成型，需要交付用户上线使用时，这时问题就会很快的暴露出来了，由于一个系统并不只是一个计算器那么简单，有很多地方都需要测试，而没有专人专岗进行这项测试工作室很难保证质量的。后期，我们组进入了两名测试人员，质量也有所提高，但是每次发版他们都要进行大量的回归测试，由于时间压力、对业务和系统的把握上总会遗留一些需要回归的地方，即使他们考虑周全，这种重复性的手工测试方法也不是我所希望的工作方式，IT人工作要的就是高效能，所以我给自己的要求就是两周内支持OEA中的OpenTest自动化测试。</p>
<h1>自动化测试框架的总体要求</h1>
<p>在实现自动化测试框架之前，我并不是急于考虑使用什么语言，如何设计等，我考虑的是我的测试框架应用时应该是什么样子的</p>
<ol>
<li><b>面向测试人员，甚至需求人员，脚本简单易学易懂</b></li>
<li><b>测试脚本易维护<br />
</b></li>
<li><b>可以与需求、开发工作同步，不需要等待开发结束后才开始编写脚本</b></li>
<li><b>框架可以由有编码经验的测试人员维护扩充</b></li>
</ol>
<h1>方案选择</h1>
<p>根据上面自动化测试框架的总体要求，我没有使用VS2010自带的录制自动化测试功能，而是在OEA中加入自己的自动化测试支持：</p>
<ol>
<li><b>不做通用自动化测试框架，专为OpenExpressApp编写自动化脚本，减少复杂性</b></li>
<li><b>编写DSL自动化测试框架，让语法变得更简单，也增加可维护性</b></li>
</ol>
<h1>采用技术方案选择</h1>
<p>由于我只给了自己两周时间完成自动化测试框架，所以只能实现一个初步可以执行的框架，完成的也是核心的部分，以下对过程中的一些技术方案进行简要说明一下</p>
<ul>
<li>自动化测试支持框架：CodeUI、TestApi<br />
一开始我是准备使用TestApi来做支持的，但是使用后发现并不是很好，随着VS2010的发布，我看到了CodedUI功能，所以想到了使用它的类库作为支持，对于CodedUI的了解可以查看我之前的blog<br />
<a id="ArchiveMonth1_Days_Entries_ctl18_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/11/1756514.html">使用VS2010的CodedUI来做自己的自动化测试框架</a><a id="ArchiveMonth1_Days_Entries_ctl00_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/07/15/1778009.html"><br />
OpenTest：CodedUI如何支持下拉树形列表选择？</a><a id="ArchiveMonth1_Days_Entries_ctl02_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/30/1768011.html"><br />
测试：VS2010的Coded UI Test参考内容列表</a></li>
</ul>
<ul>
<li>开发语言：IronRuby、IronPython、C#<br />
一开始我是使用C#来验证CodeUI类库的自动化支持功能的，并不是想实用C#来作为开发，因为我希望UITest测试框架由测试人员维护，所以不希望他们必须安装庞大的Visual Stuio，所以考虑使用脚本语言，因为他们轻巧。在脚本语言，由于需要和.Net集成，所以自然考虑了IronRuby和IronPython。对于Ruby和Python，我都懂点皮毛而已，之所以选择IronRuby，是因为公司有人对Ruby熟悉，而现在公司的自动化测试框架也是使用Ruby的，所以最后选择了IronRuby。对于选择IronRuby是经过几天的技术验证的，大家可以通过以前的blog对IronRuby进行一些了解<a id="ArchiveMonth1_Days_Entries_ctl17_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/11/1756517.html"><br />
IronRuby &#8211; 如何在VS2010下调试IronRuby代码</a><a id="ArchiveMonth1_Days_Entries_ctl16_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/13/1758024.html"><br />
IronRuby &#8211; 怎么就没有好用的IDE呢？？</a><a id="ArchiveMonth1_Days_Entries_ctl08_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/23/1763521.html"><br />
IronRuby &#8211; 文件编码惹的祸</a><a id="ArchiveMonth1_Days_Entries_ctl07_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/23/1763866.html"><br />
IronRuby &#8211; 使用NetBeans编写IronRuby代码</a><a id="ArchiveMonth1_Days_Entries_ctl06_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/24/1762981.html"><br />
IronRuby － 快速在半小时学习Ruby基础知识</a><a id="ArchiveMonth1_Days_Entries_ctl05_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/25/1764961.html"><br />
IronRuby &#8211; 编写自动化测试脚本</a><a id="ArchiveMonth1_Days_Entries_ctl03_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/28/1767096.html"><br />
IronRuby：请教如何在DOS窗口正确显示UTF-8字符后执行bat文件呢？</a><a id="ArchiveMonth1_Days_Entries_ctl00_TitleUrl" href="http://www.cnblogs.com/zhoujg/archive/2010/06/30/1768437.html"><br />
IronRuby：元编程特性【method_missing】的使用</a></li>
</ul>
<h1>框架使用方法介绍</h1>
<ol>
<li>修改inc.rb中的$ExePath = &#8220;d:/GZJ/OpenExpressApp/OpenExpressApp.Host.WPF/bin/Debug&#8221;为你的程序路径</li>
<li>在框架的TestCase目录下编写测试用例文件：XXX.rb，文件大致结构如下
<div>
<div id="highlighter_303077">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
<div>12</div>
<div>13</div>
<div>14</div>
<div>15</div>
<div>16</div>
<div>17</div>
<div>18</div>
<div>19</div>
<div>20</div>
<div>21</div>
<div>22</div>
<div>23</div>
</td>
<td>
<div>
<div><code>$用例名称 = </code><code>"这个测试用例的中文名称"</code>  <code>#出现错误后，邮件中会使用这个名称来报错</code></div>
<div></div>
<div><code>#以下两个require是必须的</code></div>
<div><code>require </code><code>"inc.rb"</code></div>
<div><code>require </code><code>"TestCase/run_app.rb"</code></div>
<div></div>
<div><code>#以下为用例步骤描述区域，相当于以前写的测试用例步骤</code></div>
<div><code>#用例步骤描述:</code></div>
<div><code># 1 新增部门， 编码：Test  名称：自动化测试</code></div>
<div><code># 2 选择前两行和【一审人员】</code></div>
<div><code># 3 选中一审人员，设置部门管理的功能权限，取消部门管理下的全部展开和全部折叠功能</code></div>
<div><code># 4 选择数据权限页签，添加PBS业务对象，设置可读表达式为 1=1</code></div>
<div><code># 5 保存</code></div>
<div><code># 6 删除当前新增记录</code></div>
<div></div>
<div><code>#以下为具体脚本</code></div>
<div><code>打开模块 </code><code>"部门管理"</code></div>
<div></div>
<div><code># 1 新增部门， 编码：Test  名称：自动化测试</code></div>
<div><code>添加</code></div>
<div><code>属性编辑器(</code><code>"编码"</code><code>).输入(</code><code>"Test"</code><code>)</code></div>
<div><code>属性编辑器(</code><code>"名称"</code><code>).输入(</code><code>"自动化测试"</code><code>)</code></div>
<div><code>....</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</li>
<li>在框架main.rb中增加测试用例的启动命令
<div>
<div id="highlighter_87536">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
</td>
<td>
<div>
<div><code>require </code><code>"inc.rb"</code></div>
<div><code>require </code><code>"mail.rb"</code></div>
<div></div>
<div><code>运行测试用例文件 </code><code>"demo/project.rb"</code></div>
<div><code>运行测试用例文件 </code><code>"demo/org_manage.rb"</code></div>
<div><code>#运行测试用例文件 "demo/contract.rb"</code></div>
<div></div>
<div><code>发送邮件</code></div>
<div></div>
<div><code># TestApplication.instance.app.close</code></div>
<div><code>Playback.Cleanup()</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</li>
<li>在框架main.rb中增加邮件接收人地址
<div>
<div id="highlighter_418136">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<div>1</div>
<div>2</div>
</td>
<td>
<div>
<div><code>#增加收件人列表</code></div>
<div><code>$收件人 &lt;&lt; </code><code>"zhoujg@grandsoft.com.cn"</code></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</li>
<li>执行rub.bat运行自动化测试脚本</li>
</ol>
<h1>todo</h1>
<ol>
<li>增加检查点支持，例如行号、值，以及异常二级窗口弹出检测等</li>
<li>增加调度服务器，支持多个客户端分布执行测试用例</li>
<li>增加在OpenExpressApp应用中的录制功能，自动生成自动化测试脚本</li>
<li>OpenMetaEdit完成后，增加图形化自动化编写工具</li>
</ol>
<h1>回顾</h1>
<ol>
<li>框架设计不能一开始陷入细节，必须先确定方向，对主要方面进行思考后才动手</li>
<li>执行时大致想好计划，哪些当前做，哪些后期做</li>
<li>时刻站在使用者角度去考虑如何简化开发方法</li>
</ol>
<div class='yarpp-related-rss'>
<h3>Related posts:</h3><ol>
<li><a href="http://www.zhoujingen.cn/blog/1458.html" rel="bookmark" title="OpenExpressApp架构－信息系统开发平台">OpenExpressApp架构－信息系统开发平台 </a> <small>软件＝商业＋架构＋过程＋组织，前一阵子谈论的Scrum更多包含的是过程和组织，这 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1832.html" rel="bookmark" title="产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲）">产品线复用和模型驱动开发（2012中国软件技术大会、中国软件工程大会主题演讲） </a> <small>定制化产品相关的话题在软件产品开发过程中比较普遍，也是很多人关心的一个主题，但深 &hellip; 继续阅读 &rarr;...</small></li>
<li><a href="http://www.zhoujingen.cn/blog/1838.html" rel="bookmark" title="如何在OpenExpressApp做客户化工作">如何在OpenExpressApp做客户化工作 </a> <small>很多产品都会遇到客户化问题，也就是在通用产品之上针对一些客户会进行配置和定制工作 &hellip; 继续阅读 &rarr;...</small></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhoujingen.cn/blog/4549.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
