I am taking over someone elses code. What are some good ways to learn what that programmer did as quickly as possible? I have been running it, stepping through it and looking at the callstack. What else can I do?
Sorry I forgot to mention, but there is little documentation and I have been trying to fix simple problems. Thanks!
Set logging to observe in what sequence things are happening.
Read here: Hired as a developer to maintain and update current code base, no docs!
Start writing unit tests, as that will get you using his classes/methods, and you will do two things, learn it, and either find bugs or have tools ready in case bugs appear.
Usually the best way is to start working on the code fixing small bugs. The more true time you spend with it is the only way to learn the code base. There is no magic way to learn a code base. It will take weeks, months or possibly years depending on the complexity. However for most generic business systems a ramp up time is about 6 months of code knowledge and 6 months separate of industry knowledge to truly understand it all.
Fix a simple problem in it.
Edit:
Then fix bigger problems, and start writing documentation and unit tests, of the areas you understand. Build on those areas, and one day you might understand the whole system.
Documentation? Reading the code itself, without running in the debugger?
Other than that, you're doing what I would do.
There's no silver bullet in how can you understand someone else's code quickly. Specially if it's full of hacks and no documentation is avaiable.
You should try to understand the class structure, and execute the normal flow of the software, with a debugger help.
Don't jump too much code sections "oh, I think I know what this section does". No, you don't. You would be surprised of what "innovation" we may find in code.
Logging is good to see what the code does.
If you have a versioning system you could go and see what changes di the programmer do to what pieces of code, browse some history.
I find it useful sometimes to somehow try to understand the programmers code style, this helps me understand how could he think about a problem and solve it.
The first thing I'd do is take a look at the simplest dialog box and its code, mostly to analyze the coding style and look at how the developer prefers to arrange the code.
Once you know the coding style, and roughly where everything will exist in the file (or if things are put in randomly -- even that is helpful to know), it will be easier to go through everything else.
Talk to the users of the other person's code if you can (either end-users or other developers that had to work with his code). That will give you a sense of the quality of the other persons code - was it released with just a few bugs or did it take 6 months of revisions to get it right? Was the developer careful about making a nicely polished application or was it a mess? That should give you some idea of whether you need to just tune-up the code a bit or start replacing large chunks of it.
I like starting to add tests to the methods of the code, if they are not already there. Figuring out how to cover the code gives you a lot of insight into the codepaths, what the expected output should be, etc...
Everything everyone else has said is accurate in learning what the coder has done.
One other way of looking at it though is to learn the program itself. Play with the application in depth like a user would and understand what the program itself does. Once you understand the final system thoroughly it will be a lot easier to work out how and why it was written.
The first place I start is the database.
In my experience, understanding the datamodel is key to giving you context when you go through the code. (this assumes the data model is not a generic key-value generic entity table)
I find that I wont learn the code completely until I start fixing bugs / modifying it. If the original programmer is still there, then discussing the changes before implementing them would help.
It wouldn't hurt to document what you learn about classes, functions, etc. as well, just so the next guy (or another person who gets hired to work on the same stuff).
Also, when I've done this before, I've found it best to use the program quite a bit before trying to understand the code. May sound obvious, but more of what you see will make sense after that. Unit testing, as other people have suggested, may also help in the same way. (Helpful when you feel confident enough to refactor, as well.)
One thing that helps me learn systems faster is writing the documentation myself.
I get a overview
I will see many bugs/bad design decisions. Which makes it easier to order and prio them. (instead of picking a irrelevant bug and solving it, I will fix those that really matters)
I later on have an documentation.
Documentation will make it easier to justify refactoring/rewrite to the suit's
I think knowing what the code does, the problem it was written to solve at an high level is a good start. With that one can then mentally, at an high level too try to envision how such a problem might be solved with the type tool used.
From then, looking through the code will take on some meaning, and it will help in making it possible to follow the thought of the original developer. In addition, you will quickly spot when you are getting lost.
I also believe the code should document itself as my experience most time is a documentation outside of the code most times is out of sync with the code and could be misleading. So a few comments here and there, class headers, method comment should help too.
First time I inherit another person's code, I had migraine after two days, i was a nightmare.
So have fun.
I've spent most of the last year working on code that I inherited from someone else. There was no documentation and a large amount of what the system was meant to do was not written down anywhere, but in the clients head. The key for me has been to ask as many questions as I could and gather information from every source available. I would recommend compiling your own documentation as you go.
Many people might say don't rewrite code, but that may often be the best way if the code is poorly commented or coded (not self documenting). For code that I struggled with it has often been the best solution.
Another helpful thing to have is some kind of standards document before you begin. The standards doc will help you decipher the code or bring code up to spec and make it easier to understand.
Related
This question already has an answer here:
Detect duplicate code in Visual Studio 2010
(1 answer)
Closed 5 years ago.
Is there any tool or way I can check how can I optimize my code? removing redundancy? I am using VS 2010
Thanx
I don't know about removing redundancy, but ReSharper has some nice code analysis features that can help to identify unused code blocks. It can also make suggestions for cleaner code, but it's not always 100% accurate.
Such tools, even if they existed, wouldn't be reliable. The best would be to perform a code review by a good developer or architect.
No tool can replace experience and expertise. There are a number of productivity tools that can help, a popular one being ReSharper for example, but it's not going to fix everything for you. At some point you just have to rely on your abilities and the abilities of your team members. Learning how to code well takes time.
It often helps to step back and look at your code with the mindset of certain design principles. S.O.L.I.D. can be a great place to start. Some other questions you can ask yourself are:
Are your classes and types properly encapsulated?
Is your code test-driven or behavior-driven in any way?
Do your tests define discrete unit of behavior, or are they just tailored to the implementation that's being tested?
To specifically address redundancy, quite simply, do you have copied/pasted code doing the same thing in two places?
A profiler will give you a good idea of where your application spends most of its time. From knowing what to how to optimize, though, requires experience as well as knowledge of both the code base in general and the problem domain.
What you want is Code Coverage tools. These keep a record of which lines of code are executing. In order for this to be effective, a complete test suite, or manual test run, is required. This will show up the lines of code that are never used, and will help you make decisions.
Static analysis can also help you with code paths and give you information about how and where your code is called.
A couple of good question sabout code coverage:
What can I use for good quality Code Coverage for C#/.NET?
C# Code Coverage metrics
Also look at Microsoft's FxCop for static analysis:
http://msdn.microsoft.com/en-us/library/bb429476(VS.80).aspx
There is http://clonedetectivevs.codeplex.com/ which is a VS plugin. It uses http://conqat.cs.tum.edu/ under the hood. I've not really used it but does what you asked. Couple that with code reviews and might help.
There is a (commercial, 249€) solution checking for duplicate code, even in large projects.
http://www.solidsourceit.com/products/SolidSDD-code-duplication-cloning-analysis.html
For that purpose we use the build-in Duplicated Finder in our TeamCity build server.
I client of mines do not care about elegant and well structured code. I am writing the applications from scratch with minimal 3rd party tools. I am using l2s, Recatcha, tinymce, lucene, and structure map.
I would like to quickly get the clients product to the market as fast as possible while sacrificing elegant code. Are there any tools out there that will enable me to rush the product to the market?
No client ever cares about elegant and well structured code. That's not why you write elegant and well structured code. You write it because it's shorter, simpler, it's faster to write, contains fewer bugs and it is easier to find those bugs.
ADD: I know what I wrote above sounds contradictory. When I started working, I didn't believe that either. I had to learn the hard way. So to make the point clearer: This is what typically happens when you don't try to write elegant, well structured code:
You'll introduce subtle bugs that lead to weird, unreproducible behavior and take 10 times more time to find than writing the code in the first place
You'll solve the same problem multiple times. Or, the other way round: The elegant solution would have solved a set of problems while the ugly solution will only solve one problem. Or part of one problem.
You'll repeat yourself a lot. That means more code to write, more code to maintain, more bugs.
You'll write code that you don't understand a week later. So instead of adding new features/solving bugs you'll waste your time trying to figure out why some piece of code works (or doesn't work)
You'll solve the wrong problems. This is by far the worst danger, and it happens too often if you try to save the time you need to plan the thing properly.
Good code is for you and not your client.
I don't think there exists such a magic pill.
But I would rather recommend you checkout Joel's 12 Steps to Better Code. Not all principles may apply to you (if you are not working with at least a certain number of people) but things like version control, how you deal with bugs, testing and others will help more than what you think.
Assuming that adding more team members is not an option, you can either:
work longer hours (live of coffee and pizza until either you or the project is finished)
defer some features for version 2.
sacrifice quality.
deliver late.
the choice is yours but option 2 would be my recommendation. A program with fewer features that works is better than a feature laden product that can't be relied on.
Bit of a cliché, but there are no tools that can get you the result you're looking for, only people. For that matter, there are no tools that can guarantee you robust, reliable, well-designed and appealing products that people will actually want to use – those are all problems that can only be tackled by meatware. Respectfully, I'd be careful about the whole concept of "rushing a product to market", if I were you: I'm sure you have your reasons for taking that approach, but more haste really does often make for less speed, and less desirable results.
When you don't have time to build a product to reasonable standards then it's important to know which parts you can cut corners on and which you can't.
The most important thing to get right is the interfaces between components. Make sure that they are correct and that coupling between components is as little as you can make it.
If for example you have a report generator that sometimes crashes, occasionally generates the wrong results, and has missing and broken features you can repair it later on when you do have time, or even scrap the whole module and do it properly.
If you've hacked the interface though, and it relies on other components storing their data in certain ways, or relies on the internal workings of other modules it becomes significantly harder to rip it out and replace it cleanly.
Don't skimp on the design of the high level modules and the interfaces between them. Keep asking yourself if I have to rip out this module and do it a different way, will it affect any of my other modules... The answer should as much as possible be know. it's "easy" to go and fix code, but not if it's all one big tangled mess. The small compoents don't need to be good as long as you can replace them easily later.
Obligatory comment - I'm not suggesting anyone writes bad code of course. Just that sometimes there are essential business requirements that make deadlines such that you can't do a good job of everything, and it is an important skill to know which things you can fix up later and which you can't.
So anyway to answer your question design tools such as UML drawing tools etc are probably more use than coding tools
Mostly you end up with this:
(source: scottsimmons.tv)
Another one that I heard a project manager once say about adding extra people to a team:
"It's not because you have 9 women that the time to grow a baby will only take one month."
I would recommend using a continuous integration tool such as CruiseControl.NET or hudson and writing many JUnit tests (or the C# equivalent).
This way even if you develop quickly and don't spend enough time working out all the pieces, the CI server should prevent you from producing bugs which will take you an extremely long time to find.
That said, I agree with what the others stated, you write elegant code so you (or your teammates) will understand it and not so your client is satisfied.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I've just inherited a large project previously coded by about 4-5 people. The documentation consists of comments, and is not very well written. I have to get up to date on this project. How do I start? It consists of many different source files. Do you just dig in? Are there tools that can help visualize the structure/flow?
If you have a chance, I'd try and talk to the original designers and developers. Ask them about any major design issues or shortcomings of the project. Is the project in good shape and only needs maintenance or are there major components that need to be added or reworked? What are going to be the biggest roadblocks to maintaining the project? Take one or two of them to lunch (separately) if you have a budget for it as they might be more free to talk about problems outside of the office.
Talking to the users is also important for getting a feel for the current status of the project. Quite often they have a different opinion of how things stand then the developers do. Make sure, however, that they don't start giving you a list of all the things they want added or changed - you should take a few weeks to understand the project before you can start making major changes to it.
As for visualization tools, I'd start with the database design if there is a database involved. Tools like Microsoft Visio can create a diagram from an existing database. I find knowing the design of the database helps me wrap my head around what the programmers were trying to accomplish. Visio is also good for documenting program flow with some basic flowcharts though you'll have to create them yourself - it doesn't generate them automatically as far as I know.
Good luck.
I would encourage you to buy and read this book thoroughly. It provides you a LOT of information in this regard, much more than you will find here.
Brainstorming a little for you:
Step around in the application with a debugger, use a Static Code Analysis tool for which ever language you are working with...
Talk with people - both developers AND USERS to get a feel of the application.
Review the issue tracking system to see if you can see any recurring types of problem...
Are there tools that can help
visualize the structure/flow?
The latest Visual Studio 2010 allows you to generate architecture diagrams.
http://ajdotnet.wordpress.com/2009/03/29/visual-studio-2010-architecture-edition/
Try to find the starting point of the system and start digging from there. It sort of sucks to be in that situation, and chances are the comments might not be that helpful either. If the original developers didn't bother (or didn't have the chance) to document, chances are they never kept the comments up to date with code changes.
So time to bring the shovel... but don't just dig in blindly. One thing that is important is to understand what the system does from a users' perspective.
Concurrent with your code digging, you need to meet with a user (or the users' liason) and have him walk through the system, showing you how it is supposed to be used, for what purpose and what it and its subsystems are supposed to do. Moreover, attempt to understand what are the business pre-conditions and post-conditions of each major operation performed with this system.
Then map (or do a hierarchical) chart of the main functions of the system; classify them by category, purpose or module. If the system performs some sort of work flows or business transactions, attempt to chart some sort of state/transition diagram documenting each (and cross-referencing each state/transition to the subsystem or module in the system that is in charge for it.)
Once you have that, you can dig according to function. It will be best if you dig for a specific purpose, say, there is a bug fix to implement. You locate the logical module or category pertaining to that bug fix, you have the pre-conditions and post-conditions; then you can dig precisely on (or around) that bug fix.
If you just dig in without a guide (at least a high level one), you can be digging for months without getting anywhere (I'm telling you from painful experience.)
If there is no user manual, implement a draft according to your meetings with the users/users' liason. That could serve as a guide for implementing a developer's/administrator's manual for the system you just inherited (if there is ever a chance to implement one.)
If code is not on source control, put it on it. Doesn't matter what SCS you pick (could even be CVS, yuck!) What matters is to put it under source control asap.
Those developers didn't exist in a vacuum, they must have had exchanged emails. Identify other tech liasons they work with. Attempt to identify what other systems, if any, this system interfaces to (.ie. your databases, other's peoples databases, cron jobs, etc.)
But this could come at a later time. I think you should, for starters, focus on understanding how to use the system and what it is for. Let's call it understanding its business/knowledge architecture. Then dig according to that... or better yet, according to that and with the purpose of fixing a bug.
Good luck.
Use Profiler to see main functions and events in your project (the fastest way to learn framework)
Learn business logic very well to better understand the code
Documenting every new thing you learn - setup wiki (you will be surprised how quickly things are forgotten)
You can use Visio to draw Database Model Diagrams. (keep them close to you while studying the code)
These are the things that helped me when I inherited the previous project (50+ developers, 70+ GB database, 1 GB of source code and not even a single line of comments in code (maybe few :), and everything written in foreign language )
Use the debugger to walk through the application. That will let you go both deep and wide. You'll also be able to learn about how the code handles specific scenarios.
When you're ready to change something as #Jaxidian said, Working Effectively with Legacy Code is a great resource.
I was recently in a similar situation. What helped in my case was focusing on the changes I needed to perform on the project, and in the process of making those changes I learned about how the project is structured and so on. Sure, the first few tasks took a bit longer, but look on the bright side: I got stuff done and I got familiar with the project at the same time.
I'd suggest two things that may help:
Be productivity-driven. In other words, find a change that needs doing and use this to learn how that bit of the system works. Your changes may not be the most elegant without a whole-picture understanding of the software, but you will get work done within days/weeks.
Follow things from the user-interface. I.e if a change involves things a user does on a dialog, find that dialog in the code (relatively easy) and then work backwards to see what bits of the code provide data to the dialog, how the dialog interacts with the system, etc. Trying to find "where does X happen in the code" is very hard without good documentation, but finding "where is the code relating to this dialog" is quite easy and gives you an entry-point into the code.
Whenever I start a new project, I spend 2-3 days skim reading the code and making notes. I basically go through the entire solution from top to bottom and make a map in a text editor of each (significant) class in each project and what it appears to do.
The aim in doing this is not to completely understand the entire codebase, so don't worry if you feel you are not getting your head around it completely. The aim is that you end up with an index of where to go when you need to start on your first piece of work. You should also end up with a cursory picture of the solution in the back of your brain that will get filled in over the next couple of months. I always do this on the first few days as your superiors will not expect you to be productive during this time and you may never get another opportunity where you have the time to do so.
Also, do not rely on code comments for direction. Even with the best intentions they are often unmaintained and may lead to incorrect conclusions about what a class or section of code may do: a comment may lie but the code always tells the truth.
If you already have a team, you could charge each with a part of framework, and the result of their exploration should be registered somewhere, like a wiki. After that, give to each a task similar to something which is already done in the system (from the functional point of view)
For example: if a list of products is displayed in your app, you could display a list of orders (the complexity should be approximately the same), in the same manner it's done actually in the app. Than make it more interesting: try to edit it and save into DB.
Than switch the tasks and let the questions appear and than the first person who made the same task will show & explain how things are done.
Like that you'll see how the things are done pretty easy + your team will be up to date with this knowledge.
Presuming there is a database, start with the data model. Somewhere (Mythical Man-Month?) it was written "if I have your tables, I don't need to see your code."
Regarding potential tools, you may want to look into NDepend. It is a code-analysis tool, with an emphasis on highlighting the internal organization and dependencies of the code base (see this post for typical outputs), and spotting code quality issues. I have not used it personally, but Patrick Smacchia, one of the developers of the product, has a few posts where he applies NDepend to some classic apps (here is NUnit for instance) and discusses what it means, and I found them interesting.
Go and speak to the users or, read the manual and / or if one exists, go on a training course for the system (internal training departments will sometimes have put them together if there are lots of users).
If you don't know what it's meant to be doing then the chances of you being able to work out how it does it are close to zero.
Consider any C# program for example, How will you start explaing that program... Friends of mine are really struggling to explain a program to their team members...
what is the best way to explain a c# program?
What is the major mistake done by developers while explaining a program to their Team leader?
If you are a team leader, what will you look for in that explanation from your team memeber?
Any tips for your team member about explaining a program?
When I interview developers for positions on my team I often pick a random project off their resume and ask "I see you worked on project Fizzbin in 2006. My mother is a retired nurse who nows runs a bed and breakfast. Suppose you were staying at her B&B and she asked you what project Fizzbin was about."
I'll then often ask them to give me the "elevator pitch" -- you find yourself alone in an elevator for 60 seconds with your CEO, who says "so, tell me about project Fizzbin" and you wish to convince them to continue your funding.
And then I'll ask questions that dive into the technical aspects.
What I'm getting at here is that I like to see candidates who can talk about the purpose of the code in terms ordinary people can understand, who understand the business reasons that the code is being produced, and who have deep technical knowledge and can communicate that.
No kidding, I have had candidates "tell my mother" something like "well, with project Fizzbin we took advantage of the homoiconicity of Lisp to build a layer that could apply maps or reductions in query objects to a geographically distributed data set across a multi-tiered blah blah blah blah blah blah blah", completely inappropriate for a conversation over breakfast with my mother.
Many candiates are completely unable to tailor their communication style to the audience appropriately. The best way to explain a program is to know what aspects of the program the person you're explaining it to is interested in, and concentrate on those, while leaving out extraneous details that they're not interested in.
I think these questions apply for any programming project in any language, not just C#.
1. What is the best way to explain a C# program?
With any program, I would give an overview of what the program DOES, in at most a few sentences. I would also explain every input and output of the program (gets input from a commmand line and outputs to a file, or gets input from a web page and outputs to other pages and the database). Then I would give an overview of the various components of the program -- UML diagrams help with this. From that point, I'd have the developers start looking at the code, and have them seek further clarification if necessary.
2. What is the major mistake done by developers while explaining a program to their Team leader?
Not being completely honest about the problems they're running into, or giving a real estimate on how long they think it'll take them to finish.
3. If you are a team leader, what will you look for in that explanation from your team memeber?
I'd want to know exactly what they're currently working on, if they're running into any problems, if there's any way that I can help them, and how long they estimate it'll take to finish what they're working on.
4. Any tips for your team member about explaining a program?
Give them the overview and any/all documentation, diagrams, etc., in a document or email. I find it very helpful if I've got a copy that I can read and reread as necessary, and refer to when discussing problems with the team lead.
This is a trick question. You should never start writing a program without at least a minimum functional specification. You don't have to explain how the program works, it merely does what it is described to do in the spec. Writing a spec after you wrote the program is the wrong way around and leads to the kind of problems you are quoting.
I might be oversimplifying this, but this is how I would describe a program (in terms of your dot points)
Explain it's function. What does it do? What problem does it solve? How will this improve you working life? Being able to express it's usefulness will go a long way.
I don't have any first hand knowledge, but my suspicion is that developers promise to solve EVERYTHING with this program.
If I was a team leader, I would want to know what it is that going to be fixed, or improved or why I should invest money and time in this program.
Be succinct. If you can't explain the nature and benefit of your program easily and succinctly, then I wonder about the dedication (not quite the right word) behind the program.
Anyway, that's my thoughts on it. I suspect someone with more specific knowledge or examples can provide some other ideas.
A couple of things I found most useful - more than all the documentation, UML diagrams combined is a (non-functional) prototype app that "demos" functionality. I found one can crank something out, for even the most complex application, in a matter of a few hours.
Alternately, you might want to create a set of wireframe diagrams.
In the team you described there's obviously a fundamental disconnect that needs to be discovered because your initial questions create more questions such as:
Why do fellow team members not understand programming concepts? Why is all the explanation needed as if nobody knows anything about programming? Why is it apparently so hard?
Are they trying to explain just C# or .NET? Do they know what they're trying to explain?
There's something deeply wrong with the scenario you describe.
Can you provide more detail, maybe starting with some background. Change the names and places if need be. We might end up recommending a motivational coach for the perfect solution, or a book about how to get out of the mire of company politics.
While, imho, the original question (and even the sub-questions) are so broad they could be interpreted one-thousand-and-one different ways (a "Scherezade" question(s), if you will) ...
What jumps out at me, reading the question, and all comments/answers to date is : not one mention of comments in the source code.
If you are really describing a "real world" application development scenario with some complexity (it is not possible for any one team member, or even the project manager(s), to fully understand all the code), then :
imho any team member who does not internally document his or her code with appropriate comments that ... at the very least ... explain their own strategies, and implementations, to themselves in a way that would easily let them explain their choices to other team members ... and also renders the code maintainable in the future ... is worthy of a career change to a position like "marketing manager," or "coffee gofer" :)
So, I would interpret the scenario which, to me, is implied in your questions, as reflecting a dysfunctional programming team, and dysfunctional team management. Something requiring : not a "band-aid," or a course in interpersonal communication, but a "cure" based on changing the "culture" of the group, and its work practices.
recently I was given the task to discover a C# solution I have never seen before, and give suggestions on refactoring it. I think I will use NDepend (for the first time ever) to see the overall picture, and also to check a lot of code metrics to figure out what could be refactored. NDepend is pretty good at showing the structure of a project, I think.
My question is a more general one: what do you think is the best way to discover code that you are seeing the first time, and need to understand it's structure?
(Unfortunately there is no logical design documentation and the code is poorly commented.)
Code Discovery is much more easy with NDepend. This tool provides a top-down approach on dependencies and layering between assemblies, namespaces and classes. This is done with some graph and depednencies matrix generated from the code.
You'll also get dependencies on tier code assemblies, which is really useful to know which part of the code does what.
Also, some graphical representation of volume metrics such as # lines of code helps a lot to get a clear idea of where the effort where done on the code.
I frequently use Reflector to study third-party assemblies as well as .NET assemblies. Not so much for a bird's-eye view of the relations between classes, but a more for close-up detail of exactly what is going on.