太阳是黑色的

少年听雨歌楼上,红烛昏罗帐.壮年听雨客舟中,江阔云低断雁叫西风. 而今听雨僧庐下,鬓已星星也! 悲欢离合总无情,一任阶前点滴到天明.

Macromedia梦

Adobe收购Macromedia。一个在业界并没有引起太多波澜的收购。既没有什么大的战略意义,也没有巨额资金的引诱。38亿美元,对于IT业的收购来说,数目并不是巨大的。

现 在就说这样打造了平面设计的旗舰还为时尚早,虽然这两家公司在已经拥有的领域里都已经举足轻重。Macromedia一直都想往企业级网站架构转 型,Flex就是一个很好的例证。Adobe也非常需要动画制作软件和网页设计软件来为它的Photoshop打开更广阔的天空。这一次,大家似乎都有了 一定的收获。

强强联手?

但愿是吧。

终于的大提琴

从我个人来说,德沃夏克的《大提琴协奏曲》有特殊的意义。首先,这张CD是Crend的。其次,真的如布拉姆斯所说,大提琴居然能够如此有情感。

还记得大一的时候,周末独自一个人听这首曲子,那种慢慢抚慰心灵的感觉,还有就是倾肠般地诉说。维也纳爱乐的弦乐部分一直都是一流的,虽然开始的时候有点显得过于慢了。不过,麦斯基始终保持着浪漫的严谨。伯恩斯坦的配合也从始至终都具有一种平静但是决不平常的呼吸。

差不多都一年没有听这首曲子了,昨天晚上一口气听完以后真的觉得这部大提琴作品的伟大。平易近人,但是一点都不庸俗。

对!这部作品的一个重要元素就是温暖。来自内心和来自世界的温暖。同时,也有痛苦,但是这种痛苦不是喊出来,而是在温暖中浸透的痛苦。

很难说这首作品在大提琴史上的地位。几乎所有的大提琴家都录制了这首作品。

其实肖邦

总还是练习肖邦的曲子。也总还是没有练好。有时发现,肖邦的确还是非常敏感。要不,为什么《船歌》的爱情那么富有幻想呢?当初买那本谱子就是冲着 《船歌》去的。五年过去了,我依然不能在阳光下的小船中荡漾起来。可每每开始《船歌》的头几个小节,我就发现自己真的找到了爱,那种天地间悠悠然忘我的 爱。

已经很多年,我不再听肖邦的唱片,我也曾经发誓要演奏所有肖邦的乐曲。可是,现在,还是很难做到真正只关心艺术了。

哦对了,还有《摇篮曲》,如果有更多人知道它就好了。比起布拉姆斯为小孩准备的“摇篮”,肖邦那似睡非睡的梦境是准备给爱人的。

其实,肖邦,只有爱。这也就足够了。

用人!

这两天作为网络中心的主任,参与了副部长的竞聘工作。也体会到了一些用人单位的苦衷,同时对于今后找工作也有了一些反向的经验。具体地说,那就是,用人单位仅仅通过一个面试,很难看出一个人的优劣。特别是,我们在平时工作中发现的一些不错的人选,都存在着或多或少的表达问题。而有一些人,又显得成熟过渡。很困难作出抉择。

斯克里亚宾的灵动

很久没有仔细听一张唱片,不过这几天听的斯克里亚宾确实让我眼前一亮。的确,要说斯克里亚宾的东西很浪漫派,我承认,但是作品中的那种灵动与秀巧,是任何 一个俄罗斯乐派作曲家的作品不能比拟的。斯克里亚宾的前奏曲水平应该是相当高的,有肖邦的影子。后期作品在色彩上比法国印象派多了一些黑色。斯克里亚宾的 东西没有那么多厚重的理性折射,非常像阳光般的下午。还有一个作品,我建议大家也可以去听听,那就是他的《钢琴协奏曲》。大家就可以发现拉赫玛尼诺夫的作 品其实有很多斯克里亚宾的影子。但是第二乐章的风铃般的飘逸,是绝对的大师级手法。

与老师探讨问题

彭老师:
又来麻烦您了,上次您给我说了关于“约瑟夫问题”的程序以后,我开始注意自己的程序结构的合理性安排。两次上机作业“多项式操作”和“表达式计算”都做好了,这些天终于把“银行的模拟”做好了,请老师看看。我下面大体说一下程序的思路。
首先,我当然用到了“队列”,因为这个程序是“队列”的应用嘛。我使用了2种队列,分别装“刚进入银行的人”和“在某个队上排队的人”,在程序里面是BankIndoor和BankQueue。关于事件的驱动,我思考了很久,最终我采用了一个存放“函数指针”的链表:

1
2
3
4
5
6
typedef struct MethodStruct
{
METHODCALLBACK (*todo)();
METHODSTATE state;
MethodStruct *next;
}MethodNode;

把 每一次要触发的事件都存在这个链表里面,而每一个基本时间段里,都由EnumerateAllMethod()这个函数通过遍历链表来达到出发所有事件的 作用。EnumerateAllMethod通过这个链表每一个节点的state值来判断当前是否激发这个事件。通过这个方法就很容易随机地产生顾客。比 如CustomerArrival()这个函数,每次都产生一个随机数,用于EnumerateAllMethod()判断下一次调用它的时间。关于这种 思路,其实我是参考了Windows的消息触发机制。
在这个事件的链表里面,有三个很重要的事件是CustomerArrival()、 CustomerQueue()、CustomerTODO()。分别处理顾客到来,顾客分队,顾客办理事务这三个事件。这三个函数互相不影响。都由 EnumerateAllMethod统一调用,并且各自监视各自的队列。
最后要说的是关于银行关门的处理,银行到达运营时间的时候产生 READYFORCLOSED的标识,这个时候CustomerArrival()就不触发了,而只触发CustomerQueue()、 CustomerTODO()。当CustomerTODO()检查到所有队列都没有顾客了的时候,就把银行标识改为CLOSED,这样就解决了这个问 题。

通过这次练习,我学到了很多东西,不过也萌发了用C语言来实现事件机制的想法,呵呵,但是我还是觉得有一些难。

程序在Visual C++.NET 2003和Dev-C++下均调试通过。程序运行时间为30秒(可以通过修改#define CLOSETIME 30来进行更改)。

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
 
//****************************************
#define WAIT_INDOOR 1
#define WAIT_QUEUE 2
#define QUEUES 5
#define FAILED 0
#define SUCCEEDED 1
#define OPEN 1
#define CLOSED 0
#define READYFORCLOSED 2
#define OVERFLOW 2
#define CLOSETIME 30
#define MINTIMEARRIVAL 2
#define MINTIMETODO 10
typedef int EVENTTYPE;
typedef int METHODSTATE;
typedef int METHODCALLBACK;
typedef long SYSTEMTIME;
typedef int STATUS;
typedef int BANKSTATE;
typedef int CustomerID;
//****************************************
typedef struct EventStruct
{
EVENTTYPE detail;
SYSTEMTIME occurtime;
CustomerID ID;
}EventNode;
 
typedef EventNode *Event;
 
typedef struct QueueStruct
{
EventNode item;
QueueStruct *next;
}QueueNode;
 
typedef QueueNode *QueuePtr;
 
typedef struct{
QueuePtr front;
QueuePtr rear;
}LinkQueue;
 
typedef struct CustomerStruct
{
SYSTEMTIME arrivaltime;
SYSTEMTIME duration;
}CustomerNode;
 
typedef struct MethodStruct
{
 
METHODCALLBACK (*todo)();
METHODSTATE state;
MethodStruct *next;
}MethodNode;
 
typedef MethodNode *MethodLink;
//*****************************************
LinkQueue BankIndoor;
LinkQueue BankQueue[QUEUES];
MethodLink Methods;
SYSTEMTIME BankClock;
BANKSTATE BankState;
time_t StartTime,EndTime;
CustomerID IDSeed;
//*****************************************
STATUS InitQueue(LinkQueue &amp;Q)
{
Q.front=Q.rear=new QueueNode;
if (!Q.front) exit(OVERFLOW);
Q.front-&gt;next=NULL;
return SUCCEEDED;
}
 
STATUS DestroyQueue(LinkQueue &amp;Q)
{
while(Q.front)
{
Q.rear=Q.front-&gt;next;
delete Q.front;
Q.front=Q.rear;
}
return SUCCEEDED;
}
 
STATUS EnQueue(LinkQueue &amp;Q,Event e)
{
QueuePtr p;
p=new QueueNode;
if (!p) exit(OVERFLOW);
p-&gt;item=*e;p-&gt;next=NULL;
Q.rear-&gt;next=p;
Q.rear=p;
return SUCCEEDED;
}
 
STATUS DeQueue(LinkQueue &amp;Q,Event &amp;e)
{
QueuePtr p;
if(Q.front==Q.rear) return FAILED;
p=Q.front-&gt;next;
*e=p-&gt;item;
Q.front-&gt;next=p-&gt;next;
if (Q.rear==p)
Q.rear=Q.front;
delete p;
return SUCCEEDED;
}
 
int QueueLength(LinkQueue Q)
{
int numbers=0;
while(Q.front!=Q.rear)
{
Q.front=Q.front-&gt;next;
numbers++;
}
return numbers;
}
 
int PlaceCustomer()
{
int min=0;
for (int i=0;i&lt;QUEUES;i++)
{
if(QueueLength(BankQueue[i])&lt;=QueueLength(BankQueue[min]))
min=i;
}
return min;
}
//*****************************************
METHODCALLBACK CustomerArrival()
{
SYSTEMTIME nexttime;
Event node;
if (BankState==READYFORCLOSED)
return 32767;
node=new EventNode;
node-&gt;detail=WAIT_INDOOR;
node-&gt;occurtime=BankClock;
node-&gt;ID=IDSeed++;
srand((unsigned)time(0));
nexttime=rand()%MINTIMEARRIVAL;
EnQueue(BankIndoor,node);
printf("Customer %d arrived in %d\n",node-&gt;ID,BankClock);
delete node;
return nexttime;
}
 
METHODCALLBACK CustomerQueue()
{
Event node;
int nexttime;
node=new EventNode;
if (DeQueue(BankIndoor,node)!=FAILED)
{
node-&gt;detail=WAIT_QUEUE;
srand((unsigned)time(0));
nexttime=rand()%MINTIMETODO+1;
node-&gt;occurtime=nexttime;
printf("Customer %d placed in queue %d(%d)\n",node-&gt;ID,PlaceCustomer(),nexttime);
EnQueue(BankQueue[PlaceCustomer()],node);
}
delete node;
return 0;
}
 
METHODCALLBACK CustomerTODO()
{
Event node;
int counter=0;
node=new EventNode;
for (int i=0;i&lt;QUEUES;i++)
{
if (DeQueue(BankQueue[i],node)!=FAILED)
{
//printf("%d\n",node-&gt;occurtime);
if (node-&gt;occurtime&lt;=0)
{
printf("Customer %d has left from queue %d\n",node-&gt;ID,i);
}
else
{
node-&gt;occurtime--;
EnQueue(BankQueue[i],node);
}
counter++;
}
}
delete node;
if (counter==0&amp;&amp;BankState==READYFORCLOSED)
BankState=CLOSED;
return 0;
}
//判断是否到了停止营业的时间
METHODCALLBACK CheckForClose()
{
if(BankClock==CLOSETIME)
{
BankState=READYFORCLOSED;
printf("The bank is ready for close.\n");
}
return 0;
}
 
//时钟
METHODCALLBACK Clock()
{
BankClock++;
return 0;
}
 
//****************************************
STATUS InitMethods()
{
if (Methods==NULL)
{
Methods=new MethodNode;
Methods-&gt;state=0;
Methods-&gt;next=NULL;
Methods-&gt;todo=Clock;
return SUCCEEDED;
}
else
return FAILED;
}
 
STATUS RegisterMethod(METHODCALLBACK (*m)())
{
MethodLink pointer;
MethodLink node;
pointer=Methods;
while(pointer-&gt;next!=NULL)
pointer=pointer-&gt;next;
node=new MethodNode;
if (node==NULL)
return FAILED;
node-&gt;state=0;
node-&gt;next=NULL;
node-&gt;todo=m;
pointer-&gt;next=node;
return SUCCEEDED;
}
 
STATUS RegisterAllMethod()
{
RegisterMethod(CheckForClose);
RegisterMethod(CustomerArrival);
RegisterMethod(CustomerQueue);
RegisterMethod(CustomerTODO);
return SUCCEEDED;
}
 
STATUS DeleteAllMethod()
{
MethodLink pointer;
MethodLink node;
pointer=Methods;
while(pointer-&gt;next!=NULL)
{
node=pointer;
pointer=pointer-&gt;next;
delete node;
}
return SUCCEEDED;
}
 
STATUS EnumerateAllMethod()
{
MethodLink pointer;
pointer=Methods;
time(&amp;EndTime);
if (difftime(EndTime,StartTime)&gt;=1.0)
{
time(&amp;StartTime);
while(pointer!=NULL)
{
if(pointer-&gt;state==0)
pointer-&gt;state=pointer-&gt;todo();
else
pointer-&gt;state--;
pointer=pointer-&gt;next;
}
}
return SUCCEEDED;
}
 
STATUS OpenForTheDay()
{
BankClock=0;
BankState=OPEN;
IDSeed=0;
//**********************
InitMethods();
RegisterAllMethod();
InitQueue(BankIndoor);
for (int i=0;i&lt;QUEUES;i++)
InitQueue(BankQueue[i]);
time(&amp;StartTime);
printf("The bank is open.\n");
return SUCCEEDED;
}
 
STATUS CloseForTheDay()
{
DestroyQueue(BankIndoor);
for(int i=0;i&lt;QUEUES;i++)
DestroyQueue(BankQueue[i]);
DeleteAllMethod();
printf("The bank is closed.\n");
return SUCCEEDED;
}
//*****************************************
int main()
{
OpenForTheDay();
while(BankState!=CLOSED)
{
EnumerateAllMethod();
}
CloseForTheDay();
system("PAUSE");
return 0;
}

什么才是我们需要的?

用户需要什么?
对于普通用户来说,美丽的界面、易用的操作和强大的功能才是真正的上帝!而架构、模式、API都是他们所不想关心,也没办法 关心的。我们现在很多问题都在了架构上,都在了具体的编程上,但是我们产品的用户体验实在是差。我们的操作实在是不简便。这一点上我们应该好好学习微软。 的确,微软很多软件不是功能最强大的,但一定是最好用的。

想到这里,我个人还是十分看好未来几年的Web applications。网络应用不仅仅是网站,而是全新的架构,全新的用户体验。我们应该做的是,打开思路。

不是没有的,只是不在

新年,很久都没有这么过了。当然,很多年来都是一如既往得平淡。今年收到很多祝福,不过那种到处都能见得到短信让我觉得很不舒服,而且还有不少是因为某些原因。我这里也不想多说。当然,也许是我多想了。

真正一件比较特别的事情倒是下午听了听《梁祝》和《黄河》。总觉得中国人的节日要该庆祝一下。以前对梁祝有一种天生的偏见。可今天听,也不像我所估计的那样差。其实抛开一些思想而言,这首小提琴协奏曲还是相当不错的。至少有一种中国民族的精神在里面。不过说是说不出来的。梅纽因有一句话说的好:如果你问我音乐有内涵吗?我会说,有。如果你问我那它是什么呢?我会说,没法说出来。的确,音乐说出来就不是音乐了。《黄河》问题就要麻烦得多。素材还是不错的,但是就是太杂。而且要把中国的东西硬塞到柴可夫斯基或者拉赫玛尼诺夫式的耀技中,很牵强。但是末乐章绝对是有一定分量的。殷承宗的演奏是很权威的。但是总觉得缺少什么,也许是大气。想听听朗朗的处理。

我不想说生活。对于我而言,也许生活才是虚幻的。可是什么都不是虚幻的呢?

他们的肖邦

你听的最多的肖邦的唱片都是谁演奏的?

波利尼?齐默尔曼?还是阿格丽姬的?是的,名家的肖邦实在是太多了。不管是冷峻的,还是热情的,抑或是有些人所谓的“肖邦化”的演奏,总之我们能够听到无数的著名的演奏家著名的版本。可事实上,在现代唱片工业时代,有才华的演奏却不一定能够传到我们音乐爱好者的耳朵里。我就很偶然聆听到了这样一个让我眼睛一亮的“肖邦”。

要说演奏得奇怪,波格雷利奇的肖邦无疑是最奇怪的,但也是最具效果的。不过钢琴家弗莱迪 肯佩夫的肖邦才真正有一种冷峻和古怪的美。说实话,这是一种真正现代意义上的演奏,有力度,有棱角,绝没有那种拖泥带水。而另一位钢琴家罗兰 彭蒂宁则出奇得将《船歌》充分演绎。老实说我听过很多版本的《船歌》,但是都有一个问题,那就是浪漫不足。为什么这么讲呢?因为肖邦的《船歌》众所周知是一部充满了浪漫气息的爱情篇章。很难得有人能够把这首曲子演奏得既典雅又富有青春的爱。彭蒂宁做到了,而且每个细节都安排得恰当而又不失分寸。当然,这些钢琴家的肖邦并不能做到每一首都能够演奏得具有说服力。这也是很正常的,我想大家和普通钢琴家的区别就在这里吧。

但事实也是告诉我们,音乐没有权威。每个人都能够体会到属于他那份特有的情感。

他们的肖邦

你听的最多的肖邦的唱片都是谁演奏的?

波 利尼?齐默尔曼?还是阿格丽姬的?是的,名家的肖邦实在是太多了。不管是冷峻的,还是热情的,抑或是有些人所谓的“肖邦化”的演奏,总之我们能够听到无数 的著名的演奏家著名的版本。可事实上,在现代唱片工业时代,有才华的演奏却不一定能够传到我们音乐爱好者的耳朵里。我就很偶然聆听到了这样一个让我眼睛一 亮的“肖邦”。

要说演奏得奇怪,波格雷利奇的肖邦无疑是最奇怪的,但也是最具效果的。不过钢琴家弗莱迪 肯佩夫的肖邦才真正有一种冷峻和古怪的美。说实话,这是一种真正现代意义上的演奏,有力度,有棱角,绝没有那种拖泥带水。而另一位钢琴家罗兰 彭 蒂宁则出奇得将《船歌》充分演绎。老实说我听过很多版本的《船歌》,但是都有一个问题,那就是浪漫不足。为什么这么讲呢?因为肖邦的《船歌》众所周知是一 部充满了浪漫气息的爱情篇章。很难得有人能够把这首曲子演奏得既典雅又富有青春的爱。彭蒂宁做到了,而且每个细节都安排得恰当而又不失分寸。当然,这些钢 琴家的肖邦并不能做到每一首都能够演奏得具有说服力。这也是很正常的,我想大家和普通钢琴家的区别就在这里吧。

但事实也是告诉我们,音乐没有权威。每个人都能够体会到属于他那份特有的情感。