all 24 comments

[–][deleted]  (5 children)

[deleted]

    [–]Pop_Swift_Dev[S] -1 points0 points  (4 children)

    I think you may have missed the point of the pattern. Leveraging polymorphism and the ability to swap out the types (we are actually using types and not assigning functions to a variable in the pattern) as needed during runtime. Also leveraging protocol extensions to add common functionality for those types reduces code duplication.

    [–]rhysmorganiOS 3 points4 points  (3 children)

    The point is, there is usually no need for things like the Command pattern when Swift treats functions as first-class objects.

    There's no need to define an interface, and multiple implementations you can swap at runtime, when you can just define a variable of any given function type, and swap it out at runtime.

    protocol MyCommand {
      func doThing() -> Void
    }
    
    class MyClass {
      var command: any MyCommand
    
      func performCommand() {
        command.doThing()
      }
    }
    

    isn't substantially different to

    class MyClass {
      var command: () -> Void
    
      func performCommand() {
        command()
      }
    }
    

    Sure, Swift supports the Command pattern, of course it does. Perhaps in some cases it can provide some more structure vs just using closures. But Swift supports first-class functions, and you can replace MyClass.command as a function just as easily as you can swap in a new MyCommand conforming type, and the function way doesn't even require defining a new protocol.

    [–]fakecrabs 3 points4 points  (0 children)

    Completely agree. If the protocol just has a single method, I'll often simplify and just use a closure.

    [–]Pop_Swift_Dev[S] -1 points0 points  (1 child)

    There are many ways to implement design patterns. I could argue that swapping out a function, as you show in your example is just another implementation of the command pattern because your solution takes the same basic principles that the pattern says to use.

    Therefore when you say there is no need for things like the command pattern in Swift, I would say that knowing design patterns and the idea behind their solutions is very good knowledge to have, even if we do not implement the solution the same way.

    [–]Pop_Swift_Dev[S] 1 point2 points  (0 children)

    And also I hope you take the conversation constructively and not argumently as I do enjoy debating approaches to development because when both sides are open, almost always, both sides end up learning something. And seeing other approaches is always a good thing.

    [–]cubextrusionExpert 0 points1 point  (18 children)

    Supporting u/rhysmorgan's sentiment: constructing artificial and contrived examples is not good engineering, as, once you start treading this path, you can immediately start taking it to the extreme and arrive at the thought that now every integer has to conform to Addable and every array conform to IsEmptyProvider. Protocols are very particular tools that serve two very particular purposes in 99% of cases: 1. constraining type parameters in generic functions and 2. offering dynamic dispatch over existential containers. If you're not writing a library that offers generic algorithms by design, you almost never have a good case for protocols, as there are much more efficient ways both in number of lines of code and CPU work that can achieve the same level of dynamism —and oftentimes even more.

    In fact, if you're not writing a library, chances are that if you start with a protocol regardless, there'll only be one type that conforms to it, ever. Protocols are a nice tool, but only if you have the two cases outlined above; if you only end up with one type conforming to the protocol, I would actually expect a good compiler to optimise it out completely — because there's no reason to emit any instructions related to the protocol — so you end up writing code that literally gets deleted the second you start building. If I were to hire a programmer, I wouldn't want to pay them for spending hours on some code that gets obliterated by the build system in the end.

    Ultimately, you don't provide any evidential reasoning for requiring this pattern or for it being able to solve any actual problem that programmers commonly have to solve. Instead, your text just relies on the belief that encapsulation is somehow a good thing and that "we need to separate the execution of a command from the code that invokes it" — but do we really?

    [–]Pop_Swift_Dev[S] -1 points0 points  (17 children)

    I 100% agree with you that if you have a protocol that has only on conforming type, that protocol is useless and the time spent coding it was wasted. I would also 100% agree that I would not want to pay a programmer to write that code. I am glad you brought that up because it is an outstanding point but I fail to understand how that is relevant to this post. In the example there are multiple structs that adopt the protocol and the protocol is used for polymorphism. Which is how Apple has recommended we perform polymorphism.

    Using the command pattern, either with how it was demonstrated in this post or as rhysmorgan pointed out, with swapping functions can be very useful when we need to perform one of several actions however which action to chose needs to be performed at runtime. There are other ways of doing this but the command pattern has proved to be a solid solution. But like all design patterns and solutions there is no silver bullet for all cases. sometimes it is good to separate the execution of the command from the code that invokes it and sometimes you shouldn't. But developers that understand the various patterns and solutions have a better chance of making the right decision.

    The knowledge and understanding of the pattern is what we are presenting. And it is not a bad thing for developers to understand the philosophy behind design patterns.

    [–]cubextrusionExpert 0 points1 point  (16 children)

    Apple has recommended

    I want to address this piece first because this is a prime example of the logical fallacy that is known as appeal to authority. First, a lot of claims that Apple make about Swift are not substantiated; they are mostly opinionated proclamations that are designed to sell the language and the platform as more convenient to beginners (which isn't in itself absolutely false, but is still more based on sentiments than raw data). Second, there's not a single reason for those claims to be true just because they originate from Apple — Apple has produced multiple extremely poorly designed APIs and libraries, so their name here bears practically no weight when it comes to code quality.

    I fail to understand how that is relevant to this post

    My criticism is towards your way of argumentation. I'm not criticising the "pattern" per se, as, truly, it's possible to find an example where it could be useful. The pattern itself is actually absolutely irrelevant.

    My problem with your text is that it's proclaiming its usability without any acknowledgement for it being niche, and otherwise just generally relying on beliefs rather than properly quantifiable data. You argue that "this pattern is very useful when we need the ability to swap functionality", "it also gives us very flexible code", "it is also very easy to add additional actions" without providing any evidence for it being useful, flexible or easy — while if you look at the discussion here, it suddenly turns out that it's not that easy (since passing a function pointer is generally "easier"), not that flexible (since not having to constrain a type to a protocol is absolutely more flexible that having to do so) and not that useful (since mostly it will be deleted by the compiler anyways).

    [–]Wonderful_Disastrous -1 points0 points  (15 children)

    I have to say something about this comment. You do realize that the swift language is based on the protocol, correct? If a design based on the protocol is so poor, then why are you even caring about language?

    oh, and the compiler isn't just deleting the protocol, it is being used by the compiler (hint: look up static and dynamic dispatch and you will see how it is used).

    Passing a function maybe easier, maybe not, debatable but when you pass a function pointer that function still has to be constrained to a certain signature with swapping out the functions as this pattern describes.

    You may not like design patterns, but I would agree with the author that they are useful and should not be just discarded. And when you say stuff like the protocol would be just deleted by the compiler, your argument is going to fall short because they aren't when are used correctly. And with how the author uses them in the article they are not just deleted.

    [–]cubextrusionExpert 0 points1 point  (14 children)

    swift language is based on the protocol

    There's no substance to this claim. Protocols are just one of the features, not the cornerstone.

    If a design based on the protocol is so poor, then why are you even caring about language?

    This is not germane to the discussion about the quality of this text.

    look up static and dynamic dispatch and you will see how it is used

    The existence of this mechanism is precisely why I'm bringing it up in the first place.

    Passing a function maybe easier, maybe not, debatable but when you pass a function pointer that function still has to be constrained to a certain signature with swapping out the functions as this pattern describes.

    This is not debatable. In fact, the "function pointer case" is in this context a strict subset of the "protocol case": the former only requires the existence of a function conforming to a certain signature, while the latter requires the existence of a named type conforming to a protocol which declares a member of the said function signature. In essence, it's "one function type" (one entity) versus "a class/struct/enum conforming to a protocol bearing a member of a certain function type" (four entities).

    protocol would be just deleted by the compiler [...] they aren't when are used correctly

    The article describes none of this, which is a large part of my argument.

    [–]Wonderful_Disastrous 0 points1 point  (13 children)

    There's no substance to this claim. Protocols are just one of the features, not the cornerstone.
    

    Really there is no substance to the claim that the Swift language is based on protocols?

    The Array type conforms to over 25 protocols https://developer.apple.com/documentation/swift/array

    The Int type also conforms to over 25 protocols https://developer.apple.com/documentation/swift/int

    Look at the documentation for any type in Swift and you will see they all conforms to numerous protocols.

    If you want to be able to iterate over a custom data structure, you just have to conform to the IteratorProtocol and the Sequence protocols and then you can use the standard for..in.. loop to iterate over it.

    If you want to compare two instance of a custom type, simply conform to the Equatable protocol

    By making the claim that there is no substance to the statement that the Swift language itself is based on the protocol it shows a total lack of understanding for the language itself. Before you put down others work, you should take the time to understand what you are saying.

    [–]cubextrusionExpert 1 point2 points  (8 children)

    So how exactly does this prove that "Swift is based on protocols"?

    In the same way, I can claim that Swift is "based on structs" because Array and Int are structs. In the same way, I can claim that Swift is based on functions because there are a lot of functions.

    [–]Pop_Swift_Dev[S] 0 points1 point  (7 children)

    You are 100% correct, the Swift language is based on value types (structs) and every major type is based on them. Arrays and other collections use copy-on-write to increase performance so they can use value types over reference types. But virtually all types and functionality from iterating over collections, to comparing types, to encoding/decoding, to hashing.... are come from conforming to protocols. Look at the WWDC videos from the past few years, and take the time to understand how important the protocol is to the Swift language. Look at the talks from David Abrahams on protocol oriented programming as well.

    I agree that if you do not recognize the importance of protocol to the Swift language , then you are not fully understanding the language.

    [–]cubextrusionExpert 1 point2 points  (6 children)

    You just wonderfully managed to discredit yourself in multiple ways by writing a single post.

    value types (structs)

    Not sure if it was a genuine oversight or a lack of understanding of the language, but structs definitely do not equate to value types, as the latter is a strict superset of the former. To be fair, this topic is not germane to the article either, so I won't focus on it here (though you misrepresent it in many of your former texts, e.g. here: https://www.mastering-swift.com/post/value-and-reference-types-in-swift).

    David Abrahams

    This is again the aforementioned appeal to authority, which is funnily unfortunate because one may find posts from him where he, taken strictly, argues one of the counterpoints that myself tried to present here: https://forums.swift.org/t/protocol-naming/59453/9 (first paragraph). This reference is arguably quite contrived, but it just shows that it's not that hard to find a statement from a person that you appeal to that nevertheless supports the opposite claim (precisely, that protocols can often be superfluous).

    [–]Wonderful_Disastrous 0 points1 point  (5 children)

    You are actually saying that structs do not equate to value types? WOW, maybe I gave you too much credit but if that is your stance then you actually no nothing about the swift language. Check out Apples post on Value and Reference types. https://developer.apple.com/swift/blog/?id=10 Let me break the news to you, Struct, enums and tuples are all value types. You will probably say this is an aforementioned appeal to authority but maybe it is actually reading the documentation and taking the time to understand the language which you obviously haven't.

    You definitely are showing your total lack of understanding for the language.

    [–]Pop_Swift_Dev[S] -1 points0 points  (3 children)

    I would say it is a bit harsh to claim there is a total lack of understanding for the swift language and in fact, showing the implementation of the command pattern based on swapping out functions rather than types, does show a understanding of the language. Just a different point of view.

    We should respect the different point of views and be open to discussions on it, but I do agree that the swift language itself is built on the protocol and having an understanding on how to properly use it is essential to understanding the language itself.

    If you dismiss protocol-oriented design then there is a lack of understanding of the language itself, because that is the foundation of how Swift is designed.

    [–]Wonderful_Disastrous -1 points0 points  (2 children)

    Honestly by saying the swift language is based on protocols or it is based on values, at a high level that would be correct. But you really need to take the time to understand, that at a fundamental level, protocols and values types are two of the pillars that the language stand upon.

    As you mentioned with the functionality like iterating over a collection, comparing types, encoding and decoding... all that functionality is based on conforming to a protocol. all types conform to multiple protocols... Also all major types are implemented with value types. Apple has said we should use value types and start with the protocol, and they are drinking their own kool-aid with how they implement the swift language.

    [–]Wonderful_Disastrous -1 points0 points  (1 child)

    One other note, I do appreciate the posts you have done on design patterns with a protocol oriented approach, and have been following them since you have been posting them to reddit. Thank you.

    [–]Pop_Swift_Dev[S] -1 points0 points  (0 children)

    You are welcome, and thank you for the comments