One of our internal projects at Y Soft R&D carried out by the Lead Developers is to prepare and maintain internal teaching materials. We have only recently started with the project and our first goal is to prepare trainings and drills for the baseline level to establish the basic skills each and every developer at Y Soft needs to know. Parts of it are also relevant for other colleagues, like Solution Architects, due to them writing and testing customizations.

Our baseline level is modeled around 4 Rules of Simple Design and we are now working on the first part, which is covering unit testing. We spent a whole day to prepare simple rules to help developers write good unit tests, defining what we call Unit Test Patterns.

There are four patterns we have defined:

  • Referentially Transparent Contract
  • Non-Referentially Transparent Contract
  • State Inspection
  • Side Effects Inspection

The first two are modeled after Classic TDD while the latter two are modeled after London school of TDD (What’s the difference?).

We are now preparing the coursework, guidelines and exercises to stick to the following outline.

  1. Unit Testing Trivia. The AAA / GWT principle.
  2. Using frameworks and tools to write / run unit tests in Java and C#.
  3. Unit Test Patterns. The Decision Flow or How do I know which pattern to use?
  4. Writing Tests using the RT Contract pattern
  5. Writing Tests using the non-RT Contract pattern
  6. Writing Tests using the State Inspection Pattern
  7. Writing Tests using the Side Effects Inspection Pattern

We want to produce internal web casts for the first three and Koans like exercises for number 4 – 7. Essentially providing contracts to write tests to and evaluating the tests by executing them on several purposedly flawed implementations.

The purpose of this is not to reinvent the wheel, but provide an easy to use, simple framework to help design and write unit tests.

Over the years, I have acummulated several acronyms, which I believe capture essence of various disciplines done right. Here are some picks from my list…

SOLID

One cannot ignore SOLID principles, if you are serious about object oriented design. While this might seem obsolete, it is now relevant more than ever. One word of advice, take SOLID as a whole, do not choose one principle over another. They are not meant to be applied in isolation.

So what SOLID stands for?

  • Single Responsibility Principle
  • Open / Closed Principle (Open for Extension / Closed for changing implementation)
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion

GRASP

Is a collection of patterns used in OOD. While I find rather artifical, I am still using it to remind myself of the different aspects of OOD I should take into account.

GRASP stands for General Responsibility Assignment Software Patterns, which is somewhat lame. What it really stands for are the following patterns or notions:

  • Controller
  • Creator
  • Indirection
  • Information Expert
  • High Cohesion
  • Low Coupling
  • Polymorphism
  • Protected Variations
  • Pure Fabrication

One day, I will write about what those really mean to me.

STRIDE

Is a recent addition, to my collection, but I quite like it. It is the threat model invented at Microsoft as part of their Secure Development Lifecycle framework.

STRIDE stands for different threats developers should take into account when capturing potential threats:

  • Spoofing Identity
  • Tampering with Data
  • Repudiation
  • Information Disclosure
  • Denial of Service
  • Elevation of Privileges

DIE

Simply put: Duplication Is Evil.

User Stories, Epics, Themes, Agile Use Cases, Behaviors… whatever helps us capture user motivation, need and the benefit is useful and an improvement over bloated analyses and specifications which (and many developers do not notice that) just steal creativity out of our work. I am not going to write another post about the benefits of this, but I am going to elaborate on one particular use story, we have met with, which was not done right.

Before I do this, I need to first introduce a notion of unintentional and intentional design. Intentional design stems from constraints imposed by customer environment, market conditions, etc. and is best captured in constraints and conditions. However, sometimes it might find its way to user stories while not defeating the purpose. Unintentional design is quite different story, and while it seems that such thing is obvious, it is far from it.

Before we delve into the story, let’s provide some background. SafeQ application has components which run on MFDs (Multi-Function Devices or Multi-Function Printers). You all know them as those rather big devices which can do copying, scanning and printing and these days, they can also run third party applications. In SafeQ, we call these applications Embedded Terminal applications. Before they can be used, they require some kind of installation or deployment.

And here comes our use story:

As an administrator, I want to automatically deploy Embedded Terminal application to the MFD, so that I save time.

Let’s delve into it…

As an administrator…

Administrator is the person who performs the deployment and the maintenance of the system. Nothing really misleading about this yet.

…I want to automatically deploy Embedded Terminal application to the MFD…

Which is the unintentional design. Automated deployment of ET application is part of our feature set, but can be done terribly wrong, if the developers focus on the automation and not the essential part, which is difficulty and sensitivity to human error.

So, let us elaborate…

As an Administrator, I want to eliminate all manual steps required to deploy Embedded Terminal application to the MFD…

Which switches our focus from automation, to something more important… the number of manual steps (and implied complexity) of the deployment of the embedded terminal application. But we still suffer from unintentional design: deployment. What is deployment? Even when we have this term defined in our glossary, it is still unclear and ambiguous word for the developers. When does the deployment start and when does it end?

As an administrator, I want to eliminate all manual steps required to perform before users can start using SafeQ features on the MFD…

And we have come up with intent, which is clear from design… the purpose of the whole activity is to enable users access SafeQ features. By all means not ideal, but much better in expressing the purpose and avoiding design.

…so that i save time.

Difficult to understand, what saving time really means. Does it mean, that we need to save time when preparing the MFD, but at the cost of difficult troubleshooting later. Is saving time really the quality we are looking for?

Look at it from the perspective of the Administrator, who needs to prepare thousands of MFDs for thousands of users (a scenario which is quite common for our customers). Does he care about his time most? From the perspective of having to deploy one machine at a time, he does. But he also cares about the readiness of the devices. Would he prefer to tradeoff some of his time just to increase the reliability of the environment? Ask them, they tell you “by all means”.

We are looking into a complex quality here… time, reliability, failing fast. So our user story is not complete yet, but I will focus on this topic in my next post.