I'm solving the following problem using the Chain Of Responsibility design pattern in Swift:Not all mechanics are created equally. Some mechanics are more  experienced and can do more than others. We need a system where every  job is propagated from the least experienced mechanic to the most.  This way  experienced mechanics that can perform more jobs are not  busy with jobs that more junior mechanics can take care of.I would love some feedback on how I can improve this. If it remains true to the definition of Chain Of Responsibility or if there are any swift standard coding convention that I should be following. Here is the code, the full repo can be found here: Design Patterns in Swift: Chain of Responsibility import Foundationenum Skill: Int{  case OilChangeOnly = 1, Junior, Apprentice, MasterMechanic}class Job{  let minimumSkillSet: Skill  let name: String  var completed: Bool = false  init(minimumSkillSet: Skill, name: String){    self.minimumSkillSet = minimumSkillSet    self.name = name  }}class Mechanic{  let skill: Skill  var name: String  var isBusy: Bool = false  init(skill: Skill, name: String){    self.skill = skill    self.name = name  }  func performJob(job: Job) -> Bool{    if job.minimumSkillSet > self.skill || isBusy{      assert(false, This mechanic is either busy or insufficiently skilled for this job, he should have never been asked to perform it, there is something wrong in the chain of responsibility);    }else    {      isBusy = true      print(\(name) with skill set \(skill) has started to do \(job.name))      job.completed = true      return true    }  }}class MechanicSkillGroup{  var mechanics: [Mechanic]  var nextLevel: MechanicSkillGroup?  var skill: Skill  init(skill: Skill, mechanics: [Mechanic], nextLevel: MechanicSkillGroup?){    self.mechanics = mechanics    self.skill = skill    self.nextLevel = nextLevel  }  func performJobOrPassItUp(job: Job) -> Bool{    if (job.minimumSkillSet > skill || mechanics.filter({$0.isBusy == false}).count == 0){      if let nextLevel = nextLevel{        return nextLevel.performJobOrPassItUp(job)      }else{        print(No one is available to do this job)        return false      }    }else{      if let firstAvailableMechanic = mechanics.filter({$0.isBusy == false}).first{        return firstAvailableMechanic.performJob(job)      }      assert(false, This should never be reached since our if-else statement is fully exhaustive. You cannot have both all mechanics busy and an available mechanic within one skill group);    }  }}class Shop{  private var firstMechanics: MechanicSkillGroup  init(firstMechanics: MechanicSkillGroup){      self.firstMechanics = firstMechanics  }  func performJob(job: Job) -> Bool{    return firstMechanics.performJobOrPassItUp(job)  }}Here is main with setup and some test casesimport Foundationvar steve = Mechanic(skill: .MasterMechanic, name: Steve Frank)var joe = Mechanic(skill: .MasterMechanic, name: Joe Alison)var jack = Mechanic(skill: .MasterMechanic, name: Jack Ryan)var brian = Mechanic(skill: .MasterMechanic, name: Drake Jin)var masterMechanics = MechanicSkillGroup(skill: .MasterMechanic, mechanics: [steve, joe, jack, brian], nextLevel: nil)var tyson = Mechanic(skill: .Apprentice, name: Tyson Trump)var tina = Mechanic(skill: .Apprentice, name: Tina Bernard)var bryan = Mechanic(skill: .Apprentice, name: Bryan Tram)var lin = Mechanic(skill: .Apprentice, name: Lin Young)var apprenticeMechanics = MechanicSkillGroup(skill: .Apprentice, mechanics: [tyson, tina, bryan, lin], nextLevel: masterMechanics)var ken = Mechanic(skill: .Junior, name: Ken Hudson)var matt = Mechanic(skill: .Junior, name: Matt Lowes)var sandeep = Mechanic(skill: .Junior, name: Sandeep Shenoy)var tom = Mechanic(skill: .Junior, name: Tom Berry)var juniorMechanics = MechanicSkillGroup(skill: .Junior, mechanics: [ken, matt, sandeep, tom], nextLevel: apprenticeMechanics)var grant = Mechanic(skill: .OilChangeOnly, name: Grant Hughes)var larry = Mechanic(skill: .OilChangeOnly, name: Larry White)var bryant = Mechanic(skill: .OilChangeOnly, name: Bryant Newman)var reza = Mechanic(skill: .OilChangeOnly, name: Reza Shirazian)var laura = Mechanic(skill: .OilChangeOnly, name: Laura Lee)var arnold = Mechanic(skill: .OilChangeOnly, name: Arnold Shummer)var oilChangeOnlyes = MechanicSkillGroup(skill: .OilChangeOnly, mechanics: [grant], nextLevel: juniorMechanics)var shop = Shop(firstMechanics: oilChangeOnlyes)var jobs = [Job(minimumSkillSet: .Junior, name: Windshield Viper),            Job(minimumSkillSet: .Apprentice, name: Light Bulb Change),            Job(minimumSkillSet: .Apprentice, name: Battery Replacement),            Job(minimumSkillSet: .OilChangeOnly, name: General Oil Change),            Job(minimumSkillSet: .OilChangeOnly, name: General Oil Change),            Job(minimumSkillSet: .OilChangeOnly, name: General Oil Change),            Job(minimumSkillSet: .OilChangeOnly, name: General Oil Change),            Job(minimumSkillSet: .MasterMechanic, name: Timing Belt Replacement),            Job(minimumSkillSet: .Junior, name: Brake Pads Replacement)]for job in jobs{  shop.performJob(job)}Here is output you'd get with this setup:Ken Hudson with skill set Junior has started to do Windshield WiperTyson Trump with skill set Apprentice has started to do Light Bulb ChangeTina Bernard with skill set Apprentice has started to do Battery ReplacementGrant Hughes with skill set OilChangeOnly has started to do General Oil ChangeMatt Lowes with skill set Junior has started to do General Oil ChangeSandeep Shenoy with skill set Junior has started to do General Oil ChangeTom Berry with skill set Junior has started to do General Oil ChangeSteve Frank with skill set MasterMechanic has started to do Timing Belt ReplacementBryan Tram with skill set Apprentice has started to do Brake Pads ReplacementProgram ended with exit code: 9   
Design Patterns in Swift: Chain of Responsibility
design patterns;swift
FormattingThere are several formatting issues with your code.The standard is 4 spaces per indentation level.  It looks like you've opted for 2, but it appears you've at least applied this consistently, although I really heavily prefer 4.Your opening braces frequently appear squished right up against the preceding word.  There should be a space.In at least one place, you've left this:}else{Which not only looks bad, but is inconsistent with other parts of your code.Personally, I prefer not to cuddle my else (and catch) keywords, and as such, I write them like this:}else {The primary inspiration behind this brace style has a lot to do with how Xcode handles collapsing code.You also have a wild semicolon ; hanging out at the end of one of your assert statements.Most of these things can be addressed automatically with SwiftLint.assert & printNeither of these are really particularly helpful.First of all, if we're going to log, we should use a real logging library.  That's a really minor issue here.  The real problem here is that we're printing to communicate things that should probably be communicate in the return values (or already are).As for the asserts, again, I think we're using these to communicate information that should probably be handled with return values.  Or in some cases, we can probably reorganize our logic to simply get rid of them altogether.Method NamingWhat your methods do and how they're named aren't exactly in sync.A method called performJob probably shouldn't return a Bool indicating whether or not the job could be performed.  And methods should generally never have Or or And as part of their name (there are exceptions, but they are rare).The performJobOrPassItUp method probably makes a lot more sense framed in this way:func firstAvailableMechanicForJobWithSkillLevel(skillLevel: Skill) -> Mechanic?That is to say... the method either returns a mechanic or returns nil.  Returning nil indicates there are no available mechanics and whatever is looking to get a job of that skill level accomplished must look elsewhere or try again later.  Otherwise, it passes back out a mechanic which can do the job.Boolean literals and checking if arrays are emptymechanics.filter({$0.isBusy == false}).count == 0First of all, we should almost never be comparing against boolean literals.  We can simply write !$0.isBusy.Second of all, if we want to know whether an array is empty, we should check isEmpty:mechanics.filter({!$0.isBusy}).isEmptyInitializersIn both your Mechanic and Job classes, you don't have a way to initialize all of the variables.  In both cases, you default initialize a Bool value.  Why not just make that part of the initializers, but give it a default value.class Job{    let minimumSkillSet: Skill    let name: String    var completed: Bool    init(minimumSkillSet: Skill, name: String, completed: Bool = false) {        self.minimumSkillSet = minimumSkillSet        self.name = name         self.completed = false    }}String-TypingThe Mechanic class has a name property which is a string.  And this is fine.  The name here is nothing more than an identifier which we might want to use to display to the user or something.But the Job class's name property is doing something completely different.  We may still want a pretty string to display to the user, but this property is doing more than that.  I think we need a full fledged type here.  Why, for example, would a General Oil Change ever require anything other than the OilChangeOnly skill?  So the list of jobs is surely countable, and the actual skill level for any particular job is surely constant.