官术网_书友最值得收藏!

Code Generation

There are, in many applications, plenty of features that are trivial to implement but must be done over and over. Perhaps it's taking an array of model objects and preparing a list view, creating classes from database schemata, or creating a list of compile-time constants from a text file.

These situations can usually be automated by generating code. The idea is to express the problem in a succinct representation, then translate that into something that can be incorporated into your program. This is pretty much what a compiler does; though many programming languages are far from succinct, they're still much less unwieldy than the machine's native instruction code.

Writing Your Own Generator Shouldn't Be A First Resort

Just as a code generator makes it easier to create a product, it makes it harder to debug. For a concrete example, consider the autotools build system discussed earlier in this chapter. Imagine that a developer is looking into a reported problem in which one of the tests fails (a problem that I had to deal with today). The log file tells them what the C program was that encapsulated the test, but the developer cannot just modify that program. They must discover where the configure script is generating that program, and what it's trying to achieve by doing so. They must then find out where in configure.ac that section of the shell script is generated and work out a change to the m4 macros that will result in the desired change to the C program, two steps later.

In short, if your target environment offers facilities to solve your problem natively, such a solution will require less reverse engineering when diagnosing later problems. It's only if such a solution is overly expensive or error-prone that code generation is a reasonable alternative.

Many of the cases given at the beginning of this section were data-driven, like the situation deriving class descriptions from a database schema for some Object-Relational Mapping (ORM) system. This is a case where some programming languages give you the ability to solve this problem without generating code in their language. If you can resolve messages sent to an object at runtime, then you can tell that object which table its object is in and it can decide whether any message corresponds to a column in that table. If you can add classes and methods at runtime, then you can generate all of the ORM classes when the app connects to the database.

The existence and applicability of such features depends very much on the environment you're targeting but look for and consider them before diving into writing a generator.

When the Generator Won't Be Used by A Programmer

If the target "customer" for this facility isn't going to be another developer, then a generator can often be a better choice than a full-featured programming language, despite the increase in implementation complexity.

A solution that's often explored in this context is a Domain-Specific Language (DSL), a very limited programming language that exposes grammar and features much closer to the problem that the customer understands than to computer science concepts. Many projects that I've been involved with have used DSLs, because they offer a nice trade-off between letting the customer modify the system as they see fit and avoiding complex configuration mechanisms.

Case study

The "customer" using the application doesn't need to be the end user of the finished product. On one project I worked on, I created a DSL to give to the client so that they could define achievements used in the project's gamification feature. A parser app told them about any inconsistencies in their definitions, such as missing or duplicate properties, and also generated a collection of objects that would implement the rules for those achievements in the app. It could also generate a script that connected to the app store to tell it what the achievements were.

主站蜘蛛池模板: 石楼县| 安乡县| 和顺县| 万安县| 定边县| 清水县| 临西县| 若羌县| 广东省| 庆云县| 上栗县| 鄂伦春自治旗| 松江区| 英山县| 潜山县| 澜沧| 灵川县| 北票市| 托克逊县| 宜宾市| 横峰县| 科尔| 长岛县| 华亭县| 承德市| 永城市| 同心县| 太湖县| 康马县| 富裕县| 铜梁县| 靖州| 浙江省| 奉新县| 扎鲁特旗| 兴化市| 邯郸县| 勃利县| 金寨县| 古田县| 江油市|