views:

909

answers:

18

I just started a new job and apparently I'm going to take over the entire company code base. When I took the job I didn't know that I would be working with the code alone and I was expecting a little longer time to familiarize myself with the code.

Well, I've had a few weeks now where I've had the chance to review the code and everything seems legit. The solution files seems to be well organized and the source code appears to be structured and reasonably commented.

The problem is though, I cannot wrap my head around it. It might be because I've been buried so deep in my old system at my old job where we always were 3-4 MAJOR versions behind on everything;

The projects at my new job seems to me to be reasonably modern, using modern patterns and best practices, like unity framework (inversion of control), hibernation, MVVM, wpf, wcf, lambda expressions, etc etc -- and I just struggle understanding what is going on.

I've always been used to being able to step through the code and follow the functionality top down, or reading it bottom up - But I'm just not able to do this here, now, and I fear for when I'm going to be alone with this code.

At the moment I am on probation and I'm wondering, what would your advice to me be?

I've been wondering if it is unreasonable of me to think that despite the code using best practices etc and looks well organised, that it could be too cleverly implemented and only readable for the ones having worked on it for years, or since startup?

Thanks!

+32  A: 

Take a deep breath, pour yourself a cup of coffee (or whatever your favourite worktime drink might be) and remind yourself that you were hired because your new employers think you can do the job. You applied for the job because you think you can do it too. You can't both be wrong :-)

Now, find a small class definition within the codebase. Read it and understand it. Repeat this until you have run out of small classes. Now start looking at the larger classes. Repeat. The picture will start to emerge, you will start to understand the code.

It's like eating an elephant: you have to do it a mouthful at a time.

If you can't see the forest for the trees, concentrate on one tree at a time, the shape of the forest will emerge.

But above all, keep calm, you can do this job.

(And, if you want any more cheesy analogies or metaphors, post again.)

High Performance Mark
Fortunately its modern and following best practices as well. It would time very well spent.
ccook
This is a good advice but you omitted one important thing: time span of the task. How much time does management demand on a man to become proficient with this thing. I was in a similar situation that was estimated to 18 months. Management didn't have the guts to say it to the client (afraid they will scare him) so they said 6 months. I left the company soon after. IMHO the problem here I think is what is expected from the OP not what he can actually do (that's the easy part).
dpb
+1 for a good answer..and the elephant analogy made my chuckle :P
Chris T
You need to execute code to get a real understanding of it, not just read it. Most human beings can't mentally execute anything more than very simple step by step processes, let alone a method with multiple conditionals, looping etc.
Ash
How do you know what it's like to eat an elephant? I think I need to call some sort of ranger about that....
samoz
@samoz: well, I've never actually eaten a whole one, but I've had a steak or two. in many parts of Africa the elephant populations are culled at intervals, and their meat is not allowed to go to waste.
High Performance Mark
@HPC Weird... Who would have thought I'd learn about elephants on SO
samoz
+2  A: 

Something that always helps me when I don't fully understand something is: taking notes. Either by writing down or typing them out. Don't just try to understand it, try to write it. Pseudo-code will do fine for the purpose of understanding the program flow and giving yourself a better overview of the project.

Oh and coffee. Lots of it.

Kevin van Zanten
+2  A: 

I would suggest taking time - quite a lot of time, if need be - to read up on the concepts that feel new and hard to grasp. Buy a book or read blogs; there are tons of stuff out there, both printed and on the web, and on every level from complete beginner to master and guru.

If possible, see if you can get some time during work hours to do this - maybe your manager can allow you to devote 10-20% of your first month or so to reading up. If not, spend your spare time learning new stuff.

And remember - this isn't about you being a poor developer or not up for the job. The C# community and the C# language have both evolved incredibly fast over the last, say, five years, so anyone who's been busy managing existing code is excused for being a little behind on new concepts =) As High Performance Mark suggested, digest the code one piece at a time, and complement it while reading tutorials and blogs/books on large concepts you feel uncomfortable with, and it will all come clear soon enough. =)

Tomas Lycken
+2  A: 

I don't think there is anything to be afraid of :) If nothing else, it will be a good learning experience. Why don't you take some existing issue/bug and try fixing that, and see how you do and how much you enjoy the learning experience. I think it is a good approach towards understanding the system.

I once inherited a humongous code-base. Initially afraid and unsure, I quickly went on to fix some major issue in it (unbelievable, but I was able to fix over 180 bugs in the product by rewriting a single function! :)), and the experience thus gained, formed the base of a new product on the same platform.

tathagata
+8  A: 

As a person who went from 0 to 60 in c++ after doing scripting in a proprietary language for years my advice is this. Go slowly. Get a good IDE for tracing. Don't be afraid to ask around for help even if you think the other coders are going to laugh at you for being such a newb. If there are any open bugs, grab one and dig into see how the flow of control operates. Draw diagrams. When you see an assert or a log warning, don't just click ignore, dig in and figure out why it's happening. Don't be afraid to trace down into low level code. Don't overestimate your own ability while giving time estimates, but don't be afraid to take coding projects for yourself that you feel uncomfortable with but excited about...when you are the lead you get first pick!

Rokujolady
And yes....over engineering and lack of consideration for readability are concerns at most companies.
Rokujolady
+1 for diagrams
Unreason
+3  A: 

Reduce the code to fan in and fan out nodes. Identify areas of code enclosed by fan out nodes. Treat enclosed areas as black boxes.

Work on understanding what is happening at the fan in points. Why can the code fan in here? What is the code doing at this point. This should be easy to understand.

Next identify what each of the black boxes is doing. Start with large black boxes first before going into the smaller contained black boxes.

So firstly you might take all the projects in the codebase and find out which projects call which other projects.

Then you might go down to a class level. Then down to a function level. Remember that the relationship between classes and functional groups may overlap or disconnect entirely. So when looking at the functional level you may want to reduce the signifaicance of the class structure that you have previously worked-on but you should not remove the class structure.

As well as starting with larger black boxes first, also consider which black boxes are the ones that you would need to work on first. ie. What future development is looming, what significant bugs are you aware of?

Grahpical UML software mapping tools may help you with this task.

A minor point about eating elephants, If the elephant is chopped and up and mixed in a curry it is better to identify what is elephant and what is potato before starting to eat. I would choose a different metaphore. If you want to understand what makes up a forest you do not start by studying all of the leaves on one tree. Identify the groups of trees then the trees individually before looking at the branches, twigs and leaves.

developer
Won't you study the forest first? To see if they are groups of trees? Maybe they are hills and stuff in the forest?
AMissico
+5  A: 

I've done this twice in recent memory - once with a V1 codebase that had most of the business logic in stored procedures, and once with a relatively new codebase with a half-decent architecture that was half developed.

Firstly - Hold off on passing judgements, and don't throw your hands in the air and give up just yet.

In both cases I made initial complaints similar to yours including:

  • this is too complex, bad practice, this sucks
  • we should redevelop from scratch
  • i should quit this job and go rogue, etc.

But after I became more familiar, my initial presumptions and impressions, while often correct, were more or less irrelevant. Familiarity and understanding of architecture and scope give me confidence. I can now maintain the system in its current configuration, and more importantly, I can target areas where it's smart to make improvements.

You just don't have the depth of knowledge required to do that without experience.

Depends on the scale of the system, but what I'd recommend for a large, mission-critical beast would be:

  • Make no drastic changes/improvements for 3 months, just keep things running
  • Spend the first 3 months or so carrying out small maintenance tasks, or adding small features by copying existing features, without properly understanding it
  • Estimate everything, including a modifier for my confidence in my understanding of the areas of the system.

As your understanding deepens development becomes less expensive and more importantly, less risky. It's smart to hold off on large, complex developments for a few months until you're confident you can do it right.

nailitdown
+1  A: 

I'd suggest trying to get some UML-type diagrams together, class diagrams at least. Since you're using C# the IDE might even be able to generate this for you, and it will let you see things hanging together.

Learning the language/tech properly is obviously important, so devote some time to that too, so any particular method is not a problem to read in isolation.

Note that learning a codebase by inspection is hard for most people. It's normally easier when you have specific tasks to work on. Maybe you can find some, or invent some, to force you to work that way.

You haven't said how big the codebase is. 10 classes? 10 thousand? Is it one application or a whole bunch of apps?

John
It's 100k code lines developed over last 5 years making use of 12-15 different frameworks
@iande - so quite big then. To be expert will take a long time, even if you know the frameworks. But to know a high-level picture of how systems fit together, not too bad I think.
John
yeah, did a little more counting: 600 interfaces and nearly 2500 classes about 1500 files
+1  A: 

You should track down the original developers. Either buy them a few beers or get your managers to contract them back for a day or two to talk you through the bits you don't understand, anything else they think you need to know, show you how to work through and solve an open issue, discuss your proposed design for an enhancement, etc.

This is something you can reasonably (and should!) escalate to your managers. I realise there's some pride at stake becase you've spent a few weeks looking at it and you don't want to admit to them you haven't got it yet, but that probably puts you in a better position to quiz the old guys and at the very least your managers need to know that you're not fully up-to-speed yet if they need you to do something.

A lot of people I work with would say to get the original developers back in to write documentation for the whole system. I'm not sure that's always that useful - I find it easier to work through tasks etc. as other people have suggested.

Rup
2nd paragraph is excellent point.
AMissico
+3  A: 

Are there NUnit tests available for this project ? Once you've gotten a broad outline of what classes do what (by following the other suggestions), you should start writing some simple ones. NUnit tests allow you to view the software from the point of view of a user i.e. 'i expect this class or module to do x,y and z ; given these inputs i expect these outputs...' etc.

This has the additional benefit for when you come to make future changes in terms of doing regression testing.

TanvirK
+1  A: 

Learn to love your debugger. Run up the application on a development system and run through some of the normal/good paths through the application. Stick a breakpoint at a pertinent point and step through the code - this is the best way to get to know it...

Paddy
Mhm, I love my debugger, but using it is actually quite difficult at the moment. With the inversion of control pattern everything is loosly coupled to the extreme.
Pat Wallace
+3  A: 

Honestly, that is what they pay you for. If it was easy they wouldn't call it work. The probation period is not for you to understand the code. It is for them to understand you and give them confidence you can do the job long-term.

Nailitdown provides the best advice. Especially, the advice of "do not make drastic changes". Yet, I would add one more, "do not make any change unless you are absolutely sure you understand the change."

I been in the spot quite a few times over the last two decades.

  1. You will introduce bugs, so try to mitigate them as much as possible, test, test, and test.
  2. You will need time to review the code and generate an estimation. In other words, when asked how long it will take, say you will get back to them tomorrow because you need time to review the changes and how those changes affect the system.
  3. The actual users can get you up to speed quickly.

After three months, you should be getting the hang of things, in six months you will be familiar with the system, but may be unfamiliar with subsystems that are mature and stable.

Rub makes an excellent suggestion, "You should track down the original developers." As a consultant I have done this a couple of times. They have always been willing to talk and it has always been helpful. I have also contracted the original developer twice before and had less success due to my inability to ask the correct questions. The third time I researched better questions only to find out that I didn't need the developer because he only confirmed what I already figured out and didn't prove any new information.

...could be too cleverly implemented and only readable for the ones having worked on it for years, or since startup?

Most likely, but in a few months you will be just as clever.

If you are still struggling at six months, you will need to reevaluate your situation.

AMissico
Good post, just to clarify I don't think probation period is for me to understand the code. I think it is for my employee to find out if I'm a good fit for the company (can I get the job done?) -> Likewise it is for me to find out if I am a good fit for the company. It goes both ways.
@iande: I might not have been clear. Yes, the probation period is to determine if you are a good fit. I was trying to make that point. :O) A probation period worked well for me once, after three months, I couldn't run out the door fast enough.
AMissico
+1  A: 

I have been in similar situations two or three times. My experience is, that it may take 2-3 years to really fully "master" a reasonable large project.

It is important that you start working with the code as soon as you can - not just theoretically but practically. Start doing small tasks and no major changes within the first months. If you don't have small tasks, just make up some small tasks (branch the code before). After completing some of these little tasks, step back and try to understand the overall architecture again. Then start doing some more challenging tasks. After a while you will get the big picture automatically. You basically iterate between a top-down and bottom-up analysis and meet in the middle :-)

Your employer can't expect from you to do major changes on a large system within the first 6 month.

And do your successor a favor: write down your insights - even if its informal using a Wiki or something. Writing down will also help you.

Stiefel
+2  A: 
  • if it is that big you will have to draw diagrams anyway.
  • look at the learning as a project of documenting (for others), too
  • read source, make diagrams, review, repeat.
  • setup full testing environment and source control if there are none
  • try to break it testing system and learn how it breaks (document)
  • try to improve system
  • consider writing unit tests
  • try to explain it to others
  • do team reviews

It is normal that you will make conceptual errors and things will blur, but when they crystallise they will start to make more and more sense. Expect to spend more time then anticipated.

Unreason
+6  A: 

Three months ago I was in the same position as you.

The top voted (current) answer says "find a small class definition within the codebase. Read it and understand it.". If only it were that simple.

That is a very time consuming and mentally challenging approach. Personally, I don't understand code fully until I can actually execute it and see it in action.

The answer (the one I applied with success) is to create a unit test project (or projects) and write test methods that simply execute various parts of the application that you're interested in.

I then change the project (test project) settings: Debug -> Start Action to "External program" and point it to the nUnit GUI test runner. Now when I run the project my tests are executed and I can step into both the tests and, more importantly, the application code they call.

If the application is divided into separate projects (as mine is) it is a simple matter to instantiate and call public methods on each project. If not (or you need to call non-public methods) check if you are allowed to re-compile the application with the "InternalsVisibleTo" attribute and give access to your test project.

These unit tests are not really classic unit tests containing multiple assert statements etc. Instead they are probably more "test harnesses", ie. an entry point that allows me to quickly and easily run specific parts of the application code. Within each test method I clearly set-up required input variables etc and can then validate any outputs etc.

This has helped me enormously and will also be a valuable executable documentation for the future support of the application.

Ash
+1: This is a good tactic for learning what code does. It's even better if you do write them as real unit tests, as these will be valuable when you refactor.
Don Roby
A: 

Overall - take your time, it is hard task.
This is the list of what helping me in this situations.

  • read the source control log.
  • analyze by Code Complexity metric to see where the problematic classes
  • try to break the program, by commenting the code lines
Avram
A: 

In my opinion you should firstly check what code do not how it do this. So see code in action, run unit tests, check documentation, write some small apps or unit tests that use this code, ask users/developers how they use applications, what kind of troubles they have with it. Later you may start fixing some defects or implementing small features to slowly learn how code works. This is more natural way (and more effective) to learn code than spending few weeks investigating every source file. I think initially you should know what code does not how.

Zuljin
A: 

You have some good answers here, but I'll also point to my answer to a similar question about a week ago: http://stackoverflow.com/questions/3315727/what-do-you-do-when-youre-suddenly-thrown-onto-a-large-project/3315770#3315770

Amusingly, I used a similar analogy to another poster (namely eating very large mammals). :)

One thing I will add is that as you go through the code and understand little bits, write a comment that tells what that bit does, even if trivial, and even if not in the production version. That will help you remember, and there's an added benefit to that that I'll get to in a second.

Secondly, you might try duplicating small bits of the code as self-contained functions/methods. Test them, make sure you know how they work, look up the functionality if needed. You will pick them up really quickly this way. Also, when you can, do as much of this duplication as possible from memory. Memory is a great friend, and will help you through things that seem, at first, hopelessly complex. Now about memory...

I'll hypothesize:

The problem isn't that you don't understand the code, it's that there is too much information to load into your brain's working memory at one time.

This is certain to happen with any new, big project. IT's why the "small bites" approach is always a good one. The more pieces you store in your brain's long term memory, so to speak, by understanding little chunks, the easier it will be to comprehend the whole project. Freeing yourself from the many little half-understood bits will free up your concentration to analyze the project on a larger scale, until the whole thing is perfectly clear.

It will be like the difference between walking into a room filled with friends vs walking into a room filled with strangely dressed aliens.

This is a "cognitive theory" approach, especially in regard to processing chunks of code and committing some understanding of them to memory. It should accelerate your adaptation to the new project.

Good luck with your new job.

Rab
Incidentally, you can and should use diagrams in parallel with this process. But in the very beginning, making a high-level diagram could be mind-bending since you won't yet understand the components. Like describing how a watch works without knowing how gears work.
Rab