luni, 4 iulie 2011

Flex DataGrid editing

The data grid is one of the most used elements in Flex, for displaying collections of data. There are many reasons for this, among which I'd like to mention its flexibility in handling different data and ease of use (basically, all you need to do, is specify a data provider).

In addition to this, the DataGrid object, can handle more advanced operations. For instance, using customized item rendering components, or data editing (and this will be our main focus for this post).

So, how can we edit the data inside a data grid? First, by specifying that the user is allowed to do this, by setting the editable property of the data grid to true. Then, when running the application, all the user has to do is click on the cell that needs to be edited.

Let's consider the following scenario. We use a data grid for editing the data in an array collection, but we want to check if a cell value was actually modified before we save the new data (since it wouldn't make sense to update the current data if no actual values were changed - i.e. the user edited a field, but then reverted it to the previous value). How do we do this?

First by understanding the events that a DataGrid object dispatches, particularly the ITEM_EDIT_END event, since it is dispatched before the old value is replaced. That being said, we know when to determine if an actual change has been made. The only problem remaining is how, specifically how do we compare the old value, with the new one?

We can determine the initial value by using the data grid's itemRenderer property, which is an instance of the component used to display the data and is passed to the event also. To access the data, we still need to determine the field that was edited, and we can do so by using the event's dataField property. Now to access the data, we can use:

event.itemRenderer.data[ event.dataField ];


So now that we have the old value, we need to get the new value. This step is a little easier, since we don't actually need to know the field that was edited, because the data grid contains a TextInput element instance, for editing a cell. We can retrieve its value by using the data grid's itemEditor property which, as mentioned above, is a TextInput instance, so we can use its text property to get the new value:

event.currentTarget.itemEditorInstance.text;

If we assign these values to, let's say, the oldValue and newValue, we can make a simple comparison to determine if indeed the new value is different from the old one.

joi, 7 aprilie 2011

IE6 is still hanging in there

If you have been in the web development industry for a few years, chances are you have heard about, got mad at (read "utterly angry"), and fought against browser compatibility issues in Internet Explorer 6. Now don't get me wrong, I don't mean to say anything bad about it (meaning I'm just glad since I don't have to work with it anymore), but this post was inspired by Chris Heilmann's article HTML5 for XP now! and particularly by a link in it: Internet Explorer 6 Countdown.

After checking it out, I must admit I found it a bit odd for Microsoft to "bury" its own baby. I mean, they could have left it silently slip out of the web scene. However, since it reigned for so long, in order to make it go extinct, they actually had to step up and do something about it themselves, rather then just let people upgrade or switch browsers. So, in my opinion that's just like saying "yeah, we made a mistake...".

So, if you haven't ever been forced to resort to hacks, IE-specific stylesheets etc. you can call yourself a lucky web developer. I am curious if there are such developers today, because sometimes I still hear "cross-browser", or "IE issues" and after I don't feel chills running down my spine anymore, the first thing I feel like saying is "Oh, that takes me back...". A few years from now I'm sure people will still remember the name of IE6 (and fear it) even though it will be long gone, and a few years later still my kids will ask "Dad, have you ever heard of IE6? Is it true that most of the development time was used to fix IE6 issues?". My answer will be "Yes, it is true, so be good if you don't ever want to use it for browsing...".

I'm pretty certain IE6 will be a sort of boogie man for future generations of web developers.

marți, 5 aprilie 2011

Be nice to developers

Lately I have been reading Scott Rosenberg's book,  Dreaming in code and besides all the interesting ideas and stories therein, one quote in particular stuck in my mind "Our civilization runs on software".

If you think about it, every item we use on a day to day basis, relies on software to function. If that's true, then it's safe to say that software developers make the world go round. This may be one way to explain why more and more people are getting into the software industry (this includes developers, testers, managers, marketers, distributors - you name it - of course, not necessarily in that order).

Which brings me to my point. A friend of mine once told me an interesting story. He was in a restaurant abroad and since he is a very good cook, he wasn't happy with the way the food he ordered was prepared. Rather than complain to the waiter, he left his food and went away. Intrigued by this I asked him what was his reason for doing so. He told me that it is never wise to argue with people who prepare or serve your food... and you can imagine why.

I have to admit it made perfect sense to me. Besides, if one person doesn't like something (in this case, the way some food is prepared), that doesn't mean there isn't someone who actually loves it that way (except for a few cases in which the food is very bad prepared). And if that's true for food, which is something we need on a daily basis, why wouldn't it be also true for software?

So in closing, if you don't mess with people who prepare and serve your food, you certainly don't want to mess with people who code your software. Remember, the people who cook your food, rely on software to get the recipes right.

Don't mess with us, we control every aspect of your modern life...

miercuri, 16 martie 2011

Flex 4 states changes

Recently I had the task of reimplementing a tool tip component, using the new Flex 4 state features. The component had to states, default and expanded. The latter had just a few additional information than the first one.

Traditionally, states were meant to implement the look and feel of a component, totally independent of each other, so it was frequent to have repeating content between states. But all that has changed in Flex 4.

After reading a very helpful article about the recent changes, which you can find here, I was pleasantly surprised to see that state content was no longer segmented (in a sense that the content for a state, is completely separated for the other states) but rather, each element in the component can be assigned to a specific state. This way the states serve merely a design/functionality purpose, and the elements themselves can be included or excluded into or from a specific state. That way, no content is repeated.

Here is a quick example of this concept, a component consisting of a text (default state) and a button (expanded state):

First, the Flex 3 implementation:


    <mx:states>
        <mx:State name="default">
            <mx:AddChild>
                <mx:TextInput id="myTextInput" />
            </mx:AddChild>
        </mx:State>

        <mx:State name="expanded">
            <mx:AddChild>
                <mx:TextInput id="myTextInput" />
                <mx:Button id="myButton" />
            </mx:AddChild>
        </mx:State>
    </mx:states>


You can see how the state layouts are completely independent of each other. Now let's take a look at the new way of defining states:


    <s:states>
        <s:State name="default" />
        <s:State name="expanded" />
    </s:states>

    <s:VGroup>
        <s:TextInput id="myTextInput" />
        <s:Button id="myButton" includeIn="expanded" />
    </s:VGroup>

Quite a difference. An equivalent implementation would be to use excludeFrom="default" instead of includeIn="expanded".

For more information regarding Flex 4 states changes and examples, read Adobe's Enhanced States Syntax article.

vineri, 25 februarie 2011

My social media platform

We are all using social media nowadays. Some for collaboration as opposed to using email, others for finding out the latest news. However, must of us use it to share stuff we find interesting.

I use it too, and mainly for the stuff I described above. I need to keep in touch with business contacts (yes yes, I do use email as well...), sometimes I want to check out what's been happening in areas I consider interesting, but mostly I like to share stuff, of course, not just my own :)

So I present to you my own social media platform:


There we have it! The cream of the crop in social media!

luni, 21 februarie 2011

TileBox - background image container component

Recently I had to implement a layout, which had in its header's background an image that could be tiled to create a rather nice looking effect. One problem in Flex is that creating containers that have a tiling background image is not so simple as in CSS (i.e. specify background-image and background-repeat properties ). To accomplish this, you would need to extend an existing component and then rewrite the rendering method.

Taking into account the fact that I slice a lot layouts, it made sense to make a component that could be easily added to any project, that needs a container with a tiling background image. I named it TileBox because you can basically use it as a standard (H/V)Box container (well, almost, you'll see...).

Before we take a look at the code, let's see a quick demo: http://romualdhalasz.com/projects/tilebox/

The way to use it in a Flex application goes something like this (I'll use MXML for simplicity):

1. Create a TileBox object (notice the namespace) with a text object as its child


<tilebox:TileBox width="100%" height="100%">
          <mx:Text text="One line" />
</tilebox:TileBox>


2. Set the source property, which is the equivalent property of an Image object's:


<tilebox:TileBox width="100%"
                          height="100%"
                          source="@Embed(source='assets/bg-image.jpg')">

        <mx:Text text="One line" />
</tilebox:TileBox>

Voila! Now we have a container that has a tiling image as it's background. But it's still not quite enough. What if we want to tile the image only on a specific axis? This is a situation we find ourselves in more often that the one described above. Not to worry, specifying the repeat axis is as is easy as setting the background-repeat property in CSS:

<tilebox:TileBox width="100%"
                          height="100%"
                          source="@Embed(source='assets/autumn-leaf-tile.jpg')"
                          backgroundRepeat="repeat-x">
        <mx:Text text="One line" />
</tilebox:TileBox>

The backgroundRepeat property's default value is "all", meaning both axes. Use repeat-y if you want to tile the background only on the vertical axis.

So far so good! But now we can tile horizontally only on top of the container, and vertically on the left side. What if we want to tile an image horizontally, on the bottom of the container, or vertically on the right side? We might have a problem, if we didn't have the backgroundPosition property:

<tilebox:TileBox width="100%"
                          height="100%"
                          source="@Embed(source='assets/autumn-leaf-tile.jpg')"
                          backgroundRepeat="repeat-x"
                          backgroundPosition="top">
        <mx:Text text="One line" />
</tilebox:TileBox>

This property work exactly like you would expect it to: it can take the usual values - "bottom", "left", "right" and "top".

You can see the demo here: http://romualdhalasz.com/projects/tilebox/

Just use the combo menus on top to modify the repeat or position property to see different uses.

If you want to use the component in your own projects, just add TileBox.swc file to your libs. You can download it here: http://romualdhalasz.com/projects/tilebox/TileBox.swc

For any suggestions on improving this little component, drop a line and I'll see what can be done!

joi, 17 februarie 2011

How do we measure good code?

A question with no simple answer, because the notion of good code varies from coder to coder, from team to team and from project to project. Also, there are many criteria for determining the quality of written code. Let me give you a few examples: actual code size, number of units, time needed to write, memory usage, request handling, practices employed etc.

As you can see, there are a myriad of criteria which play a significant role when considering the "overall goodness" of your written code and furthermore, if attempting to evaluate your code using these guidelines, you will quickly find out that the result is relative to each project, at best.

This was a concept that stuck in my head for some time now, mainly because I'm always interested in improving the quality of the projects I'm involved in, by writing improved code. I'm talking about both professional and personal projects.

First, let's consider the fact that in order to classify the code written, we need to have a solid basis for evaluating a task relative to the project it belongs to, because the same task can have varying difficulty in different projects. And here is the core of the issue. Normally, adding the feature (i.e. doing a task) to an existing project, should have the same difficulty regardless of the overall project complexity. You may not fully agree with this concept, but if you disregard project-specific data structures and keep in mind only the flow or functionality, then it might make more sense.

This is precisely why I tend to believe that "code goodness" can be determined by the amount of changes (to the already existing code) needed in order to complete the task. So, we cannot determine how well some code was written, until we see how flexible it is, in the sense that it must be flexible enough so we can add new things, without altering it. Now, that might sound weird, counter-intuitive, but it makes sense if you think about it.

Here's an example. Let's say we are implementing an application for managing songs (add / edit / delete). It might be simple enough, but there are many ways to go about it, so let me give you a quick example: We have an object that manages songs by building queries based on input data and then executes them to update the records. Now, we need to extend the functionality a bit, and add the possibility to manage videos in the same way. You can see the fact that although the data structure might have changed, the functionality itself did not. So, if we were to change the way songs are managed, just so we can manage videos as well, then that would be a sign that the code we have previously written, was not flexible enough. In more technical terms, the model was tightly coupled with the business logic. Therefore, the controller does not allow new functionality to be added without altering its previous code. We could also clone the functionality for the video manager, but it still would be far from perfect since we have two objects that exhibit the same behavior.

On the other hand, if our controller was written in such a way that it can manage varying data structures, then we know it is good. A more flexible example would be to separate the database operations manager from the input parser. The way to do that would be to have some object for gathering the data, then another for building queries based on the current data structure, and finally, one to manager the database connection and execute a query.

Now that's a lot better! We can add a whole lot of new data types, like books for instance and we can focus solely on the code needed to handle books, not songs or videos.

In conclusion, we can only determine how good code a segment of code is, after we have written it, and used it, by determining the amount of code we need to change in order to implement new requirements. Of course, this means a smaller value corresponds to a higher rating.

Also, it is generally a good idea, when designing the architecture of a project, to take into account things that resemble the requirements, but haven't been explicitly requested, this way you can help improve the flexibility of your code dramatically, and in time, it will become like a reflex. The direct result of this habit is that the code you write will be more abstracted, and therefore handle additions without too much (and later hopefully none) code changes.

luni, 31 ianuarie 2011

Achievements

I have recently read a very interesting article on the WhileTrue blog, regarding the funny situations in which Microsoft Visual Studio would have achievements, like modern games. You can read the full article here.

While reading the article, I noticed that most of the achievements, also apply in Adobe Flex, but we do have some specifics. Let me give you a few examples:

The fixer: 2 consecutive hours of writing code in debugging perspective.
The hypochondriac: 10 consecutive clean builds on a single project.
No room for error: Finishing a project with Build automatically turned on.
The non-believer: 3 consecutive SVN updates required in order to actually download anything.

luni, 17 ianuarie 2011

Keeping development issues at bay

If you work in web/software development, I'm sure that you encounter very often issues of varying difficulty. One thing that adds to the overall complexity of an issue, is having to specify a time frame needed to resolve it. If we were to classify the issues one can encounter while coding, we get two categories of issues:

1. Issues that you have encountered in the past (directly or indirectly) and you have a pretty good idea about the time needed to resolve it, even if there are some minor variations from your past experience

2. Issues that you have never come across before; in this case, estimating the time needed would prove to be more difficult

However, the first category of issues, contains a small subcategory of issues that rarely surface, but when they do, they can be quite a pain to deal with. I'm talking about issues that not only have small variations from your past experience, but on top of that, the context differs in which the issue appears differs also. Why is this a problem ?

Let's consider the first category of issues. Dealing with an issue that you have approached in the past is usually an easy task, regardless of the time needed, because once you have the necessary experience, you know which way to go. When approaching issues from the second category, if you're lucky enough to not have to specify a time frame, you can go at it at your own pace.

Now consider having to deal with an issue which you have solved in the past, but with a few variations and in a different context. Since you already have experience with it, you might be tempted to give a very optimistic time schedule because you disregard the individual details of issue. So instead of resolving the issue in, let's say, two hours, you end up doing it in two days. Not only does this screw up your schedule, but it can also be very frustrating to spend two days on a feature you initially planned to solve in two hours.

How can we overcome this kind of issues? Well sadly, there is no way to actually recognize one, until you have already missed the deadline. Then, you find yourself in the situation when someone comes you and asks to see your work and you have done only about 20%. I'm sure no one would like to be in that situation. But if you do find yourself in such a "mess", the best idea would be to split the issue in smaller steps.

What I mean specifically, is that the first thing to do is to break it up in the things that you have already resolved in the past and you can use that experience, and the ones that relate to this specific context. Next, make sure that you fully understood the issue. Nothing beats the frustration of finishing a task, and then having to make changes because you didn't understand the requirement all the way and you assumed some things that turned out to be wrong. Having this separation will help you in deciding what to focus on at any given moment, because clever as developers may be, they can only focus on one thing at a time :)

And one more thing that can really help overcome the issue is not being afraid to interact with your colleagues. I'm sure the at times, we find it hard to ask other people regarding how to solve an issue, because we assume that we'll appear unable to resolve it in the first place. That is a misconception. The experience you get by interacting with other people is much greater than the one you get by solving issues on your own. Even if you are absolutely sure you can solve an issue, if you (and they) have time to spare, present the issue and your method of resolving it. They could give you an alternative, which might actually work better (in this case don't be afraid of admitting it), or at least point out some details that haven't crossed your mind, which could help planning and save you a lot of time in the long run.

And if you have already been there, make sure you avoid the issue in the future by thoroughly examining each issue, regardless of its complexity, then making sure you have taken into account all the details that could screw up your initial estimate. This might sound like too much of an effort, but in time it will come natural to you, and hopefully you won't fall into the trap of underestimating the effort needed to resolve a seemingly simple issue.

Until next time, have a good one,
Romi

joi, 6 ianuarie 2011

Conways' game of life, a more natural approach

A few weeks ago, I attended a local programming event, entitled Code Retreat. The main purpose was to give coders a chance to focus on something other than designing / implementing features and meeting deadlines. The main focus of the event was the code itself. We had to code a version of Conway's game of life, but instead of actually finishing the task, we had to develop the application in pairs and follow some rules which underline Agile practices, for instance, all methods should be shorter than 8,6 or 4 (easy, medium, hard) lines, don't use cycles, don't use conditional statements, use very descriptive variable and method names etc.

I never thought just messing around with code could be so much fun. By the end of the event we have experienced multiple ways of implementing the application, and I have learned quite a bit of very handy tricks for coding. The ideas we discussed persisted in my head for many days and I wanted to have another go at implementing the application, since none of us got the chance to finish it at the event.

Here is what it looks like, the final version, because after getting the basics down (e.g. cells, universe,  iterations etc.), I just added stuff to it: Life game.

Let me say a few words about the code. First thing, I used the Parsley framework to develop it, because it is perfect for quick development of Flex applications, then there are a few details that are worth mentioning, regarding the dynamics of the game.

When implementing the application, there are basically two paths you can go by: the first would be to focus on the universe - which is to say, the grid that holds the cells (its most simple form is a n x n matrix, consisting of "dead cells") - specifically, at each iteration, the grid parses all the locations and updates the cells accordingly (the living ones that don't match the conditions die, and the dead ones that do meet the conditions, come alive).

Then, the second way is to focus on the cell. Each cell holds its number of living neighbors, it has two states (alive/dead), and it can update itself. The grid just parses all cells, passes the number of living neighbors to each cell, and lets it know when to update its state.

Both of these solutions work equally well in practice, and implementing one of the two is basically a matter of preference. However, in my opinion, none of them seem to reflect the way our natural universe actually works. What I mean, is that the universe does not consist of "dead cells" that "come alive" according to some rules, and another thing, once a cell dies, it shouldn't be able to come alive again (i.e. it shouldn't be allocated in memory). The universe should just manage the living cells, then spawn new ones and finally remove dead cells forever (yeah I know, it's an oversimplification but I feel it reflects the best way of how our universe works). So instead of actually having a grid of dead cells, we just need to have a list of living cells and let them do their business. This way we balance the focus between the universe and the cell.

The next problem to solve is how to instruct the cells to multiply. Again, we can look to our universe for an answer. If we assume that a cell is aware of its own position in the universe (in this case a 2D grid), the natural thing for it to (want to) do, is to multiply in all available directions (NW, N, NE, W, E, SW, S, SE) - as a side-note, I got this idea from Richard Dawkins' book The selfish gene - because a cell shoud not "care" if it can or not multiply on a specific location, it's just "wired" to do so; the universe should "tell" the cell if it can spawn an offspring at a particular location, or not - as we are about to see. OK, now that we got that down, our application is starting to function more and more like the real universe.

Now the only problem that remains, is how to spawn new cells in the universe. Let's do a quick recap:

1. The universe consists only of the living cells.
2. Cells spawn their offspring in the adjacent locations to their position, 8 in number.

According to the game rules, a new cell is born if it has three living neighbors, which is the same as saying "a new cell is born on a particular location, if three already living cells want to spawn their offspring on that same location". This way, it's like three organisms need to "come together" in order to create new life... talk about a menage a trois :)

So this way, the universe is responsible for "telling" the cells if they are allowed to multiply or not, being according to the game rules, or within the grid limits. In fact, the cells don't even know if one of their spawn locations was used to spawn a new cell, nor should they care. And correct me if I'm wrong, but this method reflects how the universe actually works, in principle at least :). So the final flow of the application looks like this:

1. The universe consists only of the living cells.
2. Determine all the locations in which cells want to spawn their offspring.
3. The universe parses those spawn locations and looks for triplicates.
4. The universe spawns new cells on locations that can be classified as triplicates.

Feel free to check out the application here (view source enabled) and let me know what you think.


'Till next time, take care!