Skip to content

Commit

Permalink
anti_patterns chapter translated.
Browse files Browse the repository at this point in the history
  • Loading branch information
Fomalhauthmj committed Jan 10, 2022
1 parent aeea544 commit fcf3254
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 101 deletions.
2 changes: 1 addition & 1 deletion SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
- [反面模式](./anti_patterns/index.md)
- [通过Clone来满足借用检查器](./anti_patterns/borrow_clone.md)
- [`#[deny(warnings)]`](./anti_patterns/deny-warnings.md)
- [Deref Polymorphism](./anti_patterns/deref.md)
- [解引用多态性](./anti_patterns/deref.md)

- [Functional Programming](./functional/index.md)
- [Programming paradigms](./functional/paradigms.md)
Expand Down
73 changes: 31 additions & 42 deletions anti_patterns/deny-warnings.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,48 @@
# `#![deny(warnings)]`

## Description
## 描述

A well-intentioned crate author wants to ensure their code builds without
warnings. So they annotate their crate root with the following:
一个善意的crate作者想确保他们的代码在构建时不会出现警告。所以他用以下内容来注释其crate根。

## Example
## 例子

```rust
#![deny(warnings)]

// All is well.
```

## Advantages
## 优势

It is short and will stop the build if anything is amiss.
注释很短,如果出现错误,会停止构建。

## Drawbacks
## 劣势

By disallowing the compiler to build with warnings, a crate author opts out of
Rust's famed stability. Sometimes new features or old misfeatures need a change
in how things are done, thus lints are written that `warn` for a certain grace
period before being turned to `deny`.
通过不允许编译器产生构建警告,crate作者失去了Rust引以为傲的稳定性。
有时,新特性或旧的错误特性需要改变处理逻辑,因此,在转为`deny`之前,会有`warn`的lint,并有一定的缓冲期。

For example, it was discovered that a type could have two `impl`s with the same
method. This was deemed a bad idea, but in order to make the transition smooth,
the `overlapping-inherent-impls` lint was introduced to give a warning to those
stumbling on this fact, before it becomes a hard error in a future release.
例如,人们发现一个类型可以有两个具有相同方法的`impl`块。
这被认为是一个坏主意,但为了使过渡顺利,`overlapping-inherent-impls` lint被引入,给那些偶然发现这个事实的人一个警告,即使它在未来的版本中将成为一个硬编码错误。

Also sometimes APIs get deprecated, so their use will emit a warning where
before there was none.
另外,有时API会被废弃,所以在它们消失前使用会发出警告。

All this conspires to potentially break the build whenever something changes.
当某些事情发生改变,所有这些都有潜在的破坏构建的可能性。

Furthermore, crates that supply additional lints (e.g. [rust-clippy]) can no
longer be used unless the annotation is removed. This is mitigated with
[--cap-lints]. The `--cap-lints=warn` command line argument, turns all `deny`
lint errors into warnings.
此外,提供额外lint的crate(例如[rust-clippy])不能再被使用,除非注释被删除。这可以通过[-cap-lints]来缓解。
命令行参数`--cap-lints=warn`可将所有`deny`lint错误变成警告。

## Alternatives
## 替代方案

There are two ways of tackling this problem: First, we can decouple the build
setting from the code, and second, we can name the lints we want to deny
explicitly.
有两种方法可以解决这个问题:第一,我们可以将构建设置与代码解耦;第二,我们可以指明我们想要显式拒绝的lint。

The following command line will build with all warnings set to `deny`:
下面的命令行参数在所有警告设置为`deny`的情况下构建:

```RUSTFLAGS="-D warnings" cargo build```

This can be done by any individual developer (or be set in a CI tool like
Travis, but remember that this may break the build when something changes)
without requiring a change to the code.
这可以由任何个人开发者完成(或者在Travis这样的CI工具中设置,但请记住,当有变化时,这可能会破坏构建),而不需要对代码进行修改。

Alternatively, we can specify the lints that we want to `deny` in the code.
Here is a list of warning lints that is (hopefully) safe to deny (as of Rustc 1.48.0):
另外,我们可以在代码中指定我们想要`deny`的lint。
下面是一个(希望)可以安全拒绝的警告lint的列表(截至Rustc 1.48.0:

```rust,ignore
#[deny(bad-style,
Expand All @@ -75,7 +63,7 @@ Here is a list of warning lints that is (hopefully) safe to deny (as of Rustc 1.
while-true)]
```

In addition, the following `allow`ed lints may be a good idea to `deny`:
此外,以下`allow`lint可能是一个`deny`的好主意。

```rust,ignore
#[deny(missing-debug-implementations,
Expand All @@ -88,19 +76,20 @@ In addition, the following `allow`ed lints may be a good idea to `deny`:
unused-results)]
```

Some may also want to add `missing-copy-implementations` to their list.
有些人可能还想在他们的列表中加入`missing-copy-implementations`lint。

Note that we explicitly did not add the `deprecated` lint, as it is fairly
certain that there will be more deprecated APIs in the future.
请注意,我们没有明确添加`deprecated`的lint,因为可以肯定的是,未来会有更多被废弃的API。

## See also
## 参见

- [A collection of all clippy lints](https://rust-lang.github.io/rust-clippy/master)
- [deprecate attribute] documentation
- Type `rustc -W help` for a list of lints on your system. Also type
`rustc --help` for a general list of options
- [rust-clippy] is a collection of lints for better Rust code
- [所有的clippy lints](https://rust-lang.github.io/rust-clippy/master)
- [deprecate attribute]文档
- 输入`rustc -W help`可查看你系统上的lint。也可以输入
`rustc --help`查看选项。
- [rust-clippy]是一个用于写出更好的Rust代码的lint集合。

[rust-clippy]: https://github.com/Manishearth/rust-clippy
[deprecate attribute]: https://doc.rust-lang.org/reference/attributes.html#deprecation
[--cap-lints]: https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints

> Latest commit 39a2f36 on 18 Oct 2021
96 changes: 38 additions & 58 deletions anti_patterns/deref.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# `Deref` polymorphism
# `Deref` 多态性

## Description
## 描述

Abuse the `Deref` trait to emulate inheritance between structs, and thus reuse
methods.
滥用`Deref` trait来模拟结构体间的继承,从而重用方法。

## Example
## 例子

Sometimes we want to emulate the following common pattern from OO languages such
as Java:
有时我们想模仿以下来自OO语言(如Java)的常见模式:

```java
class Foo {
Expand All @@ -23,7 +21,7 @@ public static void main(String[] args) {
}
```

We can use the deref polymorphism anti-pattern to do so:
我们可以使用deref多态性的反面模式来做到这一点:

```rust
use std::ops::Deref;
Expand Down Expand Up @@ -53,22 +51,15 @@ fn main() {
}
```

There is no struct inheritance in Rust. Instead we use composition and include
an instance of `Foo` in `Bar` (since the field is a value, it is stored inline,
so if there were fields, they would have the same layout in memory as the Java
version (probably, you should use `#[repr(C)]` if you want to be sure)).
Rust中没有结构体的继承。相反,我们使用组合,并在`Bar`中包含一个`Foo`的实例(因为字段是一个值,它被内联存储,所以如果有字段,它们在内存中的布局与Java版本相同(可能,如果你想确定,你应该使用`#[repr(C)]`))。

In order to make the method call work we implement `Deref` for `Bar` with `Foo`
as the target (returning the embedded `Foo` field). That means that when we
dereference a `Bar` (for example, using `*`) then we will get a `Foo`. That is
pretty weird. Dereferencing usually gives a `T` from a reference to `T`, here we
have two unrelated types. However, since the dot operator does implicit
dereferencing, it means that the method call will search for methods on `Foo` as
well as `Bar`.
为了使方法调用生效,我们为`Bar`实现了`Deref`,以`Foo`为目标(返回嵌入的`Foo`字段)。这意味着当我们解除对`Bar`的引用时(例如,使用`*`),我们将得到一个`Foo`
这很奇怪。解引用通常从对`T`的引用中得到一个`T`,这里我们有两个不相关的类型。
然而,由于点运算符做了隐式解引用,这意味着方法调用将搜索`Foo``Bar`的方法。

## Advantages
## 优势

You save a little boilerplate, e.g.,
你可以节省一点模板代码,例如:

```rust,ignore
impl Bar {
Expand All @@ -78,51 +69,40 @@ impl Bar {
}
```

## Disadvantages
## 劣势

Most importantly this is a surprising idiom - future programmers reading this in
code will not expect this to happen. That's because we are abusing the `Deref`
trait rather than using it as intended (and documented, etc.). It's also because
the mechanism here is completely implicit.
最重要的是这是一个令人惊讶的习语--未来的程序员在代码中读到这句话时,不会想到会发生这种情况。
这既因为我们在滥用`Deref` trait,而不是按照预期(文档等)使用它。
也因为这里的机制是完全隐含的。

This pattern does not introduce subtyping between `Foo` and `Bar` like
inheritance in Java or C++ does. Furthermore, traits implemented by `Foo` are
not automatically implemented for `Bar`, so this pattern interacts badly with
bounds checking and thus generic programming.
这种模式没有像Java或C++中的继承那样在`Foo``Bar`之间引入子类型。此外,由`Foo`实现的特性不会自动为`Bar`实现,所以这种模式与边界检查以及泛型编程的互动性很差。

Using this pattern gives subtly different semantics from most OO languages with
regards to `self`. Usually it remains a reference to the sub-class, with this
pattern it will be the 'class' where the method is defined.
使用这种模式,在`self`的语义上与大多数OO语言有细微的不同。
通常情况下,它仍然是对子类的引用,在这种模式下,它将是定义方法的"类"。

Finally, this pattern only supports single inheritance, and has no notion of
interfaces, class-based privacy, or other inheritance-related features. So, it
gives an experience that will be subtly surprising to programmers used to Java
inheritance, etc.
最后,这种模式只支持单继承,没有接口的概念,没有基于类的隐私,也没有其他与继承有关的特性。
所以,它给人的体验会让习惯了Java继承等的程序员感到微妙的惊讶。

## Discussion
## 讨论

There is no one good alternative. Depending on the exact circumstances it might
be better to re-implement using traits or to write out the facade methods to
dispatch to `Foo` manually. We do intend to add a mechanism for inheritance
similar to this to Rust, but it is likely to be some time before it reaches
stable Rust. See these [blog](http://aturon.github.io/blog/2015/09/18/reuse/)
我们没有一个好的替代方案。根据具体的情况,使用traits重新实现或者手动写出派发给`Foo`的facade方法可能更好。
我们确实打算在Rust中加入与此类似的继承机制,但要达到稳定的Rust,可能还需要一些时间。详情可见:
[blog](http://aturon.github.io/blog/2015/09/18/reuse/)
[posts](http://smallcultfollowing.com/babysteps/blog/2015/10/08/virtual-structs-part-4-extended-enums-and-thin-traits/)
and this [RFC issue](https://github.com/rust-lang/rfcs/issues/349) for more details.
and this [RFC issue](https://github.com/rust-lang/rfcs/issues/349)

The `Deref` trait is designed for the implementation of custom pointer types.
The intention is that it will take a pointer-to-`T` to a `T`, not convert
between different types. It is a shame that this isn't (probably cannot be)
enforced by the trait definition.
`Deref` trait 是为实现自定义指针类型而设计的。
目的是让它通过指向`T`的指针到达`T`,而不是在不同类型之间转换。
遗憾的是,这一点并没有(也许不能)由trait定义强制执行。

Rust tries to strike a careful balance between explicit and implicit mechanisms,
favouring explicit conversions between types. Automatic dereferencing in the dot
operator is a case where the ergonomics strongly favour an implicit mechanism,
but the intention is that this is limited to degrees of indirection, not
conversion between arbitrary types.
Rust试图在显式和隐式机制之间取得谨慎的平衡,倾向于类型之间的显式转换。
点运算符中的自动解引用是一个人机工程学强烈支持隐式机制的情况,但其目的是将其限制在间接程度上,而不是在任意类型之间的转换。

## See also
## 参见

- [Collections are smart pointers idiom](../idioms/deref.md).
- Delegation crates for less boilerplate like [delegate](https://crates.io/crates/delegate)
or [ambassador](https://crates.io/crates/ambassador)
- [Documentation for `Deref` trait](https://doc.rust-lang.org/std/ops/trait.Deref.html).
- [集合是智能指针的习语](../idioms/deref.md).
- 为了较少的模板代码的代表crate [delegate](https://crates.io/crates/delegate)
[ambassador](https://crates.io/crates/ambassador)
- [`Deref` trait文档](https://doc.rust-lang.org/std/ops/trait.Deref.html).

> Latest commit fb57f21 on 10 Mar 2021

0 comments on commit fcf3254

Please sign in to comment.