沧浪之水

每天进步一点点

国内软件企业的内伤(电信BSS/OSS ISV) 系列二

leave a comment

接上篇,为了解决国内厂商的前述不足,可以从几个方面来考虑改进,今天我列举一个通过构建电信运营支撑系统软件平台来解决厂商能力不足的问题,具体技术框架列表如下:

模型平台实现框架:

  • Metadata Schema Management 元数据模式管理

  • Workflow Process Management 工作流引擎

  • Role Engine & State Model 规则引擎和状态机

  • MVC Pattern Reproduction 改造MVC模式

  • Standardized Configurator Application 标准化配置程序

  • Common Data Components 公共数据构件
    • Entity Relationships ,Entity Extension,
      Entity Attribute,Entity Attribute Extension ,Default Method
      实体关系(对象和组件及关系),实体扩展,实体属性,实体属性扩展,默认方法
    • Common
    • Enumeration, Status, TimePeriod, etc.
    • UserLogin, Security
    • Content
    • Party , Human Resources
    • Accounting
    • Catalog,Catagory,Product ,Asset,Asset Management
    • Order ,Order Lifecycle Management
    • Marketing
    • Shipment
    • Work Effort
  • Common Logic Components 公共逻辑构件
    • CRUD Style Services “增删改查”式服务
    • Logic for User Interfaces and Business Processes
      UI和业务流程逻辑
    • Maintenance Jobs (usually scheduled) 管理工作/进程
    • Implementations to Expect 例外
  • User Interface Patterns & Engine UI模式和引擎
    • List of Value 值列表
    • Template Engine 模板引擎
    • Super Form 超级表单
    • Super List(ordering ,cursor)
      超级列表(排序,游标,树形)
    • Controler ,Default method 控件,默认方法
    • Super PopupWin 弹出窗口

Written by corlin

十月 12th, 2009 at 8:28 上午

国内软件企业的内伤(电信BSS/OSS ISV) 系列一

leave a comment

最近几年,我陆续参与了北京联通,网通北方各省,移动,电信的BSS,OSS系统的需求分析,设计和实施。逐步接触了国内的一些主要BSS/OSS 厂商的一些产品和海外Amdocs,Siebel,CSG Kenan等COTS套装软件。
最近海外企业逐步渗入我们国家核心电信运营支撑系统的建设,CSG的Kenan ,Siebel系统平台,Comptel公司(据说最近已被Oracle收购),Amdocs(收购朗新,成功进入电信核心系统实施),渗入的层次都比较深,例如:北京移动,浙江电信全省的运营支撑系统,全部由上述COTS软件替代;上海电信,新疆电信也基本被Amdocs,Siebel前台等包围。而浙江,北京,上海基本上是电信业的主要几个桥头堡;在这些桥头堡上,很难看到国内企业的身影,有的,也只是项目的具体外包实施(俗称高级苦力,每天早9点到晚9点的维护系统)角色,不是项目决策层。
3G已经开始具体实施,4G国外也在规划和实施了。中国内地的本土电信支撑软件提供商都怎么了。。。
从我这2年做COTS实施,国内本土软件商产品的实施对比来看,不难看出中国内地支撑软件提供商自身的一些内伤:

  1. 公司战略模糊,打一枪换一个地方
    • 大多数国内BSS/OSS厂商都是和电信运营商捆绑在一起,客户的需求散乱而没有章法,客户需要什么,厂商就开发什么;厂商没有自己的战略,或者战略根本得不到有效执行,终日被电信商,利润牵着鼻子走。
  2. 系统模型陈旧,人员观念成就;
    • 系统还停留在功能开发和堆叠的老旧模式,没有一套成熟的业务模型,业务流程;不能很好的参照国外既有标准(ITU,NGOSS,ITIL等);相应人员观念成就,大都以完成任务为准,没有考虑系统的可扩展性,易维护性,接口和平台交互性;各系统数据冗余严重,电信企业无法很好建立自己的数据中心,决策层更无法根据集中的数据中心进行决策
  3. 软件系统陈旧,亟待改造
    • 大都还是按MVC模式建立软件系统架构,对复杂多变业务支持不足,系统、流程、功能的灵活配置能力差,软件开发工作量大,成本高
  4. 没有实施方法,或实施方法不敏捷高效
    • 没有积累完善的实施方法,软件递交方法;软件实施过程混乱,需求和实现吻合度差,软件质量和性能不足,客户界面差,操作繁琐。
    • 实施过程缓慢,工作监控和量化不足,导致人浮于事,工期加长,人员情绪低落,加班加点严重
  5. 没有知识积累,人员流失严重
    • 人员,特别是业务分析,需求调研,业务专家等高级专家流失、流动严重;导致新人直接进入核心模块的设计开发,核心价值得不到有力保障。


Technorati :

Written by corlin

十月 12th, 2009 at 8:27 上午

启动ERWin的一个错误修复

leave a comment

新项目用CA 的ERWin做为ER建模工具,本来用的好好的,今天突然报出 mmopn32.exe 的程序错误,无法启动ERWin ,遂G了一下,发现是Windows目录下的 ERwin40.ini 捣的鬼,删除/改名该文件后,ERWin可以正常启动,奇怪哦,CA干吗弄INI文件到系统目录下,有空可以研究研究。

好,工具修好了,继续工作。)



Technorati :

Written by corlin

十月 12th, 2009 at 8:25 上午

圈子真的很小

leave a comment

哈哈,IT圈子真的很小,中午吃工作餐,四位原来合力的老同事又碰头了(最近差不多碰到了八九位合力的老同事),现在大家分属两家公司。做的业务也不尽相同,但大家感触都差不多;结婚生子,工作生活,堵车与开车,行业发展,公司前景。

抽取几段聊天心得:

  1. 小孩睡觉得养成好习惯,不然天天半夜闹你起床;

  2. 北京还是坐公共交通好,开车上下班费钱又费时;

  3. 3G要来了,大家都在努力准备,软件公司业务和产品的积淀是关键;

  4. 开三轮车拉活的比我们赚的多;

  5. BI和CRM该是今后电信软件建设的关键;

  6. 努力让老婆在家附近找个好工作;

  7. 移动独大的日子不久就结束了,话费估计会下调了,以后还会有固定电话吗?

  8. 电信软件公司不好过,减薪增效,按效计酬成了落后公司的风俗;奖金优厚,人才集中,天天加班也成了先进公司的习惯;优胜劣汰一直在继续

  9. 努力赚钱,多拿奖金,少加班是大家的心愿。^_^


Technorati :

Written by corlin

十月 12th, 2009 at 8:24 上午

安永的企业家精神的四个考量指标

leave a comment

1)对企业和个人设定一个高标准并坚定不移地执行和实现;
2)能够证明其克服了困难和障碍;
3)遭受过巨大的失败并且从失败中吸取教训;
4)既能信任团队,又能在不确定性前独立思考。


Technorati :
Del.icio.us :

Written by corlin

十月 12th, 2009 at 8:23 上午

需求中的逻辑实体关系设计主要为了什么

leave a comment

    理清系统中的实体,实体属性,关联,作用域信息

      将需求细化到不可分割的实体属性,如果实体的属性还有相关描述和范围,还需将属性提升到实体

        明确实体间关系和约束,建立明确的关联关系,依此来避免遗漏需求

          明确约束的必要性原则,区分强关联和弱关联,保证系统完整性和健壮性

            有机划分逻辑域 ,相同功能的实体归并到同一个域,域之间建立较少的弱关联,有利于组件化和模块化

Written by corlin

十月 12th, 2009 at 8:22 上午

Java代码优化,策略与方法

leave a comment

整理了一些影响性能的代码和优化方法,以后希望能陆续补充和优化

1. 如何使用Exception
Exception降低性能。一个异常抛出首先需要创建一个新的对象。Throwable接口中的构造器调用名为fillInStackTrace()的本地方法。这个方法负责巡检栈的整个框架来收集跟踪信息。这样无论何时有异常抛出,它要求虚拟机装载调用栈,因为一个新的对象在中部被创建。
异常应当仅用于有错误发生时,而不要控制流。
2. 不要两次初始化变量
Java通过调用独特的类构造器默认地初始化变量为一个已知的值。所有的对象被设置成null,integers (byte, short, int, long)被设置成0,float和double设置成0.0,Boolean变量设置成false。这对那些扩展自其它类的类尤其重要,这跟使用一个新的关键词创建一个对象时所有一连串的构造器被自动调用一样。
3. 在任何可能的地方让类为Final
标记为final的类不能被扩展。在《核心Java API》中有大量这个技术的例子,诸如java.lang.String。将String类标记为final阻止了开发者创建他们自己实现的长度方法。
更深入点说,如果类是final的,所有类的方法也是final的。Java编译器可能会内联所有的方法(这依赖于编译器的实现)。在我的测试里,我已经看到性能平均增加了50%。
4. 在任何可能的地方使用局部变量
属于方法调用部分的自变量和声明为此调用一部分的临时变量存储在栈中,这比较快。诸如static,实例(instance)变量和新的对象创建在堆中,这比较慢。局部变量的更深入优化依赖于你正在使用的编译器或虚拟机。
5. 停止小聪明
很多开发人员在脑子中编写可复用和灵活的代码,而有时候在他们的程序中就产生额外的开销。曾经或者另外的时候他们编写了类似这样的代码:
public void doSomething(File file) {
FileInputStream fileIn = new FileInputStream(file);
// do something
他够灵活,但是同时他们也产生了更多的开销。这个主意背后做的事情是操纵一个InputStream,而不是一个文件,因此它应该重写如下:
public void doSomething(InputStream inputStream){
// do something
6. 乘法和除法
我有太多的东东适用于摩尔法则–它声明CPU功率每年成倍增长。”摩尔法则”表明每年由开发者所写的差劲的代码数量三倍增加,划去了摩尔法则的任何好处。
考虑下面的代码:
for (val = 0; val < 100000; val +=5) { shiftX = val * 8; myRaise = val * 2; }
如果我们狡猾的利用位移(bit),性能将会六倍增加。这是重写的代码:
for (val = 0; val < 100000; val += 5) { shiftX = val << 3; myRaise = val << 1; }
代替了乘以8,我们使用同等效果的左移3位。每一个移动相当于乘以2,变量myRaise对此做了证明。同样向右移位相当于除以2,当然这会使执行速度加快,但可能会使你的东东以后难于理解;所以这只是个建议
7. 用代码有效处理内存溢出
OutOfMemoryError是由于内存不够后普遍会遇到的问题,下面一段代码能有效判断内存溢出错误,并在内存溢出发生时有效回收内存
通过该方法可以联想到有效管理连接池溢出,道理等同。
import java.util.*;
public class DataServer
{
private Hashtable data = new Hashtable();
public Object get (String key)
{
Object obj = data.get (key);
if (obj == null)
{
System.out.print (key + ” “);
try
{
// simulate getting lots of data
obj = new Double[1000000];
data.put (key, obj);
}
catch (OutOfMemoryError e)
{
System.out.print (“\No Memory! “);
flushCache();
obj = get (key);// try again
}
}
return (obj);
}
public void flushCache()
{
System.out.println (“Clearing cache”);
data.clear();
}
public static void main (String[] args)
{
DataServer ds = new DataServer();
int count = 0;
while (true) // infinite loop for test
ds.get (“” + count++);
}
}
8. Lazy Loading (Lazy evaluation)在需要装入的时候才装入
static public long
factorial( int n ) throws IllegalArgumentException
{
IllegalArgumentException illegalArgumentException =
new IllegalArgumentException( “must be >= 0″ );
if( n < 0 ) {
throw illegalArgumentException ;
} else if( ( n == 0 ) || ( n == 1 ) ) {
return( 1 );
} else (
return( n * factorial( n – 1 ) ) ;
}
优化后代码
static public long
factorial( int n ) throws IllegalArgumentException
{
if( n < 0 ) {
throw new IllegalArgumentException( “must be >= 0″ );
} else if( ( n == 0 ) || ( n == 1 ) ) {
return( 1 );
} else (
return( n * factorial( n – 1 ) ) ;
}
9. 异常在需要抛出的地方抛出,try catch能整合就整合
try {
some.method1(); // Difficult for javac
} catch( method1Exception e ) { // and the JVM runtime
// Handle exception 1 // to optimize this
} // code
try {
some.method2();
} catch( method2Exception e ) {
// Handle exception 2
}
try {
some.method3();
} catch( method3Exception e ) {
// Handle exception 3
}
已下代码 更容易被编译器优化
try {
some.method1(); // Easier to optimize
some.method2();
some.method3();
} catch( method1Exception e ) {
// Handle exception 1
} catch( method2Exception e ) {
// Handle exception 2
} catch( method3Exception e ) {
// Handle exception 3
}
10. For循环的优化
Replace…
for( int i = 0; i < collection.size(); i++ ) {

}
with…
for( int i = 0, n = collection.size(); i < n; i++ ) {

}
11. 字符串操作优化
在对字符串实行+操作时,最好用一条语句
// Your source code looks like…
String str = “profit = revenue( ” + revenue +
“) – cost( ” + cost + “)”;

// 编译方法
String str = new StringBuffer( ).append( “profit = revenue( ” ).
append( revenue ).append( “) – cost( ” ).
append( cost ).append( “)” ).toString( );
在循环中对字符串操作时改用StringBuffer.append()方法
String sentence = “”;
for( int i = 0; i < wordArray.length; i++ ) {
sentence += wordArray[ i ];
}
优化为
StringBuffer buffer = new StringBuffer( 500 );
for( int i = 0; i < wordArray.length; i++ ) {
buffer.append( wordArray[ i ] );
}
String sentence = buffer.toString( );
12. 对象重用(特别对于大对象来说)
public
class Point
{
public int x;
public int y;
public Point( )
{
this( 0, 0 );
}
}
优化为:
public class Component
{
private int x;
private int y;
public Point getPosition( )
{
Point rv = new Point( ); // Create a new Point
rv.x = x; // Update its state
rv.y = y;
return rv;
}
}
// Process an array of Component positions…
for( int i = 0; i < componentArray.length; i++ ) {
Point position = componentArray[i].getPosition( );
// Process position value…
// Note: A Point object is created for *each* iteration
// of the loop…
}
可再次优化,仅使用一个类对象:)
public
class Component
{
private int x;
private int y;
public Point getPosition( Point rv )
{
if( rv == null) rv = new Point( );
rv.x = x; // Update its state
rv.y = y;
return rv;
}
// Create a single point object and reuse it…
Point p = new Point( );
for( int i = 0; i < componentArray.length; i++ ) {
Point position = componentArray[i].getPosition( p );
// Process position value…
// Note: Only *one* Point object is ever created.
}
13. j2ee相关
a) 尽量不要将大对象放到HttpSession或其他须序列化的对象中,并注意及时清空Session
b) 使用预编译语句prepareStatement代替createStatement
c) 尽可能使用连接池
d) 能使用Cache就使用Cache,具体实现可参考jive(Cache\Cacheable\CacheObject\CacheSizes \DefaultCache\LinkdList\LinkdListNode)或ofbiz(org.ofbiz.core.util. UtilCache.java)


JDBC相关
a) 测试,为应用选择一个最好的JDBC驱动器
b) 调整合适的连接池大小
c) 该关闭连接的时候必须保证关闭连接并回收资源
a) 在finally 块中关闭 JDBC 连接
d) 在where条件中为查询建立索引
e) 用EXPLAIN SELECT 等工具命令查看SQL代码实际的运行过程 ,并关注:
a) 查询是否充分利用了索引字段
b) 避免多路连接(n-way joins )
c) 避免取得海量数据
f) 关闭自动提交功能(Auto-Commit),集合所有更新和插入操作到事物处理或/batch操作中


Technorati :

Written by corlin

十月 12th, 2009 at 3:45 上午

Log4J 最佳实践之全能配置文件

leave a comment

下面给出得Log4J配置文件实现了输出到控制台,文件,回滚文件,发送日志邮件,输出到数据库日志表,自定义标签等全套功能。

log4j.rootLogger=DEBUG,CONSOLE,A1,im
#DEBUG,CONSOLE,FILE,ROLLING_FILE,MAIL,DATABASE

log4j.addivity.org.apache=true


###################
# Console Appender
###################
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.Threshold=DEBUG
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n
#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n


#####################
# File Appender
#####################
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=file.log
log4j.appender.FILE.Append=false
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n
# Use this layout for LogFactor 5 analysis



########################
# Rolling File
########################
log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLING_FILE.Threshold=ERROR
log4j.appender.ROLLING_FILE.File=rolling.log
log4j.appender.ROLLING_FILE.Append=true
log4j.appender.ROLLING_FILE.MaxFileSize=10KB
log4j.appender.ROLLING_FILE.MaxBackupIndex=1
log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n


####################
# Socket Appender
####################
log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
log4j.appender.SOCKET.RemoteHost=localhost
log4j.appender.SOCKET.Port=5001
log4j.appender.SOCKET.LocationInfo=true
# Set up for Log Facter 5
log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n


########################
# Log Factor 5 Appender
########################
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000


########################
# SMTP Appender
#######################
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
log4j.appender.MAIL.Threshold=FATAL
log4j.appender.MAIL.BufferSize=10
log4j.appender.MAIL.From=chenyl@hollycrm.com
log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
log4j.appender.MAIL.Subject=Log4J Message
log4j.appender.MAIL.To=chenyl@hollycrm.com
log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
log4j.appender.MAIL.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n


########################
# JDBC Appender
#######################
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password=
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (‘[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n’)
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n


log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=SampleMessages.log4j
log4j.appender.A1.DatePattern=yyyyMMdd-HH’.log4j’
log4j.appender.A1.layout=org.apache.log4j.xml.XMLLayout

###################
#自定义Appender
###################
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender

log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient = corlin@cybercorlin.net

log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern =[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n


Technorati :

Written by corlin

十月 12th, 2009 at 3:44 上午

软件生产过程相关命名规程

leave a comment

基线标识:

需求基线 Requirement Base Lines RM
详细设计基线 Detailed Design Base Lines DD
代码基线 Source Code Base Lines SC
测试基线 Software Test Base Lines ST
运行基线 Production Release Base Lines PR

基线创建时机

需求基线 客户需求批准时
概要设计基线 概要设计获得批准
详细设计基线 详细设计获得批准
代码基线 完成原始软件单元编码、并通过检查和单元测试
测试基线 为测试而发布软件
运行基线(产品基线) 为运行而发布系统(产品的正式发布)
文档名称标识:

软件需求说明书 Software Requirement Specifications SRS
详细设计文档 Detail Design Documents DDD
软件项目计划 Software Project Plan SPP
测试计划 Testing Plan TP
系统测试用例 System Testing Case STC
系统测试报告 System Testing Report STR
工作说明书 Statement Of Work SOW
项目周报 Weekly Report WR
项目报告 Project Report PR
会议纪要 Meeting Summary MS
工作产品审批表 Product Approval Form PAF
工作任务分解 Work Breakdown Structure WBS
项目开发计划 Software Development Plan SDP
质量保证计划 Software Quality Assurance Plan SQAP
配置管理计划 Software Configuration Management Plan SCMP
产品审计检查表 Product Audit Check Form PACF
产品审计报告 Product Audit Report PAR
过程评审检查表 Process Review Check Form PRCF
过程评审报告 Process Review Report PRR
风险管理计划 Risk […]


Technorati :

Written by corlin

十月 12th, 2009 at 3:12 上午

楚辞 渔父

leave a comment

屈原既放,游於江潭,行吟泽畔,颜色憔悴,形容枯槁。渔父见而问之曰:
“子非三闾大夫与?何故至於斯!”
屈原曰:”举世皆浊我独清,众人皆醉我独醒,是以见放!”
渔父曰:”圣人不凝滞於物,而能与世推移。
世人皆浊,何不淈其泥而扬其波?
众人皆醉,何不餔其糟而歠其酾?
何故深思高举,自令放为?”
屈原曰:”吾闻之,新沐者必弹冠,新浴者必振衣;
安能以身之察察,受物之汶汶者乎!
宁赴湘流,葬於江鱼之腹中。
安能以皓皓之白,而蒙世俗之尘埃乎!”
渔父莞尔而笑,鼓枻而去,乃歌曰:
“沧浪之水清兮,可以濯吾缨。
沧浪之水浊兮,可以濯吾足。”
遂去不复与言


Technorati :

Written by corlin

十月 12th, 2009 at 3:11 上午