Related
I was just having a nap and then that crazy idea came into my head. Here it is.
We have 2 different photos with face in each. How can we detect if there is the same person on that two photos?
Is it possible to do that? If yes, can I do it with Java or PHP? What the way to do it? Any ideas? Maybe each face has a "algorithm" or something which could help us?
Thank you very much.
It's not an trivial solution (and cannot be covered in an SO answer); you can start by reading papers on facial recognition. If this is something you really want to do, be prepared to read a lot of background information first before you actually start writing code. This subject matter is the basis for a lot of people's doctoral and masters theses. In this case, language is not as important as the algorithm. Also be prepared for lots of math. At the very least, you'll learn something cool. :)
I was freelancing a very similar task. Its not fun. almost impossible to build face recognition - face detection is easy, recognition is the tough part... the algorithm is generally a guarded secret as I've seen.
But I did find this: http://face.com/
Face recognition API. Feed it data, it feeds you names and details you've previously fed it. You have the ability to check to see if a face exists.
If you make a lot of requests or start working at an enterprise level - they charge.
The language doesn't really matter as long as it has the tools to do number crunching on the image data. Facial recognition is too big of topic for a forum post like this. I would just google "facial recognition algorithms".
I agree with the others that this is not trivial.
detect a face in both photos
normalize the facial data
compare the data to see if they match
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 been coding since my early teenager years. I started out with HTML, went on to PHP/MySQL (created my own forums, social networking sites, etc..) and then branched out into more traditional languages such as Java and C++ (also picked up a little VB .NET in high school). I'm most familiar now with C++ as that is the language of choice taught to us in Computer Science II (skipped Comp Sci I) at RPI. I now feel like I have a very good knowledge of how to program from this class (the homework assignments were brutal).
It is now summer and I am interning at a company that is providing me some level of new experiences with programming, but I want more. I want to feel the incredible satisfaction that I got out of my computer classes at RPI whenever I finished a long assignment (generating every possible wordsearch from a set of words to include and exclude comes to mind).
My question is, where do I go from here? I tried following a tutorials online, but they were all too simple. I then tried heading over to sourceforge and helping out with various projects. But, as soon as I downloaded the code I got lost in its complexity. I have never created actual software of a real life applicapable scale. And I don't know where to get started. How do you transition from programming knowledge to actuall creation of software?
I'm also open to learning new languages (javascript/jQuery, ASP .NET, C#, Python), or using new libraries and/or frameworks with c++ (we only used the STL in Comp Sci II) and other languages. Again my question is, where do I go from here? And I am welcome to all possible answers.
Thanks Much,
Michael
You could join a big open source project, you'll learn a lot and accomplish something cool.
EDIT after comment: If this is too complicated for you, try starting a "real" project. I say "real" because it should be something that you want to do, not a "create a blog" or "how to do a loop". For instance last year I created a fully functional project management system that I now use for some of my projects. If this is real, you will be more motivated and you will want to get this done.
Pick the technology you want for it. I'd recommend Ruby on Rails because it's awesome and full of interesting concepts that will improve the way you code overtime (DRY, RESTful, MVC...)... but you can pick whatever you want.
Try to create your project using what you know and basic tutorials. You will get stuck and have to learn some more in order to get the features you want going. To me that's the best way to improve the way you code and general programming knowledge.
Since you'll start the project from scratch, you'll see where to start and how this will evolve. I'll take the project management tool. We started with "A project has todos" and we ended up with all kind of other features such as a complex calendar, a full ajax interface, a embedded chat...
Once you see how you did this, try doing the same with a friend of yours to get a fealing of teamwork in development. Learn how to use SVN, basecamp... learn about software development processes (Agile!), peer programming..
There's a lot to experience! Then you could give open source another try.
Hope that helps
I'd recommend trying a pure functional language, such as Haskell. It's a completely different way of looking at programming, and I found it very satisfying.
I recommend the book Real World Haskell for learning it.
Edit: In response to comments, my interpretation of the question is where can he go from here as a programmer. Functional programming is a logical direction. For someone learning functional programming for the first time, Haskell is nice because it doesn't really allow for imperative programming practices. Furthermore, it has basically all features you will find in other functional languages, which means it will be easy to pick up other functional languages.
I would suggest looking at Project Euler. It's a great and fun way to learn a new language, and it does provide that level of satisfaction when you solve the problems. They offer a huge range of problems at all levels of difficulty.
I think the best way to improve your skills as a programmer is to do what programming was intended for: solve problems. I'm sure you've been playing around on your machine and at one time thought to yourself "I wish there was a program that did this..." or "I wonder if there are any programs that do X..." Instead of just googling to see if someone else wrote it, write it yourself. Start with something small, and gradually make it more complex. Add features. Allow yourself to fail, and when you do, ask yourself (or us at stackoverflow) how to overcome that obstacle. Once you have the basics of programming, everything else is just making big things out of littler things, and the little things are usually pretty easy.
When you are making something you know you will actually use, it's more fun and more gratifying when you finish.
Do you understand all of the following and how they work?
Linked lists (single and double)
Sequential vs. binary search
Binary trees
Stacks
Red-black trees
Algorithmic complexity and big O notation
Recursion
Hash tables and hashing algorithms
If you don't feel completely conversant in any of these, take a class in data structures and algorithms.
It seems like you've experienced many languages, but have not created a real-world application. Creating software in any of those languages will bring you to a new level.
PS: Creating software is much more than just knowing how to mess around with a language.
Check out Design Patterns.
I believe that's beyond mere simple coding.
You could offer your abilities to a non profit or a friend or someone who needs a website or program built.
Tell them you can do it for free and then just go for it. As you start to make it you'll start to see what you need to learn.
For example I bit ago I had the program Peel www.getpeel.com on my Mac. But sold my Mac for Wind as I am traveling.
Seeing that there was nothing for Windows (or nothing I could find) like Peel. I build my own in PHP and am up to a 4th rebuilding of it as I learn betters ways to do each new thing I am learning.
You've got to find a particular type of functionality that interests you. For me it's been basic socket programming and making my own protocols. I got that feeling when I was able to create a functional file uploading control that worked in conjunction with a file upload service on the server which I had created. The protocol handles authentication, chunking and hash comparison. Sometime soon I plan on incorporating file-resume functionality as well.
Well my advice will be to find a problem/project you are interested in and try to code it. Trying a real problem is something that drives you. Find something not to complex but not too simple. Something to try when starting a new language is to write some tools. You can for example program a python script that print metrics on a C++ project. You can write a tool that extract some statistics from a website you use, etc. When I learn programming game programming was quite fun (I was young :-) ). You can try to program some simple game using a 3D engine like Ogre3D for example. Participate in an opensource project is great too but as you stated perhaps a bit overwhelming for now ;-)
Find something you like and that has a REAL useful goal for you. You will thrive to solve the problem and learn a lot along the way !
I think the transition from the kind of finite tractable problems that are part of class projects (and some internships) to "real world" projects is quite tough. Sounds like language syntax, getting bugs out of code etc. is something you are comforatble with.
When we come to larger projects, probably with many release cycles, with developers working together, different kinds of problems emerge. I remember being shocked when I saw my first big project plan - what a small propertion of the time was actually writing code!
The thing I found helpful as a junior was "Sitting By Nelly", I was lucky enough to work for enlighted employers who put me with very experienced and helpful developers. Sometimes to work with, sometime to work alongside. I reckon that helped me get over the hurdles you describe.
So, I reckon you need to find employment of this kind. Be less concerned about specific technologies, salary etc. Look instead for the culture and level of responsibility you would have.
I think you should really start a "real world application" as suggested here. You will see that a real project requires a bit more than just knowing the language.
I suggest you find some simple problem you had issue with, and make a software that solves that issue.
For example, if you want some kind of software that checks RSS feeds every 5 minutes and makes a little pop-up as soon as a new one comes along. Or you want a program that will let you do simple presentations by just dragging a few pictures in.
Then whatever you choose, start by making the simple solution to the problem and extend from there (like do different settings, extra features etc.)
I've looked for the answer to this question for a while now. Most all of the suggestions are usually either help an open source project or build something that interests you. I'm starting to realize that those answers are vague because what's 'interesting' or 'valuable' experience and how to get started doing it is completely subjective. Also, there's only one way to get real experience, which is to work on real projects. It's difficult but find a project, personal, open source, or otherwise that will increase your knowledge in a technology or platform that you think will hold your interest. Then just dig in. It doesn't have to be of earth shattering importance, just valuable in relation to your own goals.
There is no magic bullet transition from academic puzzle solving programs to real world applications. The best way to learn is just to jump in head first. It will take you a very long time to learn what you need to if you only ever look at your own code. You need to be looking at code written by professionals and struggling to understand why it works the way it does until you do understand it.
It seems overwhelming at first, but you will quickly start to see patterns if the application is at all logical. Well written code will be separated in logical ways, so you should be able to pick it apart one layer at a time.
For example, you could try a bottom up approach where you try to understand how the database interactions are handled before looking at the code that uses the database layer. You keep going upward until you get to the GUI event handlers.
Large enterprise applications can be even harder to understand because there might be a lot more than one executable, or component. Try to stay focused and learn what the component is responsible for doing, and then pick it apart a piece at a time.
You will see that there are not just patterns at the function and class level, but at higher levels as well. This makes it simpler to understand what is going on when you understand those patterns.
Try to find an internship or co-op position. I was in a similar situation after my first few courses. I took a co-op position sophomore year and I learned so much more on the job than I did in class. Class is great for teaching you theory and the basics. I learned C# on my first project on my co-op and that got me my second co-op position at another employer (wanted to see how it was working at a small company).
This past spring, I accepted a position at my first co-op employer, reworking my first major project I had started on my co-op. I have a list of side projects I also want to complete, which will help round out my skills, as well as learn some other languages.
So my suggestion is try finding a job where you can have a great mentor. On my second co-op, I learned alot of the coding standards that I code against from my supervisor. He was a great teacher, and really had some great input, and explained why things should be done certain ways.
You will almost certainly go nowhere unless you find something that interests you. Figure out what is interesting, and then how to write software involving it.
The only way to begin is to begin! There is really no other way... The best answers you get would always tell you this. You have the knowledge, now put it to work!
I have become pretty fluent in a few different languages now, but I seem to have a hard time actually figuring out the best way to go about solving particular problems. What are some ways to go about getting better at the actual problem solving of programming.
Experience. Solving something completely new is hard. The best way to solve problems is to try and find a problem that you've solved before, and that is similar, and adapt you solution to the new problem. So until you have experience with many different kinds of problems, it's hard to solve new problems that you come across. Visiting sites like this and reading questions and theirs answers are a great way of learning how others solved problems that they encountered.
Basically, "just do it". When you have to make a choice, just make any choice (except flipping a coin).
Once you have something that works, then sit back and scratch your head about what you did wrong and how to do it better.
If you have absolutely no clue how to do even that, just solve a part of the problem completely and move on.
I suggest checking out this book. They aren't the best kid on the block, though they want us to think they are...but they did well with Basecamp.
When all you have is a hammer, everything begins to look like a nail.
So, make sure you're well versed in algorithms and data structures. When you study them, think hard about what sort of uses a particular algorithm is good for.
Ask someone else. Someone in your office, on Twitter or SO, or even your wife. People with no technical knowledge often come up with simpler solutions.
If you must solve it on your own, try one of these others:
Do a quick search for another person or project which has tried to solve your problem. If they have a blog, documentation or source code, you might be able to learn from their implementation.
Come up with at least TWO solutions and pick the best one.
Pretend you have 15 minutes to solve the problem before the civilized world is destroyed by Nuclear War / Skynet / Permanent endless re-runs of Seinfeld, you might think of something much simpler which gets 99% of the work done.
The book is a set of heuristics to go through when solving a problem. Read about it on Wikipedia. Buy it on Amazon.
By solving actual problems. Practice makes perfect.
If you have time to become fluent in multiple languages, my guess is that you haven't spent much time doing any actual work. If you have a job, it might be time for a new one. If you're still in school, do you have any interest in starting a project for yourself or contributing to one that you use regularly?
It might help to know what kinds of problems you're having difficulty solving.
Go find an open source or free project you can get excited about and contribute. I learned a lot by signing up to code for my favorite video game modification.
Experience.
Study really only goes so far. Find something fun and small. Do it.
One way that seems to work for a lot of people is to pick use a book like Programming Challenges as a guide, and focus on solving problems of a particular type. For example if you're weak in an area like graph problems or dynamic programming, find a set of problems on an online judge and work through them. You'll start to recognize patterns and be able to classify problems.
Google for an answer. Chances are someone else has solved the same problem or a similar problem before.
Ask on SO. :)
Read some textbooks or online articles about design patterns.
Problems may have many solutions, some simpler and some more complicated. Don't get stuck thinking there is only one solution. Just go with the simplest solution that makes the most sense in the context of your application.
After years of experience you'll be able to think of your own solutions to most problems. :)
Study Algorithms!
Search and get a hold on as many examples, books on the subject programming or otherwise, etc.
Problem solving skills can also be improved by playing tactical games.
These made me Enjoy problem solving and become better (not necessarily good) at problem solving:
Chess and igo
I like this general method:
List the possible solutions with their strengths and weaknesses
(This will push you to briefly taste all of them)
Chose the best one and make your design on it
(If you find any heavy obstacle, reconsider other options)
Implement
most importantly, on every step, learn
The best way is probably to learn form a master if that's an option. Especially if you can find someone familiar with the problems your addressing.
Generally the more tools we have at hand the more options we have for tackling a problem. I agree that's important to always code and to always deliver something that works (however inelegant it is). But I think we need to increase our skills/knowledge in many directions:
Language skills (know your language(s) in depth)
Programming paradigms (Imperative, Object, Functional)
Framework knowledge
Algorithms
Patterns
Date-Structures
Methodologies (Agile, DDD, BDD, ?DD)
Tools
etc
You can get a lot of skill through on the job just-in-time-learning, but I usually have a pet subject at any time that I'm trying to get a deeper understanding of, typically this means getting the book and reading it cover to cover.
Work your way through Project Euler, and look at other people's solutions to the problems. Almost every problem will have been solved in a way that wouldn't have occurred to you, and usually with greater efficiency.
I think that there is a lot more than raw experience involved in becoming a good problem solver - because I've seen poor problem solvers with lots of experience.
Here are a few tips but you can find many more around the web.
Look at a number of problems and
figure out what they have in
common. The greater the generality
with which you understand the
solution to a problem, the more you
can apply it to other problems.
Try to discover approaches which
good problem solvers use to solve problem. But don't assume anyone has monopoly on problem solving
If you read Richard Feynman's
books, you'll notice that he
considers many different routes to
get to his goal. Don't narrow your
approach prematurely
Be positive. Assume that you can find
the solution to anything. Your state of mind matters. Enjoying the process of problem solving makes it much easier
Don't beat your head against the wall. If you don't
seem to be making progress with one approach, try another approach
Always be looking for more ways of
solving problems and more insights
into the process of problem solving itself
Be willing to work. It still can take a lot of effort solve some problems
The more different fields of study you know, the more viewpoints you have. I have a strong math background and I find it very useful for many problems. Physics, music or any different viewpoint might be useful
Practice solving problems.
Take an algorithms or discrete math course.
Here some tools that I've used in the past to help me understand a particular problem and its solution. I don't always use them today, but they helped me to learn how to think about breaking down a problem and coming up with a solution.
Class-Responsibility-Collaboration (CRC) cards
One card per class, details the responsibility of the class and what other classes it collaborates with. Using cards you can layout your design for the solution and see where you have too much coupling or too much responsibility. They allow you to think about the design in a lightweight manner before committing to code.
Use cases
Either actual structured use cases that describe user interaction with the system or even briefer stories or story cards. I still use stories, though I capture them in a wiki instead. This allows you to capture the interaction with the system in an informal way. Stories are basically placeholders for conversations that you need to have with the customer about what is supposed to be done. Using the collected stories, you start getting a grasp on the overall intention of the code. You can also start seeing how things interact and what works with other things. This is really the beginning of design.
UML Diagrams - particularly interaction diagrams
For awhile I used these a lot. It really helped to see how things actually worked together under the hood. I will still diagram, informally, some complex interactions to make sure I don't miss anything important. Going through a lot of these really helped me to think about how my objects interacted and now it is sort of second nature to think in terms of interactions.
Class diagrams -- a really high level view of the code.
These allow you to see your code structurally, especially if you can break the diagram down into components or layers of architecture. Mostly I use these now to explain the code to other people when necessary. When starting out these provide a pretty good visualization, though, if you're struggling with the bird's-eye view of the code.
The best advice I can give you if you try these is to follow the "rules" until you really have a good grasp of what is going on. Once you feel like you have a better understanding of what they provide, you can use them or not, or modify how you use them to keep only what is helpful and let the other stuff go.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Joining an existing team with a large codebase already in place can be daunting. What's the best approach;
Broad; try to get a general overview of how everything links together, from the code
Narrow; focus on small sections of code at a time, understanding how they work fully
Pick a feature to develop and learn as you go along
Try to gain insight from class diagrams and uml, if available (and up to date)
Something else entirely?
I'm working on what is currently an approx 20k line C++ app & library (Edit: small in the grand scheme of things!). In industry I imagine you'd get an introduction by an experienced programmer. However if this is not the case, what can you do to start adding value as quickly as possible?
--
Summary of answers:
Step through code in debug mode to see how it works
Pair up with someone more familiar with the code base than you, taking turns to be the person coding and the person watching/discussing. Rotate partners amongst team members so knowledge gets spread around.
Write unit tests. Start with an assertion of how you think code will work. If it turns out as you expected, you've probably understood the code. If not, you've got a puzzle to solve and or an enquiry to make. (Thanks Donal, this is a great answer)
Go through existing unit tests for functional code, in a similar fashion to above
Read UML, Doxygen generated class diagrams and other documentation to get a broad feel of the code.
Make small edits or bug fixes, then gradually build up
Keep notes, and don't jump in and start developing; it's more valuable to spend time understanding than to generate messy or inappropriate code.
this post is a partial duplicate of the-best-way-to-familiarize-yourself-with-an-inherited-codebase
Start with some small task if possible, debug the code around your problem.
Stepping through code in debug mode is the easiest way to learn how something works.
Another option is to write tests for the features you're interested in. Setting up the test harness is a good way of establishing what dependencies the system has and where its state resides. Each test starts with an assertion about the way you think the system should work. If it turns out to work that way, you've achieved something and you've got some working sample code to reproduce it. If it doesn't work that way, you've got a puzzle to solve and a line of enquiry to follow.
One thing that I usually suggest to people that has not yet been mentioned is that it is important to become a competent user of the existing code base before you can be a developer. When new developers come into our large software project, I suggest that they spend time becoming expert users before diving in trying to work on the code.
Maybe that's obvious, but I have seen a lot of people try to jump into the code too quickly because they are eager to start making progress.
This is quite dependent on what sort of learner and what sort of programmer you are, but:
Broad first - you need an idea of scope and size. This might include skimming docs/uml if they're good. If it's a long term project and you're going to need a full understanding of everything, I might actually read the docs properly. Again, if they're good.
Narrow - pick something manageable and try to understand it. Get a "taste" for the code.
Pick a feature - possibly a different one to the one you just looked at if you're feeling confident, and start making some small changes.
Iterate - assess how well things have gone and see if you could benefit from repeating an early step in more depth.
Pairing with strict rotation.
If possible, while going through the documentation/codebase, try to employ pairing with strict rotation. Meaning, two of you sit together for a fixed period of time (say, a 2 hour session), then you switch pairs, one person will continue working on that task while the other moves to another task with another partner.
In pairs you'll both pick up a piece of knowledge, which can then be fed to other members of the team when the rotation occurs. What's good about this also, is that when a new pair is brought together, the one who worked on the task (in this case, investigating the code) can then summarise and explain the concepts in a more easily understood way. As time progresses everyone should be at a similar level of understanding, and hopefully avoid the "Oh, only John knows that bit of the code" syndrome.
From what I can tell about your scenario, you have a good number for this (3 pairs), however, if you're distributed, or not working to the same timescale, it's unlikely to be possible.
I would suggest running Doxygen on it to get an up-to-date class diagram, then going broad-in for a while. This gives you a quickie big picture that you can use as you get up close and dirty with the code.
I agree that it depends entirely on what type of learner you are. Having said that, I've been at two companies which had very large code-bases to begin with. Typically, I work like this:
If possible, before looking at any of the functional code, I go through unit tests that are already written. These can generally help out quite a lot. If they aren't available, then I do the following.
First, I largely ignore implementation and look only at header files, or just the class interfaces. I try to get an idea of what the purpose of each class is. Second, I go one level deep into the implementation starting with what seems to be the area of most importance. This is hard to gauge, so occasionally I just start at the top and work my way down in the file list. I call this breadth-first learning. After this initial step, I generally go depth-wise through the rest of the code. The initial breadth-first look helps to solidify/fix any ideas I got from the interface level, and then the depth-wise look shows me the patterns that have been used to implement the system, as well as the different design ideas. By depth-first, I mean you basically step through the program using the debugger, stepping into each function to see how it works, and so on. This obviously isn't possible with really large systems, but 20k LOC is not that many. :)
Work with another programmer who is more familiar with the system to develop a new feature or to fix a bug. This is the method that I've seen work out the best.
I think you need to tie this to a particular task. When you have time on your hands, go for whichever approach you are in the mood for.
When you have something that needs to get done, give yourself a narrow focus and get it done.
Get the team to put you on bug fixing for two weeks (if you have two weeks). They'll be happy to get someone to take responsibility for that, and by the end of the period you will have spent so much time problem-solving with the library that you'll probably know it pretty well.
If it has unit tests (I'm betting it doesn't). Start small and make sure the unit tests don't fail. If you stare at the entire codebase at once your eyes will glaze over and you will feel overwhelmed.
If there are no unit tests, you need to focus on the feature that you want. Run the app and look at the results of things that your feature should affect. Then start looking through the code trying to figure out how the app creates the things you want to change. Finally change it and check that the results come out the way you want.
You mentioned it is an app and a library. First change the app and stick to using the library as a user. Then after you learn the library it will be easier to change.
From a top down approach, the app probably has a main loop or a main gui that controls all the action. It is worth understanding the main control flow of the application. It is worth reading the code to give yourself a broad overview of the main flow of the app. If it is a GUI app, creating a paper that shows which screens there are and how to get from one screen to another. If it is a command line app, how the processing is done.
Even in companies it is not unusual to have this approach. Often no one fully understands how an application works. And people don't have time to show you around. They prefer specific questions about specific things so you have to dig in and experiment on your own. Then once you get your specific question you can try to isolate the source of knowledge for that piece of the application and ask it.
Start by understanding the 'problem domain' (is it a payroll system? inventory? real time control or whatever). If you don't understand the jargon the users use, you'll never understand the code.
Then look at the object model; there might already be a diagram or you might have to reverse engineer one (either manually or using a tool as suggested by Doug). At this stage you could also investigate the database (if any), if should follow the object model but it may not, and that's important to know.
Have a look at the change history or bug database, if there's an area that comes up a lot, look into that bit first. This doesn't mean that it's badly written, but that it's the bit everyone uses.
Lastly, keep some notes (I prefer a wiki).
The existing guys can use it to sanity check your assumptions and help you out.
You will need to refer back to it later.
The next new guy on the team will really thank you.
I had a similar situation. I'd say you go like this:
If its a database driven application, start from the database and try to make sense of each table, its fields and then its relation to the other tables.
Once fine with the underlying store, move up to the ORM layer. Those table must have some kind of representation in code.
Once done with that then move on to how and where from these objects are coming from. Interface? what interface? Any validations? What preprocessing takes place on them before they go to the datastore?
This would familiarize you better with the system. Remember that trying to write or understand unit tests is only possible when you know very well what is being tested and why it needs to be tested in only that way.
And in case of a large application that is not driven towards databases, I'd recommend an other approach:
What the main goal of the system?
What are the major components of the system then to solve this problem?
What interactions each of the component has among them? Make a graph that depicts component dependencies. Ask someone already working on it. These componentns must be exchanging something among each other so try to figure out those as well (like IO might be returning File object back to GUI and like)
Once comfortable to this, dive into component that is least dependent among others. Now study how that component is further divided into classes and how they interact wtih each other. This way you've got a hang of a single component in total
Move to the next least dependent component
To the very end, move to the core component that typically would have dependencies on many of the other components which you've already tackled
While looking at the core component, you might be referring back to the components you examined earlier, so dont worry keep working hard!
For the first strategy:
Take the example of this stackoverflow site for instance. Examine the datastore, what is being stored, how being stored, what representations those items have in the code, how an where those are presented on the UI. Where from do they come and what processing takes place on them once they're going back to the datastore.
For the second one
Take the example of a word processor for example. What components are there? IO, UI, Page and like. How these are interacting with each other? Move along as you learn further.
Be relaxed. Written code is someone's mindset, froze logic and thinking style and it would take time to read that mind.
First, if you have team members available who have experience with the code you should arrange for them to do an overview of the code with you. Each team member should provide you with information on their area of expertise. It is usually valuable to get multiple people explaining things, because some will be better at explaining than others and some will have a better understanding than others.
Then, you need to start reading the code for a while without any pressure (a couple of days or a week if your boss will provide that). It often helps to compile/build the project yourself and be able to run the project in debug mode so you can step through the code. Then, start getting your feet wet, fixing small bugs and making small enhancements. You will hopefully soon be ready for a medium-sized project, and later, a big project. Continue to lean on your team-mates as you go - often you can find one in particular who is willing to mentor you.
Don't be too hard on yourself if you struggle - that's normal. It can take a long time, maybe years, to understand a large code base. Actually, it's often the case that even after years there are still some parts of the code that are still a bit scary and opaque. When you get downtime between projects you can dig in to those areas and you'll often find that after a few tries you can figure even those parts out.
Good luck!
You may want to consider looking at source code reverse engineering tools. There are two tools that I know of:
SWAG Kit (Linux only) link
Bauhaus academic commercial
Both tools offer similar feature sets that include static analysis that produces graphs of the relations between modules in the software.
This mostly consists of call graphs and type/class decencies. Viewing this information should give you a good picture of how the parts of the code relate to one another. Using this information, you can dig into the actual source for the parts that you are most interested in and that you need to understand/modify first.
I find that just jumping in to code can be a a bit overwhelming. Try to read as much documentation on the design as possible. This will hopefully explain the purpose and structure of each component. Its best if an existing developer can take you through it but that isn't always possible.
Once you are comfortable with the high level structure of the code, try to fix a bug or two. this will help you get to grips with the actual code.
I like all the answers that say you should use a tool like Doxygen to get a class diagram, and first try to understand the big picture. I totally agree with this.
That said, this largely depends on how well factored the code is to begin with. If its a gigantic mess, it's going to be hard to learn. If its clean, and organized properly, it shouldn't be that bad.
See this answer on how to use test coverage tools to locate the code for a feature of interest, without knowing anything about where that feature is, or how it is spread across many modules.
(shameless marketing ahead)
You should check out nWire. It is an Eclipse plugin for navigating and visualizing large codebases. Many of our customers use it to break-in new developers by printing out visualizations of the major flows.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
While solving any programming problem, what is your modus operandi? How do you fix a problem?
Do you write everything you can about the observable behaviors of the bug or problem?
Take me through the mental checklist of actions you take.
(As they say - First, solve the problem. Then, write the code)
Step away from the computer and grab some paper and a pen or pencil if you prefer.
If I'm around the computer then I try to program a solution right then and there and it normally doesn't work right or it's just crap. Pen and paper force me to think a little more.
First, I go to one bicycle shop; or another.
Once I figure nobody invented that particular bicycle,
Figure out appropriate data structures for the domain and the problem, and then map needed algorithms for dealing with those data structures in ways you need.
Divide and conquer. Solve subsets of the problem
This algorithm has never failed me:
Take Action. Often just sitting there and being terrified or miffed by the problem will not help solve it. Also, often, no amounting of thinking will solve the problem. So you have to get your hands dirty and grapple with the problem head on.
Test. Under exactly what conditions, input values or states, does the problem occur? Make a mental model of why these particular conditions might cause the problem. Check similar conditions that don't cause the problem. Test enough so that you have a clear understanding of the problem.
Visualise. Put debug code in, dump variable contents, single step code whatever. Do anything that clarifies exactly what is going on where - within the problem conditions.
Simplify. Remove or comment code, poke values into variables, run particular functions with certain values. Try your hardest to get to the nub of the problem by cutting away the chaff or stuff that doesn't have a relevance to the problem at hand. Copy code into a separate project and run it, if you have to, to remove dependencies.
Accept. A great man said: "whatever remains, however improbable, must be the truth". In other words, after simplifying as much as you can, whatever is left must be the problem, no matter how bizarre it may seem at first.
Logic. Double, triple check the logic of the problem. Does it make sense? What would have to be true for it to make sense? Is there something you're missing? Is your understanding of the algorithm wrong? If all else fails, re-engineer the problem away.
As an adjunct to step 3, as a last resort, I often employ the binary search method of finding wayward code. Simply comment half the code and see if the problem disappears. If it does then it must be in that half (and vice versa). Half the remaining code and continue.
Google is great for searching for
error messages and common problems. Somewhere, someone has usually encountered your problem before and found a solution.
Pencil and paper. Pseudo Code and
workflow diagrams.
Talk to other developers about it. It
really helps when you have to force
yourself to simplify the problem for
someone else to understand. They may also have another angle. Sometimes it's hard to see the forest through the trees.
Go for a walk. Take your head out of
the problem. Take a step back and try
to see the bigger picture of what you
want to achieve. Make sure the problem you are 'trying' to solve is the one your 'need' to solve.
A big whiteboard is great to work on. Use it to write out workflows and relationships. Talk through what is happening with another team member
Move on. Do something else. Let your subconscious work on the problem. Allow the solution to come to you.
write down the problem
think very hard
write down the answer
I can't believe no one posted this already:
Write up your problem on StackOverflow, and let a bunch of other people solve it for you.
My method, something analytic-sinthetic:
Calm down. Take a deep breath. Focus your attention in what you're going to solve. This may include going for a walk, cleaning the whiteboard, getting scratch paper and pencils ordered, some snacks, etc. Avoid stress.
High level understanding of the problem. In case it is a bug, when does it happened? in what circumstances? If it is a new task, try to diverge of what results are needed. Recollect data, evidence, get acceptance descriptions, maybe documentation or a talk with someone that knows about the issue.
Setup the test playground. Try to feel happy with the tools needed. Use the data collected in the previous step to automate something, hopefully the bug if that's the case, some failing tests otherwise.
Start sinthesizing, summarizing what you know, reflecting that on code. Executing once and once more. If you are not happy with the results, return to step two with renewed ideas, diverge more: maybe apply tools (in order of cost) that helped before, i.e. divide and conquer, debug, multithread, dissassemble, profile, static analysis tools, metrics, etc. Get in this loop until you can isolate the problem and pass the over the phone test.
Now it's time to fix it but you have all the tools set up. It won't be so much trouble. Start writing code, apply refactoring, enjoy describing your solution in the docs.
Get someone to try your solution. She can eventually get you to step 2 but that's ok. Refine your solution and redeploy.
I'm interpreting this as fixing a bug, not a design problem.
Isolate the problem. Does it always occur? Does it occur only the first time run on a set of new data? Does it occur with specific values, but not with others?
Is the system generating any error message that appear related to the problem? Verify that the error messages are not generated when the problem does not occur.
Has anything been changed recently? Those are likely places to start looking.
Identify the gap between what I know is working (e.g. I can start up the app and attempt to do a query) and what I know is not working (e.g. it gives me an error instead of the expected results). Find an intermediate point in the code where it seems possible to look for a problem (does this contain valid data at this point?). This allows me to isolate the problem on one side or the other of the point I looked.
Read the stack traces. If you have a stack trace, find the first line that mentions in-house code. The problem is not in your libraries. Maybe it will turn out to be, but just forget about that possibly first. The error is in your code. It's not a bug in java, it's not a bug in apache commons HTTP client, it's in code written in your organization.
Think. Come up with something the system could be doing that can cause the symptoms you see. Find a way to validate whether that is what the system is doing.
No possibility the bug is in your code? Google for anything you can think of related. Maybe it is a bug in the library, or poor documentation leading you to use it wrong.
Logic.
Break the problem down, use your own brain and knowledge of each component of the system to determine exactly what is happening and why; then on the basis of this you will discover where the problem isn't, and hence determine where it must be.
I stop working on it until tomorrow. I usually solve my problem in the shower the next day. I find stepping away from the issue, and allowing my brain to clear, allows a fresh perspective on the issue.
Answer these three questions in this order:
Q1: What is the desired output?
I don't care if this is a napkin with scribble on it. I want something tangible that shows me what the end result is supposed to look like. If I don't get at least this far then I stop.
Q2: What is the input?
I find out what data I have coming in. Where this data is coming from from. What formulas I may need. What dependencies there might be on A happening before B. What permissions if any are necessary to get this data. I then ask Question 3.
Q3: Is there enough input to create the output?
If the answer is No then I go back to Q2 and get more input from whoever can give it to me.
For very large problems I break them down in Phases and apply Q1 Q2 and Q3 to each phase.
To paraphrase Douglas Adams, programming is easy. You only need to stare at a blank screen until your forehead bleeds. For people who are squeamish about their foreheads, my ideal architect-and-build for the bigger problems would go something like this. (For smaller problems, like George Jempty I can only recommend Feynman's Algorithm.)
What I write is couched in an on-site business setting but there are analogues in open-source or distributed teams. And I can't pretend that every, or even most, projects pan out this way. This is just the series of events that I dream about, and occasionally come to pass.
Get advanced, concise warning of what the problem is likely to look like. This is not the full, final meeting, but an informal discussion. Uncertainty in certain specification details is fine, as long as the client (or manager) is honest. Then take a piece of paper or text editor, and try to condense what you've learned down to five essential points, and then try to condense those to a single sentence. Be happy you can picture the core problem(s) to be solved without referencing any of your documentation.
Think about it for maybe a couple of hours, maybe playing with code and prototyping, but not with a view to the full architecture: you should even do other stuff, if you've time, or go for a walk. It's great if you can learn about a job an hour before home time in order to deliver a decision around midday the next day, so you get to sleep on it. Spend your time looking at potential libraries, frameworks, data standards. Try to tie together at least two languages or resources (say, Javascript on PHP-generated HTML; or get a Python stub talking RPC to a web service). Flesh out the core problems; zoom in on the details; zoom out to make sure the whole shape is still distinct and makes sense.
Send any questions to the client or manager well in advance of a meeting to discuss both the problem and your proposed solution. Invite as many stakeholders and your programming peers along as is convenient (and as your manager is happy with.) Explain the problem back to them, as you see it, then propose your solution. Explain as much as you can; pitch the technical details at your audience, but also let your explanations fill in more details in your own mental model.
Iterate on 2 and 3 until everyone is happy. Happiness is domain-specific. Your industry might require UML diagrams and line-item quotations, or it might be happy with something jotted on a whiteboard with an almost invisible drywipe marker. Make sure everyone has the same expectations of what you're about to build.
When your client or manager is happy for you to start, clear everything. Close Twitter, instant messenger, IRC and email for an hour or two. Start with the overall structure as you see it. Drop some of your prototype code in and see if it feels right. If it doesn't, change the structure as early as possible. But most of all make sure your colleagues give you a couple of hours of space. Try not to fight fires in this time. Begin with a good heart and cheer, and interest in the project. When you're bogged down later on you'll be glad of the clarity that came out of those first few hours.
How your programming proceeds from there depends on what it actually is, and what tasks the finished code needs to perform. And how you ultimately architect your code, and what external resources you use, will always be dictated by your experience, preference and domain knowledge. But give your project and its stakeholder team the most hopeful, most exciting and most engaged start you can.
Pencil, paper and a whiteboard. If you need more organization, use a tool like MindManager.
Andy Hunt's Pragmatic Thinking and Learning has a lot to say on this question.
Question: How do you eat an elephant?
Answer: One bite at a time.
One technique I like using for really big projects is to get into a room with a whiteboard and a pile of square Post-it Notes.
Write your tasks on the Post-it Notes then start sticking them on the whiteboard.
As you go, you can replace tasks that are too big with multiple notes.
You can shift notes around to change the order that the tasks happen in.
Use different colours to indicate different information; I sometimes use a different colour to indicate stuff that we need to do more research on.
This is a great technique for working with a team. Everybody can see the big picture and can contribute in a highly interactive way.
I think about it. I take anywhere from a couple minutes to a few weeks to mull over the problem and develop a general plan of attack.
Hammer out an initial solution. This solution is probably half-baked and one or more aspects may not work.
Refine that solution. Keep working on the problem till i have something that solves the problem.
(and this may be done at any step in the process) Ask questions on stack overflow to clear up any difficulties i'm having at the moment.
One of my ex-colleagues had a unique Modus Operandi. Whenever faced with a hard programming problem (e.g. Knapsack problem or some kind of non-standard optimization problem) he would get stoned on weed, claiming his ability to visualize complex state (such as that of recursive function doing operations on set passed on the stack) was greatly improved. The only difficulty, the next day he could not understand his own code. So eventually I showed him TDD and he has quit smoking...
I write it on a piece of paper and start with my horrible class diagram or flowchart. Then I write it on sticky notes to break it down to "TO DO's".
1 sticky note = 1 task. 1 dumped sticky note = 1 finished task. This works really well for me so far.
Add the problem to StackOverflow, wait about 5-10 minutes and you usually have a brilliant solution! :)
The following applies to a bug rather than building a project from scratch (but even then it could do both if reworded a bit):
Context: What is the problem at hand? What is it preventing, doing wrong, or not doing?
Control: What variables (in the wide sense of the word) are involved? Can the problem be reproduced?
Hypothesise: With enough data on what is occurring or required, it is possible to hypothesise, that is, to draw a mental image of the problem in question.
Evaluate: How much effort, cost, etc, will the correction require? Determine if it's a show stopper or a minor irritant. At this point, it may be too early to tell, but even that is a form of evaluation. This will allow prioritisation.
Plan: How will the problem be approached? Does it require specifications? If so, do them first.
Execute: A.K.A. The fun part.
Test: A.K.A. The not-so-fun-part.
Repeat to satisfaction. Finally:
Feedback: how did it come to be this way? What lead us here? Could this have been prevented, and if so, how?
EDIT:
Really summarised, stop, analyse, act.
Probably a gross oversimplification:
But really, this holds 100% true.
CONCEIVE
What are you without an idea? You may have a problem, but first you must define it more explicitly. You have a frozen pizza that you want to eat. You need to cook that pizza! In programming, this is usually your brainstorming session for coming up with a solution from the hip. Here you decide what your approach is.
PLAN
Well, of course you need to cook that pizza! But HOW! Will you use the oven? No. Too easy. You want to build a solar cooker, so you can eat that frozen pizza anywhere that the sun grants you power to do so. This is your design phase. This is your pencil and paper phase. This is where you start to form a cohesive, step-by-step method to implementation.
EXECUTE
Well, you are going to build a solar oven to cook your frozen pizza; you've decided. NOW DO IT. Write code. Test. Commit. Refactor. Commit.
Related question that may be useful:
Helpful points of view, concepts or ways to think about problems every newbie should know
Every problem I've ever had to solve on a computer has had something to do with solving a task in the real world. Therefore, I've learned to look at how I would accomplish something in the real world and map that to the computer problem.
Example:
I need to keep track of my student's grades and come up with a final grade that is an average of all the grades throughout the year?
Well, I'd save the grades in a log (database) and I'd have a page for every student (Field StudentID) and so on...
I always take a problem to a blog first. Stackoverflow would be a good place to start. Why waste your time re-inventing the wheel when someone else may have already solved a similar problem in the past? If anything you will get some good ideas to solve it yourself.
I use the scientific method:
Based on the available information about the programming problem I come up with a hypothesis about what the reason could be.
Then I design / think up an experiment that will reject or confirm the hypothesis. This could be observing something in a debugger or screen/file output. Or changing the program slightly.
If the hypothesis is rejected then repeat 1. The information gathered in 2. may help in coming up with a new hypothesis.
If the hypothesis is confirmed then the hypothesis may be refined/become more specific (repeat 1.). Or it may already be clear what the problem is.
This directed way of find the problem is much more effective than changing things at random, observe what happens and try to (inappropriately) use statistics.
No one has mentioned truth tables! But that's probably because they're usually only mildly helpful ;) (although your mileage may vary) I used one for the first time yesterday in my 8 years of programming.
Diagramming on whiteboards or paper have always been very helpful for me.
When faced with very weird bugs. Like this: JPA stops working after redeploy in glassfish
I start from scratch. Make a new project. Does it work? Yes. Start to recreate the components of my app one piece of a time. DB. Check. Deploy. Check. Until it breaks. Continue until it breaks. If it never breaks. Ok. You just recreated your entire app. Discard of the old one. When it breaks. You pinpointed the exact problem.
I think - what am i looking for?
What method best solves this problem?
Implement it with solid logic - no code
Pseudo code
code a rough cut
execute
These is my prioritized methods
Analyse
a. Try to find the source of your problem
b. Define desired outcome
c. Brainstorm about solutions
Try on error (If I dont want to analyse)
Google a bit around
a. Of course, look around on stackoverflow
When you get mad, walk away from pc for a cup of coffee
When you still mad after 10 cups of coffee, Go sleep a night to think about the problem
GOLDEN TIP
Never give up. Persistence will always win