Some Now rellaRandom Thoughts on Objective C and related items:
So Apple has announced the Swift Programming Language at WWDC 2014.
To me this initially seems like a solution looking for a problem to solve. Development Languages need to have a reason for existence and I can't see one for Swift. It may be easy to learn (I don't think ObjectiveC was particularly hard to learn), it may work well with Xcode and it may be easy to combine with the Frameworks to build useful applications with but - So What?
So far the only nice thing is the playground concept, allowing code to be executed without a full build. This may save time when testing the implementation alternatives of code logic as the results are immediately available.
I may change my tune on this, I could see the need for Perl but hated it from day 1 and was overjoyed when Python could replace it, dislike C++ and will use ObjectiveC in preference, loved Visual Basic in its day but discarded it for C# with .Net, dismissed Java as ugly and slow and have never changed my mind on it (despite exhortations from respected colleagues) - and so on down the language chain. Swift looks to me like being in the not used enough to worry about camps.. time will tell.
Edit: from Marco.org I may need to change my tune!
Not just one for Objective C, this is a question that applies to many development languages. The use of library code provides; code reuse across applications, breaks complex applications up into logical parts that can be built and potentially released as component parts, allows for sharing of code with external developers (in many cases as community contributions) to name a few benefits. If the library is well documented we don't even need to original source code to make use of it in development projects.
The pitfalls of library code are best represented in the "DLL Hell" well known to Windows Developers and Users where an application would install its own versions of library code, breaking other applications that made use of libraries with the same name. In unix, this can be worked around with the use of symbolic links that point to different versions of libraries (Doing this is not something a normal user is likely to do) but the principal is the same, whenever we share code we need to be mindful of potential pitfalls.
Static Linking is one method to do this. Applications are compiled with library code as part of the applications footprint effectively embedding the code in the executable release. This avoids library incompatibility at the expense of disk space (much less of an issue now than in the early days of computing).
As an Objective C developer we can statically compile code with libraries, or dynamically link code (excluding the iOS platform) with a path to the library. Using dynamic libraries we have to be sure the library will exist on the computer the application is being installed on. Some applications have complex installers that work all this out but are not very Mac like and often require the user to reboot their computer at the end of the installation, which should be a complete no-no in the Mac world.
As a developer, making the decision on how to do this comes down to how we manage our project environment. For internal libraries that we have source code for we can hard code libraries into the application by copying the header and implementation files into our project. This results in a simple compilation process but means we now have the same source code files in multiple places - a real no-no for defect resolution and a nightmare for code maintenance. Do we regard one as the master and copy/overwrite files as required? Anyone working in a multi developer environment using this method has experienced the problems this creates with developers using incompatible versions of library code during the development cycle. Current thinking seems to be to include references to external files and updating the compilation settings to build using a search path. It's not perfect but it does seem to work.
Like most aspects of development, outside the syntactic restrictions of the language itself, there isn't a right and wrong answer for solving this problem, only solutions that work now that may not work in the future. For the moment I'll stick with Static libraries using referenced files and put up with having to alter the build settings for each project.
[Edit] I've taken to using sub-projects rather than direct links to library and header files. Same effect, but I can see the source code for the library if I have it.
**As an iOS user, I appreciate the logic Apple used to disallow dynamic linking for iOS applications, protecting me from malicious injections of code. I may not like it as a developer sometimes but that's not a good enough reason to change the policy.
Objective C allows for dot notation e.g.
self.Name="Barry";vs.
[self setName:@"Barry"];
In this example it's easy to see why a lot of developers prefer the dot style, it seems easier to type and at first glance easier to read. The compiler treats them the same, so they are identical functionally as well.
It does however mask the nature of what is actually being done - send a message to the object calling the method setName with the value of Barry. The dot notation implies we are setting a property of self to be Barry by direct assignment the same as if the object self was a struct with a Name property!. Now consider a method with more than one parameter:
[self calculateVolumeWithDepth:32 andWidth:12 andHeight:14];
This cannot be called with dot notation so your code would be mixed with styles. Annoyingly if the method only has one parameter it can be called using dot notation e.g.
self.calculateVolumeUsingEqualWHD=12;
This probably leads many developers to using dot notation where they perhaps shouldn't be.
I also use this style a lot:
dayCount = [aDateCalc countDaysBetweenDate1:[NSDate dateWithString:@"2012-01-16 00:00:00 +0000"] andDate2:[NSDate dateWithString:@"2012-03-30 00:00:00 +0000"] usingDateConvention:ACTon360];
Fitting all that in a dot notation style doesn't appear possible on a single line.
For reasons of consistency I'll stick with [] unless a clients style guide explicitly prohibits it.
When looking at accessing a property however - is:
var=self.namebetter or worse than
var=[self name]Hmm, I'm more familiar with the dot notation and there seems to be no distinction in purpose. I admit here to preferring and using dot notation.
Another style question - Many developers prefer to do:
if (somecondition) { doSomething; }
Me, I prefer:
if (somecondition) { doSomething; }
Why? One reason - I fold code a lot in Xcode and:
if (somecondition) {...}
is easier on the eye than:
if (somecondition) {...}
I also prefer to have the else/else if on its own line:
if (somecondition) { doSomething; } else { doSomethingElse; }
Everybody is doing Test driven development these days aren't you?
OK all you old school C developers and those of you who write code without a decent test framework can put your hands back down.
Test Driven Development is an incredibly useful paradigm that allow you to produce significantly more robust code and importantly change parts of it with very high levels of assurance you'll identify if the change broke something before you hand it over to the test team (or worse a user) and they start to pick holes in your hard work. If you've written tests from the ground up you'll have exercised all the low level functionality, moved on to more significant chucks of logic and finally to a test case that aligns with a user requirement. A lot of thought will have gone into how the code will be tested before it's written in such a way it can only be tested by hand.
What about the number of tests and should we allow multiple asserts per test?
The literature and body of knowledge has a "one test one assert" as a golden rule. For the most part this makes sense and it certainly should be followed if the test tool being used cannot run all tests if one of the asserts fails! Thankfully Xcode will run all the tests and highlight which Asserts have failed, removing one reason for the rule.
Assume we have some code in a single method or routine that uses conditional logic - Do I have a single test with multiple routines or split into multiple tests?
Let's use an example where I have business logic that says "if the period between two dates covers a leap year the number of days in the year = 366 unless the last date is the end of February". My initial pseudo test cases would be written like:
and I could write 3 test cases for each event, then write code to validate test 1, then test 2, etc or I could write a complicated test harness with parameters - but then I think we've made the test harness more complicated than the underlying code and that's not a great idea either.
I think it's better to have a single test case called for example:
testLeapYearDaysRule {...}
with the 3 rules contained in 3 asserts and a method
- (int) daysInYearBetweenDate1:(NSDate) *startDate andDate2:(NSDate) *endDate {...}
Our Test Case would then look something like:
- (void) testLeapYearDaysRule { ... yearCount = [aDateCalc daysInYearBetweenDate1:[NSDate dateWithString:@"2012-01-16 00:00:00 +0000"] andDate2:[NSDate dateWithString:@"2012-03-30 00:00:00 +0000"]]; XCTAssertEqual(yearCount, 366, @"yearCount should be 366 is %ld", yearCount); yearCount = [aDateCalc daysInYearBetweenDate1:[NSDate dateWithString:@"2012-01-16 00:00:00 +0000"] andDate2:[NSDate dateWithString:@"2012-02-29 00:00:00 +0000"]]; XCTAssertEqual(yearCount, 365, @"yearCount should be 365 is %ld", yearCount); yearCount = [aDateCalc daysInYearBetweenDate1:[NSDate dateWithString:@"2011-01-16 00:00:00 +0000"] andDate2:[NSDate dateWithString:@"2011-03-30 00:00:00 +0000"]]; XCTAssertEqual(yearCount, 365, @"yearCount should be 365 is %ld", yearCount); }
Then the code would be written to make each assert pass. I now only have one place to look to see what tests are being run on that code routine
There are a number of things I like about Xcode 5 over earlier versions. Interestingly the thing I wanted the most - a single window for most tools - has turned into something I'm not as sure about.
When I came back to writing Mac/iOS software from a long period using Visual Studio, the thing that annoyed me the most was the number of separate Windows that were open at the same time in Xcode for routine development tasks. I really wanted a VS like IDE with most things in one window.
Using a Desktop with Multiple Monitors and a Laptop with Spaces has made me change my tune a bit. The desktop allows me to have windows open on each screen, and Spaces allows me to create screens for each task I'm working on, on the laptop. Having (nearly) everything in one window means space is either wasted with panels being open or I'm clicking show/hide a lot (especially on a small laptop). Maybe I was wrong...
One thing I would still really like is an open API to extend/modify Xcode. Perhaps in Xcode 6?