All Projects → ochococo → Super Simple Architecture

ochococo / Super Simple Architecture

Licence: mit
🧩 Super Simple Architecture in Swift

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Super Simple Architecture

Domain Driven Hexagon
Guide on Domain-Driven Design, software architecture, design patterns, best practices etc.
Stars: ✭ 4,417 (+9938.64%)
Mutual labels:  architecture, design-patterns, architectural-patterns
Game Programming Patterns
Source repo for the book
Stars: ✭ 3,096 (+6936.36%)
Mutual labels:  architecture, design-patterns
Flawless Ios
Awesome iOS guides from the community, shared on Flawless iOS Medium blog 👉
Stars: ✭ 260 (+490.91%)
Mutual labels:  architecture, design-patterns
System Design And Architecture
Learn how to design large-scale systems. Prep for the system design interview.
Stars: ✭ 1,005 (+2184.09%)
Mutual labels:  architecture, design-patterns
Peasy.NET-Samples
Showcases a middle tier built with peasy and consumed by multiple client consumers
Stars: ✭ 33 (-25%)
Mutual labels:  architecture, architectural-patterns
bian
The Banking Industry Architecture Network e.V. (BIAN) model in Archimate 3
Stars: ✭ 48 (+9.09%)
Mutual labels:  architecture, architectural-patterns
Swiftui Architectures
Three different architectures (Model-View, Redux, MVVM) for using SwiftUI implemented at the example of a chat app
Stars: ✭ 413 (+838.64%)
Mutual labels:  architecture, architectural-patterns
Quiz App
A repository reflecting the progress made on the "How to Build iOS Apps with Swift, TDD & Clean Architecture" YouTube series, by Caio & Mike.
Stars: ✭ 230 (+422.73%)
Mutual labels:  architecture, architectural-patterns
Modular Monolith With Ddd
Full Modular Monolith application with Domain-Driven Design approach.
Stars: ✭ 6,210 (+14013.64%)
Mutual labels:  architecture, design-patterns
Coordinator
Implementation of Coordinators app design pattern.
Stars: ✭ 616 (+1300%)
Mutual labels:  architecture, design-patterns
Ribs
Uber's cross-platform mobile architecture framework.
Stars: ✭ 6,641 (+14993.18%)
Mutual labels:  architecture, architectural-patterns
Notes
My notes are about everything related to programming.
Stars: ✭ 104 (+136.36%)
Mutual labels:  design-patterns, architectural-patterns
data sciences campaign
【数据科学家系列课程】
Stars: ✭ 91 (+106.82%)
Mutual labels:  design-patterns, architectural-patterns
archunit-junit5-kotlin
Generic Architecture Tests written in Kotlin using ArchUnit and Junit5
Stars: ✭ 22 (-50%)
Mutual labels:  architecture, architectural-patterns
awesome-software-architecture
A curated list of awesome articles, videos, and other resources to learn and practice software architecture, patterns, and principles.
Stars: ✭ 1,594 (+3522.73%)
Mutual labels:  design-patterns, architectural-patterns
Peasy.net
A business logic micro-framework for .NET and .NET Core
Stars: ✭ 406 (+822.73%)
Mutual labels:  architecture, architectural-patterns
Awesome Scalability
The Patterns of Scalable, Reliable, and Performant Large-Scale Systems
Stars: ✭ 36,688 (+83281.82%)
Mutual labels:  architecture, design-patterns
Archit Ios
Intelygenz iOS Architecture
Stars: ✭ 203 (+361.36%)
Mutual labels:  architecture, design-patterns
Urf.core
Unit of Work & Repositories Framework - .NET Core, NET Standard, Entity Framework Core. 100% extensible & lightweight. Live demo: https://goo.gl/QpJVgd
Stars: ✭ 226 (+413.64%)
Mutual labels:  architecture, design-patterns
Designpatternslibrary
A comprehensive design patterns library implemented in C#, which covers various design patterns from the most commonly used ones to the lesser-known ones. Get familiar with and learn design patterns through moderately realistic examples.
Stars: ✭ 485 (+1002.27%)
Mutual labels:  architecture, design-patterns

Super Simple Architecture

Swift5

Super Simple

Application Architecture you can learn in minutes.

Why?

Nobody is really smart enough to program computers.

Steve McConnell (Code Complete 2.0)

We believe we should compose software from components that are:

  • accurately named,
  • simple,
  • small,
  • responsible for one thing,
  • reusable.

Components

Types:

  • Active Components (ex. Interaction, Navigation, Mediator etc.)
  • Passive Components (ex. Renderable)
  • Views (ex. UILabel)

🖼 Renderable

Renderable (noun)

Something (information) that view is able to show.

Definitions

TL;DR

Renderable is a struct that you pass to a View which should show its contents.

Renderable is:

  • Passive,
  • immutable struct,
  • often converted from model or models,
struct BannerRenderable {
    let message: String
}

View should:

  • always look the same if ordered to render the same renderable,
  • have code answering to one question: "how should I look?",
  • have no state,
  • accept infinite number of renderables in random order.

Example

Step 1 - Create Renderable:

struct BannerRenderable {
    let message: String
    
    init(message: String) {
        self.message = message
    }
}

Step 2 - Expose View ability in Protocol:

protocol BannerRendering: AnyObject {
    func render(_ renderable: BannerRenderable)
}

Step 2 - Implement View:

final class BannerView: UIView {
    @IBOutlet fileprivate var bannerLabel: UILabel!
}

extension BannerView: BannerRendering {
    func render(_ renderable: BannerRenderable) {
        bannerLabel.text = renderable.message
    }
}

🛰 Interaction

Interaction (noun)

Component answering the question: What should I do in reaction to user action.

Definitions

TL;DR

Interaction is a final class that ViewController or View owns, which performs actions in reaction to user input - gestures, text input, device movement, geographical location change etc.

Interaction:

  • Active component (has a lifecycle),
  • final class,
  • can use other components for data retrieval,
  • should be literally between two actions, the one causing and the one caused,
  • can call navigation methods when other ViewController should be presented,
  • can call render methods on weakly held views (seen via protocol).

📌 RULE: There is no good reason for inheritance of custom classes, ever.

ViewControllers and Views:

  • Can have many Interactions for separate functions,
  • should OWN Interaction and see it via protocol,
  • subviews of VC could own separate Interaction but it’s not mandatory for simple VC.

Example

Step 1 - Create Interaction protocols:

protocol PodBayDoorsInteracting: AnyObject {
    func use(_ banner: BannerRendering)
    func didTapMainButton()
}

Step 2 - Add Interaction implementation:

📌 RULE: Do not tell Interaction what to do, tell what happened, it should decide what should happen next.

final class PodBayDoorsInteraction {
    fileprivate let killDave = true
    fileprivate weak var banner: BannerRendering?
}

extension PodBayDoorsInteraction: PodBayDoorsInteracting {
    private enum Strings {
        static let halsAnswer = "I know you and Frank were planning to disconnect me, and that is something I cannot allow to happen."
    }

    func didTapMainButton() {
        guard let banner = banner else { fatalError() }

        if killDave { // Just to show the business logic is resolved here.
            banner.render(BannerRenderable(message: Strings.halsAnswer))
        } else {
            // Open doors. Not implemented :P 
        }
    }

    func use(_ banner: BannerRendering) {
        self.banner = banner
    }
}

Step 3 - Use it in ViewController (via nib):

final class DiscoveryOneViewController: UIViewController {
    
    fileprivate let podBayInteraction: PodBayDoorsInteracting
    
    @IBOutlet private var bannerView: BannerRendering!
    
    init(podBayInteraction: PodBayDoorsInteracting) {
        self.podBayInteraction = podBayInteraction
        super.init(nibName: nil, bundle: nil)
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        podBayInteraction.use(bannerView)
    }
    
    @IBAction private func didTapMainButton() {
        podBayInteraction.didTapMainButton()
    }
}

🛠 Assembler

Assembler (noun)

Assembler is gathering dependencies and injecting them into a single instantiated component.

Definitions

TL;DR

Its purpose is to assemble dependencies for one class or struct.

Assembler:

  • a struct,
  • has only one method called assemble().
  • can call ONLY ONE initializer directly,
  • will call other Assemblers to instantiate dependencies.

Example

Step 1 - Create Interaction protocols:

📌 RULE: When assembled component is dependent on other instances, you should use it's Assemblers, do not initialize more than one class directly.

protocol PodBayDoorsInteractionAssembling {
	func assemble() -> PodBayDoorsInteracting
}

struct PodBayDoorsInteractionAssembler {
    func assemble() -> PodBayDoorsInteracting {
        return PodBayDoorsInteraction()
    }
}

protocol DiscoveryOneAssembling {
    func assemble() -> UIViewController
}

struct DiscoveryOneAssembler: DiscoveryOneAssembling {

    let interactionAssembler: PodBayDoorsInteractionAssembling

    func assemble() -> UIViewController {
        return DiscoveryOneViewController(interaction: interactionAssembler.assemble())
    }
}

let interactionAssembler = PodBayDoorsInteractionAssembler()
let viewControllerAssembler = DiscoveryOneAssembler(interactionAssembler: interactionAssembler)
let viewController = viewControllerAssembler.assemble()

🧭 Navigation

Navigation (noun)

Component responsible for presenting views (here: View Controllers).

Definitions

TL;DR

Interaction may need to open another View Controller in response to user's action, it has to use Navigation component to do that.

Navigation is:

  • A class,
  • owned by Interaction,
  • can push or open views modally,
  • will use Assemblers to create ViewControllers to show.

Example

📌 RULE: We should never pass classes directly, always via protocol or Adapter.

NavigationControlling.swift

protocol NavigationControlling: AnyObject {
    func pushViewController(_ viewController: UIViewController, animated: Bool)
}

// `NavigationControlling` is a protocol convering (some) methods of `UINavigationController`
extension UINavigationController: NavigationControlling { }

Step 1 - Create Navigating protocol:

📌 RULE: When A uses B but A is not an owner of B, pass B via use(_) method, not in init.

PodBayNavigation.swift

protocol DiscoveryOneNavigating: AnyObject {
    func use(_ navigationController: NavigationControlling)
    func presentDiscoveryOneInterface()
}

Step 2 - Implement Navigation:

DiscoveryOneNavigation.swift

final class DiscoveryOneNavigation: DiscoveryOneNavigating {

    private let discoveryAssembler: DiscoveryOneAssembling
    private weak var navigationController: NavigationControlling?

    init(navigationController: NavigationControlling, discoveryAssembler: DiscoveryOneAssembling) {
        self.navigationController = navigationController
        self.discoveryAssembler = discoveryAssembler
    }

    func use(_ navigationController: NavigationControlling) {
        self.navigationController = navigationController
    }

    func presentDiscoveryOneInterface() {
        let discovery = discoveryAssembler.assemble()
        navigationController.pushViewController(discovery, animated: true)
    }
}

Additional assets

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].