Tuesday, September 27, 2011

Writing an Extensible Application – Part 2: Extensibility by Reflection

 

Hi,

This time I will present a very primitive (yet somehow effective) extensibility method: Extensibility by Reflection. This method is good when you don’t want to over complicate things and all you need is a simple way to extend some specific types. This method is based on the Reflection mechanism of .Net (as the name suggests).

Let’s make a short recap of the previous post. I have made a small application that simulates balls within an enclosed rectangular area. Each ball has three “properties”: The Collider, the Mover, and the Drawer. The UI allows the user to select each of the aforementioned properties from a list and create a ball using these properties. The most important thing I did was to design the application in an extensible way. The main application uses all the data through interfaces which are defined in an external DLL (BallsInterfaces.dll).

I have created an additional project which represents the extensibility client (a dll your user would write). For coherence, I have moved all the basic types to that dll and now all of our colliders, drawers, and movers will be loaded through extensibility. I changed the build target path of the new project to be inside <Main project dir>/Extensibility. In the main project I have added the following key to the application settings:

  1. <appSettings>
  2.   <add key="ExtensibilityPath" value="Extensibility"/>
  3. </appSettings>

From this point things are quite simple. All we have to do is to load all the DLLs from the defined path and in each such DLL find and instanciate any class that inherits from ICollider, IMover, or IDrawer interfaces. The following code does just that:

  1. private void LoadExtensibility()
  2. {
  3.   Assembly applicationAssembly =  Assembly.GetAssembly(GetType());
  4.   string extensibilityPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(applicationAssembly.Location), ConfigurationManager.AppSettings["ExtensibilityPath"]);
  5.   string[] dllFiles = System.IO.Directory.GetFiles(extensibilityPath, "*.dll");
  6.   foreach (string fileName in dllFiles)
  7.   {
  8.     Assembly currentAssembly =  Assembly.LoadFile(fileName);
  9.     Type[] innerTypes = currentAssembly.GetTypes();
  10.     foreach (Type t in innerTypes)
  11.     {
  12.       if (t.IsClass && t.IsPublic)
  13.       {
  14.         if (t.GetInterfaces().Contains(typeof(ICollider)))
  15.         {
  16.           Colliders.Add(new StrategyAdapter(t));
  17.         }
  18.  
  19.         if (t.GetInterfaces().Contains(typeof(IMover)))
  20.         {
  21.           Movers.Add(new StrategyAdapter(t));
  22.         }
  23.  
  24.  
  25.         if (t.GetInterfaces().Contains(typeof(IDrawer)))
  26.         {
  27.           Drawers.Add(new StrategyAdapter(t));
  28.         }
  29.  
  30.       }
  31.     }
  32.   }
  33. }

A few things worth mentioning:

  1. I have added three ObservableCollections named – Colliders, Movers, and Drawers and hooked them up with the ComboBoxes in the application.
  2. Each observable collection contains an adapter class (StrategyAdapter) which mitigates the extensible type with the instance creation. It also provides the Name property for display within the ComboBoxes. The StrategyAdapter code is as follows:
  1. public class StrategyAdapter
  2.   {
  3.     
  4.     protected Type _innerItemType;
  5.     public string Name
  6.     {
  7.       get
  8.       {
  9.         if (_innerItemType != null)
  10.         {
  11.           return _innerItemType.Name;
  12.         }
  13.         return "Null";
  14.  
  15.       }
  16.       
  17.     }
  18.     public StrategyAdapter(Type itemType)
  19.     {
  20.       _innerItemType = itemType;
  21.     }
  22.  
  23.     public T CreateInstance<T>() where T:class
  24.     {
  25.       return Activator.CreateInstance(_innerItemType) as T;
  26.     }
  27.   }

And from this code you may infer that the ball creation code becomes:

  1. Ball ball = new Ball(SelectedMover.CreateInstance<IMover>(), SelectedCollider.CreateInstance<ICollider>(), SelectedDrawer.CreateInstance<IDrawer>(), _environment);

To extend this example I have added three new implementations of the extensibility interfaces:

  1. The Parabolic Mover – It moves the ball as if there was gravity (i.e. with acceleration).
  2. The Blinker Drawer – It creates a slightly bigger red ball that slowly disappears and then instantly reappears.
  3. The Stopper Collider – It stops the other ball on the spot after collision.

As usual, you can download the sources from my SkyDrive -

I want to take this opportunity to say שנה טובה וחג שמח to all my Jewish friends. Nice and fun 国庆节 to all my Chinese friends, rest and spend time with your families. Happy Friday to all my Pastafarian friends (since every Friday is a holyday!).

Thanks for reading,

Boris.

Friday, September 16, 2011

Yet Another Blog Post About Windows 8 – YABPAW8

 [Edit: You can find a more in depth information on Shasha Goldshtein blog who actually attends the convention. See the links on the right.]

Hi All,
Well, this is somewhat unexpected but even I cannot ignore the recent arrival of Windows 8 preview. Microsoft has created so much hype and rumors about their new OS that even I had to go against my rule – “Never come near Microsoft beta products” – and check it out. Before this release there were many speculations about which direction Microsoft is going to take. Most of those were based on a 4 minute video and various presentation shown in conventions (and a certain leaked build that could be found on the torrents). I heard ludicrous things like “Microsoft has rewritten the entire OS in JS and HTML 5” and somewhat worrying assumptions that .Net will no longer be supported. From looking at the preview version of Windows 8, the vast majority of these rumors and speculations is not at all close to reality.
Here is a summary of my very brief experience with Windows 8. Note that I might missed important things so you can always mention them in the comments.


Installation
The installation was quite simple. I installed Windows 7 on another machine just a couple of days ago and I must say that the Windows 8 installation is much shorter and doesn’t require restarts. Nevertheless, it looks exactly like the installation of Windows 7 (at least until the post installation steps). At the beginning the installation asked if I want to upgrade my existing installation which was interesting since I was installing on a clean machine. In the post installation I was asked to enter my Live ID and after I did everything was connected and my Windows user was my Live ID. I think it is safe to guess that in the real version they will have a way to create a regular user and connect to domains (at least for the Enterprise versions).


The new UI
Once you log on to the new Windows you are immediately thrown into the new Metro UI.p1


It looks and feels very nice and it is easy to find and activate each application. Although there was one thing that bothered me. It seems that it wasn’t designed for a mouse control because you cannot drag it left and right (I hope this will be added in the release). Instead you can use a small scrollbar on the bottom of the screen or the mouse wheel to scroll. As you can see in the screenshot, Metro style applications may use the new Tiles API while other application get a default tile that shows the application name and title. I tried to run some Metro applications and found nothing really special about them. They run on full screen without windows and have a common menu style that is similar to Windows Phone and can be activated by a right-click. There was one annoying thing that I experienced. It seems that Microsoft designed the applications for tablets or something because for the hell of me I couldn’t find an “Exit” button anywhere! Eventually I had to close each application using the Task Manager since Alt+F4 didn’t close them either (and trust me I know how to exit VIOpen-mouthed smile). Good thing that Windows button works during these applications and you can easily go back to the desktop.


p2


The Old UI
The nice surprise comes when you click the Desktop tile (or Windows button or Windows + D that still works). You are flung into the familiar Windows desktop (using a strange Skew effect from the 90’s which, I hope, can be somehow modified) and there you can see some subtle changes that I feel will make working with Windows somewhat simpler. As published, the Ribbon has spread into the Windows Explorer and all the important functions were externalized. This makes work somewhat simpler since you don’t need to rely on the context menus or the hidden main menu so much.
p3
There is still a strange Start button which, when clicked, throws you back into the Metro UI. Sometimes it shows this (see screenshot) ugly black menu and huge time display when you hover over it (sometimes it shows the very important tooltip “Start”).
An even nicer surprise was the new Task Manager (which I had to use quite a lot, see previous section) which has a brand new UI that shows all the important information in a nice colorful way. You can now easily see all the significant counters and have easy access to the Performance UI (which was hidden in Windows 7) and the graphs. Other than that the UI felt unchanged from Windows 7 in both the look and feel and the behavior.

Visual Studio Express (Preview Edition)
I tried out the new Visual Studio (a.k.a. vNext) and didn’t find any surprises there (although this is the Express version and I didn’t want to install the Ultimate version, yet). It looks exactly like VS2010 with no apparent significant changes. I think the most important change is that they finally cleaned out the default toolbars and left only the most important commands there. Other than that, from what I could find from my short experience with vNext, the major changes are:
  • Moved the Quick Access window (Control+3 in VS2010) to a static toolbar item.
  • Renamed Solution Navigator to Solution Explorer (I think the original Solution Explorer was removed).
  • Removed Quick Find.
(And no, they didn’t fix the most annoying bug ever where you can’t “Find In Files” if the editor is not open!)
In the short time I tested vNext I tried to create a small Metro application in WPF. Couldn’t see anything new here. There were some strange things (a project that has no references but still compiles with no problems) but everything seems to work as I am used to. By the way, I couldn’t find an “Exit” button on the default template of the Metro application either. Which makes me believe that there is some key I can click to close the applications.


Conclusion
From my very brief experience with the new Windows 8 I can say that there are quite many new things and concepts but it is certainly not a revolution. The Metro UI looks promising for the average user but it seems to target mostly tablets and not regular PCs that still use keyboard and mouse to interact with the interface. Once you go back to the Desktop the experience is not much different than Windows 7 except for the many UX improvements and additions. As a developer I didn’t find anything interesting in vNext but I checked only this Express Preview version and there are probably some surprises hiding inside (at least I hope so). I am looking forward to see what Microsoft has in its sleeve for the release.

Have a nice day,
Boris.

P.S.
This blog post was written on my Windows 7 PC.

Saturday, September 10, 2011

Writing an Extensible Application - Part 1

Hi All,


In the next posts I will try to examine some simple ways to make your application extensible. Most of the applications we use in our daily life have some form of extensibility. For example the Visual Studio has add ins, extensions, packages and other forms of extensibility which allow you integrate your own functionality to an existing application. For the purpose of our discussion I will define extensibility of an application simply as adding new application functionality without having to recompile any part of the application.

I will demonstrate briefly several simple ways to make your application extensible. To this end I have prepared a demo project (in fact, this post will discuss only this demo project).

The Balls Simulation

The demo project might be familiar to some of my readers since I take it from the new employee training program of my previous job. The application contains a rectangular area called "field". The user adds entities to that field called "balls" and they move inside the field. The balls may collide with each other during the movement within the field and they have to react accordingly. The balls may also collide with the walls and react accordingly.

A screenshot from my demo application
The most important part of writing an extensible application is to decide how the user will be able to extend it. In the case of my application the user will be able to extend the ball behavior using three aspects:

  • Movement - Determines how the ball is going to move around the field.
  • Drawing - Determines how the ball is going to be drawn on the filed.
  • Collision - Determines how the ball will react to a collision with another ball.
Now that I decided that these three items are my extensibility points I need to decide on the design of the application. I chose to implement it using the strategy design pattern. Each of the three elements mentioned above will have a strategy object which will be assigned to a ball. (The ball will be composed of the three element.) Now that this is decided I can define a dll that will be given to the extension writers, clients, which will contain the required interfaces. You don't want to give your clients a bulky dll that will contain all the classes and the logic but a thin layer which will not confuse them but will allow to write a complete extension set.

The interfaces I defined are:
  1. public interface IMover
  2. {
  3.   void Tick(IBall ball);
  4.   void Initialize(IBall ball);
  5.   void AtWalls(IBall ball, HashSet<WallType> wallTypes);
  6. }
 
  1. public interface IColider
  2. {
  3.   void AfterCollision(IBall ball, IBall other);
  4.   void BeforeCollision(IBall ball, IBall other);
  5.   void Collision(IBall ball, IBall other);
  6. }
 
  1. public interface IDrawer
  2. {
  3.   void Tick(IBall ball);
  4.   void Initialize(IBall ball);
  5. }
 
At this point I want to dedicate a short passage on coding games. The basic design of a game contains a game timer that paces the game. The game timer activates as fast as possible but sometimes it is limited to a specific frame rate - FPS (Frames Per Second). Each time the timer activates is called a game "tick". In each tick the game manager iterates on all the entities within the game (called "sprites") and calls a method that updates their inner parameters. Then the game manager iterates on all the sprites again and draws them on the screen.

As you can see I am using a 3 method collision handling. This method will not cover all the collision cases but it is good enough for many basic games including this demo application. The rules are simple: When two balls collide then the three collision methods are called one by one on each ball with an alternating order (see the code snippet next). On the BeforeCollision method the current ball can gather and data it needs from the other ball but it is not allowed to change its own data. On the Collision method the ball may change any of its parameters based on the data collected in the BeforeCollision method. On the AfterCollision method each ball may set any parameters on the other ball but not on itself.


Putting every thing mention above into code, results in the following Tick method of the timer:





  1. #region Handle Movement
  2. foreach (Ball ball in _balls)
  3. {
  4.   ball.Move();
  5.  
  6.   HashSet<WallType> hitWalls = new HashSet<WallType>();
  7.  
  8.   if (ball.Left <= 0)
  9.     hitWalls.Add(WallType.Left);
  10.  
  11.   if (ball.Top <= 0)
  12.     hitWalls.Add(WallType.Top);
  13.  
  14.   if (ball.Right >= MainCanvas.ActualWidth)
  15.     hitWalls.Add(WallType.Right);
  16.  
  17.   if (ball.Bottom >= MainCanvas.ActualHeight)
  18.     hitWalls.Add(WallType.Bottom);
  19.  
  20.   if (hitWalls.Count > 0)
  21.     ball.AtWalls(hitWalls);
  22. }
  23.  
  24. #endregion
  25.  
  26. #region Handle Collision
  27. for (int i = 0; i < _balls.Count; i++)
  28. {
  29.   for (int j = i + 1; j < _balls.Count; j++)
  30.   {
  31.     if (IsColliding(_balls[i], _balls[j]))
  32.     {
  33.       _balls[i].BeforeCollision(_balls[j]);
  34.       _balls[j].BeforeCollision(_balls[i]);
  35.       _balls[i].Collision(_balls[j]);
  36.       _balls[j].Collision(_balls[i]);
  37.       _balls[i].AfterCollision(_balls[j]);
  38.       _balls[j].AfterCollision(_balls[i]);
  39.     }
  40.   }
  41. }
  42. #endregion


(Note that in this first version the Drawer is not used but you will see it in play in the next post)


The main object of the game is the Ball class. It is exposed to the client as an interface and the client may interact with this class through the interface. All the Ball logic is managed within the class itself, feel free to browse the code there after downloading the demo application.


The application UI is quite simple. The field is on the left side. On the right side there are three combo boxes which will allow you to select the relevant strategy objects and a create button that generates a ball with the selected strategy objects. Both the Mover and the Drawer have Initialize methods that are called once the ball is created to allow the client position and draw the ball for the first time. Note that for this initial stage of the application the combo boxes are not used (since there is no extensibility yet) and the create button creates a small blue ball that just moves around and bounces off walls and other balls.


I encourage you to try out the code to get the feel of it before diving into the extensibility part in the next posts.


You can download the code from my SkyDrive here:


 


Thank you for reading,


Boris.


 


P.S.


Thanks to David Elentok you can see that the formatting is improved a little. I hope to improve it even more in future posts.