Archive for August, 2009
Coding: The guilty bystander
While discussing the duplication in our code based which I described in an earlier post with some other colleagues earlier this week I realised that I had actually gone past this code a couple of times previously, seen that there was a problem with it but hadn't taken any steps to fix it other than to make a mental note that I would fix it when I got the chance.
At the time we needed to fix a bug around this code and noticed that the logic was scattered all around the place but decided to just add to the mess and put our fix in without refactoring the code to make it better for people coming to the code in future.
In a way then it was perhaps poetic justice that when the bug was re-tested there were still problems with it.
This time we decided to fix it properly and with the improved expressiveness the code now has hopefully it will make life easier for other people who have to work with the code.
I think this was also a really clear case of the broken windows theory whereby the likelihood of someone doing something bad to the code is much higher if it's already in a suboptimal state.
After hearing me describe this Halvard pointed out that it sounded quite like the idea of the guilty bystander whereby if you see a problem with the code and do nothing about it then you are guilty by association even though it wasn't you who wrote it.
This sounds quite similar to a post written by Ayende where he pointed out that if you own the code then it is your responsibility to keep it in good shape, you can't keep blaming the previous owners forever.
Another colleague of mine, Silvio, pointed out that sometimes it might not be feasible for us to stop doing what we're doing to go and fix something else, especially if it's unrelated code that we just happen to come across. Indeed doing this might lead to a yak shaving situation.
In this situation he suggested that we need to let it be known that something should be done possibly by writing a 'TODO' comment in capital letters around the offending code so that the next person who comes across the code can take a look at the offending code without having to assess whether or not it's in a bad state.
To continue the analogy perhaps this would be the equivalent of calling 999/911/000 to report the situation to the police which is definitely better than just ignoring the problem although not as good as helping to solve it.
In this case the help you're providing is a bit more indirect than calling the emergency services would be so I'm not sure if the metaphor quite fits!
There are certainly exceptions (such as when we inherit code which is a mess) but in general I always think we've gone horribly wrong when we get to the stage where we need to ask the business whether we can have a whole iteration (or more) to refactor the code into shape so that we can start moving faster again.
I believe that while in the short term it's our responsibility to make sure we deliver the features we're working on in the current iteration, we also need to make sure that we spend some time ensuring that we can continue to deliver features in future iterations as well and part of that second responsibility is taking the time to mould code into a state where we can build on top of it more easily even if it wasn't us who wrote it in the first place.
Coding: Group the duplication, then remove it
One of the most common activities for software developers is removing duplication from code and Dave recently showed me a technique which I hadn't seen before for doing this more effectively – first group all the code into one place without removing any of the duplication and then remove the duplication when everything is in one place.
The code where we tried out this technique was being used to construct the model for the navigation at the top of the pages on the website we're working on and before we grouped the duplication the code looked a bit like this:
public enum Options { Login = 1, Logout = 2 // and so on } public class NavigationModel { public NavigationModel(Options options, string messageOne, string messageTwo) { Configuration = options; MessageOne = messageOne; MessageTwo = messageTwo; } public Options Configuration { get; private set; } public string MessageOne { get; private set; } public string MessageTwo { get; private set; } }
Which was then used in other parts of the code base like this:
var messageOne = someRepository.GetMessageOne(); var messageTwo = someRepository.GetMessageTwo(); var navigationModel = new NavigationModel(Options.Login, messageOne, messageTwo);
var messageOne = someRepository.GetMessageOne(); var messageTwo = someRepository.GetMessageTwo(); var navigationModel = new NavigationModel(Options.Logout, messageOne, messageTwo);
There are actually 7 different types of 'Options' and the 'NavigationModel' was setup in 6 different places across 3 different controllers.
The first step was to create a static factory method on 'NavigationModel' for each of the different configurations without trying to remove the duplication, just putting it all in one place.
public class NavigationModel { public NavigationModel(Options options, string messageOne, string messageTwo) { Configuration = options; MessageOne = messageOne; MessageTwo = messageTwo; } public static NavigationModel ForLoggedInUser(IRepository someRepository) { var messageOne = someRepository.GetMessageOne(); var messageTwo = someRepository.GetMessageTwo(); return new NavigationModel(Options.Logout, messageOne, messageTwo); } public static NavigationModel ForAnonymousUser(IRepository someRepository) { var messageOne = someRepository.GetMessageOne(); var messageTwo = someRepository.GetMessageTwo(); return new NavigationModel(Options.Login, messageOne, messageTwo); } public Options Configuration { get; private set; } public string MessageOne { get; private set; } public string MessageTwo { get; private set; } }
All we've done is move the code from the controller into the 'NavigationModel' but already the duplication seemed more obvious.
Being forced to come up with a name for each of the creation methods actually made it more obvious that in the case of the anonymous user there was no need to make any calls to the repository since 'MessageOne' and 'MessageTwo' would never be used in this case.
We hadn't realised that this was the case until everything was grouped but it meant that we could save an unnecessary network call to get that data which is always good.
Another interesting side effect was that we realised that two of the creation methods we had just written were exactly the same which allowed us to remove one of them.
The next step was to push the repository calls into the constructor which is now private since noone calls it from outside this class any more:
public class NavigationModel { private NavigationModel(Options options, IRepository someRepository) { Configuration = options; MessageOne = someRepository.GetMessageOne(); MessageTwo = someRepository.GetMessageTwo(); } private NavigationModel(Options options) { Configuration = options; MessageOne = ""; MessageTwo = ""; } public static NavigationModel ForLoggedInUser(IRepository someRepository) { return new NavigationModel(Options.Logout, someRepository); } public static NavigationModel ForAnonymousUser(IRepository someRepository) { return new NavigationModel(Options.Login); } public Options Configuration { get; private set; } public string MessageOne { get; private set; } public string MessageTwo { get; private set; } }
The thinking for the next step which we haven't done as yet is to delay the call to 'someRepository' until it is actually needed by converting 'MessageOne' and 'MessageTwo' into methods which delegate to it.
I'm not sure of the best way to handle the case where either of those methods were called for the anonymous user case where we don't actually have a repository – perhaps the best way would be to create a null object version of the repository I'm not sure?
I was initially unsure how following this approach would be beneficial and I wanted to just remove the duplication straight away instead of grouping it first but from this experience I can certainly see how useful it can be.
Book Club: Unshackle your domain (Greg Young)
In this week's book club we continued with the idea of discussing videos, this week's selection being Greg Young's 'Unshackle your Domain' presentation from QCon San Francisco in November 2008. He also did a version of this talk in the February European Alt.NET meeting.
In this presentation Greg talks about Command Query Separation at the architecture level and explicit state transitions amongst other things.
Jonathan Oliver has created a useful resource page of the material that's been written about some of these ideas as well.
These are some of my thoughts from our discussion:
- I think the idea of eventual consistency is quite interesting and I can see how taking this approach instead of trying to create the impression that everything the user does is in real time we can make life much easier for ourselves.
I'm not sure how this type of idea works when users have the expectation that when they change information on a page that it is updated straight away though.
For example on a form I might decide to change my address and I would expect that if I reload the page with my address on that it would now display my new address instead of the old one. If that address was eventually consistent after 5 minutes for example the user might become quite confused and send in another update to try and change their address again.
Liz pointed out that with bank transactions it is often explicitly described to users that money transfers are 'pending' so perhaps the expectation that things aren't done in real time has already been set in some domains.
Werner Vogels has a nice article about eventual consistency in distributed systems in which he references a paper by Seth Gilbert and Nancy Lynch which talks about the idea that "of three properties of shared-data systems; data consistency, system availability and tolerance to network partition one can only achieve two at any given time."
- Dave pointed out that the idea of 'POST redirect GET' often used when processing web form submissions seems to adhere quite nicely to the idea of Command Query Separation as described in the video.
I find it quite interesting that CQS at the method level in our code is usually quite closely adhered too but so often we'll just bolt on getters onto domain objects so that we can access some data to display on the view.
The idea of not doing this and having a write only domain seems very interesting and seemed to make sense in the system that Greg described.
It would be interesting to know whether one would follow such an extreme approach at the architecture level if there weren't such high performance requirements or the need to have all the operations performed on the system available for an audit.
- Greg's idea of state transitions sounds quite similar although perhaps not exactly the same as Eric Evans' 'domain events' which he discussed in last week's book club.
It would be interesting to see what the code to process form submissions by the user would look like with this approach.
As Silvio pointed out, the complexity of this code would probably be much higher than in a more typical approach where we might just build our domain objects straight from the data the user entered.
Using Greg's approach we would need to work out which state transitions had actually happened based on the user input which would presumably involve keeping a copy of the previous state of the domain objects in order to work out what had changed.
I like the idea of making concepts more explicit though and the idea of keeping all state transitions is something that is built into databases by way of their log by default so it's not a completely new concept.
Pat Helland has a cool post titled 'Accountants don't use erasers' where he describes it in more detail.
jQuery: $.post, 'jsonp' and cross-domain requests
We spent a bit of time yesterday looking through the jQuery code trying to work out why a cross domain request we were making using jQuery's '$.post' function wasn't working.
In hindsight perhaps it should have been obvious that you wouldn't be able to do that but I didn't completely understand how we were able to do cross domain requests were possible at all but we had some '$.getJson' 'jsonp' function calls around our code base which were doing just that.
The jQuery documentation seemed to suggest it was possible to do a 'jsonp' 'POST' request but when we tried to do so we got the following error:
Error: uncaught exception: [Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)"
The failure was occurring in this part of the code on line 3517 inside the 'ajax' function:
3512 3513 3514 3515 3516 3517 | // Open the socket // Passing null username, generates a login popup on Opera (#2865) if( s.username ) xhr.open(type, s.url, s.async, s.username, s.password); else xhr.open(type, s.url, s.async); |
I had initially thought that passing in 'jsonp' to the function did something clever to fool the browser into sending the Xml Http Request but actually in a thread from the jQuery mailing list from a year ago where Michael Geary explains what's actually happening:
Cross-domain JSONP isn't AJAX at all. It doesn't use XMLHttpRequest. It's nothing more than a dynamic script element that loads JavaScript code.
You can't do a POST with a dynamic script element. Where would you put the POST data?
I don't know what the $.ajax code is trying to do – maybe it should fail in a more informative way. It will fail one way or another regardless.
We could see where this was being done in the jQuery code:
3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 | // If we're requesting a remote document // and trying to load JSON or Script with a GET if ( s.dataType == "script" && type == "GET" && parts && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){ var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.src = s.url; if (s.scriptCharset) script.charset = s.scriptCharset; ... head.appendChild(script); ... } |
On line 3477 a script tag is dynamically added into the page and on line 3478 we set 'src' to be the url for our cross domain request.
We can see on line 3473 that this only happens if we have a 'GET' request.
It turned out for us that we were actually only doing this cross domain request on one of our early test environments and that in latter test environments we have everything running on the same domain.
On this occasion we have decided to stop using this environment since it's not reflective of what our application will run like in production but if we wanted to do a cross domain request then we would need to make use of the '$.get' method with 'jsonp' passed as an option.
I was talking about this with Dave Yeung at our coding dojo last night and he pointed me to an article describing how Firefox 3.5 is now supporting the 'access control for cross site requests' recommendation which will allow cross domain XHR requests to happen by providing some extra header tags and then reading some additional tags sent back in the response where the server on the other domain can decide which domains are allowed to make calls to it.
I'm still learning this stuff so if anything I've said isn't accurate please point that out.
Pair Programming: Observations on anti-patterns
I've been pairing a bit more regularly recently after more sporadic pairing sessions over the last 9 or 10 months and I've noticed that I've picked up some habits which aren't really that effective when pairing so I'm on a mission to sort that out.
Moving around the code too quickly
One thing that I often forget is that when you're driving you know exactly where you're going with the mouse or keyboard just before you do it whereas the other person doesn't know until you've done it.
As a result of this it is useful to commentate on what you're about to do and not move around the code at break neck speed, but instead take your time and pause after each step to allow your pair to follow where you are in the code.
It seems like this might slow you down but I find that quite frequently when I race around the code in this way I'm making assumptions about the code and I didn't even know that I was doing it.
Having someone else working alongside you forces those assumptions out into the open and it's amazing how often you end up going a different way than you had originally assumed.
Moving through the code more slowly is especially important if you call someone over to help you with something since in this situation they have very little idea about what you're doing so they won't be able to provide much assistance unless you take the time to provide the context to them.
Not listening to other solutions
Another trap which is best to avoid is always thinking that you personally have the solution to all the problems the pair encounters and that your solution should always be the one used.
I think this becomes a particularly easy trap to fall into when you've learnt a few ways to solve problems and the temptation is to always use these solutions and block out suggestions which we judge as being inferior to our solution.
This seems similar to Jay Fields' post 'Kill your darlings' where he describes a technique George Malamidis taught him:
George Malamidis taught me something about code attachment a few years ago: You always gain by allowing someone to show you an alternative solution. If someone wants to solve a problem in a different way, there are several gains to be had. If their way is inferior, you have an opportunity to mentor a team-mate. If their way is equally elegant, you've gained another solution, or point of view that may be superior in the future. If their way is superior you learn something new and the codebase improves. In exchange for these gains you only need to give up time. Time is valuable, but it's also well spent on improving the ability of a team-mate or your personal ability.
I noticed that when working with my colleague Lu Ning I wasn't very keen to understand his ideas about how to structure code and move data between the client and server sides because I was convinced that the way I already knew would work better.
As it turned out when I eventually started listening I realised that his approach worked much better than any ideas I had so he taught me something new.
This situation comes up a lot when pair programming and I think it's useful to always keep an open mind – that way you might learn something you didn't expect to.
Grabbing the keyboard away
I think this one is more obviously ineffective and I don't think I do this as often.
I did suggest in another post that getting control of the keyboard can be a useful way to help you become more engaged in a pairing session, it's certainly useful to ensure that you communicate why you're doing that and checking if it's ok with your pair if you drive now.
On the other hand just grabbing the keyboard and typing without saying anything because you think you have a 'great idea' is not really an effective way of working together with your pair as it effectively sidelines them.
In Summary
These are just a few observations of some things I've noticed and as always there are no doubt more ways that we can pair program ineffectively.
Pair programming for me is not just about putting two people together and having them work the same way they would normally – there certainly seems to be a completely different dynamic to the way we work and I think it's important to adjust the way we work to adapt to that.
Coding: Coupling and Expressiveness
We came across an interesting situation in our code base recently whereby two coding approaches which I consider important for writing maintainable code seemed to come into conflict with each other.
The code we were working on needed to retrieve some customer details from a backend system by making use of the current user's 'customerId' which we can retrieve from the 'LoggedInUser'.
My initial thought was that since we only needed one property of the 'LoggedInUser' we could just pass in the 'customerId' instead of the 'LoggedInUser':
public class Repository { public Customer RetrieveCustomer(string customerId) { var backEndSystemCustomer = backEndSystem.RetrieveCustomer(customerId); return MapCustomer(backEndSystemCustomer); } }
Which we would use like this:
public class SomeController { ... public ActionResult DoSomething() { repository.RetrieveCustomer(loggedInUser.CustomerId); // and so on } }
I recently came across quite a nice post which explains different types of cohesion and coupling that we might find in our code and from my understanding the above code has data coupling which is the loosest type of coupling that we can have apart from message coupling:
Data coupling is when modules share data through, for example, parameters. Each datum is an elementary piece, and these are the only data which are shared (e.g. passing an integer to a function which computes a square root).
It seemed to me that it was better to couple the repository to the data it required rather than to the 'LoggedInUser' which would be stamp coupling:
Stamp coupling (Data-structured coupling) is when modules share a composite data structure and use only a part of it, possibly a different part (e.g. passing a whole record to a function which only needs one field of it). This may lead to changing the way a module reads a record because a field, which the module doesn't need, has been modified.
In this case I was thinking about coupling of classes instead of coupling of modules (perhaps wrongly?)
Discussing this with Dave, he pointed out that the method wasn't really very expressive and that it is actually possible to pass in any string we want – even one that might not even be a customerId. The chance of making a mistake when using this API is quite high.
We therefore changed the method signature so that it takes in a 'LoggedInUser' instead and then just takes the 'customerId' from that object.
We only build a 'LoggedInUser' from one place in our application and everyone on the team knows that so it's much less likely that someone would make a mistake and pass in the wrong instance.
public class Repository { public Customer RetrieveCustomer(LoggedInUser user) { var backEndSystemCustomer = backEndSystem.RetrieveCustomer(user.CustomerId); return MapCustomer(backEndSystemCustomer); } }
I think the code is definitely nicer like this although LoggedInUser and Repository are now coupled even though the repository only cares about one property of LoggedInUser.
It seems to me though that the main reason we care about coupling is that loosely coupling our code makes it easier to change but on the other hand making our code more expressive makes it easier to read which is also important for making it easy to change.
Maybe it's not such a big deal anyway – I just found it interesting that I thought I'd done the right thing and it turned out that a way I had previously rejected turned out to be more appropriate.
Rock Scissors Paper: TDD as if you meant it
I decided to spend a bit of time on Saturday having another go at writing Rock Scissors Paper while following Keith Braithwaite's TDD as if you meant it exercise.
We previously did this exercise at a coding dojo but I wanted to see what happens when you code for a longer period of time with this exercise since we typically only code for maybe a couple of hours at a dojo.
I decided to also checkin the code I was writing into Git after every single change I made – an idea I originally learnt from Dan North, and the code is all on github.
What did I learn?
- I was coding for maybe 4 or 5 hours and checked in about 120 times which is far more frequently than I would do normally although perhaps it shouldn't be.
I thought it would be quite distracting to have to check in that often but the checkin messages ended up becoming a stream of consciousness of what I was thinking which proved quite useful on a few occasions when I got side tracked a bit and retraced my steps in the history to find out what I was supposed to be doing – Git was pretty much acting as my sounding board since I didn't have a pair to work with on this exercise.
I'd definitely try this out again and as I've mentioned a few times I want to try it out in a coding dojo some time.
- While trying to remove some duplication that had worked its way into the code I realised that the template method would be the easiest way to remove that duplication and as I mentioned in an earlier post, having functions/actions in C# makes the implementation of this pattern a bit simpler:
public abstract class ThrowBase : IThrow { private readonly Func<IThrow, bool> beatenBy; protected ThrowBase(Func<IThrow, bool> beatenBy) { this.beatenBy = beatenBy; } .... public bool Beats(IThrow aThrow) { return IsDifferentThrowTo(aThrow) && !beatenBy(aThrow); } } }
public class Scissors : ThrowBase { public Scissors() : base(weapon => weapon.BeatsScissors()) { } ... }
If we didn't have functions then we'd need a method on 'ThrowBase' which we would need to implement in each of its sub classes.
As it is we can just pass a function into the constructor which does the same job.
- Another thing I found quite interesting about this exercise was that I was seeing more easily where methods didn't seem to belong on an existing object and I ended up creating a new object which described the interaction – chatting about the code with Liz she pointed out that I was probably creating domain events which we had discussed a few days earlier in book club.
Once I started thinking about this interactions as 'domain events' the naming of them seemed to be much more obvious – for example after this conversation with Liz I realised that the interaction between two 'Throws' would be a 'ThrowDown' and that there would probably be a 'ThrowDownAdjudicator' to decide the outcome of a 'ThrowDown'.
- I found it quite difficult to follow the rules of the exercise when I realised that I wanted to return a 'ThrowDownResult' which would indicate whether there was a winner for a 'ThrowDown' and if so who it was. I couldn't see a way to write all of this code in the test since I had already created the class previously so I ended up writing this code straight onto the class.
I think I probably extracted to a class too early on some occasions instead of waiting for a more complete version of a method to be written before moving it.
Next time I think I'd wait until I'd completed all the examples /tests I want to write around a particular method before moving it onto a class.
Book Club: What I've learned about DDD since the book (Eric Evans)
This week book club became video club as we discussed Eric Evans' QCon London presentation 'What I've learned about DDD since the book'.
I was lucky enough to be able to attend this presentation live and we previously ran a book club where I briefly summarised what I'd learnt but this gave everyone else an opportunity to see it first hand.
There are some of my thoughts and our discussion of the presentation:
- We spent a lot of time discussing domain events – one of the new ideas which Evans had observed since publishing the book – and Liz pointed out that a domain event often exists where there is some sort of interaction between objects which doesn't seem to belong on either object.
The example Liz gave is where there is an accident between two cars and we realise that there should be a Collision object to describe what's happened. Dave pointed out that commits in Git could be another example of a domain event.
We discussed some domain events which we had noticed in code bases we had worked on.
One system I worked on had the concept of transactions to describe interactions between different accounts. They were also used to calculate the balance of an account at any time in preference to keeping the balance of each account updated in real time.
The balance on the account would still be updated at the end of each day such that we would only need to make use of transactions since the last update to calculate a balance.
- What really stood out for me in our discussion is how a lot of the concepts that Eric Evans talks about are designed to make us explicitly state what we are doing in our code.
We have domain events for describing what happens in the domain, we try to define bounded contexts so we know what the object model means in specific areas of the code, we identify a core domain so we can spend our time on the most important code and so on.
Dave described this as conscious coding in that it makes us think very carefully about what we're coding rather than just coding without real analysis and probably writing code which isn't as useful as it could be.
- I'm still not sure that I really get what the core domain means but Dave described it as 'If we stripped out all the other code in our system except for the core domain we would still be able to build something around that' which actually has the side effect of pointing out that we need to ensure that this code is completely decoupled from any implementation details of the current way we are using it.
For example if we are currently writing a website and it is decided that we need to be able to display our content on a mobile phone, we should still be able to make use of the same core domain code to do that fairly easily.
- The section of the talk about the big ball of mud and the green house was also very interesting and Raphael Speyer came up with the analogy of only letting code from outside the green house inside if it had been hosed down and all the mud removed so that we can ensure that out important code is of comparable quality.
If I understand correctly the core domain is the code that should reside in that metaphorical green house and we will spend a lot of time on its modeling so that it will be easy to change in the future.
By contrast the modeling of the code outside the green house is not as important – a lot of the time the code out there is 'just data' and we want to display that data to users with minimal effort in modeling it in our code since we don't get a great deal of value from doing so.
Pair Programming: Keeping both people engaged
I've written a few times previously about pair programming and how I think it's one of the best practices I've seen used on agile teams but in order to ensure that we're making the best use of this practice it's important to ensure that both people are engaged.
It is often quite difficult to persuade people who aren't used to extreme programming that having two people working at the same machine is actually beneficial and this task can be made even more difficult if one person is losing focus or interest and therefore isn't actually adding much value in that pairing session.
Who's responsible for making the pair function well?
In all likelihood the person who's not currently at the keyboard is going to be the one losing focus and in this situation I often wonder whose responsibility it is for ensuring that the pair is functioning well.
My initial thinking is that it's the responsibility of the person driving to bring the navigator along with them and that if this isn't happening then they're not doing a very good job in the driving role.
A fairly typical scenario is for the driver to be coding and not really saying anything to their partner while they're doing so, therefore internalising all the mini decisions that they're making.
Vocalise your thoughts when driving
When I was first shown how to pair program we were taught to vocalise everything we were doing while at the keyboard, thereby pretty much providing a running commentary for our pair to allow them to follow what we were doing.
This commentary could be anything from detailing a refactoring that we've seen and want to perform to asking our pair for help to understand a bit of code that we're finding tricky.
Hopefully this commentary helps create an almost constant conversation between the two people pairing.
Regaining focus
If the driver isn't providing this commentary then an idea which Dan North suggested to me is that the navigator can try and get this conversation going by commentating on what their pair is doing or by asking them questions.
I suppose done to an extreme this might be a bit annoying but it should only be necessary to do this for a short amount of time until the driver starts being more communicative and I've found that it works quite well as a technique for getting yourself engaged again.
Another approach is to get back control (with your pair's permission!) of the keyboard and continue where your pair left off until you have regained the context that you previously lost at which stage you might hand the keyboard back.
It might also make sense to take a break for a few minutes and walk around or get a drink before returning to the pair – I find that this works well for me too.
Doing something is better than doing nothing
The key here is that once we identify the problem the worst thing that we can do is to do nothing. The current situation clearly isn't working for us so we need to do something about it.
As I learnt when studying NLP:
If what you're doing isn't working, try something else, anything else, regardless of whether what you had been doing should have worked.
While discussing some of this ideas with my colleague Lu Ning he suggested that if we are losing focus then it might be an indicator that we should split up the pair.
I think we should still look to try some of the above ideas but if they don't have any effect then Lu is probably correct.
Learning: Thoughts on doing so more effectively
One of the quite common sayings that I've come across when discussing student/teacher type situations is that it's the teacher's responsibility to present the material to the student in a way that they can understand and that if the student still doesn't understand then the teacher hasn't done their job properly.
I believe that this approach is also followed in the UK education system nowadays and while it makes sense in a way I don't think it's a particularly useful belief to have as a student since it seems to encourage you to be quite passive in the learning process.
I find that when you are in a situation where you are the student it is probably quite likely that you are aware of the best way that you understand new material whereas the teacher doesn't necessarily know and, unless they have the ability to work out which way you will understand best, they will probably explain something in the way that they would like it explained to them.
If you don't know the way that you learn best then it's quite a useful thing to try and work out.
I've worked out that I learn best when I can find something I understand already that I can link it to and as a general rule I understand things way better when I can work out a way to visualise it, usually by drawing a diagram or finding an explanation which includes a diagram.
My colleagues seem to have picked up that this is the way that I understand things best so wherever I happen to be working there will likely be stacks of papers with different diagrams on them!
I also know that it often takes me a few times before I understand something but that once I understand something I don't tend to forget it.
It used to really annoy me that I didn't understand concepts as quickly as some of my peers at university but now that I've noticed that pattern I tend to write down the concept or bookmark it if it's on the web and then come back to it later when I might have learnt something else which helps me understand the other concept.
Maybe the responsibility really does lie with the teacher, and I particularly like the quote from the last slide of this presentation which says 'If you can't explain it simply, you don't understand it well enough' but it doesn't do much harm to help them to help us.
I've also found that varying the way that I learn new ideas can sometimes be quite effective – for example there are now loads of videos available of people presenting on different technical topics and watching someone who knows a subject really well explain it through this medium can often make it easier to understand than reading an article about it.
One of the best ideas I've come across lately was from Pragmatic Learning and Thinking, which suggests discussing what you're learning with others.
This is useful because you get the chance to see how well you understand the topic by trying to explain it as well as getting their views on the subject.
From our experiences running a technical book club it's often quite surprising how varied people's opinions are despite reading/watching the same material.
It seems to me that perhaps the most important skill in the world of software development is learning how to learn new things and these are a few of the ways that I find work for me. I'd be keen to learn ways that other people are doing this too!