5 ms·
Ask HN: Bottom Up Programming Question
One thing that I have never quite grasped about the concept of bottom up programming is how to come up with the most basic components of a program without doing some kind of top down analysis. Perhaps I can illustrate my confusion better with an analogy.
Let's say you're designing a duck (in other words, an animal that can fly, has a rounded beak suitable for bottom feeding, webbed feet for swimming, etc). In a Bottom Up approach, you would start with cells. You would need to create skin cells, bone cells, eye cells, nerve cells, etc. In order to even get to this stage, however, you would first have had to have divided the duck up conceptually into different parts in order to know that different cell types are needed. Thus it seems impossible to do bottom up programming with out first doing some top down conceptualization.
So, once again the question, how can bottom up programming work without some level of top down design?
- speek 18y agoThe Design Recipe from How To Design Programs is very bottom-up based. Personally, I'm against HtDP because it strips out all of the romance in programming for me, but it does work.
- andreyf 18y agoIt isn't a question of "only top-down" or "only bottom-up". Of course, some thinking will have to go in from both directions. This is why, personally, I think the directed-tree metaphors don't really work. A much better way of thinking about "bottom-up design" is exploratory programming - where one decides what to write by writing it [1]. This means you start by discovering and solving sub-problems, by creating components which work in their own right, documenting and unit testing them (if you're working in an environment that needs it), and moving on to solving bigger problems using said components. On the other hand is the "architecture approach" - where you measure twice and cut once. By "measure", I mean decide what all of your components will be, write out UML diagrams for them, figure out your types, your interfaces, and the contracts between them, write unit tests, and only then begin to write run-time code. There are much more experience programmers than me who advocate both ways, so it's hard for me to make a call [2]. Another great metaphor I find analogous is "Mozart vs. Beethoven" style programming: http://stackoverflow.com/questions/292682/understanding-dijkstras-mozart-programming-style http://stackoverflow.com/questions/292682/understanding-dijk... I like this one because suggests that you can make "great" programs either way. I use the quotes, because obviously, music is a matter of taste, as is the quality of software we develop. This is important to remember - for some people, Windows is the perfect OS out there (for example, those concerned with Microsoft's profits over the OS's usability). 1. http://arclanguage.org/ http://arclanguage.org/ 2. Although the ones who advocate exploratory design seem more well-rouded: Alan Kay, Paul Graham, and the 37signals guys come to mind. Since I want to be well-rounded and not a specialist, I try to follow in their example. Obviously, this is a subjective judgment.
- gruseom 18y agoAnother great metaphor I find analogous is "Mozart vs. Beethoven" style programming Wow, that's really interesting. I find Beethoven to be an incomparably greater composer than Mozart, and I feel the same way about the exploratory approach to making software: it's just obviously better. Whether it is obviously better or just a better fit for me is a fair question. I will say, though, that I don't feel the same way as you about the advocates of the top-down, up-front style. What have they built? What systems did Dijkstra build? As far as I'm concerned the great practitioners are pretty much all lined up on one side. Counterexamples are welcome. (I should add that I don't mean to belittle Dijkstra's achievements, just that as far as I know they didn't lie in the direction of building working software. Of course that didn't stop him from castigating basically everyone who did do that.)
- patio11 18y agoDuck 1.0: Has a beak, which can open and close, but only eats green bugs. If you attempt to use it on a blue bug it crashes. Unfortunately, no eyes. Duck 1.2: Eyes. Duck 1.21: Eyes now see color. Duck 1.22: Eyes now see colors including black. Apparently, some bugs are black. Damn users and their damn uncolored colored bugs. Duck 1.5: Realized eyes and mouth both share a lot of code. Refactored as "nerves". Allowed consumption of turquoise bugs -- not exactly sure why they're safe when blue bugs are not, oh well. Added quack just for fun. Spent 2 weeks getting the quack to sound exactly right. Duck 2.0: Now with feet and wings! Turns out to have feet you really need muscle tissue. Refactored again, stealing code from Mouth. Supported modes of operation include walking, running, and swimming. Option in menu entry for flying but if you push it the duck dies. Duck 2.1: It glides! Duck 2.11: So it turns out that to utilize the gliding feature users were driving ducks off of tall cliffs. This resulted in downward acceleration being sufficient at end of glide to overly stress feet muscles, causing critical duck failure. Added in Bones. Damn users and their damn cliffs. As long as I had Bones I implemented them in the Mouth too, can finally eat blue bugs. Duck 2.12: Some blue bugs are poisonous?! WTF kind of bugs do you have in Australia. Added in Tongue. Borrows heavily from existing Nerve classes. More refactoring. ...
- patio11 18y agoAnd if you think that is at all unrealistic, you're talking to the guy who wrote a program to print bingo cards whose 1.0 version, among numerous other faults, could not accommodate any printer but the default one ;)
- kaens 18y agoNah, that's pretty much the tale of a lot of software that I've written.
- aaronblohowiak 18y agoThe only thing missing from some development goes is a notable feature reversion based on manager deciding that it is now going against the strategic vision. "Duck used to have webbing in his feet, but MGMT thought having another fluid-moving apparatus would diminish how much you value the wing. May be available as a paid add-on at a later date."
- hs 18y agothere should be a feedback element (or resistance of media) btw, duck can't fly so u may want to cut that feature
- gruseom 18y agoYour analogy seems to me to go awry here: you would start with cells - sounds good you would first have had to have divided the duck up conceptually into different parts in order to know that different cell types are needed - does not follow. I noticed that your premise assumes a requirements analysis that already nails down what the program is supposed to do. While that way of thinking is common in the corporate world (where, I note in passing, effective software development is not common - coincidence?), it doesn't fit well with the style of programming you're asking about. If you've read PG's piece on the subject (http://www.paulgraham.com/progbot.html http://www.paulgraham.com/progbot.html) you may recall that there's one passage in it that he emphasized. It begins: It's worth emphasizing that bottom-up design doesn't mean just writing the same program in a different order. When you work bottom-up, you usually end up with a different program. The program changes as it evolves and your understanding of what the program is changes as it evolves [~]. All sorts of interesting feedback loops result. When I work this way, I listen to what the code is telling me. That is, I start with something primitive (your "cells" in the analogy) and sense where it's leading. Perhaps it's akin to riding a horse where there's a balance between what you want to do and what the horse wants to do; or to creating a piece of art where the creative process incorporates feedback from the medium itself and from the work as it's emerging. That doesn't mean it's all spontaneous, with no guiding factor. If that were true, no system would emerge - you'd just keep going around in circles and finding yourself back at the primitive level. But the guiding factor is not at all like "dividing the duck up conceptually into different parts". It is more like having a felt vision of what a duck would be like. You have that vision and you keep referring to it as you go along. But the vision itself clarifies, and sometimes changes, in response to what happens in the code. You discover what the system is as you make it. Learning to listen to what the code is telling you is one of the most interesting things you can do as a programmer. ([~] PG's piece doesn't say that your concept of what the program is changes, only that the constructs it's composed of will be different. I think the two are related though.)
- ntoshev 18y agoYour duck example is interesting. Obviously the evolution doesn't use any top-down design.
- wulfcry 18y agoNice but you have to program the cells to contain the appearance of the duck the cells should know about and because that is a feature difficult to grasp it does not matter where you start. First design the beak put it in the cell Design the webbed feet put it in the cell Design the head put it in the cell Construct all cells and enumerate the cell based on the ducks feature And there you have it bottom up designed DUCK with out worry where to start.
- markessien 18y agoWhat you look for first is always a unit that functions on its own. Then you program that. For example, a feather could be used in a feather bed, or it could be used in a duck. You can program a feather, test it and make it work, without needing to have designed or modelled a duck yet - of course, you'll have an idea where it belongs, but since it is an enclosed and reusable component, it can be created first without a top down model.
- brent 18y agoHmm... I thought this was going to be about dynamic programming based on the title.
- deleted 18y ago[deleted]
- lgriffith 18y agoIsn't it more a matter of means vs ends. Top down is more or less means programming in which you don't really know where you are going but know how you are going to get there. Bottom up is more or less ends programming in which you don't know where you are but know how you are going to get there. Seems to me you need a good bit of both to get from where you are to where you need to be.
- jerf 18y agoThe biology analogy immediately starts you off on the wrong foot. That has nothing to do with code. In code, a function to trim whitespace from a string is perfectly functional on its own. When you actually try to write code this way, a rather large number of things can be written, larger than you may think. Rather than write a lengthy explanation, my suggestion is to write a non-trivial program in Haskell. After that you'll better understand how it is possible to have many functions that can stand on their own, and I think this will help clarify the situation in your mind. You can do this in any other language, but most languages make it relatively easy to reach out and touch lots and lots of state. Real-world evolved systems tend to do the biological equivalent all over the place, to a level even the worst spaghetti code ever written doesn't even come close to aspiring to, and do not resemble human-engineered code in the slightest. The Haskell advantage here is that it won't let you. Achieving this in other languages right now is a chicken-and-egg problem; if you knew how to do that you wouldn't be using the metaphor you cited. (BTW, just to state it explicitly: No, I didn't directly answer your question. As others point out, it's not a very informative question. I'm going for the root of the problem, how you are conceiving of functional units in a program.)
- mbac 18y ago> So, once again the question, how can bottom up programming work without some level of top down design? Ever heard of something called... LINUX!?
- DanielBMarkham 18y agoYou're always thinking top-down, even if "top" is just the next level up, as patio11's example shows. I'd start with the "outside" of the program and work inwards. This forces you to categorize features as greatest to least important. Refactoring can be significant -- much more than top-down. When used poorly, this can lead to the "design a 747 by building a wheel first" mentality, however. In other words, like everything else there's a place for it in the toolbelt. You know, you can always model the problem domain first and still code bottom-up. The structure of the data is probably the most important factor anyhow, no matter how you code or what the qualities of the language are.
- radu_floricica 18y agoIt's not that bottom up is good - it's that top down is simply impossible. Try to design a duck this way. It sounds very sensible, and you'll get a sketch in about two minutes. Not detail it: a couple of hours and 5 pages. Now continue to do this until you no longer have to backtrack: i.e. until what you discover about the duck in the current level of detail does not change at all what you have designed so far. This will have two effects: first, the complexity of the design is equal to the complexity of the duck. That's A LOT of paper. And second, most mistakes in the design will cause the duck to fail spectacularly. On the other hand, with bottom-up design you start with something which eats and reproduces, and improve it constantly until it has a beak and feathers and quacks. It will certainly not look anything like a duck at fist, but it is very likely that from the second or third iteration it will solve 80% of the client's problems. Sometimes even from the first, but that's just luck. It's messy, but it's at least doable.