编辑
开发规范
本文访问次数:0
  1. 1. 文档说明
  2. 2. 通用(Android、iOS)开发规范
    1. 2.1. 文件相关规范
    2. 2.2. 编码相关规范
  3. 3. Android开发规范
    1. 3.1. 开发工具规范
    2. 3.2. 文件相关规范
    3. 3.3. 编码相关规范
  4. 4. iOS开发规范
    1. 4.1. 开发工具规范
    2. 4.2. 编码相关规范

文档说明

  • 在APP开发过程中要严格遵守本文档制定的开发规范,如果特定开发平台的开发规范和通用开发规范出现冲突,以特定平台的开发规范为准。
  • 除非特殊说明,驼峰式指小驼峰式,即第一个单词的字母小写,其余单词的首字母大写,其余字母小写,单词之间不以空格断开或连接号(-)、下划线(_)连接的写法,如:lowerCamelCase
  • 除非特殊说明,大驼峰式(也叫帕斯卡式)指第一个单词前缀字母使用大写字母;后续单词的首字母亦用大写字母,单词之间不以空格断开或连接号(-)、下划线(_)连接的写法,如:UpperCamelCase、PascalCase
  • 除非特殊说明,小写下划线式指全部字母小写,单词之间使用下划线(_)连接的写法,如:lower_underscore_case
  • 除非特殊说明,大写下划线式指全部字母大写,单词之间使用下划线连接的写法,如:UPPER_UNDERSCORE_CASE
  • 有可能进行修改或者增加

通用(Android、iOS)开发规范

文件相关规范

  • 文件编码统一使用UTF-8

编码相关规范

  • 不要忽略异常处理
  • 缩进使用4个空格
  • 变量命名使用驼峰式
  • 方法命名使用和变量相同的格式
  • 静态变量命名使用大写下划线式
  • 变量使用名词命名,方法使用动词命名,使命名清晰易懂,避免使用缩写
  • 方法之间空一行
  • 代码块之间空一行
  • IDE设置为100列自动断行
  • 代码中不能出现中文或者拼音
  • 删除不使用的、跟程序无关的代码(变量、方法、文件等)
  • 遵守不要重复自己原则(Don’t repeat yourself)
  • 除非特殊说明,把缩写当作普通单词,遵循以上写法
  • 类、资源和变量按照适用范围从大到下,命名从短到长
  • 类、方法后的大括号隔开一个空格即可,不用另起一行
  • 在函数或者封闭空间内,不要随意直接使用全局变量,而是使用传参的方式
  • 登录使用login,登出使用logout,均作为一个单词
  • 将模型分为业务模型(网络请求模型)和本地模型(视图模型)
  • 减少继承,增加复用
  • 引入的第三方库必须再添加一层封装,这样在更换第三方库的时候不需要更改代码
  • 能在方法内作为参数的变量绝不生命为全局变量
  • 能在单个控制器声明的变量绝不声明为应用全局变量
  • 每次提交版本控制,尽量提交较少的更改

Android开发规范

开发工具规范

  • 开发工具统一使用Android官方推荐的Android Studio
  • 更改编码风格设置,私有成员变量添加m前缀
  • 使用Android Studio自带的Gradle进行依赖管理
  • 更改文件头部信息,如图覆盖设置,统一使用姓名全拼或者中文
  • 不要在module中引用其它module

文件相关规范

  • 类文件使用大写驼峰式写法,如UserFragment,RootActivity
  • 资源文件使用小写下划线式写法,如fragmengt_user,activtiy_root
  • 菜单文件命名跟布局命名类似,匹配对应的组件
  • 值文件命名规范为使用复数,如strings.xml
  • 资源文件中的变量(name、id)采用驼峰式
  • 所有xml文件默认采用小写下划线式
  • 父类或基础模块命名为base
  • 模块之间不交叉使用独立文件定义的键值,直接在文件中定义。
  • 使用独立文件放置跨文件(Fragment、Activity、UIViewController)的键值,其它键值否则定义在文件内。

  • 字符串资源名称(name)前缀

类型 说明 前缀 例子 (name)
占位符 placeholder placeholderTitle
格式 format formatPrice
Activity标题 activity activityUser
按钮标题 button buttonSubmitOrder
带冒号的说明文字 label labelUserName
度量单位 unit unitDollor
符号 symbol symbolMinus
提示 用于EditText的hint属性 hint hintOptional
标签 tab tabIndex
  • 跟状态相关的文件使用以下命名方式:
状态 后缀 例子
默认 _normal button_login_normal.png
按下 _pressed button_login_pressed.png
获得焦点 _focused button_login_focused.png
已禁用 _disabled button_login_disabled.png
已选择 _selected button_login_selected.png
  • 图片文件命名规范:
类型 前缀 例子 说明
标题图标 ab_ ab_stacked.png
普通按钮 button_ button_login_normal.png
对话框图标 dialog_ dialog_top.png
分隔线 divider_ divider_horizontal.9.png
普通图标 icon_ icon_star.png
菜单图标 menu_ menu_submenu_bg.9.png
通知图标 notification_ notification_bg.9.png
标签页图标 tab_ tab_home_selected.9.png
背景图 background_ background_user.png
占位图片 placeholder_ placeholder_goods_image.png 因为有些图片需要请求网络,在获得网络图片资源之前,显示的图片叫占位图片
  • 布局文件命名规范:
组件 类名 布局命名
Activity UserProfileActivity activity_user_profile.xml
Fragment SignUpFragment fragment_sign_up.xml
Dialog ChangePasswordDialog dialog_change_password.xml
AdapterView item item_person.xml
Banner banner_guide.xml
Partial layout partial_title.xml
  • 键值对中的键命名规范
常见键值对 键命名前缀
SharedPreferences PREF_
Bundle BUNDLE_
Fragment Arguments ARG_
Intent Extra EXTRA_
Intent Action ACTION_

如:

// 注意,变量名和变量的值保持一致
static final String PREF_EMAIL = "PREF_EMAIL";
static final String BUNDLE_AGE = "BUNDLE_AGE";
static final String ARG_USER_ID = "ARG_USER_ID";

// Intent相关的键命名要包含完整的包名
static final String EXTRA_SURNAME = "com.myapp.extras.EXTRA_SURNAME";
static final String ACTION_OPEN_USER = "com.myapp.action.ACTION_OPEN_USER";

编码相关规范

  • 禁止统一处理不同的异常,如:

    try {
      someComplicatedIOFunction();        // may throw IOException
      someComplicatedParsingFunction();   // may throw ParsingException
      someComplicatedSecurityFunction();  // may throw SecurityException
    } catch (Exception e) {                 // I'll just catch all exceptions
      handleError();                      // with one generic handler!
    }
    
  • 只引入必要的文件,使用import foo.Bar;而不是import foo.*;

  • 私有非静态变量使用m前缀
  • 私有静态变量使用s前缀
  • 大括号下一行保留4个空格,如:
    if (x == 1) {
      x++;
    }
    
  • 折行代码保留8个空格
    Instrument i =
          someLongExpression(that, wouldNotFit, on, one, line);
    
  • 覆盖父类的方法或者实现接口要在方法上方添加@Override注释
  • 按照以下方式打印数据
    Log.v(String TAG, String message);//详细
    Log.d(String TAG, String message);//调试
    Log.i(String TAG, String message);//信息
    Log.w(String TAG, String message);//警告
    Log.e(String TAG, String message);//错误
    
  • 类成员采用以下顺序
    • Constants(常量)
    • Fields(成员变量)
    • ButterKnife(绑定视图)
    • Setter and getter (成员变量的setter和getter方法)
    • Constructors(构造函数)
    • Override methods and callbacks (public or private)(重写函数和回掉函数)
    • Public methods(公有方法)
    • Private methods(私有方法)
    • Inner classes or interfaces(内部类或接口)
  • 生命周期函数按照生命周期排序,如:

    public class MainActivity extends Activity {
      //Order matches Activity lifecycle
      @Override
      public void onCreate() {}
    
      @Override
      public void onResume() {}
    
      @Override
      public void onPause() {}
    
      @Override
      public void onDestroy() {}
    }
    
  • 在xml文件中,空元素要自己关闭,如

    <TextView
      android:id="@+id/fragment_user_username_textView"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" />
    

iOS开发规范

开发工具规范

  • 开发工具使用苹果官方的Xcode
  • 开发工具必须从商店或官网下载,禁止复制未知来源的开发工具
  • 使用http://alcatraz.io/管理Xcode第三方插件、主题和模板
  • 使用https://cocoapods.org/和cocoapods-xcode-plugin进行依赖管理
  • 电脑用户名设置为姓名全拼,Xcode会把这个值用在文件头部信息中
  • 设置Organization和Class Prefix
  • 尽可能使用const定义常量
  • 按照Objective-C格式化风格进行格式化

    编码相关规范

  • 即使有命名空间限制,但是最好给每个组件都添加前缀
  • 多个target 文件、公共方法(.h文件定义的方法)和变量要添加前缀
  • 每个target中的每个类的每个方法只允许有一次method swizzle
  • 使用#pragma mark - description对代码分块,方便查阅
  • 类文件命名禁止缩写
  • 常量命名采用首字母大写的驼峰式,宏命名采用大写下划线式。使用static和const声明普通常量,使用#define声明宏,如:
    static NSString * const CompanyName = @"The Company";
    static const CGFloat ImageHeight = 50.0;
    #define DEBUG_MODE = 1;
    
  • 使用.号获取和设置属性,如:
    view.backgroundColor = [UIColor orangeColor];
    [UIApplication sharedApplication].delegate;
    
    而不是采用以下形式:
    [view setBackgroundColor:[UIColor orangeColor]];
    UIApplication.sharedApplication.delegate;
    
  • 错误处理采用以下方法:
    NSError *error;
    if (![self trySomethingWithError:&error]) {
      // Handle Error
    }
    
    而不是以下方式:
    NSError *error;
    [self trySomethingWithError:&error];
    if (error) {
      // Handle Error
    }
    
  • 使用CGGeometry functions获取CGRect变量的属性,而不是直接访问,如:
CGRect frame = self.view.frame;

CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);

而不是:

CGRect frame = self.view.frame;

CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;
  • 常量使用以下方式定义:
static NSString* const CHECK_OUT_BUTTON_TITLE_FORMAT = @"去结算(%d)";
static CGFloat const SELLECT_ALL_BUTTON_TITLE_FONT = 12;
  • 枚举类型使用以下方式定义:
typedef NS_EMUN(NSUInteger, LoginType) {
    SELLER,
    STORE_OWNER
};

即枚句类型的名称使用大写驼峰式的写法,值使用大写下划线式的写法

  • 枚举类型使用按位掩码时,采用以下方式定义:
typedef NS_OPTIONS(NSUInteger, GoodsType) {
    NEW_GOODS  = 1 << 0,
    HOT_GOODS  = 1 << 1,
    BEST_GOODS  = 1 << 2
};
  • 私有属性在类实现中定义,如:
@interface GoodsViewController ()

@property (nonatomic, strong) GADBannerView *googleAdView;
@property (nonatomic, strong) ADBannerView *iAdView;
@property (nonatomic, strong) UIWebView *adXWebView;

@end
  • 不要直接和YES比较来判断是否为空或NO,采用以下方式:
if (!someObject) {}
if (someObject == nil) {}
if (isAwesome) {}
if (!someNumber.boolValue){}
if (someNumber.boolValue == NO){}
  • 单例模式采用以下方法定义:
+ (instancetype)sharedInstance {
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[[self class] alloc] init];
    });

    return sharedInstance;
}
  • 引入文件采用以下方式:
// Frameworks
@import QuartzCore;
// Models
#import "CommonUtil.h"
// Views
#import "CustomButton.h"
  • pchFile.h引入的文件必须引入该文件必要的所有.h文件,即使pchFile已经引入了这些.h文件
    这样保证pchFile移除某些文件不会导致其他文件出现错误

  • 设计delegate时,第一个参数为发送信息的对象,如:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
  • 按照以下格式声明成员变量,如:
@property(nonatomic, strong) UIScrollView *scrollView;
  • 总是使用@property声明变量,而不是在括号中

  • UIViewController代码顺序

@property(nonatomic,strong)UIButton*button;
...
#pragma mark - life cycle
viewDidLoad
viewDidAppear
...
#pragma mark - UITableViewDelegate
#pragma mark - CustomDelegate
#pragma mark - event handlers
#pragma mark - private methods
#pragma mark - getters and setters
  • 所有属性都使用getter和setter
  • 所有View的初始化都放在getter中

    viewDidload里面只做addSubview和布局的事情,在viewDidAppear里面做Notification的监听之类的事情。至于属性的初始化,则交给getter去做。

  • 所有点击事件的添加都写在初始化getter中
  • 使用代码生成视图
  • 监听Notification后记得释放
  • 约束写在updateViewConstraints中,例如
-(void)updateViewConstraints{
    [super updateViewConstraints];
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view).with.offset(20);
        make.left.equalTo(self.view).with.offset(20);
        make.right.equalTo(self.view).with.offset(-20);
    }];
    ...
}
没有任何评论