Results 1 to 2 of 2

Thread: Guide to making a program

  1. #1
    Senior Member
    Join Date
    Nov 2003
    Posts
    107

    Guide to making a program

    Guide to making a program
    by: FlamingRain

    Step 1: Choose a language

    This step is very important. Commonly, people use a
    general-purpose language and code almost everything in it. If you know
    multiple programming languages (most coders do), select the language
    most fit for the task at hand. Choosing a language that's not very
    appropriate for the task will result in a lot of hair-pulling and
    working around things that you might never even have to deal with when
    using a different language that is more suited to that task. For
    example, why would you write something in assembler that does pattern
    matching in text files when perl or awk are much better choices? The
    language chosen should be suited to the application. If you only know
    one language and find that doing something in particular is very
    difficult, i would suggest learning another language.

    Step 2: What's the problem?

    Identify the problem. What do you want the program to do. I
    believe this is the leading cause of discouragement in beginners, either
    they want to do everything and can not yet plan to build something on
    that scale, or they can't decide what to do and just start writing code
    and wondering why the code doesn't work. For example, say you wanted to
    write a small program that can find the average of a set of numbers.
    That's your main problem.

    Step 3: Break it into smaller problems

    Try to break the main problem into little problems that are easy
    to solve so that you can make more sense of the program. In the above
    example of finding an average, there are two other problems. First, you
    must find the sum of the sequence. Then, you must divide that by the
    length of the sequence. They can then be broken down into smaller
    problems of "When do i know i've added all the elements together?" and
    "How long is the list?". So you see, by taking it to the fundamental
    level, we come up with a list of little problems that are easy to solve.

    Step 4: Explore other algorithms

    Exploring other algorithms is important. Just because you
    thought of one way to solve a problem, doesn't mean it's the best way to
    do it. In many cases, there is no best way. You can try to go for speed,
    or memory efficiency, or other criteria. For example, say we didn't have
    the full set of numbers to average and we only got them one at a time.
    Using the previous method, we'd have to store every piece of data and
    then find the average again every time we got a new piece. This isn't
    very efficient now is it? We still have to store all the numbers, re-sum
    them every time, and divide again every time. As the program goes on,
    our memory usage increases. Also, we run the risk of the sum overflowing
    the datatype we're using.

    One way to address the problem is to do some math and find that
    the average of all aligned averages in a set equals the average of the
    set itself. With this design, every time we reduce things, we take up
    less memory and worry a little less about overflow each time because
    we're only finding averages of small groups. Now, this addresses the
    problem of overflow and memory usage, but it's still very processor
    intensive and will not work on lists of prime length or very well on
    lists whose length has few factors. We still haven't addressed the
    dynamic issue yet. This algorithm would have the same problem as the
    last.

    A way to address this problem is to do some more math and figure
    out how to reweight the averages. For example, the average of two
    numbers is their sum divided by 2. Now, say we wanted to find the
    average of those two numbers and another number. We could multiply our
    old average by two, giving us the sum of the two numbers, then add our
    new number, then divide by 3. Well, that sounds like a good idea, but we
    still have that nasty overflow problem don't we? Well, we can fix that.
    Using the distributive property, we can multiply our old average by 2/3
    and then add one third of our new number. This will result in the same
    thing and will avoid the overflow problem. But now, a new problem
    arises. What happens as the divisor gets bigger and bigger? Well, it's
    possible to experience an underflow, which is what hurts this algorithm.

    So, you see, there's really no "right" algorithm for some
    problems. Depending on your criteria, any of these three could be your
    best choice, and i'm sure there are others out there too. I suggest
    repeating steps 2 and 3 for this step (you won't get far without them).
    Repeat this step until you can't think of any other ways to solve the
    problem, then pick the one that best suits the task. If you need to, you
    can write up an efficiency program (i know i did for my prime generators
    and modulus functions).

    Step 5: Designing and Planning

    Now that you have your algorithm picked out, you should consider
    how the program will work. Ask yourself these questions:

    1) What's the input?
    2) What's the output?
    3) What do i need to do to turn the input into the output?

    Now, they may sound like silly questions, but believe me, it's where
    most mistakes occur. People aren't sure what the input should be (not
    like a string or number, but like file, keyboard) and how the input is
    formatted when the program sees it. People aren't sure what the output
    should look like and don't know how to format it properly so they get
    what they want. The biggest problem is the intermediate changing of data
    though. What format is the data in when you start processing it? Should
    it be changed? What do you need to do with the data?

    Once you've answered these questions on the abstract level, go
    back into steps 2 and 3 and figure out how to make it work in general at
    least. After this, you should have a good idea of what you want the
    program to do, what purpose it serves, and what it'll be broken down
    into.

    For example, a good password generator should have the following
    components:

    1) A pseudo-random number generator (to make random numbers)
    2) A way to store the passwords
    3) A way to secure these passwords such that only the person that made
    them can get to them
    4) A way to protect data integrity (checksums and such)

    So, those are the general program parts we need. We can start to develop
    ways to solve these problems in steps 2-4. Once the problems are solved,
    you're ready to make your design plan somewhat concrete.

    This part is where some coders disagree. Some feel that you
    should continue refining your design plans until you write pseudo-code
    for them (fake code that basically tells what it should do in english,
    but not exactly how to implement each piece). Converting from
    pseudo-code to any programming language generally isn't hard and if you
    keep the language you chose in mind, you can make pseudo-code that's
    more accomadating to that particular language. Some coders feel that
    isn't necessary. That you should be able to sit down and write code once
    you have all your ideas straight.

    This is a hard one though. If you're willing to invest the time
    to make out the pseudo-code for the program (and do it well), it's
    generally easier when you sit down to code it because all you're doing
    is implementing the code on your paper in a programming language. But,
    if you're not willing to invest the time, it's usually not too bad to
    just sit down and code if you're familiar enough with your ideas.

    Step 6: Coding

    Yay! The fun part at last! Okay, this is the important part. Up
    until now, it's all just been preparation. All you do now is implement
    the ideas you had. This section is kinda sparse because there's not
    really a lot to talk about. This is actually the easiest part if you
    plan well. If you plan poorly, you'll be stuck in steps 6 and 7 for
    quite some time.

    Step 7: Debugging

    There are problems with any program. Commonly the first that
    crop up are syntax errors, errors that occur when you misspell things
    and try to do something you're not allowed to. Once you've worked out
    all of those errors, you may have problems with the logic in the
    program. Perhaps you did something that caused exactly the opposite of
    the result you wanted. There are several ways to debug and most of that
    depends on your language and tools.

    The first debugging method is just to look over your code and
    see if you just did something stupid. Don't feel bad, it happens to all
    of us. For example, a hash function program i wrote wasn't working and i
    found out after sifting through 36 pages of diagnostic material that i
    typed buf2 where i should have typed outbuf. This method can save you
    lots of headaches (and lots of paper).

    The second method is to use a program that lets you step line by
    line through your program code. This way, you can see what your
    variables are doing and everything else that's going on. This is
    probably the handiest way to debug, but sometimes we don't have the
    ability to do this.

    If you can't step through your program, but your platform has
    good error reporting (like Euphoria, who dumps out all your variables at
    the crash instance), you can use an intentional crash method. This is a
    good way to determine what exactly is going on and how far your program
    gets.

    Another way is to install diagnostic code and just dump every
    variable and its contents to the screen along with some other general
    information about the current place that's being executed. This method
    will allow you to check everything that happens on the run-through.
    However, this method isn't always the best. It results in lots of data
    you have to sift through. But sometimes, you gotta do it that way.

    The last resort method of debugging is by hand. Simply step
    through your code and write down all the variables as they change and
    their new values. This is just like diagnostic code, but you don't have
    to write any code. This method is prone to error unless you really act
    like a computer and do exactly what the code tells you to. If you don't,
    you'll have a case of human error where the program seems to work fine
    but it's because you did what you wanted the code to do, not what the
    code said to do.

    At this stage in programming, commonly, you run into technical
    problems where you find out that what you planned to do didn't work.
    This is more common in projects where you don't plan all the way down to
    the trivial level, but leave things more open. So, you go back and
    change your design plan, that's the only thing you can really do.

    Once you have found the problem in the code and figured out how
    to fix it, go back and recode it. You'll go between steps 6 and 7 quite
    a bit.

    Step 8: Documentation

    Well, i've been talking about documentation in planning a little
    bit. But, it's also important to comment your code as you go so that
    it's easier for others to understand or for you to understand later when
    the ideas in your head aren't so fresh. It makes it easier to understand
    what you were trying to do. Now, if you did a good design, most
    everything should be in there and you can just say to reference that,
    but sometimes that's not enough. I won't cover comment style in this
    because that's really personal preference.

    It's always a good idea to write up a formal design plan so that
    everything you're doing is laid right out in front of you. I have a
    general form that i follow below:

    --Formal design form--
    Program name:
    Author:
    Reason for coding:

    General program purpose/What problem does this solve?:

    List of problems to solve:

    Abstract ideas on how the problems whould be solved:

    Technical details:

    [EOF]

    With this form, i allow myself to organize what parts of the program
    there are, what i want to do with them, and i still leave room for
    techspec's for when i run into problems or when i'm cementing ideas
    (applying your abstract idea to this particular application).

    It's always good to write follow-ups for your designs after you
    finish the program, or as you finish modules. This way, you can see what
    went well, what didn't go so well, and what you'd do differently if you
    were to attack this problem again without any code at your disposal.

    It's also good practice to keep an "oopsies" list of mistakes
    you commonly make so that you can go back and check for those things
    when debugging a program. (This has saved me hours of debugging in
    previous proj's).

    Well, that's about it i think. There's not really much else for steps of
    programming, feel free to email me and give suggestions so this can be
    updated. code_x@preaker.net

    --FlamingRain
    [EOF]
    Is there a sum of an inifinite geometric series? Well, that all depends on what you consider a negligible amount.

  2. #2
    Senior Member
    Join Date
    Mar 2003
    Posts
    245
    Good post, this is classic CS wisdom, and unfortunately is not being followed today in many shops.

    Only thing I would add to it is decide on a Version Control system (e.g. CVS, Perforce, PVCS, etc.) and
    use it religiously from the beginning. The best designs often come from making a few forks of the project
    at some design-critical point, and being able to do usability tests on each fork later to determine the best
    working design for customer use.

    Again, good post.

    Happy Holidays

    -- spurious
    Get OpenSolaris http://www.opensolaris.org/

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •