- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
关闭。这个问题是 opinion-based 。它目前不接受答案。
想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文来回答。
3个月前关闭。
Improve this question
我是一名有一定经验的 iOS 开发人员,这个问题对我来说真的很有趣。我在这个主题上看到了很多不同的资源和 Material ,但我仍然感到困惑。 iOS 联网应用程序的最佳架构是什么?我的意思是基本的抽象框架、模式,它适用于每个网络应用程序,无论是只有几个服务器请求的小型应用程序还是复杂的 REST 客户端。 Apple 建议使用 MVC
作为所有 iOS 应用程序的基本架构方法,但无论是 MVC
还是更现代的 MVVM
模式都没有解释网络逻辑代码的放置位置以及如何组织它。
我是否需要开发类似 MVCS
( S
为 Service
)之类的东西,并且在这个 Service
层中将所有 0x2341341 和其他复杂的 0x2341 请求放在其他复杂的角度?在做了一些研究之后,我找到了两种基本的方法。 Here有人建议创建为每个网络请求的Web服务API
(如API
类或LoginRequest
类等)的基本要求抽象类PostCommentRequest
并且除了所有继承来创建一些全局性的网络管理器,它封装了一个单独的类常见的网络代码和其他偏好(可能是 AbstractBaseRequest
定制或 AFNetworking
调优,如果我们有复杂的对象映射和持久性,甚至是自己的具有标准 API 的网络通信实现)。但这种方法对我来说似乎是一种开销。另一种方法是像第一种方法一样使用一些单例 RestKit
调度程序或管理器类,但不是为每个请求创建类,而是将每个请求封装为该管理器类的实例公共(public)方法,例如: API
、 0x2518122311343 等。那么,最好和正确的方法是什么?还有其他我不知道的有趣方法吗?
我是否应该为所有这些网络内容创建另一个层,例如 fetchContacts
或 loginUser
层或我的 Service
架构之上的任何层,或者该层应该集成(注入(inject))到现有的 0x23138 层中NetworkProvider
?
我知道存在漂亮的方法,或者像 Facebook 客户端或 LinkedIn 客户端这样的移动怪物如何处理成倍增长的网络逻辑复杂性?
我知道这个问题没有准确和正式的答案。这个问题的目标是从有经验的 iOS 开发者那里收集最有趣的方法。最佳建议方法将被标记为已接受并获得声誉奖励,其他方法将被投票。这主要是一个理论和研究问题。我想了解 iOS 中网络应用程序的基本、抽象和正确的架构方法。我希望有经验的开发人员详细解释。
最佳答案
I want to understand basic, abstract and correct architectural approach for networking applications in iOS
collect the most interesting approaches from experienced iOS developers
Core Data
。但是您不要忘记,
Core Data
不是 ORM 或数据库,而是具有持久性的对象图管理器作为它的一个不错选择。因此,通常
Core Data
对您的需求来说太重了,您可以查看新的解决方案,例如
Realm 和
Couchbase Lite ,或者基于原始 SQLite 或 .1224138 构建您自己的轻量级对象映射/持久层。此外,我建议您熟悉
LevelDB 和
Domain Driven Design 。
fat model, skinny controller
的东西。但我
确实相信 中的
skinny everything
方法,因为任何类(class)都不应该胖。所有的网络一般都可以抽象为业务逻辑,因此我们应该有另一层,我们可以把它放在这里。
CQRS 是我们需要的:
It encapsulates the application's business logic, controlling transactions and coordinating responses in the implementation of its operations.
MVC
领域中,
Service Layer
就像是域模型和 Controller 之间的中介。这种方法有一个相当相似的变体,称为
Service Layer,其中
Store
实际上是我们的
Service
层。
Store
出售模型实例并处理网络、缓存等。我想提一下,您不应该在服务层中编写所有网络和业务逻辑。这也可以被认为是一个糟糕的设计。有关更多信息,请查看
MVCS 和
Anemic 域模型。模型中可以处理一些服务方法和业务逻辑,因此它将是一个“丰富”(具有行为)的模型。
APIClient
类,它是
ReactiveCocoa 的子类。这是应用程序中所有网络的主力:所有服务类都将实际的 REST 请求委托(delegate)给它。它包含我在特定应用程序中需要的 HTTP 客户端的所有自定义:SSL 固定、错误处理和创建简单的
NSError
对象,其中包含详细的失败原因和所有
API
和连接错误的描述(在这种情况下, Controller 将能够显示正确的用户的消息)、设置请求和响应序列化程序、http header 和其他与网络相关的内容。然后我在逻辑上将所有 API 请求划分为子服务,或者更准确地说,
AFHTTPSessionManager :
UserSerivces
、
CommonServices
、 0x251812231343123 和 1231343123 相应地实现了业务逻辑 1343141 和 1231 到 131341 的业务。这些微服务中的每一个都是一个单独的类。它们一起形成一个
SecurityServices
。这些类包含每个 API 请求的方法,处理域模型,并始终向调用者返回
FriendsServices
和解析的响应模型或
Service Layer
。
RACSignal
和服务器请求模型之间有一些逻辑,您可以使用
Carlos 模式,它将检索数据并将其映射到实体模型的逻辑与作用于模型的业务逻辑分开。因此,即使您拥有基于 Core Data 的架构,我也建议使用 Repository 模式。存储库可以抽象事物,如
NSError
、
NSManagedObjectContext
、
NSFetchRequest
等简单的方法,如
NSEntityDescription
或 0x234131
NSPredicate
原语,或者只是订阅它并在响应中显示结果看法。我注入(inject)在所有这些服务类我
get
的
Repository,将特定的服务调用转化为相应的
put
,
ReactiveCocoa
,
APIClient
,
GET
等请求REST端点。在这种情况下,
POST
被隐式传递给所有 Controller ,您可以通过参数化
PUT
服务类来明确地传递。如果您想对特定服务类使用
DELETE
的不同自定义,这可能是有意义的,但是如果您出于某些原因不想要额外的副本,或者您确定您总是会使用一个特定的实例(没有自定义)
APIClient
- 使其成为单例,但不要,请不要将服务类设为单例。
APIClient
类或其他错误的东西。因为如果你给你的类(class)打电话
APIClient
,这表明你不知道它的用途,它是一个
Typhoon 。单例也是一种反模式,在
中,大多数 情况(罕见的除外)是错误的解决方案。仅当满足以下所有三个标准时才应考虑单例:
APIClient
Controller 需要
APIManagerWhatever
等等在)。
WhateverManager
原则并使用
SOLID ,所以不要将所有服务方法和网络调用都放在一个类中,因为这很疯狂,尤其是如果您开发大型企业应用程序。这就是为什么我们应该考虑依赖注入(inject)和服务方法。我认为这种方法是现代的和
separation of concerns 。在这种情况下,我们将应用程序分为两部分:控制逻辑( Controller 和事件)和参数。
One kind of parameters would be ordinary “data” parameters. That’s what we pass around functions, manipulate, modify, persist, etc. These are entities, aggregates, collections, case classes. The other kind would be “service” parameters. These are classes which encapsulate business logic, allow communicating with external systems, provide data access.
UserProfile
,它显示用户的 friend 列表,我们可以选择从 friend 中删除。我在我的
UserServices
类中创建了一个方法,名为:
- (RACSignal *)removeFriend:(Friend * const)friend
其中
S
是一个模型/域对象(或者如果它们具有相似的属性,它可以只是一个
FriendsViewController
对象)。底层这个方法解析
FriendsServices
到
Friend
的 JSON 参数
User
,
Friend
, 0x251353132132313213231323123132我总是将
post-OO 库用于这种样板和我的模型层(前后解析、管理 JSON 中的嵌套对象层次结构等)。解析后,它调用
NSDictionary
friend_id
方法来发出实际的 REST 请求,并返回
name
中的
surname
给调用者(无论我们的用户在何种情况下显示 123132 或 4518132 的适当消息)
A Repository represents all objects of a certain type as a conceptual set. It acts like a collection, except with more elaborate querying capability.
friend_request_id
本质上是一个外观,它使用集合样式语义(添加、更新、删除)来提供对数据/对象的访问。这就是为什么当你有类似的东西时:
APIClient
,
DELETE
,
Response
你可以把它放在
RACSignal
中,因为这里的语义非常清晰。代码如下:
- (RACSignal *)approveFriendRequest:(FriendRequest * const)request;
绝对是一个业务逻辑,因为它超出了基本的
FriendsViewController
操作并连接了两个域对象(
Repository
和
getFriendsList
),这就是为什么它应该放在 0x25181314231 层另外我想注意:
不要创建不必要的抽象 。明智地使用所有这些方法。因为如果你用抽象来压倒你的应用程序,这将增加它的意外复杂性,软件系统中的复杂性
Mantle 比其他任何事情都重要
getUserGroups
层(您记得是我们的主力)。现在我们的
removeFriend
提供程序将是一个值类型(枚举),其扩展符合协议(protocol)并利用解构模式匹配。 Swift 枚举 + 模式匹配允许我们像经典函数式编程一样创建
Moya。我们的微服务将像通常的 Objective-C 方法一样使用这个改进的
Repository
提供程序。对于模型层而不是
CRUD
,您可以使用
algebraic data types 或者我喜欢使用更优雅和功能更强大的
ObjectMapper library 库。
Friend
语言鼓励这样做。但永远记住,用大量的纯函数模式、类别理论方法重载你的代码是一个坏主意,因为其他开发人员会阅读和支持你的代码,他们可能会对
Request
和你的代码中的这类东西感到沮丧或害怕。不可变模型。与
Service
相同的事情:不要
APIClient
你的代码
immutable domain model ,因为它可以很快变得不可读,特别是对于新手。当它可以真正简化您的目标和逻辑时使用它。
关于ios - 构建 iOS 网络应用程序(REST 客户端)的最佳架构方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24162051/
我在使用 gradle 构建一个特定应用程序时遇到问题。该应用程序可以用 eclipse 编译和构建,它在平板电脑上运行良好。当我尝试使用 Gradle 构建它时,“compileDebugJava”
我有一个 C 程序,是一位离开的开发人员留给我的。我试图弄清楚他到底在做什么,并将软件重新安排成更合乎逻辑的东西,这样我就可以更轻松地构建它。我正在使用 CMake 构建,而他使用的是 Make。 有
我刚开始阅读“Pro Spring MVC with web flow”,它附带了一个我想遵循的代码示例。 我要什么 - 我想像书中那样构建应用程序,使用 Gradle 有什么问题 - 我没用过 Gr
我希望有人已经这样做了。我正在尝试为我的一个 angular 2 项目在 teamcity 中建立一个连续的构建。在做了一些研究之后,我按照以下步骤操作: 构建步骤 1:为 teamcity 安装 j
我有一个旧的 ASP.Net 网站解决方案,看起来像: 当我在 Visual Studio 中构建解决方案时,我得到以下输出: ------ Build started: Project: C:\..
我使用 gulp-usref、gulp-if、gulp-uglify、gulp-csso 和 gulp-file-include 来构建我的应用程序。除了 HTML 保持原样外,构建中的一切都运行良好
我正在使用 ionic2 开发内部移动应用程序。我可以通过以下方式成功构建 ios: ionic build ios and ionic build ios --prod 但当我这样做时,它一直失败
我是一位经验丰富的 .NET/C# 开发人员,但对这里的几乎所有技术/库(包括 SQL/DB 工作)都是新手。 我正在开发一个具有 Azure/Entity Framework .NET 后端和可移植
我正在使用 VS 2008。我可以使用 IDE 成功编译我的解决方案。但是,当我尝试使用 devenv.com 构建它时,它失败并提示“错误:找不到项目输出组'(无法确定名称)的输出”。该组、其配置或
版本: ember.js 2.7,ember-data 2.7 ember-cli 2.9.1//同样适用于 ember-cli 2.7 node 6.9.1, npm 3.10.9//也适用于 no
我第一次修补 AzureDevops,设置一些 CI 任务。 我有一个公共(public)存储库(开源)和一个包含 3 个 F# 项目的解决方案(.sln)。该解决方案在 Windows/Mac/Li
目前 5.1.5 版本或 STLPort CVS 存储库似乎仍不支持 VS2008。如果有人已经完成了这项工作,那么如果可能的话,分享会很有用:) 同样,了解 VS2005 或 2008 x64 构建
我有一个 Python 2.7 项目,到目前为止一直使用 gfortran 和 MinGW 来构建扩展。我使用 MinGW,因为它似乎支持 Fortran 代码中的写入语句和可分配数组,而 MSVC
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
我想知道为什么在 Zimbra Wiki 中只列出了构建过程的特定平台。这意味着不可能在其他 Linux 发行版上构建 Zimbra? Zimbra 社区选择一个特殊的 Linux 发行版来构建 Zi
我将在 Swift 中构建一个 CLI 工具。我用这个命令创建了项目 swift package init --type executable当我构建我的项目并解析 时读取别名 Xcode 中的参数并
我想为添加到 docker 镜像的文件设置文件权限。我有这个简单的 Dockerfile: FROM ubuntu:utopic WORKDIR /app RUN groupadd -g 1000 b
当我使用 clBuildProgram在我的 OpenCl 代码中,它失败并显示错误代码 -11,没有任何日志信息。 这是我的代码的样子: ret = clBuildProgram(program
我有一个底部导航栏,它有一个列表页面,该页面使用状态块。 class _MainPageState extends State { int _index = 0; @override Wi
我在本地计算机上使用Jenkins(Jenkins URL未通过Internet公开,但该计算机上已启用Internet。) 我进行了以下配置更改: 在Jenkins工具上安装了Git和Github插
我是一名优秀的程序员,十分优秀!