Ad Hoc Programming: Notebooks
It is very common for programming problems to be solved completely without leaving the confines of a single notebook. A notebook can contain any combination of function definitions and expressions that use those functions. See, for example, the Function Definitions section of the Fast Introduction For Programmers.
The nicest thing about notebooks is that they can contain any mixture of code, prose, graphics, animation, audio and other objects. See How to Create a Lecture Notebook for an example.
Library Re-use: Packages
With increased usage, one might find some functionality has usefulness for more than one notebook. The need arises to store such functionality in a library for reuse. Such libraries are called "packages" in Mathematica. A package can be easily referenced from within a notebook, making all of its functions available to that notebook. See Setting Up Wolfram Language Packages.
Interactive Development Environments (IDEs)
Packages can be authored directly within the Mathematica front-end environment. However, many programmers prefer a more conventional IDE. There is an open-source Mathematica Plugin for IntelliJ IDEA. Alternatively, there is a commercial plug-in for Eclipse called Wolfram Workbench.
Notebooks are convenient for improvisational programming tasks, that involve a single developer. They are unfriendly in a collaborative environment involving source control because a notebook acts more like a binary file when it comes to merging. The .m files (or, as of version 10, .wl files) that store packages are simple text files that version well. The IDEs mentioned above have plug-ins to support common version control systems such as SVN or GIT.
The How To section of the Mathematica documentation is handy for new users. For the present question, see especially the Notebooks and Documents section.