Architecture and Design Philosophy

This code was written as part of a programming exercise that included a time limit. The code exemplifies a principle for software architecture and design that I believe is rarely considered today: SIMPLICITY.

March 24th, 1010 - In order to make this stuff clearer I decided to clean up the full, standalone project and post it here for your download. The project files build with Visual Studio 2008 (VC9) for Release and Debug mode on both x86 and x64 systems. Note that this project is simply a demonstration of thread and TCP/IP server management on an MS Windows system. A full-fledged application would have much more in the way of error checking, unit tests, and other infrastructure. :)

These are all cleartext files, not executables, and I'm making them available under the Mozilla trifecta license.

Example Code


By simplicity I mean do not add what is not truly known to be needed. I mean this in the strongest sense. For example, if during the coding process you add an interface element but later find it to be unused, then it is probably to your long-term advantage to remove it.

It has been my experience that the extra code is rarely used and clutters up your name spaces and source control, resulting in a greater cost of change and maintenance. Cost of change and maintenance is a serious problem for large projects, and a small amount of discipline in resisting the temptation to add the unnecessary, "just in case," pays off greatly in the long run.

Simplicity vs. Completeness

Frequently we as programmers and software engineers are driven to make an interface (C++ class) complete in the sense that all anticipated possible actions are accounted for by member variables or member functions. A second completeness practice frequently encountered is to provide multiple methods for achieving the same ends. These choices produce "swiss army knife" style interface definitions. Unless you already know the statistics of usage for your interface, say, because you are rewriting a popular or heavily used class, then "completeness" is likely to increase the cost of change and maintenance in the long run.

Simplicity vs. "Elegance"

I have participated in discussions where elegance is proposed as more important than simplicity as a software design goal. While being raised as a Computer Scientist I was inculcated with the concept of elegance. The culture of Computer Science uses the property of elegance to explain why certain choices are better than others.

  • Elegance is a programming language that is simple to define and that is very powerful in expression (APL, Lisp).
  • Elegance is expressing a language in an LALR(1) grammar (so we can use automated tools to build the compiler).
  • Elegance is a simple but powerfully consequential equation (think E=MC2).

However, elegance is frequently a matter of taste, rather like art. Some things everyone can agree upon as being elegant. Gaining agreement on other things may not be so easy. The elegance of completeness is a good one in the right situation. However, choosing the elegance of simplicity over the elegance of completeness is rarely if ever a mistake. If new capabilities are needed later then add them later.



Original Problem Statement

  • Create a Windows TCP/IP server
  • The server listener thread accepts TCP connections on a specified port
  • The server uses worker threads to process connections
  • The server queues each connection to one of the worker threads
  • Once a worker thread receives a new connection it should:
    • Read up to 100 alphabetical characters (a-z, A-Z) from the socket or until the first non-alphabetical character is encountered
    • Efficiently determine all anagrams of the typed in word given the provided English dictionary in ASCII format. An anagram is a word or phrase formed by reordering the letters of another word or phrase, such as satin to stain.
    • Send all anagrams for the entered word to the client over the socket, one word per line, each followed by a carriage return line feed.
    • Terminate the connection to the socket after all anagrams have been sent