Skip to content
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

Saving components to properties with builders? #17

Closed
thomasnield opened this issue Feb 25, 2016 · 19 comments
Closed

Saving components to properties with builders? #17

thomasnield opened this issue Feb 25, 2016 · 19 comments

Comments

@thomasnield
Copy link
Collaborator

I hope I don't sound too ignorant. I don't have much practical experience with MVC paradigms, although this library has gotten me very interested in them. I often avoided them in Swing because they felt like they added boilerplate.

But that aside, I am trying to think about how to save components to properties so I can create and combine RxJava streams off them outside the builders. Is this an acceptable pattern?

 class MyView: View() {
        override val root = VBox()

        var myButton: Button?

        init {
            with(root) {
                    myButton = button("New Entry")
            }
       }
       fun getEvents(): Observable<ActionEvent> =
            myButton?.toNodeEvents(ActionEvent.Action)
}

If so, would it add any value to create a SingleAssign property delegate so we can not only rid the null checking, but also ensure a value gets only assigned once?

class SingleAssign<T> {

    @Volatile
    private var initialized = false

    @Volatile
    private var _value: Any? = UNINITIALIZED_VALUE

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        if (!initialized)
            throw Exception("Value has not been assigned yet!")
        return _value as T
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        synchronized(this) {
            if (initialized) {
                throw Exception("Value has already been assigned!")
            }
            _value = value as T
            initialized = true
        }
    }


    private object UNINITIALIZED_VALUE
}

Then we could call it like this.

 class MyView: View() {
        override val root = VBox()

        var myButton: Button by SingleAssign()

        init {
            with(root) {
                    myButton = button("New Entry")
            }
       }
       fun getEvents(): Observable<ActionEvent> =
            myButton.toNodeEvents(ActionEvent.Action)
}
@edvin
Copy link
Owner

edvin commented Feb 25, 2016

To get rid of the null check you would declare it as lateinit var myButton: Button. That doesn't ensure you don't reassign it though, and lateinit is sadly disallowed on val. Your solution would prevent that, at the cost of synchronization.

I see the value in this, but I think the most annoying bit is the null check, and that's easily avoided. On the other hand, I can't see any harm in adding it, it's up to the user to use it :)

@thomasnield
Copy link
Collaborator Author

I did not know about lateinit modifier and you are right, that solves most of the problem. You could also make the setter private, but that could be verbose. In a multithreaded application, would you still in theory need a volatile modifier on any var property?

I'm a bit biased towards immutability and I was surprised there wasn't a feature like this already in Kotlin library.

Would you see value in making synchronized and non-synchronized versions, just like lazy()?

@edvin
Copy link
Owner

edvin commented Feb 25, 2016

You're right, and an immutable single assign property could be useful to avoid certain bugs related to builders. I think it would make sense to implement sync/non-sync in the same manner as lazy, good call. Will you give it a crack? (I won't be able to get much done before next week myself).

@thomasnield
Copy link
Collaborator Author

For sure, I'd love to.

@thomasnield
Copy link
Collaborator Author

And if you need helping document this stuff before next release please let me know. I'm a writer so I kind of like those tasks.

@edvin
Copy link
Owner

edvin commented Feb 25, 2016

Cool! I'd love some help with documentation. My english isn't all that good, so it would be a great improvement if you'd get involved there as well! I granted you collaborator access to the project now, I think you should be able to edit the wiki directly.

With each release I plan on adding documentation for all the entries in the changelog, including builder examples for all new builders, and some notes where needed, like the vbox thing on the borderpane builder etc.

If you'd give it a go, I'll be forever grateful :) In the meantime, I'll look for forum software, preferably something with github integration.

@thomasnield
Copy link
Collaborator Author

Thanks! I'll definitely help out where I can. In a warped way, I like technical writing. It relaxes me. One of my "documentation projects" without any planning became a book, so this is down my alley.

@edvin
Copy link
Owner

edvin commented Feb 25, 2016

Wow! That's so cool. That's the ultimate goal - a book for TornadoFX :) hehe

@thomasnield
Copy link
Collaborator Author

haha! Who knows we might get there, and we will be electing an animal for the cover before you know it.

@edvin
Copy link
Owner

edvin commented Feb 25, 2016

Long term plan - check! :)

@edvin
Copy link
Owner

edvin commented Feb 25, 2016

Your book looks really nice, btw. What software did you use to write it? Was it hard/expensive to get it published?

@thomasnield
Copy link
Collaborator Author

Thanks! I wrote it in Word but in hindsight I wish I used a Markdown editor. It cost me nothing other than my time and energy which was not bad since I like writing. O'Reilly picked up all the expenses and provided a great editor.

Richard Hipp (creator of SQLite) randomly reached out to me on Twitter and joined the project too, which was enormously helpful since the book uses SQLite heavily for the hands-on stuff.

I wrote the first draft as a guide to help unemployed business professionals in the Dallas area. The other volunteers insisted I publish it, and I'm really glad they talked me into it.

@edvin
Copy link
Owner

edvin commented Feb 25, 2016

Interesting... When the framework has matured a little and we have tested all concepts more thoroughly I'd like to discuss this further with you :)

@thomasnield
Copy link
Collaborator Author

Sure! I look forward to it : )

@thomasnield
Copy link
Collaborator Author

FYI, there is a very similar proposal to implement something like singleAssign() into Kotlin officially. Feel free to upvote!

@edvin
Copy link
Owner

edvin commented Mar 5, 2016

Cool :) Just voted!

@edvin
Copy link
Owner

edvin commented Mar 5, 2016

.. and saw your comment :))

@thomasnield
Copy link
Collaborator Author

I'm a sucker for product placement haha

@edvin
Copy link
Owner

edvin commented Mar 5, 2016

Haha 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants