Shahzad Bhatti

June 26, 2006

RailsConf 2006 Day 3

Filed under: Computing — admin @ 7:26 am

RailsConf 2006 Day 3
I started today with
Beyond DHTML: Introducing Laszlo on Rails
by Mike Pence. It
was interesting talk, but speaker could not give proper demo due to
Internet connection. Overall, I am not convinced why I would need Lazlo,
if I can use Ajax especially it is more resource intensive. I wish, I had
attended Selinium track because I caught last few minutes and it seemed
pretty useful.

Second session was Just the Facts (and Dimensions) — using Rails with your OLAP data model by
Ken Kunz. It was slighly useful talk, but I didn’t learn a whole a lot.

Third session was
Using Ruby on Rails to Succeed in Selling Music in the 21st Century
by
Benjamin Curtis. It was
by far the best session of the conference and I got a lot of practical
information on eCommerce. Though, I have been working for a very
lage eCommerce, but you don’t always get to see all areas. He also
has a book called “Money Train”, though I saw it only had 18 pages. This
is one area that I have not found a lot of information in books and
tutorials so it might be worth buying it.

Then I attended Deploying Rails Applications by
James Duncan Davidson
. Clearly, deployment has been more complicated
piece of Rails development and there aren’t any clean solutions available.
So, there was good discussion of using Apache/FastCGI, Lighttpd+fcgi. He
recommended Capistrano and start small. He also suggested RSS/Campfire to
keep track of deployment notifications. He also cautioned with log files,
database sockets (firewall), file permissions (public directory). The other
solution as few other people mentioned is Mongrel. It also reminded me of proxy servers and reverse proxy servers I used
in a number of projects and helped setup in some consulting gigs (and
a number of ugly issues along with it [keep-alive] ). I was surprised he
ended the talk with using “Container” to tackle these deployment issues.
Does this mean that Rails will turn into J2EE?

Final thoughts: I found this conference to be not very well organized and
simple things like lack of slides or Internet were also bothersome. Also,
there were no birds of a feather sessions.
I found most of the speakers were not experienced and many of top level
leaders of Rails such as DHH, Dave Thomas,
Chad Fowler, David Black didn’t have any sessions. The only exceptions
were Mike Clark, James Duncan Davidson and Justin Getland and except Justin,
the talks of Mike Clark and JDD were very high level (sort of like keynotes).
Though, I would not had minded expertise of speakers (if they had good
practical sessions), but I found many of those sessions were vaporware
as a number of them had much higher agendas in their talk summaries, but
speakers could not finish the APIs, demo, research or work needed.
So, overall I found the conference useful, but it didn’t meet expectations
It was sort of brown bags, but didn’t have high calibre
speakers like other conference. Also, I am not sure why they didn’t bother
inviting Bruce Tate or Jim Weirich.

Since boom of Ruby/Rails, I find that biggest beneficiaries of all this
revolution have been either 37signals, Dave Thomas (et al), Thoughtworks and a
number of other startups, book publishers and trainers. I have bought almost
all of Ruby/Rails books of Pragmatic series (along with other) and in
this conference I heard a number of upcoming books from their series
(and yes I will buy their books as well).
Also, Dave Thomas, Mike Clark and Chad Fowler have pretty good
training program going where they charge about $1800 for 3-day class (but
they didn’t offer any short sessions from their training program). So,
clearly there is a lot of money in it for all these people, but, I
hope some of this
windfall goes to Yukihiro Matz Matsumoto, the guy behind all this.

Another observation, I found that 90% of people at conference used Mac
and a I few people were giving away non-conformity certificate. Here is
mine:

or visit flicker
for this. You can also view other pictures at
See pictures from Rails
conference
.

June 25, 2006

RailsConf 2006 Day 2

Filed under: Computing — admin @ 5:27 pm

RailsConf 2006 Day 2
I started today with Ajax on Rails by Justin Gehtland. It was excellent talk, though most of it was nothing new. But Justin
gave demo of his upcoming project Streamlined that has scaffold to create views and has builtin
filter and allows managing relationships. It’s going to be very exciting
framework.

I then sat on Lessons from Blinksale and IconBuffet by Scott Raymond. Scott has worked as Rails contractor and he started
with a bit history of Vitruvius and described three tenants of architecture, i.e., firmitas (firmness), utilitas (usefulness) and venustas (beauty/delight). He presented a
number of interesting lessons such as starting project with templates,
mocking templates and then incrementally adding functionality with
very closed loop. He also emphasized testing markups before adding any
code.

Third session, I saw was Putting the BBC’s Programme Catalogue on Rails by Matt Biddulph. That talk was not as good
as I expected, I was hoping to get more practical information on
managing large database, but most of the talk covered history of BBC.
Also, I was shocked that he used ActiveRecord to migrate 2Gig data from
old database from legacy database to mysql. Clearly, an SQL script is
more suitable for such (I guess I would have used stored procedure,
but I am not sure which version of MySQL he used). He admitted, 99%
of database load was spent in creating ActiveRecords.

Then I attended an excellent talk on Rails Deployment by Ezra Zygmuntowicz. He showed a lot of practical tips on deploying
applications such as Apache/FastCGI, Lighttpd, Mongrel. A lot of tips
were from his article Rails Stack. He also plugged his upcoming Pragmatic book on Rails deployment.
Though, his talk summary included BackgrounDRb, but he didn’t talk
about it. Anyway, I look forward to his book.

I then attended talk on Testing Migrations by Glenn Vanderburg. There was a lot of good information on testing
migrations, though a lot of his approaches are still half-baked.

My last talk was by Mike Clark on
Testing Rails Apps
. I didn’t get much new from his talk, it pretty much boiled to:
Rails/Rake has excellent support for testing such as unit, integration,
functional, features and mocks. I don’t understand, why people still
inviting people to use TDD in conferences. By now, most develoeprs
understand benefits of TDD. I would be more interested in new support of
TDD in Rails or tackling difficults issues of testing. For example, I found a couple of articles of
Bruce Tate on Functiona/Integration testing much more useful, but Mike Clark’s
session was very high level sort of like keynote.

Finally, I could not connect to Internet for whole day. I don’t understand,
why RailsConf/Wyndham hotel has such poor Wifi support. My laptop connected to Wifi,
but never could get IP address from DHCP server. And one more thing,
I was forced to pay $50.0 for slides/audio sessions. I wish that was
available freely as we already paid for the conference.

June 23, 2006

RailsConf 2006 Day 1

Filed under: Computing — admin @ 8:24 pm

RailsConf 2006 Day 1
I finally was able to find tickets for RailsConf 2006 in Chicago. Though,
I could not find tickets back in Feb., but I managed to find someone who
could not make it. Anyway, I missed most of sessions due to work, but I
was able to checkout “Rails Application Optimization – Techniques and Tools” by Stefan Kaes.
It was excellent talk on profiling Rails applications and improving
performance. He also posted most of tips at A Look at Common Performance Problems in Rails about 1-2 weeks ago. Though, I am disappointed most of tips encourage
bypassing rails framework. I think we need to tackle these problems
at language and framework level and not go around and write ugly hacks.
This also shows that Rails is not really ready for real businesses despite
such claims by rails community.

Second session I attended was Rails Deployment on Shared Hosts by Geoffrey Grosenbach. It was big disappointed, if he only had said “Don’t use shared hosts”, that would have saved me an hour.

I also enjoyed Martin Fowler’s keynote. He admitted, he has never
used Rails, but he is an avid proponent of Ruby. He basically ravished
design principles of Rails, i.e., opinionated software, simplicity,
quick and clean setup (which encourages agile dev. — tracer bullet — fire/aim/fire/aim). He talked about postmodern programming which was interesting. It just means that world isn’t perfect so languages or frameworks that
try to think nothing exist outside their world fails. Clearly, Ruby has
clean design and has a lot of influence from Lisp/Smalltalk, but it also
takes tips from Perl and Python by integrating with other languages and
external environment.

Finally, I found this conference not very well organized. For example,
for popular sessions, there weren’t enough seats and people had to stand
in the doorways. Also, there are no slides handout or conference proceeding.
Worst, organizers are going to charge $50.0 for session slides and audio.
At very least, slides should have made freely available.

June 16, 2006

Integrating ActiveMQ with JBoss

Filed under: Computing — admin @ 8:49 am

Integrating ActiveMQ with JBoss
Recently, I had to integrate ActiveMQ 4 with JBoss 4
Here is how I did it:

Download and install JBoss 4.0.4

set JBOSS_HOME environment variable to point to installation directory of JBoss.

Download and install ActiveMQ 4.0

set ACTIVEMQ_HOME environment variable to point to installation directory of ActiveMQ.

Copy ActiveMQ JCA (rar) file to JBoss’s deploy directory, e.g.

cp $ACTIVEMQ_HOME/lib/optional/optional/activemq-ra-4.0-RC2.rar $JBOSS_HOME/server/all/deploy

Start Active MQ Server

cd $ACTIVEMQ_HOME/bin
sh activemq

Start JBoss Server

cd $JBOSS_HOME
sh bin/run.sh -c all
You need to keep the window open as you will see some debug messages on the console.

Create a folder for all source code, e.g.

mkdir mdbtest
cd mdbtest

Create a source, build and META-INF folder, e.g.

mkdir src
mkdir build
mkdir build/META-INF

Create a source package directory for Message-Driven Bean and Client

mkdir src/mdb
mkdir src/publisher

Define Message Driven Bean, in src/mdb/TestMessageBean.java e.g.

 1  package mdb;
 2  import java.io.PrintStream;
 3  import java.rmi.RemoteException;
 4  import java.util.Hashtable;
 5  import java.util.Properties;
 6  import javax.ejb.CreateException;
 7  import javax.ejb.MessageDrivenBean;
 8  import javax.ejb.MessageDrivenContext;
 9  import javax.jms.JMSException;
10  import javax.jms.Message;
11  import javax.jms.MessageListener;
12  import javax.jms.TextMessage;
13  import javax.naming.InitialContext;
14  import javax.naming.NamingException;
15  import javax.rmi.PortableRemoteObject;
16  import org.apache.commons.logging.Log;
17  import org.apache.commons.logging.LogFactory;
18 
19  /**
20   * @ejb.bean name="TestMessageEJB"
21   */
22  public class TestMessageBean implements MessageDrivenBean, MessageListener {
23    public TestMessageBean() {
24    }
25    public void onMessage(Message message)  {
26      try {
27        TextMessage textMessage = (TextMessage) message;
28        System.out.println(">>>Received " + textMessage.getText());
29      } catch (Exception e) {
30        e.printStackTrace();
31      }
32    }
33 
34    public void ejbRemove() {
35    }
36 
37    public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) {
38    }
39 
40    public void ejbCreate() {
41    }
42  }

Define Client Publisher in src/client/Publisher.java, e.g.

 1  package client;
 2  import java.io.PrintStream;
 3  import java.util.Properties;
 4  import javax.jms.ConnectionFactory;
 5  import javax.jms.JMSException;
 6  import javax.jms.Message;
 7  import javax.jms.Session;
 8  import javax.jms.TextMessage;
 9  import javax.naming.InitialContext;
10  import javax.rmi.PortableRemoteObject;
11  import org.apache.activemq.ActiveMQConnectionFactory;
12  import org.springframework.jms.core.JmsTemplate;
13  import org.springframework.jms.core.MessageCreator;
14 
15  public class Publisher {
16    private static final String URL = "tcp://localhost:61616";
17    private static final String DEST = "destQ";
18    private static final boolean topic = false;
19    public static void main(String[] args) throws Exception {
20      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
21      connectionFactory.setBrokerURL(URL);
22      JmsTemplate jt = new JmsTemplate(connectionFactory);
23      if (topic) jt.setPubSubDomain(true);
24      jt.send( DEST, new MessageCreator() {
25        public Message createMessage(Session session) throws JMSException {
26          Message m = session.createTextMessage("hello world");
27            m.setIntProperty("add_id", id);
28           return m;
29          }
30        }
31       );
32    }
33  }

Define META-INF/ejb-jar.xml as follows:

 <?xml version="1.0" encoding="US-ASCII"?>

 <ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"
    version="2.1">

    <description> Test ActiveMQ </description>

    <enterprise-beans>
       <message-driven>
          <description>TestMDB</description>
          <ejb-name>TestMessageEJB</ejb-name>
          <ejb-class>mdb.TestMessageBean</ejb-class>
          <messaging-type>javax.jms.MessageListener</messaging-type>
          <transaction-type>Container</transaction-type>
          <activation-config>
             <activation-config-property>
                <activation-config-property-name>destination</activation-config-property-name>
                <activation-config-property-value>destQ</activation-config-property-value>
             </activation-config-property>
             <activation-config-property>
                <activation-config-property-name>destinationType</activation-config-property-name>
                <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
             </activation-config-property>
             <activation-config-property>
                <activation-config-property-name>acknowledgeMode</activation-config-property-name>
                <activation-config-property-value>Auto-acknowledge</activation-config-property-value>
             </activation-config-property>
             <activation-config-property>
                <activation-config-property-name>messageSelector</activation-config-property-name>
                <activation-config-property-value/>
             </activation-config-property>
          </activation-config>
       </message-driven>
    </enterprise-beans>
    <assembly-descriptor>
      <security-role>
         <description>Open</description>
         <role-name>everyone</role-name>
      </security-role>
      <method-permission>
         <role-name>everyone</role-name>
         <method>
           <ejb-name>TestMessageEJB</ejb-name>
           <method-name>*</method-name>
         </method>
      </method-permission>
      <container-transaction>
        <method>
          <ejb-name>TestMessageEJB</ejb-name>
          <method-name>*</method-name>
        </method>
        <trans-attribute>Required</trans-attribute>
      </container-transaction>

       <message-destination>
          <message-destination-name>jbossQ</message-destination-name>
       </message-destination>
    </assembly-descriptor>
 </ejb-jar>
Define META-INF/jboss.xml as follows:

 <?xml version="1.0" encoding="UTF-8"?>
   <!DOCTYPE jboss PUBLIC
       "-//JBoss//DTD JBOSS 4.0//EN"
       "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd">
   <jboss>
      <jmx-name>activemq.rar:name=iTests</jmx-name>
      <enterprise-beans>
        <message-driven>
          <ejb-name>TestMessageEJB</ejb-name>
          <resource-adapter-name>activemq-ra-4.0.rar</resource-adapter-name>
          <configuration-name>ActiveMQ Message Driven Bean</configuration-name>
        </message-driven>
      </enterprise-beans>
      <assembly-descriptor>
         <message-destination>
          <message-destination-name>jbossQ</message-destination-name>
          <jndi-name>activemq/queue/outbound</jndi-name>
         </message-destination>
      </assembly-descriptor>
      <resource-managers>
         <resource-manager>
            <res-name>queuefactoryref</res-name>
            <res-jndi-name>java:/activemq/QueueConnectionFactory</res-jndi-name>
         </resource-manager>
         <resource-manager>
            <res-name>topicfactoryref</res-name>
            <res-jndi-name>java:/activemq/TopicConnectionFactory</res-jndi-name>
         </resource-manager>
      </resource-managers>

      <invoker-proxy-bindings>
         <invoker-proxy-binding>
            <name>activemq-message-driven-bean</name>
            <invoker-mbean>default</invoker-mbean>
            <proxy-factory>org.jboss.ejb.plugins.inflow.JBossMessageEndpointFactory</proxy-factory>
            <proxy-factory-config>
              <endpoint-interceptors>
                <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor>
                <interceptor>org.jboss.ejb.plugins.inflow.MessageEndpointInterceptor</interceptor>
                <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
                <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>
             </endpoint-interceptors>
           </proxy-factory-config>
         </invoker-proxy-binding>
      </invoker-proxy-bindings>

      <container-configurations>
         <container-configuration>
            <container-name>ActiveMQ Message Driven Bean</container-name>
            <call-logging>false</call-logging>
            <invoker-proxy-binding-name>activemq-message-driven-bean</invoker-proxy-binding-name>
            <container-interceptors>
               <interceptor>org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor</interceptor>
               <interceptor>org.jboss.ejb.plugins.LogInterceptor</interceptor>
               <interceptor>org.jboss.ejb.plugins.RunAsSecurityInterceptor</interceptor>
               <!-- CMT -->
               <interceptor transaction="Container">org.jboss.ejb.plugins.TxInterceptorCMT</interceptor>
               <interceptor transaction="Container">org.jboss.ejb.plugins.CallValidationInterceptor</interceptor>
               <interceptor transaction="Container" metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>
               <interceptor transaction="Container">org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor</interceptor>
               <!-- BMT -->
               <interceptor transaction="Bean">org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor</interceptor>
               <interceptor transaction="Bean">org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMT</interceptor>
               <interceptor transaction="Bean">org.jboss.ejb.plugins.CallValidationInterceptor</interceptor>
               <interceptor transaction="Bean" metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptor</interceptor>
               <interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptor</interceptor>
            </container-interceptors>
            <instance-pool>org.jboss.ejb.plugins.MessageDrivenInstancePool</instance-pool>
            <instance-cache></instance-cache>
            <persistence-manager></persistence-manager>
            <container-pool-conf>
             <MaximumSize>100</MaximumSize>
            </container-pool-conf>
         </container-configuration>
      </container-configurations>
 </jboss>
Define activemq-jms-ds.xml in JBoss’s deployment directory as follows:


 <?xml version="1.0" encoding="UTF-8"?>

 <!DOCTYPE connection-factories
     PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
     "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">

 <connection-factories>

    <tx-connection-factory>
       <jndi-name>activemq/QueueConnectionFactory</jndi-name>
       <xa-transaction/>
       <track-connection-by-tx/> <!-- Thanks to Adrian Brock for pointing this one out! -->
       <rar-name>activemq-ra-4.0.rar</rar-name>
       <connection-definition>javax.jms.QueueConnectionFactory</connection-definition>
       <security-domain-and-application>JmsXARealm</security-domain-and-application>
    </tx-connection-factory>

    <tx-connection-factory>
       <jndi-name>activemq/TopicConnectionFactory</jndi-name>
       <xa-transaction/>
       <track-connection-by-tx/> <!-- Thanks to Adrian Brock for pointing this one out too! -->
       <rar-name>activemq-ra-4.0.rar</rar-name>
       <connection-definition>javax.jms.TopicConnectionFactory</connection-definition>
       <security-domain-and-application>JmsXARealm</security-domain-and-application>
    </tx-connection-factory>

    <!--
    <mbean code="org.jboss.resource.deployment.AdminObject" name="activemq.topic:name=topicSearchRequest">
       <attribute name="JNDIName">topic/search.request</attribute>
       <depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name='activemq-ra-4.0.rar'</depends>
       <attribute name="Type">javax.jms.Topic</attribute>
       <attribute name="Properties">PhysicalName=topic.search.request</attribute>
    </mbean>

    <mbean code="org.jboss.resource.deployment.AdminObject" name="activemq.topic:name=topicSearchResponse">
       <attribute name="JNDIName">topic/search.response</attribute>
       <depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name='activemq-ra-4.0.rar'</depends>
       <attribute name="Type">javax.jms.Topic</attribute>
       <attribute name="Properties">PhysicalName=topic.search.response</attribute>
    </mbean>
    -->

 </connection-factories>
Compile your code as follows:

javac -d build -classpath $JBOSS_HOME/server/all/lib/jboss-j2ee.jar:$ACTIVEMQ_HOME/lib/optional/spring-1.2.4.jar:\
$ACTIVEMQ_HOME/lib/optional/activemq-optional-4.0.jar:$ACTIVEMQ_HOME/lib/activeio-core-3.0.jar:\
$ACTIVEMQ_HOME/lib/activemq-core-4.0.jar:$ACTIVEMQ_HOME/lib/activemq-console-4.0.jar src/*/*java

Package EJB as follows:

jar -C build -cf mdbtest.jar *

Deploy EJB as follows:

cp mdbtest.jar $JBOSS_HOME/server/all/deploy

Verify that EJB was deployed successfully in JBoss console logs
Run publisher as follows:

java -classpath build:$JBOSS_HOME/server/all/lib/jboss-j2ee.jar:$ACTIVEMQ_HOME/lib/optional/spring-1.2.4.jar:\
$ACTIVEMQ_HOME/lib/optional/activemq-optional-4.0.jar:$ACTIVEMQ_HOME/lib/activeio-core-3.0.jar:\
$ACTIVEMQ_HOME/lib/activemq-core-4.0.jar:$ACTIVEMQ_HOME/lib/activemq-console-4.0.jar client.Publisher

Verify debug message on the JBoss Console
Voila

(Note that you could use xdoclet and ant script, but I tried to focus on integration here)

See inbound-communication.html

See outbound-communication

June 13, 2006

Agile Purists

Filed under: Computing — admin @ 9:26 am

Agile Purists
I find a number of software concepts have religious following where a passionate
leader can find a lot of followers even when the ideas are not very sound or
have limited application. There are number of examples like OO, agile
methodologies, dynamic languages, microsoft, etc. In a number of cases
purists ignore real world or refuse to have a dialog with opposite side.

I read post of Cedric Beust, in which he raised interesting points about :

  • Tests are (executable) specs.
  • If it’s not testable, it’s useless.

I have been thinking about these as well and I agree that these purists have
not seen most of the code in real world. Working for a large eCommerce site
with millions of lines of code, I understand that you cannot expect 100%
coverage. Though, personally I like writing tests and have even wrote a
framework TestPlayer that sniffs
legacy applications and automatically generate:

  • Unit Tests with Mocks using jMock, JUnit 3.8.1, JUnit 4.0 and TestNG 4.0
  • Integration Tests using JUnit 3.8.1, JUnit 4.0 and TestNG 4.0
  • Acceptance Tests using FitNesse
  • Stress/Load Tests

The very fact that leader of TDD, Kent Beck works for a company that writes
tools for exploratory testing (though I am skeptical about it) shows that
having 100% coverage is unrealistic. In my experience I have found that 100%
coverage takes about 2-3 times the time that it takes to write the software
and in some cases up to 4 times. This is where Cedric recommends risk based
approach. I also read reply of Uncle Bob where he suggests
“Either make sure it works, or don’t ship it. Period.” Again such hard nose
attitude shows little experience with real life code. This tells me that
unless you don’t have 100% coverage, dont’ ship your software. Yet, with
over fifteen years of industry experience I have never seen this actually
worked. I see buggy code released all the time, it’s just matter of risk
factor, i.e., you ship the software as long as there aren’t any serious bugs.
Also, when agilists talk about TDD they mean unit tests with mocks, but
in real world you also need integrations tests to test against real
services and load tests to make sure that you don’t have any unexpected
performance problems when the software is shipped. Also, for any online
software, it is also important to do security testing or penetration testing.
However, later three get
very little attention. In fact, in order to cover all facets, you need to start
with acceptance test (using Fit/FitNesse), then unit tests and followed by
integration/performance/security tests. Clearly, you need to balance all
this and focus on high risk components of your software or your software
may never ship if you stick to 100% coverage.
Finally, despite what you think 100% coverage does not mean elimination of
your QA department, it’s just that they will be doing a lot more exploratory
testing.

The second point about using tests as specs is equally unrealistic. For any
one who has worked with over 500 developers and millions of lines of code, you
can’t expect anyone to understand software by reading tests. In fact, I had to
learn a number of commercial and open source software where developers had
same attitude that just read the code or tests (if you are lucky) and
though with enough time you can understand
the software by reading code and tests, but with good brief documentation it
can be done much faster. Also, in many cases code or tests don’t tell show
why that code is there. In many cases, there could be more than one way to
do things, without documentation it is hard to see which way is preferred under
what conditions.

Though, I like TDD and Agile methodologies specially their emphasis on
people and collaboration over processes and technology, but each team
and each project is different. It is time that agilists stop proposing
prescriptive methodologies. In the end, agility means how fast you respond
to change and reduce time to market.

Powered by WordPress