個人檔案孔雀人生相片部落格清單更多 ![]() | 說明 |
|
|
1月4日 拆机1月3日 悲惨世界昨天把电脑电源搞挂了。
这几天晚上都没得玩了。
上校友录发现又好多人结婚了。
露露都7个月了。
不知道是俺动作慢了还是他们动作太快了。
我才刚刚把领证和结婚照排上日程安排。
那边孩子都要满地跑了。
这世界变化太快。
不服老不想长大也不行!
一切一切都在处处暗示你,老了 !!
想想还是留在老家好。
留在老家现在俺应该也能买上200平的房子
开上私家车了。 9月28日 MSN网络硬盘空间4月20日 [学习]输入框文本验证突然要写个输入框文本验证的东西,正则表达式看了半天没看懂,土办法一则,附上KeyCode对照表 <input name="t1" onkeypress="return ((event.keyCode>=48 && event.keyCode<=57)) " value="6位数字" size="12" maxlength="6" />
Keycode对照表获得遥控器的输入后,要转换为KeyCode 发送给系统,一个完整的键码值表就非常必要了。 不过我也一直在想,遥控器输入的值是什么呢,如果是KeyCode不就好了么,呵呵,可能不?
12月14日 客户不签就加价<ZT>客户不签就加价 网页设计报价从来就没有个标准,公说公有理,婆说婆有理,于是很多时候我们的业务人员在跟客户谈判时,如果久谈不下就会想到降价,而我这次却用了一个恰恰相反的办法;那是个很小的单,就5、6个页面,第一次去的时候我报了个3500的价,客户听了后说:“这个价太高,我们没法接受”,我于是问他的预算是多少,客户没正面回答,只说要考虑一下,显然他自己也没底而且客户第一次不签单很正常,于是我打道回府。隔了十来天客户来电话问我“有没空聊聊网站的事呀”,于是我们又开始谈,在谈得差不多的时候我问他上次的合同还在吗?他推说不知放哪去了,我只好重新拿出一份新合同来,这次我在合同上写了个3800的价格,客户接过合同看了看说:“这样吧,我们也对比一下,如果别家公司报的价都跟你们差不多就给你们做吧”;我没说什么,我知道这时解释是多余的,因为越解释客户会越觉得你的价格是可以浮动的,于是我起身对他说:“好的,其实我们一直都很鼓励客户多做些比较的”。第三次再去时客户直接说:“网站我们是要做的,只是希望能用最实惠的价格把事情做好”,看得出来这次客户是真的打算做了,为了给客户个台阶也为了表示诚意,我也就顺水推舟的作了个100块钱的让步,最后以3400签下了这个单。 评:当然这里有两个因素我们不能忽略,首先是客户是公务员且经常出差,他所能接解触到的网络公司将非常有限,所以我也就不担心他会去做比较了,二是单子比较小,凭我的直觉客户的预算不会超过2500,也就是说正常情况下客户绝对不可能3400签,而如果价格太低我们又不想做,于是我才用了这个违反常规的办法。 出其不意赢客户 接到客户电话说让我过去谈谈网站的事,这可是件好事呀,于是“沐浴更衣后”之后就直奔客户办公室,进去后发现里面还有一个人,客户没做介绍我也就没太在意,因为有跟客户接触过几次了,很多问题都已基本清楚,聊得差不多我就直奔主题了,我说:“您这单呢,设计要求比较高,内容也不少,不过大家都这么熟了,我就给个实在点的价吧,连空间域名一起6500”。客户没说什么,这时旁边坐着的那个人开口了,他说:“其实这个单最多6000就能做,你们给得价实在有点高”。这时客户看看我又看看那个人然后笑着对我说;“他是**设计公司的,我跟他们已经接触很久了”,在这节骨眼上杀出个程咬金,情况对我十分不利,但事情到了这个份上我总不能马上改口降价吧,那样客户还能相信我们吗,想来想去我只好把心一横,于是我很严肃地对客户说:“这个网站如果按你现在的要求他们6000能做的话,那我们至少得6800”,客户满脸疑惑地问:“为什么?”我说“如果他们6000就做的话那说明他们根本没有吃透你的要求,也肯定不会做得令您满意”,这时那个人还想再说些什么,但客户却已经拿起我的合同说:“好,就凭你这句,这个网站6500交给你们啦”! 评:这次的成功也许是我出其不意的一击凑了效,但我想更重要的是客户是北方人,性格非常豪爽,所以此法仅供参考。 要经理还是要SEO 客户正饶有兴致地翻着我们给的方案,我于是不失时机地给客户讲解:“...对于做网站其实我们还是有很多优势的,比如我们一直在研究SEO,并且已经注册了广州SEO的域名,也就是说我们做的网站都能比较好的被搜索引擎收录...”这时客户突然打断我的话说:“我们有经理就行不需要SEO”,我一听糊涂了这经理跟SEO扯什么关系呀,后来一想明白了,他准是把SEO跟CEO扯一起了。所以呀去见客户时最好不要满嘴专业术语,客户可不都是计算机专业的呀。 最简单的网站是网易 客户居高临下地坐着,一脸财大气粗的表情:“网站嘛我们不喜欢弄得太复杂,你就给我简简单单做个象网易那样的就行了”,我一愣以为自己听错了,于是小心翼翼地问他:“您知道网易的网站值多少钱吗,您不妨问问他2千万卖不卖给您”。他没好气的斜了我一眼:“那就做成阿里巴巴那样也行,不过要快,最多给你们一个星期的时间,价钱嘛,因为网站比较简单就给你们1500吧,最要紧是把事做好”,我当时脑子里就只有一个愿望,那就是希望我或者他突然从对方眼前消失,以免让他看见我那满布悲哀的脸,幸好这时我电话响了,于是我赶紧拿起电话对他说:“*总,真不好意思,我弟因为贩卖军火被抓了,我得去看看他”,等我冲到门口还听到他在那嘀咕:“扯什么蛋,这年头谁还贩卖军火”,看来他是真的不知道,他可以花1500做个象网易那样的网站,我弟为什么就不能贩卖军火呢。所以呀我们这一代设计师光会做网站还远远不够,你还得担负起给普罗大众普及互联网知识的重任。 原文作者:世网竹叶青 2月24日 平面广告表现手法细臻刻划和着力渲染产品的质感、形态和功能用途,将产品精美的质地引人入胜地呈现出来,给人以逼真的现实感,使消费者对所宣传的产品产生一种亲切感和信任感。
1.直接展示法 这是一种最常见的运用十分广泛的表现手法。它将某产品或主题直接如实地展示在广告版面上,充分运用摄影或绘画等技巧的写实表现能力。细臻刻划和着力渲染产品的质感、形态和功能用途,将产品精美的质地引人入胜地呈现出来,给人以逼真的现实感,使消费者对所宣传的产品产生一种亲切感和信任感。 这种手法由于直接将产品推向消费者面前,所以要十分注意画面上产品的组合和展示角度,应着力突出产品的品牌和产品本身最容易打动人心的部位,运用色光和背景进行烘托,使产品置身于一个具有感染力的空间,这样才能增强广告画面的视觉冲击力。 2.突出特征法 运用各种方式抓住和强调产品或主题本身与众不同的特征,并把它鲜明地表现出来,将这些特征置于广告画面的主要视觉部位或加以烘托处理,使观众在接触言辞画面的瞬间即很快感受到,对其产生注意和发生视觉兴趣,达到刺激购买欲望的促销目的。 在广告表现中,这些应着力加以突出和渲染的特征,一般由富于个性产品形象与众不同的特殊能力、厂商的企业标志和产品的商标等要素来决定。 突出特征的手法也是我们常见的运用得十分普遍的表现手法,是突出广告主题的重要手法之一,有着不可忽略的表现价值 3.对比衬托法 对比是一种趋向于对立冲突的艺术美中最突出的表现手法。它把作品中所描绘的事物的性质和特点放在鲜明的对照和直接对比中来表现,借彼显此,互比互衬,从对比所呈现的差别中,达到集中、简洁、曲折变化的表现。通过这种手法更鲜明地强调或提示产品的性能和特点,给消费者以深刻的视觉感受。 作为一种常见的行之有效的表现手法,可以说,一切艺术都受惠于对比表现手法。对比手法的运用,不仅使广告主题加强了表现力度,而且饱含情趣,扩大了广告作品的感染力。对比手法运用的成功,能使貌似平凡的画面处理隐含着丰富的意味,展示了广告主题表现的不同层次和深度。 4.合理夸张法 借助想象,对广告作品中所宣传的对象的品质或特性的某个方面进行相当明显的过份夸大,以加深或扩大这些特征的认识。文学家高尔基指出:“夸张是创作的基本原则。”通过这种手法能更鲜明地强调或揭示事物的实质,加强作品的艺术效果。 夸张是一般中求新奇变化,通过虚构把对象的特点和个性中美的方面进行夸大,赋予人们一种新奇与变化的情趣。 按其表现的特征,夸张可以分为形态夸张和神情夸张两种类型,前者为表象性的处理品,后者则为含蓄性的情态处理品。通过夸张手法的运用,为广告的艺术美注入了浓郁的感情色彩,使产品的特征性鲜明、突出、动人。 5.以小见大法 在广告设计中对立体形象进行强调、取舍、浓缩,以独到的想象抓住一点或一个局部加以集中描写或延伸放大,以更充分地表达主题思想。这种艺术处理以一点观全面,以小见大,从不全到全的表现手法,给设计者带来了很大的灵活性和无限的表现力,同时为接受者提供了广阔的想象空间,获得生动的情趣和丰富的联想。 以小见大中的“小”,是广告画面描写的焦点和视觉兴趣中心,它既是广告创意的浓缩和生发,也是设计者匠心独具的安排,因面它已不是一般意义的“小”,而是小中寓大,以小胜大的高度提炼的产物,是简洁的刻意追求 6.运用联想法 在审美的过程中通过丰富的联想,能突破时空的界限,扩大艺术形象的容量,加深画面的意境。 通过联想,人们在审美对象上看到自己或与自己有关的经验,美感往往显得特别强烈,从而使审美对象与审美国微软公司者融合为一体,在产生联想过程中引发了美感共鸣,其感情的强度总是激烈的、丰富的。 7.富于幽默法 幽默法是指广告作品中巧妙地再现喜剧性特征,抓住生活现象中局部性的东西,通过人们的性恪、外貌和举止的某些可笑的特征表现出来。 幽默的表现手法,往往运用饶有风趣的情节,巧妙的安排,把某种需要肯定的事物,无限延伸到漫画的程度,造成一种充满情趣,引人发笑而又耐人寻味的幽默意境。幽默的矛盾冲突可以达到出乎意料之外,又在情理之中的艺术效果,勾引起观赏者会心的微笑,以别具一格的方式,发挥艺术感染力的作用。 8.借用比喻法 比喻法是指在设计过程中选择两个在本拷贝各不相同,而在某些方面又有些相似性的事物,“以此物喻彼物”,比喻的事物与主题没有直接的关系,但是某一点上与主题的某些特征有相似之处,因而可以借题发挥,进行延伸转化,获得“婉转曲达”的艺术效果。 与其它表现手法相比,比喻手法比较含蓄隐伏,有时难以一目了然,但一旦领会其意,便能给一以意味无尽的感受。 9.以情托物法 艺术的感染力最有直接作用的是感情因素,审美就是主体与美的对象不断交流感情产生共鸣的过程。艺术有传达感情的特征,“感人心者,莫先于情”这句话已表明了感情因素在艺术创造中的作用,在表现手法上侧重选择具有感情倾向的内容,以美好的感情来烘托主题,真实而生动地反映这种审美感情就能获得以情动人,发挥艺术感染人的力量,这是现代广告设计的文学侧重和美的意境与情趣的追求。 10.悬念安排法 在表现手法上故弄玄虚,布下疑阵,使人对广告画面乍看不解题意,造成一种猜疑和紧张的心理状态,在观众的心理上掀起层层波澜,产生夸张的效果,驱动消费者的好奇心和强烈举动,开启积极的思维联想,引起观众进一步探明广告题意之所在强烈愿望,然后通过广告标题或正文把广告的主题点明出来,使悬念得以解除,给人留下难忘的心理感受。 悬念手法有相当高的艺术价值,它首先能加深矛盾冲突,吸引观众的兴趣和注意力,造成一种强烈的感受,产生引人入胜的艺术效果。 11.选择偶像法 在现实生活中,人们心里都有自己崇拜、仰慕或效仿的对象,而且有一种想尽可能地向他靠近的心理欲求,从而获得心理上的满足。这种手法正是针对人们的这种心理特点运用的,它抓住人们对名人偶像仰慕的心理,选择观众心目中崇拜的偶像,配合产品信息传达给观众。由于名人偶像有很强的心理感召力,故借助名人偶像的陪衬,可以大大提高产品的印象程度与销售地位,树立名牌的可信度,产生不可言喻的说服力,诱发消费者对广告中名人偶像所赞誉的产品的注意激发起购买欲望。偶像的选择可以是柔美风流的超级女明星,气质不凡举世闻名的男吸星;也可以是驰名世界体坛的男女高手,其它的还可以选择政界要人、社会名流、艺术大师、战场英雄、俊男美女等。偶像的选择要与广告的产品或劳务在品格上相吻合,不然会给人牵强附会之感,使人在心理上予以拒绝,这样就不能达到预期的目的。 12.谐趣模仿法 这是一种创意的引喻手法,别有意味地采用以新换旧的借名方式,把世间一般大众所熟悉的名画等艺术品和社会名流等作为谐趣的图像,经过巧妙的整形履行,使名画名人产生谐趣感,给消费者一种崭新奇特的视觉印象和轻松愉快的趣味性,以其异常、神秘感提高广告的诉耱效果,增加产品身价和注目度。 这种表现手法将广告的说服力,寓于一种近乎漫画化的诙谐情趣中,使人赞叹,令您发笑,让您过目不忘,留下饶有奇趣的回味。 13.神奇迷幻法 运用畸形的夸张,以无限丰富的想象构织出神话与童话般的画面,在一种奇幻的情景中再现现实,造成与现实生活的某种距离,这种充满浓郁浪漫主义,写意多于写实的表现手法,以突然出现的神奇的视觉感受,很富于感染力,给人一种特殊的美感受,可满足人们喜好奇异多变的审美情趣的要求。 在这种表现手法中艺术想象很重要,它是人类智力发达的一个标志,干什么事情都需要想象,艺术尤其这样。可以毫不夸张地说,想象就艺术的生命。 从创意构想开始直到设计结束,想象都在活跃地进行。想象的突出特征,是它的创造性,创造性的想象是新的意蕴的挖掘开始,是新的意象的浮现展示。它的基本趋向是对联想所唤起的经验进行改造,最终构成带有审美者独特创造的新形象,产生强烈打坳人心的力量。 14.连续系列法 通过连续画面,形成一个完整的视觉印象,使通过画面和文字传达的广告信息十分清晰、突出、有力。 广告画面本身有生动的直观形象,多次反复的不断积累,能加深消费者对产品或劳务的印象,获得好的宣传效果,对扩大销售,树立名牌,刺激购买欲增强竞争力有很大的作用。对于作为设计策略的前提,确立企业形象更有不可忽略的重要作用。 作为设计构成的基础,形式心理的把握是十分重要的,从视觉心理来说,人们厌弃单调划一的形式,追求多样变化,连续系列的表现手法符合“寓多样于统一之中”这一形式美的基本法则,使人们于“同”中见“异”,于统一中求变化,形成既多样又统一,既对比又和谐的艺术效果,加强了艺术感染力。 商业Web站点设计策略商业Web站点设计策略 相信很大一部分人知道,我们国内的很多web站点设计项目都存在着一个特点,那就是将设计和制作混为一谈。所谓的设计站点,就是简单的把客户给的资料图形化,不考虑任何其他的因素,比如能否让站点实现预期的商业收益,让站点真正给用户提供他们想要的信息和服务。于是,大量的站点形同虚设,成了白白浪费时间、金钱、人力,最后却成立占用网络空间的一堆乏人问津的文件组合。因为一般性的web站点制作技术很易于掌握,所以,有能力制作网站的人是比比皆是,在能作和能设计之间,人们的界限慢慢模糊。很多人认识到的网站设计,可能就是把界面做的漂亮点。而实际上,设计站点远非如此简单。Web作为一个新兴的媒体,它的目的性很明确,对于一个企业来说,站点的存在就是为了商业目的。而实现站点的商业目的,不经过好的规划和出色的创意,是不可能实现。 下面,就我所接触和学习到的web设计理论,简要叙述一下web设计的基本步骤。 1、 确立目的 目的是web站点建设的中心,也是指导设计的最重要因素。目的可以简单,但不要模糊不清,否则web设计和实现都将非常困难。用户对web的期望,和web真正能很好实现的东西一般都有差距,如何和用户沟通,来达成共识是web项目一开始就要解决的。目的先要细化成可清晰描述的明确目标,越清晰的目标,越容易控制和实现。因为web的目标也可能需要漫长的时间才能实现,所以在保持总的发展策略的前提下,可以对不同时间段的目的有明确的界定,这样不但可以让发展的中心不被偏离,还可以比较容易的评析效果,以期制定对策。Web是种特殊的媒体,所以设计师必须懂得和了解这种媒体的特性,尽管设计是共通的,但对web,必须要有针对其特性的设计考虑。 web和传统媒体的比较,相对于印刷品,web因为其信息系统的结构和超文本链接指向的优势,使用户寻找到自己感兴趣的信息速度上快于印刷品。在信息的表现方式上,web可表现多媒体信息,也优于印刷品。最大的优势就是交互性,这是任何传统媒体都无法比拟的。但web也有其不足,由于我们常接触到的web主要在荧光屏上实现,因此用户在屏幕上阅读大量文本时,眼睛很容易疲劳,且就便携这一点,当前的计算机是无法和印刷品相比的。而相对于电视这一媒体,电视作为一个已存在几十年的媒体,无论是从用户的数量和用户对其的熟悉方面,还有电视在动态影像的表现,都要优于web。尽管web在带宽提高的基础上能流畅播放视频,但就一般而言,从web上观看动态影像并不现实,以上所说的动态影像是指象素化的视频。不过web相比于电视,其交互性能给用户更多自由选择的机会,能更好的和用户沟通,并给其带来特殊的体验。 在充分了解站点的目标用户的特点,和web的特性之后,针对用户的种种特点来进行设计的工作就可以开始了。 2、 构建信息系统架构 在分析了站点的目的和目标用户的特点和需求之后,让信息能真正满足用户的需求,就必须设计一个易于传递信息的站点架构。导航系统和页面中的超链接是用户最直接的交互工具,也是站点信息流动的外在体现。信息架构是一个站点的骨骼,也是站点是否能达到顺利表达信息的一个重要因素。 确定采用何种技术,技术是实现站点的最基本的东西。但是最新最先进的技术在不同计算机平台上的表现大相径庭,有些甚至不被支持。所以为了保证尽可能多的目标用户能正常的浏览站点。在使用技术上要慎重,不能盲目采用过新的技术。而同样和浏览相关的就是站点文件的大小,文件尺寸较大,下载速度就会变慢,如果页面的下载速度超出了用户心里能承受的极限,那么用户很可能就会放弃对站点的浏览而转向其他的站点。 3、 站点中的图形用户界面设计 用户界面是帮助用户浏览站点和控制与站点交互的重要工具。好的界面应该是帮助用户很顺畅找到他们所需要信息。在设计思想上,尽量采用熟知的,已经约成俗定的惯例来设计用户界面,因为用户可能具有一些站点访问的经验。 在这一环节,设计师还要做以下工作:将企业文化很好的融合进界面,合理分配版面来确保信息的传达,美化界面以使其更吸引人,确保它能给用户带来舒适的站点体验。 11月25日 数据库设计指南 Part IV第4 部分— 保证数据的完整性 1. 用约束而非商务规则强制数据完整性 如果你按照商务规则来处理需求,那么你应当检查商务层次/用户界面:如果商务规则以后发生变 化,那么只需要进行更新即可。 假如需求源于维护数据完整性的需要,那么在数据库层面上需要施加限制条件。 如果你在数据层确实采用了约束,你要保证有办法把更新不能通过约束检查的原因采用用户理解 的语言通知用户界面。除非你的字段命名很冗长,否则字段名本身还不够。 只要有可能,请采用数据库系统实现数据的完整性。这不但包括通过标准化实现的完整性而且还 包括数据的功能性。在写数据的时候还可以增加触发器来保证数据的正确性。不要依赖于商务层 保证数据完整性;它不能保证表之间(外键)的完整性所以不能强加于其他完整性规则之上。 2. 分布式数据系统 对分布式系统而言,在你决定是否在各个站点复制所有数据还是把数据保存在一个地方之前应该 估计一下未来5 年或者10 年的数据量。当你把数据传送到其他站点的时候,最好在数据库字段 中设置一些标记。在目的站点收到你的数据之后更新你的标记。为了进行这种数据传输,请写下 你自己的批处理或者调度程序以特定时间间隔运行而不要让用户在每天的工作后传输数据。本地 拷贝你的维护数据,比如计算常数和利息率等,设置版本号保证数据在每个站点都完全一致。 3. 强制指示完整性 没有好办法能在有害数据进入数据库之后消除它,所以你应该在它进入数据库之前将其剔除。激 活数据库系统的指示完整性特性。这样可以保持数据的清洁而能迫使开发人员投入更多的时间处 理错误条件。 4. 关系 如果两个实体之间存在多对一关系,而且还有可能转化为多对多关系,那么你最好一开始就设置 成多对多关系。从现有的多对一关系转变为多对多关系比一开始就是多对多关系要难得多。 5. 采用视图 为了在你的数据库和你的应用程序代码之间提供另一层抽象,你可以为你的应用程序建立专门的 视图而不必非要应用程序直接访问数据表。这样做还等于在处理数据库变更时给你提供了更多的 自由。 6. 给数据保有和恢复制定计划 考虑数据保有策略并包含在设计过程中,预先设计你的数据恢复过程。采用可以发布给用户/开发 人员的数据字典实现方便的数据识别同时保证对数据源文档化。编写在线更新来“更新查询”供 以后万一数据丢失可以重新处理更新。 7. 用存储过程让系统做重活 解决了许多麻烦来产生一个具有高度完整性的数据库解决方案之后,我所在的团队决定封装一些 关联表的功能组,提供一整套常规的存储过程来访问各组以便加快速度和简化客户程序代码的开 发。在此期间,我们发现3GL 编码器设置了所有可能的错误条件,比如以下所示: SELECT Cnt = COUNT (*) FROM [<Table>] WHERE [<primary key column>] = <new value> IF Cnt = 0 BEGIN INSERT INTO [<Table>] ( [< primary key column>] ) VALUES ( <New value> ) END ELSE BEGIN <indicate duplication error> END 而一个非3GL 编码器是这样做的: INSERT INTO [<Table>] ( [< primary key column>] ) VALUES ( <New value> ) IF @@ERROR = 2627 -- Literal error code for Primary Key Constraint BEGIN <indicate duplication error> END 第2 个程序简单多了,而且事实上,利用了我们给数据库的功能。虽然我个人不喜欢使用嵌入文 字(2627)。但是那样可以很方便地用一点预先处理来代替。数据库不只是一个存放数据的地 方,它也是简化编码之地。 8. 使用查找 控制数据完整性的最佳方式就是限制用户的选择。只要有可能都应该提供给用户一个清晰的价值 列表供其选择。这样将减少键入代码的错误和误解同时提供数据的一致性。某些公共数据特别适 合查找:国家代码、状态代码等。 数据库设计指南 PartIII第3 部分— 选择键和索引 1. 数据采掘要预先计划 我所在的市场部门一度要处理8 万多份联系方式,同时填写每个客户的必要数据(这绝对不是小 活)。我从中还要确定出一组客户作为市场目标。当我从最开始设计表和字段的时候,我试图不 在主索引里增加太多的字段以便加快数据库的运行速度。然后我意识到特定的组查询和信息采掘 既不准确速度也不快。结果只好在主索引中重建而且合并了数据字段。我发现有一个指示计划相 当关键——当我想创建系统类型查找时为什么要采用号码作为主索引字段呢?我可以用传真号码 进行检索,但是它几乎就象系统类型一样对我来说并不重要。采用后者作为主字段,数据库更新 后重新索引和检索就快多了。 可操作数据仓库(ODS)和数据仓库(DW)这两种环境下的数据索引是有差别的。在DW 环境 下,你要考虑销售部门是如何组织销售活动的。他们并不是数据库管理员,但是他们确定表内的 键信息。这里设计人员或者数据库工作人员应该分析数据库结构从而确定出性能和正确输出之间 的最佳条件。 2. 使用系统生成的主键 这一天类同技巧1,但我觉得有必要在这里重复提醒大家。假如你总是在设计数据库的时候采用 系统生成的键作为主键,那么你实际控制了数据库的索引完整性。这样,数据库和非人工机制就 有效地控制了对存储数据中每一行的访问。 采用系统生成键作为主键还有一个优点:当你拥有一致的键结构时,找到逻辑缺陷很容易。 3. 分解字段用于索引 为了分离命名字段和包含字段以支持用户定义的报表,请考虑分解其他字段(甚至主键)为其组 成要素以便用户可以对其进行索引。索引将加快SQL 和报表生成器脚本的执行速度。比方说, 我通常在必须使用SQL LIKE 表达式的情况下创建报表,因为case number 字段无法分解为 year、serial number、case type 和defendant code 等要素。性能也会变坏。假如年度和类型字 段可以分解为索引字段那么这些报表运行起来就会快多了。 4. 键设计4 原则 · 为关联字段创建外键。 · 所有的键都必须唯一。 · 避免使用复合键。 · 外键总是关联唯一的键字段。 5. 别忘了索引 索引是从数据库中获取数据的最高效方式之一。95%的数据库性能问题都可以采用索引技术得到 解决。作为一条规则,我通常对逻辑主键使用唯一的成组索引,对系统键(作为存储过程)采用 唯一的非成组索引,对任何外键列采用非成组索引。不过,索引就象是盐,太多了菜就篌了。你 得考虑数据库的空间有多大,表如何进行访问,还有这些访问是否主要用作读写。 大多数数据库都索引自动创建的主键字段,但是可别忘了索引外键,它们也是经常使用的键,比 如运行查询显示主表和所有关联表的某条记录就用得上。还有,不要索引memo/note 字段,不 要索引大型字段(有很多字符),这样作会让索引占用太多的存储空间。 6. 不要索引常用的小型表 不要为小型数据表设置任何键,假如它们经常有插入和删除操作就更别这样作了。对这些插入和 删除操作的索引维护可能比扫描表空间消耗更多的时间。 7. 不要把社会保障号码(SSN)选作键 永远都不要使用SSN 作为数据库的键。除了隐私原因以外,须知政府越来越趋向于不准许把 SSN 用作除收入相关以外的其他目的,SSN 需要手工输入。永远不要使用手工输入的键作为主 键,因为一旦你输入错误,你唯一能做的就是删除整个记录然后从头开始。 上个世纪70 年代我还在读大学的时候,我记得那时SSN 还曾被用做学号,当然尽管这么做是非 法的。而且人们也都知道这是非法的,但他们已经习惯了。后来,随着盗取身份犯罪案件的增 加,我现在的大学校园正痛苦地从一大摊子数据中把SSN 删除。 8. 不要用用户的键 在确定采用什么字段作为表的键的时候,可一定要小心用户将要编辑的字段。通常的情况下不要 选择用户可编辑的字段作为键。这样做会迫使你采取以下两个措施: · 在创建记录之后对用户编辑字段的行为施加限制。假如你这么做了,你可能会发现你的应用程 序在商务需求突然发生变化,而用户需要编辑那些不可编辑的字段时缺乏足够的灵活性。当用 户在输入数据之后直到保存记录才发现系统出了问题他们该怎么想?删除重建?假如记录不可 重建是否让用户走开? · 提出一些检测和纠正键冲突的方法。通常,费点精力也就搞定了,但是从性能上来看这样做的 代价就比较大了。还有,键的纠正可能会迫使你突破你的数据和商业/用户界面层之间的隔 离。 所以还是重提一句老话:你的设计要适应用户而不是让用户来适应你的设计。 不让主键具有可更新性的原因是在关系模式下,主键实现了不同表之间的关联。比如, Customer 表有一个主键CustomerID,而客户的定单则存放在另一个表里。Order 表的主键可能 是OrderNo 或者OrderNo、CustomerID 和日期的组合。不管你选择哪种键设置,你都需要在 Order 表中存放CustomerID 来保证你可以给下定单的用户找到其定单记录。 假如你在Customer 表里修改了CustomerID,那么你必须找出Order 表中的所有相关记录对其进 行修改。否则,有些定单就会不属于任何客户——数据库的完整性就算完蛋了。 如果索引完整性规则施加到表一级,那么在不编写大量代码和附加删除记录的情况下几乎不可能 改变某一条记录的键和数据库内所有关联的记录。而这一过程往往错误丛生所以应该尽量避免。 9. 可选键有时可做主键 记住,查询数据的不是机器而是人。 假如你有可选键,你可能进一步把它用做主键。那样的话,你就拥有了建立强大索引的能力。这 样可以阻止使用数据库的人不得不连接数据库从而恰当的过滤数据。在严格控制域表的数据库 上,这种负载是比较醒目的。如果可选键真正有用,那就是达到了主键的水准。 我的看法是,假如你有可选键,比如国家表内的state_code,你不要在现有不能变动的唯一键上 创建后续的键。你要做的无非是创建毫无价值的数据。比如以下的例子: Select count(*) from address, state_ref where address.state_id = state_ref.state_id and state_ref.state_code = 'TN' 我的做法是这样的: Select count(*) from address where and state_code = 'TN' 如你因为过度使用表的后续键建立这种表的关联,操作负载真得需要考虑一下了。 10. 别忘了外键 大多数数据库索引自动创建的主键字段。但别忘了索引外键字段,它们在你想查询主表中的记录 及其关联记录时每次都会用到。还有,不要索引memo/notes 字段而且不要索引大型文本字段 (许多字符),这样做会让你的索引占据大量的数据库空间。 数据库设计指南 Part II第2 部分— 设计表和字段 1. 检查各种变化 我在设计数据库的时候会考虑到哪些数据字段将来可能会发生变更。比方说,姓氏就是如此(注 意是西方人的姓氏,比如女性结婚后从夫姓等)。所以,在建立系统存储客户信息时,我倾向于 在单独的一个数据表里存储姓氏字段,而且还附加起始日和终止日等字段,这样就可以跟踪这一 数据条目的变化。 2. 采用有意义的字段名 有一回我参加开发过一个项目,其中有从其他程序员那里继承的程序,那个程序员喜欢用屏幕上 显示数据指示用语命名字段,这也不赖,但不幸的是,她还喜欢用一些奇怪的命名法,其命名采 用了匈牙利命名和控制序号的组合形式,比如cbo1、txt2、txt2_b 等等。 除非你在使用只面向你的缩写字段名的系统,否则请尽可能地把字段描述的清楚些。当然,也别 做过头了,比如Customer_Shipping_Address_Street_Line_1 I 虽然很富有说明性,但没人愿意 键入这么长的名字,具体尺度就在你的把握中。 3. 采用前缀命名 如果多个表里有好多同一类型的字段(比如FirstName),你不妨用特定表的前缀(比如 CusLastName)来帮助你标识字段。 时效性数据应包括“最近更新日期/时间”字段。时间标记对查找数据问题的原因、按日期重新处 理/重载数据和清除旧数据特别有用。 5. 标准化和数据驱动 数据的标准化不仅方便了自己而且也方便了其他人。比方说,假如你的用户界面要访问外部数据 源(文件、XML 文档、其他数据库等),你不妨把相应的连接和路径信息存储在用户界面支持表 里。还有,如果用户界面执行工作流之类的任务(发送邮件、打印信笺、修改记录状态等),那 么产生工作流的数据也可以存放在数据库里。预先安排总需要付出努力,但如果这些过程采用数 据驱动而非硬编码的方式,那么策略变更和维护都会方便得多。事实上,如果过程是数据驱动 的,你就可以把相当大的责任推给用户,由用户来维护自己的工作流过程。 6. 标准化不能过头 对那些不熟悉标准化一词(normalization )的人而言,标准化可以保证表内的字段都是最基础的 要素,而这一措施有助于消除数据库中的数据冗余。标准化有好几种形式,但Third Normal Form(3NF)通常被认为在性能、扩展性和数据完整性方面达到了最好平衡。简单来说,3NF 规 定: · 表内的每一个值都只能被表达一次。 · 表内的每一行都应该被唯一的标识(有唯一键)。 · 表内不应该存储依赖于其他键的非键信息。 遵守3NF 标准的数据库具有以下特点:有一组表专门存放通过键连接起来的关联数据。比方说, 某个存放客户及其有关定单的3NF 数据库就可能有两个表:Customer 和Order。Order 表不包 含定单关联客户的任何信息,但表内会存放一个键值,该键指向Customer 表里包含该客户信息 的那一行。 更高层次的标准化也有,但更标准是否就一定更好呢?答案是不一定。事实上,对某些项目来 说,甚至就连3NF 都可能给数据库引入太高的复杂性。 为了效率的缘故,对表不进行标准化有时也是必要的,这样的例子很多。曾经有个开发财务分析 软件的活就是用非标准化表把查询时间从平均40 秒降低到了两秒左右。虽然我不得不这么做, 但我绝不把数据表的非标准化当作当然的设计理念。而具体的操作不过是一种派生。所以如果表 出了问题重新产生非标准化的表是完全可能的。 7. Microsoft Access 报表技巧 如果你正在使用Microsoft Access,你可以用对用户友好的字段名来代替编号的名称:比如用 Customer Name 代替txtCNaM。这样,当你用向导程序创建表单和报表时,其名字会让那些不 是程序员的人更容易阅读。 8. 不活跃或者不采用的指示符 增加一个字段表示所在记录是否在业务中不再活跃挺有用的。不管是客户、员工还是其他什么 人,这样做都能有助于再运行查询的时候过滤活跃或者不活跃状态。同时还消除了新用户在采用 数据时所面临的一些问题,比如,某些记录可能不再为他们所用,再删除的时候可以起到一定的 防范作用。 9. 使用角色实体定义属于某类别的列 在需要对属于特定类别或者具有特定角色的事物做定义时,可以用角色实体来创建特定的时间关 联关系,从而可以实现自我文档化。 这里的含义不是让PERSON 实体带有Title 字段,而是说,为什么不用PERSON 实体和 PERSON_TYPE 实体来描述人员呢?然后,比方说,当John Smith, Engineer 提升为John Smith, Director 乃至最后爬到John Smith, CIO 的高位,而所有你要做的不过是改变两个表 PERSON 和PERSON_TYPE 之间关系的键值,同时增加一个日期/时间字段来知道变化是何时 发生的。这样,你的PERSON_TYPE 表就包含了所有PERSON 的可能类型,比如Associate、 Engineer、Director、CIO 或者CEO 等。 还有个替代办法就是改变PERSON 记录来反映新头衔的变化,不过这样一来在时间上无法跟踪 个人所处位置的具体时间。 10. 采用常用实体命名机构数据 组织数据的最简单办法就是采用常用名字,比如:PERSON、ORGANIZATION、ADDRESS 和 PHONE 等等。当你把这些常用的一般名字组合起来或者创建特定的相应副实体时,你就得到了 自己用的特殊版本。开始的时候采用一般术语的主要原因在于所有的具体用户都能对抽象事物具 体化。 有了这些抽象表示,你就可以在第2 级标识中采用自己的特殊名称,比如,PERSON 可能是 Employee、Spouse、Patient、Client、Customer、Vendor 或者Teacher 等。同样的, ORGANIZATION 也可能是MyCompany、MyDepartment、Competitor、Hospital、 Warehouse、Government 等。最后ADDRESS 可以具体为Site、Location、Home、Work、 Client、Vendor、Corporate 和FieldOffice 等。 采用一般抽象术语来标识“事物”的类别可以让你在关联数据以满足业务要求方面获得巨大的灵 活性,同时这样做还可以显著降低数据存储所需的冗余量。 11. 用户来自世界各地 在设计用到网络或者具有其他国际特性的数据库时,一定要记住大多数国家都有不同的字段格 式,比如邮政编码等,有些国家,比如新西兰就没有邮政编码一说。 12. 数据重复需要采用分立的数据表 如果你发现自己在重复输入数据,请创建新表和新的关系。 13. 每个表中都应该添加的3 个有用的字段 · dRecordCreationDate,在VB 下默认是Now(),而在SQL Server 下默认为GETDATE() · sRecordCreator,在SQL Server 下默认为NOT NULL DEFAULT USER · nRecordVersion,记录的版本标记;有助于准确说明记录中出现null 数据或者丢失数据的原 因 14. 对地址和电话采用多个字段 描述街道地址就短短一行记录是不够的。Address_Line1、Address_Line2 和Address_Line3 可 以提供更大的灵活性。还有,电话号码和邮件地址最好拥有自己的数据表,其间具有自身的类型 和标记类别。 过分标准化可要小心,这样做可能会导致性能上出现问题。虽然地址和电话表分离通常可以达到 最佳状态,但是如果需要经常访问这类信息,或许在其父表中存放“首选”信息(比如 Customer 等)更为妥当些。非标准化和加速访问之间的妥协是有一定意义的。 15. 使用多个名称字段 我觉得很吃惊,许多人在数据库里就给name 留一个字段。我觉得只有刚入门的开发人员才会这 么做,但实际上网上这种做法非常普遍。我建议应该把姓氏和名字当作两个字段来处理,然后在 查询的时候再把他们组合起来。 要把这种情况变得对用户更为友好有好 些方法。我最常用的是在同一表中创建一个计算列,通过它可以自动地连接标准化后的字段,这 样数据变动的时候它也跟着变。不过,这样做在采用建模软件时得很机灵才行。总之,采用连接 字段的方式可以有效的隔离用户应用和开发人员界面。 16. 提防大小写混用的对象名和特殊字符 过去最令我恼火的事情之一就是数据库里有大小写混用的对象名,比如CustomerData。这一问 题从Access 到Oracle 数据库都存在。我不喜欢采用这种大小写混用的对象命名方法,结果还不 得不手工修改名字。想想看,这种数据库/应用程序能混到采用更强大数据库的那一天吗?采用全 部大写而且包含下划符的名字具有更好的可读性(CUSTOMER_DATA),绝对不要在对象名的 字符之间留空格。 17. 小心保留词 要保证你的字段名没有和保留词、数据库系统或者常用访问方法冲突,比如,最近我编写的一个 ODBC 连接程序里有个表,其中就用了DESC 作为说明字段名。后果可想而知!DESC 是 DESCENDING 缩写后的保留词。表里的一个SELECT *语句倒是能用,但我得到的却是一大堆 毫无用处的信息。 18. 保持字段名和类型的一致性 在命名字段并为其指定数据类型的时候一定要保证一致性。假如字段在某个表中叫做 “agreement_number”,你就别在另一个表里把名字改成“ref1”。假如数据类型在一个表里 是整数,那在另一个表里可就别变成字符型了。记住,你干完自己的活了,其他人还要用你的数 据库呢。 19. 仔细选择数字类型 在SQL 中使用smallint 和tinyint 类型要特别小心,比如,假如你想看看月销售总额,你的总额字 段类型是smallint,那么,如果总额超过了$32,767 你就不能进行计算操作了。 20. 删除标记 在表中包含一个“删除标记”字段,这样就可以把行标记为删除。在关系数据库里不要单独删除 某一行;最好采用清除数据程序而且要仔细维护索引整体性。 21. 避免使用触发器 触发器的功能通常可以用其他方式实现。在调试程序时触发器可能成为干扰。假如你确实需要采 用触发器,你最好集中对它文档化。 22. 包含版本机制 建议你在数据库中引入版本控制机制来确定使用中的数据库的版本。无论如何你都要实现这一要 求。时间一长,用户的需求总是会改变的。最终可能会要求修改数据库结构。虽然你可以通过检 查新字段或者索引来确定数据库结构的版本,但我发现把版本信息直接存放到数据库中不更为方 便吗?。 23. 给文本字段留足余量 ID 类型的文本字段,比如客户ID 或定单号等等都应该设置得比一般想象更大,因为时间不长你 多半就会因为要添加额外的字符而难堪不已。比方说,假设你的客户ID 为10 位数长。那你应该 把数据库表字段的长度设为12 或者13 个字符长。这算浪费空间吗?是有一点,但也没你想象的 那么多:一个字段加长3 个字符在有1 百万条记录,再加上一点索引的情况下才不过让整个数据 库多占据3MB 的空间。但这额外占据的空间却无需将来重构整个数据库就可以实现数据库规模 的增长了。 24. 列命名技巧 我们发现,假如你给每个表的列名都采用统一的前缀,那么在编写SQL 表达式的时候会得到大 大的简化。这样做也确实有缺点,比如破坏了自动表连接工具的作用,后者把公共列名同某些数 据库联系起来,不过就连这些工具有时不也连接错误嘛。举个简单的例子,假设有两个表: Customer 和Order。Customer 表的前缀是cu_,所以该表内的子段名如下:cu_name_id、 cu_surname、cu_initials 和cu_address 等。Order 表的前缀是or_,所以子段名是: or_order_id、or_cust_name_id、or_quantity 和or_description 等。 这样从数据库中选出全部数据的SQL 语句可以写成如下所示: Select * from Customer, Order Where cu_surname = "MYNAME" and cu_name_id = or_cust_name_id and or_quantity = 1; 在没有这些前缀的情况下则写成这个样子: Select * from Customer, Order Where Customer.surname = "MYNAME" and Customer.name_id = Order.cust_name_id and Order.quantity = 1 第1 个SQL 语句没少键入多少字符。但如果查询涉及到5 个表乃至更多的列你就知道这个技巧 多有用了。 传说中的“数据库设计指南”第1 部分— 设计数据库之前 1. 考察现有环境 在设计一个新数据库时,你不但应该仔细研究业务需求而且还要考察现有的系统。大多数数据库项目都不是从头开始建立的;通常,机构内总会存在用来满足特定需求的现有系统(可能没有实现自动计算)。显然,现有系统并不完美,否则你就不必再建立新系统了。但是对旧系统的研究可以让你发现一些可能会忽略的细微问题。一般来说,考察现有系统对你绝对有好处。 我曾经接手过一个为地区运输公司开发的数据库项目,活不难,用的是Access 数据库。我设置了一些项目设计参数,而且同客户一道对这些参数进行了评估,事先还查看了开发环境下所采取的工作模式,等到最后部署应用的时候,只见终端上出了几个提示符然后立马在我面前翘辫子了!抓耳挠腮的折腾了好几个小时,我才意识到,原来这家公司的网络上跑着两个数据库应用,而对网络的访问需要明确和严格的用户帐号及其访问权限。明白了这一点,问题迎刃而解:只需采用客户的系统即可。这个项目给我的教训就是:记住,假如你在诸如Access 或者Interbase 这类公共环境下开发应用程序,一定要从表面下手深入系统内部搞清楚你面临的环境到底是怎么回事。 2. 定义标准的对象命名规范 一定要定义数据库对象的命名规范。对数据库表来说,从项目一开始就要确定表名是采用复数还是单数形式。此外还要给表的别名定义简单规则(比方说,如果表名是一个单词,别名就取单词的前4 个字母;如果表名是两个单词,就各取两个单词的前两个字母组成4 个字母长的别名;如果表的名字由3 个单词组成,你不妨从头两个单词中各取一个然后从最后一个单词中再取出两个字母,结果还是组成4 字母长的别名,其余依次类推)对工作用表来说,表名可以加上前缀WORK_ 后面附上采用该表的应用程序的名字。表内的列要针对键采用一整套设计规则。比如,如果键是数字类型,你可以用_NO 作为后缀;如果是字符类型则可以采用_CODE 后缀。对列名应该采用标准的前缀和后缀。再如,假如你的表里有好多“money”字段,你不妨给每个列增加一个_AMT 后缀。还有,日期列最好以DATE_作为名字打头。 检查表名、报表名和查询名之间的命名规范。你可能会很快就被这些不同的数据库要素的名称搞糊涂了。假如你坚持统一地命名这些数据库的不同组成部分,至少你应该在这些对象名字的开头用table、query 或者report 等前缀加以区别。 如果采用了Microsoft Access,你可以用qry、rpt、tbl 和mod 等符号来标识对象(比如 tbl_Employees)。我在和SQL Server(或者Oracle)打交道的时候还用过tbl 来索引表,但我用sp_company (现在用sp_feft_)标识存储过程,因为在有的时候如果我发现了更好的处理办法往往会保存好几个拷贝。我在实现SQL Server 2000 时用udf_ (或者类似的标记)标识我编写的函数。 3. 预先计划 上个世纪80 年代初,我还在使用资产帐目系统和System 38 平台,那时我负责设计所有的日期字段,这样在不费什么力气的情况下将来就可以轻松处理2000 年问题了。许多人给我说就别去解决这一问题了,因为要处理起来太麻烦了(这在世人皆知的Y2K 问题之前很久了)。我回击说只要预先计划今后就不会遇到大麻烦。结果我只用了两周的时间就把程序全部改完了。因为预先计划的好,后来Y2K 问题对该系统的危害降到了最低程度(最近听说该程序甚至到了1995 年都还运行在AS/400 系统上,唯一出现的小问题是从代码中删除注释费了点工夫)。 4. 获取数据模式资源手册 正在寻求示例模式的人可以阅读《数据模式资源手册》一书,该书由Len Silverston、W. H.Inmon 和Kent Graziano 编写,是一本值得拥有的最佳数据建模图书。该书包括的章节涵盖多种数据领域,比如人员、机构和工作效能等。 5. 畅想未来,但不可忘了过去的教训 我发现询问用户如何看待未来需求变化非常有用。这样做可以达到两个目的:首先,你可以清楚地了解应用设计在哪个地方应该更具灵活性以及如何避免性能瓶颈;其次,你知道发生事先没有确定的需求变更时用户将和你一样感到吃惊。 一定要记住过去的经验教训!我们开发人员还应该通过分享自己的体会和经验互相帮助。即使用户认为他们再也不需要什么支持了,我们也应该对他们进行这方面的教育,我们都曾经面临过这样的时刻“当初要是这么做了该多好⋯⋯”。 6. 在物理实践之前进行逻辑设计 在深入物理设计之前要先进行逻辑设计。随着大量的CASE 工具不断涌现出来,你的设计也可以达到相当高的逻辑水准,你通常可以从整体上更好地了解数据库设计所需要的方方面面。 7. 了解你的业务 在你百分百地确定系统从客户角度满足其需求之前不要在你的ER(实体关系)模式中加入哪怕一个数据表(怎么,你还没有模式?那请你参看技巧9)。了解你的企业业务可以在以后的开发阶段节约大量的时间。一旦你明确了业务需求,你就可以自己做出许多决策了。 一旦你认为你已经明确了业务内容,你最好同客户进行一次系统的交流。采用客户的术语并且向他们解释你所想到的和你所听到的。同时还应该用可能、将会和必须等词汇表达出系统的关系基数。这样你就可以让你的客户纠正你自己的理解然后做好下一步的ER 设计。 8. 创建数据字典和ER 图表 一定要花点时间创建ER 图表和数据字典。其中至少应该包含每个字段的数据类型和在每个表内的主外键。创建ER 图表和数据字典确实有点费时但对其他开发人员要了解整个设计却是完全必要的。越早创建越能有助于避免今后面临的可能混乱,从而可以让任何了解数据库的人都明确如何从数据库中获得数据。 有一份诸如ER 图表等最新文档其重要性如何强调都不过分,这对表明表之间关系很有用,而数据字典则说明了每个字段的用途以及任何可能存在的别名。对SQL 表达式的文档化来说这是完全必要的。 9. 创建模式 一张图表胜过千言万语:开发人员不仅要阅读和实现它,而且还要用它来帮助自己和用户对话。模式有助于提高协作效能,这样在先期的数据库设计中几乎不可能出现大的问题。模式不必弄的很复杂;甚至可以简单到手写在一张纸上就可以了。只是要保证其上的逻辑关系今后能产生效益。 10. 从输入输出下手 在定义数据库表和字段需求(输入)时,首先应检查现有的或者已经设计出的报表、查询和视图(输出)以决定为了支持这些输出哪些是必要的表和字段。举个简单的例子:假如客户需要一个报表按照邮政编码排序、分段和求和,你要保证其中包括了单独的邮政编码字段而不要把邮政编码糅进地址字段里。 11. 报表技巧 要了解用户通常是如何报告数据的:批处理还是在线提交报表?时间间隔是每天、每周、每月、每个季度还是每年?如果需要的话还可以考虑创建总结表。系统生成的主键在报表中很难管理。用户在具有系统生成主键的表内用副键进行检索往往会返回许多重复数据。这样的检索性能比较低而且容易引起混乱。 12. 理解客户需求 看起来这应该是显而易见的事,但需求就是来自客户(这里要从内部和外部客户的角度考虑)。不要依赖用户写下来的需求,真正的需求在客户的脑袋里。你要让客户解释其需求,而且随着开发的继续,还要经常询问客户保证其需求仍然在开发的目的之中。一个不变的真理是:“只有我看见了我才知道我想要的是什么”必然会导致大量的返工,因为数据库没有达到客户从来没有写下来的需求标准。而更糟的是你对他们需求的解释只属于你自己,而且可能是完全错误的。 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|