1. 1.       Do not repeat yourself (DRY) – check if you have added something to CPD reports. CPD can be easily taken from tools like PMD.
    2.       Take care about methods:
    ·         Do not create methods for “side effects”. They can drive you crazy in case of bugs.
    ·         Methods shouldn’t be doing multiple things.
    ·         Try to switch over to “switch” statement rather than nested “if”.
    ·         Make sure methods use abstractions rather than concretions.
    ·         Use fewer arguments.
    ·         Catch as specific exceptions as possible (use exceptions instead of returning null).
    ·         Prefer “early return” over “single return” policy.

    3.       Take care about classes:
    ·   Follow “single responsibility”, “open closed” principles.
    ·   Classes should be small unless you have strong reason for them to be large (Smaller classes are easier to grasp. Classes should be smaller than about 100 lines of code. Otherwise, it is hard to spot how the class does its job and it probably does more than a single job).
    ·   Avoid multiple languages in one file/class (C#, java, html, javascript, xml, English, French…).
    ·    Use explanatory variables.
    ·   Try and use, small and immutable objects.
    ·   Prefer composition over inheritance.
    4.       You should reconsider design in case method crosses 10 or class crosses 100 line limit.
    5.       Avoid manual memory management.
    6.       In case you are using any DI framework like spring, guice etc. don’t spread your dependencies across code and configuration files (java, c#, xml). Try keeping them either in code or in xml files. Mixing them will give you nightmares.

    Some of the tools that will be helpful for developing quality code are checkstyle, pmd, javaNCSS, coverlipse, eclipse metrics plugin, sonarqube etc. These are just some recommendations not hard lines. These have proved beneficial for most of the projects/scenarios. There could be anti-patterns to them too, on case-by-case basis. Practicing methodologies like agile, TDD etc. and standard frameworks like guava, spring etc. can also help in producing quality code.
    0

    Add a comment


  2. Around two years back I was introduced to some concepts like Big Data, Distributed Computing, NoSQL and Guava api. This lead to my introduction to the term “Functional Programming”. At that time I just parked this term and continued with my interest in NoSQL space but as my work and interest grew in these areas, more I heard about benefits for using this style. A couple of weeks back I got chance to spend time on it. I started up this as learning some DSL (domain specific language [for Big Data products]) but soon realized that this is much more than what I expected. I found that it brought new clarity to my thinking about the design of types and functions. It also allowed me to write more concise code. I also concluded that functional programming is a better fit for many of the unique challenges of our time, like working with massive data sets and remaining agile as requirements change ever more rapidly and schedules grow ever shorter.

    It’s hard to believe that objects, which have worked so well in the past, could be any less valuable today, isn’t it? For me, my growing interest in functional programming isn’t a repudiation of objects, which have proven benefits. Rather, it’s a recognition that the drawbacks of objects are harder to ignore when faced with the programming challenges of today. Both FP and OOP are tools, not silver bullets. Each has advantages and disadvantages. For me, functional programming offers the best approach to meet the following challenges, which I face every day like,
      
    • We need to write better concurrent programs.
    • Most of our programs do just, “Data Manipulation”. I personally worked a lot in Big-Data space and can tell you that Objects are big overhead.
    • We need to be agile (ORM is a classic example about our love for Objects. Working directly with more fundamental collections of data minimizes the overhead of working with object models).

    Most of the successful examples of reusable libraries are platforms that defined their own standards that everyone had to follow like spring, Eclipse plugin api, apache commons etc. They have their own custom APIs that we must conform to. For the rest of the code we need, we still rewrite a lot of it project after project. Hence, object-oriented software development isn’t the “component assembly” as we hoped. There are no standards in “Object-based” programming like digital electronics which enable innovative, better and cheaper designs.

    Agility

    Day by day our release cycles are getting shorter. All of us are feeling the pressure to get work done more quickly, without sacrificing quality, of course. Today, for most projects, understanding the domain precisely is less important than delivering some value quickly. If we misunderstand some aspect of the domain, we can fix those mistakes quickly when we do frequent deployments. If careful modeling seems less important, faithfully implementing the object model is even more suspect today than before.

    Note: I’m not trying to convince you to abandon objects altogether or to become an FP advocate. I’m trying to present here a bigger toolbox and a broadened perspective.
    0

    Add a comment


  3. Functional programming, in its “purest” sense, is rooted in how functions, variables, and values actually work in mathematics, which is different from how they typically work in most programming languages.  In functional programming, programs are executed by evaluating expressions, in contrast with imperative programming where programs are composed of statements which change global state when executed. Functional programming typically avoids using mutable state.

    Haskell Curry (for whom the Haskell language is named) helped develop Combinatory Logic, which provides an alternative theoretical basis for computation. Combinatory Logic examines how combinators, which are essentially functions, combine to represent a computation. They are useful for representing the steps in a planned/building blocks of computation, which can be analyzed for possible bugs and optimization opportunities.

    History
    The first language to incorporate functional programming ideas was Lisp, which was developed in the late 1950s and is the second-oldest high-level programming language, after Fortran. The ML family of programming languages started in the 1970s, including Caml, OCaml (a hybrid object-functional language), and Microsoft’s F#. Perhaps the best known functional language that comes closest to functional “purity” is Haskell, which was started in the early 1990s. Other recent functional languages include Clojure and Scala, both of which run on the JVM but are being ported to the .NET environment.





    Basic Principles of FP

    Avoiding Mutable state
    X2 + Y2 = Z2
    If I give you values for the variables x and y, say X=3 and Y=4, you can compute the value for Z (5 in this case). The key idea here is that values are never modified. It would be crazy to say 3++ (X++), but you could start over by assigning new values to the same variables.

    Why should we avoid mutating values?
    i. Allowing mutable values is what makes multithreaded programming so difficult. If multiple threads can modify the same shared value, you have to synchronize access to that value. If you make a value immutable, the synchronization problem disappears. Concurrent reading is harmless, so multithreaded programming becomes far easier.

    ii.   Immutable values relates to program correctness in other ways. It is harder to understand and exhaustively test code with mutable values, particularly if mutations aren’t localized to one place. Some of the most difficult bugs to find in large systems occur when state is modified non-locally, by client code that is located elsewhere in the program.

    Defensively copying objects could be an option to mimic Immutability but this could prove to be an expensive operation as and when objects become large for example, large list of Orders.  What happens when the list of orders is supposed to change, but it has become huge? Should we relent and make it mutable to avoid the overhead of making big copies? Fortunately, we have an efficient way to copy large data structures; we’ll reuse the parts that aren’t changing.

    Functional programming encourages us to think strategically about when and where mutability is necessary. If we encapsulate mutations in well-defined areas and keep the rest of the code free of mutation, we improve the robustness and modularity of our code. We still need to handle mutations in a thread-safe way. Software Transactional Memory and the Actor Model give us this safety.

       Functions as First Class values
    In OOPs, we are accustomed to passing objects and primitive values to methods, returning them from methods, and assigning them to variables. This means that objects and primitives are first-class values in OOPs.  A function is more general to method. It is not attached to any particular class or object. Therefore, all instance methods are functions where one of the arguments is the object. For example, in java you can’t pass a method as an argument to another method, return a method from a method, or assign a method as a value to a variable.

       Lambdas and Closures
    The term lambda is another term for anonymous function. It comes from the use of the Greek lambda symbol λ to represent functions in lambda calculus.  JDK8 will introduce a syntax for defining anonymous functions. Here is what the planned syntax looks like:

    public FunctionalHelloButtonApp() {
         button.addActionListener(
    #{ ActionEvent e -> System.out.println("Hello There: event received: "+e) }
    );
    }
    A closure is formed when the body of a function refers to one or more free variables, variables that aren’t passed in as arguments or defined locally, but are defined in the enclosing scope where the function is defined. The runtime has to “close over” those variables so they are available when the function is actually executed, which could happen long after the original variables have gone out of scope! Java has limited support for closures in inner classes; they can only refer to final variables in the enclosing scope. For example,
    scala> var more = 1
      more: Int = 1
      scala> val addMore = (x: Int) => x + more //
      addMore: (Int) => Int = <function>

     High Order Functions
    Functions that take other functions as arguments or return them as results. They are powerful tools for building abstractions and composing behavior. Higher-order functions allow nearly limitless customization of standard library types, like Lists and Maps, and also promote reusability. Here is a function apply which takes another function f and a value v and applies function f to v:

    def apply(f: Int => String, v: Int) = f(v)
    For example,
    class Decorator(left: String, right: String) {
      def layout[A](x: A) = left + x.toString() + right
    }

    object FunTest extends Application {
      def apply(f: Int => String, v: Int) = f(v)
      val decorator = new Decorator("[", "]")
      println(apply(decorator.layout, 7))
    }

       
    Side effect free Functions
    Another source of complexity, which leads to bugs, are functions that mutate state, e.g., setting values of an object’s field or global variables. In mathematics, functions never have side effects, meaning they are side-effect-free. For example, no matter how much work sin(x) has to do, its entire result is returned to the caller. No external state is changed. Being able to replace a function call for a particular set of parameters with the value it returns is called referential transparency.

    Side-effect-free functions make excellent building blocks for reuse, since they don’t depend on the context in which they run. Compared to functions with side effects, they are also easier to design, comprehend, optimize, and test. Hence, they are less likely to have bugs.

       Recursion
    Functional programming in its purest form doesn’t allow mutable values. That means we can’t use mutable loop counters to iterate through a collection! For example,

      for(int i=0; i < size; i++)

    The classic functional alternative to an iterative loop is to use recursion, where each pass through the function operates on the next item in the collection until a termination point is reached. Recursion is also a natural fit for certain algorithms, such as traversing a tree where each branch is itself a tree.

    However, each recursion adds a new frame to the stack, which can exceed the stack size for deep recursions. Tail-call recursions can be converted to loops, eliminating the extra function call overhead. Unfortunately, the JVM and the Java compiler do not currently perform this optimization (for details click here).



       Declarative v/s Imperative Programming
    Finally, functional programming is declarative, like mathematics, where properties and relationships are defined. The runtime figures out how to compute final values. The definition of the factorial function provides an example:

      Factorial(n) = 1        if  n=1
                            n *  factorial(n-1)   if n > 1

    Object-oriented programming is primarily imperative, where we tell the computer what specific steps to do. For example,

    public static long declarativeFactorial(int n) {
    assert n > 0 : "Argument must be greater than 0";
    if (n == 1) return 1;
    else return n * declarativeFactorial(n-1);
    }

    public static long imperativeFactorial(int n) {
    assert n > 0 : "Argument must be greater than 0";
    long result = 1;
    for (int i = 2; i<= n; i++) {
    result *= i;
    }
    return result;
    }


    Declarative programming is made easier by lazy evaluation, because laziness gives the runtime the opportunity to “understand” all the properties and relations, then determine the optimal way to compute values on demand.
    0

    Add a comment

Blog Archive
About Me
About Me
Loading
Dynamic Views theme. Powered by Blogger. Report Abuse.