代码之家  ›  专栏  ›  技术社区  ›  ChaosPandion

如何将其重构为更易于管理的代码?

  •  9
  • ChaosPandion  · 技术社区  · 15 年前

    这段代码是否足够复杂,需要更高级别的抽象?

    public static JsonStructure Parse(string jsonText)
    {
        var result = default(JsonStructure);
        var structureStack = new Stack<JsonStructure>();
        var keyStack = new Stack<string>();
        var current = default(JsonStructure);
        var currentState = ParserState.Begin;
        var key = default(string);
        var value = default(object);
    
        foreach (var token in Lexer.Tokenize(jsonText))
        {
            switch (currentState)
            {
                case ParserState.Begin:
                    switch (token.Type)
                    {
                        case TokenType.BeginObject:
                            currentState = ParserState.Name;
                            current = result = new JsonObject();
                            break;
                        case TokenType.BeginArray:
                            currentState = ParserState.Value;
                            current = result = new JsonArray();
                            break;
                        default:
                            throw new JsonException(token, currentState);
                    }
                    break;
                case ParserState.Name:
                    switch (token.Type)
                    {
                        case TokenType.String:
                            currentState = ParserState.NameSeparator;
                            key = (string)token.Value;
                            break;
                        default:
                            throw new JsonException(token, currentState);
                    }
                    break;
                case ParserState.NameSeparator:
                    switch (token.Type)
                    {
                        case TokenType.NameSeparator:
                            currentState = ParserState.Value;
                            break;
                        default:
                            throw new JsonException(token, currentState);
                    }
                    break;
                case ParserState.Value:
                    switch (token.Type)
                    {
                        case TokenType.Number:
                        case TokenType.String:
                        case TokenType.True:
                        case TokenType.False:
                        case TokenType.Null:
                            currentState = ParserState.ValueSeparator;
                            value = token.Value;
                            break;
                        case TokenType.BeginObject:
                            structureStack.Push(current);
                            keyStack.Push(key);
                            currentState = ParserState.Name;
                            current = new JsonObject();
                            break;
                        case TokenType.BeginArray:
                            structureStack.Push(current);
                            currentState = ParserState.Value;
                            current = new JsonArray();
                            break;
                        default:
                            throw new JsonException(token, currentState);
                    }
                    break;
                case ParserState.ValueSeparator:
                    var jsonObject = (current as JsonObject);
                    var jsonArray = (current as JsonArray);
                    if (jsonObject != null)
                    {
                        jsonObject.Add(key, value);
                        currentState = ParserState.Name;
                    }
                    if (jsonArray != null)
                    {
                        jsonArray.Add(value);
                        currentState = ParserState.Value;
                    }
                    switch (token.Type)
                    {
                        case TokenType.EndObject:
                        case TokenType.EndArray:
                            currentState = ParserState.End;
                            break;
                        case TokenType.ValueSeparator:
                            break;
                        default:
                            throw new JsonException(token, currentState);
                    }
                    break;
                case ParserState.End:
                    switch (token.Type)
                    {
                        case TokenType.EndObject:
                        case TokenType.EndArray:
                        case TokenType.ValueSeparator:
                            var previous = structureStack.Pop();
                            var previousJsonObject = (previous as JsonObject);
                            var previousJsonArray = (previous as JsonArray);
                            if (previousJsonObject != null)
                            {
                                previousJsonObject.Add(keyStack.Pop(), current);
                                currentState = ParserState.Name;
                            }
                            if (previousJsonArray != null)
                            {
                                previousJsonArray.Add(current);
                                currentState = ParserState.Value;
                            }
                            if (token.Type != TokenType.ValueSeparator)
                            {
                                currentState = ParserState.End;
                            }
                            current = previous;
                            break;
                        default:
                            throw new JsonException(token, currentState);
                    }
                    break;
                default:
                    break;
            }
        }
        return result;
    }
    
    2 回复  |  直到 15 年前
        1
  •  10
  •   Sam Holder Brian Adams    15 年前

    在不详细查看它的情况下,当您根据状态进行分析时,可以使用 state pattern 要分解它并根据状态在单独的类中解析每个位吗?

    这可能是个开始,虽然这只是伪代码…

    public interface IParserState
        {
        IParserState ParseToken (IToken token);
        }
    
    public class BeginState : IParserState
        {
        private readonly Stack<JsonStructure> m_structureStack;
        private readonly Stack<String> m_keyStack;
    
        public BeginState (Stack<JsonStructure> structureStack, Stack<String> keyStack)
            {
            m_structureStack = structureStack;
            m_keyStack = keyStack;
            }
    
        public IParserState ParseToken(IToken token)
            {
            switch (token.Type)
                {
                case TokenType.OpenBrace:
                    return new ObjectKeyParserState(m_structureStack,m_keyStack);
                case TokenType.OpenBracket:
                    return new ArrayValueParserState(m_structureStack, m_keyStack);
                default:
                    throw new JsonException (token);    
                }
            }
        }
    
    public class ObjectKeyParserState : IParserState
        {
        private readonly Stack<JsonStructure> m_structureStack;
        private readonly Stack<String> m_keyStack;
        private readonly JsonObject m_current;
    
        public ObjectKeyParserState (Stack<JsonStructure> structureStack, Stack<String> keyStack)
            {
            m_current = new JsonObject();
            }
    
        public IParserState ParseToken (IToken token)
            {
            switch (token.Type)
                {
                case TokenType.StringLiteral:
                    key = (string)token.Value;
                    return new ColonSeperatorParserState(m_structureStack, m_keyStack, m_current,key);
                default:
                    throw new JsonException(token);
                }
            }
    
        2
  •  2
  •   jyoung    15 年前

    在这种情况下,“概念设计”是生产规则。如果您自己设计JSON,您会认为“pair是一个键,后面跟一个冒号,后面跟一个值”吗?或者您会认为“colons会在这种情况下做‘a’,在这种情况下做‘b’,在这种情况下做‘c’”?看 http://www.json.org/ . 您将看到“概念设计”在生产规则中陈述。

    由于代码的“结构设计”没有“概念设计”的形式,因此任何重构都不会有帮助。少量更改“概念设计”会导致代码更改,这很难编码,也很难测试。您需要根据“概念设计”重写代码。

    // object
    //   "{" "}"
    //   "{" members "}" 
    private static JsonObject ProduceJsonObject(Tokens tokens)
    {
        var result = new JsonObject();
    
        tokens.Accept( TokenType.OpenBrace );
        result.members = ProduceJsonMembers(tokens);
        tokens.Accept( TokenType.CloseBrace );
    
        return result;
    }
    
    // members 
    //   pair 
    //   pair { "," pair }
    private static JsonMembers ProduceJsonMembers(Tokens tokens)
    {
        var result = new JsonMembers();
    
        result.Add( ProduceJsonPair(tokens) );
        while (tokens.LookAhead == TokenTag.Comma)
        {
           tokens.Accept( TokenType.Comma );
           result.Add( ProduceJsonPair(tokens) );
        }
    
        return result;
    }
    
    //pair 
    //  string ":" value 
    private static JsonPair ProduceJsonPair(Tokens tokens)
    {
        var result = new JsonPair();
    
        result.String = tokens.Accept( TokenType.ID );
        tokens.Accept( TokenType.Colon );
        result.Value = ProduceJsonValue( tokens );
    
        return result;
    }
    
    
    // and so forth