案例分析作业
项目 | 内容 |
---|---|
本作业所属课程 | 2020春季软件工程(罗杰 任健) |
本作业要求 | 案例分析作业 |
我的课程目标 | 具备一个软件工程师所需要的素质 |
本作业帮助 | 借助现有软件,锻炼软件分析能力 |
Visual Studio、VS Code 与 云端Codes
Visual Studio
Visual Studio
作为微软旗下的重量级IDE,江湖上有“宇宙第一IDE”的称号,虽然最近被JetBrains全家桶抢去了些许风头,但是我认为其作为IDE,提供了其它IDE无法媲美的体验。
比如使用winForms框架时,可以直接进行可视化编程,通过拖拽控件快速搭建一个页面,可见即所得。我之前只是知道有这样的功能,今天是第一次尝试,我的UI开发经验也很少,在没有看文档的情况下,10min左右就能摸索着构建一个能看的页面了:
简单通过MSDN文档学习后,利用事件机制,就能写出具有一定交互能力的程序了。
为了实现点击按钮,将文本框内的文字添加到左侧,然后将纯数字再挑选到左下的文本框内,我只需要编写这样的一个源文件:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinFormsTest2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool IsNumber(string str)
{
foreach (char c in str)
{
if (!char.IsDigit(c))
{
return false;
}
}
return true;
}
private List<int> GetNumbers()
{
var rlt = from integer in
(
from str in this.listBox1.Items.Cast<string>()
where IsNumber(str)
select int.Parse(str)
)
where !this.listBox2.Items.Contains(integer)
select integer;
return new List<int>(rlt);
}
private async void button1_Click(object sender, EventArgs e)
{
string content = this.inputBox.Text;
if (!string.IsNullOrEmpty(content) && !string.IsNullOrWhiteSpace(content))
{
this.listBox1.Items.Add(content);
this.inputBox.Text = string.Empty;
var rlt = await Task.Run(GetNumbers);
foreach (int num in rlt)
{
this.listBox2.Items.Add(num);
}
}
}
}
}
这是一个分部类,通过查看IDE生成的代码,我们可以发现该类的另一部分代码IDE帮助我们进行了生成。
注意看左侧行号,24行直接跳到了112行,其中是被折叠的自动生成的代码,展开后如下:
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.inputBox = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.listBox1 = new System.Windows.Forms.ListBox();
this.label2 = new System.Windows.Forms.Label();
this.listBox2 = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// inputBox
//
this.inputBox.Location = new System.Drawing.Point(219, 12);
this.inputBox.Name = "inputBox";
this.inputBox.Size = new System.Drawing.Size(141, 27);
this.inputBox.TabIndex = 0;
//
// button1
//
this.button1.Location = new System.Drawing.Point(219, 57);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(94, 29);
this.button1.TabIndex = 1;
this.button1.Text = "添加";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(29, 12);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(54, 20);
this.label1.TabIndex = 3;
this.label1.Text = "已添加";
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.ItemHeight = 20;
this.listBox1.Location = new System.Drawing.Point(29, 45);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(150, 104);
this.listBox1.TabIndex = 4;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(29, 164);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(114, 20);
this.label2.TabIndex = 5;
this.label2.Text = "其中纯数字有:";
//
// listBox2
//
this.listBox2.FormattingEnabled = true;
this.listBox2.ItemHeight = 20;
this.listBox2.Location = new System.Drawing.Point(29, 196);
this.listBox2.Name = "listBox2";
this.listBox2.Size = new System.Drawing.Size(150, 104);
this.listBox2.TabIndex = 6;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.listBox2);
this.Controls.Add(this.label2);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
this.Controls.Add(this.inputBox);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
之所以VisualStudio能够实现这样的功能,离不开语言的辅助。C#还提供了分部的功能,即同一个类、同一个函数,可以在不同的文件里实现,这就将IDE生成的代码和开发者编写的代码进行了分离,开发者只需要操作IDE提供的可视化界面,就可以方便地绘制用户界面,而不用在乎IDE生成的代码。此外C#提供了delegate
和event
机制,开发者只需要查看用来写各种响应时间的回调函数的文件,编写响应事件的回调函数,就可以实现交互。Visual Studio
与.NET
开发语言的配合,为开发者带来了不一样的开发体验,这是很多IDE、语言所无法匹敌的。
除了简单的代码提示外,VisualStudio还会根据上下文将更可能使用到的方法/属性提前:
还可以快速查看调用层次结构:
不需要额外插件即可实现性能分析:
此外还有很多很多很多利于开发的实用功能。
虽然在代码编辑上,VisualStudio相比JetBrain全家桶差点意思(比如缺少auto-import、输入一个变量时如果不是从头输入不会有补全提示、AutoGeneration等),甚至有时候不如VSCode,但是它确确实实提供了实用的、可视化的、代码编辑外的开发功能,这一点上,不输任何IDE。
Visual Studio Code
在Code - OSS中有如下描述:
This repository ("Code - OSS") is where we (Microsoft) develop the Visual Studio Code product together with the community. Not only do we work on code and issues here, we also publish our roadmap, monthly iteration plans, and our endgame plans. This source code is available to everyone under the standard MIT license.
可见,VSCode是由微软对开源软件Code - OSS
的构建,而Code - OSS
本身是开源的,是微软主导的、主要用TypeScript
语言开发的开源跨平台轻量级IDE。VSCode只内置了对JavaScript
、markdown
等少量语言的简单支持,绝大部分功能都依赖于插件,实际工作的编译器、解释器、调试器等皆依赖于外部的配置或者命令行接口。
事实上,作为VSCode重度用户,我可以负责地说,配置了复杂的工作负载的VSCode一点也不轻量,虽然本地并不大,但是当工作负载都加载上以后,其启动速度、资源占用丝毫不亚于重量级IDE。
VSCode近年来更新的最重要的功能就是对远程开发的支持。添加了远程开发的相关插件后,点击左下角状态栏即可通过SSH连接到服务器,在服务器环境中进行开发。
这里我在我的服务器上clone了结对编程的项目并执行了测试:
这样,我们就可以在性能较低的机器上使用性能较高的机器进行开发,或者本地不需要再配置复杂的依赖,可以直接使用服务器中的环境进行开发。这对于机器学习、复杂的软件工程,是十分方便的功能。此外,对于同时开发多个项目的团队,不需要在本地机配置环境是很大的优点,因为同时开发多个项目时,不同项目需求不同的环境,如果在同一台机器上,可能互相影响。
相比于IDE,VSCode更像是一个代码编辑器,VSCode可以在任何文件夹右键打开,相比于其它也可以右键从文件夹打开IDE,VSCode的特点是这样打开不会创建任何文件,而其他IDE往往是把当前文件夹作为一个项目的文件夹打开,需要创建.idea
、.vs
这类文件夹来保存项目信息,而VSCode直到进行debug、运行前,是不会创建配置文件的。
作为代码编辑器,VSCode可以在同一个文件夹下编写Python、Java、BAT、Shell,并且能针对性地进行增强辅助,这对于我这种喜欢写各种脚本的人来说,是在是一种福音。我一般会用VisualStudio、IDEA等重型IDE来编写主程序和单元测试,但是会同时在该文件夹下打开VSCode来写文档、写一些辅助性脚本。
此外,VSCode内置的diff功能也很好用,是我对比黑箱测试结果最喜欢使用的功能。具体使用上,先右键一个文件,点击“选择以进行比较”,再右键另一个文件,点击“与已选项目进行比较”,就可以获得两个文件的diff了:
总的来说,VSCode提供了良好简洁的代码编辑辅助,帮助开发者在不同平台、使用本地或远程资源进行舒适的代码编辑,但是缺少很多代码编辑外的功能,比如代码量统计、代码质量分析等。丰富的插件库带来丰富的功能,但同时由于插件良莠不齐,有些插件甚至可以凭一己之力拖垮整个系统。
云端Codes
Code - OSS作为一个开源的、使用脚本TypeScript
开发的轻量级IDE,人们自然会试图将其搬到浏览器中。
CodeServer是一个由开源社区维护的Web项目,将其部署到服务器后,通过文档推荐的几种方式,将其暴露到互联网后,就可以在任何地方使用浏览器打开一个“VSCode”。以下是我在我的ipad上通过Safari浏览器,访问我的服务器的效果(就是前面VSCode远程连接的那台):
连接了键鼠后,在ipad这个本没有开发功的设备上也能拥有不逊色于桌面机的开发体验。
Visual Studio Online
(后改名为Visual Studio Codespace
)和Github Codespace
本是两个不同的服务,前者属于微软Azure
的一部分,后者是Github
的一部分,但是去年9月份微软宣布将前者合并至后者(详见Visual Studio Codespaces is consolidating into GitHub Codespaces)。目前仍处于beta测试阶段,我没有排上队,就不再赘述其体验。查看文档可以看到其价格:
性能看起来不错,价格按时间收费,实际算下来可能并不算很贵。
这些云端IDE使得开发时使用的机器的性能要求相比VSCode进一步降低,无论性能多差劲、无论开发环境多缺乏,只需要有浏览器就可以进行开发,在平板电脑,甚至是手机上。另一方面,仅需求浏览器,对于刚接触编程的小白来说,如果有“师傅”(既可以是人,也可以是网络教程的提供者)帮忙处理云端环境,那么免去了配置环境的步骤,小白能够更快地入门。
但是目前这些云端IDE都存在一些问题,一方面是网络问题,IDE这样庞大的软件放到浏览器中,每次打开都要加载大量的资源,时不时会加载失败,另一方面是插件的支持问题,CodeServer
中的Code - OSS版本比较落后,很多插件不能使用最近的版本,甚至很多插件无法直接安装,必须手动到插件商店下载vsix文件后进行本地安装。
功能性bug
bug等级
等级 | 描述 |
---|---|
3 | 严重错误,可能造成系统从可用状态进入不可用状态 |
2 | 中等错误,较稳定发生,造成部分功能缺失,严重影响用户体验 |
1 | 轻微错误,偶尔发生,对用户体验有较轻影响 |
0 | 界面错误,用户界面展现内容与系统内部实际状态不一致 |
1. VSCode SSH连接远程服务器时,服务器公钥与known_host中不一致时未报告有效信息
- 本地机操作系统:Windows 10 家庭中文版 (版本号:2004;内部版本:19041.867)
- 远程机操作系统:Ubuntu 20.04.2 LTS
- VSCode版本:1.55.0(user setup)
- 插件版本:Remote-SSH:0.65.1;Remote-Development:0.20.0
- 发生频率:稳定
- 错误等级:0
复现步骤:
- 成功连接一次远程机;
- 远程机重装操作系统(或者远程机重新生成公钥,或者本地机/.ssh/known_host文件中将远程机对应的公钥进行任意更改,只要使得/.ssh/known_host文件中远程机的公钥与远程机实际的公钥不同即可);
- 再尝试连接远程机,
Remote - SSH: Connect to Host
,然后选择远程机后,不执行任何其它操作(事实上这个时候有很短暂的时间可以在上方的小弹窗中选择Continue);
此时将出现没有有效信息的错误报告:
我为了获得更多信息,提前打开输出
窗口并刻意将其提前放大,但是仍旧没有提示本地存储的公钥与远程机的公钥不一致。
该错误使得远程机更改了公钥后,曾经可以连接的本地机无法连接,并且没有准确的错误信息,难以排查问题所在。
可能的原因是VSCode使用SSH工具连接远程机,但是SSH工具本身没有更精确的错误信息,导致VSCode无法向用户报告准确的信息。
2. 在ipad中以PWA形式打开CodeServer后,使用外接键盘时界面遮挡问题
- 客户端操作系统:ipadOS 14.4.2 on iPad Pro 2020
- 服务器操作系统:Ubuntu 20.04.2 LTS
- CodeServer版本:3.9.2
- 键盘型号:logitech K380
- 发生频率:稳定
- 错误等级:2
复现步骤:
按照文档推荐的方法将CodeServer添加到桌面,然后从桌面打开,若此时通过蓝牙连接键盘,则界面下方会出现键盘的导航栏,该导航栏将遮挡CodeServer最底部的状态栏。
而直接从Safari浏览器打开则不会发生遮挡:
可能原因是ipadOS对键盘+PWA支持不够完善,CodeServer作为浏览器应用,没有权限监控键盘情况并作出反应,只能依靠ipadOS进行控制。
分析
使用此服务的所有功能,估计这个软件/网站/服务做到这个程度大约需要多少时间(团队人数6人左右,计算机大学毕业生,并有专业UI支持)。
对于VisualStudio和VSCode,我不认为这是6人团队可以完成的项目。
从可以看到工程量的Code - OSS来看,最近一周(2021/3/31-2021/4/7)一共有38位开发者向主分支提交了270个commit,修改了388个文件,增加了8637行代码。
将其clone到本地,利用cloc统计得到如下结果:
4898 text files.
4663 unique files.
2065 files ignored.
4 errors:
Line count, exceeded timeout: ./build/lib/i18n.js
Line count, exceeded timeout: ./build/lib/i18n.ts
Line count, exceeded timeout: ./extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts
Line count, exceeded timeout: ./src/vs/workbench/test/electron-browser/api/extHostSearch.test.ts
github.com/AlDanial/cloc v 1.86 T=25.76 s (173.2 files/s, 52317.2 lines/s)
--------------------------------------------------------------------------------
Language files blank comment code
--------------------------------------------------------------------------------
TypeScript 3222 135817 85011 689044
JSON 551 105 0 356545
JavaScript 222 2500 5051 42261
CSS 178 3012 1239 13770
HTML 36 209 47 4327
YAML 45 377 75 2812
Markdown 53 518 0 1019
Bourne Shell 30 162 104 635
SVG 44 10 1 394
XML 11 0 1 350
Sass 1 38 5 297
DOS Batch 9 76 0 185
PowerShell 7 27 18 165
Bourne Again Shell 5 24 46 116
CUDA 1 36 0 113
Groovy 1 65 48 106
C++ 6 10 6 73
Python 2 17 16 68
make 1 20 7 61
Perl 2 13 9 55
Handlebars 2 7 1 46
LESS 3 11 1 43
PHP 3 10 5 43
Clojure 1 6 8 38
Objective C++ 1 10 9 33
CoffeeScript 2 11 0 32
Razor 1 8 6 32
Rust 2 10 0 31
C 1 1 2 27
Ruby 1 6 14 26
HLSL 2 3 0 25
JSX 1 6 5 24
Java 1 8 11 23
Julia 1 2 1 23
Pug 2 3 5 22
Go 2 4 1 21
C# 1 0 1 16
Visual Basic 1 3 6 16
Swift 1 0 0 13
F# 1 4 3 11
R 1 4 9 11
Dockerfile 1 3 1 10
Lua 1 1 1 10
INI 1 1 2 7
SQL 1 0 0 6
diff 1 0 2 5
--------------------------------------------------------------------------------
SUM: 4463 143158 91778 1112990
--------------------------------------------------------------------------------
这显然不是中小团队可以完成的工作量。
不过以Code - OSS为基础,开发一个CodeServer
是可以考虑一下的。
首先要分析和理解Code - OSS的工作方式;然后先将主体功能移植到Web中,此时可能只是一个比较好看的文本编辑器;再之后移植内置的插件,如对git、json、markdown、html等的支持;再之后移植对外部插件的支持。由于是移植工作,并且开源仓库中有现成的测试,所以测试的压力、需求分析、架构设计等步骤,相对于开发一个全新的软件要小得多。但是毕竟项目规模很大,我预计可以在1年左右完成。
分析这个软件目前的优劣(和类似软件相比),这个产品的质量在同类产品中估计名列第几?
- 对Visual Studio,我只使用过社区版本,已经可以提供代码提示、版本管理、数据库管理、可视化编辑、代码质量分析、调用层次分析、与Unity协同开发调试等功能。对比同样是重型IDE的JetBrains,VisualStudio在辅助代码生成、代码提示方面略有劣势,并且很多功能与微软高度绑定,不方便使用其它组件,而且几乎只能在Windows系统上使用,Mac上的VS缺失很多功能;但是VisualStudio能够在同一个IDE中编辑跨语言项目,并且提供了更多的工程辅助,如模板、自动代码生成等方面更胜一筹,而且VisualStudio与微软的开发语言、服务(SQLServer、github、Azure等)有无与伦比的配合,提供独特的编码体验。对抗JetBrains全家桶可能各有优劣,但是与各个IDE单打独斗,VS绝对对得起“宇宙第一IDE”的称号。
- 对于Visual Studio Code,和VS与微软高度绑定不同,VSCode则更依赖于开源社区,虽然VSCode面世仅有6年,但是依靠丰富的插件,通过使用命令行接口,成为了几乎所有语言都能胜任的IDE,并且由于其技术选型,使得其具有很好的移植性。伴随着其优点,庞杂的插件市场导致插件质量良莠不齐,为了跨平台能力牺牲了运行效率,当VSCode高负载运行时,性能堪忧,部分过大的文件在VSCode中甚至无法顺利打开并进行代码高亮显示。但是,VSCode在推出的短短几年内就迅速抢占了大量原本属于
notepad++
等软件的市场,在CCF-CSP认证中,甚至取代了dev c++等传统专用IDE成为了官方唯一指定的IDE,就目前而言,VSCode在轻量级IDE中是王者的存在。 - 对于云端Codes产品,这是由于Code - OSS的诞生,让大家看到了云端IDE的希望,过去的各种Git平台虽然也提供在线编辑功能,但是与现代开发者使用的IDE相比,代码高亮效果、代码补全提示都差得多,更别提各种快捷功能、调试运行。Codes云端产品可能会开创一个新的领域,只需要在服务器上配置好环境,或者写好配置清单,开发者就可以在anytime、anywhere、anydevice进行开发。
建议和规划
以下基于CodeServer
进行分析:
市场概况
主要面向的人群:
- 移动设备性能不足,但同时有移动开发的需求的开发者;
- 高校、培训等计算机相关教育行业;
- 需要在服务器中进行远程开发;
- 开源社区;
市场现状
Github Codespace已经进入beta测试阶段,Codespace原生与Github绑定,对于开源社区具有无与伦比的吸引力。但是一方面,其收费策略是计时收费,另一方面服务器都是云服务器,Web支持如此庞大的应用需要消耗极大的带宽,对于有大量人员需要使用其功能的、有条件在局域网内搭建服务提的企业、学校,并不是很好的选择。
而CodeServer
虽然可以部署到私有服务器,但是目前几乎只适合个人使用,因为多设备同时连接时,共享相同的工作空间,没有用户的区分,只有一个密码作为权限验证机制。
市场与产品生态
这个产品的主要用户群有四类:
- 项目经理/架构师
- 使用场景:搭建配置环境,管理员工权限。
- 核心诉求:稳定、安全。
- 熟练的开发人员
- 使用场景:大量利用IDE的代码辅助功能,大量代码输入。
- 核心诉求:流畅,顺手,辅助功能丰富。
- 计算机专业教师/课程组
- 使用场景:搭建配置环境,管理学生权限。
- 核心诉求:稳定。
- 初入茅庐的学生
- 使用场景:学习编码,会进行各种错误的尝试。
- 核心诉求:稳定,简洁,易上手。
产品规划
基于前文的分析,CodeServer
作为可以部署到自建服务器上的IDE服务,若想获得企业、机构的认可,需要能够有用户管理功能:为CodeServer
添加用户管理机制,使得不同用户具有独立的工作空间,具有不同的权限。
本功能的实现需要分为两部分,一部分是管理者对用户的管理,一部分是使用时用户的隔离。前者需要新的界面来进行配置,后者需要开发沙盒运行环境。由于有新的页面引入,所以需要美工的工作,但同时本功能比较难以实现,所以最好能够先进行技术试验,用户部分需要保证安全性,所以充分的测试是必不可少的,我认为需要1名开发人员负责美工和管理页面的实现,2名开发人员负责测试,其余负责主要开发,测试人员在试验性开发时可以也参与试验。
开发计划如下:
周次 | 任务 |
---|---|
1 | 美工设计后台管理、用户登录界面,同时其余人试验性开发基础的用户隔离功能,不考虑扩展的情况下,不同用户能够在相互隔离的环境编辑文件 |
2 | 总结试验性开发中存在的问题,总结经验,学习补充缺少的技术栈,设计维护性高的结构 |
3 | 正式开发,后台管理、没有插件情况下的用户隔离两部分分开开发,开始搭建测试环境 |
4 | 完善用户从登录到使用的环节,引入用户的权限管理 |
5 | 引入对插件的支持 |
6 | 将后台管理与用户使用部分合并,进行基础功能的联协测试 |
7 | 发布alpha版本,邀请内测用户进行测试,收集用户反馈 |
8 | 结束alpha版本测试,总结用户反馈,修复内测中的bug |
9 | 根据用户反馈进行功能增改 |
10 | 开展运行分析,进行优化,提高流畅度 |
11 | 进行压力测试 |
12 | 发布beta版本,邀请更多内测用户进行测试,收集用户反馈 |
13 | 结束beta版本测试,总结用户反馈,修复内测中的bug |
14 | 根据用户反馈进行进一步功能修改 |
16 | 回顾测试并进行发布 |