作为开发人员,无论我们的专业是什么,无论是数据科学、前端还是后端,我们都会花费超过75的时间阅读他人编写的代码。该任务可能是一项艰巨的任务。 话虽如此,有效阅读他人代码的能力是可以使软件工程工作变得更加愉快的技能之一。不幸的是,这也是一项被学校、训练营和公司广泛忽视的技能。这是每个人都认为您知道或擅长的技能之一,只是因为您知道如何编写代码。 关于编写代码的事情是,每个人都有自己的编码风格。阅读代码不同于阅读小说或故事;这不仅仅是阅读屏幕上的说明。相反,当您阅读别人编写的代码时,您不仅仅是在阅读他们的代码。您正在尝试了解他们的思维过程以及他们在编写该代码时的想法。 不用说,这是一项极具挑战性的任务。但是,这项任务可以成倍地简化。在本文中,我将带您完成阅读和理解他人代码的4个步骤。 为了解释不同的步骤,我将通过我为网络抓取教程编写的代码。 Importneededlibrariesfrombs4importBeautifulSoupasbsimportrequestsasrqimportpygalimporttimeimportpygalfromIPython。displayimportdisplay,HTMLbasehtml!DOCTYPEhtmlhtmlheadheadbodyfigure{renderedchart}figurebodyhtmldefinefunctionsfordatacollectiondeffindbookname(table):iftable。find(caption):nametable。find(caption)returnname。textdefgetauthor(table):authornametable。find(textAuthor)。next。textreturnauthornamedefgetgenre(table):iftable。find(textGenre):genretable。find(textGenre)。next。textelse:genretable。find(textSubject)。next。next。next。textreturngenredefgetpublishingdate(table):iftable。find(textPublicationdate):datetable。find(textPublicationdate)。next。textelse:datetable。find(textPublished)。next。textpatternre。compile(rd{4})yearre。findall(pattern,date)〔0〕returnint(year)defgetpagescount(table):pagestable。find(textPages)。next。textreturnint(pages)defparsewikipage(url):pagerq。get(url)。textreturnbs(page)defgetbookinforobust(bookurl):Toavoidbreakingthecodetry:booksoupparsewikipage(bookurl)booktablebooksoup。find(table,classinfoboxvcard)except:print(fCannotparsetable:{bookurl})returnNonebookinfo{}getinfowithcustomfunctionsvalues〔Author,BookName,Genre,PublicationYear,PageCount〕functions〔getauthor,findbookname,getgenre,getpublishingdate,getpagescount〕forval,funcinzip(values,functions):try:bookinfo〔val〕func(booktable)except:bookinfo〔val〕NonereturnbookinfoGetbooksurlhttps:en。wikipedia。orgwikiTime27sListofthe100BestNovelspagerq。get(url)。textsoupbs(page)rowssoup。find(table,classwikitablesortable)。findall(tr)〔1:〕bookslinks〔row。find(a)〔href〕forrowinrows〕baseurlhttps:en。wikipedia。orgbooksurls〔baseurllinkforlinkinbookslinks〕tostorebooksinfobookinfolist〔〕loopfirstbooksforlinkinbooksurls:getbookinfobookinfogetbookinforobust(link)ifeverythingiscorrectandnoerroroccursifbookinfo:bookinfolist。append(bookinfo)puaseasecondbetweeneachbooktime。sleep(1)Collectdifferentgenresgenres{}forbookinbookinfolist:bookgenbook〔Genre〕ifbookgen:iffictioninbookgenorFictioninbookgen:bookgenfictionifbookgennotingenres:countbooksineachgenregenres〔bookgen〕1else:genres〔bookgen〕1print(genres)Plotresultsbarchartpygal。Bar(height400)〔barchart。add(k,v)fork,vingenres。items()〕display(HTML(basehtml。format(renderedchartbarchart。render(isunicodeTrue))))第1步:运行代码并查看其作用 每当您获得需要阅读和理解的代码时,要做的第一件事也是最明显的,我可能会争辩说就是运行代码并查看它的作用。它需要什么作为输入?输出是什么? 那么,让我们继续运行上面的代码并探索结果。 并非所有代码都会生成图表;一些代码的输出将是文本输出。无论输出类型如何,我们都可以探索它来猜测(如果您还不知道)编写代码的大致目的。 但是,这可能不会为您提供有关代码细节的很多细节,或者如果此代码是更大项目的一部分,您可能不知道它是如何连接的,但您将学习如何构建和运行它。此外,您还将了解它使用的库和它所依赖的框架。 尽管如此,运行代码将为您提供更好地理解它所需的信息,并确保您获得每个依赖项,您需要开始工作并扩展它。步骤2:找到主要功能或起点 现在我们知道了代码的作用和输出是什么,我们可以开始更深入地研究它的细节。为此,我们需要精确定位代码的开头。如果您使用的编程语言具有必须的main功能,如C、C或Java,请从那里开始,逐步了解其他功能。 但是,如果您使用的是Python,则并非所有代码都有函数main,但您可以使用缩进来了解代码的起始位置。比如上面的代码,我们有多个函数,那么代码的起点就在第80行。 因此,我们可以首先开始查看注释(如果有的话)并查看代码的整个主要部分,而无需深入了解子函数的细节。 遍历该main函数可为您提供代码的一般流程,每个子函数的作用,而不是它们的工作方式,而是它们的作用。步骤3:在调试模式下运行代码 仔细阅读代码的主要部分后,您可能会发现在调试模式下运行代码很有用。这样做的原因是,当您在调试器中运行代码时,它允许您观察您的代码如何与内存交互。 它将向您展示每个变量如何随着代码中的每一步而变化。这样做将使您对代码的内部功能及其不同功能有更深入的了解。 一旦您看到代码中的每个变量如何随每一行变化,您就可以开始在代码中添加自己的注释,向自己解释每一行代码的作用。步骤4:构建代码不同部分之间联系的思维导图 我发现有很大帮助的一件事是在调试器模式下运行时构建代码连接的思维导图。调试器模式向您展示了不同代码项之间的清晰联系。 从思维导图中间的代码文件的名称开始,然后分支出不同的功能以及它们的连接方式。尝试将代码中的变量也鼓励到思维导图中,也许不是所有变量,而是对整体结果影响最大的变量。 此外,尝试包括代码的输入和输出以及它们的类型或预期类型。这是上面代码的思维导图。 每当您与此代码库交互时,构建思维导图将为您节省大量时间。如果您想添加或删除代码的任何部分,它将帮助您了解连接。带走 阅读其他开发人员编写的代码可能是一项极具挑战性的任务;你需要了解他们的逻辑,他们的风格,以及他们的具体选择。看了那么多不同层次、不同年龄的程序员写的代码。经历过这些之后,我提出了自己的4步流程来简化阅读、探索和理解基本上不是我的人编写的代码。 这4步过程很简单,将为您节省大量时间和精力;您需要做的就是:运行代码并浏览结果。找到主要功能或代码的起点。在调试器下运行代码并充分理解代码的机制。构建不同代码元素之间连接的思维导图,并在您与代码交互时随时使用它。 我希望您发现这些步骤对您在下一次代码探索冒险中节省大量时间和精力很有用。事实上,阅读与写作所花费的时间之比远远超过10比1。我们不断阅读旧代码,以此作为编写新代码的一部分。。。。。。。〔因此〕使其易于阅读使得编写起来更容易。 罗伯特C马丁