This is what I mean when I say that compose has de...
# compose
j
This is what I mean when I say that compose has design flaws. Notice how the same code, moved up causes errors from nowhere. If anyone knows of a way to fix this lmk please
r
The errors are from not nowhere. You are calling method from the wrong scope ("align()") and referencing a variable that's not in scope ("song addition")
Modifier.align() exists in a ColumnScope in your render() function, and you don't have a ColumnScope in renderTextfield()
c
I would argue this is the opposite of a design flaw. This is intentional API design. It offers strongly typed APIs that prevent you from calling the wrong modifiers
👍 2
☝️ 2
☝🏻 1
☝🏾 1
👍🏾 1
p
Unlike xml view properties, modifiers are extension functions of Modifier but available under certain scope only. Isn't like xml where you could have an
orientation
property defined in a FrameLayout, when it really is just meant to the LinearLayout. Compose gives you that kind of protection
j
Well this design just cost me a lot of reusability. This is one of many times where the functional design or these scopes have made it harder to genericize code.
🚫 1
r
The way to do this is to add a Modifier parameter to your Composable and create the alignment at the call site where you have the right scope
(which I would argue is more generic)
j
Well ideally I would be able to just extend this object with the fields I want... but since its a function I have to manually redefine the fields if I want to make it generic like that. Either way we have repeated code (I wonder if kotlin should get syntatic shorthand to "extend" functions... would be cool)
r
By fields you mean songAddition for instance? If so, just pass it as a parameter
(or better yet, pass only the data needed, in your case the name string)
j
I mean like I would have to ask for a Modifier. In this case its not that bad but there have been times where I would need to ask for like 20 things
r
Composables can also be instance methods if you really want. They can access more than just their own parameters
But if you need to access so many parameters it might also be an indicator that you need to rethink the design of that Composable (or pack data in models/state objects)
j
I mean if you are making your own TextField for example where lets just say you want to simply want to have a very specific border, but want to use it everywhere in your app, you have to now basically ask for ALL the parameters in the TextField. I dont see a design problem in this as its supposed to be a generic TextField component but you have to make this super long header to do it when really this is the type of stuff that inheritance and other oop fundementals were built for
a
Except that Compose is much closer to functional programming than object-oriented. Functions cannot be inherited, so you can't "override" TextField to change only some behaviour, while also expecting the code to stay slim ("I only want to change border, nothing else, why must I pass everything else in?"). Each function has one specific task, and that's it. They're immutable; can't be changed after the fact. It's a different paradigm that requires adapting how you approach the problem. And it's not some unique thing in the frontend space. When you compare it with SwiftUI, or even React, you'll find many similarities.
In Compose you're frustrated about needing to include more parameters than you needed to change, yet here's the kicker: in the OOP world, you can encapsulate and inherit and polymorph your way around things, but what you're really doing is just splitting code density across multiple different classes. In fact, I'd argue there's more boilerplate with OOP.
h
Regarding the textfield issue. What you need to do is to create a wrapper function, let’s say AppTextField, which internally will only call the TextField adding your border. And whenever you need to use it, you just call your AppTextField. Now, regarding the problem in your picture, there are various things you are not taking into account. 1. Composable functions should start with an uppercase when they don’t return anything. Because it is like “constructing a TextField on the UI”, so the “render” prefix is inappropriate too. 2.
songAddition
is declared within the
render
method, why do you expect it to be available in the
renderTextField
method? That is not possible even in OOP. 3. Continuing from that, you are violating one of the principles of compose, which is state hoisting. It means you should leverage onStateChange listeners to the top place where your uiState is declared. Usually it will be in the ViewModel, which you will inject into a Composable root function. 4. To solve the problem with the align, you have two options: a. Declare the
renderTextField
function as an extension:
ColumnScope.renderTextField
which will allow you to use align but you will only be able to call the function within a ColumnScope. b. Directly receive a Modifier as the first parameter and set the align from the
render
function when you call
renderTextField
. This is the recommended way as it allows for easier reusability and customization Good luck, let. me know if you have any question
j
yes songAddition would be passed into the method, I was referring mostly to the modifier errors and the like. I dont have onstatechange listeners but those look helpful for eliminating some update code I have, Ill look into them. My problem is that I lack almost all of the OOP tools to hide these declarations. Its like the framework was designed to NOT allow OOP. React does not have this problem as it is based on a component model and has props inheratance
r
OOP is not disallowed. Composables can be methods on interfaces/classes
plus one 2
p
OOP has proven to fail in big software system design. Or more specific
inheritance
not all oop principles.
h
The problem is not OOP per sé but the devs that use it poorly
👍 2
💯 1
j
Inheritance is only bad when overused. In limited cases it is useful to extend classes... like UIs. On the other hand, other parts of OOP like polymorphism, and abstraction are invaluable to many code bases. Thats why i like kotlin so much, its best of both worlds
👍 1
💯 1