Objective-C 神在细节之中

“神在细节之中”

Objective-C 是 C 语言的扩展,增加了动态类型和面对对象的特性。它被设计成具有易读易用的,支持复杂的面向对象设计的编程语言。它是 Mac OS X 以及 iPhone 的主要开发语言。

Cocoa 是 Mac OS X 上主要的应用程序框架之一。它由一组 Objective-C 类组成,为快速开发出功能齐全的 Mac OS X 应用程序提供支持。

而在日常的编程中,我们除了要写代码,还需要去阅读别人的代码,熟悉过往的业务逻辑。不知,你可曾发过牢骚:这代码怎么能这么写呢?有些时候我们的代码,也会被别人去读,不知你可曾想过,当别人读到你的代码的时候会作何评价。诚然,“让代码能够工作”是做为开发者的头等大事。但是,代码的可维护性却是更加影响深远的一件事情。你的代码既有可能在下一个版本中被修改,也极有可能被交给另外的同事去修改。毕竟我们写代码,不止是在和机器沟通,而且也是在和人沟通——和其他的程序员沟通。大家都知道“学好普通话,走遍天下都不怕”,同样的道理:写出一手漂亮的代码,你和谁沟通都没问题。

即使你的原始代码修改之后,其代码风格和可读性仍会影响到可维护性和可扩展性。即使代码不复存在,你的风格和律条仍存活下来。

下面我们将围绕一些基本的准则展开讨论,目的是让我们写出一手漂亮的代码,更好的用代码与其他同事沟通,也为了提高我们代码的可维护性和可修改性,也是为了让我们自己工作的地方有一个愉悦的代码环境。

(PS:当你真的按照这些看似偏执的规则去做的时候,你就真的能够发现“伟大来自细节”,而且会受益匪浅。保剑锋自磨砺出,梅花香自苦寒来。)

总则

1.Don’t repeat your self.

2.代码自注释,依靠代码本身来表达你的设计意图,不要依赖注释。

3.单一指责,无论是类、函数、模块、包尽可能令其指责纯净且单一。

4.死程序不说谎,不要因为防止Crash写奇葩的代码。程序Crash了,反而更容易查找错误。

5.借用美国童子军军规:让营地比你来时更干净。

格式

1.任意函数长度不得超过50行。

2.任意行代码不得超过80字符。可以在设置中设置超过80个字符的提醒。

3.在定义函数的行前留白一行

4.功能相近的代码要放在一起。

5.使用#pragma来切分不同功能区域的代码。

6.二元运算符和参数之间需要放置一个空格,一元运算符、强制类型转换和参数之间不放置空格。关键字之后圆括号之前需要放置一个空格.


  1. void *ptr = &value + 10 * 3; 
  2. NewType a = (NewType)b; 
  3. for (int i = 0; i < 10; i++) { 
  4. doCoolThings(); 

7.长的字面值应被拆分为多行。


  1. NSArray *theShit = @[ 
  2. @"Got some long string objects in here.", 
  3. [AndSomeModelObjects too], 
  4. @"Moar strings." 
  5. ]; 
  6. NSDictionary *keyedShit = @{ 
  7. @"this.key": @"corresponds to this value", 
  8. @"otherKey": @"remoteData.payload", 
  9. @"some": @"more", 
  10. @"JSON": @"keys", 
  11. @"and": @"stuff", 
  12. }; 

命名

命名是编程中最基本的技能,我们给变量、函数、类、包等等命名。给他们以名字,让他们有意义,既能表示他们到底是做什么的,也能将其与其他变量区别开来。而通过,语言的发展史,我们也能够看到“方便编程人员理解和使用”一直都是编程语言发展的动力之一,而命名则是其最最核心的环节。像人一样娶一个好名字至关重要,“丁当”总比“狗蛋”来的好听。 为什么要命名?命名代表着抽象,我们使用名字将一些没必要关系的细节隐去,减少我们自己的记忆成本,也更加方便我们理解。用过C语言的人都知道,一个变量名最终会转化成类似于~~~0x11111111~~~之类的地址,相比去理解和记忆这些地址,用一个更加抽象的变量名来代表这些地址。无论从理解还是记忆上都要方便的。

命名一定要“名副其实”,尽可能使用有意的名称,而且这个意义和指称的变量真实意义相关。

尽量不要出现没有任何意义的命名类似于下述形式的命名:


  1. int a = 1; 
  2. int b = 3; 
  3. CGPoint point = CGPointMake(a,b); 

如果换成下面的形式是不是可读性强了很多:


  1. int startX = 1; 
  2. int startY = 3; 
  3. CGPoint startPoint = CGPointMake(startX,startY); 

命名首字母大写,其他命名首字母小写。并且采用驼峰格式分割单词。

例如:BWTest

使用能够读出来的名称

人类长于记忆和使用单词。大脑中的相当一部分就是用来容纳和处理单词的。单词如果能够读的出来,则非常方便我们阅读和理解。

错误的示例: genymdhms (生成日期,年、月、日、时、分、秒)

正确的实例: generationTimeStamp

使用可搜索的名称

单字母名称和数字常量有一个问题,就是很难在一大篇文字中找出来。试想一下,你找~~~MAX_CLASSES_PER_STUDENT~~~容易还是找数字7容易。

文件名

文件名反映出了其实现了什么类(包括大小写),你需要遵循所参与醒目的约定。

文件的扩展名及其意义如下:

类别的扩展名以“被扩展的类名+自定义命名部分组成”

例如:NSSstring+Utils.h

缩略词

虽然方法命名不应使用缩略词,然而有些缩略词在过去被反复的使用,所以使用这些缩略词能更好的的表达代码的含义。下表列出了Cocoa可接受的缩略词。

以下是一些常用的首字母缩略词:ASCII,PDF,XML,HTML,URL,RTF,HTTP,TIFF,JPG,PNG,GIF,LZW,ROM,RGB,CMYK,MIDI,FTP…

宏定义全部字母大写,例如:#define BW_DEBUG 1

常量定义,字符串定义以小写字母 k 开头,随后首字母大写


  1. static NSString* const kBWBarTitle = @"动态"; 

如果要定义常量使用static const优于宏定义,前者会进行类型检查

因为OC没有命名空间的概念,所以使用前两个或者多个字母来表示命名空间,例如”NSObject中的NS”,我们也使用自己的命名空间。比如


  1. 红点中使用了VAS:VASAddValueInfo... 
  2. 钱包中使用了QW:QWApplication.... 

注释

让代码自注释,不要依赖注释来解释自己的设计或者编码意图。除了特殊情况外,代码中不要有多余的注释。

函数

函数长度不要超过50行,小函数要比大函数可阅读性和可复用性强。

零元函数最好,一元函数也不错,二元函数担心了,三元函数有风险,高于三元需重构。函数的参数越多,引起其变化的因素就越多。越不利于以后的修改。

不知道当你看到如下形式的函数的时候,是什么想法:


  1. - (void)RequestGetLocation:(int)lat lon:(int)lon alt:(int)alt isMars:(BOOL)yn bJiejingSOSO:(BOOL)bJiejingSOSO; 

尽量少的写有副作用的函数

尽量不要出现火车链式的命名,如果可以尽量使用过程变量替代。

反例例如:


  1. _needLogoutAccount = [[[[BWAppSetting GetInstance] appSetting] valueForKey:NeedLogoutAccounts] retain]; 

考虑如果改成下述模样,是不是可读性一下子提高了很多:


  1. BWAppSetting* shareSetting = [BWAppSetting GetInstance]; 
  2. BWLockDictionary* defaultSettings = [shareSetting appSetting]; 
  3. _needLogoutAccount = [[defaultSettings valueForKeyPath:NeedLogoutAccounts] retain]; 

调用时所有参数应该在同一行


  1. [myObject doFooWith:arg1 name:arg2 error:arg3]; 

或者每行一个参数,以冒号对齐:


  1. [myObject doFooWith:arg1 
  2. name:arg2 
  3. error:arg3]; 

对于参数过多的函数,尽量使用后面一种对其方式。

不要使用下面的缩进风格:


  1. [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg 
  2. error:arg3]; 
  3. [myObject doFooWith:arg1 
  4. name:arg2 error:arg3]; 
  5. [myObject doFooWith:arg1 
  6. name:arg2 // aligning keywords instead of colons 
  7. error:arg3]; 

如果对传入参数进行数据保护尽量不要用~~~if(!objc)~~~,使用断言来处理。


  1. - (void) sendArgs:(NSDictionary*)args { 
  2. NSAssert(args, @"args is nil"); 
  3. ..... 

方法参数名前一般使用的前缀包括“the”、“an”、“new”。

示例:


  1. - (void) setTitle: (NSString *) aTitle; 
  2. - (void) setName: (NSString *) newName; 
  3. - (id) keyForOption: (CDCOption *) anOption 
  4. - (NSArray *) emailsForMailbox: (CDCMailbox *) theMailbox; 
  5. - (CDCEmail *) emailForRecipients: (NSArray *) theRecipients; 

Block相关

在block中使用到self变量的时候,一定要先weak再strong.


  1. __weak typeof(self) weakSelf = self; 
  2. [self doABlockOperation:^{ 
  3. __strong typeof(weakSelf) strongSelf = weakSelf; 
  4. if (strongSelf) { 
  5. ... 
  6. }]; 

控制结构

顺序结构

分支结构

if-else结构超过四层的时候,要考虑重构。多层的ifelse结构极其难维护。

当需要满足一定条件时才执行某项操作时,最左边缘应该是愉快路径代码。不要将愉快路径代码内嵌到if语句中。多个return是正常合理的。

良好的风格:


  1. - (void) someMethod { 
  2. if (![someOther boolValue]) { 
  3. return; 
  4. //Do something important 

反面教材:


  1. - (void) someMethod { 
  2. if ([someOther boolValue]) { 
  3. //Do something important 

所有的逻辑块必须使用花括号包围,即使条件体只需编写一行代码也必须使用花括号。

良好的风格:


  1. if (!error) { 
  2. return success; 

反面教材:


  1. if (!error) 
  2. return success; 
  3. ... 
  4. if (!error) return success; 

循环结构

遍历可变容器之前,需要复制该容器,遍历该容器的Copy.


  1. //typeof(self.cells) is NSMutableArray 
  2. NSArray* cellArrays = [self.cells copy]; 
  3. for(UITableViewCell* cell in cellArrays) { 
  4. ... 

尽量不要使用异常,尤其是不要将异常做为业务逻辑的一部分,在异常中尝试进行灾难恢复。

类与对象

明确指定构造函数

注释并且明确指定你的类的构造函数。

对于需要继承你的类的人来说,明确指定构造函数十分重要。这样他们就可以只重写一个构造函数(可能是几个)来保证他们的子类的构造函数会被调用。这也有助于将来别人调试你的类时,理解初始化代码的工作流程。 ###重载指定构造函数

当你写子类的时候,如果需要 init… 方法,记得重载父类的指定构造函数。

如果你没有重载父类的指定构造函数,你的构造函数有时可能不会被调用,这会导致非常隐秘而且难以解决的 bug。

重载 NSObject的方法

如果重载了 NSObject 类的方法,强烈建议把它们放在 @implementation 内的起始处,这也是常见的操作方法。

通常适用(但不局限)于init…,copyWithZone:,以及dealloc方法。所有init…方法应该放在一起,copyWithZone: 紧随其后,最后才是dealloc 方法

初始化

不要在 init 方法中,将成员变量初始化为 0 或者 nil;毫无必要。

现代的 Ojbective-C 代码通过调用 alloc 和 init 方法来创建并 retain 一个对象。由于类方法 new 很少使用,这使得有关内存分配的代码审查更困难。

保持init函数简洁,不要让init函数成为千行的大函数,当超过50行的时候,适当考虑分拆一下。

良好的风格实例:


  1. - (void) commonInit 
  2. _rightAppendImageView = [UIImageView new]; 
  3. [self.contentView addSubview:_rightAppendImageView]; 
  4. - (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
  5. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
  6. if (!self) { 
  7. return self; 
  8. [self commonInit]; 
  9. return self; 

UIView的子类初始化的时候,不要进行任何布局操作。布局操作在LayoutSubViews里面做。

UIView的子类布局必须在layoutSubViews里面进行,需要布局的时候调用~~~setNeedLayout~~~来告诉系统,需要重新布局该View,不要直接调用~~~layoutSubViews~~~

保持公共 API 简单

"保持类简单;避免 “厨房水槽(kitchen-sink)” 式的 API。如果一个函数压根没必要公开,就不要这么做。用私有类别保证公共头文件整洁。"

与 C++ 不同,Objective-C 没有方法来区分公共的方法和私有的方法 – 所有的方法都是公共的(译者注:这取决于 Objective-C 运行时的方法调用的消息机制)。因此,除非客户端的代码期望使用某个方法,不要把这个方法放进公共 API 中。尽可能的避免了你你不希望被调用的方法却被调用到。这包括重载父类的方法。对于内部实现所需要的方法,在实现的文件中定义一个类别,而不是把它们放进公有的头文件中。


  1. // GTMFoo.m 
  2. #import "GTMFoo.h" 
  3. @interface GTMFoo (PrivateDelegateHandling) 
  4. - (NSString *)doSomethingWithDelegate; // Declare private method 
  5. @end 
  6. @implementation GTMFoo(PrivateDelegateHandling) 
  7. ... 
  8. - (NSString *)doSomethingWithDelegate { 
  9. // Implement this method 
  10. ... 
  11. @end 

在OC2.0以后,你可以在实现文件中使用,类扩展来生命你的私有类别:
1

@interface GMFoo () { ... }

每个文件中只创建或者实现一个类。同一个文件中不要存在多个类。

Protocol单独用一个文件来创建。尽量不要与相关类混在一个文件中。

类的私有变量以”_“开头。

创建私有变量,份两种情况。 第一种情况子类需要继承的,在头文件中定义:


  1. // BWTest.h 
  2. @interface BWTest : NSObject 
  3. NSString* _name; 

第二种情况,不需要子类继承的,在实现文件中以Category的方式定义:


  1. // BWTest.m @interface BWTest () { NSString* _name; } 
  2. @implementation BWTest 
  3. ... 
  4. @end 

公有变量在一般使用属性的方法定义 @property (….) …

使用委托模式,设置delegate的时候,在ARC下使用 weak ;在MRC下使用 retain ,并且在dealloc中将其指针置空。

外部引用对象,外部不会发生set操作的对象,比如在创建界面元素的时候,使用readonly属性。


  1. @interface BWView : UIView 
  2. @property (nonatomic, strong, readonly) UIView* backgoundView; 
  3. @end 
  4. @implementation BWView 
  5. @end 

在类定义中使用到自己定义的类的时候,尽量不要在头文件中引入自己定义的类的同文件,使用 @class 替换。在实现文件中引入相应头文件。

例如:


  1. //BWTest.h @class BWDataCenter; @interface BWTest : NSObject @property (nonatomic, strong) BWDataCenter* dataCenter; @end 
  2.  
  3. //BWTest.m 
  4.  
  5. import “BWDataCenter.h” 
  6.  
  7. @implementation BWTest @end  

如果一个类只是DTO(data transfer object),只是作为数据传输使用,可以不用引入使用的自定义的类的头文件,只是用 @class ,表明相应的自定义的类型。

对于DTO类型的对象,在给其成员变量设置值的时候可以考虑使用KVC,实现下述函数:


  1. - (void) setValue:(id)value forKey:(NSString *)key 
  2. if ([key isEqualToString:kRedDotAppInfoPath]) { 
  3. .... 
  4. } else if ... 
  5. .... 
  6. - (id) valueForKey:(NSString *)key { 
  7. .... 

点标记语法

属性和幂等方法(多次调用和一次调用返回的结果相同)使用点标记语法访问,其他的情况使用方括号标记语法。 良好的风格:


  1. view.backgroundColor = [UIColor orangeColor]; 
  2. [UIApplication sharedApplication].delegate; 

反面实例:


  1. [view setBackgroundColor:[UIColor orangeColor]]; 
  2. UIApplication.sharedApplication.delegate; 

Cocoa相关

每个NSObject都有其生命周期,要在其生命周期的合适的时机做合适的事情。

例如:在初始化的时候,进行变量初始化,在销毁的时候,销毁变量等等。

尽量不要在界面布局的写任何死数字

错误的示范:


  1. CGFloat delta = SYSTEM_VERSION >= 7.0 ? 0.0f : -14.0f; 
  2. newFrame = CGRectMake(245 + delta, 
  3. (self.frame.size.height - tipNewSize.height)/2, 
  4. tipNewSize.width, 
  5. tipNewSize.height); 
  6. dotFrame = CGRectMake(258.0 + delta, (self.frame.size.height - tipDotSize.height)/2, 
  7. tipDotSize.width, 
  8. tipDotSize.height); 
  9. iconFrame = CGRectMake(245 + delta, 
  10. (self.frame.size.height - tipIconSize.height)/2, 
  11. tipIconSize.width, 
  12. tipIconSize.height); 
  13. numFrame = CGRectMake(245+delta, (self.frame.size.height - tipNumSize.height)/2, tipNumSize.width, tipNumSize.height); 

正确的示范:


  1. CGFloat cellHeight = CGRectGetHeight(self.frame); 
  2. CGFloat cellWidth = CGRectGetWidth(self.frame); 
  3. CGRect numFrame = CGRectZero; 
  4. numFrame.size = CGSizeMake(cellWidth,cellHeight); 
  5. ... 

布局时尽量使用相对布局,比如使用子View在父View中的相对位置。

在使用UITableView和UITableViewCell的时候一定要考虑到cell被复用的情况,在合适的时机对重用的cell进行清除操作。

为UITableViewCell功能或者子View的时候有限考虑子类化。尽量不要使用在delegate中为Cell添加View。子类化,利于Cell重用和对cell内新添加的子View的布局。

良好的风格示例:


  1. @interface BWSettingCell : UITableViewCell 
  2. @property (nonatomic, strong, readonly) UIImageView* rightAppendImageView; 
  3. @end 
  4. @implementation BWSettingCell 
  5. - (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
  6. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
  7. if (!self) { 
  8. return self; 
  9. _rightAppendImageView = [UIImageView new]; 
  10. [self.contentView addSubview:_rightAppendImageView]; 
  11. return self; 
  12. - (void) layoutSubviews 
  13. [super layoutSubviews]; 
  14. CGSize rightImageSize = _rightAppendImageView.image.size; 
  15. _rightAppendImageView.frame = CGRectMake(CGRectGetWidth(self.frame) - rightImageSize.width, 
  16. (CGRectGetHeight(self.frame) - rightImageSize.height) /2, 
  17. rightImageSize.width, 
  18. rightImageSize.height); 
  19. @end 

反面教材:


  1. - (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
  2. static NSString* const settingCellIdentify = @"settingCellIdentify"; 
  3. UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:settingCellIdentify]; 
  4. if (!cell) { 
  5. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:settingCellIdentify]; 
  6. static int kSettingCellSubViewTag = 90001; 
  7. //非常错误的地方,尽量不要这样写 
  8. [cell.contentView removeAllSubviews]; 
  9. UIImageView* rightAppendingView = [UIImageView new]; 
  10. rightAppendingView.image = nil; 
  11. rightAppendingView.frame = CGRectMake(230, 8, 30, 30); 
  12. [cell.contentView addSubview:rightAppendingView]; 
  13. return cell; 

设计模式相关

使用设计模式的最基本原则,除非你明确知道自己要做件什么事情,而且知道使用特定设计模式带来的影响,否则不要刻意的使用设计模式。

单例模式

创建一个单例模式可以使用dispatch_once


  1. + (instancetype)defaultManager 
  2. if (!_defaultManager) { 
  3. static dispatch_once_t onceToken; 
  4. dispatch_once(&onceToken, ^{ 
  5. _defaultManager = [[FlappyEggManager alloc] init]; 
  6. }); 
  7. return _defaultManager; 

观察者模式

如果只是单纯的传递数据,不要使用观察者模式,容易导致逻辑链断裂。

本文作者:佚名

来源:51CTO

时间: 2024-09-08 22:18:22

Objective-C 神在细节之中的相关文章

《代码整洁之道》目录—导读

版权声明 代码整洁之道 Authorized translation from the English language edition, entitled Clean Code: A Handbook of Agile Software Craftsmanship, 9780132350884 by Robert C. Martin, published by Pearson Education, Inc, publishing as Prentice Hall, Copyright 2009

风险识别:魔鬼隐藏在细节中

魔鬼之所以名字可怖,是因为它会给人们带来灾难性的后果.而在魔鬼现身为祸人间之前,细节正是其最好的藏身之所. 文/王锡建 杨 毓 对于风险这个魔鬼来说,如果它能够一直局限在企业运营的细枝末节之中的话,确实没必要引起管理者过多的关注,因为企业经营总是面临着无数的波折和矛盾,管理者的精力要用在最能发挥价值的地方.但魔鬼总是不甘蛰伏的,遇到合适的条件,它就要搅起风风雨雨.企业经营千头万绪,所有的活动都是由无数细节组成的,管理者特别是高层管理人员精力有限,不可能时刻盯住所有的事情.而要想识别出藏在细节中的

P2P平台是否靠谱?六大细节告诉你

近千家的P2P网贷平台和高息诱人的收益率,加上眼花缭乱的安全承诺,这种让今天的理财人十分放心动但是又持币难决,在风险和收益之间到底英国怎样取舍?如何选取"靠谱"的项目来进行投资?我们口中所说的风险,既有平台欺诈和跑路的风险,而其实也有遭遇借款人骗贷和信用的风险. 要是我们通过比较主要的P2P平台,那就能发现:网贷的魔鬼其实仍然是藏在老地方,就是在各种细节之中.其实,一个看起来貌似中规中矩的P2P网站,只要我们在看的时候多注意几个细节性的问题,那我们就能通过蛛丝马迹,从而排除其中不规范的

富士康十连跳:魔鬼藏在细节中

新闻观察 当这十个年轻人纵身一跃的时候,其实他们的身后存在着许多无形的推手,社会转型期的集体焦虑.制造业企业残酷的生存法则.社会文化配套上的严重缺失.富士康里的这些年轻生命所承受的沉重,实际上是经济社会发展所付出的一种代价,帮助他们卸掉这些负担,企业的责任不容推卸,政府和社会也都有一份应尽的义务. 专家视线一:一堵墙 这些年轻人踏入社会迈出第一步之后,就迎面碰上了一堵墙.而我们所有的机制都是排斥他们的,我们所有的声音都告诉他们,你们是打工人,你们不属于这里. 2010年5月6日,卢新从阳台纵身跳

《神戒》潘多拉之门挑战BOSS之最

故事还要从普罗米修斯说起,在希腊神话中曾经记述了这么一段.人类因为会用火而成为了万物之灵,在一次人与神的聚会中因为普罗米修斯偏袒人类惹怒了宙斯,所以宙斯收走了人类的火种,从此人类只能过着茹毛饮血的生活,同样作为神灵的普罗米修斯发起了善心,于是私自偷取了上天的火种赠送给了人类,让人类可以用火来烧烤食物,用火来驱走黑暗.前网科技旗下网页游戏<神戒>就是以古希腊神话作为背景打造,这里面自然不会少了这么一段人类重要的改变. 但故事并不是因为人类得到了火种就结束了,<神戒>中的任务也才刚刚开

魔鬼藏在细节中 谈博客外链建设的那些细节

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 行业的竞争日益激烈,各站长频繁接单为增加收入,进出各论坛.博客忙于发外链......其实还有很多细节我们都遗漏了,用博客做外链,我们的博客都准备好了吗?是否真的可以做外链了?很多站长都说博客越来越难做,你们都把自己的博客设置好了吗?今天以新浪博客为例,跟大家分享分享博客的设置: 一. 博客信息如何编写 博客名称: 用你想要做的关键字来起名字,

『 读书笔记 』4月读书总结|博文推荐

原文链接:『 读书笔记 』4月读书总结|博文推荐 写在前面 计划是每月读 5-10 本书,书籍类型大概是三个方面的:金融,技术,管理.之所以选择这三个方面,一方面是因为自己对这三个方面都很有兴趣,其次是被 linkedin 创始人 Hoffman 的 ABZ 理论 深度影响.建议大家都看看 abz 理论那篇文章,如果我有空,也会整理一些常用的这类理论模型到博客里的. 月底读书总结的形式都很简单,只是简单的一个列表和简单的书评,对觉得比较好的书会有单独的读书笔记.另外推荐大家用 excel 来做一

达则兼妓天下,穷则独占妻身——论大数据教的起源

本文的标题语,来自我的高中同学,现就职于阿里集团,擅长跳探戈的某非著名仁波切,在这里对他表示言不由衷的感谢. 与广告技术公司有关的讨论到上一篇告一段落了.作为严肃的学术性自媒体,我们从今天开始进入一个更加圣洁的领域--大数据(big data).请诸位读者找一个面朝大海.春暖花开的小木屋(把你的手机壁纸换成这样一副图也可以),慢慢地闭上眼晴,从心灵深处荡漾起一串串的0和1,随着本文的展开,进入令人激动和颤抖的大数据之国,用虔诚的祈祷让它去解决你生命中的一切悲哀与彷徨吧! 为什么这段话饱含泪水?因

如何让自己的原创文章更吸引用户眼球

众所周知,网站优化过程中优质文章的创造是任何一位seoer都必须时常关注的问题,笔者认为文章不仅仅原创就可以,原创仅仅是网站文章更新过程中最基本的要求,随着搜索引擎算法的不断变化,笔者认为文章除了原创之外,更重要的体现在能否真正解决用户目前存在的问题,能否吸引用户眼球引起读者共鸣才是核心.鉴于此,笔者认为我们主要通过以下几个策略,将优质网站内容和用户喜好结合起来,才能创作出更接地气的文章,好了闲话短续咱们进入今天主题. 第一,文章写作之前首先要分析目标客户群体.因为我们知道无论是我们自己的网站还