Crafting Clearer Code: Write abundant, quality comments!

Squirrel wants to see your comments.

From the very start of your software-engineering you should compose cogent comments right along with your code. The only exception is where your code is so small that it is trivial and obvious (to anyone besides yourself) or else you are the only audience.

This is one of those areas in which, largely, older engineers make better code-crafters: they know that the universe of possible code-contructs, patterns, APIs, add-ons and libraries is truly vast. To assume it’ll all be obvious past this moment is to guarantee future frustration and time-wastage.

For your long-view guidance – to tell your teammates what your code does and it’s basic organization – provide a “Doc” folder and give it simple text, markdown or HTML documents. This should form your basic roadmap, and here you direct your reader where to go within the code. Everything that is missing from the code-level comments, should be here. If you’re going to structure this formally – then I’d suggest you also provide a separate, informal ‘quick roadmap’ or synopsis. Come back to this regularly: do not let it become too out-of-sync with your code such that it decays into uselessness.

Here I’ll direct my tips toward the crafting of code using C#..

Use the standard for code-contructs that Microsoft’s Visual Studio provides, which is:

/// <summary>
/// This integer tracks the number of insertions since the start of this current run.
/// It can range from zero, up.
/// </summary>
private int _insertionCount;

 

Within Visual Studio, all you need do is type the first three slashes and it produces the remaining slashes for you.

The advantage of this is that when you encounter this variable from anywhere else within your codebase, you need but hover your mouse over it and this comment will magically appear. It’s like having a crib-note always attached to it, but which hides itself until you need it. This is important – otherwise your readers must navigate to the code-element itself to see your comment.

Be useful. Here is a counter-example, taken from the iText product API documentation page:

// EOFills current path.
eoFill();
 

Yeah – that’s actually the kind of API-documentation that iText provides. Does that look useful to you?

Imagine you are *trying* very hard to use this API correctly and get your code to generate that Acrobat report correctly. The company depends on you and you’re at the 11th hour (true story). You’ve no clue nor hint what the heck EOFills means.  Does that make you want to slap a body?

Do NOT use domain-specific jargon in your comments. I’ve been using the iText 7 API to create Acrobat documents and I still have no idea what the hell that method is for. If you add a comment that simply repeats the text that is already within the method-name, you mark yourself as a total idiot who should never be permitted anywhere near a keyboard. Here is an example, in C#, from the  LogNut logging library  ..

/// <summary>
/// Set the name of the log file to write file logging output to.
/// If you don't set this then a default value will be computed. See <see cref="FileOutputFilename"/>.
/// This is the same as setting the <see cref="FileOutputFilename"/> property.
/// </summary>
/// <param name="filename">the name of the file to log to - without the drive or directory information</param>
/// <remarks>
/// If you set this to null, then upon re-reading this property the default value will again be returned.
/// This duplicates the function of the <see cref="FileOutputFilename"/> property setter, for the purpose of providing a fluent API.
/// </remarks>
/// <returns>a reference to this <c>LogConfig</c> object, such that further method calls may be chained</returns>
public LogConfig SetFileOutputFilenamestring filename )
{
    FileOutputFilename = filename;
    return this;
}
#endregion
 

Yeah – this is rather verbose. That’s okay – it takes two minutes to type, as opposed to untold minutes wasted by N developers trying to guess what the heck you mean when you *don’t* bother to explain. Note that it is made explicit what argument you should supply for filename – not a path, not a drive – just a filename. It’s also made quite explicit what this is for: the log output file. LogNut has many kinds of outputs – this is for *file* output. The sentences are complete, clear, unambiguous.

Make your writing readable. That sounds too obvious – but it’s a badly-needed admonishment. Your comments should read like good exposition: avoid too-esoteric terms when a generally-known word will serve, make your sentences read easily, without being wordy. Write to guide and inform, not to fill space and not to slow your reader down.

Use proper spelling and grammar. I try to encourage being rather strict in this for one reason: the human visual-system is such that we more readily recognize and digest writing when it it correctly formed (from the perspective of our own personal background). When your mind has to stop and guess at what “snd to pip recever” is intended to convey — that interrupts your flow of thought. The result is that it is harder, and slower, to read. For individual method-parameters, you can use a non-sentence phrase: “the number of items in the collection” but for anything longer you should assemble your writing into complete sentences. Start a fragment with a lowercase letter, and start a complete sentence with an uppercase letter. Invest a little time to make it explicit.

Regarding spelling: use a spell-checking tool in your code-editor. Why is correct spelling so important? For doing text-searches, for one. But also for your teammates for whom your language is not *their* native language. It’s hard enough to keep googling for translations, but can you imagine the difficulty when your own English is not even spelled correctly? Regardless of how careful you are – mispellings will creep in. A good spell-checker will highlight those for you. But bear in mind that British spelling diverges from American English in a few cases.

Decide upon your naming-scheme and structure, and make that a consistent pattern for you and your team. This is as important within your comments as it is within your code. For the things in your code that represent something in real life and can be named any of a number of different ways – consider how you want to name them, and stick to your scheme. These patterns help everyone’s mind to instantly follow it’s structure. For example, if you’re designing a desktop application that has views and view-models, why not name all views with a “View”suffice, and all view-models with a “ViewModel” suffice? Now make every comment, everywhere, use this same nomenclature. Placing the parent-class name after the class-name can be a helpful pattern: “PictureAcquiredEventArgs” is obviously a subclass of EventArgs. And on the topic of events..

A C# event is a signal that something happened. Name it with a verb-phrase in the past tense. The name should say that a thing happened, and the Intellisense-comment should give it further detail. If your event is named “ImageUploaded”, why not name the event arguments ImageUploadedEventArgs, and the event-handler method OnImageUploaded.. this pattern makes their relationship intuitively obvious. But don’t stop there: still add your comments. What does this class contain? What does this event-handler *do* in response to the event?

Now – this is the most illusive feature to maintain and yet is the most crucial: Make your comments such that, taken as a whole, they describe the operation of your system completely. *Completely*. You should be able to bring in a brand-new employee set them loose upon it – and see them begin to feel at ease going through your code and quickly start doing useful work. The larger constructs (assemblies, libraries, classes) should convey the overall purpose and organization of your code, while the individual code-constructs provide the detail *when* your reader feels the need to zoom-in for that level of detail.

Write a comment for every non-local construct in your code. All of them. And take some care to write your comments correctly and make them useful. And then re-visit your comments over the next days to rewrite them to maintain clarity and consistency.

 

James W. Hurst

return to On Building Systems

Where are the good laptops?

Check out this keyboard and tell me what you think: if you’re shopping for a new laptop computer – what about it jumps out at you?

Figure 1. A keyboard.

It has your standard speed-typing layout! That’s right – you can go straight from your desktop computer to this laptop and back, and not miss a beat.

It seems that it is getting hard to find a competent new laptop to purchase. My previous favorite, Lenovo, has apparently parted ways with their perfect keyboards and switched to a newer chicklet design. To make matters worse, they’ve abandoned the standard two-row-by-three-column layout of the editing keys (Home, Delete, End, Insert, Page-Up, Page-Down), and the cursor-movement keys are no longer set off in their separate, easily-typed format. See the illustration in Figure 2.

 

 

Figure 2, showing the crucial editing and movement keys circled in blue.
Figure 2, showing the crucial editing and movement keys circled in blue.

It was already bad enough that the previous 1920-by-1200 pixel resolution displays disappeared. My Thinkpad W500 had that. It is starting to die intermittently, but I am loathe to give up that display for the loathsome 1920-by-1080 that all of the displays top out at now. Scanning the websites for the other laptop makers reveals that even with the few models sporting larger displays, there is nothing with a 1920-by-1200 pixel screen. Very annoying.

The saving grace is that newer, higher-resolution screens are starting to appear — Lenovo has announced their new W540 with a screen resolution of 2,880 by 1,620 pixels! This would be awesome. But I am not seeing it in any one model that has all of the basic requirements just yet.

Here, then, is a list of what I would want to see in a new laptop:

1. Decent display resolution!!!  At an absolute minimum — 1920-by-1200. We want that extra vertical band of pixels! Better: a 2650 x 1600 resolution display that is at a minimum 15.6 inches. Better yet would be to have a 17 or 18-inch option at this resolution. Why would a manufacturer expect users to shell out $2.2K+ for a new laptop, for anything less?

 

2. A keyboard whose design respects the ‘standard’ traditional Thinkpad layout and feel, meaning that the keys have a physical feel that makes it very easy to type, and a layout that matches the traditional PC desktop keyboard (cursor and editing keys are in the right places). This “standard” layout, is what my existing computers have. I have bought some excellent aftermarket keyboards with this exact layout.

Figure 3. Closeup of the editing keys.
Figure 3. Closeup of the editing keys.

There is finely thought-out ergonomics at work here. Notice the beveled edge of the keyboard well: when you slide your hand up there in a dark room or as your eyes are focused elsewhere — that edge serves to orient your hand. Your fingers instantly find their way to the Page-Up/Down keys. Through habit, then, your index finger always falls upon the Insert and Delete keys. You don’t have to re-focus your eyes to look at the keyboard to find those – it just happens subconsciously. And see that space between the column that contains the Insert & Delete keys, and the column to the left of them (the Pause and F12)? That little space your fingers will find by habit, to further home in upon their location. The excellent Lenovo Thinkpad W500, has this.  If a manufacturer foolishly messes with this, and changes the laptop’s keyboard — suddenly you’re stuck with having to replace everything and retrain yourself! The key-travel must be as on the W500 or W510, which is most definitely not a ‘chicklet’ keyboard. Professional users do type.

 

3. Multi-touch display. Not essential all of the time — the mouse does fine. But when this laptop is sitting on the family table and you want to just touch it to have something happen – that’s nice to have. Very nice to have. If we’re going to pay North of $2K for a new cptr today, it seems dumb not to have the option of Touch. Think about this: your customer is contemplating pulling the trigger on a new laptop/workstation; he’s mulling it over for a day since it’s a chunk of change ($2500); he walks into a retail shop for pencils and strolls by the counter of laptops. One is showing Windows 8.1’s start screen. He reaches over and softly touches the Music tile, and it instantly leaps to attention, ready to sound out. Sweet. Do you think he’s not going to think about that, when he next goes to sit down and revisit your web-shop page to order?

 

4. Trackpoint. Okay – I realize most people aren’t used to these and prefer the touchpad. But I and a lot of other Thinkpad users like to have the Trackpoint nib, especially for those moments when the mouse is not at hand.

 

5. Battery life that exceeds 24 hours. Look, if an iPhone burning 64 bits and quad-cores can last a full workday, why would you expect a user of your W510 to feel happy about the lousy 2 hours it provides?! Do your engineering. Provide the option of a massive spare battery if you must, that connects to the underside. But give us life!

 

6. The fastest CPU and subsystems — to yield a system as fast and snappy as a desktop. For various reasons — today most laptops feel like you’re in a slow-motion movie even when simply doing the simplest of tasks. This should not be necessary. Be mindful that professional users couldn’t care less about games. So hyped-up graphics subsystems to drive those games aren’t what’s needed. What we want, is the thing to respond to us. Always. Instantly.

 

That is not a long list. There is nothing revolutionary within it – these are the technologies that are available and have already been in production. And this doesn’t include all of the minor, common technologies that have already become common such as multiple USB 3.0 ports and a camera-memory-card reader.

return to Hardware Design

A Thought on your TDD (Test-Driven Development) Strategy

Cows
TDD can feel wet and scratchy, but it will feel nice if you treat it with understanding.

Test-Driven-Development (TDD) can be a good contribution to your project strategy. It is a means by which one can know that a given kit of software (your end-product) does perform according to a specific specification (and your suite of unit-tests should comprise a part of that specification), and can help to focus a developer’s mental energies toward meeting that specific goal. However, it can also bog your team down in detail and make-work if it is not used wisely.

To illustrate this last point – a project I was on recently used TDD throughout, religiously. We had several disparate groups who met daily for our “scrum” update, and from these meetings it seemed that for any code-change, no matter how small – one could expect that many days would be needed to get all of the unit-tests to pass.

The problem was that we did not have a real direction to our TDD. Each was told to “write tests” for anything we added or changed. Thus, a developer would wind up looking at his code for any detail that could be “verified”: assert that this flag was true, how many results returned, what strings could be present, etc. Upon adding T-SQL code to add a database view, for example, unit-tests were added to verify the number of lines of T-SQL code, and that it contained a given keyword, etc. Upon adding another bit of SQL, all of those previous unit-tests now fail (even though still valid): every detail has to be accounted for and updated.

A huge amount of time was being wasted.

It’s crucial to ask oneself: “What are these tests supposed to achieve?”

Your work as a developer is to implement functionality within your product. Do you really care about every detail of how that was implemented? Do you really need to test for every artifact of the implementation? What if the developer finds a superior way to implement, and achieves the same functionality? Do you really want him to have to re-write a huge battery of unit-tests?

And, if your developer is going through the tests, method-by-method, editing them to get them to pass, are they really serving their true purpose — which is to double-check that the functionality is actually working?

I submit this: a golden aspect of TDD is that you can edit your code and know that your unit-tests will confirm (at the press of a button) that there are no regressions. That is – if properly designed. By allowing you to NOT be sidetracked continually by the need to re-edit your tests, you can keep focused on your real code.

If the one over-riding goal of your software development work, is to produce a product that works (and I hope that it is) – then you really cannot afford to get bogged down by extraneous detail. You must move forward, solidly, or perish. No matter how large your team. Even IBM and Microsoft got ground down by excessive code complexity and detail-work. Progress grinds to a standstill. To keep others from coming to eat your lunch – your software has to evolve, to improve, to become always more solid — and to do this you have to make real, steady forward progress and not just write a bazillion unit-tests for the sake of saying you “use TDD”.

Suggestion: Forge your goals related to TDD, and discuss this with your team leaders. Know how much time is being consumed by writing and running tests (which means – individually tracking this time). And talk about and understand (together) how best to use TDD to meet your goals. Use it where it makes sense, let it go where it does not!

Your specification (your System Requirements Document) specifies what your software is going to do. Make your unit-tests mirror a part of your specification. Link right to it from your requirements document, and specify at the top of each unit-test source-code file what that section is going to test and how.

The purpose of software, is to accomplish a specified functionality. Thus your tests should serve the purpose of verifying, to the maximum extent possible, that that functionality is indeed accomplished. But it should do this in the simplest and most concise way, and avoid duplication. Only test for the correct end-result, not the steps to get there (with important exceptions – for a later article). Factor out as much as possible of the infrastructure-code (e.g. setup code) and share it amongst the team. If your API changes, then yes – you can expect a lot of rewriting of tests. But if it is a simple change of code to optimize the implementation, and it necessitates a massive number of test changes — this is a red-flag that you may be getting bogged down in unnecessary detail!

On a different project we were writing low-level code that had to work on myriad platforms — versions of Windows or Unix, 32-versus-64 bit, environments with various components already installed – or not, etc. For this we used virtual machines (VMs) — VMware in this case. One VM would represent a specific platform: for example – one for Windows XP 32-bit, a bare install, another for Windows 8 beta 64-bit that already had .NET 4.5 installed, etc. One lovely thing about these VMs is that you can deploy them and do a lot of stuff using Windows Powershell, which in turn is easily callable from your own code. Ideally you set this functionality up such that it can be invoked via a right-click on a project within Visual Studio. Thus, instead of spending days setting up for, and running, and checking the results of each out of this plethora of tests, we could just define the whole suite up front, right-click on our C# project when done coding, and select “Test this!” — and it would send the compiled code out to the proper test-VM (or set of VMs) on the dedicated test boxes, and deliver back the results (“Go”, or “No-go”). To keep things singing along, I dedicated a box just to running these VMs, one which had a PCIe SSD and oodles of RAM. I could open Remote Desktop on it (RDC) and see at a glance what was running, and what the results were. No manual file-copying, no setting configuration values.

Along with that, I strongly suggest that you look into continuous integration and to integrate that into your build process.

Note: do not use your version-control as a backup system for your source-code. Builds (and tests) happen off of that! Unless you can thoughtfully parcel your code into appropriate branches and merge it back into your main line of code when it’s ready to submit to QA.

In summary, pay heed to your process. Watch out for that trap that ensnares many teams, of getting bogged down trying to meet the needs of the tools, of the processes (like TDD or bug-tracking), and of paperwork. When your developers start to sense that your process is weighing down their productivity (as measured by the actual, real-world functionality that is evolving – the kind that your customers will actually see) then it is time to seriously re-examine your whole process.

 

James W. Hurst

 

return to Testing Software

WPF Tip: avoid App.Current.Shutdown

In your WPF application’s Exit command handler, be wary of calling App.Current.Shutdown unless you want to bypass the normal ‘Close’ process. It can result in your override of Window.OnClosing to NOT be called, and your closing-event handlers don’t get called either.

If you override the Onclosing method, don’t forget to call the base class OnClosing!

Oh – if your WindowSettings functionality is not working, check for this mistake.

Of course I’ve never done that myself. Oh no. Neeeever.

Discussion:

If you are going to shutdown your application in code other than within the WPF Window or Page class, you can accomplish this by posting an event to the main window which will in turn close itself. If you want code to execute at the close of your application – you can override OnClosing within your Window subclass to accomplish this.

#region OnClosing
/// <summary>
/// This is an override of the event-handler for the Closing event.
/// </summary>
protected override void OnClosingCancelEventArgs e )
{
    UserSettings.SaveWindowPositionIfChangedthis );
    base.OnClosinge );
}
#endregion

This way, you can execute that code within your unit-tests and it will not try to force your running program (which may be your test-runner in this case) to shutdown – because you simply have not defined a handler for that event.

If you do want to call App.Shutdown, then you need to consider the case where it is running within a unit-test and you don’t have an App present to shutdown. In this case App.Current will be null and it would throw an exception where you try to call App.Current.Shutdown. Instead, you could code it thusly:

public void ShutdownApplication()
{
    App.Current?.Shutdown();
}

Here, if App.Current is null it does not make the call to the Shutdown method (as would be the case if this is running within a test-runner instead of the normal application-program).

 

James W. Hurst

Setting an environment variable in Microsoft Windows

“Environment variables” are just simple symbols that are available to any program; Windows uses these to to hold specific values. After the days of DOS we don’t usually need to be aware of them, but they’re still heavily used in Unix administration. We sometimes call them “environmental variables”.. same thing.

Here’s the skinny on setting an “environment variable” in Windows. As an example, let’s consider the PATH environment variable. This is used to tell Windows where to search to find the program that you entered, to execute it. You’ll want to set this if, for example, you’re setting up your system for compiling Java programs from the command-line.

Here I’ll illustrate using Windows XP. Windows Vista, Windows 7 and Windows 10 are similar enough that I don’t think you’ll have any trouble.

You’ll need to open the “System” Control-Panel applet, which you can do from the Control-Panel, or else just right-click on “My Computer” and select “Properties”.

Select the “Advanced” tab. You should see the System Properties dialog-window as shown in figure 1.

Screenshot of the System Properties dialog-window
Figure 1. The System Properties dialog-window

Click the button near the bottom that says “Environment Variables”. It should bring up the following dialog-window..

Figure 2. Environment Variables

This shows your Environment Variables: those that are specific only to you (the current user) are in the upper list, and those that are system-wide are in the lower list.

Let’s set your path variable to include the directory where your Java compiler is located, to illustrate how to do this..

In the lower list, select the line that begins with “Path”. Click the “Edit” button. It should bring up this dialog..

Screenshot - setting the variable value.
Figure 3. Setting the variable value.

 

Your Path variable consists of a multitude of file-system pathnames, separated by semicolons. You can append the pathname you want to add, simply be going to the end (click anywhere within the “Variable value:” textbox, then press your “End” key on your keyboard. Type a semicolon to separate your new value from what is already there, then type “C:\Java\JDK\bin” or whatever is appropriate for where you placed your JDK.

Click “OK”, and then “OK”, and you’re done.

If you already had a DOS Command-prompt window open, you’ll need to close it and re-open in order for your changes to affect it.

James W. Hurst

Data-binding To A Simple C# Class (WPF or Silverlight)

When composing a WPF view sometimes you need to ‘bind’ a property of one of your widgets to some kind of information source. WPF’s data binding capabilities provide a way to accomplish this very easily in XAML for a range of scenarios. Here’s a trivial example.

Let’s say you want a TextBox to get it’s text from an object of your own C# class. Let’s contrive a gnarly little sample class to serve as our data source that just holds a single property:

namespace HurstOnWpfDataBinding1
{
    public class Person
    {
        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }
 
        private string _firstName = "Aline";
    }
}

Consider this to be your “view-model”; in your XAML you bind to it using this syntax:

<TextBox Text="{Binding Path=FirstName}" />

What you are saying with this, in effect, is to get it’s value from the FirstName property of the binding source. You can get values only from properties – not from instance variables.

You can leave out the “Path” part – leaving this..

<TextBox Text="{Binding FirstName}" />

 

Where do we specify the binding source? One way is to simply do that in code; in the constructor after InitializeComponent, or in your event handler for the Loaded event:

public MainWindow()
{
    InitializeComponent();

    // Set the binding source here.
    MyClass viewModel = new MyClass();
    this.DataContext = viewModel;
}

 

Now it should work – when your Window pops up on the screen your TextBox fetches it’s text content from the FirstName property of your MyClass. Juuuust peachy.

But.. if you leave it as it is here, your TextBox won’t continue to update it’s text whenever the FirstName property changes! Why? Because it has no way of knowing; it fetches the property value just once as it initializes itself and renders itself on-screen.

Let’s fix that. We can use DependencyProperties, but for now why don’t we just reach for the simplest way available.

Change your source class to implement the INotifyPropertyChanged interface. This makes it send a notification to your XAML-defined TextBox of any important changes whenever you set a new value for that property. Here’s that same source class, with two essential changes. Take careful note of the change in your FirstName property…

 

using System.ComponentModel; // for INotifyPropertyChanged

namespace DesignForge
{
    public class MyClass : INotifyPropertyChanged
    {
        // This next region of code, is step ONE (of two) of what you need
        // to support the INotifyPropertyChanged interface.
        // I usually just copy it from a previous piece of code – it just works,
        // or, put it within a base-class.
        #region INotifyPropertyChanged implementation

        public event PropertyChangedEventHandler PropertyChanged;

        protected void Notify(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion INotifyPropertyChanged implementation

        // This is step TWO.
        // For each of your properties whose changes you want to track
        // (that is, to cause the data bindings to update),
        // add the call to Notify within the setter as I did below.
        // The string that you put as the parameter to Notify,
        // must to be exactly the same as the name of the property
        // (just copy-paste it and it'll rarely be a source of mistake).
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                // Do nothing unless the new value is different..
                if (value != _firstName)
                {
                    // Set the value.
                    _firstName = value;
                    // This next line is the only change within this property.
                    // Notify anyone who cares about this.
                    Notify("FirstName");
                }
            }
        }

        private string _firstName = "Naira";
    }
}

 

Now run your app and you should be seeing your GUI fields updating themselves to track the changes in your source class. This is the simplest example of a one-way binding and handles probably the majority of cases of this nature. Subsequent posts will cover more scenarios. Please shoot back a note to me if you spot any mistakes, problems or additional insight.

James W. Hurst

Setting up to brew some Java (Updated in 2020)

Here’s what we’re going to do:

  1. Download the basic Java tools (the JDK) and install it.
  2. Make something with it.

Frog hidden amongst the algae

Updated on 2020/02/09

This series is intended as a raw-beginner-level get-started guide for getting started in building Java applications – on Microsoft Windows. It is not intended as a lesson in how to program, and it is a bit pedantic. I posted this because the online information that’s readily available seems to be a bit of a mess. Even on the main Java websites, some of the information is outdated, wrong, unclear or just poorly written. I think it’s especially important to have this be simple, easy, and correct for beginners.

Java is now owned by Oracle (who acquired Sun Microsystems in 2010). In 2019 Oracle changed their Java License to be more restrictive. They maintain a Oracle Java SE Licensing FAQ here . If you would rather not use that — they also provide the latest OpenJDK release under the open source GPL license.

Versions:  The Oracle Java version (under their Oracle Java License) is at Version 8 Update 241 (as of 2020/2/10).  However the latest General-Availability JDK (Java Development Kit) release is JDK 13.0.2. Oh no – not confusing at all.

I am here assuming you are running 64-bit Windows and we’ve no need to discuss the 32-bit version, for brevity.

I’d appreciate your feedback comments for improving this article.
Unlike some other programming languages, it can take a bit of scrounging to get setup to produce a decent Java desktop application. Here then is a list of tips for getting started. Please note that these apply only to development under Microsoft Windows (as of 2020 I’m using Windows 10): if you’re using a different operating system then you’ll need to make allowances for the differences. Also, for brevity – I’m simply going to assume you’re working with the current version. If yours is a different version then just allow for this as you read below.

Okay, let’s get started.

Choose either

or

(click on one of the above)

Download the Java JDK and install it.

 

You have selected the Oracle JDK

Your first step is to download the Java JDK (“Java Development Kit”). Assuming you want the latest release, download it from  Oracle’s Java SE Development Kit 13 Downloads.

Click on “Accept license agreement, and then download the installer file by clicking on jdk-13.0.2_windows-x64_bin.exe (or similar depending up the version).

Proceed with downloading the file onto your computer.

Double-click that file that you just downloaded to launch the installer. You should see this:

Screenshot of Java JDK Installer - panel 1
The Oracle Java JDK Installer – panel 1

 

Click “Next >” and from here the installation process is pretty much self-explanatory. In the “Destination Folder” dialog-panel you can just leave the install-to at it’s default value, or you can change it if you wish. Personally I usually set it on my machine to be “C:\Java”.

The Oracle Java JDK Installer – panel 2

 

Click on “Next” to do the installation. It’ll take a moment.

Screenshot of The Oracle Java JDK Installer - panel 3
The Oracle Java JDK Installer – panel 3

 

Add your Java compiler’s executable folder to the PATH environmental variable. If you used the default path then you’d add “;C:\Program Files\Java\jdk13.0.2\bin” (or similar, depending upon your version). The initial semicolon is what separates this from the preceding text that is already in the PATH value (unless you want to place this as the first value).

Add a CLASSPATH environment variable, setting it to “C:\Program Files\Java\jdk13.0.2\lib” or whatever your version is.

Now skip to the section “You now have Java”

 

You selected the OpenJDK Version

Download and install the Java OpenJDK (the Open-source Java Development Kit) by pointing your browser to this page that has the OpenJDK builds.

Select the version you want and click on it to download the corresponding .ZIP file.

 

Now this next step is not essential, but it can solve an issue for some people. Often when you download a file on Windows, it has a property set on it that, if you right-click on the file and select “Properties”, you will see at the bottom of the “General” tab: “This file came from another computer and might be blocked to help protect this computer.” See figure 5.

Figure 5. The circled text indicates the file has a block on it.

You can remove this block by simply checking the “Unblock” checkbox and then selecting “OK”.

 

This file is not an installer. It is a compressed file that contains the entire directory-tree containing your JDK. Decompress it using your method of choice (I use Winrar).

Now you have a directory-tree under the directory named “jdk-13.0.2” (or similar depending upon the version you chose).

You install this by moving it to where you want it (or you can just leave it there – I don’t care). Personally I place mine within C:\Java\JDK, so that the full path is now “C:\Java\JDK\jdk-13.0.2”.  I place it under a separate directory named “JDK” because I use various versions and it seems cleaner to have them all under that one folder.

 

Add your Java compiler’s executable folder to your PATH environmental variable ( Click here if you are unsure how to add something to your PATH environmental variable ). If you installed your JDK to the same location as I do ( “C:\Java\JDK\jdk-13.0.02” ) then you would add “C:\Java\JDK\jdk-13.0.2\bin” to the PATH environment variable. The various paths within that environment variable are separated from each other using semicolons.

 

You now have Java

You can test that you’ve accomplished the Java installation successfully by opening a command-line window and typing: “javac -version”. It should respond with “javac 13.0.2” or similar depending upon your version, as you can see in Figure 4.

Figure 4. Screenshot of check that the JDK is installed correctly.
Figure 4. Check that the JDK is installed correctly.

 

You can view the official Java documentation here. This has changed during the time since Oracle took over Java. You can just link to the start page for all the documentation, or if you prefer to be able to access it when not online you can download an offline version.

You now have Java installed and are ready to git down for some actual programming. Next up is creating your first command-line programs, and JavaFX.

 

James Hurst