Android架构:第一部分-每个新的开始都很艰难 (译)

本系列文章的目标是概述我们与Android应用程序体系结构(Android体系结构)的斗争。 我意识到,无论Android应用程序架构的实施可能会如此痛苦,事实证明,这是我一直在努力的每一个优秀应用程序的基础。

每项技术都有其自然演变。 或者更准确地说,它的社区经历了进化过程。 早期采用新计算机语言或框架的用户只是希望掌握技术并尽快完成一些工作。 通常情况下,新社区很小,开发人员之间知识转移的潜力有限,也就是说,由于没有可用的架构指导原则,每个人都从自己的错误中学习。

Android architecture part 1

早期的Android并不例外。 这对开发人员来说既酷又有吸引力,它为早期采用者成为围绕这一快速发展技术的社区的一部分提供了机会。

早期Android时代的痛点:谷歌是否关心?

你可以争辩说,那里有许多资深人士,他们拥有很多不同技术的经验,并且很快就会提出标准。 嗯,不一定。 如果这个技术背后有一个强大的公司可以赚钱,他们肯定会有自己的技术传播者,他们会传播关于这种新语言如何酷的文字,并且可以用它做很多事情,这很容易学习,扩展并满足数百万客户的需求。

微软经常用它的技术做到这一点。 另一方面,当谷歌购买Android时,我诚实地认为他们将其视为一些其他方面的项目。 如果您从一开始就一直处于Android世界,那么您必须记住Google根本不关心您的挫折感和感受。 那些拥有更多经验,能力和帮助社区的意愿的家伙现在已经成为Android超级巨星或者小半神 - 例如Jake Wharton。

“When Google bought Android, I honestly think they treated it just as some other side project.”

xamvxi

你可以说的另一件事是你不必考虑很多关于代码的架构和组织,因为框架为你做了。 Android强制你将你的屏幕显示放入Activities中,将可重复使用的屏幕材料分解成Fragments,并将后台的东西放入Services中,并使用Broadcast Receivers与其他人交谈,因此它使您的生活变得更加美好。 对? 没有

首先,不管技术如何,都有一些很好的做法和原则。 例如单一责任原则或依赖倒置原则,面向接口编程,杀死全局状态,试图谋杀所有状态等等。

框架很少迫使你遵循原则。 相反,他们以最糟糕的方式违反了原则。 想想Context,你必须在任何地方使用的上帝对象,各种单例,Fragments的生命周期(那是噩梦般的生活),AsyncTasks通常被错误地实现,所以他们吸食记忆,食物,水 ,并从您的APP中散发出来。

对于没有指南的年轻开发人员来说,制造怪物比制造APP简单。 把它想象成一个意大利面般黑洞般的怪物-它作为一个Pastafarian神只是一个很好的选择,但作为APP并不好。

android architecture spagetti monster

最后,技术和框架隐藏了APP的目的。 好的,这是一个Android应用程序,但是什么样的Android应用程序? 新闻阅读器? 音乐播放器? 语言学习应用程序? 天气应用? 也许这是另一个待办事项清单应用程序。 如果所有的东西都捆绑在框架提供的类中,那么你会说不清楚。

正如Robert Martin, aka Uncle Bob所说:“Your architecture should scream the purpose of the app.”更技术性地说,业务逻辑应该明确分开,并且独立于框架。

Android架构的四大黄金规则(或任何架构)

我希望现在很清楚,您不能依赖框架来使您的代码整齐有序,特别是在Android里。 在FIve里,我们很早就意识到这一点,但缺乏立即提出核心的经验。 失败真正显示出来需要很长时间,并且在项目中间无法更改整个架构。 你也无法花时间将旧项目重构为新的酷炫的梦寐以求的最佳架构。 所以,我们采取了渐进式的方法,逐渐从项目到项目逐步构建我们的架构,并从错误中学习。 我们认为我们的架构应该满足几个目标,我们可以将我们的方法与这些目标进行比较。 良好的架构应该做到以下几点:

  1. Satisfy a multitude of stakeholders.(满足各方利益者)
  2. Encourage separation of concerns.(鼓励的关注点分离)
  3. Run away from the real world (Android, DB, Internet…).
  4. Enable your components to be testable.(使您的组件成为可测试的)

I. Satisfy a multitude of stakeholders.(满足各方利益者)

Stakeholder(在这篇文章中)是任何对你的APP感兴趣的人。 除开发者外,还有UI设计师,UX设计师,PM,DB管理员,QA等。

当然,你不能以某种方式组织代码,例如,UX设计人员可以立即打开项目并理解所有内容,甚至可以进行一些更改。 这是一个独角兽。

Android Architecture stakeholders

我的意思是,你可以组织你的代码,使得当前与UX设计师一起工作的开发人员只能管理与UX相关的东西。 所以,所有的交互都在classes / modules / components /中分开,就算他们的工作是交互作用。而且特定的开发人员只在应用的UX部分工作时在这些组件上工作。

II. Encourage separation of concerns.(鼓励的关注点分离)

我之前所说的是一个关注点分离的例子。 我们鼓励这种特殊的方法,因为它可以很好地映射到团队和项目阶段的组织,但是您的架构也应该鼓励常规分离关注点。 分离问题或单一职责原则说,每个组件都应该只有一个理由需要改变。

III. Run away from the real world (Android, DB, Internet…).

从现实世界中逃脱出来的这个特殊点已经在之前提到过了。 我们已经说过,我们想要表现APP真正的功能而已。 我们想要强调业务逻辑,并在框架下留下框架细节。 这一点应该更加强烈:我们不仅要隐藏框架细节,还要隐藏与外部世界相关的所有细节。

Android Architecture under the hood

基本所有的Android的东西如传感器,通知机制,屏幕细节,数据库访问,Internet访问等等都是nitty gritty dirty

IV. Enable your components to be testable.

您应该尽可能单元测试您的APP,并且您的架构应该允许您执行此操作。 如果你不能单元测试一切,你至少应该用测试来覆盖你的业务逻辑。 与现实世界的分离与此相得益彰。 如果它明显与应用程序的其他部分分离,则测试业务逻辑会更容易。

giphy-5

第一次迭代 - 上帝的活动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public final class UsersActivity extends ListActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask<Void, Void, Void> {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

// showData(user);

return null;

}

}

}

你可能在“古代时代”看到过类似的代码。如果你还没有,那么你还很年轻。 这有什么问题? Everything!

no

我们有一个涉及数据库,进入互联网,解析,产生线程和呈现数据的Activity。 所以,所有的利益相关者都在关注单个类,没有任何问题是分离的,它不是可测试的,业务逻辑与Android的东西混杂在一起。

android architecture part 1 - 1

##第二次迭代 - MVP

第一种方法显然不起作用。 我们尝试的第一件事情之一是MVP,或model-view-presenter。 每个人都熟悉MVP。 它是最受欢迎的架构之一。 它看起来像这样:

android architecture part 2 - 2

在这里,我们分离了实际上是我们的Android Fragments的视图,我们有代表我们业务的(domain)模型,最后我们有协调所有这些的presenters。 肯定会更好。 关注点有些分离,利益相关者不再困惑,你可以写一些测试。 然而,我们仍然与现实世界混淆,因为presenter直接触及数据库和所有内容。 这是一个神的对象。 它处理模型,它将数据发送到视图,它拥有业务逻辑(业务逻辑是那些齿轮:)),并且它传递到数据库和Internet,获取传感器数据等等。所以,更好,但是 它可以变得更好。

android architecture part 1 - 3

第三次迭代 - MVP + managers

当政府不知道该做什么时,他们做了什么? 它设置一个机构。 当开发者不知道该怎么做时,他们会做什么? 他们采用一些managers。 您不必将其命名为“manager”。这些类有很多名称:utils,helper,fooBarBuzz-ator等等。我们统称为managers。

android architecture part 1 - 4

说实话,这甚至有点奏效。 业务逻辑包含在manager类中。 利益相关者知道在哪里看,关注是分开的,但他们可能更多,你可以编写更多的测试,但你仍然直接触摸Android,所以你必须编写Android测试用例和预填充数据库来测试业务逻辑,这很慢。 是的,managers往往是巨大的野兽,很快就很难维持。 你可以争辩说,它不需要比现在更复杂,你可以通过使用更简单的架构来更快地传递代码,但是这种方法会出现更多的错误,并且可维护性会受到影响。

android architecture part 1 - 5

总结

在本系列的第一部分中,我们遇到了创建实际可行的Android体系结构的挑战。 良好的Android架构应该满足众多利益相关者的需求,鼓励分离问题,强调业务逻辑,并将框架细节置于隐患之下,并使所有组件都可测试。 在系列的第二部分中,我们将向您展示我们如何管理那些对我们有用的东西。 在此之前,您对如何创建适当的Android工作流程有任何建议吗? 你遇到了什么问题?

Continue to part 2.

您还可以查看其他部分:

Part 5: How to Test Clean Architecture

Part 4: Applying Clean Architecture on Android (Hands-on)

Part 3: Applying Clean Architecture on Android