Upload
victorcr
View
495
Download
1
Embed Size (px)
DESCRIPTION
The presentation of the talk "Legacy projects: how to win the race". Made by me on JEEConf Ukraine in May 2014.
Citation preview
Legacy ProjectsHow to win the race
Technical Lead @ Infopulse UAVictor Polischuk
Many years of legacy systems reviving and refactoring experience
Loves it
E-mail:[email protected]
Skype:victor-cr
Legacy Projects History
2004
Others Java
2014
Others Java
What is……legacy projects?
Comparison Sheet
LegacyEarned a fortune
Important
Predictable
CrappyDesigned by morons
Boring
Unmaintainable
No documentation
Legacy
Crappy
What is the main difference?
Happy owner
Better quality
No difference
Project cost
What is the main difference?
Happy owner
Better quality
No difference
Project cost
Why Does……a legacy project born?
Time passed
Time
Because of time
Time passed
Tim
e
Because of time
Is it the ONLY reason?
Would you choose...
Shiny
DullMainstream
Cutting
Edge New technologies
Challenge unknown
Evolve
You are special
Main-
stream Boring stack
Challenge patience
Nothing new
You are just as everyone
Terrible Project
Clean Project
In future Now
Legacy
No escape
ReWRite……or not?
1. Specify
2. Estimate
3. Compare
4. ?????
5. Profit!!!!!
Failed somewhere?
Refactoring…cookbook
Boy-scout ruleLibraries upgrade
Build migrationCode
transformation
Code generation
Miscellaneous
Keep Stack Updated
Obsolete
Let’s upgrade
MigrationWe are good
Production
Build Health
Checkout
/
Clone
???Working
Build
Bulk Code Changes
Know Your ToolsRegexp:(?ms)public\s+static\s+([^{]+).*?(?=\s+public\s+|}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>
Prototyping
Scripting
Visio
Rational Rose
Power Designer
Script
Data Model
Template Engine
Generated Prototype
Maintain Clean Code
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
What have you done to prevent me seeing it?
Universal soldier...
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
JavaDoc... No, have never heard
private void moveFile(String from, String to) throws Exception {//move files from 'from' to 'to'
String[] cmd;if (File.separator.compareTo("\\") == 0) { //windowscmd = 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 forkProcess p = Runtime.getRuntime().exec(cmd);p.waitFor();p.destroy(); //free up memory
} 05
Code review?... WTF?
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
Fail of fail-over protection
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
Master class of API design
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 AbstractParser23: implements Parser {..........1556: }
02
Fatality!
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
What Else?
Transaction Management
Dependency Injection
Mass Relocation
Various Migrations
MindsetPrepare yourself
Legacy Law
Successful
Legacy Non-legacy
Legacy
Crappy Non-crappy
I cannot understand
It is
a crap
Assumptions
I cannot understand
It may be
a crap
Assumptions
Victim
Warrior
Pet Clinic Comparison
Regular Successful
…
Does not care
…
…
Does care
…
Who would you trust with your most precious pet?
ConclusionsFinally
Legacy is everywhere
• You cannot hide or pretend it has nothing to do with you
Legacy means success
• Truly crappy things do not live long
Knowledge is a weapon
• People feel calm when encounter known problems
Change your mindset
• It is up to you: run crying or deal with it like a boss
Trust is important
• It also influences your freedom in decision making
QuestionsThank you for attention