Nikola Brežnjak blog - Tackling software development with a dose of humor
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Home
Daily Thoughts
Ionic
Stack Overflow
Books
About me
  • Home
  • Daily Thoughts
  • Ionic
  • Stack Overflow
  • Books
  • About me
Nikola Brežnjak blog - Tackling software development with a dose of humor
Programming

Code Complete 2 – Steve McConnell – The Power of Variable Names

I just love Steve McConnell’s classic book Code Complete 2, and I recommend it to everyone in the Software ‘world’ who’s willing to progress and sharpen his skills.

Other blog posts in this series:

  • Part 1 (Chapters 1 – 4): Laying the Foundation
  • Chapter 5: Design in Construction
  • Chapter 6: Working Classes
  • Chapter 7: High-Quality Routines
  • Chapter 8: Defensive programming
  • Chapter 9: Pseudocode Programming Process
  • Chapter 10: General Issues in Using Variables

The Most Important Naming Consideration

The name must fully and accurately describe the entity that the variable represents. Names should be as specific as possible. Names like x, temp, and i that are general enough to be used for more than one purpose are not as informative as they could be and are usually bad names.

Variable names should be 10 to 16 characters long.

Computed-Value Qualifiers in Variable Names

Many programs have variables that contain computed values: totals, averages, maximums, and so on. If you modify a name with a qualifier, put the modifier at the end of the name. Try to avoid using num, instead use customerCount for total numbers of customers and customerIndex refers to a specific customer.

By establishing this convention, you avoid the confusion you might create if you were to use both totalRevenue and revenueTotal in the same program.

Naming Status Variables

Think of a better name than flag for status variables.

Here are some examples of flags with bad names:

if ( flag ) ...
if ( printFlag == 16) ...
if ( statusFlag & 0x0F) ...

Statements like statusFlag = 0x80 give you no clue about what the code does unless you wrote the code or have a documentation. Here are equivalent code examples that are clearer:

if ( dataReady ) ...
if ( reportType == ReportType_Annual ) ...
if ( characterType & PRINTABLE_CHAR ) ...

Clearly, characterType = CONTROL_CHARACTER is more meaningful than statusFlag = 0x80.

Naming Temporary Variables

They’re usually called temp, x, or some other vague and non-descriptive name. In general, temporary variables are a sign that the programmer does not yet fully understand the problem. Moreover, because the variables are officially given a “temporary” status, programmers tend to treat them more casually than other variables, increasing the chance of errors.

Naming Boolean Variables

  • Keep typical boolean names in mind:
    • done
    • error
    • found
    • success or ok – if you can, replace success with a more specific name that describes precisely what it means to be successful
  • Give boolean variables names that imply true or false
    • Names like status and sourceFile are poor boolean names because they’re not obviously true or false. What does it mean if status is true? For a better result, replace status with a name like statusOK, and _sourceFile_ with _sourceFileAvailable_ or _sourceFileFound_
  • Use positive boolean variable names – negative names like notFound or notDone are difficult to read when they are negated

Naming Constants

When naming constants, name the abstract entity the constant represents rather than the number the constant refers to. FIVE is a bad name for a constant (regardless of whether the value it represents is 5.0). CYCLES_NEEDED is a good name.

The key is that any convention at all is often better than no convention.

Guidelines for a Language-Independent Convention

  • variableName
  • RoutineName()
  • functionInsideClass()
  • ClassName
  • g_GlobalVariable
  • CONSTANT
  • i or j are integer indexes.

Sematic Prefixes

  • c – Count
  • first – The first element that needs to be dealt with in an array.
  • g – Global variable.
  • i – Index into an array.
  • last – The last element that needs to be dealt with in an array.
  • lim – The upper limit of elements that need to be dealt with in an array. Generally, lim equals last + 1.
  • m – Class-level variable
  • max – The absolute last element in an array or another kind of list. max refers to the array itself rather than to operations on the array
  • min – The absolute first element in an array or another kind of list.
  • p – Pointer.

Advantage of standardized prefixes – they give you all the general advantages of having a naming convention as well as several other advantages. Because so many names are standard, you have fewer names to remember in any single program or class.

Kinds of Names to Avoid

  • Avoid names with similar meanings. For example, input and inputValue
  • Avoid numerals in names. E.g. file1 and file2. You can almost always think of a better way to differentiate between two variables than by adding a 1 or 2 onto the end of the name.
  • Avoid words that are commonly misspelled in English: absense, acummulate, acsend, calender, concieve, defferred, definate, independance, occassionally, prefered, reciept and so on…
Programming

Code Complete 2 – Steve McConnell – General Issues in Using Variables

I just love Steve McConnell’s classic book Code Complete 2, and I recommend it to everyone in the Software ‘world’ who’s willing to progress and sharpen his skills.

Other blog posts in this series:

  • Part 1 (Chapters 1 – 4): Laying the Foundation
  • Chapter 5: Design in Construction
  • Chapter 6: Working Classes
  • Chapter 7: High-Quality Routines
  • Chapter 8: Defensive programming
  • Chapter 9: Pseudocode Programming Process

It’s easy to start using hazardous practices before you’re fully aware of your alternatives and then to continue to use them out of habit even after you’ve learned ways to avoid them.

Implicit Declarations

An implicit declaration is one of the most hazardous features available in any language. For example, if you use a variable in Microsoft Visual Basic without declaring it, the compiler declares it for you automatically (depending on your compiler settings).

What do you do if you program in a language with implicit declarations? Here are some suggestions:
+ Turn off implicit declaration
+ Declare all variables – as you type in a new variable, declare it, even though the compiler doesn’t require you to
+ Use naming conventions – establish a naming convention for common suffixes such as Num and No so that you don’t use two variables when you mean to use one
+ Check variable names – use cross-reference list generated by your compiler or another utility program

Guidelines for initializing variables

Improper data initialization is one of the most fertile sources of error in computer programming. Developing effective techniques for avoiding initialization problems can save a lot of debugging time.

The problem with improper initialization stem from a variable’s containing an initial value that you do not expect it to contain. This can happen for any of several reasons:

  • The variable has never been assigned a value. Its value is whatever bits happened to be in its area of memory when the program started
  • The value of the variable is outdated. The variable was assigned a value at some point, but the value is no longer valid
  • Part of the variable has been assigned a value and part has not. That can happen when you initialize some of the members of an object but not all of them

Guidelines for avoiding initialization problems:

  • Initialize each variable as it’s declared
  • Declare and initialize each variable close to where it’s first used
  • Use final or const when possible
  • Pay special attention to counters and accumulators. A common error is forgetting to reset a counter or an accumulator before the next time it’s used.

Scope

Scope, or visibility, refers to the extent to which your variables are known and can be referenced throughout a program.

One method of measuring how close together the references to a variable are is to compute “span” of a variable. Here’s an example:

a = 0;
b = 0;
c = 0;
a = b + c;

In this case, two lines come between the first reference to a and the second, so a has a span of two. The main advantage of keeping references to variables together is that it improves program readability.

Live time

A concept that’s related to variable span is variable “live time,” the total number of statements over which a variable is live. A variable’s life begins at the first statement in which it’s referenced; its life ends at the last statements in which it’s referenced.

Comments on scope

Many programmers approach to minimizing variables scope depends on their views of the issues of “convenience” and “intellectual manageability.” The difference boils down to a difference in emphasis between writing programs and reading them. Maximizing the scope might indeed make programs easy to write, but a program in which any routine can use any variable at any time is harder to understand.

Using each variable for exactly one purpose

It’s possible to use variables for more than one purpose in several subtle ways. You’re better off without this kind of subtlety.

  • Use each variable for one purpose only – it’s sometimes tempting to use one variable in two different places for two different activities. Usually, the variable is named inappropriately for one of its uses, or a “temporary” variable is used in both cases

  • Avoid variables with hidden meanings

    • The value in the variable pageCount might represent the number of pages printed unless it equals -1, in which case it indicates that an error has occurred
    • The variable bytesWritten might be the number of bytes written to an output file, unless its value is negative, in which case it indicates the number of the disk drive used for the output
  • Make sure all declared variables are used – the opposite of using a variable for more than one purpose is not using it at all

Ionic

Cordova Ionic Plugin for Search Ads App Attribution API

TL;DR

Cordova plugin for reading Search Ads App Attribution on iOS 10.0+ only with an Ionic demo showcasing its usage.

The Search Ads API plugin for Cordova/Ionic didn’t exist, so I created it. You can check out the plugin code on Github, view the Ionic demo app code on Github or read onward for an example on how to use it.

You can also check out the step by step tutorial about How to create a native iOS app that can read Search Ads Attribution API information if you’re not into hybrid solutions ?

What is Search Ads App Attribution?

From Apple’s documentation:

Search Ads App Attribution enables developers to track and attribute app downloads that originate from Search Ads campaigns. With Search Ads App Attribution, iOS developers have the ability to accurately measure the lifetime value of newly acquired users and the effectiveness of their advertising campaigns.

How to use the plugin

If you want to test this on a blank project, you can create a new Ionic project like this:

ionic start ionicSearchAdsDemo tabs

Since the plugin has been added to npm repository, you can simply add it like this:

ionic plugin add cordova-plugin-searchads

Add the following code in the controllers.js file under the DashCtrl controller:

.controller('DashCtrl', function($scope, $ionicPlatform) {
    $scope.data = 'no data';

    $ionicPlatform.ready(function() {
        if (typeof SearchAds !== "undefined") {
            searchAds = new SearchAds();

            searchAds.initialize(function(attribution) {
                console.dir(attribution); // do something with this attribution (send to your server for further processing)
                $scope.data = JSON.stringify(attribution);
            }, function (err) {
                console.dir(err);
            });
        }
    });
})

Replace the content of the templates/tab-dash.html file with this:

<ion-view view-title="Dashboard">
  <ion-content class="padding">
    <div class="card">
      <div class="item item-text-wrap">
        {{data}}
      </div>
    </div>
  </ion-content>
</ion-view>

Prepare the project by executing the following command in your terminal:

ionic prepare ios && open platforms/ios

After this, open up the XCode project (*.xcodeproj) file:

Make sure the iAd.framework has been added to Linked Frameworks and Libraries:

This should have happened automatically when you’ve added the plugin, but it’s good to make sure. Add it yourself if you don’t see it here.

Run the project on your device, and you should get something like this:

Hope this proves to be useful to someone! ?

#Cordova #Ionic Plugin for Search Ads App Attribution API https://t.co/D4yMevINOf

— Nikola Brežnjak (@HitmanHR) September 14, 2017

iOS

How to create a native iOS app that can read Search Ads Attribution API information

TL;DR

In this post, I’ll show you how easy it is to create a native iOS app that can read Search Ads Attribution API information.

You can check out the full working code on Github.

What is Search Ads App Attribution?

From Apple’s documentation:

Search Ads App Attribution enables developers to track and attribute app downloads that originate from Search Ads campaigns. With Search Ads App Attribution, iOS developers have the ability to accurately measure the lifetime value of newly acquired users and the effectiveness of their advertising campaigns.

Steps to recreate this yourself

  • Create a new blank project in Xcode
  • Add a label on the Main.storyboard:

  • Create an Interface Builder Outlet for this label and name it searchAdsInfoLabel. For those not familiar with iOS development, this is done by pressing Ctrl and dragging the label into the ViewController.swift file.

  • Once done, you should see this in your ViewController.swift file:
import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var searchAdsInfoLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
  • Next, import iAd to your project:

  • import iAd in your ViewController.swift file: import iAd.

Add the following function to the ViewController.swift file:

func getSearchAdsInfo() {
    ADClient.shared().requestAttributionDetails({ (attributionDetails, error) in
        if error == nil {
            for (type, adDictionary) in attributionDetails! {
                print(type);
                print(adDictionary);

                let attribution = adDictionary as? Dictionary<AnyHashable, Any>;

                let iadAdgroupId = attribution?["iad-adgroup-id"] as? String
                let iadAdgroupName = attribution?["iad-adgroup-name"] as? String
                let iadAttribution = attribution?["iad-attribution"] as? String
                let iadCampaignId = attribution?["iad-campaign-id"] as? String
                let iadCampaignName = attribution?["iad-campaign-name"] as? String
                let iadClickDate = attribution?["iad-click-date"] as? String
                let iadConversionDate = attribution?["iad-conversion-date"] as? String
                let iadCreativeId = attribution?["iad-creative-id"] as? String
                let iadCreativeName = attribution?["iad-creative-name"] as? String
                let iadKeyword = attribution?["iad-keyword"] as? String
                let iadLineitemId = attribution?["iad-lineitem-id"] as? String
                let iadLineitemName = attribution?["iad-lineitem-name"] as? String
                let iadOrgName = attribution?["iad-org-name"] as? String

                self.searchAdsInfoLabel.text = "iad-adgroup-id: \(iadAdgroupId ?? "")\niad-adgroup-name: \(iadAdgroupName ?? "")\niad-attribution: \(iadAttribution ?? "")\niad-campaign-id: \(iadCampaignId ?? "")\niad-campaign-name: \(iadCampaignName ?? "")\niad-click-date: \(iadClickDate ?? "")\niad-conversion-date: \(iadConversionDate ?? "")\niad-creative-id: \(iadCreativeId ?? "")\niad-creative-name: \(iadCreativeName ?? "")\niad-keyword: \(iadKeyword ?? "")\niad-lineitem-id: \(iadLineitemId ?? "")\niad-lineitem-name: \(iadLineitemName ?? "")\niad-org-name: \(iadOrgName ?? "")"
            }
        }
    })
}

Call this function in the viewDidLoad() method.

The full code listing, of the ViewController.swift file should now look like this:

import UIKit
import iAd

class ViewController: UIViewController {
    @IBOutlet weak var searchAdsInfoLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        getSearchAdsInfo();
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func getSearchAdsInfo() {
        ADClient.shared().requestAttributionDetails({ (attributionDetails, error) in
            if error == nil {
                for (type, adDictionary) in attributionDetails! {
                    print(type);
                    print(adDictionary);

                    let attribution = adDictionary as? Dictionary<AnyHashable, Any>;

                    let iadAdgroupId = attribution?["iad-adgroup-id"] as? String
                    let iadAdgroupName = attribution?["iad-adgroup-name"] as? String
                    let iadAttribution = attribution?["iad-attribution"] as? String
                    let iadCampaignId = attribution?["iad-campaign-id"] as? String
                    let iadCampaignName = attribution?["iad-campaign-name"] as? String
                    let iadClickDate = attribution?["iad-click-date"] as? String
                    let iadConversionDate = attribution?["iad-conversion-date"] as? String
                    let iadCreativeId = attribution?["iad-creative-id"] as? String
                    let iadCreativeName = attribution?["iad-creative-name"] as? String
                    let iadKeyword = attribution?["iad-keyword"] as? String
                    let iadLineitemId = attribution?["iad-lineitem-id"] as? String
                    let iadLineitemName = attribution?["iad-lineitem-name"] as? String
                    let iadOrgName = attribution?["iad-org-name"] as? String

                    self.searchAdsInfoLabel.text = "iad-adgroup-id: \(iadAdgroupId ?? "")\niad-adgroup-name: \(iadAdgroupName ?? "")\niad-attribution: \(iadAttribution ?? "")\niad-campaign-id: \(iadCampaignId ?? "")\niad-campaign-name: \(iadCampaignName ?? "")\niad-click-date: \(iadClickDate ?? "")\niad-conversion-date: \(iadConversionDate ?? "")\niad-creative-id: \(iadCreativeId ?? "")\niad-creative-name: \(iadCreativeName ?? "")\niad-keyword: \(iadKeyword ?? "")\niad-lineitem-id: \(iadLineitemId ?? "")\niad-lineitem-name: \(iadLineitemName ?? "")\niad-org-name: \(iadOrgName ?? "")"
                }
            }
        })
    }
}

After you run the project (make sure you run it on your device, as you won’t get any data back on the simulator) you should get some stub data that Apple returns:

Conclusion

If you’re utilizing Apple’s Search Ads, then I hope this helped you see how easy it is to fetch Search Ads App Attribution information in your app.

Of course, once you get the data, you should send this to your server for saving and further analysis.

How to create a #native #iOS app that can read Search Ads Attribution API information #SearchAdsAttribution https://t.co/6HDQBtzmM7

— Nikola Brežnjak (@HitmanHR) September 10, 2017

Programming

Code Complete 2 – Steve McConnell – Pseudocode Programming Process

I just love Steve McConnell’s classic book Code Complete 2, and I recommend it to everyone in the Software ‘world’ who’s willing to progress and sharpen his skills.

Other blog posts in this series:

  • Part 1 (Chapters 1 – 4): Laying the Foundation
  • Chapter 5: Design in Construction
  • Chapter 6: Working Classes
  • Chapter 7: High-Quality Routines
  • Chapter 8: Defensive programming

The benefits you can expect from using the pseudocode:

  • makes reviews easier – you can review detailed designs without examining the source code
  • supports the idea of iterative refinement
  • makes changes easier – a few lines of pseudocode are easier to change than a page of code
  • it’s easier to maintain than other forms of design documentation

Steps in building a routine

  1. Design the routine
  2. Code the routine
  3. Check the code
  4. Clean up loose ends
  5. Repeat as needed

1. Design the routine

  • Check the prerequisites to see that the job of the routine is well defined and fits cleanly into the overall design
  • Define the problem the routine will solve
  • Name the routine – good routine names are one sign of a superior program and they’re not easy to come up with
  • Decide how to test the routine
  • Research functionality available in the standard libraries – the single biggest way to improve both the quality of your code and your productivity is to reuse good code
  • Think about error handling – think about all the things that could possibly go wrong in the routine
  • Think about efficiency – in a vast majority of systems, efficiency isn’t critical. Design your routine so that it will meet its resource and speed goals
  • Research the algorithms and data types – if functionality isn’t available in the available libraries, it might still be described in an algorithms book
  • Write the pseudocode – you might not have much in writing after you finish the preceding steps. The main purpose of the steps is to establish a mental orientation that’s useful when you actually write the routine
  • Think about the data
  • Check the pseudocode – once you’ve written the pseudocode and designed the data, take a minute to review the pseudocode you’ve written. Back away from it, and think about how you would explain it to someone else
  • Try a few ideas in pseudocode, and keep the best (iterate)

2. Code the routine

  • Start with pseudocode
  • Write the routine declaration
    • Turn the original header comment into a programming-language code comment above declaration
  • Write the first and last statements, and turn the pseudocode into high-level comments
    /* Header comment about what routine does */
    Status ReportErrorMessage(
        ErrorCode errorToReport
    ) {
        //set the default status to "fail"

        //if the error code is valid, display the error message 
        //and declare success

        //if the error code isn't valid, notify the user that an internal 
        //error has been detected

        //return status information
    }
  • Fill in the code below each comment
/* Header comment about what routine does */
Status ReportErrorMessage(
    ErrorCode errorToReport
) {
    //set the default status to "fail"
    Status errorMessageStatus = Status_Failure;

    //if the error code is valid, display the error message 
    //and declare success
    if ( errorMessage.ValidCode() ) {
        DisplayMessage( errorMessage.Text() );
        errorMessageStatus = Status_Success;
    }

    //if the error code isn't valid, notify the user that an internal 
    //error has been detected
    else {
        DisplayMessage( "Internal Error: Invalid error code in ReportErrorMessage()" );
    }

    //return status information
    return errorMessageStatus;
}

Each comment should normally expand to about 2 to 10 lines of code.

3. Check the code

  • Mentally check the routine for errors

A working routine isn’t enough. If you don’t know why it works, study it, discuss it, and experiment with alternative designs until you do.

Compile the routine after reviewing it. It might seem inefficient to wait this long to compile. You’ll benefit in several ways, however, by not compiling until late in the process. After the first compile, you step up the pressure: “I’ll get it right with just one more compile.” The “Just One More Compile” syndrome leads to hasty, error-prone changes that take more time in the long run.

  • Step through the code in the debugger
  • Test the code

4. Clean up leftovers

  • Check the routine’s interface. Make sure that all input and output data is accounted for and that all parameters are used
  • Check for general design quality. Make sure the routine does one thing and does it well, that it’s loosely coupled to other routines, and that it’s designed defensively
  • Check the routine’s variables (inaccurate variable names, unused objects, undeclared variables, and so on)
  • Check routine’s statements and logic
  • Remove redundant comments

Alternatives to the PPP

  • Test-first development – popular development style in which test cases are written before writing any code
  • Refactoring – development approach in which you improve code through a series of semantic preserving transformation
  • Design by contract – development approach in which each routine is considered to have preconditions and postconditions
  • Hacking? – some programmers try to hack their way toward working code rather than using a systematic approach like the PPP. If you’ve ever found that you’ve coded yourself into a corner in a routine and have to start over, that’s an indication that the PPP might work better
iOS

How to use fastlane pem to automatically generate and renew your VoIP push notification profiles

In the previous tutorial, I showed you how easy it is to use fastlane pem to automatically generate and renew your push notification profiles.

In this tutorial, I’ll do the same thing, but for VoIP notifications. I found the solution in this Github issue.

In your project’s root folder create a new folder called fastlane.

Then, create a file called Fastfile in the fastlane folder.

Put the following content into Fastfile:

lane :voip_cert do
    app_identifier = "com.nikola.mygreatapp"
    apple_id = "[email protected]"
    output_path = "."
    p12_password = "password"

    UI.important "Creating a new push certificate for app '#{app_identifier}'."

    Spaceship.login(apple_id)
    Spaceship.client.select_team
    csr, pkey = Spaceship::Certificate.create_certificate_signing_request
    cert = Spaceship::Certificate::VoipPush.create!(csr:csr,bundle_id:app_identifier)

    x509_certificate = cert.download
    certificate_type = "voippush"
    filename_base = "#{certificate_type}_#{app_identifier}"

    p12_cert_path = File.join(output_path, "#{filename_base}.p12")
    p12 = OpenSSL::PKCS12.create(p12_password, certificate_type, pkey, x509_certificate)
    File.write(p12_cert_path, p12.to_der)
    UI.message("p12 certificate: ".green + Pathname.new(p12_cert_path).realpath.to_s)

    x509_cert_path = File.join(output_path, "#{filename_base}.pem")
    File.write(x509_cert_path, x509_certificate.to_pem + pkey.to_pem)
    UI.message("PEM: ".green + Pathname.new(x509_cert_path).realpath.to_s)
end

Make sure you enter the appropriate app_identifier and apple_id and password (if you’re using it).

Execute the following command from your app’s root directory:

fastlane voip_cert

You should see something like this in the output:

nikola in ~/DEV/TheOnlyAppThatMatters on git:feature/make-app-great-again ✖︎ [06:06:06]
→ fastlane voip_cert
[06:06:06]: Get started using a Gemfile for fastlane https://docs.fastlane.tools/getting-started/ios/setup/#use-a-gemfile
[06:06:06]: Driving the lane 'voip_cert' ?
[06:06:06]: Creating a new push certificate for app 'com.nikola.mygreatapp'.
[06:06:06]: p12 certificate: /Users/nikola/DEV/TheOnlyAppThatMatters/fastlane/voippush_com.nikola.mygreatapp.p12
[06:06:06]: PEM: /Users/nikola/DEV/TheOnlyAppThatMatters/fastlane/voippush_com.nikola.mygreatapp.pem
[06:06:06]: fastlane.tools finished successfully ?

And that’s it! Hope this proves to be helpful for you! ?

How to use fastlane pem to automatically generate and renew your #VoIP push notification profiles https://t.co/AvbKkbhRWD

— Nikola Brežnjak (@HitmanHR) September 7, 2017

iOS

How to use fastlane pem to automatically generate and renew your push notification profiles

This is a short tip which will save you a lot of time!

Ever gone through the tedious task of manually creating and maintaining your push notification profiles for your iOS apps? Tutorials like this one were very useful, but nowadays thanks to fastlane pem, you can do it with a single command.

The pem tool creates new .pem, .cer, and .p12 files to be uploaded to your push server if a valid push notification profile is needed.

To install pem run:

sudo gem install fastlane

Also, make sure you have the latest version of the Xcode command line tools installed:

xcode-select --install

Then, just run fastlane pem and it will ask you information about the app for which you wish to renew the certificates.

You can pass parameters like this:

fastlane pem -a com.mygreat.app -u username

If you want to generate a development certificate run:

fastlane pem --development

To get a list of available options run:

fastlane pem --help

?

If you’re looking to generate the same thing but for VoIP push notification, then check out this tutorial.

How to use fastlane pem to automatically generate and renew your #push notification profiles https://t.co/cutGxIDH6Y

— Nikola Brežnjak (@HitmanHR) September 7, 2017

Books

Resilience: Hard-Won Wisdom for Living a Better Life

My favorite quotes from the book Resilience: Hard-Won Wisdom for Living a Better Life by Eric Greitens which I rated 5/5 on my Goodreads account:

What you will become is a result of what you are willing to endure.

Use what hits you to change your trajectory in a positive direction.

The world breaks everyone and afterward many are strong at the broken places. But those that will not break it kills.

God, grant me the serenity to accept the things I cannot change, Courage to change the things I can, And wisdom to know the difference.

Great changes come when we make small adjustements with great conviction.

Action without direction rarely leads to progress.

Anyone who does anything meaningful will have critics.

A focus on excellence will, over time, lead to happiness.

Not what we have, but what we enjoy constitues our abundance.

Any fool can learn from his mistakes. Wise man learns from mistakes of others.

If you want to feel differently – act differently! At first it will feel like a lie, but ‘be’ what you would like to be and you’ll become it.

People who think you’re weak will offer you an excuse. People who respect you will offer you a challenge.

If you want to live a purposeful life, you have to create your purpose.

Working hard yourself makes you more appreciative and respectful of the hard work of others.

He who fears he shall suffer, already suffers what he fears.

  1. Why am I here?
  2. What’s going around me?
  3. What am I going to do about it?
  4. How will my actions affect others?

When the child is skillful he boasts. When the warrior has a skill, he teaches. When the child is strong, he attacks the weak. When the warrior is strong, he protects the weak. The child criticises others to make himself feel better. The warrior is his own most demanding critic.

Warriors are expected to combine courage and ferocity in battle with decency and humanity in victory.

My #notes from a great #book Resilience Hard-Won Wisdom for Living a Better Life by Eric Greitens https://t.co/HSJDYOniIj

— Nikola Brežnjak (@HitmanHR) September 4, 2017

Programming

Code Complete 2 – Steve McConnell – Defensive programming ?️

I just love Steve McConnell’s classic book Code Complete 2, and I recommend it to everyone in the Software ‘world’ who’s willing to progress and sharpen his skills.

Other blog posts in this series:

  • Part 1 (Chapters 1 – 4): Laying the Foundation
  • Chapter 5: Design in Construction
  • Chapter 6: Working Classes
  • Chapter 7: High-Quality Routines

Defensive-programming techniques make errors easier to find, easier to fix, and less damaging to production code.

Assertions

An assertion is a code that’s used during development-usually a routine or macro- that allows a program to check itself as it runs. When an assertion is true, that means everything is operating as expected.

Use error handling code for conditions you expect to occur and assertions for conditions that should never occur.

Design by contract

Preconditions and post conditions are part of an approach to program design and development known as “design by contract”.

  • Preconditions are properties that the client code of a routine or class promises will be true before it calls the routine or instantiates the object.
  • Postconditions are the properties that the routine or class promises will be true when it concludes executing.

For highly robust code, assert and then handle the error anyway.

Some experts argue that only one kind is needed. But real-world programs and projects tend to be too messy to rely solely on assertions.

Error-Handling Techniques

Depending on the specific circumstances, you might want to:

  • Return a neutral value
  • Substitute the next piece of valid data
  • Return the same answer as the previous time
  • Substitute the closest legal value
  • Log a warning message to a file
  • Return an error code
  • Call an error-processing routine/object
  • Shut down

Correctness means never returning an inaccurate result; returning no result is better than returning an inaccurate result.

Robustness means always trying to do something that will allow the software to keep operating, even if that leads to results that are inaccurate sometimes.

Safety-critical applications tend to favor correctness to robustness.

Consumer applications tend to favor robustness to correctness. Any result whatsoever is usually better than the software shutting down.

Exceptions

Exceptions have an attribute in common with inheritance: used judiciously, they can reduce complexity. Used imprudently, they can make code almost impossible to follow.

What you should know about using exceptions:

  • Use exceptions to notify other parts of the program about errors that should not be ignored
  • Throw an exception only for conditions that are truly exceptional
  • Don’t use an exception to pass the buck – handle error locally
  • Avoid throwing exceptions in constructors and destructors unless you catch them in the same place
  • Throw exceptions at the right level of abstraction

Use barricades

Defining some parts of the software that works with dirty data and some that work with clean data can be an effective way to relieve the majority of the code of the responsibility for checking for bad data.

Debugging Aids

Another key aspect of defensive programming is the use of debugging aids, which can be a powerful ally in quickly detecting errors.

Be willing to trade speed and resource usage during development in exchange for built-in tools that can make development go more smoothly.

Determining how much defensive programming to leave in production code

One of the paradoxes of defensive programming is that during development, you’d like an error to be noticeable-you’d rather have it be obnoxious than risk overlooking it. But during production, you’d rather have the error be as unobtrusive as possible, to have the program recover or fail gracefully.

Here are some guidelines for deciding which defensive programming tools to leave in your production code and which to leave out:

  • Leave the code that checks for important errors
  • Remove code that checks for trivial errors
  • Remove code that results in hard crashes
  • Leave the code that helps the program crash gracefully

Being defensive about defensive programming

Too much defensive programming creates a problem of its own. Code installed for defensive programming is not immune to defects, and you’re just as likely to find a defect in defensive-programming code as in any other code-more likely if you write the code casually.

My #notes from a great #book CC 2 by Steve McConnell chapter on Defensive programming ?️ https://t.co/KnBqvEySJd

— Nikola Brežnjak (@HitmanHR) September 4, 2017

Programming

Code Complete 2 – Steve McConnell – High-Quality Routines

I just love Steve McConnell’s classic book Code Complete 2, and I recommend it to everyone in the Software ‘world’ who’s willing to progress and sharpen his skills.

Other blog posts in this series:

  • Part 1 (Chapters 1 – 4): Laying the Foundation
  • Chapter 5: Design in Construction
  • Chapter 6: Working Classes

Routines are used to:

  • reduce complexity
  • introduce an intermediate, understandable abstraction
  • avoid duplicate code
  • hide sequences
  • hide pointer operations
  • improve portability
  • simplify complicated boolean tests and
  • improve performance

Functional cohesion

Functional cohesion is when a function performs one and only one operation.

Cohesions that are considered to be less than ideal:

  • Sequential cohesion
    • exist when a routine contains operations that must be performed in a specific order, that share data from step to step.
  • Communicational cohesion
    • occurs when operations in a routine make use of the same data and aren’t related in any other way.
  • Temporal cohesion
    • occurs when operations are combined into a routine because they are all done at the same time. Think of temporal routines as organizers of other events.

Unacceptable kinds of cohesion:

  • Procedural cohesion
  • Logical cohesion
  • Coincidental cohesion

Good routine names and length

Research shows that the optimum average length for a variable name is 9-15 characters and 15-20 for a routine name.

To name the function use the description of the return value. In object-oriented languages, you don’t need to include the name of the object in the procedure name because the object itself is included in the call.

Avoid names like: document.PrintDocument().

A large percentage of routines in object-oriented programs will be accessor routines, which will be very short. From time to time, a complex algorithm will lead to a longer routine, and in those circumstances, the routine should be allowed to grow organically up to 100 – 200 lines.

Don’t write routines longer than about 200 lines.

How to use routine parameters

Interfaces between routines are some of the most error-prone areas of the program. Here are a few guidelines for minimizing interface problems:

  • Put parameters in input-modify-output order
  • If several routines use similar parameters, put the similar parameters in a consistent order
  • Use all the parameters
  • Put status or error variables last
  • Limit the number of a routine’s parameters to about seven

Psychological research has found that people generally cannot keep track of more than about seven chunks of information at once. (Miller 1956.)

The difference between function and procedure is that procedure doesn’t return a value.

You should use macro routines with care and only as a last resort.

Page 17 of 51« First...10«16171819»203040...Last »

Recent posts

  • When espanso Breaks on Long Replacement Strings (and How to Fix It)
  • 2024 Top Author on dev.to
  • Hara hachi bun me
  • Discipline is also a talent
  • Play for the fun of it

Categories

  • Android (3)
  • Books (114)
    • Programming (22)
  • CodeProject (36)
  • Daily Thoughts (78)
  • Go (3)
  • iOS (5)
  • JavaScript (128)
    • Angular (4)
    • Angular 2 (3)
    • Ionic (61)
    • Ionic2 (2)
    • Ionic3 (8)
    • MEAN (3)
    • NodeJS (27)
    • Phaser (1)
    • React (1)
    • Three.js (1)
    • Vue.js (3)
  • Leadership (1)
  • Meetups (8)
  • Miscellaneou$ (78)
    • Breaking News (8)
    • CodeSchool (2)
    • Hacker Games (3)
    • Pluralsight (7)
    • Projects (2)
    • Sublime Text (2)
  • PHP (6)
  • Quick tips (41)
  • Servers (8)
    • Heroku (1)
    • Linux (3)
  • Stack Overflow (81)
  • Unity3D (9)
  • Windows (8)
    • C# (2)
    • WPF (3)
  • Wordpress (2)

"There's no short-term solution for a long-term result." ~ Greg Plitt

"Everything around you that you call life was made up by people that were no smarter than you." ~ S. Jobs

"Hard work beats talent when talent doesn't work hard." ~ Tim Notke

© since 2016 - Nikola Brežnjak