Legacy
Как победить в гонке
Технический лидер @ Infopulse
Виктор Полищук
Многолетний опыт
воскрешения, лечения и
профилактики старых систем
Любит это дело
E-mail:
victor2@ukr.net
Skype:
victor-cr
Twitter:
@alkovictor
Немного Истории
2004
Другие
Java
2014
Другие
Java
Что такое…
…легаси?
Сравнение
Легаси-проект
Работает
Важен
Предсказуем
Говно-проект
Сделан идиотами
Стар и уныл
Страшен и ужасен
Неочевиден
Легаси
Говно
В чем же разница?
Качество выше
Заказчик довольнее
Стоимость выше
Да, нет же разницы
Почему…
…они появляются?
Идиоты
Давно писали
Быстро надо было
Идиоты
Давнописали
Быстро надо было
Единственная ли это причина?
Выберешь ли ты...
Хипстерский
Мейнстримовый
Отстой
Ужасный
проект
Шаблонный
проект
Потом Сейчас
Легаси
Выхода нет
Переписываем…
…с нуля!!!
Что-то пошло не так?
Рефакторим
…и страдаем
Правило
бойскаута
Обновление
библиотек
Автоматизация
сборки
Манипуляции с
кодом
Генерация кода Всякое-разное
Обновляйся
Кодобилдер
Сапоги Сапожника
Мои инструменты
Regexp:
(?ms)publics+statics+([^{]+).*?(?=s+publics+|}s+z)
XSLT:
<xsl:stylesheet…>
<xsl:template match="/">
<beans>
<xsl:apply-templates
select="struts-config/action-mappings/*"/>
</beans>
</xsl:template>
<xsl:template match="action">
<bean id="{@path}" class="{@type}"/>
</xsl:template>
</xsl:stylesheet>
Прототипируем
Скрипты
Visio
Rational
Rose
Power
Designer
Приятные Мелочи
Dependency
Injection
Можно вводить частями
Не ломает существующий код
Упрощает интеграцию
Transaction
Management
Потеря данных – не шутки
Помогает найти причины редких невоспроизводимых багов
Возможен поэтапный ввод
Multi-
threading
Переводим на Executor-ы
Запрещаем ручное создание потоков
Migration
Находим модули, которые можно заменить современными библиотеками
Обкладываем их адаптерами
Удаляем тонны кода
Ящик Пандоры
Что сделал ТЫ для того, чтобы
я не увидел этого?
ResultSet aResultSet = null;
ArrayList theAttribute1List = new ArrayList();
ArrayList theAttribute2List = new ArrayList();
…
ArrayList theAttribute30List = new ArrayList();
…
StringBuffer aQuery = new StringBuffer("select ")
.append("ATTRIBUTE1,")
.append("ATTRIBUTE2,")
…
while (aResultSet.next()) {
if (aResultSet.getString("ATTRIBUTE1") != null)
theAttribute1List.add(aResultSet.getString("ATTRIBUTE1"));
…
htAttributeList.put("ATTRIBUTE1", distinct(theAttribute1List));
htAttributeList.put("ATTRIBUTE2", distinct(theAttribute2List));
010
Универсальный
солдат...
public class UniversalComparator implements Comparator {
…
if (value1 instanceof GregorianCalendar) {
GregorianCalendar lcal_obj1 = (GregorianCalendar) value1;
GregorianCalendar lcal_obj2 = (GregorianCalendar) value2;
boolean lb_value = lcal_obj1.before(lcal_obj2);
if (ii_comparatorDirection == COMP_ASC) {
if (lb_value == true) {
return 1;
} else {
return -1;
}
} else {
if (lb_value == true) {
return -1;
} else {
return 1;
}
}
}
07
if (value1 instanceof Boolean) {
Boolean lv_obj1 = (Boolean) value1;
Boolean lv_obj2 = (Boolean) value2;
String ls_value1 = lv_obj1.toString();
String ls_value2 = lv_obj2.toString();
logService.debug("compare: lb_value1, lb_value2: "
+ ls_value1 + ", " + ls_value2);
int lv_value1 = (ls_value1 == "true") ? 1 : 0;
int lv_value2 = (ls_value2 == "true") ? 1 : 0;
if (ii_comparatorDirection == COMP_ASC) {
int val = (lv_value1 < lv_value2) ? -1 : 1;
// log("val: " + val);
return (lv_value1 < lv_value2) ? -1 : 1;
} else
return (lv_value1 < lv_value2) ? 1 : -1;
}
06
Стандартные
библиотеки???
Не, не слышал
private void moveFile(String from, String to) throws Exception {
//move files from 'from' to 'to'
String[] cmd;
if (File.separator.compareTo("") == 0) { //windows
cmd = new String[] {"cmd", "/c", "move",
from.trim().replace("/", File.separator),
to.trim().replace("/", File.separator)
};
} else {//linux like, simple mv command does not work, using script
cmd = new String[] {parameters.get("movePath") + ".sh",
from.trim().replace("/", File.separator),
to.trim().replace("/", File.separator)
};
}
System.gc(); //reduces current process size before fork
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
p.destroy(); //free up memory
}
05
Код ревью?
Да, ну его
private static final List<Option> DEFAULT_OPTIONS =
new ArrayList<Option>(4);
{
DEFAULT_OPTIONS.add(new Option(1, "Unavailable"));
DEFAULT_OPTIONS.add(new Option(2, "Unidirectional"));
DEFAULT_OPTIONS.add(new Option(3, "Bidirectional"));
DEFAULT_OPTIONS.add(new Option(4, "Not applicable"));
}
04
Кодга хочешь сделать
надежно
public static void lockPartyWithLog(Party p, UnitOfWork uow) {
// Local variables
Party partyClone = null;
// Lock the object
// LOCK_NOWAIT : an exception occurs if the object is being locked
try {
partyClone = (Party) uow.refreshAndLockObject(p,
ObjectLevelReadQuery.LOCK_NOWAIT);
} catch (DatabaseException dbe) {
logService.info("The party ID = " + p.getId()
+ " is locked by an other process");
try {
Thread.currentThread().sleep(1000);
} catch (Exception e) {
logService.error("Thread Exception ", e);
}
lockPartyWithLog(p, uow);
}
}
03
Мастер-класс API дизайна
public interface Parser {
void setReport(InputStream inputstream);
void setReport(String s);
String getReport();
void save();
void delete(String Query) throws HibernateException;
void setParams(Map<String, String> map);
Map<String, String> getParams();
void saveReport(String reportPath);
Boolean isDuplicated(String fileName);
}
23: public class PMScanReport extends AbstractParser
23: implements Parser {
..........
1556: }
02
Сравнятор!
public int compare(TradeConfirmation tc1, TradeConfirmation tc2) {
int value;
Offer o1 = (Offer) tc1.getOffer();
Offer o2 = (Offer) tc2.getOffer();
if (o1.getTradingInterval() < o2.getTradingInterval()) {
value = -1;
} else {
if (o1.getTradingInterval() == o2.getTradingInterval()) {
if (o1.getType() < o2.getType()) {
value = -1;
} else {
if (o1.getType() == o2.getType()) {
PartyDef p1 = o1.getParty().getEffectiveNow();
PartyDef p2 = o2.getParty().getEffectiveNow();
if (p1.getName().compareTo(p2.getName()) < 0) {
value = -1;
} else {
if (p1.getName().compareTo(p2.getName()) == 0) {
if (o1.getTradingZone().getEffectiveNow().getIdentification().compareTo(…) < 0) {
value = -1;
} else {
if (o1.getTradingZone().getEffectiveNow().getIdentification().compareTo(…)) == 0) {
value = 0;
} else {
value = 1;
}
}
} else {
value = 1;
}
}
} else {
value = 1;
}
}
} else {
value = 1;
}
}
return value;
}
01
Мировоззрение
У нас не зомбируют
Закон Легаси
Успешный
Легаси
Остальные
Легаси
Плохие
Хорошие
Я не понимаю
Значит это говнокод
Предположения
Предположения
Я не понимаю
Это может быть
говнокод
Ветеринарная Клиника
Обычная
…
Вылечить нельзя, смириться
…
Успешная
…
Вылечить, нельзя смириться
…
Кому же вы отдадите свою
любимую зверюшку?
Итоги Подведем
наконец-то
Легаси сплошь и рядом
• Ты не сможешь спрятаться или притвориться мертвым
Легаси означает успех
• По-настоящему унылые вещи не живут долго
Знание – сила
• Люди чувствуют себя комфортнее, если проблема известна
Настрой важен
• Твой выбор: страдать и плакать или придумать и сделать
Доверие – ключ
• Ты врядли успешно закончишь работу без него
Вопросы
Спасибо за внимание

Legacy: как победить в гонке (Joker)