21

Stacker 没有人询问新程序员进入该领域时发现的最令人震惊的事情

排在首位的是继承一个必须迅速熟悉的代码库的影响。突然发现自己负责维护 N 行代码,这些代码已经被拼凑了多久,并且有很短的时间开始为它做出贡献,这可能会非常令人震惊。

您如何有效地吸收所有这些新数据?是什么缓解了这种转变?已经为足够多的开源项目做出贡献的唯一真正的解决方案是冲击消退吗?

这也适用于资深程序员。您使用什么技术来简化向新代码库的过渡?

我为此添加了 Community-Building 标签,因为我还想听听一些关于这些过渡的战争故事。随意分享您如何处理特别紧张的学习曲线。

4

13 回答 13

14

铅笔和笔记本(不要分心试图创建一个未经请求的解决方案)

  • 边走边做笔记,每周一花一个小时通读并整理前几周的笔记

  • 对于大型代码库,第一印象可能具有欺骗性,并且当您熟悉自己时,问题往往会迅速重新排列。

  • 请记住,您上一个工作环境中的问题在您的新环境中不一定有效或密切相关。谨防先入为主的观念。

  • 您所做的笔记/观察将帮助您快速了解要问什么问题以及问谁。希望您一直在收集所有官方(和非官方)利益相关者的姓名。

于 2008-10-18T05:38:30.200 回答
13

熟悉继承代码的最好方法之一就是亲自动手。从修复一些简单的错误开始,然后逐步解决更复杂的错误。与尝试系统地审查代码相比,这会让您更好地熟悉代码。

如果有需求或功能规范文档(希望是最新的),您必须阅读它。

如果有高级或详细的设计文档(希望是最新的),您可能应该阅读它。

另一个好方法是与熟悉代码的人安排一次“信息传递”会议,在那里他们提供高级设计的演示文稿,并对代码的重要/棘手部分进行演练。

于 2008-10-18T05:26:23.033 回答
11

编写单元测试。您会更快地发现缺陷,并且在需要更改代码时更加自信。

于 2008-10-18T05:09:14.767 回答
4

Try to understand the business logic behind the code. Once you know why the code was written in the first place and what it is supposed to do, you can start reading through it, or as someone said, prolly fixing a few bugs here and there

于 2008-10-18T08:53:55.000 回答
3

我的步骤是:

1.) 在代码库中设置包含所有源代码、头文件的源代码洞察(或您使用的任何好的源代码浏览器)工作区/项目。从最高功能(主要)到最低功能在更高级别浏览。在此代码浏览期间,请继续在纸/或 word 文档上做笔记,以跟踪函数调用的流程。在这一步中不要进入函数实现细节,保留它以供以后的迭代。在这一步中,跟踪传递给函数的参数、返回值、传递给函数的参数如何初始化、如何修改这些参数集的值、如何使用返回值?

2.)在步骤 1.)的一次迭代之后,您在代码库中使用了一定级别的代码和数据结构,设置 MSVC(或根据代码库的编程语言的任何其他相关编译器项目),编译代码,使用有效的测试用例执行,然后从 main 再次单步执行代码,直到函数的最后一级。在函数调用之间,不断移动传递、返回的变量值、采用的各种代码路径、避免的各种代码路径等。

3.) 不断重复 1.) 和 2.) 直到您觉得可以更改一些代码/添加一些代码/在现有代码中查找错误/修复错误为止!

-广告

于 2008-10-18T07:07:26.790 回答
2

我不知道这是“最好的方法”,但我最近的工作是编写一个代码蜘蛛/解析器(在 Ruby 中),它通过并构建了一个调用树(和一个反向调用树),它我可以稍后查询。这有点不重要,因为我们有 PHP,它调用 Perl,它调用 SQL 函数/过程。任何其他代码爬取工具都会以类似的方式提供帮助(即 javadoc、rdoc、perldoc、Doxygen等)。

阅读任何单元测试或规范都会很有启发性。

记录事情会有所帮助(对自己或其他队友,当前和未来)。阅读任何现有文档。

当然,不要低估简单地向队友(或你的老板!)提问的力量。早些时候,我经常根据需要询问“我们是否有执行 X 的函数/脚本/foo?”

于 2008-10-18T05:20:27.803 回答
1

浏览核心库并阅读函数声明。如果是 C/C++,这意味着只有标题。记录你不理解的任何东西。

上次我这样做时,我插入的评论之一是“从未使用过此类”。

于 2008-10-18T05:37:08.487 回答
1

请尝试通过修复其中的错误来理解代码。纠正或维护文档。不要修改代码本身的注释,这可能会引入新的错误。

在我们的工作中,一般来说,我们不会无故更改生产代码。这包括外观变化;即使这些也会引入错误。

无论一段代码看起来多么令人作呕,除非您有错误修复或其他更改要做,否则不要试图重写它。如果您在阅读尝试学习的代码时发现错误(或可能的错误),请记录错误以供以后分类,但不要尝试修复它。

于 2008-10-18T06:38:30.657 回答
1

Another Procedure...

After reading Andy Hunt's "Pragmatic Thinking and Learning - Refactor Your Wetware" (which doesn't address this directly), I picked up a few tips that may be worth mentioning:

Observe Behavior:

If there's a UI, all the better. Use the app and get a mental map of relationships (e.g. links, modals, etc). Look at HTTP request if it helps, but don't put too much emphasis on it -- you just want a light, friendly acquaintance with app.

Acknowledge the Folder Structure:

Once again, this is light. Just see what belongs where, and hope that the structure is semantic enough -- you can always get some top-level information from here.

Analyze Call-Stacks, Top-Down:

Go through and list on paper or some other medium, but try not to type it -- this gets different parts of your brain engaged (build it out of Legos if you have to) -- function-calls, Objects, and variables that are closest to top-level first. Look at constants and modules, make sure you don't dive into fine-grained features if you can help it.

MindMap It!:

Maybe the most important step. Create a very rough draft mapping of your current understanding of the code. Make sure you run through the mindmap quickly. This allows an even spread of different parts of your brain to (mostly R-Mode) to have a say in the map.

  1. Create clouds, boxes, etc. Wherever you initially think they should go on the paper. Feel free to denote boxes with syntactic symbols (e.g. 'F'-Function, 'f'-closure, 'C'-Constant, 'V'-Global Var, 'v'-low-level var, etc). Use arrows: Incoming array for arguments, Outgoing for returns, or what comes more naturally to you.
  2. Start drawing connections to denote relationships. Its ok if it looks messy - this is a first draft.
  3. Make a quick rough revision. Its its too hard to read, do another quick organization of it, but don't do more than one revision.

Open the Debugger:

  1. Validate or invalidate any notions you had after the mapping. Track variables, arguments, returns, etc.
  2. Track HTTP requests etc to get an idea of where the data is coming from. Look at the headers themselves but don't dive into the details of the request body.

MindMap Again!:

Now you should have a decent idea of most of the top-level functionality.

  1. Create a new MindMap that has anything you missed in the first one. You can take more time with this one and even add some relatively small details -- but don't be afraid of what previous notions they may conflict with.
  2. Compare this map with your last one and eliminate any question you had before, jot down new questions, and jot down conflicting perspectives.
  3. Revise this map if its too hazy. Revise as much as you want, but keep revisions to a minimum.

Pretend Its Not Code:

If you can put it into mechanical terms, do so. The most important part of this is to come up with a metaphor for the app's behavior and/or smaller parts of the code. Think of ridiculous things, seriously. If it was an animal, a monster, a star, a robot. What kind would it be. If it was in Star Trek, what would they use it for. Think of many things to weigh it against.

Synthesis over Analysis:

Now you want to see not 'what' but 'how'. Any low-level parts that through you for a loop could be taken out and put into a sterile environment (you control its inputs). What sort of outputs are you getting. Is the system more complex than you originally thought? Simpler? Does it need improvements?

Contribute Something, Dude!:

Write a test, fix a bug, comment it, abstract it. You should have enough ability to start making minor contributions and FAILING IS OK :)! Note on any changes you made in commits, chat, email. If you did something dastardly, you guys can catch it before it goes to production -- if something is wrong, its a great way to get a teammate to clear things up for you. Usually listening to a teammate talk will clear a lot up that made your MindMaps clash.

In a nutshell, the most important thing to do is use a top-down fashion of getting as many different parts of your brain engaged as possible. It may even help to close your laptop and face your seat out the window if possible. Studies have shown that enforcing a deadline creates a "Pressure Hangover" for ~2.5 days after the deadline, which is why deadlines are often best to have on a Friday. So, BE RELAXED, THERE'S NO TIMECRUNCH, AND NOW PROVIDE YOURSELF WITH AN ENVIRONMENT THAT'S SAFE TO FAIL IN. Most of this can be fairly rushed through until you get down to details. Make sure that you don't bypass understanding of high-level topics.

Hope this helps you as well :)

于 2014-03-20T21:43:46.483 回答
1

这里所有非常好的答案。只是想添加更多的东西:

人们可以将架构理解与闪存卡结合起来,重新访问这些卡片可以巩固理解。我发现诸如“代码的哪一部分具有 X 功能?”之类的问题,其中 X 在您的代码库中可能是一个有用的功能。

我还喜欢在 emacs 中打开一个缓冲区并开始重写我想熟悉的代码库的某些部分并添加我自己的注释等。

于 2018-11-14T16:20:23.547 回答
0

vi 和 emacs 用户可以做的一件事是使用标签。标签包含在一个文件中(通常称为 TAGS )。您可以通过命令生成一个或多个标签文件( etags 用于 emacs vtags 用于 vi )。然后我们编辑源代码,您会看到一个令人困惑的函数或变量,您加载标签文件,它将带您到声明函数的位置(不够完美)。实际上,我已经编写了一些宏,让您可以使用 Alt 光标导航源代码,有点像许多 UNIX 风格中的 popd 和 pushd。

布巴

于 2008-10-18T07:04:12.803 回答
0

在开始编写代码之前,我做的第一件事是使用应用程序(作为几个不同的用户,如有必要)了解所有功能并查看它们如何连接(信息如何在应用程序内流动)。

之后,我检查了构建应用程序的框架,以便我可以在我刚刚看到的所有界面与一些视图或 UI 代码之间建立直接关系。

然后我查看数据库和任何数据库命令处理层(如果适用),以了解这些信息(用户操作的)是如何存储的,以及它是如何进入和来自应用程序的

最后,在了解了数据的来源和显示方式之后,我查看了业务逻辑层以了解数据是如何转换的。

我相信每个应用程序架构都可以像这样划分,并且在真正调试它或添加新东西之前了解整体功能(你的应用程序中的谁)可能是有益的 - 也就是说,如果你有足够的时间这样做。

是的,与开发当前版本软件的人交谈也很有帮助。但是,如果他/她即将离开公司,请在他/她的愿望清单上记下(他们想为该项目做什么,但由于预算限制而无法做到)。

于 2008-10-18T08:41:41.953 回答
0

为您从代码库中找到的每一件事创建文档。通过实验找出它是如何工作的——在这里和那里改变几行,看看会发生什么。使用 geany,因为它可以加快程序中常用变量和函数的搜索速度,并将其添加到自动完成中。了解您是否可以通过 facebook 或通过谷歌搜索联系代码库的原始开发人员。找出代码的原始目的,看看代码是否仍然符合该目的,或者是否应该从头开始重写,以实现预期目的。

找出代码使用了哪些框架,他们使用了哪些编辑器来生成代码。

推断代码如何工作的最简单方法是实际复制您将如何完成某个部分并重新检查代码是否存在这样的部分。

这是逆向工程——通过尝试重新设计解决方案来解决问题。

大多数计算机程序员都有编码经验,如果代码中存在某些模式,您可以查找这些模式。

有两种类型的代码,面向对象的和面向结构的。

如果你知道如何做这两件事,你很高兴,但如果你不熟悉其中一个,你必须重新学习如何以这种方式编程,以理解为什么它是这样编码的。

在面向对象的代码中,您可以轻松地创建记录每个对象类的行为和方法的图表。

如果它是面向结构的(按功能表示),请创建一个功能列表,记录每个功能的作用以及它在代码中的位置。

我自己没有做过上述任何一项,因为我是一名网络开发人员,从 index.php 开始到其他页面的其余部分,相对容易弄清楚某些东西是如何工作的。

祝你好运。

于 2008-11-04T12:22:43.330 回答