středa 22. dubna 2009

Do pranice: malé samopopisující versus velké okomentované

Během code review jsem se začetl do knihy Refactoring od Martina Fowlera a musím říci, že jeho styl programování se mi velice líbí. Jde o přístup k tomu jaký volí zápis metod a využívání extract method. Obvykle co vidím nejen sám u sebe je přístup delší metody s vloženými komentáři (pokuď vůbec) co daná část metody dělá.

public Configuration getConfiguration() {

    // load the driver (supplied to installer) using custom classloader
    try {
        if (driverClass != null) {
            loadDriver(driverClass, dbDrivers);
        }
    catch (ClassNotFoundException e) {
        throw new ConfigurationException(e);
    }

    // configure datasource
    BasicDataSource dataSource = new BasicDataSource();
    // Do not set the class name, becuase the datasource calls
    // Class.forName only in the systemclassloader where the driver
    // is not present.    
    // dataSource.setDriverClassName(driverClass);
    dataSource.setUrl(connectionURL);
    dataSource.setUsername(userName);
    dataSource.setPassword(password);
    dataSource.setInitialSize(1);
    dataSource.setMaxActive(15);
    dataSource.setDefaultAutoCommit(true);

    // create configuration instance
    Factory scopes = ScopeFactory.getInstance();
    Configuration cfg = new Configuration(scopes);
    cfg.setDataSource(dataSource);

    return cfg;
}
Java2html

Podle Fowlerova receptu by mohl kód po refaktoru vypadat následovně.

public Configuration getConfiguration() {
    loadDriverInCustomClassloader();     
    BasicDataSource dataSource = configureDataSource();    
    return createConfigurationInstance(dataSource);
}

protected void loadDriverInCustomClassloader() {    
    try {
        if (driverClass != null) {
            loadDriver(driverClass, dbDrivers);
        }
    catch (ClassNotFoundException e) {
        throw new ConfigurationException(e);
    }
}

protected BasicDataSource configureDataSource() {
    BasicDataSource dataSource = new BasicDataSource();
    // Do not set the class name, becuase the datasource calls
    // Class.forName only in the systemclassloader where the driver
    // is not present.    
    // dataSource.setDriverClassName(driverClass);
    dataSource.setUrl(connectionURL);
    dataSource.setUsername(userName);
    dataSource.setPassword(password);
    dataSource.setInitialSize(1);
    dataSource.setMaxActive(15);
    dataSource.setDefaultAutoCommit(true);
}

protected Configuration createConfigurationInstance(BasicDataSource dataSource) {    
    Factory scopes = ScopeFactory.getInstance();
    Configuration cfg = new Configuration(scopes);
    cfg.setDataSource(dataSource);
    return cfg;
}
Java2html

Fowler uvádí tři základní důvody pro tento přístup.

  • lepší znovupoužitelnost metod uvnitř třídy pokud jsou jemnější
  • snazší překrytí v potomkovi
  • lepší čitelnost, větší metody se čtou jako série komentářů

Mě osobně přijde jako nejrelevantnější poslední bod, tedy čitelnost vlastního kódu. Na příkladu, který jsem uvedl, to ještě možná tak nevypadá, ale pokud se metody táhnou jak špagety, tak mi to přijde jako ideální přístup pro zlepšení čitelnosti a tím pádem kvality kódu.