Principles of Coding

In my ~15 years as a software engineer/lead in global tech corporations, I made 100s if not 1000s of Code Review s. I captured here a list of common patterns in code reviews holding them up from completion and causing 10+, sometimes 20+ review iterations before the code can be checked in.

I expect these to be beneficial especially for the junior developers but also experienced developers as a baseline and a refresher. Like all principles and best practices in software engineering discipline, there could be cases not to follow these, but the reason should be a good one and thought through.  So lets dive in.

1. Parameter Validation:

All public methods and constructors need to have parameter validation. Even better, when invalid parameters are detected, parameter name and value, should be logged.

2. Dependencies and Dependency Injection:

Take dependencies as Interfaces (not concrete classes) through class constructors explicitly. That allows your components to be testable as you can easily pass a mock implementation of the interface to your class.

Use a IoC container for object composition. This makes it easy to manage dependencies in a central location (composition root).

3. Logging:

Logging is super important. All unexpected errors (and high informational value non-errors) should be logged with enough logging metadata and information to allow us properly classify, diagnose and root cause issues happening with the code we wrote when it is used in the wild in production.

Wrap your code with performance counters to be able to monitor its metrics in Production.

4. Asynchronous Code

All I/O calls (service call, disc I/O read etc.) should be async. All async methods should be awaited ie. await FooAsync(); instead of making a blocking wait on them ie. FooAsync.Wait() , FooAsync.Result.

Making a blocking wait on an async method defeats the whole purpose of asynchrony and introduces potential deadlock issues.

Making synchronuous calls on I/O requests unnecessarily blocks the Core while I/O request is executed and introduces scalability, perf bottlenecks which can be hard to fix after the fact once these issues accumulate over time.

5. Parallel Processing

For the code that does not need to be sequentially run, leverage parallelism in your code but balance this with an upper bound on Max Degree of Parallelism. Unbounded parallelism/ over parallelism also may result in side effects.

If in doubt, measure the execution time and CPU of your code before and after and optimize the level of parallelism.

6. Code Reuse

Do not reinvent the wheel and contribute to shared code. Search code locations in your team’s repository that contains shared, reusable code to see if the api you want to implement exists, if it does use it, if not then add it to a suitable shared project so it can be reused by other engineers/teams if it has potential benefit for other teams.

7. Small Code Reviews

Send small code reviews that can ideally be completed within 5 iterations. Talk through unclear comments with the reviewer in person.

8. Engage in Design Reviews Early On

Major software and system level architectural changes should go through a Design Review before the code review is sent. Before coding starts.

Hope this helps 🙂 Happy coding.

 

Object Graph Traversal by Recursive Reflection

Every software engineer faces with this problem of traversing an object graph and processing it, at least once in his or her career :). If you are a software engineer and did not have to solve this puzzle yet, believe me that day will eventually come… If you are not a software engineer and still you had to solve this problem please send me the details, I would be very curious about how you got yourself into that situation :))

In my case, I needed to implement a public .net api as part of a public SDK in Github, basically needed to implement my own Serializer, that takes an object as a parameter, traverse its nodes and end nodes (properties) and process these as it traverses them.I put no type, interface or inheritance constraint on the input object, the type of the input object is base type of all base types “object”. That makes the api super flexible and powerful, basically you are telling the client code, send me whatever type of object you want and I am going to process it, but on the other side it is a very bold statement because the object can really be anything, we have no compile time knowledge or run time type constraints of its type, nor do we know its object graph and hierarchical structure. It can be a simple object with simple properties directly under the object root, or it can be a complex object with a depth of many layers (practically infinite) with all kinds of complex /nested/composite properties, these nested complex properties can be reference type (a class) or value type (ie. struct) and there may be a full or partial recursive loops within the object graph, to name a few of the interesting points.

So this is an object traversal/processing problem where I need to visit every intermediate and end node property of the input object and process these properties. The output of this processing logic could not be “log something to command line/logging infrastructure” either, the output generated by processor had to be accumulated and returned to the caller.

I solved this problem by recursive reflection. For more interested, I implemented a depth first traversal with structural and multiple recursion technique. You can have a look at different types of recursion in this good and short wiki article (https://en.wikipedia.org/wiki/Recursion_(computer_science)#Types_of_recursion).

The public facing API is called Flatten. It takes an object as I mentioned before, processes all of its intermediate and end nodes, lets call that function EndNodeProcessor.

The algorithm passes each node it visits to EndNodeProcessor function, in that way the responsibility of traversing the object graph and processing of each node is clearly separated between the recursive algorithm and the EndNodeProcessor function.

EndNodeProcessor’s exact signature depends on what do you want to do with the exact node and what kind of information you need from the algorithm to be passed in, as a minimum you need the nodes to be passed so EndNodeProcessor should take the node as a parameter, in my case I also needed the Type information of the current node, so that’s the second parameter.

The return type of your EndNodeProcessor also defines the return type of the public method that does traversal and node processing. (In my case it is called Flatten).

Lets say EndNodeprocessor takes each visited node as a parameter, processes them and returns an object of type of T back to the recursive algorithm, the algorithm then collects these objects and persists them in a collection. This collection is then returned back from the public api. In my case this collection is Dictionary<string, T>. In my case just an IEnumerable<T> was not enough, I also needed a way to recompose the original object back so I associated each output with a key of string type in a Dictionary <string, T>.

So the signature of EndNodeProcessor is: T EndNodeProcessor (object Node, Type type)

Note that  as mentioned, the Type parameter is something specific to my requirements, as a minimum it needs to take the node as object parameter. The return type T is a pseudo concept, you would need to decide what exact type you want the processor to return and replace the T with that exact type. I specifically left out the actual implementation of the EndNodeProcessor function because what it does with the passed in Node object is specific to the problem you want to solve and is decoupled from the traversal algorithm.

Let’s look at the code:

public static Dictionary<string, T> Flatten(object root)
{

if (root == null) return null;

//Here within the public method we instantiate Dictionary which will hold the output values generated by the NodeProcessor.

Dictionary<key, value> propertyDictionary = new Dictionary<key, value>();

//We create a HashSet to keep track of antecedents during object traversal. This is to detect complete (all the way back to root node) or partial recursive loops (back to an internal node) within object graph and terminate the recursion. If we do not do that  we will end up an infinite loop during recursion, will run out of stack memory and cause a Stack Overflow exception eventually. We like StackOverflow as a web site, we do not want any stack over flows in any other shape or form 🙂

HashSet<object> antecedents = new HashSet<object>(new ObjectReferenceEqualityComparer());

//We will pass the propertyDictionary to the private overloaded recursive method which is also called Flatten, the recursive Flatten method will update this Dictionary by reference. Dictionary is a reference type therefore stored on the heap and so any updates to the dictionary during the recursion will persist after all recursion ends and the private Flatten method returns.

return Flatten(propertyDictionary, root, string.Empty, antecedents);
}

private static bool Flatten(
Dictionary<string, EntityProperty> propertyDictionary,
object current,
string objectPath,
HashSet<object> antecedents)
{

// Recursion Termination Condition: if passed in object is null, return. This heuristically means that we have processed an end node property and we are already at the bottom of the object graph. There is no deeper layer to process.

if (current == null)
{
return true;
}

// If we reach here, that means we are either in the middle of the object graph or we are actually at the deepest layer, at the end node property but we have not yet processed it. We need to make a decision. We first get the type of the current node.

Type type = current.GetType();

// Then we assume we are at an end node property and attempt to process it by passing the current object to our NodeProcessor along with its type.
T output = EndNodeProcessor(current, type);

// If EndNodeProcessor managed to process the current object we infer it was an end node property. This logic could also be put inside the EndNodeProcessor directly.

if (output != null)
{

// We update the passed in PropertyDictionary with the output generated by the NodeProcessor.
propertyDictionary.Add(objectPath, output);

// Recursion Termination Condition: We processed an end node and now we can return from this recursion.

return true;
}

// If we reach this part of the code there are 2 options. Either we are in an intermediate node in the object graph (ie. not an end node property), therefore our EndNodeProcessor returned null. Or we are actually in an end node but the EndNodeProcessor failed to process the request. we need to make a decision. First thing we check is if we are in an intermediate node.

IEnumerable<PropertyInfo> propertyInfos = type.GetProperties();

if (!propertyInfos.Any())
{

// If we are here then the current node does not have any child nodes (properties in our example) of its own then it means that we are actually on an end node property but EndNodeProcessor failed to process that node. This is an unexpected failure so we terminate overall method execution at this point by throwing an exception.
throw new SerializationException(string.Format(CultureInfo.InvariantCulture, UnsupportedPropertyTypeForEntityPropertyConversion, type, objectPath));
}

//Recursive Reference Detection: If we are at this stage in the code we are at an intermediate node in the object graph. We need to make sure we detect recursive loops in the passed in object and avoid going into infinite recursive traversal within this part of the object graph.

bool isAntecedent = false;

// If current type is a value type ie. we are at a struct type intermediate property then there is no danger of recursive reference, recursive reference by definition only happens on reference type s (ie. a child reference type property and its parent are pointing to the same point in memory, therefore creating a circular loop.)

if (!type.IsValueType)
{

// antecedents is a custom HashSet<object> which I initialized with my own EqualityComparer implementation (ObjectReferenceEqualityComparer()).  ObjectReferenceEqualityComparer uses purely the object references to detect object equality and avoids any overloaded GetHashCode() implementations (if any) of input objects. The hashset contains all of the child properties of the current parent property. We update this hashset also recursively as we traverse in the object graph. We add all child nodes under the current node to the hashset as we traverse recursively in this part of the object graph where current node becomes the root.  And we remove all of the nodes from the hashset after we process them.

If any time during this traversal, antecdents.Contains(current) returns true, it means that we saw this reference before within ths sub tree and hence we detected a recursive reference. So we terminate. We could here decide what other things we do with recursive references, may be take an option to alter that (ie. skip those as opposed to terminate the execution etc.). In fact Circular Reference Detection is actually a topic of its own, so I may write up another article just about it to go over that part of the solution
if (antecedents.Contains(current))
{
throw new SerializationException(string.Format(CultureInfo.InvariantCulture, RecursiveReferencedObject, objectPath, type));
}

// we detect that current node is not in our hashset and so we add it to the hashset. We also set isAntecedent flag to true because we are at this stage in the code in an internal node so it is antecedent to child properties.

antecedents.Add(current);
isAntecedent = true;
}

// This is where we apply multiple recursion, we call this private Flatten method on all of the child properties of the current node.

bool success = propertyInfos
.Where(propertyInfo => !ShouldSkip(propertyInfo))
.All(propertyInfo =>
{
return Flatten(
propertyDictionary,
propertyInfo.GetValue(current, index: null),
string.IsNullOrWhiteSpace(objectPath) ? propertyInfo.Name : objectPath + propertyNameDelimiter + propertyInfo.Name,
antecedents);
});

// Once we are here in the code, we completed processing all child nodes (and their child nodes and their child nodes, all the way to their end nodes ) that are under the current property in the object graph. Since we completed the processing all nodes under this sub tree of the object starting from the current node downwards, we can safely remove the current node now from the antecedents hashset, there is no risk of circular reference beyond this ppoint in relatio to the current node.

if (isAntecedent)
{
antecedents.Remove(current);
}

// Here we return this is also the exit point when all intermediate and end node properties under the object root is traversed and we processed the entire object graph successfully.

return success;
}

 

 

 

 

 

 

Writing Complex Objects to Azure Table Storage

There are several ways you can write an object into Azure Table Storage. You can inherit from TableEntity class, you can implement ITableEntity interface, you can convert your entity into a DynamicTableEntity object or you can use an Adapter pattern that takes your original entity as inner object and itself implements ITableEntity interface.

Having said all that, none of these patterns really help if you want to write complex objects to Azure Table Storage. By complex objects I mean objects with nested properties which themselves may be complex objects with their own nested properties and so on.

And that is the exact challenge I had in one of the projects I was working on, writing and reading complex objects from Azure Table Storage. In addition, these complex objects could be of different types.

This is why I really like working on enterprise level projects, the unique problems they challenge you with, force you to invent and innovate.

To solve this problem, in a most elegant and generic way I have implemented an API which allows complex objects to be written and read from Azure Table Storage. I uploaded the package to Nuget.org:

https://www.nuget.org/packages/ObjectFlattenerRecomposer/

https://www.nuget.org/packages/ObjectFlattenerRecomposer.Core/

V2.0.0 and IEnumerable Property Support

With version 2.0.0 of the ObjectFlattenerRecomposer Api in Nuget, I have implemented support for any property type that implements IEnumerable interface. That is a big change and it covers as we know most commonly known collection types like List, Array, Dictionary, their generic versions and other interfaces that inherit from IEnumerable like ICollection, IReadOnlyCollection etc. With this change these properties would be automatically converted to json strings when flattened by the api, when reading the entity back from azure, the api will recompose the original property with the correct type and correct values all transparently.

So if you need full complex object support and ability to write/read IEnumerable properties to table storage I would recommend you to get the latest version (2.0.0) of the ObjectFlattenerRecomposer Api from Nuget. Try it and hope you enjoy it 🙂 Of course all feedback is welcome 🙂

So How Does Object Flattener Recomposer API  Work?

As the name hints, there are 2 main functionality of this API.

First It flattens the complex object and turns it into a Dictionary <string, EntityProperty>. The clients (callers of the API) can at this stage assign this Dictionary to a DynamicTableEntity, set its PartitionKey and RowKey and happily write the DynamicTableEntity to AzureTableStorage.

To flatten the complex object, the API traverses the entire object graph using recursive reflection. Creates a string key by appending the names of the properties visited during the traversal from root object to the end node property (including the name of the end node property) delimited by ‘_’.  And the Value is the EntityProperty object created using the actual value of the end node property. The API then adds this (key, value) pair into the Dictionary <string, EntityProperty>. It continues this until it traverses the entire object graph of the root object and all end node properties are saved into the Dictionary<string, EntityProperty>.

(If you want to learn a bit more about its implementation and object traversal by recursive reflection, I recently published a post about it: https://wordpress.com/post/doguarslan.wordpress.com/152)

As an example, imagine object A has 2 properties P1 and P2. P1 is a class and it has a value type property P3 with value V3. P2 is a struct and it has a value type property P4 with value  V4.

So object A looks like: (P1(P3:V3), P2(P4:V4))

This object is not writable to Azure Table Storage and none of the methods that I mentioned in the beginning of the post can help writing this to Table Storage, there is no existing API that can write this to Table Storage either.

When you pass this object to Object Flattener Recomposer API, Flatten method, it converts this object into an EntityProperty Dictionary with below Key Value pairs:
“P1_P3”, EntityProperty(V3)

“P2_P4”, EntityProperty(V4)

Magic:) So now the only thing client needs to do, is new up a DynamicTableEntity object, assign this EntityProperty dictionary to it, set PartitionKey and RowKey and you guessed it, write it to Azure Table Storage.

Moving on to the next part of the puzzle, now we wrote our flattened entity to table, we want to read it back. When we read it back, we want to pass it back to the client not in the form of a flattened DynamicTableEntity but exactly in the form of the complex object that the client code passed to our API to write it to Azure Table Storage.

This is the ConvertBack method in the Object Flattener Recomposer API. This method takes in the flattened EntityProperty Dictionary as input and recomposes the complex object of type T, which was originally passed to the Flatten method to be written to Table Storage in a complete generic and transparent way.

The ConvertBack method instantiates an instance of type T and all of its properties, recomposes its original state using the flattened EntityProperty Dictionary. How does it do this? I will leave it for you to find out by downloading the package from Nuget:)

There you go, complex objects get written and read from Azure Table Storage in a complete generic, schema-less, version tolerant and queryable way. Your complex objects do not need to implement any interface nor do they need to inherit from a specific base class (like TableEntity), you do not need to implement separate Adapters, you do not need to define any schema or version, in fact your complex objects do not even need to be complex:) This API works perfectly even if the objects just have value type properties and no nested complex properties.

What is the Minimum Requirement to flatten my complex object with ObjectFlattenerRecomposer API?

The properties need to have both Getter and Setter. The Getter and Setter do not need to be public, they can be protected or private.

The other requirement is that there should not be a recursive (cyclic) reference in the object graph. The Flatten method detects a recursive reference in any part of the object graph and terminates the flattening operation.

 If there is a property that you cannot/do not want to add a Setter even a private one, then you can exclude that property from being flattened by putting the [IgnorePropertyAttribute] to it as explained below.
How do I exclude some properties from being flattened?

There may be some use cases where you may want to exclude certain properties from being flattened ie. you have some Get only properties and you do not want to add even a private Setter or the property has a recursive reference and you want to exclude it in that case all you need to do is to add [IgnorePropertyAttribute] attribute to the top of the properties you want to exclude.

Flattening Composite Objects and Recursive Referenced objects ?
A composite object is an object that has a property of its own type. Object Flattener Recomposer API can flatten and recompose composite objects of any depth as long as the properties do not have recursive references ie. referring back to the root or a parent property.

In case of recursive referenced objects, v1.1.3 and above versions of the Object Flattener Recomposer API detects the recursive references anywhere along the object graph and exits from flattening operation, returning a null result. This avoids the flattener from going into an infinite loop traversing inside the recursive path in the object graph.

Can I change the default property name delimiter which is “_” ?

Yes. From version 1.1.4.0 and on, you can specify a custom property name delimiter as part of the newly added EntityPropertyConverterOptions parameter, by setting its PropertyNameDelimiter property.

ObjectFlattenerRecomposer API in Nuget:

https://www.nuget.org/packages/ObjectFlattenerRecomposer/

Usage:

using ObjectFlattenerRecomposer;

//Flatten object and convert it to EntityProperty Dictionary.

Dictionary<string, EntityProperty> flattenedProperties = EntityPropertyConverter.Flatten(complexObject);

// Create a DynamicTableEntity, set its Partition Key and Row Key and assign the flattenedProperties of the complex object to this DynamicTableEntity.

DynamicTableEntity dynamicTableEntity = new DynamicTableEntity(partitionKey, rowKey);

dynamicTableEntity.Properties = flattenedProperties;

// Write the DynamicTableEntity to Azure Table Storage using client SDK.

//Read the entity back from AzureTableStorage as DynamicTableEntity using the same PK and RK.

DynamicTableEntity entity = [Read from Azure using the PK and RK];

//Convert the DynamicTableEntity back to original complex object.

Imagine original complexObject was of type Order.

Order order = EntityPropertyConverter.ConvertBack(entity.Properties);

That’s all:)

Contact:
Feel free to contact me for any questions/feature requests/feedback:
Email: doguvolkanarslan@outlook.com