# Soft Cero

Dudas y aportes al desarrollo de software

## 19/9/17

### The n-Queens Completion problem

Today I've just seen this unsolved problem, and, as every problem I see, I try to solve it, at least once.

Problem says: "If some queens have already been placed on the n-by-board, can you find a solution to the n-Queens puzzle without moving any of those queens?"..."What would be necessary would be either a proof that there is an algorithm that can solve the n-Queens Completion puzzle in polynomial time, or a proof that no such algorithm exists."

The solution is :such algorithm does not exist.

Let me explain why, by using a 8x8 board.
The "some" word in the problem says that I could use any number of queens <= n. I would say < n, because if not, the problem is already solved.

We can get a board like this, with 7 queens already in there.

10000000
00000100
00000001
00001000
01000000
00010000
00000000
00000010

So, as the queens cannot be moved, there is no way to put the 8th queen to solve it. So, we've found at least one problem that has no solution.

Next, you cannot create an algorithm to find a solution that you already know (with a 100% of certainty) it does not exist, so, such algorithm does not exist.

I think I won the million dollar, didn't I?

A very different (and more difficult) challenge would be to find out how many queens (and in what positions they should be) to determine if the problem can be solved or not.

## 13/9/17

### Base Repository

I'm gonna put here my implementation for a base repository class, with some adds, like the "WhereParam" class, that, working with the "IQueryableHelper" one, allow to build complex queries with strings (ideal for javascript clients). (Blogger does not support such amount of code, so, I'm putting this a plain text)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace TestApp.Repositories
{
public enum SortingOrder
{
Ascending, Descending
}

public class BaseRepository : IDisposable
where T : class, new()
{

private DbContext _model;
private IQueryable _query;

public BaseRepository(DbContext model)
{
_model = model;
_model.Configuration.ProxyCreationEnabled = false;
_query = _model.Set().AsQueryable();
}

public BaseRepository Include(Expression> include)
{
_query = _query.Include(include);
return this;
}

#region "-------------------Typed List------------------------"

public async Task> GetAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return await _query.ToListAsync(cancellationToken);
}

public async Task> GetAsync(Expression> where = null, Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
{
BuildQuery(where, orderby, sortingOrder);
return await _query.ToListAsync(cancellationToken);
}

public async Task> GetAsync(Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAsync(null, orderby, sortingOrder, cancellationToken);
}

public async Task> GetAsync(Expression> where = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await GetAsync(where, null, SortingOrder.Ascending, cancellationToken); //using "int", but could use any type, as it is not supposed to be used.
}

#endregion

#region "-------------------Typed First------------------------"

public async Task FirstAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return await _query.FirstOrDefaultAsync(cancellationToken);
}

public async Task FirstAsync(Expression> where = null, Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
{
BuildQuery(where, orderby, sortingOrder);
return await _query.FirstOrDefaultAsync(cancellationToken);
}

public async Task FirstAsync(Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
{
return await FirstAsync(null, orderby, sortingOrder, cancellationToken);
}

public async Task FirstAsync(Expression> where = null, CancellationToken cancellationToken = default(CancellationToken))
{
return await FirstAsync(where, null, SortingOrder.Ascending, cancellationToken); //using "int", but could use any type, as it is not supposed to be used.
}

#endregion

//#region "-------------------Dynamic List----------------------" // needs reference to assembly EntityFramework.Extended

/////
///// This method returns a list of anonymous objects if the properties specified in the parameter match those in the Entity
/////
/////
/////
/////
/////
/////
/////
///// List
//public async Task> SelectAsync(string[] properties, Expression> where = null, Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
//{
//    BuildQuery(where, orderby, sortingOrder);
//    return await _query.Select("new (" + string.Join(",", properties) + ")").ToListAsync(cancellationToken);
//}

/////
///// This method returns a list of anonymous objects if the properties specified in the parameter match those in the Entity
/////
/////
/////
/////
/////
/////
///// List
//public async Task> SelectAsync(string[] properties, Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
//{
//    return await SelectAsync(properties, where: null, orderby, sortingOrder, cancellationToken);
//}

/////
///// This method returns a list of anonymous objects if the properties specified in the parameter match those in the Entity
/////
/////
/////
/////
/////
///// List
//public async Task> SelectAsync(string[] properties, Expression> where = null, CancellationToken cancellationToken = default(CancellationToken))
//{
//    return await SelectAsync(properties, where, null, SortingOrder.Ascending, cancellationToken); //using "int", but could use any type, as it is not supposed to be used.
//}

//#endregion

//#region "-------------------Dynamic First----------------------" //// needs reference to assembly EntityFramework.Extended

/////
///// This method returns an anonymous object if the properties specified in the parameter match those in the Entity
/////
/////
/////
/////
/////
/////
/////
///// List
//public async Task SelectFirstAsync(string[] properties, Expression> where = null, Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
//{
//    BuildQuery(where, orderby, sortingOrder);
//    return await _query.Select("new (" + string.Join(",", properties) + ")").FirstOrDefaultAsync(cancellationToken);
//}

/////
///// This method returns an anonymous object if the properties  specified in the parameter match those in the Entity
/////
/////
/////
/////
/////
/////
///// List
//public async Task SelectFirstAsync(string[] properties, Expression> orderby = null, SortingOrder sortingOrder = SortingOrder.Ascending, CancellationToken cancellationToken = default(CancellationToken))
//{
//    return await SelectFirstAsync(properties, null, orderby, sortingOrder, cancellationToken);
//}

/////
///// This method returns an anonymous objects if the properties specified  in the parameter match those in the Entity
/////
/////
/////
/////
/////
///// List
//public async Task SelectFirstAsync(string[] properties, Expression> where = null, CancellationToken cancellationToken = default(CancellationToken))
//{
//    return await SelectFirstAsync(properties, where, null, SortingOrder.Ascending, cancellationToken); //using "int", but could use any type, as it is not supposed to be used.
//}

//#endregion

#region "-------------------Typed List and First with WhereParams----------------------"

public async Task> GetAsync(List whereParams, CancellationToken cancellationToken = default(CancellationToken))
{
_query = _query.Where(whereParams);
return await _query.ToListAsync();

}

public async Task FirstAsync(List whereParams, CancellationToken cancellationToken = default(CancellationToken))
{
_query = _query.Where(whereParams);
return await _query.FirstOrDefaultAsync();
}

#endregion

#region "-------------------Typed PageResult with PageParameters----------------------"

public async Task> GetAsync(PageParameters pageParameters, CancellationToken cancellationToken = default(CancellationToken))
{
var queryItems = _query
.Where(pageParameters.WhereParams)
.OrderBy(pageParameters.SortParams)
.Skip(pageParameters.PageIndex * pageParameters.PageLength)
.Take(pageParameters.PageLength);

var queryCount = _model.Set()
.Where(pageParameters.WhereParams);

return new PageResult
{
PageIndex = pageParameters.PageIndex,
PageLength = pageParameters.PageLength,
Items = await _query.ToListAsync(cancellationToken),
Total = await queryCount.CountAsync(cancellationToken)
};

}

#endregion

#region "-----------------------------------CUD------------------------------------------"

{
return await _model.SaveChangesAsync(cancellationToken);

}

public virtual async Task UpdateAsync(T entity, CancellationToken cancellationToken = default(CancellationToken))
{
_model.Entry(entity).State = EntityState.Modified;
return await _model.SaveChangesAsync(cancellationToken);
}

public async Task Delete(Expression> where, CancellationToken cancellationToken = default(CancellationToken))
{
T entity = await this.FirstAsync(where, cancellationToken);
if (entity != null)
{
_model.Set().Remove(entity);
return await _model.SaveChangesAsync(cancellationToken);
}

return 0;
}

#endregion

public void BuildQuery(Expression> where = null, Expression> orderBy = null, SortingOrder sortingOrder = SortingOrder.Ascending)
{
if (where != null)
_query = _query.Where(where);
if (orderBy != null)
{
if (sortingOrder == SortingOrder.Ascending)
_query = _query.OrderBy(orderBy);
else
_query = _query.OrderByDescending(orderBy);
}
}

public void Dispose()
{
_model.Dispose();
}
}

public class PageParameters
{
public PageParameters()
{
this.PageIndex = 0;
this.PageLength = 15;
this.WhereParams = new List();
this.SortParams = new List();

}

public int PageIndex { get; set; }
public int PageLength { get; set; }
public List WhereParams { get; set; }
public List SortParams { get; set; }

}

public class PageResult
{
public List Items { get; set; }
public int PageIndex { get; set; }
public int PageLength { get; set; }
public int Total { get; set; }
}

public class WhereParam
{
public WhereParam()
{

}

public WhereParam(string propertyName, string Operator, List values = null, bool includeNull = false)
{
this.PropertyName = propertyName;
this.Operator = Operator;
this.Values = values;
this.IncludeNull = includeNull;
}

public string PropertyName { get; set; }
public string Operator { get; set; }
public List Values { get; set; }
public bool IncludeNull { get; set; }
}

public class SortParam
{
public string PropertyName { get; set; }
public SortingOrder SortingOrder { get; set; } //"Desc" or anything else
}

public static class IQueryableHelper
{
#region "Where"
public static IQueryable Where(this IQueryable source, List whereParams)
{
if (whereParams == null)
return source;

whereParams.RemoveAll(x => string.IsNullOrEmpty(x.PropertyName));

if (whereParams.Count > 0)
{
foreach (var wp in whereParams)
source = source.Where(wp.PropertyName, wp.Operator, wp.Values, wp.IncludeNull);
}
return source;
}

public static IQueryable Where(this IQueryable source, string property, string comparerOperator, List values, bool includeNull = false)
{
return source.Where(WhereExp(property, comparerOperator, values, includeNull));
}

public static IQueryable Where(this IQueryable source, string property, string comparerOperator, string value, bool includeNull = false)
{
if (value == null)
throw new Exception("No value to compare");
return source.Where(WhereExp(property, comparerOperator, new List { value }, includeNull));
}

public static IQueryable Where(this IQueryable source, string property, string comparerOperator, string[] values, bool includeNull = false)
{
return source.Where(WhereExp(property, comparerOperator, values.ToList(), includeNull));
}

public static IQueryable Where(this IQueryable source, Expression> propertyExpression, string comparerOperator, string[] values, bool includeNull = false)
{

return source.Where(WhereExp((propertyExpression.Body as MemberExpression).Member.Name, comparerOperator, values.ToList(), includeNull));
}

static Expression> WhereExp(string property, string comparerOperator, List values, bool includeNull = false)
{
if (values.Count == 0)
throw new Exception("No values to compare");

ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
Expression expression = CompareExpression(property, comparerOperator, values[0], parameter);

for (int i = 1; i < values.Count; i++)
{
Expression expression_i = CompareExpression(property, comparerOperator, values[i], parameter);
expression = Expression.OrElse(expression, expression_i);
}

if (includeNull)
{
Expression propertyEntity = Expression.Property(parameter, property);
ConstantExpression constantNull = Expression.Constant(null);
BinaryExpression comparisonNulll = Expression.Equal(propertyEntity, constantNull);
expression = Expression.OrElse(expression, comparisonNulll);
}

return Expression.Lambda>(expression, parameter);
}

private static Expression CompareExpression(string property, string comparerOperator, string value, ParameterExpression parameter)
{
Expression propertyEntity = Expression.Property(parameter, property);

var valueConverted = TypeDescriptor.GetConverter(propertyEntity.Type).ConvertFromString(value);
Expression target = Expression.Constant(valueConverted, propertyEntity.Type);

Expression finalExpression = null;

if (comparerOperator == "Equals" || comparerOperator == "=")
{
finalExpression = Expression.Equal(propertyEntity, target);
}
else if (comparerOperator == ">" || comparerOperator == "GreatherThan")
{
finalExpression = Expression.GreaterThan(propertyEntity, target);
}
else if (comparerOperator == "<" || comparerOperator == "LessThan")
{
finalExpression = Expression.LessThan(propertyEntity, target);
}
else if (comparerOperator == ">=" || comparerOperator == "GreatherThanOrEqual")
{
finalExpression = Expression.GreaterThanOrEqual(propertyEntity, target);
}
else if (comparerOperator == "<=" || comparerOperator == "LessThanOrEqual")
{
finalExpression = Expression.LessThanOrEqual(propertyEntity, target);
}
else if (comparerOperator == "Contains" || comparerOperator == "like")
{
finalExpression = Expression.Call(propertyEntity, typeof(string).GetMethod("Contains"), target);
}
else
throw new Exception("No valid operator: " + comparerOperator);
return finalExpression;
}

public static IQueryable Where(this IQueryable query, List whereParams, List sortParams)
{
if (whereParams != null)
query = query.Where(whereParams);
if (sortParams != null)
query = query.OrderBy(sortParams).AsQueryable();

return query;
}

// ------------------------  needs reference to assembly EntityFramework.Extended
//public static IQueryable Where(this IQueryable query, List whereParams, List sortParams, string[] columns)
//{
//    if (columns == null || columns.Length == 0)
//        throw new Exception("No columns specified");
//    if (whereParams != null)
//        query = query.Where(whereParams);
//    if (sortParams != null)
//        query = query.OrderBy(sortParams).AsQueryable();

//    return query.Select("new (" + string.Join(",", columns) + ")");
//}

#endregion

#region "OrderBy"

public static IOrderedQueryable OrderBy(this IQueryable source, string sortExpression)
{
return source.OrderBy(new List { sortExpression });
}

public static IOrderedQueryable OrderBy(this IQueryable source, List sortParams)
{
if (sortParams == null || sortParams.Count == 0)
return source as IOrderedQueryable;

var sortParamsAsList = new List();
foreach (var s in sortParams)
sortParamsAsList.Add(s.PropertyName + (s.SortingOrder == SortingOrder.Ascending? " asc ": "desc"));
return source.OrderBy(sortParamsAsList);
}

public static IOrderedQueryable OrderBy(this IQueryable source, List sortExpressions)
{
IOrderedQueryable orderedQueryable;
var propAndOrder = sortExpressions[0].Split(' ');
string property = propAndOrder[0];
if (propAndOrder.Length > 1 && propAndOrder[1].ToLower().Contains("desc"))
orderedQueryable = ApplyOrder(source, property, "OrderByDescending");
else
orderedQueryable = ApplyOrder(source, property, "OrderBy");

for (int i = 1; i < sortExpressions.Count; i++)
{
propAndOrder = sortExpressions[i].Split(' ');
property = propAndOrder[0];
if (propAndOrder[1].ToLower().Contains("desc"))
orderedQueryable = ThenByDescending(orderedQueryable, property);
else
orderedQueryable = ThenBy(orderedQueryable, property);
}
return orderedQueryable;
}

public static IOrderedQueryable ThenBy(this IOrderedQueryable source, string property)
{
return ApplyOrder(source, property, "ThenBy");
}
public static IOrderedQueryable ThenByDescending(this IOrderedQueryable source, string property)
{
return ApplyOrder(source, property, "ThenByDescending");
}
static IOrderedQueryable ApplyOrder(IQueryable source, string property, string methodName)
{
ParameterExpression arg = Expression.Parameter(typeof(T), "x");
Expression expr = arg;
foreach (string prop in property.Split('.'))
{
// use reflection (not ComponentModel) to mirror LINQ
expr = Expression.PropertyOrField(expr, prop);
}
Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), expr.Type);
LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

return (IOrderedQueryable)
typeof(Queryable).GetMethods().Single(
method => method.Name == methodName
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), expr.Type)
.Invoke(null, new object[] { source, lambda });
}

#endregion

}
}

As example, this REST API endpoint would use it...

```        [Route("api/VendorsPage")]
[HttpGet]
public async Task GetVendorsPageAsync([FromUri]PageParameters pageParameters, CancellationToken cancellationToken = default(CancellationToken))
{
try
{
return Ok(await vendorRepository.GetAsync(pageParameters, cancellationToken));
}
catch (Exception ex)
{

return InternalServerError(ex);
}
}```

...that would be consumed with a client like javasript in this way.

```        function getPage()
{
var pageParams = {
PageIndex: 0,
PageLength: 20,
WhereParams: [
{
PropertyName: 'VendorId',
Operator: '=',
Values: [1,2,3], //will bring Vendor Ids = 1 OR 2 OR 3
IncludeNull: false, //Not intereseted in null values for VendorId fields
}
// if you need to build an AND condition, you can add more whereParam type objects
],
SortParams: [{
PropertyName: 'VendorId',
SortingOrder: 0 //0 means ascending
}
// If you need to sort by more than one column, you can add more sortParam type objects
]
};

\$.get('/api/VendorsPage', pageParams)
.done(function (response) {
//Do whathever is needed ;
}).fail(function (a, b, c) {
debugger;
});
}```

## 24/4/14

### Two different reasons to be a Technical Leader

I was talking with a colleague, ten years older than me, about what a technical leader (TL) should do, and I was wondered of how different we think.

As usual, I started digging into his arguments, to find where my information (or his) was wrong, to find the cause of the gap in the concepts.

We talked how we started in IT. We both did almost the same path: Assembling machines, administrating servers, fixing data, fixing applications, creating applications.

Suddenly, he said "I was a programmer, receiving the specifications from the functional analyst, but I quit programming, I needed to evolve".

I could heard a huge "crack" inside my head. There it was! The source of the difference!

But first, let's talk a bit about how "programming role concepts" evolved

He was talking about the "functional analyst" and "programmer" roles.

This difference sounded too old for me, but he was talking about them as if they were very actual.

For me, from the beginning of my career I never could understand why these roles were separated. To create a program, there is a big component that is personal. Like painting a picture. How is it possible that you paint something someone else saw? By painting following instructions there is a big chance the result is not what the instructor was told that someone else (the business) saw. No matter how good painter you are.

The functional analyst, a guy who usually didn't know about the business, nor programming, was an unnecessary intermediary, and, within my experience, it was the main factor to explain why a lot of software projects failed. And the time gave me the reason: One of the Agile pillars is that the customer must be in the developers team, showing them constantly the reality, so they can paint it. A user story is not a set of instructions, it is an agreement on how the customer and the developers sees the reality. The paintings now, are pretty much closer to the reality than years ago, aren't they?

Nowadays, the programmer talks to the business. Where is the functional analyst? it's the programmer that plays that role as well. It could be  something like: Programmer + Analyst = Developer.

But this is not that clear to everyone. To my colleague, he still have this roles separated in his mind, and he never took the opportunity to see if this reality had changed. Why would he? He was not in that place any more anyway.

Because he had stopped coding, to evolve. This is the main clue to understand where he was standing.

When he decided to become a "functional analyst" he left the "software creation" path. He assumed that he already knew how to program, and he could no learn anything else. He could not evolve there.

But, couldn't he? Software Engineering has been evolving for years, and still it is. Why he could not? The answer is pretty simple: He was not interested in.

And this is a common pattern. People who made the same path, maybe driven by circumstances, but not choosing to be there, or loosing the interest in the way, but still stuck in the job. They are there, just waiting for the opportunity to leave, to "evolve". (This evolving excuse is a very common one I've heard several times.)

Now, what happens in a corporation, when you have a lot of people doing technical stuff, but thinking on stopping doing it as soon as possible? What happens when you have developers that are doing their job in its minimal expression, just waiting to become a supervisor or a manager? In other words, what happens when you have people doing what they don't feel passionate about?

For them, it is the same to repeat hundred of lines of code instead of encapsulating. Because, it's easier to copy and paste than refactoring. Some of them don't even know what that word means. The excuse is "it's faster to do this way"

For them, writing a store procedure that does everything is better than thinking on separateness of concerns. The excuse is "it is faster to do this way".

For them, hardcoding code is better than thinking on ways to make the program more flexible. The excuse is "it is faster to do this way".

The excuse is always the same . They say the want to do it faster, but what they really want is to do it with the less possible effort. Because, if they tried to do it better, it would mean that they would be spending time doing something they don't love to.

And these people, eventually will reach a higher position. Predicating their lack of interest, that will be heard and followed by other employees. Increasing the technical debt.

Here relies the main difference of what my colleague and I think about the technical lead duties: I want to be a TL to teach people to love what they are doing, the same way I do. He wants to be a TL because he wants to stop doing what he is doing now.

## 2/12/13

### Movie: Responsive Web (comedy)

I've been reading about Single Page Applications concept. This is a "new and revolutionary" concept, as it pretends to make web applications more responsive for the user.
Now, I'm wondering what is "more responsive".

To answer this, let me go back in the time. I won't go through the History of Programming languages, but I'll go to when the Web Development started.

We started to do "pages" when internet became popular. And the reason was, mainly, to allow business to sell products and services online to the customers.
The dot-com bobble was starting. You could hear everywhere that if you were not in internet, you didn't exist. And, of course, companies needed technical people to take them to internet: the web designers (at that time, the pages were statics). The demand was very high, and suddenly, there were more designers than desktop programmers in the market.

But, modifying a page each time a change was needed, was not good. The constant maintenance was a pain, for the business and for designers.

That's when IT companies, started to sell the "dynamic pages". Pages that were modified in the server before they were served.
Of course, to do this, you needed to tell the server how, and that's where specific languages and technologies came to the field. If you was a web designer, you needed to learn these languages, so, you could be a web developer.

Some of these languages were PHP and ASP. At that time, I was a desktop developer. I never thought this "web thing" would ever replace my "very responsive" desktop applications. But as every geek, I was looking at that other world very closely.

Suddenly, something went wrong. Dot-com bubble exploded, and all these developers started to join the companies they had been working for. The applications exposed to internet were still there, but the demand was low now. The companies, started to need, again, internal applications to manage their business. But they were full of these web developers... and if all you have is a hammer, every problem is a nail.

The web developers were that much, that soon you could not talk about desktop applications. They, helped by the IT companies (remember the publicity of the Browsers war) sold to the business that web apps was the future. And the companies bought it.

But, there were some problems.
1) Web is stateless, so, you needed some tricks to maintain the status of the page (most of the time, using hidden fields, maintained manually, even Microsoft created the Viewstate... which was another headache)

2) Responsiveness:  Users were used to work with very responsive desktop applications (most of them, working with mainframe terminals, DOS+xBase, or some old good apps made with Visual Basic 6) , started to ask the same to these web applications. But the apps, were not designed for that... because the protocol they were running (HTTP) was not designed for that either. When the client needed to send data to the server, the whole page was redrawn. I still remember myself waiting 12 seconds looking at a white screen to get a response.
Why would a user need to see 200 records at the same time? Just because he could do that with his old desktop app?  No way! This new web application is not wrong, the user is!. He is working wrong and he has to learn that now he will need to filter better and paginate the results.

Desktops apps never had these problems.

Meanwhile the world, with the Web 2.0, was selling the web as the silver bullet, the developers were used to solve the web development problems, to live with them, and to convince everyone those where not problems at all, but features.

There was a little star in the sky, it was Flash. But, the fans of the web, didn't like it, because compared to writing text, real programming was too hard. Also, Microsoft tried to introduce  Silverlight, getting the best from both worlds (web apps availability and desktop responsiveness), but the open and standard web wave was too big (Quickly Microsoft understood that instead of fighting, it was better to mount it, becoming one of the promoter of HTML 5)

Some more ingenious developers, started to work within the client side, to do little things in the browser. Of course, at the beginning it was clandestine, not standard... but hey, this solve those inexistent problems! That was the beginning of AJAX. (which had the AJAX frameworks war itself)

Now, we have a salad made with server side code, html (and its DOM), javascript and XML.

The apps are not responsive enough though. So, let's season the salad with some condiments. Let's add  new techno-patches like Jquery, Knockout.js, Json, Node.js, Angular.js, and God knows what else.

Yes, now we have Single Page Applications.

The apps are becoming more complex than ever. And they will be more complex even. The internet of things is almost there.

And the effort to develop and maintain this apps is huge, compared to do the same with desktop applications. And of course, the responsiveness of the web, will never be the same than the desktop one: web transmits text, desktop transmits binary.

The users are being changed. The old people is retiring, and the new employees are used to the web. They don't mind to wait a half a second to get the result. They don't know it could be much faster.

End of the story.

Trailer for the second part: There is coming an age, where the amount of data is unbelievable. That half second could become half an hour easily. When that time arrives, will we start to use the right tools to do the job, or will we still be selling that the low responsiveness is normal and what is wrong is the amount of data?

## 1/10/13

### Call yourself a programmer, if you want to.

First, I recommend to read this article called "Don't  call yourself a programmer" (or you can just read the resume in the lines below)

It says that business is  divided in two big areas: Profit Center (part of the business that generates money) and Cost Center  (a necessary waste), and that engineers should be attached to the first one, either adding revenues or reducing costs.

I agree. Add revenue or reduce cost. It's a simple rule.

And then, he says that "“Programmer” sounds like “anomalously high-cost peon who types some mumbo-jumbo into some other mumbo-jumbo.”

And I deeply disagree.

If you've decided to create a piece of software because this will add value to the business, then the added value must be greater than the costs of creating it.

So, how we increase the added value? This is what our leaders are trying to teach us: "Know the business", "Think in their processes", "We are here for the business", "The new vision", etc., etc.

But also, we could try to decrease costs.

What are these costs?
Several. But one of the most important is the maintenance costs. In average the 60% of all the costs in the software life cycle (from an IEEE Software's article: "Frequently Forgotten Fundamental Facts about Software Engineering")

How could you reduce it?
Focusing in the quality of the software. The bigger the quality, the less maintenance effort needed.

And how could you get that high quality?
Directly from the people. But not any kind of people. Programmers, developers. Technical people.

What's the point of creating new programming languages, techniques and tools for different activities of the software life cycle, design patterns, frameworks, conventions, etc. etc.? It's to increase software quality, and so for to reduce costs!

And these are only learnt by programmers. So, you need them.

Call yourself a programmer, if you want to. You will be a valuable asset for any company leaded by smart people.

## 22/2/13

### Evolution?

A: I use TCP to communicate computers.

B: TCP! But it has no standarized message format, and it is not human readable! What if I need to communicate with your computer? Should I learn your language?

A: Well... if you want to communicate with me, then yes.

B: That's not acceptable. Hold on, I will make something awesome.

-- Time later

B: Here, let me introduce HTTP. It's a protocol over TCP, where anyone can read the message!

A: Isn't it to allow browsers to request HTML to display pages?

B: Yes, but we can use it for other things, like communicate our computers! It's perfectably readable by any human...

A: But I don't want to read the message, I just need my computer does...

B: No sense. How do you know if a message is wrong? You need to read it! And, you have not to configure the router to open ports anymore!

A: Well, everybody is pushing it, so, let's try.

-- Time later

B: Hey, A! This message is wrong.

A: No, it is not.

B: Yes. It's supposed you should send me the charater 'X' in the position 'Y'.

A: No, it is not supposed to. As you can read the message, I assume you know where the 'X' character is.

B: Humgrpfh... hold on.

-- Time later

B: Hey A!, look at this! I've called it XML. You can define your own tags! No more HTML!

A: It's more text.

B: Yes, but it's designed to transport and store data. Over HTTP!

A: Weren't we ok with TCP?

B: No, no, no. This is the silver bullet!

A: ok... :(

-- Time later

B: Looooook what I ha-ave!

A: Oh no, not again.

B: Yes! It's called SOAP! People was using XML over HTTP that much that I needed to standarize it in some way. Now, you can define how to communicate with you through this new thing: the WSDL

A: So, now I have to tell anyone how to talk with me! Wasn't that the problem with TCP in first place?

B: This is different. You publish your specifications once, everyone can read it.

A: Here we go again...

-- Time later

B: Hey, this thing, HTTP+SOAP... they are calling it webservices.

A: Yep.

B: And Microsoft now have WCF, that groups all the communications services in just one API.

A: Yep.

B: Well, it's being used a lot, but you know... Web browsers cannot handle well SOAP..

A: That's why they read HTML. But, hold on... why a web browser is consuming a web service?

B: To make a web page more responsive.

A: What! Don't we have binary code running in our machines that is enough responsive?

B: You know, internet is pushing everything to HTTP, even transactional applications...

A: It's crazy! Web pages are slow! You have to have a browser to run them! You are not taking advantage of the client power! And even worse: developing a web application with similar functionality and responsiveness than a binary takes more time and effort!

B: These are not web pages any more. Now they are web applications.

A: What the... Call it as you want !

B: And, this thing, SOAP, is not well managed by javascript...

A: We are asking to HTTP more than it was designed for!

B: I think this is not the problem... So, now MS has been pushing ASP.NET MVC... and people is using the controllers as a service layer

A: ..

B: They are not using SOAP...

A: ..

B: They are using JSON, that is readable by the browsers.

A: Right. Let the server serve what the customers-browsers want. I remember when to consume a service, you needed to know what to ask and handle the response as you could.

B: Yes. Well, and now, because of the servers returning JSON, we have something called Web API, that uses the HTTP verbs.

A: Hey, wouldn't it have been better to standarize a TCP port, create a new protocol over TCP and standarize the messages structures than trying to use HTTP for what it was not designed for?

B: No, no. HTTP is fine. It was already there, so we took it.

A: It still is stateless, and we have 2 intermediaries: Browser and Web Server... so it is slow.

B: That's why they are trying to make web applications more responsive.

A: Solving the problem they created, you mean.

B:  C'mon. How hard this can be?

A: Let me put this black over white: I have a lot in the desktop development: C# with Generics, Linq, lambda expressions, reflection; a complete .NET framework; a great editor that alows me to make refactoring, handle files, debug, edit and continue, etc... And because you dont't want people to download the application we are making everything web?

B: Right.

A:  Now, compare that to the technology in the client: HTML + javascript.

B: Right.

A: Javascript! Are you kidding me? A not evolutioned langauge? Not typed? A deficient Intellisense? No refactoring tools? Not decent editor? Not compiling errors! You know what we are talking about? NOT COMPILING ERRORS! of course, if it is not compiled... Everything is a string in there !! So, a typo is not dected until the application is running!...

B: You have frameworks: Jquery, Knockout...

A: Great, frameworks that only encapsulate functionallity. They do not add anything. Is it much to ask Generics? Even VB6 was better than that!

B: There are people working in something called Typescript...

A: And what is my view? a DOM. At least I have Objects in there... but with JQuery selectors, everything is a string again! I dare you to rename a control, and find it in you code in javascript...

B: You can find in the files...

A: And when I get the data... what is this JSON thing? More string! And if I want to use this information, what type of data are these? We don't know, as it is not typed !

A: Even when I developed desktop applications, my received binary package could be mapped to an object using MS Remoting! Can these be done in javascript? Of course! How? JSON is a 'Object Notation', right?. So, when I get the data... OMG, IT'S A STRING AGAIN!!

B: Well...
A: And what if the string comes with the 'X' character in another position different than 'Y'? Does it sound familiar to you?

B: Errr... I have to go. Happy development!

Based on a couple of conversations in ALT.NET Hispano, and this entry: http://blogs.microsoft.co.il/blogs/idof/archive/2012/03/05/wcf-or-asp-net-web-apis-my-two-cents-on-the-subject.aspx

## 27/4/12

### Coding level: OMFG

------------------------------------------------------------
isActive = True

If InStr(straTemp(0, 0), "inactive") > 0 Then
isActive = False
ElseIf InStr(straTemp(0, 0), "Inactive") > 0 Then
isActive = False
ElseIf InStr(straTemp(0, 0), "INACTIVE") > 0 Then
isActive = False
End If
--------------------------------------------------------------

'My comment: Dios quiera que el usuario no tipee "inActive"