Soft Cero

Dudas y aportes al desarrollo de software

22/02/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/04/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"

25/12/10

Simplemente sin desperdicio

So, you wanted to be a computer programmer.
Tan parecido a la realidad...

http://gizmodo.com/5716226/so-you-wanted-to-be-a-computer-programer

18/08/10

Complejidad

"Cómo manejamos la complejidad?, pregunté a unos cuantos arquitectos de software... Todos ellos contestaron:[Abstracción]... en matemáticas, hay un principio que ningún arquitecto tiene en cuenta: La complejidad es constante. En otras palabras, si estás diseñando un sistema inherentemente complejo, no puedes reducir la complejidad... La abstracción, básicamente esconde esa complejiad... En muchos diseños, el problema es que una vez que la abstracción escondió la complejidad, los diseñadores tienden a olvidarla...y volverá algún día"

Excelente comienzo de éste artículo.

26/03/10

Optimizing .NET JSON Serializing (and II)

Let’s start by the end: What do I want?
- A JSON serializer which can give me the JSON representation of any object
- This serializer should let me specify exactly what I want to serialize.

So, if I need only the data of my student (but I don’t want the subjects), the output string should be: {"FileNumber":1,"Name":"student 1"}
And also, if I need only the Subject Names of the student, we should get: {“Subjects”:[{“Name”:”Subject0”}]}
Now it’s possible. Look at the new serializer called JsonSerializer (yeah, a lot of imagination to name things).

Here you have the class

public class JsonSerializer
    {
        const string DOT = ".";
 
        object _objectToSerialize;
        List<string> _propertiesIncluded;
        List<string> _propertiesExcluded;
        List<string> _cumulativeProperties; //variable to iterate through properties
        PropertiesToSerialize _propertiesToSerialize;
 
        public enum PropertiesToSerialize
        {
            All,
            AllExceptExcluded,
            OnlyIncluded
        }
 
        public JsonSerializer(object instance)
        {
            _objectToSerialize = instance;
        }
 
        public void Include(params string[] includes)
        {
            foreach (string str in includes)
                Include(str);
        }
 
        public void Exclude(params string[] excludes)
        {
            foreach (string str in excludes)
                Exclude(str);
        }
 
        public string Serialize(PropertiesToSerialize propertiesToSerialize)
        {
            _propertiesToSerialize = propertiesToSerialize; 
 
            StringBuilder sb = new StringBuilder();
            _cumulativeProperties = new List<string>();
 
            Iterate(_objectToSerialize, sb, -1);
 
            return sb.ToString();
        }
 
        void Include(string include)
        {
            if (include.Equals(string.Empty))
                return;
 
            if (_propertiesExcluded != null && _propertiesExcluded.Contains(include))
                throw new Exception("JSON.Includes: The string [" + include + "] that you are trying to include already exists in the Exclude List");
 
            if (_propertiesIncluded == null)
                _propertiesIncluded = new List<string>();
 
            //if a composed property needs to be included, the hole scale need to be included too
            string[] propertyParts = include.Split('.');
            string propertyCompose = "";
            foreach (string s in propertyParts)
            {
                propertyCompose += s;
                if (!_propertiesIncluded.Contains(propertyCompose))
                    _propertiesIncluded.Add(propertyCompose);
                propertyCompose += ".";
            }
        }
 
        void Exclude(string exclude)
        {
            if (exclude.Equals(string.Empty))
                return;
 
            if (_propertiesIncluded != null && _propertiesIncluded.Contains(exclude))
                throw new Exception("JSON.Excludes: The string [" + exclude + "] that you are trying to exclude already exists in the Include List");
 
            if (_propertiesExcluded == null)
                _propertiesExcluded = new List<string>();
 
 
            if (!_propertiesExcluded.Contains(exclude))
                _propertiesExcluded.Add(exclude);
        }
 
        void Iterate(object instance, StringBuilder sb, int propertyLevel)
        {
            propertyLevel++;
            _cumulativeProperties.Add("");
 
            sb.Append("{");
            foreach (PropertyInfo property in instance.GetType().GetProperties())
            {
                _cumulativeProperties[propertyLevel] = property.Name;
                string cumulativePropertiesConcatenated = ConcatListToString(_cumulativeProperties);
 
                switch (_propertiesToSerialize)
                {
                    case PropertiesToSerialize.All:
                        ParseProperty(instance, property, sb, propertyLevel);
                        break;
                    case PropertiesToSerialize.AllExceptExcluded:
                        if (_propertiesExcluded != null && !_propertiesExcluded.Contains(cumulativePropertiesConcatenated))
                        {
                            ParseProperty(instance, property, sb, propertyLevel);
                        }
                        break;
                    case PropertiesToSerialize.OnlyIncluded:
                        if (_propertiesIncluded != null && _propertiesIncluded.Contains(cumulativePropertiesConcatenated))
                        {
                            ParseProperty(instance, property, sb, propertyLevel);
                        }
                        break;
                }
            }
            if (sb.ToString().EndsWith(","))
                sb.Remove(sb.Length - 1, 1);
            _cumulativeProperties.RemoveAt(_cumulativeProperties.Count - 1);
            sb.Append("}");
        }
 
        void ParseProperty(object instance, PropertyInfo property, StringBuilder sb, int propertyLevel)
        {
            sb.Append('\"' + ReplaceJSONCharacters(property.Name) + "\":");
            object propertyValue = property.GetValue(instance, null);
            //if(property.PropertyType.GetInterface(typeof(ICollection<>).FullName) != null)
            if (IsEnumerable(property.PropertyType))
            {
                sb.Append("[");
 
                IEnumerable lista = (IEnumerable)property.GetValue(instance, null);
                if (lista != null)
                {
                    foreach (object obj in lista)
                    {
                        Iterate(obj, sb, propertyLevel);
                        sb.Append(",");
                    }
 
                    if (sb.ToString().EndsWith(","))
                        sb.Remove(sb.Length - 1, 1);
                }
                sb.Append("]");
            }
            else if (property.PropertyType == typeof(string))
            {
                sb.Append('\"' + ReplaceJSONCharacters(propertyValue.ToString()) + '\"');
            }
            else if (property.PropertyType == typeof(bool))
            {
                sb.Append(ReplaceJSONCharacters(propertyValue.ToString().ToLower()));
            }
            else
            {
                sb.Append(ReplaceJSONCharacters(propertyValue.ToString()));
            }
            sb.Append(",");
 
        }
 
        bool IsEnumerable(Type type)
        {
            return type.IsGenericType &&
                   (typeof (IEnumerable<>).MakeGenericType(type.GetGenericArguments())).IsAssignableFrom(type);
 
        }
 
        string ReplaceJSONCharacters(string cadena)
        {
            return cadena
            .Replace("\\", "\\\\")
            .Replace("\"", "\\\"")
            .Replace("/", "\\/")
            .Replace("\b", "\\\b")
            .Replace("\f", "\\f")
            .Replace("\n", "\\n")
            .Replace("\r", "\\r")
            .Replace("\t", "\\t");
        }
 
        string ConcatListToString(List<string> list)
        {
            return string.Join(DOT, list.ToArray());
        }
    }


Here some examples on how to use this class:
1) I want the whole object, as if I was using the standard .NET Serializer.

  JsonSerializer serializer = new JsonSerializer(student);
    string jsonStudent = serializer.Serialize(JsonSerializer.PropertiesToSerialize.All);
    return jsonStudent;

Output: {"FileNumber":1,"Name":"student 1","Subjects":[{"Id":1000000,"Name":"Subject0"}]}

2) I want just the data of the student, but not the subjects:

    JsonSerializer serializer = new JsonSerializer(student);
    serializer.Exclude("Subjects");
    string jsonStudent = serializer.Serialize(JsonSerializer.PropertiesToSerialize.AllExceptExcluded);
    return jsonStudent;

Output: {"FileNumber":1,"Name":"student 1"}

3) Now I want just the name of the subjects, and nothing more (Note how it's easy to specify properties in the aggregation, through the dot syntax)

    JsonSerializer serializer = new JsonSerializer(student);
    serializer.Include("Subjects.Name");
    string jsonStudent = serializer.Serialize(JsonSerializer.PropertiesToSerialize.OnlyIncluded);
    return jsonStudent;

Output: {"Subjects":[{"Name":"Subject0"}]}


Well, it works, and for sure it's helpful, but there still some things to improve it

1) The way to specify the properties to serialize as “strings” is not flexible at all. For example, if we practice some refactoring in our classes, let’s say, renaming properties, the properties name here will not change.
2) It could be possible to make the public methods of this class as extension methods for any "object"

If anyone can improve it, I'd like to hear about it.

25/03/10

Optimizing .NET JSON serializing (I)

Trying to send a custom object from my model to my view, I observed that it does not accomplish all the tasks I would expect from the serializer… so I decided to make my own.
I will describe how this idea came to my mind, and what improvements I’ve made.
I have the following classes (note the aggregation in the “Student “ class):

class Student
{
    public int FileNumber { get; set; }
    public string Name { get; set; }
    public IEnumerable<Subject> Subjects { get; set; }
}
 
class Subject
{
    public int Id { get; set; }
    public string Name { get; set; }
}


And I have the following method, which returns a student with his subjects.

    private static Student GetStudent(int studentId, int subjectsCount)
    {
        //instance a new studen
        Student student = new Student
                   {
                       FileNumber = studentId,
                       Name = string.Concat("student ", studentId),
                       Subjects = new List<Subject>()
                   };
 
        //add to the student the subjects
        for (int i = 0; i < subjectsCount; i++)
        {
            (student.Subjects as List<Subject>).Add(new Subject
                                                        {
                                                            Id = 1000000 + i, 
                                                            Name = string.Concat("Subject" + i)
                                                        });
        }
        return student;
    }
 
}


To serialize an object you must decorate the classes with [Serializable]attribute and use the DataContractJsonSerializer class, like in the following code snippet.

DataContractJsonSerializer serializer = new DataContractJsonSerializer(subjects.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, subjects);
return Encoding.Default.GetString(ms.ToArray());


The output string is:
{"k__BackingField":1,"k__BackingField":"student 1","k__BackingField":[{"k__BackingField":1000000,"k__BackingField":"Subject0"}]}

But, hey! This is not JSON! Or at least, it is not standard JSON (see http://www.json.org/).

After a little research, I found how to get standard JSON. You must remove the [Serializable] attribute and decorate the classes in the following way:

[DataContract]
class Student
{
    [DataMember]
    public int FileNumber { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public IEnumerable<Subject> Subjects { get; set; }
}
 
[DataContract]
class Subject
{
    [DataMember]
    public int Id { get; set; }
    [DataMember]
    public string Name { get; set; }
}


Executing the same method as before, I get:
{"FileNumber":1,"Name":"student 1","Subjects":[{"Id":1000000,"Name":"Subject0"}]}

Yes! Much better.
But, it is not good enough. This solution means that I must have access to the design of the class, which is not always true. And also, if I just need only some data of the object, I cannot serialize it partially.
I’ll show how to solve these problems in the next post.

Seguidores