3. 项目管理规范 && 命名方式规范

项目管理和命名方式都是“规范”的问题,部分公司会书写这方面的规范文档,以保证大家写出来的代码符合同一规范。这里只讨论常用的规范方式。

项目管理

项目管理这一块,涉及到解决方案中的各个概念,“解决方案”、“项目”、“文件夹”、“文件”(含说明性文档)。其中,解决方案包含项目,项目包含文件夹,文件夹包含文件。

解决方案 && 项目

一般来说一个解决方案是一个产品(网站、APP、桌面程序、类库等等)。
“项目”是一个个.csproj,最简单的就是一个解决方案、一个项目,完成开发。但大家并不会这样做,我们会把一个项目拆分成多个项目,在不同的项目中完成不同的功能,然后通过引用的方式完成不同项目之间的“粘连”。
为什么要这样做呢?一个原因是提高代码的可读性。比如最传统的三层架构,视图(eg.网站)是一个项目,业务逻辑(BLL)是一个项目,数据库操纵(DAL)是一个项目。将不同的职责放到不同的项目中,管理、优化起来更加方便,代码更加清晰。
另一个原因是,一个庞大的项目往往由多个开发组、多个开发者去开发和维护。将项目拆解成一个个独立的项目(甚至独立的解决方案),有利于多个开发者的工作。可能产品的部分功能由开发组A完成,另一部分功能由开发组B完成,而两个开发组的代码对对方来说都是不可见的。
所以“拆解”项目不要吝啬,根据业务、逻辑,最大化的去拆分项目,对未来产品的功能拓展和代码维护都有很大好处。
解决方案的命名一般和产品息息相关,比如Taobao、Wechat。而项目的命名,可以在解决方案的基础上加一些“说明”,比如Wechat.Mobile、Wechat.Tool,添加的内容概况项目的定位。
刚开始如果没有办法去很好的组织项目,可以参考其他优秀的项目,github上面有很多优秀的开源的项目,他们的项目是怎么组织的,代码是怎么写的,都非常值得学习,比如:vscodeaspnetboilerplateNewtonsoft.Json。多看高Star的项目多学习。
对于产品名字过长的问题,在命名时,可以采用“缩写”。比如“aspnetboilerplate”,项目名都是“Abp.xxx.xxx”,用“Abp”代替了“aspnetboilerplate”。这都还不算很长的产品名称,业务系统很多都是“XXXXX系统”, 比如我之前开发的“生态监测管理系统”,英文翻译为“Ecological Monitoring Management System”,如果我们不进行缩写,解决方案的名称为“EcologicalMonitoringManagementSystem”,项目的名称是“EcologicalMonitoringManagementSystem.EntityFramework”,类名为“EcologicalMonitoringManagementSystem.EntityFramework.EntityMapper.Devices.DeviceCfg” ——————————哇,这简直是个灾难!又臭又长。
所以我们要进行缩写,将“Ecological Monitoring Management System”写成“EMMS”。

文件夹 && 文件

一个项目中可以有文件夹、文件,那它们又是怎样摆放的呢?我一般将程序的入口、配置的内容放在根目录,把“同一类型”的文件放在同一文件夹下。
比如控制台程序中的Program.cs、ASP .NET Core中的appsettings.json、Startup.cs,都适合放在项目的根目录。
同一类型、同一功能的内容,比如“完成发送短信的功能”、“定义产品表”,涉及的所有内容,可以放在同一文件夹中。
“定义产品表”的文件夹中,可以包含产品表的定义、产品表的MapperConfiguration、数据库Configuration、Dto等等。
“完成发送短信的功能”,可以包含发送短信的接口、发送短信的实现(多个短信服务平台)、发送短信的统一方法(包含业务逻辑)等。可能还会有一些README文件,用来备注一些关于发送短信信息。
文件夹的命名肯定以“贴近”其中的内容为目标。文件夹的命名的单复数,可以根据内容来判断:如果文件夹像一个工厂一样,整体完成一个零件,则可以取这个零件名称的单数形式作为文件夹的命名,比如“定义产品表”-Product;如果文件夹完成了同一目的的不同实现,则可以取复数,比如“完成发送短信的功能”-SendMessages。
一般一个.cs文件放一个类,类的命名为单数,且文件和类同名。有些开发喜欢把接口和实现类、类和它包含的枚举值放在一起,是个人习惯问题,我个人不推荐这样做。
一些同功能的类使用同样的命名结尾,比如“XXXBuilder”、“XXXConfiguration”、“XXXHelper”。
这里我展示一些我开发的项目中的文件摆放。

类、变量、方法命名方式

我们先直观感受下不同语言的命名方式:
java(来自Android开发之onClick事件的三种写法


package a.a;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
 
public class AActivity extends Activity {
	/** Called when the activity is first created. */
 
	EditText Ev1;
 
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
 
		Ev1 = (EditText)findViewById(R.id.editText1);  
 
		//第一种方式  
		Button Btn1 = (Button)findViewById(R.id.button1);//获取按钮资源  
		Btn1.setOnClickListener(new Button.OnClickListener(){//创建监听  
			public void onClick(View v) {  
				String strTmp = "点击Button01";  
				Ev1.setText(strTmp);  
			}  
 
		});  
 
		//第二种方式  
		Button Btn2 = (Button) findViewById(R.id.button2);//获取按钮资源  
		Btn2.setOnClickListener(listener);//设置监听  
 
	}
 
	Button.OnClickListener listener = new Button.OnClickListener(){//创建监听对象  
		public void onClick(View v){  
			String strTmp="点击Button02";  
			Ev1.setText(strTmp);  
		}  
 
	};
 
 
	//第三种方式(Android1.6版本及以后的版本中提供了)  
	public void Btn3OnClick(View view){  
		String strTmp="点击Button03";
		Ev1.setText(strTmp);
 
	}  
}

python

import requests        #导入requests包
import json
def get_translate_date(word=None):
    url = 'url'
    From_data={}
    #请求表单数据
    response = requests.post(url,data=From_data)
    #将Json格式字符串转字典
    content = json.loads(response.text)
    print(content)
    #打印翻译后的数据
    #print(content['translateResult'][0][0]['tgt'])
if __name__=='__main__':
    get_translate_date('......')

C#(来自在C#中,Json的序列化和反序列化的几种方式总结

Student stu = new Student()
 {
	 ID = 1,
	 Name = "曹操",
	 Sex = "男",
	 Age = 1000
 };
//序列化
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Student));
MemoryStream msObj = new MemoryStream();
//将序列化之后的Json格式数据写入流中
js.WriteObject(msObj, stu);
msObj.Position = 0;
//从0这个位置开始读取流中的数据
StreamReader sr = new StreamReader(msObj, Encoding.UTF8);
string json = sr.ReadToEnd();
sr.Close();
msObj.Close();
Console.WriteLine(json);


//反序列化
string toDes = json;
//string to = "{\"ID\":\"1\",\"Name\":\"曹操\",\"Sex\":\"男\",\"Age\":\"1230\"}";
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(toDes)))
{
	DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(Student));
	Student model = (Student)deseralizer.ReadObject(ms);// //反序列化ReadObject
	Console.WriteLine("ID=" + model.ID);
	Console.WriteLine("Name=" + model.Name);
	Console.WriteLine("Age=" + model.Age);
	Console.WriteLine("Sex=" + model.Sex);
}
Console.ReadKey(); 

可以看出,不同的语言写法差异很大,一方面是来自语法、格式本身不同,一方面是不同语言的开发者的命名规范不同。
C#的命名方式也有很多,这里我只描述我最常用的方式。
所有多单词的连接,都使用骆驼命名法。即"Get Your Information",变为"GetYourInformation"。
类中的属性、方法名,以大写字母开头,字段以小写字母开头(一些开发喜欢以下划线开头)。
接口以“I”开头,比如“ISendMessage”。
命名方式,可以选择一种自己觉得最舒适的规范,然后一直遵守它。
举个例子:

public class StudentByINotifyPropertyChanged: INotifyPropertyChanged
{
	public event PropertyChangedEventHandler PropertyChanged;
	//实现INotifyPropertyChanged接口
	private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
	{
		if (PropertyChanged != null)
		{
			PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
		}
	}

	//私有字段小写
	private string sex;
	private string name;

	//公开属性大写
	public string Sex
	{
		get { return sex; }
		set
		{
			sex = value;
			NotifyPropertyChanged("Sex");
		}
	}

	public string Name
	{
		get { return name; }
		set
		{
			name = value;
			NotifyPropertyChanged("Name");
		}
	}
}

INotifyPropertyChanged是接口,以“I”开头。“StudentByINotifyPropertyChanged”这个名字不是太好,实际上这是“StudentViewModel”(MVVM相关概念)。
私有字段小写开头,公有属性大写开头。如果将Name拆分为“姓”、“名”,则私有字段是“lastName”,“firstName”,公有属性为“LastName”、“FirstName”。
有方法“获得姓名”,则应该命名为“GetName”或者“GetFullName”。

posted @ 2020-02-22 14:20  Lulus  阅读(1693)  评论(0编辑  收藏  举报