¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

[TDD] Statics and caches and mocks oh my!


 

David Burstin wrote:
One option is to add static methods to the repositories to inject canned
data into their internal lists for testing, but that seems wrong to me - it
exposes their internal implementation and breaks encapsulation (is there
such a thing with static objects?).
This is a "pattern" from the book "working with legacy code" - it's good
because it's (relatively) non-invasive and allows you to put your legacy
code under test for further refactoring. So good but temporary solution.

If you're afraid the setters will be used from normal code you can guard
by a boolean that a test must set first.

Another is to create an interface and have the production code use a
concrete implementation that internally calls the static methods.In testing
I can inject mocks. Again, this seems messy to me.
Can you substitute the database itself and let your test data be cached
as they normally would? It's always better to "mock" as little as
possible to avoid tests diverging from reality.

I personally don't like the use of static objects, but I don't know what a
better alternative is that would provide long-lived caching and easy
accessibility from anywhere in the code.
Caches don't need to be static, they just need to be reachable enough so
that they can cache something. Accessibility from anywhere in the code
is actually a design smell I think.

Everyone else on the team thinks that they are a great solution.
I hear you. It's not easy to convince others of their design problems
unless there is hard factual evidence. Look around the user code of that
object and you'll find the smells.

Michal Svoboda


 

On Wed, Jun 26, 2013 at 10:54 AM, Michal Svoboda <pht@...> wrote:

**


Everyone else on the team thinks that they are a great solution.
I hear you. It's not easy to convince others of their design problems
unless there is hard factual evidence. Look around the user code of that
object and you'll find the smells.
Or there might not be any convincing enough smells, yet!

If not, bide your time, watch for smells as the code scales, and when
convincing smells appear, then make the case for refactoring it away
(trying not to say "I told you so").

One benefit is that there may be more information later to indicate what
the most appropriate alternative would be.

SteveG



Michal Svoboda



[Non-text portions of this message have been removed]


 

As far as code smells go, some people just seem to have blocked noses!

Anyway, thanks everyone for your answers. I'm glad to see that I am on the
right track - now I just have to convince everyone else. I think the best
way forward is baby steps. I will start by encapsulating the statics inside
a concrete implementation with a well-defined interface. Even that might
take some convincing! But at least it will give the opportunity to do some
good testing.

I am looking at the possibility of using a DI framework to replace the
singleton caches, but that will be a HUGE leap for these guys. What do you
guys feel is the best strategy for caching without having to pass around an
entire collection of cache instances?


Cheers
David

On 27 June 2013 04:24, Steven Gordon <sgordonphd@...> wrote:



On Wed, Jun 26, 2013 at 10:54 AM, Michal Svoboda <pht@...> wrote:

**


Everyone else on the team thinks that they are a great solution.
I hear you. It's not easy to convince others of their design problems
unless there is hard factual evidence. Look around the user code of that
object and you'll find the smells.
Or there might not be any convincing enough smells, yet!

If not, bide your time, watch for smells as the code scales, and when
convincing smells appear, then make the case for refactoring it away
(trying not to say "I told you so").

One benefit is that there may be more information later to indicate what
the most appropriate alternative would be.

SteveG



Michal Svoboda



 

How much code control does the organization exert? Do you have regular code reviews?

My experience is that the best way is to start small. Make one class testable at a time without touching the caches. Use facade interfaces as wrappers to deal with your statics. For example, in Java I might do something like this:

Existing static:

public static ThingIWant getThingIWant() { accesses the db and caches the result }

Existing class:

class MyClass {

:

void doSomething() {
ThingIWant aThing = ThatStaticClass.getThingIWant();
process(aThing);
}
}


Modified class

class MyClass {
interface SomeInterface {
ThingIWant getThingIWant();
}

static class LiveProxy implements SomeInterface {
public ThingIWant getThingIWant() {
return ThatStaticClass.getThingIWant();
}
}

// test constructor
MyClass(SomeInterface interface) {
this.interface = interface;
}

// production constructor
public MyClass() {
this(new LiveProxy())
}

/// modified method
void doSomething() {
ThingIWant aThing = this.interface.getThingIWant();
process(aThing);
}


Your code is now testable - you supply a test version of the interface when you instantiate it, and can control the object returned. The production code uses the same interface, but supplies a production version which accesses the statics. You don't need to persuade anybody of anything, other than your code reviewers. The rest of the system remains unchanged.

At some point in the future, once you have an acceptable level of code coverage, you can tackle changing the statics, but I'd put that off as long as possible.

The important thing is to start by testing as much as you can while making as few changes as possible.

- Russ


On Jun 27, 2013, at 2:59 AM, David Burstin <david.burstin@...> wrote:

As far as code smells go, some people just seem to have blocked noses!

Anyway, thanks everyone for your answers. I'm glad to see that I am on the
right track - now I just have to convince everyone else. I think the best
way forward is baby steps. I will start by encapsulating the statics inside
a concrete implementation with a well-defined interface. Even that might
take some convincing! But at least it will give the opportunity to do some
good testing.

I am looking at the possibility of using a DI framework to replace the
singleton caches, but that will be a HUGE leap for these guys. What do you
guys feel is the best strategy for caching without having to pass around an
entire collection of cache instances?


Cheers
David


On 27 June 2013 04:24, Steven Gordon <sgordonphd@...> wrote:



On Wed, Jun 26, 2013 at 10:54 AM, Michal Svoboda <pht@...> wrote:

**


Everyone else on the team thinks that they are a great solution.
I hear you. It's not easy to convince others of their design problems
unless there is hard factual evidence. Look around the user code of that
object and you'll find the smells.
Or there might not be any convincing enough smells, yet!

If not, bide your time, watch for smells as the code scales, and when
convincing smells appear, then make the case for refactoring it away
(trying not to say "I told you so").

One benefit is that there may be more information later to indicate what
the most appropriate alternative would be.

SteveG



Michal Svoboda







------------------------------------

Yahoo! Groups Links


-----------------
Come read my webnovel, Take a Lemon <>,
and listen to the Misfile radio play <>!


 

Thanks Russ. That is exactly the way I am going to start.

Amazingly I even met some resistance to that approach - "it will be
inconsistent with the rest of the application", "someone new coming along
won't understand what is going on" ...

I have managed to convince them by showing the difficulties of unit testing
as the code stands, although they were happy just doing slow running
end-to-end tests and assuming that since the few test cases passed then the
whole system was fine. The standard policy is that for every 10 hours of
coding we need to allocate 3 hours of future defect fixing! I am hoping to
change that. Slowly, slowly...


On 27 June 2013 23:51, Russell Gold <russ@...> wrote:

**


How much code control does the organization exert? Do you have regular
code reviews?

My experience is that the best way is to start small. Make one class
testable at a time without touching the caches. Use facade interfaces as
wrappers to deal with your statics. For example, in Java I might do
something like this:

Existing static:

public static ThingIWant getThingIWant() { accesses the db and caches the
result }

Existing class:

class MyClass {

:

void doSomething() {
ThingIWant aThing = ThatStaticClass.getThingIWant();
process(aThing);
}
}

Modified class

class MyClass {
interface SomeInterface {
ThingIWant getThingIWant();
}

static class LiveProxy implements SomeInterface {
public ThingIWant getThingIWant() {
return ThatStaticClass.getThingIWant();
}
}

// test constructor
MyClass(SomeInterface interface) {
this.interface = interface;
}

// production constructor
public MyClass() {
this(new LiveProxy())
}

/// modified method
void doSomething() {
ThingIWant aThing = this.interface.getThingIWant();
process(aThing);
}

Your code is now testable - you supply a test version of the interface
when you instantiate it, and can control the object returned. The
production code uses the same interface, but supplies a production version
which accesses the statics. You don't need to persuade anybody of anything,
other than your code reviewers. The rest of the system remains unchanged.

At some point in the future, once you have an acceptable level of code
coverage, you can tackle changing the statics, but I'd put that off as long
as possible.

The important thing is to start by testing as much as you can while making
as few changes as possible.

- Russ



On Jun 27, 2013, at 2:59 AM, David Burstin <david.burstin@...>
wrote:

As far as code smells go, some people just seem to have blocked noses!

Anyway, thanks everyone for your answers. I'm glad to see that I am on
the
right track - now I just have to convince everyone else. I think the best
way forward is baby steps. I will start by encapsulating the statics
inside
a concrete implementation with a well-defined interface. Even that might
take some convincing! But at least it will give the opportunity to do
some
good testing.

I am looking at the possibility of using a DI framework to replace the
singleton caches, but that will be a HUGE leap for these guys. What do
you
guys feel is the best strategy for caching without having to pass around
an
entire collection of cache instances?


Cheers
David


On 27 June 2013 04:24, Steven Gordon <sgordonphd@...> wrote:



On Wed, Jun 26, 2013 at 10:54 AM, Michal Svoboda <pht@...>
wrote:

**


Everyone else on the team thinks that they are a great solution.
I hear you. It's not easy to convince others of their design problems
unless there is hard factual evidence. Look around the user code of
that
object and you'll find the smells.
Or there might not be any convincing enough smells, yet!

If not, bide your time, watch for smells as the code scales, and when
convincing smells appear, then make the case for refactoring it away
(trying not to say "I told you so").

One benefit is that there may be more information later to indicate what
the most appropriate alternative would be.

SteveG



Michal Svoboda



[Non-text portions of this message have been removed]



------------------------------------

Yahoo! Groups Links


-----------------
Come read my webnovel, Take a Lemon <>,
and listen to the Misfile radio play <
>!


[Non-text portions of this message have been removed]



[Non-text portions of this message have been removed]


Keith Ray
 

I just want to add that you might need to convince your coworkers to keep unit tests passing.

If they are further convinced of the usefulness of writing tests, then you can show them up how helpful refactoring for testability is.

--
C. Keith Ray
* 650-533-6535
*
*

On 2013 Jun 27, at 6:51 AM, Russell Gold <russ@...> wrote:

How much code control does the organization exert? Do you have regular code reviews?

My experience is that the best way is to start small. Make one class testable at a time without touching the caches. Use facade interfaces as wrappers to deal with your statics. For example, in Java I might do something like this:

Existing static:

public static ThingIWant getThingIWant() { accesses the db and caches the result }

Existing class:

class MyClass {

:

void doSomething() {
ThingIWant aThing = ThatStaticClass.getThingIWant();
process(aThing);
}
}

Modified class

class MyClass {
interface SomeInterface {
ThingIWant getThingIWant();
}

static class LiveProxy implements SomeInterface {
public ThingIWant getThingIWant() {
return ThatStaticClass.getThingIWant();
}
}

// test constructor
MyClass(SomeInterface interface) {
this.interface = interface;
}

// production constructor
public MyClass() {
this(new LiveProxy())
}

/// modified method
void doSomething() {
ThingIWant aThing = this.interface.getThingIWant();
process(aThing);
}

Your code is now testable - you supply a test version of the interface when you instantiate it, and can control the object returned. The production code uses the same interface, but supplies a production version which accesses the statics. You don't need to persuade anybody of anything, other than your code reviewers. The rest of the system remains unchanged.

At some point in the future, once you have an acceptable level of code coverage, you can tackle changing the statics, but I'd put that off as long as possible.

The important thing is to start by testing as much as you can while making as few changes as possible.

- Russ


On Jun 27, 2013, at 2:59 AM, David Burstin <david.burstin@...> wrote:

As far as code smells go, some people just seem to have blocked noses!

Anyway, thanks everyone for your answers. I'm glad to see that I am on the
right track - now I just have to convince everyone else. I think the best
way forward is baby steps. I will start by encapsulating the statics inside
a concrete implementation with a well-defined interface. Even that might
take some convincing! But at least it will give the opportunity to do some
good testing.

I am looking at the possibility of using a DI framework to replace the
singleton caches, but that will be a HUGE leap for these guys. What do you
guys feel is the best strategy for caching without having to pass around an
entire collection of cache instances?


Cheers
David


On 27 June 2013 04:24, Steven Gordon <sgordonphd@...> wrote:



On Wed, Jun 26, 2013 at 10:54 AM, Michal Svoboda <pht@...> wrote:

**


Everyone else on the team thinks that they are a great solution.
I hear you. It's not easy to convince others of their design problems
unless there is hard factual evidence. Look around the user code of that
object and you'll find the smells.
Or there might not be any convincing enough smells, yet!

If not, bide your time, watch for smells as the code scales, and when
convincing smells appear, then make the case for refactoring it away
(trying not to say "I told you so").

One benefit is that there may be more information later to indicate what
the most appropriate alternative would be.

SteveG



Michal Svoboda



[Non-text portions of this message have been removed]



------------------------------------

Yahoo! Groups Links


-----------------
Come read my webnovel, Take a Lemon <>,
and listen to the Misfile radio play <>!




Keith Ray
 

On 2013 Jun 27, at 4:06 PM, David Burstin <david.burstin@...> wrote:

The standard policy is that for every 10 hours of
coding we need to allocate 3 hours of future defect fixing!
Wow. I knew a programmer who was dinged by her manager because she wasn't creating enough bugs. They expected a certain number of bugs per some number of lines of code to be found in code-review and testing.

--
C. Keith Ray
* 650-533-6535
*
*


 

I used this approach at a company-that-shall-not-be-named, years ago.

I started with 2 unit tests for my group's part of the system. A week later I was up to 10, and my co-workers started seeing that I was able to work more quickly than they, so they added their own. Six months later, it was clear to the rest of the organization that we were working much faster and breaking the overall build much less frequently than everybody else. After a year, most of the organization was doing unit testing.

Good luck and let us know how you're doing!

- Russ

On Jun 27, 2013, at 7:06 PM, David Burstin <david.burstin@...> wrote:

Thanks Russ. That is exactly the way I am going to start.

Amazingly I even met some resistance to that approach - "it will be
inconsistent with the rest of the application", "someone new coming along
won't understand what is going on" ...

I have managed to convince them by showing the difficulties of unit testing
as the code stands, although they were happy just doing slow running
end-to-end tests and assuming that since the few test cases passed then the
whole system was fine. The standard policy is that for every 10 hours of
coding we need to allocate 3 hours of future defect fixing! I am hoping to
change that. Slowly, slowly...


On 27 June 2013 23:51, Russell Gold <russ@...> wrote:

**


How much code control does the organization exert? Do you have regular
code reviews?

My experience is that the best way is to start small. Make one class
testable at a time without touching the caches. Use facade interfaces as
wrappers to deal with your statics. For example, in Java I might do
something like this:

Existing static:

public static ThingIWant getThingIWant() { accesses the db and caches the
result }

Existing class:

class MyClass {

:

void doSomething() {
ThingIWant aThing = ThatStaticClass.getThingIWant();
process(aThing);
}
}

Modified class

class MyClass {
interface SomeInterface {
ThingIWant getThingIWant();
}

static class LiveProxy implements SomeInterface {
public ThingIWant getThingIWant() {
return ThatStaticClass.getThingIWant();
}
}

// test constructor
MyClass(SomeInterface interface) {
this.interface = interface;
}

// production constructor
public MyClass() {
this(new LiveProxy())
}

/// modified method
void doSomething() {
ThingIWant aThing = this.interface.getThingIWant();
process(aThing);
}

Your code is now testable - you supply a test version of the interface
when you instantiate it, and can control the object returned. The
production code uses the same interface, but supplies a production version
which accesses the statics. You don't need to persuade anybody of anything,
other than your code reviewers. The rest of the system remains unchanged.

At some point in the future, once you have an acceptable level of code
coverage, you can tackle changing the statics, but I'd put that off as long
as possible.

The important thing is to start by testing as much as you can while making
as few changes as possible.

- Russ



On Jun 27, 2013, at 2:59 AM, David Burstin <david.burstin@...>
wrote:

As far as code smells go, some people just seem to have blocked noses!

Anyway, thanks everyone for your answers. I'm glad to see that I am on
the
right track - now I just have to convince everyone else. I think the best
way forward is baby steps. I will start by encapsulating the statics
inside
a concrete implementation with a well-defined interface. Even that might
take some convincing! But at least it will give the opportunity to do
some
good testing.

I am looking at the possibility of using a DI framework to replace the
singleton caches, but that will be a HUGE leap for these guys. What do
you
guys feel is the best strategy for caching without having to pass around
an
entire collection of cache instances?


Cheers
David


On 27 June 2013 04:24, Steven Gordon <sgordonphd@...> wrote:



On Wed, Jun 26, 2013 at 10:54 AM, Michal Svoboda <pht@...>
wrote:

**


Everyone else on the team thinks that they are a great solution.
I hear you. It's not easy to convince others of their design problems
unless there is hard factual evidence. Look around the user code of
that
object and you'll find the smells.
Or there might not be any convincing enough smells, yet!

If not, bide your time, watch for smells as the code scales, and when
convincing smells appear, then make the case for refactoring it away
(trying not to say "I told you so").

One benefit is that there may be more information later to indicate what
the most appropriate alternative would be.

SteveG



Michal Svoboda







------------------------------------

Yahoo! Groups Links


-----------------
Come read my webnovel, Take a Lemon <>,
and listen to the Misfile radio play <
>!










------------------------------------

Yahoo! Groups Links


-----------------
Come read my webnovel, Take a Lemon <>,
and listen to the Misfile radio play <>!


 

On 28 June 2013 20:24, Keith Ray <keith.ray@...> wrote:
On 2013 Jun 27, at 4:06 PM, David Burstin <david.burstin@...> wrote:

The standard policy is that for every 10 hours of
coding we need to allocate 3 hours of future defect fixing!
Wow. I knew a programmer who was dinged by her manager because she wasn't creating enough bugs. They expected a certain number of bugs per some number of lines of code to be found in code-review and testing.
I remember reading that NASA projects would not be released until a
certain number of bugs had been found. This number was based on the
project size and compared against bug statistics gathered from
previous projects. Sadly, I can't find a URL to cite right now.


 

There is a practice called "bebugging" (not a typo) in which developers deliberately seed the program with known bugs. The presumption is that testers will find them at about the same rate as unknown bugs. When enough have been found, the testing is considered to be adequate. Assuming existing bug rates in the absence of bebugging can be unreliable - but only if you really do have a better way of doing things.

On Jun 30, 2013, at 5:57 AM, James Shaw <js102@...> wrote:

On 28 June 2013 20:24, Keith Ray <keith.ray@...> wrote:
On 2013 Jun 27, at 4:06 PM, David Burstin <david.burstin@...> wrote:

The standard policy is that for every 10 hours of
coding we need to allocate 3 hours of future defect fixing!
Wow. I knew a programmer who was dinged by her manager because she wasn't creating enough bugs. They expected a certain number of bugs per some number of lines of code to be found in code-review and testing.
I remember reading that NASA projects would not be released until a
certain number of bugs had been found. This number was based on the
project size and compared against bug statistics gathered from
previous projects. Sadly, I can't find a URL to cite right now.


------------------------------------

Yahoo! Groups Links


-----------------
Come read my webnovel, Take a Lemon <>,
and listen to the Misfile radio play <>!