• Advertisement
Sign in to follow this  

How do you think when programming?

This topic is 3840 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This is a very interesting topic which I feel could help people starting out, so share your techniques on how to think while programming :) I believe the problem when starting to code is in not knowing how to actually think effectively when coding, most people just start out learning a few functions and going from there, but is that enough on becoming a professional? What goes through the mind of true professionals such as John Carmack when they code? what emotions do they experience when coding? is there a particular mind set you must have for a particular language and is it possible for everything just to 'click' in to place after understanding certain key concepts? Please share your thoughts and feelings on this :)

Share this post


Link to post
Share on other sites
Advertisement
Interesting question, but I wonder if it can even be answered, and, if I can answer it, is it worth even doing so? Could you yourself adopt the same mindset I have when I work just by simply reading my words?

When I am coding I tend to be very 'visual'; the whole structure of the code is largely just shapes that get kinda shoved together, lines drawn between them (connecting them), and they warp in to many different things as I ponder the structure. Also I do all this with a single goal in mind - whatever the particular goal I am working on.

It's extremely difficult to describe since - when I think of a member of a particular class, I sort of zoom-in to the giant square that is ClassA and imagine attaching functionality to it... then I zoom out again to perceive its effect on the whole structure of the code itself, or normally, just the area I am currently working on... Like Google Earth, the farther I am zoomed out the less 'fine' detail there is, and as I get closer to an object the more detail I see.

Share this post


Link to post
Share on other sites
I definitely don't start typing until I have at least a basic idea of how a feature will work. After I figure out how to implement the feature and while I am doing the implementation, I think a lot about what the side effects, special cases, and limitiations might be. That's when those issues are most visible. When the implementation is done, I test it to verify basic functionality and also test potential problems uncovered during implementation. It might take a couple passes, too.

Share this post


Link to post
Share on other sites
I tend to do the same as JohnBolton.

I also tend to work outwards from core systems. For example, in my latest project, I began by Building the Window and Application Classes, Followed by Renderer Abstraction, Resource Cache, and then my GameState Manager. When it came time to write "Game Code" 95% of the Engine was in its final configuration, making it very easy and very quick. I can, and have, knocked out simple game-states (such as the credits) in less than 5 minutes.

I also tend to re-factor as soon as I see a "real problem". For instance, initially, my Resource System was based on handles. This had the unfortunate side-effect of forcing my Resource Cache object to be a singleton to get the behavior I desired (handles should directly "dereference" to their resource type). Switching from a handle-based implementation to one based on smart pointers provided the behavior I wanted and also resulted in shorter, cleaner code all around. Despite the centrally important nature of the Resource System, none of the "game code" was disturbed, because the interfaces were solid -- that's another thing I tend to think about as I make implementation decisions: How might I have to change this system in the future, and how do I design now to make it easy to change in the future?

Share this post


Link to post
Share on other sites
Quote:
Original post by Virtual X
This is a very interesting topic which I feel could help people starting out, so share your techniques on how to think while programming :)


And such things (or things similar to it) are a little too infrequently discussed.

Quote:

I believe the problem when starting to code is in not knowing how to actually think effectively when coding, most people just start out learning a few functions and going from there, but is that enough on becoming a professional?


No, not really, though you might be surprised how many professionals know a few functions and go from there.

Personally, I think there's a distinct middle step where you need to better understand the difference between programming (fighting with syntax to do what you want) and program design (fighting with organization to allow you to do what you want more easily).

Quote:

is there a particular mind set you must have for a particular language and is it possible for everything just to 'click' in to place after understanding certain key concepts?


For some. Functional programming is notorious for this. Sure, it's possible to make fairly large leaps after catching a certain concept. Pointers are the often given example since they tend to have that 'click' effect. Still, things don't just snap and suddenly you're a competent programmer. Even professionals have strengths and weaknesses, various levels of expertise with various flavors of problems.

Share this post


Link to post
Share on other sites
It depends on the task being performed. Sometimes you have to be in the optimization mindset, where you are writing efficient code. Other times you have to be thinking one step ahead and anticipating the problems that the current piece of code could cause. Where are there likely to be errors or malfunctions. You also have to be aware of when you need to break up code or split out common code, etc. Evaulating the refactoring needed in advance.

Writing from an existing specification is different than developing some new technology proof of concept.

Share this post


Link to post
Share on other sites
That is an interesting question, and I've never really thought about it. I have to say that I like the idea of coding visually like JohnBolton said, but my brain doesn't work that way. For me it's nothing like that.

On the lowest level I generally code by gut instinct: if a set of code doesn't feel good, then it's scrapped and rewritten. Generally when I've written some code - on some conscious or subconscious level - I'm aware that I've either written correct code, or C++-shaped gibberish.

Despite working in graphics, I'm not a very visual thinker. I am a visual person, but I'd say I'm predominantly an audial thinker. I do design, and I do my design in a visual way (such as class diagrams), but most of the time it's because I can "hear" the connections in my head as I draw them. As I code, I remember these connections, and it's almost like my brain repeats them to me as I work. "The manager class connects to the child class... The hip bone connects to the leg bone..."

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
I definitely don't start typing until I have at least a basic idea of how a feature will work.

Ditto. But that's usually as far as it goes.
when I start coding I have a very "outide->in" way of thinking and an "inside->out" way of working

Outside-in, about how the caller would want to use a function, pre- and postconditions, extra member variables. I put down al lot of the function prototypes before starting to write the internals of the functions. My train of thought is like "this will call that, that will need this information, then that will pass...", having a big part of the program flow in my head with the function prototypes as a manual, and keeping an eye on the possible problems.
At work I do TDD and after having written the prototypes or having the flow in my head I decide if and how I can test something.

Inside-out, I implement the internals of the least significant function first. Why? Personal taste, and often the top-caller can't do anything without the rest working. Or you have to write dummy functionality, which I do if I ever happen to be implementing something the other way around. Now I think about it, I guess it's also easier to work inside-out because you can fully focus on the current function without having to worry about anything that is not implemented yet.
Along the way if I see something is amiss in the way of a function getting too long or me having forgotten something in the overall picture I take a minute and contemplate my next step. And then I attack the problem right away before causing any more harm.

After the implementation I do at least one second pass to improve the code. Such as removing redundant function parameters, split functions into smaller ones.

Now, I notice this is more my way of working that my way of thinking. I guess it's hard to describe or even be aware of something that is so natural to us. I guess in general my mindset is best described as chaotic during the layout/design of a piece of functionality and very formal and structured while implementing the internals of the functions.
I always notice this when I am discussing things with my colleagues. Discussing or brainstorming about design stuff is awfully hard while discussing implementations is easy as pie. I think one of the causes for this is that an implementation is usually an exact science, whereas the design of something is more personal and open for different solutions that may be equally good.

Share this post


Link to post
Share on other sites
A lot of the times I just write hundreds of lines of codes while not conciously thinking about it at all -- that usually happens when the code is quite generic and I've written something similar before (which nowadays happens quite a lot). As it gets more complicated, I usually try and picture the whole, then I "divide and conquer", start implementing one piece after the other and inbetween I often do extensive testing and refactoring. I think what's most important for me is that I like to work in iterations meaning that I think about how to solve a problem and as soon as I have an idea, I implement it. Then if it doesn't work or if I come up with a better idea while implementing the first, I just do a new iteration and so on. The more experienced I become, the less often I have to do a whole lot of iterations after the first one. I think most people (including myself) also think in iterations. That's why brainstorming works so well - someone has an idea, someone else adds something to it, then a whole new idea comes up and so on.

What I also noticed recently is that good code generally has a certain look to it. As stupid as it may sound, I often write code and then change it so that it looks nicer. And I'm not talking about reformatting it, I'm talking about changing the whole code design. I guess you might also call that instinct ;-)

Share this post


Link to post
Share on other sites
when I program I think about it very logicaly and plane. basically I visualize everything but just in its logical form. nothing fancy lol. I basically try and see how the compiler is going to run it all by going through the code. simple I know

Share this post


Link to post
Share on other sites
I definitely use a pen and paper more than I actually type when I program at work. Especially if I'm in a new area of code that I'm not experienced with. I'll just run the game and debug through it for an hour or two, getting an idea for how the whole flow of the section I'm in works and jotting down ideas for how/where to implement whatever it is I'm working on. Once I do start coding, I constantly ask myself, "How could this be simpler?" or "What existing code can I leverage here?". Basically, I'm always trying to think of how I can write as little actual code as possible.

When I work on my own projects, I tend to be a in a lot more of a try-as-you-go mindset. I'll just start coding, and if as I go along I realize some design decision I made doesn't work, I'll go back and refactor it to fit with the new things I've added since. It's a lot less productive, but a lot more educational as well.

Share this post


Link to post
Share on other sites
'Programming' involves a large number of wildly different tasks. Usually, implementing new functionality starts with thinking about how to do it.

When designing code for the first time, I follow a divide-and-conquer principle as already described in this thread. I cut up the complete task into a set of independent and self-contained operations, which I then further divide into algorithms, which are further divided into language constructs (functions, classes). The mindset I use when doing this is the one I have when hacking up quick protoypes in functional languages: no squeaky clean Object-Oriented Programming, nor even separating things into sane functions or modules, it's just about doing whatever needs to be done in the way which requires the least code to perform, to see if it works.


I usually keep doing this until I reach the required functionality (which is usually a simple one). Then, I start writing code.

When writing code, I mostly keep in short-term memory the names of the variables I am using as well as a quick graph representing the control flow of my algorithm, and I usually lay out what I write according to idioms/patterns that I know I can implement easily without undetected errors (any errors I make when doing this are detected by the compiler). The point is to reduce the need for cognitive intervention at the lowest point possible.


Once the code is written and tested, it may contain bugs. So, I set out to correct those bugs.

A bug is, typically, a program doing a thing it shouldn't. The problem is that an incorrect result may be reached by a correct reasoning with an incorrect starting point. So, the entire debugging mentality is determining why the observable result is incorrect, determining if the last operation is correct and operated on incorrect, or if it's incorrect. If the last operation is correct, then I move back in time recursively until I reach a place where the operation is incorrect, and correct it. This is also a pretty mindless approach, as it mainly consists in iterations of the form observe-error, place-breakpoint, examine-operation.


Once the code works, it's time to get down to the meaty part—cleaning up the design to reduce coupling and increase modularity.

When refactoring code (actually, when deciding how to refactor code, as actual code refactoring is mindless search-and-rename or cut-and-paste), I am in my most mentally active state. The thought process consists in determining where a given piece of information appears, and if it appears more than once, factor that piece using one of many idiomatic techniques (based on functions, objects, generics, and so on).


Share this post


Link to post
Share on other sites
Hmm, an interesting question opposite to this one is does programming change the way you think ? I know my way of thinking changed when i started programming, especially when it comes to problem solving. Analysis, and so on ...
I was often criticized for alternative way of thinking, finding different than standard solutions to a problem, but that was when I was younger ... now days i go with the tested concepts of other complete projects and integrate them to my solution. I think that i become afraid to use anything untested, because it may be inefficient and i have an opinion that if i can come up with something, so can somebody else, and if it is better than the standard way, it will soon be common knowledge.

Share this post


Link to post
Share on other sites
This is pretty much my method of approach to thinking.

+Figure out what am I trying to accomplish now, and what might I want to add later.
+Consider what outside data I may need to access, such as files/databases.
+Think of a general psuedo-code program flow and some of the key functionality.
+Start coming up with a general list of objects/classes that I will need.
+Re-run the psuedo-code flow in my head again to make sure it doesn't have obvious flaws. Then start picturing how the code will look to accomplish that program flow.
+Start fleshing out the objects in more detail, coming up with obvious properties and methods.
+Look for common functionality needs within my objects, see where making another object to handle those needs makes sense. If it does, flesh the new object out.
+Look to see if my objects are flexible enough to allow more functionality additions and other changes later if needed. Optimize/rethink where needed.
+Start picturing functions/methods, and figuring out which I have the most and least amount of experience with working on. (This can be good because it helps gauge the difficulty of your project to a rough degree). Figure out what knowledge I'll have to acquire to further work on some of the harder problems.
+Do some research on the harder problems if needed to come up with the best approach, or see if a new one is needed then originally planned. Adjust if that is the case.
+Picture what objects are most critical to the program actually working
+Hop to work and start working on the necessary stuff first, and go down the list of importance.


I typically have an excellent memory, and I can be good about running programs/algorithms in my head mentally and organizing everything in my head. So the above strategy is a good one for me :D

Share this post


Link to post
Share on other sites
I don't care about thinking a certain way when programming. Sure, i'll design first, but after years of experience i can just visualise what needs doing. It comes with experience and although this discussion may yield some interesting insights, the only thing that will help you become a pro programmer is hard work. There are so many ways of doing things and accomplishing things that it is difficult to classify one above another.

Carmack may not think much differently to you or i, but the knowledge is what makes the difference.

Share this post


Link to post
Share on other sites
Cheeseburgers of course ( isn't that what everyone thinks about )?

But seriously, I think game-dev readily lends itself to a visual thought process, and on a more basic-level, a purely logical one. When writing a routine, I can usually "see" exactly how it will execute in the up and running game. For data-structure stuff, I invision an animation of how each call manipulates the data. Queues,trees expanding and contracting, growing and shrinking as data is added or removed. Granted, general coding is dominantly a left-brain activity, the techniques employed for games are strongly right-based as well ( at least when it comes to conceptualizing ). And as someone else mentioned, there is a lot of stream-of-consciousness coding where I my fingers seem to act of their own will, and blocks of code seem to magically appear.

Share this post


Link to post
Share on other sites
I think constructing a map describes the thought process in a programmer's head very well.

Still I wouldn't describe my own perception of the process as visual thinking, it's more along the lines that I acquire an understanding of the interaction and relations of the elements I use. Not as a mental diagram, but as something like a mental network of the connections and causalities I can shift around and think about.

One of the strangest things I noticed on several ocassions was that the number of dimensions (in the spatial sense) in this map also varies, some requirements literally translate into adding another dimension to the map, so I'm happy I'm not a purely visual thinker, otherwise I'd be in deep trouble visualizing more than 3 dimensions :)

There are also some layers of thinking: Typing on the keyboard is not a cognitive process anymore, and translating forth and back between the mental map and code also is largely an automatic process. Remodelling the design and exploring the consequences in your mental map (especially when thinking about heavily multi-faceted requirements) is what occupies my thoughts most and makes me look as if I'm daydreaming whilst programming.

Oh well, never tried expressing this process in words, so unless your mind ticks similar to mine, I guess this description will look like confusing nonsense to you :)

-Markus-

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement