百科问答小站 logo
百科问答小站 font logo



什么才算是真正的编程能力? 第1页

  

user avatar   jfmm 网友的相关建议: 
      

编程能力是一种解决问题的能力。如果问题没能被很好地解决,知道再多也没用。

编程能力是一种运用机器解决问题的能力。首先是要判断问题在什么程度上可被机器解决,比如理论计算机科学会告诉我们什么可做、什么理论上不可做、什么理论上可做实践上不可做。然后是让机器更好地理解问题,比如计算机都是(图灵-冯诺依曼模型)等价,但不同的问题可能会适用不同的编程语言。再后是让机器能更高效率地解决问题,比如同样的问题可能会有效率差别巨大的算法。

编程能力是一种抽象问题的能力。借用轮子是很好的办法,省力省时间。今天任何软件工程师都会有意无意地使用很多轮子,从操作系统编译器数据库网络到算法数据结构。想高效地借用轮子,就需要将问题分解再分解,抽象再抽象。任何一个实用的系统(不包括教科书上的示例程序和简单的脚本程序)都需要进行大量的分拆和组合。所以系统设计是编程能力里的高级技能,加合理的假设简化问题尤其有难度,此处不展开讨论。高手和新手的区别在于新手往往不知道轮子的适用范围,而高手的手上轮子数量多且熟知各种轮子的差异,所以对不同的问题可以轻松地找到合适的轮子,当实在找不到合适的轮子时可以自己动手改造现有的轮子。平时有时间拆装和改造已有的轮子会对水平提升有较大帮助。当然能知道怎样快速在搜索引擎里搜出轮子也是一种能力。

编程能力是一种需要考虑扩展性的能力。算法竞赛中的很多算法考虑的是单机的内存算法,计算模型经过高度抽象,在实践中机器的模型更为复杂。比如单机的多级结构带来的各种时间空间复杂度的取舍平衡,多机网络中如何能在提高单机性能外进一步优化整体性能。除了在机器端的扩展,在程序员一端的扩展也很重要。复杂的问题和工程往往意味着团队协同以及更长时间的开发维护,团队分工和设计沟通这里暂且不论。举个容易被忽视的例子,程序中的注释。高手会更在意完整且表达清楚的注释,因为这是写给现在和未来的团队(包括自己和其他成员)看的,直接影响到长期的整体开发维护效率。

编程能力是一种取舍的能力。局部的最优解未必是全局的最优解。如果一个美妙的解决方案需要将完工时间向后推迟一两个月,需要考虑是否先使用平凡方案解决问题,之后再进行优化。当你的工作延后会阻碍别人的工作时尤其如此。发现一个绝妙的优化方案时先想想这个优化是否真的有价值,如果只是系统中很小的部分,那么不要为了追求心理满足而花很多时间放一个漂亮的轮子上去(参考Amdahl定律)。

编程能力是一种预见未来的能力。目前的方案有哪些假设和局限性,在何种情形下会遇到问题甚至崩溃。在未来出现问题时问题是否需要重新定义,系统是否需要重新设计,代码是否需要重构或优化等等都需要未雨绸缪。

编程能力是一种工程能力。无它,唯手熟尔。


编程能力是一种解决问题的能力。如果问题没能被很好地解决,知道再多也没用。

编程能力是一种解决问题的能力。如果问题没能被很好地解决,知道再多也没用。

(重要的事情说三遍,重要的事情说三遍,重要的事情说三遍)


user avatar   marisa.moe 网友的相关建议: 
      

0:可以完全理解一问题,并且给出对应的代码。

往窄了点说,这就是acm在培养的东西。

并且这不能靠调api完全解决:

有的时候,你的问题需要你把多个标准算法串一起。

比如说最近有个把STLC AST从implicit sharing变成explicit sharing的任务,这靠LCA+reverse topo dependency calculation(没这步LCA的时候scope跟着term一起被reorder了,根本做不出),最后接上metaocaml style letlist,搞定。

有的时候,根本没有任何API,需求是从一个算法改成另一个。比如说D*算法复杂度是O(nv^3)的,很不好,我们想优化下,把复杂度往下降点,这一样没有任何包可以调。


往广了说,大一点的需求也能用这种能力。既然有‘组合性’这个概念,我们就能倒过来,给出一个大型问题,分解成多个子问题,各个被单独解决后再组合一起。

名书SICP里面就很推崇这种‘理解,分解,破解’的套路,而图灵奖得主Edward Dijkstra甚至更极端,认为这方法是唯一一种编程的方法。无论这是不是唯一法,这能力都是很不可或缺的基本功。


当你掌握这方法以后,你会发现你做的很多是在脑袋中去推敲这问题的性质,试图分解这个问题,如果可以的话调用/组合已有API/算法。。是不是很像数学?因为计算机程序在某种意义上就是Mathematical Object - Curry Howard Isomorphism/Stepwise Refinement/Program Calculation都是在说这个。而当你把这套玩熟,如果你喜欢,甚至可以做到正射必中:对于给定问题,产生绝对正确的代码。这不难理解嘛,毕竟都说了是数学对象了,证明一下就好了。

1:能在0之上加上工程方法。

有时候这套方法不管用:比如说你跟其他人在已有code base上协作,比如说需求变更了,比如说你死活分解不出来,又比如说你根本不知道具体的需求,得慢慢探索。。其实这问题本质是,软件实在太复杂了,一个数百万行代码的项目已经超越了人类物理意义上的理解极限 - 看都看不完。

这也是为什么重头起编写一个系统很难:spec太复杂,各个组件的assumption太多,并且持续进化,不可能一口气搞定,就算给定各个预先写好的组件,也会因为assumption不match而难以组合在一起,只能通过不停的prototype,不停的重构,甚至不停的重写来加深对系统的理解。

在这之上,SICP的‘一次性理解法’已经失效,这时候就需要不精确,比起逻辑学更像生物学的技巧 - 软件工程了。

该怎么设计?

该怎么重构?

啥时候不重构而是顶着debt继续往前(不然会无限重构做不出东西来)?

该用啥技术?在各种tradeoff间如何选择?

再加上debugger/unit test/ci/git/integration test这些tool。。

这些(系统编程) @h8liu 说得很好了,就不多说了。

2:对整个计算机stack有认识,能把各种技能混着耍

比如说,学过计算机体系结构,明白dennard scaling死掉后单线程已经上不去,GPU等massively parallel architecture是未来,然后给neural network迁移上GPU(deep learning)。

然后,会deep learning,发现这货给出的答案不一定是对的,但是可以当heuristic/hint,给传统方法加速(Alphago的MCTS(AI),Learn Indexed Structure中预测结果存在那(数据库),AutoTVM的快速评分(编译器),DeepCoder的降低搜索空间(Program Synthesis),Peloton的给数据库预测负载(数据库))

又或者,会FPGA,知道GPU之上还有很多优化空间,于是直接把整个matrix multiply fuse成电路(TPU),又或者会quantization,去研究怎么给quantized NN做ASIC(Bit Fusion)。

还有,会PL,发现Deep Learning的computation graph其实就是个first order PL,为了加入控制流(RNN/LSTM/TreeLSTM。。)以Lambda Cube为基础设计一个IR,再想办法在上面做反向传播,来做program optimization(TVM上的Relay)。

除了理解力到位,试图把未知的新工具用上已知领域,还有个更简单粗暴的用法:降低/消除低效接口带来的额外开销。

学了Memory Hierarchy以后,在用一个内存以前可以提前fetch,降低软件的memory access latency(prefetching)

如果有FPGA,可以把一部分任务schedule并offload上硬件,提高性能(Hardware/Software codesign)

有task要在docker里面跑?既然docker都有保护了,那还凭啥要跑一个有保护模式的OS,要多个address space并且不停在kernel/user上跑?Unikernel走起!

把这套玩到炉火纯青,还能像Midori这样,大手一挥,重新设计整个Software Stack,把里面的各种多余的抽象(protection类型系统给了,就不需要OS上搞)整合掉,爽不?

3:对不理解的CS&数学知识能在遇到的时候快速的补起来。

计算机科学实在太广太深,学习中碰到不会的东西已经是很正常了,所以说能力中还有一部分是:在代码/paper中发现完全不会的定义,如何在最短时间内学习/跳过,并不影响后续理解/debug?

而这些概念不一定只有CS的,有时候还有数学,所以还要打好最低限度的数学基础,达到‘看到不认识的数学定义不会去手足失措而是能慢慢啃/推敲’。不过还好,用到的数学跟数学系的双比不深,挺喜欢的一篇paper,Partially-Static Data as Free Extension of Algebras 也就用到了Free Algebra,属于很基础的抽象代数,并没深到那去,老板给我的paper,Sampling Can Be Faster Than Optimization ,能抓出重点,搞懂Metropolis–Hastings跟MALA(Intro to Stats就会教了,很浅),然后明白主Theorem是啥,也就差不多了,毕竟CS水这么深,主次要分清,数学能抓多少就抓多少吧。。

这些就是我所认为的不会随着时间而失效,也不能被体力劳动+调包取代的,真正的编程能力:

不停扩充自己的toolbox,并对自己的tool或多或少有本质上的理解。(Machine Learning/GPU Programming)

根据自己对这些工具的理解,想出新的组合法。(Deep Learning)

把自己的idea构建成一个复杂,大而全的系统,而不仅仅是一个玩具。(Pytorch)

落实到一个小功能的时候,能通过计算力,通过品味,设计出一个好用的API,编写一个正确高效的实现。(Reverse Mode Automatic Differentiation)

如果要用一句话概况,我猜编程能力是"对不同复杂度的问题(领域级/系统级/问题级),采用相对应工具降低复杂度,最后击破"的能力吧。


user avatar   catchen 网友的相关建议: 
      

景甜:抱歉,是我选的他。


user avatar   dsh0416 网友的相关建议: 
      如果node.js在双十一中的表现足够亮眼,对国内node.js的发展会有何影响?
user avatar   ze.ran 网友的相关建议: 
      如果node.js在双十一中的表现足够亮眼,对国内node.js的发展会有何影响?


  

相关话题

  2019 年了,Rust 到底比 C++ 强在哪里? 
  为什么我写代码时总是手滑把main打成mian? 
  你是怎样申请到 PhD 的呢? 
  计算机考研哪些学校性价比比较高? 
  如何看待明尼苏达大学因插入实验性漏洞,被禁止贡献 Linux 内核代码? 
  中国科学家做出何种贡献可以毫无争议地获得诺贝尔物理奖? 
  ISP给的100M带宽到底是怎么算的? 
  十进制有什么优点?为什么世界各地的数学不约而同的选择了十进制? 
  为什么程序员的工资比其他行业高这么多? 
  为什么编程更关注内存而很少关注CPU? 

前一个讨论
如何看待甘肃庆阳 8 岁女孩因被怀疑偷口红,被女教师唆使同班一年级男孩殴打致下体受伤一事?
下一个讨论
如何自学人工智能?





© 2024-11-21 - tinynew.org. All Rights Reserved.
© 2024-11-21 - tinynew.org. 保留所有权利