Stripe
Stripe

Objective-C Style Guide

Discover the secret to clean and efficient Objective-C code with Stripe's comprehensive Coding Style Guide. This guide is designed to help developers maintain consistency and readability in their code, ensuring a smooth and seamless experience for both team members and users. With a focus on ground rules, variable naming, control flow, documentation, literals, constants, and design patterns, this guide covers every aspect of Objective-C programming to help you write better code, faster.

Stripe's Coding Style Guide emphasizes the importance of clarity, organization, and consistency in code. From proper indentation and spacing to the use of literals and constants, the guide provides detailed instructions and examples to help developers create clean, efficient, and easy-to-understand code. By following these guidelines, developers can ensure that their code is not only functional but also maintainable and scalable.

Objective-C Style Guide

Ground Rules

NSpacing

  1. Indent using 4 spaces. No tabs.
  2. Avoid starting methods with an empty line
  3. There should not be a need to use multiple consecutive empty lines
  4. Asterisks should be attached to the variable name NSString *text unless it's NSString * const Text

Variable Naming

  1. Lean towards clarity over compactness
  2. Avoid single letter variables. Try using idx / jdx instead of i / j in for loops.
  3. Acronyms should be all lowercase as a method prefix (ex:url or urlString). Otherwise, they should be all caps when occurring elsewhere in the method name, or as a class name (ex: handleStripeURLCallbackWithURL or STPAPIClient)
  4. Internal or private methods and ivars should begin with an _, e.g. - (void)_doPrivateStuff and id _internalVariable. This is not required for private properties which should not include an underscore (this is to distinguish them from their underlying variable which automatically has an _ prefix).

Control Flow

  1. Place else if and else on the same line as the preceding closing curly brace:

if (condition) {

// A

} else if (condition) {

// B

} else {

// C

}

1
2
3
4
5
6
7
  1. Always wrap conditional bodies with curly braces
  2. Each return statement should be on a separate line for ease of debugging. i.e. do NOT write if (condition) return YES;
  3. Use ternary operators sparingly and for simple conditions only:

type = isCard ? @"card" : @"unknown";


type = dictionary[@"type"] ?: @"default";

1
2
3
  1. switch statements for enums should contain an entry for each value and avoid using default

Documentation

  1. Document using the multi-line syntax in all cases with the content aligned with the first asterisk:

/** This is a one line description for a simple method */

- (void)title;


/** This is a multi-line description for a complicated method @param @see https://... */

- (void)title;

1
2
3
4
5
  1. Header documentation should wrap lines to 80 characters

Literals

  1. Use literals to create immutable instances of NSStringNSDictionaryNSArrayNSNumber:

NSArray *brands = @[@"visa", @"mastercard", @"discover"];


NSDictionary *parameters = @{

@"currency": @"usd",

@"amount": @1000,

};

1
2
3
4
5
6
  1. Dictionary colons should be attached to the key
  2. Align multi-line literals using default Xcode indentation

Constants

  1. Use static constants whenever appropriate. Names should start with a capital letter:

static NSString * const HTTPMethodGET = @"GET";


static const CGFloat ButtonHeight = 100.0;

1
2
3
  1. Any public static constants should be prefixed with STP:

static NSString * const STPSDKVersion = @"11.0.0";

1

Folders

  1. We use flat folder structure on disk with some exceptions
  2. Save files to the appropriate root level folder. Typical folders include:
  3. stripe-ios/Stripe/
  4. stripe-ios/Tests/Tests/
  5. stripe-ios/Example/Basic Integration/Basic Integration/
  6. stripe-ios/Example/Non-Card Payment Examples/Non-Card Payment Examples/
  7. Save public header files in stripe-ios/Stripe/PublicHeaders/ for Cocoapods and Swift Package Manager compatibility

Design Patterns

Imports

  1. Ordering for imports in headers
  2. Import system frameworks
  3. Import superclasses and protocols sorted alphabetically
  4. Use @class for everything else

#import <Foundation/Foundation.h>


#import "STPAPIResponseDecodable.h"

#import "STPBankAccountParams.h"@class STPAddress, @STPToken;

1
2
3
4
  1. Ordering for imports in implementations
  2. Import system frameworks
  3. Import corresponding headers
  4. Import everything else sorted alphabetically

#import <PassKit/PassKit.h>


#import "STPSource.h"

#import "STPSource+Private.h"


#import "NSDictionary+Stripe.h"

#import "STPSourceOwner.h"

#import "STPSourceReceiver.h"

#import "STPSourceRedirect.h"

#import "STPSourceVerification.h"

1
2
3
4
5
6
7
8
9
10

Interfaces and Protocols

  1. Stick to Xcode default spacing for interfaces, categories, and protocols
  2. Always define NS_ASSUME_NON_NULL_BEGIN / NS_ASSUME_NON_NULL_END in headers. NS_ASSUME_NON_NULL_BEGIN / NS_ASSUME_NON_NULL_END should also be used in implementation (.m) files

NS_ASSUME_NON_NULL_BEGIN


@protocol STPSourceProtocol <NSObject>


// ...@end// ...@interface STPSource : NSObject<STPAPIResponseDecodable, STPSourceProtocol>


// ...@end// ...@interface STPSource () <STPInternalAPIResponseDecodable>


// ...@end


NS_ASSUME_NON_NULL_END

1
2
3
4
5
6
7
8
9
10
11
  1. Category methods on certain classes need to be prefixed with stp_ to avoid collision:

// NSDictionary+Stripe.h


@interface NSDictionary (Stripe)


- (NSDictionary *)stp_jsonDictionary;


@end

1
2
3
4
5
6
7
  1. Define private properties and methods as class extensions inside the implementation. Ex: STPSource.m.
  2. Define internal properties and methods as class extensions inside a +Private.h file. Ex: STPSource+Private.h.
  3. Access private properties and methods from test classes by defining a class extension inside the test implementation:

// STPBankAccountTest.m


@interface STPBankAccount ()


+ (STPBankAccountStatus)statusFromString:(NSString *)string;

+ (NSString *)stringFromStatus:(STPBankAccountStatus)status;


@end


@interface STPBankAccountTest : XCTestCase


@end


@implementation STPBankAccountTest


// ...


@end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Properties

  1. Properties should be defined using this syntax:

@property (<nonatomic / atomic>, <weak / copy / _>, <nullable / _>, <readonly / _>) <class> *<name>;


@property (<nonatomic / atomic>, <readonly / _>) <type> <name>;

1
2
3
  1. Omit default properties (assignreadwritestrong)
  2. Use copy for classes with mutable counterparts such as NSStringNSArrayNSDictionary
  3. Leverage auto property synthesis whenever possible
  4. Declare @synthesize and @dynamic on separate lines for shorter diffs
  5. Use properties (self.foo) instead of their corresponding instance variables (_foo). Instance variables should only be accessed directly in initializer methods (initinitWithCoder:, etc…), dealloc methods, and within custom getters and setters. For more information, see Apple’s docs on using accessor methods in initializer methods and dealloc..

Init

- (instancetype)init {

self = [super init];

if (self) {

// ...

}

return self;

}

1
2
3
4
5
6
7

Methods

  1. If a method takes more than three arguments, each argument should be on a separate line.
  2. See Coding Guidelines for Cocoa - Naming Methods

Implementation

  1. Do not use #define to define a block of code -- #define code is very difficult to debug
  2. Use #pragma mark - <text> and #pragma mark <text> to group methods In large implementation files:

#pragma mark - Button Handlers


#pragma mark - UITableViewDataSource


#pragma mark - UITableViewDelegate

1
2
3
4
5

Discover the secret to clean and efficient Objective-C code with Stripe's comprehensive Coding Style Guide. This guide is designed to help developers maintain consistency and readability in their code, ensuring a smooth and seamless experience for both team members and users. With a focus on ground rules, variable naming, control flow, documentation, literals, constants, and design patterns, this guide covers every aspect of Objective-C programming to help you write better code, faster.

Stripe's Coding Style Guide emphasizes the importance of clarity, organization, and consistency in code. From proper indentation and spacing to the use of literals and constants, the guide provides detailed instructions and examples to help developers create clean, efficient, and easy-to-understand code. By following these guidelines, developers can ensure that their code is not only functional but also maintainable and scalable.

Related examples
Google
Google
Code Review Developer Guide
Slack
Slack
How About Code Reviews?