HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Messages with status codes

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
withcodesmessagesstatus

Problem

I need to refactor following class:

public class Message
{
    public Guid ID { get; set; }
    public string MessageIn { get; set; }
    public string MessageOut { get; set; }
    public int StatusCode { get; set; } //EDIT could be changed during message lifecycle

    public bool IsDeletable
    {
        get
        {
            switch (this.StatusCode)
            {
                case 12:
                case 13:
                case 22:
                case 120:
                    return true;
                default:
                    return false;
            }
        }
    }

    public bool IsEditable
    {
        get
        {
            switch (this.StatusCode)
            {
                case 12:
                case 13:
                case 22:
                case 120:
                    return true;
                default:
                    return false;
            }
        }
    }

    public string Message
    {
        get
        {
            switch (this.StatusCode)
            {
                case 11:
                case 110:
                    return this.MessageIn;
                case 12:
                case 13:
                case 22:
                case 120:
                    return this.MessageOut;
                default:
                    return string.Empty;
            }
        }
    }
}


  • I would like to remove the business rules IsDeletable and IsEditable



  • I would like to remove these switch statements at the same time



I am not sure if it's worth knowing that I am mapping entity to database table through Entity Framework.

One more problem that I have is that fields MessageIn and MessageOut are dependent on StatusCode. One of them are always populated. I could create new property but still the switch case is there:

```
public string Message
{
get
{
switch (this.StatusCode)
{
case 10:
case 12:
case 13:
case :

Solution

I would like to remove these switch statments in the same time

[Flags]
public enum StatusCode{
    codeX = 1,
    codeY = 2,
    codeZ = 4,
    codeA = 8,
    editable = codeX | codeZ,
    deleteable = codeY | codeZ
}


Key points

  • Use the Flags attribute



  • enum values are powers of 2 - NOT multiples of 2



  • bit-wise AND, OR provides the magic!



Edit

addressing the comments:

public static class StatusCodes {
    private Dictionary values;
    private Dictionary keys;

    static StatusCodes() {

        values = new Dictionary {
            {StatusCode.A, 10},
            {StatusCode.B, 20},
            // and so on
        }

        keys = new Dictionary {
            {10, StatusCode.A},
            {20, StatusCode.B},
        }
    }

    public static int GetValue(StatusCode theStatusCodeKey) {} // don't forget error trapping!
    public static StatusCode GetKey(int theIntValue) {}  // ditto

    public static bool Editable(StatusCode thisCode) {
        return (StatusCode.editable & thisCode) == thisCode;
    }

    public static bool Editable(int thisValue) {
        return Editable( GetKey(thisValue));
    }
}


  • The definition of the codes is all in one place - that's SOLID (D = DRY, don't repeat yourself)



  • The definitions are in its own class - that's SOLID (S = single responsibility)



  • editable and deleteable can be removed from Message - that's very SOLID (S = single responsibility)



  • We know what all those integers mean - thats.. well, just good programming.



  • The StatusCodes are available anywhere and everywhere in the application - That's SOLID, an attribute of being DRY.



  • I'm not sure what "status code values might not be fixed" in the comments means. Surely the set of status codes is finite.



Edit

  • Define "editability" in StatusCodes



  • Use above to express Message is editable



  • Address issue of exposing StatusCode.editable "as if it were a valid code"



  • Adhere to Single Responsibility



  • Adhere to DRY principle



...

public static class StatusCodes
{
    private static Dictionary values;
    private static Dictionary keys;

    static StatusCodes() {

        values = new Dictionary {
            {StatusCode.A, 10},
            {StatusCode.B, 20},
            {StatusCode.C, 30},
            {StatusCode.D, 40}
            // and so on
        };

        keys = new Dictionary {
            {10, StatusCode.A},
            {20, StatusCode.B},
            {30, StatusCode.C},
            {40, StatusCode.D}
        };
    }

    [Flags]
    enum Fungability
    {
        Editable = StatusCode.A | StatusCode.B,
        Deleteable = StatusCode.B | StatusCode.D
    }

    public static int GetValue( StatusCode theStatusCodeKey ) {
        int retVal;

        values.TryGetValue( theStatusCodeKey, out retVal );
        return retVal;
    } // don't forget error trapping!

    public static StatusCode GetKey( int theIntValue ) {
        StatusCode retVal;
        keys.TryGetValue( theIntValue, out retVal );
        return retVal;
    }  // ditto

    public static bool Editable( StatusCode thisCode )
    {
        return ( (StatusCode)Fungability.Editable & thisCode ) == thisCode;
    }

    public static bool Editable( int thisValue )
    {
        return Editable( GetKey( thisValue ) );
    }

}

public class Message
{
    public StatusCode myStatus;

    public Message( int statusCode = 20 ) { myStatus = StatusCodes.GetKey(statusCode); }
    public Message( StatusCode statusCode = StatusCode.A ) { myStatus = statusCode; }

    public bool Editable
    {
        get { return StatusCodes.Editable( myStatus ); }
    }

    public bool Deleteable
    {
        get { return StatusCodes.Deleteable( myStatus ); }
    }
}


Take Away

  • Structure data in an OO way



  • Expose the data adhering to the Single Responsibility principle



  • You get DRY as a side effect



  • Structure yields simplicity, coherence, clarity. Editable is implemented with only one line of code!



  • Message.Editable went from originally "calculating" if the status code was editable, to simply asking the StatusCode "are you editable?"

Code Snippets

[Flags]
public enum StatusCode{
    codeX = 1,
    codeY = 2,
    codeZ = 4,
    codeA = 8,
    editable = codeX | codeZ,
    deleteable = codeY | codeZ
}
public static class StatusCodes {
    private Dictionary<StatusCode, int> values;
    private Dictionary<int,StatusCode> keys;

    static StatusCodes() {

        values = new Dictionary<StatusCode, string> {
            {StatusCode.A, 10},
            {StatusCode.B, 20},
            // and so on
        }

        keys = new Dictionary<in, StatusCode> {
            {10, StatusCode.A},
            {20, StatusCode.B},
        }
    }

    public static int GetValue(StatusCode theStatusCodeKey) {} // don't forget error trapping!
    public static StatusCode GetKey(int theIntValue) {}  // ditto

    public static bool Editable(StatusCode thisCode) {
        return (StatusCode.editable & thisCode) == thisCode;
    }

    public static bool Editable(int thisValue) {
        return Editable( GetKey(thisValue));
    }
}
public static class StatusCodes
{
    private static Dictionary<StatusCode, int> values;
    private static Dictionary<int,StatusCode> keys;

    static StatusCodes() {

        values = new Dictionary<StatusCode, int> {
            {StatusCode.A, 10},
            {StatusCode.B, 20},
            {StatusCode.C, 30},
            {StatusCode.D, 40}
            // and so on
        };

        keys = new Dictionary<int, StatusCode> {
            {10, StatusCode.A},
            {20, StatusCode.B},
            {30, StatusCode.C},
            {40, StatusCode.D}
        };
    }

    [Flags]
    enum Fungability
    {
        Editable = StatusCode.A | StatusCode.B,
        Deleteable = StatusCode.B | StatusCode.D
    }

    public static int GetValue( StatusCode theStatusCodeKey ) {
        int retVal;

        values.TryGetValue( theStatusCodeKey, out retVal );
        return retVal;
    } // don't forget error trapping!


    public static StatusCode GetKey( int theIntValue ) {
        StatusCode retVal;
        keys.TryGetValue( theIntValue, out retVal );
        return retVal;
    }  // ditto

    public static bool Editable( StatusCode thisCode )
    {
        return ( (StatusCode)Fungability.Editable & thisCode ) == thisCode;
    }

    public static bool Editable( int thisValue )
    {
        return Editable( GetKey( thisValue ) );
    }

}


public class Message
{
    public StatusCode myStatus;

    public Message( int statusCode = 20 ) { myStatus = StatusCodes.GetKey(statusCode); }
    public Message( StatusCode statusCode = StatusCode.A ) { myStatus = statusCode; }

    public bool Editable
    {
        get { return StatusCodes.Editable( myStatus ); }
    }

    public bool Deleteable
    {
        get { return StatusCodes.Deleteable( myStatus ); }
    }
}

Context

StackExchange Code Review Q#29680, answer score: 4

Revisions (0)

No revisions yet.