Reduce Code & Focus on Return On Code

Value of reducing code

Reducing amount of code is one of the MOST REQUIRED & IMPORTANT skill in real software development workplace, especially in team based software development.
Most of the case, reducing code is much more valuable than writing code!
Why doesn't any computer science teach this MOST important skill!
Let me point out benefits of reducing code:

  • The less code makes programmer be the easy to understand project!
    • The amount of code they should read is lesser!
    • Fledgling developer easy to understand!
    • You don't have to write much test code!
    • Complexity should tend to be lower!
  • Code duplication tends to be less!
  • Prevent regression!
  • You can only care about code which really lively works!

Put it all together, These benefits finally leads "Improve code maintainability" and "Reduce maintenance cost".
I mention just in case - reducing code doesn't mean you should merge a few "for loop" lines into single line.
My principles for reducing code are:

  • Delete unused code if you think it won't be used or just leave it for reference. The code can be easily pullout if you use version control system.
  • Remove duplication and extract abstraction. Too much abstraction is quite bad, so this principle cannot apply in an automatic manner.
  • Remove comments unless you have time to maintain them properly. Keep proper comment costs much more than you think and obsolete or meaningless comment leads downcast of project.

Most software developer (maybe including me) show off in a patronizing way about how much they can write code.
And measure value of developer by the amount of code he or she can write.
I think this measurement is completely wrong for team based software development.
Less code makes much more quicker business action possible & reduces maintenance cost.

Return on Code (ROC)

Let me propose new measurement for business efficiency or productivity of software - Return On Code (ROC).
ROC means if lines of code is less and less, the measurement is higher and higher! i.e. your code helps business (=makes money) much more efficiently.
ROC is inspired by Return On Investment (ROI) which represents the benefit to the investor resulting from an investment of some resource.
I think writing code is investment and its artifact (software) makes money. So it's natural to calculate this kind of measurement similar to ROI.
Let's write code with a focus on business rather than just writing code unconsciously!!


Java: Identify Country From IP Address

Identify Country From IP Address

Many people sometimes would like to identify country from IP address when you check access log or something.
Most of the people google with keywords like "ip address country" or "whois ip" or something, and then use the internet service which they find.

In this post, I will show you program for identifying country from IP address.
I wrote the program in Java, but if you an average developer you can easily translate into the program language you prefer.

Using File Provided by RIR

IP address is allocated, registered and managed by regional internet registry (RIR).
There are five organization based on covering region:

  • African Network Information Centre (AfriNIC): Africa
  • American Registry for Internet Numbers (ARIN): the United States, Canada, several parts of the Caribbean region, and Antarctica.
  • Asia-Pacific Network Information Centre (APNIC): Asia, Australia, New Zealand, and neighboring countries
  • Latin America and Caribbean Network Information Centre (LACNIC): Latin America and parts of the Caribbean region
  • Réseaux IP Européens Network Coordination Centre (RIPE NCC): Europe, Russia, the Middle East, and Central Asia
The each organization provides the RIR formatted file which tells "Which IP addresses are allocated to which country"
So we use this file, then we can identify country from ip address! bravo!

The RIR file format is quite simple, something like below:


The important parts are:

  • 2nd: country
  • 3rd: type
  • 4th: start ip address
  • 5th: number of ip addresses allocated from the start which is on the 4th column
  • 7th: status
I think you should download the file yourself from the following locations and read the official document here.
Then you can understand much more details rather than my too simplified explanation :P
  • http://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest
  • http://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest
  • http://ftp.apnic.net/pub/stats/apnic/delegated-apnic-extended-latest
  • http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest
  • http://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest

Java Code

The program can do below:

  • Download RIR files
  • Create IP address range cache file
  • Check country based on the IP address range cache file
What you should improve:
  • I think you might be better to store the RIR file data or cache file data in database for actual application usage.
  • you should merge some continuous IP ranges for more efficiency. For simplicity, I left it as it is.
Okie. Now I will show you the whole java program for identifying country from ip address.
The advantage of this program is only using Java Standard Development Kit. i.e. no external library required!

Core Code

package com.dukesoftware.utils.net.ipaddress;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

public class IpAddressCountryIdentifier {

    public static void main(String[] args) throws URISyntaxException,
            IOException {
        IpAddressCountryIdentifier checker = new IpAddressCountryIdentifier("c:/temp");
        // you should not call following methods every ip address check
        // updating these files once a day should be fine
        // checker.saveRIRFiles();
        // checker.createIpAddressFileFromRIRFile();
                .guessCountry("ip address which you would like to test here"));

    private static final String[] URLS = new String[] {
            "http://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest" };

    private final static Map<String, String> FILES = new HashMap<String, String>() {
            Pattern pattern = Pattern.compile("^.+/");
            for (String URL : URLS) {
                String fileBody = pattern.matcher(URL).replaceAll("");
                put(URL, fileBody + ".txt");

    private final Cache cacheV4 = new Cache(
            ipAddressStr -> ipAddressStr.contains("."),
    private final Cache cacheV6 = new Cache(
            ipAddressStr -> ipAddressStr.contains(":"),
    private final String directory;

    public IpAddressCountryIdentifier(String directory) {
        this.directory = directory;

    public void downloadRIRFilesFromNIC() throws IOException {
        for (Entry<String, String> entry : FILES.entrySet()) {
                    new File(directory, entry.getValue()).getAbsolutePath());

    public void createIpAddressCacheFileFromRIRFile() throws IOException {
        File ipv4File = new File(directory, "ipv4.txt");
        File ipv6File = new File(directory, "ipv6.txt");


        for (Entry<String, String> entry : FILES.entrySet()) {
            File file = new File(directory, entry.getValue());
            try (BufferedWriter bwV4 = newWriter(ipv4File);
                    BufferedWriter bwV6 = newWriter(ipv6File)) {
                Utils.processLine(file, line -> {
                    if (line.startsWith("#"))

                    String[] parts = line.split("\\|");
                    if (parts.length < 7)
                    String status = parts[6];

                    if (!(status.equals("allocated") || status
                    String country = parts[1];
                    String type = parts[2];
                    String start = parts[3];
                    long value = 0;
                    try {
                        value = Long.valueOf(parts[4]);
                    } catch (NumberFormatException e) {

                    try {
                        if (type.equals("ipv4")) {
                            bwV4.write(cacheV4.toCacheString(country, start,

                        } else if (type.equals("ipv6")) {
                            bwV6.write(cacheV6.toCacheString(country, start,
                    } catch (IOException e) {
                        throw new RuntimeException("IOError while reading and writing ip address file", e);

    public void loadIpAddessToMemory() throws IOException {
        File ipv4File = new File(directory, "ipv4.txt");
        File ipv6File = new File(directory, "ipv6.txt");

        Utils.processLine(ipv4File, cacheV4::put);
        Utils.processLine(ipv6File, cacheV6::put);

    public String guessCountry(String ipAddress) {
        if (cacheV4.isAcceptableIPString(ipAddress)) {
            return cacheV4.guessCountry(ipAddress);
        if (cacheV6.isAcceptableIPString(ipAddress)) {
            return cacheV6.guessCountry(ipAddress);
        throw new IllegalStateException("Unacceptable ip address format:"
                + ipAddress);

    private static BufferedWriter newWriter(File file)
            throws UnsupportedEncodingException, FileNotFoundException {
        return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(
                file, true), "utf-8"));
    public static BigInteger dotIPv4_to_BigInteger(String dottedIP) {
        String[] addrArray = dottedIP.split("\\.");        
        BigInteger num = BigInteger.ZERO;  
        BigInteger block = BigInteger.valueOf(256);
        for (int i = 0; i < addrArray.length; i++) {            
            int power = 3-i;
            BigInteger value = BigInteger.valueOf(Integer.parseInt(addrArray[i]) % 256);
            value = value.multiply(block.pow(power));
            num = num.add(value);
        return num;
    public static BigInteger colonIpV6_to_BigInteger(String colonedIP) {
        String[] addrArray = colonedIP.split(":", -1);        
        BigInteger num = BigInteger.ZERO;
        BigInteger block = BigInteger.valueOf(65536);
        for (int i = 0; i < addrArray.length; i++) {            
                int power = 8-i;
                BigInteger value = BigInteger.valueOf(Long.parseLong(addrArray[i], 16) % 65536L);
                value = value.multiply(block.pow(power));
                num = num.add(value);
        return num;


Class for represents IP address ranges with country

package com.dukesoftware.utils.net.ipaddress;

import java.math.BigInteger;

final class IpRange {
    private final BigInteger start;
    private final BigInteger end;
    private final String country;

    public IpRange(BigInteger start, BigInteger end, String country) {
        this.start = start;
        this.end = end;
        this.country = country;

    boolean inRange(BigInteger value) {
        return value.compareTo(start) >= 0 && value.compareTo(end) <= 0;

    public String getCountry() {
        return country;


Class for managing IP Address range cache files

package com.dukesoftware.utils.net.ipaddress;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

class Cache {
    private final List<IpRange> ranges = new ArrayList<>();
    private final Predicate<String> ipStringAcceptor;
    private final Function<String, BigInteger> ipStrToBigInteger;

    public Cache(Predicate<String> ipStringAcceptor,
            Function<String, BigInteger> ipStrToBigInteger) {
        this.ipStringAcceptor = ipStringAcceptor;
        this.ipStrToBigInteger = ipStrToBigInteger;

    void put(String line) {
        String[] parts = line.split("\\|");
        put(parts[0], new BigInteger(parts[1]), new BigInteger(parts[2]));

    private void put(String country, BigInteger start, BigInteger end) {
        ranges.add(new IpRange(start, end, country));

    String guessCountry(String ipAddress) {
        if (isAcceptableIPString(ipAddress)) {
            BigInteger value = ipStrToBigInteger.apply(ipAddress);
            return searchInRange(value, ranges);
        throw new IllegalStateException("Unacceptable ip address format:"
                + ipAddress);

    private static String searchInRange(BigInteger value,
            List<IpRange> ranges) {
        for (IpRange range : ranges) {
            if (range.inRange(value)) {
                return range.getCountry();
        return "";

    public String toCacheString(String country, String start,
            long value) {
        BigInteger startValue = ipStrToBigInteger.apply(start);
        BigInteger endValue = startValue.add(BigInteger.valueOf(value - 1));
        return country + "|" + startValue + "|" + endValue + "\n";

    boolean isAcceptableIPString(String ipAddress) {
        return this.ipStringAcceptor.test(ipAddress);

    void clear() {


Class for some trivial utility methods

package com.dukesoftware.utils.net.ipaddress;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.function.Consumer;

public class Utils {
    public static final int _1K_BYTES = 1024;

    public final static void saveToFile(String url, String path)
            throws IOException {
        HttpURLConnection urlCon = null;
        try {
            URL urlObj = new URL(url);
            urlCon = (HttpURLConnection) urlObj.openConnection();
            try (InputStream is = urlCon.getInputStream();
                    OutputStream os = new FileOutputStream(path)) {
                byte[] buffer = new byte[_1K_BYTES];
                for (int bytes = 0; (bytes = is.read(buffer)) != -1;) {
                    os.write(buffer, 0, bytes);
        } finally {
            if (urlCon != null) {
    public final static void processLine(File file, Consumer<String> lp) throws IOException{
        try(FileReader in = new FileReader(file);
            BufferedReader br = new BufferedReader(in)){
            String line;
            while ((line = br.readLine()) != null) {

Java: Coloned IPv6 Address To BigInteger

IPv6 Address to Long

I have written code for converting coloned IPv6 IP address to BigInteger value in Java.
I have already written similar code for IPv4 IP address (see this post). The function is useful when you compare IP addresses based on numeric magnitude relationship.

Java Code

public static BigInteger colonIpV6_to_BigInteger(String colonedIP) {
    String[] addrArray = colonedIP.split(":", -1);        
    BigInteger num = BigInteger.ZERO;
    BigInteger block = BigInteger.valueOf(65536);
    for (int i = 0; i < addrArray.length; i++) {            
            int power = 8-i;
            BigInteger value = BigInteger.valueOf(Long.parseLong(addrArray[i], 16) % 65536L);
            value = value.multiply(block.pow(power));
            num = num.add(value);
    return num;

Here is an example.

// following code output "22170076769632982771575277020213308075606016"

Java: Dotted IPv4 Address To BigInteger

IPv4 Address to Long

I have written code for converting dotted IPv4 IP address to BigInteger value in Java.
This code is inspired by PHP's ip2long function.
The function is useful when you compare IP addresses based on numeric magnitude relationship.

Java Code

public static BigInteger dotIPv4_to_BigInteger(String dottedIP) {
    String[] addrArray = dottedIP.split("\\.");        
    BigInteger num = BigInteger.ZERO;  
    BigInteger block = BigInteger.valueOf(256);
    for (int i = 0; i < addrArray.length; i++) {            
        int power = 3-i;
        BigInteger value = BigInteger.valueOf(Integer.parseInt(addrArray[i]) % 256);
        value = value.multiply(block.pow(power));
        num = num.add(value);
    return num;

Here is an example.

// following code output "2071690107"


Measure Code & Improve Team Based Software Development


In this post, I'm going to write about "Why & How to measure your code of software project. And improve it."
I am going to mainly write about this topic from the static code analysis point.

Why Measure?

There are number of reasons to measure your code.
For me especially following reasons (or intentions).

  • Daily Health Check
    • Keep code base clean
    • See impact on entire code base by your code change
    • Detect problems as soon as possible
    • Feel improvement!
  • Let every team members show what happens
    • Monitor test result status
    • Follow coding standard

Especially in team based software development, a lot of people change code for different task.
And each developer is hard to know what each developer change the code for what purpose.
If the source code measurement is public for everyone, it helps everyone to know affect of entire project which the other developers make.

What to Measure?

There are a lot of measurement is proposed but from static code analysis point, I think following covers enough for software project.
  • Lines of Code (LOC)
  • Copy and Paste
  • Code Complexity: Cyclomatic Complexity, Npath Complexity
  • Compliant of Coding Standard
  • Test Success Rate
  • Test Coverage
  • Elapsed time of Build/Test Running
  • Number of Slow Query
  • Technical Debt: Introduced by SonarQube. It calculates technical debt, whose unit is time, from code complexity or compliant rate of coding standard, etc. based on configured rules

Measurement Principles for Team Based Software Development

Before going into introduction to concrete software tools, I will show you my own principle for measuring code.

  • Automated
  • Continuously Measured
  • Public = Shared with everyone

Hope you agree with above points. Let me explain a bit about above points.
Automated - needless to say if you are a software developer having common-sense :)
Continuously Measured - Measure every small change is quite important because you can detect the change (doesn't matter bad or good) as early as possible.
In current software development world, project requires quicker and more frequent changes than before, and much more in the future.
This means measurement process should also follow with this trend.
Public = Shared with everyone - You can also use plugins on private IDE. But this is not recommended for software development based on team. Because ONLY you can run the tools and see the result.


PMD (Program Mess Detector)

This tool can calculate cyclomatic complexity or NPath complexity and aggregate by method or class or file. Then show alerts if the calculated value is higher than configured threshold.
It also show us unused variables and (private) methods.
This tool covers almost all major programming languages except PHP :P
If you would like to use it for PHP, use PHPMD.
I suggest use this with CPD (Copy & Paste Detector). Somehow CPD supports PHP.


This checks written code is compliant for configured coding standard rule.
If the code violated rule, it show us an alert.


This tool can detect the code which is bug or may introduce bug.


Most powerful tool for tracking the source code or project analysis result. It introduces "Continuous Inspection"
You can analyze almost everything - LOC, Compliance of coding standard, Complexity which is a kind of PMD provides, Code Duplication, percentage of comments, test coverage rates etc.
It provides "Time machine;" functionality - you can check time change of measurement on visualized graph.
It covers all major programming languages and provides a lot of plugins.
It also calculates "Technical Debt", whose unit is time, based on your configuration.
I highly recommend SonarQube!

Build Tools

Build tools are not directly involved with source code analysis but these are so important to achieve "Automated", "Continuously Measured" process.
The major tools I can think of in 2015 are below:

Testing Tools

If you would like to analyze testing result or measure test coverage, you should use test automation tools.
This post is not aimed for introducing testing tools so I just only give you some tools.

By the way, in java, we need not only JUnit but also need external library for calculating test coverage and mocking.
By contrast to Java, for example PHP, PHPUnit provides all mock, test coverage functionalities.

Continuous Integration Server

So far I introduced a bunch of tools which analyze source code itself.
Of course you can run these tools independently but this doesn't meet my principles - "Automated", "Continuously Measured", "Public"
In order to meet the principles, we should use continuous integration server
I think Jenkins is the most popular one but there are good commercial CI servers, too. Such as TeamCity or Bamboo.
If you have a money or budget, I think you should consider these commercial CI servers.

They provides a lot of project measurement (or code inspection) features by plugins.
For example for Jenkins, there is a plugin for visualizing PMD, CPD, Checkstyle, Test coverage result more human readable format like Violation Plugin.
You can also track time changes of number of test cases and elapse of test running.

How to Evaluate?

Now you can get and see bunch of source code measurement.
But the next step, evaluation of the measurement is as important as measuring itself.

Let me show you my evaluation standards.

  • Number of Test cases: Doesn’t matter
  • Test Coverage: Higher is better. But should NOT achieve 100%! It's waste of time!
  • Duration of Test Running: Faster is much better
  • Code Duplication Percentage: Lower is better – DRY principle
  • PMD (complexity, unused variables and methods etc.): Lower is better
  • Lines of Code: Less is better

Another important evaluation point is tracking time change.
You can compare measurement between any software projects. But for me this is not so important because the background of project is so different.
Rather than comparing between projects, I think comparing measurement result between same project is much important.

Pitfall of Measurement

The trap someone usually falls into is "Measurement and improve measurement itself becomes the purpose".

For example, trying to achieving 100% test coverage is very good attitude.
But this doesn't mean test quality is good.
And also Achieving 100% test coverage costs a lot of time (=money).
In the real software development world, we work for project success in the first place.
For each project, you should carefully choose what kind of tests should be done and what kind of tests should be skipped.
I think a good (business oriented) software developer knows this kind of cost-benefit performance and can balance test granularity properly.

Final Words

Before Blaming "What a crappy code!", you should measure, improve the code and show the improved evidence!
Measurement result should be public for every team mates.
Measurement is measurement, Not itself is the purpose.
Good Luck! Hope this post help your software development ;)