Java 进阶 hello world! - 中级程序员之路

Java是一种跨平台的语言,号称:“一次编写,到处运行”,在世界编程语言排行榜中稳居第二名(TIOBE index)。

本文目标是帮助 Java 程序员了解中级程序员应有的水平,避免陷入唯“高技术、新概念”的陷阱。Java 编程入门相对比较容易(推荐:Java入门教程)。学完语法后,很多人希望作一些进阶学习,开始编写网站、访问数据库等应用。然而,当程序比较多时,你又觉得 Java 程序很复杂。因此,我们有必要了解 Java 程序的结构与开发理念,站在项目的高度去看 Java 中级程序员需要哪些知识和能力。

1. 约定优于配置(Convention over Configuration/CoC)

1.1 环境配置

  • 操作系统 windows/Linix
  • Java 虚拟机 1.8
  • Maven 3.3+
  • IDE IntelliJ IDEA / Eclipse

1.2 概念与起源

维基百科:约定优于配置是一种软件框架使用的设计範式(原则),旨在减少软件开发人员需做决定的数量,使软件既不失灵活性,且简洁易于理解。

David Heinemeier Hansson 在使用 Ruby on Rails 开发 web 应用时提出这个概念,因为长期做同类项目,项目中程序的组织、命名习惯都会形成最佳实践,遵循这些最佳实践就不仅可以节约开发者沟通时间,而且有利于程序的构建等工作。例如,我们用 MVC 结构去开发 web 程序,程序员都知道控制器类在哪个目录下,完成哪些任务。

我们在第一次学习计算机语言时都会知道概念编码习惯(code conventions)、编程风格(programming idioms)。它们偏向于某种语言的编码规范,例如 C++,Java,Python 都有自己的编码标准,如 google 的编码规范,Pep8编码规范等,这样,IDE 使用这些规范检查你的程序是否符合标准。

约定优于配置偏向于程序的组织于结构,这样编译等工作就可以按约定习惯进行。我们在编译 PyQt 这样的框架时,非常佩服编写 make 脚本的程序员,./configuration, make, make install 这些复杂的脚本是如何保证正确的?简化开发过程中各阶段的配置,让应用开发人员集中精力编写业务处理程序(Java 的理念),不用关心如何实现快速交付、部署等问题,则是约定优于配置要解决的问题。

1.3 Maven 与约定

现在的核心问题是要做哪些约定,如何保证约定的实施?

不同领域的应用约定是不一样的,对于 Java 应用则由构建工具(如: Maven,Gradle)负责一些约定的实现,其他就是特定应用框架如 Spring MVC 等示例代码形成的无形习惯。对于一个普通 Java 程序,它的约定是什么?

(1)生成程序框架

在hello-world目录下,输入如下命令:

$ mvn archetype:generate -DarchetypeCatalog=internal  -DgroupId=com.mycompany.helloproj -DartifactId=helloworld -Dpackage=com.mycompany.helloworld -Dversion=0.0.1

参考:使用mvn archetype:generate生产maven工程,响应很慢

选默认,回车,回车。

Maven 使用惯例优于配置的原则 。它要求在没有定制之前,所有的项目都有如下的结构:

目录 目的
${basedir} 存放 pom.xml
${basedir}/src/main/java 项目的 java源代码
${basedir}/src/main/resources 项目的资源,比如说 property文件、图片等
${basedir}/src/test/java 项目的测试类,比如说 JUnit代码
${basedir}/src/test/resources 测试使用的资源

使用 IntelliJ IDEA 导入项目,就可以看到这样的程序结构:

(2)约定应用与组织规范

举例说明,Java 访问资源文件如xxx.xml,如果写成:classpath:/xxx.xml,这个类一定默认加载main/resources/xxx.xml

类似的应用约定很多,学习的办法只有一个,积累!积累!积累!,见多识广。

再看 pom.xml 文件内容:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- 项目坐标 -->
<groupId>com.mycompany.helloproj</groupId>
<artifactId>helloworld</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging> <!-- 项目名称 -->
<name>helloworld</name>
<url>http://maven.apache.org</url> <!-- 属性变量 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> <!-- 项目依赖 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

在 pom.xml 所在目录下,输入:

$ mvn package

我们看到 maven 项目做了许多工作:

  1. 下载 junit 库
  2. 复制资源文件
  3. 编译
  4. 测试
  5. 打包

结果,在 target 目录下,出现了 helloworld-0.0.1.jar 文件。

$ mvn install

结果,在 $USER_HOME/.m2/repository/com/mycompany/helloproj/helloworld/0.0.1/ 出现了 helloworld-0.0.1.jar 文件。

在 Maven 配置中, groupId:artifactId:packaging:version 四个元素唯一表示了项目的部件、版本、发布方式。

又称为项目坐标

通常,合理的命名展示了一般公司项目的管理结构。

  • 项目库目录: $USER_HOME/.m2/repository/;
  • 公司目录:com/mycompany/;
  • 项目目录:helloproj/;
  • 部件与版本目录:helloworld/0.0.1/。

通过结构约定,我们定义了企业项目管理的基本方式。

(3)约定开发流程

maven 能支持项目开发不同的生命周期阶段 (lifecycle phase )。但是最常用的是默认的 Maven生命周期 (default Maven lifecycle )。一个 Jar 包的阶段包括:

  • process-resources 阶段:resources:resources
  • compile 阶段:compiler:compile
  • process-classes 阶段:(默认无目标)
  • process-test-resources 阶段:resources:testResources
  • test-compile 阶段:compiler:testCompile
  • test 阶段:surefire:test
  • prepare-package 阶段:(默认无目标)
  • package 阶段:jar:jar

每个阶段有默认目标。 maven 命令就是 mvn goal ,常用目标有:

  • clean 清除所有阶段的成果
  • compile 编译
  • test 执行前面阶段任务,直到测试完成
  • package 打包
  • install 发布到内部项目仓库

最常见命令之一就是:

$ mvn clean package install

通过对 jar, war, ear 等工程流程(阶段)的约定,简单的配置、简单的命令就实现了开发过程自动化,

程序员仅需关注业务。

(4)扩展任务

约定了开发阶段(这也是有人认为 Maven 不灵活的因素),通过插件(plug in)就在不同阶段基础上扩展新目标。

例如:

  <build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.mycompany.helloworld.App</mainClass>
</configuration>
</plugin>
</plugins>
</build>

在 pom.xml 中添加 exec-maven-plugin 插件,就可以用 mvn exec:java 执行程序。

参见: Exec Maven Plugin使用

如果你需要打包成可执行的 jar,jar 和 assembly 插件最常用,参见

本文不是 maven 的教程,只是说明通过约定一些基本规则,程序开发编程更加简单、高效,更易于多人协同,共享成果。

2. 测试驱动的开发(Test-Driven Development/TDD)

2.1 概念与起源

测试驱动的开发是敏捷开发(短周期迭代)的一种生产实践,它要求程序的功能或特性(需求)在开发出来的同时,测试案例(程序)同步完成,并用于需求验证。

概念起源于 Kent Beck 的【极限编程/Extreme Programming】实践。如果你没有读过,越忙越要抽空读。Kent Beck是项目经理出身,所以也知道你很忙,所以书的很薄,你必定有许多共鸣的。Kent 喜欢讲故事,怎么做就让你自己领会了,【硝烟中的scrum和xp】书可以帮你。

Kent Beck 发现,在错误(bug 可能来源于业务逻辑,也可能是结构设计)比较多的程序上迭代,积累偏差会迅速放大,导致程序越来越难以调试与维护。因此,需要低成本的手段保障每次迭代产品的品质,于是提出了 TDD 的概念。

2.2 持续集成

假设一个中型项目按特定的结构建设,这个结构包含两个方面:

  • 逻辑结构,也称包结构,指一个 Java 应用的类命名空间(唯一的可管理的命名)。

    例如:helloworld 应用中, App 类的命名空间是 com.mycompany.helloworld。则这个类全称是:

    com.mycompany.helloworld.App。带来的便利是不易命名重复,易于查找、使用和管理。
  • 物理结构,也称部署结构,指一个 Java 应用哪些类、资源组成一个部件(如 Jar 文件)。

    这样,每个子项目对应一个部件,1-3个开发人员负责一个子项目的开发。带来便利是项目分解为若干独立部件,

    子项目可以独立开发、测试、升级与维护。

假设这个中型项目划分为如下依赖关系的部件:

集成测试过程如下:

  1. 按依赖顺序从 Git 加载程序,使用 Maven clean deploy 构建每个子部件,并放入本地仓库。称为“单元测试
  2. 按集成策略,编写三个集成测试用例,测试部件的组合。称为“集成测试

这样,每个部件程序员不仅要编写业务程序,也需要负责使用 Junit 或 TestNG 测试自己的模块。

测试程序员仅编写集成测试,测试部件组合后的正确性。实际测试中会复杂一些,会使用 mock 测试技术。

由于这样的测试可以每天晚上用 shell 脚本执行,所以也称为 “每日构建(Daily Building)” 或 “冒烟测试(smoking Test)

参考:基于Maven的持续集成实践

2.3 快速交付

快速交付指按固定迭代周期(2-4 周)将产品交付客户试用,及时获取客户反馈。

所以,每个迭代需要花2-3天做产品系统测试。

2.4 TDD是必需的吗?

在没有 TDD 之前,项目进展都是通过程序的日报/周报等方式评估的。项目经理从程序员获取信息,然后做项目进度图。

开始,项目进展非常快,%20,%40,%60,%80,%90,%95,%99 。。。延期,再延期。

  • 主管抱怨:bug 太多,时间不够
  • 程序员抱怨:PPT 做的好的人(PPT程序猿)经常受表扬,难道程序员做好 PPT 比做好程序重要?

TDD 改变了这一切,每个人每天收到报告,有多少测试没通过?已通过 xx%。显式度量调动了程序员积极性。

测试数据与程序员分离,有力提升 bug 发现的能力。

TDD 也不是万能的,对于 10 几个开发者的团队,那 1-2 核心程序员才是品质的保证。他们完成绝大多数代码,

TDD 对这些人驱动的意义不大,TDD 成本高于仅做系统测试。

3. 总结

本文虽然仅讨论了约定优于配置(CoC)和测试驱动的开发(TDD),能实施这两点的程序猿一定在中级或以上。

因为,掌握 CoC 和 TDD 对于一个团队来说意味着:

  • CoC 你熟悉一个以上领域程序的基本结构(逻辑结构与部署结构)与每个部分的关键技术(初级架构师要求)
  • TDD 你按项目周期合理组织项目部件的开发,并实现每天进度的量化管理(初级项目经理要求)

这证明中级程序猿有能力做一个小型开发团队(3~7人)的技术经理。因为精确度量,领导喜欢你;

因为架构和进度的优良控制,程序猿也省心,特别是哪些喜欢与计算机打交道的天才会成为你的中坚;

PPT程序猿会自动离开。

掌握 CoC 和 TDD 本质是就是 Java 开发团队具体实施敏捷开发实践的要点,它满足敏捷四条宣言:

  • 个体交互胜过过程与工具
  • 可以工作的软件胜过面面俱到的文档
  • 客户协作胜过合同谈判
  • 响应变化胜过遵循计划

在 hello world 这样规模的程序上实践,你是不可能完全理解 CoC、TDD的重要性的。

掌握一个应用领域程序的逻辑结构与部署结构,组织每天测试在实践中会有无数障碍(不做不知道)。

要成为合格的中级程序员,需要进一步努力,例如:

  • 做一个网上商店这样规模的 web 程序
  • 软件架构基本知识
  • 学习测试技术与技巧
  • 源代码管理与持续集成
  • 学习 Java 设计模式,了解更多面向对象的设计约定
  • 学习分布式基础技术,提升系统的性能与可靠性

等等

Java 进阶 hello world! - 中级程序员之路的更多相关文章

  1. asp.net菜鸟到中级程序员的飞跃 --30本好书点评

    如果你是一个菜鸟或者自认为初学者那么本文非常适合你:不能说这30本书就是最佳组合,但是可以说这个组合不差:本人曾博览群书,很多书重复,很多书讲的不适用,这些书都是目前书店可以买到的:达到中级程序员以后 ...

  2. Extjs4.2 rest 与webapi数据交互----顺便请教了程序员的路该怎么走

    这一章接着上一篇 对于Ext.data.Store 介紹 与总结,以及对以前代码的重构与优化 1.对于更新OnUpdate()函数的修改:先上代码: function OnUpdate(record) ...

  3. 程序员之路:python3+PyQt5+pycharm桌面GUI开发(转)

    程序员之路:python3+PyQt5+pycharm桌面GUI开发 http://blog.sina.com.cn/s/blog_989218ad0102wz1k.html 先看效果: 图 1 没错 ...

  4. 我的程序员之路:自学Java篇

    序章 时光疾驰,从事IT行业已两年有余. 16年11月开始自学Java,从此开启自学之路,后来实习期自学大数据.python.爬虫等,最终成长为一名平凡的程序员.回首望去,一路上的过往历历在目,有初学 ...

  5. 大神为你分析 Go、Java、C 等主流编程语言(Go可以替代Java,而且最小化程序员的工作量,学习比较容易)

    本文主要分析 C.C++98.C++11.Java 与 Go,主要论述语言的关键能力.在论述的过程中会结合华为各语言编程专家和华为电信软件内部的骨干开发人员的交流,摒弃语言偏好或者语言教派之争,尽量以 ...

  6. Java开发者薪资最低?程序员只能干到30岁?国外真的没有996?Intellij真的比Eclipse受欢迎?

    Stack Overflow作为全球最大的程序设计领域的问答网站,每年都会出据一份开发者调查报告.近日,Stack Overflow公布了其第9次年度开发者调查报告(https://insights. ...

  7. 程序员之路:以Android证道

    大道三千,何以证道? 最近有私信.邮件给我咨询一些职业生涯规划的同学,我在这里以过来人的身份给大家一些建议. 任何行业,任何职位,无论高低,无论大小,都可以分为广博.精深两个方向. 精深自然指的是在某 ...

  8. 2017年PHP程序员未来路在何方——韩天峰

    PHP 从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些技术的推 ...

  9. 2017年PHP程序员未来路在何方

    PHP 从诞生到现在已经有20多年历史,从Web时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些技术的推 ...

随机推荐

  1. 前端框架 EasyUI (2)页面布局 Layout

    在 Web 程序中,页面布局对应用程序的用户体验至关重要. 在一般的信息管理类的 Web 应用程序中,页面结构通常有一个主工作区,然后在工作区上下左右靠近边界的区域设置一些边栏,用于显示信息或放置一些 ...

  2. CLR 这些年有啥变化吗?

    引言 首先想给初学者推荐下<CLR via C#>这本好书,做.Net开发的开发者应该都读一下.为避免广告之嫌,所以这里只提供豆瓣书评的链接. CLR 作为.Net 程序跨平台运行的载体, ...

  3. SSH实战 · 唯唯乐购项目(中)

    用户模块 三:一级分类的查询 创建一级分类表并导入基本数据 CREATE TABLE `category` (   `cid` int(11) NOT NULL AUTO_INCREMENT,   ` ...

  4. Shell碎碎念

    1. 字符串如何大小写转换 str="This is a Bash Shell script." 1> tr方式 newstr=`tr '[A-Z]' '[a-z]' < ...

  5. DDD 领域驱动设计-两个实体的碰撞火花

    上一篇:<DDD 领域驱动设计-领域模型中的用户设计?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply.Sample(代码已更新) 在 ...

  6. GPG终极指南(加密/签名)

    我们平时都听过非对称加密,公钥和私钥,签名验证,但这些证书都是怎么得到的呢?本篇文章会解答这些问题. 背景介绍 加密的一个简单但又实用的任务就是发送加密电子邮件.多年来,为电子邮件进行加密的标准一直是 ...

  7. Java类访问权限修饰符

    一.概要 通过了解Java4种修饰符访问权限,能够进一步完善程序类,合理规划权限的范围,这样才能减少漏洞.提高安全性.具备表达力便于使用. 二.权限表 修饰符 同一个类 同一个包 不同包的子类 不同包 ...

  8. 【从零开始学BPM,Day5】报表配置及自定义功能页面开发

    [课程主题] 主题:5天,一起从零开始学习BPM [课程形式] 1.为期5天的短任务学习 2.每天观看一个视频,视频学习时间自由安排. [第五天课程] 1.课程概要 Step 1 软件下载:H3 BP ...

  9. Android Studio-—使用OpenCV的配置方法和demo以及开发过程中遇到的问题解决

    前提: 1.安装Android Studio(过程略) 2.官网下载OpenCV for Android 网址:http:opencv.org/downloads.html 我下载的是下图的版本 3. ...

  10. Java—恶心的java.lang.NumberFormatException解决

    项目中要把十六进制字符串转化为十进制, 用到了到了Integer.parseInt(str1.trim(), 16):这个是不是后抛出java.lang.NumberFormatException异常 ...