2015-07-25 3 views
0

Я пишу код Java для программного обеспечения сервера Minecraft под названием Spigot (spigotmc.org), и я только что написал это. Цель состоит в том, чтобы проверять каждую сторону переменной block и проверять на стене знак, как вы можете видеть. Его нужно только найти. Затем он обновит его и еще много чего. Я знаю, что этот код можно упростить, но на данный момент я не вижу, как без создания целой новой функции для кода внутри условных выражений, чего я не хочу делать. Есть ли лучший способ написать это условное выражение?Как упростить этот Java-код?

// Get an attached sign 
Block sign; 
if ((sign = block.getRelative(BlockFace.NORTH)).getType() == Material.WALL_SIGN) { 
    org.bukkit.block.Sign data = (Sign) sign.getState(); 
    data.setLine(1, "OFF"); 
    data.update(); 
} else if ((sign = block.getRelative(BlockFace.EAST)).getType() == Material.WALL_SIGN) { 
    org.bukkit.block.Sign data = (Sign) sign.getState(); 
    data.setLine(1, "OFF"); 
    data.update(); 
} else if ((sign = block.getRelative(BlockFace.WEST)).getType() == Material.WALL_SIGN) { 
    org.bukkit.block.Sign data = (Sign) sign.getState(); 
    data.setLine(1, "OFF"); 
    data.update(); 
} else if ((sign = block.getRelative(BlockFace.SOUTH)).getType() == Material.WALL_SIGN) { 
    org.bukkit.block.Sign data = (Sign) sign.getState(); 
    data.setLine(1, "OFF"); 
    data.update(); 
} 
+7

Если ваш код *** работает ***, и вы просто просите о более эффективном/более простом способе его реализации, тогда вы должны задать этот вопрос на http: // codereview.stackexchange.com/, а не stackoverflow. – Pshemo

+0

Да, я уверен, что это работает. :) спасибо – Pocketkid2

ответ

1

Ваш внутренний, если прицелы всегда то же самое, так что вы можете использовать «или» команду между условиями:

// Get an attached sign 
Block sign; 
if (((sign = block.getRelative(BlockFace.NORTH)).getType() == Material.WALL_SIGN) 
|| ((sign = block.getRelative(BlockFace.EAST)).getType() == Material.WALL_SIGN) 
|| ((sign = block.getRelative(BlockFace.WEST)).getType() == Material.WALL_SIGN) 
|| ((sign = block.getRelative(BlockFace.SOUTH)).getType() == Material.WALL_SIGN) 
    org.bukkit.block.Sign data = (Sign) sign.getState(); 
    data.setLine(1, "OFF"); 
    data.update(); 
} 
+0

Спасибо! Это похоже на то, к чему я стремлюсь! – Pocketkid2

+0

Хотя этот код логически эквивалентен OP, это не сразу понятно, потому что оценка короткого замыкания вступает в игру. Очень важно, чтобы задания 'sign' прекращались сразу после первого успешного совпадения; в противном случае «знак» оказался бы неправильным. – dasblinkenlight

+0

@ dasblinkenlight, вы правы, но в этом случае он будет работать так же, как и до –

2

Может петля?

// Get an attached sign 
Block sign; 
BlockFace[] faces = new BlockFace[] { 
    BlockFace.NORTH, 
    BlockFace.EAST, 
    BlockFace.WEST, 
    BlockFace.SOUTH}; 

for(BlockFace face : faces) { 
    if ((sign = block.getRelative(face)).getType() == Material.WALL_SIGN) { 
     org.bukkit.block.Sign data = (Sign) sign.getState(); 
     data.setLine(1, "OFF"); 
     data.update(); 
     break; 
    } 
} 

Этот подход хорошо работает, когда у вас есть много возможностей для поиска. Кроме того, если вы делаете аналогичную логику в другом месте, определенно создайте функцию, которую могут вызвать все клиенты с одинаковыми потребностями!

2

В соответствии с принципом DRY вам необходимо повторно использовать повторяющиеся детали. В вашем примере весь блок if будет таким же, кроме лица.

  1. Замена КСФ с для:

    List<BlockFace> blockFaces = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.WEST, BlockFace.SOUTH); 
    for (BlockFace face : blockFaces) { 
        Sign sign = block.getRelative(face); 
        if (sign.getType() == Material.WALL_SIGN) { 
         org.bukkit.block.Sign data = (Sign) sign.getState(); 
         data.setLine(1, "OFF"); 
         data.update(); 
         break; 
        } 
    } 
    
  2. Extracting метод:

    private boolean updateAttachedSign(Block block, BlockFace face) { 
        Sign sign = block.getRelative(face); 
        if (sign.getType() == Material.WALL_SIGN) { 
         org.bukkit.block.Sign data = (Sign) sign.getState(); 
         data.setLine(1, "OFF"); 
         data.update(); 
         return true; 
        } 
        return false; 
    } 
    
    { 
        boolean signIsUpdated = 
         updateAttachedSign(block, BlockFace.NORTH) || 
         updateAttachedSign(block, BlockFace.EAST) || 
         updateAttachedSign(block, BlockFace.WEST) || 
         updateAttachedSign(block, BlockFace.SOUTH); 
    } 
    

Второе решение, несмотря на превосходя подход в общем, по-видимому, немного сложный для вашего дела. Я придерживаюсь первого.

Редактируйте @Constantin:

Используйте короткозамкнутые условными благоразумно. Пожалуйста, обратитесь к этому замечательному сообщению, где это имеет смысл. https://softwareengineering.stackexchange.com/questions/284415/short-circuit-evaluation-is-it-bad-practice

+0

+1 для того, чтобы предположить, что ваш второй метод превосходен, потому что он гарантирует, что вызывающий не делает слишком много актуальной логики. Общее правило состоит в том, что каждый метод имеет очень специфическую функцию и не увеличивает его рабочую нагрузку.Общей ошибкой младших разработчиков является создание огромных монолитных методов, которые делают слишком много, часто повторяя код в другом месте снова и снова, потому что они не смогли сохранить его модульным – Constantin