Skip to content

Nicer (alternative?) Debug implementations #503

@aldanor

Description

@aldanor

Here's one simple suggestion that may increase user-friendliness of the crate by a huge margin:

  • Switch Debug implementations (e.g. for Date or OffsetDateTime) to user-friendly ones

Current behaviour if you ever debug-print a date or a datetime (you'll have to scroll right...):

date: Date { year: 2019, ordinal: 89 },
time: OffsetDateTime { local_datetime: PrimitiveDateTime { date: Date { year: 2019, ordinal: 89 }, time: Time { hour: 0, minute: 0, second: 0, nanosecond: 0 } }, offset: UtcOffset { hours: 0, minutes: 0, seconds: 0 } } },

Proposed behaviour:

date: 2019-03-30,
time: 2019-03-30 0:00:00.0 +00:00:00,

The main point, really, is user (or rather, dev) friendliness, to aid in developing crates that depend on time. As a hypothetical example, you're using this crate for parsing some structs from some APIs and you want to quickly derive Debug on those to see what you've just parsed, you'll have a hard time (especially with dates).

A few notes and some explanation:

  • Whichever formatting is chosen, it has to be lossless, especially for datetimes (that is, if there are non-zero nanoseconds there, they cannot be truncated).
  • Date { year: 2019, ordinal: 89 } is information for computers, not for human beings. You won't be able to tell what date it is without doing a mental (or computer-aided) computation first.
  • OffsetDateTimes are absolutely humongous when debug-printed and will likely dwarf most structs; their readable representation is a tiny string that humans can immediately parse though.
  • But Debug has to represent internals since it's meant for Debug purposes? Not really - same as Vec's Debug implementation doesn't print its capacity and the pointer, it just outputs whatever likely is the most useful information to the user. If you need to print capacity and the pointer, in very rare cases, you can always do so manually.
  • Why not implement your own Debug? You can. But sometimes you have 20 other fields in your structs, and you'd have to manually implement Debug just to be able to see your dates and times in a readable fashion.
  • You can always wrap Date in a newtype? You can. But then have to do it everywhere you use it, you'll have to implement derefs and conversions and possible end up with a bunch of newtype wrappers, and all for the sake of being able to just print it?
  • But it already implements Display? It does. But more often than not your structs and their fields won't, so you won't be able to derive it even with helper crates like derive_more.
  • Performance-wise, it doesn't really matter. It's pretty-formatting, after all.
  • If the current debug-representation is really needed, one could add a newtype wrapper for each struct which will be accessible as e.g. struct.debug(). The chances are, it will never get used, except by the devs of this crate themselves. An alternative option, if needed for dev purposes, is having a feature flag, disabled by default, for auto-derived debug (current behaviour); but then again, would it be used at all?

I could try and help out with this if needed (although it should be pretty trivial implementation-wise).

Thanks and cheers 🖖

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-coreArea: anything not otherwise coveredC-enhancementCategory: an enhancement with existing code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions