Read, test, don't repeat - how to avoid code complexity

Emergent Design: Lessons from Y2K


Book extract, part four Redundancy, testability and readability are key to building simple and maintainable code. In the fourth extract from his book, Emergent Design: The Evolutionary Nature of Professional Software Development, published by Addison Wesley, Scott Bain tackles the problems and principles involved.

We all saw an example of redundancy rearing its nasty head just a few years ago.

The Y2K remediation effort cost countless billions of dollars, scared the heck out of entire countries, and in general disrupted progress in the technology sector. Many companies basically stopped doing any kind of new projects in the latter part of 1999, because they were putting their resources into fixing the Y2K bug.

What made Y2K hard to fix? Was it a complex problem? No! Not at all. Systems all over the world had stored the year portion of the date in innumerable records as a two-digit number, rather than a four-digit number. Not a complex problem at all.

Except that it appeared in billions of places, all of which had to be found and changed.

We can criticize the programmers who wrote the original code this way, but the fact is I find redundancies in my own code and the code of colleagues all the time. It is easy to do; it tends to creep in on you, especially when you are creating an extension to a new system. Also, some aspects of the languages we use can promote redundancy. Consider the following code:

public interface Weapon{
  public void load(int rounds);
  public int fire();
  public void setSafety(boolean on);  
}

public class Pistol implements Weapon{
  private int myBullets;
  private boolean safety = true;

  public void load(int bullets){
    if(bullets<=6){
       myBullets = bullets;
    } else {
      System.out.println("Pistol only holds 6 bullets");
    }
  }

  public int fire(){
    int rval = 0;
    if(safety){
       System.out.println("The Safety is on");
    } else {
       if(myBullets > 0) {
          System.out.println("Bang!");
          myBullets = myBullets - 1;
          rval = 10;
       } else System.out.println("Click!");
    }
    return rval;
  }

  public void setSafety(boolean aSetting){
    safety = aSetting;
  }
}

public class TommyGun implements Weapon{
  private int myBullets;
  private boolean safety = true;

  public void load(int bullets){
    if(bullets<=50){
       myBullets = bullets;
    } else {
      System.out.println("TommyGun only holds 50 bullets");
    }
  }

  public int fire(){
    int rval = 0;
    if(safety){
       System.out.println("The Safety is on");
    } else {
       if(myBullets > 9) {
          System.out.println("Budda Budda Budda!");
          myBullets = myBullets - 10;
          rval = 100;
       } else System.out.println("Click!");
    }
    return rval;
  }

  public void setSafety(boolean aSetting){
    safety = aSetting;
  }
}

There are lots of redundancies here - the way setSafety() is completely identical in both Pistol and TommyGun, for example. If I want to change the way this works - make the state persistent by writing it to the disk every time, for instance - then I must remember to change it in both places.

The Java and .Net interface type leads me to this inherently; it tends to create redundancies among the implementing classes. This is because the interface cannot have any actual implementation, so I cannot put common implementation into it, and allow the implementing classes to inherit.

What if I used an abstract class instead? Look at the following code:

public abstract class Weapon{
  protected int myBullets;
  protected boolean safety = true;  

  public abstract void load(int rounds);
  public abstract int fire();

  public void setSafety(boolean aSetting){
    safety = aSetting;
  }

}

public class Pistol extends Weapon{

  public void load(int bullets){
    if(bullets<=6){
       myBullets = bullets;
    } else {
      System.out.println("Pistol only holds 6 bullets");
    }
  }

  public int fire(){
    int rval = 0;
    if(safety){
       System.out.println("The Safety is on");
    } else {
       if(myBullets > 0) {
          System.out.println("Bang!");
          myBullets = myBullets - 1;
          rval = 10;
       } else System.out.println("Click!");
    }
    return rval;
  }
}

public class TommyGun extends Weapon{
  
  public void load(int bullets){
    if(bullets<=50){
       myBullets = bullets;
    } else {
      System.out.println("TommyGun only holds 50 bullets");
    }
  }

  public int fire(){
    int rval = 0;
    if(safety){
       System.out.println("The Safety is on");
    } else {
       if(myBullets > 9) {
          System.out.println("Budda Budda Budda!");
          myBullets = myBullets - 10;
          rval = 100;
       } else System.out.println("Click!");
    }
    return rval;
  }
}

I have eliminated some of the redundancy already: The setSaftey() method is now in one place, inherited by both Pistol and TommyGun. Also, the data members myBullets and safety were common, so I put them in the superclass too and made them protected so the subclasses could still access them directly.

There's more I could do, of course. The weapons both operate in a conceptually similar way, only the details vary. If I am lucky enough to know the Template Method pattern, I could pretty easily get rid of all the other bits of redundancy here, without sacrificing any of the uniqueness of these two weapons.

Redundancy and coupling

But haven't I introduced coupling in order to deal with the redundancy problem? The abstract superclass puts one rule in one place, but it also means that a change in the superclass (Weapon) will have an effect on the subclasses (Pistol and TommyGun). This is inheritance coupling, certainly, so have I traded one problem for another?


Other stories you might like

  • IBM settles age discrimination case that sought top execs' emails
    Just days after being ordered to provide messages, Big Blue opts out of public trial

    Less than a week after IBM was ordered in an age discrimination lawsuit to produce internal emails in which its former CEO and former SVP of human resources discuss reducing the number of older workers, the IT giant chose to settle the case for an undisclosed sum rather than proceed to trial next month.

    The order, issued on June 9, in Schenfeld v. IBM, describes Exhibit 10, which "contains emails that discuss the effort taken by IBM to increase the number of 'millennial' employees."

    Plaintiff Eugene Schenfeld, who worked as an IBM research scientist when current CEO Arvind Krishna ran IBM's research group, sued IBM for age discrimination in November, 2018. His claim is one of many that followed a March 2018 report by ProPublica and Mother Jones about a concerted effort to de-age IBM and a 2020 finding by the US Equal Employment Opportunity Commission (EEOC) that IBM executives had directed managers to get rid of older workers to make room for younger ones.

    Continue reading
  • FTC urged to probe Apple, Google for enabling ‘intense system of surveillance’
    Ad tracking poses a privacy and security risk in post-Roe America, lawmakers warn

    Democrat lawmakers want the FTC to investigate Apple and Google's online ad trackers, which they say amount to unfair and deceptive business practices and pose a privacy and security risk to people using the tech giants' mobile devices.

    US Senators Ron Wyden (D-OR), Elizabeth Warren (D-MA), and Cory Booker (D-NJ) and House Representative Sara Jacobs (D-CA) requested on Friday that the watchdog launch a probe into Apple and Google, hours before the US Supreme Court overturned Roe v. Wade, clearing the way for individual states to ban access to abortions. 

    In the days leading up to the court's action, some of these same lawmakers had also introduced data privacy bills, including a proposal that would make it illegal for data brokers to sell sensitive location and health information of individuals' medical treatment.

    Continue reading
  • Behold this drone-dropping rifle with two-mile range
    Confuses rather than destroys unmanned aerials to better bring back intel, says Ukrainian designer

    What's said to be a Ukrainian-made long-range anti-drone rifle is one of the latest weapons to emerge from Russia's ongoing invasion of its neighbor.

    The Antidron KVS G-6 is manufactured by Kvertus Technology, in the western Ukraine region of Ivano-Frankivsk, whose capital of the same name has twice been subjected to Russian bombings during the war. Like other drone-dropping equipment, we're told it uses radio signals to interrupt control, remotely disabling them, and it reportedly has an impressive 3.5 km (2.17 miles) range.

    "We are not damaging the drone. With communication lost, it just loses coordination and doesn't know where to go. The drone lands where it is jammed, or can be carried away by the wind because it's uncontrollable,"  Kvertus' director of technology Yaroslav Filimonov said. Because the downed drones are unharmed, they give Ukrainian soldiers recovering them a wealth of potential intelligence, he added.  

    Continue reading
  • Alcatel-Lucent Enterprise adds Wi-Fi 6E to 'premium' access points
    Company claims standard will improve performance in dense environments

    Alcatel-Lucent Enterprise is the latest networking outfit to add Wi-Fi 6E capability to its hardware, opening up access to the less congested 6GHz spectrum for business users.

    The France-based company just revealed the OmniAccess Stellar 14xx series of wireless access points, which are set for availability from this September. Alcatel-Lucent Enterprise said its first Wi-Fi 6E device will be a high-end "premium" Access Point and will be followed by a mid-range product by the end of the year.

    Wi-Fi 6E is compatible with the Wi-Fi 6 standard, but adds the ability to use channels in the 6GHz portion of the spectrum, a feature that will be built into the upcoming Wi-Fi 7 standard from the start. This enables users to reduce network contention, or so the argument goes, as the 6GHz portion of the spectrum is less congested with other traffic than the existing 2.4GHz and 5GHz frequencies used for Wi-Fi access.

    Continue reading
  • Will Lenovo ever think beyond hardware?
    Then again, why develop your own software à la HPE GreenLake when you can use someone else's?

    Analysis Lenovo fancies its TruScale anything-as-a-service (XaaS) platform as a more flexible competitor to HPE GreenLake or Dell Apex. Unlike its rivals, Lenovo doesn't believe it needs to mimic all aspects of the cloud to be successful.

    While subscription services are nothing new for Lenovo, the company only recently consolidated its offerings into a unified XaaS service called TruScale.

    On the surface TruScale ticks most of the XaaS boxes — cloud-like consumption model, subscription pricing — and it works just like you'd expect. Sign up for a certain amount of compute capacity and a short time later a rack full of pre-plumbed compute, storage, and network boxes are delivered to your place of choosing, whether that's a private datacenter, colo, or edge location.

    Continue reading
  • Intel is running rings around AMD and Arm at the edge
    What will it take to loosen the x86 giant's edge stranglehold?

    Analysis Supermicro launched a wave of edge appliances using Intel's newly refreshed Xeon-D processors last week. The launch itself was nothing to write home about, but a thought occurred: with all the hype surrounding the outer reaches of computing that we call the edge, you'd think there would be more competition from chipmakers in this arena.

    So where are all the AMD and Arm-based edge appliances?

    A glance through the catalogs of the major OEMs – Dell, HPE, Lenovo, Inspur, Supermicro – returned plenty of results for AMD servers, but few, if any, validated for edge deployments. In fact, Supermicro was the only one of the five vendors that even offered an AMD-based edge appliance – which used an ageing Epyc processor. Hardly a great showing from AMD. Meanwhile, just one appliance from Inspur used an Arm-based chip from Nvidia.

    Continue reading
  • NASA's Psyche mission: 2022 launch is off after software arrives late
    Launch window slides into 2023 or 2024 for asteroid-probing project

    Sadly for NASA's mission to take samples from the asteroid Psyche, software problems mean the spacecraft is going to miss its 2022 launch window.

    The US space agency made the announcement on Friday: "Due to the late delivery of the spacecraft's flight software and testing equipment, NASA does not have sufficient time to complete the testing needed ahead of its remaining launch period this year, which ends on October 11."

    While it appears the software and testbeds are now working, there just isn't enough time to get everything done before a SpaceX Falcon Heavy sends the spacecraft to study a metallic-rich asteroid of the same name.

    Continue reading
  • Rise in Taiwanese energy prices may hit global chip production
    National provider considering cost increase of 8%, which could be passed on to tech customers

    Taiwan's state-owned energy company is looking to raise prices for industrial users, a move likely to impact chipmakers such as TSMC, which may well have a knock-on effect on the semiconductor supply chain.

    According to Bloomberg, the Taiwan Power Company, which produces electricity for the island nation, has proposed increasing electricity costs by at least 8 percent for industrial users, the first increase in four years.

    The power company has itself been hit by the rising costs of fuel, including the imported coal and natural gas it uses to generate electricity. At the same time, the country is experiencing record demand for power because of increasing industrial requirements and because of high temperatures driving the use of air conditioning, as reported by the local Taipei Times.

    Continue reading

Biting the hand that feeds IT © 1998–2022