Accessibility/Mac/ContributorGuide: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(7 intermediate revisions by the same user not shown)
Line 1: Line 1:
= Mac Accessibility Contributor's Guide =
= Mac Accessibility Contributor's Guide =
In this document we will collect style guidelines and information useful for individuals looking to contribute to our Mac accessibility support. There is also an [[Accessibility/Mac/ArchitectureAndDesign|architecture and design page]] where one can find a technical overview.


== Code Style ==
== Code Style ==


Our code style is based on Google's Objective C Style Guide
Our code style is based on [https://google.github.io/styleguide/objcguide.html Google's Objective C Style Guide], with a few exceptions and additions. The [https://www.mediawiki.org/wiki/Wikimedia_Apps/Team/iOS/ObjectiveCStyleGuide Wikimedia style guide] is also a good reference for things not covered here or in Google's guide.
 
=== Method Declarations ===
 
Objective C is very flexible in its handling of method declarations. These rules should help remove ambiguity.
 
==== Always Declare Methods ====
 
Objective C does not require instance methods to have a declaration in the <code>@interface</code> block. If a method is defined in the <code>@implementation</code> block, it is accessible to any caller that knows of its signature. All methods should be declared. If they are public, they should be in the <code>@interface</code> block in the header file. If they are private they should be in a private class extension in the <code>mm</code> file.
 
For example, a header file might look like this:
 
<syntaxhighlight lang="Objective-C">
@interface Hello : NSObject
- (NSString*)world;
@end
</syntaxhighlight>
 
The <code>mm</code> file will look like this:
 
<syntaxhighlight lang="Objective-C">
@interface Hello()
- (NSNumber*)somethingElseThatIsPrivate;
@end
 
 
@implementation Hello
- (NSString*)world {
  return @"earth";
}
 
- (NSNumber*)somethingElseThatIsPrivate {
  return @(3);
}
 
// BAD! This method has not been declared
- (void)iAmNotDeclared:(NSString*)bah {
  NSLog(@"%@", bah);
}
@end
</syntaxhighlight>


== Architecture and Design ==
==== Mark Methods "final" ====


The goal of this design is to allow us to provide customized interfaces for different accessibility roles in a concise and readable way that does not compromise on flexibility and possible future OSX API changes.
A class cannot declare a method as final and prevent subclasses from overriding it. If a method should not be overridden by a subclass put the word "final" in a comment above the declaration. For example:
<syntaxhighlight lang="Objective-C">
// This method returns the word "bar"
// final
- (NSString*)foo;
</syntaxhighlight>


[[File:Max a11y arch.svg|thumb|UML Class Diagram]]
==== Mark Methods "override" ====


=== Protocols ===
A subclass does not need to declare an overridden method as such. If a method is overriding a method from a superclass, or is implementing a method from a conformed protocol, put the word "override" in a comment above the declaration. For example:


==== mozAccessible Protocol ====
<syntaxhighlight lang="Objective-C">
This consists of the API necessary to talk to platform accessibility (<code>accessibilityAttributeValue</code>, etc.) and widget code (<code>representedView</code>, etc.)
// This method returns the word "bear"
// override
- (NSString*)pooh;
</syntaxhighlight>


==== mozAccessibleInner Protocol ====
=== NSObject Literals ===
This inner protocol's API is a mapping to Apple's attributes and actions. It allows us to have simple getter and setter methods for each attribute and a method for performing each action. All methods are optional, so an implementing object gets to choose which subset of these methods it supports. This gets reflected in what is returned to platform in  <code>accessibilityAttributeNames</code> and friends. An instance can also programatically block a method if it is defined and it will be excluded from the mapping.


=== Classes ===
Whenever possible, use <code>@</code> literals when creating immutable objects. Be careful not to pass <code>nil</code> values into container objects as this will cause a crash.


==== mozAccessibleBase ====
<syntaxhighlight lang="Objective-C">
// Do
NSArray* actions = @[@"AXPress", @"AXShowMenu", @"AXScrollToVisible"];
// Don't
NSArray* actions = [NSArray arrayWithObjects:@"AXPress", @"AXShowMenu", @"AXScrollToVisible", nil];


The abstract base class for all our platform accessibles. This class:
// Do
* Implements the platform and widget API defined in the <code>mozAccessible</code> protocol. The platform API it implements should be considered "final" (there is no way in Objective C to enforce this).
NSDictionary* keyValues = @{@"key1" : @"value1", @"key2" : @"value2"};
* Forwards platform methods to the mapped inner protocol's methods.
// Don't
* Filters ignored accessibles and ensures they are not exposed to the platform.
NSDictionary* keyValues = [NSDictionary dictionaryWithObjectsAndKeys:@"key1", @"value1", @"key2", @"value2", nil];


A subclass should be able to implement a handful of inner protocol getters and have a well-behaved platform accessible. An example of that is <code>mozColumnAccessible</code>.
// Do
NSNumber* isBest = @YES;
// Don't
NSNumber* isBest = [NSNumber numberWithBool:YES];


==== mozAccessible ====
// Do
NSNumber* life = @42;
// Don't
NSNumber* life = [NSNumber numberWithInteger:42];
</syntaxhighlight>


The base class for all accessibles that wrap a Gecko accessible. This class:
=== Naming Conventions ===
* Maps gecko roles to platform roles, subroles, and role descriptions.
* Caches and utilizes gecko states.
* Forwards gecko accessible events to platform notifications.
* Provides parent and children getters via gecko's hierarchy.
* Provides a base set of attributes and actions that most gecko accessibles support.


==== mozAccessible subclasses ====
==== Variables ====


Subclasses of mozAccessible are mainly gecko role-based and typically provide additional attributes that the type uses. For example a mathml subclass might provide mathml related attributes via implemented inner protocol methods (eg. <code>mathRootRadicand</code>). An accessible that backs a slider might implement special actions via the inner protocol, like <code>performIncrement</code>.
==== Classes and Files ====

Latest revision as of 22:04, 27 May 2020

Mac Accessibility Contributor's Guide

In this document we will collect style guidelines and information useful for individuals looking to contribute to our Mac accessibility support. There is also an architecture and design page where one can find a technical overview.

Code Style

Our code style is based on Google's Objective C Style Guide, with a few exceptions and additions. The Wikimedia style guide is also a good reference for things not covered here or in Google's guide.

Method Declarations

Objective C is very flexible in its handling of method declarations. These rules should help remove ambiguity.

Always Declare Methods

Objective C does not require instance methods to have a declaration in the @interface block. If a method is defined in the @implementation block, it is accessible to any caller that knows of its signature. All methods should be declared. If they are public, they should be in the @interface block in the header file. If they are private they should be in a private class extension in the mm file.

For example, a header file might look like this:

@interface Hello : NSObject
- (NSString*)world;
@end

The mm file will look like this:

@interface Hello()
- (NSNumber*)somethingElseThatIsPrivate;
@end


@implementation Hello
- (NSString*)world {
  return @"earth";
}

- (NSNumber*)somethingElseThatIsPrivate {
  return @(3);
}

// BAD! This method has not been declared
- (void)iAmNotDeclared:(NSString*)bah {
  NSLog(@"%@", bah);
}
@end

Mark Methods "final"

A class cannot declare a method as final and prevent subclasses from overriding it. If a method should not be overridden by a subclass put the word "final" in a comment above the declaration. For example:

// This method returns the word "bar"
// final
- (NSString*)foo;

Mark Methods "override"

A subclass does not need to declare an overridden method as such. If a method is overriding a method from a superclass, or is implementing a method from a conformed protocol, put the word "override" in a comment above the declaration. For example:

// This method returns the word "bear"
// override
- (NSString*)pooh;

NSObject Literals

Whenever possible, use @ literals when creating immutable objects. Be careful not to pass nil values into container objects as this will cause a crash.

// Do
NSArray* actions = @[@"AXPress", @"AXShowMenu", @"AXScrollToVisible"];
// Don't
NSArray* actions = [NSArray arrayWithObjects:@"AXPress", @"AXShowMenu", @"AXScrollToVisible", nil];

// Do
NSDictionary* keyValues = @{@"key1" : @"value1", @"key2" : @"value2"};
// Don't
NSDictionary* keyValues = [NSDictionary dictionaryWithObjectsAndKeys:@"key1", @"value1", @"key2", @"value2", nil];

// Do
NSNumber* isBest = @YES;
// Don't
NSNumber* isBest = [NSNumber numberWithBool:YES];

// Do
NSNumber* life = @42;
// Don't
NSNumber* life = [NSNumber numberWithInteger:42];

Naming Conventions

Variables

Classes and Files