Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

TDD for Android Time-tested tricks to do Test-Driven Development well
PREMIUM
Số trang
413
Kích thước
2.3 MB
Định dạng
PDF
Lượt xem
1340

TDD for Android Time-tested tricks to do Test-Driven Development well

Nội dung xem thử

Mô tả chi tiết

Test-Driven Development: Extensive

Tutorial

Grzegorz Gałęzowski

This book is for sale at http://leanpub.com/tdd-ebook

This version was published on 2020-07-13

This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing

process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools

and many iterations to get reader feedback, pivot until you have the right book and build

traction once you do.

This work is licensed under a Creative Commons Attribution 3.0 Unported License

Tweet This Book!

Please help Grzegorz Gałęzowski by spreading the word about this book on Twitter!

The suggested hashtag for this book is #tddebookxt.

Find out what other people are saying about the book by clicking on this link to search for this

hashtag on Twitter:

#tddebookxt

Contents

Front Matter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Dedications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Thanks! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

About code examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Notes for C# users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Notes for Java users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

Part 1: Just the basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Motivation – the first step to learning TDD . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

What TDD feels like . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

Let’s get it started! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

The essential tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Test framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Mocking framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Anonymous values generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

It’s not (only) a test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

When a test becomes something more . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Taking it to the software development land . . . . . . . . . . . . . . . . . . . . . . . . . . 28

A Specification rather than a test suite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

The differences between executable and “traditional” specifications . . . . . . . . . . . 30

Statement-first programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

What’s the point of writing a specification after the fact? . . . . . . . . . . . . . . . . . 31

“Test-First” means seeing a failure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

“Test-After” often ends up as “Test-Never” . . . . . . . . . . . . . . . . . . . . . . . . . . 37

“Test-After” often leads to design rework . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

Practicing what we have already learned . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

Let me tell you a story . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

Act 1: The Car . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

Act 2: The Customer’s Site . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

CONTENTS

Act 3: Test-Driven Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Epilogue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

Sorting out the bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

How to start? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Start with a good name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Start by filling the GIVEN-WHEN-THEN structure with the obvious . . . . . . . . . . 66

Start from the end . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

Start by invoking a method if you have one . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

How is TDD about analysis and what does “GIVEN-WHEN-THEN” mean? . . . . . . 75

Is there a commonality between analysis and TDD? . . . . . . . . . . . . . . . . . . . . 75

Gherkin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

TODO list… again! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

What is the scope of a unit-level Statement in TDD? . . . . . . . . . . . . . . . . . . . . . 83

Scope and level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

On what level do we specify our software? . . . . . . . . . . . . . . . . . . . . . . . . . . 84

What should be the functional scope of a single Statement? . . . . . . . . . . . . . . . . 84

Failing to adhere to the three rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

How many assertions do I need? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

Developing a TDD style and Constrained Non-Determinism . . . . . . . . . . . . . . . . 90

A style? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

Principle: Tests As Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

First technique: Anonymous Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

Second technique: Derived Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

Third technique: Distinct Generated Values . . . . . . . . . . . . . . . . . . . . . . . . . . 93

Fourth technique: Constant Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

Summary of the example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

Constrained non-determinism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

Specifying functional boundaries and conditions . . . . . . . . . . . . . . . . . . . . . . . 99

Sometimes, an anonymous value is not enough . . . . . . . . . . . . . . . . . . . . . . . 99

Exceptions to the rule . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

Rules valid within boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

Combination of boundaries – ranges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

Driving the implementation from Specification . . . . . . . . . . . . . . . . . . . . . . . . 113

Type the obvious implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

Fake it (‘til you make it) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

Triangulate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

CONTENTS

Part 2: Object-Oriented World . . . . . . . . . . . . . . . . . . . . 131

On Object Composability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

Another task for Johnny and Benjamin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

A Quick Retrospective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140

Telling, not asking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

Contractors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

A Quick Retrospective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

The need for mock objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

Composability… again! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

Why do we need composability? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Pre-object-oriented approaches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

Object-oriented programming to the rescue! . . . . . . . . . . . . . . . . . . . . . . . . . 151

The power of composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

Summary – are you still with me? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

Web, messages and protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

So, again, what does it mean to compose objects? . . . . . . . . . . . . . . . . . . . . . . 158

Alarms, again! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163

Composing a web of objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

Three important questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

A preview of all three answers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

When are objects composed? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

How does a sender obtain a reference to a recipient (i.e. how connections are made)? 166

Receive as a constructor parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

Receive inside a message (i.e. as a method parameter) . . . . . . . . . . . . . . . . . . . 168

Receive in response to a message (i.e. as a method return value) . . . . . . . . . . . . . 169

Receive as a registered observer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

Where are objects composed? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

Composition Root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

Factories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200

Classes vs interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200

Events/callbacks vs interfaces – few words on roles . . . . . . . . . . . . . . . . . . . . . 201

Small interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203

Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

Protocols exist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208

Protocol stability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

CONTENTS

Craft messages to reflect the sender’s intention . . . . . . . . . . . . . . . . . . . . . . . 210

Model interactions after the problem domain . . . . . . . . . . . . . . . . . . . . . . . . . 211

Message recipients should be told what to do, instead of being asked for information 213

Most of the getters should be removed, return values should be avoided . . . . . . . . 216

Protocols should be small and abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223

Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

Single Responsibility Principle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224

Static recipients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231

Object Composition as a Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232

More readable composition root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232

Refactoring for readability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

Composition as a language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

The significance of a higher-level language . . . . . . . . . . . . . . . . . . . . . . . . . . 245

Some advice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251

Value Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

What is a value object? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

Example: money and names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252

Value object anatomy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258

Class signature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Hidden data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Hidden constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

String conversion methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265

Equality members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

The return of investment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269

Aspects of value objects design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

Immutability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270

Handling of variability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278

Special values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282

Value types and Tell Don’t Ask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

Part 3: TDD in Object-Oriented World . . . . . . . . . . . 285

Mock Objects as a testing tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

A backing example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287

Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288

Roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

CONTENTS

Behaviors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289

Filling in the roles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290

Using a mock channel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292

Mocks as yet another context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294

Test-first using mock objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

How to start? – with mock objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

Responsibility and Responsibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295

Channel and DataDispatch one more time . . . . . . . . . . . . . . . . . . . . . . . . . . 296

The first behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296

Second behavior – specifying an error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310

Test-driving at the input boundary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312

Fixing the ticket office . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312

Initial objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313

Bootstrap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316

Writing the first Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338

Test-driving at the input boundary – a retrospective . . . . . . . . . . . . . . . . . . . . . 339

Outside-in development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339

Workflow specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340

Data Transfer Objects and TDD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342

Using a ReservationInProgress . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346

Interface discovery and the sources of abstractions . . . . . . . . . . . . . . . . . . . . . 350

Do I need all of this to do TDD? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350

What’s next? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350

THIS IS ALL I HAVE FOR NOW. WHAT FOLLOWS IS RAW, UNORDERED MATE￾RIAL THAT’S NOT YET READY TO BE CONSUMED AS PART OF THIS TUTORIAL 351

Mock objects as a design tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

Outside-in development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

Worked example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

Programming by intention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

Responsibility-Driven Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

Specifying factories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391

What not to mock? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

Internals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

How to use value objects in Statements? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

How to specify value objects? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

Terminal nodes in object graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392

Guidance of test smells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Long Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

CONTENTS

Lots of stubbing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Specifying private members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Mocking third party . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393

Revisiting topics from chapter 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394

Constrained non-determinism in OO world . . . . . . . . . . . . . . . . . . . . . . . . . . 394

Behavioral boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394

Triangulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394

Maintainable mock-based Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

Setup and teardown . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395

Refactoring mock code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

Part 4: Application architecture . . . . . . . . . . . . . . . . . . . 397

On stable/architectural boundaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398

Ports and adapters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

Physical separation of layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399

What goes into application? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400

Application and other layers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400

What goes into ports? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Data transfer objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Ports are not a layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Part 5: TDD on application architecture level . . . . 402

Designing automation layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

Adapting screenplay pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

Actors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

Data builders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403

Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404

Motivation – the first step to learning TDD . . . . . . . . . . . . . . . . . . . . . . . . . . 404

The Essential Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404

Value Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404

Front Matter

Dedications

Ad Deum qui laetificat iuventutem meam.

To my beloved wife Monika and our lovely son Daniel.

Thanks!

I would like to thank the following people (listed alphabetically by name) for valuable feedback,

suggestions, typo fixes and other contributions:

• Brad Appleton

• Borysław Bobulski

• Chris Kucharski

• Daniel Dec

• Daniel Żołopa (cover image)

• Donghyun Lee

• Łukasz Maternia

• Marek Radecki

• Martin Moene

• Michael Whelan

• Polina Kravchenko

• Rafał Bigaj

• Reuven Yagel

• Rémi Goyard

• Robert Pająk

• Wiktor Żołnowski

This book is not original at all. It presents various topics that others invented and I just picked

up. Thus, I would also like to thank my mentors and authorities on test-driven development and

object-oriented design that I gained most of my knowledge from (listed alphabetically by name):

• Amir Kolsky

• Dan North

• Emily Bache

• Ken Pugh

• Kent Beck

• Mark Seemann

• Martin Fowler

• Nat Pryce

• Philip Schwarz

• Robert C. Martin

• Scott Bain

• Steve Freeman

About code examples

Notes for C# users

The language of choice for code examples is C#, however, I made some exception from the typical

C# code conventions.

Dropping “I” from interface names

I am not a big fan of using ISomething as an interface name, so I decided to drop the I even

though most C# developers expect to see it. I hope you can forgive on this one.

Idiomatic C#

Most of the code in this book is not idiomatic C#. I tried to avoid properties, events, and most

modern features. My goal is to allow users of other languages (especially Java) to benefit from

the book.

Using underscore in field names

Some people like it, some not. I decided to stick to the convention of putting an underscore (_)

before a class field name.

Notes for Java users

The language of choice for the code examples is C#. That said, I wanted the book to be as

technology-agnostic as possible, to allow especially Java programmers to benefit from it. I tried

using a minimum number of C#-specific features and in several places even made remarks

targeted at Java users to make it easier for them. Still, there are some things I could not avoid.

That’s why I wrote up a list containing several of the differences between Java and C# that Java

users could benefit from knowing when reading the book.

Naming conventions

Most languages have their default naming conventions. For example, in Java, a class name is

written with pascal case (e.g. UserAccount), methods and fields are written with camel case,

e.g. payTaxes and constants/readonly fields are typically written in underscored upper-case (e.g.

CONNECTED_NODES).

C# uses pascal case for both classes and methods (e.g. UserAccount, PayTaxes, ConnectedNodes).

For fields, there are several naming conventions. I chose the one starting with underscore (e.g.

_myDependency). There are other minor differences, but these are the ones you are going to

encounter quite often.

About code examples 5

var keyword

For example brevity, I chose to use the var keyword in the examples. This keyword serves as

automatic type inference, e.g.

1 var x = 123; //x inferred as integer

Of course, this is no dynamic typing by any means – everything is resolved at compile time.

One more thing – var keyword can only be used when the type can be inferred, so occasionally,

you will see me declaring types explicitly as in:

1 List<string> list = null; //list cannot be inferred

string as keyword

C# has a String type, similar to Java. It allows, however, to write this type name as keyword,

e.g. string instead of String. This is only syntactic sugar which is used by default by the C#

community.

Attributes instead of annotations

In C#, attributes are used for the same purpose as annotations in Java. So, whenever you see:

1 [Whatever]

2 public void doSomething()

think:

1 @Whatever

2 public void doSomething()

readonly and const instead of final

Where Java uses final for constants (together with static) and read-only fields, C# uses two

keywords: const and readonly. Without going into details, whenever you see something like:

About code examples 6

1 public class User

2 {

3 // a constant with literal:

4 private const int DefaultAge = 15;

5

6 // a "constant" object:

7 private static readonly TimeSpan DefaultSessionTime

8 = TimeSpan.FromDays(2);

9

10 // a read-only instance field:

11 private readonly List<int> _marks = new List<int>();

12 }

think:

1 public class User {

2 //a constant with literal:

3 private static final int DEFAULT_AGE = 15;

4

5 //a "constant" object:

6 private static final Duration

7 DEFAULT_SESSION_TIME = Duration.ofDays(2);

8

9 // a read-only instance field:

10 private final List<Integer> marks = new ArrayList<>();

11 }

A List<T>

If you are a Java user, note that in C#, List<T> is not an interface, but a concrete class. it is

typically used where you would use an ArrayList.

Generics

One of the biggest difference between Java and C# is how they treat generics. First of all, C#

allows using primitive types in generic declarations, so you can write List<int> in C# where in

Java you have to write List<Integer>.

The other difference is that in C# there is no type erasure as there is in Java. C# code retains all

the generic information at runtime. This impacts how most generic APIs are declared and used

in C#.

A generic class definition and creation in Java and C# are roughly the same. There is, however,

a difference on a method level. A generic method in Java is typically written as:

Tải ngay đi em, còn do dự, trời tối mất!