I assume you do write tests. To test system boundaries, you have to find out whether methods are called. Usually, people reach out for mocks to verify behavior.
If you use a lot of mocks, though, the tests can reveal high coupling in your code: either you have to mock objects multiple levels deep, which is a sign of too much knowledge about how the collaborating objects work, or you have to mock lots of objects one level deep. The latter can be acceptable when you test a components which is some kind of coordinator. The former, though, is never to be accepted. Use the feedback of these hard-to-write tests to make your code simpler.
That’s what the Law of Demeter is for. While “law” is way too strict, its principle is sound: strive to call methods on the objects you have direct access to, but avoid calling methods on objects which you obtain through another method call in the first place.
For example, the following violates the principle:
funcviolateThePrinciple(aCollaborator:Collaborator){letaStranger=aCollaborator.obtainFriend()// this is okay so faraStranger.doSomething()// this is not, because it's 2nd level}
In your unit tests, you can add a Collaborator mock to verify the calls and then you’re good to go. No multiple levels of mock objects and stubs. You may call this “shallow reaching” (opposed to “deep reaching”), although no one else calls it that.
That’s the Law of Demeter in a nutshell: only talk to friends which you know through properties or parameters, but don’t talk to strangers which you get to know through the return values of your friends’ methods. You never know what to expect.
Since we started the Zettelkasten blog, it became weirder and weirder to keep the old posts here. I found the split among domains unfortunate.
Today, I’ve moved all Zettelkasten-related posts to the project blog at Zettelkasten.de. The old addresses won’t change, and your comments have persisted, too.
Thanks for visiting this blog, and thanks for caring about what I write! If you’re still interested in personal information management, head over to the new place. If you’re into programming, though, stay here.
Ryan Quan of Brigade Engineering has published an article about using the VIPER iOS app software architecture. Their write-up is really good: message passing is illustrated with code samples – and they even use neat box graphs!
I use a VIPER-like approach in my apps, too, and I’d like to invite you to try it for yourself. VIPER is inspired by Clean Architecture and Hexagonal.
In a nutshell, you decouple the view controllers from event handling from data management. You introduce so-called “Wireframes” to set up a module or “stack” of objects to display a view controller with certain data. The Wireframes set up everything once. Afterwards, event handlers take over, called “Presenters”. They perform transitions between scenes. View controllers do not much more than setting up the view and reacting to IBActions.
This will make maintaining code easier because the view controllers are finally put on a diet. Figuring out how data has to flow differently takes some getting used to. I’m going to write about this in a future post.
Let’s assume we need a Domain Model and can’t create our application with basic CRUD actions and data containers. Let’s further assume we have a Box Entity which can contain many Itemn. Item is an Entity, too, because its attributes may change over time, so a Value Object won’t do.
When you reason about objects in your system and their means of communication, you can differentiate between three messaging flavors according to Mathias Verraes: imperative, interrogatory, and informational messages. Before we can talk about informational messages and their value, let’s recap the other two and see what the difference is, because them calling for being extracted is not easy to spot.
Erica Sadun brought up a topic which is bugging me for some time already. It’s how Swift encourages you to handle optionals. It’s related to handling exceptions, which I covered earlier. Either you use if-let to unwrap them implicitly and do all the stuff inside the nested code block, or you end up with code which is a lot wordier than I’d like it to be.