> On Nov 3, 2017, at 11:45 AM, Mike Kluev <mike.kl...@gmail.com> wrote:
> 
> On 3 November 2017 at 18:08, Adam Kemp <adam_k...@apple.com 
> <mailto:adam_k...@apple.com>> wrote:
> 
> 1. You end up with a whole section of type aliases at the top of the file,
> 
> i'm putting those in a separate Platform.swift file
>  
> and as you read the file it’s hard to understand what those types actually 
> represent.
> 
> in the example above "View" - a very similar concept between macOS and 
> iOS/tvOS/watchOS.
> in case of doubts - command click is always at the finger tips.
>  
> Which methods are you actually allowed to use? What should code completion 
> show you? 
> 
> autocomplete shows the relevant methods on each platform correctly.
> 
> 2. The type alias is only useful when the naming of the methods/properties is 
> identical and the sequence of calls you have to make is identical, which very 
> often isn’t the case. You end up needing conditional compilation anyway for 
> cases where you only need to make a call on one platform, or where the method 
> you have to call is named slightly different or takes different arguments.
> 
> if the differences are minute i'm creating my own extension methods to make 
> the difference non existent.
> 
> example: layer is optional on OSX and non optional on iOS. the difference is 
> minute and i can make this difference non existent, e.g. by:
> 
> extension UIView {
>     var viewLayer: CALayer? {
>         return layer
>     }
> }
> 
> and a similar thing on OSX, and afterwards i have single API on both 
> platforms with no differences.
> 
> You end up needing conditional compilation anyway for cases where you only 
> need to make a call on one platform, or where the method you have to call is 
> named slightly different or takes different arguments. 
>  
>  
> i rarely have to use conditional compilation and even when have to do so i 
> normally hide it inside the relevant "utility" extensions, from then on i 
> don't see anything "conditional" within the normal app sources.
>  
> Out of the strategies I’ve seen used for cross-platform code this one was the 
> most frustrating to work with in my experience.
> 
> quite the contrary to me - the best possible experience with such an approach 
> (during many years of experience ftm)

All I can say is, again, I’ve worked with code that plays these tricks, and I 
found it much harder to deal with than the code that used partial classes. 
You’re using all the tricks you can to make it work, but in my experience those 
tricks add up to a code base that is harder to work with and harder to 
understand and more brittle than the alternative approach I described. The 
tricks are part of what makes it confusing. At the risk of sounding 
presumptuous, I think if you could actually try the other approach (i.e., if we 
actually had partial classes that work like in C#) you would likely agree. 
Unfortunately it’s hard to do that comparison when you haven’t tried both 
approaches in real world situations.

>  
>> My argument is that there should be no ledger in the first place. IMO you 
>> haven’t made the case for that requirement.
> 
> the real-world example would be:
> 
> case 1. you have a single page of paper on hands saying: "partial contract A. 
> continued elsewhere. Blah, blah". you look around and within a multitude of 
> papers on the table you managed to find another sheet of paper with "partial 
> contract A. continued elsewhere. Blah, blah". in order to find the whole 
> thing you will have to look in all papers on your table, then in the shelve 
> and then in the whole building (module boundaries)

This is not how it works in practice. In practice the files are right next to 
each other with similar names. It would be more like having “to be continued” 
at the end of a book sitting right next to another book with the same name plus 
“Volume 2”. I think you would know where to look.

If you work with people who can’t follow conventions and would try to extend 
partial classes from random places then I’m sorry. :)

You may notice that this has echoes to our earlier conversation where I was on 
the other side of a very similar disagreement about extensions. I argued that 
extensions would lead to confusion because they can be thrown anywhere, and 
someone pointed out that there are file naming conventions for that. I think 
this is different because extensions are very often included in random files 
where they are most convenient. They have a different meaning and a different 
use case that I think encourages their use in files that are not named after 
the class they’re extending.

Partial classes aren’t intended to be used that way so it really never makes 
sense to have a partial class implementation in a file that is not dedicated 
specifically to that partial class implementation. That would raise red flags 
during code reviews. It’s a very simple rule to follow: if you see “partial 
class Foo” then the file name better start with “Foo”.

If I thought it made sense to have the compiler somehow enforce the file naming 
scheme for partial classes I would propose doing that, but it really doesn’t 
make sense. I don’t think the compiler works that way, and that’s probably for 
the best.

As for cross-module usages, absolutely under no circumstances do I want this to 
be supported across modules. I don’t think either of our approaches would work 
that way so that’s probably not something we need to debate.

>> i mean this:
>> 
>> class MyView: UIView {
>>     optional part Drawing
>> }
>> 
>> part Drawing of MyView { // **** forgot to include this into target
>>     override func drawRect(...) {
>>         .....
>>     }
>> }
>> 
>> the app compiles but doesn't work correctly.
> 
> That example doesn’t make any sense.
> 
> i don't see why (and I am not talking about cross platform code at this 
> point). i have instances like these implemented via extensions in a day to 
> day code. the split of the class into files was done merely for organising 
> purposes, to keep file size manageable.

I meant that if you’re doing cross-platform coding using partial classes as 
I’ve described then the scenario you described is an example of doing things 
the wrong way. What I’m saying is there is a way of doing things with partial 
classes in C# where if you follow the pattern then you can’t run into those 
problems because you will get build errors. If you don’t follow the pattern 
then bad things could happen, just like with so many other things in 
programming. There are practices that lead to brittle code and practices that 
lead to robust code. Using partial classes in C# has best practices that avoid 
those problems, while at the same time allowing for people to work very 
efficiently.

Your ledger idea might theoretically prevent some of those bad things from 
happening, but at the expense of making the whole thing unusable for this use 
case. That’s not a good trade off.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to