• 关于

    困惑度有什么用

    的搜索结果

问题

我想请问一个关于文件结构设计的问题,网上完全搜索不到这方面的东西:报错

kun坤 2020-06-06 16:50:27 0 浏览量 回答数 1

回答

  算法,数据结构是关键,另外还有组合数学,特别是集合与图论,概率论也重要。推荐买一本《算法导论》,那本书行,看起来超爽。。。基本掌握语法还不行啊,语法的超熟练掌握,不然出了错误很难调试的。。。最重要的是超牛皮的头脑啦,分析能力,逻辑推理能力很重要。ACM很好玩啦,祝你成功。。。   acm是3人一组的,以学校为单位报名的,也就是说要得到学校同意,还要有2个一起搞的。其实可能是你不知道你们学校搞acm的地方,建议你好好询问下你们学校管科技创新方面的人。建议你找几个兴趣相同的一起做,互相探讨效果好多了,团队合作也是acm要求的3大能力之一。   数据结构远远不够的,建议你看算法导论,黑书,oj的话个人觉得还是poj好,有水题有好题,而且做的人多,要解题报告什么的也好找。我们就是一些做acm的学生一起搞,也没老师,这样肯定能行的。   基础的话是语言,然后数据结构,然后算法。   ACM有三个方向:算法,数学,实现   要求三种能力:英文,自学,团队协作   简单的说,你要能读懂英文的题意描述,要有一门acm能使用的编程语言,要会数据结构,有一点数学基础,一点编程方面天赋,要有兴趣和毅力(最重要),就具有做ACM的基本条件了。   做acm我推荐c,c++也可以,java在某些情况下好用,但是大多数情况的效率和代码量都不大好,所以建议主用c++,有些题目用java   还有什么问题,可以问我啊。   不好意思,没见过用java描述的acm书籍,大多数是用伪命令,其他有的用的c,c++,老一些的用pascal。java只是用来做高精度的一些题的,个人觉得不用专门看这方面的书,java的基本部分学好就够用了。所以我还是推荐主用c++,在高精度和个别题再用java。你可以找找java描述的算法设计与分析,这个好像有   数据结构:C语言版 清华大学出版社 严蔚敏 《数据结构》   算法:清华大学出版社 王晓东 《算法设计与分析》   麻省理工大学 中译本:机械工业出版社 《算法导论》   基本上这三本书就已经足够了,建议一般水平的人先不要看算法导论,待另外两本书看的差不多的时候,再看算法导论加深理解。   另外还有很多针对性更强的书籍,不过针对性太强,这里就不多介绍了。   以上一些都是些算法方面的书,最好的方式就是做题与看书相结合,很多在线做题的网站,PKU,ZOJ很多,推荐PKU,题目比较多,参与的人比较多。做一段时间的题,然后看书,研究算法,再做题,这样进步比较快。   还有关于ACM竞赛,我有自己的一点话说。   首先说下ACM/ICPC是个团队项目,最后的参赛名额是按照学校为单位的,所以找到志同道合的队友和学校的支持是很重要的。   刚刚接触信息学领域的同学往往存在很多困惑,不知道从何入手学习,在这篇文章里,我希望能将自己不多的经验与大家分享,希望对各位有所帮助。   一、语言是最重要的基本功   无论侧重于什么方面,只要是通过计算机程序去最终实现的竞赛,语言都是大家要过的第一道关。亚洲赛区的比赛支持的语言包括C/C++与JAVA。笔者首先说说JAVA,众所周知,作为面向对象的王牌语言,JAVA在大型工程的组织与安全性方面有着自己独特的优势,但是对于信息学比赛的具体场合,JAVA则显得不那么合适,它对于输入输出流的操作相比于C++要繁杂很多,更为重要的是JAVA程序的运行速度要比C++慢10倍以上,而竞赛中对于JAVA程序的运行时限却往往得不到同等比例的放宽,这无疑对算法设计提出了更高的要求,是相当不利的。其实,笔者并不主张大家在这种场合过多地运用面向对象的程序设计思维,因为对于小程序来说这不旦需要花费更多的时间去编写代码,也会降低程序的执行效率。   接着说C和C++。许多现在参加讲座的同学还在上大一,C的基础知识刚刚学完,还没有接触过C++,其实在赛场上使用纯C的选手还是大有人在的,它们主要是看重了纯C在效率上的优势,所以这部分同学如果时间有限,并不需要急着去学习新的语言,只要提高了自己在算法设计上的造诣,纯C一样能发挥巨大的威力。   而C++相对于C,在输入输出流上的封装大大方便了我们的操作,同时降低了出错的可能性,并且能够很好地实现标准流与文件流的切换,方便了调试的工作。如果有些同学比较在意这点,可以尝试C和C++的混编,毕竟仅仅学习C++的流操作还是不花什么时间的。   C++的另一个支持来源于标准模版库(STL),库中提供的对于基本数据结构的统一接口操作和基本算法的实现可以缩减我们编写代码的长度,这可以节省一些时间。但是,与此相对的,使用STL要在效率上做出一些牺牲,对于输入规模很大的题目,有时候必须放弃STL,这意味着我们不能存在“有了STL就可以不去管基本算法的实现”的想法;另外,熟练和恰当地使用STL必须经过一定时间的积累,准确地了解各种操作的时间复杂度,切忌对STL中不熟悉的部分滥用,因为这其中蕴涵着许多初学者不易发现的陷阱。   通过以上的分析,我们可以看出仅就信息学竞赛而言,对语言的掌握并不要求十分全面,但是对于经常用到的部分,必须十分熟练,不允许有半点不清楚的地方,下面我举个真实的例子来说明这个道理——即使是一点很细微的语言障碍,都有可能酿成错误:   在去年清华的赛区上,有一个队在做F题的时候使用了cout和printf的混合输出,由于一个带缓冲一个不带,所以输出一长就混乱了。只是因为当时judge team中负责F题的人眼睛尖,看出答案没错只是顺序不对(答案有一页多,是所有题目中最长的一个输出),又看了看程序发现只是输出问题就给了个Presentation error(格式错)。如果审题的人不是这样而是直接给一个 Wrong Answer,相信这个队是很难查到自己错在什么地方的。   现在我们转入第二个方面的讨论,基础学科知识的积累。   二、以数学为主的基础知识十分重要   虽然被定性为程序设计竞赛,但是参赛选手所遇到的问题更多的是没有解决问题的思路,而不是有了思路却死活不能实现,这就是平时积累的基础知识不够。今年World Final的总冠军是波兰华沙大学,其成员出自于数学系而非计算机系,这就是一个鲜活的例子。竞赛中对于基础学科的涉及主要集中于数学,此外对于物理、电路等等也可能有一定应用,但是不多。因此,大一的同学也不必为自己还没学数据结构而感到不知从何入手提高,把数学捡起来吧。下面我来谈谈在竞赛中应用的数学的主要分支。   1、离散数学——作为计算机学科的基础,离散数学是竞赛中涉及最多的数学分支,其重中之重又在于图论和组合数学,尤其是图论。   图论之所以运用最多是因为它的变化最多,而且可以轻易地结合基本数据结构和许多算法的基本思想,较多用到的知识包括连通性判断、DFS和BFS,关节点和关键路径、欧拉回路、最小生成树、最短路径、二部图匹配和网络流等等。虽然这部分的比重很大,但是往往也是竞赛中的难题所在,如果有初学者对于这部分的某些具体内容暂时感到力不从心,也不必着急,可以慢慢积累。   竞赛中设计的组合计数问题大都需要用组合数学来解决,组合数学中的知识相比于图论要简单一些,很多知识对于小学上过奥校的同学来说已经十分熟悉,但是也有一些部分需要先对代数结构中的群论有初步了解才能进行学习。组合数学在竞赛中很少以难题的形式出现,但是如果积累不够,任何一道这方面的题目却都有可能成为难题。   2、数论——以素数判断和同余为模型构造出来的题目往往需要较多的数论知识来解决,这部分在竞赛中的比重并不大,但只要来上一道,也足以使知识不足的人冥思苦想上一阵时间。素数判断和同余最常见的是在以密码学为背景的题目中出现,在运用密码学常识确定大概的过程之后,核心算法往往要涉及数论的内容。   3、计算几何——计算几何相比于其它部分来说是比较独立的,就是说它和其它的知识点很少有过多的结合,较常用到的部分包括——线段相交的判断、多边形面积的计算、内点外点的判断、凸包等等。计算几何的题目难度不会很大,但也永远不会成为最弱的题。   4、线性代数——对线性代数的应用都是围绕矩阵展开的,一些表面上是模拟的题目往往可以借助于矩阵来找到更好的算法。   5、概率论——竞赛是以黑箱来判卷的,这就是说你几乎不能动使用概率算法的念头,但这也并不是说概率就没有用。关于这一点,只有通过一定的练习才能体会。   6、初等数学与解析几何——这主要就是中学的知识了,用的不多,但是至少比高等数学多,我觉得熟悉一下数学手册上的相关内容,至少要知道在哪儿能查到,还是必要的。   7、高等数学——纯粹运用高等数学来解决的题目我接触的只有一道,但是一些题目的叙述背景往往需要和这部分有一定联系,掌握得牢固一些总归没有坏处。   以上就是竞赛所涉及的数学领域,可以说范围是相当广的。我认识的许多人去搞信息学的竞赛就是为了逼着自己多学一点数学,因为数学是一切一切的基础。   三、数据结构与算法是真正的核心   虽然数学十分十分重要,但是如果让三个只会数学的人参加比赛,我相信多数情况下会比三个只会数据结构与算法的人得到更为悲惨的结局。   先说说数据结构。掌握队列、堆栈和图的基本表达与操作是必需的,至于树,我个人觉得需要建树的问题有但是并不多。(但是树往往是很重要的分析工具)除此之外,排序和查找并不需要对所有方式都能很熟练的掌握,但你必须保证自己对于各种情况都有一个在时间复杂度上满足最低要求的解决方案。说到时间复杂度,就又该说说哈希表了,竞赛时对时间的限制远远多于对空间的限制,这要求大家尽快掌握“以空间换时间”的原则策略,能用哈希表来存储的数据一定不要到时候再去查找,如果实在不能建哈希表,再看看能否建二叉查找树等等——这都是争取时间的策略,掌握这些技巧需要大家对数据结构尤其是算法复杂度有比较全面的理性和感性认识。   接着说说算法。算法中最基本和常用的是搜索,主要是回溯和分支限界法的使用。这里要说的是,有些初学者在学习这些搜索基本算法是不太注意剪枝,这是十分不可取的,因为所有搜索的题目给你的测试用例都不会有很大的规模,你往往察觉不出程序运行的时间问题,但是真正的测试数据一定能过滤出那些没有剪枝的算法。实际上参赛选手基本上都会使用常用的搜索算法,题目的区分度往往就是建立在诸如剪枝之类的优化上了。   常用算法中的另一类是以“相似或相同子问题”为核心的,包括递推、递归、贪心法和动态规划。这其中比较难于掌握的就是动态规划,如何抽象出重复的子问题是很多题目的难点所在,笔者建议初学者仔细理解图论中一些以动态规划为基本思想所建立起来的基本算法(比如Floyd-Warshall算法),并且多阅读一些定理的证明,这虽然不能有什么直接的帮助,但是长期坚持就会对思维很有帮助。   四、团队配合   通过以上的介绍大家也可以看出,信息学竞赛对于知识面覆盖的非常广,想凭一己之力全部消化这些东西实在是相当困难的,这就要求我们尽可能地发挥团队协作的精神。同组成员之间的熟练配合和默契的形成需要时间,具体的情况因成员的组成不同而不同,这里我就不再多说了。   五、练习、练习、再练习   知识的积累固然重要,但是信息学终究不是看出来的,而是练出来的,这是多少前人最深的一点体会,只有通过具体题目的分析和实践,才能真正掌握数学的使用和算法的应用,并在不断的练习中增加编程经验和技巧,提高对时间复杂度的感性认识,优化时间的分配,加强团队的配合。总之,在这里光有纸上谈兵是绝对不行的,必须要通过实战来锻炼自己。   大家一定要问,我们去哪里找题做,又如何检验程序是否正确呢。这大可不必担心,现在已经有了很多网上做题的站点,这些站点提供了大量的题库并支持在线判卷,你只需要把程序源码提交上去,马上就可以知道自己的程序是否正确,运行所使用的时间以及消耗的内存等等状况。下面我给大家推荐几个站点,笔者不建议大家在所有这些站点上做题,选择一个就可以了,因为每个站点的题都有一定的难易比例,系统地做一套题库可以使你对各种难度、各种类型的题都有所认识。   1、Ural:   Ural是中国学生对俄罗斯的Ural州立大学的简称 ,那里设立了一个Ural Online Problem Set,并且支持Online Judge。Ural的不少题目算法性和趣闻性都很强,得到了国内广大学生的厚爱。根据“信息学初学者之家”网站的统计,Ural的题目类型大概呈如下的分布:   题型   搜索   动态规划   贪心   构造   图论   计算几何   纯数学问题   数据结构   其它   所占比例   约10%   约15%   约5%   约5%   约10%   约5%   约20%   约5%   约25%   这和实际比赛中的题型分布也是大体相当的。有兴趣的朋友可以去看看。   2、UVA:   UVA代表西班牙Valladolid大学(University de Valladolid)。该大学有一个那里设立了一个PROBLEM SET ARCHIVE with ONLINE JUDGE ,并且支持ONLINE JUDGE,形式和Ural大学的题库类似。不过和Ural不同的是,UVA题目多的多,而且比较杂,而且有些题目的测试数据比较刁钻。这使得刚到那里做题的朋友往往感觉到无所适从,要么难以找到合适的题目,要么Wrong Answer了很多次以后仍然不知道错在那里。 如果说做Ural题目主要是为了训练算法,那么UVA题目可以训练全方位的基本功和一些必要的编程素质。UVA和许多世界知名大学联合办有同步网上比赛,因此那里强人无数,不过你先要使自己具有听懂他们在说什么的素质:)   3、ZOJ:   ZOJ是浙江大学建立的ONLINE JUDGE,是中国大学建立的第一个同类站点,也是最好和人气最高的一个,笔者和许多班里的同学就是在这里练习。ZOJ虽然也定位为一个英文网站,但是这里的中国学生比较多,因此让人觉得很亲切。这里目前有500多道题目,难易分配适中,且涵盖了各大洲的题目类型并配有索引,除此之外,ZOJ的JUDGE系统是几个网站中表现得比较好的一个,很少出现Wrong Answer和Presentation error混淆的情况。这里每月也办有一次网上比赛,只要是注册的用户都可以参加。   说起中国的ONLINE JUDGE,去年才开始参加ACM竞赛的北京大学现在也建立了自己的提交系统;而我们学校也是去年开始参加比赛,现在也有可能推出自己的提交系统,如果能够做成,到时候大家就可以去上面做题了。同类网站的飞速发展标志着有越来越多的同学有兴趣进入信息学的领域探索,这是一件好事,同时也意味着更激烈的竞争。

小旋风柴进 2019-12-02 01:20:20 0 浏览量 回答数 0

回答

gif、jpg、png格式的图片在网站制作中的区别 Gif格式特点:   1.透明性,Gif是一种布尔透明类型,既它可以是全透明,也可以是全不透明,但是它并没有半透明(alpha透明)。   2.动画,Gif这种格式支持动画。   3.无损耗性,Gif是一种无损耗的图像格式,这也意味着你可以对gif图片做任何操作也不会使得图像质量产生损耗。   4.水平扫描,Gif是使用了一种叫作LZW的算法进行压缩的,当压缩gif的过程中,像素是由上到下水平压缩的,这也意味着同等条件下,横向的gif图片比竖向的gif图片更加小。例如50010的图片比10500的图片更加小   5.间隔渐进显示,Gif支持可选择性的间隔渐进显示   由以上特点看出只有256种颜色的gif图片不适合照片,但它适合对颜色要求不高的图形(比如说图标,图表等),它并不是最优的选择,我们会在后面中看到png是最优的选择。 Jpeg(jpg)格式特点:   1.透明性,它并不支持透明。   2.动画,它也不支持动画。   3.损耗性,除了一些比如说旋转(仅仅是90、180、270度旋转),裁切,从标准类型到先进类型,编辑图片的原数据之外,所有其它操作对jpeg图像的处理都会使得它的质量损失。所以我们在编辑过程一般用png作为过渡格式。   4.隔行渐进显示,它支持隔行渐进显示(但是ie浏览器并不支持这个属性,但是ie会在整个图像信息完全到达的时候显示)。   由上可以看出Jpeg是最适web上面的摄影图片和数字照相机中。 Png格式特点:   1.类型,Png这种图片格式包括了许多子类,但是在实践中大致可以分为256色的png和全色的png,你完成可以用256色的png代替gif,用全色的png代替jpeg   2.透明性,Png是完全支持alpha透明的(透明,半透明,不透明),尽管有两个怪异的现象在ie6(下面详细讨论)   3.动画,它不支持动画   PNG图片格式现在包含三种类型:   1.PNG8256色PNG的别名   2.PNG24全色PNG的别名   3.PNG32全色PNG的别名   基本上PNG32就是PNG24,但是附带了全alpha通道。就是说每个像素上不仅存储了24位真色彩信息还存储了8位的alpha通道信息,就如同GIF能存储透明和不透明信息一样。当我们把图片放到不太搭配的背景上的时候,透明PNG图片的边缘会显示得更加平滑。   当然,我也知道你的想法,“但是Photoshop也能生成带透明通道的PNG图片!”我也知道,它只是表面上这么说是PNG24,让我也产生困惑了。   作为一个伤感的Fireworks倡导者,我只使用PNG32支持附带alpha通道的真色彩图片。不管怎样,如果你习惯使Photoshop,你就应该知道,Photoshop在“存储为WEB格式”中只提供PNG8和PNG24两种PNG格式。   我敢肯定你经常会勾选“支持透明”选项,以获得带有透明度的PNG图片,但是这样你就获取了一张PNG32图片。——Photoshop只是觉得把PNG32这个名称给隐藏掉了。。。。 对png8的误解   Png8的在ie中的怪异表现:   半透明的png8在ie6以下的浏览器显示为全透明。   Alpha透明的全色PNG(png32)在ie6中会出现背景颜色(通常是灰色)。   由上面可以总结:   (a)全透明的png8可以在任一浏览器正常显示(就像gif一样)。半透明的png8在除了ie6及其以下的浏览器下错误的显示成全透明,其它浏览器都能正常显示半透明。这个bug并不需要特殊对待,因为在不支持半透明的浏览器下只是显示为全透明,对用户体验影响不大,它反而是透明gif的加强版。   (b)第二个bug没有什么好的方法解决,只能通过影响性能的方法AlphaImageLoader与需要加特殊标签(VML)。   因此得出结论就是:请使用PNG8。 Png8的软件问题:   Photoshop只能导出布尔透明的PNG8。   Fireworks既能导出布尔透明的PNG8,也能导出alpha透明的PNG8.

前端问答 2020-01-02 20:35:43 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

问题

必须了解的五个服务器基础问题

杨经理 2019-12-01 21:43:28 6744 浏览量 回答数 0

回答

转自:阿里云官网 — 知乎 写好代码,阿里专家沉淀了一套“如何写复杂业务代码”的方法论,在此分享给大家,相信同样的方法论可以复制到大部分复杂业务场景。 一文教会你如何写复杂业务代码 了解我的人都知道,我一直在致力于应用架构和代码复杂度的治理。 这两天在看零售通商品域的代码。面对零售通如此复杂的业务场景,如何在架构和代码层面进行应对,是一个新课题。针对该命题,我进行了比较细致的思考和研究。结合实际的业务场景,我沉淀了一套“如何写复杂业务代码”的方法论,在此分享给大家。 我相信,同样的方法论可以复制到大部分复杂业务场景。 一个复杂业务的处理过程 业务背景 简单的介绍下业务背景,零售通是给线下小店供货的B2B模式,我们希望通过数字化重构传统供应链渠道,提升供应链效率,为新零售助力。阿里在中间是一个平台角色,提供的是Bsbc中的service的功能。 在商品域,运营会操作一个“上架”动作,上架之后,商品就能在零售通上面对小店进行销售了。是零售通业务非常关键的业务操作之一,因此涉及很多的数据校验和关联操作。 针对上架,一个简化的业务流程如下所示: 过程分解 像这么复杂的业务,我想应该没有人会写在一个service方法中吧。一个类解决不了,那就分治吧。 说实话,能想到分而治之的工程师,已经做的不错了,至少比没有分治思维要好很多。我也见过复杂程度相当的业务,连分解都没有,就是一堆方法和类的堆砌。 不过,这里存在一个问题:即很多同学过度的依赖工具或是辅助手段来实现分解。比如在我们的商品域中,类似的分解手段至少有3套以上,有自制的流程引擎,有依赖于数据库配置的流程处理: 本质上来讲,这些辅助手段做的都是一个pipeline的处理流程,没有其它。因此,我建议此处最好保持KISS(Keep It Simple and Stupid),即最好是什么工具都不要用,次之是用一个极简的Pipeline模式,最差是使用像流程引擎这样的重方法。 除非你的应用有极强的流程可视化和编排的诉求,否则我非常不推荐使用流程引擎等工具。第一,它会引入额外的复杂度,特别是那些需要持久化状态的流程引擎;第二,它会割裂代码,导致阅读代码的不顺畅。大胆断言一下,全天下估计80%对流程引擎的使用都是得不偿失的。 回到商品上架的问题,这里问题核心是工具吗?是设计模式带来的代码灵活性吗?显然不是,问题的核心应该是如何分解问题和抽象问题,知道金字塔原理的应该知道,此处,我们可以使用结构化分解将问题解构成一个有层级的金字塔结构: 按照这种分解写的代码,就像一本书,目录和内容清晰明了。以商品上架为例,程序的入口是一个上架命令(OnSaleCommand), 它由三个阶段(Phase)组成。 @Command public class OnSaleNormalItemCmdExe { @Resource private OnSaleContextInitPhase onSaleContextInitPhase; @Resource private OnSaleDataCheckPhase onSaleDataCheckPhase; @Resource private OnSaleProcessPhase onSaleProcessPhase; @Override public Response execute(OnSaleNormalItemCmd cmd) { OnSaleContext onSaleContext = init(cmd); checkData(onSaleContext); process(onSaleContext); return Response.buildSuccess(); } private OnSaleContext init(OnSaleNormalItemCmd cmd) { return onSaleContextInitPhase.init(cmd); } private void checkData(OnSaleContext onSaleContext) { onSaleDataCheckPhase.check(onSaleContext); } private void process(OnSaleContext onSaleContext) { onSaleProcessPhase.process(onSaleContext); } } 每个Phase又可以拆解成多个步骤(Step),以OnSaleProcessPhase为例,它是由一系列Step组成的: @Phase public class OnSaleProcessPhase { @Resource private PublishOfferStep publishOfferStep; @Resource private BackOfferBindStep backOfferBindStep; //省略其它step public void process(OnSaleContext onSaleContext){ SupplierItem supplierItem = onSaleContext.getSupplierItem(); // 生成OfferGroupNo generateOfferGroupNo(supplierItem); // 发布商品 publishOffer(supplierItem); // 前后端库存绑定 backoffer域 bindBackOfferStock(supplierItem); // 同步库存路由 backoffer域 syncStockRoute(supplierItem); // 设置虚拟商品拓展字段 setVirtualProductExtension(supplierItem); // 发货保障打标 offer域 markSendProtection(supplierItem); // 记录变更内容ChangeDetail recordChangeDetail(supplierItem); // 同步供货价到BackOffer syncSupplyPriceToBackOffer(supplierItem); // 如果是组合商品打标,写扩展信息 setCombineProductExtension(supplierItem); // 去售罄标 removeSellOutTag(offerId); // 发送领域事件 fireDomainEvent(supplierItem); // 关闭关联的待办事项 closeIssues(supplierItem); } } 看到了吗,这就是商品上架这个复杂业务的业务流程。需要流程引擎吗?不需要,需要设计模式支撑吗?也不需要。对于这种业务流程的表达,简单朴素的组合方法模式(Composed Method)是再合适不过的了。 因此,在做过程分解的时候,我建议工程师不要把太多精力放在工具上,放在设计模式带来的灵活性上。而是应该多花时间在对问题分析,结构化分解,最后通过合理的抽象,形成合适的阶段(Phase)和步骤(Step)上。 过程分解后的两个问题的确,使用过程分解之后的代码,已经比以前的代码更清晰、更容易维护了。不过,还有两个问题值得我们去关注一下: 1、领域知识被割裂肢解什么叫被肢解? 因为我们到目前为止做的都是过程化拆解,导致没有一个聚合领域知识的地方。每个Use Case的代码只关心自己的处理流程,知识没有沉淀。相同的业务逻辑会在多个Use Case中被重复实现,导致代码重复度高,即使有复用,最多也就是抽取一个util,代码对业务语义的表达能力很弱,从而影响代码的可读性和可理解性。 2、代码的业务表达能力缺失 试想下,在过程式的代码中,所做的事情无外乎就是取数据--做计算--存数据,在这种情况下,要如何通过代码显性化的表达我们的业务呢? 说实话,很难做到,因为我们缺失了模型,以及模型之间的关系。脱离模型的业务表达,是缺少韵律和灵魂的。 举个例子,在上架过程中,有一个校验是检查库存的,其中对于组合品(CombineBackOffer)其库存的处理会和普通品不一样。原来的代码是这么写的: boolean isCombineProduct = supplierItem.getSign().isCombProductQuote(); // supplier.usc warehouse needn't check if (WarehouseTypeEnum.isAliWarehouse(supplierItem.getWarehouseType())) { // quote warehosue check if (CollectionUtil.isEmpty(supplierItem.getWarehouseIdList()) && !isCombineProduct) { throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "亲,不能发布Offer,请联系仓配运营人员,建立品仓关系!"); } // inventory amount check Long sellableAmount = 0L; if (!isCombineProduct) { sellableAmount = normalBiz.acquireSellableAmount(supplierItem.getBackOfferId(), supplierItem.getWarehouseIdList()); } else { //组套商品 OfferModel backOffer = backOfferQueryService.getBackOffer(supplierItem.getBackOfferId()); if (backOffer != null) { sellableAmount = backOffer.getOffer().getTradeModel().getTradeCondition().getAmountOnSale(); } } if (sellableAmount < 1) { throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "亲,实仓库存必须大于0才能发布,请确认已补货.\r[id:" + supplierItem.getId() + "]"); } } 然而,如果我们在系统中引入领域模型之后,其代码会简化为如下: if(backOffer.isCloudWarehouse()){ return; } if (backOffer.isNonInWarehouse()){ throw new BizException("亲,不能发布Offer,请联系仓配运营人员,建立品仓关系!"); } if (backOffer.getStockAmount() < 1){ throw new BizException("亲,实仓库存必须大于0才能发布,请确认已补货.\r[id:" + backOffer.getSupplierItem().getCspuCode() + "]"); } 有没有发现,使用模型的表达要清晰易懂很多,而且也不需要做关于组合品的判断了,因为我们在系统中引入了更加贴近现实的对象模型(CombineBackOffer继承BackOffer),通过对象的多态可以消除我们代码中的大部分的if-else。 过程分解+对象模型 通过上面的案例,我们可以看到有过程分解要好于没有分解,过程分解+对象模型要好于仅仅是过程分解。对于商品上架这个case,如果采用过程分解+对象模型的方式,最终我们会得到一个如下的系统结构: 写复杂业务的方法论 通过上面案例的讲解,我想说,我已经交代了复杂业务代码要怎么写:即自上而下的结构化分解+自下而上的面向对象分析。 接下来,让我们把上面的案例进行进一步的提炼,形成一个可落地的方法论,从而可以泛化到更多的复杂业务场景。 上下结合 所谓上下结合,是指我们要结合自上而下的过程分解和自下而上的对象建模,螺旋式的构建我们的应用系统。这是一个动态的过程,两个步骤可以交替进行、也可以同时进行。这两个步骤是相辅相成的,上面的分析可以帮助我们更好的理清模型之间的关系,而下面的模型表达可以提升我们代码的复用度和业务语义表达能力。其过程如下图所示: 使用这种上下结合的方式,我们就有可能在面对任何复杂的业务场景,都能写出干净整洁、易维护的代码。 能力下沉 一般来说实践DDD有两个过程: 1. 套概念阶段 了解了一些DDD的概念,然后在代码中“使用”Aggregation Root,Bonded Context,Repository等等这些概念。更进一步,也会使用一定的分层策略。然而这种做法一般对复杂度的治理并没有多大作用。 2. 融会贯通阶段 术语已经不再重要,理解DDD的本质是统一语言、边界划分和面向对象分析的方法。 大体上而言,我大概是在1.7的阶段,因为有一个问题一直在困扰我,就是哪些能力应该放在Domain层,是不是按照传统的做法,将所有的业务都收拢到Domain上,这样做合理吗?说实话,这个问题我一直没有想清楚。 因为在现实业务中,很多的功能都是用例特有的(Use case specific)的,如果“盲目”的使用Domain收拢业务并不见得能带来多大的益处。相反,这种收拢会导致Domain层的膨胀过厚,不够纯粹,反而会影响复用性和表达能力。 鉴于此,我最近的思考是我们应该采用能力下沉的策略。 所谓的能力下沉,是指我们不强求一次就能设计出Domain的能力,也不需要强制要求把所有的业务功能都放到Domain层,而是采用实用主义的态度,即只对那些需要在多个场景中需要被复用的能力进行抽象下沉,而不需要复用的,就暂时放在App层的Use Case里就好了。 注:Use Case是《架构整洁之道》里面的术语,简单理解就是响应一个Request的处理过程 通过实践,我发现这种循序渐进的能力下沉策略,应该是一种更符合实际、更敏捷的方法。因为我们承认模型不是一次性设计出来的,而是迭代演化出来的。 下沉的过程如下图所示,假设两个use case中,我们发现uc1的step3和uc2的step1有类似的功能,我们就可以考虑让其下沉到Domain层,从而增加代码的复用性。 指导下沉有两个关键指标:代码的复用性和内聚性。 复用性是告诉我们When(什么时候该下沉了),即有重复代码的时候。 内聚性是告诉我们How(要下沉到哪里),功能有没有内聚到恰当的实体上,有没有放到合适的层次上(因为Domain层的能力也是有两个层次的,一个是Domain Service这是相对比较粗的粒度,另一个是Domain的Model这个是最细粒度的复用)。 比如,在我们的商品域,经常需要判断一个商品是不是最小单位,是不是中包商品。像这种能力就非常有必要直接挂载在Model上。 public class CSPU { private String code; private String baseCode; //省略其它属性 /** * 单品是否为最小单位。 * */ public boolean isMinimumUnit(){ return StringUtils.equals(code, baseCode); } /** * 针对中包的特殊处理 * */ public boolean isMidPackage(){ return StringUtils.equals(code, midPackageCode); } } 之前,因为老系统中没有领域模型,没有CSPU这个实体。你会发现像判断单品是否为最小单位的逻辑是以StringUtils.equals(code, baseCode)的形式散落在代码的各个角落。这种代码的可理解性是可想而知的,至少我在第一眼看到这个代码的时候,是完全不知道什么意思。 业务技术要怎么做 写到这里,我想顺便回答一下很多业务技术同学的困惑,也是我之前的困惑:即业务技术到底是在做业务,还是做技术?业务技术的技术性体现在哪里? 通过上面的案例,我们可以看到业务所面临的复杂性并不亚于底层技术,要想写好业务代码也不是一件容易的事情。 业务技术和底层技术人员唯一的区别是他们所面临的问题域不一样。业务技术面对的问题域变化更多、面对的人更加庞杂。而底层技术面对的问题域更加稳定、但对技术的要求更加深。比如,如果你需要去开发Pandora,你就要对Classloader有更加深入的了解才行。 但是,不管是业务技术还是底层技术人员,有一些思维和能力都是共通的。比如,分解问题的能力,抽象思维,结构化思维等等。 用我的话说就是:“做不好业务开发的,也做不好技术底层开发,反之亦然。业务开发一点都不简单,只是我们很多人把它做“简单”了因此,如果从变化的角度来看,业务技术的难度一点不逊色于底层技术,其面临的挑战甚至更大。 因此,我想对广大的从事业务技术开发的同学说:沉下心来,夯实自己的基础技术能力、OO能力、建模能力... 不断提升抽象思维、结构化思维、思辨思维... 持续学习精进,写好代码。我们可以在业务技术岗做的很”技术“!。

茶什i 2020-01-10 11:53:44 0 浏览量 回答数 0

问题

【一周热点】送给程序员终身受用的建议

问问小秘 2019-12-01 22:05:12 4740 浏览量 回答数 3

回答

最近,我问了我一个朋友他对"智能合约"的看法。他是一名开发者,我想他可能会有一些有趣的见解。令我惊讶的是,他并不知道智能合约是什么。我感到特别惊讶,因为我们讨论了一年多的加密货币、美国证券交易委员会(SEC)以及许多与区块链相关的其他事情。在计算机领域深耕的人怎么可能会不知道智能合约是什么? 事实上,相比区块链行业的其它概念,智能合约可能会更令加密货币爱好者们感到困惑。因此,要解释这个概念并不容易,尤其是向那些刚刚理解区块链是什么的人解释更不容易。因此,这一概念依旧十分神秘。希望这篇文章可以清楚地解释好这一概念。 什么是智能合约? 想象一下,如果你需要卖掉一栋房子,那么这将是一个复杂而艰巨的过程,不但需要处理大量的文书工作、与不同公司和人员进行沟通,而且还得冒着各类高风险。这就是为什么绝大多数房屋卖家决定寻找房地产经纪,来帮助处理所有文书工作、推销房产,并在协商开始时充当中介、监督交易直至交易结束。 此外,该经纪机构还提供委托付款服务,这在此类交易中尤其有用,因为此类交易所涉及的金额通常很大,你将无法完全信任将要与你进行交易的人。然而,在交易成功完成之后,卖方和买方的经纪机构将获得房产卖出价格的7%作为佣金。这对卖方来说是相当大的经济损失。 在这种情况下,智能合约就可以真正派上用场,可以有效地变革整个行业,同时也减少了所需流程。或许最重要的是,智能合约能解决信任问题。智能合约基于"If-Then"("如果-那么")原则,这意味着只有商定的金额被发送到系统时,房屋的所有权才会被转移给买方。 智能合约也可以作为委托付款服务,这意味着资金和所有权都将被存储在系统中,并在同一时间被分发给各参与方。此外,该交易被数百人见证和验证,因此保证了交付是无差错的。由于双方之间不再存在信任问题,因此也不再需要中介。所有房地产经纪能做的都可以预先编程为智能合约,这同时也为卖方和买方节省了大量资金。 这只是智能合约潜在用途的一个例子。智能合约能够帮助货币、财产和其他任何有价值的东西的交易,确保交易过程完全透明,其不但无需中介服务及其附带费用,还消除了双方之间的信任问题。特定智能合约的代码包括了各方商定的所有条款和条件,有关交易本身的信息则被记录在区块链中,即去中心化的分布式公共账本。 智能合约是如何运作的? 简而言之,智能合约很像自动售货机。你只需将所需数量的加密货币放入智能合约中,而你所交易的,房屋所有权等就会自动存入你的账户。所有的规则和处罚不仅在智能合约预先定义了,而且也由智能合约强制执行。 相互依存 智能合约可以独立运行,但也可以与任何其他智能合约一起运行。当它们彼此依赖时,它们可以以某种方式被设置。例如,成功完成一个特定的智能合约可以触发另一个智能合约的启动,依此类推。从理论上讲,整个系统和组织完全可以依靠智能合约运行。某种程度上,这已经在各种加密货币系统中实现了,在这些系统中,所有的规则都是预先定义好的,因此,网络本身可以独立自主地运行。 智能合约的对象 从本质上讲,每个智能合约都有三个不可或缺的部分(也称为对象)。第一个对象是签署方(两方或多方使用智能合约,同意或不同意使用数字签名的协议条款)。 第二个对象是合约的主题。它只能是智能合约环境中存在的对象。或者,智能合约必须可以不受阻碍地直接访问该对象。尽管智能合约早在1996年就被讨论过,但正是这一特定对象阻碍了智能合约的发展。这个问题直到2009年出现第一个加密货币后才得到部分解决。 最后,任何智能合约都必须包含特定条款。这些条款都需要使用数学方法及适用于特定智能合约环境的编程语言进行完整描述。这些条款包括了所有参与方的预期要求以及与所述条款相关的所有规则、奖励与惩罚。 环境 为了使智能合约能够正常运行,智能合约必须在特定的合适环境中运行。首先,智能合约环境需要支持公钥加密,这使得用户能够使用其独特的、专门生成的加密代码来签署交易。这正是绝大多数现有加密货币所用的系统。 其次,它们需要一个开源和去中心化的数据库,合同各方都可以彼此完全信任,并且履约流程完全自动化。此外,为了实现智能合约,整个环境必须自身是去中心化的。区块链,尤其是以太坊区块链,是运行智能合约的理想环境。 最后,智能合约所使用的数据,来源必须完全可靠。这就需要使用根SSL安全证书、HTTPS和其他已经广泛被使用并在大多数现代软件上自动实现的安全连接协议。 智能合约带来了什么? 自治 智能合约消除了对第三方中介的需求,基本上使你能够完全控制合约。 信任 任何人都无法窃取或弄丢你的文件,因为它们已被加密并安全地存储在一个安全的公开账本中。此外,你不必信任你正与之交易的人,也不必指望他们会信任你,因为公正的智能合约系统基本上解决了信任问题。 节约 由于使用了智能合约,你就不需要公证人、房地产经纪人、顾问及其他众多中介机构的援助。这样也就与他们的服务相关的高额费用无关了。 安全 如果智能合约正确执行,它将是极难破解的。此外,智能合约的完美环境受到复杂的加密保护,它可确保你文档的安全。 高效 通过使用智能合约,你将节省通常浪费在手动处理大量纸质文档并将其发送或运送到特定地点等的大量时间。 谁发明了智能合约?谁在使用智能合约? 1996年,计算机科学家和密码学家Nick Szabo首次提出了智能合约。几年后,Szabo重新定义了这一概念并发布了几篇相关文章,他阐述了通过在互联网上陌生人之间设计的电子商务协议来建立合同法相关商业实践的概念。 然而,智能合约的概念直到2009年才被实现,当时第一个加密货币比特币连同它的区块链一齐出现,后者则最终为智能合约提供了合适的环境。有趣的是,Nick Szabo在1998年设计了一种称为比特黄金(Bit Gold)的去中心化数字货币。虽然它没有被实现,但它已经具备了10年后比特币可吹嘘的许多功能。 如今,智能合约主要与加密货币有关。而且,可以公平地说,它们彼此互相依赖,因为去中心化的加密货币协议本质上是具有去中心化安全性的加密智能合约。智能合约现在被广泛应用于大多数加密货币网络中,并且其也是以太坊最杰出和最被大肆宣传的特点之一。 你知道什么是智能合约吗?币圈聚贤庄来跟你分析一下! 智能合约用例 虽然世界各国政府、金融监管机构和银行对加密货币的立场从极其谨慎变成谨慎接受,但加密货币背后的技术,区块链和智能合约,已被广泛认为是具有革命性的,并且正在各个层面实现这些技术。 例如,美国信托与清算公司(DTCC)和四大银行(美银美林、花旗、瑞士信贷和摩根大通)成功地使用Axoni开发的智能合约交易区块链信用违约掉期。智能合约使用了诸如个人交易详情及相应风险指标之类的信息,据一篇新闻稿称,这提高了合作伙伴和监管机构信息处理上的透明度。 类似的事情到处都在发生。由61家日本银行和韩国银行组成的财团一直在测试Ripple的区块链和智能合约,以实现两国之间的跨境资金转移。这一新系统将于今年推出。就连俄罗斯政府控制的俄罗斯联邦储蓄银行(Sberbank),都在俄罗斯这样一个众所周知的反加密货币国家测试以太坊区块链及其智能合约。 测试结果是俄罗斯联邦储蓄银行加入了以太坊企业联盟(EEA),这是一个由100多家企业组成的联盟,其中包括了思科、英国石油、荷兰国际集团(ING)、微软等顶级企业。该联盟旨在开发一种面向商业用途的区块链,用它可以开发和实现这些公司所需的智能合约。 由于智能合约是与加密货币相关联的,因此它们仍主要被应用到金融领域和银行业。尽管如此,世界各国政府都可以使用这项技术,使得投票系统更加便利而透明。供应链可以使用它来监控货物并自动执行所涉及的所有任务和支付。房地产、医疗保健、税收、保险及其他众多行业都可以受益于智能合约的使用。 智能合约的缺点 智能合约仍是一项未成熟的技术,仍然容易出现问题。例如,构成合约的代码必须是完美无漏洞的。它也会出现错误,有时候,这些错误会被欺诈者所利用。就像DAO被黑事件一样,把资金存放在代码有漏洞的智能合约中资金就可能被盗走。 此外,这项新奇的技术也带来了很多问题。政府将如何决定监管此类合约?他们将如何进行征税?如果合约无法访问其主题,或者发生了任何意外情况,将会是什么情况?这是在传统合约签订时可能发生的,传统合同可以在法庭上被撤销,但区块链要求智能合约无论如何都要按照"代码即法律"的规则去执行。 然而,大多数这些问题的存在纯粹是因为智能合约仍未是一项成熟的技术。但这项技术肯定会随着时间的推移而逐渐完善。毫无疑问,智能合约将会成为我们社会不可或缺的一部分。

问问小秘 2019-12-02 03:07:11 0 浏览量 回答数 0

问题

【教程免费下载】实用软件架构:从系统环境到软件部署

玄学酱 2019-12-01 22:07:44 1207 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站