* update

* Update 11.a 系统设计.md

* update

* update

* Update 3.3 解决问题的能力.md

* Update 11.a 系统设计.md

* update

* Update 7.6 需求技术分析.md

* update

* update

* Update 12.1 软件概要设计说明书.md

* update

* Update 常用的软件架构模式.md

* update

* update

* update

* Update 12.2 星形系统架构模式.md

* update

* update

* update

* Update 12.5 环形系统架构模式.md

* update

* update

* update

* Update 12.1 架构进化的故事.md

* Update 12.1 架构进化的故事.md

* update

* update

* update

* update

* update

* update

* Update 12.1 架构演化的故事.md

* Update 12.2 与架构相关的概念.md

* update
This commit is contained in:
xiaowuhu 2023-02-13 12:27:15 +08:00 коммит произвёл GitHub
Родитель cf9022dcfc
Коммит 5c2e74baf7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
157 изменённых файлов: 1799 добавлений и 358 удалений

Двоичные данные
ch03.npz Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -305,14 +305,14 @@ $Z1,Z2,Z3$ 分别代表三层神经网络的计算结果。最后可以看到,
### 参考资料
\[1\]: 参见: David Deutsch, 2012: Creative blocks --- the very laws of physics imply that artificial intelligence must be possible. What's holding us up? Aeon (online magazine). Available from: https://aeon.co/essays/how-close-are-we-to-creating-artificial-intelligence.
[1]: 参见: David Deutsch, 2012: Creative blocks --- the very laws of physics imply that artificial intelligence must be possible. What's holding us up? Aeon (online magazine). Available from: https://aeon.co/essays/how-close-are-we-to-creating-artificial-intelligence.
\[2\]: 定义翻译自Mitchell, Tom (1997). Machine Learning. McGraw Hill
[2]: 定义翻译自Mitchell, Tom (1997). Machine Learning. McGraw Hill
\[3\]: 定义参考了周志华的《机器学习》清华大学出版社 2016 ISBN 978-7-302-42328-7
[3]: 定义参考了周志华的《机器学习》清华大学出版社 2016 ISBN 978-7-302-42328-7
\[4\]: 智能基础建设,智能增强,模拟人类的智能的分析来自于 Michael I. Jordan 的论述,参见: 网页。
[4]: 智能基础建设,智能增强,模拟人类的智能的分析来自于 Michael I. Jordan 的论述,参见: 网页。
\[5\]: 参见The Fourth Paradigm: Data-Intensive Scientific Discovery作者Tony Hey, Stewart Tansley, Kristin Tolle, Published by Microsoft Research, October 2009, ISBN: 978-0-9825442-0-4
[5]: 参见The Fourth Paradigm: Data-Intensive Scientific Discovery作者Tony Hey, Stewart Tansley, Kristin Tolle, Published by Microsoft Research, October 2009, ISBN: 978-0-9825442-0-4
\[6\]: 这个问题由经典的“羊车门”问题简化而来
[6]: 这个问题由经典的“羊车门”问题简化而来

Просмотреть файл

@ -134,7 +134,7 @@ $$
|观察角度1|观察角度2|
|--|--|
|<img src="..\Images\2\gd_double_variable.png">|<img src="..\Images\2\gd_double_variable2.png">|
|<img src="./img/2/gd_double_variable.png">|<img src="./img/2/gd_double_variable2.png">|
### 2.3.5 学习率η的选择

Просмотреть файл

@ -15,8 +15,7 @@ def derivative_function(theta):
return np.array([2*x,2*np.sin(y)*np.cos(y)])
def show_3d_surface(x, y, z):
fig = plt.figure()
ax = Axes3D(fig)
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
u = np.linspace(-3, 3, 100)
v = np.linspace(-3, 3, 100)
@ -27,7 +26,7 @@ def show_3d_surface(x, y, z):
R[i, j] = X[i, j]**2 + np.sin(Y[i, j])**2
ax.plot_surface(X, Y, R, cmap='rainbow')
plt.plot(x,y,z,c='black')
plt.plot(x,y,z, linewidth=2, color='black')
plt.show()
if __name__ == '__main__':

Просмотреть файл

@ -7,7 +7,7 @@ import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import LogNorm
file_name = "../../data/ch03.npz"
file_name = "ch03.npz"
def TargetFunction(x,w,b):
y = w*x + b
@ -125,8 +125,7 @@ def show_all_4b(x,y,n,w,b):
def show_3d_surface(x,y,m,w,b):
fig = plt.figure()
ax = Axes3D(fig)
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
X = x.reshape(m,1)
Y = y.reshape(m,1)

Просмотреть файл

@ -25,11 +25,17 @@
最佳实践
#### 感谢
郭百宁、Lily Sun、程彪、韦青、邹欣、沈园、董航、陈洋、贺秋时、吴淞芮、强红军
#### 关于“木头”
“木头”是一名软件工程师,给自己起了一个网名叫“木头”,为人也是有些木讷,在本书中,“木头”同学将成为所有故事的主角。
本书中有很多关于“木头”的故事,“木头”是一个虚构的人物,但是 TA 所经历的故事都是在真实事件基础上经过微小改编的,只不过故事的原主人公可能是笔者,也可能是笔者的同事或朋友。
#### 关于乐队
@ -61,6 +67,7 @@
|FTE||
|Hackathon||
|Happy Hour||
|Hire/No Hire||
|IC - Indiviudal Contributer|个人贡献者(普通员工或群众,区别于管理者)|
|InfiniBand||
|Instant Answer|即使应答,是一种具有比较丰富的信息与格式的搜索结果|
@ -78,6 +85,8 @@
|PROD Bed||
|RSDE||
|Root Cause||
|re-org||
|Screening||
|SDE||
|Solo||
|Spot Reward||
@ -87,7 +96,7 @@
|NLP||
|URL||
|UX - User Experience||
|UWP|Universal Windows Platform|
|UWPUniversal Windows Platform|通用 Windows 平台,但是常指的是的应用|
|Vendor|
|XAML||
|WFHWorking From Home|在家远程办公|

Просмотреть файл

@ -163,7 +163,7 @@
以下是一位来自微软 M365 团队的技术经理的分享(偏口语化)。
#### 1. 过往项目经历
#### 1. 项目经历
过去的项目经历,并不只是了解你做了什么,很多时候我们更希望知道你的独特的贡献是什么?因为很多时我们都是在“团队环境”下工作,你独特的贡献是什么?以及你遇到的独特的挑战和你怎么独特地解决这些挑战的?这些东西是可以在你们在面试的过程中需要特别的强调的。
@ -186,3 +186,5 @@
当然在文化上面呢,我们可能会问大家对多元和包容的理解啊,以及你是怎么做的。因为这个多元包容,不只是管理者,其实很多时候涉及到,每个人每个人都要多元和包容。
此外你是不是具有成长型思维。比如叫一个资历比较浅的员工女员工去用 Visio 画一个图,然后就问了一句,你会不会?这位女员工说我不会,但我可以学啊。其实就是这种 Growth Mindset 思维方式。很多时候我们并不是什么都会,包括我现在对我自己现在工作很多东西,我也不是都会,也很多东西不懂,但是要有这样的一个 Growth Mindset。
**玩儿归玩儿,闹归闹,别拿面试开玩笑!**

Просмотреть файл

@ -172,15 +172,15 @@
#### 保持热情
一般来说女性成熟得较早,而男性在三四十岁的时候,刚好是正值当打之年,可以大展宏图。
一般来说女性成熟得较早,而男性在三四十岁的时候正值当打之年,可以大展宏图。
笔者在微软美国总部出差的时候,见过很多白胡子大叔仍然激情四射地在写代码。这些人一直是属于生龙活虎的人,一直保持着对工作和生活的热情,一直在追逐自己的兴趣爱好,一直在处理一些比较有挑战的工作,这样就不会觉得自己会步入中年,感觉还很年轻,自然不会有危机感。
笔者在微软美国总部出差的时候,见过很多白胡子大叔仍然激情四射地在写代码。这些人一直是属于生龙活虎的人,一直保持着对工作和生活的热情,一直在追逐自己的兴趣爱好,一直在处理一些比较有挑战的技术工作,这样就不会觉得自己会步入中年,感觉还很年轻,自然不会有危机感。
#### 保持积累
笔者以前的一位在微软的领导,针对一些年轻人不断跳槽想尽快提高收入的现象,曾经这样说过:“让你得到财富的正确方法是积累,是每个月有稳定的收入汇入你的银行账户,而不是靠一夜暴富。”
在年轻的时候努力,有一些积累到后面就不会觉得很困难,而随着经验的积累也会厚积薄发。没钱买房子还可以靠银行贷款,知识储备可是没有“预支”的说法,不积累只能“透支”
在年轻的时候努力,有一些积累(无论是技术上的还是经济上的)的话到后面就不会觉得很困难,而随着经验的积累也会厚积薄发。如果说没钱买房子还可以靠银行贷款,那么知识储备可是没有“预支”或“透支”的说法,书到用时方恨少,债到还时方知多
#### 保持好奇

Просмотреть файл

@ -5,13 +5,12 @@
Nobody is an island. 没有人是一座孤岛。
微软很看重沟通能力,而且是在面试中的一个重点考察项目。为什么呢?因为大公司一般都是团队作战,不像小公司那样主要靠单打独斗,作为一个工程师会牵涉到:
微软很看重沟通能力,而且是在面试中的一个重点考察项目。为什么呢?因为大公司一般都是团队作战,不像小公司那样主要靠单打独斗。作为一个软件工程师会牵涉到:
- 和团队内其它工程师的沟通
- 和 PM 的沟通
- 和 Designer 的沟通
- 和其它团队的沟通
- 和其它开发团队的沟通
- 和老板的沟通
- 和客户的沟通
@ -42,27 +41,27 @@ Nobody is an island. 没有人是一座孤岛。
表达观点时,要有理有据(虽然不能保证合情合理),不能道听途说地只说个结论,没有推理过程或者解释说明。
比如你想说服其它人采用你的技术建议,粗糙的沟通方式是:“这种技术很多大公司都采用了,我们也应该采用。” 这种观点拿出来很容易被 challenge挑战
比如你想说服其它人采用你的技术建议,粗糙的沟通方式是:“这种技术很多大公司都采用了,我们也应该采用。” 这种观点拿出来很容易被他人 challenge挑战、挑毛病)。
可以找到两三条理由来支持的你的观点,比如:
可以找到两三条理由来支持观点,比如:
“我建议采用一个消息队列接在 Web 服务器后面,这样的好处是:
*“我建议采用一个消息队列接在 Web 服务器后面,这样的好处是:*
1. 松耦合,在设计、实现上都比较方便;
2. 异步方式可以处理高并发;
3. 集成测试或调试时,可以使用假数据单独针对接口测试,不需要架设庞大复杂的系统。
*1. 松耦合,在设计、实现上都比较方便;*
*2. 异步方式可以缓和高并发访问,后同服务不至于崩溃;*
*3. 集成测试或调试时,可以使用假数据单独针对接口测试,不需要架设庞大*复杂的系统。
很多大公司都采用,所以应该是成熟可靠的技术,我们应该采用。”
*目前很多大公司都采用这种方式,所以应该是成熟可靠的技术,我们应该采用。”*
这种方法有助于你养成想好后再说话的习惯,而不是像那些网络喷子一样只会发表不当言论。
这种方法有助于你养成想好后再说话的习惯,而不是脑海中忽然闪现出一个念头就立刻说出来,或者像那些网络喷子一样只会发表不当言论。
乐队里有一位 C自认为自己多弹了几年吉他有一些演出经验经常会长篇大论地写一些东西搬出来一些不明觉厉的名词最后总不忘加一句“这些都是我上学时就玩儿剩下的”。木头只好说“大家看看老 C 的文字,观点完整、有理有据,请大家学习。” 确实在“观点完整”上C 确实做到了。有人私下问木头这件事,木头回答说:“我说观点完整,并没有说观点正确,我说有理有据,没有说合情合理。”
乐队里有一位 C自认为自己多弹了几年吉他有一些演出经验经常会长篇大论地写一些东西搬出来一些不明觉厉的名词最后总不忘加一句“这些都是我上学时就玩儿剩下的”。木头只好说“大家看看老 C 的文字,观点完整、有理有据,请大家学习。” 确实在“观点完整”上C 确实做到了,但是**观点完整并不代表观点正确,有理有据并不代表合情合理。**
#### 2. 谨慎使用反问句
完整地表达观点,是一种思考成熟、具有知识体系的表现。微信的出现其实是为了普通大众服务的,往往是三言两语说完就走,因为不具备完整表达观点的能力。
完整地表达观点,是一种成熟思考、具有知识体系的表现。微信的出现其实是为了普通大众服务的,往往是三言两语说完就走,因为不具备完整表达观点的能力。
还有些人,可能是在中学就养成的坏毛病,总是反问别人。比如大家在邻居微信群中担忧疫情防控放开的问题,有个年轻人就说:“你得过感冒吗?” 言下之意就是新冠病毒和感冒的危害一样轻,但后来的事实证明要严重很多,恨不得是两三种感冒加起来那么严重。这个年轻人后来在群里求药,但是没有人意搭理他。
还有些人,可能是在中学就养成的坏毛病,总是反问别人。比如大家在邻居微信群中担忧疫情防控放开的问题,有个年轻人就说:“你得过感冒吗?” 言下之意就是新冠病毒和感冒的危害一样轻,但后来的事实证明要严重很多,恨不得是两三种感冒加起来那么严重。这个年轻人后来在群里求药,但是没有人意搭理他。
笔者看着他的反问句不舒服,就回答说:“年轻人可能还容易恢复,但是老年人就比较麻烦。” 没想到又有一个年轻人跳出来反问笔者:“你亲身经历过吗?” 言下之意是“不要听舆论的宣传,老年人没问题的”。笔者当时就以其人之道还治其人之身反问他:“你是老人吗?” 意思是“你不是老人就没有同理心,不会站在其它的人的立场上思考”。
@ -70,18 +69,18 @@ Nobody is an island. 没有人是一座孤岛。
#### 3. 认清“角度”与“高度”
在人类所在的三维世界中,当然有“角度”的概念,同样看一个物理存在的巨大的物体,有的只能看到它的左侧,有的人只能看到右侧,由此会引申到对待一个问题的看法,不同的人会有不同的“角度”。
在人类所在的三维空间中,当然会有“角度”的概念,同样是看一个巨大的物理实体,有的人只能看到它的左侧,有的人只能看到右侧。由此引申到对待一个问题的看法,不同的人会有不同的“角度”。但是,当有人和你沟通时用了“角度”这个词,尤其是领导,大概率是在说你的思考层次“高度”不够,而不是“角度”。为什么呢?
但是,当有人和你沟通时用了“角度”这个词,尤其是领导,大概率是在说你的思考层次“高度”不够,而不是“角度”。为什么呢?
对待项目或者技术问题,其实是存在上帝视角的,这和大家都站在地面观察普通的体积大的物体不同,领导很可能是站在“空中”观察这个物体的,甚至在观察那些观察物体的人。
对待项目或者技术问题,其实是存在上帝视角的,这和大家都站在地面观察体积庞大的物体不同,领导很可能是站在“空中”观察这个物体的,甚至在观察那些观察物体的人。
比如,你建议:“这个项目比较复杂,我们应该先挑最难的部分做,集中优势兵力打歼灭战,这样做对项目进度是有保障的。” 没错,如果从一个纯技术“角度”看,你的这个建议是对的。但是,领导可能会说:“因为这是一个合作项目,能争取过来做 owner 不容易。为了让合作方能对我们建立信心,我们应该先做简单的部分,尽快出一些阶段性成果,同时抽出一小部分人力去啃硬骨头,明修栈道,暗度陈仓。”
你自认为从 360 度观察到了事务的本质,但是领导却是从 720 度(包括上下两个维度)做了更多的思考。所以,说“角度”这个词,只是给你一个面子,其实是“高度”的差别。
你自认为从 360 度观察到了事务的本质,但是领导却是从 720 度(包括上下两个维度)做了更多的思考。所以,说“角度不同”只是给你一个面子,其实是“高度”的差别。
#### 4. 基于事实的讨论,而非立场
先看三个概念:
- 利益:隐藏起来的真正的需求。
每个人都会不自觉地维护自身利益,有可能是实际的经济利益,也有可能是地位、面子、形象等这些看似虚无的东西。
@ -92,15 +91,15 @@ Nobody is an island. 没有人是一座孤岛。
- 行为:表达出来的具体形式。
行为可以是具体的动作,大多数时间是语言/言论。
行为可以是具体的动作,也可以是语言/言论。
当两个人沟通不畅导致争论时,要分析清楚对方的利益是不是与自己不一致,自己是不是无意中触犯了对方的利益。要想分辨这一点很容易:当你想尽办法证明自己是对的,而对方对此态度冷漠口气坚定时,你很可能踩人家脚了。
当两个人沟通不畅导致争论时,要分析清楚对方的利益是不是与自己不一致,自己是不是无意中触犯了对方的利益。要想分辨这一点很容易:当你想尽办法证明自己是对的,而对方对此态度冷漠口气坚定时,你很可能已经踩人家脚(触及对方利益)了。
很典型的情况是,面对一个关键技术问题,两个人各持己见互不相让,其背后的原因很可能是采用了谁的建议,谁就会在 promotion 的路上向前迈进了一步。有个实际的例子,木头在 Windows 组时,常听到很远的隔壁的两个同事 A 和 B 因为在 Edge 浏览器上做银行插件时究竟应该采用哪种技术方案而进行讨论A 是一个 Senior DevB 是一个 SDE II。后来 B 得到了 promotion 到 Senior 级别在邮件通告中的罗列的一条理由就是B 在该项目上贡献突出,在技术方案的选择上与同组的一名 Senior 级别的员工竞争而胜出。
很典型的情况是,面对一个关键技术问题,两个人各持己见互不相让,其背后的原因很可能是采用了谁的建议,谁就会在 promotion 的路上向前迈进了一步。有个实际的例子,木头在 Windows 组时,常听到很远的隔壁的两个同事 A 和 B 因为在 Edge 浏览器上做银行插件时究竟应该采用哪种技术方案而进行讨论A 是一个 Senior DevB 是一个 SDE II。后来 B 得到了 promotion 到 Senior 级别在邮件通告中的罗列的一条理由就是B 在该项目上贡献突出,在技术方案的选择上与同组的一名 Senior 级别的员工竞争而胜出。
#### 5. 简洁不发散
沟通时,每个观点完整是必须的,但是在其它方面要简洁,不要过于发散。
沟通时,每个观点完整是必须的,但是在其它方面要简洁,不要过于发散。
有个同事在每次开 Scrum meeting 时都特能说,你要是仔细听吧,他大部分时间都是在持续不断地补充自己的观点,力图证明是正确的,甚至用一些关系不密切的证据。听起来像是“政治正确的白开水”,特别没有营养。
@ -110,9 +109,9 @@ Nobody is an island. 没有人是一座孤岛。
假设你和领导进行 1:1 的年终总结谈话,领导说:“你在这个项目里承担了一些重要的工作,技术能力很不错,但是在与同事进行技术讨论时,在说话技巧上还有一些进步的空间。”
“有进步的空间”这句话很艺术,它并没有直接说你现在做得不好,而是很委婉地说你可以做得更好。没有人愿意在和别人比较时甘拜下风,但是如果说自己有潜力可以做得更好的话,当然是可以欣然接受的事实
“有进步的空间”这句话很艺术,它并没有直接说你现在做得不好,而是很委婉地说你可以做得更好。没有人愿意听别人说自己“不好”,但是如果说“有潜力可以做得更好”的话,当然是可以欣然接受的
在《星际迷航》电影里,经常会看到这样的对话:船长说“把动力系统全部移到船头进行形成能量保护”操作员可能会说“Negative不行我们需要至少10%的能量储备用于随时做光速跃迁逃逸。”用 Positive/Negative 就会比较客观婉转,给船长留了面子。
在《星际迷航》电影里,经常会看到这样的对话:船长说“把动力系统全部移到船头形成能量保护操作员可能会说“Negative不行我们需要至少10%的能量储备用于随时做光速跃迁逃逸。” 此时用 Positive/Negative 就会比较客观婉转,给船长留了面子。
#### 7. 注意语气语调
@ -128,33 +127,33 @@ Nobody is an island. 没有人是一座孤岛。
如果需要较长时间的思考,也可以回复说“让我先想想,一会儿回复您”。
曾经有一位朋友(微软中国 ARD 的韦青老师)请笔者去给一个合资公司讲讲“微软的工程师文化”,因为笔者当时很忙,一时不能确定能不能讲好,或者是需要多长时间的准备,所以就在第一时间回复说“让我想想”。两个小时后,给予了对方肯定的答复,然后就在业余时间开始准备演讲内容,大部分内容都是本书中的实践中的软件工程,最后的演讲效果非常好,这才启发、激励笔者继续写完这本书,相信会得到很好的读者反馈。
曾经有一位朋友(微软中国 ARD 的韦青老师)请笔者去给一个合资公司讲讲“微软的工程师文化”,因为笔者当时很忙,一时不能确定能不能讲好,或者是需要多长时间的准备,所以就在第一时间回复说“让我想想”。两个小时后,给予了对方肯定的答复,然后就在业余时间开始准备演讲内容(即本书中的内容),最后的演讲效果非常好,这才启发、激励笔者继续写完这本书,相信会得到很好的读者反馈。
#### 9. 面对面的讨论更加有效,慵懒的文字会产生误解
以前在办公室里听到打字速度很快(而且还大胆地使用了机械键盘)时,就知道这个家伙一定在用电脑微信聊天,因为写代码的速度不可能那么快。现在面对疫情,大家都采用了线上办公,每天进行大量的文字交流。有的人文字表达能力非常差,而且懒,自己头脑中是有上下文信息的,但是不在文字中表达出来,往往造成对方误会。
以前在办公室里听到某人打字速度很快(而且还大胆地使用了机械键盘)时,就知道这个家伙一定在用电脑微信聊天,因为写代码的速度不可能那么快。现在面对疫情,大家都采用了线上办公,每天进行大量的文字交流。有的人文字表达能力非常差,而且懒,自己头脑中是有上下文信息的,但是不在文字中表达出来,往往造成对方误会。
有一个同事在和老板文字交流时,越来越觉得领导的态度不对,赶紧要求和老板进行语音通话交流,及时弥补了误会。而更多的时候,那些不善于文字表达的人,写出来的东西看上去一副“态度冷漠语气生硬”的嘴脸,比如领导交代你一件事,你回复“好”、“好~”、“好吧”、“好的”、“好滴”、“好的呢”、“好吧呀”,里面隐藏的情感细节非常丰富。如果不会细腻表达,表情包可以帮你大忙。
有一个同事在和老板文字交流时,觉得对方的态度越来越不对,赶紧要求和老板进行语音通话交流,及时弥补了误会。而更多的时候,那些不善于文字表达的人,写出来的东西看上去一副“态度冷漠语气生硬”的嘴脸,比如领导交代你一件事,你回复“好”、“好~”、“好吧”、“好的”、“好滴”、“好的呢”、“好吧呀”,里面隐藏的情感细节各有不同非常丰富。如果不会细腻表达,表情包可以帮你大忙。
还有一个特点是,一般的实习生在写字时都会带上一个“啊”字,比如:“是啊”、“我也不知道啊”、“就是那样啊”,听上去像吵架。因为“啊”字本身在说出来时是一个轻声的后缀,没有实际含义,但是写出来就变成了一个强调的语气词,看上去很不舒服。
还有一个特点是,一般的实习生在写字时都会带上一个“啊”字,比如:“是啊”、“我也不知道啊”、“就是那样啊”,听上去像吵架。因为“啊”字本身在说出来时是一个轻声的后缀,没有实际含义,但是写出来就变成了一个强调的语气词,看上去很不舒服。
#### 10. 少用对抗思维,多用平行思维
同事之间,如果没有上述的立场问题作怪,就尽量“先扬后抑”,或者“多扬少抑”。
同事之间,如果没有上述的立场问题作怪,就尽量“先扬后抑”,或者“少抑多扬”。
比如针对一个技术问题的选择A 的理由是1. 开发速度快2. 容易测试3. 可以多人并行开发。而 B 与 A 的后两点理由相似,但是第一点理由的差别较大。此时,如果 B 一上来就说:“我认为你的第一点理由根本不成立,我们要的是质量而不是速度”,那么 A 肯定不能接受。这就是对抗思维。
比如针对一个技术问题的选择A 的理由是1. 开发速度快2. 容易测试3. 可以多人并行开发。而 B 与 A 的后两点理由相似,但是第一点理由的差别较大。此时,如果 B 一上来就说:“我认为你的第一点理由根本不成立,我们要的是质量而不是速度”,那么 A 肯定不能接受。这就是对抗思维。
如果采用平行思维B 可以这样说:“我非常同意你的第二点和第三点理由,这对项目的帮助很大。我只是在第一点上和你有一些小的差异。” 此时 A 的反应很可能是眼睛一亮好奇地问:“哦?那你说来听听”。然后 B 再娓娓道来。
如果采用平行思维B 可以这样说:“我非常同意你的第二点和第三点理由,这对项目的帮助很大。我只是在第一点上和你有一些小的差异。” 此时 A 的反应很可能是眼睛一亮好奇地问:“哦?那你说来听听。” 然后 B 再娓娓道来。
这种技巧,是 B 先给了 A 一个较强的心理暗示:咱俩是一个阵营的。这样 A 就会表现出合作的态度。
#### 11. 说话不要绕弯子
比如,有个同事建议:“到年底,因为美国那边要休圣诞节假期,所以我们不如等他们都休假回来后再一起讨论后续的安排。” 其实是这个同事的年假没用完,他想在 12 月底休两周的假,他不直说,却把美国人搬出来当挡箭牌。
比如,有个同事建议:“到年底,美国那边要休圣诞节假期,所以我们不如等他们都休假回来后再一起讨论后续的安排。” 其实是这个同事的年假没用完,他想在 12 月底休两周的假,他不直说,却把美国人搬出来当挡箭牌。
木头的乐队里还有个例子:一个乐队的成员想在元旦时出去玩儿,但是新年音乐会定在了 1 月 6 日,他又怕到时候不能赶回来,所以他们队长就来找我说:1 月 6 日估计很多微软员工休假的还没回来,影响观众的上座率,不如我们延期举办音乐会吧?
木头的乐队里还有个例子:某个小乐队的某个成员想在元旦时出去玩儿,但是新年音乐会定在了 1 月 6 日,他又怕到时候不能赶回来,所以这个小乐队的队长就来找我说:“1 月 6 日估计很多微软员工休假的还没回来,影响观众的上座率,不如我们延期举办音乐会吧?
这听上去就是很为演出效果考虑的感觉,但是这一个改变就要到春节后再开音乐会了,排练不好安排。员工们过完春节刚刚来上班,你来个“马后炮”,不论是观众和乐手,心气儿都差远了。木头看出来了是因为他们的乐手凑不齐,所以拒绝了这个队长的请求,说:你如果缺乐手可以向别的乐队借,没必要把自己乐队的困难绕个弯子转嫁到整个演出上。
这听上去就是很为演出效果考虑的感觉,但是春节后再开音乐会的话,排练不好安排,大家过完春节刚刚来上班,不论是观众和乐手,心气儿都差远了。木头看出来了是因为他们的乐手凑不齐才会提这个要求,所以拒绝了这个队长的请求,说:你如果缺乐手可以向别的乐队借,没必要把自己乐队的困难绕个弯子转嫁到整个演出上。
#### 12. 相同的话不要重复说
@ -167,11 +166,11 @@ Nobody is an island. 没有人是一座孤岛。
#### 13. 不要乱用“沉默”的权力
笔者在写本书的“用户与需求”部分时,曾经想要求一位以前共过事的 PM 一起写,就发了一封邀请邮件,但是却石沉大海,也不好再追说,干脆自己写了。笔者感到很不可思议的是,曾经和那位 PM 在项目最艰难的时刻共同努力,最终令项目得到了总部的认可,相当于一起“扛过枪、负过伤”的交情,为什么对方会沉默呢?
笔者在写本书的“用户与需求”部分时,曾经想要求一位以前共过事的 PM 一起写,就发了一封邀请邮件,但是却石沉大海。笔者也不好意思再追问,干脆自己写。笔者感到很不可思议的是,曾经和那位 PM 在项目最艰难的时刻共同努力,最终令项目得到了总部的认可,相当于一起“扛过枪、负过伤”的交情,为什么对方会沉默呢?
不要怀疑他可能是漏看了邮件,因为他是一个非常细心的人,看邮件回邮件是他的本职工作。其实他完全可以说“工作繁忙、才疏学浅”等等来推脱,笔者是完全可以接受的,但是这种“沉默”是极大的不尊重,相当于断绝了以后交往的可能。
不要怀疑他可能是漏看了邮件,因为他是一个非常细心的人,看邮件回邮件是他的本职工作。其实他完全可以说“工作繁忙、才疏学浅”等等来推脱,笔者是重复理解并可以接受的,但是这种“沉默”是极大的不尊重,相当于断绝了以后交往的可能。
同样的问题经常发生在同事或朋友之间的微信通信上,有的时候甚至一句“新年快乐”发过去却得不到半点儿回音。笔者只是在对对方的行为或言语极为反感时,才会采用“沉默”这种手段。所以奉劝那些容易忘记回复消息的读者们,真正地把对方放在心上(这样对方才能把你也放在心上),在方便的时候第一时间回复对方。
同样的问题经常发生在同事或朋友之间的微信通信上,有的时候甚至一句“新年快乐”发过去却得不到半点儿回音。对于笔者来说,当对对方的行为或言语极为反感时,才会采用“沉默”这种“极端”手段。比如,笔者的一个同学出家当尼姑了,想让笔者捐钱给她所在的寺庙,笔者是无神论者,所以选择了沉默。所以奉劝那些容易忘记回复消息的读者们,真正地把对方放在心上,在方便的时候第一时间回复对方,这样对方才能把你也放在心上
#### 14. 不抱怨结果,要分析原因
@ -179,21 +178,21 @@ Nobody is an island. 没有人是一座孤岛。
最典型的是家长面对孩子的考试结果时,第一句便是:“你怎么不好好考试?!”,孩子听完后一脸懵弊,然后就是一言不发。
因为家长自身处于强势地位,不太注重沟通的方式。但是一般的公司领导会很注意这些细节,在上面那种情况下一般会说:“这次考试(项目)结果不太理想,应该还可以做得更好,你有没有自己分析过是什么原因造成的呢?” 这样拉开话匣子,会让对方可以接受。
家长在家庭中处于强势地位,不太注重沟通的方式。但是一般的公司领导会很注意这些细节,在上面这种情况下一般会说:“这次项目结果不太理想,应该还可以做得更好,你有没有自己分析过是什么原因造成的呢?” 这样拉开话匣子,会让对方可以接受。
#### 15. 不挑战别人的决定,而是提出建设性意见
比起上一条来,更进一步。
有一些对话经常会出现这个问题:“为什么这样做?”
经常有一些带有情绪的对话,或者是下级面对上级时,会出现这个问题:“为什么这样做?”
如果是同级别的人谈话,问话人的意思往往是“我有更好的方案”,但是他不直接说,而是以问句开始,这就容易拱火儿。
如果是同级别的人谈话,对方的意思往往是“我有更好的方案”,但是他不直接说,而是以问句开始,这就容易拱火儿。如果是不同级别的人,劝你还是最好不这样问话,因为领导掌握的信息比你多,做出的决策也会更合理,让领导解释理由是很不礼貌的,这相当于是一种挑战。
如果是不同级别的人,尤其是面对领导时,最好不这样问话,因为领导掌握的信息比你多,做出的决策也会更合理,让领导解释理由是很不礼貌的,这相当于是一种挑战。如果真的想知道理由,需要先把自己的想法摆出来,请领导评判。
不论哪种场合,如果直接了当地把自己的“具有建设性”的意见说出来,会得到领导的赏识和同事的赞许。“建设性”这个词还是木头在学习桥牌时第一次遇到的,叫做“建设性应叫”,意思是对方表达了完整的观点后,应该在尊重对方观点的前提下,提出自己的一些局部或不同方向的补充,来共同完善这个观点。
不论哪种场合,如果直接了当地把自己的“具有建设性”的意见说出来,会得到领导的赏识和同事的赞许。“建设性”这个词还是木头在学习桥牌时第一次遇到的,叫做“建设性应叫”,意思是对方表达了完整的观点后,应该在尊重对方观点的前提下,提出自己的一些局部差异化观点,是完全不同方向的补充意见,来共同完善这个观点。
### 3.1.3 沟通能力的培养
沟通的前提是要有输出,别人才能理解你,才能达到沟通的目的;也要有输入,才能正确地理解别人。一般人都可以做到输入(听),但是能力欠缺的人没有输出或者很少有输出,造成沟通障碍,据笔者观察,在一个团队中,这类人占比为 10%-20%,虽然他们不会影响整个团队的协作,但是却会影响个人的职业发展。
沟通的前提是要有输出,别人才能理解你,才能达到沟通的目的;也要有输入,才能正确地理解别人。一般人都可以做到输入(听),但是能力欠缺的人没有输出或者很少有输出,造成沟通障碍,据笔者观察,在一个团队中,这类人占比为 10%~20%,虽然他们不会影响整个团队的协作,但是却会影响个人的职业发展。
如果想提高输出的能力,从下面三点入手即可:
@ -206,10 +205,10 @@ Nobody is an island. 没有人是一座孤岛。
【最佳实践】
- 工作餐尽量和大家一起吃,有说有笑。
- 不知道该说什么的时候,可以先听听大家说什么,然后就可以确定自己的话题是不是会得到响应。
- 不知道该说什么的时候,可以先听听大家说什么,然后就可以确定自己的话题是不是会得到响应,不然说出来没人响应的话,会很尴尬
- 可以先指定一个人,比如:“老李,你上次说买了个国产车,质量行吗?我最近也想每一辆。” 对方肯定会打开话匣子给你分享经验。
- 可以讲一些趣事或笑话,但不是从网上趸来的,而是自己亲身经历的。
- 就一个新闻或一个事件发表自己的简单看法比如“NAVIDIA 不能在中国卖 GPU对它自己的利润有很多影响,中国是世界上最多使用 GPU 的国家。”
- 就一个新闻或一个事件发表自己的简单看法比如“NAVIDIA 不能在中国卖 GPU对它自己的利润有很大影响,中国才是世界上最多使用 GPU 的国家。”
#### 2. 工作中的职业沟通
@ -218,11 +217,11 @@ Nobody is an island. 没有人是一座孤岛。
- 遇到疑难问题时,主动寻求他人的帮助。当问题较为严重时,寻求老板的帮助。
- 主动帮助他人,分享你的经验。
- 开会时主动发言,发表自己的看法
- 开会时主动发言,表达自己的观点
- 主动承担任务池中的工作项,并努力完成,及时交付。
- 和 PM 搞好关系,耐心解答技术问题。
- 与外部团队合作时,态度要谦虚谨慎。
- 及时反馈无论是答应了谁做什么事,都要及时反馈,不能等着别人来问你进度。
- 与外部团队合作时,态度要谦虚谨慎,以项目成功为主要目标,其它为次要目标
- 及时反馈无论是答应了谁做什么事,都要及时反馈,不能等着别人来问你进度。
#### 3. 高级的情感沟通
@ -230,9 +229,9 @@ Nobody is an island. 没有人是一座孤岛。
【最佳实践】
- 逢年过节给亲朋好友领导同事拜年如果有人主动给你拜年,那么下次你要抢先一步回馈。
- 逢年过节给亲朋好友领导同事拜年如果有人主动给你拜年,那么下次你要抢先一步回馈。
- 发了朋友圈收了赞和评论,记得回复朋友们的评论,也记得给朋友们的朋友圈点赞。
- 关心一下他人的遭遇,比如“上次你骑车摔倒了,没伤到骨头吧?”
- 收到别人的红包,要发一个快乐的表情表示感谢,但实际上你可能只抢到了 2.46 元,而别人都是好几十块钱。此时你可以炫耀地说:“看,二四六多吉利,好事成双!”
- 多参加团队活动,或者是社会团体活动,比如乐队、读书会、羽毛球俱乐部等等,认识工作以外的人。
- 分享自己最近读过的好书、看过的好影视剧,并附加自己的正面评论。
- 收到别人的红包,要发一个快乐的表情表示感谢。你如果只抢到了 2.46 元,而别人都是好几十块钱,此时你可以炫耀地说:“看,二四六多吉利,好事成双!”
- 多参加内部集体活动,或者是外部的社团活动,比如乐队、读书会、羽毛球俱乐部等等,认识工作以外的人。
- 分享自己最近读过的好书、看过的好影视剧,并附加自己的正面评论。

Просмотреть файл

@ -2,9 +2,9 @@
关于“问题”这个词的定义有很多,在这里我们特指三类技术问题:
1. 要达到的目的,比如:用聚类算法处理数据、建立合理的拓扑结构、搭建模型预测趋势等等。
2. 要纠正的错误,比如:软件的输出和预期不一致、开发时间超过计划太多、用户量大时导致系统崩溃等等。
3. 要解决的疑问,比如:为什么在贪吃蛇游戏设计中应该使用链表、为什么很多程序员到了 30 岁就不愿意再写代码等等。
1. 要达到的目的Solution,比如:用聚类算法处理数据、建立合理的拓扑结构、搭建模型预测人口增长趋势等等。
2. 要纠正的错误Issue,比如:软件的输出和预期不一致、开发时间超过计划太多、用户量大时导致系统崩溃等等。
3. 要解决的疑问Question比如为什么井盖是圆的、为什么房子是方的、为什么在贪吃蛇游戏设计中应该使用链表等等。
### 3.2.1 能力的评级

Просмотреть файл

@ -6,7 +6,7 @@
先理清三个名词思考Think思维Thinking思想Thought
<img src="img/Slide13.SVG"/>
<img src="img/Slide14.SVG"/>
图 3.3.1 三个名词的关系
@ -71,7 +71,7 @@
而本节中的“系统化思维能力”所面对的问题,不仅仅是简单的一对一的因果关系,更多的是如图 3.3.2 中另外四种形式所示的复杂关系。所以,解决(简单)问题的能力也可以看作是一种简单的系统化思维能力。
<img src="img/Slide14.SVG"/>
<img src="img/Slide15.SVG"/>
图 3.3.2 系统化思维的几种形式
@ -83,7 +83,7 @@
举一个比较通俗的例子:木头在某个级别上很长时间不能得到晋升,如何解决这个问题呢?
<img src="img/Slide15.SVG"/>
<img src="img/Slide16.SVG"/>
图 3.3.3 星形系统与思维形式
@ -141,7 +141,7 @@ OK如果你能够从以上几个方面分析好自己当前的境遇判断
要解决这个问题需要一系列的假设数据支持,有些数据是可以从网上查到的,有些是常识,剩下的就需要靠推理了。
<img src="img/Slide16.SVG"/>
<img src="img/Slide17.SVG"/>
图 3.3.4 北京有多少个加油站
@ -226,7 +226,7 @@ OK如果你能够从以上几个方面分析好自己当前的境遇判断
在计算机硬件系统中,设计了各种各样的存储设备,这些设备成明显的层次结构,但是上小下大,介于串行系统与下面要讲的金字塔形系统之间,如图 3.3.5 所示。
<img src="img/Slide17.SVG"/>
<img src="img/Slide18.SVG"/>
图 3.3.5 金字塔形系统与思维方式
@ -252,17 +252,19 @@ OK如果你能够从以上几个方面分析好自己当前的境遇判断
表 3.4.2 从数据到智慧的进化
|Data$\rightarrow$|Information$\rightarrow$|Knowledge$\rightarrow$|Wisdom|
|Data$\rightarrow$|$\rightarrow$Information$\rightarrow$|$\rightarrow$Knowledge$\rightarrow$|$\rightarrow$Wisdom|
|-|-|-|-|
|一年中某地<br>下雨的数据|发现夏天午后经常下雨|于是夏天出门带雨伞|做出准确的天气预报|
|全国及地方的<br>人口数量数据|经过加工分析得到的统计<br>数据,比如地域性的差异、性别的差异、增长率的变化|建立人口模型,预测<br>未来人口数量的发展|辅助地方政府决策|
|姓别/年龄/职业/消费等零散数据|关联这些数据,得到它们<br>与消费金额的关系|年轻白领女性花钱最多<br>年长蓝领女性消费最少|不同消费群体的引导|
金字塔形系统有时可以被串行系统或树形系统所代替。
### 3.3.5 树形系统与思维形式
树形多用于组织结构,虽然外轮廓也和金字塔形系统一样是三角形,不同的是,处于低层的元素不是同质的。
<img src="img/Slide18.SVG"/>
<img src="img/Slide19.SVG"/>
图 3.3.6 如何举办一场音乐会
@ -320,7 +322,7 @@ OK如果你能够从以上几个方面分析好自己当前的境遇判断
### 3.3.6 环形系统与思维形式
<img src="img/Slide19.SVG"/>
<img src="img/Slide20.SVG"/>
图 3.3.7 环状系统的负反馈
@ -347,7 +349,7 @@ OK如果你能够从以上几个方面分析好自己当前的境遇判断
网状系统(或者说是表格形式)思维是最复杂的一种形式,因为它涉及到了横向思维和纵向思维两个方向,甚至是多维的。而其它的思维形式都是单向的。
<img src="img/Slide20.SVG"/>
<img src="img/Slide21.SVG"/>
图 3.3.8 网状系统的负反馈
@ -357,10 +359,12 @@ OK如果你能够从以上几个方面分析好自己当前的境遇判断
在软件质量控制过程中,如图 3.3.9 所示,需要软件可以达到很多种质量指标,如:正确性、可靠性、易用性、高效率、可维护性、可移植性等等。但是其中的某些指标是相克的,一个指标的提升会带来另外一个指标的下降。
<img src="img/Slide21.SVG"/>
<img src="img/Slide22.SVG"/>
图 3.3.9 质量指标之间的竞争
在足球场上,教练会强调两点:一是全队三条线在横向上的步调一致,一起压上进攻,或者一起收缩防守;二是在纵向上,同一边的后卫、中场球员、前锋要协调进攻。在排球场上,六个队员形成 2x3 的网格阵型,兼顾进攻与防守。
以上这些都是网状思维的典型应用场景。
网状系统经常被星形系统和环形系统所代替,就是把网格中的每个节点做为中心点(星形)或起点(环形)来处理。

Просмотреть файл

@ -24,7 +24,7 @@
另外一个极端的例子是小黄鸭调试法:程序员总是在桌子上放一只橡皮小黄鸭,在调试代码的时候详细地向鸭子解释每行代码。如果没有小黄鸭玩具,找一个同事临时充当也行,千万不要用尖叫鸡代替。你会发现在讲解的过程中,可以突然发现一些隐藏的问题,从而帮助你快速解决 Bug。其原理是你如果只是盯着代码看大脑会忽略一些重要细节而当你试图讲出来时为了让对方听明白就会揪出这些细节来。从而发现问题。
<img src="img/Slide22.SVG"/>
<img src="img/Slide23.SVG"/>
图 3.5.1 两种推荐的学习方法
@ -70,15 +70,15 @@ SQ3R 代表着五个单词:
人们在描述一个复杂问题时,通常会用画图的方式来表达,一图胜千言。为什么呢?因为人脑理解语言的过程如图 3.5.2 所示。
<img src="img/Slide23.SVG"/>
<img src="img/Slide24.SVG"/>
图 3.5.2 从语言序列重建模型
讲述一个复杂的问题时,如果用语言方式表达,则是一个序列结构,如图左侧所示。对于听者来说,如果只有一两句话,那理解起来很容易,但是当这个序列很长时,人们不得不在头脑中建立起右侧子图的结构来帮助理解,还有可能产生误解。所以,如果说话的人一开始就在纸上画出图来然后解释,会到达事半功倍的效果。
讲述一个复杂的问题时,如果用语言方式表达,则是一个序列结构,如图左侧所示。对于听者来说,如果只有一两句话,那理解起来很容易,但是当这个序列很长(大于 3时,人们不得不在头脑中建立起右侧子图的结构来帮助理解,还有可能产生误解。所以,如果说话的人一开始就在纸上画出图来然后解释,会到达事半功倍的效果。
我们举个例子:当有一个人对你说“有一个系统,它的输入是文字,输出是图片”时,你的脑海中一定会快速建立起类似图 3.5.1 所示的模型(输入文字$\rightarrow$系统$\rightarrow$输出图片),然后大脑可能会把它立刻擦除,但是当再次需要的时候,又可以立刻把它从“垃圾桶”中捡回来而无需重建。
画图是抽象思维$\leftrightarrow$具象思维来回转换的结果,善于画图,说明你对这种转换掌握得淋漓尽致。我们在平时写技术文档的时候,通常会配上几张图来说明系统框架、基本流程、状态转换、交互关系等设计理念,让文档审阅者一目了然。
画图是抽象思维$\leftrightarrow$具象思维来回转换的结果,善于画图,说明你对这种转换掌握得淋漓尽致。我们在平时写技术文档的时候,通常会配上几张图来说明系统框架、基本流程、状态转换、交互关系等设计理念,让文档审阅者一目了然。在后面的有关设计的章节中,会使用大量的图来辅助设计工作。
画图和写字一样,也有好看与不好看的区别,笔者提供一些体会供大家参考。
@ -91,7 +91,7 @@ SQ3R 代表着五个单词:
- 连线清晰:尽量避免有交叉线的出现,重叠的连线要保持拓扑清晰。
- 妙用线型:巧妙使用“粗细虚实弯直”等线型来表达不同的含义。
图画得漂亮的人,一般长得也漂亮。
图画得漂亮的人,一般长得也漂亮。哈哈!
在本书中,所有的插图都是笔者亲手在 Microsoft PowerPoint 上绘制的SmartArt 功能帮了大忙,帮助笔者对各种概念的理解更为深刻,相信对读者在阅读本书时也有同样的效果。
@ -105,7 +105,7 @@ SQ3R 代表着五个单词:
笔者回忆了一下上学的经历以及自学新知识的过程,大概经过了如图 3.5.3 所示的几个阶段,下面详细介绍这几个阶段的【最佳实践】。
<img src="img/Slide24.SVG"/>
<img src="img/Slide25.SVG"/>
图 3.5.3 构建知识体系
@ -128,7 +128,7 @@ SQ3R 代表着五个单词:
正如同费曼学习法所说的,我们如果把学习到的知识经过消化后用自己的语言再给同事们讲解出来,就会有深刻的理解。因为在准备讲解的过程中,你会发现有一些细节没有搞清楚,还有一些环节没有连接上,最糟糕的是结论和原因可能对不上,这都是没有透彻理解而导致的。如果想弥补这些问题,你必须深入地学习、透彻地理解。
在中学时代的语文课要求写 800 字的作文,对于所有学生来说都是一个噩梦,包括那些语文成绩好的学生,写作文对他们来说也不是轻而易举的事情,尤其是在考试的时候,时间有限,还要兼顾其它的小分题目。现在看来,一本 16 开版面的书的一页就是 800 字左右,可以算是一篇短文了。如果时打好基础,以后遇到码字的工作时会轻松一些。
在中学时代的语文课要求写 800 字的作文,对于所有学生来说都是一个噩梦,包括那些语文成绩好的学生,写作文对他们来说也不是轻而易举的事情,尤其是在考试的时候,时间有限,还要兼顾其它的小分题目。现在看来,一本 16 开版面的书的一页就是 800 字左右,可以算是一篇短文了。如果上学时打好基础,以后遇到码字的工作时会轻松一些。
#### 3. 写案例
@ -210,3 +210,4 @@ SQ3R 代表着五个单词:
其实布鲁姆分类体系的六个层次,与本节中所讲的建立知识体系的六个阶段也可以有比较模糊的一一对应关系的,请读者自己分析理解。所以,掌握了本节中的六个阶段的学习方法,自然也就达到了布鲁姆分类体系的六个层次。

Просмотреть файл

@ -0,0 +1,121 @@
## 3.6 成为面试官
什么的员工才能成为一名合格的面试官?
笔者认为在微软让 Senior 级别以下的人做面试官是不合适的,虽然微软内部有一个在线培训课程 Smart Interview但是它只讲了一些偏重文化、人性方面的原则。在第二章中的专业能力是必须要具备的而本章中前几个小节描述的各种能力也是每个面试官都至少应该知道甚至是具备其初级阶段素养的。
本小节的内容是笔者在加入微软 3 年时,参加 STCA 的大规模招人面试后写的体会,文中的“我”即笔者。全文摘抄如下。
### 3.6.1 面试结果的 Precision/Recall
我最近推荐了几个以前认识的朋友来参加这次招聘活动朋友们都多多少少给了我一些feedback都说首轮面试感觉不是很好。但其实他们都是很优秀的人否则我也不会推荐。而且其中有两个是一起工作过 2 年的 vendor应该是很有实力的。我没有问他们具体的面试题目是什么但是从我个人以前作为应聘者和面试官的经验来分析很可能我们有些面试环节需要改进。
在 Bing 系统中我们开发了大量的分类器classifier来判断一个东西的真伪。用于衡量分类器好坏的标准是 Precision/Recall查准率/查全率),而目标是要求 Precision/Recall 越高越好,比如 98%/95%。套用在面试过程中的实际应用是:面试官对应聘者的 Hire/No Hire 的准确程度。
我们把应聘者分为两类:一类是真正的人才(应该给 Hire一类是真正的庸才应该给 No Hire。而面试结果也有两种Hire/No Hire。交叉后得到下表
|应聘者$\downarrow \backslash$ 面试结果$\rightarrow$|Hire|No Hire|
|--|--|--|
|真正的人才|A|B|
|真正的庸才|C|D|
所谓“真正的人才”只是一个假设,因为我们没有客观标准评价一个人是否是“真正”
- 查准率 $Precision = \frac{A}{A+C}$,如果得到 100% 表示极好,意思是没有放过任何庸才,有“宁可错杀一千也不放过一个”的意思,面试标准较严,有可能误伤人才。
- 查全率 $Recall = \frac{A}{A+B}$,如果得到 100% 表示极好,意思是没有错过任何人才,面试标准较松,当然有可能把庸才也 Hire 了。
从目前面试的结果来看,由于有 Smart Interview 的指导,我们很少雇佣不合格的人,也就是 C 值很小意味着我们面试的准确度很高可以达到99%。但同时,由于我们本着宁缺勿滥的原则,所以有一些合格的人才被某些环节过滤掉了,造成 B 值较大,但是由于不能证明这件事,所以也不敢信口开河的说一个数字,但希望它不低于 90%。
面试一共 6 轮,由于在后面的 5 轮面试中,误判出现的情况较少,所以第一轮电话面试的准确程度就是决定我们的 Recall 值的关键,这就决定了做为电话面试的面试官的重要性。鉴于我们此次招聘任务的繁重性,第一轮的面试官的选择,同时也决定了我们此次招聘行动的效率。
**电话面试**方式和**面对面的面试**方式有一些细微的差别,后来由于新冠疫情的捣乱,又出现了**线上面试**的方式,是前两种方式的组合体。
下面的一些注意事项有些仅适用于其中一种方式,有些都适用。
初面筛查Screening是电话面试的目的也是面试过程中最最重要的一步搞得好面试成本大大降低搞得不好或者“误伤好人”错过可用之才或者“误引庸才”浪费后面双方的时间。Smart Interview 里讲到的都是非常正确的。但即使是参加了 Smart Interview 培训的员工,也不会得到任何实际的指导,没人告诉他们以上几种面试方式的区别是什么。
### 3.6.2 面试中的最佳实践
我个人推荐的【最佳实践】有以下几点。
#### 1. 不给应聘者压力
与对方聊天,以聊天的形式开始你的面试工作,而不是冷冰冰地一问一答,甚至可以在面试过程中很简短地说一个小笑话。不要以考官的身份出现,尽管你现在是一个考官。
以我自己为例我的情况很特殊是经过了两次面试共12轮才成为微软的一员的第一次是在必应地图项目组由于暂时没有 headcount所以以 vendor 身份进入微软,应该在一年后就会自动转为 FTE但是一年后柳虽暗但花未明项目组被 re-org 进入 STC于是又经历了第二次面试。
回想起那近乎“残酷”的过程,无形的心理压力,失败与成功相隔一线的艰险,实在是冷汗直流。于是乎,有过我这样类似经历的人会分化成两种不好的心理状态:
- 第一种:我受了这么多“考验”才成功,我也要“考验”一下后来者。
- 第二种:滋味真不好受!我不能让后来者再次品尝这种滋味!
以上这两种心理都有问题,前者容易尺度过严,后者容易尺度过松(我本人有些偏向后者)。
对于那些 Campus Hire 的童鞋们来说,他们可能没有经历过这些,从学校出来就一帆风顺,没有经历过工作生活中的种种磨难,很容易产生一种优越感,不自觉地就在面试过程中体现出来。比如,虽然他们嘴上不说,但心里总是在想:
- “这个题目这么简单都答不出来?”
- “你没有接触过这方面的工作,但在学校也应该学过啊!”
- “我已经告诉了你线索,你怎么就想不通呢?”
由于我们的面试官们接受过 smart interview 的培训,人品也都很好,所以这些话是不会说出口的,但是在内心深处有可能受到这些想法的影响,从而造成错误的判断。
而且 Campus Hire 一两年的童鞋们,由于生活阅历有限,有些人在“聊天”能力上不足,有时说出来的话很可能比较干涩,让对方莫名其妙,无法顺利沟通;或者是想与对方沟通,但说话技巧不够,不能达到目的。
#### 2. 不出复杂的算法题
有些题目面试官虽然觉得很简单,那是因为出题人已经知道了答案。举例来说,一个谜语:“一个东西,既是水果的名称,又是运动的名称”。你可能想破了脑袋也想不出来。当人家告诉是“橄榄”的时候,你就会觉得“我怎么那么笨啊”。然后你拿这个谜语去考别人,别人在使劲思考的时候,你恨不得急得想上厕所,心里想着“你怎么这么笨啊”。
在**电话面试**中, 出了一个算法题时,面试官应该能想象得到,对方可是在拿着电话在思考问题!他不得不时常发出一些无意义的单音节长声(比如“嗯~~~~”)来表明他正在思考,以保持和面试官的语音交流,同时又在思考的题目。如果题目复杂得必须绕两个弯儿才能解决,而且不画在纸上进行形象思维就不能想清楚的话,那就说明你这个题目对于电话面试方式来说太难了。
对于**面对面的面试**出题也不宜很难要给应聘者能给出答案的机会然后靠时间来评判优劣。比如同样一个题A 用了 15 分钟给出了正确答案B 用了 30 分钟C 用了 45 分钟,那当然选 A。相反如果题目很难那么 A、B、C 谁都答不出来,那还有什么意义?
有些题目确实有些难,面试官们的态度通常很好,耐心地给于应聘者提示和引导,帮助他/她发挥自己的潜能来解决眼前的问题。
#### 3. 更多地让应聘者在说话
面试官设计好问题,让对方说更多的话。
- 从对方感兴趣的领域入手,让应聘者很有激情地谈论自己的长处。
- 甚至可以以新人的姿态请教应聘者擅长的知识。
- 也可以用一些开放式思维的题目来交互,不需要在纸上写的,只说想法的那种。不必关心答案的细节,只关注应聘者的思维过程。
“言多必有失”,应聘者说得多了,自然会发现他无意中透露出来的优点/缺点。
#### 4. 用同样的题目衡量不同的应聘者
每次都用不同的题目,可以保持面试题不被泄露,但是也很难比较两个应聘者的能力。我自己每次都用同样三个题目考察应聘者,那些题目大多是我参加的 12 轮面试中的题目。如果应聘者答的比我当初给出的答案好,或者用的时间短,那我就认为对方的能力不比我差,那我就会考虑给 Hire。
让整个公司有个“面试题库”恐怕不太现实,但每个面试官都应该积累一下自己的“题库”,会让你的面试工作更轻松更有效。
#### 5. 考察应聘者的学习能力最重要
笔者在进入微软以前,在其它几个公司工作了很长时间,虽然干的都是软件开发,但主要是面向应用,很少用到诸如精美的算法,精深的数据结构,庞大的系统结构。有些面试题目,对于刚从学校毕业的学生来说更容易回答,因为学生对书本上的知识还是记忆深刻的,但是对于 Industry Hire 的应聘者来说并不友好,工作几年后就全忘了。
另外,做搜索业务的公司是少之又少,不能指望那些 Industry Hire 的人来了就能立刻贡献代码,所以学习能力很重要。同理,只看简历中有没有相关经验,通常也得不到满意的人选。所谓道不同不相为谋有点儿过激。实际上人的可塑性很强,虽说隔行如隔山,但闻道有先后,术业有专攻,不可低估一个目前是“外行人”的自我学习能力。
#### 6. 首轮面试官的人选
在面试了很多人后,有些面试官可能忽然发现个问题:不对啊!这是第 6 个人了,我觉得还可以,那第 2 个人为什么被我砍掉了呢?我无意中降低标准了吗?
其实作为面试官,是有一些心理负担的,尤其是当做为第一轮的面试官时,可能生怕放过来的人被后面的面试官“砍掉”,那会让自己很没面子。于是就可能在心理上暗示自己“一定要严格”,“提高成功率”等等。
在电话面试的面试官的人选上,我建议要选择有过多次作面试官经验的“老手”,而不是那些“新兵”。从学校毕业并不能说明你能胜任工作,同样,参加了 Smart Interview 的培训也同样不能说明你能胜任任何面试工作。
### 3.6.3 人才库的建设
由于本人以前做过 vendor对 vendor 公司也有所了解。由于没有合理的提升机制vendor 公司根本没有任何招聘方面的优势,招人时也是捉襟见肘,不能说服优秀人才加盟。一些与微软合作的 vendor 公司,有时有些 on site vendor 的机会时,在智联招聘上打出的口号是:有机会赴微软工作!这时它们的日子就会好过些,招人也容易些。
在进入微软之前,我觉得微软的面试机会很少,人多职位少。于是想到了 vendor 公司也许是很好的接近微软的渠道。但后来发现,微软根本就没有这个机制:从 vendor 中选择面试候选人。
IBMMotorola 这些公司,也有很多 on site 的 vendor他们的做法是当项目上需要人时直接从 vendor 中选拔优秀的人成为正式员工。这样的好处显而易见:
1. vendor 了解雇主公司的工作方式,熟悉所在岗位的工作性质,了解所需要的工作技能.
2. 节省了大量从社会上招聘人的时间和风险,因为用人单位对于已经在身边工作了很长时间的 vendor 非常了解。
3. 由于有了前面的提升机制,就会有更多的优秀人才慕名进入 vendor 公司,作为雇主公司的后备人才库。
如果这种方式运作得当,我们就会有一个优良的“人才储备-面试-雇佣”的生态环境,形成良性循环,后备人才信手拈来,不用满世界去削尖了脑袋玩命儿找了。
蒹葭苍苍,白露为霜。所谓伊人,在水一方。

Просмотреть файл

@ -2,6 +2,10 @@
<img src="img/Slide1.JPG"/>
团队合作,主要指的是团队内部的成员之间的合作,双人的、多人的,同事之间的、上下级之间的,相同角色之间的、不同角色之间的,等等。
在本章的最后,还介绍了团队之间的合作,以及一种特殊的形式:实习生与导师之间的合作。
<img src="img/Slide2.JPG"/>

Просмотреть файл

@ -1,12 +1,12 @@
## 4.2 团队工作的故事
## 4.1 团队工作的故事
下面讲一个真实的小故事,通过这个故事,读者可以了解到团队的成员组成以及基本的软件工程流程。
<img src="img/Slide7.JPG"/>
<img src="img/Slide3.SVG"/>
图 4.2.1 团队工作实例
图 4.1.1 团队工作实例
### 4.2.1 项目中的团队成员角色
### 4.1.1 项目中的团队成员角色
前一段时间木头接手了一个小项目:某金融公司与 MSRA 的机器学习组的研究员合作量化交易的研究。木头的任务是在 Azure 上开发一个系统,把数据上传、训练、推理、模型管理等组织起来并部署到 Azure 上,方便客户、研究员、管理者使用。
@ -29,7 +29,7 @@
下面的故事中列出了几个小的讨论细节,便于大家了解真实的团队合作过程。
### 4.2.2 需求分析
### 4.1.2 需求分析
经过一周多的需求调研,木头列出了四个子系统的 Use Case用例
@ -52,7 +52,7 @@
经过这一轮的讨论,团队内部确定了系统架构和职责划分。
### 4.2.3 技术选型
### 4.1.3 技术选型
这个系统中的技术点很多,每个点都有多种选择,需要团队讨论。木头印象较深的是推理机制触发的问题。
@ -85,7 +85,7 @@
小 P 也同意木头的意见。结果是,当客户听说可以自动化流程时,非常感兴趣,表示支持这个技术选型,下载使用那些 binary 文件也没有问题。
### 4.2.4 原型开发
### 4.1.4 原型开发
实际上原型开发就是为了验证技术选型。木头把整个系统的关键技术点分解出来,让大家认领,然后分别去验证。两个实习生被直接指派任务,去自己写代码做试验,然后回来汇报。实习生当然有权力发表自己的看法,但是面对复杂工程问题的时候,他们的实际经验并不多。
@ -99,17 +99,17 @@
- 远过程调用机制
- 邮件通知机制
### 4.2.5 产品开发
### 4.1.5 产品开发
在原型中验证了上述各种技术环节后,进入了实际的开发阶段。实际的代码量并不大,而且可以复用原型中写的大部分代码。所以很快就完成了开发工作。
### 4.2.6 用户文档
### 4.1.6 用户文档
开发完毕后,为了模拟真实的用户的客户端环境,木头特意找了一台 Windows 7 的机器,做数据上传和触发动作,没有发现任何问题。
然后木头写了一个用户文档,包括下载第三方软件并安装配置、路径设置、脚本运行方法等一系列操作的说明。小 P 根据这个文档做了一遍实际的操作,很顺利,就交给了用户。
### 4.2.7 系统切换
### 4.1.7 系统切换
一旦新系统上线,就有与旧的试验室系统并行或切换的问题。工程师石头负责旧的推理系统升级,以适应新的应用框架。

Просмотреть файл

@ -1,11 +1,11 @@
## 4.1 团队的类型
## 4.2 团队的类型
<img src="img/Slide3.JPG"/>
<img src="img/Slide4.SVG"/>
图 4.1.1 团队的阶层
图 4.2.1 团队的阶层
### 4.1.1 共同兴趣
### 4.2.1 共同兴趣
木头在小学时是上过音乐课的(不过好像所有人在小学时都有音乐课,所以木头也就失去了吹牛的资本,但那是木头唯一的一位音乐老师),每个同学都坐在一个右侧扶手即桌子的椅子上面,而音乐老师则坐在一架木制的旧钢琴后面,踩踏板发出的吱吱声音甚至比钢琴按键发出的声音还大。
@ -38,11 +38,11 @@
《构建之法》一书中的“一窝蜂团队、业余剧院团队”属于这个级别。
<img src="img/Slide4.JPG"/>
<img src="img/Slide5.SVG"/>
图 4.1.2 共同兴趣与共同规则
图 4.2.2 共同兴趣与共同规则
### 4.1.2 共同规则
### 4.2.2 共同规则
“星期四乐队”这帮人不靠这个组织挣钱,只是想发挥特长,活跃气氛;也没有太多的规则,想排一个歌,大家同意就排,用什么乐器也没什么讲究,自己会什么就用什么。只是大家商量好,知道哪个同事过生日的话,就当天到 ta 的座位旁唱一首生日歌,以便发挥音乐的魅力来团结、感染每一个人。
@ -75,7 +75,7 @@
《构建之法》一书中的“社区团队”属于这个级别。
### 4.1.3 共同利益
### 4.2.3 共同利益
随着乐队的壮大成员的身份也是五花八门性别大概是一半一半角色有工程师、PM、Designer、HR、行政助理、合同工等等各人的背景经历、语言行为习惯也各不相同这就会产生一些问题。
@ -105,11 +105,11 @@
《构建之法》一书中的“主治医师团队、明星团队、功能小组、爵士乐队”属于这个级别。
<img src="img/Slide5.JPG"/>
<img src="img/Slide6.SVG"/>
图 4.1.3 共同利益与共同文化
图 4.2.3 共同利益与共同文化
### 4.1.4 共同文化
### 4.2.4 共同文化
俗话说:小公司靠老板(以身作则,即规则执行)、中公司靠制度(规则 + 经济利益驱动),大公司靠文化(实际上是规则 + 利益 + 文化)。
@ -169,7 +169,7 @@
- 三个月后,那位原部门领导 V 退休回台湾省了。
### 4.1.5 共同信仰
### 4.2.5 共同信仰
宗教组织、党政团体是属于这种类型的,信念坚定,精神力量强大,可以忍受肉体的疼痛而赴汤蹈火,万死不辞。
@ -182,9 +182,9 @@
很多音乐人和商业化乐队在创办初期,入不敷出,凭着对音乐的热情与信仰,不顾亲人的劝阻,愣是可以坚持到出名。像朴树、许巍、赵雷、李健、汪峰,这些木头所敬仰的才华横溢的音乐人都是不到 30 岁时就已经崭露头角但是更多的音乐人和乐队是为了信仰而殉葬的ta 们的名字没人知道。正如朴树在《白桦林》里唱的:“天空依然阴霾依然有鸽子在飞翔,谁来证明那些没有墓碑的爱情和生命,雪依然在下那村庄依然安详,年轻的人们消逝在白桦林”,把歌词中的“爱情和生命”改成“音乐和信仰”就行了。
<img src="img/Slide6.JPG"/>
<img src="img/Slide7.SVG"/>
图 4.1.4 共同信仰与共同血脉
图 4.2.4 共同信仰与共同血脉
具有共同信仰的软件团队在软件行业很常见,比如很多的创业公司,他们跳跃了前面的“兴趣、规则、利益、文化”,直接拿“信仰”出来说事儿,和有共同信仰的人一同创业。
- 信仰是做事的宗旨、做事的目的、是企业的价值观。还记得那句“让天下没有难做的生意吗”就是这句话点燃了多少70、80后的热血成就了一个网络王国。
@ -194,7 +194,7 @@
《构建之法》一书中的“官僚模式、秘密团队、特工团队”属于这个级别。
### 4.1.6 共同血脉
### 4.2.6 共同血脉
这是团队的最高形式,这一点只有家族企业可以做到,企业内的领导者来自同一个家族,身体内流淌着相同的血脉,一荣俱荣,一损俱损。但是小企业还可以做到共同血脉,大企业中不可能要求员工也是共同血脉,那就灌输共同文化即可。

Просмотреть файл

@ -69,7 +69,7 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
### 4.4.2 个人在团队中如何做
<img src="img/Slide11.JPG"/>
<img src="img/Slide11.SVG"/>
图 4.4.1 个人与团队的关系
@ -157,7 +157,7 @@ A 人很好,总会安慰木头说“下次估计希望很大”,但下次 B
木头又要讲乐队的故事了,因为作为一个团队合作的典范,乐队太具有代表性了。
<img src="img/Slide12.JPG"/>
<img src="img/Slide12.SVG"/>
图 4.4.2 乐队就是典型的团队合作

Просмотреть файл

@ -1,5 +1,8 @@
## 4.5 团队之间的合作
<img src="img/Slide13.SVG"/>
### 4.5.1 建立通信
### 4.5.2 建立互信

Просмотреть файл

@ -6,6 +6,9 @@
在 MSRA通常一个导师会带 2~3 个实习生,承担数据处理、试验准备、模型训练、试验结果验证及总结、论文初稿等工作。所以导师与实习生构成了一个比较小的团队,在这样众多的小团队里也会发生一些故事。
<img src="img/Slide14.SVG"/>
#### 给定目标和范围
木头曾经带过一个实习生小 S他在某个视频网站上给大家讲高数中的学习难点给木头留下很深刻的印象觉得他思路清晰、口齿伶俐、乐于助人所以就招聘了他。入职后给他分配第一项任务“小 S这里有几篇论文都是关于古典音乐作曲的 AI 模型的,你都看一看,然后挑出一篇来重点研究。” 小 S 很痛快地答应了。
@ -38,7 +41,7 @@
两周后发现小 S 没有任何进展,木头说:“要不然你提前结束实习了吧?我觉得你的实际动手能力不太符合我们的要求。” 小 S 没说话,回去后给 HR 写了封邮件,投诉了木头:“该导师不能根据实习生的实际情况合理安排工作,总是出难题,态度生硬,理由粗暴,还想让我提前结束实习,这样的话我回到学校无法和老师交代,我需要该导师给我赔礼道歉。”
HR 这种事情见得多了,影响最不好的一次是有个实习生在某社交媒体上大放厥词说实习经历如何如何的糟糕博得大家同情。为了避免这些不必要的麻烦HR 和小 S 商量,可以给他出具实习证明和一个合适的提前结束实习的理由,才算平息此事。
HR 这种事情见得多了,影响最不好的一次是有个实习生在某社交媒体上大放厥词,说实习经历如何如何的糟糕博得大家同情。为了避免这些不必要的麻烦HR 和小 S 商量,可以给他出具实习证明和一个合适的提前结束实习的理由,才算平息此事。
### 3.5.2 流程与注意事项

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 47 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 45 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 94 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 86 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 86 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 41 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 128 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 132 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 762 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 180 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 84 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 44 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 82 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 83 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 26 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 89 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 81 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 58 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 57 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 59 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 117 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 71 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 95 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 68 KiB

Просмотреть файл

@ -0,0 +1,72 @@
接下来,我们用一个简单的实例来进行说明:
案例:用户自助寄件的需求
业务建设方:某快递公司
需求描述:目前很多城市的小区都已经有了快递柜,但快递柜主要是用于送件使用,而对于快递公司收件,用得比较少,某快递公司,就希望利用快递柜,来实现用户自助寄件的需求。
首先,我们来分析其业务需求
这个案例的业务建设方是:快递公司,其业务需求也很明确,就是:用户自助寄件。
业务方之所以要建设这个需求,其目的是:希望利用快递柜,实现更高效的收件服务,减少人工上门收件的等待、低效、人力投入成本高等问题。
其次,我们来看用户需求
这个案例的用户,就是每一个要寄快递的人,那么他们的需求是什么了?
他们的需求,其实就是在进行“自助寄件”的过程中,你尽量让我简单、易用,高效、快捷。
接下来,我们进行需求分析的转化
需求分析的转化,核心是两个点,一是对这个业务的场景进行充分的理解和认知,二是想明白业务场景中需求点,要通过何种方式来满足它。
业务需求是“用户自助寄件”这个业务要实现我们结合寄快递的实际场景其实还是蛮容易就能想到有3个关键环节
用户要填写单据:即填写收发件人的相关信息;
用户要能找到周边的快递柜,并且能打开它;
还需要进行计量、支付快递费的问题
这三个环节,基本把这个业务的三个关键阶段说明出来了,它就是:填单——>找柜子放件——>支付。
然后,逐一对三个阶段进行具体的分析:
填单阶段:
业务方需求:必须收件人、联系电话、寄件人信息清楚、明确等等。
用户需求:能选的就选,能简单填写的就简单填。
转化为功能需求,你发现,无非是通过表单形式让用户把相关信息填上来,而为了满足用户需求,你肯定需要设计对收件人的记忆功能,让用户填写一次,后续每次只需要选择而已(相关的细节还很多,这里只做举例)。
找柜子放件阶段:
业务需求:把最方便最合适的柜子告诉用户,并确保用户能安全、准确的找到快递柜、放入快递件;
用户需求:我就想知道我要把快递件放到哪里,别让我多走;
这个业务需求和用户需求说起来简单,转化成功能需求时,其实里面还蛮多细节的:
位置服务肯定需要,一是为满足发现柜子的需求,二是也有导航的需求;
如何打开柜子呢?从我们的产品经验或者竞品参考来看,可以有扫描开启、验证码等方式;
如何保证用户去到快递柜,一定就有其空的柜子可以给他放了,这里面就涉及一个快递柜忙闲资源的管理;
所以,这里转化为功能需求时,你发现:有位置服务功能、扫描开启/验证码开启功能,柜子资源分配管理功能等;
支付阶段:
业务需求:根据收费标准,准确无误、及时收到用户快递费。
用户需求:支付方便。
功能需求:
如何来计量,由于是自助寄件,称重显然不合适,那么按体积是一种较简便的方式,而如何按体积了,其实根据可快递柜的柜子;
如何支付,这个还简单,可以使用比较常用的几种支付方式就好;
以上,都只是简单的需求分析和转化的过程,实际的需求过程中,我们经常讲需要结合业务场景、用户场景把一些关键细节挖掘出来,并能在产品设计时考虑进去,以给用户一个良好的体验。
业务场景细节的挖掘
比如:在上面的开启柜子的方式中,到底用扫描开启还是验证码的方式呢?
其实用“验证码开启”会更合适,因为会存在很多这样的场景,某个寄快递的人,刚好家里有人下楼,或者认识的邻居下楼,而快递柜就在小区门口,那么找人代劳一下放件是一种很正常的事情,那么这时候,使用验证码就是一种最合适、简便的方式。
又比如:某用户希望自己的快递能更快的被寄出去。
那么,如果在给用户呈现周边分布的快递柜的同时,还告诉用户,该快递柜的收件时间,目前快递员的分布位置,是不是能让用户更好的去选择呢。
这样的细节还很多,需要在实际分析中,更好的去理解用户场景、挖掘细节,并逐步的完善。
通过上面的分析,我们发现,只要你充分认清楚业务需求方的诉求、用户在执行具体任务时的诉求,并对产品的常规实现方式有了解的话,需求分析并不是一个多复杂的过程,就是这么一步步去推理、去转化的过程。
而要把每个细节做透,就必须在实际中多去磨练,在生活中多体验,学会场景化的思维方式。
本节的内容就是这些,如果大家喜欢我的内容,请关注连载内容。

Просмотреть файл

@ -35,8 +35,7 @@
### 参考资料
- [1] 《软件工程》,清华大学出版社
- [2] 周金根《软件需求的三个层次》http://www.zhoujingen.cn/itbang/352.html
- [3] 李鸿君,大话软件工程《需求分析与软件设计》,清华大学出版社
- [4] Difference Between Aggregation and Composition, https://techdifferences.com/difference-between-aggregation-and-composition.html
- [5] 杨长春,《实战需求分析》,清华大学出版社
- 《软件工程》,清华大学出版社
- 《大话软件工程 需求分析与软件设计》,李鸿君,清华大学出版社
- 《实战需求分析》,杨长春,清华大学出版社
- Difference Between Aggregation and Composition, https://techdifferences.com/difference-between-aggregation-and-composition.html

Просмотреть файл

@ -21,7 +21,7 @@
- 校长主要是讲政策方面的内容,以及国家对学校、企业的期望,是一个宏观的大需求;
- 教务处主任从教材入手,反映了目前高校存在的 AI 教育的普遍问题即难度大学生不易听懂。所以主任的需求很简明扼要提供一门让学生能够听懂的AI课程。
我们把这种需求叫做业务需求(因为需求来自业务管理者)。
我们把这种需求叫做业务需求(因为需求来自业务管理者)或客户需求(客户代表一个法人或者一个企业,并非指某个具体的人)
<img src="img/Slide15.JPG"/>

Просмотреть файл

@ -14,7 +14,7 @@
从系统分析出发,可将需求分析方法大致分为功能分解方法、结构化分析方法、信息建模法和面向对象的分析方法。$^{[1]}$
#### 功能分解方法
#### 1. 功能分解方法
将新系统作为多功能模块的组合,各功能也可分解为若干子功能及接口,子功能再继续分解,便可得到系统的雏形,即公式 7.6.1 所示:
@ -24,7 +24,7 @@ $$
对于一个比较小的软件,或者是一个大系统中的局部功能,可以使用这种简便的方法。
#### 结构化分析方法
#### 2. 结构化分析方法
结构化分析方法是由数据流图和数据词典构成并表示,所以此分析法又称为数据流法。其基本策略是跟踪数据流,即研究问题域中数据流动方式及在各个环节上所进行的处理,从而发现数据流和加工方法。结构化分析可定义为数据流、数据处理或加工、数据存储、端点、处理说明和数据字典。
@ -38,7 +38,7 @@ $$
结构化分析法和下面要说的面向对象分析法,并不是对立的,二者可以配合使用。因为在刚开始进行分析时,不可能马上就能发现真正的“对象”,而用数据流图可以重现真实需求,帮助分析人员逐步进入状态,这也是笔者多年的经验。
#### 信息建模方法
#### 3. 信息建模方法
信息建模可定义为实体或对象、属性、关系、父类型/子类型和关联对象。此方法的核心概念是实体和关系,最初由 P.P.S. Chen 在1976年提出基本工具是 E-R 图。1981年 M.Flavin 改进后称之为信息建模法,后来又发展为语义数据建模法,并引入了面向对象的特定。其基本要素由实体、属性和联系构成。该方法的基本策略是从现实中找出实体,然后再用属性进行描述。
@ -50,7 +50,7 @@ $$
\end{aligned} \tag{7.6.3}
$$
#### 面向对象的分析方法
#### 4. 面向对象的分析方法
面向对象的分析方法的关键是识别问题域内的对象,分析它们之间的关系,并建立三类模型,即:
@ -83,11 +83,11 @@ OOAObjec-Oriented Analysis面向对象的分析方法目前已经衍
现在广泛使用的 OOA 方法有以下几种:
#### Booch 方法
#### 1. Booch 方法
Booch 方法包含“微开发过程”和“宏开发过程”。微开发过程定义了一组任务并在宏开发过程的每一步骤中反复使用它们以维持演进途径。Booch OOA 宏开发过程的任务包括标识类和对象、标识类和对象的语义、定义类与对象间的关系,以及进行一系列求精从而实现分析模型。
#### Rumbaugh 方法
#### 2. Rumbaugh-OMT 方法
Rumbaugh 和他的同事提出的对象模型化技术OMT用于分析、系统设计和对象级设计 。分析活动建立三个模型对象模型描述对象、类、层次和关系动态模型描述对象和系统的行为功能模型类似于高层的DFD描述穿越系统的信息流
@ -134,7 +134,7 @@ Rumbaugh 和他的同事提出的对象模型化技术OMT用于分析、
功能模型表明了系统中数据之间的依赖关系以及有关的数据处理功能它由一组数据流图组成。其中的处理功能可以用IPOInput/Processing/Output输入/处理/输出)图(或表)、伪码等多种方式进一步描述。通常在建立对象模型和动态模型之后再建立功能模型。
#### Coad 和 Yourdon 方法
#### 3. Coad/Yourdon 方法
Coad 和 Yourdon 方法常常被认为是最容易学习的 OOA 方法。建模符号相当简单,而且开发分析模型的导引直接明了。其 OOA 过程概述如下:
@ -145,15 +145,15 @@ Coad 和 Yourdon 方法常常被认为是最容易学习的 OOA 方法。建模
5. 定义属性及对象之间的实例连接;
6. 定义服务及对象之间的消息连接。
#### Jacobson方法
#### 4. Jacobson-OOSE 方法
也称为 OOSE面向对象软件工程。Jacobson方法与其他方法的不同之处在于他特别强调使用实例use case——用以描述用户与系统之间如何交互的场景。Jacobson方法概述如下
也称为 OOSE面向对象软件工程。Jacobson 方法与其他方法的不同之处在于他特别强调使用实例use case描述用户与系统之间如何交互的场景。Jacobson 方法概述如下:
1. 标识系统的用户和它们的整体责任;
2. 通过定义参与者及其职责、使用实例、对象和关系的初步视图,建立需求模型;
3. 通过标识界面对象、建立界面对象的结构视图、表示对象行为、分离出每个对象的子系统和模型,建立分析模型。
#### Wirfs-Brock 方法
#### 5. Wirfs-Brock 方法
Wirfs-Brock 方法不明确区分分析和设计任务。从评估客户规格说明到设计完成,是一个连续的过程。与 Wirfs-Brock 分析有关的任务概述如下:
@ -167,7 +167,7 @@ Wirfs-Brock 方法不明确区分分析和设计任务。从评估客户规格
8. 建立类的层次表示;
9. 构造系统的协作图。
#### 统一的OOA方法UML
#### 6. 统一的OOA方法UML
统一的建模语言UML已经被广泛使用它把 Booch、Rumbaugh和Jacobson 等各自独立的 OOA 和 OOD 方法中最优秀的特色组合成一个统一的方法。在 UML 中用 5 种不同的视图来表示一个系统,这些视图从不同的侧面描述系统。每一个视图由一组图形来定义。这些视图形成一个序列,如图 7.6.3 所示:
@ -182,19 +182,19 @@ Wirfs-Brock 方法不明确区分分析和设计任务。从评估客户规格
也可以叫做功能模型。
这个视图从用户( 在UML中叫做参与者角度来表示系统。它使用用例use case来建立模型并用它来描述来自终端用户方面的可用的场景6.7 节中讲述。
这个视图从用户( 在UML中叫做参与者角度来表示系统。它使用用例use case来建立模型并用它来描述来自终端用户方面的可用的场景7.7 节中讲述。
2. 结构模型视图
也可以叫做对象模型。
从系统内部来看数据和功能,即对静态结构(类、对象和关系)模型化,在 6.8 节中讲述。
从系统内部来看数据和功能,即对静态结构(类、对象和关系)模型化,在 7.8 节中讲述。
3. 行为模型视图
也可以叫做动态模型。
这种视图表示了系统状态和行为,还描述了在用户模型视图和结构模型视图中所描述的各种结构元素之间的交互和协作,在 6.9 节中讲述。
这种视图表示了系统状态和行为,还描述了在用户模型视图和结构模型视图中所描述的各种结构元素之间的交互和协作,在 7.9 节中讲述。
4. 实现模型视图
@ -202,9 +202,9 @@ Wirfs-Brock 方法不明确区分分析和设计任务。从评估客户规格
5. 环境模型视图
表示系统实现环境的结构和行为,在本书的第 5 部分中讲述。
表示系统实现环境的结构和行为,在本书的第 6 部分中讲述。
通常UML 需求分析建模的注意力放在系统的用户模型和结构模型视图,而 UML 系统设计建模则定位在行为模型、实现模型和环境模型。但是正如 6.9 节中将要学习到的,行为模型有两种:一种是还原现实世界的行为,属于需求分析的范畴;另外一种是在计算机的数字世界中设计新的行为模型,后者是对前者的抽象和扩充。
通常UML 需求分析建模的注意力放在系统的用户模型和结构模型视图,而 UML 系统设计建模则定位在行为模型、实现模型和环境模型。但是正如 7.9 节中将要学习到的,行为模型有两种:一种是还原现实世界的行为,属于需求分析的范畴;另外一种是在计算机的数字世界中设计新的行为模型,后者是对前者的抽象和扩充。
### 7.6.3 小结
@ -214,11 +214,11 @@ Wirfs-Brock 方法不明确区分分析和设计任务。从评估客户规格
表 7.6.1 - 各种需求方法的比较
|步骤|功能分解法|结构化分析法|信息建模法|面向对象法|UML法|
|步骤|功能分解法|结构化分析法|信息建模法|OMT 法|UML 法|
|--|--|--|--|--|--|
|1. 描述原始需求|功能|系统关系图,顶层数据流图|原始信息|功能模型|用户模型|
|2. 提取静态结构|子功能|数据存储,端点|对象和属性|对象模型|结构模型|
|3. 捕捉动态行为|功能接口|数据处理,数据流|关系类型,关联对象|动态模型|行为模型|
|1.描述原始需求|功能|系统关系图,顶层数据流图|原始信息|功能模型|用户模型|
|2.提取静态结构|子功能|数据存储,端点|对象和属性|对象模型|结构模型|
|3.捕捉动态行为|功能接口|数据处理,数据流|关系类型,关联对象|动态模型|行为模型|
表 7.6.1 的内容,需要对各种方法仔细研究后才能理解,最后的结论是,无论哪种方法,都可以异曲同工地达到需求分析的目的,所以在实践中可以选取一种方法为主导,混用一些其它的自己熟悉的分析方法。

Просмотреть файл

@ -1,67 +0,0 @@
- 高并发的设计
- 异地灾备的设计
- 消息队列的设计
- 微信系统的设计(点对点通信)
- 微博系统的设计(消息订阅,发布)
- 异地访问延迟
- 高性能
- 微服务
- 语音系统的设计
- 地图系统的设计
软件工程的三要素:方法、工具、过程
方法
方法一词的产生有两个由来:
1. 与工匠有关。
墨子说:“轮人(做车的工匠)操其规,将以度量天下之圆与不方圆。曰中吾规者谓之圆,不中吾规者谓之不圆,则圆法明也。匠人亦操其矩,将以度量天下之方与不方也。曰中吾矩者谓之方,不中吾矩者谓之不方,则**方法**明也。” 大概意思是做木工活的时候,工匠用特殊的工具来度量木材是否是圆的或方的,由此我们知道了**规矩**和**方法**的来历,只是**圆法**这个词并没有流传下来。
2. 与中医有关。
传说我国古代有一位皇帝患上了噎膈病,进食即吐,找了很多医生开了许多方子,都没有见效。最后请来一位隐居的和尚,经过一番望、闻、问、切,拟出一方,让太监速去取药。可太监拿到药方后,不由一愣,自言自语道:“什么高明医术?这不和之前医生所开方药一模一样吗?” 和尚拿过前医所开药方一看,药味、药量均与他分毫不差,但只是沿用传统的水煎口服,而皇帝现如今是滴水不进,何况药液?于是和尚亲自把药熬好,并浓缩到只剩下两匙勺,让皇帝拿小勺把药盛到嘴里用舌头慢慢舔尽,如此反复直至把药液舔完为止。连服数剂药之后,病果然大有起色。
和尚解释说:“医者,既要有方,又要有法。前医之方虽对症,但用法不对。皇上饮药反胃都吐了出来,自然不能发挥作用;而我让皇上舔取精华,量少而不反胃,乃是据症选法。” 皇帝听后,恍然大悟说道:“方法,方法,**方**与**法**结合也。” 从此,便产生了**方法**一词。
所以,方法其实是由“方”和“法”组成,方法既规矩,是一种知识体系或衡量标准。
软件工程中的方法
功能分解法
结构化分析法
结构化设计法
信息建模法
面向对象分析法
面向对象设计法
方法
工具
过程
道:思想
法:方法
术:技术
器:工具
https://zhuanlan.zhihu.com/p/137343992
https://blog.csdn.net/weixin_43914604/article/details/105047495
https://blog.csdn.net/weixin_44529208/article/details/106359025?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-106359025-blog-105047495.pc_relevant_recovery_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-106359025-blog-105047495.pc_relevant_recovery_v2&utm_relevant_index=21
甲乙两个人
【slide】
比如Bing Ads Team 一直想为广告客户(出钱在 Bing Search 针对用户的 Keyword 做广告的商家)提供一套推荐机制,

Просмотреть файл

@ -1,6 +1,6 @@
## 10.1 原型开发的目的
## 11.1 原型开发的目的
### 10.1.1 木头与 UWP 原型开发的故事
### 11.1.1 木头与 UWP 原型开发的故事
UWPUniversal Windows Platform统一 Windows 平台),是微软在 Windows 10 上的战略,在任何微软设备上,如 Surface Hub、Desktop、Laptop、HoloLens、Windows Phone 上,都运行同一套操作系统。因此,在 UWP 的基础上开发的 APP可以无缝部署到任何设备上而无需额外的移植工作。
@ -12,14 +12,14 @@ Designer 在自己的手机上看到 Demo 后,感觉字号不对,就来和
<img src="img/Slide3.JPG"/>
图 10.1.1 - UWP 原型开发
图 11.1.1 - UWP 原型开发
从图 10.1.1 中可以看到左侧为软件开发栈从下到上依次是Windows 10PreivewPC 操作系统、SDK 10Preview、SimulatorPreview模拟器右侧为硬件部署栈从下到上依次为Lumia 640Trial手机、Windows Phone 10Preview手机操作系统、UWPPrototype软件。整个技术架构是名副其实的“原型”从软件到硬件从操作系统到开发工具包全都是在原型阶段只不过大家的称谓不同Preview、Trial、Prototype原型的成熟度也不同。最终的 UWP APP 可以在这个环境中诞生、部署、运行,也是非常不容易的一件事,怪不得 Designer 会很兴奋。
从图 11.1.1 中可以看到左侧为软件开发栈从下到上依次是Windows 10PreivewPC 操作系统、SDK 10Preview、SimulatorPreview模拟器右侧为硬件部署栈从下到上依次为Lumia 640Trial手机、Windows Phone 10Preview手机操作系统、UWPPrototype软件。整个技术架构是名副其实的“原型”从软件到硬件从操作系统到开发工具包全都是在原型阶段只不过大家的称谓不同Preview、Trial、Prototype原型的成熟度也不同。最终的 UWP APP 可以在这个环境中诞生、部署、运行,也是非常不容易的一件事,怪不得 Designer 会很兴奋。
### 10.1.2 为什么需要原型?
### 11.1.2 为什么需要原型?
建立原型的主要目的是为了解决在产品开发的早期阶段不确定的问题。这种不确定性来自多个方面,如图 10.1.2 所示的四个主要方面:
建立原型的主要目的是为了解决在产品开发的早期阶段不确定的问题。这种不确定性来自多个方面,如图 11.1.2 所示的四个主要方面:
- 上方:来自甲方的需求;
- 下方:来自乙方的设计;
- 左侧:来自工程领域的选型;
@ -27,12 +27,12 @@ Designer 在自己的手机上看到 Demo 后,感觉字号不对,就来和
<img src="img/Slide4.JPG"/>
图 10.1.2 - 原型开发的目的
图 11.1.2 - 原型开发的目的
下面我们依次解释这四个方面的细节:
1. 来着甲方:用户需求的确认和引导
#### 1. 来着甲方:用户需求的确认和引导
用户通常描述不清楚他们的真实想法,开发团队需要尽快做出一个原型,让用户看到界面,并亲自动手来体验交互过程,输入一些仿真的数据,得到仿真的输出结果。如果用户对原型不满意,可以改进它直到用户满意为止;或干脆丢弃它,开发一个全新的系统。
@ -44,16 +44,16 @@ Designer 在自己的手机上看到 Demo 后,感觉字号不对,就来和
- Designer 选择使用卷滚条来呈现多于一屏的内容,但用户觉得卷滚条比较难以操作,还是用“上一页、下一页”这样的分页模式比较好。
2. 来自乙方:验证概念的可行性
#### 2. 来自乙方:验证概念的可行性
微软的用户服务团队有一个传统做法叫做 POCProof of Concept概念验证即有了一个新的想法或设计但是需要一系列的验证才能最终证明是可行的。它可能是上面的三点的综合更重要的是要跑通 e2eend to end的业务逻辑所有的关键点都是用真实的技术但是代码质量可以是粗糙的。
<img src="img/Slide5.JPG"/>
图 10.1.3 - 手写单据数字化业务流程
图 11.1.3 - 手写单据数字化业务流程
木头遇到的一个真实的故事是:银行客户需要处理历史遗留下来的纸质单据,数字化后存入计算机系统。这个处理系统的流程如图 10.1.3 所示:
木头遇到的一个真实的故事是:银行客户需要处理历史遗留下来的纸质单据,数字化后存入计算机系统。这个处理系统的流程如图 11.1.3 所示:
- 批量扫描纸质单据;
- 通过 OCROptical Character Recognition光学字符识别模型做脱机手写体汉字识别得到文本
@ -66,7 +66,7 @@ Designer 在自己的手机上看到 Demo 后,感觉字号不对,就来和
通过 POC 过程,服务团队决定暂时不向客户提交方案,避免因关键技术环节的准确率不过关而影响项目的整体质量。
3. 来自工程领域:技术选型的合理性
#### 3. 来自工程领域:技术选型的合理性
在底层技术支持问题上,有时候还会有多种选择,同样也会造成烦恼。比如系统需要每天都存储一个大的数据文件,在 Azure 上,有可能的选择有:磁盘、块存储、数据库、热存储等等。开发团队需要考虑以下一些因素:
@ -82,7 +82,7 @@ Designer 在自己的手机上看到 Demo 后,感觉字号不对,就来和
我们在 10.2 节中专门讨论这个问题。
4. 来自科研领域:新技术实现可行性
#### 4. 来自科研领域:新技术实现可行性
有些功能以前没有做过,需要一种新的软硬件技术的支持。在确定要使用这些新技术之前,开发人员需要做一些探索性的试验,验证技术可行性,包括功能和性能两个方面。

Просмотреть файл

@ -1,10 +1,10 @@
## 10.2 技术选型
## 11.2 技术选型
### 10.2.1 技术选型原则
### 11.2.1 技术选型原则
<img src="img/Slide6.JPG"/>
图 10.2.1 - 技术选型的原则
图 11.2.1 - 技术选型的原则
做技术选型要考虑以下几个方面:
@ -29,7 +29,7 @@
当然,一个技术不可能满足所有这些要求,这和 6.5 节中讲的非功能需求中的“好、快、省”是一个道理。
### 10.2.2 项目的故事
### 11.2.2 项目的故事
木头参与的一个真实项目,虽然不怎么大,但是麻雀虽小五脏俱全。无论规模如何,都要全力以赴,谨慎对待。
@ -43,16 +43,16 @@
<img src="img/Slide7.JPG"/>
图 10.2.2 - 系统架构
图 11.2.2 - 系统架构(这张图换一个)
图 10.2.2 展示了本系统的逻辑架构图,针对每个部分,我们下面讨论都需要做哪些技术选择。
图 11.2.2 展示了本系统的逻辑架构图,针对每个部分,我们下面讨论都需要做哪些技术选择。
### 10.2.3 存储技术选择
### 11.2.3 存储技术选择
我们首先解决存储问题,因为股票数据的量还是比较大的,而且还要保存历史数据。
表 10.2.1 - Azure上的存储技术列表
表 11.2.1 - Azure上的存储技术列表
|技术|描述|特点|价格(月)|
|--|--|--|--|
@ -63,11 +63,11 @@
|存档|在存储不常访问的数据方面具有优势的行业价格|自动加密静态数据、与热存储层和冷存储层无缝集成、由领先的数据管理合作伙伴支持|$0.001/GB|
|HPC 缓存|用于高性能计算的文件缓存|加快对基于文件的大型工作负荷的数据访问、支持 Azure 现有的 HPC 工作负荷、简化存储资源管理|$29/GB|
表 10.2.1 列出了 Azure 上的主要存储技术,可以用图 10.2.3 简要概括:
表 11.2.1 列出了 Azure 上的主要存储技术,可以用图 11.2.3 简要概括:
<img src="img/Slide8.JPG"/>
图 10.2.3 - 存储技术选择
图 11.2.3 - 存储技术选择
其中两个比较特殊的是磁盘和 HPC 缓存:
@ -89,13 +89,13 @@
使用 Azure Blob 后,由于它提供 REST API 是外部可访问的,且性能很高,所以相当于这个系统有了一个唯一的存储点,避免分散管理或者共享带来的麻烦。
### 10.2.4 上传、下载技术选择
### 11.2.4 上传、下载技术选择
确定存储技术后,紧接着是确定如何读写存储。
<img src="img/Slide9.JPG"/>
图 10.2.4 - 文件传输技术选择
图 11.2.4 - 文件传输技术选择
如果存储选择“块存储”技术的话,那么客户端的上传和下载,自然而然地就解决了,因为 Azure Blob 提供了 AzCopy.exe 客户端程序,安全性、性能、稳定性都没有问题,不需要我们在客户端开发软件了,只需要用批处理脚本调用 AzCopy.exe指定合适的参数即可。
@ -136,7 +136,7 @@
直到最后我们也没有能说服这个学生改变他的想法,因为在他看来,只要是网上开源的软件就都可以使用;而在我们工程师看来,要遵守微软的商业准则、维护公司形象,要确保系统运行稳定可靠,慎用第三方软件和服务。在可以使用已有产品的地方,绝不开发新的产品。比如 AzCopy有一个专业的 team 在维护,其稳定性、安全性、性能等等肯定比任何其它方法都要好。
### 10.2.5 模型试验管理技术选择
### 11.2.5 模型试验管理技术选择
模型管理在传统软件工程中是不存在的,只有在训练机器学习或深度学习模型时才会用到。
@ -159,12 +159,12 @@
<img src="img/Slide10.JPG"/>
图 10.2.5 - 文件传输技术选择
图 11.2.5 - 文件传输技术选择
ML-flow 是基于 Python 环境的,所以需要一台虚拟机部署,木头选择了一台 Windows 2019 Server当然也可以选择 Linux Ubuntu 19由于我们的应用都是在 Python 上,所以区别不大。它既能够管理模型,也可以把代码当作模型的附属一并管理,这样就省去了单独管理代码但是又需要和模型匹配的麻烦。
### 10.2.6 训练、预测实例化技术选择
### 11.2.6 训练、预测实例化技术选择
我们的研究员都是用 Pytorch 做模型训练,所以预测也要使用 Pytorch这样软件就定了我们要选择的是硬件。
@ -175,7 +175,7 @@ ML-flow 是基于 Python 环境的,所以需要一台虚拟机部署,木头
木头又看了一下容器技术,在 Azure 上,是需要事先申请好计算资源池,然后在池中创建容器的,所以并不能省钱。况且容器技术是一种微服务,对本场景来说并不适合。
### 10.2.7 控制中心的编程框架技术选择
### 11.2.7 控制中心的编程框架技术选择
首先要确定软件开发环境。因为训练、预测、模型管理都使用了 Python所以我们干脆也用 Python 来实现控制门户吧,代码管理方便,部署环境一致,技术栈统一。

Просмотреть файл

@ -1,15 +1,15 @@
## 10.3 原型模型
## 11.3 原型模型
### 10.3.1 水平原型与垂直原型
### 11.3.1 水平原型与垂直原型
<img src="img/Slide11.JPG"/>
图 10.3.1 - 水平原型与垂直原型
图 11.3.1 - 水平原型与垂直原型
#### 水平原型
在 10.1.2 中的第1点用户需求确认及引导就是水平原型也叫做行为原型behavioral prototype。在图 10.3.1 左侧的子图中功能A/B/C/D构成了水平原型一般是指的用户界面。用户才不会关心你后面是如何实现的只要界面满足要求即可所以水平原型一般是给用户或者业务人员看的。
在 10.1.2 中的第1点用户需求确认及引导就是水平原型也叫做行为原型behavioral prototype。在图 11.3.1 左侧的子图中功能A/B/C/D构成了水平原型一般是指的用户界面。用户才不会关心你后面是如何实现的只要界面满足要求即可所以水平原型一般是给用户或者业务人员看的。
这类原型只是绘制了主用户界面,而无需进行任何实质性编码,以便用户能够感受到实际系统的外观。
@ -17,15 +17,15 @@
#### 垂直原型
在 10.1.2 中的第2点验证概念可行性就是垂直原型vertical prototype也叫做结构化原型或概念证明实现了一部分应用功能。在图 10.3.1 的右侧子图中功能C/C1/C2/C3形成了一个垂直原型在实现过程中应用要使用的技术搭建业务链比如界面、组件、数据访问、数据库等在模拟出来的或真实的环境中运行确保输入和真实环境一致看看输出是否满足预期。
在 10.1.2 中的第2点验证概念可行性就是垂直原型vertical prototype也叫做结构化原型或概念证明实现了一部分应用功能。在图 11.3.1 的右侧子图中功能C/C1/C2/C3形成了一个垂直原型在实现过程中应用要使用的技术搭建业务链比如界面、组件、数据访问、数据库等在模拟出来的或真实的环境中运行确保输入和真实环境一致看看输出是否满足预期。
图 10.3.1 右侧子图中其它三条线A/B/D可能由于业务链较短技术较为成熟所以不需要搭建垂直原型。
图 11.3.1 右侧子图中其它三条线A/B/D可能由于业务链较短技术较为成熟所以不需要搭建垂直原型。
### 10.3.2 低保真原型和高保真原型
### 11.3.2 低保真原型和高保真原型
<img src="img/Slide12.JPG"/>
图 10.3.2 - 低保真和高保真原型
图 11.3.2 - 低保真和高保真原型
@ -39,9 +39,9 @@
通过使用这个原型,客户可以对系统有一个真实的感觉,因为与原型的交互可以使客户更好地理解所需系统的需求。
表 10.3.1 展示了两种原型的对比。
表 11.3.1 展示了两种原型的对比。
表 10.3.1 - 低保真和高保真原型对比$^{[3]}$
表 11.3.1 - 低保真和高保真原型对比$^{[3]}$
||低保真原型|高保真原型|
|--|--|--|
@ -52,20 +52,20 @@
|缺点|交互性有限,需要使用者自己脑补细节,可测试性弱|费时,需要专业人员制作|
### 10.3.3 抛弃型原型或进化型原型
### 11.3.3 抛弃型原型或进化型原型
从原型存在生命时机考虑分为抛弃型原型和进化型原型。
<img src="img/Slide13.JPG"/>
图 10.3.3 - 抛弃型原型或进化型原型
图 11.3.3 - 抛弃型原型或进化型原型
#### 抛弃型原型
抛弃型原型不作为最终产品的一部分,只是作为探索性的回答一些需求问题,细化需求并提高需求质量。由于在开发阶段最终将抛弃这些原型,因此不需要花太大力气去建立该原型。$^{[1]}$
木头曾参与一个与 Azure 相关的项目,在原型阶段,木头让实习生调研了启动虚拟机和获得虚拟机 IP 地址的功能。实习生为了方便起见,使用了 Azure CLICommand Line Interface命令行接口来控制虚拟机于是写了图 10.3.2 中左图所示的代码片段,其中,红色框(启动虚拟机)和黄色框(列 IP 地址)内的源代码片段,如:
木头曾参与一个与 Azure 相关的项目,在原型阶段,木头让实习生调研了启动虚拟机和获得虚拟机 IP 地址的功能。实习生为了方便起见,使用了 Azure CLICommand Line Interface命令行接口来控制虚拟机于是写了图 11.3.2 中左图所示的代码片段,其中,红色框(启动虚拟机)和黄色框(列 IP 地址)内的源代码片段,如:
```
os.system('az vm start ...')
@ -82,7 +82,7 @@ os.system('az vm start ...')
#### 进化型原型
同样用图 10.3.2 中绿色框所示的代码为例,就是一种比较浅显的进化型原型的例子,右侧的代码基本继承了左侧代码的逻辑,写法不同而已。
同样用图 11.3.2 中绿色框所示的代码为例,就是一种比较浅显的进化型原型的例子,右侧的代码基本继承了左侧代码的逻辑,写法不同而已。
从大的方面讲,进化型原型一般在处理架构时会采用,这和 MVPMinimum Viable Product最小可用产品有异曲同工之妙。即
1. 可以不实现全部系统,而只写核心业务逻辑的代码作为进化型原型,并且保证质量;
@ -91,17 +91,17 @@ os.system('az vm start ...')
3. 然后再继续改进进化型原型,增加更多的功能或者提高鲁棒性等等,向真正的产品进化。
仍以图 10.3.1 中的垂直原型为例我们可以先用C1做成进化型原型简化的有限功能子集而把C2/C3看作抛弃型原型这样整个功能C就可以跑通了。然后再改进C1或者把C2再变成进化型原型。如此进化功能C最终就变成实际产品了。
仍以图 11.3.1 中的垂直原型为例我们可以先用C1做成进化型原型简化的有限功能子集而把C2/C3看作抛弃型原型这样整个功能C就可以跑通了。然后再改进C1或者把C2再变成进化型原型。如此进化功能C最终就变成实际产品了。
### 10.3.4 原型分类与流程总结
### 11.3.4 原型分类与流程总结
<img src="img/Slide14.JPG"/>
图 10.3.4 - 抛弃型原型或进化型原型
图 11.3.4 - 抛弃型原型或进化型原型
图 10.3.4 横向看:
图 11.3.4 横向看:
- 作为一种需求分析工具,明确并完善需求原型,它初步实现所理解的系统的一部分。
@ -109,18 +109,18 @@ os.system('az vm start ...')
- 作为一种开发工具,发展为最终的产品原型,是产品最初子集的完整功能实现,通过一系列小规模的开发循环后可以完成整个产品的开发。
图 10.3.4 纵向看:
图 11.3.4 纵向看:
- 在面向用户界面部分PM 和 Designer 需要多与用户进行交流,得到反馈,不断改进原型,成为真实产品;
- 在面向系统架构部分,系统设计人员需要与开发人员多进行交流,及时了解业界最新或最成熟技术方案,抛弃原型中的替代品,开发简化版组件,并最终进化成实际产品组件。
图 10.3.5 说明了在原型模型中执行的步骤。
图 11.3.5 说明了在原型模型中执行的步骤。
<img src="img/Slide15.JPG"/>
图 10.3.5 - 原型开发流程
图 11.3.5 - 原型开发流程
1. 需求调研和分析:原型模型从需求分析开始,详细定义系统的需求。访问用户以了解系统的需求。
@ -136,7 +136,7 @@ os.system('az vm start ...')
6. 形成工程产品:一旦完全满足要求,用户接受最终原型。对最终系统进行全面评估,形成稳定的产品。
### 10.3.5 原型工具
### 11.3.5 原型工具
这里说的原型工具主要是针对水平原型来说的,即用户界面层。
@ -150,10 +150,10 @@ os.system('az vm start ...')
<img src="img/Slide16.JPG"/>
图 10.3.6 - 原型界面只是冰山的顶端
图 11.3.6 - 原型界面只是冰山的顶端
我们可以通过原型来引导用户来使用系统解决问题,但原型不仅仅是需求,它还是设计、开发工具,所以作原型时不仅需要客户的参与,也需要技术人员的参与,但应该尽量由业务人员而非开发人员来实现原型的需求部分。
图 10.3.6 在 UCD 社区里面看到的一张图,原型最主要功能是表现界面,但要做好界面其实不容易,山下面还有很多东西需要考虑才能支撑界面,其实做原型的过程就是设计系统的过程。我们都希望尽量把开发工作前移,需求能做的工作就不留到开发环节做。如果软件模式一定,那么框架做得好的话就一定可以让业务人员来做一部分现在属于开发人员的工作(注:这部分工作其实本就该属于业务人员),那时大家就能体会到开发软件就如同做原型一样的乐趣了!
图 11.3.6 在 UCD 社区里面看到的一张图,原型最主要功能是表现界面,但要做好界面其实不容易,山下面还有很多东西需要考虑才能支撑界面,其实做原型的过程就是设计系统的过程。我们都希望尽量把开发工作前移,需求能做的工作就不留到开发环节做。如果软件模式一定,那么框架做得好的话就一定可以让业务人员来做一部分现在属于开发人员的工作(注:这部分工作其实本就该属于业务人员),那时大家就能体会到开发软件就如同做原型一样的乐趣了!

Просмотреть файл

@ -1,8 +1,8 @@
## 10.4 估计与计划
## 11.4 估计与计划
如果是轻车熟路的项目PM 很容易根据历史经验估算出开发时间依次指定计划完成PM Spec。但是如果是一个与已有产品有部分不同或者完全不同的项目就需要先做原型开发验证一些技术关键点之后才能有比较准确的估计。
### 10.4.1 成本估算模型
### 11.4.1 成本估算模型
COCOMO是COnstructive COst MOdel建设性成本估算模型的缩写最早是由Dr. Barry Boehm在1981年提出是一种精确的、易于使用的成本估算方法。 COCOMO II模型的原型是在1996年提出并持续改进。由于其采用了模型化的管理方法在国外有很高的影响力。由于国内现有的软件开发项目数据还不是很完善该方法在国内的使用还是受到限制。所以很多资料以及参数只能从国外的网站上去参考。而参数的准确性则由于文化、开发背景、技术熟练度、编程环境和成本等的差异不能直接使用在现有开发项目中只能作为大致的参考。
@ -38,16 +38,16 @@ COCOMO II 模型的使用场景如下:
6. 制定遗留软件库存决策:修改、逐步淘汰、外包等;
7. 通过重用、工具、过程成熟度、外包等,设置混合投资策略来提高组织的软件能力。
### 10.4.2 项目的规模度
### 11.4.2 项目的规模度
我们先了解一下规模度的概念,见图 10.4.2。
我们先了解一下规模度的概念,见图 11.4.2。
<img src="img/Slide17.JPG"/>
图 10.4.2 - 规模度因子
图 11.4.2 - 规模度因子
举例来说某个项目在图10.4.2中满足下列条件:
举例来说某个项目在图11.4.2中满足下列条件:
1. $PREC = 2.48$,即有前例可以借鉴,程度为“高”;
2. $FLEX = 3.04$,即开发灵活性为“正常”;
@ -55,10 +55,10 @@ COCOMO II 模型的使用场景如下:
4. $TEAM = 1.10$,即团队成熟度“非常高”;
5. $PMAT = 4.68$,即过程成熟度为“正常”。
则根据公式10.4.1
则根据公式11.4.1
$$
B = 0.91 + \frac{1}{100}\sum_{i=1}^5{W_i} \tag{10.4.1}
B = 0.91 + \frac{1}{100}\sum_{i=1}^5{W_i} \tag{11.4.1}
$$
计算得到B值为
@ -67,15 +67,15 @@ $$
B=0.91+(2.48+3.04+5.65+1.10+4.68)/100=1.0795
$$
### 10.4.3 工作量评估
### 11.4.3 工作量评估
我们用 PMPeople Month人月来估算软件开发的工作量如公式10.4.2所示。
我们用 PMPeople Month人月来估算软件开发的工作量如公式11.4.2所示。
$$
PM = A \times Size^B \tag{10.4.2}
PM = A \times Size^B \tag{11.4.2}
$$
这里的$A$通常取常数2.94$Size$是代码行数(千行),$B$是公式10.4.1的结果值。
这里的$A$通常取常数2.94$Size$是代码行数(千行),$B$是公式11.4.1的结果值。
假设一共4万行代码
@ -83,18 +83,18 @@ $$
PM = 2.94 \times (40000/1000)^{1.0795}=2.94 \times 53.63=157.67(人月)
$$
### 10.4.4 成本驱动属性
### 11.4.4 成本驱动属性
成本驱动属性因子的加入扩展了基本模型的能力。17个成本驱动属性因子可以分为4个部分如图10.4.3所示。
成本驱动属性因子的加入扩展了基本模型的能力。17个成本驱动属性因子可以分为4个部分如图11.4.3所示。
<img src="img/Slide18.JPG"/>
图 10.4.3 - 成本驱动属性因子
图 11.4.3 - 成本驱动属性因子
表 10.4.2 给出了原文,便于大家进一步查找资料学习。
表 11.4.2 给出了原文,便于大家进一步查找资料学习。
表 10.4.2 - 后体系结构模型的成本驱动属性
表 11.4.2 - 后体系结构模型的成本驱动属性
|序号|缩写|原文|中文|分类|
|--|--|--|--|--|
@ -123,30 +123,30 @@ $$
所有的因子相乘得到工作量调节因子EAF
$$
EAF = \prod_{i=1}^{17}{EM_i} \tag{10.4.3}
EAF = \prod_{i=1}^{17}{EM_i} \tag{11.4.3}
$$
公式10.4.4是在公式10.4.2的基础上,考虑了成本驱动属性后的改进:
公式11.4.4是在公式11.4.2的基础上,考虑了成本驱动属性后的改进:
$$
PM = A \times Size^B \times EAF \tag{10.4.4}
PM = A \times Size^B \times EAF \tag{11.4.4}
$$
在针对每个属性取值后我们假设公式10.4.3的乘积结果为1.13。仍然用前面的数值例子,计算得到:
在针对每个属性取值后我们假设公式11.4.3的乘积结果为1.13。仍然用前面的数值例子,计算得到:
$$
PM = 2.94 \times 53.63 \times 1.13 = 178.17(人月)
$$
### 10.4.5 微软常用的估计方法
### 11.4.5 微软常用的估计方法
用 COCOMO 模型的问题是,代码行数通常是开发完毕后才知道的,所以有一个改进的办法是,把$Size$值改成子模块数。一般一个子模块的代码行数在500~2000行之间可以大致与 KLOCKilo Line of Code相当。
在微软通常使用T-Shirt Size方法来估算开发时间具体见图10.4.4。
在微软通常使用T-Shirt Size方法来估算开发时间具体见图11.4.4。
<img src="img/Slide19.JPG"/>
图 10.4.4 - T-Shirt Size估算法
图 11.4.4 - T-Shirt Size估算法
这是一种简化的方法。既然用复杂的模型很难计算出准确的数值,那么我们干脆就使用一些简化的模型来估算。
@ -163,10 +163,10 @@ $$
4. LLarge大号
5. XLExtremly Large特大号。
根据软件复杂度每个功能点或模块所需要的时间也是不同的见图10.4.4中的表格。
根据软件复杂度每个功能点或模块所需要的时间也是不同的见图11.4.4中的表格。
最后,我们把所有的功能点或模块所需要的时间相加,就是该软件总共需要的开发时间。
还有一个经验是以简单软件为例通常没有超过5天的功能点或模块如果超过了就要把该模块继续分解成若干小模块所有小模块的尺寸都必须小于等于M这样就可以比较准确地估算整体工作量。
当然,以上的估算方法也是以团队成熟度为前提的。图 10.4.4 的右半部分给出了一个示意:假设有一个 M 尺寸的模块,对于成熟团队来说很快就可以完成,而对于稚嫩的团队来说,尺寸可能会增加到 L。
当然,以上的估算方法也是以团队成熟度为前提的。图 11.4.4 的右半部分给出了一个示意:假设有一个 M 尺寸的模块,对于成熟团队来说很快就可以完成,而对于稚嫩的团队来说,尺寸可能会增加到 L。

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 56 KiB

После

Ширина:  |  Высота:  |  Размер: 56 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 94 KiB

После

Ширина:  |  Высота:  |  Размер: 94 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 90 KiB

После

Ширина:  |  Высота:  |  Размер: 90 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 114 KiB

После

Ширина:  |  Высота:  |  Размер: 114 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 138 KiB

После

Ширина:  |  Высота:  |  Размер: 138 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 94 KiB

После

Ширина:  |  Высота:  |  Размер: 94 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 66 KiB

После

Ширина:  |  Высота:  |  Размер: 66 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 63 KiB

После

Ширина:  |  Высота:  |  Размер: 63 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 109 KiB

После

Ширина:  |  Высота:  |  Размер: 109 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 113 KiB

После

Ширина:  |  Высота:  |  Размер: 113 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 91 KiB

После

Ширина:  |  Высота:  |  Размер: 91 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 79 KiB

После

Ширина:  |  Высота:  |  Размер: 79 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 85 KiB

После

Ширина:  |  Высота:  |  Размер: 85 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 61 KiB

После

Ширина:  |  Высота:  |  Размер: 61 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 97 KiB

После

Ширина:  |  Высота:  |  Размер: 97 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 90 KiB

После

Ширина:  |  Высота:  |  Размер: 90 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 98 KiB

После

Ширина:  |  Высота:  |  Размер: 98 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 69 KiB

После

Ширина:  |  Высота:  |  Размер: 69 KiB

Просмотреть файл

До

Ширина:  |  Высота:  |  Размер: 80 KiB

После

Ширина:  |  Высота:  |  Размер: 80 KiB

Просмотреть файл

@ -0,0 +1,41 @@
<img src="img/Slide1.SVG"/>
概要设计、总体设计、架构设计high level design
详细设计design patternlow level design
架构,源于中国古代建筑术语。架 = 加 + 木,构 = 木 + 勾,把一堆木头加起来并互相勾住,以形成一个完整的、牢固的建筑。引申到软件产品概念上,就是:
1. 把一个软件项目整体切分成不同的部分;
2. 定义不同的角色来完成这些部分的工作;
3. 建立相互沟通的机制,使得这些部分能够有机的结合为一个整体,并完成这个整体所需要的所有功能。
有两种常用的架构方法RUPRational Unified Process统一开发过程TOGAFThe Open Group Architecture Framework
<img src="img/Slide2.SVG"/>
https://blog.csdn.net/lfsf802/article/details/8487990
https://towardsdatascience.com/10-common-software-architectural-patterns-in-a-nutshell-a0b47a1e9013
https://zhuanlan.zhihu.com/p/41395345
https://blog.csdn.net/Jayphone17/article/details/103651076
https://zhuanlan.zhihu.com/p/41395345
https://www.ou.nl/documents/40554/791670/IM0203_03.pdf/30dae517-691e-b3c7-22ed-a55ad27726d6
https://towardsdatascience.com/10-common-software-architectural-patterns-in-a-nutshell-a0b47a1e9013
https://max.book118.com/html/2016/1115/63079375.shtm
https://blog.csdn.net/hguisu/article/details/78259898

Просмотреть файл

@ -0,0 +1,140 @@
## 12.1 架构演化的故事
还记得第一章中关于“木头与软件工程的故事”吧?这里有另外一个版本,是同样的应用场景,但是想说明的是软件**架构**演化的故事。
### 12.1.1 单机架构
我们首先假设木头有个熊孩子,还在上小学。数学不是很好,所以木头想了一个注意:每天出 20 道 100 以内的加减法算术题。这个对木头来说很容易,花了 1 个小时用 C# 搞定了一个小的应用程序。
**再小的软件也是有架构的,所以架构是可大可小的,能用小的、简单的架构解决问题,就不要用大的、复杂的架构。**
这个小应用程序的架构很简单:一个有界面的应用程序,显示出题目,孩子计算出结果后填入一个数字,提交,如果正确则进入下一题,错误则提示重做。那些题目是事先生成好的(经过人工核对,以保证不重复和一定的复杂程度),包括答案,都放在了一个数据文件里。
木头自己家里就有一个台式机运行 Windows 10 操作系统,是平时在余时间写书用的,性能还可以。于是木头就把应用程序和数据文件都放在一个目录中,在桌面上创建一个应用程序的快捷方式,孩子每次点击打开即可使用。
见图 12.1.1 阶段1。
<img src="img/Slide3.SVG"/>
图 12.1.1 架构计划-1
### 12.1.2 点对点架构
很快,木头发现一个问题:每天晚上如果孩子在使用台式机做题的时候,自己就不能使用。木头忽然想到家里还有一个比较旧的 Surface 笔记本电脑,于是拿出来升级到 Windows 10性能还可以接受。
然后把应用程序拷贝到笔记本电脑上,数据文件仍然放在台式机上(这样木头就可以随时在台式机上维护那个文件),用点对点网络共享的方式把数据文件共享给笔记本电脑,这样在笔记本电脑上的应用程序可以像读本地磁盘一样打开数据文件。
于是,父子俩每天晚上都可以在局域网内共同使用电脑了。见图 12.1.1 阶段2。
### 12.1.3 客户端/服务器架构
熊孩子和同学们吹嘘自己在用电脑做算术题,同学们很羡慕。其中有个同学就住在木头家的隔壁,哭着喊着带着家长过来学习先进经验。
木头本来想把这个应用直接拷贝给邻居使用,但是邻居基本上是个电脑盲。木头忽然想到 Wifi 信号可以穿墙,于是在无线路由器上开了一个端口给邻居,并让邻居买了一台二手笔记本电脑,装好 Windows 10 操作系统和应用程序软件,登录到木头家的路由器。自己家的笔记本电脑也登录到同一个路由器上。
但是两台笔记本电脑操作同一个数据文件会产生一些读写冲突木头又花了几个小时的时间把对数据文件的读写改成了数据库读写SQL Server 数据库(个人版)部署在自己的台式机上,两台笔记本电脑可以同时访问数据库获得习题并提交答案了。
其实这种模式还不是标准的客户端/服务器模式,只能算是网络数据库模式,如果把数据库看成是服务器的话,也勉强算是客户端/服务器模式。
见图 12.1.1 阶段3。
### 12.1.4 浏览器-服务器架构
熊孩子的进步突飞猛进,引起了老师的注意。经过询问后得知有这么一个好工具,立刻和教务处及校长汇报,然后联系木头寻求合作。
面对下一代的教育问题,木头当仁不让。但是,如果全校师生都用的话,需要做的改动有(其实是重新设计开发):
- 要有广域网(互联网)的支持,因为同学们是在各自的家中使用;
- 题库需要很大的改进以满足各个年级的需要,并且用一个强壮一些的数据库来存储题库,如 SQL Server 企业版,可以有很多并发连接;
- 软件也需要重新进行架构设计,因为不能要求所有的学生都有一台 Windows 10 的电脑,所以必须改成浏览器/服务器模式;
- 由于是业余练习,目前还不需要记录成绩,所以在服务器端配置一台 Web 服务器连接数据库,允许简单的上传下载功能即可。
木头寻思了一下,这个事情自己一个人做不了,后期还需要持续升级维护,所以和公司领导汇报,看看是不是能组织一个小组来试水教育领域的软件开发。领导很支持,调配了 3 个人和木头一起花了一个月的时间完成了这件事。
见图 12.1.2 阶段4。
<img src="img/Slide4.SVG"/>
图 12.1.2 架构演化-2
### 12.1.5 MVC 架构
运行一段时间后,数学老师们觉得效果非常好,校长知道后也很高兴,就想把这个模式推广到其它学科。于是,除了体育老师、音乐老师、美术老师以外,其它学科的老师纷纷找木头讲述需求,木头忙得脚丫子朝天,把小学课程整个都复习了一遍,觉得知识很生疏。
由于各门课的内容差异很大,所以要求有不同种类的界面来支持,一台实现简单逻辑 Web 服务器已经不能满足要求了。开发小组内部商量后决定用 MVC 模式,用 ASP.NET 的 MVC 框架来实现,完全分离模型、视图、控制,以免所有逻辑都混在一起。其中,模型负责与数据库交互获得数据,视图负责展示给浏览器,控制器负责接收用户的请求,调用不同的学科的模型和视图。
而数据库也从 Web 服务器中拆出来,安装在一台独立的服务器中。
见图 12.1.2 阶段5。
### 12.1.6 数据库主从架构
增加了很多学科,当然要在数据库中增加更多的内容。
在开发小组向数据库中逐步增加题库的同时,木头感觉如果全校的上千名学生同时使用这个系统的话,数据库访问会是个瓶颈。于是和校长/教务处商量,又购买了一台数据库服务器,与已有的一台数据库配置成了主从关系,即:
- 主数据库负责写入,然后同步给从数据库;
- 从数据库负责查询/读出;
- 当检测到从数据库压力较大时,可以再增加一台从数据库服务器,做负载均衡。
这样就基本解决了数据库的压力,而且数据有了备份。当然,如果发现一台从数据库服务器不够用了,还可以再增加。而 Web 服务器的压力,目前预测还可以承受,木头和开发小组决定上线后先观察一下再说。
见图 12.1.3 阶段6。
<img src="img/Slide5.SVG"/>
图 12.1.3 架构演化-3
### 12.1.7 多层架构
木头和开发小组正在严密监视着 Web 服务器的流量问题,意想不到的事情发生了:体育老师、音乐老师、美术老师来找开发小组谈业务了!口口声声是推动数字化教学方案!
木头心想:嗐,多增加几个学科也没问题吧,反正前面的架构设计也没有限制具体的学科。但是,这几位老师的需求完全不同:他们需要增加大量的视频、音乐、图片,供同学们下载观看和倾听。
木头和开发小组商量,不得已又申请了几台机器,把以前单纯的 Web 服务器变成了一个服务器群,花了半个月的时间,把以前的 MVC 架构改了改,最后变成了三层架构。其中,表示层中含有原来的视图和控制器部分的代码,实体中含有以前的模型部分的代码,相当于是 MVC 架构在三层模式中的实现。
数据库当然也要增加,从数据库从 1 台变成了 3 台,校长虽然心疼,但还是批准了预算。还有一些视频、音频、图片文件都放在了独立的文件服务器上,这些文件都是只读的,不需要修改。
见图 12.1.3 阶段7。
### 12.1.8 负载问题
就这样平稳运行了半年多,木头和开发小组都觉得风平浪静的日子有些枯燥,突然接到了市教育局的电话,对方一个冷冰冰的女声:“是木头吗?听说你们没有经过我们教育局审核,就给某小学开发了一套课外教育系统?” 一听这话,木头手中正在旋转的鼓棒“咣啷”一声掉在地上,结结巴巴地说:“啊?审核?这个...校长没有说起过有这个手续呀?” 那个女声说:“校长也是想出成绩,明年升级为市重点小学。这样吧,你们明天来一趟教育局,带好相关材料,我们补一个审核!” 木头愣了一会儿,问:“哦?哦!是教育局,不是公安局吧?” 女声说:“对,是教育局,公安局在我们对面,想去那里也很方便。”
听了这话,木头才放下心来,没有法律责任,也没有经济处罚,而且还能补审核,好事!于是捡起鼓棒,又转了起来......
审核很快通过了,主要是界面上要多一些官方认证的标志、许可证号码等等,最关键的是,市教育局想在全市推广这套系统!这下子木头可乐坏了,赶紧向领导申请加派人手,领导也很高兴,欣然同意。
由于教材是统一的,所以在需求上没有大的改动,只不过需要增加登录系统,以区分学校和学生,便于市教育局进行统计。但是有两个重大变化:
1. 系统不能部署在某个学校了,市教育局申请了 Azure 云资源,所有的软件都要部署在 Azure 上。
2. 要承担全市小学的课外辅导工作,用户量剧增,并发访问量剧增。
据此,木头和开发团队(从小组变成了团队,准备进军教育行业)做了以下设计:
- 在最前端增加了**负载平衡**机制,这样 Web 服务器就可以根据访问量横向扩展了。
- 在应用层,为每个学科单独开发了对应的服务,**负载分解**,以满足不同学科之间的需求差异,还能随时扩展。数据存取层也放在这里。
- 在数据库层也是采用了分库的机制,每个学科单独使用一套主从数据库,有些作业量不大的学科可以共享一套数据库。通过这些**负载调整**,每个数据库都处于合理的繁忙程度的运行状态。
见图 12.1.4 阶段8。
<img src="img/Slide6.SVG"/>
图 12.1.4 架构演化-4
### 12.1.9 性能问题
在部分学校开始使用这套系统后,系统运行还算平稳。渐渐地,当更多的学校使用后,木头团队逐渐发现了两个问题:
- 文件服务器访问量太大了,似乎同学们对视频、图片、音乐更感兴趣。
- 以前写数据库的操作特别少,但是有了用户系统后,需要不断地向数据库中写入日志,数据库的压力也变得很大。
针对第一个问题,开发团队租用了 CDNContent Delivery Network内容分发网络来缓存静态文件资源提高响应速度同学们看视频、听音乐、看图片更起劲儿了体育老师、音乐老师、美术老师都很高兴。
针对第二个问题,开发团队在数据库写入前端加了消息队列,使得大量的并发写入都先进入消息队列进行削峰处理,然后在分批次地写到数据库路中,可以保证数据不丢失,这是由消息队列的特性来保证的。这也可以看作是用空间换时间的缓存机制。
见图 12.1.4 阶段9由于细节太多而版面有限无法绘制出来所以采用了框架图。
### 12.1.10 总结
注意,我们讲的是架构**演化**,而不是**进化**,意思是用户需求处于什么阶段,我们就使用什么样的架构。演化的各个阶段的具体架构没有好坏之分,只要最适合当前需求的就是最好的。每个后续的阶段都会比上一个阶段更复杂,开发、维护、部署的成本都更高,所以要谨慎选择。

Просмотреть файл

@ -0,0 +1,236 @@
## 12.2 与架构相关的概念
### 12.2.1 基本概念
先澄清一些容易混淆的基本概念,在网络上这些概念鱼龙混杂,让读者不明所以。
#### 1. 架构、架构师、构建、框架、结构
**架构师**architect使用**架构**模式**构建**construct了一个**框架**framework用于约束那些开放者们只能使用规定的**结构**structure来进行二次开发。
#### 2. 架构设计、系统设计、概要设计、详细设计
架构设计比概要设计更抽象。
概要设计主要要描述出系统分为哪些功能模块,每个模块又可以分为哪些子模块,每个模块的主要功能是什么等,
而架构设计一般不需要详细描述到子模块,主要描述系统的层次结构、各层包含的重要的模块、各层之间的接口和通讯方式、大模块的物理部署等。
一般大型项目都是在需求分析之后先做架构设计,再进行概要设计和详细设计,不过一般中小型的项目很多都没有架构设计,直接进行概要设计,在概要设计里阐述架构设计。
- 架构
- 功能
- 数据
本着敏捷开发的原则,概要+详细设计比较臃肿,详细设计可以针对具体的模块、算法,由相应的开发人员完成。或者,把概要设计做得稍微详细一些,可以代替详细设计。
#### 3. 架构、框架、设计模式
<img src="img/Slide7.SVG"/>
从 12.1 节的架构进化的故事中,想必读者已经对“架构”有了一些基本的概念。本章中主要讨论架构设计,所以先澄清一下三个重要概念:
**1架构**
简单的说架构就是一个蓝图,是一种设计方案,将客户的不同需求抽象成为抽象组件,并且能够描述这些抽象组件之间的通信和调用。
比如,三层架构、事件总线架构等,这些架构代表的模式也可以叫做架构模式,它定义了系统的总体结构。
**2框架**
软件框架是项目软件开发过程中提取特定领域软件的共性部分形成的体系结构,不同领域的软件项目有着不同的框架类型。框架不是现成可用的应用系统。而是一个半成品,提供了诸多服务,开发人员进行二次开发,实现具体功能的应用系统。框架是代码,是工具,不是知识。
比如 .Net Framework 是开发框架PyTorch 是深度学习框架。一旦使用了某个框架,就会有一定的粘性,想迁移到其它框架上会有困难。比如使用 PyTorch 搭建好神经网络模型后,如果想迁移到 Tensor Flow另外一个深度学习框架需要重新学习语法、重新搭建、重新训练。
框架有哪些?
C++语言的QT、MFC、gtkJava语言的SSH 、SSIphp语言的 smarty(MVC模式)python语言的django(MTV模式)等等
【最佳实践】
不要轻易地决定是否使用框架,一旦投入,就和框架绑定了,需要学习理解框架的底层逻辑,代码结构要遵守框架的约定,框架的 bug 也会让项目陷入泥潭。
笔者曾接手 Windows Phone 10 上的新浪微博的开发,上一个开发者采用了一个框架,用于处理用户交互事件,第一印象是:本来很直接的一件事,非得要通过框架绕一个弯儿。而笔者是第一批在 Windows Phone 10 上开发的先驱,对整个开发体系非常清楚,自然看不上这么一个奇奇怪怪的不知名的框架,于是不费什么力气,就摘掉了这个框架。意想不到的是,发布出去以后,用户反映整个应用的响应速度比以前快了,软件运行流畅了很多。
【最佳实践】
不要轻易决定自己写框架
- 没人用
- 与业务逻辑耦合
**3设计模式**
是一套被反复使用、广为人知的、经过分类的代码设计经验的总结,它强调的是一个设计问题的解决方法。设计模式是知识,是概念,不是代码。
稍微有些底层软件开发经验的读者,都知道有约 23 种软件设计模式,比如工厂模式、适配器模式、策略模式等等,目的是保证代码的可重用性、可读性、可靠性。而且还有 7 种设计原则,是上述的 23 种 设计模式要遵守的基本规则。
在上层的架构设计上,同样有设计原则和设计模式,一个合格的架构师就是根据这些原则和模式来工作的。
**4三者的比较**
所以,从概念大小和开发顺序上看,架构 $\gt$ 框架 $\gt$ 设计模式。
- 首先架构应该是一个最大的概念,是最高层次的设计。所以在做一个项目的时候首先出来的应该是架构,是对整个问题的一个总体上的设计。可以根据已有架构模式衍生出具体的架构,或者自己设计出新的架构。一个架构设计中可能会用到多个框架和多个设计模式。
- 其次会考虑采用什么现有的框架或者自己实现框架来解决架构设计中的子系统、子任务。一个架构中,在不同的局部可能要采用不同框架,比如在靠近应用层的部分应该采用 MVC 框架,而靠近后台处理的部分应该采用 xx 框架。系统小的话,只使用一种框架也可以。框架是针对共性抽象出来的半成品,所以,如果开发者自己实现框架的话,基本上会和实例(实际的应用)代码混在一起,分不出哪个是框架,哪个是应用。
- 最后,在具体的功能模块实现时就需要用到设计模式,所以设计模式就是解决单一问题的设计思路和解决方法。
这三者的共同点都是解决软件开发中的问题而出现的,而且都会表现出来的就是“高内聚,低耦合”的理念,就是让我们的设计更面向对象化。
所以我们要想做好一个好的项目,那么架构设计、框架选型、设计和使用、设计模式的使用是非常重要的。
简而言之:架构是大智慧,用来对软件设计进行分工;框架是半成品,加入代码来实现自己想要的功能;设计模式是小技巧,对具体问题提出解决方案,以提高代码复用率,降低耦合度。
### 12.2.2 架构设计方法
<img src="img/Slide8.SVG"/>
#### 1. RUP 4+1
RUPRational Unified Process即统一开发过程。
<img src="img/Slide9.SVG"/>
0. 场景视图Scenario View
通过数量一些重要场景(更常见的是用例)进行无缝协同工作,我们为场景描述相应的脚本(对象之间和过程之间的交互序列)。
1. 逻辑视图Logical View
主要支持功能性需求,即系统应该为用户提供哪些服务。
2. 过程视图Process View
一些非功能性的需求,如性能和可用性。它解决并发性、分布性、系统完整性、容错性的问题,以及逻辑视图如何与过程结构配合在一起,在哪个控制线程上,对象的操作被实际执行。
3. 开发视图Development View
关注软件开发环境下实际模块的组织。软件打包成小的程序块(程序库或子系统),它们可以由一位或几位开发人员来开发。子系统可以组织成分层结构,每个层为上一层提供良好定义的接口。
4. 物理视图Physical View
主要描述硬件配置。在UML中通常被称为部署视图它主要考虑如何把软件映射到硬件上。通常需要考虑到解决系统拓扑结构、系统安装和通信等问题。
#### 2. UML
UML即Unified Model Language统一建模语言。
<img src="img/Slide10.SVG"/>
1. 用户模型Use Case View
强调从用户的角度看到的或需要的系统功能,是被称为参与者的外部用户所能观察到的系统功能的模型图。
用用例图描述。
2. 结构模型Logic View
展现系统的静态或结构组成及特征,也称为结构模型视图(Structural Model View)或静态视图(Static View)。
用类图和对象描述。
3. 行为模型Concurrent View
体现了系统的动态或行为特征,也称为行为模型视图(Behavioral Model View)或动态视图(Dynamic View)。
用状态图、时序图、协作图、活动图描述。
4. 实现模型Component View
体现了系统实现的结构和行为特征,也称为实现模型视图(Implementation Model View)。
用组件图描述。
5. 环境模型Deployment View
体现了系统实现环境的结构和行为特征,也称为环境模型视图(Environment Model View)或物理视图(Physical View)。
用配置图描述。
#### 3. TOGAF
TOGAF即 The Open Group Architecture Framework开放组织架构框架是由 The Open Group 这个开放组织指定的企业发展架构的方法和工具(即框架)。
<img src="img/Slide11.SVG"/>
0. 组织架构
在 TOGAF 中不存在(所以图中为灰色),但却是客观存在的,由人或部门组成的公司管理层,不属于架构设计范畴。
1. 业务架构Business Architecture
业务战略、组织和关键业务流程。
2. 应用架构Application Architecture
也叫做刨面架构、逻辑架构。
3. 数据架构Data Architecture
各类逻辑和物理数据资产以及数据管理资源的结构。
4. 技术架构Technology Architecture
支持上述架构的必要软硬件,包括基础设施、中间件、网络、部署。
#### 4. 其它
1. 开发架构
开发架构则更关注程序包不仅仅是我们自己写的程序还包括应用程序依赖的SDK、第三方类库、中间价等。尤其是像目前主流的Java、.NET等依靠虚拟机的语言和平台以及主流的基于数据库的应用都会比较关注。和逻辑架构有紧密的关联。
2. 逻辑架构
逻辑架构关注的是功能,包含用户直接可见的功能,还有系统中隐含的功能。或者更加通俗来描述,逻辑架构更偏向我们日常所理解的“分层”,把一个项目分为“表示层、业务逻辑层、数据访问层”这样经典的“三层架构”。
3. 运行架构
顾名思义,更关注的是应用程序运行中可能出现的一些问题。例如并发带来的问题,比较常见的“线程同步”问题、死锁问题、对象创建和销毁(生命周期管理)问题等等。开发架构,更关注的是飞机起飞之前的一些准备工作,在静止状态下就能规划好做好的,而运行架构,更多考虑的是飞机起飞之后可能发生的一些问题。
4. 数据架构
数据架构更关注的是数据持久化和存储层面的问题也可能会包括数据的分布、复制、同步等问题。更贴切来讲如何选择需要的关系型数据库、流行的NOSQL如何保障数据存储层面的性能、高可用性、灾备等等。很多时候和物理架构是有紧密联系的但它更关注数据存储层面的物理架构更关注整个基础设施部署层面。
5. 物理架构
物理架构更关注的系统、网络、服务器等基础设施。例如如何通过服务器部署和配置网络环境来实现应用程序的“可伸缩性、高可用性”。或者举一个实际的例子如何通过设计基础设施的架构来保障网站能支持同时10W人在线、7*24小时提供服务当超过10W人或者低于10W人在线时可以很方便的调整部署架构来支撑。
### 12.2.3 技术架构模式
架构模式是在给定上下文中对软件构建中常见问题的通用、可重用解决方案。架构模式类似于软件设计模式,但层次更高、范围更广。
串行模式
1. 分层模式 (Layered pattern)
4. 管道-过滤器模式 (Pipe-filter pattern)
星形模式
2. 客户端-服务器模式 (Client-server pattern)
6. 对等模式 (Peer-to-peer pattern)
3. 主-从模式 (Master-slave pattern)
树形模式
5. 代理模式 (Broker pattern)
7. 事件总线模式 (Event-bus pattern)
环形模式
8. 模型-视图-控制器 (MVC) 模式 (Model-view-controller pattern)
9. 黑板模式 (Blackboard pattern)
10. 解析器模式 (Interpreter pattern)

Просмотреть файл

@ -0,0 +1,177 @@
## 12.2 星形系统的架构模式
### 12.2.1 客户端-服务器模式Client-Server
这是一种最传统、最基本的模式,简称为 C/S是其它一切模式的基础。见图 12.2.1。
<img src='img/Slide10.svg'>
图 12.2.1 客户端-服务器架构
#### 架构说明
最早的软件都是在主机(大型机或小型机)上开发的,使用者用哑终端方式通过串行接口接入到主机,实际上所有代码都是在主机上运行,因为哑终端只有输入、输出功能,没有计算能力。
后来出现了个人电脑 PCPersonal Computer运算能力很强并且有了局域网络。这两个技术突破让人们可以重新构建代码把关键逻辑和数据放在主机后称服务器在终端后称客户端上运行本地逻辑用户专用和界面并通过快速的局域网络与服务器进行通信。主动发起请求的叫客户端响应的一方叫服务器。当然相比之下服务器的运算能力更强是专用的商业计算机。
客户端-服务器模式由两个部分构成:**一台**服务器与**多个**客户端,拓扑结构为星形。服务器组件同时为多个客户端组件提供服务。客户端向服务器发启服务请求,服务器将相应服务信息回应给客户端。此外,服务器持续监听来自其它客户端的请求。二者之间一般采用 TCP/IP 网络协议,传统的架构是局域网,但是现在互联网速度很快,所以可以扩展到广域网。
#### 扩展模式
- 有些时候一台服务器不能满足客户端的所有请求,比如:在档案管理系统中,服务器 1 只负责处理查询身份证号码的请求,而服务器 2 只负责处理更改个人信息的请求。那么在客户端 1 中,不同的用户请求会发送到不同的服务器上,这是在客户端代码中预先配置好的。而在服务器端,服务器 1 的内存可能会比较大,因为它可以缓存成千上万个身份证号码,便于快速得到查询结果;而服务器 2 的硬盘(存储设备)读写可能会比较快,因为它要快速地更新数据。
- 还有一种可能就是两个客户端的权限不一样,客户端 1 权限较高,可以提供所有功能;而客户端 2 权限较低,只能提供部分功能。这在银行系统中常见:有的机器只能自助取钱,而另外一些机器可以存钱和取钱。
- 有些负载均衡网络设备,可以把客户端请求均匀地分配给服务台集群中的每一台服务器。也可以在服务器端软件中实现简单的负载均衡,即每次用户请求时先返回本服务器的繁忙状态:如果很忙,则告诉客户端访问其它服务器;如果不忙,则继续请求/响应;如果所有服务器都忙,则在客户端显示系统繁忙信息。
#### 优缺点
优点:
- 开发阶段可以在两端分两组同时进行。
- 客户端与服务器分离,排查错误方便。
- 一个服务器可以服务于多个客户端。
- 当多个服务器可以同时提供服务时,单个服务器的升级很方便。
- 安全,所有数据都存储在服务器上,可以更好地控制访问和资源,以保证只有那些具有适当权限的用户可以访问和更改数据。
- 由于数据的集中存储,数据的更新更容易。
缺点:
- 当计算任务较重时,服务器可能成为瓶颈。
- 当数据传输较多时,网络带宽可能成为瓶颈。
- 需要客户端具有一定的计算能力。
- 当客户端较多时,升级客户端软件不方便。
- 当客户端操作系统不同时,需要开发多个版本的客户端软件。
#### 应用场景
当需要在个人电脑内下载、安装软件,并且必须有服务器端的支持才能工作时,这类的应用都属于客户端-服务器模式,比如:
- 公司内的电子邮件服务
- 公司内的文件共享服务和打印服务
- 银行窗口业务
- 图书馆查询系统
- 联网游戏
目前使用的手机类应用,比如微信、淘宝、微博、京东等等,也都可以算作是客户端-服务器模式。
### 12.2.2 浏览器-服务器模式Browser-Server)
此模式简称为 B/S从 C/S 模式发展而来。见图 12.2.2。
<img src='img/Slide11.svg'>
图 12.2.2 浏览器-服务器架构
#### 架构说明
随着互联网的发展,尤其是:
- 广域网网络速度提升
- 浏览器引擎性能提升
- 浏览器开发框架成熟
这三点让人们意识到,如果把业务逻辑都挪到网页中,那么在客户端只要安装一个浏览器就行了,而无需为了 10 种应用安装 10 种客户端,这无疑对软件厂商和最终用户都有利。
#### 与 C/S 架构的比较
表 12.2.1 C/S 架构与 B/S 架构的比较
||C/S|B/S|
|-|-|-|
|硬件环境|客户端计算能力较强,几乎可以完成任何操作|客户端能运行浏览器即可,但可处理逻辑也相对简单|
|网络环境|局域网、安全的广域网|广域网、局域网|
|操作系统|指定的操作系统,比如 Windows|只要有浏览器即可,比如 Mac、Linux|
|安全要求|客户端和服务器的安全性都要考虑,安全性较高|只考虑服务器端的安全性,用户行为不可控|
|开发成本|购买费用和培训费用高|低|
|软件重用|不好|较好|
|系统维护|升级难,维护难|无缝升级,维护开销极小|
|常用场景|公司内部|公众用户|
|用户界面|专用的用户界面,美观漂亮,可定制程度高|会用浏览器即可,一般的软件都会设计得比较人性化|
|网络协议|TCP/IP|HTTP基于TCP/IP之上|
#### 应用场景
常见的是信息发布,但是由于浏览器技术的发展,几乎可以应用于任何应用场景。
从图 12.2.2 的组网实例可以看到,客户端可以使用任何操作系统上的任何浏览器。公司内部可以有自己的 Web 服务器,在局域网内直接访问内部的网页信息;通过路由器访问互联网上的外部 Web 服务器。
### 12.2.3 对等模式Peer-to-peer
这是客户端-服务器模式的双向扩展。见图 12.2.3。
<img src='img/Slide12.svg'>
图 12.2.3 对等架构
#### 架构说明
对等模式中的组件称之为对等体peer或节点既作为向其他节点请求服务的客户端同时也做为响应其他节点请求的服务端。节点可以在运行过程中动态地改变其角色既可以单独做为客户端或服务端运行又可同时作为客户端与服务端运行。
在没有出现服务的年代,一个小公司内部往往使用对等网络来共享资源,它是一种投资少、见效快、高性价比的实用小型网络系统,比如 10 台计算机以下。互联网时代,在网络的各个角落也可能存在一些节点,它们各自知道同伴们的网络地址,进行点对点通信。
#### 扩展模式
如果有多个节点,它们之间的两两互相连接也可以看作是对等模式。只从一个节点向外看,还是星形网络。
#### 优缺点
优点:
- 一个节点瘫痪时,其它节点还可以继续工作并提供服务。
- 可在网络的任何地方共享内容和资源。
- 由对等节点组成的网络易于扩展,而且比单台服务器更加可靠,不容易有网络瓶颈。
- 由对等方组成的网络可共享处理器,整合计算资源以执行分布式计算任务,而不只是单纯依赖一台计算机,如一台超级计算机。
- 用户可直接访问自己所在的节点计算机上的共享资源,在本地存储器上共享文件,而不必在远程服务器上进行共享。
缺点:
- 数据分布在每个节点上,管理困难。
- 升级软件时需要有计划地逐个节点升级,而且备份、恢复资源困难。
- 网络安全性差,资源分散,容易有薄弱环节
- 当用户所在的节点做为服务器时,会影响用户本地的计算性能。
#### 应用场景
- 网络文件共享系统Gnutella 目前是一个分布式文件共享协议的名称,主要用于分享音乐文件。此名称有时也用来指该网络本身以及原始的 Gnutella 软件。
- 流媒体协议P2PTV 与 PDTP众多客户端访问媒体服务器所造成的压力是服务器所不能承受的因此当新的请求到达时服务器会根据访问记录把请求转给刚刚访问了相关媒体数据的客户端然后在两个客户端之间做媒体数据传输。
- 区块链:区块链是一个去中心化的数据库,由很多独立的节点组成,分布在世界各地,通过互联网相互点对点连接,每个节点都具有数据层、网络层、共识层、激励层、合约层和应用层,集体维护一个可靠数据库,可用于智能合约、证券交易、电子商务、物联网、社交通讯、文件存储、存在性证明、身份验证、股权众筹、金融征信等领域。
### 12.2.4 主从模式Master-Slave/Primary-Secondary
因为 Slave 这个词比较敏感,因此英文中更多地使用 Primary-Secondary我们只要知道 Slave 不是“奴隶”的意思就好。见图 12.2.4。
<img src='img/Slide13.svg'>
图 12.2.4 主从架构
#### 架构模式
这种模式由两部分组成:主节点和从节点。主节点将工作分配给不同的从节点,并根据从节点返回的结果计算最终结果。图 1.2.4 右侧显示了主从节点之间分配工作的顺序图,其中有一个硬性的要求:初始任务必须是可以**分割**的。
主从模式是分治divide-and-conquer原则的一个例子。每个从节点都是独立的没有任何共享状态因为它们是并行运行或者是在同一个主机的不同进程中或者是在不同的主机上所以主从通信的延迟可能是一个问题。
### 优缺点
优点:
- 读写分离。
- 适合读多写少的场景,大并发读取时,多个从节点可以提供负载均衡。
- 从节点数量扩展灵活。
- 不怕数据丢失,有很多个备份。
缺点:
- 同步延迟问题,主从节点上的数据在某一时刻有可能不一致,不适合于要求一致性高的场合。
- 如果有大量写操作,会集中在主节点上。
- 主节点发生故障会比较麻烦,自动切换的复杂度高。
#### 应用场景
那么什么叫做可以分割?注意“分割”这个词比较生硬,它并非智能地“分解”,也非理性地“分析”。有几种应用:
- 并行计算:把一批数据或任务整齐地拆分成 N 份儿,然后分配给 N 个从节点去处理。比如大规模的并行计算时,可以把多个矩阵的运算分配给多个从节点并行完成,再在主节点中合并。
- 容错主节点把同一个计算任务分配个多个从节点然后从最快结束运算的从节点那里获得返回结果并返回给调用者或者是比较所有从节点的返回结果取相似性最高的结果三个结果是1.512一个结果是1.511则取1.512),返回给调用者。
- 提供准确度:不同的从节点执行同一个任务,但是它们各自的实现方式不同,比如,一个是用神经网络推理,一个用线性回归做预测,还有一个用表格匹配法取近似值,最终在主节点上用一种策略来决定最佳结果,如平均值或最多相似值。
- 数据库复制:主数据库被视为权威源数据库,从数据库与之同步。在有读取请求时,主数据库把请求转给从数据库,以提高并非读取的速度;在有写入请求时,只发生在主数据库上,然后再同步给从数据库。

Просмотреть файл

@ -0,0 +1,114 @@
## 12.3 串行系统架构模式
### 12.3.1 管道-过滤器模式 (Pipe-filter pattern)
见图 12.3.1。
<img src='img/Slide15.svg'>
图 12.3.1 管道-过滤器架构
#### 架构说明
这种架构是可以非常自然地产生的因为它符合人们按部就班地做事的习惯和我们每个开发者刚开始学习的流程图和结构化开发也很类似。这种方结构有一个数据起点原始数据、一个数据汇点处理好的数据、N 个过滤器(处理逻辑)和 N+1 个管道组成,我们常说的 Pipeline 就是这个机制。
其中:
- 数据起点和汇点可能是数据库或者数据文件(源代码也可以看作是数据)。
- 过滤器一般都是可独立运行的模块被动被主控程序调度或主动常驻进程地把数据从前面的管道拉入pull处理好后推入后面的管道push
- 管道可以是内存中的各种数据结构、系统管道,或者是临时放在磁盘中的文件(这种情况要注意定时清理临时文件,避免磁盘被占满)。
#### 扩展模式
允许一个过滤器把数据分可后分别推送到不同的管道中,以便后续的不同逻辑的过滤器处理,甚至有可能进入不同的数据汇点。或者是在一开始,就有不同的数据源进入,但是共享某些过滤器(这种情况一般是分当作两个 pipeline 处理)。
#### 优缺点
优点:
- 很容易通过增加新的过滤器来扩展整个 pipeline 的功能。
- 可复用性好,因为每个过滤器都可以完成独立的处理功能,所以可以应用于任何其它系统中相同的场景。
- 同分层结构一样,事先定义好的接口可以运行并行开发、测试、集成。
缺点:
- 性能较低,一般用于非实时系统的后同数据处理流程中。
- 数据传输和转换开销大,注意中间数据存储要及时清理。
#### 应用场景
在 Unix 系统中的 Shell就是一个管道模式的例子比如
```
cat a.txt | grep 'food' | sort | uniq > out
```
这个命令行首先用 cat 命令把 a.txt 中的文本行取出来,送给 grep 命令,把其中含有 'food' 的行取出来,送给 sort 命令,排序后把结果送给 uniq 命令去重,最后输出到 out。
管道过滤器模式的另外一个例子是编译器,如图 12.3.2 右侧所示。其中一个词法分析器分析源文件并将生成的符号序列发送到解析器,产生语法树,再由语义分析器产生增强语法树。然后由代码生成器用来生成字节代码,这些代码被优化后,并最终被翻译成机器代码(可能需要更多或更少的步骤)。
### 12.3.2 分层模式
见图 12.3.2。
<img src='img/Slide14.svg'>
图 12.3.2 分层架构
#### 架构说明
分层模式用于对软件系统进行层次拆解,每个层次都是独立的抽象,包含一组子模块,为其上层提供服务。其目的主要是为了分散关注、松散解耦、逻辑复用、标准定义。由于其众多的优点,已经成为典型的软件系统架构,也已经成为构建企业软件的标准。
一个好的分层式结构,可以使得开发人员的分工更加明确。一旦定义好各层次之间的接口,负责不同逻辑设计的开发人员就可以**分散关注**,齐头并进。例如 UI 人员只需考虑用户界面的体验与操作,领域的设计人员可以仅关注业务逻辑的设计,而数据库设计人员也不必为繁琐的用户交互而头疼了。每个开发人员的任务得到了确认,开发进度就可以迅速的提高。
**松散耦合**的好处是显而易见的。如果一个系统没有分层,那么各自的逻辑都紧紧纠缠在一起,彼此间相互依赖,谁都是不可替换的。一旦发生改变,则牵一发而动全身,对项目的影响极为严重。
降低层与层间的依赖性,既可以良好地保证未来的可扩展,在**复用性**上也是优势明显。每个功能模块一旦定义好统一的接口,就可以被各个模块所调用,而不用为相同的功能进行重复地开发。
进行好的分层式结构设计,**标准定义**也是必不可少的。只有在一定程度的标准化基础上,这个系统才是可扩展的,可替换的。而层与层之间的通信也必然保证了接口的标准化。
#### 扩展模式
- 有些时候也可以跨层调用,比如从 第 3 层直接调用第 1 层的功能。
- 同一层中有可能有两个独立的组,它们之间没有关系,只是根据上层业务逻辑提供不同的、独立的服务。
#### 优缺点
优点:
- 下层可以为所有的上层提供服务,调用灵活。一般不允许平级调用,否则被调用者就应该放在下一层。
- 高内聚,低耦合,每一层都有标准化抽象。
- 上下层之间指定好接口后,可以分组独立开发。
- 测试、集成、排查错误、升级维护等都比较容易。
缺点:
- 逐层调用会降低系统性能,需要每一层都有相应的提高性能的措施。
- 有时会导致级联的修改,这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。
- 代码量变多,肯定比都聚合在一起的代码量大。
分层后代码量自然要比不分层多
#### 应用场景
一个复杂的应用系统通常被拆分为以下四个层次,如图 12.3.1 右侧所示:
- 表示层(也称为 UI 层)
- 应用层(也称为服务层)
- 业务逻辑层(也称为领域层)
- 数据访问层(也称为持久化层)
这几乎成为了行业标准。有时候应用层和业务逻辑层也可以合并,变成标准的三层架构。
而在开放系统互联标准协议中,一共定义了 7 层,从下到上分别为:
- 物理层,比如光纤、同轴、双绞线设备。
- 数据链路层,提供物理编址、错误校验、数据帧序列生成、流量控制。
- 网络层IP 协议在这一层实现,如确定 IP 地址并建立连接。
- 传输层TCP 协议在这一层实现,用于可靠地传输数据。
- 会话层SSL、TLS 等安全协议在这一层实现。
- 表示层,加密解密、压缩解压缩。
- 应用层FTP、HTTP、POP3、SMTP 等重要协议都在这一层实现。

Просмотреть файл

@ -0,0 +1,59 @@
## 12.4 树形系统架构模式
### 12.4.1 代理模式 (Broker pattern)
#### 架构说明
代理模式用于在结构化系统中对组件解耦。系统内各组件间采用远过程调用remote service invocations的方式交互。代理Broker组件充当组件间通讯的协调角色。
提供服务的组件将其能力(服务以及特性)发布给代理,客户端均向代理请求服务,由代理将请求重定向到先前已发布过对应服务的组件进行处理。
使用场景
消息中间件软件Apache ActiveMQApache KafkaRabbitMQ 与 JBoss 等等
#### 优缺点
优点:
- 通过一个代理对象完成一系列的处理,在将来的程序改动中,就会允许动态更改、添加、删除和重新定位对象,这使开发人员的发布变得透明,符合开闭原则。
- 代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 远程代理使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算机性能与处理速度,可以快速响应并处理客户端请求。
- 代理模式在架构中还可以让虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度
缺点:
- 要求对服务描述进行标准化,我们要使用代理模式时则需要考虑异步处理机制、协议创建流程和错误环境控制,比较的繁琐。
- 由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
- 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。这些问题就造成了不易开发的弱点。
#### 应用场景
- 当客户端对象需要访问远程主机中的对象时可以使用远程代理。
- 当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时可以使用虚拟代理,例如一个对象需要很长时间才能完成加载时。
- 当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时可以使用缓冲代理。通过使用缓冲代理,系统无须在客户端每一次访问时都重新执行操作,只需直接从临时缓冲区获取操作结果即可。
- 当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时可以使用保护代理。
- 当需要为一个对象的访问(引用)提供一些额外的操作时可以使用智能引用代理。
#### 几种“代理”的区别
|英文|中文|解释|比喻|
|-|-|-|-|
|Agent|自主性代理|智能性较高,接收到 A 的请求,自主决定访问 B 还是访问 C然后把 B 或 C 的返回结果告诉 A但 A 并不知道 B 或 C 的存在||
|Broker|中介性代理|A 通过本代理得知 B 的存在,但是不知道如何访问 B发送请求给代理代理把该请求变成 B 可以听懂的语言发送给 B 并获得结果返回给 A|股票经纪人代买卖股票|
|Delegate|委托性代理|A 不知道怎么才能从 B 那里得到服务,甚至不知道 B 的存在,就把请求告诉代理,代理完成其它的任务|律师代理诉讼|
|Proxy|透传性代理|无智能,在 A 不能合法/有效地访问B时把 A 的请求拿过来原封不动地传给 B再把 B 的响应原封不动地回传给 A|传声筒|
### 12.4.2 事件总线模式 (Event-bus pattern)
#### 架构说明
事件总线模式应用于事件处理主要由四个组件构成事件源event source事件侦听者event listener通道Channel以及总线event bus。 事件源将消息发布到总线的特定通道,侦听者订阅相应的通道,事件源所发布的消息经通道通告给订阅通道的侦听者。
使用场景
Android 开发
通告Notification服务
#### 优缺点
#### 应用场景

Просмотреть файл

@ -0,0 +1,171 @@
## 12.5 环形系统的架构模式
### 12.5.1 MVC 模式
MVC 这个名词很多读者都熟悉,它代表了 Model-View-Controller。但大多数人熟悉的应该是 MVC 框架和设计模型,我们这里要讲解的是 MVC 架构模型。表 12.5.1 举例说明了三者的区别。
表 12.5.1 三种概念的举例比较
|MVC|基本功能|MVC架构举例|MVC框架举例|MVC设计举例|
|-|-|-|-|-|
|模型|数据或状态的表示,应用逻辑的封装。<br>如:游戏卡带。|管理电子邮件系统<br>的所有数据|JAVA: JavaBean<br>ASP.NET: 用户自定义类|封装对象:<br>文件、<br>文件列表|
|视图|用户界面组件,模<br>型数据的可视化,<br>允许用户输入。<br>如:游戏手柄和电视。|Web网站可以同时<br>提供浏览器页面和<br>手机WAP页面来收<br>发电子邮件|JAVA: JSP<br>ASP.NET: Razor|控件绑定:<br>大图标、列表、<br>小图标、详情|
|控制器|选择模型和视图,将<br>用户的操作转换为对<br>模型或者视图的更改<br>如:游戏主机。|根据请求类型决定<br>是浏览邮件还是发<br>送邮件,选择不同<br>模型,并确定视图|JAVA: Servlet<br>ASP.NET: Controller|用户操作:<br>剪切、复制、<br>更名、删除、<br>排序、新建|
|说明|通用功能定义,<br>以游戏机为例|以电子邮件系统为例|以Java和<br>ASP.NET为例|以 Windows 的<br>文件管理器为例|
#### 架构说明
见图 12.5.1。
<img src='img/Slide18.svg'>
图 12.5.1 MVC 架构
MVC 模式将交互式应用程序拆分为三个部分:
- 模型model包含业务功能及数据、状态。
- 视图view把模型中的数据信息用指定的界面展示给用户通常有多个视图可供控制器选择。
- 控制器controller处理用户的输入操作选择模型和相应的视图。
MVC 模式通过将内部信息表示、用户信息呈现以及用户操作接收分开的方式解耦组件,实现高效的架构重用。
以老式插卡游戏机为例:
- 游戏主机是控制器 C。注意这里的“控制”不是指用户的操作而是对各个零部件的控制。它接收手柄的操作信号把模型中指定的视图播放到显示器上。
- 游戏卡是模型 M封装了游戏的数据和逻辑和其它两个部件完全无关可以任意更换游戏卡只要接口一致即可。它决定显示器上的图像。
- 游戏手柄和显示器是视图 V。注意手柄是用户交互设备所以属于视图而不是属于控制器。
#### 优缺点
优点:
1. 耦合性低
视图层和业务层分离这样就允许更改视图层代码而不用重新编译模型和控制器代码同样一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离所以很容易改变应用程序的数据层和业务规则。
2. 重用性高
MVC模式允许使用各种不同样式的视图来访问同一个服务器端的代码因为多个视图能共享一个模型它包括任何WEBHTTP浏览器或者无线浏览器WAP比如用户可以通过电脑也可通过手机来订购某样产品虽然订购的方式不一样但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化所以同样的构件能被不同的界面使用。
3. 部署快,生命周期成本低
MVC使开发和维护用户接口的技术含量降低。使用MVC模式使开发时间得到相当大的缩减后端开发人员集中精力于业务逻辑界面程序员集中精力于表现形式上。
4. 可维护性高
分离视图层和业务逻辑层也使得 WEB 应用更易于维护和修改
缺点:
1. 完全理解MVC比较复杂。
完全理解并掌握 MVC 不是一个很容易的过程。
2. 调试困难。
因为模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难,每个构件在使用之前都需要经过彻底的测试。
3. 不适合小型,中等规模的应用程序
在一个中小型的应用程序中,强制性的使用 MVC 进行开发,往往会花费大量时间,并且不能体现 MVC 的优势,同时会使开发变得繁琐。
4. 增加系统结构和实现的复杂性
对于简单的界面,严格遵循 MVC使模型、视图与控制器分离会增加结构的复杂性并可能产生过多的更新操作降低运行效率。
5. 视图与控制器间的过于紧密的连接并且降低了视图对模型数据的访问
视图与控制器是相互分离,但却是联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
#### 应用场景
一般用于主流开发语言所构建的互联网网页应用架构,比如 ASP.NET MVC、Spring MVC。
在图 12.5.1 右侧显示了 ASP.NET MVC 框架的工作流程:
1. 用户浏览器向 Web Application 提出请求 URLhttps://xxx.com/home/index
2. Routing Module 执行 RouteTable 中定义的路由动作;
3. MVCHandler 生成 home_Controller
4. 执行 URL 中的 index_action向 Model 请求数据;
5. Model 从数据库中获得数据;
6. Controller 决定使用哪个 View
7. 把 Model 交给 View
8. 合成好网页后返回给用户浏览器。
读者可以很容易地找到 Spring MVC 框架的工作流程自行阅读,相信会有所帮助,在此不再赘述。
### 12.5.2 黑板模式Black Board
#### 架构说明
#### 优缺点
#### 应用场景
一、定义
黑板模式是一种常用的架构模式,应用中的多种不同数据处理逻辑相互影响和协同来完成数据分析处理。黑板模式允许多个消息读写者同时存在,消息的生产者和消费者完全分开。这就像一个黑板,任何一个教授(消息的生产者)都可以在其上书写消息,任何一个学生(消息的消费者)都可以从黑板上读取消息,两者在空间和时间上可以解耦,并且互不干扰。这种模式对于没有确定解决方案策略的问题是有用的。
二、模式组成
黑板模式由3个主要组成部分组成。
(1)知识源:包含独立的、与应用程序相关的知识,知识源之间不直接进行通讯,它们之间的交互只通过黑板来完成。
(2)黑板数据结构:按照与应用程序相关的层次来组织并解决问题的数据,知识源通过不断地改变黑板数据来解决问题。
(3)控制组件;完全由黑板的状态驱动,黑板状态的改变决定了需要使用的特定知识。
黑板模式一般不会对架构产生什么影响,但它通常会要求有一个清晰的消息结构。黑板模式一般都会提供一系列的过滤器,以便消息的消费者不再接触到与自己无关的消息。在实际开发中,黑板模式常见的有两种实现方式:
(一)数据库作为黑板
利用数据库充当黑板,生产者更新数据信息,不同的消费者共享数据库中信息,这是最常见的实现方式。该方式在技术上容易实现,开发量较少,熟悉度较高。缺点是在大量消息和高频率访问的情况下,性能会受到一定影响。在该模式下,消息的读取是通过消费者主动“拉取”,因此该模式也叫做“拉模式”。
(二)以语音识别为例:
语音识别黑板里边就是语言包 ;语言包就是知识源,控制机构就是管理语言包的,当你说一句话,不知道是什么语言,所以时非确定性的问题,控制机构把你说的话对应的语言包给你看,这就是黑板模式的流程
所有的组件都可以访问黑板。组件可以生成添加到黑板上的新数据对象。组件在黑板上查找特定类型的数据,并通过与现有知识源的模式匹配来查找这些数据。
三、模式实现
(一)利用数据库
利用数据库充当黑板,不同的应用共享数据库中信息,并且可以更新数据信息。这也是最常见的实现方式。
(二)利用发布—订阅模式
这种实现方式通常采用消息队列作为黑板队列工作在主题模式Topic专家作为队列的订阅者同时可以向队列发送消息消息会被发送至所有订阅者。以上过程实现了专家间的信息交流。
四、影响黑板系统的因素
影响黑板系统设计的最大因素是引用问题本身的特性,但是支撑应用程序的黑板体系结构有许多相似的特征和构件。对于特定应用问题,黑板系统可通过选取各种黑板、知识源和控制模块的构件来设计;也可以利用预先制定的黑板体系结构的编程环境。
五、应用实例
黑板系统的典型应用是信号处理领域,如网络信息检索、电子商务、自动控制、商业管理智能决策、语音和模式识别、智能控制领域等
实际应用
在实际应用中常见的实现模式有:
A 利用数据库
利用数据库充当黑板,不同的应用共享数据库中信息,并且可以更新数据信息。这也是最常见的实现方式。
特点:
1 便于实现信息的查询筛选和统计这方面关系数据库提供了SQL 92的强大支持。
2 不能用于较高实时性要求的环境,这种实现是工作在“拉模式”下的,并且高频率的访问数据库会导致严重的系统性能问题。
B 利用发布—订阅模式
这种实现方式通常采用消息队列作为黑板队列工作在主题模式Topic专家作为队列的订阅者同时可以向队列发送消息消息会被发送至所有订阅者。以上过程实现了专家间的信息交流。
特点:
1、可以有效应用于实时性要求较高的系统这种实现工作在“推模式”下。
2、难于实现信息的统计分析不像实现方式一那样可以通过SQL支持这些工作必须开发者自己完成。
六、优缺点分析
优点:可用于非确定性问题求解,启发式解决过程,可维护性,可重用
缺点:不能确保期望结果,效率低下,回退,不支持并行,共享空间的访问需要同步
### 12.5.3 解释器模式
#### 架构说明
#### 优缺点
#### 应用场景

Просмотреть файл

@ -0,0 +1,18 @@
https://blog.csdn.net/hguisu/article/details/78259898
具体的设计实例:
- 高并发的设计
- 异地灾备的设计
- 消息队列的设计
- 微信系统的设计(点对点通信)
- 微博系统的设计(消息订阅,发布)
- 淘宝系统的设计
- 异地访问延迟
- 高性能
- 微服务
- 语音系统的设计
- 地图系统的设计
https://blog.csdn.net/danpu0978/article/details/107274524

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 56 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 144 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 39 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 99 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 100 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 77 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 61 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 51 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 94 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 75 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 65 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 43 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 79 KiB

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

После

Ширина:  |  Высота:  |  Размер: 164 KiB

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше