CSC/ECE 517 Fall 2010/ch2 S23 GP

From Expertiza_Wiki
Jump to navigation Jump to search

Introduction to Object-Oriented Domain-Specific Languages

Domain-specific Languages, or DSLs, are programming languages or a subset of other languages that are used to solve domain specific problems. This is in opposition to general purpose programming languages that are used for all problems. The advantage of DSLs over general purpose languages is they are more targeted to a specific set of problems that may be higher level than is necessary for a general purpose language. Domain-specific languages are very ubiquitous, even though it may not be apparent. Here are examples of some domain-specific languages:

  • CSS
  • SQL
  • Regular Expressions
  • UnrealScript [3]

General purpose languages contain more functionality than DSLs and generally provide specific system level access. Of course this may be a misnomer since a DSL may be developed specifically to handle system level APIs, like file systems. Examples of general purpose languages include:

  • Java
  • C++
  • C#

Object-oriented Domain-specific Languages (OODSLs) differ from traditional DSLs in the same way that traditional languages differ from their object-oriented counterparts. An OOP uses "objects", which are data structures that contain both data members and methods. Therefore, OODSLs are simply DSLs that employ and object-oriented paradigm. Examples of OODSLs are:

  • Scalable Vector Graphics (SVG) [7]
  • Extensible Application Markup Language (XAML) [6]
  • Kiddo
  • Spring Configuration

Internal vs. External

Among OODSLs there is a distinction between internal OODSLs and external OODSLs [5]. Internal or embedded OODSLs give a "host" language domain-specific extensions or elements. For example, an internal OODSL may extend a general purpose language to allow for easier implementation of generating graphics through the use of specific APIs. An example of an embedded OODSL is JavaScript hosted within an HTML document.

However, there is a fuzzy line between embedded OODSLs and 3rd party libraries. For example, the drawing methods of a Graphics object within Java may be considered an embedded OODSL or just a series of library APIS that are used in a contractual way.

External OODSLs are languages that are not hosted within another language, but are compiled or interpreted in a standalone manner. These OODSLs usually have a complete tool set and development environment behind them. It is up to the language implementer, but external OODSLs are generally interpreted instead of compiled. However, an OODSL does not necessarily need to be compiled into executable code. An OODSL may be a representation of something else. The CSound OODSL compiles an Orchestra and Score markup files into audio. Another example is compiling or converting SVG into a rasterized image, such as Portable Network Graphics (PNG).

Practical Example: Java Swing and SVG

One way to illustrate the benefits of OODSLs is to compare a OODSL and a general purpose language performing the same task. The following practical example illustrates how a language like Java and an OODSL perform painting tasks. Both examples will draw a square button with the word Button in the center. The Java code is taken from a common Swing construct where a JButton overrides its paintComponent method to draw something more custom than the Swing default look and feel. The Java Graphics API is used to perform both vector and raster drawing operations within a Java application. These operations could be used for either drawing user interfaces or directly onto in-memory images for later display. Here is an example of drawing a square button using a Java Graphics object.

@Override
protected void paintComponent(Graphics g) {
	// Save the current context's color
	Color savedColor = g.getColor();

	// Fill the shape
	g.setColor(Color.gray);
	g.fillRect(0, 0, getWidth(), getHeight());

	// Draw the text
	g.setColor(Bolor.black);
	g.drawString("Button", 2, getHeight()-3);

	// Draw the border
	g.setColor(Color.black);
	g.drawRect(0, 0, getWidth()-1, getHeight()-1);

	// Restore the context's color
	g.setColor(savedColor);
}

This is quite procedural despite it being a methodology within an object-oriented language. Using a general purpose language like Java to perform something as domain-specific as graphics generation can lead to a lot of redundant overhead that is taken care of in a specialized language. This example illustrated the saving and restoring of the Graphic object's Color attribute, but could have required the saving and subsequent restoration of multiple properties, such as the current Transform, Stroke or Font. An OODSL would provide a more robust and flexible set of drawing and graphics APIs that would ideally perform the redundant tasks like saving and restoring the graphics state attributes, as is the case with SVG. Here is the same example written in using this OODSL.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg width="10%" height="10%" version="1.1" xmlns="http://www.w3.org/2000/svg">
	<rect width="100%" height="100%"
	      style="fill:rgb(128,128,128);stroke-width:1;stroke:rgb(0,0,0)" />
	<text x="35%" y="50%">Button</text>
</svg>

This code is more declarative, object-oriented and much less procedural. Instead of using a method to draw a rectangle the rectangle itself is an object with many data members used to define how the rectangle is rendered. Ironically, the style attribute of the rectangle is a subset of CSS, another OODSL. Since SVG is a language specific to the vector and imagery domain it provides capabilities (like opacity and gradients) that may be difficult to perform in general purpose languages without specialized libraries or an internal OODSL.

The SVG declaration could be "compiled" into an image format (such as JPG) as opposed to the Java code, which can only paint on the Graphics context passed into it. The point is the SVG implementation is more versatile within the image domain in performing the same or similar methods as a general purpose language like Java.

When should OODSLs be used?

In order to determine if a OODSL should be used or created you must first examine the advantages of OODSLs. If the problem domain is a well-known domain that already has an OODSL defined for it then it may be useful to use this OODSL, after all it was created for a reason. If the selected OODSL does not fully support the operations needed for the problem domain then maybe a different OODSL is needed or the OODSL needs to be extended.

If, however, there is no existing OODSL defined then creating a new OODSL may be the answer. This usually happens when there is a well-defined or at least well-understood domain where certain operations are performed over and over again. For example, a good candidate for an OODSL is robotics. Consider a robotic arm in a factory that needs to perform repetitive tasks such as picking up an object from one conveyor belt and moving it to another. If there is a OODSL that defines the movements of the arm then new behaviors could be easily added to the armature and existing actions can be easily changed. These changes in behavior may even be performed by a technician or subject matter expert (SME) instead of a developer.

Conclusion

Object-oriented Domain-specific Languages provide a level of abstraction to a given domain. This abstraction may result in enhanced capabilities (such as rapid prototyping) or a greater control or understanding of that domain. It may also enable non-developers, like SMEs, to write "code" that utilizes the OODSL to affect a system or generate some sort of output. OODSLs are classified as either internal or external where internal is an OODSL that "lives" within a host language and external is a standalone language in its own right. General purpose languages are good for just that, general purpose development. OODSLs are very focused and are prevalent in almost every niche of computing.

References