Friday, June 21, 2024

Old School Code Generation, Combined with the New

 While Generative AI can help with some problems, what if you want to generate a lot of code consistently? The Telosys code generator might be the right tool. Let's take a look at templates for a Spring Boot application with some help from deepseek-coder:6.7b and starcoder2:3b.


DeepSeek

Prompt: Write a velocity template for the telosys code generator to create a java record

#set( $className = $entityName )
#set( $package = "com.example" )

import java.time.*;

public record ${className}(
    #foreach($field in $fields)
        #if($field.type == 'DATETIME')
            ${field.name} LocalDateTime,
        #elseif($field.type == 'DATE')
            ${field.name} LocalDate,
        #else
            ${field.name} ${field.javaType},
        #end
    #end    
) { }

It also supplied the usual support text with additional information (not shown).
The basic syntax is reasonable (error with a comma at the end, the types are in the wrong place, missing java time in javaType) and roughly matches a manually created version.
 
Here is a manually created version for comparison:
 
package ${target.javaPackageFromFolder(${SRC})};

#foreach( $import in $java.imports($entity) )
import $import;
#end

public record ${entity.name}(#foreach( $attribute in $entity.attributes )
$attribute.type $attribute.name#if( $foreach.hasNext ), #end
#end) {}



StarCoder

The code gets more interesting once a function is created. Once a select query is created in the repository, starcoder2:3b can use that information to auto generate the rest.

    private static final String insertSql = """
          insert into ${entity} (
#foreach( $column in $entity.sqlColumns  )
           #if( $foreach.index!= 0 ),#else,#end ${column}
#end
          ) values (
#foreach( $column in $entity.sqlColumns  )
           #if( $foreach.index == 1 ),#else,#end :${column}
#end
          );
         """;
    
    private static final String updateSql = """
          update ${entity} set
#foreach( $column in $entity.sqlColumns  )
           #if( $foreach.index!= 0 ),#else,#end ${column} = :${column}
#end
          where 1=1;
         """;
    
    private static final String deleteSql = """
          delete from ${entity} where 1=1;
         """;


The original manual version used entity.sqlColumns. It might make sense to spend extra time getting the first function in a class right to get a slightly closer-to-being-correct version of the rest of the code.

The Template

The full template that creates a service side application with select/insert/update code from an existing database is available on github. The generated code is available on the generated branch. Including the prompts that were used.

Conclusion


DeepSeek can be useful for general syntax and StarCoder helpful for adding code inline. For consistent, generated code, Telosys is very good.