Skip to content

Commit

Permalink
Merge pull request #54 from Trendyol/project-file-organization-additions
Browse files Browse the repository at this point in the history
Update code_style_guideline.md and add ExamplePresenter.swift for file organization additions
  • Loading branch information
eminozkalaycioglu1 committed May 17, 2024
2 parents 2001995 + 2bd2054 commit 2be46ff
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 80 deletions.
157 changes: 77 additions & 80 deletions code_style_guideline/code_style_guideline.md
Original file line number Diff line number Diff line change
Expand Up @@ -675,64 +675,7 @@ return String(format: "user name: %@, user id: %d, user height: %f", user.name,

## File Organization

### Alphabetize and deduplicate module imports within a file. Place all imports at the top of the file below the header comments.

**Why**: A standard organization method helps engineers more quickly determine which modules a file depends on.
Duplicated import statements have no effect and should be removed for clarity.

**Not Preferred**:
```swift
// Copyright © 2024 Trendyol. All rights reserved.
//

import TYCoreUtils
import Foundation
import CommonKit
import AccessibilityKit

import MemberKit
```

**Preferred**:
```swift
// Copyright © 2024 Trendyol. All rights reserved.
//

import AccessibilityKit
import CommonKit
import Foundation
import MemberKit
import TYCoreUtils
```

#### @testable usage

**Preferred**:
```swift
// Copyright © 2024 Trendyol. All rights reserved.
//

import AccessibilityKit
import CommonKit
import Foundation
import MemberKit
import TYCoreUtils

@testable import Trendyol
```

**Also Preferred**:
```swift
// Copyright © 2024 Trendyol. All rights reserved.
//

import AccessibilityKit
import CommonKit
import Foundation
import MemberKit
@testable import Trendyol
import TYCoreUtils
```
### Alphabetize and deduplicate module imports within a file. Place all imports at the top of the file below the header comments. (Also see [Imports](#imports).)

### Limit consecutive whitespace to one blank line or space (excluding indentation)

Expand Down Expand Up @@ -835,11 +778,21 @@ class Planet {
* Nested types and type aliases
* Static properties
* Class properties
* IBOutlet properties
* Instance properties
* Lifecycle methods
* Static methods
* Class methods
* IBAction methods
* Instance methods

### Protocol conforms should be ordered for understanding action structure easily.

* Private method extension
* Type protocol conform extension
* Delegate conform extension
* Output conform extension

### Add empty lines between property declarations of different kinds. (e.g. between static properties and instance properties.)

**Not Preferred**:
Expand Down Expand Up @@ -867,6 +820,10 @@ var atmosphere: Atmosphere {
}
}
var gravity: CGFloat

init() {
...
}
```

**Preferred**:
Expand All @@ -877,8 +834,38 @@ var atmosphere: Atmosphere {
print("oh my god, the atmosphere changed")
}
}

init() {
...
}
```

**Also Preferred**:

If a swift file contains a lot of computed and stored property, they can be grouped and sorted among themselves with using MARK.

```swift
// MARK: - Identitiy Properties
var name: String
var surname: String
var fullName: String {
"\(name) \(surname)"
}

// MARK: - X Component Properties
var xComponentTitle: String
var isXComponentFlagEnabled: Bool
var shouldShowXComponent: Bool {
!xComponentTitle.isEmpty && isXComponentFlagEnabled
}

init() {
...
}
```

Also see for file organization [ExamplePresenter.swift](/code_style_guideline/examples/ExamplePresenter.swift)

## Code Organization

Use extensions to organize your code into logical blocks of functionality.
Expand Down Expand Up @@ -1005,49 +992,59 @@ Alphabetize and deduplicate module imports within a file. Place all imports at t

A standard organization method helps engineers more quickly determine which modules a file depends on.
Duplicated import statements have no effect and should be removed for clarity.

**Not Preferred**:
```swift
// Copyright © 2018 Airbnb. All rights reserved.
// Copyright © 2024 Trendyol. All rights reserved.
//
import DLSPrimitives
import Constellation
import Constellation
import Epoxy

import TYCoreUtils
import Foundation
import CommonKit
import AccessibilityKit

import MemberKit
```

**Preferred**:
```swift
// Copyright © 2018 Airbnb. All rights reserved.
// Copyright © 2024 Trendyol. All rights reserved.
//

import Constellation
import DLSPrimitives
import Epoxy
import AccessibilityKit
import CommonKit
import Foundation
Exception: @testable import should be grouped after the regular import and separated by an empty line.
import MemberKit
import TYCoreUtils
```
**Not Preferred**:

#### @testable usage

**Preferred**:
```swift
Details
// Copyright © 2018 Airbnb. All rights reserved.
// Copyright © 2024 Trendyol. All rights reserved.
//

import DLSPrimitives
@testable import Epoxy
import AccessibilityKit
import CommonKit
import Foundation
import Nimble
import Quick
import MemberKit
import TYCoreUtils

@testable import Trendyol
```
**Preferred**:

**Also Preferred**:
```swift
// Copyright © 2018 Airbnb. All rights reserved.
// Copyright © 2024 Trendyol. All rights reserved.
//

import DLSPrimitives
import AccessibilityKit
import CommonKit
import Foundation
import Nimble
import Quick
import MemberKit
@testable import Trendyol
import TYCoreUtils
```

Import only the modules a source file requires. For example, don't import `UIKit` when importing `Foundation` will suffice. Likewise, don't import `Foundation` if you must import `UIKit`.
Expand Down
157 changes: 157 additions & 0 deletions code_style_guideline/examples/ExamplePresenter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import CommonKit
import CoreTracker
import CoreUtils
import DependencyEngine
import MemberKit

protocol ExamplePresenterInterface {
var shouldShowButton: Bool { get }
var fullName: String { get }
var shouldShowXComponent: Bool { get }

func firstMethod() -> Bool
func secondMethod()
}

extension ExamplePresenter {
private enum Constants {
static let dataFetchLimit = 2
static let defaultBarTitle = "..."
}
}

final class ExamplePresenter {
private typealias View = ExampleViewInterface
private typealias Interactor = ExampleInteractorInterface

static let staticProperty: Int = 1
class var classProperty: String = "Trendyol"

private weak var view: View?
private let interactor: Interactor
private let userId: Int
private lazy var manager = FavoriteManager()

// MARK: - Identitiy Properties
private var name: String
private var surname: String
var fullName: String {
"\(name) \(surname)"
}

// MARK: - X Component Properties
private var xComponentTitle: String
private var isXComponentFlagEnabled: Bool
var shouldShowXComponent: Bool {
!xComponentTitle.isEmpty && isXComponentFlagEnabled
}

var shouldShowButton: Bool {
firstFlag && secondFlag
}

var barTitle: String {
data.productName ?? Constants.defaultBarTitle
}

init(view: View, interactor: Interactor, userId: Int) {
self.view = view
self.interactor = interactor
self.userId = userId
}

static func workHard(motivation: Bool = true) {
.
.
}

class func beHappy() {
.
.
}
}

extension ExamplePresenter {
private func fetchFirstData() {
.
.
interactor.fetchFirstData()
.
.
}

private func fetchSecondData() {
.
.
interactor.fetchSecondData()
.
.
}

@discardableResult
private func handleName(with text: String?) -> Bool {
guard let text else { return false }
manager.name = text
secondMethod()
return true
}
}

// MARK: - ExamplePresenterInterface
extension ExamplePresenter: ExamplePresenterInterface {
func firstMethod() -> Bool {
.
.
.
return result
}

func secondMethod() {
guard isXComponentFlagEnabled else { return }
.
.
.
.
if firstCondition {
.
.
} else if secondCondition {
.
} else {
.
.
}
.
.
}
}

// MARK: - TYPopupDelegate
extension ExamplePresenter: TYPopupDelegate {
func tyPopup(_ popup: TYPopup, didClickButtonFor type: Type) {
.
.
}
}

// MARK: - FavoriteManagerDelegate
extension ExamplePresenter: FavoriteManagerDelegate {
func favoriteManagerDidAddToListSuccessfully(_ manager: FavoriteManager) {
.
.
.
}
}

// MARK: - ExampleInteractorOutput
extension ExamplePresenter: ExampleInteractorOutput {
func handleResult(_ result: Result<ExampleResponseModel, Error>) {
switch result {
case .success(let data):
let ids = data.products.compactMap{ $0.id }
saveProducts(with: ids)
case .failure:
view?.showErrorAlert()
}
}
}

0 comments on commit 2be46ff

Please sign in to comment.