Wednesday, 18 March 2015

Remote Meetings - Balancing the Act

Meetings are hard when some team members are remote and are physically based in the same location.

It is easy for the remote user to feel second class in terms of the meeting. Remote workers can find it hard to add to the meeting without interrupting or getting left behind.

One practice to balance the process of remote meeting is to ensure that if one or more parties are remote, all participants remote into meeting.

Benefits

  • Levels playing field - everyone should have equal opportunity to contribute.
  • Removes lag - everyone has the same experience of time/delay.
  • Includes online benefits such as message logs, sharing of screen.
  • Comfort of own desk/environment.

This idea was taken from Stack Exchange's post detailing why they still believe in remote working.

Wednesday, 11 March 2015

Dependency Elimination Principle

This is the third, and final part of my series on abstractions.

I've wrote about what good dependencies are before, and the benefits if you can limit and remove them where possible.

You can take this idea further though, by applying concepts from functional programming such as "depend on values rather than dependencies".

A wise colleague started me down this path of passing values, rather than dependencies on collaborators after we repeatedly found ourselves depending on implementation details. This meant our high level domain logic was tightly coupled to low level implementation details.

Brian Geihsler reminded me of this concept with an excellent demonstration of this in practice and has allowed me to put a name to this practice.

Additionally J.B. Rainsberger's example is with a virtual clock, another common dependency we often need. In this case, ask for the time, not how you get the time. The example also highlights another common problem with conventions when using a framework or library.

Here we can handle commands but only those that match the signature of taking a single command, and returning no response. In order to apply the Dependency Elimination Principle (DEP) and remove the clock wrapper we can introduce an overload. Our tests will be expressed using the overload, while the production code will make use of the standard method. If the class in question has a relevant set of interfaces, the overload would be omitted from this to ensure that consumers have a clean, focused API to consume.

When the DEP is applied to other dependencies such as configuration details, flexibility is achieved by the ability to provide these values from any source. As a side effect, coupling has been reduced, while also removing an unnecessary abstraction from the codebase.

Try to apply the DEP where possible. Remove as many dependencies as possible for flexible, maintainable code. Not all dependencies can be eliminated, but unless the dependency is a valid abstraction it may be worth considering removing or reducing use.

Tuesday, 3 March 2015

Reused Abstraction Principle

This is the second part of my series on abstractions.


The Reused Abstraction Principle is a simple in concept in practice, but oddly rarely followed in typical enterprise development. I myself have been incredibly guilty of this in the past.

Most code bases have a 1:1 mapping of interfaces to implementations. Usually this is the sign of TDD or automated testing being applied badly. The majority of these interfaces are wrong. 1:1 mappings between interfaces and implementations is a code smell.

Such situations are usually the result of extracting an interface from an implementation, rather than having the client drive behaviour.

These interfaces are also often bad abstractions, known as "leaky abstractions". As I've discussed previously, these abstractions tend to offer nothing more than simple indirection.

Example

Apply the "rule of three". If there is only ever one implementation, then you don't need the interface/base class. If you do need to introduce an interface, have the client provide it. Try to resist the urge to extract from an implementation. Any stubs or testing implementations should be treated as valid implementations, despite no use within the production code directly.

In the first example there is a 1:1 mapping. This is clutter and needless indirection. As we have nothing to replace FooService with, the interface offers no value. The second example shows multiple implementations of IFoo. Here different implementations have unique responsibilities. We could use a test stub, or use the decorator pattern whenever we use IFoo. The abstraction is valuable.

If you can introduce a composite or decorator this is probably a sign of a good abstraction at work. Likewise the ability to replace your implementation and have the code still function is a good sign. Such an example would be SqlRepository replaced with MongoRepository when IRepository is required.

Additionally just because you opt to use dependency injection, there is no rule stating said dependency must be an interface or base class.

The final point is to remember what good dependencies are, everything else can be an implementation detail leading to more flexible and resilient code.