• Home
  • Quick Bytes
  • Algorithms
  • Java
  • iOS
  • Android
  • Certifications
  • About Me

Lets Code Them Up!

  • Clean Architecture – Chapter 8 | OCP | Open Closed Principle

    April 1st, 2023

    Open Closed Principle (OCP) is the O in SOLID principles. We already read about S (SRP) in previous post.

    A software artifact should be open for extension but closed for modification

    Robert Martin

    To better explain this, let’s go through the example provided by author. 

    Let’s say, we have a system that displays financial summary on web page. The data on page is scrollable and negative numbers are marked in red. Now let’s say the stakeholders ask that the same information be rendered into a report printed on black and white printer. Negative numbers should be surrounded by parenthesis and report should be properly paginated. 

    This would mean the existing system should change, new code needs to be written. But to extent of the change would depend on the architecture. A good architecture would try to minimize the changes needed to extend functionality, ideally zero.

    How can we achieve software that can be extended with zero change? 

    1. By following single responsibility principle in identifying components that have different reasons to change and separating them. This would ensure that change in one component would not need change in another component. 
    2. Organizing dependencies properly (dependency inversion principle)
    3. Making sure the behavior can be extended easily

    If our architecture looks like as shown in above figure, let’s evaluate if it follows OCP and is easy to extend – 

    1. We have divided the whole architecture into components. There is View layer which is responsible to display the results, Presenter layer which is responsible to do the processing on data so that it becomes ready for Views. Then we have controller layer, which is responsible to get the data from the Interactor and send it to  the presenters. The Interactor is responsible to extract data from database and send it to controller. It acts as a layer between the controller and database. Each component has a single responsibility. 
    2. The arrows are single directional. They show that component A depends on component B, eg. Web View depends on Screen Presenter. If there are any changes in View, there won’t be any changes needed in Presenter. If there are any changes in Presenter, there won’t be any changes needed in Controller and so on. Look how that Interactor is safe from any changes in Views/Presenter/Controller/Database. It also shows dependency inversion, both Controller and Database depend on it. 
    3. There is like a hierarchy of protection based on notion of levels. Interactors are highest level, the are the components that deal with the central logic of system, and so are most protected. Controller are next in level, they might not be peripheral for Interactor, but are central to Presenters and are thus are less protected . Presenters are higher than Views, but lower than controllers and so are less protected than controller. Views are the least protected. This is OCP at architecture level.
    4. Say we want to add another mobile view to this system, we would just need to add the Mobile Presenter and Mobile View, no other component would need to change, we can see system is easily extensible. 

    Thanks for stopping by! I hope this gives a good preview into OCP. Eager to hear your thoughts and chat, please leave comments below and we can discuss. 

     

     

  • Clean Architecture – Chapter 7 | SRP | Single Responsibility Principle

    March 26th, 2023

    The next few chapters discuss how SOLID principles are relevant at architecture level and discusses them briefly starting with SRP. 

    S in SOLID principles is called Single Responsibility Principle (SRP).

    It is quite normal to assume that SRP means every module should do just one thing because of the inappropriate name. Before reading this chapter, even I had the same misconception. Let’s clear this up in this post.

    The most accepted definition of SRP is – 

    A module should have one, and only one, reason to change. 

    A software system is changed to satisfy stakeholders and users. So the users and stakeholders are the “reason to change”. The users and stakeholders can be grouped into one actor that require the software to change. So the author gives this as final definition of SRP –

    A module should be responsible to one and only one actor .

    Now, let’s look at the ways in which this principle is violated to better understand it. 

    1. Accidental Duplication

    Let’s say we have class A that has three methods method1, method2, and method3. Class B’s method depends on method1, Class C’s method depends on method2 and Class D’s method depends on method3.

    We can clearly see that Class A is violating SRP as we have three different actors depending on it’s method. Say, method1 and method2 depend on some logic in methodE of Class E. If methodB requires a changes in methodE’s logic, goes ahead and makes the change, tests and deploys it. Later methodC finds out the issue it is facing is because of change in methodE. All this can be avoided if we separate code from a class that different actors depend on.  

    2. Merges

    We all see this fairly often, two developers are working on same class and there is merge conflict when they push their code which needs to be resolved. 

    Let’s say developers from team B and team C are working on Class A, they make some changes which is now resulting in conflict. Now both the teams have to come together solve the conflict before pushing the changes. 

    All this can be avoided if we separate code that supports different actors. 

    Solutions

    One of the solutions is to have each function is separate functions from data, where in each class depends on the data which is simple data structure without functions. 

    For example, say we have Employee class with three functions calculatePay, reportHours and saveEmployee which are responsible to three different actors respectively. Instead, we can separate out the three functions into three classes where each class will be responsible to one actor. So, we can have PayCalculator, HoursReporter, and EmployeeSaver each having their own functions that depend on EmployeeData. It leads to problem of having three different classes and separate ways to initialize them, for which facade pattern can be used. Now each class follows SRP, as each class is responsible to only one actor. 

    Thanks for stopping by! I hope this gives a good preview into SRP. Eager to hear your thoughts and chat, please leave comments below and we can discuss. 

  • Clean Architecture – Chapter 6 | Functional Programming

    March 18th, 2023

    To explain Functional Programming, the author uses an example of square of numbers written in clojure (derivative of lisp)

    (println (take 25 (map (fn [x] (* c c) ) (range))))
    

    Let’s break it down to understand it as I am also new to this language. In clojure everything in brackets is a function. Starting from inner most function the execution would be something like this – 

    1. Range function returns a never-ending list of integers.
    2. The list is passed to map function, which calls the square function on each integer in the never-ending list of integers
    3. This never ending list of squared integers is passed to take function which returns new list with only first 25 elements
    4. println function prints the list of 25 elements

    Let’s see how the same program would look in Java

    for(int num = 1; num <= 25; num++)
    {
          int square = num * num;
          System.out.println(num);
    }
    

    The difference between Java and Clojure is – 

    1. In Java there is a mutable variable num whose value changes stare with execution
    2. In Clojure, there is no mutable variable. The value of variable x is initialized but never modified. In functional programming, variables don’t vary. They are immutable.

    What’s the importance of immutability when it comes to architecture? 

    Ans – All race conditions, deadlock conditions, and concurrent update problems happen because of mutable variables. Think, if. there is no variable to update there will be no concurrent update problem. All these will go away if we have processes that work on immutable variables.

    The author asks architects to ask themselves this question – Is immutability practicable?

    His ans – Yes, immutability is practicable, but with certain compromises. 

    First compromise is that we need to segregate system into components that are mutable and immutable. The immutable components will be implemented using functional programming and use immutable variables. They can talk with the mutable components and allow for state of variables be mutated. This does expose the components to problems of concurrency and it is common to use some sort of transactional memory to protect the mutable variable against race conditions and concurrent updates. Architects must try to move as much processing as possible in to immutable components.

    Second compromise is Event sourcing. It is a strategy wherein we store transactions, but not state. When state is needed, we apply all transactions from the beginning of state. 

    Consider the example of banks. They maintain account balances of millions of customers. It mutates those balances when the withdrawal and deposits are made. Say, instead of mutating the account balances, we store only the deposit and withdrawal transactions. And when required, we create the account balance using the transactions from start of account creation. This approach doesn’t need the mutable variables. 

    Yes, it would need lot of memory and processing power to maintain the numerous transactions and compute the balance when needed. This could be optimized, like we store state everyday at midnight. So if anyone wants account balance next day, we would just need to compute transactions starting from midnight. 

    In this approach we are storing transactions, so nothing ever gets updated or deleted from our data store. This makes the data store CR instead of CRUD. No deletion/updation and so no concurrent update problem.

    With the advancement of computer technology, now we have enough memory and processing power that this immutablility can be achieved. 

    To nail his point on benefits of functional programming and immutable variables, he gives the example of our source code control system. 

    Thanks for stopping by. Hope this gives a summary of functional programming. Eager to hear your thoughts and chat, please leave comments below and we can discuss. 

  • Java Optionals – Can you use them in models?

    March 11th, 2023

    Let’s say, we have a model class called Employee. Some of the fields of Employee could be null. If these null values are not handled properly by the caller, this could lead to NPEs(Null pointer exception). Optionals is the library provided by java for cleaner way to handle null values and avoid NPEs. So it makes sense to use Optional methods in our model class.

    But there is a catch, as per this response on stack overflow, Java optionals were not designed to be 

    1. passed as parameters
    2. to be field of an object
    3. when return is an array/list of objects.

    Java optionals are not serializable and so if we want to serialize/deserialize our model, optional fields would make that difficult.

    If we would want our model to have optional fields, then we will have to find other ways to do that. Some of the different ways to use optionals in models are – 

    1. As jackson supports serializing/deserializing objects with optional fields, use them in your project/package. (src)
    2. Spring 4.x supports serializing/deserializing objects with optional fields, so that option can be looked into.
    3. Create your own optional which is serializable/deserializable.

    Thanks for stopping by. Have you ever come across a situation where you have to use Optionals where they are not intended to be? Share your thoughts by adding comments below.

  • Clean Architecture – Chapter 5 | Object Oriented Progrmming

    March 5th, 2023

    What is Object Oriented?

    I have always come across that object oriented (OO) is a way to model real world. It was the same definition, while I was in bachelors, same while I was doing masters. The author labels this definition as evasive and doesn’t tell us what OO is. He refers perhaps we accepted this definition because it makes software closer to us as it emulates real world

    The other popular definition is “OO is combination of data and functions”. It implies o.f() is different than f(o), which is absurd as programmers have been passing data structures in functions long before OO was discovered. 

    Yet another definition is OO is a proper mixture of encapsulation, inheritance and polymorphism. And then author goes on to refute this definition as well, ultimately defining OO by the end of the chapter. Let’s see what argument he makes against all these three.

    Encapsulation

    OO languages provided easy way to encapsulate both data and functions into one object. But this is not unique to OO languages, C even before OO had perfect encapsulation.  

    In C, we used to declare the data structures and functions in header files and then implement them in implementation files. The users of the data structures never has access to the implementations. (we always import header files in other C files, and use data structures and functions from there)

    Modern programming languages, removed this distinction between header and implementation and combined them into one, thus diluting encapsulation. So in a way modern OO languages don’t provide any improvement on encapsulation, rather degrade it. So we cannot say OO depends on strong encapsulation.

    Inheritance

    Inheritance is redeclaration of group of variables and functions within an enclosed scope. In C, it was possible to manually do this. Safe to say, inheritance was there in pre OO languages in some form. Modern OO languages build upon that concept, making it more easy to do.  

    Polymorphism

    Polymorphism is an application of pointers to functions. In C, C++, there were pointers (referring to location of a resource) that were passed between functions. This kind of polymorphism was manual, and the programmers need to be careful to follow the pointers safely to avoid errors. Although modern programming languages didn’t start polymorphism, they have made its development simple and intuitive.

    Dependency Inversion – the real power of OO

    Traditionally, in structured programming languages, the flow of dependencies followed the flow of control of program. It has been done using include in C, import in Java, etc.

    Polymorphism enables us to control the flow of source code dependencies and keep it separate from the flow of control using dependency inversion.

     

    OO is the ability through the use of polymorphism, to gain absolute control over every source code dependency of the system. It allows the architect to create a plugin architecture, in which modules that contain high level policies are independent of modules that contain low level details. These modules can be developed independently of each other.

    Robert Martin.

    Thanks for stopping by! See you in next post! Hope it was good byte on object oriebted methodoloty. Don’t hesitate to start conversation using comments below.

  • Clean Architecture – Chapter 4 | Structured Programming

    February 25th, 2023

    In this chapter, the author takes us back in time to when Dijkstra started working as programmer.

    Dijsktra was studying both theoretical physics and computer programming, but was fascinated by programming and decided to pursue it as his career.

    He wanted to apply mathematical proofs to programming. His vision was that programmers would use structures proven by mathematical proofs and use code to tie these structures together, which would then prove themselves correct.

    While trying to prove computer problems mathematically, he had to break them down into sub problems. During this work, he found that use of goto statement makes it hard to divide problems into small enough functions, thereby making them unsolvable using mathemetical proofs.

    He also discovered certain control statements like sequence, if/then/else and do/while could be proven mathematically. He proved sequence using enumeration. Enumeration is a technique that traces inputs of sequence to output of sequence. He proved selection (if/then/else) by reapplication of enumerations. If the selected path gave the same result as expected path, then it proves the selected path correct. For induction, his logic was, if it works for one enumeration, and N enumerations then it would also work for N+1 enumeration. 

    Modern structured programming’s principle to break large system into multiple modules which get further broken into functions and so on, is based on his work of breaking problem in to small provable units. He was not able to use mathematical proofs, instead we turned to science to get that provability.

    Just like in science, we don’t try to prove a statement true, instead try to prove that statement false. If we cannot prove it false after enough experiments, we deem it provable for our purposes. Like this we break software system into small testable/falsifiable units which can be proven wrong individually and also collectively as a system. 

    Today, we break a problem given to us into small functions, code those functions and then write test-cases to prove those functions wrong. 

    For any feature we develop, our testers/Quality Assurance Engineers perform testing with all possible permutation/combination they can think of. If they don’t find any bugs, they give green light to release the feature. Even if they don’t find bugs, there is possibility that there are still bugs hidden in the system. For present, we just took a decision that it is good to go. 

    Testing shows presence not absence of bugs.

    Dijkstra

    These falsifiable units makes structured programming important today. From big system to its smallest unit, everything is falsifiable. 

    Thanks for stopping by! Hope this gives you a perspective on structured programming. Post comments to start a discussion.

    Notes on previous chapters can be found here.

    See you in the next post.

←Previous Page
1 … 5 6 7 8 9 … 22
Next Page→

Proudly powered by WordPress

 

Loading Comments...