Should I use function_exists() and/or add_action() in theme development?

Do not use function_exists().

Technically, your approach works. In practice, you create problems in your code without any benefit.

  • Readability. When someone else reads your code (e.g. you, one year later), the first question will be: why don’t you know your own code? The second one is probably: OK, where is that function defined, how can I figure out which one is called?

  • Interoperability. When I want to replace your code, I am bound to your name. skematik_doc_type() is a poor name for a function that spits out doctype. I cannot replace it with skematik_doctype() or a class method.
    Oh, and you cannot rename it either, because other peoples code might rely on that name.

  • Inconsistent behavior.

    • You cannot reuse such a function, because you never know what it might do or return.
    • function_exists() behaves not like defined(), you cannot return from a file if the function returns true, because all other code in that file will be parsed earlier. See the comments in the manual for examples. So you cannot reorganize your file structure later.

Using function_exists() is a design decision as Chip pointed out. But a very bad one. It isn’t forbidden in the theme review guidelines, but it should be. The WordPress core will not introduce more “pluggable” functions for the reasons listed above.