TDD as if you Meant It: Some Traditional TDD – part 1 (Episode 6)

TDD as if you Meant It: Some Traditional TDD – part 1 (Episode 6)

About

This is the first episode of an alternative evolutionary design approach. During the last episode (Episode 5) I refactored the code to generate a builder. The alternative presented in Episode 6 and 7 is to stop using TDD as if you Meant It for a while and start using some traditional TDD.

Traditional TDD

In a traditional TDD approach I am creating some structures up-front. I can create more or less design up-front, but still the minimum I create is the production class or function I want to test. This approach is different from TDD as if you Meant It where I am extracting the code from the test method, to the test class and to a production class.
In a traditional TDD approach we can have different approaches: bottom-up, top-down, middle-top, middle-bottom, etc. But I take this decision depending on the clear need I observe in the current moment.

Specifications with TDD

Whenever I start with traditional TDD, I need to define the clear specifications. Or in other terms, I define the clear needs of the design structure I need to add. In this current case I defined the fact that I need a fluent builder. So my current tests will reflect the need in the tests. In this approach the evolutionary part of the design is marginal. As I am very clear with what I need, I don’t need a lot of proof. This is not always the case.

Scale of Evolutionary Design

At one extreme I am in the point where I know exactly what I need. In this case any form of Evolutionary Design or TDD is useless. I might want to add automated tests (while adding the code or after) to perform the checks on the code just for regressions.
At another extreme I don’t know at all what I need, but I have the specs. So I start with them and I focus on the principles of refining the code concepts in order to extract the appropriate design entities.

During this codecast I will situate myself very close to the extreme where I know pretty well what I want. But careful to be sure you always introspect and clarify if you have all the information to take a design decision without enough proof. Your solution might be too complicated or just inappropriate.

 

Read More →

TDD as if you Meant It: Refactoring to Builder (Episode 5)

TDD as if you Meant It: Refactoring to Builder (Episode 5)

About

Cost of Change during evolution

There are some language structures that make Evolutionary Design difficult. One of them is the constructor. When I evolve the code, I often understand that one more parameter is needed for the constructor. Because of this I need to minimize the cost of change of the constructor. The best way I know to do that is by creating a builder. In this way I will call the constructor only once, in the builder. So my cost of change is really small.

Duplication

If I need to introduce a new design concept, I make sure before that I minimized the duplication connected to that new design concept. Calling new Board(…) many times is a clear sign of duplication. This duplication would make the code evolution considerably slower.

State Immutability

Testing becomes easier when state does not change during the life cycle of the object. Or, there are no setters on any object. That is why I use constructors and private fields.

Fluent Builder

A builder is called fluent when it looks like playerBuilder.withName(“Adi”).withAge(7).withColor(“Red”).build(). If let’s say I need to introduce a new characteristic to my player, I can always add a new method to the PlayerBuilder. And I would have something like playerBuilder.withName(“Adi”).withAge(7).withColor(“Red”).withExperienceLevel(“Beginner”).build().

Focused Tests with Idempotence

Having this type of builder also lets me have focused tests. I don’t want my test that needs only Age to contain Name. So I want to be able to have playerBuilder.withAge(34).build(). In this case all the values for all the other fields of Player will have a default value that is not generating any side-effects in the system. We could call this characteristic an idempotence of the builder.

Read More →

Talk: Behind Agile Practices (RO)

Talk: Behind Agile Practices (RO)

About

I gave this talk about Agile Practices at the Bucharest Agile Software Meetup Group, Agileworks. It’s in Romanian, because that’s what the audience wanted.

One by one I explain how some of the most common agile practices emerged. Also I explain when and why it’s a good idea to apply them. As seen in practice, some practices are just a hype, and they are very difficult to implement in an organization. Due to that you should always take into account the negative impact of introducing a new practice. Also be prepared for the consequences. There is no such thing as a perfect practice, you can always generate negative effects.

Agile started to become a hype because more and more companies are forced to deliver software faster. Because the markets are changing faster, the production and delivery speed is essential in this fast-paced world.

The last topic I am addressing is the apparent need or organizations to scale agile. There are multiple ways of scaling agile (horizontal, vertical, etc). Most of all we must ask ourselves if we really need to scale. Scaling agile too fast may generate counter-effects. Probably the worst effects are the decrease in productivity and minimizing the focus on the product value. Finally we can scale an organization and focus on the agile format, but not on its values.

Best Practices Read More →

TDD as if you Meant It: Refactor to a new Class (Episode 4)

TDD as if you Meant It: Refactor to a new Class (Episode 4)

About

Extract Class

Starting from the methods that I extracted in the testing class I make them static and then extract them to a new class. The methods from the extracted class are then static. I change the static call with a call to an instance created in the setup of the test. There is a small trick I use when doing that, so that I am always on green while refactoring. Check the codecast to spot it!

The Rule of Three – extract class

In this case as well The Rule of Three applies: only extract duplication when spotted at least three times. When extracting methods to a new class I need at least three methods that belong together.

As mentioned in the previous articles, this is just a guideline. If you are sure, extremely sure, that one method should be extracted, then go for it. But be careful not to generalize to soon. Premature generalization is the root of all evil (Donald Knuth paraphrase).

Testability – Guidelines

Because all the tests are calling the extracted class, it is tested as well, but indirectly. This is a classicist TDD approach where I don’t mind if I test a few classes together, without any dependency injection, stubbing or mocking. Another approach would be to start adding tests to the extracted class, after it was extracted. It is a question of style, but there are also some guidelines to this.
The extracted class needs to either have only logic, or only to hold data.
Whenever I don’t have any logic in the extracted class, I won’t add new tests.
If the extracted class has logic, but it is trivial, I will use the existing indirect tests.
If the extracted class has a lot of logic, I will split the existing tests to have specific tests for the extracted class, and smaller (simpler) initial tests.

Read More →

TDD as if you Meant It: Refactor Primitives to Concepts (Episode 3)

TDD as if you Meant It: Refactor Primitives to Concepts (Episode 3)

About

Hidden Concepts

Each primitive is always hiding a business concept (or call them Domain Entities if you wish). During this episode these primitives will get better names (“Maximize Clarity” from the Four Elements of Simple Design) and when I see duplication between them, it will be removed (“Minimize Duplication” from the Four Elements of Simple Design).

Whenever these concepts remain hidden, the cost of change is big. The more hidden design concepts we have, the bigger the cost of change. I optimize my code for fast and cheap changeability. Because this example is written using Object Oriented Programming concepts, each of these concepts needs at the end to become a class.

Classical Evolutionary Design Layers

The business concepts grow in layers from: primitives, to variables, methods and then classes. With TDD as if you Meant It we always use the rule of three when evolving from one layer to another. I always use refactorings to make duplication explicit and then minimize it. I never skip a layer, because that would be a much too bigger step. We could call this approach Evolutionary Design in Baby Steps.

This approach is useful when starting bottom-up, when there are no, or not may classes and methods, but tests. This approach would not be suitable usually when having a top-down approach.

Read More →

TDD as if you Meant It: I care about Behavior and not about Representation (Episode 2)

TDD as if you Meant It: I care about Behavior and not about Representation (Episode 2)

About

Intentional Primitive Obsession

In the first episode I added some tests where I represent state as strings. This is an intentional approach to hide the complexity of the concepts with primitives. Since with TDD as if you Meant It I am not allowed to add any new classes, I need to start the problem by using primitives. I could have used an array to define the Board concept, but that already means that I am taking more complex design decisions.

Triangulating

I am focusing on triangulating on the concept of GameResult in order to have enough proof in order to extract it to a method. The typical proof I am searching for is duplication. I apply the Rule of Three to spot duplication and then to generalize my code.

Deductive vs Inductive

When doing evolutionary design I am deductive or inductive.
Inductive: I start from small concepts and I generalize them. Whenever I can can generalize some higher order concepts from the code I have, I extract them. These higher order concepts are usually a crystallization of the raw primitives.

Deductive: when doing design up-front I am deductive. I start from some bigger idea and then I try to prove it with code.
Read More →

TDD as if you Meant It: Think – Red – Green – Refactor (Episode 1)

TDD as if you Meant It: Think – Red – Green – Refactor (Episode 1)

About

TDD as if you meant it is a very strict way of writing code in a Test Driven Development approach. One needs to follow the rules below:

Guidelines

In the first episode the main focus in to respect a few guidelines:

  1. Guideline 1: Always start with outputs when doing an analysis
  2. Guideline 2: Behavior Slicing
  3. Guideline 3: SIMPLIFY!
  4. Guideline 4: Introduce only one notion (domain concept) at a time, one per test
  5. Guideline 5: The rule of three “only extract duplication when spotted at least three times”
  6. Guideline 6: Triangulation

Read More →

Evolutionary Design: Normalize Growth

Evolutionary Design: Normalize Growth

The Definitions

Evolutionary Design is the practice of creating the components and interactions of a system while it is evolving, on the basis of the client requirements and user needs.

Normalization refers to a process that makes something more normal or regular

Normalization may refer to more sophisticated adjustments where the intention is to bring the entire probability distributions of adjusted values into alignment from Wikipedia

Growth refers to a positive change in size, and/or maturation, often over a period of time from Wikipedia

 

The Moment

I am a big fan of gardening. Whenever I can, I take care of my plants and think about subjects like Evolutionary Design. One moment I was taking care of my young tomato plants: I needed to rip the small leaves that grow and just take the food away from the flowers and fruits. And it struck me: any gardener is doing Evolutionary Design.

pruning

Read More →

Talk: Easier to change CODE

Talk: Easier to change CODE

This is a talk from I T.A.K.E. Unconference 2016, Bucharest.

It is a hands-on talk, where I refactor some code live with the help of the audience.

Techniques

During this talk you will see techniques that are useful for tackling legacy code issues. You will be able to see how, with the help of the audience, the code can be improved to become easier to change. We want to change existing code in just a few situations: solve bug, add feature, improve the testability of the system. Remember that when you change existing code you understand what is the reason to do this.

Before changing the code is important to have some tests as a safety net. For that I am using Characterization Tests. Only after having these characterization tests, we can start to refactor the code, but with care in order not to introduce defects. Even though we have a safety net, it is not enough and bugs might appear. So to make sure we have more trust in tests the first refactoring steps are made with the purpose to be able to add unit tests.

Adding unit tests gives me better quality feedback, because if I introduce a defect I will know better what I have done wrong. A characterization test is too big, and I might need to dig a while to find the reason.

Changing legacy code needs to be done with care, in small steps and try to always remain with the tests on green. The longer I stay on red, the riskier is that I introduce defects and I lose my refactoring direction.

Easier to change CODE means the total opposite of the Legacy Code is Fear concept. I have my toolbox with legacy code techniques. I know how to use them,  and so I am able to make the code to be easier to change.

Video

 

Interview by Lemi Orhan for Software Craftsmanship Turkey

We discussed about things like:

  • Well crafted code
  • Ways to improve one’s craft
  • How to become a conference speaker
  • and many more…