Making the world better via refactoring – Intro

I love Ely’s DragTile component (demo). However, I have always wished that it were easier to extend its behavior to encompass different layouts. To me, that immediately suggests a (big) refactoring. For those of you who have never done refactoring or who don’t refactor as often as you should, I thought it might be fun to walk through this step by step.

What is refactoring?

Refactoring is the process of incrementally changing the structure of your code without changing the outward functionality. It may seem silly to focus on not changing the functionality, but it is actually pretty important.

The idea is that there are two distinct phases of work: coding and refactoring. During coding, you add new functionality. During refactoring, you restructure your code while making sure that it continues to work properly. Not changing functionality during refactoring gives you a strong reference point as you make lots of iterative changes to the structure. You know your refactoring was successful if the new code still does what the old code did.

Refactoring for better reuse

Usually, you refactor code so that it can be more flexible or more reusable that it currently is. Sometimes, the change that is required is obvious. In other cases, you have to think a little before figuring out how to transform your code.

In this particular case, we want to make it easier to change layouts. Looking at the DragTile code, there is quite a bit that would be the same no matter what the layout is, and relatively little that needs to change with each new layout algorithm. Because the layout algorithm is something that is likely to change in various use cases, it is probably a good idea to isolate this functionality into a separate class.

Tip 1: Cleanly separate out the code that you think will need to change often into a separate class.

The most obvious way to divide up the DragTile layout code from the rest of the DragTile code is through inheritance:

Splitting things up in this way allows us to create a new subclass with a different layout (say, a circle) while reusing the logic that might be common to both, such as the code to talk to item renderers and do animation.

The other main way to split things up is through composition:

In this case, the container delegates to another object in order to do layout. There are a number of advantages to this approach:

  1. Using delegates often makes it possible to modify behavior at runtime. After we are finished with this particular refactoring, we should be able to change the layout of one of our containers without reparenting. Woohoo!!
  2. Decomposing larger classes into smaller classes can make it easier to evolve different parts of the system separately as needs change. For example, let’s say we later decide to split up FlexibleContainer into two classes: one that is lightweight for easy download, and another that is robust, to handle caching, localization, etc. Should “DragTile” inherit from the light one or the robust one? If layout is handled through delegation, you may not need to choose.
  3. Composition often allows for greater decoupling. For example, let’s say you are building a photo organizer module. With the inheritance approach above, it would be difficult to create the module in such a way that the photo module knows absolutely nothing about the layout. With the composition approach, you could provide a default layout (say, Tile), while allowing the user of the module to pass in a different layout if needed.

All of this leads to the next tip, which is:

Tip 2: Think hard before using inheritance. Composition is almost always a better way to separate out the flexible part of a class from the invariant part.

So now we have a general idea of what we want to separate out, and how we want to do it. We’ll start digging into actual code in the next post.

14 Responses to “Making the world better via refactoring – Intro”

  1. kuwamoto.org » Blog Archive » Making the world better via refactoring - Step 1

    […] about | contact « Making the world better via refactoring – Intro   15May2007 […]

  2. Armand

    Many people don’t realise just how important refactoring is for any reasonable-sized project.

    I like to think that there are two kinds of refactoring:
    1. reactive – when you need to add a feature and you realize you can’t do that without altering internal structure;
    2. proactive – when you improve the inner organisation of the code to future-proof it.

    It may seem silly, but it’s a good attitude to keep code clean and well-organised. This way, when the client/users ask for a new feature or a different behaviour, it doesn’t break the whole app.

  3. trace(chris.foster) » kuwamoto.org » Blog Archive » Making the world better via refactoring - Intro

    […] kuwamoto.org » Blog Archive » Making the world better via refactoring – Intro May 17th, 2007 […]

  4. Sammy Larbi

    Nice post… But I think you should do explain better why inheritance is the wrong choice here – I finished reading feeling as if you consider it a valid approach to solving the problem (which it doesn’t seem to be).

    I was glad you explained the benefits of composition, because when you said “the most obvious way” was to use inheritance, I was like, “?!?!?!?!?!” =)

    I don’t think inheritance is the obvious choice here =).

  5. sho

    I think I probably tipped the discussion toward composition in the words that I chose to describe the problem. Even picking a class name like FlexibleContainer in that first diagram probably colored the discussion.

    I think that inheritance is a viable strategy here depending on your needs. Imagine that I had an inheritance hierarchy that looked like this:

    I don’t think there’s anything wrong with that, per se. I do, of course agree with you that composition is a better choice here, which is why I went down that path!

  6. jwopitz

    Sammy, I would not go so far as to say that someone should favor composition over inheritance as a general rule of thumb. Both have their advantages and disadvantages.

    Of course container type classes, by their very nature, would probably favor composition (as Sho has stated in the 5th comment). Not alway true with control type classes. There is more than on way to skin a cat… And here is why:

    Due to copious use of private and mx_internal APIs, accessing many aspects of a child component (i.e. composition) becomes nearly impossible. Obviously private properties and methods we can do nothing about, but some might say to go ahead and access the mx_internal aspects. I have done so, but Adobe even says, “This namespace is used for undocumented APIs — usually implementation details — which can’t be private because they need to visible to other classes. APIs in this namespace are completely unsupported and are likely to change in future versions of Flex.”.

    Until Adobe starts making more of the private APIs more accessible by utilizing the other namespaces AND/OR solidifies their stance on future support for the mx_internal namespace, I am not going to write inheritance off just yet.

  7. Refactoring or “making world better” |

    […] Making the world better via refactoring – Intro […]

  8. Posta kodu

    It’s very useful component especially for flash based e-commerce sites. Thanks.

  9. 小薛部落格 » Blog Archive » [翻譯]重構讓世界更美好(Making the world better via refactoring - Intro)

    […] [翻譯]重構讓世界更美好(Making the world better via refactoring – Intro) 這些文章翻譯自Sho Kuwamotoçš„ActionScript Refactoring 三部曲,經過原作者同意翻譯之。 本文原文連結在此。 […]

  10. articles « Panduramesh’s Weblog

    […] ActionScript Refactoring :: Intro :: Step 1 :: Step 2 :: Step […]

  11. ARTICLES ON FLEX « Panduramesh’s Weblog

    […] View Helper An architectural blueprint for Flex applications Advanced ActionScript Refactoring :: Intro :: Step 1 :: Step 2 :: Step 3 MVC Considered Harmful :: Great discussion in […]

  12. Articles on FLEX « welcome nandhu

    […] ActionScript Refactoring :: Intro :: Step 1 :: Step 2 :: Step […]

  13. Articles_on_FLEX « welcome nandhu

    […] ActionScript Refactoring :: Intro :: Step 1 :: Step 2 :: Step […]

  14. ARTICLES ON FLEX « Adiflex’s Blog

    […] View Helper An architectural blueprint for Flex applications Advanced ActionScript Refactoring :: Intro :: Step 1 :: Step 2 :: Step 3 MVC Considered Harmful :: Great discussion in […]

Leave a Reply