You've already forked comprehensive-rust
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:
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
|
Reference in New Issue
Block a user