Refactoring: Legacy<br />The True Hacker's Guide To The Legacy<br />
What is...<br /><ul><li>Very old projects, had been written long long ago.
Mature projects, optimization required.
Die hard, nobody knows why it is still alive.
Market victim, nobody wants this sh%t anymore.
Problem child, nobody loves it.
Every project in active long term support.</li></li></ul><li>What is usually NOT...<br /><ul><li>Badly written projects wh...
Low quality designed projects.
Small projects.
Every project you don't understand.</li></li></ul><li>What do we need?<br /><ul><li>Legacy project.
Developers who want refactor it.
A customer eager to pay for it.
RegEx
Advanced File Manager
Perfect IDE
Open mind – for everything else and many more</li></li></ul><li>Migration #1: from TOM to POM<br /><target name="generate....
Migration #2: IoC (DI) FTW<br />public class BlockDefService {<br />    private static Logger logger = Logger.getLogger(Bl...
Migration #3: AOP driven<br />ActionForward forward = null;<br />try {<br />	// updateScreenCode(request);<br />	if (isTra...
Migration #4: Update libraries<br />Pros:<br /><ul><li>Newer versions usually better optimized so you will get performance...
Newer versions have better different integration options.
Newer versions can provide richer API sufficient to compete task better/faster/easier.</li></ul>Cons:<br /><ul><li>Newer v...
Upcoming SlideShare
Loading in …5
×

Club of anonimous developers "Refactoring: Legacy code"

2,104
-1

Published on

Published in: Technology, Art & Photos
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
2,104
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Club of anonimous developers "Refactoring: Legacy code"

  1. 1. Refactoring: Legacy<br />The True Hacker's Guide To The Legacy<br />
  2. 2. What is...<br /><ul><li>Very old projects, had been written long long ago.
  3. 3. Mature projects, optimization required.
  4. 4. Die hard, nobody knows why it is still alive.
  5. 5. Market victim, nobody wants this sh%t anymore.
  6. 6. Problem child, nobody loves it.
  7. 7. Every project in active long term support.</li></li></ul><li>What is usually NOT...<br /><ul><li>Badly written projects which are not in production.
  8. 8. Low quality designed projects.
  9. 9. Small projects.
  10. 10. Every project you don't understand.</li></li></ul><li>What do we need?<br /><ul><li>Legacy project.
  11. 11. Developers who want refactor it.
  12. 12. A customer eager to pay for it.
  13. 13. RegEx
  14. 14. Advanced File Manager
  15. 15. Perfect IDE
  16. 16. Open mind – for everything else and many more</li></li></ul><li>Migration #1: from TOM to POM<br /><target name="generate.libs"<br /> depends="init"<br /> unless="ignore.generate.libdep"<br /> description="Generate library dependencies"><br /> <mkdir dir="${build}/svn-checkout"/><br /> <!-- Get here the sources and build the jar --><br /> <ant inheritAll="false"<br />antfile="${build.config.dir}/svnsupport.xml"<br /> target="checkout"><br /> <property name="svn.username" value="${svn.username}"/><br /> <property name="svn.password" value="${svn.password}"/><br /> <property name="svn.url" value="${svn.url.eterracore}"/><br /> <property name="svn.target.dir" value="${build}/svn-checkout"/><br /> </ant><br /> <!-- Run the ant into the checkout dir --><br /> <ant inheritAll="false"<br />antfile="${build}/svn-checkout/build.xml"<br /> target="jar"><br /> </ant><br /> <copy todir="${libdep.dir}"><br /> <fileset dir="${build}/svn-checkout/build/"><br /> <include name="*.jar"/><br /> </fileset><br /> </copy><br /></target><br /><modules><br /> <module>core</module><br /> <module>demo</module><br /> <module>noncla</module><br /> <module>protocol/bayeux</module><br /> <module>protocol/dwrp</module><br /> <module>protocol/json</module><br /> <module>serverside/guice</module><br /> <module>serverside/hibernate</module><br /> <module>serverside/hibernate2</module><br /> <module>serverside/spring</module><br /> <module>serverside/struts</module><br /> <module>serverside/various</module><br /> <module>serverside/webwork</module><br /> <module>ui/dojo</module><br /> <module>ui/dwr</module><br /> <module>ui/gi</module><br /> <module>ui/jaxer</module><br /> <module>ui/scriptaculous</module><br /> </modules><br />
  17. 17. Migration #2: IoC (DI) FTW<br />public class BlockDefService {<br /> private static Logger logger = Logger.getLogger(BlockDefService.class);<br /> public static final int MIN_DURATION = 4;<br /> public static List<BlockDef> getBlockDefList(final BlockDefParamsparams) {<br /> return BlockDefQueries.getBlockDefList(params);<br /> }<br /> public staticBlockDefloadBlockDef(final Long blockDefId) {<br /> return BlockDefQueries.loadBlockDef(blockDefId);<br /> }<br /> public static void deleteBlockDef(final Long blockDefId) throws PartyException {<br /> …<br /> }<br />public class BlockDefBusiness {<br /> public static final int MIN_DURATION = 4;<br /> private static final Logger LOG = Logger.getLogger(BlockDefBusiness.class);<br /> private PartyDaopartyDao;<br /> private BlockDefDaoblockDefDao;<br /> private PartyRoleDaopartyRoleDao;<br /> public List<BlockDef> getBlockDefList(GregorianCalendarcurrentDay, Long partyId) {<br /> return blockDefDao.getBlockDefList(currentDay, partyId);<br /> }<br /> public BlockDefloadBlockDef(Long blockDefId) {<br /> return blockDefDao.loadBlockDef(blockDefId);<br /> }<br /> public void deleteBlockDef(Long blockDefId) throws PartyException {<br /> …<br /> }<br />
  18. 18. Migration #3: AOP driven<br />ActionForward forward = null;<br />try {<br /> // updateScreenCode(request);<br /> if (isTransactionable()) {<br />TransactionManager.beginTransaction();<br /> }<br />forward = executeAction(mapping, form, req, res);<br /> if (isTransactionable()) {<br />TransactionManager.commit();<br /> }<br />} catch (NullPointerException e) {// TODO It is not good<br />LOG.error("NPE error in the action", e);<br /> forward = mapping.findForward(SYSTEM_ERROR);<br />} catch (ModuleException e) {<br />LOG.error(e.getMessage(), e);<br /> throw e;<br />} catch (BusinessException e) {<br />LOG.error(e.getMessage(), e);<br /> throw e;<br />} catch (Throwable e) {<br />LOG.error("Error in the action", e);<br /> forward = mapping.findForward(SYSTEM_ERROR);<br />}<br />ActionForward forward = executeAction(mapping, form, req, res);<br />…<br /><bean id="failAdvice" class="eterra.sr.service.FailAdvice“/><br /><tx:advice id=“interceptor" transaction-manager="trManager"><br /> <tx:attributes><br /> <tx:method name="save*" propagation="REQUIRED"/><br /> <tx:method name="load*" propagation="REQUIRED"/><br /> <tx:method name="do*" propagation="REQUIRED"/><br /> <tx:method name="get*" propagation="SUPPORTS" read-only="true"/><br /> </tx:attributes><br /></tx:advice><br /><aop:config><br /> <aop:pointcut id=“actionClasses" expression=“…"/><br /> <aop:advisor advice-ref=“interceptor" pointcut-ref=“actionClasses" order="10"/><br /> <aop:aspect ref="failAdvice" order="1"><br /> <aop:around method="aroundTransactional" pointcut-ref=“actionClasses"/><br /> </aop:aspect><br /></aop:config><br />
  19. 19. Migration #4: Update libraries<br />Pros:<br /><ul><li>Newer versions usually better optimized so you will get performance for free.
  20. 20. Newer versions have better different integration options.
  21. 21. Newer versions can provide richer API sufficient to compete task better/faster/easier.</li></ul>Cons:<br /><ul><li>Newer versions can be incompatible with: JDK, other libraries, old configuration files etc.</li></li></ul><li>Migration #5: Code cleanup<br />Collections.sort(list, new Comparator() { public int compare(Object o1, Object o2) {<br />int value;<br /> Offer offer1 = (Offer) ((TradeConfirmation) o1).getOffer();<br /> Offer offer2 = (Offer) ((TradeConfirmation) o2).getOffer();<br /> if (offer1.getTradingInterval() < offer2.getTradingInterval()) {<br /> value = -1;<br /> } else {<br /> if (offer1.getTradingInterval() == offer2.getTradingInterval()) {<br /> if (offer1.getType() < offer2.getType()) {<br /> value = -1;<br /> } else {<br /> if (offer1.getType() == offer2.getType()) {<br />PartyDef party1 = offer1.getParty().getEffectiveParty(deliveryD);<br />PartyDef party2 = offer2.getParty().getEffectiveParty(deliveryD);<br /> if (party1.getName().compareTo(party2.getName()) < 0) {<br /> value = -1;<br /> } else {<br /> if (party1.getName().compareTo(party2.getName()) == 0) {<br /> if (offer1.getTradingZone().getEffectiveTradingDef(deliveryD).getIdentification().compareTo(…) < 0) {<br /> value = -1;<br /> } else {<br /> if (offer1.getTradingZone().getEffectiveTradingDef(deliveryD).getIdentification(…)) == 0) {<br /> value = 0;<br /> } else {<br /> value = 1;<br /> }<br /> }<br /> } else {<br /> value = 1;<br /> }<br /> }<br /> } else {<br /> value = 1;<br /> }<br /> }<br /> } else {<br /> value = 1;<br /> }<br /> }<br /> return value;<br /> }<br /> });<br />
  22. 22. Instead of an epilogue...<br /><ul><li>How-to convert “procedural” code to OOP.
  23. 23. How-to integrate a DI container.
  24. 24. How-to reduce headache using AOP.
  25. 25. How-to find and eliminate unreadable code.
  26. 26. Questions</li></li></ul><li>Procedure to Method<br /><ul><li>Copy all “procedural” classes into separate folder.
  27. 27. Write appropriate regular expression to remove all except method declarations.
  28. 28. Declare result as interfaces.
  29. 29. Create delegate implementations which calls old “procedural” classes.
  30. 30. Patiently relocate methods body from old to new classes during whole development process.</li></li></ul><li>
  31. 31.
  32. 32. Ready for DI container<br /><ul><li>Every time when we think that IoC (DI) container should either take care of all application classes or not at all – we are wrong.
  33. 33. New code must not use the same bad approach as “the legacy” part or it never ends.
  34. 34. Even legacy code can sometimes be declared in container context. Singletons for instance.</li></li></ul><li>AOP - even more flexibility<br /><ul><li>It is a good idea to separate exception handling (at least) from code.
  35. 35. If it looks like “aspect”, it is “aspect” with 95% probability, trust me.
  36. 36. Annotations with AOP have incredible power.
  37. 37. Wisely chosen name conventions, annotations, module structure can make your application working really fast.</li></li></ul><li>
  38. 38. “Lulz” hunting<br /><ul><li>Developers tend to have their own style. If you find something ugly/funny - search it again using a pattern or a regular expression.
  39. 39. FindBugs, CPD, PMD, FxCop etc.
  40. 40. Scripts and configuration files are the most dangerous.
  41. 41. Pair programming is very effective during project start.
  42. 42. Sometimes an “ugly” code is not so ugly.</li></li></ul><li>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×