mindscratch |
figuring it out |
| New post up on Rubysource: Ruby Colored Glasses: Elixir — http://rubysource.com/ruby-colored-glasses-elixir/ | |
| Ruby Colored Glasses: Elixir Source: rubysource.com One of the sweetest things about Ruby is its elegant syntax and developer friendliness. So how does Erlang fit in? It turns out a brilliant Brazilian name Jose Valim decided to view Erlang through Ruby colored glasses. | |
From Wikipedia, the free encyclopediaJump to: navigation, searchGeneral Responsibility Assignment Software Patterns (or Principles), abbreviated GRASP, consists of guidelines for assigning responsibility to classes and objects in object-oriented design.
The different patterns and principles used in GRASP are: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations. All these patterns answer some software problem, and in almost every case these problems are common to almost every software development project. These techniques have not been invented to create new ways of working but to better document and standardize old, tried-and-tested programming principles in object oriented design.
It has been said that “the critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology”.[1] Thus, GRASP is really a mental toolset, a learning aid to help in the design of object oriented software.
Contents
[hide][edit] Patterns
[edit] Creator
See also: Factory patternCreation of objects is one of the most common activities in an object-oriented system. Which class is responsible for creating objects is a fundamental property of the relationship between objects of particular classes. Simply “Creator pattern is responsible for creating an object of class”.
In general, a class B should be responsible for creating instances of class A if one, or preferably more, of the following apply:
- Instances of B contains or compositely aggregates instances of A
- Instances of B record instances of A
- Instances of B closely use instances of A
- Instances of B have the initializing information for instances of A and pass it on creation.
[edit] Information Expert
See also: Information hidingInformation Expert is a principle used to determine where to delegate responsibilities. These responsibilities include methods, computed fields and so on.
Using the principle of Information Expert a general approach to assigning responsibilities is to look at a given responsibility, determine the information needed to fulfill it, and then determine where that information is stored.
Information Expert will lead to placing the responsibility on the class with the most information required to fulfill it.[2]
[edit] Controller
See also: Model–view–controllerThe Controller pattern assigns the responsibility of dealing with system events to a non-UI class that represent the overall system or a use case scenario. A Controller object is a non-user interface object responsible for receiving or handling a system event.
A use case controller should be used to deal with all system events of a use case, and may be used for more than one use case (for instance, for use cases Create User and Delete User, one can have one UserController, instead of two separate use case controllers).
It is defined as the first object beyond the UI layer that receives and coordinates (“controls”) a system operation. The controller should delegate to other objects the work that needs to be done; it coordinates or controls the activity. It should not do much work itself. The GRASP Controller can be thought of as being a part of the Application/Service layer [3] (assuming that the application has made an explicit distinction between the Application/Service layer and the Domain layer) in an object-oriented system with common layers.
[edit] Low Coupling
Main article: loose couplingLow Coupling is an evaluative pattern, which dictates how to assign responsibilities to support:
- low dependency between classes;
- low impact in a class of changes in other classes;
- high reuse potential;
[edit] High Cohesion
Main article: cohesion (computer science)High Cohesion is an evaluative pattern that attempts to keep objects appropriately focused, manageable and understandable. High cohesion is generally used in support of Low Coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system. Alternatively, low cohesion is a situation in which a given element has too many unrelated responsibilities. Elements with low cohesion often suffer from being hard to comprehend, hard to reuse, hard to maintain and adverse to change.[4]
[edit] Polymorphism
Main article: polymorphism in object-oriented programmingAccording to Polymorphism, responsibility of defining the variation of behaviors based on type is assigned to the types for which this variation happens. This is achieved using polymorphic operations.
[edit] Pure Fabrication
See also: service (systems architecture)A Pure Fabrication is a class that does not represent a concept in the problem domain, specially made up to achieve low coupling, high cohesion, and the reuse potential thereof derived (when a solution presented by the Information Expert pattern does not). This kind of class is called “Service” in Domain-driven design.
[edit] Indirection
See also: delegation patternThe Indirection pattern supports low coupling (and reuse potential) between two elements by assigning the responsibility of mediation between them to an intermediate object. An example of this is the introduction of a controller component for mediation between data (model) and its representation (view) in the Model-view-controller pattern.
[edit] Protected Variations
Main article: delegation patternThe Protected Variations pattern protects elements from the variations on other elements (objects, systems, subsystems) by wrapping the focus of instability with an interface and using polymorphism to create various implementations of this interface.
[edit] See also
- Anemic Domain Model
- Design pattern (computer science)
- Design Patterns (book)
- Solid_(object-oriented design)
[edit] References
[edit] Notes
- ^ Larman 2005, p. 272.
- ^ Larman 2005 chapter 17, section 11.
- ^ “Application Layer like business facade?”. Yahoo! Groups (domaindrivendesign). http://tech.groups.yahoo.com/group/domaindrivendesign/message/7582. Retrieved 15 July 2010.
- ^ Larman 2005, pp. 314–315.
Retrieved from “http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)”
A nice primer to Git.
Clearer Unit Tests: Assert, Guard, and Throw
I hate the book “xUnit Test Patterns” for being over 800 pages long. I am convinced a good editor can turn any 800 page book into a 700 pager with the exact same content… that includes you Leo Tolstoy! The problem is that xUnit Patterns is still the definitive reference to test concepts and implementation. There is no better book on testing available, but the sheer weight and size the book means few have actually read it. Well I have, and I highlighted the damn thing just to prove it. In this post you’ll find 3 techniques to improve test clarity that, in my opinion, are underutilized in the development world today.
Custom Assertion Methods
I commonly see assertions repeated throughout a test case in sets. For instance, my current system deals in User objects, and you can see the same 3 lines of code sprinkled throughout a test case:User user = ... assertEquals("userId", user.getUserId()); assertEquals("fname", user.getFirstName()); assertEquals("lname", user.getLastName());
This is a form of test code duplication. It plain English, you want to say “make sure that the user we got back is the same one we expect”. This points to two concerns: an assertion (“make sure”) and equality (“the same”). It is temping to refactor using Extract Method, but this is a poor solution:User user = ... assertEquals("userId", "fname", "lname", user); static assertEquals(String userid, String fname, String lname, User user) { assertEquals("userId", user.getUserId()); assertEquals("fname", user.getFirstName()); assertEquals("lname", user.getLastName()); }
This isn’t bad, it just isn’t good. The test reads better, but the parameter list of the custom assertEquals is quite busy. It sort of half encapsulates equality. Equality is defined in the assertion method, but the attributes that contribute to equality are defined in at the place where assertEquals is invoked. A better solution is proper, canonical Assertion Method: two parameters and static.User actualUser = ... User expectedUser = ... assertEquals(expectedUser, user); static assertEquals(User expected, User actual) { assertEquals(expected.getUserId(), user.getUserId()); assertEquals(expected.getFirstName(), user.getFirstName()); assertEquals(expected.getLastName(), user.getLastName()); }
I follow this pattern because it keeps my options open. The assertEquals method is static. When I need to move it to my AssertionUtils or CommonAssertions class, then it is just a keystroke away (Ctrl Alt V or F6). Also it is common to construct a factory method for a canonical, or expected user. Having assertEquals written with a (User, User) parameter list means that you can hide the expected data behind a factory method and not have it clutter up your test. For me, a custom assertion method is the cleanest solution. The test code is readable because it captures the equality concern without showing the equality implementation. Hey, it’s an abstraction!Guard Assertion
In tests, decisions are the enemy of clarity. If you read a test method, any decision you come across is a detail that can clutter and obfuscate the meaning of the test. Mock object setup is classic clutter: “when x is called then return y” is a setup step that seldomly is a meaningful part of the test case. But assertions can contain decisions as well. Consider this test:List users = ... if (users != null) { if (users.size() == 1) { User actualUser = users.get(0); assertEquals(expectedUser, actualUser); } else { fail("user list wrong size"); } } else { fail("null users"); }
On first glance it looks complicated. This is how we sometimes write production code… be defensive and always guard against null pointers and illegal state. But remember, tests are different. What do you want your test to do when there is a null pointer? Blow up with a null pointer exception, of course! Forget these fail() methods and just write it so it blows up:List users = ... assertEquals(1, users.size()); assertEquals(expectedUser, users.get(0));
It is shorter, and less to take in. But there are less decisions in the test as well. No deciding on sizes and nullability. If the user list of user is null then it blows up with a stack trace. Which is what you want in a test! The conversion from conditional statements to assertions is called a Guard Assertion. Use them to clarify your tests by eliminating unneeded conditionals and decisions.Throw Everything
I blogged a while back about testing exceptions. Now it is time to say don’t test exceptions. Consider this approaches to handling exceptions in test methods:public void testSomething() throws IOException, LoggedException, EnterpriseException { ... }
This happens with fancy IDEs. A quick shortcut adds the exception to the method signature. But what’s the point? There is absolutely no reason a test shouldn’t just throw Exception. It is simpler, you can add it to your test method template, you never have to look at it again, and you never have to think about it. Throw Exception. It’s the simplest thing you can do. Another common occurrence is to see this type of exception code in a test method:public void testSomething() { try { ... } catch (IOException ex) { fail("Could not execute test"); } }
Yes, it is important to fail the test when an exception occurs. But do you know what happens when fail executes? It throws an unchecked exception. This code suppresses the cause of the exception only to throw a different one. The try catch block is a form of an unneeded decision in your test case. It can be completely eliminated by just throwing Exception in the test method. This way your stack trace points to where the problem occurred, not where it was handled. Both these examples are simplified into the same result:public void testSomething() throws Exception { ... }That’s it: 3 tips for clearer test code. And in far less than 800 pages!
Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.This entry was posted on Monday, September 27th, 2010 at 10:06 pm by Hamlet and is filed under General. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
7 Comments »
Igor Popov said,
September 28, 2010 @ 3:24 pm
For the first example why don’t you override Object’s equals method? That way you don’t need to define a custom assertion method… you’ll just use the generic method from the jUnit API:
static void assertEquals(java.lang.Object expected, java.lang.Object actual);So, what I’m saying can be resumed to:
public class User {
private int id;
private String firstName;
private String lastName;// other methods, ctors, setters, getters
public boolean equals(Object obj) {
if(!(obj instanceof User)) return false;
User user = (User) obj;
if(id != user.getId()) return false;
if(!firstName.equals(user.getFirstName())) return false;
if(!lastName.equals(user.getLastName())) return false;return true;
}
}and in your test method you’ll have just:
@Test
public void testUsers() {
User user1 = new User(1, “Bob”, “Morice”);
User user2 = new User(2, “Joe”, “Elvis”);
assertEquals(user1, user2); // should fail; it will use user1.equals(user2);
// so you don’t need custom asserts (at least for this example)
}Is this a better abstraction? At least the User is better encapsulated… you don’t need to know it’s fields or other things… you just ask if 2 users are the same… you don’t ask them for each particular attribute if it’s equal if the other…
What do you think?
PS. I didn’t compile this code so it might contain errors, but you should get the idea from this example.
Igor Popov said,
September 28, 2010 @ 3:25 pm
For the first example why don\’t you override Object\’s equals method? That way you don\’t need to define a custom assertion method… you\’ll just use the generic method from the jUnit API:
static void assertEquals(java.lang.Object expected, java.lang.Object actual);So, what I\’m saying can be resumed to:
public class User {
private int id;
private String firstName;
private String lastName;// other methods, ctors, setters, getters
public boolean equals(Object obj) {
if(!(obj instanceof User)) return false;
User user = (User) obj;
if(id != user.getId()) return false;
if(!firstName.equals(user.getFirstName())) return false;
if(!lastName.equals(user.getLastName())) return false;return true;
}
}and in your test method you\’ll have just:
@Test
public void testUsers() {
User user1 = new User(1, \Hamlet said,
September 28, 2010 @ 8:01 pm
Equality for testing purpose’s is often different than Object equality. So I avoid this.
Tweets that mention Rich Internet Applications (RIA) » Blog Archive » Clearer Unit Tests: Assert, Guard, and Throw — Topsy.com said,
September 29, 2010 @ 1:10 am
[…] This post was mentioned on Twitter by HamletDRC, Aleš Najmann, Richard Laksana, Rene Gröschke, Zak Jacobson and others. Zak Jacobson said: Great, concise. RT @DZone “Clearer Unit Tests: Assert, Guard, and Throw” http://dzone.com/rHpb […]
Jon Davis said,
September 29, 2010 @ 8:19 am
I agree with this article, however I have a reservation about one caveat. In your example regarding “just throw null exceptions”, my concern is that it is helpful to break down the scope of the null exception to scope of the variables being called upon.
In C# there is an ArgumentException which tells the developer which parameter of a method was invalid, i.e. null. When a parameter is needed for something and its value is null, let’s say it is of class type Foo and the code invokes the property Bar, the param name might be foo and the code inside the method would invoke the property foo.Bar. If foo was null, the test will fail with a null reference exception. Were this a unit test, this is exception is considered sloppy and unhelpful because we don’t know what’s null, we just know that something died.
We could implement decision logic inside the catch statement, going against what you had described, to see if the variable that was null was foo and to re-throw based on that information. Alternatively, an approach I’d recommend, is that the unit test should start off just validating the parameters; if foo==null throw new ArgumentException(“foo is null”, “foo”). Unfortunately, in real-world unit testing this gets to be a burden.
It seems it is a limitation of the languages, unfortunately, that a null reference exception will not describe the name of the variable that was called upon which was null. Due to this, there is sometimes no getting around a little bit of “excess” logic that must be written in defensive business logic as well as in helpful unit tests in order to fully communicate the essence of a programmatic error.
Alan Franzoni said,
September 29, 2010 @ 10:07 am
In my opinion, you\’re still using too many assertions.
http://www.artima.com/weblogs/viewpost.jsp?thread=35578
http://blog.jayfields.com/2007/06/testing-one-assertion-per-test.htmlTake this code:
List users = …
assertEquals(1, users.size());
assertEquals(expectedUser, users.get(0));I would have split it into two separate, tests, one called something like testRepoReturnsJustOneUserWhenInvokedWith…, the other one called testReturnedUserHasCertainProperties…
If users.size() is 0 or users is null, the second test would give an error by whatever means. If users.size() > 1 it is probably none of the second test concerns; the logic populating users is probably separate from the logic that creates a User object, and should be tested independently.
If it isn\’t your case, it\’s probably an issue with your code more than with your tests.
Hamlet said,
September 29, 2010 @ 6:42 pm
@Jon – Be careful. I did not say Throw a null pointer exception from the production code. THat is not OK and you need a better message. But from the test code, if a certain assertion line throws a NPE then you know exactly where the problem is without anything but the line number.
@Alan – Don’t confuse “each test method should test one thing” with “each test method should have one assertion”. The number of assertions a test method has depends on context not a rule.
RSS feed for comments on this post · TrackBack URI
Leave a Comment
Nice post from hamlet d’arcy.
Static VersionFlow Control in npm
Flow control is a popular subject in NodeJS. Since most of us learned synchronous object-oriented programming patterns in school, it can be a bit of a shift to really leverage asynchronous functional programming for all it can do.
As it turns out, a great way to leverage huge chunks of the node API is to build a package manager. npm has to do a lot of stuff with the file system, child processes, and HTTP requests to the registry. Fetching and building packages is a lot of “laundry list” programming. That is, the algorithms are very simple (fetch this file, put it over there, run that script, etc.), but there’s a lot to do, and you’ve gotta make sure everything gets done right (and in the right order).
To keep this from getting out of hand, I’ve leveraged two fairly low-level patterns that are found throughout the NodeJS API, but which I haven’t seen documented anywhere yet, and which I’m calling “the Action/Callback pattern”.
Action functions
Action functions can take a variable amount of arguments, but the last argument is always a callback function. It MUST call that cb exactly one time, once it’s done doing stuff.
Callback functions
Callback functions can take any number of arguments, but the first argument is always an error or null.
Example
You’ve probably seen this example:
read-file-example.jsfs.readFile("/etc/passwd", function (er, data) { if (er) throw er // doSomething(data)})
fs.readFileis an action function. The function being passed to it,function (er, data)...is a callback function.Consistent Patterns are Consistent
Every function in npm, if it does something async, does it using this mechanism.
Every callback function in npm, will expect an error argument as the first argument, so calling it like that will always bubble the error up.
Polymorphism Wins
Because of this consistent pattern, there is a lot of room for powerful creativity.
asyncMap(list, fn, cb)Let’s say you have a list of filenames, and you have to remove each one. A pretty typical use case in npm, but once you generalize “do this to those”, you start noticing nails in need of a hammer.
asyncMapis the answer for that. (The current async-map.js in npm is a bit more complicated, because it allows you to specify a list of functions rather than just one.)async-map.jsfunction asyncMap (list, fn, cb_) { if (typeof cb_ !== "function") throw new Error( "No callback provided to asyncMap") var data = [] , errState = null , l = list.length if (!l) return cb_(null, []) function cb (er, d) { if (errState) return if (arguments.length > 1) data = data.concat(d) if (er) return cb_(errState = er, data) else if (-- a === 0) cb_(errState, data) } // expect the supplied cb function to be called // "n" times for each thing in the array. list.forEach(function (ar) { fn(ar, cb) })}Note that the top-level
cb_function is called with an array of all the results. So, data is being proxied up, as well as errors. (That’s why it’s called asyncMap, rather than asyncForEach.)So, now we can simply do this:
remove-file-list.jsfunction removeFileList(fileList, cb) { asyncMap(fileList, rm, cb)}Proxying
You catch that? An Action function can pass its own cb over to another Action function if it doesn’t need to do anything with success or failure. We could also have done something like this:
proxying.jsfunction removeFileList (fileList, cb) { asyncMap(fileList, rm, function (er) { if (er) log("Failed to remove fileList!") cb(er) })}
chain(fn1, fn2, ..., cb)There are other cases where you want to make sure that a list of functions are called in a specific order. For instance, we need to make sure that all
preinstallscripts are done running before starting in on theinstallscripts. That’s wherechaincomes in handy.
chaintakes a list of function arguments which take a callback, and a final argument which is the ultimate callback function.chain.jsfunction chain () { var steps = Array.prototype.slice.call(arguments) , cb_ = steps.pop() , n = 0 , l = steps.length function cb (er) { if (er) return cb_(er) if (++ n === l) return cb_() steps[n](cb) } steps[n](cb)}chain 2
This is great, but it requires using Function#bind if we want to pass arguments to those functions other than a callback. This API would be nice:
chain2-usage.jschain( [fn1, a, b] , [obj, "method", x, y, z] , function (cb) { doSomething(1,2,3,cb) } , cb )Basically, each argument is one of:
- a function which will be called with a single cb argument
- an array containing a function and 0 or more arguments
- an array containing an object, a method name, and 0 or more arguments
- a falsey value, so we can do stuff like: foo && [ doFoo, foo, bar ]
Revamped to handle this calling style, chain looks like this:
chain2.jsfunction chain () { var steps = Array.prototype.slice.call(arguments) , cb_ = steps.pop() , n = 0 , l = steps.length nextStep(cb) function cb (er) { if (er) return cb_(er) if (++ n === l) return cb_() nextStep(cb) } function nextStep (cb) { var s = steps[n] // skip over falsey members if (!s) return cb() // simple function if (typeof s === "function") return s(cb) if (!Array.isArray(s)) throw new Error( "Invalid thing in chain: "+s) var obj = null , fn = s.shift() if (typeof fn === "object") { // [obj, "method", some, args] obj = fn fn = obj[s.shift()] } if (typeof fn !== "function") throw new Error( "Invalid thing in chain: "+typeof(fn)) fn.apply(obj, s.concat(cb)) }}Mix and Match
Because everything in npm (and a lot of things in node) use this pattern, you can mix very high-level operations with very low-level operations. Why, even
chainandasyncMapare “action” functions, so they can take any vanilla callback, or be arguments to one another.This is without any sophisticated “async flow control” library. Just a few short JavaScript functions and an adherence to a few simple patterns.
As long as you stick to these patterns, you can use any Action function in any asyncMap or chain call, and make sure that all Action functions call their cb exactly once.
Get creative! This language is powerful, and it’s not that hard to do interesting things with it.
postme is my playground for exploring the posterous API and using node.js
Save the Date! Join us November 14th-17th at The Fairmont San Francisco for Sencha Conference 2010.
Read the blog post at Sencha.com. More...
I recently started using this method to sync between my development machines. I use my local Dropbox clone as a...
So, because of Google is into the whole social graph techno-hippie stuff Buzz works with open standards for moving...
My Android app primarily uses the ListView and this Google I/O 2010 session titled “The World of ListView” was really helpful. The ViewHolder...
Watching the Android UI design patterns session from Google I/O 2010. The Official Twitter app is a really cool example of these design patterns. I...