Hacker News new | past | comments | ask | show | jobs | submit login

I like flutter and would definitely pick it if I had to make a mobile app, but if you have to write a conditional at every step to pick the right component for each platform, I don't see the point of keeping one codebase any more. You're writing code twice, and you have to test it twice, and each underlying implementation can have its own quirks. It can only get worse if you have to work with platform-specific layouts that mean your larger views have to be conditionals as well. I can understand the impulse to have one common codebase for the logic, but these days you can do that with many languages - like Kotlin or Rust - while using the native UI toolkits. If you're writing what is essentially two view layouts, you might as well write them in the native toolkit and skip the overhead of flutter altogether.



> I like flutter and would definitely pick it if I had to make a mobile app, but if you have to write a conditional at every step to pick the right component for each platform, I don't see the point of keeping one codebase any more.

I agree that wrapping every single UI widget in conditionals and writing it twice is not a good practice, but I'd still want one codebase.

Any reasonable application architecture will separate UI presentation code from application logic code. You'd still benefit from a single, shared backend to the codebase.

I managed a dual-platform software project a few years ago. I made the call to build native apps for each because our use case didn't work well with the cross-platform tools.

Writing the UI code on each platform was not difficult, but it was surprisingly challenging to make sure the application logic behaved the same on both platforms for every possible edge case. It's easy in a small app, but as complexity grows so do the edge cases. Having a shared codebase, even if the UI code had to be special-cased, wouldn't be too bad.

That said: The app in the article appears to have equivalent layouts for most screens on Mac and Windows. It seems that a single UI library could be constructed to handle both without special-casing every single thing. I'd much rather have a library that made a best-effort guess at the right thing for either platform and then add platform-specific exceptions.


We’ve build app with the business logic in Kotlin: https://kotlinlang.org/lp/mobile/


Yes! OP here, and I fully agree with your comments. Indeed, it should be trivial to make a separate package to handle picking the right UI component for each platform.

And yes, the main advantage of my approach is that I use the exact same business logic in both versions: database calls, models, settings, application behavior are shared in the codebase.


Sure, you can keep things common with one codebase, but why does that codebase have to be flutter? IMO dart is a pretty meh language, and as others have pointed out flutter doesn't even use native controls. There's tons of options for common logic in native apps these days that don't mandate a choice of view layer.


And IMO if you’re going to pick on Flutter, it’s surprising to me that you’d start with Dart. :)

I know JS is a lot better than it was 20 years ago and even half a dozen years ago, but it gave me enough PTSD over the years that compared to using JS for hybrid apps, Dart was such a breath of fresh air when I built my first Flutter app! I felt it made sense and just got out of the way so I could focus on what I wanted my app to do, and I didn’t even have to read any docs to start using it in Android Studio. And this is coming from having a lot of experience with compiled languages and a lot of Ruby in addition to JS.


Oh sure, I wanted to talk more about the "one codebase" idea - and with the state of FFI being what it is today, if you can pick anything, why pick Dart? is my thinking.

And I don't particularly hate Dart. It's fine. I've written a lot of Java so it's not much worse. But if I had free reign to choose, I'd much rather take Rust.


But for most users, do you really think they want to deal with manual memory management like with Rust? It's a UI framework not a backend performance critical one, I don't think Rust would make much sense. Dart is also compiled and gets good enough performance, at least way better than JS which is JIT not compiled to machine code.


Stateful hot reload is pretty awesome when doing UI work. On desktop that is pretty hard to find.

Also, as a TypeScript/Swift/Kotlin person, Dart is fine; sure I’d like algebraic data types but overall it is good. The tooling (auto completion etc) is great. And it has a few cool unique(ish?) features like cascade and every class is an ‘interface’.


(…Here comes the wizard of…) Just hide those system specific components behind a factory and make sure all components conform to a polymorphic API/contract.

The situation described above, abstracted, happens all the time in software. Littering the code with these system specific conditionals is a pain so encapsulate those system specific concerns in objects/components/whatever-you-call-your-lego-blocks and then use a factory to encapsulate which system specific thing you get.

The trade off is your code is a little harder to understand, but the benefit is now you can design a common ‘core’ and contain the platform specific details in bundles.

That’s ((just)) my two cents!


>> Just hide those system specific components behind a factory and make sure all components conform to a polymorphic API/contract.

But the entire point of having a "cross-platform" GUI toolkit is that you don't have to do that. This guy wrote two bits of code for a text input box which is one of the most basic GUI components there is after buttons.


>> But the entire point of having a "cross-platform" GUI toolkit is that you don't have to do that.

That's still true for flutter but it all depends on the requirements of the project. In the OP article, the point was to make something that is "native-looking" to Mac OS and Windows OS. This requirement does imply a requirement for different looking and behaving UI. Lose that requirement and then you can get the non-fractured code base back.

Perhaps you may reply "the framework should do that translation for you," to which I would respond "maybe you're right." It would be nice as a framework user to offload this type of work to the framework authors. Conversely, from the perspective of the framework authors they get to work on other features if they offload this type of work to the framework users.

I suspect the deeper questions for both framework users and authors is "who owns this work?" "what tradeoffs are users willing to make to gain this framework features?" and "what does joint ownership of this requirement look like?" Different framework communities will arrive at different answers.

At the end of the day as a pragmatic programmer you just kinda have to hack around the edges to smooth everything out for the end user.


In my projects when I need independent UI per platform I just extract the logic to a new component that renders the right thing for each platform. That way my views aren’t filled with conditionals the component handles it.


And this is why I think the goal of a cross-platform toolkit is misleading. If your language/library/compiler make it really ergonomic to conditionally target code for a platform, then you get the benefit of keeping your business logic in one place, and the pain only with testing the application.

Usually this is not the case, since interfacing with Cocoa is so different from Win32, for example. However, one shouldn't conflate that difficulty with the difficulty of testing an app across platforms.


> and you have to test it twice

Note that whatever solution you choose, you still need separate tests for every platform. Ignoring the differences between them and assuming everything is going to work the same way is a recipe for disaster.


I know modern programmers are raised to disregard design patterns because some blog said they’re dumb, but I hope nobody actually writes code like this.


OP here!

It wasn't that hard to handle the conditional logic for the UI components. It can also be encapsulated in a separate package, something that is already available for Flutter on mobile (iOS and Android UI): https://github.com/stryder-dev/flutter_platform_widgets

I could also not strive to make it look native, but go with the default UI (Google's Material UI). As I explained in the post, I decided to take some extra steps and use the two UI packages (macos_ui and fluent_ui), to make it adapt to the platform.

Please bear in mind that I am a single developer, with ~1 year of working with Flutter and Dart, and my main background is web development. I think that teams with more members and experience can certainly do this for even larger in scope apps.


We find that most developers want their apps to look and feel the same on multiple platforms, with some relatively minor tweaks. Flutter itself handles many platform specifics automatically, e.g. scrolling physics, adding scrollbars, button press effects, etc.


You write components at the lowest levels with the if/then, or maybe at the page level if the pages are completely different, but many of your UIs are going to share the same code.


I think you would end up writing applications that look native, but not behave in a native way at all. We have a lot of those already. Just some thoughts:

- for an application that modifies files (e.g. a text editor), are changes applied to the file immediately or is there a separate "save" action? Platforms differ on this. Basically your internal data handling becomes platform-dependent.

- define a set of keyboard shortcuts that is consistent and intuitive, but plays well with the platform's shortcuts. You'll basically define a separate set of shortcuts per platform.

- whenever functionality overlaps with existing native applications, cooperate with them instead of duplicating their functionality (especially in an incompatible way)


> I like flutter and would definitely pick it if I had to make a mobile app, but if you have to write a conditional at every step to pick the right component for each platform

Looking at the examples given, perhaps it would be relatively trivial to wrap both these libraries into a single one where the library does the if statements for you.


Yes, that's certainly possible. It is also done for iOS and Android (Cupertino and Material) by another package: https://github.com/stryder-dev/flutter_platform_widgets

It indeed can be extended to do a similar job for macOS and Windows (or Linux).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: