CHICIO CODING

Dirty clean code. Creative Stuff. Stuff.

The birth of ID3TagEditor and Mp3ID3Tagger and my journey into the ID3 tag standard

The first of a short series of post in which I describe my two latest project: ID3TagEditor and Mp3ID3Tagger. In this post I will talk about why I started to develop them.


Recently I bought a new car. After a lot of searches I finally decided to buy the Renault Clio 2017 1.5 dci. I love this car. It has been a big step forward on my previous car. One of its most interesting feature is its media entertainment system: the Media Nav Evolution system. This system has a 7’’ touchscreen with map integration and a basic smartphone integration with Siri voice recognition and phone call support.

media nav clio

One of the thing that caught my attention was the possibility to start to listen to my mp3 collection while I’m driving (on my previous car I had a standard cd player). So I prepared an usb key with some of my mp3 and I started to listen to them. I suddenly made a great discovery: some of my songs were displayed on the touchscreen with information about the album and they were displaying the cover of the album!!!!! :heart_eyes:. I though: “Whoahh this is very cool!! I need to start to fill my mp3 with all this information. I want to see the cover of the album for each mp3 I have!!!!!!!”. This is exactly the moment where my journey into the development of ID3TagEditor and Mp3ID3Tagger started, but I was not yet aware of it :grin:. So I sat in front of my MacBook, I opened iTunes and I started to tag my mp3 files. I saved them on a usb key and I went to my car to test them. The result was the following:

mp3 no cover

What the hell is going on??!!?! :angry: The title and the album where displayed but the cover was not show on the screen. So I got back to my desk and I started to download some native macOS app that let the user edit what I discovered was called ID3 tag. None of them worked as expected. Then I found an app called Mp3Tag. This is Windows application that runs also on macOS using Wine. So I downloaded it and tried to tag some mp3. I put them on a usb key and then…

mp3 with cover

Mp3Tag was working as expected :relieved:. But then I started to ask myself: “What is doing Mp3Tag that the other native macOS application are not doing?”. The only way to discover the reason behind this mystery was to compare an mp3 tagged with Mp3Tag with an mp3 tagged with one of the other applications. So I opened with my favourite hex editor HexFiend an mp3 tagged with iTunes and another one tagged with Mp3Tag and I compared them…

mp3 compare itunes mp3tag

Yep, a single byte could make a big difference :open_mouth:. The fact is that the ID3 standard accept multiple types of attached picture for an mp3: front cover, back cover, icon, artist photo ecc. The type of picture is represented as a byte just after the MIME type in the attached picture frame of the ID3 standard. The problem is that iTunes and other “mp3 tagger” native macOS applications don’t let the user modify the type of the attached picture. All this application set the byte to 0x00 that in the ID3 standard corresponds to the “Other” cover type. But the Media Nav Evolution system of my Renault Clio is able to read only attached picture frames inserted in the tag with a specific type, for example 0x03 “Cover (Front)”, that is the default type inserted by Mp3Tag. The attached picture frames that have the 0x00 “Other” type are discarded :unamused:. My next question was: “How is it possible that there’s not a native macOS app? There are only cross platform/web solution. I want an app that a real Apple fag would be happy to use…“:apple::stuck_out_tongue:. Honestly, I didn’t find it. So I started to think: “I could develop this app, using some modern framework/programming paradigm I studied in the last months…In this way I have a chance to create my first macOS app and add some other interesting projects to my Github profile…and in this way I can work on a project where I don’t have to launch the commands npm install or npm run build hundred times in a hour…”. Here we are after two months of work with the public release of:

  • ID3TagEditor, a pure Swift framework (only Apple Foundation framework dependencies) to read/modify ID3 tag of your mp3 files with support for the following Apple platforms: macOS, iOS, watchOS and macOS (so the entire Apple ecosystem :grin:)
  • Mp3ID3Tagger, a native macOS app written in Swift using the reactive programming paradigm and in particular its Rx (Reactive Extensions) variant with the frameworks RxSwift and RxCocoa (Rx????!?!?!? WHATTTT?!?!?!? :cold_sweat:).

If you are still interested in knowing the details about the development of this two projects, you can follow the links below:

mp3id3tagger id3tageditor

I hope you will see how much love and passion I put into this projects and I also hope you will find all the technical details inside them interesting :sparkling_heart:.

Clean Code: data structures vs objects and the law of demeter

In this post I will talk about clean code: data structures, objects vs procedural and the law of demeter.


In this previous post I described what Clean Code is and what does it mean to use meaningful names in your code. This time I will talk about Data structures and objects. But wait, do we really know the definition of them? Let’s see what Uncle Bob says about them in its Clean Code book:

Objects hide their data behind abstractions and expose functions that operate on that data. Data structures expose their data and have no meaningful functions.

It’s easy to see that they are opposites. A lot of programmers are convinced of the fact that in software development everything should be an object. If you think about the nature of objects you will see that there are times where you just want simple plain data structures that you can manipulate in a procedural way. This is a consequence of the fact that adding new functions to an object may require much more work, because maybe you need to modify all the objects of the same type to add a new function. This give us the following definitions, stated by Uncle Bob in its Clean Code book:

Procedural code (code using data structures) makes it easy to add new functions without changing the existing data structures. Object oriented code, on the other hand, makes it easy to add new classes without chaging existing functions.

Procedural code makes it hard to add new data structures because all the functions must change. Object oriented code makes it hard to add new functions because all the classes must change.

This set of rules must guide us when we have to choose between objects vs procedural implementation:

  • do you expect to add more and more functions to your code, and keep unmodified the data structures you use? Ok, let’s go with procedural code :relaxed:.
  • do you expect to add new types without adding new functions to your code? Well, use objects :bowtie:.

Related to the object oriented programming, Uncle Bob talks about the law of demeter that says a module should not know about innards of the objects it manipulates. The focus of this law is to improve the decoupling of objects. More precisely its definition is:

A method f of a class C should only call the methods of these:

  • C
  • an object created by f
  • an object passed as argument to f
  • an object held in a instance variable of C

This bring us to talk about what is called train wreck: concatenation of function/properties calls. The difference between objects and data structures gives us a clear understand of when a train wreck is really dangerous:

  • if in a method you’re working with data structures, law of demeter is not applied to them because is natural for a data structure to expose their internal structure.
  • if in a method you’re working with objects, then you should consider concatenation of method calls as violation of the law of demeter

The next time you will write a piece of code try to consider these concepts and how they can improve your code.

Clean code uncle bob superman

Blender tutorial: introduction to basics of modeling - part 1

In this new post of the Blender tutorial series I will talk about the fundamental of modeling in Blender.


In the previous post of the “Blender tutorial” series we talked about how we can select and transforms objects. In this new post thing will start to get more interesting: we will start to talk about modeling. First of all let’s see which kind of primitives mesh we can create with blender.
We can start by opening a new file and removing the default cube mesh by selecting it and pressing the “x” key. Now we are ready to add new primitive meshes. We can do it in two ways:

  • from the Tools -> Create menu in the 3D window
  • from the Add -> Mesh menu at the bottom of the 3D window, when we are in object or edit mode

Blender support a series of basic primitives, from which we can start modeling more complex meshes:

  • plane
  • cube
  • circle
  • UV sphere
  • ico sphere
  • cylinder
  • cone
  • torus

When we choose a primitive mesh to be created, it will be placed where the 3D cursor is pointing at the moment of creation. After the creation of the mesh, a new panel at the bottom left of the 3D window will be shown. In this panel we can customize the properties of the mesh.

blender modeling create primitive meshes

As we said before, we can start from a primitive mesh and model a more complex one. So the first thing we need to learn is how we can select vertices, edges and faces. How can we do that? First, we need to choose edit mode, by selecting the mesh and by choosing it from the editing/interaction mode menu component in the 3D window (or alternately by pressing the “tab” key). After that, we can choose the selection mode between vertices, edge or faces in the bottom bar of the 3D window or by pressing “ctrl + tab” keys.

blender select edges faces vertices

After selecting the edges, vertices or faces that we want to modify, 3D axis will be shown near your selection. They are similar to the ones shown for transformations. By dragging one of these axes the selcted vertices, edges or faces will move accordingly to the direction of the dragging.
We can improve the selection of edges by pressing “ctrl + alt + right click” keys while we are in edge selection mode: in this way we will be able to select edges loops, a series of connected closed edges series.
We can also improve the selection by using the more/less option to select entire levels of edges/vertices/faces.

blender modified mesh

By selecting individual edges, vertices and faces you can start modeling you meshes. Anyway, sometimes you will need to be able to do a more soft modeling than the one we already described above in this article (for example while working on organic objects. This is why it is possible to use the proportional editing. When we use this kind of modeling, the modification on a vertices/edge/face will influence the other element around with a proportional falloff. You can activate the proportional editing using the menu Mesh -> Proportional Editing in edit mode or using the dedicated button in the bottom bar of the 3D window.

blender modeling proportional editing

Below you can find an example of two meshes modified with and without the proportional editing enable.It’s easy to see the difference.

blender modeling proportional editing example

In the next post we will continue to talk about the fundamental of modeling.

Golden master testing aka Characterization test: a powerful tool to win your fight against legacy code

In this post I will talk about golden master test aka characterization test: what it is and how to use it.


In the last few months the focus during my daily job was not only on mobile. I had the chance to work on some front-end and back-end application of lastminute.com group. In particular, I worked with my team to renew the customer area of all the main brands sites: volagratis .com, lastminute.com and rumbo.es. During the last week I did pair programming with Emanuele Ianni. Emanuele is a senior full-stack software engineer and a true nerd :alien:/computer science lover :heart:. We needed to implement a new feature for a family of microservices (based on Java 1.8 and Spring Boot) that make up the back-end of the customer area, both for web and mobile apps of lastminute.com group. Unfortunately, we found some legacy code without tests, exactly where we planned to add the feature. At this moment Emanuele showed me the Golden master testing technique. Soooo what is golden master testing? As always (and maybe you can expect it because you are a huge fan of my blog and you read all my previous posts :laughing:) Wikipedia gives us all the answer we need:

In computer programming, a characterization test (also known as Golden Master Testing) is a means to describe (characterize) the actual behavior of an existing piece of software, and therefore protect existing behavior of legacy code against unintended changes via automated testing. This term was coined by Michael Feathers…… When creating a characterization test, one must observe what outputs occur for a given set of inputs. Given an observation that the legacy code gives a certain output based on given inputs, then a test can be written that asserts that the output of the legacy code matches the observed result for the given inputs.

So Golden master testing, mostly know as characterization test, is a technique by which we can be able to put large and complex legacy code under test: we generated some output given some input for a piece of code, and we write tests in which we assert that the output from the source code must be the same we received before. In this way we can start to refactor a piece of code and be sure that our modifications didn’t change the behaviour of the source code. Whooaaa!! No more risky approaches to do refactoring without tests!!! :relieved: :clap:
Now it’s time for an example. In this article I will show you a simple example where I apply this technique to put under test a piece of legacy code. You can find the entire source code in this github repository. Suppose for example that you found this class, TravelsAdapter, in the code you’re working on.

public class TravelsAdapter {
    public List<Travel> adapt(JsonNode jsonNode) throws InvalidTravelException {
        List<Travel> travels = new ArrayList<>();
        JsonNode payloadNode = jsonNode.with("data");
        if (payloadNode.findValue("orderId") == null || 
                StringUtils.isBlank(payloadNode.findValue("orderId").textValue())) {
            throw new InvalidTravelException("Invalid order id");
        }
        long orderId = payloadNode.findValue("orderId").asLong();
        JsonNode flights = payloadNode.withArray("flights");
        if (flights.size() == 0) {
            throw new InvalidTravelException("Invalid json (no flights)");
        }
        flights.iterator().forEachRemaining(flight -> {
            ObjectNode nodeFlight = (ObjectNode) flight;
            if (nodeFlight.get("flightId") == null || StringUtils.isBlank(nodeFlight.get("flightId").textValue())) {
                try {
                    throw new InvalidTravelException("Invalid flightNumber value");
                } catch (InvalidTravelException e) {
                    e.printStackTrace();
                }
            }
            String flightNumber = nodeFlight.get("flightId").textValue();
            String arrivalAirport = nodeFlight.get("to").textValue();
            String departureAirport = nodeFlight.get("from").textValue();
            String airline = nodeFlight.get("airline").textValue();
            travels.add(new Travel(
                            orderId,
                            flight.toString(),
                            flightNumber,
                            airline,
                            departureAirport,
                            arrivalAirport));
        });
        return travels;
    }
}

It’s really a mess. So we start to think “I want to see the tests of this class to understand what it does”, but we search for them in the project and……there aren’t any tests for this class!!! :fearful:. The logic contained in this class seems a little bit twisted, and also it would take a lot of time to write a complete suite of test case because we need to understand from the beginning every single path contained in this class. This is a case where golden master testing could help us.
The first thing we can do is to observe the method returns a list of Travel objects. To write our golden master tests we need to find a way to do a comparison between the Travel objects returned from the adapt method and the one we expect. To do this we can add for example a toString method the Travel class and test the returned value from it. So the Travel class will be the following one.

public class Travel {
    private final long orderId;
    private final String flights;
    private final String flightId;
    private final String airline;
    private final String departureAirport;
    private final String arrivalAirport;

    Travel(long orderId,
           String flights,
           String flightId,
           String airline,
           String departureAirport,
           String arrivalAirport) {
        this.orderId = orderId;
        this.flights = flights;
        this.flightId = flightId;
        this.airline = airline;
        this.departureAirport = departureAirport;
        this.arrivalAirport = arrivalAirport;
    }

    @Override
    public String toString() {
        return "Travel{" +
                    "orderId=" + orderId + ", " +
                    "flights='" + flights + '\'' + ", " +
                    "flightId='" + flightId + '\'' + ", " +
                    "airline='" + airline + '\'' + ", " +
                    "departureAirport='" + departureAirport + '\'' + ", " +
                    "arrivalAirport='" + arrivalAirport + '\'' +
                '}';
    }
}

Now we can write some tests and use the output as the expectation. In this way we will be sure that if we start to do some refactoring operation on this class our modification didn’t broken any behaviour of the class. So we can do our refactoring with an high level of confidence that everything is working as it was working before our modification :relieved:. To get the output for the test, you can write your test and made them fails, and in the meanwhile log the result so that we can copy it and use it in the next run iteration of our test. The following test is the one we generated for the class we saw before.

public class TravelsAdapterTest {

    @Test
    public void goldenMaster() throws IOException, InvalidTravelException {
        TravelsAdapter travelsAdapter = new TravelsAdapter();

        List<Travel> travels = travelsAdapter.adapt(generateRequest());

        StringBuilder builder = new StringBuilder();
        travels.forEach(bp -> {
            builder.append(bp.toString());
            builder.append("\n");
        });
        assertThat(
                builder.toString(),
                is("Travel{" +
                            "orderId=0, " +
                            "flights='{" +
                                "\"from\":\"MXP\"," +
                                "\"to\":\"FCO\"," +
                                "\"flightId\":\"1111\"," +
                                "\"direction\":\"OUTBOUND\"," +
                                "\"airline\":\"U2\"," +
                                "\"departure\":\"2018-04-20T12:00:00\"," +
                                "\"boardingCard\":{" +
                                    "\"id\":\"485\"," +
                                    "\"firstName\":\"Fabrizio\"," +
                                    "\"lastName\":\" Duroni\"," +
                                    "\"seat\":\"V23\"," +
                                    "\"urls\":[" +
                                        "\"http://aboardingcard/resource1\"," +
                                        "\"http://aboardingcard/resource2\"," +
                                        "\"http://aboardingcard/resource3\"" +
                                "]}}', " +
                                "flightId='1111', " +
                                "airline='U2', " +
                                "departureAirport='MXP', " +
                                "arrivalAirport='FCO'" +
                          "}\n" +
                        "Travel{" +
                            "orderId=0, " +
                            "flights='{" +
                                "\"from\":\"FCO\"," +
                                "\"to\":\"MXP\"," +
                                "\"flightId\":\"1112\"," +
                                "\"direction\":\"RETURN\"," +
                                "\"airline\":\"AA\"," +
                                "\"departure\":\"2018-05-01T10:00:00\"," +
                                "\"boardingCard\":{" +
                                    "\"id\":\"486\"," +
                                    "\"firstName\":\"Chiara\"," +
                                    "\"lastName\":\"Polito\"," +
                                    "\"seat\":\"A15\"," +
                                    "\"urls\":[" +
                                        "\"http://aboardingcard/resource1\"," +
                                        "\"http://aboardingcard/resource2\"," +
                                        "\"http://aboardingcard/resource3\"" +
                                    "]}}', " +
                                    "flightId='1112', " +
                                    "airline='AA', " +
                                    "departureAirport='FCO', " +
                                    "arrivalAirport='MXP'" +
                        "}\n"
                )
        );
    }

    private JsonNode generateRequest() throws IOException {
        return new ObjectMapper().readTree(
                "{\n" +
                "  \"data\": {\n" +
                "    \"orderId\": \"73hb6yh3be6ebe63bdy6\",\n" +
                "    \"flights\": [\n" +
                "      {\n" +
                "        \"from\": \"MXP\",\n" +
                "        \"to\": \"FCO\",\n" +
                "        \"flightId\": \"1111\",\n" +
                "        \"direction\": \"OUTBOUND\",\n" +
                "        \"airline\": \"U2\",\n" +
                "        \"departure\": \"2018-04-20T12:00:00\",\n" +
                "        \"boardingCard\": {\n" +
                "            \"id\": \"485\",\n" +
                "            \"firstName\": \"Fabrizio\",\n" +
                "            \"lastName\": \" Duroni\",\n" +
                "            \"seat\": \"V23\",\n" +
                "            \"urls\": [\n" +
                "              \"http://aboardingcard/resource1\",\n" +
                "              \"http://aboardingcard/resource2\",\n" +
                "              \"http://aboardingcard/resource3\"\n" +
                "            ]\n" +
                "        }\n" +
                "      },\n" +
                "      {\n" +
                "        \"from\": \"FCO\",\n" +
                "        \"to\": \"MXP\",\n" +
                "        \"flightId\": \"1112\",\n" +
                "        \"direction\": \"RETURN\",\n" +
                "        \"airline\": \"AA\",\n" +
                "        \"departure\": \"2018-05-01T10:00:00\",\n" +
                "        \"boardingCard\": {\n" +
                "            \"id\": \"486\",\n" +
                "            \"firstName\": \"Chiara\",\n" +
                "            \"lastName\": \"Polito\",\n" +
                "            \"seat\": \"A15\",\n" +
                "            \"urls\": [\n" +
                "              \"http://aboardingcard/resource1\",\n" +
                "              \"http://aboardingcard/resource2\",\n" +
                "              \"http://aboardingcard/resource3\"\n" +
                "            ]\n" +
                "        }\n" +
                "      }\n" +
                "    ]\n" +
                "  }\n" +
                "}"
        );
    }
}

In this example we generated just one test case, but usually a lot more of them. Basically we can apply a technique named “property testing”: a lot of random input are generated so that there will be an high probability to execute all the possible branch in our source code (and in this way have a higher test coverage).
So we put our TravelsAdapter under test and we can now start to work on this class without any kind of risk :relieved:. Now it’s time to test this technique in your legacy code :grin:.

Code review: what it is and why it matters

In this post I will talk about code review: what it is and why it matters.


In some of my previous posts (for example in this one), I talked about my new experience at lastminute.com group and how much we care about code quality. In fact I already talked about the fact that we do pair programming during our daily job. But pair programming is not the only techniques we use to be sure that our software matches high code quality standard :sunglasses:.
One of the most important procedure I use during my daily job with my colleagues is code review. What is it? Let’s see a standard definition from wikipedia:

A code review is a process where two or more developers visually inspect a set of program code, typically, several times. The code can be a method, a class, or an entire program. The main code-review objectives are:

  • Best Practice: a more efficient, less error-prone, or more elegant way to accomplish a given task.
  • Error Detection: discovering logical or transitional errors.
  • Vulnerability Exposure: identifying and averting common vulnerabilities like Cross-Site Scripting, Injection, Buffer Overflow, Excessive Disclosure, etc.
  • Malware Discovery ~ This often-overlooked and very special code-review objective looks for segments of code that appear extraneous, questionable, or flat-out weird. The intent is to discover back doors, Trojans, and time bombs. In today’s world malevolent code is a very real threat and should not be overlooked, especially by Government agencies.

The definition is simple and clear. Basically you go through the code of another guy (or from a couple if they are doing pair programming) to find errors, bugs, code style/best practice not compliant to the team set of rules.
Three weeks ago I attended a coding dojo with my colleagues Angelo Sciarra. Angelo is a senior full-stack software engineer with many years of experience.
You may wonder now what is also a coding dojo. So again, here we are with another definition :bowtie::

A Coding Dojo is a meeting where a bunch of coders get together to work on a programming challenge. They have fun and they engage in order to improve their skills.

During the dojo that I attended with Angelo we tried to resolve the Minesweeper problem.
Basically we had to write an automatic Minesweeper resolver (do you remember the Windows game? :heart_eyes:). At the end of the dojo we didn’t complete the task, so I decided to try to solve it in another way. I developed a complete command line version of a Minesweeper resolver and let Angelo do the code review of my implementation. In this way I can show you the power of code review :neckbeard: (and last but not least how much meticulous is Angelo during his code review :cold_sweat::sweat_smile::cupid:).
Before starting, I suggest you to have a look at this repository that contains the entire Minesweeper implementation I develop and, on the Code review pull request opened on this repo you can find the observation/new implementation from Angelo. Usually the code reviewer doesn’t implement by himself/herself the stuff of his/her observation, but in this case we did it so that we can share the code before/after the code review in a pull request (and also to show you the Angelo’s skills :heart_eyes:).
To facilitate you in the navigation of the two different implementations I created two class diagram: one that describe my implementation before the code review, and the second one that shows the final result after Angelo’s code review. The following one describes my implementation of the minesweeper.

fabrizio duroni minesweeper

This one describes Angelo’s implementation.

angelo sciarra minesweeper

So let’s start to see which kind of observation I received from Angelo, that basically include most of the observation you could receive during a code review.
The first observation I received from Angelo is about the java JDK version I used for my project. I did the setup of the project using JDK 1.5 instead of JDK 1.8 (as you may know, this is a more recent version). In general it is common to receive suggestion about technology specific problems/setup/changes, especially if your code reviewer is more experienced than you on that type of technology.

technology version update

In fact Angelo gave me another technology advice during his review. He suggested to change some pieces of code with others that leverage the power of functional programming. This is really interesting because it is easy imagine how much knowledge you can absord from the experience of your code reviewer.

functional update functional update with new class

Another important aspect that is one of the main subject of the code review is software design. In fact Angelo discovered a series of improvement and refactoring opportunities in my code:

  • the Minesweeper class doesn’t need to receive the fields input at construction time but directly in the play() method. In this way the Minesweeper class becomes a stateless object, and the same istance could be used to resolve/unmask multiple fields input.

stateless object

  • The objects that are the building block of a chain of responsability
    named FieldRowParser could become lighter and some of their responsibility could be assigned to some new collaborators. Also the object that contains the parsing status could become more lighter.

lightweight chain parsing status

As you can see from these kind of comments the code review could really improve the general architectural design of your application :heart_eyes::relieved:. Code convention are another important thing to check during code review. For example Angelo told me to move all the constants at the beginning of some of the classes. Usually tools like Github or Gitlab let you discuss your code review by adding comments directly to the code.

constants position guidelines comments

Last but not least, if you are a real fan of clean code, you know that meaningful names are important. So you can suggest some more meaningful name for a class, variable or method.

rename

That’s all for code review. I hope you understood how much important it is to do it and how much your codebase can improve if you use code review as a validation tool and as a tool to find new refactoring opportunities (anyway, I hope Angelo will never be your reviewer :laughing::sparkling_heart:).