I find myself refactoring to DSLs when I have a lot of composition to do and I want to cut the verbosity out of doing all of it. I'll take everything and turn it into something I can compose with and the DSL just knits everything together.
For example, I made an application that generates different kinds of feeds from a database. I found myself making a bunch of classes that responded to .call with similar interfaces, arrays of hashes. So I refactored everything to composable method classes and even identified and extracted concepts inside the composable methods so that I could compose even the method classes.
All the DSL does is compose the feed objects from the method classes. Each feed is composed of transformers, each transformer is a class with a .call method that takes an array of hashes and returns an array of hashes, unless it's pulling directly from the database, one of these is always the first of the transformers in the list. Or it's returning the end product, in which case it's always the last in the list.
That app is just way too much fun to work on now. It has the kind of design I would have thought of if I'd done it in BDUF fashion, only instead of coming up with it up front, I refactored working code to it. And I would not have wanted to do it in anything but Ruby.
For example, I made an application that generates different kinds of feeds from a database. I found myself making a bunch of classes that responded to .call with similar interfaces, arrays of hashes. So I refactored everything to composable method classes and even identified and extracted concepts inside the composable methods so that I could compose even the method classes.
All the DSL does is compose the feed objects from the method classes. Each feed is composed of transformers, each transformer is a class with a .call method that takes an array of hashes and returns an array of hashes, unless it's pulling directly from the database, one of these is always the first of the transformers in the list. Or it's returning the end product, in which case it's always the last in the list.
That app is just way too much fun to work on now. It has the kind of design I would have thought of if I'd done it in BDUF fashion, only instead of coming up with it up front, I refactored working code to it. And I would not have wanted to do it in anything but Ruby.