You example is too simple to discuss the separation of code and modularization seriously, but I'll take a risk to give some advice. It should be considered as some food for thought, not a set of rules.
So, first of all, the set of prospective units, whatever they are, should be though as something in 2D space. Why 2D? Because adding more dimensions would be hard to keep in the developers imagination: our vision is 2D in its nature, and anything simpler would be too primitive. So, you mentally arrange your units "vertically" and "horizontally".
Vertical separations should be layered: you put on the bottom layer the most abstract, fundamental and application-agnostic facilities, and, hence, the will be the most universal. In other words, if some features are less likely to change (but can be extended), are more suitable for wider range of applications of wider range of possible yet unknown changes of your current application, the more likely they should be implemented in the bottom. The application itself is on the top layer; and if you have some plug-in mechanism, the plug-ins belong on the very top. In some big systems, I explicitly named the layers, bottom to top, "Agnostic" (semantic-agnostic) or "Universal", then "Semantic", then "Application" and "Plug-in". Again, this is not a rule, just an idea; and you should not make it more complex than your whole solution requires. The main rule of the layers: each layer can use any of the bottom layers, but never any of the top layers. In other words, any layer should be kept totally agnostic to the content of upper layer (but you, as a developer, should be totally aware of the purpose of down layer and its use by upper layers). And that dependency principle
is the rule.
Horizontal separation it the separation by the "topic". Examples are: "network", "data", "file system", "graphics", "UI", and so on. Note that some horizontal units can be represented on one layer, but they could be in one or more layers. For example, some agnostic data management mechanism could be on the fundamental layer, but, say, some semantic data schema can be on the semantic layer above it; and it will use data units of the universal layer. Again, this is just an example.
I don't explain what those units should be. It really depends on the scale of your solution. For example, the layer should be of the scale represented by the whole group of the separate projects, each project representing a horizontal "topic"; so those groups of projects should be also placed in different directories, physical, solution folders, or both. At the same time, in much smaller solution, the whole layer could occupy just one code file. And you can use all the scales in between. In even bigger scale, a layer could occupy the whole host machine and represent a separate tier.
One important thing to understand: with .NET, types (classes, structures) turn out much more stable than files, and files more stable than assemblies. It means: don't scratch your head too much to decide what goes to what assembly. Assembly is the most fundamental concept in .NET, and yet, it's way too easy to move some code from one assembly to another. From the development point of view, the boundaries between assemblies are almost invisible (you only need to use public and protected access modifiers). You can easily start from a monolithic solution and split it as it become more complex.
Your decision not good because of their quality or correctness, they are really good if they are easier to change in future. In other words: don't be afraid of making mistakes, be afraid of making too firm decision preventing fixing your mistakes.
Very generally, the most important consideration in you modularization should be: think how stable your decisions are. Main thing is understanding that you should be able to change everything later; so you can make intermediate or temporary decisions. Try to separate less certain from more certain.
Some more detail: UI plays special role and should be isolated as much as possible. Why? I think this is because of one important social/cultural factor: UI architectures emerge and disappear too quickly. Let's say, this is a field of practical computing and the
technosphere which is the least stabilized one. There is a good number of approaches dedicated to isolation of UI from other aspects of the solution. Please see:
http://en.wikipedia.org/wiki/Presentation%E2%80%93abstraction%E2%80%93control[
^],
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller[
^],
http://en.wikipedia.org/wiki/Hierarchical_model%E2%80%93view%E2%80%93controller[
^],
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93adapter[
^],
http://en.wikipedia.org/wiki/Observer_pattern[
^],
http://en.wikipedia.org/wiki/Model_View_ViewModel[
^].
See also:
http://en.wikipedia.org/wiki/Modular_programming[
^],
http://en.wikipedia.org/wiki/Multitier_architecture[
^],
http://en.wikipedia.org/wiki/Modularity#Modularity_in_technology_and_management[
^],
http://en.wikipedia.org/wiki/Modular_design[
^].
—SA