Tag: 软件构架

Swift中的Type Erasure

在上一篇文章中,我写了关于将代码拆分为较小框架的文章。 但是有时候这说起来容易做起来难。 我当前的挑战是调制可重用的UI处理。 这就是为什么我创建FancyUI。 除了某些配置扩展之外,我还为主题支持实现了组件管理器。 FancyUI中的样式表和组件管理器 可样式设置是继承可样式设置协议的视图。 它们强制您实施style(colorScheme:)方法,以便您可以配置视图的颜色。 您可以在组件管理器中注册它们。 组件管理器充当观察者,而可样式元素本身就是主题更改的侦听器。 您可以通过组件管理器轻松传递新的颜色方案,以轻松管理应用程序中的主题支持。 问题 FancyUI的实现应该能够创建自定义ColorScheme类型。 因此,Styleable必须对ColorScheme使用通用类型。 可样式化是一种协议,因此ColorScheme必须是关联的类型。 组件管理器(它是一个结构)保存ColorScheme并将其传递给已注册的styleables。 这就是问题所在:因为组件管理器是struct,所以它具有通用类型GenericSchemeType而Styleable具有关联的类型SchemeType 。 我必须将通用SchemeType转换为关联类型SchemeType ,这是不可能迅速实现的。 解决方案:类型擦除 问题是在编译时无法推断类型。 这就是为什么我试图创建一个结构AnyStyleable。 此类型将样式函数存储为闭包,并在调用style()函数时执行它。 组件管理器现在注册AnyStyleable而不是Styleable。 注意:类型信息并没有真正删除。 它已经搬迁了。 闭包在运行时推断其类型,因此我们在这里没有问题。 该问题已解决。 但是我对解决方案有一个体系结构上的问题:样式类型必须另存为闭包,而视图本身不是Styleable。 正如我已经提到的,我喜欢提取东西。 我想象在一个大型的成长型企业应用程序中使用样式方法。 在viewDidLoad或init中设置AnyStyleable会使事情变得blo肿,因此我对Styleable协议的初衷是在单独的扩展中实现它(并让视图控制器本身作为Styleable本身)。 因为样式位于另一种类型,所以这不可能了。 但是我也有解决这个问题的方法。 替代方法:实型擦除 在我目前的方法中,原始的Styleable协议没有太大变化。 几乎是一样的,除了协议是由另一个协议继承的:AnyStyleable.AnyStyleable是一个将样式函数作为闭包的结构,现在它是一个将style(scheme:)方法定义为Any类型的协议。 这意味着:AnyStyleable是具有具体类型的协议(即使它是Any)。 这使我们可以将AnyStyleables注册到组件管理器。 魔术来了:正如我提到的,Styleable协议继承了AnyStyleable协议。 因此,我可以将Styleables注册到组件管理器,因为它正在等待AnyStyleable的类型。 您现在可能会问自己:可样式设置具有 style(colorScheme:) 方法。 当它们实际注册为AnyStyleable时如何调用? AnyStyleable协议定义_style(colorScheme:)方法,该方法作为默认实现实现。 _style(colorScheme:)实现在运行时检查传递的类型是否与关联的类型匹配,如果成功,则调用style(colorScheme)函数。 因此,实际上,组件管理器调用_style(colorScheme:)方法,该方法在运行时委托给style(colorScheme:)方法。 这种方法的好处是实现完全不必处理擦除。 它可以只调用所使用的register(self) ,并且可以将实现的样式函数提取为扩展。 结论 我通常会尝试避免类型检查和类型转换。 但是这种方法对我来说似乎是合法的(也是因为它已用于标准库中的某些类型)。 […]

我们决定重新写Snapp; 这就是为什么

大约一周以来,我们试图在我们的iOS应用中重现一些令人讨厌的错误,最近我们听到了很多。 大量的脱毛什么也没做。 我们很拼命。 我们决定放弃该错误并宣布失败。 但这无法继续。 必须要做的事情,所以我们决定从头开始重新编写应用程序。 当开发人员正在使用他们未编写的某些代码库时,这种情况经常发生。 他们尝试在各行之间阅读以了解原始开发人员在编写它们时的想法。 几乎总是无济于事,因此他们决定丢弃所有内容并自己编写代码,希望这些错误不再出现。 而且,它并不总是与调试有关。 我们很难在旧代码库的基础上开发新功能。 由于Snapp的快速增长,我们承担了许多技术债务。 我们必须提出一个新的体系结构和代码库,该体系结构和代码库可以使用很长时间,并且在以后的几年中都将在其基础上开发功能。 我们有两种选择:逐渐迁移代码或暂停所有内容,然后从头开始重新编写应用程序。 移民 当然,风险较小的方法是迁移。 这样,我们不必停止开发代码库,并且可以在很长一段时间内顺利进行。 但是我们发现这种方法存在一些问题。 首先,在某些最重要的代码部分中,我们遇到了严重的体系结构问题。 Snapp是一个网络密集型,实时,事件驱动的应用程序,我们的事件处理程序和网络代码在该应用程序中无处不在。 我们对应用程序的静态部分或较少使用的部分没有任何问题,我们的主要问题来自该应用程序的实时功能。 我们发现,重构应用程序的网络部分实际上意味着重写整个应用程序,因此无法进行逐步重构。 其次,我们以前在重构网络代码的某些部分时遇到过失败的经验。 它从来没有完成过,因为那时我们还没有可靠的质量检查机制,并且如果我们无法彻底测试它,就不会冒险发布该应用程序。 重构应用程序重要部分的每一次尝试都扩大到编辑项目中几乎每个文件。 您可能会认为“好吧,您可以先编写单元测试”。 尝试为具有M [assive] VC架构的iOS应用编写单元测试。 这不愉快,不可能。 改写 因为我们排除了“迁移”,所以最终只有一个选择:使用可靠且可扩展的软件体系结构完全重新编写应用程序,并在此基础上编写单元测试。 质量检查小组也有足够的时间提出有关如何测试该应用程序的想法。 这是技术方面的事情,我们开发人员深信重写是必经之路……但是! 重写已经在生产环境中使用多年的软件存在风险。 像Snapp这样的大型企业所依赖的重写软件的风险更大。 因此,我们必须说服管理层让我们为这个雄心勃勃的项目分配足够的时间和资源。 当我们考虑是否要从头开始重写Snapp时,我们寻求其他公司的经验,就像任何理智的头脑一样。 如果您在Internet上搜索以寻找决定重新编写其应用程序的公司,那么您可能最终会阅读Joel Spolsky的文章,其中涉及Netscape在重新编写浏览器时如何使自己失望。 这是一篇不错的文章,在决定重新编写正在使用的软件之前,您必须先阅读它。 但这只是事情的一方面。 大公司肯定有成功的改写,又有什么公司比强大的优步做得更好的改写呢? 当我们开始研究这些问题时,我们发现Uber最近启动了他们的新应用程序,这是我们启动该项目所需的灵感。 下一个原因是由于在Objective-C中开发存在问题。 开发该应用程序的第一个版本时,Swift 2尚未发布,不仅它周围没有社区,而且语言本身也有缺陷。 因此,总而言之,选择Objective-C是一个合理的决定。 Flash向前发展了几年,并发布了Swift 4,它相当稳定,几乎所有第3方库和工具都支持Swift,并且使用Swift进行编程非常令人高兴。 团队中的所有新开发人员也对Swift更加满意,因此转向Swift似乎是不可避免的。 从长远来看,这是值得的。 现在我们有了理由,但首先我们必须说服管理层这是一个明智的商业决策。 幸运的是,管理层开了绿灯,我们开始了这个项目。 我们进行了大约5个月的研究,最后提出了自己的架构框架,然后花了将近10个月的时间使用该框架编写应用程序并最终发布。 […]

无畏和高效地使用第三方iOS框架

当我开始职业生涯时,我在一家不允许使用第三方框架的公司里工作。 我们必须从头开始编写所有功能,以使其可以在其他项目中作为我们自己的内部框架重用的方式来构建它们。 这是一个奇怪的政策,但它可能是我作为软件开发人员曾经遇到的最好的学习工具之一。 而且,如果您认为从头开始编写功能不可行,我可以向您保证。 尽管进行了额外的工作,我们始终设法按时交付,并且该业务是可盈利的。 也就是说,我完全理解了这种情况无法承受的情况。 实际上,在我的另一项工作中,该协议正好相反:如果有一个第三方框架可以完成我们不希望使用的功能,那么我们会因浪费时间和资源进行重新发明而受到谴责。车轮。 那也是一个很奇怪的政策,但是我从使用第三方框架中学到了很多-这样做使我可以接触到其他人的代码,这反过来又为我提供了很多额外的知识和经验。 我记得那时起有那么多aha时刻。 在我的职业生涯中经历过两次极端时,我发现在两者之间取得平衡通常会给我带来更好的工作成果。 一方面,我坚信自己做事是最好的学习方法,并且从零开始编写一切都教会了我如何构建框架,可重用的模块化代码,良好的API等。 它促使我学习如何有效地编码并解决任何问题,尤其是在我的职业生涯早期,学习曲线陡峭的时候。 另一方面,选择使用第三方框架可以帮助我快速创建高质量的解决方案,使我能够向世界各地经验丰富的开发人员学习,并在遇到软件开发方面的不同见解时提高了自己的技能。 这两种工作方式都非常有价值,我希望每个开发人员也有机会体验它们。 当然,并不是每个人都可以自由地从头开始编写自己的工作,在这种情况下,通过附带项目进行尝试通常是学习的好方法。 这正是我所做的。 早在2009年,作为学习如何编写iOS应用程序的练习,我为网络和JSON,XML和HTML解析器编写了所有Objective-C实现。 为了持久性,我编写了SQLite和Core Data包装器。 我什至编写了自己的基于文本的文件存储方案,这听起来很愚蠢,但这是解决许多问题的简单方法,最终使我的客户满意。 我们非常习惯使用已知技术,以至于我们常常忘记像Core Data这样的框架在很多情况下是过大的,而自定义解决方案更便宜,构建和维护也更快。 明确地说,我还不时使用Core Data,它为更复杂的项目提供了巨大的价值。 例如,即使在过去我曾经在iPod Touch(第3代)上测试应用程序的过去,它也有助于保持较低的内存占用并保持响应式UI线程。 使用定制解决方案来做这些事情将是困难且昂贵的,尤其是在处理大量数据时。 那么,您如何在这两个极端之间找到平衡? 每次从头开始编写都是很浪费的,但是编写模块并在项目领域中重用它们是一个不错的选择,尤其是在学习时。 同时,忽略第三方框架也很浪费,这样做可能会导致您面临许多在其他人的项目中已经解决和验证的挑战。 但… 还记得解析吗? 我做。 我们很难宣布。 从今天开始,我们将关闭Parse服务,经过长达一年的时间(截至2017年1月28日),Parse将完全退休。我们很自豪能够帮助如此多的人构建出色的移动应用程序,对此我们感到很自豪,但我们需要将资源集中在其他地方。 —来自他们的 博客 解析“继续前进”,但是他们的客户继续前进又有多容易呢? 我敢肯定,你们中的许多人都受到Parse关闭的影响,这很可能是关于过多依赖第三方服务的重要教训。 但这并不总是必须像关闭服务那样极端。 例如,当您使用的服务仍然存在但不再满足您的需求时会发生什么? 长期以来,我最喜欢的REST应用程序入门框架是RestKit-与其说是REST方面,不如说是它的主要功能,而是它强大的映射框架,它允许我从JSON / XML源创建应用程序域模型而无需将该责任泄露给模型类。 我希望我可以只使用框架的那部分,但是它的体系结构使得很难分开。 令我感到奇怪的是,我无法创建自己的客户端实现,因为RestKit的许多类都在子类化AFNetworking组件(它是建立在AFNetworking 1.x之上的),因此该项目完全依赖于AFNetworking。 即使这样,我还是决定接受这些缺点并将其用于网络层。 尽管我决定仍然使用它来节省很多开发时间,但我将其隐藏在一个不会泄漏对我的应用程序依赖关系的协议后面。 我的应用程序仅使用API​​协议,并且期望返回不从Core Data,RestKit或任何框架依赖项继承的应用程序域模型。 这使得应用程序极其易于编写和编写,维护和测试,而且轻巧。 然后是苹果推出NSURLSession的那一天,而我正在从事的项目之一需要一些新功能,例如后台下载。 RestKit社区开始了有关如何移植其客户端体系结构以支持此操作的漫长讨论,但截至目前,它尚未完成。 AFNetworking […]

IOS APP的VIPER体系结构优势

众所周知,软件行业的软件体系结构至关重要。 设计代码很重要,这样每一部分都易于识别,具有特定目的并以逻辑方式与其他部分组合在一起。 它应该易于维护,可扩展并具有高质量。 在开发iOS应用时,请务必考虑应使用哪种iOS项目架构。 大多数开发人员使用Apple建议的模式。 但是还有其他! 在本文中,我们将研究VIPER体系结构,它是MVC的一种流行替代方案,它可以帮助您克服其限制,同时保持代码的组织良好,从而改善开发过程。 VIPER是View,Interactor,Presenter,Entity和Router的反义词。 此体系结构基于“单一职责原则”,这导致了干净的体系结构,从而为您的iOS项目提供了更好的结构。 让我们详细了解每个字母的含义: 视图。 视图的职责是将用户操作发送给演示者,并显示演示者告诉其的内容。 交互器。 这是应用程序的骨干,因为它包含应用程序中用例描述的业务逻辑。 交互器负责从模型层获取数据,并且其实现完全独立于用户界面。 主持人。 它的职责是根据用户操作从交互器获取数据,创建一个视图模型实例,并将其携带到视图中以进行显示。 实体。 它包含Interactor使用的基本模型对象。 它具有其他体系结构中模型层的部分职责。 路由器。 它具有用于描述何时显示哪些屏幕的所有导航逻辑。 在Viper架构中,每个块对应一个具有特定任务,输入和输出的对象。 这与装配线中的工人非常相似:一旦工人完成了对某个对象的工作,该对象就会传递给下一个工人,直到完成产品为止。 块之间的连接表示对象之间的关系,以及它们之间传递的信息类型。 从一个实体到另一个实体的通信是通过协议给出的。 这种架构模式背后的想法是隔离应用程序的依赖关系,以平衡实体之间的职责委派。 基本上,Viper架构将您的应用程序逻辑划分为较小的功能层,每个功能层都有严格的预定义职责。 这使得在层之间的边界处测试交互更容易。 它非常适合单元测试,并使您的代码更可重用。 简化复杂的项目。 由于模块是独立的,Viper非常适合大型团队。 使它具有可伸缩性。 使开发人员能够尽可能无缝地同时进行处理 解耦代码以实现可重用性和可测试性 根据角色划分应用程序组件 设定明确的责任,Viper是责任分配的倡导者 轻松添加新功能 由于您的UI逻辑与业务逻辑分离,因此使编写自动化测试变得容易 它鼓励将关注点分离开来,从而更容易采用TDD。 Interactor包含独立于任何UI的纯逻辑,这使得测试驱动变得容易 易于使用 创建清晰且定义明确的界面,独立于其他模块。 这使更改界面向用户呈现各种模块的方式变得更加容易。 借助单一责任原则,可以更轻松地通过崩溃报告跟踪问题 使源代码更清洁,更紧凑和可重用 减少开发团队中的冲突数量 适用SOLID原则 减少合并冲突的次数 您可能想要先创建初始体系结构框架,然后再将模块逐个交给其他开发人员以实现逻辑。 使代码库看起来相似。 阅读他人代码变得更快。 Viper架构具有很多好处,但必须指出的是,最好将其用于大型和复杂的项目。 由于涉及的元素数量众多,该体系结构在启动新的小型项目时会产生开销,因此对于不打算扩展的小型项目而言,Viper架构可能会显得过大。 因此,对于此类项目,最好使用其他内容,例如MVVM。 […]

iOS中的行为驱动开发

在编写单元测试时,开发人员通常由内而外地执行测试。 这意味着首先要编写对数据访问层的测试,然后是业务逻辑层,最后是用户界面层。 问题在于,我们离应用程序行为越远,我们与应用程序功能的隔离就越紧密。 行为驱动开发使我们可以从用户的角度而不是开发人员的角度来看应用程序。 在这篇文章中,我将使用行为驱动开发的原理来实现注册用户功能。 项目名称是“ People ”,它由一个单视图应用程序,一个单元测试项目和一个UI测试项目组成。 与其从数据库层开始,不如从我们要实现的功能/行为开始。 下面列出了一些功能: 作为用户,我应该能够成功注册一个帐户 作为用户,如果我使用现有的用户名,则应该收到错误消息 我坚信,如果您不进行测试优先开发,那么您将失去编写单元测试的许多好处。 TDD和BDD不仅允许您测试应用程序,而且还规定了应用程序的总体体系结构。 测试优先开发 甚至不用考虑在您的应用程序中编写一行代码! 我们将从编写单元测试开始。 我们将从编写UI测试开始,该测试将代表注册新用户的行为。 为了访问测试中的控件,您将需要使用可访问性标签提供一个标识符,如以下屏幕截图所示: 另外,请注意XCTest框架中没有tapAndType函数。 tapAndType函数是一种自定义扩展方法,它允许快速选择和设置UITextField的文本。 即使设置了标识符,测试仍将失败。 原因是我们尚未实现注册按钮事件的代码,并且尚未将用户带到登录屏幕。 此时,您将返回RegistrationTableViewController并实现按钮单击事件,如下所示: 由于您没有名为User的类或名为dataAccess的实例,因此这些代码均无效。 这将导致您实现User类,如下所示: 您还可以在iOS单元测试项目中编写单元测试,以确保可以创建User类的实例,如下所示: 我认为上述单元测试不会为我们实现所需功能提供任何价值。 单元测试仅仅是测试我们可以创建类的实例。 您应该始终编写单元测试来测试业务领域的复杂性,而不是语言功能。 这将引导我们进入数据访问层,我们将在下一节中介绍它。 资料存取层 为简单起见,我们将使用UserDefaults存储我们的数据。 我们将从实施单元测试开始,如下所示: 该测试甚至不会编译,因为我们的DataAccess类没有saveUser和getUsers函数。 让我们如下所示添加它们: 上面的代码进行了多次迭代和大量失败的单元测试。 即使现在,由于用户不符合NSCoding的要求,测试仍将失败。 让我们更新User类,使其符合NSCoding协议。 现在,如果您再次运行测试,则测试将通过,因为所有部分均已安装到位。 尽管数据访问测试可以通过,但最外部的测试仍将失败,因为注册后用户不会转移到“登录”屏幕。 塞格斯 在开始添加segue之前,请看一下之前实现的以下代码。 这是saveButtonClicked代码的最终版本。 原始实现如下所示: 如您所见,原始版本没有动态执行任何排序。 segue是使用Storyboard从按钮控件创建到LoginTableViewController的 。 这允许测试通过,但是后来我们转到下一个功能时测试被破坏了。 作为用户,如果我使用现有的用户名,则应该收到错误消息 现在,您将看到测试优先方法如何帮助我们设计了更好的应用程序。 打扫干净 单元测试最重要的原则之一是,它应该在完成状态后始终将其恢复为原始状态。 这意味着,如果您的单元测试将数据添加到数据库中,那么在测试结束时,它应该从数据库中删除数据。 这样可以确保在运行下一个测试时数据库处于初始状态。 […]

在准备好后端/设计之前有效地开发Swift应用程序

UI模块和系统的其余部分之间也是如此。 用户界面需要输入FeedItem的输入(以在屏幕上呈现),因此,只要我们描述了界面边界(合同),我们就可以继续并行开发,而不会因没有后端或UI设计呢。 一旦后端和UI设计就绪,我们就可以将所有模块组合在一起。 最后,由于我们的组件暂时不支持UI(和平台),因此我们创建了一个新的macOS框架,该框架将帮助我们加快开发和测试过程,因为我们无需在运行缓慢的iOS上运行应用程序或测试模拟器。 立即订阅我们的YouTube频道, 每周获取** 免费的新剧集**,以及 在GitHub上关注项目的进度。 最初在 www.essentialdeveloper.com上 发布 。 我们一直在帮助敬业的开发人员从低薪工作转变为高级职位-有时只需几周! 为此,我们会不断进行和分享免费的市场研究,以了解如何提高同理心,正直和经济学的技巧。 如果您想从事自己的职业,请立即免费获取我们的最新研究成果。 如果您喜欢本文,请访问我们的网站https://essentialdeveloper.com,并获得更多类似的深度定制内容。 在以下位置关注我们:YouTube•Twitter•Facebook•GitHub

简要介绍:实现MVVM-C模式

您可以阅读它或尝试与我们创建一个简单的pp。 我们建议使用后者。 我们已经发布了有关MVVM模式的文章: MVVM体系结构:分步指南 ViewModel有什么不同。 essays.decode.agency 以及关于使用协调器的一项: 与协调员配合应用流程 向庞大的ViewController告别。 essays.decode.agency 因此,唯一合乎逻辑的下一步就是将两者放在一起,并在一个实际示例中引导您实现MVVM-C模式。 我们将其称为“红色和绿色”应用程序。 基本结构 我们将在语义上将“红色与绿色”应用程序的屏幕分组为单位。 每个单元包括以下组件: 视图 ViewController 视图模型 ViewModelProtocol ViewModelProtocol用于进一步封装ViewController和ViewModel之间的通信。 我们的应用程序有一个主屏幕,可以选择红色或绿色。 选择红色将我们带到红色屏幕,绿色将我们带到绿色屏幕。 每个VC通过两个组件初始化: mainView —定义屏幕的可视部分并在其上配置操作 viewModel —分离UI部件的逻辑; 在MVVM-C模式中,它还负责与协调器进行通信 让我们深入了解并定义主屏幕。 我们将其称为MainVC: 在LoadNibFromEnum中,您会看到我们使用了自定义函数来调用Nibs: 视图是通过相应的XIB定义的,其中有两个按钮,这些按钮在屏幕上显示,因此可以定义对它们的操作。 ViewModelProtocol定义了可以在VC-VM关系上执行的所有动作。 在这种特定情况下,我们只需要在上述两个按钮上定义动作,因此我们将这样做: 可以以多种方式定义动作,但是出于代码易读性的考虑,我们仅通过块定义动作。 ViewModel可以是符合ViewModelProtocol的类或结构,这意味着在ViewModelProtocol中定义的所有方法或动作也必须在ViewModel中定义。 然后,我们最终可以将视图中的按钮动作与ViewModel中定义的动作连接起来: 我们的MainView是公开的,因此我们可以在viewDidLoad中的按钮上定义所有动作,并将每个动作转发到ViewModel中的块。 这样,ViewController不必知道导航接下来会发生什么,并且无需承担控制UI的责任。

避免使用遏制和子视图控制器的大规模视图控制器

View Controller是提供基本构建块的组件,我们以此为基础来构建iOS开发中的应用程序。 在Apple MVC世界中,它充当View和Model之间的中间人,充当两者之间的协调器。 它以控制器作为观察者开始,该观察者对Model的更改做出反应,更新View,使用Target Action接受来自View的用户交互,然后更新Model。 作为iOS开发人员,即使我们使用MVVM,MVP或VIPER之类的体系结构,在很多情况下我们也将面临处理Massive View Controller的问题。 有时,View Controller的职责太多,无法在一个屏幕中处理。 它违反了SRP(单一责任原则),在模块之间建立了紧密的耦合,并使得重用和测试每个组件变得困难。 我们可以以下面的应用屏幕截图为例。 您可以在一个屏幕上看到至少3个职责: 显示电影列表; 显示可以选择应用于电影列表的过滤器列表; 清除所选过滤器的选择。 如果我们要使用Single View Controller构建此屏幕,则可以确保View Controller会变得非常庞大和肿胀,因为它在一个单一View Controller中处理过多的职责。 我们如何解决这个问题? 解决方案之一是使用View Controller Containment和Child View Controller。 使用此解决方案的好处如下: 将电影列表封装到MovieListViewController ,后者仅负责显示电影列表并对电影模型中的更改做出反应。 如果我们只想显示没有过滤器的电影列表,那么我们也可以在另一个屏幕中重用此MovieListViewController 。 将过滤器逻辑的列表和选择封装到FilterListViewController ,后者仅负责显示和处理过滤器的选择。 当用户选择和取消选择过滤器时,我们可以使用委托与父级View Controller通信。 将主View Controller缩小为一个ContainerViewController ,该ContainerViewController只是负责将“过滤器列表”中的选定过滤器应用于MovieListViewController的Movie模型。 它还设置布局,并使用容器视图添加子视图控制器。 您可以在下面的GitHub Repository中查看完整的项目源代码。 alfianlosari / Filter-MVC-iOS 使用子级View Controller进行封装,可重用,并避免使用Massive View Controller… github.com 使用Storyboard组成View Controller 根据上述情节提要,以下是我们用于构建“筛选器”屏幕的视图控制器: ContainerViewController […]

移动应用程序的简单架构

在加入BigCommerce担任高级移动软件工程师之前,我很幸运在Mutual Mobile工作了五年以上,担任过iOS工程师到架构师的职位。 对于不熟悉MM的人士,他们是一家全球数字创新和新兴技术机构,总部位于德克萨斯州奥斯汀(与BC省相同)。 在代理机构中成为移动开发人员的最大好处之一就是项目范围广泛。 有一天,您可能正在开发银行应用程序。 六个月后,它可能是围绕体育社区构建的社交应用程序,健身应用程序,网状网络系统,智能家居管理器等等。 尽管客户多种多样,但他们总是有共同点,在Mutual Mobile,我们开发和开源了许多开发人员至今使用的工具和体系结构。 由Jeff Gilbert和Conrad Stoll在Mutual Mobile上开发并倡导的一种名为VIPER的体系结构在iOS社区及以后的社区中获得了广泛的关注。 最近在BigCommerce开始新的移动项目时,我考虑过回到熟悉的体系结构。 VIPER是适用于移动应用程序的Clean Architecture应用程序,专注于将逻辑与视图控制器分开的可测试代码。 在移动世界中,大多数应用程序都使用MVC架构,这通常意味着包含应用程序逻辑的视图控制器(也称为Massive视图控制器)。 通过将视图与业务逻辑分开,VIPER使类更易于理解,测试和维护。 但是最终我决定VIPER超出了我的需要。 尽管它是一种出色的,可测试的现代体系结构,但它往往需要大量文件才能正确执行。 可以使用几个开源项目来生成执行VIPER所需的文件(尽管如果像吉尔伯特那样执行TDD风格,则仅在需要时创建这些文件)。 我决定尝试一下自己的个人建筑构想。 它是最小的,不是样板化的,并且高度便携。 我已经使用它在Objective-C,Swift和JavaScript中编写了应用程序,并且没有理由说它不能在其他十几个版本中运行。 它绝对受到VIPER及其背后思想的影响。 其中心论点是:移动应用程序是由数据传递流和子流(开始,结束,前进和后退以及有时执行操作)管理的屏幕构造。 因此,我将其称为“流程体系结构”。 流架构介绍 无论是将用户(这是该架构的起源),登录服务还是仅使用带有不同屏幕导航堆栈的基于选项卡的应用程序,几乎任何应用程序过程都可以描述为屏幕流和信息。 这一切都从一个开始开始。 / **启动流程,提供可选的初始数据* / func start(带有数据:任何?) 当然,任何可以开始的流程也可以结束。 / **完成一个流程,提供可选数据* / func end(带有数据:任何?) 某些流程,例如入职或登录,可能需要前进和后退。 / **向后退,提供可选数据* / func back(带有数据:任何?) / **前进到流程中,提供可选数据* / func next(带有数据:任何?) 有时,流程可能需要执行一些不一定导致前进或后退的动作。 一个动作需要一个ID来标识它,并可能提供一些数据来为其提供上下文。 我也可能会记录一个操作,例如用于分析。 流量没有实际变化。 […]

Etkinlikte NeYaptım?

AGUCS移动黑客马拉松’18 AGU’de @ agucompsocietytarafındanVİİTA 赞助商luğundagerçekleştirilenHackathon’aUğurAyaz ilekatıldık。 她的母亲和孩子之间的关系由她的母亲和女儿组成。 安卓系统uygulamasınıpaylaşmakister memnunkalırız,eminim anlatacakşeylerivardır’bilseniz iyi olur’dediği。 AyrıcaAbdullahGülÜniversitesi/计算机协会’ye de,bu vesileyle bir kez dahateşekkürüborçbilirim。 Harika bir ekipsiniz,güzelinsanlardanoluşan。 Etkinlikkapsamındakonu belli olduktan sonra verilensüreiçerisindeşuuygulamayıtasarlayıpgeliştirdim: Projegeliştirirken18个人资料GitHub’aattım。 从olacak到güzelbiranıolarak kalacak。 🙂 Proje Linki:https://goo.gl/WGsS2a iOS应用程序MVC mimari paternini mutlakaduymuşsunuzdur。 Zira Start-> New-> ProjectdediğimizdeXcode bizimiçin默认olarak MVC mimarisinioluşturuyor。 Pekigerçektenöylemi? iOS版本的MVC MVC模式在gerçekalanınındışındakullanılmasındandoğandezavantajlar var中。 您可以在MVVM’ingüzelbir alternatifolduğunudüşünüyorum中进行操作。 Zira ben deyukarıdabahsettiğimprojeyi MVVM mimarisiüzerindeinşaettim。 MVVM […]