[HN Gopher] Swift Protocol Oriented Programming and Testing
       ___________________________________________________________________
        
       Swift Protocol Oriented Programming and Testing
        
       Author : geekylife
       Score  : 53 points
       Date   : 2021-07-30 15:46 UTC (7 hours ago)
        
 (HTM) web link (arturgruchala.com)
 (TXT) w3m dump (arturgruchala.com)
        
       | solarexplorer wrote:
       | I have seen this a lot, am I the only one who thinks that this is
       | ugly?
       | 
       | Crafting a protocol after the fact to match some class' interface
       | (and then put an empty extension) seems just wrong.
       | 
       | I very much prefer to pass simple types around. (like two
       | closures in this case) You don't need to remember any protocol
       | name and don't need to define a ton of mock objects.
        
       | peey wrote:
       | Suggestion: title should be renamed to "Protocol Oriented
       | Programming and Testing in Swift".
       | 
       | "Swift Protocol" is something else entirely
       | https://docs.openstack.org/swift/latest/
        
       | bww wrote:
       | This sort of thing is a common pattern in Go, where it is
       | accomplished by the fact that Go interfaces do not require types
       | to opt into them by declaring their adoption. If a type conforms
       | to the interface it's a type of the interface.
       | 
       | So one can create a new interface type that supports the specific
       | subset of functionality you need from a larger type that you
       | don't control and use it in a similar way to Swift protocols.
        
         | monocularvision wrote:
         | While you have to declare it, you can do the same in Swift
         | using an extension.
        
       | pixel_tracing wrote:
       | Not that great of an example to be honest.
       | 
       | For starters the use-case which was defined `UserDefaults` you
       | can just use a property wrapper to make it easier. Then in your
       | class you can do:
       | 
       | @Defaults(key: "usesDarkTheme") var usesDarkTheme: Bool
       | 
       | Now it uses type erasure under the hood and call sites are
       | cleaner.
       | 
       | For PoP, it's kind of outdated. Better to use Value Oriented
       | programming nowadays
        
         | amw-zero wrote:
         | They go hand in hand, because values can still implement
         | protocols.
        
       | armchairhacker wrote:
       | This was popular in Java (see libraries with "Foo" interface and
       | "FooImpl" class).
       | 
       | Sometimes it really is useful, but it was over-used in Java. A
       | lot of times you don't even need a mock.
       | 
       | In fact a lot of times even a singleton is good enough. YAGNI. I
       | don't think the example was good: in the "potential situation"
       | where you actually need a second `UserDefaults`, you could've
       | just find and replace. Maybe for a massive project, but I've
       | never worked on something too big for doing things like to avoid
       | Shift-Ctrl-F.
        
         | liuliu wrote:
         | Rule of thumb is always: if you need it, do it, otherwise,
         | don't. Real world cases could be:
         | 
         | 1. If you write a unit tests and really need to have a double
         | of that particular component, then do it. Otherwise, don't.
         | 
         | 2. You need to decouple the dependency (maybe these are
         | circular), then do it. Otherwise, just take on it as a
         | dependency.
        
           | ratStallion wrote:
           | #2 is interesting...can you give an example solving circular
           | dependencies? Even if you had an interface, wouldn't you
           | still have the implementations still causing a circular
           | dependency?
        
             | amw-zero wrote:
             | You can turn A->B, B->A into A->I,B->A + A.I=B and that
             | does avoid a circular dependency.
             | 
             | A->B means a depends on B, A->I means A depends on an
             | interface, and A.I=B means that B is set as the
             | implementation of the I interface that A depends on.
             | 
             | I'm on mobile so that was the best I could come up with.
             | Try it out using Swift though, and that can be translated
             | pretty directly.
        
         | marcellus23 wrote:
         | The same problem exists in Swift. I inherited an iOS project a
         | couple years ago where the original dev over-used protocols
         | like crazy. The result is spaghetti code that's impossible to
         | understand. Luckily we're mostly replacing it with simple
         | encapsulation now.
        
       | 3grdlurker wrote:
       | POP was an exciting idea when it first came out, but in practice,
       | it just doesn't make sense to "orient" your codebase towards
       | protocols. I've seen a project that was faithful to this and they
       | came up with a codebase that's extremely difficult to maintain
       | and read because they made more abstractions than they need, and
       | they defined so many custom types that the requisite vocabulary
       | became huge.
       | 
       | Protocols have their uses, but MVC works really well and scales
       | really well in making apps for Apple platforms.
        
         | mpweiher wrote:
         | Well...it also wasn't really new, POP is just OOP by people who
         | didn't understand OOP (and overcomplicated it)
         | 
         | https://blog.metaobject.com/2015/06/protocol-oriented-progra...
        
           | dgb23 wrote:
           | Funny article!
           | 
           | Yes, OO as defined by Alan Kay was about the interface,
           | protocol or what ever we call it in a given language. It's a
           | tool for abstraction, so you think about communicating
           | instead of structure and state.
           | 
           | Now, most modern (~10y/o) general purpose languages I know
           | have moved away from ADTs or simply inheritance. Inheritance
           | was just a means to an end and never the point.
        
           | ribit wrote:
           | Unfortunately, the notion "OOP" has been taken hostage by C++
           | and Java and they don't want to give it back.
        
           | Apocryphon wrote:
           | "Compiler Oriented Programming"... nice one.
        
         | iddan wrote:
         | Rust makes a great example of POP in scale. They are called
         | traits there but it's the same thing
        
         | 90minuteAPI wrote:
         | Swift is multi-paradigm. Improved support (over ObjC) for
         | functional style, protocol-oriented design, and value types has
         | led many to overuse them.
         | 
         | Multi-paradigm isn't a cop-out, it's a pretty specific goal of
         | the language. Being overly "faithful" to particular patterns
         | will conflict with this, as you've likely experienced. I
         | appreciate the ability to break out and use different styles
         | where appropriate. That pesky "last 10%" is now far less
         | painful. It also allows for varying styles per module based on
         | functionality required and libraries in use.
        
         | Someone wrote:
         | _"because they made more abstractions than they need"_
         | 
         | If you replace _protocol_ by _trait_ , _class_ , _function_ ,
         | _macro_ (basically anything that was invented to allow
         | abstraction), the statement remains true, So I don't think
         | that's a good argument against protocol-oriented programming.
        
           | 3grdlurker wrote:
           | If you're not using protocols almost everywhere though, is
           | your code really protocol- _oriented_?
           | 
           | I don't even want to bother with answering that question,
           | though. Even Apple didn't have a clear definition for it, so
           | debating this point seems moot to me, I'm afraid.
        
             | jolux wrote:
             | Rust pretty much only has protocols, and people seem to do
             | fine programming with it. Type classes (protocols, traits)
             | and regular classes are both different ways of achieving
             | polymorphism, which every abstraction needs. It's just a
             | question of whether you think about your application as
             | oriented around types or oriented around objects.
        
         | swiftaccount1 wrote:
         | I made a new account just to ask this: 'MVC works really well
         | and scales really well" Is this a joke? Do you have any
         | professional iOS experience?
         | 
         | MVC is famous for scaling terribly on iOS and resulting in view
         | controllers with thousands of lines. MVC is great for small
         | apps. No need to overcomplicate things. But if you're building
         | something bigger, you should look into using the right tool for
         | the job. Don't blindly follow a popular pattern, but choose the
         | right pattern to make the code easy to read, easy to test, and
         | easy to modify.
        
           | ardit33 wrote:
           | Do you realize that the whole Apple's UIKit Framework is a
           | version of MVC?
           | 
           | I have seen many versions for it in iOS, MMVC, MVVC, or
           | whatever, but really they are iterations of separation of
           | business logic and view/display logic.
           | 
           | You can disperse the view logic, without having traditional
           | centralized controllers, but your business logic will end up
           | centralized in one place. So, in practice you end up with a
           | Model-Business-Logic / View paradigm, where traditional
           | controllers end up just being a thin layer.
           | 
           | Protocol driven development, reminds me the old Java style of
           | having a class (eg. MyFunctionalityClass), which was either
           | abstract, or had only protocols declared, then have another
           | MyFunctionalityClassImpl to actually implement it.
           | 
           | I didn't think it was pretty, and it seemed it was done by
           | C++ developers to simulate the lack for header .h files in
           | Java.
           | 
           | Ps. Before you reply on a ad-hominen way, I probably have
           | much more iOS experience than you, since I both have worked
           | on it since day one, and have worked on some the currently
           | largest apps in the world.
        
             | swiftaccount1 wrote:
             | I basically agree with you, actually. It feels like a lot
             | of this is breaking down into semantics. I'm not fond of
             | acronyms, I believe it's important to go to core principles
             | and never do anything blindly, but only when it's useful.
             | 
             | The fundamental challenge of iOS architecture is picking
             | the right level of abstraction for the complexity of your
             | application.
             | 
             | The trouble that comes in with MVC, as I see it, is how
             | easy it is to shoot yourself in the foot. It's too easy to
             | do it "wrong", which is why so many have tried to come up
             | with something different. Of course you can't escape the
             | MVC-ness of the platform, it's all about how you manage it.
        
           | Apocryphon wrote:
           | The problem is that the Cocoa framework, even after the
           | advent of Swift, has always been created with MVC in mind.
           | We're now at a point in iOS where trends have rolled around
           | and now people are saying to pick MVC because that was
           | Apple's intention, other architectures were created because
           | people were doing it wrong:
           | 
           | https://medium.com/flawless-app-stories/the-only-viable-
           | ios-...
           | 
           | Obviously most significant production apps are using variant
           | architectures such as at the bare minimum having view models,
           | and the introduction of SwiftUI and popular earlier
           | frameworks such as RxSwift also complicates things. Most apps
           | aren't using pure MVC, sure, but it doesn't mean that the
           | architecture isn't scalable. The alternatives might also be
           | pretty gnarly:
           | 
           | https://developer.squareup.com/blog/ziggurat-ios-app-
           | archite...
        
             | swiftaccount1 wrote:
             | That's an interesting article. I find iOS architecture
             | fascinating and spend a lot of time thinking about it. It
             | seems like "MVC" in common usage (based on talking to other
             | iOS devs) means spaghetti, but I guess it doesn't have to
             | be like that.
             | 
             | To me that article proposes a more disciplined MVC than
             | what I've seen in real codebases. I think a lot of the
             | architectures people come up with (like the second one you
             | linked) try to build that discipline in. I try not to be
             | dogmatic and instead go to core principles. Do I know what
             | this class is supposed to be doing? Are my data and view
             | layers reasonably separated with minimal glue code? Can a
             | new dev easily navigate this project?
             | 
             | It's an endless discussion with no right answer. Thanks for
             | sharing!
        
               | smoldesu wrote:
               | > I find iOS architecture fascinating and spend a lot of
               | time thinking about it.
               | 
               | > It's an endless discussion with no right answer.
               | 
               | These don't seem like the hallmarks of a well-designed,
               | mature platform.
        
           | 3grdlurker wrote:
           | > Is this a joke? Do you have any professional iOS
           | experience?
           | 
           | Let's just say that I can build a view controller for a
           | large, multi-sectioned list where each section calls a
           | different APIs and shows items with different layouts, and
           | still end up with less than 500 lines of VC code even with
           | generous line breaking. Oh, and I can make custom
           | UICollectionView layouts with self-sizing headers and cells.
           | 
           | That said, your comment is just ad hominem and you should be
           | downvoted to oblivion.
        
             | gregkerzhner wrote:
             | How do you manage data flow from your view layer to your
             | API layer? Like for example, if a UITableViewCell has a
             | button in it which needs to load some data from the API? Do
             | use an event/delegate which flows from the UITableViewCell
             | through the `cellForRowAtIndexPath` method to the
             | controller, out to some other class? It must feel pretty
             | great to have your business logic and API layers abstracted
             | into other classes, and have your lean view controller just
             | be the glue. Yay MVC!
             | 
             | Now imagine that your table view has 20 cells, and each
             | cell is managed by a team of 5 people and needs 1,000 lines
             | of code to fulfill its business logic. How would this
             | approach hold up? Would you have all 100 people working on
             | the same `cellForRowAtIndexPath` method, piping every event
             | for those 20,000 lines of code through there?
             | 
             | When people talk about scale on iOS, they are talking about
             | potentially 100s of people working on the same screen. With
             | something like React, this is trivial by having each team
             | work independently on its own components. With iOS, its
             | much harder out of the box.
        
             | swiftaccount1 wrote:
             | Yeah, sorry for the choice of words; I just fired something
             | off with no editing. In my mind, I was thinking of MVC at
             | it's worst (which is unfortunately common).
             | 
             | That being said, would love to learn more about how you
             | structure code. What does a project structure look like for
             | you? I usually conceptually try to separate the view and
             | data starting with the simplest file structure and dividing
             | as needed.
        
           | jmull wrote:
           | There's nothing about MVC that makes you put thousands of
           | lines in a controller. I don't know of any software
           | development patterns that will stop you from writing
           | spaghetti code or adopting "ball of mud" design if you decide
           | to do that.
        
             | swiftaccount1 wrote:
             | I'm not sure if I fully agree with that. It's true that you
             | can spaghetti with any pattern, but I think on multi dev
             | teams it helps to have guidelines about what goes where to
             | ensure a clear separation of responsibilities. Someone
             | linked another thought provoking article here about how MVC
             | does not have to equal spaghetti which I found interesting.
             | But I also think we need to take a step back and ask, "why
             | have so many ended up with the same result?"
        
               | 3grdlurker wrote:
               | Well I also used to make giant controllers when I was a
               | beginner. That's why you can pretty much "spaghetti with
               | any pattern".
               | 
               | Over time I realized that I can just create dedicated
               | controllers or handlers or managers or services with more
               | specific and limited functionality, and then my VCs
               | simply dispatch to those. It's called composition.
        
           | gregkerzhner wrote:
           | I fully agree here - MVC scales terribly. Of course, it's not
           | impossible to come up with a well designed MVC app at scale,
           | but it takes a ton of skill and feels like you are fighting
           | the framework at most steps.
           | 
           | One particular challenge is lack of modular components and
           | component nesting. For example, if you have a list view, it's
           | very natural to have one component define the list, and child
           | components define each entry in the list. Something like
           | React makes this trivial.
           | 
           | On iOS on the other hand, you are encouraged to use a
           | UITableViewController with UIViews for each cell. This
           | immediately pushes you towards one mega-controller which
           | mixes the responsibilities of the list with those of the
           | individual cells. To overcome this, you could try to have a
           | UIViewController for each cell (uncommon), or have the UIView
           | of each cell start taking on more responsibilities of a
           | UIViewController (breaking MVC).
           | 
           | In general though, iOS's MVC is a perfect storm of being both
           | bare bones as well as opinionated at the same time. For these
           | reasons many large corporations have moved away from MVC to
           | their own custom in-house architectures to handle scale _.
           | 
           | _ Facebook - https://www.youtube.com/watch?v=mLSeEoC6GjU. *
           | Uber - https://github.com/uber/RIBs * Square -
           | https://github.com/square/workflow
        
           | mpweiher wrote:
           | > MVC is famous for scaling terribly on iOS
           | 
           | You have to distinguish between MVC, which scales really
           | well, and what Apple _calls_ "MVC", which does not.
           | 
           | https://blog.metaobject.com/2015/04/model-widget-
           | controller-...
           | 
           | And yes, the fact that they overloaded the term is a problem.
           | 
           | https://blog.metaobject.com/2017/03/concept-shadowing-and-
           | ca...
        
           | [deleted]
        
       | ChrisMarshallNY wrote:
       | I'm looking forward to using PoP more; especially as I move into
       | SwiftUI (Which was designed for it).
       | 
       | Right now, I am still very much in polymorphic OO land, as I am
       | working on a classic UIKit app (It's a bit of a kludge to use PoP
       | in UIKit, as UIKit was designed with the classic MVP pattern in
       | mind).
       | 
       | But I'm not a fan of dogma. It's just another tool. I sometimes
       | use techniques I learned in the 1980s.
        
       ___________________________________________________________________
       (page generated 2021-07-30 23:01 UTC)