Norway


Swift extends the courtesy of an annotated to its top level members. I’m going to call this “inheritance”, but I know there’s a better name for this but I just don’t know what it is.

Consider the following:

// Base type is public
public struct MyStruct {}

// Here, the extension is declared public, so each top level member
// "inherits" that access level.
public extension MyStruct {
  // This is public even if it is not annotated
  static var firstValue: String { return "public" }

  // This is also public but the compiler will warn.
  public static var secondValue: String { return "public but warned" }

  // This class is also public via "inheritance" 
  class PublicSubclass {
    // However, its members must be annotated. This is public
    public static let publicValue = "public"
    // This defaults to internal
    static let internalValue = "internal"
  }
}

In this example, firstValue inherits the public access level from the MyStruct extension. The explicit annotation for secondValue is warned by the compiler as unnecessary.  If you treat warnings as errors, that’s a problem.

- Screen Shot 2019 02 14 at 10 - Extension Access Control — Erica Sadun

Each of the static properties are accessible outside the module except for internalValue, as even in a public class declaration, its members do not inherit its control level:

- Screen Shot 2019 02 14 at 11 - Extension Access Control — Erica Sadun

Before I start putting some preliminary style guidance out there, I’d like to point out a few more things about this. Here’s a second example:

internal class InternalType {}

extension InternalType {
  public static var value: String { return "value" }
}

Swift compiles this code without error. It is clearly a developer-sourced issue. The intent to make the member public is fundamentally flawed. as it exceeds the type’s access control level. This issue also exists outside of extensions, where the compiler will not warn on too-high levels for direct type members:

internal class AnotherInternalType {
  public var value = "value" // no warning
}

You’d imagine this is a place where the compiler should up its game, no? This is a point of code that is technically functional and compilable but whose specification undercuts the documenting nature of using access control. Shouldn’t the annotation be limited and warned here?

The compiler will find mismatches between the extension ACL and the type ACL:

- Screen Shot 2019 02 14 at 11 - Extension Access Control — Erica Sadun

And that’s where the problem comes in because the guidance I’m working on says: “Do not annotate extensions with access control levels except when working with trivial utilities”. Skipping extension ACL ensures that you can meaningfully and intentionally add access control to each member declared within that extension. Each access level is co-located with the declaration it decorates. This makes your code more easily audited and its access levels will be immediately apparent as to intent and implementation.

What are your thoughts? Can you think of any reasons why extensions should ever be ACL’ed in production code? And is this just a bug/language enhancement thing or is there something I’m missing. Thanks in advance for your feedback.



Source link
Based Blockchain Network

LEAVE A REPLY

Please enter your comment!
Please enter your name here