The Internet of Things (IoT) is turning into practice. To drive innovations, it is crucial that programmers have means to develop IoT applications in the form of IoT programming frameworks. These are toolkits to develop applications according to a certain style or method and that let developers focus on the essence of their applications. New IoT programming frameworks are emerging frequently and this can be overwhelming. To gain useful insights on these frameworks, we define a taxonomy that classifies their architecture. At the same time, the process of developing this taxonomy makes the essential architectural aspects of these frameworks explicit. For each of these aspects, we provide discriminating categories with respect to the effects each category has on certain extra-functional (quality) properties in IoT. We apply the taxonomy on three IoT programming frameworks, namely Works with Nest [1], ARM mbed IoT Device Platform [2] and Alljoyn [3]. Our analysis results in useful insights not only on the architecture of the frameworks but also on the basic differences between the frameworks. Comparing multiple candidate frameworks based on the taxonomy helps to find the most suitable framework for a desired IoT application.