Wednesday, March 1, 2017
Generating model with inheritance from swagger specification
BTW I must admit I like more code formatting options on ghost platform than what I have here with blogger.
Saturday, January 21, 2017
The great red dragon and the novice programmer
As a novice software developer at some point of time you will find enlightenment. You will understand what is the source of Power. Power of perfect code development. Power of ideal expression ideas to text. SOLID and clean, intentional and free of any accidental complexity.
You will desire that Power. Like the Pilgrim admired the power of The Great Red Dragon. But still you need a transformation. Pilgrim needed his victims to see his beauty, as he himself admired the Red Dragon. You will instead look at code you work with. The real code. Ugly. Legacy. Half year old code written on 2 releases backward Spring version. You will show your vict... sorry, colleagues that bad code. And yourself as a powerful Red Dragon. But... You're not yet him.
You need your transformation. I was there too. Now I know. Please keep in mind one thing. Consult your more experienced colleagues before you start making that code better. Example from my transformation.
I spent some time years ago to refactor piece of code using collection to keep objects of various classes. Then cascade of instanceOf... This was looking for me as an unacceptable implementation. Unfortunately, my employer would have been more happy if I had focused on my tasks instead of refactoring code that was correctly working since years. From his perspective my hard work was not considered as productive. Now I know I just was not able to recognize which part of system needs what kind of refactoring.
Here I must refer to Procent's excellent talk with Jarek Palka (in Polish). You can find out a lot of important hints regarding working with legacy code. Which is code you have just commited. One of hints is why compulsive refactoring may affect your projects and may cause inability to deliver.
After years I learnt that system I was working with was actually quite good thanks to good design and correct, efficient, event driven architecture. As a young developer, influenced by Clean-Code evangelism, I was focused on local parts, not on wider scope. Lot of implementation details were given to novice programmers and far from ideal. They SHOULD be better, but system was good enough to resist local code ugliness. Please try to learn what is important in your system first, before you start assuming that whoever wrote some piece of code was an ignorant or does not even know the programming language. Remember you have not yet transformed into The Great Red Dragon.
Sunday, December 4, 2016
Using groovy for tests
So with pleasure I am now discovering really nice points of using Groovy - as language that powers the tests and complements the Java main sources. It turns out that even with no frameworks mentioned above, you can benefit just from using Groovy in your test. Here are the reasons:
- You already know almost all of syntax. Old good Java code will probably just work. It is not like JavaScript, which is similar to Java just in name. Rest things you need you can find in documentation - which is quite good and answers most of my questions.
- Forget semicolons, alias imported objects, use list and map literals, multiline strings, use def. Almost like Scala.
- No more @VisibleForTesting. Groovy allows you to break object members visibility. Maybe it is not best idea to look into internal state of objects, but now you can. At least tested methods do not need to be kept in package visibility.
- Power assert. This looks just like Java assert. But output on your console when there is a failure... I just love this feature. Just take a look:
Assertion failed: assert apiResponse.code() >= 200 && apiResponse.code() < 300 | | | | | | | | 404 true | | 404 false | | retrofit2.Response@42d0a255 | false retrofit2.Response@42d0a255 - BigDecimal everywhere. 42.0 is not a float any longer. If your code has something in common with money you can feel relief.
- @TypeChecked. Why not just use compiler? With Groovy you can! It is so nice when machine corrects your errors.
Friday, October 7, 2016
IT Aristocracy to guillotine! How to treat IT head hunters?
Dear programmers!
I know you get 100 calls from desperate head hunters each week. I am aware, they are disturbing our flow of mind and taking us from zone away so we need to spend counterproductively next half hour to recover. But, hey, isn't that you who posted your phone/email on linkedin and N other jobboards along with shiny CV full of keywords? Is it more or less ridiculous than guys posting their ID into facebook? Have you expected that none of invited to your professional/social network recruiters ever call you? They may of course have sometimes be prepared to talk to you less than expected. Not knowing all that 3,4 letters acronyms and not knowing technology stack. That's right. They have no clue. That is why YOU are doing the job worth 6x more that what people you talk to by phone earn. They just have not dedicated half of their lives to profound depths of technological magic.Nothing bad will happen also when we expose unprofessional behavior on the other side and talk about problems in our two-way communication. I am also aware not everyone is able to do it in such an elegant form as Rafal did.
Sometimes all of us have bad day, or just have been contacted by company which fired them 3 years ago. I can understand that each of us could behave
But primitive, vulgar offence is not "unprofessional behavior"! That is not acceptable!
Otherwise we, as the "computer people" will receive back from our society just hatred for being vulgar jerks. Just imagine that could have happened just before this or next government is run out of
One day, sooner or later, you will be looking forward to change your job. One day you will wish the head hunters to call you, and treat you not like just one more CV from million. That people are really able to help you get where you want. Unless you're a dick.
TL;DR If you are frustrated buy the rubber duck! Never offend head hunters.
Thursday, May 19, 2016
Changing merge request target branch in gitlab
Yes, it's possible with API usage.
There is even a script that chamges target branch with minimal configuration.
Gitlab is increasingly popular alternative for Github, commonly used by corporations that are able to save monthly fee for Github. It's open source project and front end and its usability seems to be still behind commercial and successful predecessor.
In my opinion Merge Requests are functionality that is exceptionally affected by suboptimal design. You just need to get used to it and train yourself not to click big green 'Click me' button, which causes MR to be merged. And changing the target branch of merge request seems to be impossible.
Thanks to careful readers among my colleagues, I have found out that this option exists, however only way to do it is to use Gitlab API. The API (similarly to Jenkins) utilizes concept of private token. It is a secret that allows a user to authenticate using unique token instead standard username and password. Maybe it is not most secure way, but certainly that is easy and convenient. Each HTTP request to Gitlab API that is performed in some user context, must contain that private token. It may be sent as a header or url parameter. Depending on your deployment configurationone of that ways may or may not be disabled ;> Url parameter worked for me quite well.
To edit a Merge Request we need to know project it relates to, as well as MR identifier, which is not same as visible in GUI (that one is referred to as iid, unique in project scope).
Operation will take 3 HTTP calls. First is ment to retrieve project id by its name.
GET /projects/search/:name_to_findI assume there are no more than one projects found by given name.
Second will convert id from GUI to MR id.
GET /projects/:id/merge_requests?iid=42or you can select manually from all opened MRs.
GET /projects/:id/merge_requests?state=openedKnowing project id and MR id we can now update target branch by sending simple json object carrying new target branch as a value.
PUT /projects/:id/merge_request/:merge_request_id
{ "target_branch": "the_target_br" }
In my case I had to remove plural form `s` from merge_requests in url (that was different from API documentation, but I assume it's change in some other version of Gitlab).
I was happy this option was possible, however I must admit I had to write the script to make the changing user friendly.
Saturday, April 2, 2016
massive directory name case change
So let's automate that. Solution would be to recursively visit each directory and in case its case is wrong - rename. You can have that in java, I would rather be happy to have that in script, however I am not sure whether scripting cmd or bash port on windows will actually handle that rename sanely.
Fortunately there is nice tool in python that accomplishes the same goal -
os.walk. Usage is trivial and script is portable to any platform. File system paths can be also abstracted easily with os.path.join. There is even a method in python string that checks case of whole content - so you will not write any extra loop iterating over characters. Python handles nicely filtering in list comprehensions - so it is possible to use the condition in for statement.
from os import walk, rename
from os.path import join
for (dirpath, dirnames, filenames) in walk( join('src', 'main', 'java') ):
for d in [f for f in dirnames if f.isupper()]:
rename(join(dirpath, d), join(dirpath, d.lower()))
As you can see some APIs may be even more developer friendly than what is in Java standard.
Now came the difficult part - for some reason git was unable to recognize character case change in filenames. It happens that some default on windows is aligned with os approach to case sensitivity. Making git see the difference is changing its configuration:
git config core.ignorecase false
Monday, March 21, 2016
Guava's Optional defficiencies
Guva used to be a most handy toolbox for modern (post-Java 5) projects. It was able to leverage new features and quickly became even more popular than old, good apache-commons (in my opinion some commons classes are still indispensible). Lot of ideas introduced by googlers behind Guava were incorporated into official Java releases (mostly 8, however in 7 you may find some pieces of API visibly inspired by spirit of Guava helpers).
One of most popular innovations was Guava's approach to bringing Scala's Option[T] into world of Java. I assume idea is known and I hope also readers would agree with me that derogating `null` values would be a benefit for each developer as well for end users. After very enthusiastic reception, some critical voices could have been heard. Namingly Guava's Optional was missing important feature to call it a monad. That was an offence to real functional programmers.
Is that problem really that severe? Well, Optional is by now integrated very well with other nice Guava's classes. This is still tempting to use it along with eg. FluentIterable, which has brought Stream-alike API into pre-Java 8 development. It can greatly be used to address deficiency mentioned above. Consider following code:
public static <In, Out> Optional<Out> flatMap(Optional<In> in, Function<In, Out> function) {
Function<Out, Iterable<Out>> asIterable = asIterable();
return FluentIterable.from(in.asSet()).transform(function).transformAndConcat(asIterable).first();
}
private static <In> Function<In, Iterable<In>> asIterable() {
return new Function<In, Iterable<In>>() {
@Override public Iterable<In> apply(In input) {
return Optional.fromNullable(input).asSet();
}
};
}
Using the function above we managed to implement quite succint version of `flatMap` for Optional. We could now conclude, everything's fine, we have our monad now, and everyone's happy.
But...
There is more problematic issue with this implementation.
The issue that degrades Optional just to simple null pointer warning, built into static code inspection, similarily to what would we gained by declaring checked exception. It however is useless as a flow control tool. Something that we are used to when using Scala's Option, and also much better implemented in java.util.Optional. The very problem is that our `map` function (known here as `transform`) is not really working. Let's verify what would happen when passed an null value to a transformation.
import com.google.common.base.Optional;
public class BrokenGuava {
public static void main(String[] args) {
Optional<String> optional = Optional.fromNullable("aaa");
System.out.println("optional = " + optional);
Optional<String> transformed = optional.transform(x -> null);
System.out.println("transformed = " + transformed);
}
}
which brings us the result of:
optional = Optional.of(aaa) Exception in thread "main" java.lang.NullPointerException: the Function passed to Optional.transform() must not return null. at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:226) at com.google.common.base.Present.transform(Present.java:71) at options.guava.BrokenGuava.main(BrokenGuava.java:10) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
The standard has got it implemented in a much better way:
import java.util.Optional;
public class NotSoBrokenUtil {
public static void main(String[] args) {
Optional<String> optional = Optional.of("aaa");
System.out.println("optional = " + optional);
Optional<String> transformed = optional.map(x -> null);
System.out.println("mapped = " + transformed);
}
}
this time you can see:
optional = Optional[aaa] mapped = Optional.emptyThis time it worked much better. Maybe not perfect (as we have empty as result - this is good topic for some next post), but at least not exploded in runtime.
So... Price is the same, why whould I choose suboptimal solution? Time to mark Guava's Optional deprecated.

