Sunday, June 21, 2020

Modulo Operation Tricks

When you solve a problem that might result in values beyond integer limits (e.g., Wouldn't fit into a 64bit integer), you're often asked to print the value modulo a significant prime value (e.g. 10^9 + 1).

To be able to use the modulo operation correctly, you need to understand its properties.

Trick #1 Multiplication/Summation of values

For example, if you are multiplying/adding a set of numbers (a, b, c, d) then its useful to know that:

(a*b*c*d)%N = (a%N)*(b%N)(c%N)*(d%N) = ((a*b*c)%N)*d%N

The above is quite useful when you want to always keep calculations to fit into the given limits.

Trick #2 Multiplicative Inverse

For division, it's a little bit tricky though, you can't merely assume that:

(a/b)%N = (a%N/b%N)

Although that would be awesome, it's unfortunately not correct - So to solve this, you have to understand the modular multiplicative inverse of a number A.

So to calculate (a/b)%N, you can convert it to a%N*power(b, N-2) - I will not explain how or why, please refer to the wiki page above for more details.

Trick #3 Negative Numbers

Another problem one would face during programming contests is when you calculate modulo for a negative number, which doesn't really work as intended.

So -1%10 would result in -1 rather than 9 - This really depends on the programming language you use but this trick is useful for Java and C++ but not for Python which produces the right value 😊.

To overcome this, you can calculate it by adding N to the number so, -1%10 = 9%10 = 9 👍.

That's it! I will keep this post up to date with any other tricks I find in the future.

Sunday, May 24, 2020

Speak so that others want to listen

How many times were you in a meeting or discussing with a group of people, and was your turn to say something, and someone either interrupted you or waited until you finished and continued talking or just switched the topic?

I'm pretty sure this has happened many times throughout your career and will continue to happen even after you read this article and practice its techniques, but I can promise it will be less often than before.

I've been observing others and myself in meetings and always found out that most of the discussions followed the same scenario I've described above, so I started to look for ways to improve the way I speak and spotting the mistakes I and others often do.

I've found many techniques and suggestions that are helpful for someone to speak effectively and make people more engaged to what he/she says, I've chosen only 3 of them to talk about in this article.

Note: The following techniques are not only useful when speaking, but for example, rule #3 is a handy technique to write persuasive and easy to follow/read content (e.g., Email).

1. The power of the pause


This technique is one of the essential methods one could learn and practice to improve the effectiveness of his contributions in discussions and meetings.

Adding a pause before you talk allowing the other person to finish, rather than jumping with the first thing comes to your mind to avoid the risk of interrupting the other person if he wants to continue to add something.

Adding pauses when you jump from one point to the next, grabs your audience full attention to what you are saying.

This technique will make people feel more comfortable talking to you and, of course, actively listening to you and what you say. It will also make you and the others more engaged in the discussion.

2. Speak with clarity and confidence



How many times have you been asked (or asked someone) to repeat what you/he/she's just said (multiple times)?

One mistake we all do (both native and non-native speakers) is speaking too fast and tend to swallow the endings of some words, which might change the meaning or cause confusion. If the audience lost focus for few seconds to think about what you said or feels difficulty tracking it, then he will either ask you to repeat what you just said or stop focusing because he is still thinking about some words that you mispronounced.

So next time, try to speak at a slower pace and make yourself clear when speaking. You will see the difference in how confident you become and how engaged the audience is - practicing this technique will improve your cadence, and later it will naturally happen when you speak.

One tip I liked is to speak slowly as if you are giving your phone number to someone and want to make sure he gets it right and able to write it down.



3. The rule of three


Structuring your content, for example, when writing an Email or in a presentation in three parts, makes it very easy for your audience to follow and remember and makes you (the author) as a speaker or writer appear more knowledgeable, credible, and convincing.

As you can see, I followed this approach in this article, and after reading through it, I genuinely believe that you will be able to memorize all three techniques quickly next time you speak or write about something.

Do you know more techniques? Please comment on the article and share them with other readers and me. And as a little practice, write your review using the above methods about the topic and share it with friends.

Saturday, April 6, 2019

The Beatles Problem A - Codeforces #549 DIV1

Few days ago I was trying to solve the beatles problem which was a little bit tricky and I had to analyze it to find enough observations in order to come up with a good solution .. In this article I will go through my observations step by step and hope its easy for you to digest. 

The editorial of the problem is very concise and not easy for everyone to understand so I will be as detailed as possible in this article to make sure you get the idea by going through my observations one by one and of course combine them to code a solution.

Observation #1:


Lets assume the jump we take each time is L, how many jumps do we need to get to S again (S is the start position)? Lets find out by example:

Note: For this observation we can completely ignore a and b

Assume we have n = 2, k = 3 and we start at S = 2:

If L = 1 then the path will be {2, 3, 4, 5, 6, 1, 2} => 6 jumps!
If L = 2 then the path will be {2, 4, 6, 2} => 3 jumps!
If L = 3 then the path will be {2, 5, 2} => 2 jumps!

From the above example we figured out that #jumps = #cities/gcd(#cities, L)

Where gcd is Greatest Common Divisor.

Observation #2: 

We need to figure out L as its much easier to use to brute force a solution (I will show you why in the next observation).

To be honest I didn't get to that observation until I took a small hint from a solution which I couldn't understand (The solution was checking 4 possible values to find L) :O but after some manual work I figured it out.

The 2 X markers on the line are the first and second cities .. from the problem statement we know that city1 has the nearest restaurant at distance A and city2 has nearest restaurant at distance B -> Nice!

We have 2 possibilities for nearest restaurant of the first city .. either its before or after (marked as A1, A2) .. Same for nearest restaurant of the second city (marked as B1, B2).

We know also from the problem statement that the distance between any two neighboring restaurants = K, That means the distance between A* and B* is i*k, where i is any value between 1 ... n (We will know why its < n in the next observation).

- Remember we need to figure out the distance between the 2 Xs which is ???

- Yes, correct - its L

That leaves us with the following 4 possibilities:

Possibility #1: Restaurants are located at (A1, B1):

-> L = i*k + (B1 - A1)

Possibility #2: Restaurants are located at (A1, B2):

-> L = i*k + (-B2 - A1)

Possibility #3: Restaurants are located at (A2, B1):

-> L = i*k + (A2 + B1)

Possibility #4: Restaurants are located at (A2, B2):

-> L = i*k + (A2 - B2)


Observation #3:

Now we need to iterate to find the value of L, but what are the boundaries to find L?

We know that L = i*k + c, where c is one of the possible values {(A+B), (A-B), (-A-B), (B-A)}. 

We also know we have only N*K cities .. so i could be any value between (1 ... N), right?

Now with the above 3 observations we can easily code a solution .. here is my C++ solution for this problem.

using namespace std;

main() {
        long long n, k, a, b;
        cin >> n >> k >> a >> b;

        long long possible[] = {a+b, a-b, -a-b, b-a};

        long long mn = n*k, mx = 1;

        for (int i = 1; i <= n; i++) {
                for (int j = 0; j < 4; j++) {
                        long long x = possible[j]%k;
                        if (x < 0) x += k;

                        mn = min(mn, n*k/__gcd(n*k, i*k+x));
                        mx = max(mx, n*k/__gcd(n*k, i*k+x));

        cout << mn << " " << mx << endl;

If you have questions/feedback or spot a mistake please let me know in the comments.

Sunday, January 13, 2019

Java ForkJoinPool with an exmaple

ForkJoinPool was introduced with the release of Java 7 to solve a very particular set of problems that tend to be hard to solve with any other thread pool implementation.

The class is designed to work with divide and conquer algorithm: those where a task can recursively broken into broken sub-tasks.

It looks just like any other thread pool e.e.,ThreadPoolExecutor class, it implements the Executor and ExecutorService interfaces. It uses an unbounded list of tasks that will be run by the number of worker threads configured or by default the number of CPUs exist.

Example: Parallel Merge Sort

Sorting an array of 1 million elements. We have 3 main sub-tasks to sort the array:
  • Sort the first half of the array
  • Sort the second half of the array
  • Merge the two sorted sub-arrays
The base case is when its faster to use insertion sort to sort the sub-array (lets assume when the array has 10 elements) of course makes more sense than using parallel merge sort here. In the end there will be 1 million tasks to sort the leaf arrays, more than 500,000 tasks are needed to merge those sorted sub-arrays, and more than 250,000 tasks to sort the next merged sub-arrays .... and so on.

The most important point to notice is that none of the tasks can complete until the tasks that they have spawned have also completed. Here is when the ForkJoinPool comes very handy. Of course its doable through a ThreadPoolExecutor but can't be done as efficient as ForkJoinPool and the implementation is much more complex.

In ThreadPoolExecutor a parent task must wait for its child tasks to complete, A thread cannot add another task to the queue and then wait for it to complete as once a thread is waiting it can't be used to run one of the sub-tasks.

bla bla bla ... show me the code.

import static org.hamcrest.MatcherAssert.assertThat;
import static;

import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ThreadLocalRandom;
import lombok.AllArgsConstructor;

public class ForkJoinPoolSample {

  private static int[] elements;

  private static class MergeSortTask extends RecursiveTask<Integer> {
    private int first;
    private int last;

    protected Integer compute() {
      int len = 0;

      if (last-first <= 10) {
        Arrays.sort(elements, first, last+1); 
        len = (last-first+1);
      } else {
        /* Sort two sub-arrays */
        int mid = (first+last) >>> 1;
        MergeSortTask leftSubtask = new MergeSortTask(first, mid);
        MergeSortTask rightSubtask = new MergeSortTask(mid+1, last);

        len += leftSubtask.join();
        len += rightSubtask.join();

        /* Merge two sorted sub-arrays */
        MergeTask mergeTask = new MergeTask(first, mid, last);

      return len;

  private static class MergeTask extends RecursiveTask<Integer> {
    private int first;
    private int mid;
    private int last;

    protected Integer compute() {
      int[] tmp = new int[last - first + 1];
      int left = first, right = mid + 1, indx = 0;

      while (left <= mid && right <= last) {
        if (elements[left] <= elements[right]) {
          tmp[indx++] = elements[left++];
        } else {
          tmp[indx++] = elements[right++];

      while (left <= mid) {
        tmp[indx++] = elements[left++];

      while (right <= last) {
        tmp[indx++] = elements[right++];

      for (indx = 0; indx < tmp.length; indx++) {
        elements[first + indx] = tmp[indx];

      return tmp.length;

  private static void createRandomInts() {
    elements = new int[100000];
    final ThreadLocalRandom random = ThreadLocalRandom.current();

    IntStream.range(0, 100000)
        .forEach(i -> elements[i] = random.nextInt());

  public static void main(String[] args) {

    long before = System.currentTimeMillis();
    int n = new ForkJoinPool().invoke(new MergeSortTask(0, elements.length-1));
    long after = System.currentTimeMillis();

    System.out.println("Sorted " + n + " Elements in " + (after-before) + " ms.");

    boolean sorted = IntStream.range(0, elements.length-1)
        .allMatch(i -> elements[i] <= elements[i+1]);

    assertThat(sorted, is(true));

From the doc:

fork(): Arranges to asynchronously execute this task in the pool the current task is running in
join(): Returns the result of the computation when it is done

Those methods use a series of internal, per-thread queues to manipulate the tasks and switch threads from executing one task to executing another. Of course all of that is transparent to the developer.


Saturday, January 5, 2019

Java Weak References

Reusing objects is important in Java but also it can cause memory and performance issues if the objects to be reused can't be freed out by GC. Sometimes we need to reuse objects as soon as they are still being referenced or as soon as they may have good chance to be used in the future.

Weak references give us the opportunity to achieve this by not largely affecting memory and performance of our application (In a more GC-friendly). In today's post I will go through the differences between strong and weak references in Java and the effect of them on garbage collector.

Strong References


Strong references are the default type/class references in Java. Objects that are strongly references aren't eligible for GC neither minor nor full GC until they are not strongly referenced anymore. 


All object references in Java are strongly referenced unless explicitly specified, see below sections.

StringBuilder builder = new StringBuilder();

Weak References

Weak reference objects are not default and must be explicitly specified. This type of references is to maintain references to objects that are `WEAK` meaning that if the object is eligible for GC `not strongly referenced anymore` but still `weakly referenced` the object can be collected.

StringBuilder builder = new StringBuilder();
WeakReference<StringBuilder> weakBuilder = new WeakReference<>(builder);

Soft References


This type of references is also a weak reference that remains in memory for longer - It resists minor GC until memory is really needed to be reclaimed (Application is reaching OOM then it will clear all soft references). Soft references are essentially one large, least recently used (LRU) object pool (cache).

The JVM keeps track of the last access to each reference and calculates if the soft reference is eligible for GC. This is controlled by the JVM `-XX:SoftRefLRUPolicyMSPerMB` flag which is by default = 1000 = One second of lifetime per free megabyte in the heap

StringBuilder builder = new StringBuilder();
SoftReference<StringBuilder> weakBuilder = new SoftReference<>(builder);

Phanotm References


Phantom references help us doing finalization to avoid implementing the `Object.finalize` method which could have negative implications to the application as its not deterministic and can make the object reachable again or negatively impact application performance.

Phantom references are different from Weak/Soft references in that GC will not collect a phantom reachable object until its cleared out all acquired resources.

`PhanomReference` class accepts two parameters the referent object and a `ReferenceQueue` which is then used to enqueue objects eligible for clearance.

ReferenceQueue q = new ReferenceQueue();
PhantomReference pr = new PhantomReference(object, referenceQueue);
// Later on another point
Reference r = q.remove();
// Now, clear up any thing you want

Quick Summary (From: Java Performance - The Definitive Guide)

  • Indefinite (soft, weak, phantom) references alter ordinary lifecycle of java objects, allowing them to be reused in ways that may be more GC-friendly.
  • Weak references should be used when an application is interested in an object only if that object is strongly referenced else where in the application.
  • Soft references hold onto objects for (possibly) long periods of time, providing a simple GC-friendly LRU cache.
  • Indefinite reference consume their own memory and hold onto memory of other objects for long periods of time; they should be used sparingly.

Monday, December 24, 2018

Command line tools every (Java) developer should know

In this post I will go through some useful command line tools to debug and tune your service. I will show a sample output and description of the most important parts of the output, feel free to read the manual pages for more details about the tools and supported flags to tune their output.


This system tool is very useful to view and monitor statistics of your system processes, memory, paging, block IO, disks, and CPU. Its useful to check IO/CPU utilization and spot any bottlenecks.


$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 12583088 119480 1590740    0    0   406    72  470 1035 10  3 87  0  0
 0  0      0 12582832 119480 1590740    0    0     0     0  451 1562  1  0 98  0  0
 0  0      0 12579484 119480 1590732    0    0     0     0  408 1345  1  0 98  0  0

The above command is to show stats with 1 second delay.

Processes: Amount of runnable and un-interruptible processes
Memory: Free/cache memory and memory used as buffers and the amount of virtual memory used (swpd)
Swap: Swap in and out (from disk)
IO: Blocks in (READ) and out (WRITE) from disk
System: Number of interrupts per second and context switches
CPU: Time running user code vs system (kernel) code, idle time, and waiting for IO



This system tool is very useful to view and monitor IO statistics of your system.


$ iostat -xm 5
Linux 4.15.0-42-generic

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.27    0.02    1.59    0.15    0.00   92.97

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     5.29   20.82    6.42     0.43     0.11    40.69     0.02    1.18    0.25    4.20   0.14   0.39

The -x flag is to show extended statistics and -m is to view stats in megabytes per second. Of course some of the information above can also be viewed by the previous tool `vmstat`.

%user, %system, %iowait, %idle: The percentage of CPU spent running user code, system code, waiting for IO, and idle
rrqm/s, wrqm/s: The number of (read/write) requests merged per second that were queued to the device
r/s, w/s, rMB/s, wMB/s: Reads/Writes (after merge) per seconds, MBs per seconds (read/write)
await, r_await, w_await: Average time in ms for IO requests to the device to be served, average time in ms for read, average time in ms for write


This tool isn't installed by default in linux systems but can be installed using package managers or downloaded from sourceforge. It basically does the same as previous tools but for network monitoring.


$ nicstat 5
    Time      Int   rKB/s   wKB/s   rPk/s   wPk/s    rAvs    wAvs %Util    Sat
20:10:52       lo    0.33    0.33    3.98    3.98   85.25   85.25  0.00   0.00
20:10:52   wlp2s0    6.18    1.85   12.23    9.03   517.6   210.0  0.00   0.00

Prints network statistics ever 5 seconds.

Int: Interface name
rKB/s, wKB/s: KBs Read(Received) Write(Sent)
rPk/s, wPk/s: Packets received/sent
rAvs, wAvs: Average packet size received/sent
%Util, Sat: Percentage utilization of the interface, Saturation (errors/second)


This tool and the coming few ones come along with the JDK and can be used to send diagnostic commands to a running JVM.


$ jcmd 8880 VM.uptime # 8880 is the process ID, VM.uptime is to check uptime of the running java process

163.883 s

$ jcmd 8880 VM.system_properties # View system properties of a single java process

#Mon Dec 24 20:32:01 CET 2018 Runtime Environment
java.vm.vendor=Oracle Corporation
path.separator=\: 64-Bit Server VM
..... # and more .....

$ jcmd 8880 VM.version

OpenJDK 64-Bit Server VM version 25.191-b12
JDK 8.0_191

$ jcmd 8880 VM.command_line # The command line of the process was started

VM Arguments:
java_command: HelloWorld -Dse7so=29 -client
java_class_path (initial): .
Launcher Type: SUN_STANDARD

$ jcmd 8880 VM.flags # Enable flags - try with [-all]

-XX:CICompilerCount=3 -XX:InitialHeapSize=262144000 -XX:MaxHeapSize=4175429632 -XX:MaxNewSize=1391460352 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=87031808 -XX:OldSize=175112192 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC

$ jcmd 8880 Thread.print # Thread dump - see also jstack tool below
# Very long output here that can be saved to a file for later analysis

$ jcmd 8880 #
Command executed successfully

$ jcmd 8880 GC.class_histogram # Show heap histogram ([C is character array, [B is byte array, [I is integer array)

 num     #instances         #bytes  class name
   1:          1157        1614520  [C
   2:           131         216072  [I
   3:           474          53992  java.lang.Class
   4:          1145          27480  java.lang.String
   5:           531          26632  [Ljava.lang.Object;
   6:            20          25264  [B
   7:           378           9072  java.util.LinkedList$Node
   8:           211           6752  java.util.HashMap$Node
   9:           190           6080  java.util.LinkedList
  10:            75           5400  java.lang.reflect.Field
  11:           256           4096  java.lang.Integer
  12:            93           3720  java.lang.ref.SoftReference
  13:           111           3552  java.util.Hashtable$Entry
  14:             7           2632  java.lang.Thread
  15:            12           1984  [Ljava.util.HashMap$Node;
  16:            51           1896  [Ljava.lang.String;
  17:            38           1824  sun.util.locale.LocaleObjectCache$CacheEntry
  18:            47           1504  java.util.concurrent.ConcurrentHashMap$Node
  19:            23           1472
  20:            14           1120  [Ljava.util.WeakHashMap$Entry;
  21:            14           1120  java.lang.reflect.Constructor
  22:             2           1064  [Ljava.lang.invoke.MethodHandle;
  23:             1           1040  [Ljava.lang.Integer;
  24:            26           1040
  25:             6            992  [Ljava.util.Hashtable$Entry;
  26:            15            840  java.lang.Class$ReflectionData
  27:            21            840  java.lang.ref.Finalizer


In fact this tool is a GUI tool but it worth mentioning as it provides very useful information to monitor and control java applications.

It views information about Memory, CPU, Threads, and Classes loaded.


Provides heap dumps and other information about JVM memory usage.


$ jmap -dump:live,format=b,file=/tmp/dump.hprof 9293
Dumping heap to /tmp/dump.hprof ...
Heap dump file created

Generates a dump from a live process, in binary format and saves it to /tmp/dump.hprof - you can then analyze it with any heap dump analyzer.


Useful to generate thread dumps with full stack traces.


$ stack -l > /tmp/myapp.tdump

You can then analyze the thread dump using any thread dump analyzer.


This is also a GUI tool but very useful to monitor your java application. Its man page describes it as all-in-one java troubleshooting tool and in fact it is very nice and can be very useful along with the above commands. you can also use to analyze heap and thread dumps generated earlier using jmap and jstack.


Is one of the best tools to view very useful stats about GC, JIT compiler, and so many other things to monitor.


$ jstat -gcutil -t 9293 100ms
Timestamp         S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   
         5452.8   0.00   0.00  77.88   0.86  96.16  84.57     10    0.056    10    0.295    0.351
         5453.0   0.00   0.00  77.88   0.86  96.16  84.57     10    0.056    10    0.295    0.351

The above shows GC information (the -t to show timestamps) every 100ms.

S0, S1: Survivor spaces 0 and 1 utilization as a percentage of the space's current capacity
E, O, M: Eden space, Old space, Metaspace utilization as percentage of the space's current capacity
CCS: Compressed class space utilization as a percentage
YGC, YGCT: Number of young generation GC events and young generation gc time
FGC, FGCT: Number of full GC events, and full GC time
GCT: Total garbage collection time

When the Eden space percentage goes up this triggers a young generation minor GC event which then will reduce its size and the S0, S1 will be swapped and of course Old generation increases a bit (some objects move from Y to O) - Full GC events are triggered when the Old generation percentage goes up  and as a result its size is reduced and fragmented.

$ jstat -class -t 9293 1s
Timestamp       Loaded  Bytes  Unloaded  Bytes     Time   
         5845.2   3602  7665.3       13    15.8       1.33
         5846.2   3602  7665.3       13    15.8       1.33
         5847.2   3602  7665.3       13    15.8       1.33
         5848.2   3602  7665.3       13    15.8       1.33

The same command but to view class loader statistics every 1 second.

Loaded: Number of classes loaded
Bytes: Number of bytes loaded
Unloaded: Number of classes unloaded
Bytes: Number of bytes unloaded
Time: Time spent performing class loading and unloading

$ jstat -printcompilation -t 9293 1s
Timestamp       Compiled  Size  Type Method
         6067.7     3744    684    1 java/util/ComparableTimSort sort
         6068.7     3744    684    1 java/util/ComparableTimSort sort
         6069.7     3744    684    1 java/util/ComparableTimSort sort

The same command but to view Java HotSpot VM compiler method statistics.

Compiled: Number of compilation tasks performed on the method
Size: Size of code byte code (not binary code)
Type: Compilation type of the most recently compiled method 
Method: Class name and method name identifying the most recently compiled method
$ jstat -compiler -t 9293 1s
Timestamp       Compiled Failed Invalid   Time   FailedType FailedMethod
         6378.9     3753      3       0    12.54          1 org/netbeans/lib/profiler/server/ProfilerRuntimeObjLiveness traceObjAlloc
         6380.0     3753      3       0    12.54          1 org/netbeans/lib/profiler/server/ProfilerRuntimeObjLiveness traceObjAlloc
         6381.0     3753      3       0    12.54          1 org/netbeans/lib/profiler/server/ProfilerRuntimeObjLiveness traceObjAlloc
         6382.0     3753      3       0    12.54          1 org/netbeans/lib/profiler/server/ProfilerRuntimeObjLiveness traceObjAlloc

Java HotSpot VM Just-in-Time compiler statistics.

Compiled: Number of compilation tasks performed
Failed: Number of failed compilation tasks
Invalid: Number of invalidated compilation tasks
Time: Time spent on compilation
FailedMethod: The most recent failed method to compile

The last two examples are a bit hard to understand if you don't really know the basics of JIT and how it works .. you can go ahead and read what happens behind the scene to realize the importance of both examples and how you can use them to diagnose possible performance issues in your services.

Those are the most useful tools from my point of view to monitor, diagnose, troubleshoot your services .. please comment with other tools you might see useful but not stated above.

Saturday, October 20, 2018

The guide to be a better team member

Its been a while since I posted something, and even longer for a non-tech one. 

Today's post is a recipe for being a better team member or even better if you already are. The major thing here is to start applying all the following steps yourself before asking others to do them. 

Step 1: Feedback


Everyday we give or receive feedback in different formats (e.g., Code review, Design review, or even face to face feedback). I see most of the issues that arise in every team is because of feedback - either someone gives feedback in an inappropriate way or not being open for feedback.

My manager once told me "Any feedback is a good feedback", and another manager told me once "Take the feedback and filter what really makes sense to you but always respect and assume good intentions".

The idea behind this is to always assume good intentions keeping in mind culture difference and preferences of people based on culture, background, and experience.

In case you are the one who is giving feedback, always think about it and think what is the best way to give it either in private or if OK to be in public (e.g., Review sessions). Also keep in mind culture difference and other people's preferences and make sure you don't turn people down by giving feedback inappropriately, this way you will lose them or even worse lose their trust.

Step 2: Disagree and commit


Everyday you and other team members propose solutions for current team problems either technical or non-technical. You and your colleagues have less chance to agree on all of them.

Never ever take it personal or be frustrated that there are different opinions or views "I know its hard" .. but usually if the team agrees on something and commit to it, you MUST commit to it as well. This has great potential for someone in the team to learn something new.

Step 3: Choose a mentor for yourself

Mentoring is one of the best ways for someone to learn and receive great feedback that helps improving.

I personally usually ask one or two of my colleagues to observe me and give me feedback in private if they have any, from my personal experience this helped me to improve in different areas which I had good potential for improvement "and of course still have".

Step 4: Mentor someone


This is exactly the same as step number 3 but the other way around, where you will be the mentor/observer for another team memer(s).

From my experience this helps earning your colleagues' trust and appreciation for your honest feedback both positive and non-positive.

Step 5: Learn from your mistakes

This is of course the clearest one so far. Its also a great way to measure improvement. 

As an example if you receive code review feedback in an open way as potential to learn something new by constructive discussions with other team members, only this way you will learn and remember to not repeat the same mistake again and again.

Good luck