10/25/19

App Services in Microsoft Azure : Web Apps and Web Jobs

Azure offers a set of PAAS(Platform-As-A-Service) offerings known as App Services. Web Apps and Web Jobs are two of the services under the App Services category.

Before Azure Web Apps, in order to deploy web applications built using the .Net framework, we needed an infrastructure comprising of software and hardware. For example - we needed a machine with a windows operating system, along with the .Net framework components and an IIS web server. We could scale up, but if we needed to scale out, we had to replicate this process several times.

With Web Apps we can now deploy a web application to a Web App without having to worry about setting up any of the underlying infrastructure. Our web application can be up and running in just a few minutes. We can also scale up (i.e. increase the processing power) or scale out (increase the number of instances) very easily via the Azure portal. We can also use Web App as a pre-production environment as well in order to test our application before we go live. We can also do a/b testing with one Web App instance running the production code and another Web App instance running the new features that we are testing. We can then very easily swap the existing production instance with the pre-production instance if needed.

Azure Web jobs are used for deploying batch jobs without worrying about the underlying infrastructure. An example of a batch job that can be deployed to a Web Job would be a windows service. In the past, if we developed a windows service, we needed an infrastructure similar to the web application, in order to install it and run it. With Web Jobs, we just deploy our windows service .exe file to a Web Job and everything is ready to go. Windows Services usually work in tandem with web applications so a Web Job is deployed to the same instance as the related Web App. It is also very easy to debug the Web Apps and Web Jobs.

NOTE: Web Apps and Web jobs support other platforms and languages like Java and Python and others in addition to the .Net platform.

4/14/17

Why do we need Integration Tests?

In the world of software development, every moderately complex software application will have a large code base consisting of several modules. There will be several software developers working on a given module. if you are a software developer, how would you ensure that your changes have not broken some existing functionality? How would you know if some other developer has made some changes that will end up breaking your code changes? One way is to keep testing the application 24/7 and making sure you have covered every possible use case. This is not only a preposterous but also an impossible approach to solving the problem at hand. This is exactly where Integration tests come into play. 

While developing the software application, we create integration tests for as many use cases as we can. At the very least, we need to ensure that we have tests for the core use cases, the bread and butter of the application. Once we have these tests in place, we run them before every new check-in that happens. If any of the existing tests fail, that will mean that the new changes need to reviewed before they can be checked-in. Every developer needs to make it a habit to run these tests before every check-in. 

There should also be continuous integration builds in place for the integration tests project. This will ensure that the tests will get run on different environments along the deployment cycle. This will ensure that there are no environment-specific dependencies that will cause the test to pass in one environment and fail in another. This will ensure that the tests are self-contained and can be run in any environment that we need to. If the company plans to move towards a continuous delivery model, then it becomes even more imperative that the integration tests are run during every build cycle.

Besides the functionality-breaking reasons, there is one other very important reason to have integration tests. Since the integration tests are self-contained, they are repeatable, which means they can be run over and over without causing any side effects. This is something that is not possible functionally. Let us say you are trying to troubleshoot a particular issue that requires certain data to be present. If you wanted to point your code to the application itself, then you would have to recreate the scenario and associated data every single time.This could be a very tiresome and time-consuming process that can be very frustrating. This can be compounded several times if your servers are on different machines across different networks.

With integration tests, you can simulate the issue via code on your local machine. Since the test is repeatable, the required data will need to be created only once. The test can keep creating and dropping the scenario every time it is run. This will eliminate the need to crank up the application on the web server and go through the hassle of creating data inside the application. There is no dependency on external servers and associated latency. We are not impacted if the external servers are brought down for maintenance or if the databases are refreshed.

In the process of troubleshooting the issue via integration tests, we will end up writing more and more integration tests that will remain in place once we have managed to get them to pass. This repeatable nature of integration tests makes them very powerful and valuable.

10/1/16

Designing a Vending Machine

I interact with Vending machines at work every single day, to purchase some snacks or get a drink and so on. I have always wanted to implement one just out of curiosity but never got around to doing it. Then one day I got an email from a software consulting firm asking me if i was interested in interviewing with them and if so, I should do a code exercise and send it back to them. One of the coding exercise options turned out to be a vending machine. It had a set of features that were expected. Though I had no interest in interviewing with that company, I decided that I was going to code the Vending Machine for fun anyways.

Following were the vending machine features in that coding exercise:
  • Accept Coins
    • As a vendor I want a vending machine that accepts coins So that I can collect money from the customer. The vending machine will accept valid coins (nickels, dimes, and quarters) and reject invalid ones (pennies). When a valid coin is inserted the amount of the coin will be added to the current amount and the display will be updated. When there are no coins inserted, the machine displays INSERT COIN. Rejected coins are placed in the coin return. 
    • NOTE: The temptation here will be to create Coin objects that know their value. However, this is not how a real vending machine works. Instead, it identifies coins by their weight and size and then assigns a value to what was inserted. You will need to do something similar
  • Select Product
    • As a vendor I want customers to select products So that I can give them an incentive to put money in the machine. 
    • There are three products: cola for $1.00, chips for $0.50, and candy for $0.65. When the respective button is pressed and enough money has been inserted, the product is dispensed and the machine displays THANK YOU. If the display is checked again, it will display INSERT COIN and the current amount will be set to $0.00. If there is not enough money inserted then the machine displays PRICE and the price of the item and subsequent checks of the display will display either INSERT COIN or the current amount as appropriate.
  • Make Change
    • As a vendor I want customers to receive correct change So that they will use the vending machine again.
    • When a product is selected that costs less than the amount of money in the machine, then the remaining amount is placed in the coin return.
  • Return Coins
    • As a customer I want to have my money returned So that I can change my mind about buying stuff from the vending machine.
    • When the return coins button is pressed, the money the customer has placed in the machine is returned and the display shows INSERT COIN.
  • Sold Out
    • As a customer I want to be told when the item I have selected is not available So that I can select another item.
    • When the item selected by the customer is out of stock, the machine displays SOLD OUT. If the display is checked again, it will display the amount of money remaining in the machine or INSERT COIN if there is no money in the machine.
  • Exact Change Only
    • As a customer I want to be told when exact change is required So that I can determine if I can buy something with the money I have before inserting it.
    • When the machine is not able to make change with the money in the machine for any of the items that it sells, it will display EXACT CHANGE ONLY instead of INSERT COIN.

My implementation included the following classes:

Client: This class represents the end user that will be interacting with the Vending Machine.

public class Client
    {
        public void Start()
        {
            var vm = new VendingMachineFacade(new CoinService(),new ProductService(new ProductRepository(),new ProductInventoryRepository()));

            //case 1 - invalid coins
            var response = vm.AcceptCoin(new InputCoin() { Weight = 1000, Size = 50 });
            if(response.IsSuccess == false)
            {
                //print response.Message to console
                return;
            }

            //case 2 - valid coins,return coins
            vm.AcceptCoin(new InputCoin() { Weight = 100, Size = 50 });
            vm.ReturnCoins();

            //case 3 - valid coins, invalid product code
            vm.AcceptCoin(new InputCoin() { Weight = 100, Size = 50 });
            vm.SelectProduct("COOO1");

            //case 4 - valid coins, valid product code, exact change only
            vm.AcceptCoin(new InputCoin() { Weight = 100, Size = 50 });
            vm.SelectProduct("CO1");

            //case 5 - valid coins, valid product code, less amount entered
            vm.AcceptCoin(new InputCoin() { Weight = 100, Size = 50 });
            vm.SelectProduct("CO1");

            //case 6 - valid coins, valid product code, more amount entered, make change
            vm.AcceptCoin(new InputCoin() { Weight = 100, Size = 50 });
            vm.SelectProduct("CO1");

            //case 7 - valid coins, valid product code, correct(>=) amount entered, sold out
            vm.AcceptCoin(new InputCoin() { Weight = 100, Size = 50 });
            vm.SelectProduct("CO1");

            //case 8 - valid coins, valid product code, correct(>=) amount entered, sold out, return coins
            vm.AcceptCoin(new InputCoin() { Weight = 100, Size = 50 });
            vm.SelectProduct("CO1");
            vm.ReturnCoins();
        }
    }

VendingMachineFacade :  This class represents the vending machine interface that the client will be interacting with.

public class VendingMachineFacade
    {
        private double _cost;
        private CoinService _coinService;
        private ProductService _productService;
        public VendingMachineFacade(CoinService coinService,ProductService prodService)
        {
            _coinService = coinService;
            _productService = prodService;
        }

        //behaviors
        public VendingResponse AcceptCoin(InputCoin coin)
        {
            VendingResponse response = new VendingResponse();                       

            //check if the values correspond to an accepted coin            
            var currentCoin = _coinService.GetCoin(coin.Weight, coin.Size);

            //not a valid coin
            if (currentCoin == null)
            {
                response.Message = "Insert Coin";
                response.IsRejectedCoin = true;
                response.RejectedCoin = coin; //return rejected coin
                return response;                                
            }

            //valid coin
            _cost += currentCoin.Value;
            response.Message = _cost.ToString();
            response.IsRejectedCoin = false;
            return response;
        }
        public VendingResponse SelectProduct(string code)
        {
            var response = new VendingResponse();
            
            //check if the code is valid            
            //if no, return error object with details
            var product = _productService.GetProduct(code);

            //invalid code entered
            if(product == null)
            {
                response.Message = "Invalid Product Selected. Please try again";
                response.IsSuccess = false;
                return response;
            }

            //no coins entered, but selection pressed
            if (_cost == 0)
            {
                //if exact change item, message = "exact change only"
                response.Message = "Insert Coin";
                response.IsSuccess = false;
                return response;
            }

            //entered coins less than cost
            if (_cost < product.Cost)
            {
                response.Message = string.Format("Price : {0}", product.Cost);
                response.IsSuccess = false;
                return response;
            }

            //if exact change product            
            if (_productService.IsExactChangeOnlyProduct(product) && product.Cost != _cost)
            {
                response.Message = "Exact Change Only";
                response.IsSuccess = false;
                return response;
            }

            //all good, valid code and valid amount entered
            var quantity = _productService.GetProductQuantity(code);
            if (quantity > 0)
            {
                response.Message = "Thank You";
                response.IsSuccess = true;
                _productService.UpdateProductQuantity(code);
                MakeChange(_cost - product.Cost);
                return response;
            }
            else
            {
                response.Message = "SOLD OUT";
                response.IsSuccess = false;
                return response;
            }                        
        }
        public ItemChange ReturnCoins()
        {
            return MakeChange(_cost);
        }
        private ItemChange MakeChange(double input)
        {
            ItemChange itemchange = new ItemChange();
            var change = input - _cost;
            if (change == 0) return itemchange;
            double remainingAmount = 0;

            //get the number of quarters in the remaining amount
            var quarters = (int)(change / 0.25);
            if (quarters > 0)
            {
                itemchange.NoOfQuarters = quarters;
                remainingAmount = (change - (quarters * 0.25));
                if (remainingAmount == 0) return itemchange;
            }

            var nickels = (int)(change/ 0.10);
            if(nickels > 0)
            {
                itemchange.NoOfNickels = nickels;
                remainingAmount = (change - (nickels * 0.10));
                if (remainingAmount == 0) return itemchange;
            }            

            var dimes = (int)(change / 0.05);

            if (dimes > 0)
            {
                itemchange.NoOfDimes = dimes;
                remainingAmount = (change - (dimes * 0.05));
                if (remainingAmount == 0) return itemchange;
            }
                        
            return itemchange;
        }        
        private void SoldOut(string code)
        {
            //inventory manager checks quantity
        }
        private void ExactChangeOnly() { }
    }  


InputCoin: This would represent the coin inserted by the user

 public class InputCoin
    {
        public int Weight { get; set; }
        public int Size { get; set; }
    }


CoinService :  This class provides functionality related to Coins.

  public class CoinService
    {
        private static IEnumerable AcceptedCoins = new List() { new Quarter(), new Dime(), new Nickel() };

        public Coin GetCoin(int weight, int size)
        {
            return AcceptedCoins.Where(x => x.Weight == weight && x.Size == size).FirstOrDefault();
        }
    }


ProductService :  This class provides functionality related to the actual products that can be purchased.

  public class ProductService
    {
        private ProductRepository _productRepository;
        private ProductInventoryRepository _productInventoryRepository;
        public ProductService(ProductRepository repository, ProductInventoryRepository inventoryRepository)
        {
            _productRepository = repository;
            _productInventoryRepository = inventoryRepository;
        }

        public int GetProductQuantity(string code)
        {
            var quantities = _productInventoryRepository.GetInventory();
            return quantities[code];
        }

        public Product GetProduct(string code)
        {
            return GetAllProducts().Where(x => x.Code == code).First();
        }

        public IEnumerable GetAllProducts()
        {
            return _productRepository.GetProductList();
        }

        public void UpdateProductQuantity(string code)
        {
            //this should happen in a lock to handle concurrency
            _productInventoryRepository.UpdateInventory(code);
        }

        public bool IsExactChangeOnlyProduct(Product product)
        {
            if (product.Type == ProductType.Chips) return true;
            return false;
        }
    }


ProductRepository : This class is the acts as the ORM layer for interaction with the product datasources.

 public class ProductRepository
    {
        private static List _products;
        //reader writer lock
        public virtual IEnumerable GetProductList()
        {
            if (_products == null)
            {
                _products = new List();
                _products.Add(new Product() { Code = "CO1", Type = ProductType.Cola, Cost = 1.0 });
                _products.Add(new Product() { Code = "CO2", Type = ProductType.Cola, Cost = 1.0 });
                _products.Add(new Product() { Code = "CO3", Type = ProductType.Cola, Cost = 1.0 });

                _products.Add(new Product() { Code = "CH1", Type = ProductType.Chips, Cost = 0.50 });
                _products.Add(new Product() { Code = "CH2", Type = ProductType.Chips, Cost = 0.50 });
                _products.Add(new Product() { Code = "CH3", Type = ProductType.Chips, Cost = 0.50 });

                _products.Add(new Product() { Code = "CA1", Type = ProductType.Candy, Cost = 0.65 });
                _products.Add(new Product() { Code = "CA2", Type = ProductType.Candy, Cost = 0.65 });
                _products.Add(new Product() { Code = "CA3", Type = ProductType.Candy, Cost = 0.65 });
            }

            return _products;
        }
    }
  

ProductInventoryRepository: This class is the acts as the ORM layer for interaction with the product inventory related datasources.

public class ProductInventoryRepository
    {
        private static Dictionary _productQuantities;
        public Dictionary GetInventory()
        {
            if (_productQuantities == null)
            {
                _productQuantities = new Dictionary();
                _productQuantities.Add("CO1", 10);
                _productQuantities.Add("CO2", 10);
                _productQuantities.Add("CO3", 10);

                _productQuantities.Add("CH1", 10);
                _productQuantities.Add("CH2", 10);
                _productQuantities.Add("CH3", 10);

                _productQuantities.Add("CA1", 10);
                _productQuantities.Add("CA2", 10);
                _productQuantities.Add("CA3", 10);
            }

            return _productQuantities;
        }
        public void UpdateInventory(string code)
        {
            //sorround with reader writer lock
            var currentCount = _productQuantities[code];
            if(currentCount > 0)
                _productQuantities[code]--;
        }
    }



ItemChange: This class represents the return amount


public class ItemChange
{
    public int NoOfQuarters;
    public int NoOfNickels;
    public int NoOfDimes;
}


This represents my initial thought process in regards to a Vending Machine implementation. I will continue to tweak this code as time permits and as I get better ideas,

3/13/16

Process Monitor a.k.a Procmon

Process Monitor is an advanced monitoring tool for Windows that shows real-time file system, Registry and process/thread activity. You can get more information here

A couple of months ago, I ran into a very strange issue with some data update functionality involving two separate but related applications, one a WPF client and the other a console application running as a scheduled task.

The data update happened in two ways. In the first case, the user explicitly requested for an update using one of the context menu options inside the WPF Client. In the second case, the data update request was automatically queued up by the same Client when certain state changes happened. These queued requests were then processed by the scheduled console application at a later time.The code to perform the actual data update was in a separate dll and both these applications were referencing the same dll.

What was strange was that the manual request was updating the data successfully whereas the queued up request was failing to do so.

I stepped through the code but I was not able to find anything different. so I decided to use the process monitor to troubleshoot this issue. I ran procmon and monitored the manual data update request. Procmon shows you all the activities like registry access and files being loaded. I didn't notice any assembly loading failures or any other access failures.

I then repeated the same process with the console process. In this case, I noticed that there was an assembly loading failure. The console process was trying to load a particular assembly and it wasn't able to locate it after trying several locations. Procmon shows you all the paths that the process is looking at. The assembly that the process was trying to load was missing and that was the reason for the data update failure. Once we dropped the missing dll into a specific location, the process was able to load it and the data process worked just fine.

We later found out that the install team had forgotten to include that particular dll while building their installers. Once the installer got fixed, the data update issue went away.


3/24/15

Using the Thread Pool in .NET

The Microsoft.Net framework provides a Thread Pool, which is a pool of threads available for applications to use. There is one Thread Pool per CLR and all the Application Domains managed by the CLR will have access to the threads in that Thread Pool.

The applications do not need to go through the hassle of creating and managing the threads as all that is taken care of by the Thread Pool. Using the threads in the Thread Pool is more efficient in terms of resources since the threads can be reused. Using the Thread Pool threads will also lead to an improvement in performance since the creation of threads is a time consuming operation that could negatively impact performance.

One way for applications to use the threads in the Thread Pool is to call the ThreadPool.QueueUserWorkItem method in the System.Threading namespace. This method takes a method and related parameters as input and adds an entry into the Thread Pool's global queue.


//we are adding the method ProcessCreditCard to the ThreadPool queue
System.Threading.ThreadPool.QueueUserWorkItem(ProcessCreditCard, 100);
//this method will be executed by a thread pool thread private void ProcessCreditCard(object input)
{
   //do something here
}
When a thread becomes available in the Thread Pool, it will take this entry from the queue and execute it. The drawback of using this method is that there is no way to interact with the Thread Pool thread that is executing your task. We do not know if the method completed successfully or if there were any exceptions. We also do not have the ability to get a return value from the method. To fix these limitaions Microsoft introduced the concept of Tasks.

Task is a class in the System.Threading.Tasks namespace. It provides an alternative for scheduling tasks for execution by the Thread Pool.

//create a task that will schedule a delegate(ProcessAmount) that returns a bool
 Task t1 = new Task(ProcessAmount);
//this line queues up the delegate for execution by a Thread Pool thread   t1.Start();
//we are waiting for the execution to complete   t1.Wait();
//we are printing the result from the execution   Console.WriteLine(t1.Result);
//this is the delegate that will be executed by a thread pool thread  private bool ProcessAmount()
 {
        return true;
 }
As you can see, we can schedule a task that returns a bool, wait for it to complete and then get the result back.

We also have the ability to cancel the task if necessary.

 CancellationTokenSource source = new CancellationTokenSource();
//this line queues up the delegate for execution by a Thread Pool thread Task t1 = new Task(()=>ProcessAmount(source.Token));
 t1.Start(); source.Cancel();
 private static bool ProcessAmount(CancellationToken token)   {
    //some periodic operation
   //check if the task has been cancelled,    //if yes, this method will throw an OperationCanceledException       token.ThrowIfCancellationRequested();       return true;
   }
The calling code can capture the exception thrown by the Task on cancellation and do whatever is necessary.

The System.Threading.Tasks namespace also contains a static class called Parallel that provides two methods For and ForEach.

Both of them internally use Task objects to execute the code using the Thread Pool threads

//regular For
for(int i=0;i<100 i="" p="">//do something
//Parallel's For
Parallel.For(0,100, SomeDelegate);
When we call the For method of the Parallel class, the thread pool thread's perform this task in parallel resulting in improved performance.It is ideal for situations where you want to execute a large number of tasks in parallel OR if there are long-running tasks. Few operations or short operations are not good for executing in parallel. This is also not an ideal option if the processing needs to happen sequentially since the Thread Pool threads execute in no particular order. This option is also not ideal if the operations share some data since this would require some kind of synchronization that will negatively impact the performance.

Parallel.ForEach and Parallel.Invoke also work similarly.

Parallel LINQ

When dealing with collections via LINQ, we can use Tasks(a.k.a the Thread Pool threads) to execute the operations on the collections in parallel in order to improve performance. This is possible via the AsParallel method of the System.Linq.ParallelEnumerable class. This method can be used to convert sequential queries based on IEnumerable or IEnumerable to parallel queries as follows:

var filteredList = GetItems.AsParallel().where(//do some filtering here);
private IEnumerable GetItems()
{

   //return a list
}
As is the case with Parallel.For and Paralle.ForEach and Parallel.Invoke, Parallel LINQ is ideal for situations where you want to execute a large number of tasks in parallel OR if there are long-running tasks. Few operations or short operations are not good for executing in parallel. This is also not an ideal option if the processing needs to happen sequentially since the Thread Pool threads execute in no particular order. This option is also not ideal if the operations share some data since this would require some kind of synchronization that will negatively impact the performance.

(Reference: CLR via C# by Jeffrey Richter)

4/19/14

Traits in Scala

Scala is a popular programming language that combines the best features of object-oriented and functional programming languages. It has some really cool features that are not available in other languages like C# or Java. Traits is one such feature that provides a viable solution for the problems associated with multiple inheritance in other languages.

Multiple inheritance is not allowed in Java/C# and the only other way to build common functionality among a set of related classes is via interfaces. But interfaces are abstract and require concrete implementation. The other option is to create a class that implements the desired interfaces and then inherit from that class. This is not very convenient.

Following are some of the cool features of a trait:
  • A Trait is much like an abstract class in C#. It can contain abstract members as well as concrete implementations
  • A Trait can contain abstract fields as well as concrete fields
  • A class in Scala can only have one base class but it can implement any number of Traits. So a lot of concrete implementations are readily available for use. 
  • A Trait can extend other Traits.
  • A Trait can extend other classes
  • An instance of a class can implement a Trait. So, not the class, but the desired instances of that class can implement Traits as needed. 
Following are some code samples of Traits:

An abstract Trait called Runner that has an abstract method called Run

trait Runner
{
   def Run(destination:String) //a string input param called "destination"

}


A class called Athlete that provides the implementation for the Trait:
class Athlete extends Runner
{
  //override keyword is not necessary while implementing an abstract method of a trait
  def Run(destination:string) {println(destination)}
}


A concrete Trait called Runner that has a concrete method called Run
trait Runner
{
  def Run(destination:String)  //a string input param called "destination"
  {
    println(destination)

   }
}


A class called Athlete that implements the Trait and calls the Run method. In Scala slang "The Runner functionality is mixed in with the Athlete class"
class Athlete extends Runner { def PrintDestination(destination:String) { Run(destination); } }


A trait called MarathonRunner that extends the trait Runner

trait MarathonRunner extends Runner
{
  def PrintMarathonDestination(destination:String)
  {
   Run(destination)
   }
}


A class called Athlete that implements both Runner and MarathonRunner
class Athlete extends Runner with MarathonRunner { }
NOTE : In Scala, the first trait is implemented using the extends keyword and the second trait is implemented using the with keyword


Let us say that there is a trait called HalfMarathonRunner, an instance of the class Athlete can implement this trait:
val objAthlete = new Athlete with HalfMarathonRunner


A trait with an abstract field
trait Runner
{
 val MaxDistance:int //no initial value means abstract
}


a trait with a concrete field
trait Runner
{
  val MaxDistance = 15
}

2/9/14

Randomizing Display Ads

I was working on the home page of a website that had a small area on the top right corner that was set aside for advertisements. The real-estate had to be shared by four different Ads provided they satisfied the criteria for display. Each had a different criteria that determined their eligibility for display. Criteria included the logged-in user's age, postal code and gender.

So it was possible that at any given time there could be one, two, three or four Ads eligible for display.Then the Ads that were eligible for display had to be randomized to ensure that each had an equal likelihood of appearing on the page.

The model for the page was as follows:


 public class MyHomeModel
  {
   public bool ShowNexusAd {get;set;}
   public bool ShowIpadAd {get;set;}
   public bool ShowSurfaceAd {get;set;}
   public bool ShowKindleAd {get;set;}
  }


So when we returned the model to the view, each of the properties had to have a value of true or false, that would be used in the view to determine whether to hide or show the particular Ad as follows:

@if(model.ShowNexusAd)
{
  //show Nexus Ad
}


For randomization, I decide to use the Random class in .NET to generate a random number in a specified range (1-9) and then use the value generated to determine which ad to show. The code would like this:

if(ShowNexusAd && ShowIpadAd && ShowSurfaceAd && ShowKindleAd)
{
   //generate a number between 1 and 9(including 1)
   Random randomNumber = new Random(1,9) 
   if(randomNumber <=2)
      ShowNexusAd = true;
   if(randomNumber >2 && randomNumber <=4)
      ShowIpadAd = true;
   if(randomNumber >4 && randomNumber <=6)
      ShowSurfaceAd = true;
   if(randomNumber >6 && randomNumber <=8)
      ShowKindleAd = true;
}


But there is a problem here.......

what if only three of the ads were eligible for display or two or just one? we would end up with code as follows:
if(ShowNexusAd && ShowIpadAd && ShowSurfaceAd && ShowKindleAd)

{
 Random randomNumber = new Random(1,9)
 if(randomNumber <=2) 
  ShowNexusAd = true;
 if(randomNumber >2 && randomNumber <=4) 
  ShowIpadAd = true;
 if(randomNumber >4 && randomNumber <=6) 
  ShowSurfaceAd = true;
 if(randomNumber >6 && randomNumber <=8) 
  ShowKindleAd = true;
}else
if(ShowNexusAd && ShowIpadAd && ShowSurfaceAd )
{
 Random randomNumber = new Random(1,7)
 if(randomNumber <=2) 
  ShowNexusAd = true;
 if(randomNumber >2 && randomNumber <=4) 
  ShowIpadAd = true;
 if(randomNumber >4 && randomNumber <=6) 
  ShowSurfaceAd = true;
}else
if(ShowNexusAd && ShowIpadAd && ShowKindleAd)

{
 Random randomNumber = new Random(1,7)
 if(randomNumber <=2) 
  ShowNexusAd = true;
 if(randomNumber >2 && randomNumber <=4) 
  ShowIpadAd = true;
 if(randomNumber >4 && randomNumber <=6)
  ShowKindleAd= true;
}
.......................and so on with all the possible permutations and combinations

As the number of Ads increase(or even for the existing four Ads) it will become a nightmare to extend this logic and even maintain it. So how do we make the code smart enough to handle this?

I hit upon the following idea(which might not be the greatest idea, but is pretty decent)

I created the following classes:

public abstract class AdDisplayBase
{
 public MyHomeModel ViewModel { get; set; }
 public abstract bool ShowAd { set; }
}

public class NexusAdDisplay : AdDisplayBase
{
 public override bool ShowAd
 {
  set { ViewModel.ShowNexusAd = value; }
 }
}

public class IpadAdDisplay : AdDisplayBase
{
 public override bool ShowAd
 {
  set { ViewModel.ShowIpadAd = value; }
 }
}

public class SurfaceAdDisplay : AdDisplayBase
{
 public override bool ShowAd
 {
  set { ViewModel.ShowSurfaceAd = value; }
 }
}

public class KindleAdDisplay : AdDisplayBase
{
 public override bool ShowAd
 {
  set { ViewModel.ShowKindleAd = value; }
 }
}

My goal was to convert the simple value types(the boolean properties) into reference types, so that I could treat them as objects. This would enable me to add the objects to a collection and handle them in a generic manner. To achieve this, I created an abstraction around the boolean properties by creating a class for each type of Ad.

I then refactored the unmanageable conditional logic above to the following method:

void ManageAdsDisplay(MyHomeModel model)
{
  int randomNum;
  var lstAdsToDisplay = new List();

  if (model.ShowNexusAd ) 
     lstAdsToDisplay.Add(new NexusAdDisplay () { ViewModel = model });
  if (model.ShowIpadAd ) 
     lstAdsToDisplay.Add(new IpadAdDisplay () { ViewModel = model });
  if (model.ShowSurfaceAd ) 
     lstAdsToDisplay.Add(new SurfaceAdDisplay () { ViewModel = model });
  if (model.ShowKindleAd ) 
     lstAdsToDisplay.Add(new KindleAdDisplay () { ViewModel = model });
  
  switch (lstAdsToDisplay.Count)
  {
    case 1:
 lstAdsToDisplay[0].ShowAd = true;
 break;
    case 2:
 randomNum = new Random().Next(1, 9);
 lstAdsToDisplay[0].ShowAd = (randomNum <= 4);
 lstAdsToDisplay[1].ShowAd = (randomNum > 4);
 break;
   case 3:
 randomNum = new Random().Next(1, 10);
 lstAdsToDisplay[0].ShowAd = (randomNum <= 3);
 lstAdsToDisplay[1].ShowAd = (randomNum > 3 && randomNum <= 6);
 lstAdsToDisplay[2].ShowAd = (randomNum > 6 && randomNum <= 9);
 break;
  case 4:
 randomNum = new Random().Next(1, 9);
 lstAdsToDisplay[0].ShowAd = (randomNum <= 2);
 lstAdsToDisplay[1].ShowAd = (randomNum > 2 && randomNum <= 4);
 lstAdsToDisplay[2].ShowAd = (randomNum > 4 && randomNum <= 6);
 lstAdsToDisplay[3].ShowAd = (randomNum > 6 && randomNum <= 8);
 break;
  }
}

By doing this we avoid the need to write complicated and confusing conditional statements and it is pretty easy to extend this design if there are more Ads in the future. To be honest, I am not completely happy with the Switch/Case part of the solution and I am trying to find a better way to do this. It will definitely end up as another blog post if I do.