Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You break complex tasks in simpler tasks:

- Go To School

  - Shower

    - Get wet

    - Clean

    - Rinse

  - Get Dressed.

  - Have breakfast

    - Prepare food

    - Eat
    
So different tasks have a different level of detail. The advantage is that you end up with more reusable methods. Like "shower" or "Prepare food" that can be used elseware.

In another time there used to be more emphasis on top-down design, but I feel that has been lost and I do not know if it is still taught.



> The advantage is that you end up with more reusable methods. Like "shower" or "Prepare food" that can be used elseware.

But that is exactly the author of this post's point. When you have something that is more reusable, like "Prepare food", you end up using it in multiple situations, increasing the complexity of relationships between components.

So for example, when you want to make sure you eat bacon with breakfast, you can't just add "Prepare bacon" to "Prepare food" b/c now the "Prepare food" task may be executed in "Have lunch", "Have dinner", and "Have midnight snack". And you don't want bacon with your midnight snack! Instead, you have to add a parameter to the task, some conditional, add parameter to each call site, etc... i.e. more complex.


Is "prepare bacon" necessarily part of "prepare food" itself, though? Rather than hardcoding preparing bacon as a stage of food prep, it's probably more maintainable to have the kinds of food passed in (as a list, a Menu object, whatever) - what you're cooking strongly influences the entire process.

  washHands()
  for f in val(foods) do
     coroutine.init(f)
     ...
  end
  waitUntilDone()
  if (not aLazyGit) then doDishes() end
Really, cooking usually involves interwoven stages of things like setting water boiling, whisking a roux, kneading dough, chopping peppers, etc. Tacking on "...and make bacon" at the end of all cooking batches doesn't make sense. Instead, break prepareFood() down further into operations such as boilWater(vol), preheatOven(temp), etc.; Those should be reusable, barring unusual circumstances (e.g. boiling water at high altitudes). Without a lot of specialization via arguments, prepareFood() is too coarse an abstraction, about as vague as doTaxes().


Begs the question: How do you know whether an abstraction is too coarse without writing the code?


Maybe you don't. So then you refactor when you find out.


Re-using showering code is less error prone than maintaining separate copies of showering code!


Not necessarily. When you make a single change to a shared function, you might cause undesired changes to other code that calls that function.


So you're advocating copy/paste style coding, and telling us it is less buggy?

Seriously? And without some extensive explanation?

What about the studies showing number of bugs is proportional to lines of code? Your way adds more lines of code.


No, I'm saying that putting common code in a separate method is not necessarily -- as in, "as a logical result or consequence" -- less error-prone.

I'm not advocating cutting and pasting huge blocks of code everywhere, but a 1-line calculation duplicated in 4 spots is probably okay.


It probably is okay to duplicate a calculation 4 times, all other things being equal. At the same time, I'd say it's probably a sign of other problems. If you need to reuse a calculation, that calculation is part of your application's domain (using the term loosely) and should be represented there, rather than being embedded inside scenario-appropriate parts of the system.


The function may be doing too much, then. It would probably contains several reusable pieces if you broke it up differently.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: