Introducing YaaS Java SDK

2017-05-28 DSP2017, Hybris, Java, Open source, RxJava, YaaS No comments

Introduction

In my company, there’s a concept of so-called “innovation day”. I have the possibility to “use” 1 innovation day per 2 development sprints. Last year, I used only 1 day due to the tight release schedule and a lot of work. Now, we are right after release, so I had time to take innovation day once again. I’ve decided to create YaaS Java SDK. If you don’t know what the YaaS is, check out my previous article about Basic usage of YaaS proxy for the microservice. In a few words, it’s a proxy for the microservices with authorization & monitoring capabilities, which allows using other services available on the YaaS market. SDK created by me is really simple, was created in a short period of time and does not cover all features of the YaaS. This SDK allows performing authorized requests to the microservices hidden behind YaaS proxy.

Tech stack used for this project is as follows:

For unit testing I used:

Quick start

I wanted to make this SDK as simple as possible so the user can add YaaS integration to the Java application within just a few lines of code.

YaaSProject project = new YaaSProject.Builder()
    .withClientId("YOUR_CLIENT_ID")
    .withClientSecret("YOUR_CLIENT_SECRET")
    .withOrganization("YOUR_ORGANIZATION")
    .withService("YOUR_SERVICE")
    .withVersion("v1")
    .withZone(Zone.EU)
    .build();

Client client = new YaaS(project);

client.get("path/to/your/endpoint")
    .subscribeOn(Schedulers.newThread())
    .blockingSubscribe(response -> System.out.println(response.body().string()));

As you can see, it looks really simple and straightforward. In the code snippet above, we’ve done the following thigs:

  1. Defined YaaS Project with YaaS service
  2. Created YaaS Client
  3. Performed HTTP GET request to the endpoint of the microservice on the new thread
  4. Received and printed body of the HTTP response from the microservice on the current thread as a String

All of that was done with Flowable type from RxJava2, which wraps Response type from OkHttp. We have a reactive stream of HTTP response here and we can do with it whatever RxJava2 offers us. Like filtering, mapping, throttling, combining it with other stream and so on.

For more information, visit repository of the project at: https://github.com/pwittchen/yaas-java-sdk.

Future plans

I have the following plans related to this project, which may be realized when I’ll have time:

  • Add more unit tests (I didn’t have enough time to cover all cases)
  • Add continuous integration
  • Integrate YaaS with SAP Hybris Backoffice or SAP Hybris Core Platform through this SDK (PoC)
  • YaaS Android SDK (copy YaaS Java SDK, downgrade it to Java 7 & optionally migrate to Kotlin and create sample mobile app)
  • Optionally, add more features to YaaS Java SDK
  • Optionally, deploy an artifact to Maven Central repository

Links

Interesting links related to this article:

Releasing Prefser v. 2.0.7

2017-05-28 Android, DSP2017, Java, Open source No comments

I’ve recently released new version of Prefser. It’s a wrapper for Android SharedPreferences with object serialization and RxJava Observables.
The new version number is 2.0.7.

In this release, I performed mostly internal work not related to the external library API. Nevertheless, it’s important for the library development in the future.

The following things were done:

  • updated dependencies
  • updated Gradle configuration
  • migrated unit tests to Robolectric
  • started executing unit tests on Travis CI
  • added integration with codecov.io and coverage report
  • extracted code related to accessors from the Prefser class (refactoring library internals)

Organizational work is done and now I’m ready for migration to RxJava2 in this project on a separate branch. I want to keep backward compatibility with RxJava1 as in my other projects. This update is planned for version 2.1.0.

Stay tuned!

Joining lists of RxJava Observables

2017-05-15 DSP2017, Java, RxJava No comments

In RxJava we have a few operators for joining Observables. The most common are:

Take a look at the documentation in these links. It has interactive marble diagrams showing how the operators work on the streams. You can move marbles along the lines and see how the output stream changes. It really helps to understand how it works.

Code snippets in this article are based on RxJava 2.1.0 with JUnit 4.12 and Google Truth 0.32 for unit tests.

Let’s say, we have the following Observables:

public Observable<String> emitNumbers() {
  return Observable.fromArray("1", "2", "3", "4").delay(1, TimeUnit.SECONDS);
}

public Observable<String> emitLetters() {
  return Observable.fromArray("a", "b", "c", "d");
}

We can merge them in the different ways.

Concat

Concat operator emits the emissions from two or more Observables without interleaving them.

We can perform the following operation:

public Observable<String> concatStreams() {
  return Observable.concat(emitNumbers(), emitLetters());
}

The easiest way to verify, how this operator works, is to create exploratory unit test as follows:

@Test
public void shouldConcatStreams() {
  // given
  Observable<String> observable = playground.concatStreams();
  List<String> expectedValues = Arrays.asList("1","2","3","4","a","b","c","d");
  List<String> joinedValues = new ArrayList<>();

  // when
  observable.blockingSubscribe(s -> joinedValues.add(s));

  // then
  assertThat(joinedValues).isEqualTo(expectedValues);
}

This operation can be represented graphically as well.

         1 --- 2 --- 3 --- 4
                  |
         a --- b --- c --- d
                  |
                  |
                concat
                  |
                 \|/
1 -- 2 -- 3 -- 4 --- a -- b -- c -- d  

As we can see one stream is appended to another regardless of the execution time of both streams.

Merge

Merge operator combines multiple Observables into one by merging their emissions.

Here we have a similar story, but changed operator:

public Observable<String> mergeStreams() {
  return Observable.merge(emitNumbers(), emitLetters());
}

We are writing another unit test:

@Test
public void shouldMergeStreams() {
  // given
  Observable<String> observable = playground.mergeStreams();
  List<String> expectedValues = Arrays.asList("a","b","c","d","1","2","3","4");
  List<String> joinedValues = new ArrayList<>();

  // when
  observable.blockingSubscribe(s -> joinedValues.add(s));

  // then
  assertThat(joinedValues).isEqualTo(expectedValues);
}

Merge operation should look like that:

         1 --- 2 --- 3 --- 4
                  |
         a --- b --- c --- d
                  |
                  |
                merge
                  |
                 \|/
a -- b -- c -- d --- 1 -- 2 -- 3 -- 4

This operator doesn’t synchronize the streams and merges them as values are emitted. Numbers are emitted later than letters, so letters are placed in the beginning of the output stream. Try to manipulate marble on the interactive diagram on the reactivex.io website to see how it should work.

Zip

The last operator, I’d like to discuss in this article is “Zip” operator. Zip combines the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function.

In simple words, it waits until many observables are emitted and then combines them into a pair (or triple Observable, etc. in the case or more Observables).

Now, we need to create a function, which will transform our streams and return combined stream.

public Observable<String> zipStreams() {
  return Observable.zip(emitNumbers(), emitLetters(),
      (s1, s2) -> String.format("(%s,%s)", s1, s2));
}

Next, we can verify it with test as usual:

@Test
public void shouldZipStreams() {
  // given
  Observable<String> observable = playground.zipStreams();
  List<String> expectedValues = Arrays.asList("(1,a)","(2,b)","(3,c)","(4,d)");
  List<String> joinedValues = new ArrayList<>();

  // when
  observable.blockingSubscribe(s -> joinedValues.add(s));

  // then
  assertThat(joinedValues).isEqualTo(expectedValues);
}

and it can be represented graphically like that:

        1 --- 2 --- 3 --- 4
                 |
        a --- b --- c --- d
                 |
                 |
                zip
                 |
                \|/
 (1,a) -- (2,b) --- (3,c) -- (4,d)

Now, we have pairs of merged streams.

Summary

Of course, RxJava is complicated library and these methods are not covering all possibilities of merging and combining the Observable streams. Neverhteless, examples in this article are quite basic and may help you to understand how mentioned operators work. After that we can apply the best operator to appropriate situation.


Reference thread on StackOverflow: http://stackoverflow.com/questions/28843318/android-rxjava-joining-lists

Analyzing performance of the web application with Chrome Dev Tools

2017-05-15 DSP2017, Performance, Tools, Web Development No comments

Introduction

Recently, I attended a training related to ZK framework. One part of that training was quite interesting for me and was related to measuring and monitoring the performance of the web applications. In Chrome Browser, we have Chrome Dev Tools, which can be opened with Ctrl+Shift+I shortcut or ⌘+Shift+I shortcut on Mac. Inside these tools, we have “Performance” tab. We can hit red “record” icon in the upper left corner of the Tools window and start recording performance of the website while loading it, clicking around or whatever situation we want to monitor. After that, we can see a really nice graph.

This graph presents a performance of our application during the time and shows different metrics divided into the different sections like:

  • Loading
  • Scripting
  • Rendering
  • Painting
  • Other
  • Idle

It can help us to find bottlenecks of the performance and critical sections.

Client-side performance issues

As we can see in this example, “Scripting” takes a lot of time so we can assume that client-side of our application slows down its performance. Moments, where application slowed down are marked with red lines on the main chart. We can select this area and investigate it further.

We could find the exact call of the JavaScript method and now we can try to optimize it in the future.

Server-side performance issues

When “Scripting” doesn’t take most of the time, but an application is still slow, we may suppose, that performance problem is caused by the server-side. In case of Java and JVM application, we can use JVisualVM program to monitor performance of our project. It can be subject of the separate article.

In Chrome Dev Tools, we may also switch to the “Network” tab and mark “XHR” sub-tab, which stands for XML Http Request, which are usually AJAX network calls done via JavaScript to the server.

Next, we can review our request and check, which one is slow. We may also review its header and response.

In the “Timing” tab we can take a look at the execution time of asynchronous connection. If it’s really slow, we may start the further investigation on the server-side in the place where this request is called.

Please note, slow XHR connections may be caused not only by inefficient code on the server-side but also by the infrastructure, servers & networking issues. We should isolate pieces of code & perform unit tests to show that it’s a server-side issue. We can also perform end-to-end tests, measure performance and compute average execution time to conclude what is the real source of the problem.

Summary

As we can see, monitoring performance and finding bottlenecks is not an easy task, but Chrome Dev Tools can help us to fix such issues in a really convenient way.

Short roadmap and plans for my OSS – May 2017

2017-05-14 DSP2017, Open source No comments

As few people might notice, I’m developing a few open-source projects right now. It’s not so easy to manage this stuff when you’re working in a full-time job, doing different not only IT-related things and don’t want to sit in front of the computer all the time. Nevertheless, doing this stuff really helps me to develop my programming & communicating skills and be up to date with various technologies. Instead of searching for excuses, I have the following plans related to releasing updates for my projects in the nearest future:

ReactiveNetwork

  • Review reported issues
  • Verify if reported bugs are real bugs
  • Adjust code to recent RxJava2 features if necessary
  • Handle Walled Garden issue OOTB
  • Add more useful code samples
  • Update existing code samples

Prefser

  • Release decent updates related to project configuration and updating dependencies
  • Migrate project to RxJava2 as a separate artifact
  • Keep backward compatibility with RxJava1 as in ReactiveNetwork project

Others

  • Review projects and their issues
  • Perform new releases in the project with unreleased, but commited changes
  • Handle users’ requests when possible
  • Migrate all RxJava-based projects to RxJava2 while keeping backward compatibility
  • Start new projects (which are currently drafts in my head/notepad/electronic notes/empty private git repos/etc.)

Moreover, I also have plans to learn a few new things not related to my ongoing projects, so that may slow down their development. In addition, I’m going to the conference this week and probably won’t be updating anything at this time. If anyone of you is interested in developing any of my projects, feel free to do it, go ahead and create your PRs! For sure, it will speed up the updates if you’re waiting for any of these.

Emitting different RxJava Observables depending on the condition

2017-05-14 DSP2017, Java, RxJava No comments

Sometimes, we may need to emit different RxJava Observables depending on the specific condition dynamically. Moreover, it’s good to do it right without breaking a chain (stream of Observables). We want to combine different Observables together and do not want to nest one subscription inside another subscription because this will lead us to “subscription hell” similar to “callback hell”. Luckily RxJava has mechanisms to deal with such problems. In this article, I’m basing my examples on RxJava 2.1.0.

Let’s say we have two Observables:

public Observable<String> trueObservable() {
  return Observable.fromCallable(() -> "trueObservable");
}

public Observable<String> falseObservable() {
  return Observable.fromCallable(() -> "falseObservable");
}

and we have another Observable wrapping Boolean value:

public Observable<Boolean> createCondition(boolean returnedValue) {
  return Observable.fromCallable(() -> returnedValue);
}

This Observable can emit true or false depending on the provided parameter.

What we want to do is to:

  • emit trueObservable() when createCondition(boolean) returns true
  • emit falseObservable() when createCondition(boolean) returns false
  • emit falseObservable() when createCondition(boolean) emits empty Observable (default behaviour)

We can do it in the following way:

public Observable<String> emitTrueObservableDynamically() {
  return createCondition(true)
      .defaultIfEmpty(false)
      .flatMap(condition -> condition ? trueObservable() : falseObservable());
}

In such case, this method will emit trueObservable(). When we change parameter of the createCondition(boolean) method to false, Observable will emit falseObservable(). When we replace createCondition(boolean) method with Observable.empty(), method will return falseObservable() by default. As we can see, it’s easily solved with flatMap and defaultIfEmpty operators.

This is quite useful technique, which we can apply to reactive applications to control our flow without breaking the chain. Please note, it’s just an example you can create more complicated constructions and handle more complicated types than just boolean and more than two use cases.


Reference thread for this article on StackOverflow: http://stackoverflow.com/questions/34195218/rxjava-exequte-observable-only-if-first-was-empty.

Basic code refactoring principles

2017-05-05 Code Refactoring, DSP2017, Software Development, TDD, Unit Tests No comments

Introduction

I’ve recently read a book about Test Driven Development by Kent Beck. It’s really good, presents the importance of the TDD and shows how to make a life of the software developer easier. In the TDD we follow red-green-refactor process in which we create a failing unit test, then we fix it and refactor it to make code-base better. There’s no golden rule when to refactor or how to refactor code and each project is different, but there are a few principles we may follow when we want to improve our projects through refactoring.

Finding similarities and duplications

One of the common code smells is duplication. We should search for the following patterns:

  • Two similar loops » try to merge them into one loop
  • Two similar instructions inside conditional statements » try to unify operations and get rid of the “if” statement
  • Two similar methods » try to unify them and remove one of them
  • Two similar classes » try to unify them and remove one of them
  • and so on…

Perform these operations carefully. If something goes wrong, go one step backward. Sometimes it may be impossible to remove all duplications.

Isolating changes

Before we start performing changes, it’s good to isolate a piece of code. We can move it e.g. to separate method, perform changes and then inline our method. That could help us avoid breaking the whole system.

Data migration

If we want to change the meaning of the data, we can temporarily duplicate them, perform changes, update interfaces and then remove original code.

Method extraction

If a method in our class is too big (according to Clean Code, “too big” is longer than 20 lines), we should find code doing specialized mini-task and extract part of it to a separate method. In IntelliJ IDEA we can use Ctrl+Alt+M shortcut or ⌘+Alt+M on Mac for that.

Method inlining

Sometimes, we’re extracting too many pieces of code to separate methods, what may decrease code readability. If the code inside the method is really simple, so it could be written in a single line or optionally in two lines, we may think about inlining this method. To do so, we should remove method and place code directly in the place where it’s called. To perform inlining in IntelliJ, we can use Ctrl+Alt+N shortcut or ⌘+Alt+N on Mac.

Interface extraction

When we want to create additional implementations of the operations, which already exists in our code-base, we may extract these operations into the interface. IntelliJ IDEA also has support for that. I’m not sure if there’s a shortcut, but you can use Ctrl+Shit+A shortcut or ⌘+Shift+A on Mac to open window with operation search and then type “extract interface”. It should work.

Moving method

It may happen, that our class or interface is becoming too big or it has methods, which are not directly related to this class. In such case, we may simply move one method or a few methods to another, more appropriate class or create a separate class or interface for them.

Object-method

We may encounter a situation when a specific method has too many parameters. In such case, we may consider creating Object-method. It’s some kind of data class, which contains attributes the same as method parameters. It will help us to pass data in our system in a more readable way. We can also connect this solution with a Builder software design pattern.

Adding parameter

During the time, the business logic of our system is getting bigger and one of our methods need to be extended. In such case, we can add another parameter to it. We may also consider creating another, similar method with just one more parameter. When we’re providing API or framework for other developers, we have to remember about proper “deprecated” annotations.

Moving parameter from method to the constructor

It may happen that we want to move a parameter from the method to a constructor to simplify the logic of the project. In order to that, we can move local variable to a class variable (in IntelliJ IDEA: Ctrl+Alt+V shortcut or ⌘+Alt+V on Mac) and then create constructor with this variable (Alt+Insert or ⌘+N on Mac).

Summary

As we can see, there are a few principles, which we may apply during code refactoring to make our project better. Moreover, most of them are supported by IntelliJ IDEA, which is great IDE. If you’re programming in another language than Java and want to have refactoring tools, you should check JetBrains products. Nevertheless, there’s no golden rule of refactoring. Sometimes it’s better to leave the code as it is. Especially if code-base is huge, the project is in production and there are no unit tests. If you want to know more about principles from this article, read Test Driven Development book by Kent Beck. Probably there are more principles than these described in this article. We should perform refactoring carefully and we need to remember about tests. Everything depends on the concrete project and our situation.

Monitoring usage of open-source projects

2017-05-05 DSP2017, Open source 2 comments

While developing open-source projects it’s important to monitor usage of them. Having that information we know on which projects we should concentrate the most and which are becoming more popular. In this short article, I’ll present you two tools, which can help you with that.

GitHub

On GitHub, each project has “Traffic” tab. After clicking on it, we can see how many visitors and unique visitors we have, we can also check how many project clones and unique clones were performed (including CI servers). Moreover, we can see referring sites for our projects. It’s useful information because we can check how people gather information about our project.

Sonatype

GitHub stats can be used for any type of project for any language. When we’re developing Java or JVM library and we publish it on SonaType, we can also use oss.sonatype.org website for monitoring usage of our libraries. It provides us quite interesting information, which actually tells us if anyone is using our library.

In the “Central Statistics” section, we can select GroupId and also ArtifactId. We can see accumulated information about downloads of all our projects in time and check, which project is the most popular. We can also view downloads from unique IPs. What I found interesting here is the fact that one of my projects called prefser is quite popular and people really started using it in their projects! Approximately 47% of downloads of all my projects are downloads of that single library. Nevertheless, the last release of this library (v. 2.0.6) was almost one year ago. It encouraged me to put more effort into this project and make it better. I actually started working on it again and planned new releases. Trust of many people is a huge motivation factor & honor for me.

Do you know any more methods of measuring usage of your projects? Maybe for different technologies than Java?

Share your experiences in comments :).

Basic usage of YaaS as a proxy for the microservice

2017-04-30 DSP2017, Hybris, Microservices, YaaS No comments

Introduction

The company, where I currently work – SAP Hybris is developing a project called YaaS, which is an abbreviation of Hybris as a Service. Unfortunately, this article is not sponsored yet :). What a pity :(. I just like to understand many things & how they work to see the bigger picture. Moreover, company strategy is to leverage YaaS and search for the new possibilities and use cases of this project. There are situations where delegating some work to a separate service makes sense so this knowledge may be useful even when we’re developing the monolithic enterprise applications. That’s why I wrote this article. I work in a completely different project – Enterprise Commerce Platform, where I’m the part of the Backoffice team. As you can read on the official website, YaaS is a microservices ecosystem helping businesses to rapidly augment and build new, highly flexible solutions. It’s kind of marketing statement, which business people may like. Nevertheless, for developers, it’s just a bunch of buzzwords, which does not help you to understand this project. One of the aims of this article is to explain it in a simple and clear way.

yaas - hybris as a service

From the technical point of view, YaaS gives you the following possibilities:

  • it can be a proxy for your microservice, which can be deployed anywhere
  • it gives you separate proxy servers for EU and US, which you can use depending on the server or user location
  • it provides you a domain like api.eu.yaas.io/yourorganization/yourservice/
  • it provides secured connection
  • it gives a mechanism, which allows you to secure endpoints of your microservice via dynamically generated token
  • it gives you the possibility to manage access to your service for advanced use cases with features like clients, roles, etc.
  • it gives you monitoring possibilities
  • it allows you to perform versioning of your API
  • it allows you to integrate other services/packages from YaaS Market with your service
  • it gives you web interface called YaaS Builder, which you can use for managing your projects and organization

YaaS is NOT:

  • the hosting platform like Heroku or AWS – you need to have another place where you can deploy your service (like Heroku or whatever)
  • the part of the Core Hybris Platform – it’s completely separate project, but it can be integrated with the Hybris Platform

The official website of the project is: www.yaas.io.

In this article, I won’t explain all the features of YaaS. I will simply show you:

  • how to create a simple proxy for your microservice
  • how to secure endpoint of your microservice
  • how to access secured endpoint of your microservice

Maybe I’ll explain more features in the separate articles in the future.

Creating a simple proxy for the microservice

We need to do the following steps:

  1. Go to https://builder.yaas.io
  2. Create an account & log in
  3. Create an organization
  4. Create a project
  5. Within the project create a service
  6. Provide address to your service
  7. Provide API version (e.g. v1)
  8. Deploy service
  9. Right now, your service is deployed, but not accessible yet
  10. Create a Client and assign it to your service
  11. Now you should be able to access your service at: https://api.eu.yaas.io/orgranization/service/v1

Below you can see a screenshot from service configuration inside the YaaS Builder.

Securing the endpoint of the microservice

We have created our service. Now, we want to secure its endpoint. To do so, we can create Authorization Rule from the Service configuration inside YaaS Builder.

We can define methods of the HTTP request, endpoint address, and other parameters.

When we’re done, we can proceed to more tricky part. Authorization procedure of the microservice endpoint is presented in the scheme below.

calling microservice with authorization via YaaS proxy

First, we need to obtain Bearer ID. To do so, we need to perform HTTP request with Client ID and Client Secret. We can do it from terminal via curl:

curl -X POST -i 
-H "Content-Type: application/x-www-form-urlencoded" 
-d "grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET" 
https://api.eu.yaas.io/hybris/oauth2/v1/token

Then, we’ll receive a response like that:

{"token_type":"Bearer","access_token":"023-018f03da-cdb7-4710-a4cf-70f89e23003f","expires_in":3600,"scope":"hybris.tenant=pwtest"}

and we can make an authorized call to our microservice:

curl -X POST -i 
-H "Authorization: Bearer 023-018f03da-cdb7-4710-a4cf-70f89e23003f" 
-H "Content-Type: application/json" 
-d "" 
https://api.eu.yaas.io/pwittchen/test/v1/endpoint

after that, we should receive a response from the microservice. Note, that Bearer ID will be valid for the particular amount of time.

Hint #1: To make calls more readable in the article, I split them into lines. If you’re making a real call it’s better to have whole instruction in a single line.
Hint #2: You can get Client Secret and Client ID from the YaaS Builder while editing your Client.

Summary

As we could see, creating a microservice proxy and securing the endpoint is not so complicated, but it’s not straightforward as well. It requires some knowledge about YaaS and its design. Using this approach won’t be a good idea every time, but I think there are use cases when it can be useful. Especially, when we care about monitoring & security and when we want to have unified & controlled access to our services.

Here are a few of my ideas of delegating work to the microservice from the monolithic enterprise commerce application:

  • file or image storage
  • backups of the data
  • classification of the products – e.g. we can delegate images to the external service, which will use machine learning and neural networks to classify products by colors or by something else
  • long running operations & queues – e.g. we can delegate such things to the separate microservice to relieve CPU & Memory of the server, where core system is running and simply receive push notification with final result of the operation from the microservice when the work is done
  • sending e-mails and other types of notifications
  • and more… (if you have your own ideas – share them in comments!)

I think the basic idea could be the distribution of computations to the different servers, what may extend capabilities of the core system, make it faster, lighter and more stable. In addition, it should make work of developers easier and more joyful because they could work on the smaller parts of the system, which have a clearly specified goal and smaller codebase, which is easier to manage.

2 cool terminal emulators for Linux

2017-04-30 DSP2017, Linux, Tools No comments

There are many terminal emulators for Linux, but two of them acquired my attention.

Yakuake

Yakuake is a terminal emulator, which you can drop down from the top of the screen in any situation. It may look familiar to those who played Quake III, because this game has a very similar concept of the terminal for configuration purposes. It’s very convenient when we want to check something quickly. We can just press F12 do our task and press the same key to close the window.

yakuake - terminal emulator

Tilix

Tilix is another interesting terminal emulator, which is quite similar to iTerm2 for macOS. It has the possibility to create tiles and tabs just like iTerm2. It can be some kind of alternative for Tmux. Moreover, it allows searching through the console what is very useful.

tilix - terminal emulator

Do you know more interesting terminal emulators for Linux or maybe for other operating systems? Share them in comments!