All Slides

CSC-430

Phillip Wright

About the Course

Overview

The high level goal of this course is to learn how to transition from coding for courses to coding in the real world.

The Plan

  • Object Oriented Programming (review)
  • Advanced Java
  • Tools of professional development
  • Design patterns
  • Clean coding practices
  • Software development processes
  • …and more?

What do I know about the real world?

A lot! Teaching is my hobby; writing code is what I actually do for a living. I am teaching you the things I wish I had known when I graduated.

What people say about CSC-430

“Candidates used to struggle to get through the technical portion of interviews…now the technical questions are largely useless, because students do so well now…”

What people say about CSC-430

“…we started probing the students to find out what had changed and the answer was CSC-430”

A local employer (paraphrased)

Grading

Component Weight
Assignments 68%
Exams 28%
Misc 4%

Textbooks

For this course, we will be using the following textbooks, in addition to free online resources:

  • Head First Design Patterns, 2nd Edition, Freeman & Robinson
  • Effective Java, 3rd Edition, Bloch

Resources II

You are expected to read everything that is assigned. If you don’t:

  • Do plan on failing.
  • Do not plan on sympathy.

Help

Don’t be afraid to ask questions!

I am available during my office hours and online throughout the day via email and the #csc430 slack channel.

Additional office hours can be planned in advance, so contact me!

Help II

Don’t be afraid to ask questions!

Help III

Don’t be afraid to ask questions!

Important Class Policies

  • Late submission penalty: 50%
  • Plagiarism will be punished as severely as possible

Staying Up To Date

Canvas will be used to handle the general organization of the course and all critical announcements.

Other reminders, notes, etc. may be distributed via twitter @msupwright4 and slack.

Final Note

My goal is to push you hard. Easy classes are not worth the money you are paying and a degree with no actual skills is worthless.

Be responsible. Ask questions. Do your work.

How You Code Now

Why Are We Here?

To understand why this class exists, we need to first analyze how you code now, and then we can talk about why this does not scale beyond the classroom.

Code Volume

Most of your coding experience probably consists of projects with less than 100 lines of code.

How do you manage this code?

Code Volume II

Code Contribution

Code Volume III

Code Contribution

Code Volume IV

Some line counts for a few projects I work on:

  • 20,185
  • 269,924
  • 271,335
  • 173,568

Code Volume V

At these sizes, just working with the code (distributing, sharing, etc.) becomes a non trivial task.

We need a way to backup our code, track changes, and avoid conflicts with coworkers–at scale.

Testing

How do you test your course projects?

Testing II

Manually testing large codebases is, literally, not possible without doing a poor job.

The number of paths in your code to test grows exponentially! If the time you spend testing does not, then you are not testing your code.

Testing III

Even writing tests for large codebases is not possible if the code is written poorly.

Accordingly, we need to automate testing and write our code in a way that makes it feasible to write sufficient tests.

Building

How do you build your code?

Do you even know how you build your code?

Building II

As projects grow in size and complexity, even compiling, building, and deploying your code becomes a problem.

We can not rely on manual steps!

Building III

Instead, we must automate the build process (including testing!) to ensure that we can deliver code in a reproducible, safe way.

Ideally, we automate deployment as well.

Maintenance

How hard is it to maintain your code after a year?

You don’t know, because you throw it away after a week!

Maintenance II

In the real world, your code will live for years (or decades) and will have to be maintainable by the unlucky individual that gets stuck with your legacy code.

Maintenance III

Often, you are that unlucky individual.

Also often, you will not even understand your code if you are not careful with how you write it.

Maintenance IV

Time Travel

Solution

We can largely conquer these problems (and more) by simply caring about our code and automating all the things.

Course Thesis

Humans suck at coding and we must humbly accept all of the help we can get from tools, processes, etc.

Intro To Maven

Maven

According to its own website…

Apache Maven is a software project management and comprehension tool […] can manage a project’s build, reporting and documentation from a central piece of information

Maven II

We will boil that down to the following, though:

Maven is a dependency management and build tool.

Dependency Management

What is dependency management?

Dependency Management II

Code you work on for your courses is often completely self contained, in one or two class files.

You will typically only be importing other classes from the standard library.

Dependency Management III

In a real world project, though, you will typically be relying on a significant amount of code written by others.

Dependency Management IV

This code will be packaged in jar files which you will need to have available when building and distributing your code.

Dependency Management V

In the bad old days, this meant:

  • You had to find the libraries
  • You had to download them
  • You had to keep track of them
  • You had to ensure their dependencies are included
  • You have to make sure to include them properly when compiling you code

Dependency Management VI

This may not sound to bad, but on large scale projects, this can be a huge source of problems!

Dependency Management VII

A dependency manager will allow you to provide a small amount of configuration, and it will then handle all of these problems for you in an automated manner.

Build Tools

When we talk about a build tool, we are generically referring to any tool that allows you to provide a configuration (or script), which can then handle all build steps that are necessary to produce your end product.

Build Tools II

For instance, you could use a build tool to trigger dependency management, compile your code, execute automated tests, package your compiled code, and more!

Automation

A keep theme here is automation.

If our build process is too complicated, we will forget steps and make mistakes.

This will lead to inconsistencies and errors.

Automation II

Complex manual processes also make it difficult to work with collaborators, because it takes significant work just to get the code running the same on all developer machines.

Automation III

Instead, we use a clear, precise configuration and feed it to a build tool to guarantee that we have reproducibility anywhere our code is built.

This also allows us to reduce our build process to a single command!

Maven III

There are usually multiple build tools that can be used for any given programming language, but Maven is one of the most commonly used in the Java world.

You may be interested in becoming familiar with Gradle as well, though.

Project Object Model

Maven relies on a configuration called a Project Object Model (POM) file.

Our main concern at this point is how to configure dependencies.

For simple projects, the building works out of the box!

Coordinates

To add a dependency, we simply need to provide the group id, artifact id and version of the library you want to use.

We call these the coordinates of the artifact.

Coordinates II

For example, we might add a dependency on a course library like:

<dependencies>
  <dependency>
    <groupId>edu.murraystate</groupId>
    <artifactId>BlobAPI</artifactId>
    <version>1.0</artifactId>
  </dependency>
</dependencies>

Transitivity

Note that, when you add a dependency, it may also need its own dependencies.

Fortunately, Maven artifacts are packaged with their own POM file, so Maven will go ahead and download all dependencies transitively.

Repositories

Maven is configured, by default, to pull artifacts from Maven Central, which is a public, centralized artifact repository.

You may, however, need to use custom, private repositories.

Repositories II

<repositories>
  <repository>
    <id>BlobAPI-mvn-repo</id>
    <url>https://raw.github.com/MSUCSIS/csc430-maven/mvn-repo/</url>
    <snapshots>
      <enabled>true</enabled>
      <updatePolicy>always</updatePolicy>
    </snapshots>
  </repository>
</repositories>

Review: Object Oriented Programming

Let’s Review

For this course, being comfortable with object oriented programming concepts and having a good understand of why they are beneficial is required.

Interfaces

Let’s start with interfaces!

First, what are interfaces?

Interfaces II

We could say that interfaces are “contracts” between the implementers of some code and the users of that code.

Interfaces III

In other words, in an interface, you are stating what methods you guarantee will be provided by any class implementing that interface.

Interfaces IV

Next, how do interfaces differ from classes?

Interfaces V

The old school explanation would be that interfaces can not contain implementations of methods. They may only contain method signatures.

(This isn’t actually true anymore, though)

Example

public interface Transform {
  String apply(final String input);
}

Interfaces VI

This interface represents the abstract concept of code which performs String transformations.

Note that this code does not do anything! It just states that any class implementing this interface will provide a method called apply that will perform a String transformation.

Classes

Now how about classes?

We mentioned above that classes contain actual implementation details. In other words, they contain code that actually does stuff.

Example II


public class Reverse {
  public String transform(final String input){
    final StringBuilder sb = new StringBuilder();
    for(int i=input.length-1; i>=0; i--){
      sb.append(input.charAt(i));
    }
    return sb.toString();
  }
}

Classes II

Is this a class?

Does it perform a String transformation?

Does it implement the Transform interface?

Example III

public class Reverse implements Transform {
  public String apply(final String input){
    // ...
  }
}

Now we have stated that we are agreeing to the “contract” defined by Transform

Example IV

final Reverse transformer = new Reverse();
System.out.println(transformer.apply("Hello");
final Transform transformer = new Reverse();
System.out.println(transformer.apply("Hello"));

What’s the difference here? Why would we do this?

Polymorphism

At this point, there is no real reason to use interfaces at all. What happens, though, when we decide to add another type of transformation to our code.

Example V

if(doReverse){
  final Reverse reverse = new Reverse();
  return reverse.apply("Hello");
}else if(doNoVowels){
  final NoVowels noVowels = new NoVowels();
  return noVowels.apply("Hello");
}else if ...

Polymorphism II

While all of these classes do different things, they all, at a high level, are transforming Strings.

So, if we use the Transform interface for all of them, then we can unify them with one variable.

Example VI

final Transform transform;
if(doReverse){
  transform = new Reverse();
}else if(doNoVowels){
  transform = new NoVowels();
}else if ...

return transform.apply("Hello");

Polymorphism III

This may not seem to impressive, but what if the logic choosing the transformation is not in our code?

What if we have to pass a transform into someone elses code?

What if we need a collection of transformations?

Example VII

final SomeoneElses code = new SomeoneElsesCode();
// We have no idea what this could possibly return!
final Transform transform = code.getTransform(); 
// ...but we can use it anyway, because we know its interface!
return transform.apply("Hello");

Example VIII

In someone else’s code:

public void setTransform(final Transform t){
  transform = t;
}

In our code:

//They have no idea what this is
final Transformer tx = new Reverse();
//...but they can still use it!
code.setTransform(tx);

Example IX

final List<Transform> txs = new ArrayList<>();
txs.add(new Reverse());
txs.add(new NoVowels());
//...

Side Quest

What are all of the angle brackets?

final List<Transform> txs = new ArrayList<>();

Side Quest II

I guess we’re going to need to talk about generics.

We mentioned how an interface can be used to represent different classes by referring to them as instances of the interface instead.

Side Quest III

We can also do this with an ancestor classes, if all of the classes have a common ancestor. So, in the bad old days, a List would simply store Objects, because Object is a common ancestor for all other classes.

Raw Types

This led to problems:

final List txs = new ArrayList();
txs.add(new Reverse());
// Not an error, because it's an object
txs.add("Hello"); 
// Have to cast, because we need a Transform, not an Object
final Transform tx = (Transform)txs.get(1);

Generics

To fix this, generics were introduced to allow for more type safe code to be written:

final List<Transform> txs = new ArrayList<>();
txs.add(new Reverse());
//Now this is an error
txs.add("Hello");
//And a cast wouldn't be needed if the above didn't crash!
final Transform tx = txs.get(0);

Example X

Let’s improve our Transform interface now:

public interface Transform<T,U> {
  U apply(final T input);
}

Now we’re not limited to String transformations!

Example XI

public class Reverse implements Transform<String,String> {
  public String apply(final String input){
    //...
  }
}

Example XII

final List<Transform<String,String>> stringTransformers;
final List<Transform<Integer,Integer>> intTransformers;
final List<Transform<String,Integer>> stringToIntTransformers;

Can you feel the power??? Programming is so awesome.

Inheritance

Ok, let’s dial things back a bit and get back to some basics.

What is inheritance? How does it work?

Inheritance II

Previously, we implemented an interface.

Sometimes, though, we want to extend a class.

Inheritance III

When a class B extends a class A, then the class B will inherit the methods and fields of class A.

Example XIII

public class ReReverse extends Reverse {

}

Example XIV

What will the following do? Will it compile?

final Reverse r1 = new ReReverse();
System.out.println(r1.apply("hello");

Example XIV

public class ReReverse extends Reverse {
  public String apply(final String input){
    final String reversed = super.apply(input);
    final String reReversed = super.apply(reveresed);
    return reversed;
  }
}

Super?

Example XV

What will the following do?

final Reverse r1 = new ReReverse();
System.out.println(r1.apply("hello");
final ReReverse r2 = new Reverse();
System.out.println(r2.apply("hello");
final Transform t = new ReReverse();
System.out.println("hello");

Polymorphism IV

When we declare a variable’s type, that tells us what fields and methods must exist, but it might not be the precise type of the value bound to that variable.

(The actual value may have more fields and methods!)

Polymorphism V

When we call a method declared in the parent class, the JVM will determine, at run time, what the actual type of the value is, and will use this information to select the correct implementation of the called method.

What is the correct implementation?

Polymorphism VI

If the child class has not overridden the method, then the parent class will be checked for an implementation.

If the child class has overriden the method, then the implementation in the child class is chosen.

Remember, though, that you can have several levels of inheritance!

Access Modifiers

Don’t forget that access modifiers affect what fields and methods are visible to children!

If, for example, a parent class declares a private field, the child can not access it!

Access Modifiers II

  none private protected public
class Y Y Y Y
package Y N Y Y
subclass N N Y Y
world N N N Y

Spooky!

A common mistake students (and professionals!) make is to assume that the access modifiers apply to instances of a class. This is not true!

For instance, a private field in class A is visible ot every instance of A!

Example XVI

For example, this code is perfectly valid!

public class A {
  private final int x;

  //...

  public void compareXs(final A anotherA){
    // works even though x is private!
    return x==anotherA.x;
  }
}

Abstract Classes

Let’s circle back around to some of the basics:

An interface (sort of) only provides method signatures.

A class must be completely implemented.

An abstract class is when you want something in between.

Example XVII

public abstract class Censor 
                      implements Transform<String,String> {
  public abstract List<String> getBadWords();

  public String apply(String input){
    for(final String word : badWords){
      input = input.replace(word, "!!!")
    }
    return input;
  }
}

Now we can create different variations by subclassing and implementing getBadWords.

Inheritance IV

What if we want to inherit from two classes?

Inheritance V

You can’t!

You can implement several interfaces, but you can only extend one class (concrete or abstract).

However…

Default Methods

You can now, actually, provide “default” implementations of methods in interfaces.

Which means that you can often accomplish what you were trying to do with two parent classes by instead implementing two interfaces with default methods.

Default Methods II

There are, however, limitations. First, remember that you can only store static, constant fields in an interface. If you need instance data for your default methods, you are out of luck.

Default Methods III

You can, though, add a getter to the interface for the instance data, and use that in your default method.

Then implementers will declare their own instance fields and implements the getter.

Example XVII

public interface Censor extends Transform<String,String> {
  List<String> getBadWords();
  
  default String apply(String input){
    for(final String bad : getBadWords()){
      input = input.replace(bad, "!!!");
    }
    return input;
  }
}

Implement or Extend

Another common mistake is to try and implement an interface in another interface. This makes no sense, because you aren’t (generally) providing an implementation!

So, interfaces extend other interfaces!

Multiple Interfaces

An interesting use for multiple interfaces is to create an interface for each kind of behavior that might be needed, and mixing them together.

Example XVIII

public interface Labeled {
  public String getLabel();
}

public interface Logged {
  public List<String> getLog();
}

Example XVIV

public class Reverse 
       implements Transform<String,String>, Labeled, Logged {
  private final List<String> log = new ArrayList<>();

  public String getLabel(){return "Reverse (Transform)";}
  public List<String> getLog(){return log;}

  public String apply(final input){
    log.add("Starting transform of input: " + input);
    //...
    log.add("Transform complete:" + result);
    return result;
  }
}

Multiple Interfaces II

So, in addition to being able to use this class wherever we need a Transform, we can use it anywhere we expect, for example, instances with a label.

Multiple Interfaces III

For example, imagine a UI where we can select operations to perform. Some might be transformers, other might not be, but we can put them all in a common UI widget with a nicely displayed label if they all implement the Labeled interface!

instanceof

At runtime, though, we may not know what interfaces are implemented, so we will need to check using the instanceof operator.

Example XIX

public void doTransform(final Transform<String,String> t){
  final String input = getInput();
  final String output = t.apply(input);
  if(t instanceof Logged){
    final Logged logged = (Logged) t;
    printLog(logged.getLog());
  }
  writeOutput(output);
}