阿遂_Asui

阿遂_Asui 查看完整档案

北京编辑北京工业大学  |  计算机科学与技术 编辑SegmentFault  |  技术编辑 编辑 github.com/Sapesn 编辑
编辑

SegmentFault 思否社区老编辑

饮水机の守护神,艾泽拉斯的勇士,朝阳区埃米纳姆,我爸我妈的儿子,深夜撰稿者,统领一猫一狗的国王,Glory to the Sin'dorei!

个人动态

阿遂_Asui 发布了文章 · 今天 10:18

万物互联的背后,有一座“数据围城”

物联网之父 Kevin Ashton 在近期的一次访谈中表示:“物联网的真正意义,不在于收集存储数据。更多场景下,在于正确高效地利用数据。”

之所以提出这个观点,是因为现阶段的物联网也被称作数据“泛在聚合”意义上的物联网。万物互联的时代造就了庞大的数据海洋,Kevin 认为应该通过对其中每个数据进行属性的精确标识,全面实现数据的资源化。

如果不能合理、合规、合情的利用这些数据,我们将会进入一座物联网时代的“数据围城”。

一、物联网时代的“数据围城”

未来学家托夫勒认为,改变世界的有四种力量:暴力、知识、金钱,以及大数据。

战争改变人类社会的走向,知识影响社会的发展轨迹,金钱操纵着世界发展的命脉。而大数据之所以能位列其中,是因为“大数据”就代表着社会的形态,如何定义和理解大数据,就是如何定义和理解这个社会。

物联网作为一种建立在互联网上的泛在网络,让互联网时代的大数据从量变发展到了质变 —— 数据既包含数据本身,也包含了物联网中的万物以及物的状态,物与物、物与人之间的交互。

“像是一座被围困的城堡,城外的人想冲进去,城里的人想逃出来。”这是钱钟书先生书中所描述的围城,而物联网时代的“数据围城”,是指数据虽然可以为我们认知社会、推进社会发展提供源源不断的动力,但却因为我们的不“善假于物”,被不合理的分析和解读。

二、为何要打破这座“数据围城”?

打破这座“数据围城”,既是互联网深入发展的必然要求,也是物联网的使命所在。

而想要打破这座“数据围城”,就需要在物联网所造就的数据海洋中,构建一种“泛在的聚合”关系,使人们不再受系统环境、外部设备和数据终端的限制,便可对各类数据执行方便的检索、计算和分析,并结合已有的数学分析模型,挖掘这些数据所代表的事务之间普遍存在的复杂联系,从而实现人类对周边世界认知能力的革命性飞跃。

打破“数据围城”的前提,是要洞悉物联网时代的数据特点,这其中包括了数据采集、数据处理、数据共享和数据的有效性甄别四个方面,只有在特定场景中进行特定的处理,数据才能转化成我们所需要的信息。

以数据采集为例,作为物联网的第一道关隘,若想打破“数据围城”,切入点必须从传感器入手。传感器是物联网感知层的数据接口,主要负责感知外界信息、响应上层指令,并配合各类终端设备完成数据的统一标准化接入。然而,不同类别的传感器所捕获的信息内容和信息格式均不相同,需要按一定的频率,周期性地采集环境信息并实时更新。随着现代物联网的发展,传感器本身也需要具备智能化处理的能力,即能够对物体实施智能控制。

因此,从传感器入手,需要思考的是如何重新定义“传感器”和“数据”间的关系。如果能将传感器和智能处理相结合,从海量信息中提取、分析、加工和处理数据,辅助业务决策,适应用户的多种需求,便能拓展出全新的应用领域和应用模式。

牵一发而动全身,仅仅从数据采集这一层切入,便要考虑如此多的因素。因此,若想真正打破物联网时代的“数据围城”,将会涉及物联网产业中的多个角色,但只要围绕着前文提到的数据特点进行突破,一定可以达到事半功倍的效果。

三、如何利用物联网时代的数据特点打破“数据围城”

物联网的本质是由众多生态、系统通过特定的规律整合而成,无论生态多么庞大、系统多么复杂,其都可以细分为一个个组件和功能模块,洞悉了这些组件和模块的数据特点,便可以推导出与之关联的物联网的“破城口”。

以现代企业智慧办公为例,来看一下在该场景如何利用各个组件和功能模块的数据特点打破这座“数据围城”。通过前文的分析,已知该场景的数据特点包含三个层面:数据共享、场景化(数据处理)和效率(数据的有效性甄别)。(详情请阅览:《纵观 Excel 演化史,开发者如何通过“表格技术”提升企业生产力》

其中的数据共享,既是该场景的特点,也是物联网时代数据的重要特征。进入物联网时代后,办公软件的使用场景从 PC 和桌面端,扩展到了移动设备、智能手机、PAD 等更多的移动端,企业所面临的智慧办公最大的难点也已经从单纯的一台操作设备,升级成跨设备以及多人之间的协作协同,越来越多的数据需要被采集、分享和运用。

在操作系统层面, HarmonyOS 借助了自身分布式软总线、分布式数据管理和分布式安全三大核心能力有效解决了跨设备的协同问题。但对于具体数据信息的采集、处理、共享和多人协作编辑,仍需要各类在线文档软件的支持。

在线文档类软件的出现,为企业办公提供了全新的工作模式,通过将办公数据从本地迁移到云端,打破了时间和空间的限制,用“更高的效率和更低的成本”实现了在线实时存储和多人协作,这一点也与物联网未来的发展不谋而合。

可见,对于在线文档类软件来说,只要能贴合物联网时代的数据特点,便可以协助打破这座“数据围城”。而无论是数据的采集、计算分析和多人协同交互等都离不开表格控件所提供的底层支持。葡萄城,作为物联网数据类应用落地“协作者”的代表之一,提供的正是这样的能力。(详情请阅览:打破技术壁垒, 用SpreadJS 抢占“表格文档协同编辑系统”的入市先机

作为全球领先的软件开发技术提供商,葡萄城以“ 赋能开发者”为使命,致力于通过各类软件开发工具和服务,创新开发模式,提升开发效率,服务企业数智化转型。

葡萄城研发的纯前端表格控件 SpreadJS ,提供了表格文档协同编辑、 数据填报和类Excel报表设计的功能支持,可帮助软件厂商和系统集成商有效应对数据处理、数据共享和数据有效性甄别等业务需要。

纯前端表格控件 SpreadJS

借助 SpreadJS“高性能、跨平台、与 Excel 高度兼容”的产品特性,可以让数据处理不再受硬件、操作系统与使用环境的限制,从而实现高效的在线填报、模板设计以及多人协同,构建出更为便捷、易用、安全的分布式数据管理架构。(了解详情:SpreadJS 纯前端表格控件

结语:物联网时代,重新审视人与世界间的关系

互联网时代让我们重塑了人与人之间的关系。而物联网时代则将这层关系网放大,需要让我们重新审视物与物、人与物之间的关系,这也是之所以需要打破这一座“数据围城”的意义所在。

了解物联网行业的朋友都知道,物联网产业链中包含八大环节:芯片提供商、传感器供应商、无线模组(含天线)厂商、网络运营商(含 SIM 卡商) 、平台服务商、系统及软件开发商、智能硬件厂商和技术服务提供商。

其中网络运营商负责的是物联网的底层通道,也是目前物联网产业链中最成熟的环节;芯片、传感器等硬件厂商则是物联网的大脑和四肢,低功耗、高可靠性的半导体芯片是物联网几乎所有环节都必不可少的关键部件之一;专供物联网的操作系统虽然仍处于起步阶段,但目前入局的都是 IT 行业的巨头,如谷歌、微软、苹果、华为、阿里等。

纵观整个环节中,目前最容易被忽视、最需要与物联网相结合的恰恰是物联网应用落地真正的“协作者” —— 技术服务提供商。他们才是万物互联时代链接人与物、人与物联网之间最直接的一根纽带。

打破万物互联时代的数据围城,既需要迎合时代大的技术背景,也需要聚焦到每个人的需求当中。我们需要华为、阿里、谷歌这类技术先锋为人类扩展技术的无限可能,也需要像 SpreadJS 这样的垂直细分产品,以人为中心,在技术大潮中服务用户的本质需求。

segmnetfault 思否

查看原文

赞 26 收藏 2 评论 0

阿遂_Asui 赞了文章 · 今天 09:55

遥感资源大放送(下)| 11 个经典遥感数据集

内容提要:利用遥感影像进行土地类别分型,最常用的方法是语义分割。本文继上期土地分类模型训练教程之后,又整理了几大主流公开遥感数据集。

原创:HyperAI超神经

关键词:遥感数据集   语义分割   机器视觉


在上一期遥感资源大放送(上):用开源代码,训练土地分类模型 中,我们详细介绍了遥感影像进行土地分类的常用方法,以及具体如何使用利 deeplab-v3+ 用于土地 7 分类的具体训练过程及代码。

教程地址:

https://openbayes.com/console...

遥感图像原图(上)与 7 分类图(下)示例

除了分类与识别问题之外,遥感影像的常用场景还包括:

  • 超分辨率重建问题
  • 多源遥感影像快速处理问题
  • 遥感影像的分布式存储问题

本期中,我们整理了 11 个遥感数据集资源,其检测目标分类少则 2 种,多则可达 45 类,能够为大家的模型训练提供更加充足的「弹药」,请按需取用。

Part 1:用于 2-5 分类问题

UCAS-AOD 遥感影像数据集

UCAS AOD 遥感影像数据集,用于飞机和车辆检测。

具体来说,飞机数据集包括 600 张图像和 3210 架飞机,而车辆数据集包括 310 张图像和 2819 辆车辆。所有的图像都经过精心挑选,使数据集中的物体方向分布均匀。

车辆(a)与飞机(b)目标检测示例

该数据集由中国科学院大学(国科大)于 2014 年首次发布,并于 2015 年补充,相关论文有《Orientation Robust Object Detection in Aerial Images Using Deep Convolutional Neural Network》。

以下是该数据集的详细信息:

UCAS-AOD 遥感影像数据集

发布机构:中国科学院大学

更新时间:2014 年发布,2015 年补充

包含数量:600 张飞机 & 310 张车辆图像

图像来源:谷歌地球卫星图像

数据格式:.png

图片尺寸:1280*659

数据大小:3.48GB

类别数量: 2 类

下载地址:_https://hyper.ai/datasets/5419_

Inria Aerial Image Labeling Dataset

Inria Aerial Image Labeling Dataset 是一个用于城市建筑物检测的遥感图像数据集,其标记被分为建筑(building)和非建筑(not building)两种,主要用于语义分割。

以下是该数据集的详细信息:

Inria Aerial Image Labeling 数据集

发布机构:INRIA(法国国家信息与自动化研究所)

发布时间:2017 年

包含数量:360 张图像

数据格式:GeoTiff

图像尺寸:5000*5000

数据大小:69GB

类别数量:2 类

发布时间:2017 年

下载地址:_https://hyper.ai/datasets/5428_

RSOD-Dataset 物体检测数据集

RSOD Dataset 是用于遥感图像中物体检测的数据集,其包含飞机、操场、立交桥和油桶四类目标,数量分别为:

  • 飞机:446 张图,包含 4993 架飞机;
  • 操场:189 张图,包含 191 个操场;
  • 立交桥:176 张图,包含 180 座立交桥;
  • 油桶:165 张图,包含 1586 个油桶。

以下是该数据集的详细信息:

RSOD Dataset

发布机构:武汉大学

发布时间:2015 年

包含数量:976 张图像

数据格式:.jpg

数据大小:324.96MB

类别数量:4 类

下载地址:_https://hyper.ai/datasets/5425_

Part 2:用于 5-10 分类问题

RSSCN7 DataSet 遥感图像数据集

RSSCN7 Dataset 包含 2800 幅遥感图像,这些图像来自于 7 个典型的场景类别 —— 草地、森林、农田、停车场、住宅区、工业区和河湖,其中每个类别包含 400 张图像,分别基于 4 个不同的尺度进行采样。

该数据集中每张图像的像素大小为 400*400,场景图像的多样性导致其具有较大的挑战性,这些图像来源于不同季节和天气变化,并以不同的比例进行采样。

以下是该数据集的详细信息:

RSSCN7 Dataset

发布机构:武汉大学

发布时间:2015 年

包含数量:2800 张图像

数据格式:.jpg

图像尺寸:400*400

数据大小:348.02MB

类别数量:7 类

下载地址:_https://hyper.ai/datasets/5440_

NWPU VHR-10 地理空间物体检测遥感数据集

NWPU VHR-10 Dataset 是一个用于空间物体检测的 10 级地理遥感数据集,其拥有 650 张包含目标的图像和 150 张背景图像,共计 800 张,是从Google Earth和Vaihingen数据集裁剪而来的,然后由专家手动注释。

其目标种类包括飞机、舰船、油罐、棒球场、网球场、篮球场、田径场、港口、桥梁和汽车共计 10 个类别。

以下是该数据集的详细信息:

NWPU VHR-10 数据集

发布机构:西北工业大学

发布时间:2014 年

包含数量:800 张图像

数据格式:.jpg

数据大小:73MB

类别数量:10 类

下载地址:_https://hyper.ai/datasets/5422_

Part 3:用于 11-20 分类问题

RSC11 DataSet 遥感影像数据集

RSC11 Dataset 是一个遥感影像数据集,来源于 Google Earth 的高分辨率遥感影像,合计包含 11 类场景图像,包括密林、疏林、草原、港口、高层建筑、低层建筑、立交桥、铁路、居民区、道路、储罐。其中每类有约 100 张,共计 1232 张,空间分辨率为 0.2 米。

该数据集由中科院于 2015 年发布,主要发布人为赵立军。

以下是该数据集的详细信息:

RSC11  数据集

发布机构:中科院

发布时间:2015 年

包含数量:1232 张图像

数据格式:.tif

图片尺寸:512*512

数据大小:20.12MB

类别数量:11 类

下载地址:_https://hyper.ai/datasets/5443_

SIRI-WHU 遥感影像数据集

SIRI-WHU Dataset 包含了 12 个类别的场景,图像共计 2400 张,其中每个类别有 200 张,每张图像的像素尺寸为 200*200,空间分辨率为 2 米。

该数据集资源来自 Google Earth,主要涵盖中国城市地区,其中场景图像数据集由武汉大学 RS-IDEA 集团设计。

以下是该数据集的详细信息:

SIRI-WHU  遥感影像数据集

发布机构:武汉大学

发布时间:2016 年

包含数量:2400 张图像

数据格式:.tif

图片尺寸:200*200

数据大小:162.08MB

类别数量:12 类

下载地址:_https://hyper.ai/datasets/5437_

WHU-RS19 DataSet 遥感影像数据集

WHU-RS19 Dataset 是一个遥感影像数据集,其包含 19 个类别的场景影像共计 1005 张,其中每个类别有 50 张。可用于场景分类和检索。

该数据集由武汉大学于 2011 年发布,相关论文有《Satellite Image Classification via Two-layer Sparse Coding with Biased Image Representation》。

以下是该数据集的详细信息:

WHU-RS19 数据集

发布机构:武汉大学

发布时间:2011 年

包含数量:1005 张图像

数据格式:.tif

图片尺寸:600*600

数据大小:99.54MB

类别数量:19 类

下载地址:_https://hyper.ai/datasets/5434_

Part 4:用于 20+ 分类问题

UC Merced Land-Use DataSet

UC Merced Land-Use Dataset 是一个用于研究的 21 级土地利用图像遥感数据集,均提取自 USGS National Map Urban Area Imagery(美国地质调查局国家地图城市地区图像) 系列,其被用于全国各地的城市地区。

此数据集公共领域图像的像素分辨率为 1 英尺(0.3 米),图像像素大小为 256*256,包含 21 个类别的场景图像共计 2100 张,其中每个类别有 100 张。

这 21 个类别分别是:农业、飞机、棒球场、海滩、建筑物、树丛、密集住宅、森林、高速公路、高尔夫球场、港口、路口、中型住宅、移动家庭公园、立交桥、停车场、河、跑道、稀疏住宅、储油罐。

以下是该数据集的详细信息:

UC Merced Land-Use 数据集

发布机构:UC Merced Vision&Learning Lab

包含数量:2100 张

数据格式:.png

图片尺寸:256*256

数据大小:317.07MB

类别数量:21 类

发布时间:2010 年

下载地址:_https://hyper.ai/datasets/5431_

AID DataSet 遥感影像数据集

AID Dataset 是一个遥感影像数据集,其包含 30 个类别的场景图像,其中每个类别有约 220–420 张,整体共计 10000 张,其中每张像素大小约为 600*600。

该数据集由华中科技大学和武汉大学于 2016 年发布,相关论文:《AID: A Benchmark Dataset for Performance Evaluation of Aerial Scene Classification》。

以下是该数据集的详细信息:

AID 遥感影像数据集

发布机构:华中科技大学和武汉大学

包含数量:10000 张

数据格式:.jpg

图片尺寸:600*600

数据大小: 2.47GB

类别数量:30 类

发布时间:2016 年

下载地址:_https://hyper.ai/datasets/5446_

NWPU DataSet 遥感影像数据集

NWPU Dataset 遥感影像数据集,包含像素大小为 256*256 共计 31500 张图像,涵盖 45 个场景类别,其中每个类别有 700 张图像。

这 45 个场景类别包括飞机、机场、棒球场、篮球场、海滩、桥梁、丛林、教堂、圆形农田、云、商业区、密集住宅、沙漠、森林、高速公路、高尔夫球场、地面田径、港口、工业地区、交叉口、岛、湖、草地、中型住宅、移动房屋公园、山、立交桥、宫、停车场、铁路、火车站、矩形农田、河、环形交通枢纽、跑道、海、船舶、雪山、稀疏住宅、体育场、储水箱、网球场、露台、火力发电站和湿地。

该数据集由西北工业大学发布,相关论文有《Remote Sensing Image Scene Classification: Benchmark and State of the Art》。

以下是该数据集的详细信息:

NWPU Dataset 遥感影像数据集

发布机构:西北工业大学

包含数量:31500 张

数据格式:.jpg

图片尺寸:256*256

数据大小: 403.71MB

类别数量:45 类

发布时间:2017 年

下载地址:_https://hyper.ai/datasets/5449_

以上就是本期资源包的全部内容,你也可以访问以下链接:https://hyper.ai/搜索「遥感数据集」,就可直达全部资源。

查看原文

赞 1 收藏 0 评论 0

阿遂_Asui 发布了文章 · 2月24日

Python 紧急修复漏洞,攻击者此前可远程代码执行漏洞

Python-漏洞

近日,Python 软件基金会 (PSF) 紧急推出 Python 3.9.2 和 3.8.8 稳定版,解决了两个严重的安全缺陷,其中一个从理论上攻击者可远程代码执行漏洞。

PSF 在最新的声明中表示:“自从发布 3.9.2 和 3.8.8 的候选版本以来,由于安全方面的原因,我们收到了大量终端用户的查询督促,要求我们加快最终稳定版本的发布速度。”


PSF 在声明中指出,发布候选版本中包含两个安全修复方案:CVE-2021-3177 和 CVE-2021-23336。

修复的漏洞具体的原因在于,Python 3.x 到 3.9.1 的 ctypes/callproc.c 中 PyCArg_repr 有缓冲溢出,这可能导致远程代码执行。它会影响“接受浮点数作为不受信任的输入的 Python 应用程序,如 c_double.from_param 的 1e300 参数所示”。

发生该错误是原因,是因为不安全地使用了“sprintf”。影响之所以广泛,是因为 Python 已将其预先安装到了多个 Linux 发行版和 Windows 10 当中。

但 PSF 也指出,虽然 CVE-2021-3177 被列为“远程代码执行”漏洞,但这类漏洞遭利用的可能性非常小,因为要实现成功的 RCE,必须满足如下条件:

  • 远程一方将不受信任的浮点数传递给 ctypes.c_double.from_param(注:Python 浮点数不受影响)
  • 将该对象传递给repr() (例如通过 logging)
  • 使该浮点数成为有效的机器代码
  • 使该缓冲区溢出漏洞在执行代码的地方覆写栈。

而 Red Hat 在评估该漏洞后,表示“最大的威胁是系统可用性”。

“可以肯定的是,通过恶意输入造成拒绝服务也是一个严重的问题。”出于这一原因。PSF 决定停止位漏洞修复版本提供发布候选版本。同时也为那些认为发布候选版本不够的社区成员发布了最终的 3.9.2 和 3.8.8 稳定版本。

部分参考资料来源:

segmentfault 思否

查看原文

赞 0 收藏 0 评论 0

阿遂_Asui 赞了文章 · 2月20日

火星无人机全部代码公开!毅力号带着手机芯片和 Linux 系统上太空

毅力号登陆火星,带着手机芯片和 Linux 系统上太空了!

历经 203 天,穿越了 4.72 亿公里之后,美国“毅力号”火星车终于在美东时间下午 3:55 成功登陆火星。

结束近 7 个月的旅程后,“毅力号”传回了通过避险摄像机拍摄的第一张火星表面景象。这次,“毅力号”的主要任务是——寻找古代生命的迹象,并收集火星岩石和土壤样本带回地球研究。

值得一提的是,配合“毅力号”完成探测任务的“机智号”无人机搭载的是骁龙 801 处理器。没错,就是那个用在手机上的骁龙 801。当年,小米 4 用的就是这款芯片。

此外,这也是人类第一次在火星上运行 Linux 系统。“毅力号”上的无人机“机智号”实际上是通过 Linux 操作系统控制的。不止如此,NASA 还把这个专门为火星无人机开发的 Linux 飞行控制系统开源了!

这就是毅力号在火星表面拍摄的第一张图像:

image.png

“恐怖 7 分钟”艰难着陆

2020 年 7 月 30 日,耗资 24 亿美元的毅力号从美国佛罗里达州的卡纳维拉尔角太空部队站发射升空,带着收集火星样本的任务迈出了火星探索的第一步。

美国宇航局科学副主任托马斯说,“毅力号是从火星带回岩石的第一步,我们不知道这些来自火星的原始样本会告诉我们什么,但无疑是非常重要的,甚至可能包括曾经存在于地球之外的生命。”

image.png

毅力号进入下降阶段时,以大约 20000 km/h 的速度飞行,尽管火星的气氛很稀薄,但它仍将给毅力号带来极大的阻力。进入火星大气层大约 80 秒钟之内,航空器外壳外部的温度将达到 1300 摄氏度。

约四分钟后,毅力号的“降落伞”展开,保护性航空器外壳脱落。当毅力号下降到火星表面上方约 4 公里时,它将激活其地形导航系统。

410 秒后(将近 7 分钟),毅力号终于在火星成功着陆。与 2018 年 8 月的“好奇号”火星车非常相似,它也在着陆时经历了类似的“恐怖 7 分钟”。

image.png

火星表面首次有直升机起飞

毅力号首次将直升机带上了火星,机智号火星无人机将在火星表面飞起几英尺的高度,并在毅力号火星车的周围盘旋,收集图像信息。这将是直升机在火星极薄的大气层中首次实现动力飞行。

image.png

机智号无人机仅重 1.8 公斤,通过顶部安装的 4 个碳纤维螺旋桨提供动力,每分钟转速为 2400 转,功率为 350 瓦。为了配合毅力号的探测任务,它要面对许多挑战。

要知道,实现直升机在火星上飞行是有很大难度的。一方面火星的稀薄大气使得难以获得足够的升力。另一方面由于火星大气层的密度比地球密度低 99%,直升机的旋转叶片也要做的更大,并且转速要非常快才能起飞。

image.png

机智号采用骁龙 801 处理器,带着 Linux 系统上火星

由于太空探索对硬件设备的稳定性要求极高,很多设备都采用了已经在地面运行了多年的处理器,机智号也是如此。但值得注意的是,机智号这次没有采用商业级别的处理器,而是用于手机的民用处理器。这是因为,机智号被 NASA 视为一项“技术演示”,因此愿意接受更多风险,于是采用了民用的骁龙 801 处理器。

image.png

此外,由于毅力号的任务对信息的收集和处理要求极高,需要捕捉图像、分析特征,并以 30 赫兹的频率从一帧到另一帧跟踪它们。以往已经使用多年的商业级处理器已无法达到标准。而骁龙 801 的本质是一款手机处理器,而且它的主板非常小。它的功能远比其他火星车上的处理器多得多,拥有更强大的计算力。

除了手机处理器,机智号还带来了一个惊喜,将 Linux 带上了火星。

这是人类第一次在火星上使用 Linux 飞行控制系统,据 NASA 介绍,机智号使用的软件框架是JPL 为立方体卫星和仪器开发的,并在几年前就开源了。也就是说,任何人都能使用这个在火星直升机上的软件框架,并将它用在你自己的项目上。

将开源进行到底,火星无人机代码已全部公开

F Prime 是火星无人机“机智号”的飞行软件框架,目前已在 GitHub 上全部公开!

F Prime 是为机智号量身定制的一个组件驱动的框架,可以快速开发和部署太空飞行及其他嵌入式软件应用程序。

那么,有了这些公开的代码,我们是不是也能下载机智号同款代码搞个火星无人机出来了呢?

image.png

NASA 开源的 F Prime 提供了一个完整的开发生态系统,包括建模工具、测试工具和地面数据系统。开发人员使用建模工具编写高级规范,自动使用 C ++ 生成实现,并使用特定领域的代码填充实现。框架和代码生成器提供 F Prime 部署所需的所有样板代码,包括用于线程管理的代码,用于组件之间通信的代码以及用于处理命令,遥测和参数的代码。测试工具和地面数据系统简化了在工作站和实验室中的飞行硬件上的软件测试。

此外,F Prime 还实现了以下几个关键功能:

1.可重用性:基于组件的体系结构可实现高度的模块化和软件重用。

2.可移植性:F Prime 在从微控制器到多核计算机的多种处理器以及多种操作系统上运行,将其移植到新的操作系统非常简单。

3.高性能:采用点对点架构,最大程度地减少了计算资源的使用,非常适合较小的处理器。

4.量身定制,可满足小型任务所需的复杂程度,不仅易于使用,还能同时仍支持多种任务。

5.可分析性:类型化的端口连接为编译时的正确性提供了有力的保证。

快速安装指南

前提条件:

  • cmake
  • git
  • Python 3.5+ with pip

安装这些实用程序后,即可安装 F Prime Python 依赖项。在 Python 虚拟环境中安装依赖项可以防止系统级问题,但是不需要在虚拟环境中进行安装。

要快速安装 F Prime,请输入:

image.png

太空冒险迈上新台阶,“移民火星”不是梦

毅力号将在火星完成一系列高度复杂的任务,为人类探索古代生物信息和火星土壤研究提供有力支持。随着毅力号一起登陆火星的机智号也为人类的太空事业迈上了一个更高的台阶。

与此同时,中国的“天问一号”火星车也即将今年 5 月登陆火星。人类的太空冒险仍在继续,也许“移民火星”在未来的某一天真的将不止是梦想,而真正照进现实。

参考链接:https://spectrum.ieee.org/aut...
https://www.futurezone.de/sci...
GitHub 地址:https://github.com/nasa/fprime

segmentfault 公众号

查看原文

赞 7 收藏 1 评论 1

阿遂_Asui 赞了文章 · 2月19日

如何提高代码的可读性 学习笔记

本文整理自 taowen 师傅在滴滴内部的分享。

1.Why

对一线开发人员来说,每天工作内容大多是在已有项目的基础上继续堆代码。当项目实在堆不动时就需要寻找收益来重构代码。既然我们的大多数时间都花在坐在显示器前读写代码这件事上,那可读性不好的代码都是在谋杀自己or同事的生命,所以不如一开始就提炼技巧,努力写好代码; )

2.How

为提高代码可读性,先来分析代码实际运行环境。代码实际运行于两个地方:cpu人脑。对于cpu,代码优化需理解其工作机制,写代码时为针对cpu特性进行优化;对于人脑,我们在读代码时,它像解释器一样,一行一行运行代码,从这个角度来说,要提高代码的可读性首先需要知道大脑的运行机制。

image.png

下面来看一下人脑适合做的事情和不适合做的事情:

大脑擅长做的事情

名称图片说明
对象识别image.png不同于机器学习看无数张猫片之后可能还是不能准确识别猫这个对象,人脑在看过几只猫之后就可以很好的识别。
空间分解image.png人脑不需要标注,可以直观感受到空间中的不同物体。
时序预测image.png你的第一感觉是不是这个哥们要被车撞了?
时序记忆image.png作为人类生存本能之一,我们多次走过某个地方时,人脑会对这个地方形成记忆。
类比推测image.png人脑还有类比功能,比如说这道题大多数人会选择C吧。

大脑不擅长做的事情

名称图片例子
无法映射到现实生活经验的抽象概念image.png人脑看到左图时,会比较轻松想到通关方式,但是如果换成右图这种抽象的概念,里面的对象换成了嘿嘿的像素,我们就不知道这是什么鬼了。比如说代码里如果充斥着Z,X,C,V 这样的变量名,你可能就看懵了。
冗长的侦探推理image.png这种需要递归(or循环)去检查所有可能性最后找到解法的场景,人脑同样不擅长。
跟踪多个同时变化的过程image.png大脑是个单线程的CPU,不擅长左手画圆,右手画圈。

代码优化理论

了解人脑的优缺点后,写代码时就可以根据人脑的特点对应改善代码的可读性了。这里提取出三种理论:

  1. Align Models ,匹配模型:代码中的数据和算法模型 应和人脑中的 心智模型对应
  2. Shorten Process , 简短处理:写代码时应 缩短 “福尔摩斯探案集” 的流程长度,即不要写大段代码
  3. Isolate Process,隔离处理:写代码一个流程一个流程来处理,不要同时描述多个流程的演进过程

下面通过例子详细解释这三种模型:

Align Models

在代码中,模型无外乎就是数据结构算法,而在人脑中,对应的是心智模型,所谓心智模型就是人脑对于一个物体 or 一件事情的想法,我们平时说话就是心智模型的外在表现。写代码时应把代码中的名词与现实名词对应起来,减少人脑从需求文档到代码的映射成本。比如对于“银行账户”这个名词,很多变量名都可以体现这个词,比如:bankAccount、bank_account、account、BankAccount、BA、bank_acc、item、row、record、model,编码中应统一使用和现实对象能链接上的变量名。

代码命名技巧

起变量名时候取其实际含义,没必要随便写个变量名然后在注释里面偷偷用功。

// bad
var d int // elapsed time in days

// good
var elapsedTimeInDays int // 全局使用

起函数名 动词+名词结合,还要注意标识出你的自定义变量类型:

// bad
func getThem(theList [][]int) [][]int {
    var list1 [][]int // list1是啥,不知道
    for _, x := range theList {
        if x[0] == 4 { // 4是啥,不知道
            list1 = append(list1, x)
        }
    }
    return list1
}

// good
type Cell []int // 标识[]int作用

func (cell Cell) isFlagged() bool { // 说明4的作用
    return cell[0] == 4
}

func getFlaggedCells(gameBoard []Cell) []Cell { // 起有意义的变量名
    var flaggedCells []Cell
    for _, cell := range gameBoard {
        if cell.isFlagged() {
            flaggedCells = append(flaggedCells, cell)
        }
    }
    return flaggedCells
}
代码分解技巧

按照空间分解(Spatial Decomposition):下面这块代码都是与Page相关的逻辑,仔细观察可以根据page的空间分解代码:

// bad
// …then…and then … and then ... // 平铺直叙描述整个过程
func RenderPage(request *http.Request) map[string]interface{} {
    page := map[string]interface{}{}
    name := request.Form.Get("name")
    page["name"] = name
    urlPathName := strings.ToLower(name)
    urlPathName = regexp.MustCompile(`['.]`).ReplaceAllString(
        urlPathName, "")
    urlPathName = regexp.MustCompile(`[^a-z0-9]+`).ReplaceAllString(
        urlPathName, "-")
    urlPathName = strings.Trim(urlPathName, "-")
    page["url"] = "/biz/" + urlPathName
    page["date_created"] = time.Now().In(time.UTC)
    return page
}
// good
// 按空间分解,这样的好处是可以集中精力到关注的功能上
var page = map[string]pageItem{
    "name":         pageName,
    "url":          pageUrl,
    "date_created": pageDateCreated,
}

type pageItem func(*http.Request) interface{}

func pageName(request *http.Request) interface{} { // name 相关过程
    return request.Form.Get("name")
}

func pageUrl(request *http.Request) interface{} { // URL 相关过程
    name := request.Form.Get("name")
    urlPathName := strings.ToLower(name)
    urlPathName = regexp.MustCompile(`['.]`).ReplaceAllString(
        urlPathName, "")
    urlPathName = regexp.MustCompile(`[^a-z0-9]+`).ReplaceAllString(
        urlPathName, "-")
    urlPathName = strings.Trim(urlPathName, "-")
    return "/biz/" + urlPathName
}

func pageDateCreated(request *http.Request) interface{} { // Date 相关过程
    return time.Now().In(time.UTC)
}

按照时间分解(Temporal Decomposition):下面这块代码把整个流程的算账和打印账单混写在一起,可以按照时间顺序对齐进行分解:

// bad 
func (customer *Customer) statement() string {
    totalAmount := float64(0)
    frequentRenterPoints := 0
    result := "Rental Record for " + customer.Name + "\n"

    for _, rental := range customer.rentals {
        thisAmount := float64(0)
        switch rental.PriceCode {
        case REGULAR:
            thisAmount += 2
        case New_RELEASE:
            thisAmount += rental.rent * 2
        case CHILDREN:
            thisAmount += 1.5
        }
        frequentRenterPoints += 1
        totalAmount += thisAmount
    }
    result += strconv.FormatFloat(totalAmount,'g',10,64) + "\n"
    result += strconv.Itoa(frequentRenterPoints)

    return result
}
// good 逻辑分解后的代码
func statement(custom *Customer) string {
    bill := calcBill(custom)

    statement := bill.print()

    return statement
}

type RentalBill struct {
    rental Rental
    amount float64
}

type Bill struct {
    customer             *Customer
    rentals              []RentalBill
    totalAmount          float64
    frequentRenterPoints int
}

func calcBill(customer *Customer) Bill {

    bill := Bill{}
    for _, rental := range customer.rentals {
        rentalBill := RentalBill{
            rental: rental,
            amount: calcAmount(rental),
        }
        bill.frequentRenterPoints += calcFrequentRenterPoints(rental)
        bill.totalAmount += rentalBill.amount
        bill.rentals = append(bill.rentals, rentalBill)
    }
    return bill
}

func (bill Bill) print() string {

    result := "Rental Record for " + bill.customer.name + "(n"

    for _, rental := range bill.rentals{
        result += "\t" + rental.movie.title + "\t" +
            strconv.FormatFloat(rental.amount, 'g', 10, 64) + "\n"
    }
    

    result += "Amount owed is " +
        strconv.FormatFloat(bill.totalAmount, 'g', 10, 64) + "\n"

    result += "You earned + " +
        strconv.Itoa(bill.frequentRenterPoints) + "frequent renter points"

    return result
}

func calcAmount(rental Rental) float64 {
    thisAmount := float64(0)
    switch rental.movie.priceCode {
    case REGULAR:
        thisAmount += 2
        if rental.daysRented > 2 {
            thisAmount += (float64(rental.daysRented) - 2) * 1.5
        }
    case NEW_RELEASE:
        thisAmount += float64(rental.daysRented) * 3
    case CHILDRENS:
        thisAmount += 1.5
        if rental.daysRented > 3 {
            thisAmount += (float64(rental.daysRented) - 3) * 1.5
        }
    }
    return thisAmount
}

func calcFrequentRenterPoints(rental Rental) int {
    frequentRenterPoints := 1
    switch rental.movie.priceCode {
    case NEW_RELEASE:
        if rental.daysRented > 1 {
            frequentRenterPointst++
        }
    }
    return frequentRenterPoints
}

按层分解(Layer Decomposition):

// bad
func findSphericalClosest(lat float64, lng float64, locations []Location) *Location {
    var closest *Location
  closestDistance := math.MaxFloat64
  for _, location := range locations {
    latRad := radians(lat)
    lngRad := radians(lng)
    lng2Rad := radians(location.Lat)
    lng2Rad := radians(location.Lng)
    var dist = math.Acos(math.Sin(latRad) * math.Sin(lat2Rad) +  
                         math.Cos(latRad) * math.Cos(lat2Rad) *
                         math.Cos(lng2Rad - lngRad) 
                        )
    if dist < closestDistance {
            closest = &location
      closestDistance = dist
    }
  }
    return closet
}
// good
type Location struct {
}

type compare func(left Location, right Location) int

func min(objects []Location, compare compare) *Location {
    var min *Location
    for _, object := range objects {
        if min == nil {
            min = &object
            continue
        }
        if compare(object, *min) < 0 {
            min = &object
        }
    }
    return min
}

func findSphericalClosest(lat float64, lng float64, locations []Location) *Location {
    isCloser := func(left Location, right Location) int {
        leftDistance := rand.Int()
        rightDistance := rand.Int()
        if leftDistance < rightDistance {
            return -1
        } else {
            return 0
        }
    }
    closet := min(locations, isCloser)
    return closet
}
注释

注释不应重复代码的工作。应该去解释代码的模型和心智模型的映射关系,应说明为什么要使用这个代码模型,下面的例子就是反面教材:

// bad
/** the name. */
var name string
/** the version. */
var Version string
/** the info. */
var info string

// Find the Node in the given subtree, with the given name, using the given depth.
func FindNodeInSubtree(subTree *Node, name string, depth *int) *Node {
}

下面的例子是正面教材:

// Impose a reasonable limit - no human can read that much anyway
const MAX_RSS_SUBSCRIPTIONS = 1000

// Runtime is O(number_tags * average_tag_depth), 
// so watch out for badly nested inputs.
func FixBrokenHTML(HTML string) string {
    // ...
}

Shorten Process

Shorten Process的意思是要缩短人脑“编译代码”的流程。应该避免写出像小白鼠走迷路一样又长又绕的代码。所谓又长又绕的代码表现在,跨表达式跟踪、跨多行函数跟踪、跨多个成员函数跟踪、跨多个文件跟踪、跨多个编译单元跟踪,甚至是跨多个代码仓库跟踪。

对应的手段可以有:引入变量、拆分函数、提早返回、缩小变量作用域,这些方法最终想达到的目的都是让大脑喘口气,不要一口气跟踪太久。同样来看一些具体的例子:

例子

下面的代码,多种复合条件组合在一起,你看了半天绕晕了可能也没看出到底什么情况下为true,什么情况为false。

// bad
func (rng *Range) overlapsWith(other *Range) bool {
    return (rng.begin >= other.begin && rng.begin < other.end) ||
        (rng.end > other.begin && rng.end <= other.end) ||
        (rng.begin <= other.begin && rng.end >= other.end)
}

但是把情况进行拆解,每种条件进行单独处理。这样逻辑就很清晰了。

// good
func (rng *Range) overlapsWith(other *Range) bool {
    if other.end < rng.begin {
        return false // they end before we begin 
    }    
    if other.begin >= rng.end {
        return false // they begin after we end 
    }
  return true // Only possibility left: they overlap
}

再来看一个例子,一开始你写代码的时候,可能只有一个if ... else...,后来PM让加一下权限控制,于是你可以开心的在if里继续套一层if,补丁打完,开心收工,于是代码看起来像这样:

// bad 多层缩进的问题
func handleResult(reply *Reply, userResult int, permissionResult int) {
  if userResult == SUCCESS {
    if permissionResult != SUCCESS {
      reply.WriteErrors("error reading permissions")
        reply.Done()
        return
    }
    reply.WriteErrors("")
  } else {
    reply.WriteErrors("User Result")
  }
  reply.Done()
}

这种代码也比较好改,一般反向写if条件返回判否逻辑即可:

// good
func handleResult(reply *Reply, userResult int, permissionResult int) {
  defer reply.Done()
  if userResult != SUCCESS {
    reply.WriteErrors("User Result")
    return 
  }
  if permissionResult != SUCCESS {
    reply.WriteErrors("error reading permissions")
    return
  }
  reply.WriteErrors("")
}

这个例子的代码问题比较隐晦,它的问题是所有内容都放在了MooDriver这个对象中。

// bad
type MooDriver struct {
    gradient Gradient
  splines []Spline
}
func (driver *MooDriver) drive(reason string) {
  driver.saturateGradient()
  driver.reticulateSplines()
  driver.diveForMoog(reason)
}

比较好的方法是尽可能减少全局scope,而是使用上下文变量进行传递。

// good 
type ExplicitDriver struct {
  
}

// 使用上下文传递
func (driver *MooDriver) drive(reason string) {
  gradient := driver.saturateGradient()
  splines := driver.reticulateSplines(gradient)
  driver.diveForMoog(splines, reason)
}

Isolate Process

人脑缺陷是不擅长同时跟踪多件事情,如果”同时跟踪“事物的多个变化过程,这不符合人脑的构造;但是如果把逻辑放在很多地方,这对大脑也不友好,因为大脑需要”东拼西凑“才能把一块逻辑看全。所以就有了一句很经典的废话,每个学计算机的大学生都听过。你的代码要做到高内聚,低耦合,这样就牛逼了!-_-|||,但是你要问说这话的人什么叫高内聚,低耦合呢,他可能就得琢磨琢磨了,下面来通过一些例子来琢磨一下。

首先先来玄学部分,如果你的代码写成下面这样,可读性就不会很高。

image.png

一般情况下,我们可以根据业务场景努力把代码修改成这样:

image.png

举几个例子,下面这段代码非常常见,里面version的含义是用户端上不同的版本需要做不同的逻辑处理。

func (query *Query) doQuery() {
  if query.sdQuery != nil {
    query.sdQuery.clearResultSet()
  }
  // version 5.2 control
  if query.sd52 {
    query.sdQuery = sdLoginSession.createQuery(SDQuery.OPEN_FOR_QUERY)
  } else {
    query.sdQuery = sdSession.createQuery(SDQuery.OPEN_FOR_QUERY)
  }
  query.executeQuery()
}

这段代码的问题是由于版本差异多块代码流程逻辑Merge在了一起,造成逻辑中间有分叉现象。处理起来也很简单,封装一个adapter,把版本逻辑抽出一个interface,然后根据版本实现具体的逻辑。

再来看个例子,下面代码中根据expiry和maturity这样的产品逻辑不同 也会造成分叉现象,所以你的代码会写成这样:

// bad
type Loan struct {
    start    time.Time
    expiry   *time.Time
    maturity *time.Time
    rating   int
}

func (loan *Loan) duration() float64 {
    if loan.expiry == nil {
        return float64(loan.maturity.Unix()-loan.start.Unix()) / 365 * 24 * float64(time.Hour)
    } else if loan.maturity == nil {
        return float64(loan.expiry.Unix()-loan.start.Unix()) / 365 * 24 * float64(time.Hour)
    }
    toExpiry := float64(loan.expiry.Unix() - loan.start.Unix())
    fromExpiryToMaturity := float64(loan.maturity.Unix() - loan.expiry.Unix())
    revolverDuration := toExpiry / 365 * 24 * float64(time.Hour)
    termDuration := fromExpiryToMaturity / 365 * 24 * float64(time.Hour)
    return revolverDuration + termDuration
}

func (loan *Loan) unusedPercentage() float64 {
    if loan.expiry != nil && loan.maturity != nil {
        if loan.rating > 4 {
            return 0.95
        } else {
            return 0.50
        }
    } else if loan.maturity != nil {
        return 1
    } else if loan.expiry != nil {
        if loan.rating > 4 {
            return 0.75
        } else {
            return 0.25
        }
    }
    panic("invalid loan")
}

解决多种产品逻辑的最佳实践是Strategy pattern,代码入下图,根据产品类型创建出不同的策略接口,然后分别实现duration和unusedPercentage这两个方法即可。

// good
type LoanApplication struct {
    expiry   *time.Time
    maturity *time.Time
}

type CapitalStrategy interface {
    duration() float64
    unusedPercentage() float64
}

func createLoanStrategy(loanApplication LoanApplication) CapitalStrategy {
    if loanApplication.expiry != nil && loanApplication.maturity != nil {
        return createRCTL(loanApplication)
    }
    if loanApplication.expiry != nil {
        return createRevolver(loanApplication)
    }
    if loanApplication.maturity != nil {
        return createTermLoan
    }
    panic("invalid loan application")
}

但是现实情况没有这么简单,因为不同事物在你眼中就是多进程多线程运行的,比如上面产品逻辑的例子,虽然通过一些设计模式把执行的逻辑隔离到了不同地方,但是代码中只要含有多种产品,代码在执行时还是会有一个产品选择的过程。逻辑发生在同一时间、同一空间,所以“自然而然”就需要写在了一起:

  • 功能展示时,由于需要展示多种信息,会造成 concurrent process
  • 写代码时,业务包括功能性和非功能性需求,也包括正常逻辑和异常逻辑处理
  • 考虑运行效率时,为提高效率我们会考虑异步I/O、多线程/协程
  • 考虑流程复用时,由于版本差异和产品策略也会造成merged concurrent process

对于多种功能杂糅在一起,比如上面的RenderPage函数,对应解法为不要把所有事情合在一起搞,把单块功能内聚,整体再耦合成为一个单元。

对于多个同步进行的I/O操作,可以通过协程把揉在一起的过程分开来:

// bad 两个I/O写到一起了
func sendToPlatforms() {
    httpSend("bloomberg", func(err error) {
        if err == nil {
            increaseCounter("bloomberg_sent", func(err error) {
                if err != nil {
                    log("failed to record counter", err)
                }
            })
        } else {
            log("failed to send to bloom berg", err)
        }
    })
    ftpSend("reuters", func(err error) {
        if err == DIRECTORY_NOT_FOUND {
            httpSend("reuterHelp", err)
        }
    })
}

对于这种并发的I/O场景,最佳解法就是给每个功能各自写一个计算函数,代码真正运行的时候是”同时“在运行,但是代码中是分开的。

//good 协程写法
func sendToPlatforms() {
    go sendToBloomberg()
    go sendToReuters()
}

func sendToBloomberg() {
    err := httpSend("bloomberg")
    if err != nil {
        log("failed to send to bloom berg", err)
        return
    }
    err := increaseCounter("bloomberg_sent")
    if err != nil {
        log("failed to record counter", err)
    }
}

func sendToReuters() {
    err := ftpSend("reuters")
    if err == nil {
        httpSend("reutersHelp", err)
    }
}

有时,逻辑必须要合并到一个Process里面,比如在买卖商品时必须要对参数做逻辑检查:

// bad
func buyProduct(req *http.Request) error {
    err := checkAuth(req)
    if err != nil {
        return err
    }
    // ...
}

func sellProduct(req *http.Request) error {
    err := checkAuth(req)
    if err != nil {
        return err
    }
    // ...
}

这种头部有公共逻辑经典解法是写个Decorator单独处理权限校验逻辑,然后wrapper一下正式逻辑即可:

// good 装饰器写法
func init() {
    buyProduct = checkAuthDecorator(buyProduct)
    sellProduct = checkAuthDecorator(sellProduct)
}

func checkAuthDecorator(f func(req *http.Request) error) func(req *http.Request) error {
    return func(req *http.Request) error {
        err := checkAuth(req)
        if err != nil {
            return err
        }
        return f(req)
    }
}

var buyProduct = func(req *http.Request) error {
    // ...
}

var sellProduct = func(req *http.Request) error {
    // ...
}

此时你的代码会想这样:

image.png

当然公共逻辑不仅仅存在于头部,仔细思考一下所谓的strategy、Template pattern,他们是在逻辑的其他地方去做这样的逻辑处理。

image.png

这块有一个新的概念叫:信噪比。信噪比是一个相对概念,信息,对有用的;噪音,对没用的。代码应把什么逻辑写在一起,不仅取决于读者是谁,还取决于这个读者当时希望完成什么目标。

比如下面这段C++和Python代码:

void sendMessage(const Message &msg) const {...}
![image.png](/img/bVcOMhy)
def sendMessage(msg):

如果你现在要做业务开发,你可能会觉得Python代码读起来很简洁;但是如果你现在要做一些性能优化的工作,C++代码显然能给你带来更多信息。

再比如下面这段代码,从业务逻辑上讲,这段开发看起来非常清晰,就是去遍历书本获取Publisher。

for _, book := range books {
  book.getPublisher()
}

但是如果你看了线上打了如下的SQL日志,你懵逼了,心想这个OOM真**,真就是一行一行执行SQL,这行代码可能会引起DB报警,让你的DBA同事半夜起来修DB。

SELECT * FROM Pubisher WHERE PublisherId = book.publisher_id
SELECT * FROM Pubisher WHERE PublisherId = book.publisher_id
SELECT * FROM Pubisher WHERE PublisherId = book.publisher_id
SELECT * FROM Pubisher WHERE PublisherId = book.publisher_id
SELECT * FROM Pubisher WHERE PublisherId = book.publisher_id

所以如果代码改成这样,你可能就会更加明白这块代码其实是在循环调用实体。

for _, book := range books {
  loadEntity("publisher", book.publisher_id)
}

总结一下:

  • 优先尝试给每 个Process一个自己的函数,不要合并到一起来算

    • 尝试界面拆成组件
    • 尝试把订单拆成多个单据,独立跟踪多个流程
    • 尝试用协程而不是回调来表达concurrent i/o
  • 如果不得不在一个Process中处理多个相对独立的事情

    • 尝试复制一份代码,而不是复用同一个Process
    • 尝试显式插入: state/ adapter/ strategy/template/ visitor/ observer
    • 尝试隐式插入: decorator/aop
    • 提高信噪比是相对于具体目标的,提高了一个目标的信噪比,就降低了另外一个目标的信噪比

3.总结

当我们吐槽这块代码可读性太差时,不要把可读性差的原因简单归结为注释不够 或者不OO,而是可以从人脑特性出发,根据下面的图片去找到代码问题,然后试着改进它(跑了几年的老代码还是算了,别改一行线上全炸了: )

image.png

查看原文

赞 19 收藏 4 评论 0

阿遂_Asui 赞了文章 · 2月8日

从推荐算法到前端开发,字节跳动技术 Leader 们都在学什么?

本文为授权转载内容。内容来源:字节跳动技术范儿

“春季招聘和金三银四要开始了,我想提升技术,更上一层楼,除了投简历刷题,还有什么可以努力的方向啊?”

如果你是技术领域的新人,或者已经毕业多年、正在考虑转向新的技术方向,上面这个问题可能正在困扰着你。

为了回答这个问题,技术范儿找到了多媒体、推荐算法、计算机视觉、强化学习、机器翻译、知识图谱、安卓、iOS、前端等几个方向的 Leader,推荐了各个技术方向的自学资源。

其中,有不少业界知名的书籍、全球 CS 名校的公开课程,可以系统性地帮你了解一个领域的全貌。

还有不少应用技术和开源项目,工业界的常备工具都列齐了。

另外,也有一些是 Leader 们推荐团队内部同学学习的资料,如果你理解掌握得足够好,说不定可以在面试官心目中留下不错的印象。

如果你是正在准备春招的在校生,或者已经毕业并希望在金三银四获得更好的平台,不妨收藏起来,慢慢学习。

image.png

多媒体

多媒体团队 Leader Jessica 推荐了三类内容:

第一类是图像、视频处理的基础理论书籍;

第二类是视频编码标准方面的书籍;

第三类是业内常用的开源项目。

《数字图像处理》

作者:Rafael C. Gonzalez 等

image.png

数字图像处理领域的经典教材,也普遍作为学习图像处理、计算机视觉的入门必备书籍,经久不衰。

《视频处理与通信》

作者:王瑶 等

image.png

系统性介绍视频处理关键技术的一本经典教材,从视频基础理论到视频编码、视频通信等。适合有一点信号系统或者图像处理理论基础的同学进一步学习使用。

《新一代视频压缩编码标准--H.264/AVC》

作者:毕厚杰、王健

image.png

一本能让读者很好地了解主流视频编码技术的参考书。

《Audio Signal Processing and Coding》

作者:Andreas Spanias, Ted Painter, Venkatraman Atti

image.png

音频的书相比视频而言少很多,但这本算是音频信号处理与编码领域较为经典的了,可以作为音频处理学习相关的参考书。

相关开源工程

FFmpeg:https://github.com/FFmpeg/FFmpeg

迄今为止最流行的开源多媒体框架之一,非常强大,基本算是互联网视频技术相关的必修开源工程了。

vlc:https://github.com/videolan/vlc

Ijkplayer:https://github.com/bilibili/i...

exoplayer:https://github.com/google/Exo...

播放器相关三大经典开源工程,了解主流视频解码、播放技术必选。

Jessica说,上述这些开源工程基本上是各个方向上不同时期最top的了,业内从业者对它们都非常熟悉。

image.png

推荐算法

抖音推荐团队Leader William同学推荐了5本书,基本都是深度学习、机器学习方面非常经典的书。

《Deep Learning深度学习》

作者:Ian Goodfellow、Yoshua Bengio、Aaron Courville

image.png

这本书就是业内知名的「花书」,是深度学习领域奠基性的经典教材。

《动手学深度学习》

作者:李沐 等

image.png

William说,这是他见过最好的机器学习、深度学习教材,理论与实践结合,并且中英双语都有,而且还是免费开源的资源。

资源链接

电子版:https://zh.d2l.ai/index.html

GitHub:https://github.com/d2l-ai/d2l-zh

《百面机器学习》

作者:诸葛越

image.png

William说,这本书的作者是Hulu中国负责人,书里知识点很多,也有不少工业界的观点,相关知识点最好都弄清楚,对从事算法工作会有比较大的帮助。

《深度学习推荐系统》

作者:王喆

image.png

William认为,这本书可以帮助读者了解业界推荐系统的基础知识体系,梳理推荐算法的发展脉络。

《推荐系统实践》

作者:项亮

image.png

推荐系统入门必备,非常适合初学者。

image.png

计算机视觉

图像算法方向的Leader吴辛隆说,团队同学主要靠学习CV论文来提升自己的技术能力。除了历年顶会的论文之外,他也推荐了业界最常用的PyTorch和TensorFlow两大框架,以及影响力最大的几位专家的书籍课程。

吴恩达深度学习工程师全套课程

主讲:吴恩达

桃李满天下的吴恩达老师的课程,深度学习方向的同学应该都听说过。

链接:https://mooc.study.163.com/sm...

斯坦福 CS231n:用于视觉识别的卷积神经网络

主讲:李飞飞

斯坦福一大知名课程,主讲人是推动了CV行业飞速发展的ImageNet发起人李飞飞。

链接:http://cs231n.stanford.edu/

《机器学习》

作者:周志华

image.png

这本书也是业界知名的教材,它从“如何挑西瓜”这个例子开头,又被称作「西瓜书」,来自南京大学周志华教授。

PyTorch教程-Yunjey Choi

image.png

PyTorch作为备受欢迎的深度学习两大框架之一,对于计算机视觉等方向的研究者来说是必备技能。如果你已经看过了PyTorch官方教程,来自韩国NAVER AI Lab研究员Yunjey Choi的开源PyTorch教程是不错的补充,在GitHub上有将近20000颗星,教程中的大多数模型是由不到30行代码实现的。

链接:https://github.com/yunjey/pyt...

TensorFlow中文官方文档

image.png

深度学习另一大框架TensorFlow官方教程的中文版,由极客学院Wiki翻译。

链接:https://github.com/jikexueyua...

CVF顶会论文库

image.png

计算机视觉基金会(CVF)赞助了包括CVPR、ICCV等在内业界主流的几大计算机视觉顶会,他们的论文库也结构性地整理了这些顶会历年的所有论文,可以方便同学们系统性的查找计算机视觉相关各方面的论文。

链接:https://openaccess.thecvf.com...

image.png

强化学习

强化学习研究员Flood Sung和ChnX两位的推荐名单里除了一本名为《强化学习》的经典书目之外,还有斯坦福和UC伯克利的开源教学内容。

《Reinforcement Learning: An Introduction》

作者:Richard S. Sutton and Andrew G. Barto

image.png

这本书是强化学习最全面、最基础的教材,两位研究员强烈建议每一位同学通读一至两遍英文原版。

前面抖音推荐团队Leader William也非常推荐这本书,这本强化学习综述书, 可以帮助初学者建立相关知识体系。

英文原版:http://incompleteideas.net/bo...

相关课程:https://www.davidsilver.uk/te...

UC伯克利CS285:Deep Reinforcement Learning

主讲:Sergey Levine

这套课程包含23节课程和5个课后作业,适合对强化学习、机器学习有一定了解的人。

链接:http://rail.eecs.berkeley.edu...

斯坦福CS 330:Deep Multi-Task and Meta Learning

主讲:Chelsea Finn

CS 330整体课程比较长,大约需要3个月的学习时间,不过两位研究员更推荐课程中Meta-RL的部分,压力会小一点。

链接:https://cs330.stanford.edu/

image.png

机器翻译

机器翻译团队Leader王萱选择了经典的书目和课程。

《统计学习方法》

作者:李航

image.png

王萱认为,这本书由浅入深,涉及的知识面非常广,算法包括NB、LR、SVM、CART、GBDT、感知机、最大熵、EM、HMM、CRF等,书中例子、推导、算法介绍相对比较详细,适合花比较完整的时间,细细赏读。

另外,这本书还有一个优势是网上的解析、课程甚至所有算法的GitHub开源都非常完整,碰到难懂的问题,都可以很快找到答案。

前面抖音推荐团队Leader William同学也认为,这本书每个模型讲的很透彻,对提升机器学习背后的数学能力有帮助。

斯坦福CS 224N:Natural Language Processing with Deep Learning

主讲:Christopher Manning, John Hewitt

王萱说,斯坦福的自然语言处理课程非常棒,主要介绍深度学习相关知识,从 word2vec 开始,到机器翻译、Transformer、BERT 都有详细的介绍。所有的课程设置也非常合理,包括练习、代码、slides、相关文献官方都做了非常好的整理。

链接:http://web.stanford.edu/class...

image.png

知识图谱

字节跳动知识图谱算法工程师David推荐了两本知识图谱相关的中文书籍和一本英文书,斯坦福CS 520也是业界备受推崇的课程。

《知识图谱:概念与技术》

作者:肖仰华

image.png

这本书系统地介绍知识图谱概念、技术与实践,可以帮助读者建立知识图谱学科体系,贴近工业界的情况。

《知识图谱》

作者:赵军

image.png

知识图谱方面全面综述性的书籍,方方面面都有讲到,是不错的入门书。

《Linguistic Categorization》

作者:John R. Taylor

image.png

牛津语言学教科书,涵盖了1987年以来认知语言学的重大发展,也是相对基础的一本书。

斯坦福CS 520:Knowledge Graphs

主讲:Vinay K. Chaudhri, Naren Chittar, Michael Genesereth等

饱受好评的斯坦福CS系列,授课人是30余位来自学术界和工业界的专家,在国内也有相当多的簇拥。

链接:https://web.stanford.edu/clas...

image.png

安卓

在安卓开发Leader JackLin看来,安卓开发者官方网站是最适合初学者的地方,问答社区Stack Overflow中的安卓板块也是一个宝藏平台。

安卓开发者官方网站

image.png

JackLin说,谷歌的安卓官方网站是最为严谨的学习资料,适合绝大多数安卓开发学习者,可以解决安卓初学者的绝大多数问题。

链接:https://developer.android.com/

Stack Overflow 社区

image.png

Stack Overflow是程序员们基本都知道的社区,有很多高质量的问答和资料,社区很活跃,信息全面,也可以看到业界对前沿技术的讨论。

链接:https://stackoverflow.com/que...

image.png

iOS

iOS开发Leader赵子真同样推荐了业内知名的三大技术博客/社区。

技术博客NSHipster

image.png

NSHipster是iOS大神发起的技术博客,涵盖了OC、Swift、Cocoa那些被忽略的特性。

链接:https://nshipster.com/

技术社区raywenderlich

赵子真称raywenderlich为「iOS界的百科全书」,它适合初学者,各种tutorial非常浅显易懂。

网站:https://www.raywenderlich.com...

视频:https://www.youtube.com/user/...

iOS社区objc.io

image.png

这个社区的内容高质量、深入深入再深入,对国内很多iOS社区影响深远。

链接:https://www.objc.io/

image.png

前端

前端Leader月影推荐了不少在线课程。

HTML: The Living Standard

image.png

月影说,这份资料有助于大家理解HTML标准和语义化,打好前端基础。

链接:https://html.spec.whatwg.org/...

MDN Web文档

这份文档比较全面的介绍最新的 HTML/CSS/JavaScript 标准和特性,非常好的参考资料。

链接:https://developer.mozilla.org...

JavaScript高级程序设计(第4版)

作者:Matt Frisbie

image.png

几代前端人的JavaScript“红宝书”,李松峰老师翻译。

image.png


最后,在你擅长的领域,还有什么你觉得非常好的学习资源?欢迎在评论区留言,写下让你收获丰富的书籍/论文/开源项目/公开课或任何形式的资料。

查看原文

赞 15 收藏 8 评论 0

阿遂_Asui 赞了文章 · 2月6日

我是如何在 72 小时内复刻 ClubHouse 的

大家好,我是白宦成(@bestony),前几天在 B 站直播写 ClubHouse 复刻版的开发者。当然,除了这个身份,在真实生活中,我还是 Linux 中国开源社区的技术负责人,负责开发我们自己的自用工具和平台。

作为一个 indiehacker(自诩的),我想和大家一起来复盘一下,这一次的直播活动和意料之外的爆火。

为什么要做 NESHouse

我其实想到复刻 ClubHouse 的时间是非常早的,我是在 2 月 1 日拿到了 ClubHouse 的邀请码,在试玩了一段时间以后,就觉得这个软件还不错,理念很有意思,但并没有太在意,放在了一边。可到了晚上,因为知道 Elon Musk 要来做分享,作为一个比较欣赏他的人,我自然不能错过,但遗憾的是,当我打开 ClubHouse 的时候,已经有太多的人涌入这个 App,几乎无法使用,总是不停的卡顿。

这时让我产生了怀疑:这个东西到底有多少的工作量?为什么这么容易性能卡顿?

结合实际的使用发现,有些时候,我可以正常聊天,但是却会报错,可以发现问题不在语音服务,而是在 ClubHouse 自身的业务能力不足以支撑超过预期的访问量

我上一份工作是在一家云计算企业工作,所以相对来说,对云计算产品有一定的了解。在我看来,这样的一个产品的增量,很难把现有的云计算产品的服务容量打穿,你能想象 ClubHouse 把 AWS、GCP、Azure 等云服务厂商打穿么?

我觉得,要么是开发者的大规模服务的架构经验不足,虽然用了云,但是没设计好,无法充分适应弹性;要么是开发者没有对超过预判的访问量做的预案不足。

这就让我思考,我能否复刻一个 ClubHouse?用一些更加具有弹性的服务?给大家打个样? 云计算是好,但用起来也要姿势对,才能不出问题。

72 小时复刻一个 ClubHouse,是一个什么概念?

既然要复刻项目,自然要做的不能和碰瓷的一样(这里鄙视几家碰瓷的 App,拿很久之前写的具备了语音聊天的 App,来碰瓷 ClubHouse)。

但我又不希望在这个事情上花费太多的事情,我还有很多更重要的事情要做,所以我选择了 72 小时。48 小时或 24 小时是一般的 Hackthon 的时间长度,但我确实又不熟悉这个项目,所以用 72 小时比较稳妥。

于是便立了一个 Flag ,说我要在 72 小时内,复刻一个 ClubHouse。立了个 Flag,说干就干。关于这 72 小时,我希望可以强调两点,也希望这两点能够帮助到你。

1. 明确自己要做的和不要做的

我的时间和精力以及资源都有限,所以并不是什么东西我都能要的。比如在做复刻的时候,考虑到我如果开发原生的 App 或者小程序,就需要提交审核。那我就不能选择做 App,不然 72 小时到了,审核还没过,就食言了。也是出于审核的考虑,我最终选择了使用 Web 的方式来开发 NESHouse

而到了具体的功能特性层面,受限于 Web 和 App 的机制不同,我很难要求用户必须做什么样的操作,也很难确保 App 响应什么样的功能,因此,我对于 ClubHouse 的功能进行了一些删减,邀请上台之类的功能,我就选择性的先不做,将重点放在更加重要的功能中。

在开发黑客松项目的时候,一定要先想清楚自己要什么,不要什么,这样才能确保自己在给定的时间内完成自己的工作。不然大概率会发现时间马上要截止,但核心功能还没有研发完成。

2. 选择一些新的、以后可能会用到的技术

在这次项目开发的时候,我选择的前端技术栈并非我过去惯用的 React、Vue ,而是一个相对小众 JS 框架的 Alpine.js。

选择 Alpine.js 的原因很简单,我后续需要在其它的项目上使用这个框架,但我此刻确实也不熟悉。如果我在这 72 小时里把这个工具用了一遍,如果评估觉得不错,我就可以在后续的项目中使用,如果这次我用的不太好,那我损失的也只有 72 小时,比在正式项目中使用的损失成本要低很多

而在另外的两个服务,选择起来就简单多了:

  • LeanCloud 的云服务我使用了很多年,使用体验也很不错,而且他们这种 Serverless 云服务,可以让我在开发 NESHouse 的时候,免于去写很重的部署和基础逻辑,更加专注在业务逻辑上。
  • 音频服务我则选择了国内用户比较多,开发起来也比较方面的声网,声网的 API 比较简单, NESHouse 中的声网音频接入只用 4 行代码就实现了。

除此之外,便是使用了 NES.css 这样的 CSS 框架,来让这个项目更加的有趣,更加的 Funny。

对于开发黑客松项目的时候,可以想想自己能否接受这一次的失败,如果可以接受自己的失败,不妨将这次黑客松看做是一次玩的机会,玩一玩新的技术,就算失败了,也不过是损失给定的时间。但如果你在工作项目中出现了问题,损失可就大了。

总结

72 个小时的复刻对于我来说不算难,实际上我也只花了 55 个小时就复刻成功了。但更难的,是如何让一个开源项目持续的成长下去,持续的获得用户、获得关注。

最后,在思否发文章,给自己的项目求个 Star 不过分吧(

项目求 Star:https://github.com/bestony/ne...

查看原文

赞 14 收藏 0 评论 2

阿遂_Asui 赞了文章 · 2月6日

重磅发布丨2021年OpenAtom XuperChain 开源技术路径

image.png

本文为授权转载内容。以下文章来源于 XuperChain 开源社区 ,作者:XuperChain

2020 年,国家发改委公布了加强新型基础设施建设发展的顶层设计,区块链作为新技术基础设施首次被写入新基建发展规划之中。同时,美国将区块链技术列入国家安全技术清单,未来将对区块链核心技术形成卡脖子问题。

一方面,从数字货币单一场景到赋能产业,在多行业、多业务场景落地,对区块链网络建设底层技术提出了新的挑战;另一方面,我们需要加强自主创新,明确主攻方向,攻克关键核心技术,让国产区块链技术走在世界前列。

我们认为,2021 的区块链技术要实现“两个升级”。

  1. 符合中国国情、核心技术持续突破,更加「自主可控」。
  2. 源于产业、服务于产业、深入产业发展,更适合「产业区块链发展」。

当然,我们也面临以下挑战:

  1. 不同的落地场景对底层技术的需求是差异化、多样化的,需要可灵活扩展订制,多场景适用的区块链网络建设底层技术。如何做到广域场景适用,满足不同场景的个性化需求?
  2. 区块链系统复杂度高、网络建设维护成本高、业务集成难度高,区块链技术全面赋能产业,就需要打通这最后一公里。如何降低区块链技术落地应用门槛?
  3. 区块链技术支撑大规模应用,对系统扩展能力、性能提出了更高的需求。如何进一步突破区块链性能和扩展能力瓶颈?

针对这些挑战,开放原子可信账本工作组 XuperChain 项目,将从架构、易用性、性能提升、开源社区管理四个方面做全面升级,落地新一代自主创新核心技术,更好的支撑区块链技术全面赋能产业,推进数字经济建设。

01 更灵活扩展、更广域适用的架构

  • 可灵活扩展的动态架构

在 2021 年,XuperChain 内核技术 XuperCore 将独立发展,落地由多引擎架构和区块链内核组件编程规范两大核心设计构成的新一代动态内核技术。通过多引擎架构,让内核具备可多纬度、轻量级、无代码侵入订制扩展核心处理流程和做不同内核组件技术选型的能力;通过区块链内核组件编程规范,让内核各核心组件可以无代码侵入自由替换扩展,同时让引擎订制变得非常轻量级。首创实现区块链内核核心流程和内核核心组件皆可无代码侵入扩展订制,使内核具备极好的可扩展性,满足不同落地场景对于底链技术的个性化诉求。

  • 广域场景适用的底链技术

现有主流的区块链框架基本都有明确的适用场景定位,面向不同应用场景的链实现差异是比较大的,一套实现很难适用各种场景。在 2021 年我们将基于新一代的动态内核技术,轻量级定制切合场景的区块链发行版,从而做到广域创建适用,更好的赋能产业,推进区块链在各行各业落地。

02 更好的易用性,多纬度降低落地应用成本

  • 更丰富的生态工具,全面提升易用性

在生态工具方面,2021 年我们将持续补齐生态工具,全面提升 XuperChain 易用性。我们将在 H1 发布全新设计的开源文档,引入 EVM 虚拟机,支持以太坊生态工具链兼容,并发布 XuperChain 智能合约 IDE 和多语言 SDK 标准实现;在 H2 发布区块链浏览器,XuperChain 可视化工具和支持 Python 开发智能合约。从生态兼容、多语言支持、周边工具建设、文档优化多个方面,全面提升易用性。

  • 探索构建云原生链,打通落地应用屏障

全面赋能产业,必须要解决区块链系统复杂度高、网络建设维护成本高、业务集成难度高的难题。在 2021 年我们将结合云原生理念,探索设计云原生链,结合云原生工具和浏览器 admin,对用户屏蔽区块链系统自身的复杂性,做到全自助云上构建和管理区块链网络。

03 持续优化性能,进一步突破性能上限

实际业务落地中,存在数据规模大、性能要求高、业务形态复杂的问题,对数据规模、系统性能、组网形态有着更高的要求,但目前区块链在性能和数据规模上还存在瓶颈,难以横向扩展。在 2021 年我们将探索设计双层网络架构,支持在特定超高性能要求的场景下采用分布式子网来替代单机节点,来进一步突破 XuperChain 性能上限。

04 更温暖、开放的社区,与开发者共同发展、成长

今年已经有 100 多位开发者在社区积极交流、提问,在 github 参与代码、文档等贡献,大力推动了 XuperChain 开源社区发展。即使在疫情下,社区依然高频举办 20 多次线上活动,观看人数超过 10 万,生产 100 多篇开发者文档内容,包括技术开发、应用实践等。

2021 年,我们会继续保持高频的技术沙龙活动,从实践实操、项目案例的角度,持续分享开发经验,更好地帮助开发者项目落地。我们也将推出一系列激励扶持与共同发展计划,例如针对企业的商机共享、品牌传播、官方技术方案指导等;针对个人开发者的培训认证、技术社区荣誉、奖品奖金等,来更好推动社区发展。

同时,我们会建设更完备的社区管理机制,为开源社区推荐贡献方向、迭代流程等,帮助开发者更好的参与社区贡献,让更多优秀的项目回流到开源社区。

立足当下、布局未来。未来,XuperChain 也将不断钻研创新,攻克区块链核心技术方向;不断加大开源力度,让区块链开发者、企业零成本使用更高性能、更易用的区块链技术;不断加大开源社区建设,构建更温暖、更开放的社区,与广大开发者共建区块链开源生态。

segmentfault 思否

查看原文

赞 10 收藏 0 评论 0

阿遂_Asui 发布了文章 · 2月6日

“知情同意、最小必要”,工信部将用 22 条规定保护个人信息

据悉,工信部将推出《移动互联网应用程序个人信息保护管理暂行规定》(以下简称“规定”),共计 22 条。

规定以知情同意和最小必要两项个人信息保护的基本原则为纲,要求,从事 App 个人信息处理活动,应当以清晰易懂的语言告知用户个人信息处理规则,由用户在充分支持的前提下做出自愿、明确的意思表示;最小必要规定,从事 App 个人信息处理活动,应当具有明确合理的控制,并遵循最小必要的原则,不得从事超出用户同意范围或者与服务场景无关的个人信息处理活动。


移动互联网应用程序(App)得到广泛应用,但 App 强制授权、过度索权、超范围收集个人信息等现象大量存在,违法违规使用个人信息的问题十分突出。

此次推出的规定以 App 开发运营者、App 分发平台、App 第三方服务提供者、移动终端电信设备生产者和网络技术服务提供者作为重点监管服务的对象,规定了五类主体应当遵循的个人信息保护总体要求和应承担的义务。

相关主体如果违反规定,将依次按照通知整改,公开通报,下架处置,断开接入流程进行处置。未按要求完成整改或反复出现问题,采取技术对抗等违规情节严重的,除直接下架和断开接入以外,还将建议 App 分发平台和终端电信设备生产者在集成、分发、预置和安装等环节进行风险提示。

对于这一规定的出台,西南政法大学政治与公共管理学院副教授和静钧 此前在媒体采访中曾提出如下观点:

移动互联网应用程序(App)使用合约,是在数字通讯条件下双方信息高度不对称、技术能力高度不对等的基础上缔结的格式契约,虽有契约之名,双方并无实质协商,是典型的“霸王条款”,App 方拥有支配地位,存在超范围收集、窥探他人个人信息的诱因和动机。由于公民个人信息安全是国家安全的重要组成部分,移动互联网数据是网络空间时代的重要地缘战略资源,App 方任意侵犯他人个人信息权的行为,不仅仅只是私法范围内的合同权利义务之争,还是关系着公共安全的大是大非问题,需要公权力即工信部介入,才能解决好 App “霸王条款”存在的问题。

在《民法典》、《消费者权益保护法》、《网络安全法》中,均规定了个人信息保护制度,但并没有有效的防止对个人信息的侵害,此次规定的推出,相当于是对此前制度的进一步细化,将增强制度的落地性与可操作性。

而「知情同意、最小必要」作为基本原则,将督促 App 方使用权利的时候明确义务,有助于帮助建立更为规范的行业准则以及行业契约精神,

*部分资料与观点来源于网络


相关阅读:《2020 中国移动应用生态及开发者现状调研报告》(附下载)| 思否观察

segmentfault 思否

查看原文

赞 0 收藏 0 评论 0

阿遂_Asui 赞了文章 · 2月6日

《2020 中国移动应用生态及开发者现状调研报告》(附下载)| 思否观察

image.png

移动互联网已经成为信息产业中发展最快、竞争最激烈、创新最活跃的领域之一。在新一轮的信息产业发展中,设备制造、网络运营、终端研发能力不断增强,系统、芯片、软件等基础支撑能力明显提升,新产品和新技术层出不穷。同时,移动互联网技术的融合发展趋势日趋明朗,其影响正迅速地向经济、社会、文化的各领域进行广泛的渗透扩散,新的移动互联网产业生态系统正在建立,并蔚然成形。

移动应用作为移动互联网的主要承载形式之一,一般以智能移动设备的软件形式呈现,随着移动互联网的发展,现阶段的移动应用已经从单纯的技术创新进化到应用生态的价值挖掘。移动应用开发者作为移动应用的建设者,自然成了当下移动应用生态发展中的关键点,也正面临着新一轮的变化、难题和挑战。

在此背景下,SegmentFault 思否推出了《变化、难题、趋势丨2020 中国移动应用生态及开发者现状调研报告》

该份报告整合了 SegmentFault 思否以及行业相关研究机构对移动应用生态的最新研究资料,对移动应用生态的现状进行了概括和总结,并从移动应用的用户、开发者以及移动应用平台等角度对整个产业进行了剖析,对移动应用生态未来的发展趋势进行了预判。

一、报告核心摘要

1、随着移动应用领域的迅速发展及针对应用开发的服务不断丰富,开发经验与技能以及配套开发工具也不再是移动应用开发者面临的首要问题。在现阶段的企业技术岗位分工中,移动应用开发通常是以项目经理或技术负责人主导,前、后端开发者配合的小团队模式进行业务侧的技术实现,因此要求参与移动应用开发者必须具备至少 1-2 年的实际开发经验。

image.png

2、重复造轮子对应用本身存在一定的促进作用,但如果无法实现对创新的鼓励,也就越来越难以有优秀的应用产品出现。如何在同质竞争中建设差异化优势是开发者的核心任务,也是在内卷化周期保持产业活力的基础。人工智能、5G 等新技术与移动应用的耦合,或将进一步拓宽移动应用的领域,从而为用户提供更多应用选择,或者让用户在固有移动应用领域体验提升。

image.png

3、云计算技术正在与传统的 IT 业务进行快速融合,这对移动应用开发者而言,既是机会也是挑战。企业上云与数字化转型看似降低了应用开发的技术门槛,但其实也提高了对于开发效率与质量的整体行业标准,对应用开发者的技术能力以及行业认知提出了更高的要求。

4、开源工具在移动开发行业中将越来越主流,开源也将成为更为优越的开发模式。在如今的中国环境下,包括开源开发在内的企业数字化的基础建设是一个很大的需求点,而开源开发工具或正在逐渐成为移动应用开发者主流选择。

5、因为平台、技术、工具的多样性,场景不同、设备不同,移动应用间共存和共享能力的需求变得越来越旺盛,对于移动应用开发者而言,多端一致性的发展趋势,将使之前割裂的开发实践趋于统一。但多端一致性在技术投入上几乎是无底洞,底层的平台架构差异根深蒂固,以各类跨端方案目前的成熟度仅能覆盖极其有限的一部分,但这正是现阶段移动应用开发者必须面临的变化之一。

6、随着移动应用开发技术的发展,未来的移动应用将会呈现更加多样的形态、采用更全面的分发方式,如小程序、快应用等,借助平台的流量为应用产品带来更高的触达率。但现阶段小程序多数还只能承载一些相对浅层和简单的服务,对于需要进行大量交互、沉浸式体验的业务产品而言,App 类移动应用仍是最重要的形态。

image.png

7、国家政策的调整以及新冠疫情事件的发生,使得移动应用的出海全球化之路遇到了前所未有的挑战。另一方面,随着海外的流量红利逐渐消失,产品本地化、本地合规及本地推广三大出海难题也于近几年内愈发明显。但凭借我国厂商近年来在移动应用领域的发展与探索,很多品类的移动应用在全球市场范围内仍具备着良好的竞争力与可能性,国内的各类应用市场也正在逐渐增强对移动应用开发者的出海支持。

image.png

二、专家观点分享

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png

image.png


特别鸣谢:

感谢以下专家对本次调研的支持(按姓氏拼音首字母排序)

韩知白(探探副总裁)

陆俊峰(网易云音乐大前端技术总监)

林顺(Cocos CTO)

祁宁(SegmentFault 思否联合创始人&CTO)

钱荣明(悦跑圈 CTO)

王亮(金融行业开发工程师)

小元(资深出海应用开发者)

张海云(滴滴出行客户端负责人/高级技术专家)

张向东(国内 SaaS 云安全服务平台技术负责人)

张宇鹏(陌陌资深架构师)

周大鑫(学而思网校移动研发部负责人)


数字、移动和社交媒体都已经在世界范围内渗透、融入人们的生活,成为不可或缺的一部分。在这样庞大的基数支撑下,移动应用市场在未来定然存在更大的探索、挖掘、发展的潜力和空间。而移动应用开发者,必将承担更大的责任、背负更多的使命。

更多详细内容,请点击下方链接或扫描下方二维码下载完整版《变化、难题、趋势丨2020 中国移动应用生态及开发者现状调研报告》

点我获得完整报告:传送门

↓扫描下方二维码获取完整报告↓

联图二维码.png
查看原文

赞 5 收藏 0 评论 0

认证与成就

  • 认证信息 SegmentFault 编辑
  • 获得 2637 次点赞
  • 获得 23 枚徽章 获得 0 枚金徽章, 获得 2 枚银徽章, 获得 21 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • 「SFIDSP - 思否独立开发者支持计划」

    为助力独立开发者营造更好的行业环境, SegmentFault 思否社区作为服务于开发者的技术社区,正式推出「思否独立开发者支持计划」,我们希望借助社区的资源为独立开发者提供相应的个人品牌、独立项目的曝光推介。

  • 「SFOSSP - 思否开源项目支持计划」

    为助力优质开源项目成长, SegmentFault 思否社区作为服务于开发者的技术社区,正式推出「SFOSSP - 思否开源项目支持计划」,我们希望借助社区的资源对开源项目进行相关的宣传推广,并作为一个长期项目助力开源事业的发展,与广大开发者共建开源新生态。

  • 「SFKP • 计算机百科」

    《SFKP • 计算机百科》是 SegmentFault 思否编辑部策划的专题内容,面向在 21 世纪冲浪的每一位网友,进行计算机相关知识点的科普与开放讨论。

注册于 2019-07-21
个人主页被 160.6k 人浏览