/*
*
* 让接口容易被正确使用,不易被误用
*
* 所谓软件设计,是 “令软件做出你希望它做的事情“ 的步骤和方法,
* 通常以颇为一般性的构想开始,最终演变成十足的细节,以允许特殊
* 接口的开发         ————— 侯捷译《Effective C++》
*
* 理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,
* 这个代码就不应该通过编译。 也就是说,一旦代码通过了编译,那么,
* 它的作为就该是客户所想的。         ————— 侯捷译《Effective C++》
*
* 想开发出一个 ”容易被正确使用, 不容易被误用“ 的接口,首先必须考虑
* 客户可能做出什么样的错误。         ————— 侯捷译《Effective C++》
*
* 任何接口如果要求用户必须记得做某些事情,就是有着 ”不正确使用“ 的倾向
* 因为客户可能永远会忘记做那件事。      ————— 侯捷译《Effective C++》
*
* 附:软件设计的基本原则:
*
* 1、开放封闭原则:对于扩展是开放的,对于更改是封闭的 
* 2、依赖倒转原则:抽象不依赖细节,细节依赖抽象。
* 3、里氏代换原则:子类型必须能够替换掉他们的父类型
* 4、单一职责原则:就一个类而言。应该仅有一个引起它变化的原因。
*                        ————— GOF 《设计模式》
*/

#include <iostream>
#include <string>

using namespace std;

//以下例子改编自侯捷译《Effective C++》

class Date
{
public:
	// 这个接口就容易导致明显的两个错误:
	// 1、用户输入的年月日顺序与参数列表不匹配(却不报错)
	// 2、用户输入的年月日是个无效的时间(也不报错)
	Date(int year, int month, int day)
	{
		m_year = year;
		m_mouth = m_mouth;
		m_day = day;
	}
	int m_year, m_mouth, m_day;

	//...

};

//改进方案
class day1
{
public:
	day1(int day)
	{
		//如果输入的day无效,则抛出异常;
		//否则
		m_day = day;
	}

	int m_day;
};

class mouth1
{
public:
	mouth1(int mouth)
	{
		//如果输入的mouth无效,则抛出异常;
		//否则
		m_mouth = mouth;
	}

	int m_mouth;
};

class year1
{
public:
	year1(int year)
	{
		//如果输入的year无效,则抛出异常;
		//否则
		m_year = year;
	}

	int m_year;
};

class Date1
{
public:

	//这样如果输入顺序有误的话,就会抛出异常了
	Date1(const year1& year, const mouth1& mouth, const day1& day)
	{
		m_year = year.m_year;
		m_mouth = mouth.m_mouth;
		m_day = day.m_day;
	}
	int m_year, m_mouth, m_day;
};

//当然,也可以给月份以管理。

class mouth2
{
public :
	static mouth2 Jan() { return mouth2(1); }
	//...
	static mouth2 Dec() { return mouth2(12); }

private:
	explicit mouth2(int mouth)
	{
		//这里设置月份的专属数据
	}

	//这里定义月份的专属数据...
	//...
};


int main()
{
	return 0;
}