Going back to school
I just finished a meeting with one of my collegues in which we discussed our recruiting trip back to our alma mater, Stephen F. Austin State University. For those of you who do not know, SFA is a smaller state school located in beautiful Nacogdoches, Texas and has a reputation for being an excellent forestry and teaching university. But what most people do not know about SFA is that the business school is accredited by AACSB International-The Association to Advance Collegiate Schools of Business. Only about 29 percent of the business schools in the United States share this distinction. I graduated from SFA in December of 1999 with a bachelor of business administration in computer information systems and coincidentally, sat next to one of my best friends, pledge brother and roommate for 3 years - Jason Ortega - during graduation.
The other fact that is not well known is the quality of the computer science department at SFA. The faculty doesn't mess around with teaching visual basic and calling it a computer science degree. When I went through the CIS program, I was enrolled in all but two classes in the true computer science degree plan. When I graduated, it was almost as if I had double majored in CS and business. Most schools nowadays are selling MIS degrees, where they teach "analysis" and a few computer science courses. While those students are learning how to build a requirements document, SFA's CIS students are doing 8 dimensional arrays on a mainframe (RIP Dr. Dailey).
So now I get to go back and mingle with my old professors as a colleague and not a student. It will be interesting to see how my perceptions will change seeing them in a new light. Not only do I get to present in front of the 426 class and do a presentation to the Computer Science Club later that afternoon, but I get to spend the better part of 2 days just hanging out on campus talking with students and enjoying the academic side of things.
ScrumMaster Certification Course Review
First off, I would like to thank Peter Borsella for addressing my detailed questions during breaks and during the class. He did a great job not only presenting the material, but also addressing our individual concerns and inquiries without hindering the progress of the group. It was just the right mix of personal attention.
So what did I learn?
- The books on Scrum are fantastic but do not accomplish what you need completely. After reading some of the scrum books such as Agile Development with SCRUM and User Stories Applied, I thought I had a good idea on how a team would react to planning poker and estimating. I was correct on many of my assertions but again, we would continuously find ourselves having the basic discussion again and again about the meaning of this or the meaning of that. The books are great supplements but you need to watch this process living and breathing.
- It's amazing how much everyone differs in their definitions of certain words in the IT industry. When one of our non-functional requirements of "use proper security and data protection", it started a wide array of discussions, going all the way from offloading SSL to black-box machines to the data protection requirements in Swiss banks. The variation of definition is not something I am just now realizing but it never ceases to amaze me how much 7 or 8 people can differ on a simple word - such as "complete".
- SCRUM is a structure, not a process definition. I was thinking it would be implemented in a more strict control setting but it amazingly light and flexible.
- The majority of people's concerns did not seem to be technological issues or subject matter, but rather people and logistics. We continuously brought up themes of personality management and how to hedge dependencies and get away from waterfall. I was not surprised at all that we spent quite a bit of time discussing how to handle executive intrusion into the process and roadblocks from outside forces.
Overall, it was a good experience and nice refresher about Scrum. Now, if I could only get deployed on a project actually using it. I also took a bunch of notes with phrases and terms used by both Peter and my classmates which will be subjects for the blog for at least a couple of weeks.

Certified ScrumMaster Training – Day One
Getting to the building promptly at 8:30, we got started almost immediately. We jumped right into project histories and getting a feel for the groups overall knowledge about scrum/agile as well as some opinions about how recent project experiences have been. For day one, we went over the basics of the framework and some of the background source info for the reasons behind Scrum. We also did some excercises showing some of the positive effects of empowering the individual to get the job done.
My overall thoughts:
- I have always assumed that longer sprints would be the way to go, but the more and more I look at the timeline, 2 weeks or 3 weeks might be the longest you would want to go. Most clients I have worked for in the recent past (and current) change their minds weekly (sometimes daily) about requirements or implementations so therefore 2 week cycles would give the business the ability to buy into the process and let the team run.
- There are a lot of conflicting views just on the basics of Scrum.
I will post more at the conclusion of today.
Using Static Inner Classes to Clean Up After Your Junit Test
Unit tests are awesome. Unless you have a system that isn't modular and the units of work depend on persistence. You don't want to run around trashing your development and test database with what could be hundreds (or thousands) of unit test records but in between your test methods, it's hard to remember what needs to be cleaned up.
Create a static inner class to help you remember.
public class TestCase01 extends AbstractSessionBeanTestCase {
public void testUseCase001() {
try {
//create some records and save them
Cleanup.addTableAId(yourAId);
} catch (Exception e) {
} finally {
Cleanup.performCleanup();
}
}
public void testUseCase002() {
try {
//create some records and save them
Cleanup.addTableBId(yourBId);
} catch (Exception e) {
} finally {
Cleanup.performCleanup();
}
}
public void testUseCase003() {
try {
//create some records and save them
Cleanup.addTableAId(yourAId);
Cleanup.addTableBId(yourBId);
} catch (Exception e) {
} finally {
Cleanup.performCleanup();
}
}
@Override
protected void preTearDown() throws Exception {
Cleanup.performCleanup();
}
public static class Cleanup {
private static Collection<Long> tableAIds = new ArrayList<Long>();
private static Collection<Long> scheduleIds = new ArrayList<Long>();
public static void addTableAId(Long transactionId) {
transactionIds.add(transactionId);
}
public static void addTableBId(Long scheduleId) {
scheduleIds.add(scheduleId);
}
public static void performCleanup() {
//delete all the records from table A
//delete all the records from table B
}
}
}
public abstract class AbstractSessionBeanTestCase extends TestCase {
protected abstract void postSetUp() throws Exception;
protected void preTearDown() throws Exception {
}
@Override
protected void setUp() throws Exception {
postSetUp();
}
@Override
protected void tearDown() throws Exception {
preTearDown();
}
}
Fighting the Good Fight
"So besides being TECHNICALLY correct, what other benefits would we have in implementing this functionality your way rather than the way it's being done now?"
From a young age, we are taught to do what is right. You are taught to forsake friendships, put yourself in danger and expose yourself to unnecessary harm for the sake of what is right. Some are even taught to go to extreme actions to uphold certain principles. We use words like "brave" and "integrity" when we see someone going against the grain, and fighting the good fight. We hold these qualities in high esteem.
So what happens when you think you are doing the right thing but realize no one really cares?
Let's take an example that happens all the time in the world of software development, especially with system maintenance. You scope some changes and start drilling into some code and realize the table structures and class organization are seriously flawed. I'm not talking about an extra column flawed, but rather a many-to-many, non-normalized heap of something combined with no class hierarchies, duplicated code everywhere, hard coded constant duplicates, no interfaces, and no factories. And then you utter the phrase spoken so many times by as developer....
"Dude, I could rewrite this entire thing faster than make the changes."
Especially in a consulting or contracting role, when you raise the questions you run some serious risks. You risk alienating yourself from the team and looking like the bad guy. Let's face it, even the most modest developer sometimes takes criticism personally. It's human nature. I do it. Everyone does. So you might raise some very, very solid points, backed by oodles of documentation and years of well-known software development principles but in the end, you are basically criticizing someone's work. When that someone is the lead or the architect, and has been a valued employee for x years, you can really get into hot water. No one wants a trouble maker and no matter how TECHNICALLY correct you may be.
So what happens if you just do the job? You are miserable. You are constantly frustrated by the flaws and they eat at you every day you are forced to repeat them. You can actually get into bad habits, start to assimilate into the code and start coding incorrectly, although it is correct for this project. For some developers (and I have met quite a few of them), they can seriously just remove themselves from the struggle. "It's a job" is a phrase heard often. For those that can remove themselves, it's easy. For those of us who are a little more on the OCD side, it can really be painful.
You also risk not being able to help. Teams sometimes just don't realize how easy some changes could make their lives. Some just don't understand the proper use of a particular pattern and why decoupling can help reduce regression testing requirements. You can help in so many ways but you constantly are confronted with the risk of being a wave maker, which in the consulting/contracting world, can be deadly.
So when you see something that is wrong, what do you do?
Personally, I try to find a common ground and start small. A pattern implementation here and a code demonstration there is a great way to get on the same wavelength with your team. I try to understand the motivations of the developers by asking questions as well. "Why was this implemented this way" or "Did the _____ pattern not work in this situation" are great questions to let the developer explain the motives behind the code. I document what I think and I pass it on, either to the team or the project manager. If it's ignored, then it's ignored. You fight the good fight but you should only fight when the result can be positive. Too many times, no matter what, you can be absolutely right and at the same time, it can be the wrong thing to do.
It's all about finding that delicate balance between trying to do the right thing and doing it in the right way. You can lead a horse to water, but you can't make them drink - just don't beat him to death on the way to the trough.
Making Things Too Complicated
The Data Access Object pattern is a staple of the developer cookbook. To abstract the persistence mechanisms from the application resolves many issues with extensibility and flexibility, but also gives the developer a sandbox to improve performance. Rarely do you see pieces of business logic you write actually become the bottleneck of an application. More often than that, it's either an IO issue, a serialization issue or a DBMS issue - some piece of code you need to perform the business logic, but isn't a logical piece of the model.
So where does a DAO go wrong? Just like other values of application development, the issue boils down to a quote from our friend Albert Einstein...
"Everything should be made as simple as possible, but not one bit simpler. "
So let's look at an example of a DAO pattern. If you are a developer and unfamiliar with this pattern, shame on you. But here's a link anyway. While your at it, go google the GOF patterns and spend the weekend memorizing them. You will be asked about them on your next interview.
When you have simple tables with no foreign key relationships, it's as easy as pie.
CREATE TABLE SCHD_TYPE (
SCHD_TYPE_ID VARCHAR2 (2) NOT NULL,
DESCRIPTION VARCHAR2 (20) NOT NULL,
CONSTRAINT SCHD_TYPE_PK
PRIMARY KEY (SCHD_TYPE_ID)
);
public interface ScheduleType {
public String getDescription();
public void setDescription(String description);
public String getScheduleTypeId();
public void setScheduleTypeId(String scheduleTypeId);
}
public class ScheduleTypeImpl implements ScheduleType {
private String scheduleTypeId;
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getScheduleTypeId() {
return scheduleTypeId;
}
public void setScheduleTypeId(String scheduleTypeId) {
this.scheduleTypeId = scheduleTypeId;
}
}
public interface ScheduleTypeDAO {
public static final String FIND_ALL = "SELECT * FROM schd_type";
public Collection<ScheduleType> findAll();
public static final String FIND_PK = "SELECT * FROM schd_type WHERE schd_type_id = ?";
public ScheduleType find(long scheduleTypeId);
}
public class ScheduleTypeDAOImpl extends AbstractDataAccessObject implements ScheduleTypeDAO {
static final private Logger log = Logger.getLogger(ScheduleTypeDAOImpl.class.getName());
public Collection<ScheduleType> findAll(){
StringBuffer sql = new StringBuffer(ScheduleTypeDAO.FIND_ALL);
Connection con = null;
ResultSet rs = null;
Collection<ScheduleType> results = null;
try {
con = DatabaseConnectionFactory.getConnection(DatabaseConnectionFactory.POWERLINK);
PreparedStatement stmt = con.prepareStatement(sql.toString());
rs = stmt.executeQuery();
results = populate(rs);
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage());
throw new DAOException(e);
} finally {
close(rs);
close(con);
}
return results;
}
public ScheduleType find(long scheduleTypeId){
StringBuffer sql = new StringBuffer(ScheduleTypeDAO.FIND_PK);
Connection con = null;
ResultSet rs = null;
ScheduleType result = null;
try {
con = DatabaseConnectionFactory.getConnection(DatabaseConnectionFactory.POWERLINK);
PreparedStatement stmt = con.prepareStatement(sql.toString());
stmt.setLong(1, scheduleTypeId);
rs = stmt.executeQuery();
result = populate(rs).iterator().next();
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage());
throw new DAOException(e);
} finally {
close(rs);
close(con);
}
return result;
}
private Collection<ScheduleType> populate(ResultSet rs){
try {
Collection<ScheduleType> result = new ArrayList<ScheduleType>();
while (rs.next()) {
ScheduleType o = new ScheduleTypeImpl();
o.setScheduleTypeId(rs.getString("schd_type_id"));
o.setDescription(rs.getString("description"));
result.add(o);
}
return result;
} catch (SQLException e) {
log.log(Level.SEVERE, e.getMessage());
throw new DAOException(e);
}
}
}
Simple. Clean. Extends. Flexible.
But then people get too fancy for their own good. For example, we all know there are fancier ways to populate objects witha resultset. Here's an example of the fancy way.
protected static synchronized Object populateObject(DataTransferObject dto, HashMapmapping,
ResultSet rs){ Class clazz = dto.getClass(); Iterator columnNames = mapping.keySet().iterator(); ResultSetMetaData rsmd = null; try { rsmd = rs.getMetaData(); } catch (SQLException e1) { e1.printStackTrace(); } Object o = null; try { o = clazz.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } while(columnNames.hasNext()){ String columnName = columnNames.next(); String fieldName = mapping.get(columnName); Object columnValue = null; try { columnValue = rs.getObject(columnName); } catch (SQLException e) { e.printStackTrace(); } Field field = null; try { field = clazz.getDeclaredField(fieldName); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { field.set(o, columnValue); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return o; }
Fancy Schmancy. Until the developers want to do a join to populate an object. Or the developers need to build extra columns into a domain object but don't want to include an entire separate object. Or you have a naming conflict in the columns of multiple tables. This will work for some of your code but will leave the developers scrambling and coming up with their own implementations, which will all be DIFFERENT.
Keep it simple. Keep it readable. Keep it easy. Is it 3 minutes more of coding? Yes. Will it save you hours and hours of time down the road when you want to refactor or something doesn't fit the mold? Yes.