The Problem With Generated Code (rant)
Code Generators are great! I picked up my imaginary suitcases and walked from the Sinatra (Ruby) and Flask (Python) microframeworks to the Ruby on Rails ecosystem because Rails could generate a complete user interface, aware of the relationship between models with a slight modification to the template. And being able to generate a config file with defaults for most add-on gems for Rails makes it that much better.
However, generated code is often ugly when it tries to do too much. Assume you are a newbie and you look at the controller code from scaffolding in Ruby on Rails:
# PATCH/PUT /movies/1 or /movies/1.json
def update
respond_to do |format|
if @movie.update(movie_params)
format.html { redirect_to movie_url(@movie), notice: "Movie was successfully updated." }
format.json { render :show, status: :ok, location: @movie }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @movie.errors, status: :unprocessable_entity }
end
end
end
If you are new to Ruby and the Rails framework, that atrocity is incomprehensible.
Let’s take another example: https://curlconverter.com/ruby/
I did a quick Google search to find “curl Kafka connect” and I find a Gist with the command:
curl -X POST \
http://localhost:8083/connectors \
-H 'Content-Type: application/json' \
-d '{ "name": "cosmosdb-sink",
"config":
{
"topics":"blogpost",
"connector.class":"at.grahsl.kafka.connect.mongodb.MongoDbSinkConnector",
"key.converter":"org.apache.kafka.connect.json.JsonConverter",
"key.converter.schemas.enable":false,
"value.converter":"org.apache.kafka.connect.json.JsonConverter",
"value.converter.schemas.enable":false,
"mongodb.connection.uri": "<PUT_YOUR_CONNECTION_STRING_HERE_AND_ADD_DATABASE_NAME>",
"mongodb.collection": "blogpost"
}
}
'
I then take this and put it into the code generator to get:
require 'net/http'
require 'json'
uri = URI('http://localhost:8083/connectors')
req = Net::HTTP::Post.new(uri)
req.content_type = 'application/json'
# The object won't be serialized exactly like this
# req.body = "{ \"name\": \"cosmosdb-sink\",\n \"config\":\n {\n \"topics\":\"blogpost\",\n \"connector.class\":\"at.grahsl.kafka.connect.mongodb.MongoDbSinkConnector\",\n \"key.converter\":\"org.apache.kafka.connect.json.JsonConverter\",\n \"key.converter.schemas.enable\":false,\n \"value.converter\":\"org.apache.kafka.connect.json.JsonConverter\",\n \"value.converter.schemas.enable\":false,\n \"mongodb.connection.uri\": \"<PUT_YOUR_CONNECTION_STRING_HERE_AND_ADD_DATABASE_NAME>\",\n \"mongodb.collection\": \"blogpost\"\n }\n}\n"
req.body = {
'name' => 'cosmosdb-sink',
'config' => {
'topics' => 'blogpost',
'connector.class' => 'at.grahsl.kafka.connect.mongodb.MongoDbSinkConnector',
'key.converter' => 'org.apache.kafka.connect.json.JsonConverter',
'key.converter.schemas.enable' => false,
'value.converter' => 'org.apache.kafka.connect.json.JsonConverter',
'value.converter.schemas.enable' => false,
'mongodb.connection.uri' => '<PUT_YOUR_CONNECTION_STRING_HERE_AND_ADD_DATABASE_NAME>',
'mongodb.collection' => 'blogpost'
}
}.to_json
req_options = {
use_ssl: uri.scheme == 'https'
}
res = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(req)
end
The code is very similar to what I see from curl-to-ruby so it’s probable (but I cannot say with any kind of certainty) they are using the same library for the conversion.
Notice how toward the end they specify the use of HTTPS (SSL), which the original curl command did not specify because the author of the code generator thought it would make the generated application code more secure. And they try to accomplish whatever they can with Ruby built-in functionality. If it were human-coded, you might see the use of the faraday gem to possibly make the code cleaner and easier to read.
Yes, you can find the template for the code generator and modify it to give you any kind of code, but how many people actually change the templates? Even for my use case of using Rails scaffolding, most people don’t edit the templates and build the code files that are generated.