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

首先要道歉。
非常抱歉,本来答应前几天回复,不过最近每天真是太忙了,计划表中每天都要实现一个功能,所以直到今天早上才查看并修改。


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


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 prefab
		GUILayout.Label ("Basic Settings", EditorStyles.boldLabel);
		
			prefabHeight = EditorGUILayout.IntField ("PrefabHeight:",prefabHeight);
			prefabWidth = EditorGUILayout.IntField ("PrefabWidth:",prefabWidth);
		
		EditorGUILayout.Space();
		
		// the area of map editor
		GUILayout.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 button
		EditorGUILayout.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

你可能感兴趣的:(规范代码,EleGameStudio)