-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove Default when useless on its own #978
Comments
I partly agree with that, some points to consider.
I think we should keep the existing setters to avoid an unnecessary breaking change. I'd also be very careful about which |
Yes, but we can not mark them as deprecated directly. That's why I think the only way to do it is with a bigger breaking release or by marking the setters deprecated. Which is also not ideal.
I think there are two approaches to widgets: Storing the state or being thinner wrappers taking references. Currently the second one is used. rendering by ref would go towards storing stuff inside the widget itself. This question should be answered before thinking about removing the setters. Personally I would like to always have useable things. If they should be empty (like your Dataset example), they should be created explicitly. It should not be possible to do so by accident. The API should push the people to use it correctly. Having a single way to use an object is the best way in doing so.
With serde support that is indeed something we need to think about. |
First up - I'm definitely in agreement that values should be generally constructed in a usable state and the API should push the construction of valid structs. There are a few things I think are worth considering to this:
|
Normally with the builder pattern there are two structs, the target one which only exists when possible and the builder which is kind of default in the beginning. Ratatui has both merged into a single struct.
I think removing |
Yeah - I think this was probably a mistake when compared to more formal builder approaches, but it's what we inherited, and it worked well for many apps. The pattern is sometimes called the builder-lite pattern. https://matklad.github.io/2022/05/29/builder-lite.html (and the associated reddit thread has more discussion)
Agreed. I wonder whether it's worth considering a more explicit builder approach for the incremental build needs? Effectively meaning |
For most widgets I don't think so. When a List has ListItems (even an empty Vec) its valid. The rest is optional. Keeping them that way is just simpler I guess. So its only relevant for things like a Block which on its own is useless but has border or title which both make it useful. |
See #978 Also remove other derives. They are unused and just slow down compilation.
https://rust-lang.github.io/api-guidelines/interoperability.html#c-common-traits
|
See ratatui-org#978 Also remove other derives. They are unused and just slow down compilation.
There are a lot of structs mentioned in this. If you do decide to work on this, please don't submit a PR that is large and does all of these. This type of PR tends to be difficult to review reasonably and languishes in the PR queue because of that. More useful would be a smaller targeted PR for a few of these at a time. However, I think the result of this seems to be that we should not remove default when it's reasonable and only remove it where it's patently obvious that there is no sensible default. Does that align with your thinking on this @EdJoPaTo? |
Description
Some structs implement Default. When using said default its pointless on its own. It requires other methods which can easily lead to mistakes.
What is a
Terminal::default()
? (Chart)Dataset::default()
without data.To Reproduce
Just using default without something else is pointless:
Expected behavior
Default should work on its own without further modifications.
Rust is well suited to create only valid data structures. The builder pattern is a great example for this preventing invalid data structures on
build()
.There should be a new method accepting the required data instead of manipulating a default.
In this case the
data
method should also be removed to have a single way of creating the struct. Especially with the single-use, short-lived structs there is no point in keeping the setters rather than confusion.When structs contain other structs that have a Default implementation which does not make any sense on its own then
Option::None
is a way better fit instead of some pointless default.Migration suggestion:
Defaults which seem useless
An easy indicator: When the documentation of the struct never uses the
default()
on its own.Some are debatable like
Style
(its very convenient to useStyle::default()
overNone
) and especially widgets are straight forward.BarChart
BarGroup
Bar
Block
(default is useless but with titles and borders probably the simplest way to keep it that way?)Title
Buffer
Cell
CalendarEventStore
(unsure)Canvas
Label
Layer
BrailleGrid
CharGrid
HalfBlockGrid
Circle
Line
Map
(drawing withColor::Reset
me be intended but very unlikely)Rectangle
Chart
Axis
ChartLayout
Dataset
Clear
(Clear::default()
->Clear
)Constraint
(Either you don't need a layout or you want something specific?)Gauge
LineGauge
Layout
(Either you want a specific layout or you don't need it)Margin
(default is likely a bug? Explicit zero or something calculated)Size
(default is likely a bug? Explicit zero or something calculated)Line
(default is likely a bug? Should be explicitly empty?)Span
Text
List
Masked
(why mask nothing?)Paragraph
Wrap
Scrollbar
ScrollbarState
symbols::scrollbar::Set
(many emptystr
, what a benefit)Sparkline
Style
(unstyled ==Option<Style>::None
?)Modifier
(why created in the first place then?)StyledGrapheme
(default is likely a bug? Should always be something?)Table
Cell
Row
Tabs
Terminal
CrosstermBackend
ModifierDiff
TermionBackend
Fg
Bg
ModifierDiff
WordWrapper
LineTruncator
The text was updated successfully, but these errors were encountered: