|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: How to write programs?
by jZed (Prior) on May 26, 2005 at 18:03 UTC | |
update: and sprinkle with liberal amounts of review by peers and refactoring at each step; if the documentation can't be understood, the interface is too complicated, so aim for clear documentation first. | [reply] |
|
Re: How to write programs?
by mstone (Deacon) on May 27, 2005 at 05:52 UTC | |
I tend to work declaratively, and backwards. Broadly speaking, there are two kinds of programming: declarative and imperative. Declarative programming lists a sequence of results, and leaves the reader (or the computer) to work out the operations that produce those results. Imperative programming lists a sequence of operations, and leaves the reader (or the computer) to work out the results. Most of what we think of as 'software' falls under the imperative style, while things like SQL and mathematical proods fall under the declarative style. Thing is, those two styles link directly to the two questions that are most important to programmers: What? and How? "What does this code do?" is a declarative question. It asks you to identify the result produced by the code, or more generally, to describe the relationship between what goes into the code and what comes out. "How does this code work?" is an imperative question. It asks you to define the procedure that connects what goes in to what comes out. Now, as I mentioned earlier, most code is written imperatively, but it's a lot easier to design code declaratively. The trouble with imperative code is that it's easy to get bogged down in the details. It makes you to choose a way of representing your data, often before you know exactly what kind of data you really need to represent. Then it makes you write all sorts of representation-support code just so you can work with the values you want to use as inputs and outputs. With all that furniture in the way, the actual logic of your program.. the stuff that actually handles the work of mapping the inputs to the correct outputs.. can get hard to see. Choosing a representation early also makes it difficult to change your basic data structures if you decide there's a better way of doing things later on. People will often stick with a representation that doesn't really do what they want, just because they don't want to throw away the code they've already written. Declarative programming keeps you from having to code up a representation. Instead, you define a collection of types.. sets that contain valid input values, and valid output values.. then you use those to define the relationships between your inputs (the things you have) and your outputs (the things you need). You define types by listing assertions that will always be true for any item in the set: And the beauty of declarative design is that you don't have to start off with a big long encyclopedia of assertions for each type. You can start with a few very rough ideas, then go back and refine them.. either by making them more specific or adding more assertions to the list.. whenever the new rules become necessary. You're free to evolve your types as the design grows, and you get a better idea of what's actually going on, because you aren't handcuffed to any specific representation. The idea of building a design backwards harks back to the old programming maxim: "start with the part that produces output." The output is the part of the program you can see. It's the where you find out whether you got the result you expected or not. If you start by generating output in its simplest and most trivial form, you know at least that much of the program works. Then you can work your way back through the design, adding one layer of complexity at a time, and verifying that the new code actually does what you expect. That keeps you from creating those really frustrating situations where you've written a whole bunch of code blind, then run into bug after bug after bug when you actually try to run it. It's also a good mood-maintenance trick. It's exhausting to have to write tons of code before you have anything that will actually run. It's much more satisfying to be able to run something every five minutes and see yourself making progress along the way. The back-to-front approach also lends itself nicely to declarative design, because the first version of any declarative design is basically:
If we start with 'inputs' being 'nothing' and 'outputs' being "hello, world.\n", the imperative version ends up being pretty easy to code. If we want to make things more complicated by saying the program has to write its output to a web browser rather than to STDOUT, we end up doing some more twiddling with "Content-type" headers, HTML formatting, and so on. But the basic principle ends up being the same. Back-to-front design also helps you decide exactly what inputs you actually need in order to generate the output you want. If we were to refine the design above to use an HTML template that lives in an external file, the new diagram might end up looking like so:
and at this point, the assertions for the 'HTML template' type require us to think about error handling. If we add a rule that says, "every 'HTML template' must be valid markup," and interpret the diagram above to mean that the 'file reader' part of the program must always return an 'HTML template', then we have to find some way to guarantee valid markup if the file doesn't exist, or the program can't open the file because of permissions problems, and so on. If we really wanted to get finicky about it, we'd even parse and validate the contents of the file if we could read it, just to make sure the file actually contains valid HTML. So that leads to a further-refined diagram like so:
where we assert that 'hardcoded error template' is also a member of 'HTML template'. Then we'd go to work on the message itself:
and so on. The longer you keep refining the diagram, the closer you get to a set of requirements that are trivially easy to program. And once you know exactly which parts of the program need what information, it's much easier to define object classes or data structures that will carry the information where it needs to go. That's the appropriate time to worry about data representation issues, algorithms, and all the imperative stuff. So.. my basic policy is to start with "What?" and work my way back to "How?". | [reply] [d/l] [select] |
|
Re: How to write programs?
by 5mi11er (Deacon) on May 26, 2005 at 18:38 UTC | |
As the difficult stuff is accomplished, the easy stuff is usually stolen from were ever I can find something that gets me close to what I want, and modified as needed. (not that this is any different for the difficult parts, but the easy stuff is generally more readily available and/or easily found; Perl & CPAN certainly make the difficult stuff a whole lot easier to find and/or accomplish :-) I've been told I've a better than average ability to see both the big picture and the details at the same time, but I've always shrugged it off. I can't understand how anyone could be good at programming if they couldn't do both. But, maybe that's part of the reason why the really good programmers are relatively rare? -Scott | [reply] |
|
Re: How to write programs?
by bofh_of_oz (Hermit) on May 26, 2005 at 19:25 UTC | |
1. Know what you're doing. You should know quite clearly what you want this program for and what it should do. Otherwise, you shouldn't be writing this program... 2. Write the program logic down (use plain <your language here>, pseudocode, block diagrams etc., but on paper. Not everyone can do it nowadays, but if you can, it will help you... 3. If you can, write the code down (again, on paper). You can always scan and OCR it later... Often, you will see a design flaw or something that needs redoing, and often it is very hard to find it in code when it's on computer (or maybe, it's just me coming from that old generation of people who actually read paper-based books) 4. Code (on a computer). Include enough comments so that you won't get lost looking at this program three years later. If you feel like a technical writer and don't care about your job security, make extensive documentation... 5. Test. If everything goes well on the first try, re-check the program - something is definitely wrong ;) (remember Murfy's laws?) 6. Put into production. Don't forget to keep the source in case the company will want to fire you later and you will have to use threats and blackmail to get your severance package out of them...
--------------------------------
| [reply] |
|
Re: How to write programs?
by mrborisguy (Hermit) on May 27, 2005 at 00:06 UTC | |
To be honest, I always start out making something that runs.
I'm not really sure why, but that's the first thing I do EVERY time I start writing a new program, regardless of what it is supposed to do. Sure, sometimes I use, "hello" or "what's up?", and sometimes I'll even throw in a "\n", but regardless of what I'm making, I always start this way. I think after this is done. -Bryan | [reply] [d/l] [select] |
|
Re: How to write programs?
by Transient (Hermit) on May 26, 2005 at 19:05 UTC | |
1. Ensure requirements are well-written, fully explained and completed. 2. Double check that requirements are finalized. 3. Break down the task into sub-tasks (be that OOP or otherwise) 4. Pseudo-code tests (documenting major functionality) 5. Write tests (I admit I don't usually do this) 6. When the requirements change (and they always do), work at a frantic pace to accomodate, introducing bugs and other undesirable things. 7. Test until you drop 8. Repeat 6 and 7 ad nauseum | [reply] |
by bofh_of_oz (Hermit) on May 26, 2005 at 19:30 UTC | |
--------------------------------
| [reply] |
by chromatic (Archbishop) on May 26, 2005 at 21:19 UTC | |
There are subtle undocumented changes between test and production environments that introduce new bugs... Step 0. Remove all changes between test and production environments that introduce new bugs, no matter how subtle or undocumented. | [reply] |
by jordanh (Chaplain) on May 27, 2005 at 16:48 UTC | |
by adrianh (Chancellor) on May 27, 2005 at 09:42 UTC | |
Following these rules strictly would probably mean that I would never get to stage 3 :-) This is why I like techniques that allow clients to change the requirements in a structured way - because there is nothing like having a partial implementation in front of you to make you realise what you really wanted. | [reply] |
|
Re: How to write programs?
by redhotpenguin (Deacon) on May 27, 2005 at 07:25 UTC | |
What is interesting is to see the results of programs built in the opposite order.
1) Write some code. 2) Write some tests because your users have told you your code is breaking. 3) Write some documentation so your users can understand the app, maintainers can maintain, and you can figure out what you have done here.
This approach is invariably faster to market, and also great a deal more prone to failure and a high incidence of defects. Having used both approaches, I prefer the original order of docs, tests, code, especially when additional requirements arise, because the total cost of development is lower, and the product quality is higher. That documentation is a contract between you and the user. | [reply] |
|
Re: How to write programs?
by chas (Priest) on May 26, 2005 at 21:50 UTC | |
I used to write English papers by putting a sheet of paper in the typewriter (a machine most of you probably haven't heard of...they're extinct now) and typing - slowly with a lot of thought. I hate writing outlines! But clearly this wouldn't work for everyone. Anyhow you do it, it takes a lot of concentration and effort, but if you get results I wouldn't worry much about methodology. chas | [reply] |
|
Re: How to write programs?
by Mutant (Priest) on May 27, 2005 at 09:51 UTC | |
Time and again, however, I've found the design wasn't able to forsee all problems, or couldn't achieve the depth of understanding necessary to spec a full implementation. To actually do this requires the application to be implemented. Only then are all issues properly understood. Except in very simple applications, your initial spec will almost always have to be altered, even if the requirements are static. | [reply] |
by jplindstrom (Monsignor) on May 27, 2005 at 11:49 UTC | |
The incompleteness of our ideas only become evident during implementation. True, true. /J | [reply] |
by ihb (Deacon) on May 27, 2005 at 12:23 UTC | |
The incompleteness of our implementations only become evident during tests. and The incompleteness of our tests only become evident during demonstration for important people. ;-) ihb
See perltoc if you don't know which perldoc to read! | [reply] |
|
Re: How to write programs?
by djohnston (Monk) on May 26, 2005 at 19:45 UTC | |
Ok, kidding aside... There's already alot of good advice posted here, so I will just add my $0.02... Having run a BBS in the 80's has instilled in me the appropriate amount of paranoia to always quadruple check user input. I've drawn from that experience to avoid many of the CGI pitfalls without having to experience the shame of falling victim first. But then, I don't do that for a living either. | [reply] |
|
Re: How to write programs?
by samizdat (Vicar) on May 27, 2005 at 15:25 UTC | |
In short, I think the ultimate methodology is to keep in mind who you're trying to please the most and how to do that, and then get into Flow and go. All else is details and gradually increasing experience. :D | [reply] |