Friday, December 9, 2016

Convert protobuf to base64

using System;
using p = Google.Protobuf;

namespace TestProtobuf
{
    class MainClass
    {
        public static void Main(string[] args)
        {


            var c = new Person 
            {
                FirstName = "Anders", LastName = "Hejlsberg"
            };


            int n = c.CalculateSize();
            var ba = new byte[n];

            var os = new p.CodedOutputStream(ba);

            c.WriteTo(os);

            var s = Convert.ToBase64String(ba);

            Console.WriteLine(s);
        }
    }
}

Tuesday, May 3, 2016

Inlined if-else assignment

This if-else statement:
AssignmentEnum assignment;
if (loggedUser == onboard.Employee)
    assignment = AssignmentEnum.Employee;
else if (loggedUser == onboard.CreatedBy)
    assignment = AssignmentEnum.Manager;
else
    assignment = 0;

Can be shortened to:
AssignmentEnum assignment = 
    loggedUser == onboard.Employee ?
        AssignmentEnum.Employee
    :loggedUser == onboard.CreatedBy ?
        AssignmentEnum.Manager 
    :
        0;


Happy Coding!

Wednesday, April 20, 2016

Secure Amazon Download using Query String Authentication

// https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html#RESTAuthenticationQueryStringAuth

using System;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace ConsoleApplication1
{
    class Program
    {
        static string CreateSignatureAsBase64(string secretKey, string stringToSign)
        {
            byte[] dataToSign = Encoding.UTF8.GetBytes(stringToSign);
            using (var crypt = new HMACSHA1(Encoding.UTF8.GetBytes(secretKey)))
            {
                return Convert.ToBase64String(crypt.ComputeHash(dataToSign));
            }
        }
        

        /// <summary>
        /// Returns date expiration in seconds since 1970
        /// </summary>
        /// <param name="minutesExpiration"></param>
        /// <returns></returns>
        public static long GetExpiration(int minutesExpiration)
        {
            DateTime date   = DateTime.UtcNow;
            DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            TimeSpan diff   = date.ToUniversalTime() - origin + new TimeSpan(0, minutesExpiration, 0);
            return (long) Math.Floor(diff.TotalSeconds);
        }

        static void Main(string[] args)
        {
            long expiration = GetExpiration(minutesExpiration: 1);
            
            string fileToDownload = "ice-bucket/someFilenameHere.pdf";
            
            var stringToSign = 
                "GET" + "\n" +
                "\n" +
                "\n" +
                expiration + "\n" +
                "/" + fileToDownload;

            string secretAccessKey       = "blah/meh";
            string signature64           = CreateSignatureAsBase64(secretAccessKey, stringToSign);            
            string urlEncodedSignature64 = HttpUtility.UrlEncode(signature64);

            string accessKey = "developerId";
			
            string url = 
                string.Format(@"https://s3-us-west-2.amazonaws.com/{0}?AWSAccessKeyId={1}&Expires={2}&Signature={3}", 
                    fileToDownload, 
                    accessKey,
                    expiration, 
                    urlEncodedSignature64);

            Process.Start(url);

        }
    }
}

Thursday, March 31, 2016

The O in ORM

This code is not object-oriented enough. Objects are not oriented to objects; instead, objects are oriented to database detail, read: keys.

// Consumer code
var fields = Event.GetEventFields(da, actual.Event, language, language);

// Implementing code
public static IEnumerable<Dto.NotificationDto.Template.Response.EventFieldDto>
GetEventFields(IDomainAccess da, EventEnum @event, string lang, string fallbackLang)
{
    var list = 
        from e in da.Query<Event>()
        join f in da.Query<EventField>()
        on e.Enum equals f.Event.Enum

        where e.Enum == @event

        select new Dto.NotificationDto.Template.Response.EventFieldDto
        {
            FieldName = f.Field.TextXlat.Localize(lang, fallbackLang),
            FieldTag  = f.Field.Mnemonic
        };
}


When using a decent ORM like NHibernate, keys shouldn't leak as much as possible on the application layer, as keys could be composite. Joining and filtering with composite keys is a PITA, so just use object when joining and filtering.

Linq and NHibernate can facilitate that. It's only less capable ORM like Entity Framework that insist on accessing stuff through keys.

As much as possible, make objects communicate to objects.

To wit, here's how the ORM queries could be more object-oriented, oriented to object, instead of oriented to database. Foreign keys and primary keys are removed from the Linq query.


// Consumer code:
var fields = Event.GetEventFields(da, da.JustKey<Event>(actual.Event), language, language);


// Implementing code:
public static IEnumerable<Dto.NotificationDto.Template.Response.EventFieldDto>
            GetEventFields(IDomainAccess da, Event eventNeeded, string lang, string fallbackLang)
{

    var list = 
        from e in da.Query<Event>()
        join f in da.Query<EventField>()
        on e equals f.Event // notice that we can use the object themselves on joins. NHibernate is smart enough to know what is the primary key(s) of the object.

        where e == eventNeeded // same here. We don't need to use the primary key

        select new Dto.NotificationDto.Template.Response.EventFieldDto
        {
            FieldName = f.Field.TextXlat.Localize(lang, fallbackLang),
            FieldTag  = f.Field.Mnemonic
        };
    }



When using ORM, just forget the details of what is the primary key is, the primary key's property name may change or the primary could grow two composite key(two or more column keys), but the object itself stays the same.

So even if the name of the primary key (e.g., Id, Code, Enum) is changed to something else or primary key is changed to composite the suggested object-oriented Linq above would still work, future-proof.


Another thing to note, since there is a collection of EventField in Event itself, we can eliminate the join in code by using the EventField collection instead, and then flatten the Event's EventField collection by using SelectMany.


The join-using code above could be shortened to:


// Consumer code:
var fields = Event.GetEventFields(da, da.JustKey<Event>(actual.Event), language, language);


// Implementing code:
public static IEnumerable<Dto.NotificationDto.Template.Response.EventFieldDto>
            GetEventFields(IDomainAccess da, Event eventNeeded, string lang, string fallbackLang)
{
    var list = 
        from eventField in da.Query<Event>().SelectMany(e => e.Fields) 
                      
        where eventField.Event == eventNeeded

        select new Dto.NotificationDto.Template.Response.EventFieldDto
        {
            FieldName = eventField.Field.TextXlat.Localize(lang, fallbackLang),
            FieldTag  = eventField.Field.Mnemonic
        };

    return list.ToList();
}


Lastly, since the object can protect its children by enforcing protected access modifier, accesing the child from the aggregate directly is perfectly fine, it's still DDD as long things are accessed via aggregate's root.


// Consumer code:
var fields = Event.GetEventFields(da, da.JustKey<Event>(actual.Event), language, language);


// Implementing code:
public static IEnumerable<Dto.NotificationDto.Template.Response.EventFieldDto>
            GetEventFields(IDomainAccess da, Event eventNeeded, string lang, string fallbackLang)
{
    var list = 
        from eventField in da.Query<EventField>()

        where eventField.Event == eventNeeded

        select new Dto.NotificationDto.Template.Response.EventFieldDto
        {
            FieldName = eventField.Field.TextXlat.Localize(lang, fallbackLang),
            FieldTag  = eventField.Field.Mnemonic
        };

    return list.ToList();
}


Another approach is to get the aggregate root, and then project the collection, this way creating static method can be avoided.

// Consumer code:
Event eventNeeded = da.Get<Key>(actual.Event);
var fields = eventNeeded.GetEventFields(lang, fallbackLang); 


// Implementing code:
public IEnumerable<Dto.NotificationDto.Template.Response.EventFieldDto>
 GetEventFields(string lang, string fallbackLang)
{
    var list = 
        from eventField in this.Fields
        // where eventField.Event == eventNeeded // this will not be necessary anymore
        select new Dto.NotificationDto.Template.Response.EventFieldDto
        {
            FieldName = eventField.Field.TextXlat.Localize(lang, fallbackLang),
            FieldTag  = eventField.Field.Mnemonic
        };

    return list.ToList();
}  


However, for performance-conscious developers or users, the drawback of not using static method when accessing the aggregate's children is it will incur two queries to database. A query for getting a single row from parent, and another query for getting the children of the parent.


To improve the performance of the code above while giving the illusion of accessing the aggregate's intance method instead directly, use extension method. Thanks C#! :)

The code below will just issue one query to database, on event_field table only, event table will not be queried.

From a consumer:
var eventNeeded = da.JustKey<Event>(actual.Event);
var fields = eventNeeded.GetEventFields(da, language, language); // GetEventFields looks like an instance method and not an static method.



The instance method illusion helper:
public static class EventPerformanceHelper
{
    public static IEnumerable<Dto.NotificationDto.Template.Response.EventFieldDto>
    GetEventFields(this Event eventNeeded, IDomainAccess da, string lang, string fallbackLang)
    {
        var list =
            from eventField in da.Query<EventField>()

            where eventField.Event == eventNeeded

            select new Dto.NotificationDto.Template.Response.EventFieldDto
            {
                FieldName = eventField.Field.TextXlat.Localize(lang, fallbackLang),
                FieldTag  = eventField.Field.Mnemonic
            };


        return list.ToList();
    }
}


Read more about using DDD while not sacrificing performance: http://www.ienablemuch.com/2013/12/pragmatic-ddd.html

Wednesday, March 30, 2016

Highfalutin code #4. With great power, comes great responsibility.

No matter how powerful our programming language is..

foreach (var item in documentFields.SelectMany(documentField => documentField.Options, (documentField, option) => new { documentField, option }))
{
   item.option.DocumentField = item.documentField;
}


..we still have a great responsibility to make our code readable and maintainable:
foreach (var documentField in documentFields)
    foreach (var option in documentField.Options)
    {
        option.DocumentField = documentField;
    }


SelectMany's intent is to flatten *ALL* the option collection from all fields, and then assign each option item in collection to their parent field.

Though the objective of the first code is to make the program's intent obvious, its verbosity blurs the intent of the code.

In fact, if we want to make it appear we are flattening the collection, we can also do it as follows:

foreach (var documentField in documentFields) foreach (var option in documentField.Options)
{
    option.DocumentField = documentField;
}


If we look at the two for loops as projecting a table with two columns, the projected options will now look like flattened rows.

We just have to tilt our perspective sometimes :)


Disclaimer: I won't use the last code.

Thursday, March 10, 2016

Sometimes longer code is ok

This code even it's longer..

.Select(permission => (Common.Security.PermissionEnum) System.Enum.Parse(typeof(Common.Security.PermissionEnum), permission.Value));

..is superior to this short code:

.Select(permission => (Common.Security.PermissionEnum) int.Parse(permission.Value));


The first code, even if the enum is updated to long data type, will still work.


How often do we upgrade the enum to long though?


Happy Coding!

Thursday, February 25, 2016

Unintended NHibernate Update

I encountered a strange error wherein NHibernate UPDATE an entity even I'm just selecting it from Linq.

The nature of the problem is similar to this stackoverflow question: http://stackoverflow.com/questions/2001297/nhibernate-doing-updates-on-select/2001389#2001389


Though it's similar, it befuddled me for a while as I thought there's a flaw on my implementation of custom Jsonb .NET type for Postgresql.

I tried commenting all properties that uses Jsonb type, still there's an UPDATE when just selecting an entity.

When I'm down to few properties and commented them, the DateTime type, the unintended UPDATE error is gone.

The error is in the default value of non-null DateTime, if it's not explicitly assigned, the default value is 0001-01-01, so that's what gets saved to the database. That makes NHibernate wonky when reading the entity again, the pushed value to DateTime type and the read value become different.

The timestamp column is not nullable and have a default value of CURRENT_TIMESTAMP, so I thought it's prudent to make the corresponding property on application (.NET) a not nullable type too. There's a problem with making the .NET type non-nullable, if the value is forgotten to be explicitly assigned a value (e.g., DateTime.Now) in the application, the value that will get saved to database is 0001-01-01 since it's the default value of DateTime when it's not assigned a value.


To conclude, it's better to make the .NET DateTime type nullable even if the underlying datetime type is not nullable, so when it's forgotten to be assigned a value, what will be saved to database will be null, and since the timestamp column in the table is not nullable, it will throw an exception, it will fail fast, early error, early fix, no corrupt data.


Happy Coding!

Wednesday, February 10, 2016

Cannot Load Visual Studio Project

Error:

The Web Application Project SomethingGood.Api is configured to use IIS. The Web server 'http://www.localhost.com/api' could not be found.


One possible cause of this error is when you configured your IIS 10 to accept wildcard in host name, think subdomain, or multi-tenant website. To fix it, do Unload Project, then edit the csproj, then change the IISUrl to something like this:

<IISUrl>http://*.localhost.com/api</IISUrl>

Thursday, January 28, 2016

Aggregate

There are only four aggregates here, can you spot them?


Here are they:


An Aggregate works as one unit, its parts should be as close together as possible.



Happy Coding!