我对代码完整书中的段落感到有些困惑.
在"要避免的类"一节中,它写着:
"避免使用动词命名的类只有行为但没有数据的类通常不是一个类.考虑将类似DatabaseInitialization()或StringBuilder()的类转换为其他类的例程"
我的代码主要由没有数据的动词类组成.有发票阅读器,价格计算器,消息构建器等.我这样做是为了将每个类集中到一个任务.然后我将依赖关系添加到其他类以获取其他功能.
如果我正确理解了段落,我应该使用代码
class Webservice : IInvoiceReader, IArticleReader {
public IList<Invoice> GetInvoices();
public IList<Article> GetArticles();
}
Run Code Online (Sandbox Code Playgroud)
而不是
class InvoiceReader : IInvoiceReader {
public InvoiceReader(IDataProvider dataProvider);
public IList<Invoice> GetInvoices();
}
class ArticleReader : IArticleReader {
public ArticleReader(IDataProvider dataProvider);
public IList<Article> GetArticles();
}
Run Code Online (Sandbox Code Playgroud)
编辑 感谢所有回复.
我的结论是,我目前的代码比OO更多SRP,但它也受到"贫血领域模型"的影响.
我相信这些见解将来会对我有所帮助.
当你可以创建类并做简单的事情(GUI,阅读文本文件等......)时,我从哪里开始?我已经开始阅读Code Complete第2版了,它很棒,但更像是一本通用的编程书.接下来我应该学习哪些主题?
在Code Complete中的"Good Encapsulation"部分中,建议隐藏私有实现细节.C++中给出了一个例子.这个想法基本上是将接口与实现完全分开,即使在类级别也是如此.
class Employee {
public:
...
Employee( ... );
...
FullName GetName() const;
String GetAddress() const;
private:
EmployeeImplementation *m_implementation;
};
Run Code Online (Sandbox Code Playgroud)
这真的很好用吗?这不仅效率低下(这会带来什么样的性能损失?),但Code Complete("管理复杂性")的整个座右铭似乎已经被逆转 - 这不会增加复杂性吗?
在这个论坛上看了几个星期后,我觉得是时候做我的第一篇文章.
我目前正在重读Code Complete.我认为这是自上次以来的15年,我发现我仍然无法编写代码;-)
无论如何,在Code Complete中的第138页,你会发现这个编码恐怖的例子.(我删除了一些代码)
class Emplyee {
public:
FullName GetName() const;
Address GetAddress() const;
PhoneNumber GetWorkPhone() const;
...
bool IsZipCodeValid( Address address);
...
private:
...
}
Run Code Online (Sandbox Code Playgroud)
史蒂夫认为不好的是功能松散相关.或者他写道:"检查邮政编码,电话号码或工作分类的员工和例程之间没有逻辑联系"
好的,我完全赞同他.也许类似下面的例子更好.
class ZipCode
{
public:
bool IsValid() const;
...
}
class Address {
public:
ZipCode GetZipCode() const;
...
}
class Employee {
public:
Address GetAddress() const;
...
}
Run Code Online (Sandbox Code Playgroud)
检查拉链是否有效时,您需要执行类似的操作.
employee.GetAddress().GetZipCode().IsValid();
Run Code Online (Sandbox Code Playgroud)
对于得墨忒耳法而言,这并不好.
因此,如果你想删除三个点中的两个,你需要使用委托和一些像这样的包装函数.
class ZipCode
{
public:
bool IsValid();
}
class Address {
public:
ZipCode GetZipCode() const;
bool IsZipCodeValid() {return GetZipCode()->IsValid()); …Run Code Online (Sandbox Code Playgroud) 我使用 VS Code v1.25.1 并添加了 Python 扩展。虽然它向我建议了库和类的属性和方法,即我输入from sklearn.它会提出诸如此类的建议ensemble, exception,但当我生成一个 numpy 数组x_data = np.linspace(0.0, 10.0, 1000000)并在下一行说我想使用一个方法或属性时,例如argmax它不输入后显示建议列表x_data.。
在 Jupyter Notebook 中,我曾经tab在输入后按x_data.以查看列表。我想知道是否有任何捷径可以实现相同的目标。
tl; dr-以下引用的段落是什么意思?
怀疑只有一个实例的类。单个实例可能表明设计使对象与类混淆。考虑是否可以仅创建对象而不是新类。可以将派生类的变体表示为数据而不是单独的类吗?Singleton模式是该准则的一个明显例外。
麦康奈尔,史蒂夫(2004-06-09)。代码完成(第二版)
扩大的视野:
我目前正在阅读Code Complete,并且无法理解上述段落。对于上下文,它来自继承准则的第6章。起初我以为这是不建议使用Singletons的建议,但到本段末尾时,我显然被证明是错误的。
我根本无法理解作者试图通过我厚厚的头骨做些什么。例如,我不知道他通过将对象与类混淆来设计的意思,也不知道在仅具有一个实例的类的情况下这意味着什么。救命!
我创建了一个以下列方式将对象附加到列表的行
>>> foo = list()
>>> def sum(a, b):
... c = a+b; return c
...
>>> bar_list = [9,8,7,6,5,4,3,2,1,0]
>>> [foo.append(sum(i,x)) for i, x in enumerate(bar_list)]
[None, None, None, None, None, None, None, None, None, None]
>>> foo
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
>>>
Run Code Online (Sandbox Code Playgroud)
这条线
[foo.append(sum(i,x)) for i, x in enumerate(bar_list)]
Run Code Online (Sandbox Code Playgroud)
会给一个pylint W1060表达式什么都没有,但由于我已经在使用foo列表来附加值,所以我不需要将List Comprehension行赋予某些东西.
我的问题更多的是编程正确性
我应该删除列表理解并使用简单的表达式吗?
>>> for i, x in enumerate(bar_list):
... foo.append(sum(i,x))
Run Code Online (Sandbox Code Playgroud)
或者是否有正确的方法来使用列表理解和分配到什么?
回答
谢谢@ user2387370,@ kindall和@Martijn Pieters.对于其余的注释,我使用append,因为我没有使用list(),我没有使用i + x,因为这只是一个简化的例子.
我把它留下如下:
histogramsCtr …Run Code Online (Sandbox Code Playgroud) c++ ×2
python ×2
autocomplete ×1
c# ×1
class-design ×1
composition ×1
delegates ×1
oop ×1
pimpl-idiom ×1
pylint ×1