Comments on: Why Declarative Coding Makes You a Better Programmer https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/ Build Fast Java Applications for the Fastest Business Performance Fri, 01 May 2020 05:21:37 +0000 hourly 1 https://wordpress.org/?v=5.1.1 By: Per Minborg https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-32 Thu, 08 Aug 2019 09:24:29 +0000 #comment-32 Thanks for you comments.

Apparently, you have almost as many years as I do in terms of code experience. That is good!

It is important to remember that the article never states any code metrics for "readability" and "maintainability" and thus, it is never formally claimed that these parameters are always better/worse with any particular coding style. As you rightfully point out, there are no known serious tool that can measure said properties.

The article do however claim that "Declarative … constructs … CAN provide many benefits including faster coding, better code quality, improved readability, less testing, reduced maintenance costs and more". Seen over a greater population and a greater example set, it is very likely that this is the case. We are many working here in the office for example that think so.

The article do claim and, in fact proves, that the code metrics of LOC, Statements, Cyclomatic Complexity and Cognitive Complexity (as defined) are improved with Declarative constructs for the given examples. This is not an opinion but rather a fact.

It is highly unlikely that "reliability and maintainability" are only trumped by any other arbitrary requirement (such as performance and dependability) with a probability of 1E-12 as you state. I'll guess you mean that "readability and maintainability is important" but failed to capture that semantically. We can all agree on that. My personal opinion is that declarative code is easier to read and maintain but I know that there are people that disagree with this.

People coming along and using "clever" streams are very common. As I mentioned in previous comments, Streams are in no way obscure and has been a part of Java since Java 8 (released March 2014) it should be expected that any Java programmer worth her salt should be familiar with Streams and lambdas.

In my opinion, based on creating and maintaining one of the most popular Java ORMs on the planet, declarative constructs generally presents better performance, shorter development time, less errors, shorter code, simpler unit tests and more. However, there are cases when imperative coding could be the better choice and there are also some downsides with declarative coding, for example stack trace readability. On the other hand, you are, in my opinion, much less likely to ever read a stack trace.

I am curious to learn if you have references to articles or papers that points to the contrary of this article.

Thanks again for your comment

]]>
By: Anonymous https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-33 Wed, 07 Aug 2019 23:43:49 +0000 #comment-33 Which other code metrics do you mean support coding with imperative style?

You can not measure "readiblity and maintainablity" with existing tools. Those are way more important for 99.99999999999% of all code written. Someone not as "clever" as you is going to come along behind you and you do not want to be on the hook for something they can not maintain. All a manager will hear is "this is opaque I do not know what it does, why it does it or how, I need to spend even more time re-aquiring the requirements that this is supposed to solve, figure out if it actually meets them, if so, how and how to modify it. Which is met with "just re-write it to be clearer" and you get a silent reputation of writing crap code. 37+ years of reading and writing code tells me this.

]]>
By: Per Minborg https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-34 Tue, 06 Aug 2019 09:11:43 +0000 #comment-34 This is the evaluated code:

public class SumArrayOther implements SumArray {

@Override
public long sum(int[] arr) {
return sum(0, arr, 0);
}

private static long sum(long head, int[] tail, int index) {
while (index != tail.length) {
head = head + tail[index++];
}
return head;
}
}

]]>
By: Per Minborg https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-35 Tue, 06 Aug 2019 09:04:25 +0000 #comment-35 Thanks again for yet another proposal. This code works perfectly well and it has the following code metric properties:

LOC: 15
Statements: 4
Cyclomatic Complexity: 3
Cognitive Complexity: 1

So, it is slightly worse than the two solutions devised in the article but nevertheless interesting to see.

I suspect that the performance of this solution is not as good as the solutions provided in the article but that is another story and perhaps an issue for another article.

]]>
By: Per Minborg https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-36 Tue, 06 Aug 2019 08:38:25 +0000 #comment-36 Thanks for this alternate solution!

After fixing a zero-size array bug above and adapting to the problem interface, the recursive code looks like this:

@Override
public long sum(int[] arr) {
return sum(0, arr);
}

private static long sum(long head, int[] tail) {
return tail.length == 0
? head
: sum(head + tail[0], Arrays.copyOfRange(tail, 1, tail.length));
}

However, the code will only work for small arrays. Larger arrays will produce a StackOverflowError because the thread's stack is limited. Also, the code will exhibit worse code metrics compared to both the perviously devised Declarative and Imperative solutions in the article.

Interesting solution anyhow and good to learn how this solution stacks up against others.

]]>
By: Per Minborg https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-37 Tue, 06 Aug 2019 08:05:06 +0000 #comment-37 Thanks for your comment.

The solution devised above is indeed a declarative solution where the portion "IntStream.mapToLong(i -> i)" is the declarative part where lower level functions are composed to yield a higher order function. The operation ".sum()" is then applied to said construct to compute some value.

Streams are in no way "magic". On the contrary, it is a well established and proven part of Java for many years.

I am curious to see evidence supporting the statement that imperative code is much better given that standard code metrics indicates just the opposite. Which other code metrics do you mean support coding with imperative style?

The fact that the exemplary problems were structured as an interface and the solutions implementing such interfaces does not have any bearing on the solution being imperative or declarative or of some other sort.

It is true that the example you show breaks up declaration of a class and computation into two parts. However, this is not the generally used definition of "declarative constructs".

Thanks again for your comment.

]]>
By: Anonymous https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-38 Tue, 06 Aug 2019 00:55:42 +0000 #comment-38 class Main {
public static void main(String[] args) {
System.out.println(sum(0,new long[]{1,2,3,4,5},0));
}

private static long sum(long head, long[] tail, int index) {
while (index != tail.length) {
head = head + tail[index++];
}
return head;
}
}

]]>
By: Anonymous https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-39 Tue, 06 Aug 2019 00:44:48 +0000 #comment-39 import java.util.Arrays;

class Main {
public static void main(String[] args) {
System.out.println(sum(0,new long[]{1,2,3,4,5}));
}

private static long sum(long head, long[] tail) {
return tail.length == 1 ? head + tail[0] : sum(head + tail[0], Arrays.copyOfRange(tail, 1, tail.length));
}
}

]]>
By: Unknown https://speedment.com/why-declarative-coding-makes-you-a-better-programmer/#comment-40 Mon, 05 Aug 2019 19:41:39 +0000 #comment-40 > public class SumArrayDeclarative implements SumArray {

@Override
public long sum(int[] arr) {
return IntStream.of(arr)
.mapToLong(i -> i)
.sum();
}
}

This is not a declarative solution. You are doing the computations still right inside the function. Just doing it in some ugly and not clear way. Some streams and magic for such a simple task. The imperative code is much better, much clearer because it does not use additional streams magic and does not required the reader to know that magic.

The declarative approach is something like this

public class ArraySum implements Number {
private final int[] arr;

public ArraySum(final int[] arr) {
this.arr = arr;
}

@Override
public long longValue() {
long sum = 0;
for (int i : arr) {
sum += i;
}
return sum;
}
}

Number sum = new ArraySum(arr);

In this example I'm just returning a object, a Number which is a sum of array elements. I'm declaring that it is the sum of array elements. No computations is done at that moment. I'm just declaring.

]]>