前言
项目与技术部中语言选型是至关重要一个环节,是架构的重要组成部分。如果对语言选型出现错误,将会造成巨大的损失,对于初创公司,可能代表创业失败。所以章节语言选型这个架构性问题,所以本节有别上两节的全描述技术方向,主讲架构方向。
鸟菜啊简单介绍
非大学生,半自学编程语言
有7年的编程工作经历
入门语言java,因工作与自身爱好需要自学并应用到项目中有 JavaScript,c#, php, python,scala, lua,,shell,bat 。自身爱好并应用到项目有:c/c++ , 还接触过perl , object-c.目前只记得这么多了。算是经历良多。
高级语言种类
存在的高级语言多到你无法想象,如果想看世界上有多少种高级语言请点击wikipedia统计的高级语言。注意可能看得你会心慌
语言那么多,很多都没见过,也不用到。那那些是常用语言了。请看Tiobe最新排行版
高级语言的根基与魂
目前大多高级语言的解释器与编译器或vm都是用 c语言实现的。
- 比如 java等语言都是基于jvm实现,jvm是用c与c++实现
- chromium的v8内核是用c/c++实现的,所以node.js的c/c++实现的
- obejct-c 看名字....你懂得!!!
- github在搜索lug,第一个就是lub的解析器的实现,语言标示是 c
- php,python,perl,ruby,go,等等这些语言已经占据了语言届的90%
C语言开创了括号为代码结构的先河。c语言的语法对其他基于c实现一些高级语言有很大的影响,比如 c++。java, c# , JavaScript等。
谁是世界上最好的语言
先来一个段子
某女:你能让这个论坛的人都吵起来,我今晚就跟你走。
某软件工程师:PHP是最好的语言!
某论坛真的就炸锅了,各种吵架……
某女:服了你了,我们走吧,你想干啥都行。
某软件工程师:今天不行,我一定要说服他们,PHP必须是最好的语言……
看在不要美女,还要证明PHP是世界上最好的语言。优秀的程序员上。暂且证明 PHP是世界上最好的语言。赶快与女神去滚床单。
开源
一个语言的实现是闭源的。那么语言提供的公司,提供的相关技术,也会闭源。不会制定规范。等于把扩展的大门关闭了。公司发展越来越大,对技术要的要求越来越高,对语言本身的要求,探索加强,如果闭源,那么对大型公司来说,是致命的伤害。
如何分析对语言进行分析
性能
- 未了性能选择 c/c++,ga 可直接编译成二进制
想什么
那么从操作系统及往上的计算机世界看,大家用高级语言做了那方面的事情
操作系统实现
- UNIX类Unix系统 Linux,Mac OS X,iOS
- Windows (不包含windows xp 与下)
上面的操作系统都是基于 c 实现的。所以在操作系统实现方面,C语言是毫无争议的唯一
- 只有极少公司有能力踏入这个领域
- 相对封闭的领域,关注的人很少
- 维护软件人员的团队,不庞大,产量低,维护人员的技术水平与个人能力普遍很变态
- 需求变化少,更新换代低,产出慢
功能软件
- 数据库方面软件
- 关系型数据库
- MySQL
- sqlserver
- db2
- oracle
- kv数据
- redis
- memcached
- ........
- 关系型数据库
- 语言实现软件
- 驱动程序
- tpc代理服务与http代理与反向代理。
- lvs
- nginx
功能软件十分注重性能。所以功能软件的软件基本基于c/c++实现。所以在这个领域c/c++处于绝对领导地位
- 能创造一个软件的公司也非常稀少
- 维护软件人员的团队,不庞大,产量低,维护人员的技术水平与个人能力普遍很变态
- 相对封闭的领域,关注的人较多,大部分只关注如何使用
- 需求变化少,更新换代低,产出慢
人工智能
鸟菜啊,没有接触过人工智能。但是从技术咨询从得到。尤其是google的那条狗,是用python的实现。python在这个领域有绝对的优势。所以在这个领域语言方面也没有任何争议。
- 能创造一个软件的公司也非常稀少
- 维护软件人员的团队,不庞大,产量低,维护人员的技术水平与个人能力普遍很变态
- 相对封闭的领域,关注的人较多,仅仅是知道
- 需求变化少,更新换代低,产出慢
大数据
目前来说大数据基本是java的天下。大数据的应用软件基本在apache基金会里面,那些应用软件基本是java实现的。所以在这个领域语言方面也没有任何争议。
- 能创造一个软件的公司也非常稀少
- 维护软件人员的团队,不庞大,产量低,维护人员的技术水平与个人能力普遍很变态
- 相对封闭的领域,关注的人较多,大部分只关注如何使用
- 需求变化大,更新换代快,产出快
运维方面
- shell
- perl
- python
- 相对封闭的群体
- 基本每家公司必备,但是在公司比例极低
- 基本每家公司都会工作
- 需求变化大,更新换代快,产出快
视图应用
桌面应用
- c#
- object-c
- c++ qt
- python(pyqt)
- node(有道)
桌面操作系统基本是windows与苹果系统的天下的天下
移动app
- Android
- java
- 苹果系列
- object-c
- weex与react native 目的统一移动app,移动web,电脑web
- JavaScript
浏览器
- JavaScript
- html
- css
上面的三剑客,各占一方,谁也离不开谁,非常和睦的在一起。算是计算机语言界的奇迹与典范
趋势
现在越来越多的小型硬件系统走向Android成为趋势
大型公司喜欢使用c++,然后写好基础模块,然后对平台的api进行调用。
越来越采用夸平台型解决方案。使用夸平台的框架 比如qt,或者使用夸平台语言python或者node.js。
已嵌入浏览器的方式。或者使用JavaScript。html,css的解析,渲染内容。实现平台的统一,这个趋势尤其在易懂段越来越明显
总结
在这个领域里面,没有什么好争议。要么使用平台支持的语言,要么使用跨平台解决方案。
JavaScript在视图应用层面的分量越来越重。原因如下
- 可以对浏览器,移动,桌面进行统一
- JavaScript,html,css这三剑客对视图的编写比原声的简单得多
- 移动端的语言之争麻烦。比如Android的官方语言从java往kotilin转变,苹果的由object-c往swift转变。对整个移动端的冲击非常大。改变语言的过程中,使用JavaScript可以保证视图,与大量的视图逻辑不变。同时提高相同的接口调用就可以。
- 相对活跃的群体
- 基本每家公司必备,但是在公司占比2成左右
- 需求变化大,更新换代快,产出快
网络服务提供语言
网络服务提供语言。分两个方向一个是对外提供tcp,udp与http。另外一个是对内提供rpc调用。
对内提供rpc调用
- dubbo
- soa
- 不支持多语言
- 只支持java
- spring cloud
- 微服务解决方案
- http作为网络传输协议,支持多语言,对java支持最好
- java实现
- grpc
- soa 解决方案
- http作为网络传输协议,支持多语言
- 有多语言的客服端,
- tars
- 微服务解决方案
- 多语言支持
- c++ 实现
对外提供tpc服务
这个领域基本是c++与java的天下,比如游戏2012年之前基本是c++,慢慢后面有一些对性能要求不高的,向java转型了。
对外提供http服务
擅长对外提供http调用的语言有如下
- python
- php
- net( net不讲述,操作系统限制与不开源,直接淘汰)
- node.js
- java
- c++ ( c++ ,实现http服务比较复杂,使用的公司比较少。只带过)
- 非常相对活跃,庞大的群体
- 基本每家公司必备,但是在公司占比非常高
- 需求变化大,更新换代快,产出快
发现语言之间,只是在web开发这个领域。这个领域是最大的一个领域了。其实争论的只是开发效率而已。请下软件工程
总结
- 在操作系统层面 c
- 在性能软件方面 c/c++,性能要求不高选择java
- 运维方面。 python(鸟菜啊的经验,能用python解决的问题,绝对不用shell)
- 视图方面,尽量从架构方面优化适应JavaScript
- 网络服务方面,选择java
- 小型web开发要求效率,选择python,php,node.js。
语言转型浪潮
功能软件:c++转型java浪潮
Google的Chubby 实现是c++ Zookeeper是java Google的GFS 实现是c++, HDFS是java。google的那套大数据开发体系全是使用c++实现,现在基本有java的实现
转变的原因是 c++ 开发效率低,同时这些软件对执行性能要求不高,对操作系统要求高。
网络服务: net转型java
在16年左右,携程还是以.net为主,框架组也有java框架,可以允许部分创新项目用java做,自从换了一个新的CTO,突然决定技术转型,新开的项目强制性的使用java,携程是以.net起家的,技术积累已经相当深厚,可以说是目前国内最大的.net公司了,我有几个疑问: 1、在.net积淀浓厚的情况下突然转型带来的好处是什么? 2、公司几千.net人员怎么处理,不太可能让这些人都去学习java做项目吧,那还不如新招一些3.4年的java人呢? 3、这个重大决定,会像之前在12年左右把宝压在移动互联网这样再一次获得巨大成功吗?
携程为什么突然技术转型从 .NET 转 Java 大公司c#&.net转型java的原因有哪些?
当年选择net因为windows携带品。windows系统最早被政府接受,大学的可能大量教授.net,开发环境与运行运行环境一致的因素,所以被大量的能接受。.net是闭源的,官方提供的框架也是闭源了,让一些国外的开发者慢慢放弃了net。随着国内计算机世界越来越开发,积淀越来越多,慢慢国外的优秀思想,优秀框架传播到国内,慢慢被发现java比net更好
网络服务: php转型java
看过淘宝技术十年的朋友都知道淘宝早起是LAMP架构。两三年之后,直接换成了java。 天猫,新浪的一些页面是php写,在2014年开始慢慢的都消失了。主要是大型公司
java的Velocity框架很强大,大公司统一技术栈。node.js的出现
一些语言的抱怨
抱怨Scala
记得在15年之前,scala好火,认为是一种可以拯救世界的语言,可以替代java....几年过去在tiobe的排名从21名到现在的40,50名。
为什么公司要从Scala转到Go Scala的抱怨 Scala很难 从 Scala 迁移到 Go,永不回头
软件工程
工程与软件工程
工程是用复杂且较好的设备来进行的工作(维基百科)
软件工程是一门研究用工程化方法构建和维护有效的、实用的和高质量的软件的学科。它涉及程序设计语言、数据库、软件开发工具、系统平台、标准、设计模式等方面。(百度)
企业级应用是指那些为商业组织、大型企业而创建并部署的解决方案及应用。这些大型企业级应用的结构复杂,涉及的外部资源众多、事务密集、数据量大、用户数多,有较强的安全性考虑。
当代的企业级应用决不可能是一个个相互独立的系统。在企业中,一般都会部署多个彼此连接的、相互通过不同集成层次进行交互的企业级应用,同时这些应用又都有可能与其它企业的相关应用连接,从而构成一个结构复杂的、跨越Intranet和Internet的分布式企业应用群集。 此外,作为企业级应用,其不但要有强大的功能,还要能够满足未来业务需求的变化,易于升级和维护。
鸟菜啊认为工程是一件复杂,庞大,持续时间长,需要大量工具,需要大量人之间协作,需要不同的环节连贯合作的事情。同时需求变化大,更新换代快,产出快
出现原因
- 公司团队规模不停的增加,合作与协调,沟通,管理成本不同提升
- 需要实现的功能越来越多,代码量,模块,依赖 越来越多
- 对性能要求高,数据量越来越大
- 技术的更新换代, 技术上问题越来越多
- 技术栈越来越复杂,应对的软件提供商越来越多。比如单体服务,rpc,soa与微服务的演进
- 人来人走,学习曲线慢慢增加
从语言开始选择,减少,抵消上面的问题,减少技术债务。要做到减少技术债务,应该做到以下几点。
- 学习,研究,深入曲线低
- 有相对的开发效率
- 代码,设计,架构容易理解,
- 对软件生态圈,全面的支持
- 项目能快速搭建,部署
- 更加强大的容错性
符合软件工程的语言,只有java。不服看下面的分析。
开发效率
在开发效率方面,先淘汰c/c++。是公认开发效率慢的语言
编译语言
编译语言有性能上的优势
垃圾回收器,在内存方面性能比动态语言性能好
面向对象
类型的好处
- 类型是一种规范
- 类型更加容易组织代码
- 类型是一种优秀的代码结构
- 类型让代码通俗易懂
面向对象的好处
- 接口与抽象类,是一种规范
- 良好的类结构管理
- 基本所有设计模式都可以实现
动态类型没有重写
class Objects:
obj = {}
def __init__(self):
self.obj = []
def addValue(self):
print("Objects")
def addValue(self,de):
print(111)
Traceback (most recent call last):
File "D:\project\logback\pytest\test.py", line 59, in <module>
obj.addValue()
TypeError: addValue() missing 1 required positional argument: 'de'
动态类型没有重载,无法调用
class Objects:
obj = {}
def __init__(self):
self.obj = []
def addValue(self):
print("Objects")
class Aodedd(Objects):
def addValue(self):
self.addValue()
print("Aodedd")
if __name__ == '__main__':
obj = Objects()
obj.addValue()
obj = Aodedd()
obj.addValue()
Traceback (most recent call last):
File "D:\project\logback\pytest\test.py", line 64, in <module>
obj.addValue()
File "D:\project\logback\pytest\test.py", line 56, in addValue
静态类型,最好是强类型
弱类型的问题,在上章节已经讨论过。这里不进行讨论。静态类型的声明对idea提示等十分友好。声明与不声明在代码可读性上有天然之别,对声明的属性与方法进行调用的效率,成本非常低。只是在定义与修改的时候比较麻烦,不爽。但是使用很爽
字段声明的好处
下面举例,是鸟菜啊,在工作的时候,经常的遇到。有时候是鸟菜啊自己,更多的时候是团队合作出现的问题,有几次出现真心是崩溃的。居然在运行的时候出现了。
在繁多的定义了繁多的属性,有声明与无声的区别。有声明的代码通俗易懂。
/** Parent bean factory, for bean inheritance support */
private BeanFactory parentBeanFactory;
/** ClassLoader to resolve bean class names with, if necessary */
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
/** ClassLoader to temporarily resolve bean class names with, if necessary */
private ClassLoader tempClassLoader;
/** Whether to cache bean metadata or rather reobtain it for every access */
private boolean cacheBeanMetadata = true;
/** Resolution strategy for expressions in bean definition values */
private BeanExpressionResolver beanExpressionResolver;
/** Spring ConversionService to use instead of PropertyEditors */
private ConversionService conversionService;
/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
private final Set<PropertyEditorRegistrar> propertyEditorRegistrars =
new LinkedHashSet<PropertyEditorRegistrar>(4);
/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
private TypeConverter typeConverter;
/** Custom PropertyEditors to apply to the beans of this factory */
private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors =
new HashMap<Class<?>, Class<? extends PropertyEditor>>(4);
/** String resolvers to apply e.g. to annotation attribute values */
private final List<StringValueResolver> embeddedValueResolvers = new LinkedList<StringValueResolver>();
/** BeanPostProcessors to apply in createBean */
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
private boolean hasInstantiationAwareBeanPostProcessors;
/** Indicates whether any DestructionAwareBeanPostProcessors have been registered */
private boolean hasDestructionAwareBeanPostProcessors;
/** Map from scope identifier String to corresponding Scope */
private final Map<String, Scope> scopes = new LinkedHashMap<String, Scope>(8);
/** Security context used when running with a SecurityManager */
private SecurityContextProvider securityContextProvider;
/** Map from bean name to merged RootBeanDefinition */
private final Map<String, RootBeanDefinition> mergedBeanDefinitions =
new ConcurrentHashMap<String, RootBeanDefinition>(256);
/** Names of beans that have already been created at least once */
private final Set<String> alreadyCreated =
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(256));
/** Names of beans that are currently in creation */
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<Object>("Prototype beans currently in creation");
/** Parent bean factory, for bean inheritance support */
parentBeanFactory;
/** ClassLoader to resolve bean class names with, if necessary */
beanClassLoader = ClassUtils.getDefaultClassLoader();
/** ClassLoader to temporarily resolve bean class names with, if necessary */
tempClassLoader;
/** Whether to cache bean metadata or rather reobtain it for every access */
cacheBeanMetadata = true;
/** Resolution strategy for expressions in bean definition values */
beanExpressionResolver;
/** Spring ConversionService to use instead of PropertyEditors */
conversionService;
/** Custom PropertyEditorRegistrars to apply to the beans of this factory */
propertyEditorRegistrars =
new LinkedHashSet<PropertyEditorRegistrar>(4);
/** A custom TypeConverter to use, overriding the default PropertyEditor mechanism */
typeConverter;
/** Custom PropertyEditors to apply to the beans of this factory */
customEditors = new HashMap<Class<?>, Class<? extends PropertyEditor>>(4);
/** String resolvers to apply e.g. to annotation attribute values */
embeddedValueResolvers = new LinkedList<StringValueResolver>();
/** BeanPostProcessors to apply in createBean */
beanPostProcessors = new ArrayList<BeanPostProcessor>();
/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
hasInstantiationAwareBeanPostProcessors;
/** Indicates whether any DestructionAwareBeanPostProcessors have been registered */
hasDestructionAwareBeanPostProcessors;
/** Map from scope identifier String to corresponding Scope */
scopes = new LinkedHashMap<String, Scope>(8);
/** Security context used when running with a SecurityManager */
securityContextProvider;
/** Map from bean name to merged RootBeanDefinition */
mergedBeanDefinitions =
new ConcurrentHashMap<String, RootBeanDefinition>(256);
/** Names of beans that have already been created at least once */
alreadyCreated =
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(256));
/** Names of beans that are currently in creation */
prototypesCurrentlyInCreation = new NamedThreadLocal<Object>("Prototype beans currently in creation");
属性定义与调用循序的问题
class Field:
def field(self):
print(self.field)
pass
def addFiled(self):
self.field
if __name__ == '__main__':
field = Field()
field.field()
<bound method Field.field of <__main__.Field object at 0x02F6E830>>
类型修改造成问题
class Objects:
obj = {}
def __init__(self):
self.obj = []
def addValue(self):
self.obj[1] = 2
if __name__ == '__main__':
obj = Objects()
obj.addValue()
Traceback (most recent call last):
File "D:\project\logback\pytest\test.py", line 53, in <module>
Hello world, laohu (__str__)
obj.addValue()
File "D:\project\logback\pytest\test.py", line 49, in addValue
self.obj[1] = 2
IndexError: list assignment index out of range
对ide友好
class Field:
def field(self):
print(self.field)
pass
def addFiled(self):
self.field
eclipse根本就不知道,field字段是否定义了。所以没有任何提示。疯的节奏
方法声明的好处
没有声明,可能不知道传递什么,应该传递什么类型。这些只能靠程序员自己预防,测试。如果不小心传递错误,就异常。这样的事情在鸟菜啊遇到过,有因为是团队其他成员问题,也有与其他团队,项目合作的时候,其他的不小心。在线上这样的问题,太疲劳了。
class Objects:
def addValue(self, num):
print(num + 1)
if __name__ == '__main__':
obj = Objects()
obj.addValue("1")
Traceback (most recent call last):
File "D:\project\logback\pytest\test.py", line 56, in <module>
obj.addValue("1")
File "D:\project\logback\pytest\test.py", line 50, in addValue
print(num + 1)
TypeError: Can't convert 'int' object to str implicitly
完整的语言体系
在类里面可以定义静态属性
class Objects{
public static final String de = "niaocaia";
}
没有内置类型, 全局方法
java只有9大基本类型,其他的都是类类型。使用所有的类类型,都需要通过 new 实例化。有完整的组织结构。 python [] {} JavaScript [] {} 没有内置类型使之,理解简单,思想统一,容易扩展
当年为了找,python,JavaScript的内置类型,全局方法,真心找得累.....
注解
注解是配置的一种,注解在类,方法等地方引入。注解可以减少大量的工作量
枚举
枚举与静态变量没有区别,但他是一种明确的约束。缺点是无法继承
异常
有完善的异常体系,才能实现一个健全的软件工程项目。哪里出错,为什么出错,出错的提示是什么,不同异常不同处理
class Statement{
public final synchronized List<String> statement(String name) throws RuntimeException, IOException{
return Collections.emptyList( );
}
public void test(){
try {
this.statement( "1" );
} catch ( RuntimeException | IOException e ) {
log.erren(e);
} catch (Exception e){
thows new RuntimeException(e , "这个异常我不处理");
}finally{
}
}
}
强大的api
记得当年架构终端项目的时候,选择了python找类似于java中ConcurrentHashMap功能的类,死活找不到。java.util.concurrent里面类,在python里面基本没有对应的实现。满脸闷逼。
强大的ide,调试,运行监控工具
java 与c# 拥有最强大的ide,这点大家毋庸置疑吧。ide用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。所有具备这一特性的软件或者软件套(组)都可以叫集成开发环境
java 拥有强大的监控工具。有查看java进程的jps,有查线程的jstack等等,下面是jvisualvm的运行图。这些强大的监控帮助开发快速,精确的排除各种问题。从而提高开发效率。
各种基础规范,标准强大的一致性
java定义很多,很多规范,这些规范给软件提供方制造了很多约束。但是方便了使用者,不需要了解是哪个软件提供方提供,更加不需要了解软件提供方如何实现的,只需引入对应规范的jar,按照规范使用就行了。
jdbc1.0规范中就定义了操作相关的接口和类位于java.sql包中。包含了DriverManager类,Driver接口,Connection接口,Statement接口,ResultSet接口,SQLException 类等。任何软件提供方都基于这些规范实现了自己的客服端。jdbc标准概要
项目搭建,发布,运行
在远古社会....java在项目搭建,发布,运行。就是一个神坑..................
从图中看,java项目的发布流程,十分麻烦,而且重启出错。这是鸟菜啊的亲身经历。这是很多其他语言开发者不喜欢java的地方。
java不可能原地踏步。
maven没有出现之前,java项目的搭建,就是一个悲剧。一个新手搭建一个java项目,并且配置好,运行起来。可能好一个星期。
- 到个个框架的网站,去下载
- 导入到ide
- 如果 个个框架的依赖依赖不一致,版本之间的依赖不一致。作为一个搭建者可能要找可就躺了。
这是其他语言开发者最讨厌java的地方之一
自从有了maven之后,java拜托其他php的唾弃,一下从穷屌丝变成了人见人爱,花见花开的高富帅。java项目的搭建,比其他语言轻松多了。但是maven的入门门槛高了。maven的jar依赖,在模块化的领域,强于其他语言的依赖管理。
- java的依赖管理,是基于jar的。其他语言是基于 文件的。
- maven的本地,私有,中央。非常方便使用自己的发布到本地,私有服务的jar。
- maven强大的流程,可以test等。打成运行jar,直接可以到服务上运行。其他语言可能还要在服务上解决依赖关系
spring-boot的轰动出现,让java在运行,开发方面有一个质量的提升
-
使用yml,start插件机制和注释的方式基本放弃了让人唾弃的xml配置,简化了项目构建,部署,管理的成本
-
解决web项目启动复杂度。以前发布一个web项目,需要按照tomcat,部署在tomcat里面。现在不需要了。直接启动jar就行了
在这个方面是java的超级短板,也是其他语言使用者唾弃的地方,随着庞大的java程序员的需求,优秀的java程序员不停的提供优秀的解决方案。使之这个短板变成了java的有点
健全,完善,活跃,成熟的各种框架与库
- java实现了大量软件
- java拥有spring,mybatis等
- 消息中间件
- 大数据全家桶
- 大量分布式框架 ..........
总结
软件工程语言注重的在复杂情况下的效率,而不是简单开发。所以维护,生态园才是根本