paulwong

#

某hadoop视频教程内容

@import url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); 第1章节:
> Hadoop背景
> HDFS设计目标
> HDFS不适合的场景
> HDFS架构详尽分析
> MapReduce的基本原理



第2章节
> Hadoop的版本介绍
> 安装单机版Hadoop
> 安装Hadoop集群



第3章节
> HDFS命令行基本操作
> Namenode的工作机制
> HDFS基本配置管理



第4章节
> HDFS应用实战:图片服务器(1) - 系统设计
> 应用的环境搭建 php + bootstrap + java
> 使用Hadoop Java API实现向HDFS写入文件



第5章节
> HDFS应用实战:图片服务器(2)
> 使用Hadoop Java API实现读取HDFS中的文件
> 使用Hadoop Java API实现获取HDFS目录列表
> 使用Hadoop Java API实现删除HDFS中的文件


第6章节
> MapReduce的基本原理
> MapReduce的运行过程
> 搭建MapReduce的java开发环境
> 使用MapReduce的java接口实现WordCount



第7章节
> WordCount运算过程分析
> MapReduce的combiner
> 使用MapReduce实现数据去重
> 使用MapReduce实现数据排序
> 使用MapReduce实现数据平均成绩计算



第8章节
> HBase详细介绍
> HBase的系统架构
> HBase的表结构,RowKey,列族和时间戳
> HBase中的Master,Region以及Region Server


第9章节
> 使用HBase实现微博应用(1)
> 用户注册,登陆和注销的设计
> 搭建环境 struts2 + jsp + bootstrap + jquery + HBase Java API
> HBase和用户相关的表结构设计
> 用户注册的实现



第10章节
> 使用HBase实现微博应用(2)
> 使用session实现用户登录和注销
> “关注"功能的设计
> “关注"功能的表结构设计
> “关注"功能的实现


第11章节
> 使用HBase实现微博应用(3)
> “发微博"功能的设计
> “发微博"功能的表结构设计
> “发微博"功能的实现
> 展现整个应用的运行



第12章节
> HBase与MapReduce介绍
> HBase如何使用MapReduce



第13章节

> HBase应用实战:话单查询与统计(1)
> 应用的整体设计
> 开发环境搭建
> 表结构设计



第14章节
> HBase应用实战:话单查询与统计(2)
> 话单入库单设计与实现
> 话单查询的设计与实现



第15章节
> HBase应用实战:话单查询与统计(3)
> 统计功能设计
> 统计功能实现



第16章节
> 深入MapReduce(1)
> split的实现详解
> 自定义输入的实现
> 实例讲解



第17章节
> 深入MapReduce(2)
> Reduce的partition
> 实例讲解



第18章节
> Hive入门
> 安装Hive
> 使用Hive向HDFS存入结构化数据
> Hive的基本使用


第19章节
> 使用MySql作为Hive的元数据库
> Hive结合MapReduce



第20章节
> Hive应用实战:数据统计(1)
> 应用设计,表结构设计



第21章节
> Hive应用实战:数据统计(2)
> 数据录入与统计的实现 

posted @ 2013-01-05 12:59 paulwong| 编辑 收藏

HBase的一些应用设计tip

1,对于HBase的存储设计,要考虑它的存储结构是:rowkey+columnFamily:columnQualifier+timestamp(version)+value = KeyValue in HBase,一个KeyValue依次按照rowkey,columnkey和timestamp有序。一个rowkey加一个column信息定位了hbase表的一个逻辑的行结构。
0XJJ{2%~G~[G]JBPMW}YE~A 

2,从逻辑存储结构到实际的物理存储结构要经历一个fold过程,所有的columnFamily下的内容被有序的合并,因为HBase把一个ColumnFamily存储为一个StoreFile。

3,把HBase的查询等价为一个逐层过滤的行为,那么在设计存储时就应该明白,使设计越趋向单一的keyvalue性能会越好;如果是因为复杂的业务逻辑导致查询需要确定rowkey、column、timestamp,甚至更夸张的是用到了HBase的Filter在server端做value的处理,那么整个性能会非常低。 

4,因此在表结构设计时,HBase里有tall narrow和flat wide两种设计模式,前者行多列少,整个表结构高且窄;后者行少列多,表结构平且宽;但是由于HBase只能在行的边界做split,因此如果选择flat wide的结构,那么在特殊行变的超级大(超过file或region的上限)时,那么这种行为会导致compaction,而这样做是要把row读内存的~~因此,强烈推荐使用tall narrow模式设计表结构,这样结构更趋近于keyvalue,性能更好。 

5,一种优雅的行设计叫做partial row scan,我们一般rowkey会设计为<key1>-<key2>-<key3>...,每个key都是查询条件,中间用某种分隔符分开,对于只想查key1的所有这样的情况,在不使用filter的情况下(更高性能),我们可以为每个key设定一个起始和结束的值,比如key1作为开始,key1+1作为结束,这样scan的时候可以通过设定start row和stop row就能查到所有的key1的value,同理迭代,每个子key都可以这样被设计到rowkey中。 

6,对于分页查询,推荐的设计方式也不是利用filter,而是在scan中通过offset和limit的设定来模拟类似RDBMS的分页。具体过程就是首先定位start row,接着跳过offset行,读取limit行,最后关闭scan,整个流程结束。 

7,对于带有时间范围的查询,一种设计是把时间放到一个key的位置,这样设计有个弊端就是查询时一定要先知道查询哪个维度的时间范围值,而不能直接通过时间查询所有维度的值;另一种设计是把timestamp放到前面,同时利用hashcode或者MD5这样的形式将其打散,这样对于实时的时序数据,因为将其打散导致自动分到其他region可以提供更好的并发写优势。 

8,对于读写的平衡,下面这张图更好的说明了key的设计:salting等价于hash,promoted等价于在key中加入其他维度,而random就是MD这样的形式了。
  VN{YX`@[2P9AQ[@(2U8N9{0

9,还有一种高级的设计方式是利用column来当做RDBMS类似二级索引的应用设计,rowkey的存储达到一定程度后,利用column的有序,完成类似索引的设计,比如,一个CF叫做data存放数据本身,ColumnQualifier是一个MD5形式的index,而value是实际的数据;再建一个CF叫做index存储刚才的MD5,这个index的CF的ColumnQualifier是真正的索引字段(比如名字或者任意的表字段,这样可以允许多个),而value是这个索引字段的MD5。每次查询时就可以先在index里找到这个索引(查询条件不同,选择的索引字段不同),然后利用这个索引到data里找到数据,两次查询实现真正的复杂条件业务查询。

10,实现二级索引还有其他途径,
比如:
1,客户端控制,即一次读取将所有数据取回,在客户端做各种过滤操作,优点自然是控制力比较强,但是缺点在性能和一致性的保证上;
2,Indexed-Transactional HBase,这是个开源项目,扩展了HBase,在客户端和服务端加入了扩展实现了事务和二级索引;
3,Indexed-HBase;
4,Coprocessor。 

11,HBase集成搜索的方式有多种:1,客户端控制,同上;2,Lucene;3,HBasene,4,Coprocessor。 

12,HBase集成事务的方式:1,ITHBase;2,ZooKeeper,通过分布式锁。 

13,timestamp虽然叫这个名字,但是完全可以存放任何内容来形成用户自定义的版本信息。

posted @ 2013-01-02 23:09 paulwong 阅读(1088) | 评论 (0)编辑 收藏

用JAMES实现自己的邮件服务器

应用服务器Apache企业应用XMLC
简介
James 是一个企业级的邮件服务器,它完全实现了smtp 和 pops 以及nntp 协议。同时,james服务器又是一个邮件应用程序平台。James的核心是Mailet API,而james 服务齐是一个mailet的容器。它可以让你非常容易的实现出很强大的邮件应用程序。James开源项目被广泛的应用于与邮件有关的项目中。你可以通过它来搭建自己的邮件服务器。我们可以利用Mailet API,编程接口来实现自己所需的业务。James集成了Avalon 应用程序框架以及Phoenix Avalon 框架容器。Phoenix为james 服务器提供了强大的支持。需要说明的是Avalon开源项目目前已经关闭。
快速上手
安装james
我这次使用的安装包是james 2.3.1。大家可以从这里下载到http://james.apache.org/download.cgi
现在让我们开始我们激动人心的james之旅。首先我们将james-binary-2.3.1.zip解压缩下载到你的安装目录。我们可以把这个过程理解为安装的过程。我在这里将它解压到c:\.并且把它改名为james.这样我们的james就安装好了。目录为C:\james。很简单吧!

准备知识 - 学习一些必要的知识
在我使用james的时候让我感觉首先理解james的应用程序结构是很重要的。否则你会在使用中感到很困惑。
它的应用程序结构是这样的:
James
|_ _apps
|_ _bin
|_ _conf
|_ _ext
|_ _lib
|_ _logs
|_ _tools
我们重点介绍一下两个文件夹bin 和 apps.
bin目录中的run.bat和run.sh是James的启动程序。只要记住这个重要文件就可以。
启动之后控制台显示如下:
Using PHOENIX_HOME: C:\james
Using PHOENIX_TMPDIR: C:\james\temp
Using JAVA_HOME: C:\j2sdk1.4.2_02
Phoenix 4.2
James Mail Server 2.3.1
Remote Manager Service started plain:4555
POP3 Service started plain:110
SMTP Service started plain:25
NNTP Service started plain:119
FetchMail Disabled
Apps 目录下有个james的子目录这个目录是它的核心。
james
|_ _SAR-INF
|_ _conf
|_ _logs
|_ _var
|_mail
|_address-error
|_error
|_indexes
|_outgoing
|_relay-denied
|_spam
|_spool
|_nntp
|_....

|_users
SAR-INF 下有一个config.xml是james中的核心配置文件。
Logs 包含了与james有关的Log。调试全靠它了。
Var 包含了一些文件夹通过它们的名字我们大概也能猜测出它们的用途。Mail主要用于存储邮件。nntp主要用于新闻服务器。Users用于存储所有邮件服务器的用户。也就是邮件地址前面的东东。如:pig@sina.com的pig就是所谓用用户。

创建用户:
我们在James上建若干用户,用来测试收发邮件。当然如果你不用james本身的用户也可以。James以telnet 的方式提供了接口用来添加用户。下面我来演示一下。
首先使用telnet来连接james的remote manager .
1.telnet localhost 4555 回车
2.然后输入管理员用户名和密码(user/pwd : root/root 是默认设置这个可以在config.xml中修改)
JAMES Remote Administration Tool 2.3.1
Please enter your login and password
Login id:
root
Password:
root
Welcome root. HELP for a list of commands

3.添加用户
adduser kakaxi kakaxi
User kakaxi added

Adduser mingren mingren
User mingren added

4.查看添加情况
listusers
Existing accounts 2
user: mingren
user: kakaxi
得到上面的信息说明我们已经添加成功。


发送器
这个类主要用来测试我们的邮件服务器,可以不用将其打入包中。
java 代码 
package com.paul.jamesstudy;   
  
import java.util.Date;   
import java.util.Properties;   
  
import javax.mail.Authenticator;   
import javax.mail.Message;   
import javax.mail.PasswordAuthentication;   
import javax.mail.Session;   
import javax.mail.Transport;   
import javax.mail.internet.InternetAddress;   
import javax.mail.internet.MimeMessage;   
  
public class Mail {   
    private String mailServer, From, To, mailSubject, MailContent;   
  
    private String username, password;   
  
    private Session mailSession;   
  
    private Properties prop;   
  
    private Message message;   
  
    // Authenticator auth;//认证   
    public Mail() {   
        // 设置邮件相关   
        username = "kakaxi";   
        password = "kakaxi";   
        mailServer = "localhost";   
        From = "kakaxi@localhost";   
        To = "mingren@localhost";   
        mailSubject = "Hello Scientist";   
        MailContent = "How are you today!";   
    }   
    public void send(){   
        EmailAuthenticator mailauth =    
new EmailAuthenticator(username, password);   
        // 设置邮件服务器   
        prop = System.getProperties();   
        prop.put("mail.smtp.auth", "true");   
        prop.put("mail.smtp.host", mailServer);   
        // 产生新的Session服务   
        mailSession = mailSession.getDefaultInstance(prop,   
                (Authenticator) mailauth);   
        message = new MimeMessage(mailSession);   
  
        try {   
        message.setFrom(new InternetAddress(From)); // 设置发件人   
        message.setRecipient(Message.RecipientType.TO,    
new InternetAddress(To));// 设置收件人   
        message.setSubject(mailSubject);// 设置主题   
        message.setContent(MailContent, "text/plain");// 设置内容   
        message.setSentDate(new Date());// 设置日期   
        Transport tran = mailSession.getTransport("smtp");   
        tran.connect(mailServer, username, password);   
        tran.send(message, message.getAllRecipients());   
        tran.close();   
        } catch (Exception e) {   
            e.printStackTrace();   
        }   
    }   
    public static void main(String[] args) {   
        Mail mail;   
        mail = new Mail();   
        System.out.println("sending");   
        mail.send();   
        System.out.println("finished!");   
    }   
  
}   
  
class EmailAuthenticator extends Authenticator {   
    private String m_username = null;   
  
    private String m_userpass = null;   
  
    void setUsername(String username) {   
        m_username = username;   
    }   
  
    void setUserpass(String userpass) {   
        m_userpass = userpass;   
    }   
  
    public EmailAuthenticator(String username, String userpass) {   
        super();   
        setUsername(username);   
        setUserpass(userpass);   
    }   
  
    public PasswordAuthentication getPasswordAuthentication() {   
        return new PasswordAuthentication(m_username, m_userpass);   
    }   
}   


posted @ 2012-12-16 13:14 paulwong 阅读(902) | 评论 (0)编辑 收藏

java程序实现对sftp服务器的操作

FTP服务器中,如果使用的是FTP协议,则用户名和密码是以明文方式传输的,如果是以SFTP 的方式,就会通过加密的方式传输。

如果服务器中的用户增加了公钥的设置,则要求客户端要有相对应的私钥。

公/私钥的产生方法可见:http://www.jcraft.com/jsch/examples/KeyGen.java.html,值得注意的是,可以产生用密码的公私钥和无密码的公私钥。

SFTP服务器:http://www.xlightftpd.com/cn/tutorial/SSH2_SFTP_Setup.html,下载后,添加虚拟服务器,添加用户,并为用户添加公钥文件,即可。

JAVA模拟一个SFTP服务器:http://mina.apache.org/sshd-project/embedding_ssh.html
http://svn.apache.org/repos/asf/mina/sshd/trunk/
public void setupSftpServer(){
    SshServer sshd = SshServer.setUpDefaultServer();
    sshd.setPort(22);
    sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));

    List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<NamedFactory<UserAuth>>();
    userAuthFactories.add(new UserAuthNone.Factory());
    sshd.setUserAuthFactories(userAuthFactories);

    sshd.setCommandFactory(new ScpCommandFactory());

    List<NamedFactory<Command>> namedFactoryList = new ArrayList<NamedFactory<Command>>();
    namedFactoryList.add(new SftpSubsystem.Factory());
    sshd.setSubsystemFactories(namedFactoryList);

    try {
        sshd.start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

在这里介绍对sftp操作的一种java框架:JSch-Java Secure Channel,官方地址是:http://www.jcraft.com/jsch/

具体使用方法请看下面代码:

package jsch;

import java.io.File;
import java.io.FileInputStream;
import java.util.Properties;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class Test {

    protected String host;//sftp服务器ip
    protected String username;//用户名
    protected String password;//密码
    protected String privateKey;//密钥文件路径
    protected String passphrase;//密钥口令
    protected int port = 22;//默认的sftp端口号是22

    /**
     * 获取连接
     * 
@return channel
     
*/
    public ChannelSftp connectSFTP() {
        JSch jsch = new JSch();
        Channel channel = null;
        try {
            if (privateKey != null && !"".equals(privateKey)) {
                //使用密钥验证方式,密钥可以使有口令的密钥,也可以是没有口令的密钥
                if (passphrase != null && "".equals(passphrase)) {
                    jsch.addIdentity(privateKey, passphrase);
                } else {
                    jsch.addIdentity(privateKey);
                }
            }
            Session session = jsch.getSession(username, host, port);
            if (password != null && !"".equals(password)) {
                session.setPassword(password);
            }
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");// do not verify host key
            session.setConfig(sshConfig);
            // session.setTimeout(timeout);
            session.setServerAliveInterval(92000);
            session.connect();
            //参数sftp指明要打开的连接是sftp连接
            channel = session.openChannel("sftp");
            channel.connect();
        } catch (JSchException e) {
            e.printStackTrace();
        }
        return (ChannelSftp) channel;
    }
    
    /**
     * 上传文件
     * 
     * 
@param directory
     *            上传的目录
     * 
@param uploadFile
     *            要上传的文件
     * 
@param sftp
     
*/
    public void upload(String directory, String uploadFile, ChannelSftp sftp) {
        try {
            sftp.cd(directory);
            File file = new File(uploadFile);
            sftp.put(new FileInputStream(file), file.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 下载文件
     * 
     * 
@param directory
     *            下载目录
     * 
@param downloadFile
     *            下载的文件
     * 
@param saveFile
     *            存在本地的路径
     * 
@param sftp
     
*/
    public void download(String directory, String downloadFile,
            String saveFile, ChannelSftp sftp) {
        try {
            sftp.cd(directory);
            sftp.get(downloadFile,saveFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除文件
     * 
     * 
@param directory
     *            要删除文件所在目录
     * 
@param deleteFile
     *            要删除的文件
     * 
@param sftp
     
*/
    public void delete(String directory, String deleteFile, ChannelSftp sftp) {
        try {
            sftp.cd(directory);
            sftp.rm(deleteFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void disconnected(ChannelSftp sftp){
        if (sftp != null) {
            try {
                sftp.getSession().disconnect();
            } catch (JSchException e) {
                e.printStackTrace();
            }
            sftp.disconnect();
        }
    }
}

在jsch自带的例子中,有一个可以根据密钥生成公钥的类,叫做UserAuthPubKey.java, 且带有图形界面。有用到的可以自己试试。

posted @ 2012-12-15 19:54 paulwong 阅读(9998) | 评论 (1)编辑 收藏

PathMatchingResourcePatternResolver

通常如果要查找文件,是用的File再传入一个绝对路径,如果要找WEB下面的就不方便了。SPRING有个好用的Resolver:PathMatchingResourcePatternResolver。

PathMatchingResourcePatternResolver是一个通配符的Resource查找器,包括:
/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml

如果要处理一个目录下的文件就可以下面的代码: 
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        
Resource[] resources = resolver.getResources("classpath:com/you/atlas/webx/context/*.class");
        
System.out.println(resources[0].getURL());
File file = resources[0].getFile();
echo:file:/home/work/branche/springtest/target/classes/com/you/atlas/webx/context/WebxContextLoader.class

posted @ 2012-12-15 19:47 paulwong 阅读(1232) | 评论 (0)编辑 收藏

WINDOWS下的SFTP服务器安装搭建

因为最近的一个项目的客户需要使用SFTP给我放传送文件,公司的服务器都是WINDOWS 2003或者WINDOWS 2008,我必须找到一个免费的(这点很重要),好用的,稳定的SFTP服务端软件。

经过一番苦寻,找到了以下几款:

1. OpenSSH

参考文章:《Windows下用sftp打造安全传输》

OpenSSH 安装起来很快速,然后就是在CMD命令行里做若干设置,但是不知道哪里没做好,用CUTEFTP-SFTP客户端访问总是报错,折腾了一小会索性放弃,没有图形界面的东西,还是有点不太习惯,反正我也不是LINUX爱好者。

image

2.Core FTP Mini-Sftp Server

华军下载链接:http://www.onlinedown.net/soft/75991.htm

Core FTP Mini-Sftp Server是个绿色软件,什么都不用设置,下载后就一个exe程序,运行它,软件界面简单的吓人,就2个按钮:Start和About,随便写个用户名和密码点start就大功告成了,从客户端访问很正常。缺点是太不像个服务器软件了,呵呵,不能以系统服务方式运行,这要不小心关闭了或者机器重启后忘记打开它了就麻烦了,而且支持1个用户,遂放弃。

image

3. CoreFTPServer

官方网站: http://www.coreftp.com/server/

我想既然有Core FTP Mini-Sftp Server,它就一定有高级的、完整的版本,google一搜,还真找到了,貌似还是免费的,去下载了最新版,在服务器上安装运行,图形界面设置比较丰富,功能比较多,在setup中试着建立了一个domain,从SFTP客户端访问正常。

缺点:免费版只支持一个域名和2个用户访问,最便宜的标准版的收费是一年50美元,还是算了,咱穷啊!

image

4.Sysax Multi Server

Sysax Multi Server也提供了免费功能受限版,它非常容易安裝,也提供了 GUI设置 介面,管理起来很方便,对WINDOWS 2008支持也很好,不像CYGwin就不支持WIN08。

载后记得先到 Buy a License for Sysax Multi Server or Sysax FTP Automation 页面点选 Request Personal Edition License for Sysax Multi Server 按钮申请一组免费的序号。

虽然有个人免费版,但功能限制还蛮多的,例如同时只能一个人连线、不支援 Web-based 远端管理、…等等,还真的是名符其实的「个人」版,但是该有的功能一个都没少,可以方便你安全的传文件。 考虑后今后的多用户使用情况,还是放弃了。

image image

5. Cygwin下安装SFTP Server

参考文章:http://hi.baidu.com/www100/blog/item/e985c717e656b601c93d6d10.html

http://blog.csdn.net/ezdevelop/article/details/67936

Cygwin 是 Windows 上类似于 Linux 的环境。它包括一个提供 UNIX 功能性基本子集的 DLL 以及在这之上的一组工具。安装好 Cygwin 之后,通常可以忽略它,即使您是命令行的爱好者,您仍能发现您活得更舒坦了。

看了一下文档,感觉安装和使用上都不是很方便,没有亲自下载安装测试。略过它了。

image

6. Serv-U

国内的管理员们用的最多的FTP服务器软件,能够支持多种FTP服务,包括Ftp,SFtp,Ftps等等,功能非常强大,破解版非常给力,不介意破解版的朋友可以使用它。

但是我本人还是不太喜欢在服务器上运行破解软件和注册机等程序,另外我的服务器放在国外,对知识产权比较敏感,所以放弃了Serv-U

image

7. freeSSHd

官方网站下载:http://www.freesshd.com

众里寻他千百度,千呼万唤始出来!这是我安装试用了freeSSHd后发出的感叹,此软件免费,功能非常丰富且强大,同时支持软件用户、本地系统用户和域用户验证,对各用户选择性开放SFTP,Telnet, Tunneling服务,所以功能和服务完全不受限制的使用,总之太棒了,一款免费软件做的比收费软件还要强大,强烈推荐。

这里有一篇博文详细介绍了FreeSSHD的使用:http://blog.163.com/ls_19851213/blog/static/531321762009815657395/

freeSSHd截图:

image

image

Cuteftp 客户端截图:

image

8.F-Secure SSH Server

F-Secure SSH server是一款商业性质的SSH服务程序,也有免费限制版本,因为有了freeSSHd,就偷懒了没有去试用F-Secure SSH Server,抱歉。

image

posted @ 2012-12-15 01:29 paulwong 阅读(29783) | 评论 (1)编辑 收藏

如何提高编码质量

问题 
一般程序员都会发现这样的问题,需求拿了,编码写完了,编译也通过了,运行也没报错,就以为程序OK了,但到测试人员那里,一运行测试用例,就发现漏了这个那个的,产生了所谓的质量问题。

原因
这通常是由于程序员一拿到需求,就马上想要几个CLASS,然后就开始编码了。

解决方案
  1. 拿到需求后,先想大概会用到哪些OBJECT,即SERVICE,DAO之类的
  2. 设计出会遇到哪些场景
  3. 设计出分别在这些场景中,那些OBJECT合作的流程图
  4. 编码
举例
需求:有一系统会在每天的某个时间点,在某个文件夹内,导出一个一定格式名称的文件,现在要求程序实现在文件生成后,读取这个文件,抽取某些内容后,再生成另一文件,通过SFTP发走。

方案:
  1. 会用到排程器,控制器,SPRING BATCH JOB
  2. 有这几种场景:没有发现文件时,发现了文件后正常处理,控制器和SPRING BATCH JOB出现错误时等
  3. 处理流程:控制器没有发现文件后,通知排程器继续下一次循环;控制器发现文件后,通知SPRING BATCH JOB处理,然后通知控制器退出;控制器出现错误或SPRING BATCH JOB出现错误后,控制器通知排程器退出。
  4. 根据这几种场景设计程序结构,编码
  5. 编写单元测试用例


posted @ 2012-12-14 11:57 paulwong 阅读(409) | 评论 (0)编辑 收藏

从程序员到技术总监,分享10年开发经验

在中国有很多人都认为IT行为是吃青春饭的,如果过了30岁就很难有机会再发展下去!其实现实并不是这样子的,在下从事.NET及JAVA方面的开发的也有10年的时间了,在这里在下想凭借自己的亲身经历,与大家一起探讨一下。
明确入行的目的

很多人干IT这一行都冲着“收入高”这一点的,因为只要学会一点HTML, DIV+CSS,要做一个页面开发人员并不是一件难事,而且做一个页面开发人员更容易找到工作,收入比普通的工作还要高一些,所以成为了很多高校毕业生的选择。如果您只是抱着这样一个心态来入行的话,那阁下可真的要小心了。因为干IT这一行竞争本来就比较激烈,特别是页面设计这方面,能够开发的人很多,所以为了节省成本,大部分公司都会在需要的时候才招聘这类人员;在没有订单的时候,一些小公司还可能找各类的借口或者以降薪的手段去开除这类员工。而在招聘信息上常常会看到“招聘页面设计师,条件:30岁以下……欢迎应届毕业生前来应聘”这样一条,因为这一类工员对技术上的要求并不高,找应届生可以节约成本。所以在下觉得“IT行业是吃青春饭的”这句话只是对着以上这类人所说的,如果阁下缺乏“进取之心”,而只抱着“收入高,容易找工作”这样的态度而入行,那“IT行业是吃青春饭”将会应验了。

选择合适的工具

JAVA、C#、PHP、C++、VB……10多种热门的开发语言,哪一种最有发展潜力呢?其实开发语言只不过是一个工具,“与其分散进攻,不如全力一击”,无论是哪一种开发语言,只要您全力地去学习,到有了一定的熟悉程度的时候,要学习另一种的语言也是轻而易举的事情。开发语言主要分为三大类:

1. 网络开发

现在网络已经成为世界通讯的一座桥梁,好像Javascript、PHP、Ruby这几类开发语言大部分是用作网络开发方面。

2. 企业软件开发

JAVA、C#、VB这几类开发语言都实现了面向对象开发的目标,更多时候用于企业系统的开发。

3. 系统软件

C语言、C++、Objective-C这些软件更多是用在系统软件开发,嵌入式开发的方面。

当然,这分类不是绝对,像JAVA、C#、VB很多时候也用于动态网站的开发。在很开发项目都会使用集成开发的方式,同一个项目里面使用多种开发语言,各展所长,同步开发。但所以在刚入门的时候,建议您先为自己选择一种合适的开发工具,“专注地投入学习,全力一击”。

明确发展方向

当您对某种开发语言已经有了一定的了解,开始觉得自己如同“行尸走肉”,成为一个开发工具的时候,那您就应该要明确一下自己的发展方向了。

平常在公司,您可以看到做UI层的开发人员大多数都有20多岁,他们充满干劲,而且没有家庭负担,在两年前ASP.NET MVC 、Silverlight等刚出现的时候,他们可以在晚上回家的时候买几本书或者直接上网看看,研究三五个星期以后,对需要用到的技术就已经有一定的了解了。而年过30的人多数是已经成家了,他们每天9:00点上班唯一的希望就是快些到6:00点,能回家吃饭。吃完饭只想陪孩子玩一下,看看孩子的功课,对新增的技术缺乏了学习的欲望。所以很多接近30岁的程序员都有着一种逼迫感(包括30岁时候的我自己),再过几年应该怎么办?这时候,您就更应该明确一下目标,努力向自己的发展方向前进了。归纳一下,可从下面几项里选择适合自己的一条道路:

1. 从技术向业务过渡

在国外,很多发达国家都很重视人才,一个高级的程序员与一个Project Manager收入相差一般不超过15%。但中国是世界上人口最多的国家,国内人才众多,所以人才滥用的情况经常可以看到。一个小公司的开发部里面经常会见到新面孔,但PM却不会常换。因为做老板的对技术是一窍不通,依他们看来只到拉住PM的心,那技术方面方面就能搞得定,至于技术部要换人,他们根本不需要费力气去管。所以从一个技术员过渡到一个PM是向前发展的一个选择,但开发人员也需要知道,要成为一个PM不单单是使用技术,而更重要的是对管理方面的认识。一个PM主要的工作是组织团队,控制成本,管理业务,控制项目进度,与客户进行沟通,协调工作,定期进行工作报告等。所以要成为一个成功的PM更要重视组织能力,PM必须能提高团队的积极性,发挥团队所长,在有限的开发资源前提下为公司得到最大程度上的利润。成为一个PM后,通常不需要直接接触技术开发,而着重管理的是业务发展,但PM对技术也需要有一定的了解(在下曾经为PM对技术了解的必要性写过一篇文章,得到很多支持但也惹来不少的争议)。在这里我还是要强调自己的观点:要成为一个成功的PM最重视的是管理能力,但对技术也应该有足够的了解,因为这是与团队成员沟通的桥梁,只有这样才能与整个团队的成员有着紧密的结合,让团队成员感觉到他们自己存在的意义,从而调动团队的积极性,而不是漠视技术人员的存在。技术并非成为一个成功PM的充分条件但却是必要条件!

2. 从程序员向技术管理发展

其实一个Team Leader的职责与Project Manager相像,但Team Leader更着重于技术开发方面,通常一个大型项目都会有一两个开发团队由Team Leader带领,负责开发核心部分,而其它部分分派给不同开发小组或者分派给外包公司。在网上常看到几句话,贴切地形容了PM与TL的区别:“技术人员乐于被领导;但他们不喜欢被管理,不喜欢像牛一样被驱赶或指挥。管理者强迫人们服从他们的命令,而领导者则会带领他们一起工作。管理是客观的,没有个人感情因素,它假定被管理者没有思想和感受,被告知要做什么和该如何做。领导是引领、引导,它激励人们达成目标。领导力是带有强烈个人感情色彩的,它不是你能命令的,也不是你能测量评估和测试的。”

无论是PM与TL,对业务与技术都要有深入的了解,只是PM更侧重于业务的管理,盈利的多少,风险的大小等等,而TL则侧重于项目的成本,开发的难度,软件的架构等技术方面的问题。在某些人眼中,技术与管理就像鱼与熊掌,不可兼得,但依在下看来,两者却是秤不离砣,密不可分。只要及时提升自己对技术与管理的认识,不断地向深一层发展,要从程序员提升到技术管理人员只是时间的问题。打个比方,一个普通的.NET程序员,开始可能限制于ASP.NET的页面开发,但一旦他有了发展之心,他自然会对ASP.NET MVC、Silverlight、WinForm、WPF这些UI的开发手法感到兴趣,学习不需要多少时间,他可能就会认识这些UI开发只不过是一些工具,其实在开发原理上没什么区别。接着他就会向深一层的通讯模式进行了解,认识TCP/IP、Web Service、WCF、Remoting这些常用到的通讯方式,这时候他可能已经感觉到自己对开发技术有了进一步的了解。进而向工作流、设计模式、面向对象设计、领域驱动设计、面向服务开发等高层次进发,最后成为技术的领导者。上面只是一个比喻,但要注意的是,在学习的时期必须注意的是与同事之间沟通,很多的开发人员喜欢独来独往,开发的项目总想一个人搞定,不受外界的干扰。但要明白,就算你有天大的本事,一项大型的项目也不可能由你一个人全扛着。所以团队的合作性与同事间的沟通是必要的,这也是成功一个TL的必要条件。

3. 单方面向技术发展

能成功进行技术开发的尖端人才,这是在下最向往的工作,却也没本事登上这个位置。很多从事开发的人都会认为,业务总会带着“金钱的味道”,老板从来不管开发是否合符开发原则,是否经过必要测试,他们只会在客户面前无尽地吹嘘,项目到期能成功交货,只要不出什么大问题那这个项目就算成功了。其实我们也要明白:开发项目最终目标是为了赚钱,在开发过程中对项目成本的限制和效率的控制这也是必须,所以这才需要管理人员对项目进行管理。但开发人员也很想避开这“金钱的尘嚣”,全心投入到技术的世界当中。所以对技术有着浓厚兴趣的人,往往会深入地研究某一项技术,成为技术上的精英。但在这里说一句令人心淡的话:中国已经属于是世界上第二大经济体同盟国,但国民生产总值主要来源于第三方加工产业方面。中国可以说是人才济济,但却在高新产业上却比发达国家落后。这几年的确看到我们国家在高新科技上有着质的飞跃,但跟欧美发达国家还有着一段距离。所以想在中国成为尖端技术的人才,无可否定比在国外要难。依在下看来,要想成为尖端的开发者,必须对C、C++、汇编语言、嵌入式开发、Windows API、Linux API这些底层技术有着深入的了解。要知道解JAVA、.NET……等这些之所以称为高级开发语言,并不是指它们比C、C++、汇编语言更高级,而是指它们封装了C、C++等等的功能,更适合用于企业软件的开发,使开发变得简单。但如果要开发一些底层的软件,大型的系统的时候,就必须用到C、C++、汇编等开发语言,这是成功尖端人才的一个条件。

确定未来的目标

人是从历练中成长的,古人云:三十而立,形容的不是一个人的社会地位,经济来源,而是形容一个人对未来的目标,对人生的意向。要成为一个成功人,就应该早日为自己定下长期的发展目标,作为一个开发者也当如此。随着人的性格,取向各有不同,大家为自己所选择的路也有不同:

1. 自立门户,勇敢创业

快30岁了,很多人会认为要想真正赚得了钱,就应该自立门户,为自己创业建立一个基础。像北京、上海、广州这些一级城市,要买房子,一手楼基本要在2万~4万元/平方米左右,而在一家普通的IT公司当上一个项目经理,基本收入一般都在1.5万~3万之间(除非在大型的跨国企业内工作,那另当别论),要买一间100平方米左右的房子,就算不吃不喝也几乎要10年的年薪,所以选择自主创业,是很多IT开发人员的一个未来目标,想要达到这个目标,就应该更多地把业务作为重点。不可否认的一件事,在中国社会里很多时候讲的是“关系”,即使这30年的改革开放使中国的经济蓬勃地发展起来,但几千年来留下的歪风还是不能完全的磨灭。所以想要创业的人事建议你要多跟客户打好关系,与合作伙伴保持互利互动的模式,这将有利于日后事业的发展。

2. 急流勇退,退居二线

这也是不少人的选择。很多人在有了家庭以后,感觉到压力太大,人的一生并非只有事业,他们想把更多时间用于对亲人的照顾,对孩子的关心上。所以很多人会选择一份像系统分析、系统维护、高校教师、专业学院讲师这一类的工作。收入稳定,而且往往没有一线开发人员那么大的压力。

3. 不懈努力,更进一步

无论你是一个Project Manager或者是Team Leader,如果你想继续晋升一级,那还是会两极分化的。从一个PM到一间公司的管理层,那所面对的事件会有很多变化。一个公司的总经理,要管理的不再是一到两个项目的成本,而是整个部门的运作,整间公司的业务流程,所以要肩负的任务会更重。在下曾经有一位上司彭博士,他是企业的最高领导人,年薪超过三百万,而且在报纸杂志上也曾经亮过相。平常只会在某些会议上轻轻地亮下相,说两句讲词,平常的公司运作与业务管理都不需要他直接执行。这并不是说一个作为管理层很清闲,因为他们要面对的是更多的社会关系,与公司合作企业的联系上。这跟一个PM的工作有很大的区别,所以要从一个PM晋升到管理层,那可是要付出更多的努力与汗水。

如果要从Team Leader上升为一个技术总监,那工作的方向也有所改变。像之前所说:一个TL可能更重视的是技术层面,讲求与团队之间的互动合作性,更注重的是开发的完善。而一个技术总监就无需要直接参加某个项目的开发,而注意的是开发的效率与成果,如何合理使用有限的开发资源,控制开发的风险和可能带来的效果。

发展感受

经历了8年多时间,在下从一个程序员到一个项目经理,之间经过很多的曲折,但因为每一个人的际遇都有所不同,所走的路也有不同,正所谓条条大路通罗马,成功的路不止一条,在下也不想令各位误解,而只想为大家说一下我的发展方向。如果您是一位开发人员,“程序员->架构师->Team Leader(Project Manager)->技术总监”是一条不错路,这也是在下选择的路。在我国,想要进一步提升自己,无论你想是以技术为重点还是以业务为重点,都离不开管理二字。在一些大型的企业,一个团队往往会配备一个PM与一个架构师,尽管两个人负责的任务各有不同,但你会看到一个架构师的收入往往不如一个PM,PM往往是这个团队的核心领导者,是关键人物。因为公司能否赚钱,PM有着重要的作用。PM与TL并没有绝对的区别,而且在一些中小型企业,一个开发团队只有3~5人,一个TL往往会兼备业务处理、成本控件、架构设计、开发管理等多项任务。所以在下会把Team Leader与Project Manager定于同一层次,一个公司的老板往往不会知道团队的架构师、程序员是何人,而只会向PM询问项目的进度,所以只有晋升到这个层次,才有机会进一步提升管理能力,让自己有上升的空间。至于要成为一个技术总监,那要求就不再单单是对单个项目的管理,而应该更则重于新兴技术的引用,开发资源的合理利用,对开发项目敏捷性的处理等等,对此在下也在试探当中,未敢多言。

与编程牵手 和代码共眠 从程序员到技术总监

从业IT十年,从程序员成为技术总监,现在回头看一看,这条路也伴随国内的IT一起风雨兼程10年,对IT技术由其是IT的纯软件开发这一块,向即将要从事软件技术研发的朋友谈一谈我的看法:

一.认清当前IT形势,选择合适的技术方向和技术起点

估计大家都多多少少知道,这个IT行业知识的更新很快,竞争很急烈.

如果你对自己以后发展的方向在从业前有一个清析的计划或认识,相信你会比别人走得更好,走得更远,赚的钱也更多...呵呵

IT软件从业的方向,一般都会有这些机会:产品售前(市场,业务),产品开发(编码,设计,测试),产品售后(支持,实施),产品管理(项目管理等)

A.产品售前(市场,业务)

要从事这一块的工作,主要是在软件开发的前期(无产品),或者合同签订前期(有产品).
一般要求对相关的业务和技术都要求很高,这可不仅仅是要求人际关系,交际能力.
要想别人买你的产品,你得以专业的产品品质为后台,以专业的谈吐,专业的技术和专业的业务理解能力来取胜.

从业者要求:
要求从业者要有一定的社会经验,技术经验或业务经历,或一定的社会圈子和交际能力.

建议:
刚刚从学校毕业的朋友或不符合上面条件的朋友最好要考虑清楚了.当然这世上没有什么绝对的东西,就看你自己了.

现实情况:
据我所了解的,作这一块的都会是公司一些高层(有关系,有经验)和业务专家或特殊背景的人员等.

B.产品开发(编码,设计,测试)

这一块的工作,当然是IT从业大军的主力了,但也得要考虑清楚.
如果你要作设计师,或测试,最好先作一段时间的编码,
一个好的设计师是不可能不精通相关技术平台的!
国外好的测试人员也几乎是从开发人员中选出来的,基至是软件开发高手.

a.代码编写
在这一个职业选择范围内最好是从代码编写开始.当然你也可以先作测试,看看人家是怎么写代码的是如何来作这个软件的,
借用人家的测试经验也可以,以后有机会再来编一段时间的代码也行.
有时自己去写一个软件也可以,所以作编码和测试都是一个双向交互的.而不是编码在前测试在后的.

作代码的编写最好自己先看看别人的软件,或由一些高手带着指导一下,现在技术的学习都不成问题,关健是要连成一条线来学习和思考就会有一定的局限了.
所以要熟悉整个的项目流程或业务流程不是靠个人编码或在培训班学一下就能解决的,个人的技术学习和培训班大部分只能解决技术的学习问题,但作软件不仅是要技术呀
三分技术七分业务说得不为过,业务的学习也是一个开发人员所要必备的,如果你在不熟悉业务细节之前建议你不要急着去写代码,那样肯定会是对以后软件的影响很大.先要熟悉一下业务.

所以软件开发人员掌握一门技术平台和语言是必备条件但同时也必须要有一定的业务知识,这样才是一个合格的软件开发人员.当然精通软件编码,懂设计,熟悉业务,熟悉软件项目开发流程的软件开发人员是优秀的,那是高级研发人员的必备条件.

如果你才入门或转行或刚毕业,建议从基础的代码编写开始,跟着高手或找一些成熟的项目多学习,

b.软件设计
当然这个职业要求行业的经验,技术经验都要有一定的基础,薪水一般也会高很多,所以也是一些开发人员热烈追逐的目标.但一个好的设计师不是一二年所能练就的,精通编码,熟练设计模式和公司所采用的技术平台,熟练一些设计理论并实际多运用,熟练公司业务,其实这个层面的压力也最大,一个好的软件在设计上的比重几乎要占到七成.

建议刚毕业的朋友或软件初学者不要在这一块来凑热闹,即使你作成了设计师,但在我眼中看来你也不是一个合格的设计师...当然你有这个能力来作设计师就要恭喜你了.



c.软件测试

熟练软件测试的各种理论或实际运用,也要熟悉编码技术及相关的技术平台,熟练掌握业务.
软件测试中一般都会有:
单元测试,要求你熟练开发技术进行跟踪调试,也就是白盒测试了
集成测试,对整个项目流程的测试,要求掌握业务知识,对设计的软件能作功能上的测试或压力测试等 ,属黑盒测试
确认测试,对业务要很熟悉,测试软件是否完全满足了客户的业务需求.

总体建议:
1.熟练一种技术平台,熟悉一种业务
刚入门的朋友很容易犯的一个毛病是,熟练:VB,VC,.NET,JAVA,C++,C,Dephi,PB,几乎市场上要用的他全部会,唉,如果我看到他的简历上有这么一句话,这个人肯定不会在我考虑的范围了.
现在全球用得最广最多的技术平台体系也就三大体系:

sun的J2EE技术体系(JAVA):在高安全性,高性能上更胜一步,中高端市场上用得多

微软件的技术体系(C++,.NET,c#,VB):在中,低端市场占绝对优势,也是全球个人电脑操作平台用户最多的.

CORBA技术体系统(一种分布式技术体系和标准),
全称:Common Object Request Broker Architecture:公共对象请求代理结构,可以用不同的编程语言写成,运行在不同的操作系统上,存在于不同的机器上。
一般介于底层和上层管理软件之间,


其他的还会包括底层开发:C,汇编,属纯底层的开发,当然要求技术的起点和业务背景更强,最好是学的专业:电子电气,嵌入式行业,机械制造,数据采集等...


看中你想要从事的技术体系,选好一门语言工具,好好上路吧...:)
永远要记住:你什么都想学,你什么都学不精


2.从基础入手,不要好高鹜远,眼高手低,要与实际结合


B.产品售后(支持,实施)
这一块对于开发技术的要求来讲不是那么明显,主要工作会在软件开发后的工作,跟客户打交道多,但更多要求体现在对业务的把握和客户的交际上.
有些软件产品业务比较成熟,如果参与这一阶段的工作,可以快速学习很多的业务知识,积累客户交往的经验

建议:刚入门或刚毕业的朋友,可以在这个工作上多选择,等待时机成熟,立马杀入软件的开发或设计阶段,当然,这一块的工作作得好也不容易,如果适合你作,
工作环境或工资都不错你就大可不必多想了...



C.产品管理(项目管理等)

这一块的工作主要体现在管理上,当然适合有一定经验或管理能力的人员来担当,

最后的技术从业方向总结:

技术型:先选择好一种技术平台,熟练一种开发语言和数据库...专业专注的搞几年再说

技术+管理型:如果你有一定的技术经验了,并且人际交往,管理能力不错,你就可以向这个方向发展

技术+业务型:精通一种技术平台,精通一种业务,好好搞,这种人才最受欢迎...

管理型: 如果你有一定的社会经验,从业经验,如果人际交往,管理能力还可以,老板也喜欢,就搞这个

业务型(市场):如果你对业务很感兴趣,跟客户的交往等也不错,你可以选择了,有适合的专业技术就更能锦上添花了

技术+市场+管理:老大的位置....:) 

posted @ 2012-12-09 17:26 paulwong 阅读(534) | 评论 (1)编辑 收藏

谈谈离职和跳槽

这篇文章是我在部门会议上一次发言的总结。之所以会有这次会议,是因为我的一名员工向我提出了辞职,在思索了几天后,我整理了一下自己的思路,于是便有了这次的会议和现在的这篇文章。
收入是由什么决定的?

这位员工辞职的原因主要有两个:

公司的薪水无法达到他的预期,未来一年在公司的收入前景也不是很明确。
想要去做更底层的开发,方向是使用C/C++开发3D图形图像。而我们公司主要是.NET开发。

既然其中的一个原因是薪水无法符合预期,那么首先要搞清楚的就是收入是由什么决定的。

1.积累

首先要说的一点就是:积累。积累就是你在这家公司所创造的价值的积累。

你今天所领的薪水,并不是由你现在所创造的价值所决定的,而是包含了以前一段时期内其他同事所创造的价值。举个例子来说,公司目前排名前三的大客户:客户A、客户B、客户C。

客户A是2008年接下来的,现在每年为公司贡献600万。
客户B是2009年接下来的,现在每年为公司贡献500万。
客户C是2010年接下来的,现在每年为公司共享350万。

我的年薪是你的两倍还多。可我也承认,我现在所能创造的价值,和我的能力绝对不可能是你的两倍。可问题是:2008年、2009年、2010年这些年份我都在公司,上面的每一个大客户,都有我的贡献。而你2012年才新进公司,你并没有之前的积累。所以,新员工入职后,工资相较老员工会低一些是正常的。很多新员工总是认为自己的收入低了,吃亏了,实际上,很多情况下,新员工在加入公司的头一年,公司仅能维持平衡,即新员工创造的价值全当工资发给他了。直到第二年,有了上一年的积累之后,公司才有所盈余。而加入半年就离职的员工,对公司来说基本上是亏本的。这也就解释了为什么人员流动特别快的公司活不长,因为人力成本太高。

关于积累,我可以再举几个例子说明一下:

洪小莲,李嘉诚的秘书,几十年来一直追随李嘉诚,她从几千元的工薪族,做到身家上亿的工薪族,享受的是公司成长的回报。这种回报并非是她个人的学识和能力有了大幅的提高而得到的等价交换,很大程度上仅仅是因为她忠诚地待在这趟车上。

杨元庆,联想现在的CEO,研究生毕业后就一直追随柳传志,尽管一开始从事的是他并不很乐意的销售工作,但最终还是坚持了下来。上一次注意到他,是看到一则新闻,标题是“杨元庆自掏2000万奖励一线员工”。

上面只是正面的例子,也有反面的例子:

吴士宏,曾写了一本书叫做《逆风飞扬》,可谓是红极一时。1986年进入IBM,1998年离开IBM,进入微软,担任微软中国公司总经理,1999年进入TCL,2002年离开TCL。之后就离开了公众的视线。我特意去百度搜索“吴士宏现在在哪里”,没有任何的消息。我想如果她很成功的话,一定还属于“公众人物”,不至于连度娘都不知去向。

跳槽的话显然就要放弃先前的积累。比方说,当你跳槽到另一家公司以后,你曾经做过的系统、曾经服务过的客户仍然在为先前的公司创造着利润,可是跟你已经一毛钱关系都没有了(极少数公司有股票,另当别论)。所以跳槽之前要慎重考虑,跳得不好,有可能越跳越低。

既然新员工相对于老员工来说,收入低一些是正常的,那么老员工工资高也是合情合理的。但是有一些公司,我将其归为“无良公司”,它们会在老员工的收入高到一定程度的时候,将老员工砍掉,然后再招募低廉的新人来承担之前老员工的工作,以赚取更高的利润。我觉得这些都是小聪明,最后的结果就是,聪明能干一些的人,在看出公司的这些伎俩之后果断离职;能力一般的员工,也会把你这里当成培训基地,翅膀硬了就飞了,受损的最后还是公司,实在是得不偿失。还不如厚待老员工,也让新进的员工对未来有一个更好的预期。也有一些人向我抱怨说:“老员工待得久了,干劲都被磨光了,每天都是混日子,还不如新员工,不开他开谁?”。然后我反问他:“激励员工难道不正是你工作的一部分吗?”。这种情况的出现,更多时候,是管理者的责任,而非员工。
2.老板

这个“老板”是宽泛的老板,不一定是公司最大的老板。有的时候,公司比较大,你的职位又比较低,大老板连有没有你这个人都不知道,此时的老板就是你的顶头上司。很多时候,你的收入与他也有着莫大的关系。

对于我来说,我的原则是:在我的能力范围内,我会为我的员工争取更好的待遇。表面上看,这样做很蠢,花6000块就能雇到一个人,为什么要花8000块?我不是这样认为的,我期望能和我的员工形成这样一种互动:我尽我的能力为你争取好的待遇,你也尽你的努力做好工作。

我不能要求员工“你先把工作做好,我自然会给你好的待遇”。总是要有人先迈出一步,总是要有一方先信任另一方,所以在你什么还没有做的时候,我就先信任你,并且给你尽可能好的待遇,那么我该做的事情都做了,我问心无愧,剩下的,就看你的表现了。

可能有人会想,都这样了怎么还会有人提出辞职?实际上,提出辞职的是一个毕业刚一年的小伙子,1989年生,毕业1年多,我给他的待遇是试用期9000,转正后9500。在给他这个待遇之前,我是进行过一些调研的,我打电话给我的一个表妹,她是西安电子科技大学的研究生(陕西省排名第三的学校,211院校),她和她的同学在今年毕业找工作的时候,多得是6000到8000的工资。所以从这方面来说,我并没有亏待你,而你要求12K的工资,我并不是不愿意给这么多,你的表现也说明了你是个很有潜力的人才。只是受经济环境的影响,今年公司的效益不及往年,要在一定程度上节省开支。其次,你让其他的老员工情何以堪?所以,综合起来,你的要求超出了我的能力范围之外,我无法开口向公司申请提高你的薪水。

3.门槛

除了积累和顶头上司两个决定因素以外,第三个决定因素就是你从事工作的门槛。为什么餐厅服务员的收入很低?为什么坐在前台收发快递的文员收入很低?因为这些工作的门槛很低,门槛低就意味着你不做有的是人能做,你不做有大批的“后备队伍”在等着做。由于庞大的后备队伍的竞争,你就无法提高自己的要价。而提升自己所从事工作的门槛,实际上就缩减了竞争者的规模。

程序开发也是一样。如果你想收入高,你就做一些别人做不了,又有市场的。

.NET在程序开发中就属于门槛比较低的一类。个中原因我想大家都懂的,就不在这里赘述了。做.NET不需要你科班出身,或许一点兴趣再加上一点时间,或许一个类似北大青鸟的培训,都可以让你开始从事.NET开发了。你可以不懂指针、不懂数据结构、不懂算法、不懂汇编、不懂很多东西,但照样可以做出一个.NET程序来。而这些人往往又是对薪资的要求没那么高的,这样无形中就拉低了.NET程序员的“身价”。.NET的易学易会,很大程度上是由于它的封装性比较好。底层的东西都屏蔽掉了,你只要知道学习一下命名空间,然后寻找相关的API去调用就好了。记得我们公司曾经开发过一个基于C语言的手持设备程序,没有任何的类库支持,连排序、链表这样.NET中的基本功能,都要自己来实现,更别提内存管理和程序逻辑了,和.NET比起来,门槛就相对高一些了。

所以,如果想收入高一些,那么就去做更高难度的技术工作,这里随便想了几个例子:

百度、谷歌的搜索引擎算法。
微软、谷歌、苹果的操作系统。
网络游戏,例如《征途》的游戏引擎。
大型企业的ERP,比方说SAP。
软硬结合,比如单片机,电气自动化。
以及我这位即将离职的同事说的,3D图形图像。

所以,从这个角度来看,这位同事的辞职是明智的,他很年轻,有的是机会重新选择自己的道路,所以我也祝愿他能有更好的发展。而这些好赚的钱,就留给我们来做了:-)。

4.平台

接下来要说的一个决定因素是平台。很多程序员觉得30岁就瓶颈了,30岁写程序就到头了,实际上,这只是你的平台比较小罢了。就拿我自己的公司来说,平台就不大,只要是踏踏实实工作过5年的程序员,基本上就能够胜任公司90%的技术工作了,剩下的10%,请教一下其他同事,进行一下技术交流,也完全能够解决。这样就存在一个问题:随着你年龄的增长,你的生活压力越来越大,要求越来越高,可是公司只要5年经验的程序员就够用了。假设市场上5年经验的程序员的平均要求是10K,凭什么要给你15K?你的优势在哪里?如果你没有突破,就会有“30岁写程序就到头了”的感觉。

而如果平台大一些情况就会不一样,比方说,你去了IBM,可能5年的经验不过刚刚入门而已。IBM有一个工程院,其中有5位院士(IBM Fellow)获得过诺贝尔奖,很多人钻研技术都超过20年或者更久。如果你对技术感兴趣,并执着去钻研的话,你可以不断地去挑战和攀登。

当然,你可能没那么好的运气和实力进入IBM,那么其他一些中型的平台也是不错的,比方说阿里巴巴、金蝶、百度、腾讯等等。在这里,至少你有足够的理由和需要再去进行深入学习。因为在这些地方,5年的经验是远远不够的,还需要进一步地学习和努力。

如果你和我一样,不巧没有那么大的平台,此时的选择大概有这么几种:

1. 你可以凭借你在公司的积累(第一节讲过的),过比较安逸的日子。如果比较幸运,押对了宝,公司发展得比较好,收入一样会变得非常可观;如果比较不幸,公司经营的状况不好,那就要承担比较大的风险了。说得难听一点,公司倒闭了你去哪里?你过去的积累已经一文不值,而你的年龄已经35,水平却相当于只有5年经验。你的竞争力在哪里?

2. 你可以凭自己的努力将现在所在的平台做大,换言之,把自己的小公司做大。这当然是比较积极的做法,也是我一直努力的方向。现在你看到的大公司,不也是从小公司一步一步做起的吗?不过这里还有两个问题:1、有的时候,你的力量在公司中的占比没那么大,你再怎么努力推进的速度也还是有限;2、你缺乏慧眼,选中的公司本身就缺乏长大的资质。我们往往只看到成功了的公司,却忽视了更多在竞争中倒下的公司。

3. 主动选择更大的平台,也就是跳槽了。但是跳槽也是有风险的,尤其是过了30岁的程序员。你在这家公司的收入高,是因为有之前的积累,换一家就没有积累了,等于从新人开始,而大多数的公司,5年经验的程序员就够用了。如果跳得不好,收入还可能越跳越低,如果还有老婆、孩子、房贷,那将面临更大的压力。所以当你想要从一个低的平台向更高的平台跳跃的时候,平时就要做足功夫,认真积累自己的实力。对于我来说,我缺乏大型项目的管理经验,但是没关系,我努力学习考一个PMP没什么问题吧?我缺乏大型软件的架构经验,但是没关系,我把.NET的基础知识和各种设计模式掰开了揉碎了没什么问题吧?我缺乏大型团队的管理经验,但是没关系,每次遇到管理方面的问题我都认真思考仔细总结没什么问题吧?有些人总是抱怨没有机会,运气不好,我想机会总是有的,但只属于有准备的人。

5.行业

我想说的最后一点就是行业。有时候你觉得已经万事俱备了,可是你所处的这个行业本身就属于极低利润率的,你再怎么努力也很难有很高的收入。很多情况下,可能公司也想提高你的待遇,但是由于缺乏利润的支撑,公司也是有心无力。所以,在选择公司,尤其是小公司的时候,要重点考察一下公司所处的行业如何?是不是前景比较好、利润比较高的行业?如果是大公司的话,这方面的问题就会少一些,因为如果方向有问题,它就无法做成大公司。

行业是有周期性的,可能在一段时期内这个行业好,下一段时期这个行业就不行了。最典型的一个例子就是软盘,我现在的老板在成立这家公司之前是做销售的,他有一个客户,做索尼软盘的,这种软盘我想很多80后都见过。当时生意做得很大,可是当光盘出来以后,软盘的市场是会急剧萎缩的,可是这家公司的领导层居然没有看到,或者是看到了但不愿意转变,像鸵鸟一样在危机来临时把头埋在土里,继续做它的软盘。几年以后,这家公司就倒掉了。

选择行业也不是选择暴利行业就一定好,比方说房地产。资本都是逐利的,当一个行业属于暴利,同时所有人都知道它是暴利的时候,危机就来了。这个危机就是会有大量的社会资源、人力物力投入到这个行业中企图分一杯羹。而全局上又没有一个统一的把控,这个行业究竟需要多少公司才是合适的?最后的结果就是过剩。就好像股票在崩盘时,也许跌到3000点是比较合理也比较正常的位置,但是由于人们的恐慌,它就跌到1600点了。

感谢阅读,希望这篇文章能给你带来收获。

不是所有一年工作经验的毕业生都有这样的待遇,我主要是看能力,而不是年龄、学历等。特别说明一下,以免误导。 @import url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

posted @ 2012-12-06 22:36 paulwong 阅读(587) | 评论 (0)编辑 收藏

Activiti 5.11 发布,业务流程管理

1. 圣诞大礼包
这是我第一次为Activiti的发布撰文,因为这次的发布我觉得很有必要和大家分享,这其中包含了我期待的新特性和已知问题的修复;而且还有一个重量级的模块Activiti Modeler。

在5.8版本之前一直以每两个月一版的的频率发布,但是在5.8~5.10之间波动比较大,5.9和5.10都是5个月才发布一版,不过从5.11开始又开始恢复每两个月一版的频率了,我认为短周期的发布有利于占领市场,对于开发者来说能尽快修复比较严重的问题。

5.11版本在代码管理方面做了很大调整,首先把源码由原来的svn转移到了Github有利于引擎的发展,可以让更多的开源爱好者参与进来,大家一起捉虫,想Activiti Team提交自己的想法,Github可以很好的满足这些;通过Github的“Fork”我们可以很容易的做到这些。

2. 新特性及优化
新模块Activiti Modeler:添加了Web版本的流程定义设计器—Activiti Modeler到Activiti Explorer中,而且两者可以无缝结合;可以把Modeler设计的流程定义部署到Exploer中,也可以以已部署的流程定义为基础进行修改后重新部署。具体的使用可以参考这里。
汉化Activiti Explorer:本人有幸参与并完成了汉化工作,汉化介绍。
添加Native Query:允许通过本地SQL方法查询Activiti的对象;在这之前查询一直是一个比较头疼的事情,因为开发人员只能使用一些Query对象显示调用设置属性的方法过滤,如果想做到自定义条件查询没有这类接口提供;现在可以使用下面的方式灵活组装查询条件。参考手册的Query API部分。
历史变量查询功能增强:在5.11之前的版本中变量和表单属性(表单的字段,动态表单和外置表单)保存在同一张表中ACT_HI_DETAIL,以DETAIL的TYPE区分(FormProperty和VariableUpdate);在5.11中把两者做了分离,添加了一张表ACT_HI_VARINST专门用来存储变量(也就是在ACT_HI_DETAIL中类型为VariableUpdate类型的记录),这样表单的字段和变量就区分开来了(表单字段类型是字符型,变量有具体的类型);并且专门添加了一个变量实例接口HistoricVariableInstance,以及对应的变量实例查询对象HistoricVariableInstanceQuery。
运行时变量删除:允许通过API方式删除流程实例或者任务的相关变量,调用方式:runtimeService.removeVariable('foo')
改进挂起与激活状态:在5.9版本时我曾在JIRA提交了一个改进意见ACT-1228,不过最后被关闭了……在5.11中终于支持了这一特性,当挂起一个流程实例的时候同时也把相关的任务挂起;原来针对流程定义的挂起与激活功能也进行了优化,可以选择当挂起或者激活某个流程定义时是否挂起相关的流程实例,并且允许定时执行挂起与激活任务(利用Job,定时器)。如此,对于一些流程实例或者流程定义暂时不需要处理时就可以利用挂起功能,在待办任务列表仅显示处于激活状态的即可。
优化对DB2和MSSQL的支持:在SQL脚本方面做了优化。
允许在Java Delegate中调用引擎Service接口:当为某个活动添加了一个Java Service任务设置了Java Delegate时如果需要获取引擎的7个Service,只能通过自己写工具类的方式获取,或者用Spring代理监听或者Java Delegate类用注入的方式实现。现在可以通过DelegateExecution的对象获取,详细请参考这里。
结构调整:抽取独立的模块(jar包)activiti-explorer、activiti-rest,对应的activiti-webapp-explorer2依赖activiti-explorer,activiti-webapp-rest2依赖activiti-rest;如此我们可以很容的把这两个模块集成到现有系统中。创建新的模块:activiti-bpmn-converter、activiti-bpmn-model、activiti-json-converter作为基础的组件,提供bpmn文件的解析以及转换功能(稍后会写篇文章专门讲解如何使用这些基础组件)。
除了以上的改进和新特性之外还修复了大量的Bug,完整的Changlog请参考JIRA。

3. 下载新版本
5.11版本下载地址:https://github.com/downloads/Activiti/Activiti/activiti-5.11.zip

压缩包中的wars目录包含两个文件,activiti-rest模块可以单独部署了,修改数据库配置就可以作为自己的REST服务使用。
Github上的5.11分支:https://github.com/Activiti/Activiti/tree/activiti-5.11

4. 升级建议
5.11版本是一个改进版本,添加了很多有用的新特性,很值得升级;当然在升级产品环境之前做好充分的测试并备份数据。

5. 版本5.12前瞻
在5.11发布之前我曾在JIRA提交了一个关于Activiti Explorer中流程图的一个Bug-ACT-1469,是的,又被关闭了;不过后来在twitter上和Activiti的Team Leader 交流了一下,我分享了我的做法并得到了他的肯定,而且想让我参与到开发中用Javascript和Css方式实现流程图的跟踪功能。
另外国内开发者遇到的流程图中文乱码问题也考虑在5.12版本中给出解决方案,这一点我也和Tijs进行了讨论,我的想法是在引擎配置中添加一个字体名称的设置项,对于英文字符集之外的国家就可以通过这个配置使用本地语言的字体以解决乱码问题。 @import url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

posted @ 2012-12-06 21:50 paulwong 阅读(1323) | 评论 (0)编辑 收藏

仅列出标题
共112页: First 上一页 69 70 71 72 73 74 75 76 77 下一页 Last