---
created_at: '2014-12-20T11:23:45.000Z'
title: Why Why Functional Programming Matters Matters (2007)
url: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters
author: olalonde
points: 141
story_text: ''
comment_text: 
num_comments: 36
story_id: 
story_title: 
story_url: 
parent_id: 
created_at_i: 1419074625
_tags:
- story
- author_olalonde
- story_8776383
objectID: '8776383'

---
[Source](http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters "Permalink to Why Why Functional Programming Matters Matters")

# Why Why Functional Programming Matters Matters

![raganwald][1]  
(_This is a snapshot of my old weblog. New posts and selected republished essays can be found at_ [**raganwald.com**][2]. _A reformatted and cleaned up version of this post can be found_ [**here][3]**.)  
  

Sunday, March 11, 2007

  [Why Why Functional Programming Matters Matters][4]

  
  
I recently re-read the amazing paper [Why Functional Programming Matters][5] (“WhyFP”). Although I thought that I understood WhyFP when I first read it a few years ago, when I had another look last weekend I suddenly understood that I had missed an important message.1  
  
Now obviously (can you guess from the title?) the paper is about the importance of one particular style of programming, functional programming. And when I first read the paper, I took it at face value: I thought, “Here are some reasons why functional programming languages matter.”  
  
On re-reading it, I see that the paper contains insights that apply to programming in general. I don’t know why this surprises me. The fact is, programming language design revolves around program design. A language’s design reflects the opinions of its creators about the proper design of programs.  
  
In a very real sense, the design of a programming language is a strong expression of the opinions of the designer about good programs. When I first read WhyFP, I thought the author was expressing an opinion about the design of good programming languages. Whereas on the second reading, I realized he was expressing an opinion about the design of good programs.  
  
**Can we add though subtraction?**  
  

> It is a logical impossibility to make a language more powerful by omitting features, no matter how bad they may be.

  
Is this obvious? So how do we explain that one reason Java is considered “better than C++” is because it omits manual memory management? And one reason many people consider Java “better than Ruby” is because you cannot open base classes like `String` in Java? So no, it is not obvious. Why not?  
  
The key is the word _better_. It’s not the same as the phrase _more powerful_.2 The removal or deliberate omission of these features is an expression about the idea that programs which do not use these features are better than programs which do. Any feature (or removal of a feature) which makes the programs written in the language better makes the language better. Thus, it _is_ possible to make a language “better” by removing features that are considered harmful,3 if by doing so it makes programs in the language better programs.  
  
In the opinion of the designers of Java, programs that do not use `malloc` and `free` are safer than those that do. And the opinion of the designers of Java is that programs that do not modify base classes like `String` are safer than those that do. The Java language design emphasizes a certain kind of safety, and to a Java language designer, safer programs are better programs.  
  
“More powerful” is a design goal just like “safer.” But yet, what does it mean? We understand what a safer language is. It’s a language where programs written in the language are safer. But what is a “more powerful” language? That programs written in the language are more powerful? What does that mean? Fewer symbols (the “golf” metric)?  
  
WhyFP asserts that you cannot make a language more powerful through the removal of features. To paraphrase an argument from the paper, _if removing harmful features was useful by itself, C and C++ programmers would simply have stopped using_ `malloc` _and_ `free` _twenty years ago_. Improving on C/C++ was not just a matter of removing `malloc` and `free`, it was also a matter of adding automatic garbage collection.  
  

> This space, wherein the essay ought to argue that Java compensates for its closed base classes by providing a more powerful substitute feature, left intentionally blank.

  
At the same time, there is room for arguing that some languages are improved by the removal of harmful features. To understand why they may be improved but not more powerful, we need a more objective definition of what it means for a language to be “more powerful.” Specifically, what quality does a more powerful programming language permit or encourage in programs?  
  
When we understand what makes a program “better” in the mind of a language designer, we can understand the choices behind the language.  
  
**Factoring**  
  
Factoring a program is the act of dividing it into units that are composed to produce the working software.4 Factoring happens as part of the design. (_Re_-factoring is the act of rearranging an existing program to be factored in a different way). If you want to compare this to factoring in number theory, a well designed program has lots of factors, like the number `3,628,800` (`10!`). A [Big Ball of Mud][6] is like the number `3,628,811`, a prime.  
  
Composition is the construction of programs from smaller programs. So factoring is to composition as division is to multiplication.  
  
Factoring programs isn’t really like factoring simple divisors. The most important reason is that programs can be factored in orthogonal ways. When you break a program into subprograms (using methods, subroutines, functions, what-have-you), that’s one axis of factoring. When you break an a modular program up into modules, that’s another, orthogonal axis of factoring.  
  
Programs that are well-factored are more desirable than programs that are poorly factored.  
  

> In computer science, **separation of concerns** (SoC) is the process of breaking a program into distinct features that overlap in functionality as little as possible. A concern is any piece of interest or focus in a program.  
  
SoC is a long standing idea that simply means a large problem is easier to manage if it can be broken down into pieces; particularly so if the solutions to the sub-problems can be combined to form a solution to the large problem.  
  
The term separation of concerns was probably coined by Edsger W. Dijkstra in his paper [On the role of scientific thought][7].

  
—Excerpts from the Wikipedia entry on [Separation of Concerns][8]  
  
Programs that separate their concerns are well-factored. There’s a principle of software development, [responsibility-driven design][9]. Each component should have one clear responsibility, and it should have everything it needs to carry out its responsibility.  
  
This is the separation of concerns again. Each component of a program having one clearly defined responsibility means each concern is addressed in one clearly defined place.  
  

> Let's ask a question about Monopoly (and Enterprise software). Where do the rules live? In a noun-oriented design, the rules are smooshed and smeared across the design, because every single object is responsible for knowing everything about everything that it can 'do'. All the verbs are glued to the nouns as methods.

—[My favourite interview question][10]

  
  
In a game design where you have important information about a rule smeared all over the object hierarchy, you have very poor separation of concerns. It looks at first like there’s a clear factoring “Baltic Avenue has a method called `isUpgradableToHotel`,” but when you look more closely you realize that every object representing a property is burdened with knowing almost all of the rules of the game.  
  

![][11]![][12]  
  
[The Seasoned Schemer][13]![][12] is devoted to the myriad uses of first class functions. This book is approachable and a delight to read, but the ideas are provocative and when you close the back cover you will be able to compose programs from functions in powerful new ways.  
  

The concerns are not clearly separated: there’s no one place to look and understand the behaviour of the game.  
  
Programs that separate their concerns are better programs than those that do not. And languages that facilitate this kind of program design are better than those that hamper it.  
  
**Power through features that separate concerns**  
  
One thing that makes a programming language “more powerful” in my opinion is the provision of more ways to factor programs. Or if you prefer, _more axes of composition_. The more different ways you can compose programs out of subprograms, the more powerful a language is.   
  
Do you remember [Structured Programming][14]? The gist is, you remove `goto` and you replace it with well-defined control flow mechanisms: some form of subroutine call and return, some form of selection mechanism like Algol-descendant `if`, and some form of repetition like Common Lisp’s `loop` macro.  
  
Dijkstra’s view on structured programming was that it promoted the separation of concerns. The factoring of programs into blocks with well-defined control flow made it easy to understand blocks and rearrange programs in different ways. Programs with indiscriminate jumps did not factor well (if at all): they were difficult to understand and often could not be rearranged at all.  
  
Structured [68k ASM][15] programming is straightforward in theory. You just need a lot of boilerplate, design patterns, and the discipline to stick to your convictions. But of course, lots of 68k ASM programming in practice is only partially structured. Statistically speaking, 68k ASM is not a structured programming language even though structured programming is possible in 68k ASM.  
  
Structured Pascal programming is straightforward both in theory and in practice. Pascal facilitates separation of concerns through structured programming. So we say that Pascal “is more powerful than 68k ASM” to mean that in practice, programs written in Pascal are more structured than programs written in 68k ASM because Pascal provides facilities for separating concerns that are missing in 68k ASM.  
  
**For example: working with lists**  
  
Consider this snippet of iterative code:  
  

    
    
      
    int numberOfOldTimers = 0;  
    for (Employee emp: employeeList) {  
        for (Department dept: departmentsInCompany) {  
            if (emp.getDepartmentId() == dept.getId() && emp.getYearsOfService() > dept.getAge()) {  
                ++numberOfOldTimers;  
            }  
        }  
    }  
      
    

  
This is an improvement on older practices.5, 6 For one thing, the `for` loops hide the implementation details of iterating over `employeeList` and `departmentsInCompany`. Is this better because you have less to type? Yes. Is it better because you eliminate the fence-post errors associated with loop variables? Of course.  
  
But most interestingly, you have the beginnings of a _separation of concerns_: how to iterate over a single list is separate from what you do in the iteration.  
  

> Try calling a colleague on the telephone and explaining what we want as succinctly as possible. Do you say “We want a loop inside a loop and inside of that an if, and…”? Or do you say “We want to count the number of employees that have been with the company longer than their departments have existed.”

  
One problem with the `for` loop is that it can only handle one loop at a time. We have to nest loops to work with two lists at once. This is patently wrong: there’s nothing inherently nested about what we’re trying to do. We can demonstrate this easily: try calling a colleague on the telephone and explaining what we want as succinctly as possible. Do you say “We want a loop inside a loop and inside of that an if, and…”?  
  
No, we say, “We want to count the number of employees that have been with the company longer than their departments have existed.” There’s no discussion of nesting.  
  
In this case, a limitation of our tool has caused our concerns to intermingle again. The concern of “How to find the employees that have been with the company longer than their departments have existed” is intertwined with the concern of “count them.” Let’s try a different notation that separates the details of _how to find_ from the detail of _counting what we’ve found_:  
  

    
    
      
    old_timers = (employees * departments).select do |emp, dept|  
      emp.department_id == dept.id && emp.years_of_service > dept.age  
    end  
    number_of_old_timers = old_timers.size  
      
    

  
Now we have separated the concern of finding from counting. And we have hidden the nesting by using the `*` operator to create a Cartesian product of the two lists. Now let’s look at what we used to filter the combined list, `select`. The difference is more than just semantics, or counting characters, or the alleged pleasure of fooling around with closures.  
  

  
![][16]![][17]  
I'm not a Haskell user (yet), but [The Haskell School of Expression: Learning Functional Programming through Multimedia][18]![][17] has received rave reviews and comes with solid recommendations. It's on my [wish list][19] if you're feeling generous!  
  

`*` and `select` facilitates separating the concerns of how to filter things (like iterate over them applying a test) from the concern of what we want to filter. So languages that make this easy are more powerful than languages that do not. In the sense that they facilitate additional axes of factoring.  
  
**The Telephone Test**  
  
Let’s look back a few paragraphs. We have an example of the “Telephone Test:” when code very closely resembles how you would explain your solution over the telephone, we often say it is “very high level.” The usual case is that such code expresses a lot more _what_ and a lot less _how_. The concern of what has been very clearly separated from the concern of how: you can’t even _see_ the how if you don’t go looking for it.  
  
In general, we think this is a good thing. But it isn’t free: somewhere else there is a mass of code that supports your brevity. When that extra mass of code is built into the programming language, or is baked into the standard libraries, it is nearly free and obviously a Very Good Thing. A language that doesn’t just separate the concern of how but does the work for you is very close to “something for nothing” in programming.  
  
But sometimes you have to write the _how_ as well as the _what_. It isn’t always handed to you. In that case, it is still valuable, because the resulting program still separates concerns. It still factors into separate components. The components can be changed.  
  
I recently separated the concern of describing “how to generate sample curves for some data mining” from the concern of “managing memory when generating the curves.” I did so by writing my own lazy evaluation code (Both the [story][20] and the [code][21] are on line). Here’s the key “what” code that generates an infinite list of parameters for sample beziér curves:  
  

    
    
      
    def magnitudes  
      LazyList.binary_search(0.0, 1.0)  
    end  
      
    def control_points  
      LazyList.cartesian_product(magnitudes, magnitudes) do |x, y|  
        Dictionary.new( :x => x, :y => y )  
      end  
    end  
      
    def order_one_flows args = {}  
      height, width = (args[:height] || 100.0), (args[:width] || 100.0)  
      LazyList.cartesian_product(  
          magnitudes, control_points, control_points, magnitudes  
      ) do |initial_y, p1, p2, final_y|  
        FlowParams.new(  
          height, width, initial_y * height,  
          CubicBezierParams.new(  
            :x => width,          :y => final_y * height,  
            :x1 => p1.x * width,  :y1 => p1.y * height,  
            :x2 => p2.x * width,  :y2 => p2.y * height  
          )  
        )  
      end  
    end  
      
    

  
That’s it. Just as I might tell you on the phone: “Magnitudes” is a list of numbers between zero and one created by repeatedly dividing the intervals in half, like a binary search. “Control Points” is a list of the Cartesian product of magnitudes with itself, with one magnitude assigned to `x` and the other to `y`. And so forth.  
  
I will not say that the sum of this code and the code that actually implements infinite lists is shorter than imperative code that would intermingle loops and control structures, [entangling][22]![][23] _what_ with _how_. I will say that it separates the concerns of what and how, and it separates them in a different way than `select` separated the concerns of what and how.  
  
**So why does “Why Functional Programming Matters” matter again?**  
  
The great insight is that better programs separate concerns. They are factored more purely, and the factors are naturally along the lines of responsibility (rather than in Jenga piles of `abstract` `virtual` `base` `mixin` `module` `class` `proto_` `extends` `private` `implements`). Languages that facilitate better separation of concerns are more powerful in practice than those that don’t.  
  
WhyFP illustrates this point beautifully with the same examples I just gave: [first-class functions][24] and [lazy evaluation][20], both prominent features of modern functional languages like Haskell.  
  
WhyFP’s value is that it expresses an opinion about what makes programs better. It backs this opinion up with reasons why modern functional programming languages are more powerful than imperative programming languages. But even if you don’t plan to try functional programming tomorrow, the lessons about better programs are valuable for your work in _any_ language today.  
  
That’s why [Why Functional Programming Matters][5] matters.  
  

* * *

1. And now I’m worried: what am I _still_ missing?
  

2. Please let’s not have a discussion about [Turing Equivalence][25]. Computer Science “Theory” tells us “there’s no such thing as more powerful.” Perhaps we share the belief that _In theory, there’s no difference between theory and practice. But in practice, there is_.
  

3. I am not making the claim that _I_ consider memory management or unsealed base classes harmful, but I argue that there exists at least one person who does.
  

4. The word “factor” has been a little out of vogue in recent times. But thanks to an excellent [post on reddit][26], it could make a comeback.
  

5. So much so that we won’t even bother to show what loops looked like in the days of `for (int i = 0; i < employeeList.size(); ++i)`. 
  

6. Another organization might merge employees and departments, or have each department “own” a collection of employees. This makes our example easier, but now the _data_ doesn’t factor well. Everything we’ve learned from databases in the last forty years tells us that we often need to find new ways to compose our data. The relational model factors well. The network model factors poorly.
  

Labels: [java][27], [lispy][28], [popular][29], [ruby][30]

  ¶ [10:21 PM][4]

**Comments on “_Why Why Functional Programming Matters Matters_”**:  

Regarding the "power" footnote:  
Why not invent a term such as "factorability", since that's what you spend most of the post talking about? Power is power, and Church and Turing have pretty much dealt with that. Let's not overload the word power with other concepts that make it too hard to tell what we're talking about. At the very least, pick something a bit closer. "Expressiveness," perhaps.  

[#][31] posted by ![Anonymous][32] Scott : 1:53 AM

 

Hi Reginald,  
  
Just a Ruby comment. In your code sample, the operator * is used for 2 arrays as a cartesian product. While this is trivial to add it to the Array class, I don't find it the standard ruby distribution 1.8.5. Did you implement it or did you use an extension lib for the Array class?  

[#][33] posted by ![Blogger][34] [Eric][35] : 1:57 AM

 

In the Ruby version of counting old timers, am I misreading something or shouldn't the first "employees_and_departments" really be an "old_timers"?  

[#][36] posted by ![Blogger][34] [Vineet][37] : 2:50 AM

 

Consider the APL and J languages, and the latest from that camp, Arthur Whitne's K (at http://kx.com/ ). It's a programming language that dominates the golf course, and has notoriety as less readable than perl because of that; But most importantly, it eschews standard notions of OO and many FP languages. Instead, it focuses on 40 or so basic operations, and some 20 ways to compose them. The result is really amazing -- a functional (thus, safe) language, very easy to use once you get the hang of it, with an incredibly quick interpreter that often outdoes comparable C code, in a 120K executable.  

[#][38] posted by ![Anonymous][32] Anonymous : 3:54 AM

 

Scott: CHurch and Turning have dealt with _computability_ in _theory_.  
  
This essay discusses power in practice. See the footnote above.  

[#][39] posted by ![Blogger][34] [Reginald Braithwaite][40] : 7:34 AM

 

Eric:  
  
The code for * is in the lazy lists class mentioned above (the source is [here][21]).  
  
There is an implementation for arrays as part of the Ruby Facets class, it is the combinations method added to Enumerable.  
  
My version happens to work with infinite lists. And by strange coïincidence, the code above does not actually declare that the given lists are Arrays...  
  
Perhaps they are also lazy?  

[#][41] posted by ![Blogger][34] [Reginald Braithwaite][40] : 8:03 AM

 

Hi Reg,  
  
Another thoughtful post, thank you. Being an admirer, I also appreciate your reference to Edsger W. Dijkstra's Separation of Concerns.  
  
In reading a number of your posts, I see a common theme of talking about the problem of the semantic distance between the language of the problem domain and the language used to implement a solution, without explicitly saying that you are talking about this distance. Your example of contrasting two implementations of counting the employees is a wonderful demonstration of this distance. My question is why do you not come out and specifically say that this is what you are talking about or to turn around your question: what am I missing?  

[#][42] posted by ![Anonymous][32] [Norbert][43] : 8:53 AM

 

To abridge the discussion that has been going on at Reddit (http://programming.reddit.com/info/19leo/comments/c19lwv) Reg's argument seems to involve a measure of power for a language that has to do with transformations that are possible to do once an idea is expressed in that language.  
  
My position is that I would prefer a measure of power that increased depending on how few transformations are needed to move the proposed solution from an idea in your head to an expression in the language.  
  
It'll take me probably a week to get this down coherently no my web site, but once I do so it will be at http://www.kirit.com/Measuring%20the%20power%20of%20programming%20languages  

[#][44] posted by ![Blogger][34] [Kirit][45] : 9:16 AM

 

I think the established word that you are looking for is 'compositionality' or 'decompositionality'.   
  
There are many advantage to compositionality, many of which you list. But there is one major disadvantage as well: efficiency. Compositional optimisation, i.e. optimising the various parts of a program then plugging them together, will always be strictly less efficient that global optimisation, which always results in spaghetti code.  

[#][46] posted by ![Blogger][34] [Dan][47] : 10:05 AM

 

Another great article.  
  
Just a quick note re: your nested looping antidote example. Ruby supports some light destructuring out of the box, so you could have written   
  
old_timers = (employees * departments).select do |emp,dept|  
  emp.department_id == dept.id && emp.years_of_service > dept.age  
end  
number_of_old_timers = old_timers.size  
  
instead. Pretty trivial, but makes the code even nicer to read.  

[#][48] posted by ![Anonymous][32] Justin : 12:54 PM

 

_Ruby supports some light destructuring out of the box_  
  
Hey, I didn't know you could do that without splattage. Thanks!  

[#][49] posted by ![Blogger][34] [Reginald Braithwaite][40] : 12:58 PM

 

Reginald yet another gem from you.  
  
_"So how do we explain that one reason Java is considered "better than C++" is because it omits manual memory management?"_  
  
As a side note, a wrong perception is always given that Java removes/omit memory management. In fact it "replaces" it with a Garbage Collector.   
  
Which does not mean you are not responsible for memory management any more. We are sill responsible for memory management but a different way. I blogged about it some time back   
[ Memory management is STILL your responsibility][50]   
  
Off course you mention the Java example to explain a lot different thing.  
  
Cool post keep them coming!  

[#][51] posted by ![Anonymous][32] [TH][52] : 2:57 PM

 

TH:  
  
_Which does not mean you are not responsible for memory management any more. We are sill responsible for memory management but a different way._  
  
Funny thing, but when we started selling JProbe Memory Debugger, we had to pound that message into the market over and over and over.  
  
One of our favourite "talking points" was a list of four kinds of memory leaks in Java programs.  
  
The thought at the time was that "Java programs do not leak," so that was always a fun topic.  

[#][53] posted by ![Blogger][34] [Reginald Braithwaite][40] : 3:04 PM

 

Regarding the code samples wrt iterating over the lists:  
  
The code you show is not object oriented at all, it's relational and hence your problems. If you designed your DAO and logic objects properly you'd just write something like:  
int oldTimers = 0;  
for (Department dept: departments) {  
for (Employee emp: dept.getEmployees()) {  
if (emp.getYearsOfService() > dept.getAge()) {  
++oldTimers;  
}  
}  
}  
  
In fact, your Ruby version makes things possibly even worse. Unless there is some lazy magic there, your Cartesian product will needlessly eat lots of memory and get garbage collected just afterwards (of course, your Java version might needlessly connect to a database behind, so it's hard to decide which is really worse). In the Ruby version you're also creating an unneeded list of oldtimers, but its only fate is to yield its length and get eaten as well.  
  
But whatever happens, both your Java and Ruby versions needlessly iterate over dept_count*emp_count pairs, while properly designed OO version iterates only emp_count times over exactly those pairs (dept, emp) which make sense.  
  
I really can't believe that functional design cannot do that.  

[#][54] posted by ![Blogger][34] [albert bulawa][55] : 5:49 PM

 

Albert:  
  
_If you designed your DAO and logic objects properly_  
  
In other words, if you **pushed joining two lists somewhere else**?  
  
So what is the real argument? Could it be that _a properly designed system separates the mechanism of joining (by putting it in a DAO that talks to an RDBMS) from what we want to do with the result_?  
  
Are we arguing **the exact same point**, only using different examples?  
  
I think this is a case where perhaps you would have preferred to see some production code to a simple example?  

[#][56] posted by ![Blogger][34] [Reginald Braithwaite][40] : 5:58 PM

 

For monopoly, I'd imagine that it'd be better to make a new static class called Referee, who'd know all the rules. Then you would consult with the Referee for any moves you made. Also, any tweaks to the rules (such as whether or not landing on Free Parking paid out of a pot) could be kept in one place.  

[#][57] posted by ![Blogger][34] [Sean][58] : 6:04 PM

 

As promised, Kirit has followed up:  
  
[Measuring the power of programming languages][59].  
  
I like it, thanks!  

[#][60] posted by ![Blogger][34] [Reginald Braithwaite][40] : 10:48 PM

 

_But whatever happens, both your Java and Ruby versions needlessly iterate over dept_count*emp_count pairs, while properly designed OO version iterates only emp_count times over exactly those pairs (dept, emp) which make sense._  
  
Indeed. In Ruby a good solution would probably end up looking something like the one you've given. I'd say that is a better separation of concerns as well, as either an employee should know their department or a department should know their employees.  
  
That said, a similarly written solution in Haskell (from my understanding) need not hold the list of all employees and departments.  
  
This would be a rather natural way of writing that program, using a list comprehension.  
  
  
length [Nothing | emp <\- employees,   
dept <\- departments,   
getDeptId emp == getId dept,   
getYearsOfService emp > getDeptAge dept]  

[#][61] posted by ![Blogger][34] [Peter][62] : 11:46 PM

 

Oy, debating the merits of object designs is interesting, but really should be over at the Monopoly post... which is about design.  
  
But we're programmers, and if we see an essay with 500 words and five lines of code, we'll give the words a few minutes and then we'll spend hours talking about the five lines of code.  
  
Remember, the code is to illustrate something about factoring.  
  
Okay, so:  
  
First, it's easy to have an employee hold a reference to a department. If I did that, I could change the example to count departments that have old timers.  
  
Whats the difference? Now you have a problem of going from department to employee.  
  
Should departments hold a collection of employees? I don't think so. I'm okay with a _convenience method_ that returns such a collection, but behind the scenes, something else has to manage that collection.  
  
Although we say "department has many employees" aloud, if we actually make a department a container for employees, we have two different entities sharing a responsibility.  
  
What happens when we write "emp.department = new_dept"? You have to update two different objects, the employee and the department. Likewise, if you write "dept.employees << new_hire_employee", you have to update two objects again.  
  
You end up with employees responsible for managing departments AND departments responsible for managing employees. This is a code smell: there should be exactly one place where the relationship between the two is updated.  
  
Of course, you can write those exact statements in Rails. Is that bad? No, because Rails virtualizes those methods.  
  
In actual fact, there is one thing in Rails that manages the relationship, a table in a database. The methods are provided for convenience. And if you change the relationship, the methods change for you automatically: you don't have to update the methods in two places.  
  
So while Rails looks like it give you employees that have a reference to a department and departments that have a collection of employees, the actual mechanism for managing the relationship is factored out of employees and out of departments.  
  
Which, I think, i entirely in keeping with the actual point of the words of this post, about factoring how away from what.  

[#][63] posted by ![Blogger][34] [Reginald Braithwaite][40] : 7:49 AM

 

Reginald: Weren't we talking about SoC?! That's exactly what you missed from that example. This code should not know that there is any deptid and that this is what links an employee to their department. Depending on what application should really do, this Department.getEmployees() method could return a pre-created list, join lists in background, do a select to a single RDBMS column, whatever. But that does not belong in this code snippet, and neither do fields which may be required by backend storage but are meaningless at this business logic level.  
  
I may miss your point, so a real-life code sample could probably help.  

[#][64] posted by ![Anonymous][32] albert bulawa : 10:08 AM

 

"a select to a single RDBMS column"  
  
Of course, I meant a table.  

[#][65] posted by ![Anonymous][32] albert bulawa : 10:10 AM

 

Albert:  
  
Your suggestion that the methods be proxies for some other thingie is exactly what I would do in "real life."  
  
I would probably use some metaprogramming (or annotation or whatever the language in question calls code that writes code).  
  
But you know, my example is still entirely valid and concise. There is a better separation of concerns using Cartesian product and select than there is iterating when you wish to perform a join and filter.  
  
I think you are bothered by the example of employees and departments because you probably imagine that the relationship is something permanent and ought to be reflected directly in the Entity-Relationship Model.  
  
If you like, you can consider a case with a much more transient relationship. For example:  
  
We have a list of coffee shops, graded by quality and geocoded for location. We have a list of potential offices where we can locate a new start up.  
  
We are looking for locations that have at least two good coffee shops within walking distance from them.  
  
I am tempted to ask whether we can agree that one style of code separates the concern better than the other.  
  
In fact, that is not the question. The **real** question is, can we agree that some styles of code separate concerns better than others?  
  
As long as we agree that some code separates concerns better than others, that's all that matters.  
  
You can really pick any two chunks of code that do the same thing and point out which one does a better job. The thesis is that some code separates concerns better than others, and that some tools facilitate that separation better than others.  

[#][66] posted by ![Blogger][34] [Reginald Braithwaite][40] : 10:34 AM

 

In response to your disclaimer about Turing equivalence, and your comment to Scott: you _can_ make **formal** claims about expressive power beyond Turing equivalence. There's a [classic paper][67] by Felleisen (co-author of the _Seasoned Schemer_, which you cite) about this. Read, enjoy, and be enlightened.  

[#][68] posted by ![Blogger][34] [Shriram Krishnamurthi][69] : 10:19 PM

 

  

  
  
  
<<[ Home][70]

[Reg Braithwaite][71]

  
  

Recent Writing

[Homoiconic Technical Writing][72] / [raganwald.posterous.com][73]  
  

Books 

[What I‘ve Learned From Failure][74] / [Kestrels, Quirky Birds, and Hopeless Egocentricity][75]   
  

Share

[rewrite_rails][76] / [andand][77] / [unfold.rb][78] / [string_to_proc.rb][79] / [dsl_and_let.rb][80] / [comprehension.rb][81] / [lazy_lists.rb][21]   
  

Beauty

[IS-STRICTLY-EQUIVALENT-TO-A][82] / [Spaghetti-Western Coding][83] / [Golf is a good program spoiled][84] / [Programming conventions as signals][85] / [Not all functions should be object methods][86]   
  
[The Not So Big Software Design][87] / [Writing programs for people to read][88] / [Why Why Functional Programming Matters Matters][89] / [But Y would I want to do a thing like this?][90]   
  

Work

[The single most important thing you must do to improve your programming career][91] / [The Naïve Approach to Hiring People][92] / [No Disrespect][93] / [Take control of your interview][94] / [Three tips for getting a job through a recruiter][95] / [My favourite interview question][10]   
  

Management

[Exception Handling in Software Development][96] / [What if powerful languages and idioms only work for small teams?][97] / [Bricks][98] / [Which theory fits the evidence?][99] / [Still failing, still learning][100] / [What I’ve learned from failure][101]   
  

Notation

[The unary ampersand in Ruby][102] / [(1..100).inject(&:+)][103] / [The challenge of teaching yourself a programming language][104] / [The significance of the meta-circular interpreter][105] / [Block-Structured Javascript][106] / [Haskell, Ruby and Infinity][20] / [Closures and Higher-Order Functions][24]   
  

Opinion

[Why Apple is more expensive than Amazon][107] / [Why we are the biggest obstacles to our own growth][108] / [Is software the documentation of business process mistakes?][109] / [We have lost control of the apparatus][110] / [What I’ve Learned From Sales][111] [I][112], [II][113], [III][114]   
  

Whimsey

[The Narcissism of Small Code Differences][115] / [Billy Martin’s Technique for Managing his Manager][116] / [Three stories about The Tao][117] / [Programming Language Stories][118] / [Why You Need a Degree to Work For BigCo][119]   
  

History

[06/04][120] / [07/04][121] / [08/04][122] / [09/04][123] / [10/04][124] / [11/04][125] / [12/04][126] / [01/05][127] / [02/05][128] / [03/05][129] / [04/05][130] / [06/05][131] / [07/05][132] / [08/05][133] / [09/05][134] / [10/05][135] / [11/05][136] / [01/06][137] / [02/06][138] / [03/06][139] / [04/06][140] / [05/06][141] / [06/06][142] / [07/06][143] / [08/06][144] / [09/06][145] / [10/06][146] / [11/06][147] / [12/06][148] / [01/07][149] / [02/07][150] / [03/07][151] / [04/07][152] / [05/07][153] / [06/07][154] / [07/07][155] / [08/07][156] / [09/07][157] / [10/07][158] / [11/07][159] / [12/07][160] / [01/08][161] / [02/08][162] / [03/08][163] / [04/08][164] / [05/08][165] / [06/08][166] / [07/08][167] /   

  

![][168]

[1]: http://weblog.raganwald.com/assets/media/raganwald_2008_350_150.png "raganwald 2008"
[2]: http://raganwald.com
[3]: http://raganwald.com/2014/12/20/why-why-functional-programming-matters-matters.html
[4]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html "permanent link"
[5]: http://www.cse.chalmers.se/~rjmh/Papers/whyfp.html
[6]: http://www.laputan.org/mud/
[7]: http://www.cs.utexas.edu/users/EWD/transcriptions/EWD04xx/EWD447.html
[8]: http://en.wikipedia.org/wiki/Separation_of_concerns
[9]: http://www.amazon.com/gp/product/0201379430?ie=UTF8&tag=raganwald001-20&linkCode=as2&camp=211189&creative=374929&creativeASIN=0201379430 "Object Design: Roles, Responsibilities, and Collaborations"
[10]: http://weblog.raganwald.com/2006/06/my-favourite-interview-question.html
[11]: http://weblog.raganwald.com/uploaded_images/seasoned_schemer.jpg
[12]: http://www.assoc-amazon.com/e/ir?t=raganwald001-20&l=as2&o=1&a=026256100X
[13]: http://www.amazon.com/gp/product/026256100X?ie=UTF8&tag=raganwald001-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=026256100X
[14]: http://en.wikipedia.org/wiki/Structured_programming
[15]: http://dmoz.org/Computers/Programming/Languages/Assembly/68k/
[16]: http://weblog.raganwald.com/uploaded_images/haskell_school_of_expression.jpg
[17]: http://www.assoc-amazon.com/e/ir?t=raganwald001-20&l=as2&amp;amp;o=1&a=0521644089
[18]: http://www.amazon.com/gp/product/0521644089?ie=UTF8&tag=raganwald001-20&link_code=as3&amp;camp=211189&creative=373489&creativeASIN=0521644089
[19]: http://www.amazon.com/gp/registry/wishlist/3A2XEHODQK2WP/ref=wl_web/
[20]: http://weblog.raganwald.com/2007/02/haskell-ruby-and-infinity.html
[21]: http://raganwald.com/source/lazy_lists.html
[22]: http://www.amazon.com/gp/product/B000002J27?ie=UTF8&tag=raganwald001-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B000002J27 "A Trick of the Tail by Genesis, Track 2, Entangled"
[23]: http://www.assoc-amazon.com/e/ir?t=raganwald001-20&l=as2&o=1&a=B000002J27
[24]: http://weblog.raganwald.com/2007/01/closures-and-higher-order-functions.html
[25]: http://en.wikipedia.org/wiki/Turing-complete
[26]: http://programming.reddit.com/info/18td4/comments
[27]: http://weblog.raganwald.com/labels/java.html
[28]: http://weblog.raganwald.com/labels/lispy.html
[29]: http://weblog.raganwald.com/labels/popular.html
[30]: http://weblog.raganwald.com/labels/ruby.html
[31]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173678780000#c9188498039672755580 "permanent link"
[32]: http://www.blogger.com/img/anon16-rounded.gif
[33]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173679020000#c8393597926251233162 "permanent link"
[34]: http://www.blogger.com/img/b16-rounded.gif
[35]: http://www.blogger.com/profile/16484514586929815703
[36]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173682200000#c1522927386593674741 "permanent link"
[37]: http://www.blogger.com/profile/12361589059366845911
[38]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173686040000#c564851405134288722 "permanent link"
[39]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173699240000#c4264162708606160611 "permanent link"
[40]: http://www.blogger.com/profile/13132345822387028437
[41]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173700980000#c2727997777031538467 "permanent link"
[42]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173703980000#c3115549260185715326 "permanent link"
[43]: http://weblog.raganwald.com/www.aiglerenaissance.com
[44]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173705360000#c893481966213253812 "permanent link"
[45]: http://www.blogger.com/profile/02188707816239176630
[46]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173708300000#c7929310602969070329 "permanent link"
[47]: http://www.blogger.com/profile/14866637943603692944
[48]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173718440000#c4098452317040832631 "permanent link"
[49]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173718680000#c3666194320387600509 "permanent link"
[50]: http://bootstrapping.wordpress.com/2007/02/16/memory-management-is-still-your-responsibility/
[51]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173725820000#c3322145014968360863 "permanent link"
[52]: http://bootstrapping.wordpress.com
[53]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173726240000#c6068961215324565907 "permanent link"
[54]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173736140000#c542642112773020438 "permanent link"
[55]: http://www.blogger.com/profile/01378450378511697449
[56]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173736680000#c3332436822315095447 "permanent link"
[57]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173737040000#c6316561053236557536 "permanent link"
[58]: http://www.blogger.com/profile/06911558688467600710
[59]: http://www.kirit.com/Measuring%20the%20power%20of%20programming%20languages
[60]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173754080000#c6421238193068478455 "permanent link"
[61]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173757560000#c6493940383892080858 "permanent link"
[62]: http://www.blogger.com/profile/03799579139256306118
[63]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173786540000#c6019288179712596084 "permanent link"
[64]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173794880000#c6527232970767009087 "permanent link"
[65]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173795000000#c4176168431190705502 "permanent link"
[66]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1173796440000#c7679108939386311702 "permanent link"
[67]: http://www.ccs.neu.edu/scheme/pubs/scp91-felleisen.ps.gz
[68]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html?showComment=1220408340000#c4142214880613397262 "permanent link"
[69]: http://www.blogger.com/profile/02956763366608000839
[70]: http://weblog.raganwald.com/welcome.html
[71]: http://braythwayt.com
[72]: http://homoiconic.com
[73]: http://raganwald.posterous.com
[74]: http://leanpub.com/shippingsoftware "A quarter-century of experience shipping software, distilled into fixnum bittersweet essays"
[75]: http://leanpub.com/combinators "Raganwald's collected adventures in Combinatory Logic and Ruby Meta-Programming"
[76]: http://github.com/raganwald/rewrite_rails
[77]: http://github.com/raganwald/andand
[78]: http://raganwald.com/source/unfold.rb.html
[79]: http://raganwald.com/source/string_to_proc.rb.html
[80]: http://raganwald.com/source/dsl_and_let.html
[81]: http://raganwald.com/source/comprehensions.html
[82]: http://weblog.raganwald.com/2008/04/is-strictly-equivalent-to.html
[83]: http://weblog.raganwald.com/2008/03/spaghetti-western-coding.html
[84]: http://weblog.raganwald.com/2007/12/golf-is-good-program-spoiled.html
[85]: http://weblog.raganwald.com/2007/11/programming-conventions-as-signals.html
[86]: http://weblog.raganwald.com/2007/10/too-much-of-good-thing-not-all.html
[87]: http://weblog.raganwald.com/2007/05/not-so-big-software-application.html
[88]: http://weblog.raganwald.com/2007/04/writing-programs-for-people-to-read.html
[89]: http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html
[90]: http://weblog.raganwald.com/2007/02/but-y-would-i-want-to-do-thing-like.html
[91]: http://weblog.raganwald.com/2008/04/single-most-important-thing-you-must-do.html
[92]: http://weblog.raganwald.com/2008/02/naive-approach-to-hiring-people.html
[93]: http://weblog.raganwald.com/2008/01/no-disrespect.html
[94]: http://weblog.raganwald.com/2006/11/take-control-of-your-interview.html
[95]: http://weblog.raganwald.com/2006/08/three-tips-for-getting-job-through.html
[96]: http://weblog.raganwald.com/2008/02/exception-handling-in-software.html
[97]: http://weblog.raganwald.com/2007/11/what-if-powerful-languages-and-idioms.html
[98]: http://weblog.raganwald.com/2007/08/bricks.html
[99]: http://weblog.raganwald.com/2007/06/which-theory-first-evidence.html
[100]: http://weblog.raganwald.com/2007/06/still-failing-still-learning.html
[101]: http://weblog.raganwald.com/2005/01/what-ive-learned-from-failure.html
[102]: http://weblog.raganwald.com/2008/06/what-does-do-when-used-as-unary.html
[103]: http://weblog.raganwald.com/2008/02/1100inject.html
[104]: http://weblog.raganwald.com/2007/10/challenge-of-teaching-yourself.html
[105]: http://weblog.raganwald.com/2006/11/significance-of-meta-circular_22.html
[106]: http://weblog.raganwald.com/2007/08/block-structured-javascript.html
[107]: http://weblog.raganwald.com/2008/05/why-apple-is-more-expensive-than-amazon.html
[108]: http://weblog.raganwald.com/2008/04/why-we-are-biggest-obstacle-to-our-own.html
[109]: http://weblog.raganwald.com/2008/03/process-is-to-software-as-software-is.html
[110]: http://weblog.raganwald.com/2007/09/we-have-lost-control-of-apparatus.html
[111]: http://weblog.raganwald.com/2007/01/what-ive-learned-from-sales-part-i.html
[112]: http://weblog.raganwald.com/2007/01/what-ive-learned-from-sales-part-i.html "What I've Learned From Sales, Part I: Don't Feed the Trolls"
[113]: http://weblog.raganwald.com/2007/01/what-ive-learned-from-sales-part-ii.html "What I've Learned from Sales, Part II: Wanna Bet?"
[114]: http://weblog.raganwald.com/2007/10/how-to-use-blunt-instrument-to-sharpen.html "What I've Learned from Sales, Part III: How to use a blunt instrument to sharpen your saw"
[115]: http://weblog.raganwald.com/2008/05/narcissism-of-small-code-differences.html
[116]: http://weblog.raganwald.com/2008/01/billy-martins-technique-for-managing.html
[117]: http://weblog.raganwald.com/2007/10/three-stories-about-tao.html
[118]: http://weblog.raganwald.com/2007/02/programming-language-stories.html
[119]: http://weblog.raganwald.com/2005/07/why-you-need-degree-to-work-for-bigco.html
[120]: http://weblog.raganwald.com/archives/2004_06_01_archive.html
[121]: http://weblog.raganwald.com/archives/2004_07_01_archive.html
[122]: http://weblog.raganwald.com/archives/2004_08_01_archive.html
[123]: http://weblog.raganwald.com/archives/2004_09_01_archive.html
[124]: http://weblog.raganwald.com/archives/2004_10_01_archive.html
[125]: http://weblog.raganwald.com/archives/2004_11_01_archive.html
[126]: http://weblog.raganwald.com/archives/2004_12_01_archive.html
[127]: http://weblog.raganwald.com/archives/2005_01_01_archive.html
[128]: http://weblog.raganwald.com/archives/2005_02_01_archive.html
[129]: http://weblog.raganwald.com/archives/2005_03_01_archive.html
[130]: http://weblog.raganwald.com/archives/2005_04_01_archive.html
[131]: http://weblog.raganwald.com/archives/2005_06_01_archive.html
[132]: http://weblog.raganwald.com/archives/2005_07_01_archive.html
[133]: http://weblog.raganwald.com/archives/2005_08_01_archive.html
[134]: http://weblog.raganwald.com/archives/2005_09_01_archive.html
[135]: http://weblog.raganwald.com/archives/2005_10_01_archive.html
[136]: http://weblog.raganwald.com/archives/2005_11_01_archive.html
[137]: http://weblog.raganwald.com/archives/2006_01_01_archive.html
[138]: http://weblog.raganwald.com/archives/2006_02_01_archive.html
[139]: http://weblog.raganwald.com/archives/2006_03_01_archive.html
[140]: http://weblog.raganwald.com/archives/2006_04_01_archive.html
[141]: http://weblog.raganwald.com/archives/2006_05_01_archive.html
[142]: http://weblog.raganwald.com/archives/2006_06_01_archive.html
[143]: http://weblog.raganwald.com/archives/2006_07_01_archive.html
[144]: http://weblog.raganwald.com/archives/2006_08_01_archive.html
[145]: http://weblog.raganwald.com/archives/2006_09_01_archive.html
[146]: http://weblog.raganwald.com/archives/2006_10_01_archive.html
[147]: http://weblog.raganwald.com/archives/2006_11_01_archive.html
[148]: http://weblog.raganwald.com/archives/2006_12_01_archive.html
[149]: http://weblog.raganwald.com/archives/2007_01_01_archive.html
[150]: http://weblog.raganwald.com/archives/2007_02_01_archive.html
[151]: http://weblog.raganwald.com/archives/2007_03_01_archive.html
[152]: http://weblog.raganwald.com/archives/2007_04_01_archive.html
[153]: http://weblog.raganwald.com/archives/2007_05_01_archive.html
[154]: http://weblog.raganwald.com/archives/2007_06_01_archive.html
[155]: http://weblog.raganwald.com/archives/2007_07_01_archive.html
[156]: http://weblog.raganwald.com/archives/2007_08_01_archive.html
[157]: http://weblog.raganwald.com/archives/2007_09_01_archive.html
[158]: http://weblog.raganwald.com/archives/2007_10_01_archive.html
[159]: http://weblog.raganwald.com/archives/2007_11_01_archive.html
[160]: http://weblog.raganwald.com/archives/2007_12_01_archive.html
[161]: http://weblog.raganwald.com/archives/2008_01_01_archive.html
[162]: http://weblog.raganwald.com/archives/2008_02_01_archive.html
[163]: http://weblog.raganwald.com/archives/2008_03_01_archive.html
[164]: http://weblog.raganwald.com/archives/2008_04_01_archive.html
[165]: http://weblog.raganwald.com/archives/2008_05_01_archive.html
[166]: http://weblog.raganwald.com/archives/2008_06_01_archive.html
[167]: http://weblog.raganwald.com/archives/2008_07_01_archive.html
[168]: http://www.assoc-amazon.com/s/noscript?tag=raganwald001-20

