Book Image

Real-World Implementation of C# Design Patterns

By : Bruce M. Van Horn II
5 (3)
Book Image

Real-World Implementation of C# Design Patterns

5 (3)
By: Bruce M. Van Horn II

Overview of this book

As a software developer, you need to learn new languages and simultaneously get familiarized with the programming paradigms and methods of leveraging patterns, as both a communications tool and an advantage when designing well-written, easy-to-maintain code. Design patterns, being a collection of best practices, provide the necessary wisdom to help you overcome common sets of challenges in object-oriented design and programming. This practical guide to design patterns helps C# developers put their programming knowledge to work. The book takes a hands-on approach to introducing patterns and anti-patterns, elaborating on 14 patterns along with their real-world implementations. Throughout the book, you'll understand the implementation of each pattern, as well as find out how to successfully implement those patterns in C# code within the context of a real-world project. By the end of this design patterns book, you’ll be able to recognize situations that tempt you to reinvent the wheel, and quickly avoid the time and cost associated with solving common and well-understood problems with battle-tested design patterns.
Table of Contents (16 chapters)
1
Part 1: Introduction to Patterns (Pasta) and Antipatterns (Antipasta)
4
Part 2: Patterns You Need in the Real World
8
Part 3: Designing New Projects Using Patterns

The Big Ball of Mud

Around the same time Brown, et al. were writing their book on antipatterns, another research team was engaged in a similar effort. The product of their work was titled Big Ball of Mud, by Foote and Yoder (1997), which I’ve listed in the Further reading section at the end of this chapter. It’s their work that inspires the title of this chapter.

The Big Ball of Mud antipattern is remarkably similar to our outline of stovepipe systems. However, the authors go into greater depth on how these systems understandably come to be.

They often start with throwaway code. I think this is self-explanatory. It’s code that you knock out in a few hours, or even a few weeks, that serves as a rough prototype. It proves to you and perhaps your stakeholders that the problem in front of you is soluble. It might even be good enough to demonstrate to the client. This is where the trap is sprung. The prototype is good enough to publish, so, at the behest of your boss, you do. We’ll simulate this later in this chapter in a section titled A throwaway code example by intentionally building a prototype that is good enough to ship, but not good enough to survive extension. This rough prototype will do everything asked of us. Right after this imaginary software project ships its first release, we’ll then find ourselves faced with a second factor in the construction of a Big Ball of Mud: piecemeal growth. A project manager might refer to this pejoratively as scope creep. I have been a consulting software engineer and a corporate software engineer. I can tell you the project management view of scope creep as being something negative is misinformed. While it is a source of frustration from a planning and billing perspective, new requirements coming in after the initial release are the hallmark of a successful system. It is my strongest advice that you begin every project with the idea that it will be wildly successful. This may seem overly optimistic, but it is in fact the worst-case scenario if you have published throwaway code.

Piecemeal growth leads to a strategy called keeping it working. Again, this needs little explanation. As bugs and new features are identified, you just fix the offending bits and make the program satisfy the new set of requirements. And, oh, by the way, we need this done by next week.

After the second release, keeping it working becomes your daily job description. If your program is really successful, you will start to hire people to help you with keeping it working, which naturally amplifies the problems and technical debt as the project continues to grow.

To reiterate, this sounds very similar to our elucidation of a stovepipe system. Foote and Yoder consider in more detail the forces that lead to our unfortunate muddy circumstances. Forces, as in nature, are outside actors that you can rarely ever control. These forces consist of the following:

  • Time
  • Cost
  • Experience
  • Skill
  • Visibility
  • Complexity
  • Change
  • Scale

Let’s talk a little more about each.

Time

You may not be given enough time to seriously consider the long-term ramifications of the architectural choices that you’re currently making. Time also limits your project by limiting what you can accomplish with what you’re allotted. Most developers and project managers try to get around this by padding their estimates. In my experience, Parkinson’s law is true: projects where time estimates are padded, or even doubled, usually expand to fill or exceed the time allotted.

Cost

Most projects don’t have an infinite budget. Those that do are open source projects that have no monetary budget at all, instead substituting it with the time of volunteers, which is itself a cost. Architecture is expensive. The people with the knowledge and experience to develop a sound architecture are rare, though slightly less inaccessible given that you are reading this book. They tend to draw higher salaries, and the expense involved in the effort to create and maintain proper architecture doesn’t pay off immediately in the minds of your stakeholders, bosses, or customers.

Good architecture requires time, both on the part of the development staff and the architect, but also domain experts who know the business behind the software. The domain experts are rarely dedicated to the software development effort. They have regular jobs with real requirements and deadlines outside the software project. Involving a business consultant who bills at $250 USD per hour is eating up time that could be billable, but you honestly can’t complete the project without this access.

Experience

Software developers are experts in software development. They rarely have expertise in the business domain where they are building solutions. For example, it’s rare that someone building a system that quotes insurance policies has worked as an actuary or even an adjuster. Lack of experience in the business domain makes the job of modeling software a process of trial and error, which naturally affects the program’s architecture.

Skill

Not all software developers have equal levels of skill. Some are new to the field. Some are slower learners than others. Some learned to use a few golden hammers (more on this later) and refuse to upskill any further. And there’s always a superstar on the project that makes everybody else feel as though they’re a poser.

Visibility

You can’t see inside a working program. Sure, you can fire up a debugger, but normal people can’t look around the architecture of your code the same way that they can inspect the architecture of a physical structure such as an office building. For this reason, architecture is neglected. Your boss will not likely give you a fat bonus for your amazing abstractions and interface structures. They will, however, reward you for shipping early. This leads to a very human, lackadaisical attitude toward how your code is structured.

Complexity

Complex problem domains beget muddy architectures. Imagine modeling a collection of modern light bulbs. That’s pretty easy. Properties such as wattage, light output in lumens, and input voltage jump out at you as if they are second nature. Now, imagine modeling a light bulb in 1878. You’re in uncharted territory. Thomas Edison patented his first light bulb in 1879 and is famously quoted as saying that he had discovered two thousand ways to not build a light bulb. If the domain is complex or unexplored, you should expect a bumpy ride as far as your architecture is concerned.

Change

Change is the one thing that always remains constant. Foote and Yoder wrote that when we devise an architecture, it is based entirely upon a supposition: a set of assumptions about the future wherein we expect changes and extensions to that architecture to be bound only to the realm of possibilities that we have considered so far. This is all well and good, except another truism invariably surfaces: no battle plan survives first contact with the enemy. The change requests will come in the most inconvenient form, at the most inconvenient time, and it’s your job to deal with that. The easy way out is always the most palatable to the stakeholders but it is what leads to a Big Ball of Mud.

Scale

Creating a system to be used by 100 people in total is a very different problem than creating a system that can process 10,000 requests per second. The style in which you write your code is different. Your reliance on highly performant algorithms is largely absent in a small system, but vital to the success of a large one. Rarely do projects start at the scale typically considered by Google or Amazon. Successful projects must be able to scale up according to how successful they become.