Categories
程式開發

我为什么放弃移动开发


当我还在上大学的时候,Android和iOS还是新兴的平台,每个人都对这两项技术很感兴趣。如果你参加一些当时的编程研讨会,最后总会写一个小型的Android应用。这就是我向Android生态系统迈出的第一步,也可能是我随后成为了一名移动开发者的原因。

在这篇文章中,我想要分享我关于Android SDK和Flutter的糟糕体验。我提到的某些要点也适用于iOS SDK。我已经在几年前放弃了移动开发的工作,希望后来许多事情已经在朝好的方向改进。但在当时,我发现移动生态系统是如此的令人感到困惑和挫败,以至于我选择了一条不同的职业路径。

本文由原作者发表在medium.com,经原作者授权由InfoQ中文站翻译并分享

我为什么放弃移动开发 1

设备的碎片化

对开发者而言,Android开发的最大痛点,就是设备配置的巨大差异。我一直都未能理解为什么SDK中大部分功能(尤其是用户交互界面的部分)取决于设备,而不是我的应用。这从根本上导致我必须使用支持库,针对每个目标API级别调试我的应用。除此之外,我还经常遇到在仿真器或者测试设备上好好的代码,却在某个三星或者华为的设备上崩溃的情况。

质感设计(Material Design)

当我在HackerNews或者Reddit上读到关于谷歌的Material Design的评论时,某些时刻会感到我是唯一真正喜欢它的人。我觉得它在视觉上很具吸引力,我通常很享受这样的用户体验。官方的文档网站发展得很快,也非常成功,我觉得这是优秀文档的典范。当它被宣布用于Android时,我感到非常兴奋!

话虽如此,在Android平台上从Holo过渡到Material Design并非一帆风顺。因为它好像是被急匆匆发布出来似的。在接下来的几年之中,官方的Material Design支持库一直缺少一些非常基本的组件。虽然你有时可以在谷歌自有的应用上看到这些组件,但是它们并没有真正被纳入到支持库中。开发者不得不构建自己的组件,或者使用GitHub上质量无法保证的实现作为替代品。这次使用Material Design支持库的经历,再加上大量的不一致的视觉设计和实现错误,让我第一次停下来真正地思考和质疑这个生态系统。

我为什么放弃移动开发 2

无人理会的最佳实践

构建一个可靠的Android应用,是一项充满挑战的任务。这主要是因为SDK对开发者并不友好。理论上,一个Android应用程序可以永远挂在后台不使用任何系统资源,然后在用户需要时立即回到先前的状态,这实在是令人惊讶。不过前提是开发者正确地实现了这个应用的状态和生命周期管理机制。

开发者:你好,互联网!我的应用在改变屏幕方向时崩溃了,该如何解决?
互联网:这很简单!禁止改变屏幕方向即可。

——啊哦,不幸的是,这种回复很普遍。

你是否曾经使用过Java中的线程(Threads)?在可变变量随处可见的的命令式代码库中,这件事变得非常困难。但你猜怎么着?在Android SDK中使用线程更加困难。如果你想要在一个Activity中管理Thread,那你就只能自求多福了。幸运的是,我们最终保留了Fragments,这最终让这件事变得容易了一些。但代价是在一开始就需要使用Fragments。

在我作为一名移动开发者的职业生涯中,我面试了一些高级Android开发者。他们几乎无一例外,都很难给出这些话题的正确答案。

我一直希望谷歌能更坦然地承认这些问题,并且和社区一起解决。这些问题可能随着Kotlin的发布有所改善,但Android生态系统的根基仍然存在很多潜在的问题。

无效的设计模式和对抽象的注解(Annotation)

开发者很快就意识到,在Android SDK提供的抽象之上,构建一个真实世界的应用是不可能的。对此的解决方案是层出不穷的设计模式,甚至每周可能都会出现新的设计模式,我记得的包括:MVC、MVP、MVVM和MVI。而且由于无法使用普通的构造函数调用来管理依赖项,我们不得不在代码库的每个地方使用注解。这些本来并没有必要。Java,甚至Kotlin,本来就有足够的能力可以对这些东西建模,更何况是以一种透明而直接的方式。但Android更喜欢XML定义和反射式实例化,因此开发者不得不在代码中使用注解和各种设计模式。实话实说,我真的无法形容这到底有多麻烦。

从未利用过的平台优势

在某种程度上,原生iOS和Android开发都是作为平台在与网页端竞争。但iOS和Android拥有只属于一家企业的巨大的平台优势,相比之下,网页端有许多利益相关者,这些利益相关者都想要根据他们的需要来影响网页端的开发。

然而,网页端拥有更加活跃和创新的生态系统。只需要想想React的成功故事:基于组件的用户界面,是我们目前提出的最简洁的抽象方法,这是无可否认的。多年以来,Android并不理会这一趋势,直到最近才宣布推出“Jetpack Compose”,但是这仍然仅支持在开发者预览模式下使用。同样的事情也出现在iOS开发中。

所以,现状是我们仍然需要继承android.view.View类,这个类有1.5万行代码,和数十个生命周期函数,但同时我们还要尝试注入自己的merge XML文件。iOS和Android本来可以成为这个竞争中的引领者,但实际上,它们已经被远远甩在了后面。

请不要对UI开发抱以希望

一个精美的应用的关键在于用户界面(UI)。我在上文已经吐槽了不少关于组件的问题,但这些还不是最严重的。你是否曾经调试过网站上的故障?通常的操作是:打开浏览器的开发工具,点击有问题的元素,然后使用CSS和HTML的属性来调试。与此相比,Android是一个无法访问的黑盒。老实说,我一直没有完全理解Android的主题和样式机制,并且与Web相比,Android的工具显得毫无用处。

想要在这个框周围添加阴影吗?没问题,请使用这个奇怪的.9.png文件,或者依靠API Level 21,你就可以正确渲染阴影了(尽管只有凸形阴影)。
不好意思,你忘记实现自定义视图四个构造函数的其中一个了。但我不会抛出编译错误,我只会在运行时崩溃!
现在有支持超高屏幕密度的手机了。可以在应用里添加 xxxhpi的assets吗?不行,不支持矢量图,我们做不了这个。
——来自Android SDK的深夜独白

矢量图

在Android 21(5.0)之前,Android平台根本不支持正确的矢量图。这背后的原因是,多样的Android设备导致了多种不同的屏幕密度,这要求图像针对每种屏幕密度都做仔细的调整。务实的开发者自然而然地开发了转换矢量图的工具,将logo.svg转换成ldpi/logo.png,mdpi/logo.png,hdpi/logo.png,xhdpi/logo.png,xxhdpi/logo.png以及xxxhdpi/logo.png。幸运的是,最终谷歌改变了它们的想法,并提供了VectorDrawble来支持部分可缩放矢量图形(SVG)。的确,这足够减轻当时的痛苦。但仍然令我困惑的是,一个以能够在任何设备配置上运行为优势的开发环境,是如何在这么长时间都不支持矢量图的情况下活下来的?

死局

这些年,我开始越来越担心我的知识会在不远的将来过时。我学到的大多数知识都是Android开发所特有的,很少适用于更广泛的软件开发领域。考虑到这些方面,我不认为原生的移动开发会一直存在,所以我开始担心所学到的技能的实用性。

Flutter

当Flutter发布时,我非常激动。它承诺将解决一些主要的Android SDK的缺陷,同时无偿提供跨平台支持。所以在我上一份工作中,我们开始从原生Android迁移到Flutter上。我必须承认,Flutter信守了它的承诺:

  • Flutter内置的渲染流水线完全解决了Android的碎片化问题。
  • 从一开始,它就提供了详尽的高质量的Material Design组件库。
  • 热重载功能的灵活性完全颠覆了我的认知。
  • 你能获得前所未有的高质量界面外观的跨平台体验。

但不幸的是,它也不完美。而且有点可惜的是,Flutter遇到的问题本可以通过一个全新的项目轻松避免。

  • Dart很糟糕:它还是一门相对年轻的语言,但它重蹈了不少它的前辈的覆辙(错误的类型系统,Null,使用语句而不是表达式,等等)。
  • Flutter SDK中让人不解的设计决策:它们本应创造一个更好的React,但却创造了一个更糟糕的。本可以通过简单的函数调用解决的问题,往往需要通过有状态的面向对象编程(OOP)机制才能解决。(我记得对话框的路由和处理在这个方面尤为痛苦)

结论

在某一时刻,我清楚的意识到,我不想在这种技术上倾注心血了。我向自己许诺,绝不再在移动平台上编程。一个设计精美的、响应式的网站在今天已经可以给你足够好的体验,所以这是我的不二之选。只需要一个代码库,它就能适用于每个客户端。如果我还是不得不构建一个移动应用程序,我仍然会选择Flutter,甚至是在我仅针对Android的情况下。我绝对不会再使用Android SDK。

话虽如此,但要澄清一点,我还是非常喜爱和欣赏精心制作的原生应用的(无论是在移动设备上还是桌面上)。我对那些使用现有工具就能创建出这样的应用的开发者,致以崇高的敬意。只是,我不想再成为他们中的一员。

原文链接:

9 reasons why I gave up on being a Mobile Developer