poniedziałek, 30 maja 2016

piątek, 6 maja 2016

iOS interviews done right

There's been a heated debate about technical interviews lately. More specifically, about whiteboard interviews. The first time I've encountered the community damning the whiteboard interviews was with loud and popular tweet by Max Howell, the creator of open source code like PromiseKit.




That's strong, isn't it? Seems like the dev community hates whiteboard interviews. Not just because they're hard, but because they're supposedly pointless and tell nothing about technical skills of the candidate.

Is that a justified opinion, or just a rant from people who failed a test ? What's the "right way" to interview developers ?

Whiteboard Interviews

You get an algorithm challenge and a marker. You're supposed to write code on a whiteboard, while other people are watching you. What does that really test ?

  • It shows that the candidate can write code under pressure - This is the biggest problem. Programming isn't about typing, or writing stuff on a board. Programming is about thinking and solving problems. How are you supposed to focus, think and solve a problem if someone is watching, evaluating and expects you to come up with a solution. I can't even program on a normal IDE when someone is watching. Solving problems with someone watching you closely is a skill, sure. Is it a skill that a good developer should have ? Hell, no! Programmers work best when left alone to think and focus in silence, or to tunes of their favorite music.
  • It shows that the candidate remembers the syntax and collections API by heart - Do experienced programmers use google frequently ? Yes! And that's completely normal. Nobody remembers everything. Swift string has a complicated API - I need google almost every time I need to do something advanced. There's a reason why sites like fuckingswiftblocksyntax.com exist. We program with auto-complete, documentation, google and syntax highlighting. It would be crazy to do otherwise. Is remembering everything by heart a clear sign of a great developer ? Hell, no!
  • It shows that the candidate has algorithms knowledge - This I can't argue with. If I had two similar candidates I'd choose the one who seems to be better at solving coding algorithm problems. It's valuable to test that in a candidate.
The first two points are really big obstacles for even the best programmers. I had one whiteboard interview and it was just awful. Writing code that's supposed to compile, on a board, is just unnatural.

How do you test candidate's problem solving and algorithm skills ? How about the normal way ? By using something like Codility, or just leaving the candidate alone for an hour, while he's solving the problem on a computer, with a normal IDE and access to documentation.

How to interview iOS developers

Testing the developer's problem solving skills is just the tip of the iceberg. 

I've interviewed a lot and I've been interviewed a lot. Testing the knowledge and experience of iOS developers in their domain is the most most important thing you can evaluate in a candidate. How do you do that ?

  • Let's start by saying that: Ignoring people with a lot of experience, open source contribution and ambitious project just because they marked 20% on a Codility test is a bad idea.
  • Let them talk about their experience. Inquire about their projects, passions, challenges, war stories. It's very important that you listen. It's a very good idea to ask technical questions relative to the candidate's experience, to verify his knowledge. It happened to me only once and it was a very positive experience: the interviewer chose and noted the technical questions as I talked about my past projects. It was valuable for both sides: the interviewer could verify the experience I described and I felt that the interviewer actually listened to me - not something that happens every often. Choose the questions for the interview accordingly to the candidate.
  • Browse iOS programming blogs for interesting and detailed questions. A candidate that knows advanced auto-layouthow stuff gets drawn on the screen under the hoodknows how runtime of his language works is a very valuable candidate.
  • Choose some fun questions to evaluate the candidate's creativity. One of my favorites is: "If you were assigned to crash an app with code, what would you write ?" or something like: "Try to think of a feature that's not allowed by Apple and would definitely get rejected by the review team".
  • I've read a lot of posts saying that giving candidates 5-10 hour demo projects is a good idea. In my opinion, making the candidates work for 10 hours for free is not optimal. If the candidate doesn't have any open source contributions, to see how they perform in coding real solutions, just have a project ready with 2 or 3 tasks to finish. It should take an hour maximum and you'll have a candidate's code example, style and architecture.
  • Assign fast simulated problems: "Please make a pseudo-diagram of architecture for app with such requirements:...", "Please design a CoreData scheme for such requirements...", "The client has reported that... What do you do?". It's a great way to see how the candidate would react in real life problems.
  • Prepare small snippets of codes with common mistakes in them and see if the candidate will be able to tell what's wrong with them. A typical example is a memory leak in a closure/block. More examples here (question 7), and here.
Unlike whiteboard coding these are all very relaxing ways of interviewing a developer. Moreover I like such interviews and I learn every time I go through one.

If you're ever in charge of creating the recruting process, please think about avoiding whiteboard coding in favor of more humane and friendly kinds of questions and challenges. 

środa, 9 marca 2016

czwartek, 17 grudnia 2015

"MVVM is not very good" - How do you make it better ?

Soroush has created a blog post that describes my funny feelings when using MVVM.

MVVM is an evolution of MVC. It's "better" than MVC, because it reorganizes the way you layout your logic between the modules. View and Model are very clear in their purpose, so where did all the rest of the logic go ?

The ViewModel naturally. As Soroush states, you just push all of your code from the ViewController to the ViewModel and how does that solve anything really ?

What if I told you...

What if I told you that design patterns are just ideas, and you should never follow the blindly ? The problem with design patterns, tutorials and examples that describe them are written in the void. They usually contain a couple of lines of code that don't exist in context of a big system. That's why MVVM looks great in case of a simple tutorial timer interface.

The problem appears, when you start using it in an actual app that does a lot of things. You end up with a ViewModel that contains business logic, sorting, validating, calls to database model, calls to the networking model. You start to realize that you have an class that's called ViewModel, you can't really say what it does. That spits at Single Responsibility Principle.

Does that mean that MVVM is bad and you should not use it ? No. you're going to run into the same problem using VIPER. You'll have tons of classes named Presenters and they'll all do a lot of different things. Sure, they'll follow SRP a little better, but they still won't be perfect.

MVVM, MVC, VIPER are just paradigms and you as the architect of your system have to choose explicit design that's best for your context. 

It's hard, but it's beautiful - it means that you have to be creative, you still have a lot of work to do. Just because someone invented MVVM it doesn't mean that you're free of thinking about architecture.

So how do you do it right, while following MVVM ?

Anything can be your ViewModel - ViewModel is just an idea. It's just something that tells you: "Hey, stop putting logic into your view". ViewModel is just a class with a couple of properties and commands and that's it - it doesn't say anywhere, that you have to put everything in one class.

You can have a lot of ViewModels for one view - That's the main sin of ViewModel tutorials. They create one big ViewModel for each View and that's it. It works for simple tutorials, but doesn't for big applications.

Follow the Single Responsibility Principle - You should be able to describe what your ViewModel does in a very short sentence. It'll help you decide how many ViewModels you need for one view.

Name your ViewModels accordingly - Naming things in programming is hard, I know, but anything other than XViewModel is better already.

Think of your ViewModel as a Mediator (design pattern) - If you need to. It mediates between all sorts of different modules and presents the data gathered. It's very useful for collections for example. It's hard to divide logic of a collection, between different ViewModels, because it has to be presented in one particular place. In short, you can't have 3 ViewModels for sorting the collection, fetching the collection locally and fetching the collection remotely, because the View is bound to only one ViewModel.

MVVM Card Game

Very simple and quick example.

Requirements:

• You have a view with a table of cards
• User can put cards from a deck on the table
• The table's function is to sort the cards
• The table accepts carts that values sum to 100
• The sort result is saved to the server after sorting

Blindly following MVVM you'd put that all in CardTableViewModel, but that's bad. Here's all modules you define instead:

• UsersHand (ViewModel) - Contains logic for user's cards in the deck. Used to draw and put cards back.
•• UsersHandLocalStorage - Used by UsersHand to store the user's hand in the database.

CardsTableMediator(ViewModel) - Mediator for sorting, validating, storing the table locally and sending it to the server. It presents the table to the view, after mediating the data between all the modules.
•• CardsTableCollection, CardsTableLocalStorage, CardsTableRemoteStorage, CardsTableValidator, CardsTableSorter - Modules used by the mediator to present the table.

So, we don't have a huge ViewModel, and it's still MVVM, isn't it ?

Stop following patterns blindly and be the architect of your app.

piątek, 11 grudnia 2015

Things you need to know about Swift's runtime

When learning advanced features of Objective-C I learned how much power does knowing about it's runtime give you. I've decided to start my adventure with Swift with studying it's runtime. This way you know exactly what you're telling the computer to do. 


Class vs Struct

Ahh, the famous "class vs struct" Google search. 

Październik 2014 - October 2014 - Release of Swift

Of course, structs are less complicated, thread safe and helpful when designing immutable models. What we're interested in this post though, is the runtime. 

A lot of people will say "structs are safe, but slow, because their value has to be copied every time it's passed", and won't even imagine how wrong they are.

Structs are way faster to allocate and deallocate, because they're values, so they're stored on the stack. Operations on the stack are much faster, than complicated operations on the heap. Here's some dedicated guy that actually tested it (swift 1.2, though).

Ok, but copying structs is an operation that you're going to do often - obviously it has to be slower than just copying references ? It also should take much more memory than simple references? It doesn't have to be true. Here's what apple has to say about it:

"... “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization."


That means that when you copy structs, it doesn't have to mean that the memory copy will be executed and doubled. Swift uses copy-on-write, that makes sure that the memory will be copied only when changed.

Let vs Var

Of course you know the difference by now, but did you know that setting your variables as constants can affect the performance of your program ? Setting your variables as let tells the compiler that it can apply the value as inline in code. This means that it doesn't involve allocating any memory.

It's something that's been with us since C, but it's worth mentioning that it works the same with class, inline and instance methods. Inline, and class methods are much faster. For the same reason as above.

Is Swift dynamic or static ?


The best part for last. Swift's class methods are sometimes resolved dynamically, and sometimes statically. What this means is that the compiler knows exactly which method to call, and sometimes runtime has to lookup a vtable to find the correct method. Try to make sure that it's always static by:

Using final and private keywords - the compiler will know that the methods won't be overriden, so it can statically assign the method, otherwise it'll use a virtual table lookup to resolve.

Avoiding subclassing NSObject - this will make the class use Objective-C dynamic dispatch

• Avoid using @dynamic keyword - same

One good thing about having dynamic dispatch is method swizzling.


It's funny that good performance in Swift = clean code :)

Want to know more ? Swift has been open sourced so it's an open book now :)






czwartek, 3 grudnia 2015

Dependency Carrying in Swift (with storyboards)


Every programmer must've struggled with Dependency Carrying, even though he might've not known that it has it's own name. Dependency Carrying is extremely uncomfortable, when you have a lot of dependencies and you have to pass them deeper through the object tree. You have to define the same code for each class in the hierarchy - there must be a different way, right ?

View Controllers are actually a great example. Let's say that you have a Navigation Controller that navigates between 20 different View Controllers. If you have a database context, a networking context, you have to inject it manually into all of the controllers. What if you have 6 or 8 dependencies ? That's a lot of copy and paste injection code. What I usually did was refactor the dependencies into an aggregate and create different interfaces for that aggregate, but there must be an easier way to manage your dependencies, right ?

Swinject

I usually avoid using any dependency frameworks, because it just seems too extreme for me to have a library in your project just for a design pattern, but maybe I was wrong ? Let's try and use a dependency injection framework and see how it solves our problem.

The only reason I decided to test this approach is because Swinject is so easy and lightweight. You don't need any configuration files and it supports storyboards, which is awesome!

Let's create a new project with a storyboard and two view controllers.


Now let's create an separate file, an extension for Swinject that will run when setting up the storyboard.


That's it! Your view controllers will now be injected with the objects you've registered. I must say that I really liked it. It's very easy, you configure everything in one file and in Swift and it works great with storyboards. The code isn't very elegant, but if you have 20 view controllers you can just use a function that will inject needed dependencies depending on the view controllers protocol.

One more awesome thing: your view controllers are ready to unit test! Well, not really in my example, because I didn't obscure concrete classes with protocols, so I can't mock, but if you do, you can register a different class configuration in your unit tests and you're ready to go!

Swinject has a lot of different features that you can leverage, so you should definitely check it out!

There's very little code (that's good!), but if you want to check out how it's all connected here's the repo.

środa, 25 listopada 2015

Things I've learned while building an iOS SDK

There are times in programming when you think "I wish I knew that from the beginning". Building an SDK is quite different from making an app. You have more things to remember about and the distribution is more tricky. It's also a big responsibility, because if you screw something up, you can't just update right away - you might have a lot of users, and you don't control when they update your library and push to the store. This is a list of my i-wish-i-knews when building the Pulsate SDK

My SDK is too big!

I've started building the SDK with writing it from scratch, instead of refactoring the old code. One of my goals was to make the SDK smaller, as it was about 20 mb. When I finished an early version I was shocked to find out that the SDK still weighs the same. Only when I've educated myself about how does clang actually work - while writing this post - I realized that it's ok.

There's a big difference between a library and an executable. Library contains a lot of metadata that weighs a lot. Also, you want your static library to contain a lot of slices, including the simulator ones. The final executable strips all unneeded parts, making our demo executables with as much as 1 mb (with all the graphical assets etc.).

Also, Xcode 7 allows you to use bitcode which will reduce the executable on user's device even more. Remember to make sure you support bitcode in your library by using bitcode linker flags - if you don't, inform your users about that!

Watch out for symbol conflicts

Another big difference when building a library is that it's meant to be linked with someone else's code. Not only do you have to be careful to add prefixes to your classes to avoid symbol duplicates, but you have to make sure that you don't ship your dependencies (like AFNetworking) without making sure they're not going to clash with users using them too - It's not a problem if your code is open source and you're using CocoaPods, but it's a problem if you're shipping a compiled library. I've explained it in more detail in my other blog post.

Want to distribute compiled library through CocoaPods?

No problem! I didn't think it was possible, but it is and it's very easy. Our SDK is for commercial use only, so we couldn't open source it obviously. Check out our repo for the .podspec

Automate your process

It saves a lot of time to automate the building and distribution process. For a while I was using lipo to create a fat static library, commiting to GitHub and CocoaPods manually. I've written custom scripts that do that automatically now. It takes a couple of seconds to create a new release.

Here's my XCode script that builds both device and simulator, creating a fat library out of them and putting them in the release version folder.


Some things about the .bundle

If you need to ship your .framework with a .bundle (if you have some assets, or a CoreData model) there are some things you need to know.

The first thing that surprised me was that when we tried to publish an app with our SDK, it got rejected. Xcode automatically generates an executable and puts that executable info into the .plist file. You have to remove that executable, and .plist line from the .bundle in order for it to be accepted on iTunes. More here.

You can also distribute the .bundle file with CocoaPods.

Your users might not use some features. Create separate bundles, if you have a lot of assets, so users can choose which assets they need.

Some other tips

• Make sure you always distribute the release version
• Make sure you have a way to see what version of the SDK this is, just by looking into files. It's very useful
• Make sure you add the simulator slices
• If you're using a different server for testing, or any debug features and different for production use C macros and define a DEBUG identifier for debug builds so you make sure it won't get leaked into production like it just did for Vine.



czwartek, 1 października 2015

UITableView animations cautionary tale

I want this to be a quick post to make people aware of a certain bug/feature in iOS UITableView. For example Skype people are either not aware of it, or just don't know how to fix that. My guess is that they are aware, as you can see that the cells are fading in as if they wanted to hide that:


Even though the cells are being faded in you can see as the top cells get recycled and transformed/animated from one size to another.

Why does it happen ? When you change the height constraint on the UITableView and call layoutIfNeeded in an animation block, it'll also update the UITableView cell's contents frames in the very same animation block

Because UITableView recycles cells, the message bubble could be 30 points in width before it got recycled and you set it to 100 points width and called layoutIfNeeded in a block high in hierarchy. That's why we see it animate from 30 points to 100 points! Of course it won't happen if all contents in a UITableViewCell have a constant size. It would of course happen too without recycling, as it would animate from the initial xib/storyboard size to the dynamically calculated size.

I had a pleasure to listen one of Marin Todorov's talks on animations yesterday and I think one of the demo's suffered, or would suffer from this problem - the contents of UITableViewCells being animated as the UITableView animates. I created a quick project to duplicate his demo and this is the result, when the square's width in the UITableViewCell is random:





Take a close look at the bottom cells as they're being animated from their old size to the new size. 

What to do now ?!

I found two good solutions to this problem:

• Disable animations for the views that suffer to this problem. It's kind of a hack, but it works. For this example, I've created a dontAnimate UIView subclass and set it as the blue rectangles in the demo.


• Animating contentInset and contentOffset instead.

Did you ever have that problem ? How did you fix it ? Is that a bug ? I invite you for a discussion :)


wtorek, 11 sierpnia 2015

The Clean Code Trap

   Often times instead of just smoothly bashing away at the keyboard to produce fresh lines of code I hit the creative block. I sit in front of the screen with one thought in my mind "this isn't clean... I can't do that". After dozens of such incidents I've came to agree with one obvious conclusion: making the software work is the main goal, following principles and patterns is just a tool.

Important Distinction

   Clean Code is mostly about how easy it is to change or add new features, how easy it is to understand by a human being and how easy it is to test it.

   Clean Code isn't about following all the principles, SOLID, patterns and other hard rules you've read over the course of your career. These are just all optional tools, that may help you in making your code cleaner.

The Cost of Principles

   Every time you constraint your code to a principle or a pattern, you make a tradeoff. By making your code more abstract, easy to change or test you're making it more complex, add more classes, interfaces and indirection - it makes it harder to read and grasp by a human being.

   The hard task of Object Oriented Design is to find the golden mean to all that. It's hard, but there are a lot of rules of thumbs for each pattern that you can follow and one general I've come up with:

Don't let patterns create code, let the code create the patterns.

   Don't make the code and constantly look for occasions to force a pattern in. Don't create patterns just for the sake of creating patterns. Familiarize yourself with all the principles, all their pros and cons, know them by heart, and while creating code the need to use one will come naturally.

   Each pattern is a mean to some end, you have to ask yourself and find hard reasons to use one each time. It works similarly with anti-patterns: when you have a need to use one, but just battle with yourself because you know you shouldn't, ask yourself why shouldn't I use one in context of my code. Here are some examples:

I Feel Bad When I...

  • Downcast - Using downcasting is said to be a code-smell - a bad OOP design. "You should use polymorphism instead". Don't be afraid to use it! It's there for a reason. If you can't find another way, or just feel it's natural to do it in your context, just do it.
     
  • Use Singletons - It's thought to be an anti-pattern by many. I don't like it, but sometimes it just saves you a lot of hassle, dependency injection, delegating etc.
     
  • Use Static Classes/Methods - You can't test them, you can inject them, but they're the easier way to use utility methods.
     
  • Use Magic Strings/Numbers - My rule of thumb is: I create a constant for a magic/number string mostly when a) it's unclear what it is b) it's duplicated in the code. Don't be afraid to write Object.Height = 0; if it makes sense to you - all programmers know what it means.
     
  • Don't create interfaces for each dependency - It's reasoned, that we need to create an interface for each dependency, because it's the only way we can mock it in unit tests. For a lot of languages you can mock an object and it's behaviors without using an interface. For example, for Objective-C you use method swizzling and in Java you use reflection (implemented in Unit Test frameworks). It saves you a lot of time, complexity and you don't have 100 useless inteface files just for the sake of unit tests. It was such a relief when I deleted 15 protocols in my iOS project. You still need to pass concrete dependencies, but that's good.
     
  • Use Cross Cutting Concerns - If it doesn't bother you, that's fine! Getting rid of these is hard and usually bloats the code or makes you use libraries.
   When you hit a creative block, ask yourself: is it really that bad in the context of my code, or am I just being blocked by those stupid rules again? It's important to remember: these rules are easy to understand and apply in the void, out of context, but it turns out that it's a whole different thing when trying to apply on living software. Sometimes doing something which is deemed a bad thing in general, might be reasonable in your code.

   If you really, really feel you're doing something bad: just do it!!



Shia really wants you to do it
   Because you're here to make software for real people for the most part.Making it nicely is the second objective. Just do it and forget about it. Mark it as TODO if it makes you feel better

   Go take a walk, be with your loved ones and I guarantee you that you'll find the right way after you've stopped thinking about it :)

Bonus: Your Code Is Too SOLID




piątek, 19 czerwca 2015

What's new in iOS9 and Xcode 7 - WWDC 2015

Objective C Nullability

This was actually introduced in XCode 6.3, but it's a failry new feature presented at WWDC 2015. You can set your parameter to be nonnull or nullable:



This code will produce a warning while building, and crash in runtime if the code that passes nil to name is executed.

It looks a lot nicer with property declarations.

You can use NS_ASSUME_NONNULL_BEGIN and NS_ASSUME_NONNULL_END macros to mark blocks of code where you want your parameters/properties to be nonnull at default.

There's also null_resetable that will mark your variable to be nullable, but will never return null.

Objective C Generics!

At last! The Apple gods have listened to us. I don't mind the fact that you can hold different object types in a collection. The worst thing about NSArray was that you never knew what it held, unless you... remembered. Now you can define a NSArray to hold a specific object and get a compiler warning if you try to put there something else.
That's not all! You can use generics in your own classes too!

UIStackView

It's a small great view. If you've ever programmed in some other frameworks with a WSIWYG you're probably already familiar with it: you put views inside this layout, and it places all the elements next to each other horizontally or vertically. It'll save us developers a lot of time. A great example is a form with 10 boxes: you've had to create so many constraints to keep all of them the way you wanted. Now you just put it in a UIStackView and that's it!

Here's a quick tutorial on UIStackView.

App Thining

If you have an iOS device with 8 GB of memory, you know the pain of disk management. That's why Apple introduced app thining. It's a group of operations that are supposed to make the bundle you download from the app store smaller.

Sliicing is used to make sure you only download assets needed for your particular device. It's that simple.

On-Demand Resources lets your assets to be downloaded dynamically, not initially with the bundle. It all works smoothly in the background so you get faster initial start, without any downsides.

BitCode is a powerful but invisible feature. You upload the intermediate LLVM code to Apple Store so they can recompile your code to machine code if they make some changes or add some new architecture.

Address Sanitizer


What do you do ? Sit down, and cry... Then sit down and cry some more trying to figure it out. That's the curse of unmanaged languages - low level memory errors are very hard to debug.

But in XCode 7 you can use the Address Sanitizer tool!


  • "You enable the address sanitizer in the build scheme. Once enabled, added instrumentation is built into the app to catch memory violations immediately, enabling you to inspect the problem right at the place where it occurs. Other diagnostic information is provided as well, such as the relationship between the faulty address and a valid object on the heap and allocation/deallocation information, which helps you pinpoint and fix the problem quickly. Address sanitizer is efficient—fast enough to be used regularly, as well as with interactive applications. It is supported on OS X, in the Simulator, and on iOS devices."




Cocoa Touch Best Practices - WWDC 2015

Launch quickly

The first thing you learn is that you shouldn't do process extensive tasks on UI thread. People sometimes forget that if you do the same in the delegate callbacks you'll freeze UI.
  • Always return quickly from applicationDidFinishLaunching to launch the app as quickly as possible. Your app even might be killed if it takes too long!

Use Background Queues

Loading data from database or server on a main queue through dispatch_async is a basic thing. The problem is that if there are many operations on the main_queue it still may make the UI not responsive. The less time you spend wasting CPU cycles on the main thread, the more responsive your UI will be.
  • When dispatching use a background queue when possible

RAM Usage while suspended

When you go back to an app you instantly resume at the point where you've left it. It's a great thing in mobile devices, that lets us save our time and make the apps more responsive.

The sad truth is that your app might get killed from the suspension state. We want to make sure it lives as long as possible, right ? iOS kills the apps that use the most RAM first!


Don't bet that app!

  • When you get the applicationDidEnterBackground callback make sure you release as much data as possible. Use a background task if you need more time to clean after yourself.

Keep Your Code Unrelated To Time

Sometimes you want to do something after a certain animation finishes. You can predict how long will that animation last and just use a NSTimer and launch a block of code to happen after that time. What if in future iOS updates the time of the animation changes ? Try to keep your code relative to events and callbcks, not time. For example by using UIViewControllerTransitionCoordinator.

Clang compiler under the hood


When you build an iOS application you're not really interested with how does it all work under the hood most of the times. You just place some layout, hit "Run" or "Archive" and that's it. It just works.

It's when you start building your own library you start wondering: how does it all work?

Static Library

Clang is no different than GCC when it comes to compiling and linking. When you compile a static library you create a .a file. The so called archive file is nothing more than just a package of compiled object files. The .o files, which are in ELF format contain not only code, but also the roadmap of the file: symbols and data. This data is needed for the linker to resolve symbols at executable linking time.

When you include a static library to your executable, symbols and code are copied into the file. With -dead_strip flag enabled only the symbols used in your executable are used - it helps in reducing the executable file size.


example of "nm" and "file" programs
You can use nm to list all symbols in a file. As you can see, there are no symbols for functions, because of of Objective-C`s dynamic nature. Function symbols are internal (-g flag of nm shows only external symbols). Because of this, if you have any categories in your static library, you have to put a -ObjC or some other flag like -force_load to your linker flags, or you'll get a crash at runtime, because the functions of the category will not be copied at all, as they are not referenced anywhere. Unfortunately it makes the executable file larger*.

Symbols with U are "unresolved" meaning that they are to be resolved during the executable link time (in case of static libraries).

During the final executable link time, the linker creates a table and searches for all the needed symbols in defined search paths. If it doesn't find a needed symbol it stops the linking process with something you might be familiar with:


oops

Duplicate Symbols Problem

Objective-C doesn't have namespaces. That's why you see every library with a two or three letter prefix. It helps avoids collisions. If someone creates a class XXXModel and links his program with a static library that uses YYYModel he doesn't get a collision.

What if your static library uses AFNetworking and your library's users want to use AFNetworking too ? They'll get a collision. The most common way of solving that is to add a prefix to AFNetworking.

The other way is: using dynamic libraries.

Dynamic Libraries

A dynamic library unlike the static library isn't just a collection of code to be linked. It's a collection of code ready to be executed.

When you link your executable the dynamic library has to be present so the linker know what to reference, but the code doesn't get copied to your executable.
source


When a system loads an executable, and that executable has references to dynamic libraries, the dynamic linker searches for these libraries, loads them to RAM fills the code jump pointers for the executable.

Dynamic libraries can drastically reduce the size of an executable, not only because the code doesn't get copied, but also because you get to dynamically load AFNetworking once, not get it precompiled in every library you use.

iOS8 enabled using shared libraries, but they still get copied into the bundle. The only difference is that you can share a library between all your iOS extensions.

CocoaPods

One of CocoaPods' jobs is to manage dependencies. If you include 100 dependencies that depend on AFNetworking it'll only include the code once, not one hundred times. But that's the case for open-source software, not pre-compiled libraries.

-ObjC flag*

As I mentioned earlier -ObjC makes your executable larger, because it forces to load all files containing Objective-C code.

As I mentioned earlier categories are not loaded, because they are not referenced anywhere. What if we were to force reference them ?

Just declare any symbol in the file:


declare an extern int variable

declare the variable
Now you have to use that symbol somewhere so it gets link referenced:

That's it! Now you don't have to force your static library users to link with -ObjC flag.



czwartek, 23 kwietnia 2015

Demystifying decoupling and cohesion in Software Architecture


Decoupling and cohesion are phrases that are thrown around in software very often. You kind of know what they mean, but do you really? 

Decoupling

Coupling in software architecture usually applies to modules in OOP. It measures how dependent are modules from each other - how strong is the connection between them. Why should that bother us? The main problem is that if modules are highly coupled, that usually means that when you change something somewhere, you create a ripple effect and you have to change other modules as well.

 How do we measure it? There's no one rule, but there are some guidelines.
  • If a change in class A forces you to change other modules, it's a sign that these modules may be highly coupled
  • If you use some custom classes, instead of primitives to pass data around modules, you increase the strength of the relationship
  • If module B has a pointer to object A, and vice versa
In order to decouple modules:
  • Think of your modules as independent, as if the rest of the program didn't exist
  • Prefer abstractions - they tend to help you think of your modules as independent
  • Design patterns of course
  • Cohesive code is often decoupled
  • Prefer composition, over inheritance.
  • Use layers of architecture

                                                                                                                 source

Interfaces != Decoupling



One very common misconception is that Dependency Injection magically decouples your code. If you do this right, by abstracting your modules, it will help you to layout your code in  modules to be independent, hence decoupled. If you just create an interface for every dependency and inject it, it doesn't decouple the code, it just gives you an illusion of doing so, because interfaces aren't abstractions.

You can have decoupled code, without using one interface.

Cohesion

Cohesion is strongly connected to decoupling but there is a subtle difference. 

"In computer programming, cohesion refers to the degree to which the elements of a module belong together."

If you have low cohesive code, it's almost definitely strongly coupled. SOLID's Single Responsiblity Rule commands to created modules, with single responsibility, hence cohesive.

Your module is cohesive, if:
  • The functionalites of the class have a lot in common and the class' responsibility can be described in a simple sentence without "and", "or".
  • Doesn't use unrelated dependencies (network module using database module)

                                                                                                                           source