Open dodexahedron opened 10 months ago
I'm not smart enough yet to really grok all of this.
I'm also not confident in our Pos/Dim/SetRelativeLayout/LayoutSubviews unit test coverage.
Therefore, my vote is "Go for it! But before you do, we must significantly up our unit test game in this area."
Also, wait until I get Dim.Auto
done so I'm not working on a moving target. https://github.com/gui-cs/Terminal.Gui/pull/3062
In my work on Dim.Auto
so far I have found several places where I don't think anyone understood the codebase. I found several cases that were clearly broken, but nobody noticed (e.g. Pos.Center() + Pos.Absolute()
)). There's another dragon lurking that I have a bad feeling about having to do with Dim.Fill
and Pos.Center
...
I'd be happy to work on some TDD for those types, once I'm finished with the work I'm doing with TerminalGuiDesigner's test project.
They're pretty critical core classes, so I wholeheartedly agree they should be tested excessively. :)
I imagine the work on the TerminalGuiDesigner test project will probably take me another week or two, if I'm able to keep up my current pace.
See
It makes progress on cleaning up these classes.
Now that #3480 is merged and #3415 is almost ready, it would be awesome if this Issue were updated with a clear list of the remaining issues you have related to all this.
Yeah I actually think this one is basically obsolete, as some things have changed over time.
The fundamental thoughts are still more or less the same, but this was originally intended to be more of a discussion and brainstorming prompt than anything.
For actual work, smaller bite-sized pieces like the interface issue draft I started are more my intent for this. Although that one isn't exactly tiny either. But it's still not really terribly complex - especially if I whiteboard it out to better visualize stuff.
I may actually shift to that stuff for tomorrow, since EV validation for the new org code signing cert is going to take a bit of time and then the physical usb token/essentially smart card (FIPS 140-3...woooo... 🙄) is sent by FedEx ground from Ontario to Arizona once that's all done. So I won't be publishing refactored NuGet packages for a few more days, still, at least, while I'm waiting on that.
What follows is all related to Pos and Dim, but are more like ideas and discussion prompts. None of these things are bugs, but rather are design details that I think are worth considering. Some are based on C# design guidelines, and some are more opinionated, based on my experience with TG and TGD from primarily the consumer side, but also the maintainer side.
Soooo let's begin with a whopper!
readonly record struct
would be immutable and have implicit value equality of all members auto-generated by the compiler.struct
, and I didn't say anything then because I wanted to check myself first, but what is the actual concern there?struct
s are still just another kind ofType
and can be reflected on like anything else. Properties, fields, methods, attributes - you name it - it's all there, just as with a reference type.object
. The reflection methods are all going to returnobject
anyway, so this isn't even a hit to performance. Boxing it yourself makes the compiler grab it and deal with it like you're used to dealing with any other boxed value type. Ideally, if there's a public interface defined that the struct implements, you can even just cast it to that once you have the struct, and just interact with it strongly-typed from there (just as you would with a reference type).record struct
s[^1], you are able to use thewith
operator for non-destructive mutation, when needed. That syntax is hella nice and is nearly identical to regular object initializers. The difference is the compiler generates the copy constructor for you (by-value copy constructor), and thewith
statement lets you change as many or as few properties as you like, including just an empty block (myRecordStructInstance with {}
) which is just a straight-up copy.A structural thing, but from a more pragmatic view of current implementation, where benefits can be realized with surprisingly little actual work:
And, as an even less impactful change/thought (which I've also tried out):
abstract
keywords on them.new Pos()
can't be cast to the other types, because it's the base and covariance doesn't work that way without generics, which aren't relevant here.abstract
? Very! Simply addingabstract
to thePos
class required no other changes to the code to build and pass all tests (aside from the 2 that just call the constructor and nothing else).Anchor
beabstract
instead of justvirtual
, to force descendants to implement it, caused no issues, and proved to me that Pos.Anchor always yielding zero isn't actually a problem because it never happens and can't ever happen anyway. Plus, it's internal, so users can't call it without reflecting anyway, so it's a prime candidate for refactor.And then going beyond TG itself, into tools that consume it and generate code using it, such as TGD:
Alignment
enums (which are essentially analogous to a combination of what XCenter, XAnchor, and other similar types in TG do)record structs
are mutable by default for some reason I can't fathom, unless you declare them asreadonly record struct
) [^3]: Plus details such as type and member visibility, which would either need broader exposure or (less ideally) require proxy/wrapper types to fake everything via reflection and other runtime trickery against Terminal.Gui under the hood or even not using Terminal.Gui at all until the actual creation of syntax trees and such for C# code generation. Obviously I'd much rather duplicate as little effort as possible, especially since this project represents years of several people's fantastic hard work.