Saturday, February 13, 2021

Strategy? My two cents on Design Patterns

This may seem a bit out of the blue. But I've been reading a bit on Design Patterns lately. 🤓 Even though there are plenty of materials out there on the topic, I still thought it was worth making a note out of. So here goes nothing.

For someone who have formally studied Computer Science, Design Patterns most probably must have been one of the first and foremost things to learn. For people like us, who came in to already vastly evolved computer science world, this might seem like just another theory, but thinking back to a time when these 'theories' didn't exist, it must have been really challenging developing rapidly growing and robust systems. 

Design Patterns, just like most of other theories in computer science, came to be from within the community itself. Developers, who encountered problems and found solutions in the systems they are developing, could see same thing happening all over again to fellow developers. They identified these common patterns that can be universally applied to similar systems and called them Design Patterns.

When it comes to software systems, we often have to think about objects, classes and relationships. We can apply design patterns to all of these aspects. We have patterns that takes object instantiation in to consideration, patterns that focus on class relationships and patterns that can be applied to object behaviors. Let's look at some famous design patterns divided into these categories.




One of the first design patterns I came across early in my carrier was the Strategy Pattern. Like most of us, I honestly did not expect to see the theories I studied being applied on live projects, and I was pleasantly surprised.😇 So I'm gonna make this post about this particular pattern.

Let me put forth the definition of the Strategy Pattern I studied way back in the good old university days here first. 👀

"The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it"

😕

I have no idea why these definitions have to be so hard to grasp, but this particular one is not so bad in my opinion. This simply implies that we can design a class, which uses some algorithm to do something, such that we can switch that algorithm without affecting the class itself. To give you an example, let's say we have a List class that has a 'sort' method. We should be able to switch the algorithm used in the sort method to any algorithm we want, be it the quick sort, the bubble sort or any other sort, without changing the List class. Sounds powerful, isn't it? Let's look at some UML Diagrams then.



Above diagram demonstrates how we can apply strategy pattern to the example I just gave. We can say that we have multiple sort 'strategies' or 'behaviors' or as per the definition, 'related algorithms' and we need to use them inter changeably in out list classes or 'clients' without changing any of them.

The List class above is the super class to all the list implementations which is denoted by the inheritance arrow. We call that relationship an 'is-a' relationship. LinkedList is-a List, ArrayList is-a List, so forth.  Where as the relationship between the List and the ISortStrategy is a 'has-a' relationship. In formal words, a Composition relationship. This is the relationship that makes it possible for us to switch the sorting algorithms as we see fit.

Let's say we want our ArrayList to have BubbleSort as it's sort method. Here's How we do this.

List arrayList = new ArrayList()
ISortStrategy bubbleSort = new BubbleSort()
arrayList.setSortStrategy(bubbleSort)
arrayList.performSort()  //will sort using  bubble sort


Now if we wanted to switch the algorithm to CustomSort, that's very easy to do.

ISortStrategy customSort = new CustomSort()
arrayList.setSortStrategy(customSort)
arrayList.performSort()  //will sort using  custom sort

See, we didn't have to do a single change to any of our List classes. Plus it's easier to introduce new sort algorithms to our system. This is how powerful the Strategy Pattern is. ðŸ’¥

This went longer than I expected. So I'm gonna stop my rambling now. Well, in a gist, Strategy Pattern encourages Composition over Inheritance because, with inheritance, the systems tend to get too complicated and unmaintainable with rapidly growing systems. 

Finally I want to introduce this amazing book I'm reading on Design Patterns, "Head First Design Patterns". I've never been more enthusiastic about a theory book until I got my hands on this one. Really cool writing style, as the title says, "A Brain Friendly Guide". KUDOS to the Authors!

See you in another post!


Link to the Book



Tuesday, January 19, 2021

Email Templates , the good, the bad, the worst! - Lessons learned

 I recently had to work on redesigning some email templates, and as usual, encountered some bumps along the way. So thought of making a note to myself as well as to the community while resurrecting this old blog of mine. So here we go.

In summery here are some dos and don'ts which I will explain in detail later in the post.

Always try to chose,

  • <table> over <div>
  • Hex color codes over RGB
  • Pixel dimensions over relative ones(such as %, em, rem)
  • Web safe fonts over web fonts
  • Inline styles over css class rules

 

Now lets get into the Whys 

 

Template Structure


While many email clients nowadays support rather modern html tags, there are still some clients which don't. The <table> tag being one of the oldest html tags we can safely assume all the clients to date support it. 

Special Tip: Use <table> as the wrapper element of the email content and any inner structures that need fixed relative width. This is because some clients are cutting out the body tag, so this wrapper becomes the container for the entire template. Wrap the entire layout in a single table instead of having multiple tables in the body. This is because when there are multiple tables with different sizes, mobile email clients scale them separately to fit mobile screens which might distort the original intended layout.

 

 Here's how I ended up with my template structure.

 


 Sizing

Limit the width of the layout to 600-800px. Specify width, max-width and min-width values of outer elements and use % widths for inner elements if necessary. For images, specify both width and height, don’t give auto height if not intended.

 

Spacing and alignment 

 

Better to use px to specify spacing(padding, margin etc) than relative measures because they highly depend on device dpi and the email client's interpretation of it. Don’t use flex or flex-box layouts. Control positioning with table elements instead.  For tables, (at least outer once) set border, cellpadding, cellspacing to 0 and use padding/margin to maintain proper distances. Use align to align content within table cells. 


Styling 

 

Some mail clients cut out <style> tags. Use inline styles(additionally).


Fonts 
 
Try to use web safe fonts and if web fonts are a must, use similar web safe fonts as fallback fonts. Don’t use shorthand css “font” when specifying fonts, use “font-family”, “font-size” etc instead. Use px for font sizes, the baseline for em can be different for email clients.
Below is a list of email clients with their support for web fonts.So that's about it generally for any email template design. (Source: https://helpx.adobe.com/si/fonts/using/html-email.ug.html)
 
 
 
Below is a small tip for Django developers(like me) regarding translation tags in email templates.
 

Additionally, Translations(Django): Try to minimize html elements inside translation tags(specially be careful with blocktranslation tags). And if cannot be avoided, keep the style/css out of them. This is to keep style changes from affecting the translations.

 

Happy 2021! See you in another post.

Wednesday, December 30, 2015

Using GeoWebCache cached tiles as OpenLayers Tiled layer

If you have created maps using Geoserver then you may aware that those maps can be cached as image tiles using GeoWebCache. If you want to get rid of another back-end server to render and serve your map, serving it as map tiles might be a good idea. Open Layers ol.source.XYZ is the option provided for us to render a map from cached image tiles. But with GeoWebCache caching mechanism there is a little problem. XYZ source requires the tiles to be stored in a structure similar to {z}/{x}/{y}.png where z is the zoom level and x,y is the coordinate of the tile and GeoWebCache generated tiles are not in this format.  OpenLayers gives us an option to provide a url generation function as tileUrlFunction. I came up with functions below with the help of GeoWebCache.js which is the OpenLayers 2 way of doing this.

var zeroPad = function(num, len, radix)
{
    var str = num.toString(radix || 10);
    while (str.length < len)
    {
        str = "0" + str;
    }
    return str;
};

var customUrlFunction = function(bounds)
{
    var x = bounds[1];
    var y = bounds[2];
    var z = bounds[0];
    var shift = z / 2 | 0;
    var half = Math.pow(2, shift + 1);
    var digits = 1;
    if (half > 10) {
        digits = ((Math.log(half) / Math.LN10).toFixed(14) | 0) + 1;
    }
    var halfX = x / half | 0;
    var halfY = y / half | 0;
 
    var path = [
        gridsetName + "_" + zeroPad(z, 2),
        zeroPad(halfX, digits) + "_" + zeroPad(halfY, digits),
        zeroPad(x, 2 * digits) + "_" + zeroPad(y, 2 * digits) + "." + "png"
    ].join("/");
 
    var base = url.replace(/\/$/, "") + "/";
    return base + path;
};

The gridsetName is the name of the GridSet which was used to cache the tiles in GeoServer, normally this is the projection, for example, 'EPSG:4327'. The url is the local folder where the tiles are located.
By default, openlayers start calculating the tile coordinates starting from the bottom-left corner of the map. But Geoserver cached tiles are named taking top-left corner as the origin. So to make it right, when initializing the XYZ source, a tile grid must be provided with the origin set to top left corner of the map.

var tileGrid = ol.tilegrid.createXYZ({
        extent: mapExtent,
        tileSize: 256,
        origin: [mapExtent[0], mapExtent[1]]
    });

var tiled_layer = new ol.layer.Tile(
        {
           source: new ol.source.XYZ(
                    {
                        projection: projection,
                        tileGrid: tileGrid,
                        maxExtent: mapExtent,
                        tileUrlFunction: customUrlFunction
                    })
       });

Following is the complete code I used to load the tiles I have generated from GeoWebCache.

var url = file/path/to/tiles/directory/;
var gridsetName= name_of_the_Gridset;
var projection = projection_of_the_map;
var mapExtent= [];
var zeroPad = function(num, len, radix)
{
    var str = num.toString(radix || 10);
    while (str.length < len)
    {
        str = "0" + str;
    }
    return str;
};

var customUrlFunction = function(bounds)
{
    var x = bounds[1];
    var y = bounds[2];
    var z = bounds[0];
    var shift = z / 2 | 0;
    var half = Math.pow(2, shift + 1);
    var digits = 1;
    if (half > 10) {
        digits = ((Math.log(half) / Math.LN10).toFixed(14) | 0) + 1;
    }
    var halfX = x / half | 0;
    var halfY = y / half | 0;
 
    var path = [
        gridsetName + "_" + zeroPad(z, 2),
        zeroPad(halfX, digits) + "_" + zeroPad(halfY, digits),
        zeroPad(x, 2 * digits) + "_" + zeroPad(y, 2 * digits) + "." + "png"
    ].join("/");
 
    var base = url.replace(/\/$/, "") + "/";
    return base + path;
};

var tileGrid = ol.tilegrid.createXYZ({
        extent: mapExtent,
        maxZoom: 8,
        tileSize: 256,
        origin: [mapExtent[0], mapExtent[1]]
    });


var tiled_layer = new ol.layer.Tile(
        {
           source: new ol.source.XYZ(
                    {
                        projection: projection,
                        tileGrid: tileGrid,
                        maxExtent: mapExtent,
                        tileSize: 256,
                        tileUrlFunction: customUrlFunction
                    })
       });


var map = new ol.Map(
        {
            target: 'map',
            layers: [tiled_layer],
            view: new ol.View(
                {
                   center: [(mapExtent[0]+mapExtent[2])/2, (mapExtent[1]+ mapExtent[3])/2],
                   projection: projection
                })
        });

Thursday, February 27, 2014

JQuery Dynatree - Limit number of multiple selections

JQuery Dynatree is another simple and useful plugin for display tree structures. Additionally it allows selection of nodes, single selection (radio-button) or multiple selections (Check-box). A simple multiple choice dynatree can be loaded with a script similar to this:
$("#dynaTree").dynatree({
        checkbox: true,
        classNames: { checkbox: "dynatree-checkbox " },
        selectMode: 2,
        children: TreeData,
        onSelect: function (select, node) {
            var selNodes = node.tree.getSelectedNodes();           
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });
            var selKeys = $.map(selNodes, function (node) {
                return node.data.key;
            });           
        },
        onClick: function (node, event) {
            if (node.getEventTargetType(event) == "title") {
                    node.toggleSelect();
                }
        },
        onKeydown: function (node, event) {
            if (event.which == 32) {
                node.toggleSelect();
                return false;
            }
        }
    });
 This tree has selecteMode set to 2 which enables multiple selections. There is no limit to the number of selections. So what if we want to limit the number of selections to say, 5? Here’s how to do it. Every time an click event occurs on the tree onClick function is called first. Right now it only toggles selection if a title is clicked (we don’t need to toggle if click event is “checkbox” because it will result a double toggle). In order to limit selections, what we have to do is get the number of already selected nodes and if it is greater than or equals to 5 simply return false. Then it will not call onSelect function which add node to selected nodes. Here is the code:
$("#dynaTree").dynatree({
        checkbox: true,
        classNames: { checkbox: "dynatree-checkbox " },
        selectMode: 2,
        children: TreeData,
        onSelect: function (select, node) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });
            var selKeys = $.map(selNodes, function (node) {
                return node.data.key;
            });           
        },
        onClick: function (node, event) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });           
            if (node.getEventTargetType(event) == "title") {
                    if (selTitles.length >= 5 ) {
                        //disable toggle if selection limit is exceeded
                        return false;
                    }                  
            }               
             else if (node.getEventTargetType(event) == "checkbox") {
// disable selection if hospital limit is exceeded
                    if (selTitles.length >= 5 ) {
                        return false;
                    }                   
               }
        },
        onKeydown: function (node, event) {
            if (event.which == 32) {
              var selNodes = node.tree.getSelectedNodes();
              var selTitles = $.map(selNodes, function (node) {
                                  return node.data.title;
                            });           
              if (selTitles.length >= 5 ) {
                 return false;
              }                   
              else{
                node.toggleSelect();
                return false;
              }
            }
        }
    });

Apart from just disabling the selections when limit exceed, we might want to toggle selection if an already selected node is clicked again so that we can uncheck one node and select another node in its place. For that, we need to check whether the clicked node is selected or not. If selected we can toggle the selection. I modified the code to enable it:
$("#dynaTree").dynatree({
        checkbox: true,
        classNames: { checkbox: "dynatree-checkbox " },
        selectMode: 2,
        children: TreeData,
        onSelect: function (select, node) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });
            var selKeys = $.map(selNodes, function (node) {
                return node.data.key;
            });           
        },
        onClick: function (node, event) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });           
            if (node.getEventTargetType(event) == "title") {
              // click on a title
                    if (selTitles.length >= 5 && !node.isSelected()) {
              //disable toggle if limit is exceeded and node is not a selected one
                        return false;
                    }                  
                     else {
                           node.toggleSelect();
                     }
            }               
             else if (node.getEventTargetType(event) == "checkbox") {
              // click on a checkbox
                    if (selTitles.length >= 5 && !node.isSelected()) {
            //disable selection if hospital limit is exceeded and node is not a selected one
                        return false;
                    }                   
               }
        },
        onKeydown: function (node, event) {
            if (event.which == 32) {
var selNodes = node.tree.getSelectedNodes();
              var selTitles = $.map(selNodes, function (node) {
                                  return node.data.title;
                            });           
              if (selTitles.length >= 5 && !node.isSelected()) {
                 return false;
              }                   
              else{
                node.toggleSelect();
                return false;
              }
            }
        }
    });



Wednesday, February 26, 2014

JQuery async-treeview with unique set to true

I’ve been working in a project which uses JQuery treeview plugin to display a set of data which are queried from a database. This projects implementation is a bit old and so is the plugin. But it showed fairly well performance until recent where we had a heavy load of data added to our database. It became extremely slow loading, updating and adding folders to structure so that we frequently got unresponsive script errors.
Basic script to load a treeview is as follows:
   $("#tree").treeview({
        collapsed: true,
        animated: "medium",
        control: "#sidetreecontrol",
        unique: true
    });

Treeview as it is, requires whole tree structure available at the client side before render. So that is a lot of js to process mostly in browsers like IE. There were two options, one was to move on to newer and more efficient plugin and other was to try to use jquery.treeview.async.js which ships with treeview plugin to load data asynchronously.
I considered the second option first and found that with this extra code I could load the tree in chunks. In other words, in initial load it only needs root folder structure and when a node get expanded sub tree is loaded sending an ajax request back to server. It looked like exactly what we were looking for. So I went ahead added relevant functionality to use jquery.treeview.async.js following this blog post.
So that is the same script with few additional parameters ‘url’ and ‘ajax’:
$("#tree").treeview({
        collapsed: true,
        animated: "medium",
        control: "#treecontrol",
        unique: true,
 url: '/Home/GetTreeData/',
        ajax: {
            type: 'post'
        }
    });

It all worked fine until I set unique: true in the treeview because that’s how it was in pervious implementation. There is only one node open at a time when this attribute is set to true. The async treeview with unique set to true is the worst nightmare we could have because it started to send ajax requests for each and every node in the same level for a single expand or collapse. This happened because JQuery treeview handles unique by toggling the all other nodes. And async treeview extends the toggle function to send ajax requests and get child nodes which results a sequence of ajax calls back and forth. So setting unique true in an async tree was definitely not an option if efficiency is what you are after.
So I found a little work around to achieve the same functionality after some research. I simply extended the toggle function to send a second request to collapse any node that is already expanded in the same level for each click. And it reduced the amount of Json calls in a considerable amount. So it works the same as unique set to true but doesn’t send unnecessary ajax requests toggling all same level nodes.
Here is the code:
$("#tree").treeview({
        collapsed: true,
        animated: "medium",
        control: "#treecontrol",
        unique: false,
 url: '/Home/GetTreeData/',
        ajax: {
            type: 'post'
        },
        toggle: function () {
            var collpsable = $(this).parent().find(".collapsable");
            var id = $(this).attr("id")
            $.each(collpsable, function (index, element) {
                if (element.id !== id) {
                    element.children[0].click();
                }
            });
        }
    });



Monday, December 2, 2013

A Simple Web Application With ASP.NET MVC - part 1

In my last post, I explained how easy it is to start web development using ASP.Net MVC with the help of different kinds of tools. So as promised I’m going to show you how to use those tools to develop a simple web application. I’m going to develop a simple student management System with a little database and few pages to edit, delete and update student details. I’m using Visual Studio 2012 and C# and I have both MVC 3 and 4 installed.
As always the first step is to create a new project. You can do that by selecting new project under files menu.



 In the left side menu, expand Installed, Templates, then Visual C# there is a ‘Web’ option listed. That is what you need to select to create a web application. When you select 'Web' VS will list a set of different templates available. You can choose any MVC version. I’m creating an MVC 3 web application, so I’m going to choose ASP.NET MVC 3 Web Application. Give a name and a location and click ok. 



Then you will be asked to select a project template.  The Internet application template provides a homepage and links to register login and log off. The empty template is better if you want to build your user interface from scratch. Since we need to understand how things work, I’m going to use that. Keep the default value for the view engine (Razor) and click ok. It will create an empty new project.



You can run the app but it will simply show a 404 error massage. If you look at the solution explorer, you can see the structure of your project. There is an APP_Start folder which contains some routing and bundling data, and a Content folder which contains CSS and themes, a Scripts folder to contain all the scripts and few others too. Among them the folders we need to work on are Models, Views and Controllers. Before that, I want you to take a look at Web.config file and Globle.asax file. Web.config file has all the configuration data, for example if we are going to connect a database to our project the connectionStrings should go in to this file and if we want to enable client side validation, this is the file we have to configure. Globle.asax is the bootstrap of our application. Everything starts with the Application_Start() method in it. Just notice it calls a method to register the routes. That’s how the server that our application runs on know how to navigate through our app. Default values in that method looks like this.



By default the controller is Home and the action is Index. Our app currently gives a 404 error massage because we still don’t have those default value in our app. So let’s go ahead and add them. Right Click on controllers folder and select Add => Controller. 



It will present a dialog box to add some values. In the controller name notice how ‘Controller’ part has automatically appended to the name. This is a must in ASP.NET MVC. Every controller must end with ‘Controller’. Let’s name it HomeContriller.  Under scaffolding options we have several templates to select from. An ‘empty controller’ will create a controller with only Index action. ‘Controller with read/write actions and views, using Entity Framework’ will create almost complete controller with all CRUD actions to your database (Like I said.. Lots of auto generation :-) ).  Since we don’t have a database yet, just select a Controller with empty read/write actions and click add. 



That option generated a bit of code (just empty methods) and we have to add method bodies later. For now let’s just run our application. Notice now we don’t get a 404, but get a different error like this.



That is because now we have created default controller and the action (i.e. Home and Index) server can navigate to ../Home/Index. What we don’t have is a view. The server looks at the places that are listed in the error massage for a matching view. It can’t find it because we haven’t created a view called Index anywhere. Creating a view in ASP.NET MVC is very easy. Right click in the controller method and select Add View.


These dialog boxes are very intelligent, they know since I’m in the Index method, I want a view called Index. View engine is Razor and I will explain what that is later. Again create strongly typed view is an option which generates a lot of code automatically. But for this time we will leave it blank and do things manually. Keep everything else as they are and click add. 


Notice how it created a new folder called Home (i.e. name of our controller) inside Views folder and added Index.cshtml file inside it. Save everything and run the app again. Now you can see there are no errors. You have a huge blank page with a large ‘Index’ header in it.


So congratulations! That’s your first web application. :-)

I didn't use any of the tools I mentioned in the last post yet. We have yet to add Entity Framework, write model classes and generate the database. For this post my main purpose was to show you how ASP.NET MVC makes it easy to create, organize and manage your code. You don’t have to wonder around thinking what goes where. If you know something is missing, you’ll know exactly where to look when you are working with ASP.NET MVC.

So I hope everything is clear. I will add some functionality to the web application in my next post.