📜 ⬆️ ⬇️

Code Generation Approaches

In the previous article, we looked at how code generation is applied in real products.
In this article we will look at how some approaches to code generation can make life easier for us.

Code Generation


Code generation is the process of generating code from specific data.

I would like to highlight some areas:

Higher-level code generation


This approach allows us to get on the basis of a simple, intuitive code - code of a lower level. This approach helps to preserve abstraction. The language in which the source code is written may not coincide with the language of the code that will be generated.
')
For example, we write a site in some kind of our own language. And on the server we have PHP. Let's see what kind of generation is theoretically possible.
user = Users.find (5);
user.lastActivity = DateTime.Now;
user.save ();

We configured the site to use MySQL and can get similar code at the output:
$ user_query = mysql_query ( 'SELECT * FROM `users` WHERE` id` = 5' , $ mysql_connection );
$ user = mysql_fetch_assoc ( $ user_query );
mysql_query ( 'UPDATE `users` SET` lastActivity` =' .time (). 'WHERE `id` =' . $ page [ 'id' ], $ mysql_connection );

And if the code generator is smart, then it can generate something like this:
mysql_query ( 'UPDATE `users` SET` lastActivity` =' .time (). 'WHERE `id` = 5' , $ mysql_connection );

Suddenly we decided not to use MySQL, but to use, for example, direct writing to files, the code could be like this:
$ user_list = unserialize (file_get_contents ( 'users.txt' ));
foreach ( $ user_list as $ current_user )
{
if ( $ current_user -> id == 5 )
{
$ user = $ current_user ;
break ;
}
}
$ user -> lastActivity = time ();
file_put_contents ( 'users.txt' , serialize ( $ user_list ));


One more example. We write in our language:
deletedRowsCount = query: delete from myTable where id> 5;

In the case of MySQL, we could get this code:
$ query = mysql_query ( 'DELETE FROM `myTable` WHERE` id`> 5' , $ mysql_connection );
$ deletedRowsCount = mysql_affected_rows ( $ mysql_connection );

In the case of using files, we could get this code:
$ deletedRowsCount = 0 ;
$ myTable_list = unserialize (file_get_contents ( 'myTable.txt' ));
foreach ( $ myTable_list as $ key_myTable => $ current_myTable )
{
if ( $ current_myTable -> id> 5 )
{
unset ( $ myTable_list [ $ key_myTable ]);
$ deletedRowsCount ++;
}
}
file_put_contents ( 'myTable.txt' , serialize ( $ myTable_list ));


Code examples are not perfect, but they cope with the task of demonstrating code generation.

I also want to give an example of the work of a real code generator operating on this principle. This is the LINQ code generator.

Source:
byte [] source = new byte [] { 1 , 5 , 7 , 4 , 3 , 9 , 8 , 2 , 6 };
var dest = from n in source where n> 5 select n;


Result code:
IEnumerable < byte > dest = Enumerable. Where < byte > ( new byte [] { 1 , 5 , 7 , 4 , 3 , 9 , 8 , 2 , 6 }, new CS $ <> 9__CachedAnonymousMethodDelegate1 (Main_b__0));

The delegate is also generated:
[ CompilerGenerated ]
private static Func < byte , bool > CS $ <> 9__CachedAnonymousMethodDelegate1 ;

And method:
[ CompilerGenerated ]
private static bool Main_b__0 ( byte n)
{
return (n> 5 );
}


Metadata Generation


This approach allows us to create code for working with data based on the description of the data structure (metadata). For example, we have a MySQL database. I want to generate entities to work with the database. The most simple data on the structure of the database is easy to obtain:
show tables;
+---------------+
| Tables_in_gen |
+---------------+
| users |
+---------------+

describe users;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(100) | YES | | NULL | |
+-------+--------------+------+-----+---------+----------------+

From this, you can generate a primitive user information storage class.
class User
{
public $ id ;
public $ name ;
}


If you think about it, you can still implement the methods select, update, insert, delete. In the future, we will encounter similar code generators and even consider developing such.

Pattern based code generation


This is one of the simple and everyday approaches to code generation. An example of such a system is Smarty. This system is mainly used to generate HTML code based on templates. During the experiments, I generated PHP and C # code.

For example, we have in a certain source $ source a list of fields is stored and we need to make a class with properties based on them.

The template can be taken as follows:
class MyClass
{
{{foreach from = $ source item = name}}
public $ {{$ name}} ;
{{/ foreach}}
}

And with $ source = array ( 'width' , 'height' , 'name' ) we get:
class MyClass
{
public $ width ;
public $ height ;
public $ name ;
}


In the next article, we will look at how complexity can be controlled using code generation.

Source: https://habr.com/ru/post/23858/


All Articles