DCSIMG
Adapters and Functional Abstraction - .NET Geek

.NET Geek

"It is upon the Trunk that a gentleman works" - Confucius

Adapters and Functional Abstraction

I can’t decide what I think about the following implementation so I decided to throw it out here. Any thoughts are welcome.

In a previous post I wrote about our wrapper around Bouncy Castle PGP encryption. Turned out it worked pretty well except one little problem. The PGP implementation on the receiving end would complain about our signature. In despair I even posted (and later answered) a question on StackOverflow. :-)

The problem was that they use an old version of a PGP library that couldn’t deal with our newer v4 signatures. Oh, forget it, I’m not going to bore you with the details…

I looked at the code for creating the object that does the signing and it returns an instance of a PgpSignatureGenerator (A Bouncy Castle class). Instead of using this signature generator we needed to use a PgpV3SignatureGenerator (Also a Bouncy Castle class). It was no big deal to change the code to instantiate and return a different type. However, we wanted to be able to return the v4 signature generator as well. Since both PgpSignatureGenerator and PgpV3SignatureGenerator are concrete implementations without a common base class we could not just return a common abstraction. Ok, still not a big deal. We can just create a wrapper (adapter) around the implementations and return that.

That’s when you’re hit by the principle/rule police. SOLID, good? SOLID bad? should you prefer composition over inheritance or use a inheritance based version of the adapter pattern. Oh no, is this Adapter or is it Facade? … Just kidding…
But I couldn’t resist it after the last couple of weeks of noise around principles and rules and whether they’re good or not.

After a closer look at the two classes, I saw that they conform to the same interface (for the parts relevant to us at least). So I decided to skip over any design pattern I knew of and just take the shortest path to a solution that works. We need to make two calls on the signature generator while encrypting. This is after the initial setup of the signature generator. You can see the two signatures below. For this discussion it doesn’t matter what they accomplish.

public void Update(byte[] buffer, int offset, int length);
public PgpSignature Generate();
 

 

 

The following class captures this functionality and the caller doesn’t know at the time of calling the methods whether it’s a v4 or v3 signature.

public class Signer
{
    public Action<byte[], int, int> Update { get; set; }
    public Func<PgpSignature> Generate { get; set; }
}

Signer can now be instantiated with either a v3 or v4 signature generator.

public Signer GetSignatureGenerator(Stream compressedOut, 
                                    SignatureVersion signatureVersion)
{
    if (signatureVersion == SignatureVersion.V3)
    {
        PgpV3SignatureGenerator pgpV3SignatureGenerator = 
            new PgpV3SignatureGenerator(...);
 
        // some more initialization code
        return new Signer
        {
            Update = (data, offset, length) => pgpV3SignatureGenerator.Update(data, offset, length),
            Generate = () => pgpV3SignatureGenerator.Generate()
        };
    }
    else if (signatureVersion == SignatureVersion.V4)
    {
        PgpSignatureGenerator pgpSignatureGenerator = 
            new PgpSignatureGenerator(...);
 
        // some more initialization code
        pgpSignatureGenerator.GenerateOnePassVersion(false).Encode(compressedOut);
        return new Signer
        {
            Update = (data, offset, length) => pgpSignatureGenerator.Update(data, offset, length),
            Generate = () => pgpSignatureGenerator.Generate()
        };
    }
    else
    {
        throw new ArgumentException("Invalid signature version");
    }
}

You can get a v3 signature generator by using the following.

var signer = GetSignatureGenerator(compressedOut, SignatureVersion.V3);

While it might not be entirely idiomatic to encapsulate by capturing only the behavior of the adaptee, I kind of like the minimalistic approach. It migth break in more complex scenarios without a common interface, but for the simple stuff I think I like it.

So what do you think?
Nice? Ugly? other?

Comments

lpe said:

I think it's pretty good.

It can be perfect extracting an interface and maybe use dependency injection here but your solution is much simpler.

Sometimes, when you need to deliver a solution it's better not to be driven with design patterns too much.

After all, a design pattern is a best practice but it can also be customized into your organization's needs.

And i quote from Wikipedia:

"...a design pattern is a general reusable solution to a commonly occurring problem in software design. A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations."

# February 24, 2009 9:29 PM

name said:

It is a very good thing,

# July 29, 2009 6:20 PM

icons downloads said:

 I consider, that you are not right. I am assured. Let's discuss. Write to me in PM, we will communicate.

<a href="www.hpixel.com/.../a>

# September 24, 2012 10:37 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: