In a certain sense, I'm still very much a beginner, but I don't need to read C++ Primer or Learn C++ in 21 Days, or at least, I only take a peek every now and then for reference's sake. So what is my problem?

Basically, I started to write a small game to help my process of learning. Along the way, I've learned most of anything that you need to know to be called 'fluent' in C++. I know all about overloading, templates, exceptions, RTTI, polymorphism, etc. I've also taken another small step forward and started using the STL and its containers and algorithms. Recently I started reading about the Boost library. I also read some good material about design patterns and actually applied a couple of ideas to this game of sorts.

But now the whole thing has ground to a stop after about 3k lines of code. Why? It's not that I don't know the language or don't have the ideas. But knowing the vocabulary and having the ideas does not make one a novelist. Even knowing how to write sentences is not enough. You have to understand flow, structure, and all the rest to write a successful novel.

In my practical case, I'm tending to waste a lot of time structuring the code so as to work properly, e.g. I'm losing track of whether to send a certain kind of event before another. The program obviously compiles fine, but the runtime behaviour may not be exactly as intended. I'm also losing track of who owns what, who should take care of what, and so forth. Maybe I'm not strong enough when it comes to algorithms, or maybe the culprit is object oriented design - I'm not sure.

The truth is that the code is starting to look a lot like a chaotic mess, not so much in terms of the actual appearance of the code as in terms of the ideas themselves and their interrelation. The maintenance time has become too much already.

Anyway, sorry for the longish post, but I was wondering what to learn next. I've had a look at the books thread on SO, which is wonderful, but I was hoping for a rather more specific direction. I need to spend less time on the rewriting and more on the actual writing.

+4  A: 

blow your mind

disclaimer: links above may help with large projects by being able to write smaller code. They may not necessarily help you identify architectural design or patterns

That template metaprogramming book looks promising, thanks.
Kristian D'Amato
This won't exactly help him with large project maintenance.
Noah Roberts
@Noah you are correct, but let me explain:meta programming (in my case) removed lots of repetitive boilerplate, leading to smaller code base.Phoenix is lambda library, and lambda functions in my opinion remove lots of boilerplate as well.Free pooma is very well designed to abstract pretty tedious details behind simple templates and their example show it
Yeah, I make use of metaprogramming a LOT (wrote a refactoring library with it actually). But I don't think it solves the OP's problems. It's a good tool to use once you have experience in tearing down problems and making them simpler and get some ideas of what causes problems in maintenance, but it won't help until that stuff is learned. For example, before you can use MPL to remove "boilerplate code" you need to be able to recognize it when you see it and know how and why it will cause problems later.
Noah Roberts
+1 for these beautiful links
@Noah okay, I see your point and I agree with it. I guess once I learned template somewhat I became crazy about them
+3  A: 

Two advices:

  • Learn another language, such as Python or Java.

  • Read a lot of code. (in open source projects for exemple)

This is how you can extend your vision of the programming world.

Pierre 303
I can't vote this down because it *is* useful, but I also can't vote it up because it's certainly *not* the most efficient path for the OP to advance.
Pierre 303
Switching languages and reading other people's code is like suggesting that the best way to learn how to be a professional race car driver is to buy a car from a different brand, and sit on the curb watching other cars drive past. It might be fun, but it's not precision racing school.
Yes like having one and only girlfriend in your life, or going at the same place in holidays every year.
Pierre 303
+11  A: 

Here is what I would recommend:

  • Pick up some books on programming patterns (learn about Singletons, Factories, Reflection, and the list goes on)
  • Practice! Don't stop tweaking your code. When you say you get to 3k lines of code, refactor until you get bored and start something new (use references, try to make each of your projects the best they can be -- even simply for development sake)
  • Follow open source projects in C/C++ (maybe the kernel?) and try to pick up and get accommodated with code -- understand why people thinks its good, what makes it good, and then start making your own judgments (learn how to support your beliefs as to how others program). Check out C++ projects on Github.

Also, look through as many other answers to your question and others similar to it. This is a very popular question in this field with already lots of great responses.

NOTE: As someone else mentioned, learning other languages (in my opinion) is extremely important. Paradigms are applied differently, there are various different specifications to programming languages (type system, memory allocation, syntax, etc.). Most importantly, have fun with it.

I doubt the Linux kernel is a good example to learn from. For starters, it's C. Second, it's a kernel: to get its work done, some good coding practices have to be sacrificed. I do fully agree with your first two points, though.
Okay well I did mention "C/C++" right before it. :) But I agree, it'd be more productive to stay away from a kernel to start. There are a bunch of open source projects written in C++, the one I mentioned just wasn't a great example...
There's a lot to be said for learning about breaking up a project to give it structure, but don't get *too* caught up in the design pattern craze. There's some good stuff in there, but also things that are only really relevant to certain platforms and needs. There are, unfortunately, people who try to use design patterns just because they can, not because there's a good reason to.
Steven Sudit
@Steven, I totally agree, it's more about just being exposed to them and learning to take what you should from them. I think a good example of the point you make is `Singletonitis` -- it's proof that you really need to take patterns with a grain of salt and still make judgments from experience and exposure to appropriate program architecture and design (this is where looking at open source projects comes in handy).
Well said. In fact, I just reviewed some code today that had a singleton purely for the sake of having one, and should have just been a member variable in the one class that used it, so that was a particularly apt example. I think the bottom line on patterns is that you should learn them, but also learn when to use them and (especially) when not to. Besides, Kristian's problem is most likely not going to be solved by a Singleton. Rather, he needs to learn more about layering so as to achieve strong cohesion and weak coupling. The rest of the advice will help him with that.
Steven Sudit
"Singletons, Factories, Reflection" - if your factory is static, then you've picked the three worst anti-patterns to mention. Singletons are terrible because they don't have any flexibility. Reflection is terrible because it breaks too much of language assumptions (screaming LSP violation). In my opinion, understanding the motivation behind a few main principles of programming (OCP, LSP, DIP, ISP, ...) is much more important than learning a lot of Design Patters, many of which are useless.
+3  A: 

Well it seems to me you reached the point to think about architecural design, writing use cases, diagrams and so forth - none writes a well structured 10k+ loc app without any papers in behind. Maybe its a good start to create a UML from your existing code and then try to improve it on a "higher level".

While doint this, keep on coding, reading and debugging. You could debug your app j4f, to see what is really going on.

Books for uml beginning:

  1. Martin Hitz, Gerti Kappel: UML at Work. Von der Analyse zur Realisierung. Dpunkt Verlag.

  2. Bernd Oestereich: Analyse und Design mit UML 2: Objektorientierte Softwareentwicklung; Oldenbourg.

Your answer perks my interest, especially because I have no idea about use cases are or how to make a good architectural design. Any good books on that subject that you know about?
Kristian D'Amato
@Kristian D'Amato I'm afraid I have only german book titles. I will add them to my answer and try to find the english later on.
"Good architectural design" is not really something you can get from any book. You can get it from a LOT of books and a lot of practice but's more an art than a science. Furthermore, just like you can't write a "10k loc" app (that's really, really small) strait out of your head without diagrams, you can't make a diagram without code. The kind of have to happen at the same time and you usually want to proof your architecture with scratch code. Go to and read all of Robert Martin's articles.
Noah Roberts
@Noah Yeah, nice for you if 10k are really really small. But the OP stucks at 3k. Sure you cant get it from a book alone - but you HAVE to read the theory. Even Artist have to learn their handcraft and thats what I want to tell the OP. Of course you can make a lot of useful good diagrams without code...thats why you make them - they are quite independent from the code. See use cases, thats what you want to show the customer, or some sort of. And besides, its not the coding thing what the OP wanted to ask us. He has the code thing, so he can go to the diagrams and SWE theory.
+2  A: 

I've spent about a year working on a DB application. It was my first, and parts of it are getting to the point of being a "chaotic mess." I tried to do the textbook thing and design a normalized database that's flexible, extensible, the whole nine.

But then I ran into issues that you see: adding extra logic takes a long time, and there are several steps to go through to get basic information about objects in the DB because it's normalized. I had added a lot of infrastructure that probably was unnecessary for where I needed to go.

But this is the important thing, and I think it's the same important thing that you can get out of yours: You can see what's wrong with it, and so you can start over and do it better the second time around -- and probably do it faster as well.

So look over your code and find the ideas that aren't working anymore. The idea for me that wasn't working was "normalized databases are superior to flatter databases." That just wasn't true. There are similar ideas in your code. Don't be afraid to rewrite. I was afraid for a while, but now I'm not, and things are moving along better now.

John at CashCommons
Unfortunately this option is not always available. It's of course available to anyone working on a hobby project, but once you start working for someone else your options become fewer. I did finally talk the company into rewriting a piece of software that had been around for ever but if I said, "We need to back up, take what we've learned, and rewrite the rewrite," people would freak out. I think some heads would explode. Refactoring becomes an absolutely necessary skill in the workplace because you're actually rarely given the opportunity to throw it out and rewrite again.
Noah Roberts
True, but the sense I got from the OP's question is that she has a fair bit of autonomy.
John at CashCommons
+21  A: 

Do not get discouraged. You're entering into a major part of software development. Organization of code and maintaining your mindset for how different pieces relate to one another is a significant portion of any substantial programming project.

Try taking a break from the project for a while, maybe only a day. Come back and make a map of all the key pieces of your program and how they relate to each other. Draw this out. Keep it updated as you move forward with your project. It sounds like you need some kind of reference to remind you of how the project is intended to work.

Development is more than just programming, it's a combination of multiple disciplines. You might also try reading a book on design patterns as suggested by other people in this thread. I've used Applying UML and Patterns to some success, and I think you should be able to find a PDF copy fairly easily.

Dean Putney
I've had a look at Head First's *Design Patterns* and the GoF book, which are very good, and approaching the problem that I face. It appears that learning UML is good from your recommendation and someone else's, so I might try that next. Thanks.
Kristian D'Amato
@Kristian: Head First's Design Patterns is a phenomenal book for most readers. Made me want to keep reading and get the work done.
+29  A: 

After many years in the field I have to say that all of these things continue to be problems for me as well. It's just plain difficult to maintain and develop large projects. The larger it gets the more it seems that new development is mostly composed of maintaining and refactoring the old code. You could go to seminars and crap like I have but to be honest, I don't think those people know how to solve the problem either; I always come out wondering if I actually learned anything useful and when I get back to work I find I'm still where I was before.

Every project is different too. It's not like you can learn some secret set of skills that's going to make it all easy.

Part of the problem is that the human brain simply cannot hold enough information in it at one time to be able to track everything that needs to happen in a program of any sizable complexity. The only thing you can do to alleviate this is to compose the project into smaller areas that ARE possible to track. This just takes practice. I read tons of books, went to tons of seminars, college, etc...none of it really did much but give me a couple ideas here and there.

If you make sure to adhere to certain principles it does make getting there a little easier. Things like RAII and patterns are a start but you can also look into the "Principles of Object Oriented Programming"; there's somewhere between 4-10 depending on who you ask. Things like OCP, LSP, SRP, etc...these help to recognize when you're making unmaintainable code.

Of course none of that's a cure all. It's just something that takes practice, and if my experience is any takes f'n years of it. Welcome to the field.


And just you wait until you're not only trying to understand a large project but also integrate and track the works of several developers of varying ability and all with their own ideas of what's good/easy to work with into something that is even remotely possible to understand by anyone.

Noah Roberts
Thanks! That's exactly the problem as I see it, and you obviously have got the experience to back it up. I think when you reach a certain level of complexity the brain, just like you said, cannot and will not keep track of what's going on, so the solution must lie in breaking down the problem successfully. Thanks for the heads up!
Kristian D'Amato
Good advice, particularly about not trying to see the entire forest at once while dealing with each tree.
Steven Sudit
Couldn't agree more with this answer. Can't say much about taking seminars, but what resonates with me in this answer is the _"make sure to adhere to certain principles"_. That's particularly important when thinking about a program's architecture, but also in a broader sense: I find that often, I'm unable to deal well when given too much freedom, so *restricting oneself* can help. This was the incentive for me to quit C++ (which is just one monster of a complex multi-paradigm language) and start with C#. Recently I've become interested in functional programming, for much the same reason.
I haven't seen any reason to quit C++ or go to something else. The same principles that apply to OO apply equally as well to generic programming, which is more or less the other paradigm in C++. The template system also allows me to put in artificial constraints that are otherwise unavailable, like leveraging the type system to enforce dimensional equivalence in physical system modeling or a totally type safe reflection system.
Noah Roberts
(@Noah: C++ is a *wonderful* programming language (and I mean it), but it's just *so* d^#n hard to master. I eventually gave up on it because I was fed up with all those detail choices, such as: Should I use references or pointers here? Do I need to explicitly provide this and that copy constructor, or does the implicitly generated one suffice? I still produced silly syntax errors after years of being exposed to C++. Plus, I was eventually won over to automatic garbage collection once I saw it in action, and I've never looked back. Let's say I prefer tools that are easy to handle...)
@stakx: Even if you've mastered C++, that doesn't mean it's the best tool for the job.
Steven Sudit
If I could choose two correct answers, this would have been the second one for sure. Thankyou for your insight once again.
Kristian D'Amato
@stakx - If you can ask the question, "Should I use a pointer or reference here," the answer is almost always to use the reference.
Noah Roberts
[email protected]:_ Thanks for that clarification, I agree with you on this particular issue. My main argument was that I no longer *want* to ask the question, "`*` or `
+4  A: 

Welcome to the mode of a Software Architecture. Let me tell you my story.

I've started learning Web Development 4 years ago and (me being a nerd) I went ahead and started learning Struts. I went to write my own Web app (still not finished) and found out I'm not coding things efficient or effectively. I went to start learning DAO, then a year later, Martin Fowler's pattern of Enterprise Architecture, then I learned SOA, to Spring MVC, to (the list goes on)

Now, 4 years later. I'm back to square 1 with alot of expertise in what I've gathered in the 4 years of development. I'm still adament to finish this project but for now my advice for you will be.

1) Create your objective about your project. Prioritize them. 2) Design how the end product will be like and start creating an architecture based on....

  • High Level component
  • Low Level Component
  • Middleware (if necessary)

Else, you'll be as confused and as excited as all nerds like me.

Hope this helps.

Learn Software Architecture it helps.

PPS Never rewrite Software ( by Joel Spolsky.

The Elite Gentleman
Rewriting software is not the same thing as throwing out software. Besides, if the SW model changes enough, the bugs that cropped up in the code may cease to apply. Fixing all of those bugs could have been a design issue that is remedied by a stronger design.
John at CashCommons
@John: I have to agree. Spolsky's advice is against throwing out mature, working products to recreate them from scratch. On the other hand, a small, immature product that hits an organization wall is probably easier to rewrite than refactor.
Steven Sudit
I fully agree with both of you. I just thought it would be an added bonus putting the link.
The Elite Gentleman
@john I agree "rewriting" is not "throwing out" which is what Joel Spolsky was talking about. Rewriting with reference to the original is fine and good. Refactoring should play a strong role too.
+4  A: 

I think your problem is that you're focusing too much on learning the language. Learning how to best use a language and design code comes with time and practice, and you're not really practicing unless you're creating actual programs. So it's time to dive in.

So what's the best way to get to the meat of things? Most software, especially visual software like games, utilizes a framework that takes care of a lot of the boilerplate details and also steers the architecture and structure of your code. If you get started with tutorials on how to use a GUI framework, for example, you'll soon be able to flesh out some of the pieces of your application. Then, once you grok the way to do things in that framework, the code will sort of write itself.

+1, because I think you are saying the same as me, just more succinctly.
+82  A: 

Ok, I have 2 answers for you - pick the one that is most relevant.

Firstly, to successfully finish your app, you need domain specific information. This isn't about C++ any more. If you're programming games, you need to read more about how games actually do it. Otherwise it's like trying to write a crime novel having memorised a dictionary and a grammar guide, to continue the analogy. It's not just about flow and structure - those are still fairly low-level concepts. You need to examine how people approach the genre and then from there you can pick out the types of flow and the structures you will need with more confidence. Messy code is often just as much about not fully understanding the specification as it is about not knowing how to program effectively. Knowing the domain helps you pin down clear and well-understood solutions.

I recommend the Game Coding Complete (3rd ed) book by Mike McShaffrey for a good insight into the overall approach to making a game. I have also heard good things about Game Engine Architecture by Jason Gregory but I haven't read it myself. Note that both of these books are quite complex and focused on industrial-strength solutions. If you don't need an industrial-strength solution, you might ask yourself why you're using C++ to write a game when other languages are more suitable for rapid development. Flash is a good choice, for example.

Which leads me on to my second answer: code something you actually care about. If you're only using the game project as a vehicle for learning the language, chances are high that you lost interest as you reached the point where you stopped learning new things about the language and had to start worrying about things specific to games that are more about rearranging the concepts that you already know. This is typically the point where learning is something you should be incorporating into practical solutions rather than something you have to force yourself to do purely for pedagogical reasons. We learn best when the task is interesting.

Love your answer, thanks. I'll have a good look at those two books. It seems like you understand my problem perfectly.
Kristian D'Amato
+1 for both points: domain specific knowledge and interest are certainly necessary.
Matthieu M.
Flash is _never_ a good choice. It's akin to QBasic for teaching and forcing bad programming practices.
I'll add to this excellent answer: find a sample application of the genre you're working on it and dissect it and modify it. Working within an existing large codebase is how lots of us have got to where we are. You get to see others' approaches to large-scale problems and designs. Sometimes they're great, sometimes not. Only experience will teach you in depth which is which. If you want to do games, find a tutorial game to work with. Large full applications that function well as tutorials can be hard to find, but look hard. :) e.g. Apple's "Sketch" sample is a full paint program for Mac.
I tried getting in a sample open source game some time ago but found it a bit too confusing (and frankly, huge, with about 200k lines, hehe). I think I should try something a bit less ambitious at first, perhaps.
Kristian D'Amato
Yeah, getting a "real" application/game is too big for what you want. You want like a huge tutorial project. Apple has some for their platforms; MSFT likely does for theirs too.
@Kylotan +1 really nice answer, however I think You missed some points. See my answer.
@Malfist - you missed the point. I wasn't recommending Flash as a teaching language, but as a rapid development system for games. And for that, it is a perfectly good choice, in that it gets the job done. The quality of Actionscript as a language is a bit beyond the scope of what I'm trying to say.
+1 for the novel analogy. I would have elaborated on that some more...
@Kylotan, I understand that. My comment was more of an aside than anything. I would argue that the Big-O notation for developing in Flash verses something like c++ is much larger. For small programs, flash is okay, you can know and understand the nuances, but for largish programs, flashs' insanities gets more and more in the way. Significantly slowing, or even halting development process. Look at some of the limitations, no synchronous url loading, single constructors which must be public or internal, no polymorphism. It's really atrocious.
All I can say is that if you truly find ActionScript that bad, then I hope you never have to work with Visual Basic or PHP. ;)
This was a bit of an eye-opener for me. I'm in pretty much the same position as the questioner, and I've been stagnating ever since I stopped constantly learning. I assumed the next step was to program some console games, which seemed cool at first but isn't retaining my interest. Only now do I realize that, and it's time for me to take a new direction with programming. :D... of course, I still have to figure out which direction that is, but I'm sure that'll come with time.
@Malfist: Flash (or more specifically AS3) is absolutely a good choice in certain situations, but not always. That can be said for most languages. As for your gripes: No polymorphism? Look again. Lack of synchronous URL loading a serious flaw (outside of a very specific app scenario)? Come on.

If you are doing something about a few k-Lines, just begin with writing your ideas to an text-file, if something like pixel stuff for a pixel-shader (i don't know if its the case) isn't clear or something else just take a paper and draw what the algorithm does how (especialy if something isn't working).

And of course, UML and that stuff helps for realy big project with some teammates but UML is no source-code. So if you realisize after the plaing phase that ur UML ideas don't work you need to rethink the whole system...

And don't forget to document your code with a System like Doxygen, this is everytime helpful if you took a break for week or months.

+2  A: 

I think your first issue is the focus on technic.

Technic is important, but ultimately it's a tool, not a goal.

In General:

Ditch UML: it's a communication tool, to document the project. You're better off drawing freely, and not being distracted by specific syntax / construct.

Take a glimpse at the Patterns if you wish so. But ultimately they're more about communicating and fixing ideas, you'll probably realize you had the basic ones yourself (factories, singletons, prototypes): it's logical, after all the patterns were identified from existing code, and not the other way around.

Ultimately, I would say that you should learn to think by (and for) yourself. Some reading along the way cannot be bad, but don't focus on learning, focus on doing and you'll learn naturally.

For this Project:

Wait for the week-end, and some calm.

  • Analyze the problem: if it's vague you'll fail. State the requirements, try to break it down into subproblems and analyze them in turn until you have precise requirements.
  • One at a time: often times the main issue is to think too generally. You'll want to see the solution to the generic problem but it's just too vast for a human mind to encompass.. It's better to take one of the problem, which dependencies have solved already (or which has none) and solve it. It also help measure your progress, which is good for motivation ;)

And for next time ? Well, you'll have more experience, so it'll be easier to decompose and you'll spot difficulties ahead of time.

Matthieu M.
+7  A: 

I think it's time to stop architecting for a while and start finishing your application. You say "the runtime behaviour may not be exactly as intended" and while you might mean that sometimes you don't get what you intended, I have a sneaking suspicion that you're not very familiar with the runtime behaviour of this code you're lavishing attention on. I've worked with guys who would rewrite functions over and over "for performance" at a time when the app as a whole would not build and that particular function had never ever been executed even once.

I think this whole writing code thing is going to make a whole heap more sense if you now spend some time running your code, testing your code, working out where it doesn't work and what to do about it. Along the way you are going to find places where all you had to do was put a -1 somewhere, or move one line before another, and places where you have to change 16 function calls to all take an extra parameter or check for a magic return value or something, and while you're shoveling away in one of those parts of the code, you're going to have a lightbulb moment connected to something you've read that just became concrete for you.

If (and I doubt it) your game works perfectly when you run it, then simulate the business world. In the real world tax rates change, companies start selling things they didn't use to sell, or offering discounts on volume, or suddenly have two of something they swore they would only have one of. Do something like that to your game. Like what if you can have two weapons or your backpack can hold another backpack or you can wear a ring that makes you stronger than the maximum or whatever makes sense (or more importantly, doesn't make sense) in your universe. Now, what do you have to do to your code? Again, parts will be easy and parts will be painful. Connect the pain to what the books said. Notice if using STL or using Boost or using design patterns or restructuring the code that 11th time have made this pain worse or better. Notice what techniques were easy at first but made changes hard, were hard at first but made changes easy, or achieved the nirvana of easy at first and make changes easy.

Then you'll be ready to do it all over again on a completely different application in a completely different domain and learn the same things again, and from this will start to build a sense of universal rules vs project specific rules. Of course since you're still likely to be in a team of one they won't be as universal as they could be, but it will be progress.

Most people don't think about it this much at the beginning. It's not wrong to prep so much, just unusual. But thinking alone doesn't solve problems. Design patterns alone can't delight users. So run your code and do what it takes to make the runtime behaviour all that you want. Learn the meta lessons about your architecture and your methodology from that process.

Kate Gregory
+1 I agree totally. Finish something and get some feedback on it! Making incremental improvements to something that is working is a lot more fun. And it will give you great insight into how to create your next project.
James Westgate
"...if you now spend some time running your code, testing your code, working out where it doesn't work and what to do about it." I agree, and would add "profiling your code." It's important to learn that, if you're not getting the performance you need, your intuitions about what's bottlenecking performance are often wrong. See (for example) for discussion.
@eggsyntax good point. Maybe even write something two ways and profile both to see if it made any difference.
Kate Gregory
+3  A: 

You are ready to take that next step that makes young developers hate old developers: learning the "right way" to do things.

You've learned the technical mumbo-jumbo, now you're ready for deeper theory. It's time to learn stuff like the SOLID principles, Design Patterns, and other "you should do it this way" type policies and paradigms. I'm not saying you should follow them slavishly -- even SOLID, which I consider to be one of the most important set of rules for software development ever, can (and should) be broken when necessary. The point at this level is to learn why those rules became rules -- what's good about them? why do they do it this way? -- and when they should be broken for the sake of getting the job done. Learn when to use inheritance and when to avoid it, and why.

Start looking into the other tools of the trade, like UML and modeling in general. Learn how to take a step backward and view your application or system from the top down as well as the bottom up.

And teach! Pass on what you know, and in doing so better yourself.

+1 for teaching
+6  A: 

Whether you use data flow diagrams, mind maps, or uml diagrams, spend some time trying to visually organize your thinking, your goals. Keep it informal and do what works best for you. Trying to keep it all in your head is nearly impossible. I am not advocating documenting your system, just exploring your ideas, keeping the diagrams around just as long as they remain useful. You can explore many ideas and solutions in a fraction of the time it takes to write them, whether test driven or not.

Someone mentioned Larman's Applying UML and Patterns. Useful, though you may not be quite ready for it or anything else heavily architectural. If you are, definitely learn a bit about patterns. They may or may not help with organizing your thoughts, depending upon your domain. Understanding your domain is critical. Google for domain analysis and design. Another good book, though java centric, is Growing Object Oriented Software, Guided By Tests. The authors present some very good thoughts on designing systems and how to explore your options through tests and mock objects.

Several have mentioned learning another language. While learning another language can lead to a real epiphany, I believe a much bigger bang comes from a deeper understanding of design concepts and graduating to architecture and analysis. Of course, they all speak of modeling, but modeling itself is just a tool. See Scott Ambler's stuff on Agile Modeling for great suggestions.

Bill Turner
+1 for Craig Larman's fantastic book.
+3  A: 

I may not be getting at the right problem, and correct me if I'm wrong since you may know already know what I am going to say or I may have misinterpreted your question, but it looks to me like your biggest problem may have been a lack of a cohesive plan.

Anyway since you started with a novel writing metaphor I'll run with it. What is the difference between a successful novelist and a guy like me BSing his way through a college essay for his humanities class (besides the amount of interest in the topic of course)? The novelist had gone to he trouble to finish his process of though write an outline and then go through multiple drafts of his book most likely one chapter at a time. In other words he has a picture of the final novel in his head and the product one piece at a time until it resembles that picture the closest.

To put this in perspective in the programing sense I will illustrate to problems I have encountered in the past regarding having this overall picture of a program and how it runs.

The first is a lack of picture. The best example for me is when I had to write a program for a test in college since I only had about an hour and a half to do them. Since I didn't really have any idea what the whole thing was going to be or just had a number of abstract ideas and wasn't sure how I would tie them together in the long run. In this case I always produced a piece of code that compiled and had the minimum functionality but had very awkward programing and tended to be sluggish e full of bugs. This is since I couldn't predefine how all my ideas needed to fit together and would just wing it.

The other was also in college and it involved a software engineering project which ironically was to write a game of pong that could use table pc functionality. We all had a good idea of what the overall functionality but not a very good idea of what specific pieces we needed to achieve it or how they related and this kept changing with every phase of the life cycle. This produced a number of individual modules which were generally good on their own but couldn't work together since we weren't able to get a concise picture of who called who when, for what and how.

So basically here is my recommendation to you (and I am still learning myself). First make sure you decide how your idea is going to fit in with the rest of the ideas before you implementing it and finish its implementation before doing anything else that would affect it. If you keep changing it you will eventually loose track of how it fits in and if you do too much at once you will end up deciding on something that may not fit with the way you decided to implement something else. For example you will want to wait until your game is finished and functional before you implement a save/load function. if not every time you implement something new you will have to rewrite the function and if you give it full functionality before implementing everything else you will end up with a bunch of code that doesn't compile or run since not everything it calls is implemented yet making any other debugging a nightmare.

Also work on every idea in a separate concise manner. For example you have 2 menus in your game the affect each other. First you would work on one menu. Get it to visually appear and then get all functions that only affect that menu to work properly. Do this on function at a time and debug each function as you write it. Then do the same for the other menu. After they are 2 functional self contained units work on the communication between them. This way both menus are already working and when you work on their communication you can focus on how that will work and fit it in to the already existing structure. In my experience if you try to tackle both the menu's implementation and communication at the same time You will encounter the problem you are having.

I hope this answers the your question and correct me if I happened to misinterpret it.

Yes, you have very accurately described the problem as well. I do understand what you mean by working on each separate idea concisely, and I do agree that 90% of the problems are not having it thoroughly well planned beforehand. But sometimes, it feels as if the novelist (programmer) loses track of his characters (objects, functions, event handlers, whatever), or rather, the way they interact between themselves. I can't imagine what it would be like if you're at 100k lines of code and have to struggle with remembering who handles what, etc...
Kristian D'Amato
Of course, that's what good encapsulation and object oriented design is all about I guess, but it's much easier said than done!
Kristian D'Amato
@Kristian D'Amato I completely agree with what you have to say, and I do say that I also share the common hatred of documentation and would rather use code and fix. But when it comes down to 100k lines of code I think at least a basic outline would probably be necessary to keep your sanity, and I say this since I avoid doing it like the plague and prefer to use coda and fix which has lead me to sometimes encounter the problem and sometimes not. Bottom line I guess if your program is getting that complicated make a simple diagram to keep your sanity.
+1  A: 

I was in the same boat. I knew languages, but what I didn't know was Design Patterns and Best Practices. That and knowing a bunch of standard Algorithms and Data Structures will go a long way towards helping you structure and design your code in a better way.

The good thing about knowing these things is that you don't have to be limited to one language. The best practices and algorithms that you learn can be applied to different languages. Of course, each language will have its own set of paradigms and best practices, but there are a few core best practices that you can use in almost any language.

I recommend reading Pragmatic Programmer. It is language-agnostic and goes a long way towards helping you become a better programmer.

Good luck!

Vivin Paliath
+2  A: 

Martin Fowler's book 'Refactoring: Improving the Design of Existing Code' should also be useful to you. Reading it might help you bridge your understanding between code at the lower levels and the architectural decisions and concepts you wish to learn about. It will also help reveal some of the motivations for those decisions.

Not forgetting it should also help you to restructure your existing project into something less messy and unmaintainable!

Thanks, that book is among the top ones on my list for next buy!
Kristian D'Amato
+2  A: 

If you are losing track of which code is responsible for what, most likely you aren't using appropriate abstractions.

If you've learned the "real world objects" model of abstraction and then jumped straight to the Design Patterns book, you've probably missed something in-between. Imagine a group of office workers implementing your game logic. There will certainly be people "doing", but there will also be people "managing".

Managers are pretty common programming abstractions. They typically contain either multiple objects or multiple references to external objects. They often "own" their contained data, meaning they are responsible for ensuring it's deleted - but very often they delegate that responsibility to something else. The key point is that the abstract some particular role or set of responsibilities, rather than some real-world "object".

I'm in no sense a games programmer, but like many, I've written occasional casual games in my free time. Some useful manager abstractions I seen used a lot, and have copied myself, include...

  • Event manager - basically a queue of event or message objects, responsible for ensuring that each event is handled at the appropriate time.
  • Task manager - a container for ongoing "task" objects (typically small state machines), responsible for ensuring that each task gets a chance to update with each game loop, and that completed tasks are cleaned up.
  • Game object manager - a container for game objects, but also responsible for multi-object actions such as update-all-AIs, update-all-positions, check-for-collisions. It's sometimes useful to have a tree structure for game objects - following objects being children of a leader, limbs being children of the body, etc.
  • Platform component manager - e.g. DirectX graphics manager. Basically narrows the gap between the excess generality and complexity the platform provides and what your game needs.

Basically, if you are losing track of the details, you need to delegate the responsibility for those details. Then you get back to the big picture.


An example... Imagine one of those sliding tile puzzles. You want to animate the tile slide. You also want up to three tiles sliding at a time, and you want the three tiles to start and stop at slightly different times to give a more visually appealing effect. Each tile should accelerate and decelerate, rather than move at a uniform speed.

That could already be a fair bit of complexity. On the other hand, you could just fire off up to three start-tile-move events. Each of these, at the appropriate time, starts a tile-moving task. Each task does position updates with each game loop until the tile reaches its target, then fires off a move-completed event as it dies. When your main game logic recieves the last of these move-completed events, it knows all the animation is done, and it's ready for the next move.

The point is that each tile-moving task is very simple, and you aren't piling up more and more responsibilities on the tile object itself. Your event and task managers do their job, keeping that clutter out of other places. Event the event could be a special task-starting event type, so that delayed task-starting is only coded up once. Your main game logic basically just detects the key/mouse event (probably another manager role), fires off the events, then waits.

@Steve314 +1 for Your comprehensive and detailed answer. However I think the OP's problems are deeper rooted. See my answer.
+19  A: 

This is a complementary answer. It is not intended to replace all other answers, but to add to the great information already provided by them. There are some very good answers and I've upvoted them accordingly, but still I think that all of them miss one point.

What Your question is NOT about

  • Game Design: This point addresses Kylotan's and Steve314's answers. (which are great). Yes You're stuck in the development of Your game. Further You're stuck at a point, where the reasons for the stall do not lie in Your lack of knowledge of the C++ programming language. So the suggestion to gather domain specific knowledge sounds plausible. However, I think that there's one point in between these two: Application design / program structuring / software engineering / whatever you want to call it. You should address these points.
  • Design Patterns: This point addresses answers suggesting books on this topic. Design patterns are a subset of overall software design and therefore address the issue I mentioned in the point above. However, solely studying them will not teach You when, where and how to apply them. I would even go as far as saying, that a design patterns book in the hand of an immature programmer causes more harm than help, as he/she is being provided with a huge toolset but no idea how to apply it and will therefore choose the wrong tools in the wrong situations based on his/her limited experience.

What Your question actually IS about

Your question is about a mentor. Yes You've learned to fluently program in C++ (more than I can say of myself^^) and You might no longer be a beginner. But You are an immature programmer! (every good programmer is immature till the end of his life). I think what You really need is a mentor, a person that will have a look over Your code and suggest how You could improve it based on his years long experience and maybe share some of his/her passion with You ~ along the lines of:

Mentor: "Wow, I really like Your game, nice job mate! Hm, that's the part that causes You trouble?, let's see. I think these two parts of Your programm know too much of each other and every change in one results in the need of the change of the other. But we can decouple them with an interface, it's easy, you'll see =D...".

To summarize: From my point of view You should focus on software design after You've learned the language. Some answers point that out as well by suggesting books like "The Pragmatic Programmer". And until You don't find a mentor, I think these are Your best bet, but from my point of view they will never be as effective as an experienced, passionate programmer that can explain concepts, patterns, design decisions (and reasons), ... to You in an easy to understand way.

Mastering programming takes long. Don't give up, code something that You enjoy in order to not loose interest too early as Kylotan suggested. I wish You all the best!

+1 best answer here
+1  A: 

I've been where you are. Now you need how to learn how to get stuff done. On the plus side for you, its easier now than it ever was to connect with other software developers. :)

One of the classics on software development is the book Code Complete by McConnell. You should buy it and read it.

There is a limit to how much play you can do with a language - eventually, you want to get stuff done, and you need to be able to get it done in an organized, timely fashion. So now your task is, using something you want to get done, learn about the task of code construction.

Paul Nathan
+1  A: 

First off be aware that game programming (and the design) that goes along with it is one of the hardest programming that you will come across, so don't be discouraged by the fact that you are having trouble. On the upside it sounds like your definitely heading down the right track with your learning process and I applaud you pursuit of best practice and knowledge of how to effectively use your selected tools.

From where you are now I would suggest there 3 things that will significantly aid you in feeling more in control of your software.

1.) Learn as much as you can about Object Oriented development. This fundamentally addresses your feeling of disorganisation. If you get your OO right things will make sense and scale much better as you progress. IMO this is the heart of engineering, doing it well will make you great.

2.) Look at Design Patterns. They are of great help in many areas of architectural design and will allow you to design for code that will scale.

3.) Look at the body of knowledge with regard to game design. Check out for some of this, and there are HEAPS of books on amazon.

Now finally I would say that once you start getting this stuff right you will genesis from being a programmer to being a software engineer (the difference is significant and important). A programmer knows how to write code, algorithms and use libraries to get the job done. A software engineer knows all of this and also has an organised and reproducible process to tackle any task, generally using architectural design techniques.

Most of what you want here must be gained through experience, there is no quick fix. I would recommend constantly looking at your architecture and imagine a redesign from scratch, you should at least be able to spot where you went wrong and if you can't keep looking!. The key here is iteration, design again and again until you get it right (or close enough).

There are three books that I would recommend:
Design Patterns // the first and seminal book on design patterns
Modern C++ Design: Generic Programming and Design Patterns Applied // awesome architectural design book
Game Engine Architecture // is what it says, good knowledge to be found

+1  A: 

When I was a few years into programming experience, a friend recommended a few books to me:

  1. The Practice of Programming -- Kernighan & Pike
  2. The Elements of Programming Style -- Kernighan & Plaugher
  3. The Mythical Man Month -- Fred Brooks Jr.
  4. Programming Pearls (and the followup) -- Jon Bentley (note, this is not about the Perl programming language)

It's not a coincidence that Kernighan authored two of those books. He really (really) knew what he was doing with the whole C & Unix thing. I ended up reading "Awk & Sed" too simply because I liked the writing style, but it also gives you an insight into what went through the minds of a few brilliant programmers.

I read these books on the bus back from work every evening, and I could feel the change in my approach to programming every day that I got back to work. The order of reading these books doesn't matter. Each book has its own lessons to teach. Don't read them only for the programming lessons, but also for the writing style. Understand that your code needs to be prosaic. A good programmer can write good prose, and his or her code becomes easier to read and understand.

A few other things I've learnt...

Learning different programming paradigms teaches you to think about the same problem in different ways. Very often a small part of your application is better suited to a different paradigm than the whole of your application. I found that writing in Perl allowed me to use multiple paradigms in the same source file. It wasn't necessarily the best code I'd written, but it helped me visualise and understand the problems I was trying to solve.

A visual language (I started with Spectrum BASIC) is great for prototyping and getting interested in what you're doing. Don't worry about it teaching you bad programming practices. You can't avoid mistakes unless you first know what they are.

Longish answer, but I hope it helps you and others.

+2  A: 

Previous posts have mentioned Fred Brooks and The Mythical Man Month. One of the great quotes in there is, "Plan to throw one away; you will, anyhow."

As you've been working through your current set of problems you've likely learned some things that work and others that don't work. Unfortunately it sounds like things are so tangled up that's its hard to extricate the good bits from the bad. Why bother, particularly as the point here is to learn and practice? Start over using the insights you've gained. Trust me, it'll take a lot less time the second time through. If you can find someone more senior to critique your design that will speed up the process as well.

Following in the novel analogy, writers don't publish their first draft. There is a lot of revision that happens behind the scenes. Think of it as practice. Another writer technique that would help is the writers workshop. Writers bring their work and ask the opinions of their peers. Sometimes an outside look can be very helpful.

It's like the guy asking for directions to Carnegie Hall:

Q: "How do I get to Carnegie hall?"

A: "Practice!"

Paul Rubel
+1 great hint, @Kristian: Don't get frustrated about Your programming problems and don't get a too big headache about which books to buy^^, You'll improve by time automatically.
+1  A: 

I'd be tempted to say that C++ is a special case because it's a multi-paradigm programming language (as designed by Bjarne Stroustrup, as a superset of the C language).

C++ by itself does not impose a particular programming style, or a specific code structure. You can use a varying subset of its functionalities, being functional programming, structural programming, using templates, multiple inheritence... You can even not use classes at all.

When you start a relatively large-scope project, you should stick to a well-defined set of features and a consistent programming style. I'm afraid C++ is not a good language to learn that kind of discipline, due to its versatility. That's why I would recommend expanding your horizon by learning other languages that might teach you such discipline.

Java is a good candidate in my opinion, and I'll explain why.

When I first learned programming, I was taught a subset of C++ that I thought was enough to create whatever idea I had in mind. However, I soon started to develop programs with a lot of pointers around and poorly controlled memory ownership.

Then I started learning Java, which really frustrated me at first, with its "one class per file" policy, and the use of imports and packages, as well as single inheritence only, and lack of operator overloading. Soon after, though, Java, being strictly object-oriented, and a relatively simple and clean language, made me adopt a certain pattern of thought, to focus on clean code organization and reuse. I also learned how to really plan ahead better in terms of architecture, especially thanks to interfaces, that allowed me to better isolate components between code units, and focus on solving local problems without affecting the larger structure.

When I then came back to C++, I started to better organize my source code using namespaces, proper file and variables/functions naming conventions, and re-discovered C++ features like pure virtual functions and abstraction, as well as references instead of pointers. All in all, I learned a coding style that I found convenient and pretty reusable over projects. (and that was before I even properly learned STL).

Last but not least, there's also an important point in learning a language: one's own code never looks pretty to read after a while. The more you learn, the more you can see your past mistakes, and the more you are tempted to refactor your code if you're still maintaining your project. Do not refactor your code too often. Instead, focus on other things, go on with learning, and then, come back at a later time to better see what you did wrong. You then have a much broader perspective, so you can get it right, and write code you feel proud of !

+1  A: 

It sounds like you are at the turning point to where you have hit the wall in progress and maybe even the "programmer high" for your application. Working solo, this can happen quickly sometimes, but it is common for sure.

For my application, this is the point where I had to go back and update my spec. Hopefully, you have a specification of what the design is and what you exactly what you want it to do. It doesn't have to be super formal. See what Joel wrote on it: Joel on Painless Specs. In the early fun stages, the program grows in your head. All the possibilities, the cool things it could do. It gets rough to keep it all under control, so this could be a good time to step away from the code and write down exactly what you want version 1 to do. I had to remove features and update the design to be a simple version to make sure I just got a working version done. This is really helpful. You know there is a "version 2," but sometimes you can overdesign and try to plan for all the upcoming stuff, churning away. You have to nip that. Get your version 1 working and put it out there. Then iterate. You'll have to redesign. You'll have to redo stuff. That's okay. Your knowledge of the application will be growing. And you can abstract more and more as you go.

+3  A: 
Norman Ramsey

I am not an expert but just wanted to say somethin about languages. Language is just a way to express some concrete logic. You can try the following to get out of the language mess. Take a logic and code it in C, C++, Java, Python etc. This will get you to think only about actual solutions to your problem, rather than the language specific features. For that matter don't even stick to design patterns/UML. They evolved as a result of logical arrangements of sub solutions. I feel its better to think in terms of how an ideal solution(not bound by any construct/limit) will be and then fit it into your current language. Just concentrate on semantics, everything else is BS, be it the greatest language in the world.


I think what you also recognise is that a lot of software is actually quite innovative, pioneering and specialised. There are no books on "How to write a High Performance Web Server in 21 Days" or "High Frequency Algorithmic Trading Systems, A Primer".

Such knowledge (even for professional programmers) is gained over time, by redesigning and refactoring code. Software development is often highly iterative. Most of the time, there is no best way of doing things, but lots of different approaches that are tried and tested, each with their own trade-offs. Sometimes, a completely new approach may be the best option.

If writing games is your cup of tea, why not also participate in the the development of an open source game? Learn from many different open source projects, if possible. What works well? What does not work well? Learning from experiences is also an important part of software development.

Learn the theory, and more importantly, learn how to put it into practice effectively. For example, years after design patterns became common (or required) knowledge, software developers realised that design patterns could be overused, resulting in over-engineered software that was bloated and difficult to maintain.

+1  A: 

congrats on your promotion to the rank greater than a beginner. Soon you will discover, by knowing more, that you really don't know much at all. This is not intended as an insult, it's more philosophic. Let me give you an example:

  • Fresh out of University, Frantic Freddie, as his friends call him, is on top of the world. Frantic knows Java and C#, and can even write a linked list. He gets a job as a Jr. Programmer and begins to critique his collegues code. He can do it better, faster, stronger than the others. He eagerly rewrites a lot of the core of the application (without permission) optimizing the threading and memory management of the system. Proud of his work, he checks it in. All 924 Java classes, refactored Frantic Freddie style.

    The lead, horrified at the 924 diffs he just received in email, runs over to Freddie's desk and screams: "Why did you do that?! Why did you change that entire code base?". "Relax", Freddie says with an arrogant smile. That code was inefficient. I did you all a favor and rewrote it in my image. Now it's super fast!! "No, screams the development lead! You don't understand! That code base serves as an example of how not to code! Now I want you to revert all your changes!" Freddie, confused at the issue just nods and says "Ok", and begins reverting. The lead, looking at Freddies changes as he reverts each class suddenly stops him in his tracks and says "Actually, hang on a minute. Why don't you just leave it all checked in as is"

And on a more serious note. I've been coding for 18 years. Started as a machine language coder on 68000 Motorola series processors for automating industrial production lines, then to dBase III, then dBase IV (radical difference), then to C, VB, C++, Delphi, and the last language I learned was Java 10 years ago. And you know what? I still find ugliness in my code, it doesn't look good to me, I always think it could be better. The code usually works and is maintainable but I am far from achieving a Nirvanic state of coding. You may discover that you will be your own worst critic. And it's fine to criticise yourself as it makes you better, but don't forget to praise yourself once and a while too.

billy vandory
+4  A: 

I want to address this one issue you raised I'm also losing track of who owns what, who should take care of what, and so forth This is an EXCELLENT question!

If you get this wrong, your code WILL end up being more spaghetti-looking than elegant, and be VERY unstable and crash at seemingly "random" times.

Two important issues: Object Lifetime, and Object Ownership. In UML, its the subtle difference between a solid black diamond vs. a hollow diamond, but I don't want to discuss UML semantics.

Object LIFETIME deals with WHEN an object is instantiated and WHEN it is destroyed.

Object OWNERSHIP deals with WHO is responsible for instatiating the object, WHO is responsible for destroying the object, and WHO maintains the "reference"(s) to the object (yes, one object can be referenced by MANY other objects). Interestingly, there could be 1 object that does all the creation/referring/destroying, or different objects that do each one. Obviously, these two issues go hand-in-hand (i.e. LIFETIME of an object is defined by the object(s) responsible for creating/destroying it).

Many times, objects are completely owned by other objects, and their lifetimes match exactly, e.g. a CPerson object contains 2 string objects, Name and Address. However, a CEmployee object derived from CPerson may also have a member that is a container of CEmployer objects, and these CEmployer must NOT be "owned" by this one CEmployee object because the LIFETIME of the CEmployer object is completey different than the lifetime of the CEmployee object, yet the CEmployee's name and address strings are OWNED by the sub-class CPerson because their lifetimes are identical.

This could be modeled as

class CPerson
      string Name;  // Name and address strings are completely OWNED by CPerson
      string Address;

class CEmployee : public CPerson
      HiredBy(CEmployer *pNewEmployer);
      DownsizedBy(CEmplyer *pEmployer);
      CArray<CEmployer *> aEmployers;  // I do NOT own any of these CEmployer objects

Questions to-be-answered: Who creates the CEmployee objects? Who destroys them? Who creates the CEmployer objects? Who destroys them? How do other code access a specific CEmployee object - via the employer using an employee ID? via a singleton CMap using SSN?

If you are using a framework and deriving a lot of YOUR classes from the framework's classes, many of these LIFETIME questions are implemented by the FRAMEWORK - BUT YOU STILL NEED TO UNDERSTAND IT, otherwise, you may attempt to dereference a pointer to a CPerson object and find out that it's been deleted!! By who? When? Why didn't I know it was being deleted?

If you are responsible for most of these lifetime questions, get that designed out in detail. Improper Object lifetime implementation can cause crashes (by dereferencing deleted pointers), or memory leaks, which can become substantial in a gaming type app (imagine you were never deleting any "ground contour" graphic resource objects and 30 minutes into the game it CRASHES due to low GDI O/S resources or heap memory)

Objects within functions that are allocated on the stack, get used, then are auto-matically destroyed when the variable falls out of scope is EASY when it comes to lifetime/ownership issues. However, objects that must be dynamically created due to their design requirements, or must be in heap due to their runtime dynamic behavior must have a thought-out lifetime/ownership design.

Yes, I'm talking about that subtle UML solid black diamond vs. hollow diamond. Design and document that right, and it will make your set of classes that much easier to use.

+1 for posting on this important issue. I never explicitly thought about object lifetime and ownership until I looked into the dependency injection pattern and IoC containers, and at the RAII idiom and `std::auto_ptr` in C++.

I've run into some of the same issues with some of my code. Basically, I realized I have architecture problems with it, and need a better design. You need take your game back to the drawing board and really think through the best way to implement the flow of it, and then refactor from there. It'll put the fun back into coding as well, as you'll know where to put everything and can be confident that the cool algorithms you come up with will be effective in your program.

If you try to work through refactoring, and still draw a blank, then you should probably go to experienced coders. Either read game design books written by great people, or try to work with great people. It's not really about algorithms as much as it's about the overall structure and architecture of how the code works. The algorithms are more for making certain parts of the game fast, better, etc.

Anyway, good luck!


You need to start to use graphical tools like UML, to have an overview of your code.


You just learned an important lesson. You really need a blueprint before you try to build a house.