Did you know that you can navigate the posts by swiping left and right?

A Better Approach; The DRY Approach


13 May 2019 . 7 mins : learning . Comments
#tech #coding #lessons #programming practices #python

Dry clothes are really easy to use, store and carry; then there are wet clothes: heavy, stinky and dripping.

Similar is the story for code: DRY (Don’t Repeat Yourself) is always preferred over WET (Write Everything Twice).

I’ve recently started learning .NET, ASP.NET, MVC, and related technologies, and thereon I stumbled upon the concept of DRY programming; it is a simple methodology which aims at simplifying the code everyone writes and, consequentially, make it easier to read and maintain for everyone interacting with it.

In the following essay, I’ve summarised the techniques I’ve learned so that I can go DRY in my mode and less DRY in my life.


Abstraction

Abstraction In Employee

Abstraction has been the go-to concept for simplification of complex architectures and ideas, from where more complex entities branch out with a defined common and understood base. It allows the higher level classification and sharing of similar attributes and methods between different entities. An example of this would be,

In a system where most of the methods are API calls over the network which receive JSON response from the server. Here, we can derive or wrap all such functions in a status_checker function (illustrated below). The function intercepts the status code and if it’s anything other than success, a predefined logic is executed. This saves the time (both development and execution) as the code need not be written again and again for all methods. From the maintenance point of view, if a change in the section is required it needs to be done at a single place only and the risk of missing out a place where the section might have been written is removed.

status_checker (func a, *args, **kwargs) {
	// logic for checking status using provided args
	// running func if status OK
}

*Sidenote: Python decorators are a great way to implement function interceptors as the above example. *

Another point, I took from above is that if something is repeating in the code, it’s either better as an implementation under OOP (Object Oriented Programming) model or as a separate function. As a rule of thumb,

if a section of code is written three times or more, it’s better to abstract it as a function, a wrapper or parent class

Sidenote: Principles of inheritance and polymorphism are good OOP features that simplify abstraction implementation

Please KISS

Keeping It Simple and Stupid has it’s own merits and are a great way to reduce the headache one can go through during maintenance or someone else reading the code. The first and foremost step to take is; don’t put all the brains in writing one-liners: they are complex to understand and raise the code reading time. It is always preferable to write multiple statements to make it more clear.


# this is complex and smart
return [p[:i]+[l[0]]+p[i:] for i in range(sz) for p in perm(l[1:])]

# this is simple and stupid
result = []
for p in perm(l[1:]):
  for i in range(sz):
    result.append(p[:i]+[l[0]]+p[i:])
return result

Inspiration for the above example is StackOverflow

Only God Knows

Anticipation can be a huge tool to kill over-emphasis on particular aspects of a solution that may never be reached. A simple example (taking inspiration from our first code block about status code) would be creating handlers for all HTTP response status codes while we know that the server we are connecting to will either give 200 (Success) or 403 (unauthorized access). Writing logic to take care of each and every scenario when the response can be anticipated is WET and is highly discouraged.

Another important aspect is that each function or method should handle a single scenario; an implementation of Single Responsibility Principle. Under this, one function should be used for the execution of a single task and other tasks, if any, should be handled using side-effects.

A similar concept to SRP is Single Source of Truth which emphasis on not having duplicate entries for the same data or fetching the same data from multiple sources; for single data entry, there should be a single point where all the CRUD operations for the same are done. This helps in reducing mismatch of data entry in case of a failure of communication (or execution of intermediate methods) and, in the absence of a master-slave architecture, can cause fatal system errors.

(Y)AGNI

You Aren’t Going to Need It is the principle that suggests the removal of unused and unreachable code. There are two cases possible for this: either the code is commented out but kept in case it might be needed in the future or it is inside an unreachable conditional block. In the former case, if we are using a VCS (Version Control System) there is nothing to worry and we should [safely] remove the commented code. The latter case occurs when the response or future pathways are not anticipated (example of handling all status codes when not required). These help a lot, especially the person trying to understand the code as he doesn’t have to brainstorm and find which scenarios can lead to response status code 400 when there are none.


DRY code is definitely easier to maintain, develop and improve. On a contrary note, it is very hard to even understand WET code as there are redundancies, multiple data entries and many more hurdles to “peaceful programming” that keep on building on top of each until code becomes such that no further development is possible. This has been the case with many legacy codes, which are then (if required) written from scratch with better practices. Thus,

Wet clothes smell and stink when put in closet!


Me

I'm intrigued by human psychology and code backend for videogames. I live with a philosophy to be simple, true, and kind always. I enjoy taking days slowly and writing when I learn something new - ah! that reminds me, I enjoy learning from new experiences a lot.