Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 463 Vote(s) - 3.42 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Proper namespacing (or class naming) convention in Swift frameworks (for iOS)

#1
**TLDR**

1. If framework is called **AEConicalGradient**, should classes in it be called **ConicalGradientLayer** and **ConicalGradientView** or just **Layer** and **View**?

2. If framework is called **AELog**, and it has class also called **AELog** and other class called **Line** with some delegate callback which is using this **Line** type, how to implement this delegate if your code also has defined type called **Line**, because adding framework name as a prefix in method signature `func didLog(line: AELog.Line)` will make error `'Line' is not a member type of 'AELog'` which in fact it isn't (it's part of **AELog framework**, but it's not member of **AELog class** inside of it).

**Read More**

While updating several frameworks of mine for Swift 3 I was having a lot of second thoughts about what's the proper naming convention for framework classes depending on framework name itself.

In the end I realized that I didn't really used same convention across different frameworks, so now I don't like this lack of consistency.

I'll jump straight into some real-world examples which I encountered:

**1. Example: Framework doesn't have a class named as framework name:**

Framework is named **AEConicalGradient** and it consists of 2 public classes:

- CALayer subclass
- UIView subclass

What should be proper name for each of these classes?

a) **AEConicalGradientLayer** and **AEConicalGradientView**

b) **ConicalGradientLayer** and **ConicalGradientView**

c) **Layer** and **View**

**Discussion:**

a) *I used this in the first version of framework with both of these classes in single **AEConicalGradient.swift** file. I don't like this approach anymore, I'm separating sources into multiple files so now I'm thinking between **b)** and **c)** approaches.*

b) *In this approach I like the fact that someone can just drag these files into project (e.g. without using any dependency manager) or copy/paste code and it wouldn't loose context too much (because of clear names), but on the other side it sounds a little bit repetitive if you think of it as **AEConicalGradient.ConicalGradientLayer** and **AEConicalGradient.ConicalGradientView**.*

c) ***AEConicalGradient.Layer** and **AEConicalGradient.View** sounds like the way I want it, but on the other side those are more likely to make a conflict if someone has their own **Layer** or **View** classes, or if they just drag files or copy/paste code context is pretty much lost (like what is this **Layer** or **View** class for?).*

**2. Example: Framework does have a class named as framework name:**

Framework is named **AELog** and it consists of 3 public classes and a delegate protocol:

- Shared Instance (and delegate for it)
- Log Line model
- Config

**Discussion:**

a) *Similar to the first example in the first version of framework I had classes named **AELog**, **AELogDelegate**, **AELogLine** and **AELogConfig** - all inside single **AELog.swift** file.*

b) *In the latest update for Swift 3 I ended up with multiple files and class names: **AELog**, **AELogDelegate**, **Line** and **Config**.*

*That's when I realized that if you `import AELog` and implement `AELogDelegate` (which has only `func didLog(line: Line)`) AND you already have a different `Line` class defined in your own module **it will make a conflict which can be solved only by renaming one of those two `Line` classes!***

*To be honest, I don't really understand how to avoid this. Because if you try to namespace type in delegate method like `func didLog(line: AELog.Line)` you'll get error `'Line' is not a member type of 'AELog'` which in fact it isn't (it's part of **AELog framework**, but it's not member of **AELog class** inside of it).*

*That's when I started to feel a bit concerned on this "loose" naming. Any suggestions or opinions on this specific matter?*

c) *In the spirit of very "loose" naming like in **1.c)** approach, is it ok to rename **AELog** class to just **Log**, and **AELogDelegate** to just **Delegate**? Would this fix error stated in **2.b)** because there's no class named same as framework name so maybe compiler would recognize **AELog.Line** in that case?*

**Question:**
What are some "clean code" arguments on either of these approaches? Is there an obvious "proper" way on how it should be done? Am I missing something important here?
Reply

#2
## TL;DR

1. The type names should be ConicalGradientView and ConicalGradientLayer. "View" and "Layer" are just not descriptive enough for the case of a "view" or a "layer" concept.

2. It is not possible for the Swift compiler to disambiguate a clashing module / type name in that context. You will not find code from Apple or from 3rd parties that use clashing names for frameworks / modules vs types within them. This may be for a technical reason, but it also would be confusing and your case of 'AELog' as a Swift type name is also not idiomatic.

## The long answer

The name of a type should somehow [describe its role][1] in the program you use the type in. Whilst this is of course subjective, I don't think a "View" is very descriptive name for a view subclass, given there are dozens of NSView / UIView subclasses in Cocoa alone and views fulfil potentially hundreds of roles across your own app. So, by the logic that just by seeing that unqualified type name alone you can't really make guesses about what it does, therefore it cannot be a good name. The module / namespace name's function is more to provide a minimal level of disambiguation that leads to undefined behaviour on name clashes (a luxury not available traditionally in C / Objective-C for example), but arguably its role is not to be routinely used in the fully qualified form.

Think about it also from a perspective of "what if I wanted to introduce a new variant of a View in my framework?" – a separate framework for specifically _conical_ gradients for instance sounds a little bit funny. A framework perhaps for different sorts of views that have a gradient to them sounds like a more reasonable "minimal size" for a framework (even if you may have implemented only a _conical_ case for your needs for now), and the same applies also to a concept like "Layer". If "AEGradientView" for instance is the name of your framework, then you could have things like ConicalGradientView, RadialGradientView, etc in it, and that would read out all nicely. Finally, should you wish to make things more brief when consuming APIs from that framework, you can always use `typealias`.

So, being sufficiently descriptive is one factor, but of course brevity is the other factor you want to balance. If you really genuinely do have a case of a type that really is unique in the framework and the type name can be both brief and clearly indicating its role, then my convention at least is indeed to use the most brief possible name. So for instance in a certain image data and metadata handling framework which I've co-designed, [`Image`][2] is the name of a type used as a container for image data and metadata. because there genuinely in the lingo of that framework only ever a single class in an "image" role, and crucially, it describes clearly what the class is for (unlike for instance "View"). In the same way, I use the briefest possible name for nested types, so for example the type used to denote an "image error" (an enum conforming to `Swift.Error`) is called `Carpaccio.Image.Error`.

Regarding your second question about a module / type name clash, this ambiguity is not possible to resolve by the compiler in that context. You also indeed will not find any instances of a module and type name getting confused in any of Apple's frameworks (nor can I think of having come across any example of this in 3rd party code). Beside the technical reason that the compiler most likely has no means of disambiguating between the module and the clashing class name there, it's also confusing for a programmer following platform conventions: think of the module name as the name of a "product" and the types inside as the constituent parts – whilst `AELog` is a good name for a logging framework in Swift, it would not be an idiomatic name of a type in Swift code; Name prefixes like "AE" are just not used in Swift for types – they're not even necessary for Objective-C subclasses you make in Swift because the fully qualified name of the class seen by the Objective-C runtime actually includes the module name as a prefix.

There's a nice WWDC talk from earlier this year also on [Swift API naming considerations][3], discussing some of what is mentioned above as well.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply

#3
You won't be able to please everyone. Keep that in mind. So the question maybe needs to be "what works out best for most"?

(1) Redundancy a la "AEConicalGradient.ConicalGradientView" does not.

(2) There are several ways a developer may import your "Layer" class into their project. You need to make sure they can get their work done without added complexity. I'd go with the most "general" import way - import your entire framework, not an individual file - over something like importing the "Layer" file.

(3) I'm showing my age, but there is nothing similar to "include" files in Xcode.

Starting with that, I'd say keep things as generic as possible at the deepest level - make a "layer" file and class, and let the user do the manual changes needed to make it "AELayer" if they decide to import a single file. After all, they are grabbing a single file, right?

So my choice for a hierarchy is:

>AEFramework

>>Canonical

>>>Layer

>>>View

>>Log

>>>Delegate

>>>Line

>>>Config

Your choice as to what needs to be in individual files. Here's my proposed framework setup:

File "AEFramework.swift" (this is your target also):

public class Canonical {

}

File "Canonical.swift":

extension Canonical {
public class View: UIView {

}
public class Layer: CALayer {

}
}

File "Layer.swift":

extension Canoncial.Layer {

}

The simplest way to use things is:

import AEFramework
let myLayer = Canoncial.Layer()

The most complex way involves changing "Layer.swift" after adding it to your project:

extension CALayer {

}
Reply



Forum Jump:


Users browsing this thread:
3 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through