Thursday, August 13, 2020

How to build a development laptop on macOS X

Developer tools enhance

Install xcode

xcode-select --install

Install git

Latest Mac OS X has git integrated.

$ git --version

Type the above command will show the git version installed by default or it will prompt you to install one.

sudo command

Unlike redhat, ubuntu, to execute a sudo command in darwin Terminal on your Mac, you must be logged in with an administrator account that has a password. When you're logged in to your Mac using an administrator account, you can use the sudo command in the Terminal app to execute commands as a different user, such as the root user. After you enter the command, Terminal asks you to enter your account password.

Install macport

Mac os don't have native package manager such as rpm or apt-get, which can install linux package and its dependencies from package repository using command line. Third party tools filled this void. The most popular package management tools for mac os are macport and homebrew. 

So far macport has more packages and the architecture is more stable on the newer versions of mac os. 

Homebrew is geared towards ease of use, and its repository is limited by the fact that it uses OS X's shipped libraries wherever it can. Homebrew is the installing tool in the documents for lots of softwares like springboot, Git, Ruby, and Node. Homebrew don't need sudo command to install software.

Without macport or homebrew, you can still download the *.pkg files from various websites then double-click to install them on your mac os. The recommended website is apple's app store. 

So in short, if you don't want to use command line to install packages, use app store or other package providers' download page, if you are a developer favor quick moving, use homebrew, otherwise use macport. Installing both homebrew and macport on the same machine will invite compatibility issue in the long run.

To install homebrew, go to homebrew page and follow the instructions.

To install macport, go to macport download page and download the pkg file corresponding to your mac version. The mac version can be found by clicking the apple icon at the top left corner, then select "About This Mac".

Alternatively, you can run the following scripts to install macport from git repo source code. You need to login with an administrator account that has a password to finish the install.
$ mkdir -p /opt/mports
$ cd /opt/mports
$ git clone https://github.com/macports/macports-base.git
$ git checkout v2.6.3  # skip this if you want to use the development version

$ cd /opt/mports/macports-base
$ ./configure --enable-readline
$ make
$ sudo make install
$ make distclean
$echo "export PATH=/opt/local/bin:/opt/local/sbin:\$PATH" >> ~/.profile

After the install, the command "port version" should tell you the version 2.6.3 is installed.

From now on, if you find any linux command missing, for example wget, you can type
$port search wget
$sudo port install wget

to have the command installed.

Java Stack

Install java

now you have macport, you can search for openjdk
$port search openjdk

then install one of the jdk from the list. 
$sudo port install openjdk14

Alternatively, you can go to oracle website and download the openjdk14 and double-click. The advantage of this approach is, you don't need to login with an administrator account.

After installation, you can verify the jdk installation path:

$echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk{your-jdk-version}.jdk/Contents/Home

Install maven

You need to download maven binary then add it to the command path.
The following script did that for you

$wget http://mirror.cogentco.com/pub/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
$tar xzvf apache-maven-3.6.3-bin.tar.gz
$echo "export PATH=/opt/apache-maven-3.6.3/bin:\$PATH" >> ~/.profile

after that, you can type "mvn --version" to verify the installation.

Install spring tools 4 for eclipse

Got a dmg file from https://spring.io/tools and double click it.

Javascript Stack

Install nodejs

You can use 
$port search nodejs
$sudo port install nodejs14
to have macport to install nodejs for you.

Alternatively, you can go to https://nodejs.org/en/download/ and download the MacOs Installer and double click to install it.

Once installed, type "node --version" to verify it is installed.

Install npm

The npm to NodeJS is like maven to Java. When you download Node.js, you automatically get npm installed on your computer. The npm (Node Package Manager) is a command-line tool for interacting with online repository for open-source Node.js projects.

use command "npm version" to verify the tool is enabled.

Install Visual Studio Code

Visual Studio Code is the most popular javascript IDE. The installation is copied from the Visual Studio Code site.

  1. Download Visual Studio Code for macOS.
  2. Open the browser's download list and locate the downloaded archive.
  3. Select the 'magnifying glass' icon to open the archive in Finder.
  4. Drag Visual Studio Code.app to the Applications folder, making it available in the macOS Launchpad.
  5. Add VS Code to your Dock by right-clicking on the icon to bring up the context menu and choosing OptionsKeep in Dock.

Install angularjs

install angular cli with npm:
$npm install -g @angular/cli

after angularjs is installed, verify with
$ng --version

Python Stack

Install pyenv and python

Python has many versions, the default version on your mac might not satisfy your project's requirement, you want to be able to install multiple versions of python and switch among them freely. The solution here is pyenv.

If you are use homebrew, installing pyenv is as simple as 
brew install pyenv

macport doesn't have a pyenv port yet.

Anyway, you can install pyenv wihtout homebrew or macport. 
You can follow the instructions and install pyenv with pyenv-installer.

once pyenv is installed, you can install and use multiple versions of python.

To install a particular python version.
$ pyenv install 3.7.3

Then you can set that version as system default.
$ pyenv global 3.7.3

The python version 3.7.3 is now the default, you can verify that with
$ python -v

Install pycharm or do python support for visual studio.

pycharm is python dedicated IDE, it is recommended for developers who want to build large python project. pycharm is reported to be heavy and slow. The alternative is visual studio code with python support installed.

DB Stack

Depending on the requirements, there are many kinds of database we can use, here we only cover MySQL and MongoDB as examples of structured and non-structured databases.

CPA triangle for DBs


Install mysqlDb

Install mysql and set it as default

$ sudo port install mysql8-server
$ sudo port select mysql mysql8

set the owner
$ sudo chown -R _mysql:_mysql /opt/local/var/db/mysql8/ 
$ sudo chown -R _mysql:_mysql /opt/local/var/run/mysql8/ 
$ sudo chown -R _mysql:_mysql /opt/local/var/log/mysql8/ 

auto start at machine boot
$ sudo port load mysql8-server
undo
$ sudo port unload mysql8-server

set password
$ /opt/local/lib/mysql8/bin/mysqladmin -u root -p password

Install MongoDb

solution with homebrew can be found 

for macport
$ port install mongodb@4.4.0
$ sudo port select mongodb@4.4.0
$ sudo port load mongodb@4.4.0

verify the mongodb started with command "mongo"

Cloud Stack

Install docker and kubernetes

docker is the full development platform to build, run and share containerized applications.
kubernetes is the best container orchestration system for GCP (as aws-cli for AWS).

A Docker Desktop package for mac installs both docker and kubernetes.

Install aws cli

aws-cli is the command line util to interact with amazon cloud. You can install it with a mac os package file.

Install azure-cli

azure-cli to microsoft cloud is aws-cli 
currently microsoft support provided only one installation method via homebrew

Install Vagrant

Vagrant allows you to capture environment dependencies in a config file so that you can recreate them on other machines.


Install Ansible

Ansible allows you to manage many remote servers with ssh command. It can be installed with pip

$ pip install --user ansible

Friday, August 7, 2020

Java Design Patterns that makes good use of lambda expressions

Design patterns makes designs and communicating about the designs much easier. By applying the proper design patterns, the we can get rid of boiling plates code, make the code more flexible maintainable, no mention the code is safer and easier to be reused.

Java 7 introduced lambda functions, which allow us to pass functions around as variable. By combining the design patterns and java lambda expressions, we now get even conciser and more powerful code.

Lambda expressions can act as a design tool. In stead of wrapping a function inside an object and pass the object around, we can pass the lambda function as a variable around. Long gone the days of writing lengthy inner classes, welcome to the world of lambda functions.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class test {
    public static void main(String[] args) {
//        Thread t = new Thread(new Runnable() {
//            public void run() {
//                System.out.println("in thread");
//            }
//        });
        Thread t = new Thread(() -> System.out.println("in thread"));
        t.start();
        System.out.println("in main");
        
        ExecutorService exec = Executors.newSingleThreadExecutor();
        exec.execute(() -> System.out.println("in executor thread"));
        exec.shutdown();
    }
}

in thread
in main
in executor thread

Strategy patten

One of the most commonly used design pattern is strategy pattern. We have a Duck class which makes different sound depending on the situations. Instead of passing in a concrete class which provides makeSound function, we pass in an interface with makeSound function. At run time, we can have many concrete implementation of that interface, the Duck class remain the same, but it can make different sounds. Now with lambda expression, the same pattern looks like the following:

public class Duck {
    public static void main(String[] args) {
        QuackBehavior duckCry = () -> System.out.println("quack!");
        FlyBehavior duckFly = () -> System.out.println("fly with wings");
        QuackBehavior dummyCry = () -> System.out.println("no sound ...");
        FlyBehavior dummyFly = () -> System.out.println("wooden duck don't fly");
        
        Duck duck = new Duck(duckCry, duckFly);
        duck.cry();
        duck.fly();
        
        duck = new Duck(dummyCry, dummyFly);
        duck.cry();
        duck.fly();
        
        duck = new Duck(dummyCry, duckFly);
        duck.cry();
        duck.fly();
    }
    
    private QuackBehavior quack;
    private FlyBehavior fly;
    
    public Duck(QuackBehavior quack, FlyBehavior fly) {
        this.quack = quack;
        this.fly = fly;
    }
    
    public void cry() {
        this.quack.makeSound();
    }
    
    public void fly() {
        this.fly.fly();
    }
    
    private interface QuackBehavior {
        public void makeSound();
    }
    
    private interface FlyBehavior {
        public void fly();
    }
}

Decorator Pattern

Recall our famous Starbuzz Beverages Example.

starbuzz decorator example
starbuzz decorator example


We have an abstract class Beverage with the two methods getDescription() and cost(). The getDescription() method is already implemented for us, but the cost() method is abstract.

public abstract class Beverage {
    String desc = "some beverage";
    public String getDescription() {
        return desc;
    }
    public abstract double cost();
}

Then there are a few coffee type classes that extend the Beverage. For example, 
public class DarkRoast extends Beverage {
    public DarkRoast() {
        super.desc = "DarkRoast";
    }
    @Override
    public double cost() {
        return .99;
    }
}

Now the decorators.
The super class of all sorts of decorators is and abstract class that extends Beverage, it force the subclasses to provide the description.

public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}

A decorator extends CondimentDecorator, it takes the wrapped object as a parameter in constructor, then store it as an instance variable, so that when later the getDescription() or cost() is called, it can add new states to the wrapped object, like a decorator does.

public class Milk extends CondimentDecorator {
    Beverage beverage;
    
    public Milk(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ", Milk";
    }

    public double cost() {
        return beverage.cost() + 0.10;
    }
}

public class Soy extends CondimentDecorator {
    Beverage beverage;
    
    public Soy(Beverage beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ", Soy";
    }

    public double cost() {
        return beverage.cost() + 0.11;
    }
}

Finally, the decorated objects can be wrapped by another decorator class, and we can do this wrapping forever.

public class StarbuzzCoffee {
    public static void main(String...args) {
        Beverage coffee = new DarkRoast();
        coffee = new Milk(coffee);
        coffee = new Soy(coffee);
        System.out.println(coffee.getDescription());
        System.out.println(coffee.cost());
    }
}

output:
DarkRoast, Milk, Soy
1.2000000000000002

What we have learned from the example? We can start from the outmost layer of wrapper class, apply its behavior function, then apply the inner layer's behavior function, which in turn, after applying its own behavior function, then calls another layer of inner wrapper class's behavior function, like a chain reaction.

Let's open the LambdaStarBuzzCoffee shop, hope you enjoy it. Wait, where are the coffees, shop and condiments in this futuristic shop?

import java.util.function.*;
import java.util.stream.Stream;
public class LambdaBeverage {
    
    public String getDescription(String desc, Function<String, String>...descriptionDecorators) {
        return Stream.of(descriptionDecorators).reduce(Function.identity(), Function::andThen).apply(desc);
    }
    
    public double cost(double cost, Function<Double, Double>...costDecorators) {
        return Stream.of(costDecorators).reduce(Function.identity(), Function::andThen).apply(cost);
    }
    
    public static void main(String...args) {
        Function<Double, Double> soyCost = i -> i + 0.11;
        Function<Double, Double> milkCost = i -> i + 0.10;
        Function<String, String> soyDesc = i -> i + ", soy";
        Function<String, String> milkDesc = i -> i + ", milk";
        LambdaBeverage LambdaCoffee = new LambdaBeverage();
        System.out.println(LambdaCoffee.getDescription("darkroast", soyDesc, milkDesc));
        System.out.println(LambdaCoffee.cost(0.99, soyCost, milkCost));
    }
}

output:
darkroast, soy, milk
1.2000000000000002


Fluent interface pattern

In software engineering, a fluent interface is an object-oriented api whose design relies extensively on method chaining. Its goal is to increase code legibility by creating a domain specific language. For example, instead of pass in the private field values as constructor parameters. They are set in the setter functions. The setter function returns the object itself, therefore we can chain the setter methods together to get a more fluent interface.

public class Kitten {
    private String name;
    private String color;
    public Kitten name(String name) {
        this.name = name;
        return this;
    }
    public Kitten color(String color) {
        this.color = color;
        return this;
    }
    
    public void play() {
        System.out.println(name + " has " + color + " fur");
    }
    
    public static void main(String[] args) {
        new Kitten().color("red").name("Mina").play();
    }
}

The drawback in the above pattern is, we have to create the object with new keyword. It is a drawback because:
  1. the user of Kitten class don't necessarily concern about how the Kitten object is created, as long as it has name and color property.
  2. the code is not flexible. If we want to get the Kitten object from an object pool instead, the burden has to be put to the user, who might be a simple user and should not deal with tech aspects such as object pool, reflection, spring annotation etc.
The LambdaKitten class get the fluent interface design pattern further. Instead of having the user to create the Kitten object with new keyword, the Kitten object is created within the LambdaKitten class itself. The user's responsibility is to specify the name and color of a given kitten. This way, the LambdaKitten class can change the object creation code without changing the interface.

import java.util.function.Consumer;

public class LambdaKitten {
    private String name;
    private String color;
    private LambdaKitten() {}
    public static void play(Consumer<LambdaKitten> consumer) {
        LambdaKitten kitten = new LambdaKitten();
        consumer.accept(kitten);
        System.out.println(kitten.name + " has " + kitten.color + " fur");
    }
    
    public LambdaKitten name(String name) {
        this.name = name;
        return this;
    }
    
    public LambdaKitten color(String color) {
        this.color = color;
        return this;
    }
    
    public static void main(String...args) {
        LambdaKitten.play(kitten -> kitten.name("Mina").color("red"));
    }
}

Virtual Proxy Pattern

We sometimes use a proxy class to control access to an object that is expensive to instantiate. In this pattern, both the class providing the functionality and the proxy representing these functionality implement the sa,e interface. The proxy class has an instance of the proxied class as a private field. When client need to access the functionality promised in the interface, they don't have access to the proxied class, they only have access to the proxy class. The proxy class can implement techniques such as lazy loading, a functionality which is not necessary a concern of the proxied class. For example.

public interface Singer {
    public void sing();
}

=============================
public class XyzSinger implements Singer {
    private String songName;
    
    public XyzSinger(String songName) {
        this.songName = songName;
        practice(songName);
    }
    
    public void sing() {
        System.out.println(this.getClass().getName() + " sings " + songName);
    }
    
    private void practice(String songName) {
        System.out.println("practicing " + songName);
    }
}
============================
import java.util.Random;

public class Proxy implements Singer {
    private Singer singer;
    private String songName;
    public Proxy(String songName) {
        this.songName = songName;
    }

    public void sing() {
        if(singer == null) {
            singer = new XyzSinger(songName);
        }
        singer.sing();
    }
    
    public static void main(String...args) {
        Singer singer = new XyzSinger("always song");
        Proxy agent = new Proxy("Lazy song");
        if(new Random().nextBoolean()) {
            singer.sing();
            agent.sing();
        }
    }
}

output:
practicing always song
=====or===============
practicing always song
XyzSinger sings always song
practicing Lazy song
XyzSinger sings Lazy song

In the above example, Proxy doesn't really concern about which singer is singing the song, and the singer probably doesn't care about how the proxy arranges the shows for the same song she/he has practiced.

The advantage of proxy is lazy loading. If we have the XyzSinger to sing the song, he/she will always practice the song even without audience. The lazy proxy, after taking the songName, don't even bother to have his/her represented singer to practice unless the show is real.

This kind of lazy loading requirement can be alternatively achieved with lambda functions.

public interface Singer {
    public void sing();
}

=============================
public class XyzSinger implements Singer {
    private String songName;
    
    public XyzSinger(String songName) {
        this.songName = songName;
        practice(songName);
    }
    
    public void sing() {
        System.out.println(this.getClass().getName() + " sings " + songName);
    }
    
    private void practice(String songName) {
        System.out.println("practicing " + songName);
    }
}
import java.util.Random;
import java.util.function.Supplier;

public class LamdaProxy<T> {
    private T instance;
    private Supplier<T> supplier;
    public LamdaProxy(Supplier<T> supplier) {
        this.supplier = supplier;
    }
    public T get() {
        if(instance == null) {
            instance = supplier.get();
            supplier = null;
        }
        return instance;
    }
    
    public static void main(String...args) {
        Singer diligentSinger = new XyzSinger("always song");
        LamdaProxy<Singer> agent = new LamdaProxy<>(() -> new XyzSinger("lazySong"));
        if(new Random().nextBoolean()) {
            diligentSinger.sing();
            Singer singer = (Singer)agent.get();
            singer.sing();
        }
    }
}

As we can see, LambdaProxy in this case is fat and clumsy, however, it demonstrated a new way of achieving lazy load. The constructor takes a Supplier that expresses how to supply a singer, however, the singer object won't be created until the get() method is called. LamdaProxy is more flexible than the Proxy, because now the creation of singer became a variable. While Proxy can only represent a XyzSinger, the LambdaProxy can represent any singer. For example, you can introduce your spouse or 5 year old kid to the LamdaProxy, the LamdaProxy will arrange a show to have them sing whatever song you like with whatever special effect you want.

import java.util.function.Function;


public interface Singer {

    public void sing(Function<String, String>...songDecorators);

}


=============================

import java.util.Random;

import java.util.function.Function;

import java.util.function.Supplier;

import java.util.stream.*;


public class LamdaProxy<T> implements Singer{

    public static Function<String, String> lightEffect = i -> i + ", color enhenced";

    public static Function<String, String> soundEffect = i -> i + ", disco enhenced";

    private T instance;

    private Supplier<T> supplier;

    public LamdaProxy(Supplier<T> supplier) {

        this.supplier = supplier;

    }

    public T get() {

        if(instance == null) {

            instance = supplier.get();

            supplier = null;

        }

        return instance;

    }

    

    public static void main(String...args) {

        String songName = "whatever song";

        Singer a = decorators -> {

            String customizedSong = Stream.of(decorators).reduce(Function.identity(), Function::andThen).apply(songName);

            System.out.println("practicing " + customizedSong);

            System.out.println("whatever name sings " + customizedSong);

            };

        LamdaProxy<Singer> agent = new LamdaProxy<>(() -> a);

        if(new Random().nextBoolean()) {

            agent.sing(soundEffect, lightEffect, i -> i + ", happy birthday");

        }

    }


    public void sing(Function<String, String>...songDecorators) {

        Singer singer = (Singer)supplier.get();

        singer.sing(songDecorators);

    }

}


no output or output the following:

practicing whatever song, disco enhenced, color enhenced, happy birthday

whatever name sings whatever song, disco enhenced, color enhenced, happy birthday


Isn't it cool or is it a little bit too much?

Like it or not, the lambda expression is a great design tool.

meta.ai impression

Meta.ai is released by meta yesterday, it is super fast you can generate image while typing! You can ask meta.ai to draw a cat with curvy fu...