起名何以是 Trait

Trait 有哪些优势 ?

trait 有什么样优势?来看一段代码:

class User extends Model
{
    use Authenticate, SoftDeletes, Arrayable, Cacheable;

    ...
}

本条用户模型类,大家引入了三个特色:注册与授权、软删除、数组式操作、可缓存。

咱俩看到代码的时候一眼便了解当前匡助了咋样个特性。再看下边此外一种写法:

abstract AdvansedUser {
  // ... 实现了 Authenticate, SoftDeletes, Arrayable, Cacheable 的所有方法
}
class User extends AdvansedUser
{
    ...
}

你只可以再去读书 AdvansedUser 的代码才能通晓。你想说没有可读性是因为我基类的称谓没起好?不过,这种各类特色组合的一个基类是根本不可能起一个见名知义的名目标,不信你可以试一下。

就是你真的起了一个见名知义的称呼:AuthenticateCacheableAndArrayableSoftDeletesUser,然而当需要变动,要求在 FooUser(同样连续了那个基类)
中去除缓存特性,而 User 类保留那么些特性,怎么做?再创设一个基类么?

这就是自我通晓的 Trait:

它不仅是可复用代码段的会见,它应有是一组描述了某个特性的的属性与艺术的会聚。它的亮点在于随意组合,耦合性低,可读性高。

经常写代码的时候可能怎么拆分才是我们的痛点,分享以下多少个技巧:

  • 从需求或效益描述拆分,而不是写了两段代码发现代码一样就涉嫌联合;
  • 拆分时某些性能也共同指引,比如下边第一个例证里的价位,它是“可卖性”必备的特性;
  • 拆分时一旦给 Trait
    起名困难时,请认真想想你是不是确实拆分对了,因为科学的拆分是很容易描述
    “它是一个负有何等效劳的特点” 的;

可想而知一定要切记:不要为了让两段同样的代码提到联合这样简单粗暴的措施来拆分。

上述是个人见解,欢迎各位琢磨。​起名 1

 

from:http://overtrue.me/articles/2016/04/about-php-trait.html

分类及其方法命名

分拣机制平日用于向无源码的既有类中新增效益。分类中的方法是直接加在类里面的,它们就好比这多少个类固有的方法,将分类方法插手类中这一操作是在运行期系统加载分类时做到的。运行期系统会把分类中所实现的各类方法都出席类的点子列表中。假设类中自然就有此方法,而分类中又实现了五回,那么分类中的方法会覆盖原来那一份实现代码。实际上可能会发生很频繁蒙面,比如某个分类中的方法覆盖了”主实现”中的相关办法,而另外一个分类中的方法又覆盖了这一个分类中的方法,多次覆盖的结果以最终一个分拣为准。当有多份实现时,无法确定运行时采取的是那份实现。由那样吸引的
bug 很难追查。

那么,如何来最大限度的避免这种覆盖呢?

在 iOS
开发中,没有命名空间的定义。平常,大家经过为品种中兼有类命名加上有意的前缀来兑现命名空间的功能,来避免可能暴发的与利用第三方库中的方法命名相同。同样的,这里大家也是为分类,以及分类中的所有办法都添加一定前缀。这一个前缀应该与使用程序库中其余地方所用的前缀相同,通常会拔取公司名或应用程序名来做决定。例如来编排一个判定目的是不是为空的归类方法:

NSObject+ACLNetworkingMethods.h

@interface NSObject (ACLNetworkingMethods)

- (BOOL)acl_isEmptyObject;

@end

此间为分类名以及分类中的方法加上了 ACL
的前缀。注目的在于措施中,需前缀小写。

其它,使用分类时,不要刻意覆写分类中的方法,尤其是当你把代码发布为程序库供其他开发者使用时,因为你不可能控制此外开发者需要的是办法哪份实现。

总结:

  • 向第三方类中添加分类时,总应该给分类名称加上你专有的前缀,前缀须大写。
  • 向第三方类中添加分类时,总应该给分类中的方法名加上你专有的前缀,前缀须小写,且以下划线连接前缀与办法名。

迎接留言互换。

Trait 是为接近 PHP 的单继承语言而准备的一种代码复用机制。Trait
为了削减单继承语言的范围,使开发人士可以轻易地在不同层次结构内独立的类中复用
method。Trait 和 Class
组合的语义定义了一种缩小复杂性的措施,制止传统多延续和 Mixin
类相关典型问题。

Trait 和 Class 相似,但仅仅意在用细粒度和相同的法子来构功用应。
不可能透过 trait
自身来实例化。它为观念延续扩大了水平特性的组合;也就是说,应用的几个Class 之间不需要继续。

  • 常量命名
  • 用枚举表示情形、选项、状态码
  • 类及其方法命名
  • 分拣及其方法命名

Trait 是从 PHP 5.4
插手的一种细粒度代码复用的语法。以下是法定手册对 Trait 的叙说:

类及其方法命名

Objective-C
没有其它语言这种内置的命名空间(namespace)机制。由此,大家在起名时要想方设法制止地下的命名争执,否则很容易就重名了。制止此问题的唯一办法就是变相实现命名空间:
为所知名称都添加适量前缀。所选前缀可以是与企业、应用程序或者两者皆有涉嫌的名字。使用
Cocoa 和 Cocoa Touch 创设应用程序时必然要专注,Apple
宣传其保存使用具有”两个假名前缀”(tow-letter
prefixed)的权利。所以你协调选择的前缀应该是两个假名的。你能够在苹果官网
Class Names Must Be Unique Across an Entire
App

看到上述表明:

In order to keep class names unique, the convention is to use prefixes
on all classes. You’ll have noticed that Cocoa and Cocoa Touch class
names typically start either with NS or UI. Two-letter prefixes like
these are reserved by Apple for use in framework classes.

Your own classes should use three letter prefixes. These might relate
to a combination of your company name and your app name, or even a
specific component within your app.

You should also name your classes using a noun that makes it clear
what the class represents, like these examples from Cocoa and Cocoa
Touch:

| NSWindow | CAAnimation | NSWindowController | NSManagedObjectContext

另外,在文档 Coding Guidelines for
Cocoa

中提到:

Use prefixes when naming classes, protocols, functions, constants, and
typedef structures. Do not use prefixes when naming methods; methods
exist in a name space created by the class that defines them. Also,
don’t use prefixes for naming the fields of a structure.

那边需要表明两点:

  • 上述所说的functions指的是纯 C 函数。对于纯 C
    函数和全局变量,不论其处于头文件或者其实现文件中,在编译好的目的文件中,这多少个名称要真是”一级符号”(top-level
    symbol)的。因此我们总应该为这种 C
    函数的名字加上前缀。通常情状下,那类 C
    函数大家得以以定义其类的名字作为前缀。这样,在调节时,若此标志出现在栈回溯信息中,则很容易就能判断问题源自哪块代码。例如:

ACLSoundPlayer.h

#import <Foundation/Foundation.h>

@interface ACLSoundPlayer : NSObject

@end


ACLSoundPlayer.m

#import "ACLSoundPlayer.h"
#import <AudioToolbox/AudioToolbox.h>

void ACLSoundPlayerCompletion(SystemSoundID ssID, void *clientData) {

}

@implementation ACLSoundPlayer

@end
  • 上述引用说到不应当为 Objective-C methods
    添加前缀,我以为应该加上一个不比,当大家定义分类中的方法时,则总应该为其充足前缀,这会在下一条详细表达。

最后一种情形,若为第三库编写自己的代码,并准备将其揭露为程序库供客人付出应用程序所用时,你应该给你所用的这份第三方库代码都丰硕你自己的前缀。为方便表明,假如你要揭橥的程序库叫
EOCLibrary,你所拔取的第三方库叫 XYZLibrary,则你应当把你利用的
XYZLibrary 中颇具名字都冠以 EOC, 成为 EOCXYZLibrary, 原因如下:

  • 您的顺序所含有的非凡第三方库也许还会为应用程序本身所引入。
  • 你可能会想,让应用程序本身并非一向引入 XYZLibrary,改用 EOCLibrary
    中选用的老大,不过,应用程序也许还会引入另一个名为 ABCLibrary
    的第三方库,而该库中又带有了 XYZLibrary。此时,假若你和 ABCLibrary
    的作者都不给各自所用的 XYZLibrary
    加前缀,那么应用程序如故汇合世重复符号错误。
  • 你的库里所引述的第三方库是 X 版本的,而应用程序却需要引用第三库的 Y
    版本的效用。

对于类中的方法命名,应遵照以下规则:

  • 倘若情势的再次回到值是新建的,那么方法名的第一个词应是再次来到值的品种,例如:
    +stringWithString:。除非前面还有修饰语,例如
    localizedString。属性的存取方法不按照这种命名格局。
  • BOOL属性应加 is 前缀。假如某艺术重临非属性的 Boolean
    值,那么相应依据你效能,采纳 has 或 is 当前缀。

什么是 Trait ?

实际说通俗一点,就是能把重复的方法拆分到一个文件,通过 use 引入以达成代码复用的目的。

这就是说,我们应该怎么样去拆分大家的代码才是方便的啊?我的眼光是这般的:

Trait,译作 “特性”、“特征”、“特点” 。那么问题就来了:什么才是特点?

一个销售公司有很多种产品:电视机,电脑与鼠标垫,卡通手办等。其中鼠标垫与漫画手办是非卖品,只用于赠送。

那么这里的 “可卖性” 就是一个特色,非卖品是一直不价格的。我们便得以抽象出
“可卖性” 那个 Trait 来:

trait Sellable
{
    protected $price = 0;

    public function getPrice()
    {
        return $this->price;
    }

    public function setPrice(int $price)
    {
        $this->price = $price;
    }
}

自然我们具有的成品都会有品牌与其它基本属性,所以我们一般会定义一个产品类:

class Pruduct
{
    protected $brand;
    //...

    public function __construct($brand)
    {
        $this->brand = $brand;
    }

    public function getBrand()
    {
        return $this->brand;
    }

    //...
}

咱俩的电视机与电脑类:

class TV extends Pruduct
{
    use Sellable;
    //...

    public function play()
    {
        echo "一台 {$this->brand} 电视在播放中...";
    }

    //...
}

class Computer extends Pruduct
{
    use Sellable;

    protected $cores = 8;
    //...

    public function getNumberOfCores()
    {
        return $this->cores;
    }

    //...
}

而鼠标垫与手办等礼品是不可卖的:

class Gift extends Pruduct
{
    protected $name;

    function __construct($brand, $name)
    {
        parent::__construct($brand);
        $this->name = $name;
    }

    //...
}

上边的这些事例中,“可卖性”
便是一些货品的一个表征,也可以通晓为货物的一个分类。你恐怕会说,我也得以再添加一个
Goods 类来形成地点的事例啊,Goods 继承 Product,再让拥有可卖的货色继承于
Goods 类,把价格属性与措施写到 Goods
里,同样可以代码复用啊。的确,那没啥问题。可是你会发现:你有两个需要区分的特点时,由于
PHP
唯有单继承的原故,你不得不组合很六个基类出来,将他们层叠,最后得到的树状结构是很复杂的。这也是
Trait 所带来的优势:随意组合,代码清晰。

实则还有很多事例,比如可飞行的,那么把飞行这些特性所所有的习性(如:中度,距离)与措施(如:起飞,降落)放到一个
trait 就是一个理所当然的拆分。

正文谈谈 iOS
开发中的命名规范,首要涉及常量命名、枚举命名、类及其方法命名,以及分类及其方法命名。假诺您找的是官网的编码规范,请移步:
Coding Guidelines for
Cocoa
。当然本文会讲一些官网没有的东西。

迎接到自身的 个人博客
http://liumh.com

浏览此文

用枚举表示情状、选项、状态码

品类中,可用枚举来表示一密密麻麻的气象、选项和状态码。例如 iOS SDK 中象征
UICollectionView 滑动方向的枚举定义如下:

typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {
    UICollectionViewScrollDirectionVertical,
    UICollectionViewScrollDirectionHorizontal
};

或者定义 UITableView Style 的枚举:

typedef NS_ENUM(NSInteger, UITableViewStyle) {
    UITableViewStylePlain,      // regular table view
    UITableViewStyleGrouped     // preferences style table view
};

从这边可以看出,定义的枚举类型名称应以 2~3
个大写字母起始,而这一般与体系安装的类公事前缀相同,跟随其后的命名应利用驼峰命名法则,命名应准确表明枚举表示的意义,枚举中逐一值都应以定义的枚举类型起始,其后跟随各种枚举值对应的动静、选项或者状态码。

对此急需以按位或操作来组成的枚举都应运用 NS_OPTIONS 宏来定义,例如 SDK
中:

typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};

那般定义的选项可以以 按位或操作符
来拓展结合,枚举中每个值均可启用或者剥夺某一选项,在利用时,可以利用
按位与操作符 来检测是否启用了某一选项,如下:

UIViewAutoresizing resizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

if (resizing & UIViewAutoresizingFlexibleWidth) {
// UIViewAutoresizingFlexibleWidth is set

}

除此以外,大家兴许使用 switch 语句时,会在终极加上 default
分支,不过若用枚举定义状态机,则极端不用接纳 default
分支,因为如果稍后再加了一种情状,那么编译器就会生出警告,指示新投入的状态没有在
switch 分支中处理。即使写上了 default
分支,那么它就会处理这一个新情状,从而致使编译器不暴发警示,用 NS_ENUM
定义其他枚举类型时也要注意此问题。例如在概念代表 UI
元素样式的枚举时,通常要力保 switch 语句能正确处理所有样式。

总括一下:

  • 相应用枚举来代表状态机的情状、传递给艺术的选项以及状态码等值,给这么些值起个通俗的名字。
  • 假使把传递给某个方法的选项表示为枚举类型,而四个选项又可同时利用,那么就将各选项值定义为
    2 的幂,以便通过按位或操作将其重组起来。
  • 用 NS_ENUM 与 NS_OPTIONS
    宏来定义枚举类型,并指明其底层数据类型。这样就足以确保枚举是用开发者所选的平底数据类型实现出来的,而不是运用编译器所选的类型。
  • 在处理枚举类型的 switch 语句中永不实现 default
    分支。那样进入新的枚举值之后,编译器就会时有发生警示指示,switch
    还有未处理的枚举值。

常量命名

iOS 开发中,肯定避免不了要命名一些常量,那么,我们应该怎样来定名常量呢?

在研商上述问题前,先来询问定义常量的两种艺术。

第一种,使用 #define 预处理定义常量。例如:

#define ANIMATION_DURATION 0.3

概念一个 ANIMATION_DURATION 常量来代表 UI
动画的一个常量时间,这样,代码中装有应用 ANIMATION_DURATION
的地点都会被替换成
0.3,可是如此定义的常量无类型消息,且假使你在调节时想要查看
ANIMATION_DURATION
的值却得不到出手,因为在预处理阶段ANIMATION_DURATION
就曾经被沟通了,不便于调试。由此,弃用这种格局定义常量。

第三种,使用项目常量。将地点的预处理定义常量修改成类型常量:

static const NSTimeInterval kAnimationDuration = 0.3;

这般就为常量带入了类型音讯,那么定义类型常量又有咋样标准呢?

  • 对于局限于某编译单元(实现公文)的常量,平常以字符k始于,例如上文中的
    kAnimationDuration,且需要以 static const 修饰,例如:

static const NSTimeInterval kAnimationDuration = 0.3;

  • 对于定义于类头文件的常量,外部可见,则平时以定义该常量所在类的类名起首,例如
    EOCViewClassAnimationDuration, 仿照苹果风格,在头文件中开展 extern
    阐明,在贯彻公文中定义其值:

EOCViewClass.h

extern const NSTimeInterval EOCViewClassAnimationDuration;


EOCViewClass.m

const NSTimeInterval EOCViewClassAnimationDuration = 0.3;

对此字符串常量,则会像这么:

EOCViewClass.h

extern NSString *const EOCViewClassStringConstant;


EOCViewClass.m

NSString *const EOCViewClassStringConstant = @"EOCStringConstant";

常量定义是从右往左解读,下面的演示中就是概念了一个常量指针,其针对性一个
NSString 对象,
这样该常量就不会被擅自改动。至于那种透露出来的类常量最前头是不是丰裕字母k,
可以遵照自己习惯在集体中开展预约,因为从 iOS
的接口中本身看齐这两种处境都有, 如

NSString *const UIApplicationLaunchOptionsRemoteNotificationKey;
NSString *const UIApplicationLaunchOptionsLocalNotificationKey;

还有:

NSString *const kCAAnimationCubic;
NSString *const kCAAnimationCubicPaced;

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图