程序员必读的书,StackOverflow 创始人推荐

伯乐在线/艾凌风

原载: http://blog.jobbole.com/100450/

Stack Overflow 创始人 Jeff Atwood 推荐给程序员的书。


本文最近一次更新是2015年3月份。 为什么我很少更新我的读书清单呢?因为虽然在这 10 年里,计算机一直在迅猛发展,但人始终却没有变。 为了开发出更好的软件,你需要理解人是如何工作的,这也是我推荐的这些书所关注的领域。

代码大全2

Steve McConnell所著的《代码大全2》 就像是为软件开发者所编写的《烹饪的乐趣》。能够去阅读这本书,说明你很享受自己的工作,并且在认真地对待自己的工作。同时,你还想要不断的进步。在《代 码大全》中Steve写到,普通程序员每年阅读的技术书籍不到一本。仅仅是阅读这本书的行为,就可能已经把你和你90%的程序员同事们区别开来了。

我非常喜欢这本书,以至于本站(coding horror)的名字也源于此书。书中列举的编程反例都被打上了”Coding Horror”的标签。没有什么比Coding Horror更有意思的了,直到你自己遇上一次。突然间一切都不那么有趣了。帮自己一个忙,把这本书作为你要研读的第一本书,并把它作为你推荐给同事的第一本书。

人月神话

这本书可能是我们这领域唯一的一本经典了。如果你还没读过,那就太不对了。

我敢说任何一个拿起这本书的程序员都没有发现关于那个早就不使用操作系统的故事以及它的开发团队之间惊人的相关性。这本二十五年前出版的老书大胆的阐明了一个观点:计算机也许会变,但人永远不会。

花时间去阅读这本经典书籍一定比你去阅读当今哪些几千页的大部头书籍更加有意义。

点石成金 : 访客至上的网页设计秘笈

在关于可用性的书籍中,这是我读过的最好的一本书。书名提到了“网页的可用性”,但是请不要被这一虚假的特指所迷惑。Steve Krug在书中提到了可用性这一概念所包含的全部重要内容,而且讲的很好,书也很有意思。如果你只想读一本关于可用性的书,那么读这本就可以了。这本书囊括了很多有用的信息,并且以简练的、平易近人的方式将这些信息呈现给你。这本书对于很多人都是适用的:技术人员、非技术人员、用户、开发者、经理等凡是你能说出名字的任何人。

呃。。。好吧。从来没有开过这样的会议。顺便提一下,解决这个问题的办法是进行一次快速的可用性测试。请想象这样的场景:基于实际数据来做决定而不是基于一场为了通过说服所有持有反对意见的人的辩论。真是革命性的转变啊!

快速软件开发

这本书的全称是:《快速软件开发:掌控软件开发进度》,这个标题不仅冗长还有些可笑,更不幸的是它用词不当。

快速软件开发》并不是一本关于快速开发的书。它讲述的是软件开发失败这一现实问题。大多数的软件开发项目都会失败:有时是没能按期交付,有时是开发出了不合格的产品,甚至有的时候都没有能够完成开发。这并不是什么论点,而是一个事实。一个令人不快的事实是:你的团队要足够的好,才能避免失败,更别说取得成功了。尽管这一切听起来可能会令人沮丧——好吧,这确实令人沮丧——但你仍然会想要去读一读这本书。

为什么呢?因为你曾经犯过的错误,或者其他人犯过的错误,如果能够避免再犯,就已经成功了一半*了。这本书传达了一个真谛:犯错是有益的——只要这些错误是一些未曾犯过的错误。如果你犯了一些经典的老错误,那么你在没有开始前就已经失败了。同时,你可能并没有意识到,你现在就在犯着类似的错误。

对我们这一行来讲,唯一不变的就是变化。所以拥抱变化和采取不同的“快速”开发技术是很自然的一件事。但是这句话反过来说就不对了。我们不能认为自 1970年以来,所有的旧式软件开发课程同今天的技术相比已经是废弃的或是没用的了。老生常谈的一件事是:计算机改变了很多;人却没有。在你准备开始前, 至少对于哪些可行哪些不可行有个认识。用 McConnell 的话说就是:“粉刷之前请先阅读油漆桶上的说明文字。” 诚然,这听上去已经足够直白了,但是直到你读了这本书,你才意识到,我们很少会真正去这么做。

  • 根据书的内容,严格来讲,有四分之一的内容。但是我觉得要比这多得多。

人件

如果你曾经看到过一个全明星球队,因为教练水平不高而战绩不佳,那你肯定会喜欢这本书。如果团队成员不能相互沟通或是认同一件事,那么你的团队中不 论有多少“编程之星”都没用。如果一个开发者经常被一些琐事打断,即使他是个天才,也不能够高效的工作。开发者并不清楚他们自己的社交技能,但是,讽刺的 是:这可能是你项目成功的关键因素。如果你希望成为一个真正的“团队领袖”,而不是徒有其名,你需要看看这本书。

尽管《人件》中有很多不错的、完全正确的观点,但是书中描绘的这种雇员管理对于大多数公司来讲纯粹是幻想。但是至少你可以在你的工作环境,或是你的团队出现问题的时候有所察觉——最重要的是,你可以知道怎么做。

设计心理学

软件开发有时候是一件极度令人沮丧的事情,因为很多事情都会做错。我们做的很多事情都是防御性的:尝试在情况变坏之前做出预测。这令人十分伤神,并 且最终可能会被证明是错的。我经常根非技术人员这样去解释这个问题:就好像去造一块有上千个运动部件的手表,其中每个部件都会动不动就随机坏掉。棒极了!

软件开发是很困难的,这点没错,但是做一个门也很困难。设计的微妙之处存在于我们接触到的每个事物,不论是最新的 SQL 引擎还是一双普通的鞋。这本书会让你对“恶魔藏在细节里”这句话产生新的认识。如果设计一个门并不是我们想象的那样是一件很简单的事的话,也许是时候因为 意识到我们也无法设计出完美的软件而给自己放个假了。

About Face:交互设计精髓

Alan Cooper 是 Visual Basic语言之父,可用性领域的教父级人物。我拥有这本书的多个版本(现在是第四版),这本书是少数越修订越好的书,越来越多的合作者向本书加入了不同的观点。

《About Face》一书中包含了关于移动应用和 web 应用的通用实用指导。 以老掉牙的 Windows 95 人机界面作为例子来进行阐释,将该系统已经改进的地方(在进行对话框选择前使用视觉样例进行展示)和还没有改进的部分(使用愚蠢的模态框来停止正在运行的 进程)进行对比是很有趣的一件事。

这是一本非常有用的书;我在我自己的项目中用到了书中提到了全部的指导。

交互设计之路:让高科技产品回归人性

正是这本书向世人介绍了角色模型的概念:不要把用户想象为一群抽象的、难以描述的、无定形的人。角色模型指导我 们和特定的用户进行交谈,这些用户有名字,有个性,有需求也有目标。我们的用户是否需要打印预览功能?谁知道?但是,如果对于客户经理 Gerry Manheim 来说,打印每周花销报表是他的工作,那你最好提供打印预览功能给他。这里边没有什么神奇的东西;一如既往的是,一切都归结于你的用户是谁,他们究竟要做什 么——角色模型是解决这一问题的好办法。

程序员认为自己在设计产品可用性时能够代表“普通”用户作出某些决定,但是在现实世界中,他们完全不能代表用户。程序员是一群怪人,充其量能算是是 一种极端的用户——就好比“逻辑人(Homo Logicus)” vs. “现代智人(Homo Sapiens)”。除非你碰巧开发的是一款编译器,因为编译器的用户也是程序员。

这本书有一个隐含的观点,有的时候,无论你的设计有多好,就像由 Alan 担任顾问并在此书中用作案例的这两款软件:扫描仪软件以及网页开发软件,在市场上都没有能够取得成功,但这和软件的可用性无关,因为它们的可用性已经被证明是非常优秀的了。有些时候,非常优秀的产品同样会失败,而其失败的原因是你无法掌控的,无论你多么努力。对于此书中的一些华而不实的词藻,你可以用以上事实将自己拉回到现实当中。

  • 我有书中图片里的同款 USB 扫描仪,设备配套对软件令我印象深刻。后来我把这台扫描仪送给了我父亲。有一次和他打电话,我并没有提到任何关于扫描仪的事情,但是他却提到他很喜欢这个扫描软件。这一切都发生在这本书出版之前!

编程珠玑

在这里推荐《编程珠玑》,我本来有些犹豫,因为这本书中介绍了很多底层的编程技巧。但是书中确实包含了很多软件开发中的『珠玑』,所以值得每位开发者花时间去读一读。任何包含这幅图的书…

…都是物有所值的。利用TRS-80 与 DEC Alpha 的对比来阐释48n和n3算法的差别?各位,真的没有比这样做更合适的了。能和大师一起工作一年是最好的了,退而求其次,你也可以读读《编程珠玑》。这本书将很多软件工程师的智慧提炼成了简洁易懂的文字,纳入其中。

我不会骗你:有一些章节是可以完全略过的。比如说,第11、13和14章分别介绍了如何实现排序,堆和哈希算法,考虑到现如今这些基本算法都有成熟 的库可以使用,我无法想象再去实现它们有什么意义。 对于那些和教科书一样恼人的习题,这里有一个很实在的建议。浏览一下这本书,跳过代码部分。有件事可能会让你失望,第八章“粗略估算”(Column 8, “Back of the Envelope” )是必须要看的。这里有我见过的最佳的估算方法。这章还解释了一些疯狂的面试问题,一些公司很喜欢用这些问题提问我们。

如果你还在犹豫,你也可以在网上阅读一下此书的样章。最近我用书中关于字符串的章节去解释了马尔科夫链在生成人造数据填充空数据库时的作用。

程序员修炼之道:从小工到专家

看这本书时常会让我想到《编程珠玑》,但是实际上这本书更好一些。因为这本书没有那么的专注于代码,取而代之的的是,作者在这本书中总结了实际工作中发现的全部实用方法。并非所有的方法都是与编程相关的。比如,问问自己『为什么我要做这件事?是否值得这样做?』,跳出固有的思维方式。你应该把这些东西融入到你和你同事的日常生活中。正是这些内容,使得《程序员修炼之道》成为了一本如此优秀的书。

如果你想再多了解一些这本书,我建立一个HTML 版本的插页参考卡片,这个参考卡片很好的总结了这本书的内容。

Web 可用性设计

Jakob Neilsen 因为他所创建的可用性网站而出名。1989年,当他的书出版的时候,他就是一个可用性专家了。《Web 可用性设计》是一本专注于 web 可用性的新手教程,所以它和面向 GUI 的 Cooper 的那本书有所不同。

定量信息的视觉显示

视觉解释:图像和数量,证据与线索

想象信息

美丽的证据

信息是很美的。一个设计良好的 GUI 也很美。

除非你是个完美主义者(或是一个受虐狂,我猜),否则你没有必要把一套四本全买齐,但是前两本是必须的。

Chris Sells 对 Tufte 的书有些有趣的见解,这些见解源于他2004年6月参加Tufte研讨会时的见闻。

正则表达式经典实例

众所周知 UNIX 非常复杂、难以理解。正则表达式也是这样。

我可能已经是『保持简单直白』俱乐部的正是成员了,但是我愿意将正则表达式作为一个特例。若能正确的书写正则表达式,则在处理字符串时,它可以帮你节省非常多的时间。我从来没有遇到过一个项目,正则表达不能在某些地方为我们提供方便。

一旦你深入研究了正则表达式,你就会沉醉于正则表达式惊人的能力和潜力,这一切也造就了 Perl。记住,绝对的权利会导致绝对的腐败。但是同样非常的赞。

译者简介


艾凌风:兴趣点:Python,C/C++,在线教育,英语

Practical Guide to implementing Neural Networks in Python (using Theano)

By

Source: http://www.analyticsvidhya.com/blog/2016/04/neural-networks-python-theano/

Introduction

In my last article, I discussed the fundamentals of deep learning, where I explained the basic working of a artificial neural network. If you’ve been following this series, today we’ll become familiar with practical process of implementing neural network in Python (using Theano package).

I found various other packages also such as Caffe, Torch, TensorFlow etc to do this job. But, Theano is no less than and satisfactorily execute all the tasks. Also, it has multiple benefits which further enhances the coding experience in Python.

In this article, I’ll provide a comprehensive practical guide to implement Neural Networks using Theano. If you are here for just python codes, feel free to skip the sections and learn at your pace. And, if you are new to Theano, I suggest you to follow the article sequentially to gain complete knowledge.

Note:

  1. This article is best suited for users with knowledge of neural network & deep learning.
  2. If you don’t know python, start here.
  3. If you don’t know deep learning, start here.

Practical guide to implement neural network in python using theano

 

Table of Contents

  1. Theano Overview
  2. Implementing Simple expressions
  3. Theano Variable Types
  4. Theano Functions
  5. Modeling a Single Neuron
  6. Modeling a Two-Layer Networks

 

1. Theano Overview

In short, we can define Theano as:

  • A programming language which runs on top of Python but has its own data structure which are tightly integrated with numpy
  • A linear algebra compiler with defined C-codes at the backend
  • A python package allowing faster implementation of mathematical expressions

As popularly known, Theano was developed at the University of Montreal in 2008. It is used for defining and evaluating mathematical expressions in general.

Theano has several features which optimize the processing time of expressions. For instance it modifies the symbolic expressions we define before converting them to C codes. Examples:

  • It makes the expressions faster, for instance it will change { (x+y) + (x+y) } to { 2*(x+y) }
  • It makes expressions more stable, for instance it will change { exp(a) / exp(a).sum(axis=1) } to { softmax(a) }

Below are some powerful advantages of using Theano:

  1. It defines C-codes for different mathematical expressions.
  2. The implementations are much faster as compared to some of the python’s default implementations.
  3. Due to fast implementations, it works well in case of high dimensionality problems.
  4. It allows GPU implementation which works blazingly fast specially for problems like deep learning.

Let’s now focus on Theano (with example) and try to understand it as a programming language.

 

2. Implementing Simple Expressions

Lets start by implementing a simple mathematical expression, say a multiplication in Theano and see how the system works. In later sections, we will take a deep dive into individual components. The general structure of a Theano code works in 3 steps:

  1. Define variables/objects
  2. Define a mathematical expression in the form of a function
  3. Evaluate expressions by passing values

Lets look at the following code for simply multiplying 2 numbers:

Step 0: Import libraries

import numpy as np
import theano.tensor as T
from theano import function

Here, we have simply imported 2 key functions of theano – tensor and function.

Step 1: Define variables

a = T.dscalar('a')
b = T.dscalar('b')

Here 2 variables are defined. Note that we have used Theano tensor object type here. Also, the arguments passed to dscalar function are just name of tensors which are useful while debugging. They code will work even without them.

Step 2: Define expression

c = a*b
f = function([a,b],c)

Here we have defined a function f which has 2 arguments:

  1. Inputs [a,b]: these are inputs to system
  2. Output c: this has been previously defined

Step 3: Evaluate Expression

f(1.5,3)

1. output 1

Now we are simply calling the function with the 2 inputs and we get the output as a multiple of the two. In short, we saw how we can define mathematical expressions in Theano and evaluate them. Before we go into complex functions, lets understand some inherent properties of Theano which will be useful in building neural networks.

 

3. Theano Variable Types

Variables are key building blocks of any programming language. In Theano, the objects are defined as tensors. A tensor can be understood as a generalized form of a vector with dimension t. Different dimensions are analogous to different types:

  • t = 0: scalar
  • t = 1: vector
  • t = 2: matrix
  • and so on..

Watch this interesting video to get a deeper level of intuition into vectors and tensors.

These variables can be defined similar to our definition of ‘dscalar’ in the above code. The various keywords for defining variables are:

  • byte: bscalar, bvector, bmatrix, brow, bcol, btensor3, btensor4
  • 16-bit integers: wscalar, wvector, wmatrix, wrow, wcol, wtensor3, wtensor4
  • 32-bit integers: iscalar, ivector, imatrix, irow, icol, itensor3, itensor4
  • 64-bit integers: lscalar, lvector, lmatrix, lrow, lcol, ltensor3, ltensor4
  • float: fscalar, fvector, fmatrix, frow, fcol, ftensor3, ftensor4
  • double: dscalar, dvector, dmatrix, drow, dcol, dtensor3, dtensor4
  • complex: cscalar, cvector, cmatrix, crow, ccol, ctensor3, ctensor4

Now you understand that we can define variables with different memory allocations and dimensions. But this is not an exhaustive list. We can define dimensions higher than 4 using a generic TensorType class. You’ll find more details here.

Please note that variables of these types are just symbols. They don’t have a fixed value and are passed into functions as symbols. They only take values when a function is called. But, we often need variables which are constants and which we need not pass in all the functions. For this Theano provides shared variables. These have a fixed value and are not of the types discussed above. They can be defined as numpy data types or simple constants.

Lets take an example. Suppose, we initialize a shared variable as 0 and use a function which:

  • takes an input
  • adds the input to the shared variable
  • returns the square of shared variable

This can be done as:

from theano import shared
x = T.iscalar('x')
sh = shared(0)
f = function([x], sh**2, updates=[(sh,sh+x)])

Note that here function has an additional argument called updates. It has to be a list of lists or tuples, each containing 2 elements of form (shared_variable, updated_value). The output for 3 subsequent runs is:

2. shared

You can see that for each run, it returns the square of the present value, i.e. the value before updating. After the run, the value of shared variable gets updated. Also, note that shared variables have 2 functions “get_value()” and “set_value()” which are used to read and modify the value of shared variables.

 

4. Theano Functions

Till now we saw the basic structure of a function and how it handles shared variables. Lets move forward and discuss couple more things we can do with functions:

Return Multiple Values

We can return multiple values from a function. This can be easily done as shown in following example:

a = T.dscalar('a')
f = function([a],[a**2, a**3])
f(3)

3. multiple output

We can see that the output is an array with the square and cube of the number passed into the function.

Computing Gradients

Gradient computation is one of the most important part of training a deep learning model. This can be done easily in Theano. Let’s define a function as the cube of a variable and determine its gradient.

x = T.dscalar('x')
y = x**3
qy = T.grad(y,x)
f = function([x],qy)
f(4)

This returns 48 which is 3x2 for x=4. Lets see how Theano has implemented this derivative using the pretty-print feature as following:

from theano import pp  #pretty-print
print(pp(qy))

4. pp

In short, it can be explained as: fill(x3,1)*3*x3-1 You can see that this is exactly the derivative of x3. Note that fill(x3,1) simply means to make a matrix of same shape as x3 and fill it with 1. This is used to handle high dimensionality input and can be ignored in this case.

We can use Theano to compute Jacobian and Hessian matrices as well which you can find here.

There are various other aspects of Theano like conditional and looping constructs. You can go into further detail using following resources:

  1. Theano Conditional Constructs
  2. Theano Looping Statements
  3. Handling Shape Information

 

5. Modeling a Single Neuron

Lets start by modeling a single neuron.

Note that I will take examples from my previous article on neuron networks here. If you wish to go in the detail of how these work, please read this article. For modeling a neuron, lets adopt a 2 stage process:

  1. Implement Feed Forward Pass
    • take inputs and determine output
    • use the fixed weights for this case
  2. Implement Backward Propagation
    • calculate error and gradients
    • update weights using gradients

Lets implement an AND gate for this purpose.

 

Feed Forward Pass

An AND gate can be implemented as:

2

Now we will define a feed forward network which takes inputs and uses the shown weights to determine the output. First we will define a neuron which computes the output a.

import theano
import theano.tensor as T
from theano.ifelse import ifelse
import numpy as np

#Define variables:
x = T.vector('x')
w = T.vector('w')
b = T.scalar('b')

#Define mathematical expression:
z = T.dot(x,w)+b
a = ifelse(T.lt(z,0),0,1)

neuron = theano.function([x,w,b],a)

I have simply used the steps we saw above. If you are not sure how this expression works, please refer to the neural networks article I have referred above. Now let’s test out all values in the truth table and see if the AND function has been implemented as desired.

#Define inputs and weights
inputs = [
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
]
weights = [ 1, 1]
bias = -1.5

#Iterate through all inputs and find outputs:
for i in range(len(inputs)):
    t = inputs[i]
    out = neuron(t,weights,bias)
    print 'The output for x1=%d | x2=%d is %d' % (t[0],t[1],out)

5. single neuron

Note that, in this case we had to provide weights while calling the function. However, we will be required to update them while training. So, its better that we define them as a shared variable. The following code implements w as a shared variable. Try this out and you’ll get the same output.

import theano
import theano.tensor as T
from theano.ifelse import ifelse
import numpy as np

#Define variables:
x = T.vector('x')
w = theano.shared(np.array([1,1]))
b = theano.shared(-1.5)

#Define mathematical expression:
z = T.dot(x,w)+b
a = ifelse(T.lt(z,0),0,1)

neuron = theano.function([x],a)

#Define inputs and weights
inputs = [
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
]

#Iterate through all inputs and find outputs:
for i in range(len(inputs)):
    t = inputs[i]
    out = neuron(t)
    print 'The output for x1=%d | x2=%d is %d' % (t[0],t[1],out)

Now the feedforward step is complete.

 

Backward Propagation

Now we have to modify the above code and perform following additional steps:

  1. Determine the cost or error based on true output
  2. Determine gradient of node
  3. Update the weights using this gradient

Lets initialize the network as follow:

#Gradient
import theano
import theano.tensor as T
from theano.ifelse import ifelse
import numpy as np
from random import random

#Define variables:
x = T.matrix('x')
w = theano.shared(np.array([random(),random()]))
b = theano.shared(1.)
learning_rate = 0.01

#Define mathematical expression:
z = T.dot(x,w)+b
a = 1/(1+T.exp(-z))

Note that, you will notice a change here as compared to above program. I have defined x as a matrix here and not a vector. This is more of a vectorized approach where we will determine all the outputs together and find the total cost which is required for determining the gradients.

You should also keep in mind that I am using the full-batch gradient descent here, i.e. we will use all training observations to update the weights.

Let’s determine the cost as follows:

a_hat = T.vector('a_hat') #Actual output
cost = -(a_hat*T.log(a) + (1-a_hat)*T.log(1-a)).sum()

In this code, we have defined a_hat as the actual observations. Then we determine the cost using a simple logistic cost function since this is a classification problem. Now lets compute the gradients and define a means to update the weights.

dw,db = T.grad(cost,[w,b])

train = function(
    inputs = [x,a_hat],
    outputs = [a,cost],
    updates = [
        [w, w-learning_rate*dw],
        [b, b-learning_rate*db]
    ]
)

In here, we are first computing gradient of the cost w.r.t. the weights for inputs and bias unit. Then, the train function here does the weight update job. This is an elegant but tricky approach where the weights have been defined as shared variables and the updates argument of the function is used to update them every time a set of values are passed through the model.

#Define inputs and weights
inputs = [
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
]
outputs = [0,0,0,1]

#Iterate through all inputs and find outputs:
cost = []
for iteration in range(30000):
    pred, cost_iter = train(inputs, outputs)
    cost.append(cost_iter)
    
#Print the outputs:
print 'The outputs of the NN are:'
for i in range(len(inputs)):
    print 'The output for x1=%d | x2=%d is %.2f' % (inputs[i][0],inputs[i][1],pred[i])
    
#Plot the flow of cost:
print '\nThe flow of cost during model run is as following:'
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(cost)

6. output single update

Here we have simply defined the inputs, outputs and trained the model. While training, we have also recorded the cost and its plot shows that our cost reduced towards zero and then finally saturated at a low value. The output of the network also matched the desired output closely. Hence, we have successfully implemented and trained a single neuron.

 

6. Modeling a Two-Layer Neural Network

I hope you have understood the last section. If not, please do read it multiple times and proceed to this section. Along with learning Theano, this will enhance your understanding of neural networks on the whole.

Lets consolidate our understanding by taking a 2-layer example. To keep things simple, I’ll take the XNOR example like in my previous article. If you wish to explore the nitty-gritty of how it works, I recommend reading the previous article.

The XNOR function can be implemented as:

6

As a reminder, the truth table of XNOR function is:

8. tt xnor case 1

Now we will directly implement both feed forward and backward at one go.

Step 1: Define variables

import theano
import theano.tensor as T
from theano.ifelse import ifelse
import numpy as np
from random import random

#Define variables:
x = T.matrix('x')
w1 = theano.shared(np.array([random(),random()]))
w2 = theano.shared(np.array([random(),random()]))
w3 = theano.shared(np.array([random(),random()]))
b1 = theano.shared(1.)
b2 = theano.shared(1.)
learning_rate = 0.01

In this step we have defined all the required variables as in the previous case. Note that now we have 3 weight vectors corresponding to each neuron and 2 bias units corresponding to 2 layers.

 

Step 2: Define mathematical expression

a1 = 1/(1+T.exp(-T.dot(x,w1)-b1))
a2 = 1/(1+T.exp(-T.dot(x,w2)-b1))
x2 = T.stack([a1,a2],axis=1)
a3 = 1/(1+T.exp(-T.dot(x2,w3)-b2))

Here we have simply defined mathematical expressions for each neuron in sequence. Note that here an additional step was required where x2 is determined. This is required because we want the outputs of a1 and a2 to be combined into a matrix whose dot product can be taken with the weights vector.

Lets explore this a bit further. Both a1 and a2 would return a vector with 4 units. So if we simply take an array [a1, a2] then we’ll obtain something like [ [a11,a12,a13,a14], [a21,a22,a23,a24] ]. However, we want this to be [ [a11,a21], [a12,a22], [a13,a23], [a14,a24] ]. The stacking function of Theano does this job for us.

 

Step 3: Define gradient and update rule

a_hat = T.vector('a_hat') #Actual output
cost = -(a_hat*T.log(a3) + (1-a_hat)*T.log(1-a3)).sum()
dw1,dw2,dw3,db1,db2 = T.grad(cost,[w1,w2,w3,b1,b2])

train = function(
    inputs = [x,a_hat],
    outputs = [a3,cost],
    updates = [
        [w1, w1-learning_rate*dw1],
        [w2, w2-learning_rate*dw2],
        [w3, w3-learning_rate*dw3],
        [b1, b1-learning_rate*db1],
        [b2, b2-learning_rate*db2]
    ]
)

This is very similar to the previous case. The key difference being that now we have to determine the gradients of 3 weight vectors and 2 bias units and update them accordingly.

 

Step 4: Train the model

inputs = [
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
]
outputs = [1,0,0,1]

#Iterate through all inputs and find outputs:
cost = []
for iteration in range(30000):
    pred, cost_iter = train(inputs, outputs)
    cost.append(cost_iter)
    
#Print the outputs:
print 'The outputs of the NN are:'
for i in range(len(inputs)):
    print 'The output for x1=%d | x2=%d is %.2f' % (inputs[i][0],inputs[i][1],pred[i])
    
#Plot the flow of cost:
print '\nThe flow of cost during model run is as following:'
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(cost)

7. 2 layer op

We can see that our network has successfully learned the XNOR function. Also, the cost of the model has reduced to reasonable limit. With this, we have successfully implemented a 2-layer network.

 

End Notes

In this article, we understood the basics of Theano package in Python and how it acts as a programming language. We also implemented some basic neural networks using Theano. I am sure that implementing Neural Networks on Theano will enhance your understanding of NN on the whole.

If hope you have been able to follow till this point, you really deserve a pat on your back. I can understand that Theano is not a traditional plug and play system like most of sklearn’s ML models. But the beauty of neural networks lies in their flexibility and an approach like this will allow you a high degree of customization in models. Some high-level wrappers of Theano do exist like Keras and Lasagne which you can check out. But I believe knowing the core of Theano will help you in using them.

Python Libraries Artificial Neural Networks (ANNs) +3 What is the best neural network library for Python?

Source: https://www.quora.com/What-is-the-best-neural-network-library-for-Python

利用Python,四步掌握机器学习

本文由 伯乐在线J.F. 翻译,renlytime 校稿

为了理解和应用机器学习技术,你需要学习 Python 或者 R。这两者 都是与 C、Java、PHP 相类似的编程语言。但是,因为 Python 与 R 都比较年轻,而且更加“远离”CPU,所以它们显得简单一些。相对 于R 只用于处理数据,使用例如机器学习、统计算法和漂亮的绘图分析数据, Pthon 的优势在于它适用于许多其他的问题。因为 Python 拥有更 广阔的分布(使用 Jango 托管网站,自然语言处理 NLP,访问 Twitter、Linkedin 等网站的 API),同时类似于更多的传统语 言,比如 C python 就比较流行。

在Python中学习机器学习的四个步骤

1、首先你要使用书籍、课程、视频来学习 Python 的基础知识

2、然后你必需掌握不同的模块,比如 Pandas、Numpy、Matplotlib、NLP (自然语言处理),来处理、清理、绘图和理解数据。

3、接着你必需能够从网页抓取数据,无论是通过网站API,还是网页抓取模块Beautiful Soap。通过网页抓取可以收集数据,应用于机器学习算法。

4、最后一步,你必需学习机器学习工具,比如 Scikit-Learn,或者在抓取的数据中执行机器学习算法(ML-algorithm)。

1.Python入门指南:

有一个简单而快速学习Python的方法,是在 codecademy.com  注册,然后开始编程,并学习 Python 基础知识。另一个学习Python的经典方法是通过 learnpythonthehardway ,一个为广大 Python 编程者所推荐的网站。然后还有一个优秀的 PDF, byte of python 。python社团还为初学者准备了一个Python资源列表list of python resources。同时,还有来自 O’Reilley 的书籍 《Think Python》,也可以从这里免费下载 。最后一个资源是 Python 用于计量经济学、统计学和数据分析的介绍:《Introduction to Python for Econometrics, Statistics and Data Analysis 》,其中也包含了 Python 的基础知识。

2.机器学习的重要模块

关于机器学习最重要的模块是:NumPyPandasMatplotlib 和 IPython 。有一本书涵盖了其中一些模块:《Data Analysis with Open Source Tools》 。然后来自于1.的免费书籍《Introduction to Python for Econometrics, Statistics and Data Analysis》,同时也包括 Numpy,Pandas,Matplotlib 和 IPython这几个模块。还有一个资源是 Python for Data Analysis: Data Wrangling with Pandas, NumPy, and IPython,也包含了一些很重要的模块。以下是其他免费模块的相关链接: Numpy (Numerical PythonNumpy UserguideGuide to NumPy),  Pandas (Pandas, Powerful Python Data Analysis ToolkitPractical Business PythonIntros to Pandas Data Structure)  和  Matplotlib books

其它资源:

3.从网站通过API挖掘和抓取数据

一旦理解了Python的基础知识和最重要的模块,你必需要学习如何从不同的源收集数据。这个技术也被称作网页抓取。传统的源是网站文本,通过API进入twitter或linkedin一类网站得到的文本数据。网页抓取方面的优秀书籍包括:《 Mining the Social Web》 (免费书籍),《Web Scraping with Python》 和《 Web Scraping with Python: Collecting Data from the Modern Web》。

最后这个文本数据必须要转换为数值数据,通过自然语言处理(NLP)技术完成, Natural language processing with Python 和 Natural Language Annotation for Machine Learning 上面有相应的资料。其它的数据包括图片和视频,可以使用计算机图像技术分析: Programming Computer Vision with PythonProgramming Computer Vision with Python: Tools and algorithms for analyzing images  和  Practical Python and OpenCV ,这些是图片分析方面的典型资源。

以下例子中包括可以用基本的Python命令行实现,有教育意义,而且有趣的例子,以及网页抓取技术。

4. Python 中的机器学习

机器学习可以分为四组:分类,聚类,回归和降维。

drop_shadows_background2

“分类”也可以称作监督学习,有助于分类图片,用来识别图片中的特征或脸 型,或者通过用户外形来分类用户,并给他赋不同的分数值。“聚类”发生在无监督学习的情况,允许用户在数据中识别组/集群。“回归”允许通过参数集估算一 个值,可以应用于预测住宅、公寓或汽车的最优价格。

modules, packages and techniques 罗列了 Python、C、Scala、Java、Julia、MATLAB、Go、R 和 Ruby等语言中所有学习机器学习的重要模块、包和技巧。有关Python机器学习的书籍,我特别推荐《Machine learning in action》。尽管有点短,但它很可能是机器学习中的经典,因为它提到了“集体智慧编程时代”:Programming Collective Intelligence。 这两本书帮助你通过抓取数据建立机器学习。最近关于机器学习的出版物大多都是基于模块 scikit-learn 。由于所有的算法在模块中都已实现,使 得机器学习非常简单。你唯一要做的事就是告诉 Python ,应该使用哪一个机器学习技巧 (ML-technique) 来分析数据。

免费的 scikit-learn教程 可以在 scikit-learn 官方网站上找到。其他的帖子可以通过以下链接获取:

关于机器学习和 Python 中模块 scikit-learn 的书籍:

接下来数月将要发行的书籍包括:

机器学习相关的课程和博客

你想要得到一个学位,加入在线课程,或者参加线下讲习班、大本营或大学课程么?这里有一些关于逻辑分析、大数据、数据挖掘和数据科学的在线教育站点链接:Collection of links 。另外推荐一些在线课程–来自Udacity的Coursera 课程:machine learning  和 Data Analyst Nanodegree。还有一些关于机器学习的博客列表:List of frequently updated blogs

最后是来自 Jake Vanderplas 和 Olivier Grisel,关于探索机器学习的优秀 youtube 视频课程

机器学习理论

想要学习机器学习的理论?那么,《The Elements of statistical Learning》和《 Introduction to Statistical Learning》 是常常被引用的经典。然后还有另外两本书籍:《Introduction to machine learning 》和《 A Course in Machine Learning》。这些链接包括免费的PDF,你不需要付费!如果不想阅读这些书籍,请观看视频:15 hours theory of machine learning

如何从菜鸟程序员成长为高手

2016-02-24 蛋疼的axb ACSE
关注上方“ACSE”来及时了解中国理工科留学生联盟的最新动态以及新鲜科技好文章
小编有话说
从今天开始ACSE公众号每天会更新一篇科技相关的精选好文章来帮助大家了解科技前沿以及提高自己的技术水平。
今天这篇文章是由大神级别程序员总结的学习方法,值得收藏起来每周看一遍,只要照着一一做到,总有一天能够成为高手。
1.摘要
最近有一些毕业不久的同事问我:“你工作的时候有没有什么窍门?怎么才能快速成为高手?”
想起当初刚入职,新人培训的时候,也跟其他同事讨论过这个问题:如何才能成为业界大牛?当时自己只是觉得兴趣是最好的老师,思路方法什么的没有多想。
加 入微博平台架构部的时间也不短了,趁着快过春节总结了一下自己入职微博以来的工作情况,从互联网开发的半个门外汉,到如今能设计一些架构、排查一些问题、 分享一些经验,收获颇多,感想颇多,也逐渐意识到思路和方法的重要性,在此跟大家分享一下。主要分为学、做、想三方面。
2.学会学习
学习无疑是程序员最为重要的素质之一,尤其是互联网这种日新月异的行业,把学习当做工作的一大半也不为过。
2.1.自主学习
最近发现身边的人并不是不想学习,只是每天都在纠结自己到底学什么好:简单的没挑战,复杂的看不懂;旧技术怕过时,新技术没方向…… 
讲 讲自己毕业后的经历,毕业之后去了个不大不小的公司,工作主要是做一些XX管理系统之类的东西,没什么挑战,也用不上什么技术,基本上前端用个extjs 后面套个sql server就解决了。工作稳定了几年,业余时间除了wow没别的事情做,觉得这么闲下去不是办法,于是之后一年的时间里,用上班摸鱼和下班休息的时间学 了这些东西:
1. 闲着无聊想做个小游戏,发现游戏相关的书大多是英文的,看不懂,一咬牙翻译了《Real-time rending 3rd》的前几章,刚开始前言都看不懂,只能一个词一个词的翻字典,一句话要琢磨几个钟头到底作者说的到底是什么意思。翻译了几百页英文书之后,发现自己 看英文书没什么障碍了,于是开始每天用休息和摸鱼的时间看书。
2. 看完游戏引擎的书之后,把irrlicht引擎的代码看了一遍,然后自己山寨了一个3d渲染的场景管理器,还有个朴素的渲染引擎。
给自己的游戏引擎写了个基于脚本语言的解释器,为此看了不少编译原理和虚拟机的书,了解了程序究竟是什么东西,这是我觉得收益很大的一件事情。
3. 看编译原理的书的时候发现操作系统的知识有些欠缺,又去看了linux内核相关的书。之后买了个开发板天天修改内核玩,毕业以后又一次了解了内核的cpu 调度、内存管理和文件系统,了解了应用是怎么跑在操作系统上,操作系统又是怎么运行在硬件上的,这也是收益很大的一件事情。
4. 看完操作系统又顺着看网络相关的书,之后把lighthttpd的代码看了一遍,用c写了个linux下的http服务器,把几种网络编程模型挨个实现了一遍。
5. 实现http服务器的过程中觉得自己编码能力还是有欠缺,把代码大全翻了一遍,顺着又去看了设计模式的书,并且用自己的理解把每个模式用文字重新描述了一遍。
6. 中间还看了很多语言和框架相关的书,就不一一列举了。可以参考这里。
我把学习的方向分为三类:
1. 为了工作,满足当前工作所必备的知识
2. 为了提升,与当前工作相关的知识(深度)
3. 拓展视野,与当前工作无关的知识(广度)
学习(1)之后只是个熟练工,2和3才是提升自己的途径,伴随着知识储备的提升,接触新事物时更容易找到相似的知识加以类比,加快理解,也更容易掌握本质。如果每天都在纠结“到底学什么”,那么只能说明还是学的太少了。(真正没什么可学的大牛们应该不会读到这里吧……)
所 以,如果觉着没什么东西可以学的时候,那么可以考虑一下学一下更有深度的知识(比如虚拟机或编译器),或者完全不同的知识(新的语言或当前比较火的方 向),甚至完全不相干的知识(单纯练习英文阅读,学习ppt排版之类)吧。随着知识储备增加,自己的不足和未来的学习的方向也会更加明确起来。
2.2.向历史学习
以微博为例,在微博发展的过程中经历了不少波折,并逐渐衍生出了目前的系统架构。很多新人最喜欢问的问题便是“现在线上是怎么做的?”
这 个问题不错,但是还不够好。在程序员的世界里罕有能解决所有问题的“银弹”,当前的做法用不了多久也会被替换掉,如果想了解一件事情,那么就多关注一下 “它是怎么变成今天这样的”吧。学会用发展的眼光看问题,了解一些经历过的经验教训,收获会比单纯学会一件什么事情多的多。
那么,如何向历史学习?
1. 公司内部的资料库、wiki等大都会有旧时的资料,刚入职时大多不会太忙,这些资料库简直是挖不完的宝藏
2. 部门内部分享,比如我当初入职时经常去听“微博XXXX架构演化历程”之类的内部分享
多问一下自己”它为什么不那么设计“
3. 老员工忆苦思甜吹牛逼的时候多奉承几句_(:з」 ∠)_
2.3.向他人学习
这里有两个极端,
1. 有的人喜欢自己闷头捣鼓,什么也不问,这必然是不利于自己提高的;
2. 也有人碰到问题就问,这也有问题,浪费他人时间不说,更关键的是说明这人向他人学习的思路错了,要学习他人的并不是具体某个知识(要学知识看书就能解决了),而是学习别人的思维方式。
但是思维方式这种东西很难通过交流的方式学到,后来我发现有个很简单的学习方式:口头禅。举几个例子,大家体会一下:
“这个其实是两个问题”
“有没有更好的方案”
“能不能举个例子”
“能不能给个一句话总结”
除了口头禅,很多牛人都会有非常鲜明的思维方式和处事原则,如果有幸与业界的大牛共事,那么恭喜你,只要多交流、多观察、多思考,那么提升速度会提升好几个数量级。
3.多做有意义的事情
有的人每天时间浪费在跟问题本身无关的事情上,比如我要设计架构的时候还要考虑架构图怎么画,写完代码还要反复部署测试好几轮才pass,查bug的时候把时间浪费在扫日志上。人的精力总是有限的,把时间浪费在这些事情上面,让自己提高的时间就变得少了。
3.1.练习,更多的练习
这里有个误区:“做有意义的事情”不等于“只做自己没做过的事情”。
对于程序员来说,写代码是基本功中的基本功,编码的规范、设计的权衡、甚至顺手的IDE快捷键都要靠平日的试错和积累,很难通过几本书或者几天培训领悟到。
曾 经目睹一些人写代码一年之后开始做一些小项目的设计,然后就迫不及待的把重心全都转移到设计甚至架构上,这种没有基础能力支撑做出的设计和架构最多只能算 是高级意淫,大多没等落地就荒废了,意义不大。究其原因,大多是设计出来的东西“不好做”或者“不好用”,就像是只看过一遍课本就去参加高数考试,现实 吗?(学霸们我错了……)
举 个例子,几年前在看设计模式的过程中,用qt做了个看漫画的应用,把能用的模式都试了一遍,当然有很多用的不合适的地方,正是这些不合适的地方让我对面向 对象编程和设计模式的思考深入了很多,如何权衡灵活性和复杂性也有了新的认识。之后在设计很多系统的时候少走了很多弯路,既保证了时间点又保证了质量。如 果当时指望着“用的时候再说”,大概已经被项目坑的不能自理了。
3.2.善用工具
工具能解决的事情就用工具去解决,好的工具能节约大把的时间用在更有意义的事情上。
工具的范畴很广,比如linux的各种命令、比如团队内部的各种系统、比如顺手的应用、甚至包括上下班骑的自行车。只要能节约时间、提高效率,那就值得一试。
在这里我列举几个大幅度提升了我的效率的东西:
1. 双屏显示器
2. 顺手的键盘
3. google(不是baidu!不是bing!)
4. mac
5. mac上的应用:idea、alfread、omnifocus、甚至synergy和istats menus之类跟开发本身关系不大的应用。
我更倾向于把“使用工具”作为一种生活态度:是否希望让自己的生活专注于有意义的事情。如果你认同这个观点,那么想一想投入和回报比例,还是很可观的。
(当然,为了不花钱而自己破解应用的大神也是极叼的……)
3.3.提高时间的利用率
时间是所有期待提升自己的人最宝贵的资源,效率再高,没时间做也没意义。
网上有个流传挺广的图:打扰程序员的成本。事实上我每天的工作时间非常碎片化,来到公司之后可能不断的接电话、被问问题、被拉去开会、回复邮件等等;也经常会有时间不够用或者没事做的困惑,这里分享一下心得:
1. GTD可以整合很多碎片时间。除了把事做完之外,把上下文相关的事情集中在一起完成也很有帮助。比如把几件想去其他办公室做的事情整合成一趟完成。
2. 减少无意义的时间浪费,比如家住在公司边上可以每天节省几个小时的时间用来学习或者做别的事情。(但如果节省下来的时间用来刷微博,那就没有必要了。)
另外一个很有趣的现象:一个软件的注册费就10几刀,贵些的几百刀,把日常用到的所有工具的费用全加起来都顶不上一个肾6贵,但是很多人还是坚持着没有破解不用的观念,为了几百块钱浪费了大把时间。
3. 加班可以创造很多时间,并且能有效减少被打扰的几率,但是也会给身体和精神带来很大负担。因此加班做的事情必须能对个人进步产生足够多的收益。如果加班只是用来处理无意义的工作的话,那应该是日常工作出了什么问题。
4. 事情可以分成紧急重要、紧急不重要、重要不紧急、不重要不紧急四类,在todo列表里随时要有重要不紧急的事情。
4.学会思考
4.1.深究
当有什么问题解决不了的时候,很多人会有畏难或者拖延的情绪,典型口头禅就是“就这么凑合着用吧”或者“先这样吧,以后有时间再研究”,说这些话的人大多并不是真的那么忙,甚至有人一边刷着微博一边跟我说没时间研究……(你tm在逗我?)
要克服畏难情绪其实很简单,找一个具体的似懂非懂的问题,想尽办法把问题研究清楚,体会几次解决问题时的愉悦感,建立自信。
大部分问题其实没有什么高深的科学原理,甚至只要翻几页书就解决了,但是遇到问题不深究,久而久之会形成自我暗示:这些问题是我懂的,那些是我不懂的,自己反而把自己进步的路给堵上了。
说到如何深究,也有几条心得:
1. 遇事多想为什么,并且要反复问为什么。很多貌似理解了的问题过一阵再重新想想,往往会发现之前还有没考虑到的地方
2. 问题要有明确答案,哲学之类的就别纠结了
3. 查找资料时选权威的书籍或者网站,避免被误导
4. 找人讨论,或者直接拉小伙伴入伙,既可以互相交流,又可以互相监督
5. 分享你的成果
6. 不要所有事情全都深究,会给自己太多压力
4.2.多说,多写,多交流
平常工作中有一个感受,有交流和写作习惯的人思路会更清晰一些,能接触到的观点也会多一些。这方面其实属于我的弱项,大概总结几个观点。
1. 隔一段时间最好能书面形式总结一下最近的工作,比如说写个心得感悟,或者持续更新自己的简历
2. 写作的时候有两个难点:对要说明的事情做总结和抽象,形成观点统一、调理清晰的主线;从对方的视角考虑,把事情说明白,避免自言自语。
3. 找人讨论之前自己先要有个基本完整的思路,否则大部分的时间都要耗在解释原理之类的上网查反而更快的事情上。
4. 讨论之后要有一句话就能说明白的结论和描述清晰的时间点。
5. 有些人喜欢纠结于“这个不是我的问题,为什么要我处理”之类的事情。在我看来这是很好的机会。既能增长见识,又能展示水平,还能留个认真负责的好名声,何乐而不为呢。
5.最后
最后分享一下关于我理解的程序员的自我修养,在我看来,可以总结为:负责任,重名声。
负责任,说的更具体些:写的代码自己有没有测过、做的框架自己有没有用过、设计的架构自己有没有认真权衡过。
重名声,说的直接些:没有测过的代码、没有用过的框架、没有权衡过的方案有没有脸交付给别人。
与各位共勉。
作者:蛋疼的axb

原网址:http://blog.2baxb.me/archives/1077
中国理工科留学生联盟(ACSE)
致力于推动留美各校理工科留学生间的相互交流以及资源共享和对接

程序员,你的安全感呢?

作者:杨栋

链接:http://www.cnblogs.com/yangdong/p/5190818.html

同病相连

最近跟一位同事谈心,他非常热爱技术,是一个不折不扣的极客,不仅如此他有很强的执行力,并能持之以恒,从他的身上我看到了未来几年将会成长起来的一个技术牛人。但是,他有比较严重的焦虑症,比如:几天没有看书就会非常纠结,通常情况是他需要花时间来陪孩子和家人,他会感觉自己浪费了宝贵时间,精力无法集中在当前所做的事情上。我接触的同事中,越是对技术有追求,好像越是有这样的感觉,算起来这种不安的感觉应该属于特定程序员群组中一种典型现象,其实做为导师的我也是常年被这种感觉所困扰。 他是这么描述自己的:

我已经工作4年了,但是我在数据库底层,HTTP协议,并发,分布式系统都没有深入地理解,我觉得特别害怕。

不用讨论工作4年的程序员应该有什么样的表现,掌握多上技术,深度如何,视野是否开阔,我们来看看别人眼中的他吧:

  • 对技术极度有热情
  • 学东西非常快,几周时间就搞定了Ansible, Chef, Puppet
  • 阅读非常广,除了技术之外,涉足项目管理,金融,心里,社会等

看看他的书单(我截取了其中1/4的一年要读完的书单,实际上他读完的书比计划要多),也会对他有更深刻的认识:

  • 像外行一样思考,像专家一样实践:科研成功之道(修订版)
  • 古今数学思想(新版·典藏本)(套装全3册)(第1~3册)
  • 思考,快与慢
  • 数据化管理:洞悉零售及电子商务运营
  • 探索复杂性
  • 日志管理与分析权威指南

心理学上的安全感

安全感是心理学研究中的重要概念之一,最早见于弗洛伊德精神分析的理论研究。虽然国内外对此做过诸多研究,然而对于“安全感”至今尚未达成共识,以下列举了一些关于安全感的定义:

  • 弗洛伊德认为当个体所受到的刺激超过了本身控制和释放能量的界限时,个体就会产生不安全感。换句话说,在弗洛伊德的精神分析理论中,冲突、焦虑、防御机制等是由个人幼年、成年阶段某种欲望的控制与满足方面缺乏安全感造成的。
  • 人本主义心理学家马斯洛最早对安全感作出了明确界定,指出“安全感”是一种从恐惧、焦虑中脱离出来的信心、安全和自由的感觉,特别是满足一个人现在和未来各种需要的感觉。
  • 安莉娟等对精神分析理论、人本主义心理学理论中的安全感理论进行总结,提出安全感的定义为:安全感是对可能出现的对身体或心理的危险或风险的预感,以及个体在应对处置时的有力无力感,主要表现为确定感和可控制感。

从以上的定义我们大致能够看出安全感大致有两大要素:负面的外部刺激,正面的内在能量。简单来说当内部能量能够抵消负面的外部刺激,人是有安全感,因为我的“能量结界”没有消散,反之则没有安全感,没有人会在“能量结界”被打穿之后还怡然自得。那么这个“能量结界”的大小就是所谓的舒适区域了,如果用绿色表示很安全的话,那么舒适区域应该是中心是深绿色周边是浅绿色的圆。理所当然,随着它的范围的增大,个人的舒适区域也就不断的增大。

为什么会焦虑

人为什么会焦虑,当某一件能够刺激内心产生负面影响的事情发生时,人们就有可能会产生焦虑的情绪。这是一种缺乏安全感的情绪和典型表现。在学生时代,我们会因为惧怕考试失败而焦虑;在职场上,我们会因为无法完成某项工作而焦虑;在孩子的教育过程中,我们会因为担心无法找到合适的学校而焦虑;在人到中年时,我们为因为身体的退步而焦虑。因为我们无法确定能否处理这种情形。因此对于一些场景,我们到会显得十分从容,“开卷考试,有书在手心中无忧”,“跟自己的下属沟通绩效问题,轻车熟路”,“住在一个教育资源较为发达的地区,孩子的教育问题就显得不那么明显”,“每天花半小时来做慢跑,非常显著的改善身体状况”。

奇普•康利(Chip Conley)在他的《如何控制自己的情绪》很好的阐释了为什么会焦虑:

焦虑 = 不确定性 * 无力感

在讲述如何控制焦虑者众情绪时,他分享了一段TED上的经历:

TED曾要求我谈谈幸福的无形资产,以及商界和政界领导人应如何开始学习衡量和重视人生最有意义的东西。这似乎是一个无情的讽刺,我的任务是登上讲坛,以一个专家的身份,探讨一个那时连我自己都觉得难以捉摸的主题。尽管我在《巅峰》一书中宣称要以自我实践的方法来经商,但我已经失去了那种神奇的感染力。“我陷入了觉得自己无用的思维定式,而能够克服这一挑战的唯一办法就是写下有关我人生经历的演讲词并练习无数遍。我以为追求完美是缓解焦虑的良药。你也许有过类似的遭遇,认为设定目标会让自己舒服。但事实是,追求完美只会放大焦虑。在接下来的几个月里,我一直痛苦地写着一份以幸福为主题的演讲词,这一次和我正常准备演讲的经历完全不同。我的风格是倾向于即兴发挥和贴近听众,而非机械式和反复演练。于是越临近TED大会,我就变得越焦虑。我的演讲被安排在会议的最后一天(就在电影导演詹姆斯·卡梅隆之前)。所以当我抵达会场时,我还有5天痛苦难熬的日子,要在聆听其他演讲者发言中度过,这使我越发焦虑。”

因此,越是不确定或者超出自己能力的事情,焦虑的情绪就越容易产生,而越是这样,从这种焦虑情绪正挣脱的信心就越低,不安全的感觉就越强。

哪样的程序员更有安全感

每个人都有一个自己的舒适区域,结合内部舒适区域和外部期待,下图能说明一些问题:

根据上图所示,具有安全感的程序员一般长这样:

跃跃欲试,接受挑战, 扩展自己的舒适区。我们的身边总是不乏这样的人,他们跃跃欲试,脸上总是挂着自信的笑容,总是各种场合中的焦点,从来不满足现状,每每有新挑战时,总会看到他们的身影。 如果用动态的眼光来看待他们的话,我们会发现他们的舒适区域始终处于一个动态的过程——始终在扩张之中,或者说他们在不断GET新技能。随着舒适区域的扩张,个人追求不断实现,而个人追求的实现,又带动其自身的扩张,还有什么比实现自己目标多带来的自信和成就感更足呢。等待的,将是社会期待的增加,也就是你的同事,领导对你有了认可,并提升了他们对你的期待,随之而来的将是更有挑战的工作,又一个扩展自己舒适区域或者GET新技能的机会便发生了。

快速学习, 迅速减小社会期望和舒适区的差别。程序员的一个非常厉(ku)害(bi)的技能就是学习能力。除去被逼迫的成分外,这是一个非常实用,堪称看家本领之一。因为IT行业技术迭代速度之快令人发指,当某一项技术还没有熟悉的时候,关于该技术的缺陷以及改进方案已经吵的很热了;当你刚刚为掌握某个软件开发实践而洋洋得意时,突如其来的xxx已死之说,真是让你死的心都有了。其中的例子数不胜数,我们不妨看看(一个例子说明)。ThoughtWorks对员工有这么一个要求,每年至少学习一门编程语言,其实真是不多,实际上每年学习的都要远远多于要求。因此,强悍的快速学习能力,能够快速武装自己,胜任新的工作,提神核心竞争力,迅速扩大舒适区同时减小社会期望与其的差别。当然,并非所有新技术都值得学习,但是有两点值得提出:1. 新技术的思想能够扩展自己的视野,拓宽自己的思路;2.新技术的获取,能够大大提升自己的学习能力,你会越学越快,这个加速度会一直保持到你的大脑达到生理水平的巅峰。

很强的执行力, 减小不确定性. 它的反义词大概是“拖延症”,俗称懒病。某百科上给出了这样的解释:

严重的拖延症会对个体的身心健康带来消极影响,如出现强烈的自责情绪、负罪感,不断的自我否定、贬低,并伴有焦虑症、抑郁症等心理疾病,一旦出现这种状态,需要引起重视。

看到这里,相信很多人都中招了吧。无限的拖延,无法正面改变即将发生的事情,但是它却能极大的增加事情的不确定性,并且随着事情的临近,这种不确定性在内心中的焦虑反应呈指数级增长,反过来,这种情绪又反哺拖延,除非有强大的外部力量介入,强行打破这种负能量闭环。说的这么高端,有没有实际的例子呢。不仅有,而且非常多,很多人大概都有这样的经历吧,在年终总结的截止日期的前一天晚上,奋笔疾书加班加点的写总结,又或者在做演讲的前一天晚上,开始写PPT。

获取安全感

Rule #1: 学习那些自信满满地程序员们

当然也需要甄别一下啦,有的人可能只是看起来很自信。不过上面提到的三个特征应该是妥妥的能够提升你的安全感的办法。其实我在写这条建议是,很是纠结。纠结在哪呢?我觉得内心没有安全感的程序员极度“肤浅”的分成两类:懒和其他。据非常不负责任统计(看看周围的人),其实很多时候还是因为懒,如果是真的懒,那就没救了。

Rule #2: 通过焦虑情绪公式来提升安全感

发动数学天赋,当某人或事情让人感到焦虑时,这两件事情能够帮忙:

制作一张平衡表列出你知道的和你能影响的,它可以帮助你消除不确定性,去掉你对不知道的事情的神秘感,明确你所面临的是什么。因为焦虑只会潜藏在黑暗中,人们对不了解的事物有一种天然的恐惧,就好比美味的螃蟹在一开始的时候并不是每个人都敢吃的。然而黑暗中的不明事物也有可能真的是你所恐惧的事物也说不定,但这又有什么关系呢!当你知道原来在黑暗之中潜藏了一个恐怖猎人——霸王龙,你的对手已经清晰了,接下来要考虑的是你是否有能力对付的了它。你的焦虑情绪现在全部由无力感组成了。

当你把所有的相关因素归类到这四个象限后,也就意味着能够帮助你消除的计划产生了:你不需要对不能影响的事情做出任何反应,因为只是徒劳而已;你需要做两件事情,弄清楚那些不知道的因素,做一些能够对解决当前问题产生正面影响的行动。

想想最极端的结果,降低无力感,如果最快的结果也是能够承受的,那还有什么是输不起的呢,更何况通常最坏的结果都不是最坏的,最坏的是由最坏的结果所引发的内心恐惧,焦虑和不安的负面情绪。当然每个人的无力感是不同的,因为每个人的舒适区域是不同的,舒适区域越大,无力感想对会越小。这很好理解,因为从概率的角度来讲,你能处理的问题范围,把握度会随着舒适区域的增大而增强。但直面极端结果是一个普适的方法。一方面,往往当最坏的事情发生时,你却释然了,反而一身轻松,能够坦然面对。这正是该公式所表达的核心思想之一,当结果发生时,不确定性为0,焦虑的情绪得到了释放,你当然会前所未有的轻松,这也是为什么人们到了让TA抓狂的事情发生时,却能坦然处之,临危不乱。另一方面,想想最极端的结果,有助于你评估失败的代价,很多时候人都是被自己或者他人吓怕了,一旦评估的结果并没有那么不可接受,自然也就没有必要战战兢兢的过着了。

Rule #3: 匹配外部期待和个人能力

左图是一张耶基斯-多德森定律图,其中包含三个要素:效率,动机和任务难易程度。在一般情况下,动机愈强烈,工作积极性愈高,潜能发挥的愈好,取得的效率也愈大;与此相反,动机的强度愈低,效率也愈差。因此,工作效率是随着动机的增强而提高的。然而,心理学家耶基斯和多德森的研究证实,动机强度与工作效率之间并不是线性关系,而是倒U形的曲线关系。具体体现在:动机处于适宜强度时,工作效率最佳;动机强度过低时,缺乏参与活动的积极性,工作效率不可能提高;动机强度超过顶峰时,工作效率会随强度增加而不断下降,因为过强的动机使个体处于过度焦虑和紧张的心理状态,干扰记忆、思维等心理过程的正常活动。

因此,你需要做的是让别人更好的了解自己,如果你觉得自己很厉害但是确没能让别人知晓,那么别人对你的期待就会低于你的预期,你将要做的工作的难度也不太可能匹配你所掌握的技能,当然面对这样的工作,估计大部分人也没有新鲜,激动,亢奋,大鸡血的感觉吧。另外一方面,如果你给别人的感觉是很牛X,结果有可能让你面临超出自己技能很多的任务,这会增加你的焦虑,降低你的效率,影响个人的名声。

Rule #4: 焦虑,焦虑着也就没那么焦虑了。

说了这么多,感觉焦虑是一种要完全消灭,即便不能消灭也叫尽量避免的情绪,但凡事没有绝对,完全没有焦虑这种情绪也是不可取的,程序员需要适时地扩大自己的舒适区,而且焦虑也有它正能量的一面。

走出舒适区会增加人的焦虑程度,从而产生应激反应,其结果是提升对工作的专注程度。在这个区域中被称作最佳表现区——在这个区域之中,人的工作表现将会得到改善,并且他们的技巧也会被优化。但是罗伯特 耶基斯(1907)的报告中提到“焦虑可以改善工作表现,但是当超过某一最佳激励状态之后,工作表现就开始恶化”,如果一个人离开最佳表现区,他将进入一个危险区,在危险区中焦虑程度的上升或者舒适程度下降会带来工作表现的快速恶化。

所以在绩效管理之中管理者,或者是教练应该让人进入最佳表现区,并且维持一段足够的时间,从而达到更好的工作表现,提升他们的技巧,并且将这些表现和技巧固定下来。同样的道理,在目标设定之中改变焦虑的程度就会改变工作表现。

程序员的编程能力层次模型

来源:良少的博客(@虚拟化良少)

网址:http://blog.csdn.net/shendl/article/details/43835421

前言

程序员的编程技能随着经验的积累,会逐步提高。我认为编程能力可以分为一些层次。

下面通过两个维度展开编程能力层次模型的讨论。

一个维度是编程技能层次,另一个维度是领域知识层次。

编程技能层次

编程技能层次,指的程序员设计和编写程序的能力。这是程序员的根本。

0段—非程序员:

初学编程者,遇到问题,完全是懵懵懂懂,不知道该怎么编程解决问题。也就是说,还是门外汉,还不能称之为“程序员”。计算机在他面前还是一个神秘的黑匣子。

1段—基础程序员:

学习过一段时间编程后,接到任务,可以编写程序完成任务。

编写出来的代码,正常情况下是能够工作的,但在实际运行中,碰到一些特殊条件就会出现各类BUG。也就是说,具备了开发Demo软件的能力,但开发的软件真正交付给客户使用,恐怕会被客户骂死。

程序员程序是写好了,但到底为什么它有时能正常工作,有时又不行,程序员自己也不知道。

运行中遇到了bug,或者需求改变,需要修改代码或者添加代码,很快程序就变得结构混乱,代码膨胀,bug丛生。很快,就连最初的开发者自己也不愿意接手维护这个程序了。

2段—数据结构:

经过一段时间的编程实践后,程序员会认识到“数据结构+算法=程序”这一古训的含义。他们会使用算法来解决问题。进而,他们会认识到,算法本质上是依附于数据结构的,好的数据结构一旦设计出来,那么好的算法也会应运而生。

设计错误的数据结构,不可能生长出好的算法。

记得某一位外国先贤曾经说过:“给我看你的数据结构!”

3段—面向对象:

再之后,程序员就会领略面向对象程序设计的强大威力。大多数现代编程语言都是支持面向对象的。但并不是说,你使用面向对象编程语言编程,你用上了类,甚至继承了类,你就是在写面向对象的代码了。

我曾经见过很多用Java,Python,Ruby写的面向过程的代码。

只有你掌握了接口,掌握了多态,掌握了类和类,对象和对象之间的关系,你才真正掌握了面向对象编程技术。

就算你用的是传统的不支持面向对象的编程语言,只要你心中有“对象”,你依然可以开发出面向对象的程序。

如,我用C语言编程的时候,会有意识的使用面向对象的技巧来编写和设计程序。用struct来模拟类,把同一类概念的函数放在一起模拟类。如果你怀疑用C语言是否能编写出面向对象的代码,你可以看一下Linux内核,它是用C语言编写的,但你也可以看到它的源代码字里行间散发出的浓浓的“对象”的味道。

真正掌握面向对象编程技术并不容易。

在我的技术生涯中,有两个坎让我最感头疼。

一个坎是Dos向Windows开发的变迁过程中,框架的概念,很长一段时间我都理解不了。Dos时代,都是对函数库的调用,你的程序主动调用函数。Windows时代,则换成了框架。就算是你的main程序,其实也是被框架调用的。UI线程会从操作系统获取消息,然后发送给你的程序来处理。Java程序员熟悉的Spring框架,也是这样一个反向调用的框架。

现在因为“框架”这个术语显得很高大上,因此很多“类库”/“函数库”都自称为“框架”。在我看来这都是名称的滥用。

“类库”/“函数库”就是我写的代码调用它们。

“框架”就是我注册回调函数到框架,框架来调用我写的函数。

另一个坎就是面向对象。很长一段时间我都不知道应该怎么设计类和类之间的关系,不能很好的设计出类层次结构来。

我记得当时看到一本外国大牛的书,他讲了一个很简单、很实用的面向对象设计技巧:“叙述问题。然后把其中的名词找出来,用来构建类。把其中的动词找出来,用来构建类的方法”。虽然这个技巧挺管用的,但也太草根了点,没有理论依据,也不严谨。如果问题叙述的不好,那么获得的类系统就会是有问题的。

掌握面向对象思想的途径应该有很多种,我是从关系数据库中获得了灵感来理解和掌握面向对象设计思想的。

在我看来,关系数据库的表,其实就是一个类,每一行记录就是一个类的实例,也就是对象。表之间的关系,就是类之间的关系。O-Rmapping技术(如Hibernate),用于从面向对象代码到数据库表之间的映射,这也说明了类和表确实是逻辑上等价的。

既然数据库设计和类设计是等价的,那么要设计面向对象系统,只需要使用关系数据库的设计技巧即可。

关系数据库表结构设计是很简单的:

1、识别表和表之间的关系,也就是类和类之间的关系。是一对一,一对多,多对一,还是多对多。这就是类之间的关系。

2、识别表的字段。一个对象当然有无数多的属性(如,人:身高,体重,性别,年龄,姓名,身份证号,驾驶证号,银行卡号,护照号,港澳通行证号,工号,病史,婚史etc),我们写程序需要记录的只是我们关心的属性。这些关心的属性,就是表的字段,也就是类的属性。“弱水三千,我取一瓢饮”!
4段—设计模式:

曾经在网上看到这样一句话:“没有十万行代码量,就不要跟我谈什么设计模式”。深以为然。

记得第一次看Gof的设计模式那本书的时候,发现虽然以前并不知道设计模式,但在实际编程过程中,其实还是自觉使用了一些设计模式。设计模式是编程的客观规律,不是谁发明的,而是一些早期的资深程序员首先发现的。

不用设计模式,你也可以写出满足需求的程序来。但是,一旦后续需求变化,那么你的程序没有足够的柔韧性,将难以为继。而真实的程序,交付客户后,一定会有进一步的需求反馈。而后续版本的开发,也一定会增加需求。这是程序员无法回避的现实。

写UI程序,不论是Web,Desktop,Mobile,Game,一定要使用MVC设计模式。否则你的程序面对后续变化的UI需求,将无以为继。

设计模式,最重要的思想就是解耦,通过接口来解耦。这样,如果将来需求变化,那么只需要提供一个新的实现类即可。

主要的设计模式,其实都是面向对象的。因此,可以认为设计模式是面向对象的高级阶段。只有掌握了设计模式,才能认为是真正彻底掌握了面向对象设计技巧。

我学习一门新语言时(包括非面向对象语言,如函数式编程语言),总是会在了解了其语法后,看一下各类设计模式在这门语言中是如何实现的。这也是学习编程语言的一个窍门。

5段–语言专家:

经过一段时间的编程实践,程序员对某一种常用的编程语言已经相当精通了。有些人还成了“语言律师”,擅长向其他程序员讲解语言的用法和各种坑。

这一阶段的程序员,常常是自己所用语言的忠实信徒,常在社区和论坛上和其他语言的使用者争论哪一种语言是最好的编程语言。他们认为自己所用的语言是世界上最好的编程语言,没有之一。他们认为,自己所用的编程语言适用于所有场景。他们眼中,只有锤子,因此会把所有任务都当成是钉子。

6段–多语言专家:

这一个阶段的程序员,因为工作关系,或者纯粹是因为对技术的兴趣,已经学习和掌握了好几种编程语言。已经领略了不同编程语言不同的设计思路,对每种语言的长处和短处有了更多的了解。

他们现在认为,编程语言并不是最重要的,编程语言不过是基本功而已。

他们现在会根据不同的任务需求,或者不同的资源来选择不同的编程语言来解决问题,不再会因为没有使用某一种喜爱的编程语言开发而埋怨。

编程语言有很多种流派和思想,有一些编程语言同时支持多种编程范式。

静态类型编程范式

采用静态类型编程范式的编程语言,其变量需要明确指定类型。代表语言:C,C++,Pascal,Objective-C,Java,C#,VB.NET,Swif,Golang。

这样做的好处是:

1、编译器可以在编译时就能找出类型错误。
2、编译器编译时知道类型信息,就可以提高性能。

这种范式认为,程序员肯定知道变量的类型,你丫要是不知道变量的类型,那你就别混了!编译时,程序会报错。
Swift和Go语言都是静态类型编程语言,但它们都不需要明确指定类型,而是可以通过推断由编译器自动确定其类型。

动态类型编程范式

采用静态类型编程范式的编程语言,其变量不需要明确指定类型。任意变量,可以指向任意类型的对象。代表语言:Python,Ruby,JavaScript。

动态类型的哲学可以用鸭子类型(英语:ducktyping)这个概念来概括。JamesWhitcombRiley提出的鸭子测试可以这样表述:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

这种范式认为,程序员肯定知道变量的类型和它支持的方法和属性,你丫要是不知道变量的类型,那你就别混了!运行时程序会崩溃!程序崩溃怨谁?怨你自己呗,你不是合格的程序员!

动态类型的好处是:

不需要明确定义接口和抽象类型。只要一个类型支持需要的方法和属性,那么就OK。程序会相当灵活和简单。C++,Java,C#视之为命脉的接口/基类,在动态语言这里都视如无物!

缺点是:

1、如果类型不对,编译器也无法找到错误,而是运行时程序崩溃
2、因为编译器不知道变量的类型,因此无法优化性能。

面向对象编程范式

面向对象编程范式,从上世纪70年代末开始兴起。它支持类和类的实例作为封装代码的模块。代表语言:Smalltalk,C++,Objective-C,Java,C#,VB.NET,Swift,Go,Python,Ruby,ActionScritp,OCaml.

早期编程语言都是面向过程的。就是顺序,条件,循环,构成一个个函数。随着代码规模的增大,人们发现有必要对代码进行模块化。一个概念对应的代码放在一个文件中,这样便于并发开发和进行代码管理。

人们还发现了“程序=数据结构+算法”的规律。因此,一个概念对应的数据结构和函数应该放在一个文件中。这就是类的概念。

面向对象编程范式,确实极大地提高了生产效率,因此得到了广泛的应用,因此在语言层面支持面向对象编程范式的语言是极多的。

C语言尽管在语言层面上并不支持面向对象编程范式,但现代的C语言开发都会应用面向对象的模块化思想,把同一类的数据结构和函数放在一个文件中,采用类似的命名方式。

毕竟C语言没有在语言层面上支持面向对象,因此就有很多程序员想给C语言添加面向对象支持。其中的代表是C++和Objective-C。

C++是一种新的语言,但大部分语言元素是和C兼容的。

Objective-C是完全兼容的C的。Objective-C是给C添加了薄薄的一层语法糖以支持接口(就是其他语言的类)和协议(就是其他语言的接口)。甚至,Objective-C一开始的实现,就是一个C语言的预编译器。Objective-C坦白讲,除了添加的语法不太符合C流外,实际上其面向对象系统设计是相当精妙的。乔布斯早年慧眼识珠,把Objective-C收人囊中,因为封闭于Apple/NextStep系统内,因此少有人知。随着iOs系统的普及,Objective-C近几年才名满天下。

函数式编程范式

函数式编程范式,是一些数学家发明的编程语言,他们认为程序就是数学函数嘛。代表语言:Lisp,Erlang,JavaScript,OCaml,Prog。

有很多大牛极力鼓吹过函数式编程语言,认为其极具革命性。但我认为他们过高估计了函数式编程范式的威力,我并不认为函数式编程范式相对于面向对象编程范式有何高明之处。

函数式编程语言,核心就是函数,它们没有Class类的概念。但它的函数又不是传统面向过程语言的函数,它的函数支持“闭包”的概念。

在我看来,函数式编程语言的函数,也就是“闭包”,说白了,其实就是“类”。编程语言发展到今天,就是需要模块化,就是需要把“数据结构”和“算法”结合起来。不论何种语言,不把它们结合起来的编程方式,都是没有出路的。

面向对象编程语言,用类把“数据结构”和“算法”结合起来。类的核心是“数据结构”,也就是其“属性”,而不是“算法”,其“函数”。在类中,是函数依附于属性。

而函数式编程语言,用闭包把“数据结构”和“算法”结合起来。是函数能够抓取外部的字段。是“属性”依附于“函数”。

“类”本质上和“闭包”是等价的。现在很多面向对象编程语言都加上了对闭包的支持。观察其代码,我们可以发现,它们实际上都是用“类”来实现“闭包”的。

“类”和“闭包”谁更易用?明显是“类”。

而“闭包”更简洁一些,因此“闭包”在面向对象编程语言中常用来替换匿名类。只有一个函数的类,写成一个类太麻烦,不如写成闭包,更加简洁。

吐槽一下OCaml语言,其前身Caml语言本身是一种挺好的函数式语言,硬生生添加了一套完整的面向对象机制,同时支持面向对象和函数式编程范式,很容易像C++一样脑裂的。

也有很多面向对象语言控看着JavaScript嫌烦,总是想把面向对象支持添加到JavaScript上。ActionScript就是其中一种尝试。我用过,真的是和Java没多少区别了。

再吐槽一下ExtJS。当初选型Web前端开发框架时比较了ExtJS和JQuery。

ExtJS明显是Java高手开发的,硬生生用JavaScript模拟Swing的设计思想,搞了一套UI库。

JQuery开发者明显是领悟了JavaScript的函数式编程范式,依据JavaScript的动态函数式编程语言的特点打造了一套UI库,立刻秒杀ExtJS。

由ExtJS和JQuery的故事,我们可以看到多语言编程能力是多么的重要。ExtJS的作者精通并喜爱Java,因此他把手术刀JavaScript当做锤子Java使,一通乱敲,费力不讨好。

函数式编程语言,还有尾递归等一些小技巧。尾递归可以不用栈,防止递归调用时栈溢出。

模板编程范式

模板编程,就是把类型作为参数,一套函数可以支持任意多种类型。代表语言:C++。

模板编程的需求,是在C++开发容器库的时候发明的。因为容器需要保存任意类型的对象,因此就有了泛型的需求。

C++的模板编程,是在编译时,根据源码中的使用情况,创建对应类型的代码。除了C++这种方式,Java,C#也有类似的机制,叫做“泛型”,但它们的实现方式和C++的模板很不同。它们的编译器不会生成新的代码,而是使用强制类型转换的方式实现。

在没有模板/泛型的编程语言中,怎样在容器中存放对象呢?存取公共基类类型(Java,C#)的对象,或者void*指针(C)即可,取出时自己强制类型转换为实际类型。动态类型语言,不关心类型,更是无所谓了,随便什么对象直接往容器里扔进去,取出来直接用即可。

一些C++高手又在模板的基础上搞出了“模板元编程”。因为模板编程,就是C++的编译器搞定的嘛,模板元编程就是让编译器运算,编译完结果也就算出来了。我不知道除了研究和炫技,这玩意有啥用?

小结

一门语言是否值得学习,我认为有几个标准:

1、是否要用,要用就得学,这么没有疑问的。毕竟我们都要吃饭的嘛。

2、其语言特性是否给你耳目一新的感觉。如果是,那就值回票价了。如Go语言废掉了异常,改用返回多值。我深以为然。我其实已经主动不用异常好多年了。因为,我觉得既然C不支持异常也活得很好,为什么需要异常呢?出错了,返回错误码。无法挽回的错误,直接Abort程序就可以嘛!而且,异常实际上是违反面向过程编程原则的。一个函数应该只有一个入口一个出口。抛出异常就多了出口了。

3、是否擅长某一个领域。如果你手里只有一把锤子,那么你就只能把所有任务都当做钉子猛锤一通。但如果工具箱里有多种工具,那面对不同的任务就得心应手多了。

7段—架构设计

还需要掌握架构设计的能力,才能设计出优秀的软件。架构设计有一些技巧:

1、分层

一个软件通常分为:

表现层–UI部分
接口层–后台服务的通讯接口部分
服务层–实际服务部分
存储层—持久化存储部分,存储到文件或者数据库。

分层的软件,可以解耦各个模块,支持并行开发,易于修改,易于提升性能。

2、SOA

模块之间通过网络通讯互相连接,松耦合。每一个模块可以独立部署,可以增加部署实例从而提高性能。每一个模块可以使用不同的语言和平台开发,可以重用之前开发的服务。SOA,常用协议有WebService,REST,JSON-RPC等。

3、性能瓶颈

1)化同步为异步。

用内存队列(Redis),工作流引擎(JBpm)等实现。内存队列容易丢失数据,但是速度快。工作流引擎会把请求保存到数据库中。

通过化同步请求为异步请求,基本上99.99%的性能问题都可以解决。

2)用单机并行硬件处理。

如,使用GPU,FPGA等硬件来处理,提高性能。

3)用集群计算机来处理。

如,Hadoop集群,用多台计算机来并行处理数据。

自己的软件栈中,也可以把一个模块部署多份,并行处理。

4)用cache来满足请求。常用的内容加热cache后,大量的用户请求都只是内存读取数据而已,性能会得到很大的提升。

cache是上帝算法,记得好像它的性能只比最佳性能低一些,就好像你是上帝,能够预见未来一样。现在X86CPU遇到了主频限制,CPU提升性能的主要途径就是增加高速Cache了。

4、大系统小做

遇到大型系统不要慌,把它切分成多个模块,用多个小程序,通过SOA协作来解决。这秉承了Unix的设计思想。Unix上开发了大量单一目的的小程序,它主张用户通过管道来让多个小程序协作,解决用户的需求。当然,管道方式通讯限制太多,不够灵活。因此,现在我们可以通过URI,通过SOA的方式来让多个程序协作。Andorid和iOS上的应用程序,现在都是通过URI实现协作的。这也算是Unix设计思想的现代发展吧?!

5、Sharding切片

现在有一个潮流,就是去IOE。I-IBM大型机,O-Oracle数据库,E-EMC存储。之前,大型系统常用IOE去架构,在大型机上部署一个Oracle数据库,Oracle数据库用EMC存储保存数据。IOE是当今最强的计算机,数据库和存储。但他们面对海量系统也有抗不住的一天。

Oracle数据库是Shareeverything的,它可以在一个计算机集群(服务器节点不能超过16个)上运行。计算机集群都共用一个存储。

去IOE运动,标志着ShareEverything模式的破产。必须使用ShareNothing,系统才能无限扩展。

用MySQL数据库就可以应付任意规模的数据了。前提是,你会Sharding分片。把大系统切分成若干个小系统,切分到若干台廉价服务器和存储上。更Modern一些,就是切分到大量虚拟机上。

如,铁道部的12306网站。我们知道火车票都是从属于某一列列车的。那么我们把每一个列车作为一个单元来切分,就可以把12306网站切分成几千个模块。一台虚拟机可以承载若干个模块。当某些列车成为性能瓶颈之后,就可以把它们迁移到独立的虚拟机上。即使最终有部分列出服务不可用,系统也不会完全不可用。

12306网站,只有一个全局的部分,就是用户登录。这个可以交给第三方负责。如可以让用户用微信,微博,qq等账户登录。

也可以自己实现用户登录服务。还是用切片的方式用多台Redis服务器提供服务。Redis服务器存储每一个登录用户的sessionId和userId,角色,权限等信息。sessionId是随机生成的,可选择其部分bit用于标识它在哪一个Redis服务器上。用户登录后,把sessionId发给客户。用户每次请求时把sessionId发回给服务器。服务器把sessionId发给Redis服务器查询得到其用户信息,对用户请求进行处理。如果在redis服务器上找不到sessionId,则让用户去登录。即使所有注册用户同时登陆,也不需要太多的内存。而且,可以在session内存过多时,删除最早登陆的用户的session,强制他再次登陆。同时活跃的用户数不会太多。

领域知识层次

前面的所有层次,都是关注编程本身的技能,说白了,就是基本功,本身并不能产生太大的价值。但有太多的程序员浪费太多的时间在那些筑基的层次上。

有些程序员特别喜欢钻研编程语言,每有一种新的编程语言出来或者旧语言被热炒,就会投入精力进去研究。我就是其中之一,浪费了很多精力在编程语言上,在奇技淫巧上。

我觉得C++语言是一个特别大的坑。刚开始是作为面向对象的C被开发的。后来发现了模板编程,就大力鼓吹模板编程和进一步的模板元编程。最近又推出了C++11,C++14等新标准,进一步添加了很多新东西,函数式编程,类型推断等。C++过分复杂,太多的坑消耗了大量程序员的大量精力。我使用C++时,只使用面向对象部分和模板部分,其他过于精深的特性都不使用。

计算机科学是一个面相当广泛的学科,有很多领域知识需要和值得我们深入研究,我们才能写出有价值的程序来。软件必须要和行业结合起来,要落地才有价值。仅仅研究编程技巧,不懂领域知识是写不出有价值的程序的。

计算机科学领域有很多,列举一些如下:

存储—-块设备,文件系统,集群文件系统,分布式文件系统,光纤SCSI,iSCSI,RAID等。

网络—-以太网,光纤网,蜂窝网络,WIFI,VLAN等。

计算机体系结构,主要就是CPU指令集。x86,ARM等。

USB协议。需要知道URB包。

PCI协议,PCI-E协议。现代计算机的外设都是PCI协议和PCI-E协议的。显卡现在全是通过 PCI-E协议连接到计算机上的。相对来说减少了很多需要学习的知识。搞虚拟化就需要深入掌握PCI协议。

图像处理–图像压缩,视频实时编码等。

3D游戏
关系数据库
NoSQL数据库
操作系统
分布式操作系统
编译原理
机器学习–现在大数据要用哦!

了解这些领域知识,也包括了解该领域现有的商用硬件、商用软件和开源软件。很多时候,你要完成的工作,已经有现成的工具了。你只要使用现成的工具就可以完成任务,不需要进行开发。有时候,只需要组合现有的工具,写一些脚本就可以完成任务。

如,我一次要实现一个双向同步任务。找到了一个优秀的开源软件Unison,编写一下配置文件就圆满地完成了任务。不需要编写任何代码。

还有一次,要做高可用,用Python调用了几个开源软件就轻松实现了。

编写安装程序,定制操作系统,知道了操作系统的领域知识,写几行脚本就可以轻松搞定。

不具备领域知识的人,就可能不得不进行大量无谓的开发,甚至开发很久之后才发现,这根本就是一条死路。

另外,扎实的领域知识,可以大大提高编程调试、查错的能力。知道编译器和编程语言运行时工作原理,就能快速根据编译错误和警告信息修改代码。

知道操作系统底层运行机制,就能快速找到运行时错误的问题根源。如,有一次我编写一个windows升级服务程序。它是一个windows服务,需要执行dos脚本,这个脚本会替换掉这个windows服务本身。发现有时脚本执行无效,查了一晚上,发现当windows服务安装后,第一次启动就执行脚本时就会有权限问题,log都正确,但实际执行这个脚本没有任何效果。但一旦windows服务程序启动一次之后就ok。这必然是windows操作系统底层安全机制的问题,因为我对Windows内核了解不多,因此花了很长时间才发现这个问题,并对造成这个问题的根源并不清楚。

0段—领域知识菜鸟

对领域知识没有多少认知,通过搜索引擎找到一些该领域的软件和硬件的介绍性文章,按照文章指示配置和使用软件。勉强能够使用现有软硬件。

1段—领域知识行家

了解领域内常用硬件,深入掌握领域内常用软件的配置和使用技巧。能够使用现有软硬件熟练搭建解决方案,能够解决实际工作中遇到的种种问题。

2段—领域知识专家

当你不仅仅掌握了该领域的软件和工具,知道怎么用,还知道其原理,“知其然,也知其所以然”,就是该领域的知识专家了。

你知道网络协议的原理,你才能在网络出现问题时知道是哪里可能出现了问题。是mac冲突,ip冲突,还是网络环路?

你知道存储的原理,你才能知道为什么这种存储方式不适合虚拟化,那种存储方式适合虚拟化,另一种方式适合资料备份。

你知道PCI协议,你才能知道你怎样才能虚拟化一个硬件设备。

你知道网卡硬件协议,你才能模拟出一个虚拟机能正常使用的虚拟网卡。

你知道视频编码格式和原理,才能知道什么视频格式占用带宽最少,什么视频格式占用CPU最少。

你了解IntelVT/Amd V指令集,才能知道虚拟化是怎样实现的。

你明白工作流其实就是状态机,在遇到复杂工作流程时,你才能知道怎样设计满足要求的工作流引擎。

3段—科学家

你是领域知识专家,但你的知识都是来自于书本,来自于其他人的。

如果你满足于当领域知识专家,你只能拾人牙慧,永远别想超越。别人的研究成果,未必愿意告诉你。当别人告诉你的时候,它可能已经发现了更新的理论,并且新一代产品可能马上就要发布了。

科学家是探索未知,勇于创新的人,是推动人类社会进步的人。

传说,思科的一位高管曾经半开玩笑地说过:“如果思科停止了新技术的研发,华为就会找不着方向”。这是在嘲笑华为只是处在领域知识专家的水平,只能山寨无法超越。我不知道华为的实际情况,但希望现在的华为已经走到了领跑者的位置。

欧文·雅各布斯发现了CDMA码分多址的原理,并发现它在通讯上大有可为,组建了高通公司。高通公司主要以专利授权费为生,它雇佣了大量科学家在通讯领域展开研究。有人说高通是专利流氓。这些人不明白知识的价值。在他们眼里,Windows的合理价格就应该是5元钱,一张光盘的价格。iPhone就应该是1000多元裸机的价格。高通是专利流氓,那你也流氓一个CDMA,LTE出来给我看看!

X86芯片在设计上没有考虑虚拟化。因此会有所谓的“虚拟化漏洞”出现。就是说,一些CPU特权指令执行时,在虚拟机环境下不会抛出异常,因此就无法切换到Host。这样,X86芯片上就无法运行虚拟机。

VmWare公司是由美国的几位科学家在1998年创建的。他们发现可以使用二进制翻译的技术,在X86计算机上运行虚拟机。

Xen虚拟化软件也是几位科学家发明的。他们发现只要修改虚拟机操作系统和Host操作系统的内核,在需要执行“虚拟化漏洞”指令时直接调用Host的功能,就可以实现虚拟化,而且大大提高了虚拟机的运行性能。

后来,Intel为自己的芯片添加了IntelVT指令集,Amd为自己的芯片添加了AmdV指令集,弥补了“虚拟化漏洞”。于是就有了KVM虚拟机软件,它直接用CPU硬件指令实现虚拟化。

KVM在执行CPU指令时,是直接在物理CPU上运行的,因此效率极高。但是,虚拟机运行虚拟外设时,就必须用软件模拟,因此虚拟机的IO访问速度很慢。

IBM科学家RustyRussell,借鉴了Xen的研发经验,创建了VirtIO技术。就是在虚拟机中编写一套PCI虚拟设备和驱动,这套虚拟PCI设备有一块虚拟设备内存。这个虚拟设备内存Host是可以访问的,虚拟机通过VirtIO驱动程序也可以访问。也就是一块内存在虚拟机和Host中共享,这就解决了虚拟机的IO性能问题。

再讲一个搜索引擎的故事:

很久以前,我要给一个程序添加搜索功能。刚开始使用sql查询实现,发现实在太慢了。后来找了开源的Lucene项目。它使用反向索引技术,通过在文件中创建反向索引,大大提高了搜索速度。

Google的两位创始人发现了html中link的秘密,他们发现可以通过html页面的link关系来为每一个html页面设置权重。也就是PageRank算法。于是,Google的自动搜索引擎击败了Yahoo人工分类的搜索引擎。

OK,利用反向索引技术和PageRank,以及一个简单的html爬虫机器人,我们就可以创建一个搜索引擎了。但是,互联网很大,每天产生大量新网页,要为整个互联网建立反向索引是很困难的。

若干年后Google又公开了三篇论文:Googlefs,Mapreduce,Bigtable。于是Lucene项目的开发者根据Google的Mapreduce论文开发了Hadoop项目。MapReduce就是使用大量计算机存储数据并计算,最后汇总结果。使用Hadoop+反向索引+PageRank,就可以创建搜索引擎了。Yahoo,Baidu等公司纷纷基于Hadoop开发了自己的搜索引擎。

但是,其他公司的搜索引擎效果还是没法和Google相比。这一点我们程序员最清楚。像我,就总是翻墙出去,只为了Google一下。

Google黑板报上发表了吴军博士的一些文章,其中介绍了很多机器学习方面的知识。从文中可以知道,Google其实使用机器学习来分析搜集到的页面。Google明显不会把这个公式公开出来。即使有一天Google真的公开了这个公式,那么可以想见Google肯定又研发出了更加犀利的秘籍,山寨货的搜索引擎效果还是比不上Google的。

山寨是通向创新的必由之路。在成为领域的领头羊和领导者之前,必然要经过学习,模仿的阶段。但要成为行业的老大,成为Champion,必须勇于弯道超车,勇敢地走上创新之路,成为真正的科学家,真正的大牛!

总结

编程能力可分为两个维度:一个是编程技能水平,另一个是领域知识水平。

有些程序员可能把精力都花在提升编程技能上了,领域知识知之甚少,这其实在日常工作中也是极其有害的。有些需求可能早已经有了现成、开源免费的解决方案,或者只需要组合几个现有软件就可以快速搞定,而他们却不得不自己花大量时间去开发。另外,缺少领域知识,在程序出现非预期状况时,很难快速定位到问题的根源,很难解决bug。

什么是真正的编程能力

2016-01-18 转载自:知乎 开点工作室

问题:什么才算是真正的编程能力?

还在读书,也在实验室帮忙做了些东西,自己也搭过几个网站。在周围人看来似乎好像我很厉害,做了那么多东西,但是我发现这些东西虽然是我做的,但是实际上我手把手自己写的代码却并没有多少,很多都是用开源的东西,我写的代码无非是把别人的东西整合下,类似于胶水一样的工作。

我之前所认为的编程是全手动一行一行敲代码,但是现在我发现哪怕是工程上也有很多人是复制黏贴来解决问题的,并且提倡不要重复造轮子。

但是靠谷歌和复制别人的轮子,虽然我做出了很多东西,可是我并不觉得自己能力上有提升,倒是利用搜索引擎的能力的确提升了不少。而学校里另外一部分在搞ACM的人,他们每天都在刷题练算法,但单凭我个人的感受感觉他们似乎对工程上有些东西并不了解,或许算法的能力才算是实打实的编程能力?那”胶水”的能力和整合轮子的能力算不算编程能力呢?

所以我现在就很困惑,所谓的编程能力到底是什么,我该如何提升自己的编程能力?

回答:

作者:刘贺

链接:http://www.zhihu.com/question/31034164/answer/61625952
来源:知乎

非常好的一个问题。这可能是我在知乎见到过的问编程有关的问题中问得最好的一个了。我非常喜欢这个问题。

计算机科学有两类根本问题。一类是理论:算法,数据结构,复杂度,机器学习,模式识别,等等等。一类是系统:操作系统,网络系统,分布式系统,存储系统,游戏引擎,等等等等。

理论走的是深度,是在追问在给定的计算能力约束下如何把一个问题解决得更快更好。而系统走的是广度,是在追问对于一个现实的需求如何在众多的技术中设计出最多快好省的技术组合。

搞ACM的人,只练第一类。像你这样的更偏向于第二类。其实挺难得的,但很可惜的是第二类能力没有简单高效的测量考察方法,不像算法和数据结构有ACM竞赛,所以很多系统的苗子都因为缺少激励和正确引导慢慢就消隐了。

所以比尔盖茨才会说,看到现在学编程的人经常都把编程看作解各种脑筋急转弯的问题,他觉得很遗憾。

做系统,确实不提倡“重复发明轮子”。但注意,是不提倡“重复发明”,不是不提倡“重新制造”。恰恰相反的,我以为,系统的编程能力正体现在“重新制造”的能力。

能把已有的部件接起来,这很好。但当你恰好缺一种关键的胶水的时候,你能写出来吗?当一个已有的部件不完全符合你的需求的时候,你能改进它吗?如果你用的部件中有bug,你能把它修好吗?在网上繁多的类似功能的部件中,谁好谁坏?为什么?差别本质吗?一个开源代码库,你能把它从一个语言翻译到另一个语言吗?从一个平台移植到另一个平台吗?能准确估计自己翻译和移植的过程需要多少时间吗?能准确估计翻译和移植之后性能是会有提升还是会有所下降吗?

系统编程能力体现在把已有的代码拿来并变成更好的代码,体现在把没用的代码拿来并变成有用的代码,体现在把一个做好的轮子拿来能画出来轮子的设计蓝图,并用道理解释出设计蓝图中哪些地方是关键的,哪些地方是次要的,哪些地方是不容触碰的,哪些地方是还可以改进的。

如果你一点不懂理论,还是应该学点的。对于系统性能的设计上,算法和数据结构就像在自己手头的钱一样,它们不是万能的,但不懂是万万不行的。

怎么提高系统编程能力呢?土办法:多造轮子。就像学画画要画鸡蛋一样,不是这世界上没有人会画鸡蛋,但画鸡蛋能驯服手指,感受阴影线条和笔触。所以,自己多写点东西吧。写个编译器?渲染器?操作系统?web服务器?web浏览器?部件都一个个换成自己手写的,然后和已有的现成部件比一比,看看谁的性能好,谁的易用性好?好在哪儿?差在哪儿?为什么?

更聪明一点的办法:多拆轮子。多研究别人的代码是怎么写的。然而这个实践起来经常很难。原因:大部分工业上用的轮子可能设计上的思想和技术是好的,都设计和制造过程都很烂,里面乱成一团,让人乍一看毫无头绪,导致其对新手来说非常难拆。这种状况其实非常糟糕。所以,此办法一般只对比较简单的轮子好使,对于复杂的轮子,请量力而行。

轮子不好拆,其实是一个非常严重的问题。重复发明轮子固然是时间的浪费,但当轮子复杂而又不好拆的时候,尤其是原来造轮子的人已经不在场的时候,重新发明和建造轮子往往会成为无奈之下最好的选择。这是为什么工业界在明知道重复发明/制造轮子非常不好的情况下还在不断重复发明/制造轮子的根本原因。

程序本质是逻辑演绎的形式化表达,记载的是人类对这个世界的数字化理解。不能拆的轮子就像那一篇篇丢了曲谱的宋词一样,能读,却不能唱。

鄙人不才,正在自己研究怎么设计建造一种既好用又好拆的轮子。您没那么幸运,恐怕是等不到鄙人的技术做出来并发扬光大了。在那之前,多造轮子,多拆好拆的小轮子,应该是提高编程能力最好的办法了。

以上。嗯。
(文章属个人观点,与本人工作雇主无关。)

回答:

作者:家飞猫
链接:http://www.zhihu.com/question/31034164/answer/61625952
来源:知乎

编程能力是一种解决问题的能力。如果问题没能被很好地解决,知道再多也没用。
编程能力是一种运用机器解决问题的能力。首先是要判断问题在什么程度上可被机器解决,比如理论计算机科学会告诉我们什么可做、什么理论上不可做、什么理论上可做实践上不可做。然后是让机器更好地理解问题,比如计算机都是(图灵-冯诺依曼模型)等价,但不同的问题可能会适用不同的编程语言。再后是让机器能更高效率地解决问题,比如同样的问题可能会有效率差别巨大的算法。
编程能力是一种抽象问题的能力。借用轮子是很好的办法,省力省时间。今天任何软件工程师都会有意无意地使用很多轮子,从操作系统编译器数据库网络到算法数据结构。想高效地借用轮子,就需要将问题分解再分解,抽象再抽象。任何一个实用的系统(不包括教科书上的示例程序和简单的脚本程序)都需要进行大量的分拆和组合。所以系统设计是编程能力里的高级技能,加合理的假设简化问题尤其有难度,此处不展开讨论。高手和新手的区别在于新手往往不知道轮子的适用范围,而高手的手上轮子数量多且熟知各种轮子的差异,所以对不同的问题可以轻松地找到合适的轮子,当实在找不到合适的轮子时可以自己动手改造现有的轮子。平时有时间拆装和改造已有的轮子会对水平提升有较大帮助。当然能知道怎样快速在搜索引擎里搜出轮子也是一种能力。
编程能力是一种需要考虑扩展性的能力。算法竞赛中的很多算法考虑的是单机的内存算法,计算模型经过高度抽象,在实践中机器的模型更为复杂。比如单机的多级结构带来的各种时间空间复杂度的取舍平衡,多机网络中如何能在提高单机性能外进一步优化整体性能。除了在机器端的扩展,在程序员一端的扩展也很重要。复杂的问题和工程往往意味着团队协同以及更长时间的开发维护,团队分工和设计沟通这里暂且不论。举个容易被忽视的例子,程序中的注释。高手会更在意完整且表达清楚的注释,因为这是写给现在和未来的团队(包括自己和其他成员)看的,直接影响到长期的整体开发维护效率。
编程能力是一种取舍的能力。局部的最优解未必是全局的最优解。如果一个美妙的解决方案需要将完工时间向后推迟一两个月,需要考虑是否先使用平凡方案解决问题,之后再进行优化。当你的工作延后会阻碍别人的工作时尤其如此。发现一个绝妙的优化方案时先想想这个优化是否真的有价值,如果只是系统中很小的部分,那么不要为了追求心理满足而花很多时间放一个漂亮的轮子上去(参考Amdahl定律)。
编程能力是一种预见未来的能力。目前的方案有哪些假设和局限性,在何种情形下会遇到问题甚至崩溃。在未来出现问题时问题是否需要重新定义,系统是否需要重新设计,代码是否需要重构或优化等等都需要未雨绸缪。
编程能力是一种工程能力。无它,唯手熟尔。

编程能力是一种解决问题的能力。如果问题没能被很好地解决,知道再多也没用。
编程能力是一种解决问题的能力。如果问题没能被很好地解决,知道再多也没用。
(重要的事情说三遍,重要的事情说三遍,重要的事情说三遍)

据说 JS 是世界上最好的编程语言?

作者:伯乐在线 – 伯小乐

网址:http://web.jobbole.com/84693/

【伯乐在线导读】:2016年1月中旬,Stack Overflow发起本年度的开发者调查。调查结果于近日公布,伯乐在线翻译组黄小非完整翻译了的调查报告。本文盘点 JS 开发者应该会关心的部分数据。

Stack Overflow 技术排行榜:

在2015年6月,JavaScript超越了Java成为Stack Overflow上最热门的标签。

Stack Overflow 技术趋势

新潮的Web开发技术,比如React,Node.js,还有AngularJS正在逐渐起势。

从 2013 至 2016 年,JS 四年蝉联最热门技术

程序员最想要的技术,Node 和 Angular 排第二和第三

全栈工程师最青睐的技术,JS 第一

前端开发者最青睐的技术,JS 自然第一

后端开发者最青睐的技术,JS 第一

学生程序员最青睐的技术,JS 第二

JavaScript 是这个星球上最受欢迎的编程语言。而且后端开发者甚至更喜欢使用JavaScript来工作。

多个相关的技术:

每一个开发者(在日常工作中)平均要使用四五种主流编程语言、框架或者技术。最常规的双技术组合是 JavaScript和 SQL。最常见的三技术组合是 JavaScript、PHP 和 SQL。

根据职业划分的技术栈

看到栈了没?全栈开发者选择使用PHP作为后端原因,比任何其他语言都多。(紧接着的是C#和Java)。

JavaScript是如此普及,以至于后端开发者不管用什么类型的3技术组合都包含了JavaScript。这也说明有很多后端开发者其实也就是披着后端外衣的全栈开发者。我们的内部统计显示,有60%的职业开发者实际上是在做全栈的工作的。

按职位分类看程序员的报酬:

在用 JS 的全栈工程师中

在用 JS 的前端工程师中,

按职位分类的报酬:

懂得使用JavaScript并在为云平台工作的全栈开发者,以及使用React或者Redis技术的开发者比其他的开发者报酬更多。

懂得使用JavaScript和React,Node或者Angular技术的前端开发者比其他前端开发者的报酬更高。

开发环境(2016):

根据职位分类的开发环境:

数据科学家使用Vim和Notepad++。全栈开发者使用Visual Studio和Sublime。学生则使用Notepad++和Visual Studio和Notepad++。

操作系统:

去年,在开发者们使用的操作系统中,Mac系统比Linux的份额多了一点点,排在第二名。今年形势则非常明朗而且操作系统的发展趋势也很明显。如果这种趋势依然保持下去的话,那么明年Windows系统的使用量将会低于50%。

开发者希望在工作中学到什么?

一旦开发者找到了工作,他们就会去尝试学习新东西或创造新东西。对于印度开发者来说,得到升职的优先级要比其他国家的开发者来得高。

工作中的挑战:

不切实际的预期,糟糕的文档,不够详细的需求,这些都是开发者日常要面对的烦心事。听上去熟悉吧?

《StackOverflow 2016 年开发者调查》完整版中还有关于女程序员的数据,请查看:http://blog.jobbole.com/98977/