如何在App开发中使用Functional Programming

时间:2016-07-21 06:10:56

标签: ios swift functional-programming

我一直在阅读和使用功能编程(FP),我非常喜欢它的概念,但我不确定如何在我的大多数应用程序中应用它们。

我会更具体,让我们谈谈iOS应用。我确实看到了如何使用一些概念,如不可变数据结构和高阶函数,但不知道如何只使用/大多数纯函数 - 避免副作用 - 这似乎是FP的主要部分。

我觉得应用程序的大部分内容都是协调输入调用,显示数据,保存数据,发出网络请求,从一个屏幕导航到另一个屏幕,动画。

所有这些都是FP上的不纯函数:

  • 协调输入:按钮点击,通知,服务器套接字推送,所有我必须决定要呼叫的内容,在哪里观察它们等。
  • 显示数据:从本地数据库或服务器读取(副作用)。
  • 保存数据:与上述相同(但写作)。
  • 提出网络请求:很明显,所以我在这里举一个例子 - 从Instagram检索列表图片。
  • 导航:它基本上呈现了视图控制器,这是一种副作用。
  • 动画:改变屏幕上的内容,副作用。

我必须处理数据的地方很少,而且几乎总是从数据库中检索一些Struct并将多个信息连接到View Controller将使用的另一个Struct(&# 39; s像5行...假设您需要在视图中显示5个属性)。当然,您可能需要进行一些处理,例如转换money: Int = 20 to moneyString: String = "US$\(money).00",但那就是它。

我觉得我未能在我的应用开发周期中实施FP。任何人都可以澄清我如何实现这一目标吗?也许有例子。

谢谢。

编辑:现在,按照Clean Architecture的想法,我的架构就像这样:

enter image description here

输入可以来自View,只需按一下按钮,它们就会转到决定调用哪个ViewController的{​​{1}}。 Interactor将访问必要的Interactor以获取一些数据,并将其转换为可传递给Gateway的可呈现数据(以委托的形式)。最后,Presenter将更新Presenter以显示新数据。

此外,输入可以来自View来源,例如服务器告诉您某些数据已更新,您必须刷新External。这将转到View(以观察者的形式),它将跟随链的其余部分,如上例所示。

唯一的FP部分是将Interactor数据转换为可显示的数据。所有其他都有副作用。我觉得我做错了,也许有些代码应该以不同的方式组织,以便更多的代码可以转移到纯函数。

3 个答案:

答案 0 :(得分:2)

暂时搁置FP,多用户或时间依赖模型面临的挑战是程序前的最终用户不是控制事件的唯一来源。

为了保持依赖关系的清洁,我们应该将外部触发器视为用户输入的一种形式(可能是未经请求的)并通过相同的路径处理它们。

如果最终用户以某种方式通过心灵感应通知新数据可用,他可以按下按钮让程序获得它。然后,不需要反向控制流(例如推送通知)。

在这个完美的世界中,用户获取数据的操作首先会在视图级别捕获,然后在图层中进行。

这告诉我们通知应该由视图控制器处理,或者更好的是由用于接收通知的视图组件处理。但是,此类通知不包含任何数据,除非可能表明该模型的哪个部分已失效。

回到FP,如果您考虑之后的所有函数调用将返回可能不同的结果,这当然是一个巨大的副作用。但是...

在数学方面,如果你定义一个函数,给你一个给定速度的行进距离,但不提供时间参数,你不是副作用的受害者,你只是忘了提供输入值。

因此,如果我们认为所有软件层都是纯函数但是时间是初始输入给出的隐式参数,则可以通过检查重复调用(以任何顺序)到函数来验证您的程序是否符合FP。系统在冻结时间时应始终返回相同的结果。

如果数据库可以在任何给定时间保持其状态的100%完整快照集,则可以通过冻结时间或将其作为参数来验证应用程序的纯FP一致性。

现在回到现实世界,出于性能原因,这种设计通常是不切实际的。它几乎排除了任何形式的缓存。

不过,我建议您尝试将通知分类为设计中未经请求的用户输入。我相信这可能有助于解决一些难题。

答案 1 :(得分:0)

工具箱中应始终有多个工具。 FP是一种很好的方法,也是大多数人应该使用的程序(例如,通过MVVC中的视图控制器在视图上显示模型)。

尝试在应用程序中的所有内容上使用FP可能不值得。一旦你要坚持数据或管理时间的流逝,你就必须处理各州。即使是“宁静”服务(概念上是FP方法的良好候选者)也不会是纯粹的FP并且具有一些状态依赖性。这不是因为它们是不好的FP实现,而是因为它们是管理外部持久状态的目的。您可以将其旋转以将存储的数据视为“输入”,但是从服务的任一侧,另一方仍然是副作用(除了只读操作)。

如果你搞砸了MVVC负责管理状态转换并允许其组件之间存在非FP关系这一事实,那么为每个组件实现更小规模的FP范例变得更加容易。

例如,您的视图控制器不应具有复制或维护模型中任何数据的转换版本的任何变量。在MVVC组件之间使用委托确实在某些情况下破坏了FP规则,但在视图控制器的功能范围内,这些是输入(而不是状态)。通过在开始编码之前规划(和绘制)交互图,您将能够更好地隔离关注点,而不会进入会破坏组件中FP的死角。

在模型本身中,计算属性可以确保您遵守FP。

在任何情况下,如果你从不使用var语句(在某些地方这将是一个挑战),你很可能最终得到符合FP的代码。

答案 2 :(得分:0)

功能编程有助于解决特定的编程问题。 FP擅长的是并发/并行编程;如果您已经阅读了Herb Sutter撰写的关于并发编程的任何文章,那么您将开始看到良好的并行/并行编程和功能设计的重叠。

对于申请,正如Alain所说,你必须与州合作。您可以围绕状态修改方式应用FP设计模式,但无论如何,您必须在某个时刻修改状态,这与您发现的一样,不与纯FP对齐。

FP是编程模式工具箱中的一个工具,但它不是唯一的工具。