【回复:致我团队中的程序员应聘者】

来源:互联网 发布:综合性数据库包括 编辑:程序博客网 时间:2024/04/30 17:00
首先要道歉。
非常抱歉,本来答应前几天回复,不过最近每天真是太忙了,计划表中每天都要实现一个功能,所以直到今天早上才查看并修改。


代码功能先放在一边,首先有几个问题要说明。


1.代码不可运行。
不知道是不是Unity版本不对,
或是什么别的原因,
代码拷进来之后根本无法运行,
提示错误连篇。
于是我开始大幅度修改,
直到成功运行。


不过版本问题先放在一边,
话说发过来的版本中Init方法中的Window都没有调用Show方法,
不知道原本是如何运行的。


2.在半个小时的修改过程中,
我主要做了以下几件事:


-----------------------------


①.重命名变量。
比如说那个map_a,
非局部变量应使用骆驼峰式命名。


②.抽取方法。
当看到OnGUI中格式代码(StartHorizontal)和功能代码混在一起,
一个方法就有三四十行的时候,
我有些失去耐心了。


提取方法我使用了以下几种方法:
(1).删除重复代码。比如说那个DestroyImmediately,提取成了assertNull,
还顺便取消原来的"gobj"变量。


(2)化繁为简。比如说我将两个Button的功能提取为两个方法,简明扼要。


(3)便于理解。将长代码拆分成不同的功能部分,一来简化代码,其次将不同的
功能区域区分开,便于阅读。


③.减少花括号数目。
这一点你在编程时也能感受到,
当五六七八个花括号叠在一起时,
无论是阅读还是欣赏都毫无意义。
如果你之前习惯Java或是Android编程,
那我要提醒一句,
在Unity或是C#中,
这么玩可不行。


双重for循环无法精简,那就将里面的if和else拆分开就可以了。
使用continue或是break什么的代替,
很容易就能减少花括号的数量。


④.减少临时变量数目。
obj和gobj的命名问题先放在一边,
但这两个临时变量多次出现在不同方法,
这一点就足以证明程序不够精简,
运行起来也会毫无疑问效率较低。
尽最大可能减少临时变量的出现,
尤其是重复出现时,
就该思考是否有什么方法可以弥补这一点。


⑤.取消多余行数/添加符号空格。
这一点如果你之前习惯使用成熟的编译器可能无法体会,
但在脚本编程中,
符号是否有空格就决定了其旁边的变量名是否可以被搜索到,
也就决定了是否可以使用Ctrl + H来重命名。
要知道脚本语言大部分无法被Refactor。
成千上万行的脚本,如果无法使用Ctrl+H来重命名,
那修改代码的效率自然可以想象。


至于行数的作用,
最主要的就是分隔功能块。
如果这一点无法保证,
那代码注释再多也无济于事。


⑥.添加/取消注释。
之前你跟我说我的代码的注释太少,
我承认这一点。
在一个人编程的时候,
我并不太过在意注释问题,
因为我崇尚一条真理:


——最好的注释就是没有注释。


为什么?
因为将所有注释应该写明的东西,
用完整的命名,有条理的顺序,以及规范的格式就可以表现。
脱离这一点,
试图使用注释来弥补其他方面的弊端,
那自然是欲盖弥彰。


除此之外,
代码中尽量不要出现中文,
这也是成熟团队的一个默认标准。


-----------------------------


这只是一个检验,
我并不只是想看看应试者是否能够"实现"什么东西,
更重要的是希望看到你们如何来"实现"。


你们每个人并不是对Unity都非常了解,
正因如此,
类似as关键词的使用或是接口选择之类的问题我并未列在上述表单之中。


但编程能体现的是一个编程者对于程序的理解,
以及他的经验。


功能在我看来是最简单不过的东西,
一个功能,研究一天,一星期或是一个月一年总该有结果,
但实现的过程,
却并非一朝一夕可以完善的。


团队编程最重要的就是相互之间的默契,
而代码,就是程序员之间的交流语言,
一注释一空格之间就足以表明诸多要素。


我自己热爱编程,
每次编程都能够乐在其中,甚至大多数情况都无法自拔。
因为我将编程的过程看作是写诗,
如何去构造,如何去描述,如何选词酌句,
都是需要大量的实践与思考才能至善至美的。
在这个过程中,
我可以很明显地可以感受到沉浸其中所带来的快乐的。


抛开这一点不提,
程序员最讨厌的莫过于Bug。
而绝大多数的Bug并非在于逻辑错误,
而是在于编程规范。
如何减少Bug,
也是编程水平提升的重要一步。



至此,
再次为我迟到的回复致以歉意。
并推荐几本书,供你日后编程作为参考:


《Clean Code》
《Refactoring To Patterns》

《敏捷编程系列》


更改后代码:

using UnityEngine;using UnityEditor;using System.Collections;public class MapGenerator: EditorWindow {/// <summary>/// The height of the meta prefab./// </summary>int prefabHeight = 1;int prefabWidth = 1;const int horizontalNumber = 8;const int verticalNumber = 8;/// <summary>/// The map array./// </summary>public Object[,] mapArray = new Object[verticalNumber,horizontalNumber];[MenuItem ("MyTools/MapGenerator")]static void Init () {MapGenerator window = (MapGenerator)EditorWindow.GetWindow(typeof (MapGenerator));window.Show();}void OnGUI () {// setting of prefabGUILayout.Label ("Basic Settings", EditorStyles.boldLabel);prefabHeight = EditorGUILayout.IntField ("PrefabHeight:",prefabHeight);prefabWidth = EditorGUILayout.IntField ("PrefabWidth:",prefabWidth);EditorGUILayout.Space();// the area of map editorGUILayout.Label ("MapEditor", EditorStyles.boldLabel);for(int j = 0;j < horizontalNumber;j++){EditorGUILayout.BeginHorizontal();for(int i = 0;i < verticalNumber;i++)mapArray[i,j] = EditorGUILayout.ObjectField(mapArray[i,j],typeof(Object), true);EditorGUILayout.EndHorizontal();   }EditorGUILayout.Space();// the area of buttonEditorGUILayout.BeginHorizontal();if (GUILayout.Button("Create"))Create();if (GUILayout.Button("Reset"))Reset();EditorGUILayout.EndHorizontal();}private void Create(){for(int j = 0;j < horizontalNumber;j++){for(int i = 0;i < verticalNumber;i++){if(null == mapArray[i,j])continue;assertNull(GameObject.Find("Tile" + j + i));Vector3 pVector = new Vector3(i*prefabWidth, (horizontalNumber-j)*prefabHeight, 0);generateObject(pVector,j,i);}}}private void Reset(){prefabWidth = 1;prefabHeight = 1;for(int j = 0;j < horizontalNumber;j++){for(int i = 0;i < verticalNumber;i++){if(null == mapArray[i,j])continue;assertNull(GameObject.Find("Tile" + j + i));mapArray[i,j] = null;}}}/// <summary>/// Generate object and assign some properties/// </summary>/// <param name='pos'>/// Generate position./// </param>/// <param name='h'>/// Index of height/// </param>/// <param name='w'>/// Index of weight./// </param>protected void generateObject(Vector3 pos,int h,int w){Object obj = Instantiate(mapArray[h,w],pos, Quaternion.identity);obj.name = "Tile" + h + w;(obj as GameObject).transform.localScale = new Vector3(prefabWidth,prefabHeight,1);}/// <summary>/// Asserts the gameObject is null./// </summary>/// <param name='gameObject'>/// Game object./// </param>protected void assertNull(GameObject gameObject){if(gameObject)DestroyImmediate(gameObject);}}


By Elezor 2013.8.24
原创粉丝点击