views:

286

answers:

9

On either a hobby project or an assigned project, how do you choose where to start? Do you start on the easiest component or the hardest component first? Do you build the system bottom-up, or in a top-down manner with stubs for low-level pieces to be implemented later? Do you research similar projects and just steal reuse whatever existing code you find and build off of that? Or do you do things differently depending on whether it's a hobby/work/school project?

The reason I ask is I want to make a Python1 to Whitespace compiler, but am having difficulty deciding what part to do first: write the grammar and build a parser, write algorithms to do semantic checking of the AST, write the code generation algorithms, or just go find and work off a similar open-source compiler/interpreter (which souds the least fun, though I'd probably learn more).

1 Not actually Python, but a much simpler language with Python-style syntax

+3  A: 

Easier said than done, but for a commercial project, try to tackle the highest risk items first, as these are the ones that could force you into design changes if you can't make them work.

Leave the no brainers 'til last, or until you need a rest.

seanb
+1  A: 

some possibilities -

on projects that you must do:

  1. define features
  2. identify risks
  3. plan alternatives and time-boxes
  4. spike/prototype risky areas
  5. proceed with features in some logical order - customer priority, architectural topology, bottom-up composition, most-fun to least-interesting, etc.

XP/TDD assumed

on projects that you are just 'tinkering with':

  • proceed from knowns to unknowns, or
  • pick the most fun/interesting piece and start with that, or
  • try to architect/design the whole thing for the intellectual exercise

working on the parts that you know how to do may shed light on the parts that you don't know how to do

on the other had, working on the interesting parts may be the point of a hobby project in the first place; completion is optional as long as you are learning and having fun

Steven A. Lowe
+3  A: 

The most important thing is to just start. Anywhere. With big projects I probably appear to be chaotic, when in reality its not the case. Sometimes you work on the high risk items and sometimes you pick the low hanging fruit (the easy ones). I often burn the candle at both ends, work forward from the beginning and backward from the end and meet in the middle. Follow a path/problem until you hit a brick wall. Take another path and save the prior for later. All the while keeping all the problems past, present, and future in the back of your mind, simmering.

Where CAN you start, is there an area in the problem that you already know enough about to get going? Start there, if you have not already let the problem simmer long enough, slept on it enough nights, etc, having something not so terribly difficult will allow your mind to also solve the big picture. How many lego blocks am I going to break this problem into, what are the boundaries, how rigid are those boundaries? Do I take the input and cook into another file format and then go from there, or cook it into some internal data structures? If I write my own parser and change my mind can I glue in a publicly used one or does failing at the parser mean the whole project fails as originally planned? Perhaps start there.

As a hobby what do you want to get out of this? Make a better mouse trap to show off to the world (open source)? Get rich quick? Learn about something you always wanted to learn? Or just have something fun to do to kill time and maybe get some credit down the road for it, maybe not?

For your work is a little different. Are you planning on being at this place for a long time? Do you care to make a big impression for yourself, team, department? Do you tend to get stuck with your work cradle to grave or are you the pioneer that cuts new trails but never has to pave them? If you and your boss and the team just wants this cranked out, grab an open source solution (understanding the baggage that goes with it) for the parts you can and just add your secret sauce. If you are married to the bosses daughter and there is no way you are leaving this place and this is going to be the flagship product, perhaps you want to own every bit of it, re-invent that wheel.

If you have a passion to do or at least try this project then start anywhere, anywhere you can, anywhere that you think you can make progress on and that will keep you interested in the project. Even if this first cut is all throw away code, get started. You should then quickly start to sort out the lego blocks of the project, what shapes and colors and how they fit together. Isolate the low hanging fruit from the risk items. Alternate between the two, when you fail at a risk item, pick the low hanging fruit for a while to both make forward progress and to let your mind rest. Then after a rest go back to the risk item.

dwelch
Very nice answer, although I'm not sure you know what Whitespace is. Nobody will be making money off of it. The whole purpose of working on this compiler is to learn about compiler design and to build something so useless it's cool :).
Cybis
+2  A: 

Disclaimer: I'm a biologist/statistician who programs regularly for research purposes, as opposed to a full time "pure" programmer, so my habits may be a bit unusual.

I generally try to break thinks down by taking a task and saying to myself, "This would be dead simple if only I had the following primitives." By primitives, I basically mean functions or classes that I can assume "just work" and treat as black boxes. If I still can't see where to get those primitives, I apply this thinking recursively to each newly created subproblem until either I've gotten to stuff that either seems fairly trivial or that is in some library. Once I have this functionality tested, debugged, and if necessary, optimized, I go back to thinking of it as a set of primitives and build the next higher level on top of it.

As far as which "primitive" to implement first, I usually go with either the most interesting (to get me in the zone and excited) or the one where I most expect to encounter things that could change my high-level design and/or perspective of the problem.

dsimcha
Wow. What a well thought out answer. ^_^
Nicholas Flynt
+2  A: 

Well, the best thing is just to think really hard before coding it.. it`s like playing pool, if you take the time to think ahead, everything will be easier. Once you know everything you need to do, and how you do it, where to start will be natural.

And for my own experience, I really like the top-down approach and I usually always code the high-level method first.. something like this:

int main() { ClientSocket socket("www.google.com", 80);

string line; while (socket.getline(line)) { cout << line << endl; }

}

I create the classes I need for this to compile (ClientSocket).. and then, once I know exactly what I need to accomplish, I code it. :)

So, for your compiler, I would start by thinking of all gramars, all the classes I would need.. I'd write them down. Then, I would probably write a main() that would use those classes.. And then, I would just "Fill the blank".. but hey, that's my method, I'm sure everyone use different methods and it really change depending of the project, time, etc.

Good luck!

This sounds a lot like the Test Driven Development approach to writing software.
Sergio Acosta
+2  A: 

I start with thinking about how to lay out the system as a whole. Then I tend to pick the smallest subset that can work by it's self and do something remotely useful. Adding pieces that will let me add components in the most granular way I see.

That said, personal preference, what look fun and what I can best understand also play a part.

BCS
+1  A: 

heh - having now actually read the description of the Whitespace compiler, the first thing you should do is something else

Steven A. Lowe
I'm not building this to be a useful product. I just want to learn about compilers and the issues involved in language design. Building a compiler + language, I think, is the best way to do that. Since I can't compete with useful languages, why not go in the opposite direction?
Cybis
@Cybis: given the description of the whitespace compiler, i don't think it is possible to create a useful product based on this! But hey, whatever makes you happy!
Steven A. Lowe
+1  A: 

I tend to work several different ways.

The first thing I do on any project is get output to the screen and make sure my devkit is set up, etc.

(1) If the project is something sequential, something that will do steps X,Y,and Z in order (like a converter, for example) I work in chronological order, and debug the steps as they happen.

(2) If the project is a game, I tend to start by getting my character working in the most complex environments first. For example, in a platformer, my first goal would be to get the player walking around and not falling through the floor on a flat plane. I proceed to add enemies and later levels.

(3) If the project is something more of an application, I try to make the thing function as soon as possible. That is so say, minimal interface, bug ridden, but I can get the main point of it to work sort of right away, and then add features and polish from there. This also has the added benefit of usually causing me to code the most complex and important part of the application first, which allows me to design the program's code around that part of the application.

No matter what the project though (unless its just very small) the first step is always to design a roadmap of the things I need to do, and try to block out the code a bit so I have a general idea of what I need to do and how the parts need to communicate, what libraries I'm going to need to rely on, etc.

Oh, and I forgot to mention the most important part which is my first part of coding: I choose the right programming language for the job.

Nicholas Flynt
+1  A: 

Start with something small and easy, so that you can make it works quickly. You'll get feedback and fun, which will motivate you to go on.

For instance for a compiler, I might start with integer variable: declare, assign with a numeric constant and perhaps print - or any other way to ensure it works. Then I could try to declare two variables and assign one with the other, add an incrementation operator, implement arithmetics ... Next step could be string variables, then conversion between integers and strings. Notice this does not seem to be suitable for a Whitespace compiler project.

I won't start implementing an exhaustive grammar parser, or any other "layer", as I could have to recode it if I find a better way. However the Whitespace grammar seems pretty simple.

Start small, add features little by little, and keep evaluating your design.

philippe