You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-07-12 01:00:16 +02:00
Use a terser style on slides. Avoid footnotes
This commit is contained in:
@ -4,15 +4,15 @@ minutes: 5
|
|||||||
|
|
||||||
# Leveraging the Type System
|
# Leveraging the Type System
|
||||||
|
|
||||||
Rust's type system is _expressive_.\
|
Rust's type system is _expressive_: you can use types and traits to build
|
||||||
We can use types and traits to build abstractions that make our code harder to
|
abstractions that make your code harder to misuse.
|
||||||
misuse. In some cases, we can even go as far as enforcing correctness at
|
|
||||||
_compile-time_. Quite often, these abstractions have no runtime
|
|
||||||
overhead[^zero-cost].
|
|
||||||
|
|
||||||
The type system can also be used to model concepts and constraints from your
|
In some cases, you can go as far as enforcing correctness at _compile-time_,
|
||||||
business domain. By designing our types carefully, we can improve the clarity
|
with no runtime overhead.
|
||||||
and maintainability of the entire codebase.
|
|
||||||
|
Types and traits can model concepts and constraints from your business domain.
|
||||||
|
With careful design, you can improve the clarity and maintainability of the
|
||||||
|
entire codebase.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
@ -36,12 +36,12 @@ Additional items speaker may mention:
|
|||||||
doesn't support inheritance, and object boundaries must be mindful of the
|
doesn't support inheritance, and object boundaries must be mindful of the
|
||||||
constraints introduced by the borrow-checker.
|
constraints introduced by the borrow-checker.
|
||||||
|
|
||||||
|
- Mention that type-level abstractions are often referred to as "zero-cost
|
||||||
|
abstractions", although the label can be misleading: the impact on compile
|
||||||
|
times and code complexity may be significant.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
{{%segment outline}}
|
{{%segment outline}}
|
||||||
|
|
||||||
[1]: https://pragprog.com/titles/swdddf/domain-modeling-made-functional/
|
[1]: https://pragprog.com/titles/swdddf/domain-modeling-made-functional/
|
||||||
|
|
||||||
[^zero-cost]: They often referred to as "zero-cost abstractions", although the
|
|
||||||
label can be misleading: the impact on compile times and code complexity may
|
|
||||||
be significant.
|
|
||||||
|
@ -36,27 +36,26 @@ impl Username {
|
|||||||
- The newtype pattern, combined with Rust's module and visibility system, can be
|
- The newtype pattern, combined with Rust's module and visibility system, can be
|
||||||
used to _guarantee_ that instances of a given type satisfy a set of
|
used to _guarantee_ that instances of a given type satisfy a set of
|
||||||
invariants.\
|
invariants.\
|
||||||
In the example above, the raw `String` stored inside the
|
In the example above, the raw `String` stored inside the `Username` struct
|
||||||
`Username` struct can't be accessed directly from other modules or crates,
|
can't be accessed directly from other modules or crates, since it's not marked
|
||||||
since it's not marked as `pub` or `pub(in ...)`. Consumers of the `Username`
|
as `pub` or `pub(in ...)`. Consumers of the `Username` type are forced to use
|
||||||
type are forced to use the `new` method to create instances. In turn, `new`
|
the `new` method to create instances. In turn, `new` performs validation, thus
|
||||||
performs validation, thus ensuring that all instances of `Username` satisfy
|
ensuring that all instances of `Username` satisfy those checks.
|
||||||
those checks.
|
|
||||||
|
|
||||||
- The `as_str` method allows consumers to access the raw string representation
|
- The `as_str` method allows consumers to access the raw string representation
|
||||||
(e.g. to store it in a database) but, thanks to Rust's borrow checker,
|
(e.g. to store it in a database) but, thanks to Rust's borrow checker, they
|
||||||
they can't modify it.
|
can't modify it.
|
||||||
|
|
||||||
- Stress the importance of evaluating _the entire API surface_ exposed by a newtype
|
- Stress the importance of evaluating _the entire API surface_ exposed by a
|
||||||
to determine if invariants are indeed bullet-proof.\
|
newtype to determine if invariants are indeed bullet-proof.\
|
||||||
It is crucial to consider all possible interactions, including trait implementations,
|
It is crucial to consider all possible interactions, including trait
|
||||||
that may allow users to bypass the invariants. For example, if the `Username`
|
implementations, that may allow users to bypass the invariants. For example,
|
||||||
type implements the `DerefMut` trait, users can modify the underlying string
|
if the `Username` type implements the `DerefMut` trait, users can modify the
|
||||||
directly, bypassing the validation checks in `new`.
|
underlying string directly, bypassing the validation checks in `new`.
|
||||||
|
|
||||||
- Type-level invariants have second-order benefits.\
|
- Type-level invariants have second-order benefits.\
|
||||||
The input is validated once, at the boundary, and the rest of the program can rely
|
The input is validated once, at the boundary, and the rest of the program can
|
||||||
on the invariants being upheld. We can avoid redundant validation and
|
rely on the invariants being upheld. We can avoid redundant validation and
|
||||||
"defensive programming" checks throughout the program, reducing noise and
|
"defensive programming" checks throughout the program, reducing noise and
|
||||||
improving performance.
|
improving performance.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user