Proposal: Feature - AbstractViewOwner#9
Conversation
|
This code is dumb, I totally forgot you can't call super two levels up, so this exact example doesn't work, but I'm leaving it because you still get the gist of what I'm looking at here. |
|
Okay, better version now, this makes more sense for my explanation, I'd actually also be happy if this was the final solution, works for me. |
|
I think you make a good point, but most of my ViewOwner implementations don't implement all of the fundamental methods (create/init/reset/respond). The createUI() method, in particular, is almost never implemented since the common case is to put the XML in the MyViewOwner.snp file which will be loaded automatically with the default createUI() method. The initUI() method is regularly not needed if the UI is straight forward. It is mostly needed to configure things that aren't covered by the XML. I've even had a few cases where one of the resetUI()/respondUI() methods isn't implemented, though this is rare. Might happen if the UI is read-only (no respond method needed). Or if the UI only has buttons in it (no reset needed). |
Yeah, this is one of the thoughts I was having as well. This would be one of the advantages to having the Another way I didn't think about until later was, could also make the other methods final, but I think relying on final is one of those things that can get you stuck in a hole and have people unable to use things for a purpose different than what was first thought. There have been a couple other projects running similar init, loop, react type models, such as JMonkeyEngine. In their particular case, they implemented everything in a "Simple" class, and then have you override what is necessary, but that requires you to fully understand the library before you learn it. It takes time for that knowledge to sink in, and it's easy to forget if you spend some time away. Especially when there are lots of other methods in the same class that you have to check out. That's why I was leaning towards the extension class, since you can always downgrade it back to the parent once you are more confident/ once you have implemented what is necessary. It also therefore doesn't break any existing or future workflows.It's what I'm running with right now, since I keep forgetting the method names of the stages. It might be making more work about nothing, but this is one of those things that I found quite helpful on my own, knowing what I am supposed/allowed to change, and what I should leave alone. Especially during the learning stage, being able to stay in the code editor and not switch out all the time is nice. I should say though, not heartbroken if you don't want it. I can just as easily add it as a class in my own project, just thought it might be nice to help people get a handle on this library faster. |
821dc85 to
4dc5c5c
Compare
…methods are the essential ones. Documentation change. Provided an actually usable implementation of the idea, complete with default methods that reference the original ViewOwner. @APinote is not supported by Gradle Javadoc plugin. Added a CustomViewOwner class that makes ViewOwner controls explicit. Otherwise harmonious with existing ViewOwner.
4dc5c5c to
a267667
Compare
|
Squashed commits. |
|
I agree with your point on this - and I like the new name, CustomViewOwner, but I would still like to hold off on this until there are more users to debate the issue. In the early years I added a lot of functionality for the sake of convenience, but in recent years I've been trying to reverse course with a "Less is more" strategy. Everything that is added has to be documented, explained and maintained. Which makes it that much harder to walk back if it's wrong. I did take a quick look at ViewOwner last week - I think there's a few more methods that could go away to further simplify it. Like you suggest, I tend to keep a "utils" package or classes to hold my mods to any major framework I use. The test is when those mods show up in almost every project then it's time to add it. I hate to do anything discouraging - because as you can see, I'm lucky to have you taking such a strong interest. I'm not sure what is the secret to encourage adoption. I probably need to really start cranking out docs, demos and tutorials. Or "we need"? 😀 |
|
Don't worry, I'm quite vocal (and verbose), but it is your project at the end of the day. As long as you are okay if I pipe up frequently with whatever crosses the desk, then I'm good if not everything actually passes. I find that features get better out in the open with a good and healthy discussion, and such discussion sometimes means that things don't get through.
When I started looking at the library, I immediately noticed the difficulty in getting started. While the views are build-able through the SnapBuilder application, it is very buggy and has some non-intuitive controls (can't hit delete to delete something, and had a hard time figuring out how to get elements to sit in the right place), and can only build simple views, it has no support for adding menu bars or any other fancy parts. Were it not for your other examples on your site, I'd have thought it was a "idealist" project and nothing more. When I did actually start jumping into the code, with my existing Swing knowledge, I immediately started to love the project. Having a border layout have dedicated methods to assign each part was fantastic, and is how I feel Swing should have been worked in the first place. And once I had enough feel for it (although I'm still in that learning stage now) I get your vision, and I was able to use the xml view files on my own. The important thing to note I think is that some of the big features of this project, like the snp files instead of code for views, isn't actually obvious why a new user should care at first. You've done a fair job of explaining the benefits already "The best line of code is the one you didn't have to write", but maybe a descriptor of the xml format would be a good idea as well. Once you've created some views, its easy to see how to extend it (One of my tests was to add a separator that I found in the code, and to see it just appear on the view in ViewBuilder when I added a line to the snp file was simply amazing). That system alone is something I am hoping to pull into other projects of mine in the future, as you've made a very nice and serializable format for a Swing-like UI that would be usable in many projects (in my case, looking at something like server provided arbitrary UIs for a game). Once I understood this feature, I absolutely swapped my focus, and now I'm also trying to use the snp files most of the time... they are also easier to write/edit by hand than the usual Swing code. All of this to say, there is a documentation bubble in some places, and there would be a benefit to covering these areas. But I also wouldn't want to see hefty manuals that are so dry that you can't get through them. I'm reading through the PostgreSQL manual right now, and it is so painful; I feel like I'm reading a bad textbook at university again. I personally am generally a "Read the ReadMe and the 'Get Started' page, then try to work exclusively in code until you get actually stuck" type of coder. For me, the Javadoc and code comments inside my IDE are much more useful (thankfully, you have actually done a pretty good job in this area) than general documentation outside of the library jars. I am a big fan of abstract methods and interfaces that tell me exactly what the code wants me to do, rather than having to try and scry the answer from the ether like an 11th century astrologer. Having code that actually fits together jigsaw like is so much easier to assemble than something that does it all for me, but doesn't actually tell me what to do without studying the docs and reading every line of the source code. That said, no one likes AbstractAbstractBeanInterfaceHandler, myself included. But a service that includes the "instructions" alongside the default implementation is my dream. I have said a lot (sorry for making you read so much), but probably the biggest reason why the project is not more popular is the licensing. Lots of people won't touch GPL 3 due to the viral conditioning. I am actually usually included amongst those people, but I read your responses on all of your projects in regards to the licensing and decided that I trust your word in regards to the " I would like it to be free for anyone who needs it to be free"... 'but would still like to get paid', and I get the spirit of what you are trying to accomplish. People will use even broken MIT or Apache licensed projects because they don't have to worry about that future day when they want to release it to their first customer/client/whatever, and then they have to release the entire project they've been working on as GPL 3. Both Swing and JavaFX are GPL2 with classpath extension, so while their changed code must be contributed, they don't infect the project. With those choices, most people would choose to pick one of the two more mature projects with more open licensing. In this era too, it is common to encounter a much used library where the contributors are no longer around (for whatever reason). In such cases, even if they said they were willing to do something, since they are no longer around, they cannot do that something, and you are stuck with the project and its terms as is (and if you hit it big and disregarded the license, there is always the chance of heirs or the person returning and issuing a lawsuit over the 'misuse' of the code, even if the context seemed permissive). That said, I don't think you need to change the license at this time, as I do think your current terms are reasonable, and you have stated that you will provide what is needed should it be requested (and you are still here working on it 7 years later). I think if we polish the on-ramping a bit, that might be enough to sway some others over. I know I already am really liking this library, even though it has some caveats/ bugs.
One moment of confusion that I had was "GetUI() is the method I'm supposed to override right?", and there's not really anything in the code saying that that isn't the case, except by omission in the getting started docs. When relying on overriding as the method of implementation, you also require the user to know exactly what every component does, which a new user simply won't. This was the main part of the having an abstract class, which is then extended by the current ViewOwner class. An example from my workplace is we have a utility that loads a series of jobs. The In that same example, we have another base class that extends that class to add some specific functionality for a specific purpose, and to make any new task easier for that narrower scope. This one is almost entirely implemented, because its terms are narrower. You still could override the main runner if you wanted to/knew exactly what you wanted, but for the newcomer or simple use case, you can just use the extended functionality that that class provides as is. This is the biggest stumbling block with this project as a newcomer code wise for me. I feel like we have the second part in One of the easiest ways I found to learn a system in Java was to create a Lambda (or just create a "new" whatever), see what methods the base class needed to implement, and then check one of the children and how they handled it/ what they left unhandled for the end user. There just isn't something like this for the ViewOwner class as it is right now, and I wonder if that is a contributing factor to any new-comers. A whole lot of blabber in this comment, I'll try to shorten it up in later ones, but I think that about says what I wanted to say. Regarding this issue specifically, I am absolutely okay for it to sit on the scales for a while, it is just one possible solution among many, and I'm still running through things seeing what there is to see. We might come up with a much better idea later. |
|
Thanks for taking the time to write all that - I really appreciate the engagement. I have a tremendous amount of fun with SnapKit and it is rewarding, but also lonely. 😀 Re: 'it is your project at the end of the day': I'd desperately like for SnapKit to be popular enough that this is not the case. 😀 Re: SnapBuilder is buggy: So true - I hate to admit how much that thing is slapped together. It's a load of fun and could almost be a stand-alone project/product - but, it could also easily be someone's full-time job. SnapKit itself has a dozen areas that could be full-time jobs: Components, painting, layout, text, 3D, parsing, serialization, gamekit, etc. And then there's SnapCode - so much work for one developer. I've spread myself stupidly thin. Re: "The best line of code is the one you didn't have to write": I totally stole this from my first employer, NeXT. Once you learn the InterfaceBuilder religion, there is no going back. Re: getUI(): Now there's a method that should maybe be declared final! I don't think there's any way around the idea that ViewOwner requires the developer to attend a 1 hour tutorial. It's just so fundamental and functional. I sometimes wish it was called ViewController - because it really is the C in MVC. Re: License: I really just tried to kick that can down the road to someone who knew what they were doing. I don't think SnapKit can be successful and sustainable without some kind of funding, but I've talked to a few large companies in the past about ReportMill and other past products, and I would hate for one of them to show up and say, "We like your stuff and our reading of the license says we can just take it". And I've had large companies say stuff like that to me before. |
You've made a pretty nifty project, and sure it's a little rough in some spots, but I do think you've got something going here. I love Java, and I don't like how its becoming only for web app backends. I'm only using the library as an excuse in a single project right now, but I have a couple of thoughts of things I would like to help extend in the future once I get there. There is no reason Java can't be utilized in more things.
That was something I was wondering about too, especially since you do have that part about how View is the V in MVC. It might honestly be worth refactoring, because I do think ViewController is more clear about how it operates than ViewOwner.
I think I agree. I don't like things being final in general, we don't know how someone else will use the tools we make... but I think essential working stuff like that makes total sense to declare final.
I had a feeling that you might have had an interaction like that at some point. And it absolutely is the direction that a lot of corporations go when faced with that sort of choice. I do think you are okay for right now, the only word of warning I will give is that, as contributors are added to the project, it becomes harder and harder to change the license. Legally (Insofar as the US is concerned, this is a complex topic globally, and I am also not an American) each contributor owns copy-rights to their contributions, meaning that if they contribute code that is GPL3 to the project, the project can't be swapped without removing their code (without their permission, and in some jurisdictions that permission is a signed contract. The waters are kind of messy, the big Linux GPL 2 lawsuit that is going on right now will probably add some clarity to the situation in time). No worries from me on that front, insofar as I am concerned, this is still your project, I'm happy with just the attribution as a contributor. Still feel that I should give the word of warning... but as you mentioned, scarcely little outside contributions to this project, so I don't think it is a worry right now haha. |
My only problem with Controller is that it (weirdly) bothers me that the word is so long. To make matters worse, I usually name my ViewOwner subclasses with the suffix "Pane" or "Panel", depending on whether the block of UI is just a pane in a larger UI window (e.g., UserAccountPane, SettingsPane), or whether it is available to use as a stand-alone panel, like ColorPanel or FontPanel. |
The variable naming makes total sense, pane and panel are standard labels for such components. The The length argument is a fair one, although I'd still be in favour of a refactor. Owner works fine, but Controller is precise. But it is splitting hairs over a name, which is silly, so I am good either way on that one. (Especially since there isn't a namespace for |
This pull request is an request for discussion.
I would like something similar to this in the project to assist with on-boarding people who are not familiar with the format (including myself). Right now the ViewOwner class is difficult to tell which methods are meant to be overridden, and which ones are not, at a glance. The starting out wiki page helps with this, but the API contract should reflect this as well.
I can see several different ways that it could be done.
ViewOwnerintoAbstractViewOwner, make the major methods abstract there, and then provide default implementations inViewOwnerclass (orDefaultViewOwneror something). The pluses with this way is that all existing code would continue to work, but that most references toViewOwnershould be refactored toAbstractViewOwnerViewOwnerand make the modifiable methods abstract in that class. This is what I have done in the provided code, but I would recommend a different classname, becauseAbstractViewOwnerimplies that it is the parent ofViewOwner, rather than the other way around. This way requires no refactoring at all, but would have your documentation directed towards this new abstract class, rather thanViewOwnerdirectly. It also goes against common convention, but isn't a big deal because it doesn't break anything.1.i.in the previous statement for the end user.I have no hard demands one way or another, but this was something that got me a little stumped at the start, and if it wasn't for the how-to-guide, I would not have been able to guess this from the code. I personally would prefer that the main ViewOwner class was abstract (especially since this library expects you to extend it), but that default implementations were available in a default class or method. That said, the code example I've provided works as is with no changes required, but it doesn't match the Java pattern very well. Give it a different name and it might be totally fine though.
Let me know what you think, these are just some starter ideas I came up with, but so long as there is an easy way to determine the API expectations, I'm all for it.