ChatGPT - How Long Till They Realize I’m a Robot?

Image
I tried it first on December 2nd... ...and slowly the meaning of it started to sink in. It's January 1st and as the new year begins, my future has never felt so hazy. It helps me write code. At my new company I'm writing golang, which is new for me, and one day on a whim I think "hmmm maybe ChatGPT will give me some ideas about the library I need to use." Lo-and-behold it knew the library. It wrote example code. It explained each section in just enough detail. I'm excited....It assists my users. I got a question about Dockerfiles in my teams oncall channel. "Hmmm I don't know the answer to this either"....ChatGPT did. It knew the commands to run. It knew details of how it worked. It explained it better and faster than I could have. Now I'm nervous....It writes my code for me. Now I'm hearing how great Github Copilot is - and it's built by OpenAI too...ok I guess I should give it a shot. I install it, and within minutes it'...

Adapter Design Pattern

The adapter pattern is an extremely useful pattern for a few reasons. The reason I like it so much is because if you understand it, then you understand the concept of Dependency Inversion (the "D" in SOLID object-oriented design).

Dependency Inversion is an object-oriented principle which states that in code, higher level modules should not depend on lower level modules. Instead, lower level modules should depend on higher level ones. Let's say you've got one higher level object that requires a lower level object to do it's job. But the lower-level object is likely to change or be swapped out for another. Here's the bad way to do it:

namespace HigherLevelModule
{
    public class HigherLevelObject
    {
        ......

        public void Run()
        {
            LowerLevelObject obj = new LowerLevelObject();
            
            string result = obj.GetSomething();
            Console.WriteLine(result);
        }
    }
}

namespace LowerLevelModule
{
    public class LowerLevelObject
    {
        ......

        public string GetSomething()
        {
            return new String("you got me!");
        }
    }
}



Now, the reason that this is bad, is because it makes the task of swapping out the lower level object more difficult than it needs to be. The higher level depends on the lower level! LowerLevelModule can be compiled without HigherLevelModule but not vice versa - which is the opposite of what we want.

So here's a better version:

namespace HigherLevelModule
{
    public class HigherLevelObject
    {
        ......

        public void Run()
        {
            IAdapter obj = LowerLevelObjectFactory
                                .GetInstance()
                                .GetLowerLevelObject();
            
            string result = obj.GetSomething();
            Console.WriteLine(result);
        }
    }

    public interface IAdapter
    {
        string GetSomething();
    }

    public class LowerLevelObjectFactory
    {
        private static LowerLevelObjectFactory Factory =
                                new LowerLevelObjectFactory();
        
        private LowerLevelObjectFactory()
        {
        }

        public static LowerLevelObjectFactory GetInstance()
        {
            return Factory;
        }

        public IAdapter GetLowerLevelObject()
        {
            return new LowerLevelObjectA();
        }

    }
}

namespace LowerLevelModule
{
    public class LowerLevelObjectA : IAdapter
    {
        ......

        public string GetSomething()
        {
            return new String("you got A!");
        }
    }

    public class LowerLevelObjectB : IAdapter
    {
        ......

        public string GetSomething()
        {
            return new String("this time you got B!");
        }
    }
}

With this new code, the higher level doesn't care what the actual type of the ILowerLevel instance is, it just cares that it has a GetSomething() method, which is guaranteed by the ILowerLevel contract. Now the higher level can use the factory method to create lower level objects all over the place, and if the type of the lower level object ever has to be changed, there's only one line of code that needs to be changed:

public IAdapter GetLowerLevelObject()
{
    return new LowerLevelObjectB();
}


Now THAT's maintainability. Wurd.

Comments

Popular posts from this blog

ChatGPT - How Long Till They Realize I’m a Robot?

My experience with Udacity

Architectural Characteristics - Transcending Requirements