2008 Archives
重新擦亮思考的火花 原文: http://www.china-pub.com/37838 孟岩 上世纪九十年代初期,当时正在加州大学埃尔文分校攻读博士学位的Douglas Schmidt在观察了他所参与的软件项目开发实践之后,得出一个结论,即未来的软件开发将越来越多地体现为整合(integration),而不是传统意义上的编程(programming)。换言之,被称为
"软件开发者" 的这个人群,将越来越明显地分化:一部分人开发核心构件和基础平台,而更多地人将主要是配置和整合现有构件以满足客户的需求,类似现代汽车、机床和家用电器制造业的产业格局即将到来。面对这一前景,博士生Schmidt一方面写文章对于其进步意义大加赞扬,另一方面毫不犹豫地投入到核心构件及平台的开发阵营中去。他很清楚,在这样一种分工体系中,由于软件整合产业很难出现垄断局面,因此大多数利润总是被截留在上游,人当然要往高处走,整合是好事,但他老兄宁可让别人来做这个好事。 事实上,软件产业中大多数看上去挺靠谱的预测都被历史的发展无情地抛到垃圾堆里了,然而Schmidt博士生的这个预测却惊人的准确,其后十几年软件工业的发展完美地印证了他当年的判断。因此,他本人基于这一预测所选择的人生道路也一帆风顺。如今已经是教授的Douglas Schmidt先后创造了ACE、TAO、CIAO等一系列分布式计算基础件,先后主导了美国学界和国防领域内若干重大科研与实际开发项目,称为世人公认的分布式计算架构领导者。 抛开他个人的辉煌不说,"整合化"趋势实际上已经深刻地改变了世界软件工业的面貌,从而也影响了身为晚进者的我们的命运。如今大部分的程序员实际上是在整合与配置现有资源以满足需求,而不是真正意义上的"编程"。这当然是一件好事,整合同样需要深刻的洞察力和创新精神,优秀的整合者与天才的程序员一样不可多得,甚至更加罕见。然而我们也不能不承认,大多数整合性的工作是机械的,简单的,重复的,欠缺创意的,深入的思考往往不必要。因此,在这个整合为王的时代里,思考的精神在钝化。更有甚者,互联网和搜索引擎的出现大大加速了这种钝化,几乎所有的问题都有人解决并且张贴在互联网上了,因此独自思考和解决问题已经成了不必要的、降低效率的行为,不但不时髦,而且不经济。软件开发迅速成为一个强调搜索和短期记忆力的技能,我想这是50年前第一代程序员们做梦也没有想到的。 老实讲,就整体而言,我仍然认为这是一种进步。任何一个产业的成熟,无不伴随着分工的明晰、技能的简化和从业门槛的降低。与少数人享受思考乐趣的需求相比,大多数人享受便宜而无处不在的软件服务的需求显然远为重要。但是,对于身处软件行业中的个体来说,思考力的削弱和丧失却是不折不扣的悲剧。这一点不必过多解释,正在苦苦寻找自己核心竞争力的开发者们都知道我说的是什么意思。几年来对中国开发者社群的近距离观察使我确信,尽管作为一个产业,中国软件一直享受着比较快的成长,但是总体而言,中国的软件开发者越来越迷惘、焦躁和不自信。这一情况当然是由多种原因导致的,但开发者们每念及此,多抱怨体制、产业、市场等身外之物,实在也有失偏颇。评心而论,这几年中国软件技术界的生存环境还是有了很大改善,对于那些真正出类拔萃的程序员来说,过上一种充实自信的生活并不困难。摆在每一个个体面前的主要问题还是在于能否出类拔萃,而这就需要我们重新找回思考的能力。具备强悍思考能力的人,也就具备强悍的解决问题的能力,而这样的开发者永远都是产业中的稀缺资源。
我认为这正是《代码之美》这本书的一个重要价值。合作的诸位大师级作者,给我们一个很好的机会,让我们能够一边阅读,一边思考,找回深思熟虑的智慧火花。这本书里所讲的每一个问题,可以说都是程序员在工作中会遇到或者至少会擦边的问题,既没有故弄玄虚的文字游戏,也没有携带了领域知识的私货,只有朴实而实际的一个个问题。虽然不是以提问的方式给出,但在整个阅读的过程中,我们还是能够找到很多机会与大师互动,不断地发现问题和解决问题。我在阅读中经常感到,看上去一个很简单的问题,却被这些大师们一层一层挖掘的如此深入,到最后阶段不由得令人感到战栗和震撼。看着这些智慧的光芒,我们不但可以领略大师之所谓称为大师的秘密,而且也认识到思考的真谛。因此,千万不要想看小说一样一带而过,那样会错过本书95%的价值!我们不是要阅读这些文字,而是要与文字背后的作者交流学习,一点一点把自己的心得记下来,对于作者提出的新问题,先自己思考,直接写程序尝试,争取跟上大师的思路,甚至可能需要反复几遍,才能真正读通这本书。这样的精力不会是白费的,读者应当认识到,当我们拥有这本书的时候,我们获得了怎样宝贵的机会,可以在相对比较短的时间里有效地提升自己的思考能力。这是一个机会,也是一次考验,我绝对相信,通过了这次考验的读者,会在思考和解决问题的能力上有一个大的进步。
不是我故作潇洒,
也许人心太复杂,
让我感到害怕往事就忘了它吧,
为何你不肯作罢,
你不要说我是个无情的人,
说我不曾真正爱过也许就像是爱这么简单的一个字,
却占据了我生命所有重要的篇幅
别说我总是沉默,
别说我总是冷漠,
你又何必再触动我内心深处也许就像是爱这么简单的一个字,
却是我一生一世不能抛开的包袱
我也许一无所有,
至少我曾经拥有,
把爱挂在嘴边的人如何体会,
我所谓的爱
itemNodes = [doc nodesForXPath:@"ItemSearchResponse/Items/Item" error:&error];
doc 为NSXMLDocument boject,上面的语句的意思是按ItemSearchResponse-->Items--->Item
顺序查找Item,保存在NSArray itemNodes
NSXMLDocument:An instance of NSXMLDocument represents an XML document as internalized into a logical tree structure. An NSXMLDocument object can have multiple child nodes but only one element, the root element. Any other node must be a NSXMLNode object representing a comment or a processing instruction. If you attempt to add any other kind of child node to an NSXMLDocument object, such as an attribute, namespace, another document object, or an element other than the root, NSXMLDocument raises an exception. If you add a valid child node and that object already has a parent, NSXMLDocument raises an exception. An NSXMLDocument object may also have document-global attributes, such as XML version, character encoding, referenced DTD, and MIME type.
- (NSString *)stringForPath:(NSString *)xp ofNode:(NSXMLNode *)n
{
NSError *error;
NSArray *nodes = [n nodesForXPath:xp error:&error];
if (!nodes) {
NSAlert *alert = [NSAlert alertWithError:error];
[alert runModal];
return nil;
}
if ([nodes count] == 0) {
return nil;
}
else return [[nodes objectAtIndex:0] stringValue];
}
从NSXMLNode 使用nodesForPath 搜索 :
比如NSXMLNode"<Item><ASIN>0321503619</ASIN><DetailPageURL>http://www.amazon.com/Cocoa-Programming-Mac-OS-3rd/dp/0321503619%3FSubscriptionId%3D1CKE6MZ6S27EFQ458402%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0321503619</DetailPageURL><ItemAttributes><Author>Aaron Hillegass</Author><Manufacturer>Addison-Wesley Professional</Manufacturer><ProductGroup>Book</ProductGroup><Title>Cocoa(R) Programming for Mac(R) OS X (3rd Edition)</Title></ItemAttributes></Item>"
可以传入ASIN,DetailPageURL,Manufacture来取ASIN,URL,出版商.
NSXMLNode :Objects of the NSXMLNode class are nodes in the abstract, logical tree structure that represents an XML document. Node objects can be of different kinds, corresponding to the following markup constructs in an XML document: element, attribute, text, processing instruction, namespace, and comment. In addition, a document-node object (specifically, an instance of NSXMLDocument) represents an XML document in its entirety. NSXMLNode objects can also represent document type declarations as well as declarations in Document Type Definitions (DTDs). Class factory methods of NSXMLNode enable you to create nodes of each kind. Only document, element, and DTD nodes may have child nodes.
翻翻以前的代码,留着用:
ABAddressBookRef book = ABAddressBookCreate();
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(book);
CFIndex nPeople = ABAddressBookGetPersonCount(book);
NSMutableArray *masterList = [[NSMutableArray alloc] init];
for (int i = 0; i < nPeople; i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(people, i);
CFStringRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
CFStringRef phonenum=ABMultiValueCopyValueAtIndex(ABRecordCopyValue(ref,kABPersonPhoneProperty) ,0);
[masterList addObject:[NSString stringWithFormat: @"%@%@%@", (NSString *)firstName,(NSString *)lastName, (NSString *)phonenum]];
}
[masterList release];
测试代码:
NSString *urlString =@"http://macgeeks.cn/index.php";
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:30];
NSData *urlData;
NSURLResponse *response;
NSError *error;
char *buffer[40960];
memset(buffer,0,sizeof(40960));
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
[urlData getBytes:buffer];
printf("%s\n",buffer);
Directive | Definition |
|---|---|
Begins the declaration of a class or category interface. | |
Begins the definition of a class or category. | |
Begins the declaration of a formal protocol. | |
Ends the declaration/definition of a class, category, or protocol. |
following mutually exclusive directives specify the visibility of instance variables:
Directive | Definition |
|---|---|
Limits the scope of an instance variable to the class that declares it. | |
Limits instance variable scope to declaring and inheriting classes. | |
The default is @protected.
These directives support exception handling:
Directive | Definition |
|---|---|
Defines a block within which exceptions can be thrown. | |
Throws an exception object. | |
Catches an exception thrown within the preceding | |
Defines a block of code that is executed whether exceptions were thrown or not in a preceding |
In addition, there are directives for these particular purposes:
Directive | Definition |
|---|---|
Declares the names of classes defined elsewhere. | |
Returns the compiled selector that identifies method_name. | |
Returns the protocol_name protocol (an instance of the Protocol class). ( | |
Yields a character string that encodes the type structure of type_spec. | |
Defines a constant | |
Defines a constant | |
Defines a block of code that must be executed only by one thread at a time. |
- (void)awakeFromNib
{
_imageArray = [NSMutableArray new];
NSBundle * mainBundle = [NSBundle mainBundle];
NSArray * imagePaths = [mainBundle pathsForResourcesOfType:@"jpg"
inDirectory:nil];
int count = [imagePaths count];
NSMutableArray *colorArray = [NSMutableArray arrayWithObjects:
nil];
int i;
for (i = 0; i < count; i++) {
NSImage *image = [[NSImage alloc] initWithContentsOfFile:
[imagePaths objectAtIndex:i]];
[image lockFocus];
[NSBezierPath fillRect:NSMakeRect(0., 0., 200., 200.)];
[[NSString stringWithFormat:@"hello %d", [_imageArray count]] drawAtPoint:NSMakePoint(5., 5.) withAttributes:nil];
[image unlockFocus];
MyImageItem *item = [[MyImageItem alloc] initWithImage:image imageID:[NSString stringWithFormat:@"image-%d", [_imageArray count]]];
[_imageArray addObject:item];
[image release];
}
[u_imageBrowser setDataSource:self];
[u_imageBrowser reloadData];
}
-(void)drawInRect:(CGRect)b inContext:(CGContextRef)ctx
{
NSLog(@"drawing");
CGAffineTransform tf;
tf = CGAffineTransformMake(b.size.width / funcRect.size.width, 0,
0, b.size.height / funcRect.size.height,
b.size.width/2, b.size.height/2);
CGContextSaveGState(ctx);
CGContextConcatCTM(ctx, tf);
CGContextSetStrokeColorWithColor(ctx, color);
CGContextSetLineWidth(ctx, 0.4);
float distance = funcRect.size.width / HOPS;
float currentX = funcRect.origin.x;
BOOL first = YES;
while (currentX <= funcRect.origin.x + funcRect.size.width) {
float currentY = [self valueAt:currentX];
if (first) {
CGContextMoveToPoint(ctx, currentX, currentY);
first = NO;
} else {
CGContextAddLineToPoint(ctx, currentX, currentY);
}
currentX += distance;
}
CGContextStrokePath(ctx);
CGContextRestoreGState(ctx);
}
- (IBAction)createNewPolynomial:(id)sender
{
Polynomial *p = [[Polynomial alloc] init];
[polynomials addObject:p];
CALayer *layer = [CALayer layer];
CGRect b = [[self layer] bounds];
b = CGRectInset(b, MARGIN, MARGIN);
CGPoint zeroPoint;
zeroPoint.x = 0;
zeroPoint.y = 0;
[layer setAnchorPoint:zeroPoint];
[layer setFrame:b];
[layer setDelegate:p];
[layer setCornerRadius:12];
[layer setBorderColor:[p color]];
[layer setBorderWidth:3.5];
[[self layer] addSublayer:layer];
[layer display];
CABasicAnimation *anim
= [CABasicAnimation animationWithKeyPath:@"position"];
[anim setFromValue:[NSValue valueWithPoint:[self randomOffViewPosition]]];
[anim setToValue:[NSValue valueWithPoint:NSMakePoint(MARGIN,MARGIN)]];
[anim setDuration:1.0];
CAMediaTimingFunction *f
= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[anim setTimingFunction:f];
[layer addAnimation:anim forKey:@"whatever"];
}
- (IBAction)deleteRandomPolynomial:(id)sender
{
NSArray *polynomialLayers = [[self layer] sublayers];
if ([polynomialLayers count] == 0) {
NSBeep();
return;
}
int i = random() % [polynomialLayers count];
NSPoint toPoint = [self randomOffViewPosition];
CALayer *layerToPull = [polynomialLayers objectAtIndex:i];
CABasicAnimation *anim
= [CABasicAnimation animationWithKeyPath:@"position"];
[anim setValue:layerToPull forKey:@"representedPolynomialLayer"];
[anim setFromValue:[NSValue valueWithPoint:NSMakePoint(MARGIN,MARGIN)]];
[anim setToValue:[NSValue valueWithPoint:toPoint]];
[anim setDuration:1.0];
CAMediaTimingFunction *f
= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[anim setTimingFunction:f];
[anim setDelegate:self];
[layerToPull addAnimation:anim forKey:@"whatever"];
[layerToPull setPosition:CGPointMake(toPoint.x, toPoint.y)];
}
NSPoint bottom = NSMakePoint((bounds.size.width/2.0), 0);
NSPoint bottom1 = NSMakePoint((bounds.size.width), 0);
NSPoint bottom2 = NSMakePoint(0,(bounds.size.height));
//NSPoint bottom = NSMakePoint((0), 0);
NSPoint top = NSMakePoint((bounds.size.width/2.0), bounds.size.height);
NSPoint left = NSMakePoint(0, (bounds.size.height/2.0));
NSPoint right = NSMakePoint(bounds.size.width, (bounds.size.height/2.0));
[NSBezierPath setDefaultLineWidth:5];
//[NSBezierPath setDefaultLineWidth:<#(CGFloat)lineWidth#>];
[[NSColor whiteColor] set];
[NSBezierPath fillRect:bounds];
[[NSColor redColor] set];
[NSBezierPath strokeRect:bounds];
//[NSBezierPath strokeLineFromPoint:top toPoint:bottom];
[NSBezierPath strokeLineFromPoint:top toPoint:right];
[NSBezierPath strokeLineFromPoint:top toPoint:left];
//[NSBezierPath strokeLineFromPoint:right toPoint:left];
[NSBezierPath strokeLineFromPoint:bottom2 toPoint:bottom1];
[NSBezierPath strokeLineFromPoint:right toPoint:bottom];
[[NSColor blueColor] set];
[[NSBezierPath bezierPathWithOvalInRect:bounds] stroke];


