1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-07-11 16:50:16 +02:00

Use a terser style on slides. Avoid footnotes

This commit is contained in:
LukeMathWalker
2025-07-02 17:16:42 +02:00
parent ac219256b5
commit edfe9e8348
2 changed files with 27 additions and 28 deletions

View File

@ -4,15 +4,15 @@ minutes: 5
# Leveraging the Type System
Rust's type system is _expressive_.\
We can use types and traits to build abstractions that make our code harder to
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].
Rust's type system is _expressive_: you can use types and traits to build
abstractions that make your code harder to misuse.
The type system can also be used to model concepts and constraints from your
business domain. By designing our types carefully, we can improve the clarity
and maintainability of the entire codebase.
In some cases, you can go as far as enforcing correctness at _compile-time_,
with no runtime overhead.
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>
@ -36,12 +36,12 @@ Additional items speaker may mention:
doesn't support inheritance, and object boundaries must be mindful of the
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>
{{%segment outline}}
[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.

View File

@ -36,27 +36,26 @@ impl Username {
- 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
invariants.\
In the example above, the raw `String` stored inside the
`Username` struct can't be accessed directly from other modules or crates,
since it's not marked as `pub` or `pub(in ...)`. Consumers of the `Username`
type are forced to use the `new` method to create instances. In turn, `new`
performs validation, thus ensuring that all instances of `Username` satisfy
those checks.
In the example above, the raw `String` stored inside the `Username` struct
can't be accessed directly from other modules or crates, since it's not marked
as `pub` or `pub(in ...)`. Consumers of the `Username` type are forced to use
the `new` method to create instances. In turn, `new` performs validation, thus
ensuring that all instances of `Username` satisfy those checks.
- 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,
they can't modify it.
(e.g. to store it in a database) but, thanks to Rust's borrow checker, they
can't modify it.
- Stress the importance of evaluating _the entire API surface_ exposed by a newtype
to determine if invariants are indeed bullet-proof.\
It is crucial to consider all possible interactions, including trait implementations,
that may allow users to bypass the invariants. For example, if the `Username`
type implements the `DerefMut` trait, users can modify the underlying string
directly, bypassing the validation checks in `new`.
- Stress the importance of evaluating _the entire API surface_ exposed by a
newtype to determine if invariants are indeed bullet-proof.\
It is crucial to consider all possible interactions, including trait
implementations, that may allow users to bypass the invariants. For example,
if the `Username` type implements the `DerefMut` trait, users can modify the
underlying string directly, bypassing the validation checks in `new`.
- Type-level invariants have second-order benefits.\
The input is validated once, at the boundary, and the rest of the program can rely
on the invariants being upheld. We can avoid redundant validation and
The input is validated once, at the boundary, and the rest of the program can
rely on the invariants being upheld. We can avoid redundant validation and
"defensive programming" checks throughout the program, reducing noise and
improving performance.