10 years later… female programmers and programmers to be

Ten years ago, I wrote a blog post entitled Female Programmers and Programmers to Be. It was largely a response to Kathy Sierra’s tweets on the topic. Now that I have ten years more experience, I decided to look back what I wrote and see how my thoughts on the matter have evolved.

Significance of being a “Woman In Tech”

The 2009 me wrote:

While I certainly haven’t been in the field as long as Kathy, I am a female programmer.  And I haven’t really thought about it since college.  Until recently.  It’s not significant to me; I don’t think it is significant to people I work with.  And yet in some ways it is.  My response to this tweet was:

@KathySierra sorry; you’re a VISIBLE female programmer & a role model for the next generation(aka me); don’t have any at work so branch out -Jeanne Boyarsky

And this is why I’ve been thinking about it.  Whether I notice or not, I am starting to become a role model to some people.  I know because they told me!  Sometimes it is people I know and sometimes it is people who read my posts on JavaRanch.

Well, now I’m definitely a role model! I’ve been a FIRST robotics mentor for over ten years, a regular conference speaker and a Java Champion. I think my 2009 self nailed it with the VISIBLE comment.

Ten years later, I do have more female programmer role models. (Phew.) Most of them either aren’t from work or are about my age though. Which I suppose makes sense. There weren’t going to spontaneously be more female programmers 10-20 years older than me. I also realized I was only counting people who chose the path over development over management. Between having a bigger network and time having passed, I definitely have more female peers and role models that I know in real life.

I do feel the same way as 10 years ago in that most of the time gender doesn’t matter, but every so often it does. I’ve been lucky that for me that has mostly been in the space of empowering others and less in the space of negative personal experiences. I also learned that I go through a long process in my head when I have to deal with the whole female role model thing. When asked something like being on a women in tech panel, my thought process is:

  1. Ugh. I just want to code.
  2. I want everyone who likes to code to feel like they can be a developer.
  3. I remember when almost all of my role models were men.
  4. Being seen helps others.
  5. Ugh. I’m going to have to talk and think about it.
  6. Grumble. I wish this didn’t matter.
  7. I remember in college being told this wouldn’t be a problem by now.
  8. Sigh. All right, all right I’ll do it.

In some ways, I was “lucky” that I got my exposure to “girls shouldn’t do science of IT” folks in middle school and high school. I built up immunity and didn’t care what they thought. It turns out that having a high school teacher say that in class definitely makes you think. I decided that programming was too fun to worry about it. My only regret was not making a formal complaint to the school administration at the time. (Instead I taught science to the girls in the class who were struggling so they got higher averages. Doing that during his rants about girls was sorta fun.)

I also had early exposure to a manager who felt cursing at his staff was appropriate. (This was not a gender thing.) But it gave me the “opportunity” to decide what was a line for me. To this day, I am unwilling to be cursed at at work. (Note to colleagues: I don’t care if people curse around me; I do care if it is directed at me.) I practiced in my head what I would say/do. I hope I’m never in the situation where I have to find out if I’m brave enough to test out whether I would. It’s “easy” to say what you’d want to do. It’s not easy that situation. So when you “armchair coach” a woman on what she should do/say, remember it isn’t as easy as it appears.

High schoolers

@jeanneboyarsky agree in principle, just that conference keynoters are NOT on teen girl’s radar and don’t “count” as visibility/motivation. -Kathy Sierra

This school year, I started volunteering as a mentor with FIRST robotics as a high school programming mentor.  The lead student programmer is also female. 

I agree that conference keynoters/speakers are not on teen girl’s radar (at least not at industry conferences.) I’ve spoken a few times at StuySplash (a conference run by a FIRST robotics team for other teams.) Most of the audience was high schoolers.

I think I replied wrong though. Having female conference speakers isn’t for high schoolers. It’s for future conference speakers. There’s that thing about how men apply for jobs when they meet a smaller percentage of the requirements than women. That applies to conferences too. I think women seeing female speakers would make them more likely to apply. It also helps men see there are strong female techies even if they don’t work someplace that is true.

Female Architects

@KathySierra: “women speakers in tech?” I always wonder why ‘women’ are different. Don’t we want good _people_ in these sessions? –Steve Johnson

And absolutely favor strength over gender when choosing conference speakers.

Where I work, there aren’t yet any female architects. And by that I mean the really senior folks who have been doing this 20-30 years like Bear Bibeault and Ernest Friedman Hill rather than the watered down “developer with 7 years experience” definition.

Yes, I want to be an architect someday.  But I want to get there because I’m good at what I do, not because I am female.

One of the nice things about getting rejected as a JavaOne speaker so many years in a row was that I knew I didn’t get picked for being female! (I got picked the year after there was a video of my giving an awesome talk on youtube). I do think I got an opportunity/nudge to give a full day training at Dev Nexus because I’m female. But I had also given a shorter version of that training at JavaOne.  I definitely still think it is important to favor strength over gender. But I think encouragement is ok. (Back to the “but I don’t meet 100% of the requirements” thing).

I’m pleased to say 10 years later that the statement of not having any female architects at work is no longer true! (I’m not an architect; I was and then I moved to a team where there isn’t a need for one. I’m still a tech lead and work)

What can we do

  1. Like what you do; be passionate about what you do – Male or female, this is the core of why technology is fun!  If you happen to be female, let this excitement shine through and let others see it.  I’m volunteering as a programming mentor for robotics because I enjoy it.  Being a positive role model for the students is a side effect.

  2. Point out the “she” – If you are female and someone refers to you as “he” or “sir”, correct them.  This is how we introduce visibility into the fact that there are strong techies out there.  Scott Selikoff does so if someone calls me “he” in a blog comment. Some people do this so often at JavaRanch that Campbell Ritchie has made it a running joke. But it helps.  It serves as little reminders that we do have strong female technical females running around.  Not to the the teens of course.  But to the existing programmers.

  3. Look to the future – Things change over time.  The senior architects of the today were largely born in the 50’s, 60’s and 70’s.  This was before people had the internet in their homes.  The students of today are growing up with social networking.  Computers aren’t as geeky.  There is more social interaction in the job.  In another couple of decades people my age will be those senior architects and then there will be more female role models.

I agree with all three of these pieces of advice from 2009. I have two more:

4) Refer to the people on your team. When interviewing, mention accomplishments of multiple people on the team. This provides an opportunities to show you have women, people from “ethnic” groups, etc without making a big thing out of it.

5) Encourage people do things they are almost ready for. (Notice I said “people” not “women”. This applies to guys too, especially if they are reserved or not reaching for opportunities.” Also, craft opportunities for them to push themselves in ways that are smaller so not as scary. For example, I recently asked an entry level teammate to do five minutes of a presentation with me. (I had the other 45 minutes.)

OCP 11 Book Bonus: Creating a HSQL Database/Stored Procedure in Java 11

For the PreparedStatement section of chapter 10, we used Derby. We recommend following the creating Derby instructions first.

For the CallableStatement section we used HSQL (Hyper Structured Query Database). We switched because Derby doesn’t use SQL based stored procedures which are the most common form.

You don’t need to know anything about creating stored procedures for the exam. You do have to know how to call them. This blog post is for readers who have purchased our book, OCP: Oracle Certified Professional Java SE 11 Programmer II Study Guide: Exam 1Z0-816 and want to follow along. It also includes the database installation instructions and setup code so you can simply copy/paste it. The actual book covers what you need to know for the exam.


This blog post assumes you are reading chapter 10 of our OCP 11 book for 816 exam and have gotten up to the part that references this blog post.


Download HSQL

Option 1: Download the hsqldb.jar from Maven Central

Option 2: HSQL is an open source database. It is really easy to install and use. To install:

  1. Go to the HSQL home page.
  2. Click on the link for the latest version. (At the time of this blog post, that was 2.5.0)
  3. Click through the many screens until it downloads.
  4. Download the zip file and unzip it. This will create a folder named something like hsqldb-2.5.0. Drill down to hsqldb and then lib to get the hsqldb.jar file.

Copy this hsqldb.jar to someplace convenient on your machine. The same directory you picked for the derby jar is a good choice.

Creating your initial database

To start out, copy this code into a file named SetupHsqlDatabase.java.

import java.sql.*;

public class SetupHsqlDatabase {

    public static void main(String[] args) throws Exception {
        String url = "jdbc:hsqldb:file:zoo";
        try (Connection conn = DriverManager.getConnection(url);
             Statement stmt = conn.createStatement()) {

            run(conn, "DROP PROCEDURE read_e_names IF EXISTS");
            run(conn, "DROP PROCEDURE read_names_by_letter IF EXISTS");
            run(conn, "DROP PROCEDURE magic_number IF EXISTS");
            run(conn, "DROP PROCEDURE double_number IF EXISTS");
            run(conn, "DROP TABLE names IF EXISTS");
            run(conn, "DROP TABLE exhibits IF EXISTS");

            run(conn, "CREATE TABLE exhibits ("
                    + "id INTEGER PRIMARY KEY, "
                    + "name VARCHAR(255), "
                    + "num_acres DECIMAL(4,1))");

            run(conn, "CREATE TABLE names ("
                    + "id INTEGER PRIMARY KEY, "
                    + "species_id integer REFERENCES exhibits (id), "
                    + "name VARCHAR(255))");

            run(conn, "INSERT INTO exhibits VALUES (1, 'African Elephant', 7.5)");
            run(conn, "INSERT INTO exhibits VALUES (2, 'Zebra', 1.2)");

            run(conn, "INSERT INTO names VALUES (1, 1, 'Elsa')");
            run(conn, "INSERT INTO names VALUES (2, 2, 'Zelda')");
            run(conn, "INSERT INTO names VALUES (3, 1, 'Ester')");
            run(conn, "INSERT INTO names VALUES (4, 1, 'Eddie')");
            run(conn, "INSERT INTO names VALUES (5, 2, 'Zoe')");

            String noParams = "CREATE PROCEDURE read_e_names() "
                    + "READS SQL DATA DYNAMIC RESULT SETS 1 "
                    + "BEGIN ATOMIC "
                    + "DECLARE result CURSOR WITH RETURN FOR SELECT * FROM names; "
                    + "OPEN result; "
                    + "END";

            String inParam = "CREATE PROCEDURE read_names_by_letter(IN prefix VARCHAR(10)) "
                    + "READS SQL DATA DYNAMIC RESULT SETS 1 "
                    + "BEGIN ATOMIC "
                    + "DECLARE result CURSOR WITH RETURN FOR " +
                    " SELECT * FROM names WHERE name LIKE CONCAT(prefix, '%'); "
                    + "OPEN result; "
                    + "END";

            String inOutParam = "CREATE PROCEDURE double_number(INOUT num INT) READS SQL DATA\n" +
                    "  DYNAMIC RESULT SETS 1 " +
                    "  BEGIN ATOMIC " +
                    "  SET num = num * 2; " +
                    "  END";

            String outParam = "CREATE PROCEDURE magic_number(OUT num INT) READS SQL DATA\n" +
                    "  BEGIN ATOMIC " +
                    "  SET num = 42;" +
                    "  END";

            run(conn, noParams);
            run(conn, inParam);
            run(conn, outParam);
            run(conn, inOutParam);

            printCount(conn, "SELECT count(*) FROM names");
        }
    }

    private static void run(Connection conn, String sql) throws SQLException {
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.executeUpdate();
        }
    }

    private static void printCount(Connection conn, String sql) throws SQLException {
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ResultSet rs = ps.executeQuery();
            rs.next();
            System.out.println(rs.getInt(1));
        }
    }
}

To run the program, you need to include the hsqldb jar file in your classpath. See the bottom of the creating Derby instructions FAQs if you aren’t sure how to do to this.

For example:

java -cp "<pathToHsql>/hsqldb.jar" SetupHsqlDatabase.java

If all goes well, the program will output the number 5.

What does this program actually do?

This program starts by doing the same thing as the Derby one. It then creates the stored procedures used in the book.

HSQL will create some “zoo” files in your current directory for the database and logs.

What does “user lacks privilege or object not found in statement” mean?

In HSQL, it means “something went wrong.” It could be a runtime error in your stored proc. It could be that you aren’t calling it right. Confusing message, I know.

OCP 11 Book Bonus: Creating a Derby Database in Java 11

If you are taking the Java 8 exam, see the Java 8 version of this post instead.

While it is certainly possible to get all the JDBC questions on the exam correct without running any code or understanding any SQL, it is nice to be able to follow along. This blog post is meant to help anyone who has purchased our book, OCP: Oracle Certified Professional Java SE 11 Programmer II Study Guide: Exam 1Z0-816, download and run through the examples in the text. It also includes the database installation instructions and setup code so you can simply copy/paste it. The actual book covers what you need to know for the exam.


This blog post assumes you are reading chapter 10 of our OCP 11 book for 816 exam and have gotten up to the part that references this blog post.


Download Derby

Option 1: Download the derby.jar from Maven Central

Option 2: Apache Derby is an open source database. It is really easy to install and use. To install:

  1. Go to the Derby download page
  2. Click on the link for the latest version. (At the time of this blog post, that was 10.15.1.3)
  3. Download the zip file and unzip it. This will create a folder named something like db-derby-10.15.1.3-bin. The unzipped contents will look like this:

In the lib directory, copy the derby.jar to a convenient location on your machine.

Creating your initial database

To start out, copy this code into a file named SetupDerbyDatabase.java.

import java.sql.*;

public class SetupDerbyDatabase {

    public static void main(String[] args) throws Exception {
        String url = "jdbc:derby:zoo;create=true";
        try (Connection conn = DriverManager.getConnection(url)) {

            // run(conn,"DROP TABLE names");
            // run(conn,"DROP TABLE exhibits");

            run(conn,"CREATE TABLE exhibits ("
                    + "id INTEGER PRIMARY KEY, "
                    + "name VARCHAR(255), "
                    + "num_acres DECIMAL(4,1))");

            run(conn,"CREATE TABLE names ("
                    + "id INTEGER PRIMARY KEY, "
                    + "species_id integer REFERENCES exhibits (id), "
                    + "name VARCHAR(255))");

            run(conn,"INSERT INTO exhibits VALUES (1, 'African Elephant', 7.5)");
            run(conn,"INSERT INTO exhibits VALUES (2, 'Zebra', 1.2)");

            run(conn,"INSERT INTO names VALUES (1, 1, 'Elsa')");
            run(conn,"INSERT INTO names VALUES (2, 2, 'Zelda')");
            run(conn,"INSERT INTO names VALUES (3, 1, 'Ester')");
            run(conn,"INSERT INTO names VALUES (4, 1, 'Eddie')");
            run(conn,"INSERT INTO names VALUES (5, 2, 'Zoe')");

            printCount(conn,"SELECT count(*) FROM names");
        }
    }

    private static void run(Connection conn, String sql) throws SQLException {
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.executeUpdate();
        }
    }

    private static void printCount(Connection conn, String sql) throws SQLException {
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ResultSet rs = ps.executeQuery();
            rs.next();
            System.out.println(rs.getInt(1));
        }
    }
}

To run the program, you need to include the Derby jar file in your classpath. If you don’t know how to find it or encounter problems see the below frequently asked questions in this blog post.

For example:

java -cp "<pathToDerby>/derby.jar" SetupDerbyDatabase.java

If all goes well, the program will output the number 5.

Note that we used single file source code execution here. This simplified the classpath since we only needed to specify the derby jar. Had we compiled our class we would have needed to include it as well (along with an operating system delimiter)

Alternatively, you could have added Derby to your CLASSPATH environment variable and just run the program as

java SetupDerbyDatabase.java

What does this program actually do?

The main method starts out by obtaining a connection to the Derby database. It then calls a run method to actually run the SQL. The run method uses a PreparedStatement with all the data hardcoded.

The code runs two SQL statements to create tables in the zoo database. The commands each include:

  • the table name – exhibits and names
  • the fields in each table along with their type. Integer is like a Java int. Decimal is like a Java double. Varchar stands for variable character and is like a String. The variable length part means that the database doesn’t need to allocate space for all 255 characters and should only use the space for the actual length of the string. (This matters when you frequently update the field with values of different lengths)
  • the primary key for each table – this tells the database how to you uniquely identify each row

Then the code runs seven SQL statements to insert rows into these tables. The order of the data columns matches the order the fields were defined in the create statements.

Finally, the code runs a query to check the rows were added to the database. The count(*) function in SQL always returns a number. For an empty table, this number is zero. Therefore, we can call rs.next() outside of a conditional or loop. We know there is always a number being returned.

Derby will create a “zoo” directory and a derby.log file in whatever directory you ran the program in. The zoo directory is your database.

Frequently Encountered Problems

If you have an error that isn’t here or have trouble with these instructions, feel free to ask a question in the CodeRanch forums

ERROR #1 – DERBY IS NOT IN YOUR CLASSPATH OR POINTS TO AN INVALID LOCATION

Exact error message:

Exception in thread "main" java.sql.SQLException: No suitable driver found for jdbc:derby:zoo;create=true
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:702)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
	at SetupDerbyDatabase.main(SetupDerbyDatabase.java:7)

Solution:

Check you are actually pointing to Derby in your classpath. Also check your classpath has the three required components

ERROR #2 – THE TABLES ALREADY EXIST

Exact error message:

Exception in thread "main" java.sql.SQLException: Table/View 'EXHIBITS' already exists in Schema 'APP'.
	at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:115)
...

Solution:

The program can only be run once as is. If you want to run it again, uncomment the two “drop table” lines.

Error #3 – NoClassDefFoundError: SystemPermission

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/derby/shared/common/security/SystemPermission
	at org.apache.derby.iapi.jdbc.AutoloadedDriver.connect(AutoloadedDriver.java:134)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:251)
	at injection.AttackStatement.main(AttackStatement.java:12)
Caused by: java.lang.ClassNotFoundException: org.apache.derby.shared.common.security.SystemPermission
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)

If you are using an IDE that uses the module path instead of the classpath, add derbyshared.jar to your module path in addition to derby.jar. (This jar is needed when running with modules.)

Note: While the exam does have topics on modules, they are distinction questions. We recommend using the classpath (and command line) when studying all topics other than the Java Platform Module System.