Making Good Software

A blog by Alberto G (Alberto Gutierrez)

Written by Alberto Gutierrez

March 27th, 2011 at 12:19 pm

The obsession with beautiful code, the refactor syndrome.

with 18 comments

There is lately an emerging obsession with beatiful code, up to the point where some programmers are overprioritizing it over more important goals such as:

  • Correctness
  • Robustness
  • Traceability
  • Supportability

When this is taken to the extreme, and all that the programmer cares about is the beauty of the code, can cause him/her to fall under the refactor syndrome.

The refactor syndrome has the following symptoms:

And usually causes:

  • An explosion of services, managers, helpers or other utility like classes.
  • Integration bugs.
  • Lack of robustness.
  • Loss of productivity.

The main issue with the refactoring syndrome is that is based in the beauty of the code, and this, upfront, has three big issues.

  1. Not achievable. All code is crap. This is one of my favorite quotes, and to me is proven by the following facts:
    • Exclusion principle. All programmers tend to think that only their code is the only good code in the universe.
    • Legacy code principle. As a programmer, as you learn new stuff, you even consider your not so new code to be crap.
    • Experience principle.I have never seen, or produced any real code which I thought it was beautiful.
  2. Not so important. Even if beatiful code was achievable, it doesn’t prove that the code is correct, and among other things, correctness is way more important than beauty.
  3. Wrong perspective. Focusing in the code itself, and not in the application makes the programmer forget about other more important areas.

This refactor syndrome seems to be associated with some programmers taking the last agile tendencies as religious dogmas. This happens when programmers confuse the tools and engineering practies like TDD, refactoring, pairing and unit testing… with what needs to be achieved. This would be comparable to a builder who believes that having shiny, new and clean tools, is more important than the house he is building.

It is important to understand that none of the tools or engineering process that the different agile family of processes propose are bad per se, they are usually great. Is just that when we decide to overuse them that we might be getting close to the refactoring syndrome.

In summary, is important to remember that:

  1. It is not important how beatiful is your code if it doesn’t work.
  2. Refactor only when is necessary, not only when you don’t like the code or you think you are going to make it more beatiful. Not liking something IS NOT a reason enough to change it.
  3. Unit tests have very limited value when it comes to integration and end to end issues. Do real end to end test!!
  4. Know all the different tools and engineering practices, but don’t take them as dogmas, learn what is good and bad from each and apply them when necessary.
  5. Good programmers are gonna keep doing good software, bad programmers are gonna keep doing bad software, no matter what processes they follow.

Update

Apparently this article is causing some controversy, so I want to make clear some points which I see after the comments I didn’t made clear enough.

  1. I do think that Unit Test is great, I just want to point out that it CAN’T and it SHOULDN’T pretend to substitute integration and end to end test from the developer.
  2. When I say that a bad programmer is going to write bad software, no matter what process he follows, I didn’t mean to say as in, a bad programmer also will always be a bad programmer, we all have been very bad programmers when we started, and we only hope that we improve as we aquire more experience.


Written by Alberto Gutierrez

March 19th, 2011 at 9:32 am

Solving Sudokus with Java and tree data structures

with one comment

A few weeks ago I published Java and tree data structures a post where I mentioned that I would try to put together some code to handle tree data structures… Well, this is the first installment of what I hope it will become a series of articles/code that will look into creating this tree library.

This first article/code is going to be about building trees dynamically. It is going to be illustrated by an example on how to use dynamic tree building to find the solution for a Sudoku. All the source code is available for downloading in a SVN repository, the URLs are:

Tree source code: https://subversion.assembla.com/svn/making-good-software/trunk/mgsTrees
Sudoku source code: https://subversion.assembla.com/svn/making-good-software/trunk/mgsSudoku

Dynamic tree building to find a solution

One widely used technique in computer science is to use a tree data structure to find the solution for something that needs to be solved but which solution is not obvious and requires many steps. One example could be chess, or a puzzle, a crossword, or like in this case, a sudoku.

The premise is simple, given an initial state, start building a tree of developed states from this original step until we find the state we were looking for. In the specific case of a sudoku, start building a tree where the branches are the different valid developments for that sudoku and stop when we find the solution.

The key element for building a tree dynamically is recursivity, starting from the original state, we find what the next candidate are, and them we do the same with each of them. In the mgsTrees library this can be easily accomplished by implementing an interface:

public interface ExpandTreeStrategy<T> {
	public ExpandAction<T> expand (T toExpand);
}

The return type of the ExpandTreeStrategy is an ExpandAction. An ExpandAction has 3 flavors.

  • stopBranch: It signals that this node is not expandable. In the Sudoku solver this is used when an ilegal Sudoku is reached.
  • stopTree: It signals that is not necessary to keep building the tree. In the sudoku solver this is used when the solution is found.
  • continueWith: This is used to specify what are the next states to look at. In the sudoku solver this is used when a intermediate sudoku is reached to specify what the next candidates are.

This is how to create the ExpandTreeStrategy Implementation for the Sudoku solver.

public class ExpandSudokuLookingForSolutionStrategy implements ExpandTreeStrategy<Sudoku> {
	private final SudokuAnaliser sudokuAnaliser;

	public ExpandSudokuLookingForSolutionStrategy(SudokuAnaliser sudokuAnaliser) {
		this.sudokuAnaliser = sudokuAnaliser;
	}

	@Override
	public ExpandAction<Sudoku> expand(Sudoku toExpand) {
		SudokuAnalysis sudokuAnalysis = sudokuAnaliser.analise(toExpand) ;
		
		if (sudokuAnalysis.isSolved()) return ExpandAction.stopTree ();
		if (! sudokuAnalysis.isLegal()) return ExpandAction.stopBranch ();
		
		if (sudokuAnalysis.hasDirectSolutions()) {
			return continueWithSudokuWithAllDirectSolutionsFilled(sudokuAnalysis);
		} else if (sudokuAnalysis.hasNextCandidates()){
			return continueWithSudokuVariantsForSquareLocationWithLessPossibleValues(sudokuAnalysis);
		}else{
			throw new RuntimeException("Is not possible to have a sudoku not solved, legal and without direct soluctions or candidates");
		}		
	}

	private ExpandAction<Sudoku> continueWithSudokuVariantsForSquareLocationWithLessPossibleValues(SudokuAnalysis sudokuAnalysis) {
		List<SudokuMovement> movements = sudokuAnalysis.getPossibleMovementsForSquareWithLessPossibleValues();
		List <Sudoku> nextSudokus = new ArrayList<Sudoku>();
		for (SudokuMovement movement : movements) {
			nextSudokus.add(sudokuAnalysis.getSudoku().with(movement));
		}
		return ExpandAction.continueWith(nextSudokus);
	}

	private ExpandAction<Sudoku> continueWithSudokuWithAllDirectSolutionsFilled(SudokuAnalysis sudokuAnalysis) {
		List<SudokuMovement> movements = sudokuAnalysis.getAllDirectSolutionMovements();
		return ExpandAction.continueWith(sudokuAnalysis.getSudoku().with(movements));
	}
}

At the end the entire tree building logic is wired in the TreeFactory class, which has a method, buildTree, that takes the starting point for the tree, and which constructor takes the ExpandStrategy to be used to build the tree. The result of this call is a TreeResult, which contains three main methods;

  • getTree(): The resulting tree
  • isBuildInterrupted(): Will tell you if the build is interrupted, in the case of the SudokuSolver this would mean that the solution was found.
  • getLastBranch(): A sequential ordered list of all the last branch nodes startging from the root node, the original node. In the case of the sudoku solver this is used to retrieve in case that the solution is found (isBuildInterrupted == true) the sequence of Sudokus from the original one to the solution.
public class TreeFactory<T> {
	private final ExpandTreeStrategy<T> expandTreeStrategy;
	
	public TreeFactory(ExpandTreeStrategy<T> expandTreeStrategy) {
		this.expandTreeStrategy = expandTreeStrategy;
	}
	
	public TreeResult<T> buildTree (T seed){
		System.out.println(seed);
		ExpandAction<T> expandActionResult = expandTreeStrategy.expand (seed);
		if (expandActionResult.isStopBranch ())	return TreeResult.stopBranch (seed);
		if (expandActionResult.isStopTree ()) return TreeResult.stopTree (seed);
		
		Node<T> rootNode = new Node<T> (seed);
		List<Node<T>> currentBranch = new ArrayList<Node<T>>();
		currentBranch.add(rootNode);
		
		Iterator<T> childIterator = expandActionResult.getChildIterator();
		TreeResult<T> lastSubTreeResult = null;
		while (childIterator.hasNext()){
			Node<T> next = new Node<T> (childIterator.next());
			lastSubTreeResult = buildTree(next.getContent());
			rootNode.addChild(lastSubTreeResult.getTree().getRootNode());
			if (lastSubTreeResult.isBuildInterrupted()) {
				currentBranch.addAll(lastSubTreeResult.getLastNodeBranch());
				return TreeResult.interrupt (rootNode, currentBranch);
			}
		}
		
		currentBranch.addAll(lastSubTreeResult.getLastNodeBranch());
		return TreeResult.buildCompleted (rootNode, currentBranch);
	}
}

The final code to solve any given Sudoku will look like:

public static void main(String[] args) {
		Sudoku sudoku = new Sudoku(
			new SquareValue [][]{
				{__, __, __, 	__, __, __, 	_6, __, __},
				{__, __, _3, 	_7, __, __, 	__, __, _1},
				{__, _8, __, 	_1, __, _6, 	_9, _4, __},
				
				{_7, __, __, 	_5, __, __, 	__, __, __}, 
				{__, __, _5, 	__, _4, __, 	_8, __, __},
				{__, __, __, 	__, __, _2, 	__, __, _7},
				
				{__, _2, _9, 	_6, __, _4, 	__, _3, __},
				{_6, __, __, 	__, __, _8, 	_4, __, __},
				{__, __, _4, 	__, __, __, 	__, __, __}
			}
		);
		
		IteratorStrategy rowNavigator = OneLineIteratorStrategy.horizontal();
		IteratorStrategy columnNavigator = OneLineIteratorStrategy.vertical();
		IteratorStrategy matrixNavigator = MatrixIteratorStrategy.instance();
		SudokuProcessor sudokuProcessor = new SudokuProcessorImpl(rowNavigator, columnNavigator, matrixNavigator);
		SudokuAnaliser sudokuAnaliser = new SudokuAnaliserImpl(sudokuProcessor );
		ExpandTreeStrategy<Sudoku> expandTreeStrategy = new ExpandSudokuLookingForSolutionStrategy(sudokuAnaliser);
		TreeFactory<Sudoku> treeFactory = new TreeFactory<Sudoku>(expandTreeStrategy);
		
		TreeResult<Sudoku> buildTree = treeFactory.buildTree(sudoku);
		List<Sudoku> lastBranch = buildTree.getLastBranch();
		System.out.println("Solution: " + lastBranch.get(lastBranch.size()-1));
	}

Written by Alberto Gutierrez

January 26th, 2011 at 5:15 pm

How to manage Exceptions in Java. 4 basic considerations.

with 8 comments

Managing exceptions correctly in Java is not as simple as it may sound, there are many wide extended bad practices and programmers who simply don’t care. But having good exception handling is essential to diagnose problems in production and to basically make the maintenance of the application easier. What follows are, in my opinion, the 4 main considerations to effectively handle exceptions in Java.

1.- An exception should only be handled once.

Handling an exception more than once is one of the most common mistakes when dealing with exceptions. There are two main anti patterns:

Exception swallowing.

NEVER shallow an exception. This is, without a question, the most dangerous error when dealing with exceptions. Swallowing an exception = Making your application lie to you. Once that you shallow an exception there is no coming back. Any error caused as consequence of this first exception is going to be extremely hard to diagnose.

Exception handled more than once

Havin an exception handled more than once basically means that in its way out of the stack trace, more than one method catches the same exception. The two main scenarios when a exception is handled more that once are:

Log and throw exception.

Logging and throwing an exception, from a naive perspective, may seem like a valid approach, but is an approach that generates noise and lacks elegance. It lacks elegance because the exception is thrown again after being logged, causing further catch blocks in the stack trace to also deal with it and consequently force them to shallow the exception or to log duplicated information. To prove it let´s imagine that a method logs and throws again one exception, the following would be the main options for further catch blocks in the stack trace.

1) Log exception. This will cause a duplicate stack trace being printed in the logs.

2) Ignore exception, the exception will get to the top of the stack trace, and the JVM will handle it. This will also cause a duplicate stack trace in the logs.

3) Shallow exception. This is a common case of exception swallowing. It usually happens when we know the internals of the method we are calling and we know that the exception is already logged. As already mentioned, exception swallowing is very dangerous.

Don’t wrap runtime exceptions without adding more information.

This is another common scenario of handling an exception more than once that causes a lot of noise. It usually happens when inside a method we have to handle a checked exception, so the programmer decides to catch all the exceptions and wrap them in runtime exceptions. i.e.

catch (Exception e)
     throw new RuntimeException (e)

 
The issue with the code above, is that it will also catch all RuntimeExceptions, and it will wrap them in a new RuntimeException, which is useless, because it doesn´t add more information. A better approach would be:

catch (RuntimeException re)
     throw re
catch (Exception e)
     throw new RuntimeException (e)

 

2.- Create your own type and tree of exceptions.

Having your own type of exceptions, and your own hierarchy of exceptions, have a lot of advantages.

– Code becomes more readable.

– Logs become more readable.

– Helps to standardize the output of the exceptions.

– Makes it easy to tell what is the source of the exception.

3.- Who should catch the exception?

Place catch blocks carefully, if you are not sure if you want to handle the exception, don’t handle it. In general, only use catch when:

a.- You need to provide graceful error recovery. For instance: every entry point of your code that faces the customer should have a try catch strategy. Remember always to handle the exception as late as possible, otherwise you will end up swallowing the exception or handling it more than once.

b.- You are forced. If you receive a checked exception and you don’t want to handle it just now, feel free to wrap it up in a RuntimeException, but NEVER, shallow the exception.

c.- In batch like process that loop through a series of elements. inside the loop, ALWAYS, catch all exceptions.

d.- You want to add more information to the exception. For instance: Wrap an exception in a more specific, more related to your domain exception.

4.- Understand the purpose and nature of the exceptions.

The root cause for most of the anti patterns when handling with exceptions is the fact that the developers don’t fully understand the nature and purpose of the exceptions. An exception represents unexpected exceptional behavior, which we can try to recover from or handle gracefully. Catching exceptions is the mechanism the application gives us to step in before the JVM deals itself with the exception, is the last frontier. Having this is mind

– Be careful with exceptions when creating new exceptions. When dealing with exceptions, don’t make much assumptions, if you try to do something smart and you cause a further exception, you will loose the first exception.

– Don’t use exceptions to handle standard business cases. They are better off handled by your standard Java code.


Written by Alberto Gutierrez

January 14th, 2011 at 10:53 am

How to interact with web services, databases and other integration points. 4 main considerations.

with one comment

Interacting with external resources from your application is a common practice in modern applications, especially for “enterprise like” applications.

An external resource is anything we need to interact with, which sits outside of the application runtime environment. An integration point is where our application handles the interaction with the external resource. The most common integration point types you are likely to deal with are: Web services, databases, files, ftp, external devices…

The problem with any integration point is that you don’t have any control over them, which means that they are not reliable; this requires the developer to have in mind additional considerations to successfully develop robust integration points.

What follows are, in my opinion, the 4 main considerations for software developers to have in mind when developing an integration point.

1.- Always assume that your integration point may fail.

Every single integration point may fail; keep always this mind when developing. This would be the only consideration I would highlight if I only could highlight one.

Is important to make it clear that this consideration doesn’t mean that you have to always handle exceptional errors on the integration points. For instance, let’s say you are logging to a file. A file is an integration point, so you know it may fail, in this scenario it could be fair to say: If there’s an exceptional error on logging, let the log process crash, so you don’t handle the exceptional behavior. But at least you are asking yourself the golden question “What if the integration point crashes? ”

The golden rule to deal with unexpected errors in your integration points is to flag and record them so they can be reproduced later.

2.- Cover your back.

One of the main problems when dealing with integration errors is that when they fail, they usually cause data corruption, or other major issues in your application. These issues can many times only be recovered or tracked by extracting information from your logs. That is the reason why you need good logs in production.

Logging requires additional thought in your integration points than other parts of your applications, just because they are more likely to fail. In general any integration point should be able to tell you in the logs 3 things:

• What is the message that initiated the interaction?

• Was there any unexpected error?

• The result of the interaction with the integration point.

Keep in mind that saying that the integration point should be able to log the three previous questions, doesn’t mean that it always have to log them, or that is the only required logging, that’s something that is only going to be clear once that the application is deployed and actually used. It means that you should be able to turn on or off this logging. There is very few worst things than having an integration point failing in production and not being able to turn on any logging to see what is going on.

3.- Isolate the interactions with the integration point.

As already specified, interacting with integration points is dangerous, so is good to strategize its interactions to make sure that their outcome don’t affect the normal behaviour of the application. Some considerations would be:

• Minimize the amount of interactions with integration points.

• Wrap the logic of your interactions in transactions.

• Allow for automatic retries

• Separate the logic that handles your integration point and your business logic.

4.- Do “what if..” integration testing before going to production.

Getting your integration points right is very difficult, in my opinion, this and synchronicity are the two most difficult things to get right in enterprise software development.

For this reason is important that you assume that if you don’t prove yourself wrong, your integration points are going to fail. Make sure that before you deploy into production you test as close as end to end as many as possible “what if…” scenarios as possible.


Written by Alberto Gutierrez

December 21st, 2010 at 1:37 pm

Agile dogmas: You shall never do any design.

with 9 comments

Agile has become one of the most beneficial and needed change in software development. It has helped to move the focus of software development:

  • From: Project managers, architects, documentation and requirements.
  • To: Programmers, implementation and opened discussions.

Paradoxically, some companies and programmers are pushing this change of paradigm so hard, that they are falling in the very same errors that doomed waterfall: Lack of flexibility and dogmatism.

One of the most popular dogmas among the agile community is: “you shall never do any design.”. This dogma it’s been mostly influenced by TDD, and that’s why this article focuses on it

TDD and its core pattern “red-green-refactor”, is an emergent design engineering practice that can dramatically improve the quality of the code. Being based in emergent design means that is not necessary to do any explicit design in software development, but that the design will flourish from the implementation.

The issue with TDD, as with any other emergent design approach, is that it doesn’t make any differentiation between the implementation design level (tactics), and the architectural design level (strategy). This lack of differentiation between strategy and tactics, for simple developments is OK, but for more complex developments becomes an issue.

A good metaphor would be climbing a mountain. Let’s imagine two different approaches; one where every single step of the route is prepared beforehand, and the other where we would just start climbing paying attention just to what we have a few steps ahead of us. The first approach would be the equivalent of an extremist waterfall approach; the second would be the equivalent of an extremist approach to agile. Obviously none of them would work.

Software development is, in that sense, like climbing a mountain. It is necessary to have a strategy and a tactic. Is also important to realize that, as climbing, we have to adapt to the different circumstances we face in the day to day of software development.

TDD, as any other emergent design technique, is ideal for the tactical part of software development, but they ignore the strategic part, which for complex developments is very important.

One of the biggest factors to determine whether a development is simple or complex is uncertainty. Having a high uncertainty means that there are a lot of critical details from the development that are no evident. When uncertainty is high, is when we can take advantage of doing design.

One sample of simple development, with almost no uncertainty, and which won’t require any previous design would be developing a component that would take a quantity and a percentage and would tell us what the interests are at the end of the year.

An example of a more complex development would be to develop a component that would be able to resolve a Sudoku. In this case we would take advantage of doing some previous design.

When doing designs, is important to take into consideration the following guidelines:

  1. The design should be informal. It shouldn’t have to be in any particular format or using any particular methodology.
  2. The design should be incomplete. We should distance from the Waterfall BDUF, we only want to capture the 20% of the essence, which is going to help us fix the 80% of our problems.
  3. The design should be small, and should take short time. We shouldn’t expend more than 2 hours doing the design, if so, the reason would probably be that we need to split the development into smaller development items.
  4. The design should be democratic and simple. This means that there shouldn’t be any architect throwing the design to the programmers. The design should be done via open discussions with your colleagues, and simplicity should be preferred to any other approach.
  5. The design changes and evolves. We have to move away from the waterfall approach where the design is static, in agile, the design should be used to help us identify the bigger picture and it changes as we discover hidden aspects of what we are developing.

Continuing with the previous Sudoku example and with the design guidelines just commented above, one design approach for a component that resolves Sudokus summarized in a few points, could be:

  • To find the solution for a Sudoku we have to guess, one at a time, what are the missing numbers in the empty cells.
  • The best approach to pick the next number to guess is to find a blank spot in the Sudoku that can only hold 1 valid number.
  • When a solution for one cell is found, a new Sudoku with that cell filled is created and recursively we keep looking for the next solution until all the cells are filled. Then the Sudoku is solved.
  • When there isn’t any cell with an unique possible value, we have to search the cell with the less amount of valid possible values and create an hypothesis from there. That’s it, from the list of possible values, pick randomly one of them.
  • With the hypothesis we keep looking for the solution as if it wasn’t an hypothesis, but a completely valid solution. The difference is that with hypothesis, if we ever get to a point where there isn’t any possible solution, we go back to the originating Sudoku of the current hypothesis, and we create a new hypothesis.
  • The hypothesis can contain other hypothesis.

It is important to realize from the previous design that it doesn’t get into implementation details, and is very informal. They are only a few guidelines to help with the development.

Even thought, they may not seen very important, this mini design sessions are key to help developers to obtain the bigger picture of what they are developing. Remember:

  • It is not right to try to guess beforehand what are all the directions we have to take paying no attention to the road.
  • Neither it is, to start walking only to realize 2 kilometres later that we took the wrong direction.

Balancing out the right amount and timing of designing and coding is, with any question, a quality common to all the best programmers in the world.


Written by Alberto Gutierrez

November 7th, 2010 at 2:44 pm

Demystifying agile, top 7 myths.

with 9 comments

After a few years of experience working with agile, I have come to the conclusion that many of its principles are just buzz talking targeted to management and that they don’t help in the development of the application.

What follows is a list of the most common myths I have seen around agile. Please, feel free to add a HA! After you mentally read each of their titles.

1.- Stories are better if you follow such and such conventions to create them.

Have you ever had a fight over the best convention to use to name a story? Or have you ever expend hours trying to split your backlog into stories that fit such and such criteria? Or maybe spend weeks deciding the best application to store them?

There is a funny fact about stories, when there is a communication issue in the team, stories are usually blamed: They are not clear enough, the acceptance criteria wasn’t good enough, the color of the cards was wrong…

Stories are great placeholders for discussions between development, management, QA and the customer. That’s all they are. All you need to do is make sure that everybody involved understands them and keeps an open discussion.

The ones to blame when communication doesn’t work is the team, and the solution is usually not improving the stories, but improving the communication.

2.- Planning, with agile is fun and accurate.

Fact: Planning in software development is not accurate. You can use days, hours, points, play poker or blackjak, is not going to work, and if it works is usually by coincidence. So, should we stop planning? … mmm… I don’t think managers would be very happy about that.

Definitely planning adds value, it tells you about the scope of the task: is it hours/days/weeks? And it helps to determine the percentage of completion of functionality of the application. It is also useful to set expectations for management.

Agile actually does a good job setting the right expectations. With agile the customer should legitimately expect to receive the best solution as possible for a given date, but agile is not going to tell you when you are going to be finished, still is probably going to be more accurate than waterfall.

3.- Daily stand-up, the communication panacea.

Stand-ups don’t substitute communication in the team, but some agile teams tend to think so, the “let’s raise it in the tomorrow’s stand-up” approach, doesn’t work.

Stand-ups are ok, they provide an overview for the previous and the current day, but that’s all they are. Communication is very important in software development and it can’t be limited to a 10 minutes discussion in the morning.

4.- Agile the process that fits everything.

Agile is not the silver bullet. That’s probably one of the most repeated sentences in agile environments; still, I have seen the very same people that say so behave like if it was.

Applying agile principles to everything is not only wrong, but lends to dogmatic ridiculous situations, like never documenting the code, never creating documentation or never creating even a light design upfront.

Software development is a complex matter that requires different approaches depending the circumstances, sometimes a waterfall approach is better suit than an agile approach or vice versa, and most of the times what is going to be better suit is going to be a mixed approach.

5.- Retrospectives, they fix everything.

Not only is a bad practice to wait for the retrospective to raise an issue, is childish to expect them to be fixed just because they get raised, issues raised in retrospectives are usually serious impediments, and management tend to leave them for after, which usually means never.

Over the years I have come to the conclusion that removing impediments or improving the process are usually up to individuals. “Hero developers” make most of the big differences made in software development.

These hero developers are the ones that usually get fed up of not having SCM or not having an automated test suite… And they decide to champion an action and fix things on their own terms.

6- Unit tests is all you need.

There is a tendency in agile to believe that unit tests is all you need. But the problem is that the major issues are always in the integration points and E2E aspects of the application, and that’s something that your unit test are never going to highlight. Unit tests are still very important, they have a lot of value for refactoring and to help you design your code, but keep in mind that you are still going to require integration, end to end, adhoc and other types of testing to guarantee the quality of your product.

Another stupid affirmation is the ones that refer to an specific necessary quantity of code coverage in the project. This type of metrics are useless and usually come from people that has never coded for real. Your unit tests must cover parts of your application that contains your business logics, not getters, setters, integration points etc.

7.- Agile is a process fitted for junior programmers.

Short answer: No, agile is not a process suited for junior programmers. Agile switches the main responsibilities of the development from a few to everyone in the team.

Everyone is responsible for maintaining the quality of the application, and when you asked someone without experience for this kind of responsibility you are calling for troubles.


Written by Alberto Gutierrez

October 29th, 2010 at 4:17 am

Tips to create a new business website

with one comment

There are many businesses that decide to create their webpage without having the expertise or the resources to hire professionals.

For these businesses is difficult to get started, as they usually get the priorities wrong. Many new businesses start developing the web page by building a prototype that looks nice, and then they try to adapt their content to it, so they only care about the visuals.

There is much more to a webpage than a nice layout, actually a nice layout is not going to get you any customers. What follow are in my opinion the main key areas to understand before developing any business website.

Customer, customer, customer.

Nothing is more important in your website than your customer.This may seem obvious but many websites still look like if they have been designed for the directors of the company.

Elements like: flash animations, paragraphs explaining why this company is the best company, pointless images, text or data… Are only going to make your customer go away.

Figuring out what the customer wants to see is tough. One technique that is helpful is to use “personas”. “Personas” is an extremely simple but very powerful technique to help you guess what your customer reactions are going to be when they visit the website.

For example if we were making the website for a shoe maker, we could start by doing a website targeted only to customers summarised in three personas.

Sam “The casual guy” Alfred “The professional guy” Hellen “The pro”
Gender Male Male Female
Age 32 28 38
Budget 60$ 140$ 120$
Buys shoes Once every year Once every 6 months Once every 2 months
Description Not really into shoes, looking for an easy way to buy them. Looking for a nice looking, quality pair of shoes for the office. Looks for everything: quality, design, brand…
Computer skills Medium High Medium
Connects from Home Home and office Home, office and mobile devices
Priorities -Fast delivery
-Guarantee
-Quality
-Brand
– Information.
– Quality
– Fast delivery.

Having decided that these are the three personas that are going to define the user type of our web application makes simpler now decisions like, “What should be the links on the home page?”, “What content are we going to display in the search result page?”…

Even if you don’t use personas, is critical that you have a picture of who you are targeting with your webpage and what type of data are they going to be looking for.

Usability and simplicity

Usability, and not visuals, is the most important quality of a web page. Unfortunately that’s something that many businesses fail to identify when launching their new website.

Usability measures how friendly to the user a web page is. If I had to highlight only one technique to enhance your usability, that would be: “Hire people, to make usability testing”.

I found this technique mentioned for first time in the book by Steve Krug “Don’t make me think”. What basically says is that there isn’t any better feedback than real feedback. You need to find people to test your application usability. Once you have found them, ask them to perform diverse operations on your web page and pay attention at their reactions and feedback. I usually find it useful to record them so you can go over the session again or with other people from your company.

Other key area of usability is simplicity. If something can be simpler, then it should be simpler. Complex web pages are not friendly to users, unnatural navigational elements, scroll bars or navigation structures…

At last is important to remember some very basic navigation rules that should never be broken or would affect your usability otherwise:

  1. The user must always know where he is.
  2. The user must know how he got to where he is.
  3. The user must easily be able to go back to any previous page he visited.
  4. The user must easily know how to get to the home page.
  5. The user must easily identify what are the navigation elements and content areas of the page are.
  6. The user interface must be kept consistent in all the pages.
  7. The user must easily be able to read the any text in the web page.

Content

There is a golden rule, “decide your content first, then design your website”. Nowadays there are many websites that are first designed, and then the content is created to fit in them.

If you find yourself too often restricted to publish some content, because is too long, or it doesn’t have a header, or because you want it to have an image… then you are likely to be in this category.

Users only care about how good your website looks for around 2 seconds. Then they are going to look into your content, and if your content is limited because of your design, they are going to find other web page that simply has better content and not such a nice interface.

Reporting and management

A website, in 99% of the cases, needs to be updated continuously, otherwise it will die. User habits keep changing, and the content that is not up to date, is not taken seriously.

There is nowadays very powerful and usually free tools to help you to understand how your users are interacting with your web page so you can take an informed decision next time you want to change your website to improve the user experience.

Some of these tools are freely available and should be enough for a new website, like google analytics or feedburner.

Don’t reinvent the wheel

99% of the functionality you need has already been created and is freely available in Internet. This is something hard to grasp for inexperienced people, but is not an exaggeration, actually the other 1% is the reason why web development shops exists.


Written by Alberto Gutierrez

September 8th, 2010 at 12:34 pm

Lean: Avoiding Waste in Software Development

with one comment

Written by Alberto Gutierrez

August 16th, 2010 at 4:50 pm

How to prepare a programming job interview

with 10 comments

Since I have been myself hunting for a job recently, I thought it would be a good idea to share with you what I think are a few and basic key points to successfully face job interviews.

Before the interview

1.- Find out about the company. Visit their website. Usually, at the beginning of the interview, you are given the chance to explain what you know about the company. Use this opportunity to show that you have some interest in them, and that you have done some research. For instance, if you know the names of the people who are interviewing you, google their names, many times you can find valuable information about them in sites linkedin or their personal blogs.

2.- Review the specifications for the position. They may ask you about technologies that you haven’t used for a while. A quick review the day before the interview can make a huge difference.

3.- Make sure you know where the interview is and how to get there. An obvious one, but worth to remind. I find it very useful to bring with me some notes with the names of he guys interviewing me, the address and the phone number of the agency.

4.- Arrive always a bit before to the interview. Another obvious one, I personally like to arrive to the interview 5-10 minutes before.

During the interview

5.- If you don’t know the answer to a specific technical question, be plain and honest. There is only one thing worst than not knowing the answer to a question and that is not being sure about yourself. If you don’t know it, don’t fake it.

6.- If you know the answer to a specific technical question, be precise, concise and rational. Meaning: answer what they ask you about, not something related. Explain as much as necessary, no more, no less. If possible, explain why your solution is valid as opposite to another solution.

7.- If asked to do some code review, design… Ask permission to stand up and use the board to explain better your ideas (assuming there is a board in the room). It is not only easier to explain your ideas through diagrams, it also shows that you are confident and have initiative.

8.- Ask questions at the end of the interview. Having interviewed people myself, one of the things I most appreciate is people that come up with good questions at the end of the meeting. Some examples maybe asking about their continuous integration process, testing strategy, architecture… One particular question I like to ask at the end of the meeting is “do you have any concern about my technical skills?” This question works great, because you are opening a door for the interviewer to provide you with immediate feedback about the interview. Also, if they do have some concern, you have a second chance to revisit the areas where they think you may be not strong enough.

At all time

9.- Smile and look in the eye to your interviewer. Looking confident and friendly is very important in a job interview, eye contact and smiling is fundamental.

10.- Relax, try to enjoy. Relaxing in a job interview and approaching it from a “let’s have fun” perspective is going to help you a lot to finish convincing your interviewers that you are the right candidate for the position.

[EDIT] Best contributions IMHO from the coments

11.- Bob: I would add: Study logic puzzles, algorithms and data structures like crazy… at least if you are going to interview for a coding position at any kind of startup. My last interview (two weeks ago) consisted of 4 hours and 5 different interviewers, and I spent a good 3 hours at the white board solving, or trying to solve, tricky logic puzzles and programming problems. There was very little interest in my work experience and past projects, and I have 15 years experience. Google and MSFT have ruined the interview process…

12.- Amin: Good points. Another tip can be referring to your previous cool projects. For example when you are talking about a method or algorithm you can refer to a project that you have used that method or algorithm and talk more on the results.

13.- Rick: Good, but all rather reactive. The most important thing to remember is that your chances of getting the job don’t depend on the quality of your answers, but in the way you can make your interviewers feel about you.

One good starting point for that is to try to figure out before or during the interview what problem they have that they are looking to solve by hiring. Because it is rare that a company is looking for just another programmer like the other ones they already have. There’s a specific void that needs filling, and only a small part of that void is described in the job description.


Written by Alberto Gutierrez

July 25th, 2010 at 12:11 pm

Java and tree data structures.

with 18 comments

There isn’t any standard java implementation.

In almost every single project I have been involved, at some stage, I have found necessary to use a tree data structure, but I have found myself rewriting the same code to represent it because Java doesn’t provide with standard interfaces and implementations for Trees.

There are some open source tree data structures, but they are not flexible enough.

It is also surprising that there isn’t any major open source project, at least that I’m aware of, that tries to fill this gap. I have found on the Internet a few attempts to implement trees, but even thought they are correct, I don’t think they are as flexible as they should be.

The usual solution, the composite pattern on the objects itself, is far from ideal.

The most common implementation of trees, is using the composite pattern on the objects itself, meaning that no abstractions are created for classes as Tree, or Node. This approach has two main flaws:

  • Low cohesion: Now each object which is member of the tree needs to also have methods for navigation, insertion or other operations which are completely out of the scope of their own nature.
  • High coupling: Each node knows about their parents or about their children, changing one of them usually requires to changes the others as well.

How it should be (IMHO)

In my opinion, these are at least the main characteristics that a flexible Tree library should have.

  1. Ability to branch and sub-branch. Instead hanging nodes directly from other nodes, have the ability to add branches and sub-branches to nodes and hang the child nodes from them.
  2. XPath enabled. So you can call something like Node<Something> node = tree.get (“path/to/node”);
  3. Navigation specified through strategy. Navigator nav = tree.getNavigator (Strategy);
  4. Ability to filter.Navigator nav = tree.getNavigator (Strategy, Filter);
  5. Ability to create sub-trees from nodes. Tree subTree = new Tree (tree.get (“path/to/node”));
  6. Multi-threaded.

Your opinion and collaboration.

The main reason to write this article, is that I’m actually about to start writing this library myself, and I would like to share it with everyone, but before, I would like to hear from you guys. What’s your opinion: Do you think this sort of library would be useful? Would you use it? Do you think there are classes already that I might not know that have this functionality?

I am really looking forward for your comments!

Update

To find more information about the above mentioned Java tree library, including the SVN locations to download the source code check here.