2018年7月13日 星期五

一個違反 ISP Interface Segregation Principle 介面隔離原則 的範例說明

ISP Interface Segregation Principle 介面隔離原則 也是對於很多想要了解 SOLID 物件導向程式設計觀念與技能的人,相當困惑的。有人會說,要是我,才不會設計出這樣的程式碼,但是,現實情況是,產生這樣的問題,真的很常見,而且,會造成開發者的困擾,這怎麼說呢?
羅馬不是一天造成的,程式不是很快就可以寫出來的,當相同的程式經過多人的手,並且有著修改時間壓力下,往往會造成很多不可思議的程式碼,畢竟,這些程式碼都是人寫出來的。在底下的範例中,開發人員想要開發出個辦公室事務機器,因此,定義了許多功能,也造就了 IBusinessPrinters 這個介面,緊接著實作出 AllInOnePrinter 這個具體類別;可是,客戶想要開發出更具有價格競爭力的商品,因此,就想到只留下列印功能,把其他功能都移除,設計出一個超時尚的 SimplePrinter 印表機,另外,又想要移除傳真功能而已,造就出讓中小企業有能夠購買的 CopyPrinter 拷貝列印機。從底下的類別宣告,您看出了甚麼問題嗎?
C Sharp / C#
public interface IBusinessPrinters
{
    void Scan();
    void Print();
    void Copy();
    void FaxSending();
    void FaxReceiving();
}
public class AllInOnePrinter : IBusinessPrinters
{
    public void Copy() { Console.WriteLine("拷貝中"); }
    public void FaxReceiving() { Console.WriteLine("傳真接收中"); }
    public void FaxSending() { Console.WriteLine("傳真發送中"); }
    public void Print() { Console.WriteLine("列印中"); }
    public void Scan() { Console.WriteLine("掃描中"); }
}
C Sharp / C#
public class SimplePrinter : IBusinessPrinters
{
    public void Copy() { Console.WriteLine("錯誤!! 無此功能"); }
    public void FaxReceiving() { Console.WriteLine("錯誤!! 無此功能"); }
    public void FaxSending() { Console.WriteLine("錯誤!! 無此功能"); }
    public void Print() { Console.WriteLine("列印中"); }
    public void Scan() { Console.WriteLine("錯誤!! 無此功能"); }
}
public class CopyPrinter : IBusinessPrinters
{
    public void Copy() { Console.WriteLine("拷貝中"); }
    public void FaxReceiving() { Console.WriteLine("錯誤!! 無此功能"); }
    public void FaxSending() { Console.WriteLine("錯誤!! 無此功能"); }
    public void Print() { Console.WriteLine("列印中"); }
    public void Scan() { Console.WriteLine("掃描中"); }
}

關於 Xamarin 在台灣的學習技術資源

Xamarin 實驗室 粉絲團
歡迎加入 Xamarin 實驗室 粉絲團,在這裡,將會經常性的貼出各種關於 Xamarin / Visual Studio / .NET 的相關消息、文章、技術開發等文件,讓您可以隨時掌握第一手的 Xamarin 方面消息。
Xamarin.Forms @ Taiwan
歡迎加入 Xamarin.Forms @ Taiwan,這是台灣的 Xamarin User Group,若您有任何關於 Xamarin / Visual Studio / .NET 上的問題,都可以在這裡來與各方高手來進行討論、交流。
Xamarin 實驗室 部落格
Xamarin 實驗室 部落格 是作者本身的部落格,這個部落格將會專注於 Xamarin 之跨平台 (Android / iOS / UWP) 方面的各類開技術探討、研究與分享的文章,最重要的是,它是全繁體中文。
Xamarin.Forms 系列課程
Xamarin.Forms 系列課程 想要快速進入到 Xamarin.Forms 的開發領域,學會各種 Xamarin.Forms 跨平台開發技術,例如:MVVM、Prism、Data Binding、各種 頁面 Page / 版面配置 Layout / 控制項 Control 的用法等等,千萬不要錯過這些 Xamarin.Forms 課程

2018年7月12日 星期四

一個違反 LSP Liskov Substitution Principle 里氏替換原則 的範例說明

有很多人對於 LSP Liskov Substitution Principle 里氏替換原則 所講述的內容,看得很模糊,有些時候是學習者對於物件導向程式設計觀念不慎清楚、開發經歷中,也甚少經常設計類別繼承的程式碼,不過,也有人說,我都有設計類別繼承,要是我,才不會有這樣的問題;可是,這是個原則,講的是當您遵從這個原則之後,就不會設計出有行為異常的子類別,有些時候,您也可能需要維護別人開發的舊專案,這個專案也許不知道經過幾個人來維護過了,往往有需求變更的時候,為了客戶時效要求,手頭上有很多專案要開發,就直接繼承類別,產生新的子類別來設計出滿足變更需求的程式,當然,經過一段時間之後,這個專案上就會產生違反 LSP 的問題;不過,說實在的,若這個專案從頭到尾都是您自己開發,也是有可能產生違反 LSP 的問題。一旦程式碼出現違反 LSP 的原則,就會產生出許多意想不到的問題,而這些問題,很多時候是在設計與除錯時候,無法立即發現到的 (更多關於 LSP 的介紹,網路上已經有海量的文章,請各位自行去搜尋、研究)
現在,讓我們來看看底下的範例,您能夠看出它存在著甚麼問題嗎?
另外,他是否有遵從 LSP 原則嗎?
不論答案是肯定或者是否定,請您要提出的論述觀點,這樣,才能夠知道,您是否真正明瞭甚麼是 LSP Liskov Substitution Principle 里氏替換原則
C Sharp / C#
class 鳥
{
    public virtual void 飛() { Console.WriteLine("鳥在飛"); }
    public virtual void 吃() { Console.WriteLine("鳥在吃"); }
}
class 老鷹 : 鳥
{
    public override void 飛() { Console.WriteLine("老鷹在飛"); }
    public override void 吃() { Console.WriteLine("老鷹在吃"); }
}
class 鴕鳥 : 鳥
{
    public override void 飛() { throw new NotSupportedException("鴕鳥不能飛"); }
    public override void 吃() { Console.WriteLine("老鷹在吃"); }
}
底下是使用上面類別的範例程式碼
C Sharp / C#
class Program
{
    static void Main(string[] args)
    {
        List<鳥> birds = new List<鳥>();
        birds.Add(new 鳥());
        birds.Add(new 老鷹());
        birds.Add(new 鴕鳥());
        BirdsFly(birds);
    }
    static void BirdsFly(List<鳥> birdList)
    {
        foreach (var item in birdList)
        {
            item.飛();
        }
    }
}

關於 Xamarin 在台灣的學習技術資源

Xamarin 實驗室 粉絲團
歡迎加入 Xamarin 實驗室 粉絲團,在這裡,將會經常性的貼出各種關於 Xamarin / Visual Studio / .NET 的相關消息、文章、技術開發等文件,讓您可以隨時掌握第一手的 Xamarin 方面消息。
Xamarin.Forms @ Taiwan
歡迎加入 Xamarin.Forms @ Taiwan,這是台灣的 Xamarin User Group,若您有任何關於 Xamarin / Visual Studio / .NET 上的問題,都可以在這裡來與各方高手來進行討論、交流。
Xamarin 實驗室 部落格
Xamarin 實驗室 部落格 是作者本身的部落格,這個部落格將會專注於 Xamarin 之跨平台 (Android / iOS / UWP) 方面的各類開技術探討、研究與分享的文章,最重要的是,它是全繁體中文。
Xamarin.Forms 系列課程
Xamarin.Forms 系列課程 想要快速進入到 Xamarin.Forms 的開發領域,學會各種 Xamarin.Forms 跨平台開發技術,例如:MVVM、Prism、Data Binding、各種 頁面 Page / 版面配置 Layout / 控制項 Control 的用法等等,千萬不要錯過這些 Xamarin.Forms 課程



2018年7月11日 星期三

對於學習 SOLID 五個原則 Principle 的感想

因為工作上的需要,因此,我特別安排時間來進行 SOLID OOD 物件導向程式設計的研究與學習,我想,我應該是與大家一樣,開始都是從 Google 上來搜尋 SOLID SRP OCP LSP ISP DIP Principle 等關鍵字,看看網路上的人怎麼說,也須我的資質不好,搜尋到一大票的文章,怎麼看,怎麼不懂,最重要的是,當我好不容易看懂,例如 Single Responsibility Principle SRP ,接著看到更多的文章所說明的內容、圖片、解釋、範例,就更加的模糊與不清楚他到底是要做甚麼用到、可以幫助我做甚麼事情、我該如何將我的程式碼撰寫或重構成具有 SRP 精神的程式碼,這也包括了不同作者所舉例的程式碼,並不是我孰悉的 C#,這讓我在閱讀那些程式碼的過程中,也是備感艱辛;過程中,我也產生了許多的疑問,再次以 SRP 為例,為什麼每個文章作者,對於所舉例的範例程式碼,緊接著就說這段程式碼具有三個責任,所以,我們要把這三個責任進行分離開,我的老天鵝呀,我是真的不知道為什麼是三個責任,不是兩個,也不是五個。
好吧,既然廣泛涉獵的許多網路上的 SOLID 的文章,那麼,只好痛下決心,花點索費,到 Amazon 去買 Uncle Bob 寫的兩本書來看看 (會去買 Uncle Bob 的書,這是因為 SOLID 是 Uncle Bob 根據不同人提出的分享,綜合出這五個原則) ,也花了點時間,找出 Uncle Bob 當初所提出的 SOLID 五篇文章,既然東西都到手之,就要開始花點時間把這些最初的資料給他閱讀一番。不過,最後,我還是想辦法把當初提出這些原則人寫的文章、書,也給他購買或者找出來,並且從中細細體味出箇中奧妙之所在。
因此,對於想要把 SOLID 弄清楚的人,在此提出幾個建議

OOP 物件導向程式設計

若您對於 OOP 的四個特性不慎了解,甚至沒有研究過 OOP 四個特性,我覺得您應該要先去了解與孰悉 OOP 的四個特性:抽象、封裝、繼承、多型

弄清楚這些名詞的意義

當您在進行 SOLID 學習過程中,需要處處存著兒時好奇心態,保持您的疑問,雖然,當時您可能無法理解或明瞭其中含意,不過,這對於您日後學習上,會有著明顯的好處;若平常都有做善事,有著好機緣,碰到真正會的有緣人(千萬不要去問自以為是,處處都是我認為、我想的、我平常都是這樣做的的人去問,這樣,您會走火入魔的),把你蒐集起來的問題,向他們請教看看。
首先,您需要了解 甚麼事 Principle 原則,因為, SOLID 是由五個 Principle 所組成,若您不瞭解何謂 Principle 的意義,那麼,就算您學會了這五個 Principle,您覺得對你會有甚麼幫助呢?
緊接著,要把每個原則的每個英文字與其解釋(我是參考 Uncle Bob書中對於這五個原則的描述),挑出主要的名詞,了解他們存在的意義與目的 (千萬不要使用您本身所學的經歷來看待這些名詞,畢竟,這些原則是早在 20 年前所提出來的,那個時候,可是沒有 C# / Java 這樣的語言存在,還是那句話,不要憑感覺來認為自己就是一切),這樣會有助於您去閱讀書中、文章中之各原則的論述。

SRP Single Responsibility Principle 單一責任原則

A class should have only one reason to change
請了解甚麼事個 Responsibility 責任,不過,在其他文章中,您可能會看到有些內容會使用 Module 模組來取代 Class 類別,您可以嘗試體會與思考看看,為什麼會有 Module 這個名詞出現,這會對於您之後學習過程中有莫大的幫助;另外,也需要甚麼是 Change 變更需求,為什麼會有它,他會造成甚麼影響,如何改善因為 Change 所產生出來的問題。總之,凡事抱著疑問來學習。

OCP Open Closed Principle 開放封閉原則

Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification
OCP 開放封閉原則,是我們進行專案開發過程中,最為重要與經常會面對的問題,所以,務必要花些時間來精通才好。
在這裡,請要了解這些詞彙的意義與精神: Open / Closed / Software Entity / Extension / Modification 。對於後面兩者,請要去了解,就是目標對象指的是誰,也就是誰要開放,誰要封閉,究竟怎麼開放,怎麼封閉。
在您觀看 OCP 內容的時候,會看到很多文章舉的例子,都是使用 Interface 介面,來做為重構成為符合 OCP 的作法,請千萬不要畫地自限,以為,想要符合 OCP 的精神,就只能使用 介面 來解決,有興趣的人,可以去嘗試看看,要做出符合 OCP 精神的程式碼,至少有六七種以上的技術可以做到。

LSP Liskov Substitution Principle 里氏替換原則

Subtypes must be substitutable for their base types
這個原則主要的重點就是替換這個名詞,您也許會覺得很奇怪,這到底是甚麼原則,為什麼要放在 SOLID 這五個原則內,他有甚麼重要性?在想要了解這個原則,您應該要先從他的背景來研究,那就是 OOP 裡面的繼承與多型,也就是說,若您對於這兩個名詞也一知半解,那麼,這個原則所提到的內容,您是無法體會出來的。

ISP Interface Segregation Principle 介面隔離原則

Clients should not be forced to depend upon interfaces that they don't use
這也是個大家覺得好莫名的原則,介面與隔離,是這個原則要探討的重點,還是那句話,若您在開發程式設計過程中,幾乎沒有自己設計過介面,或者不太了解介面的應用與特色,那麼,您會學得很辛苦;另外,就是一個問題,為什麼會產生一個具有那麼多方法宣告的介面,也許,您會說:要是我自己開發,就不會有這樣的問題?可是,請不要用自己的經歷、角度來看這些原則,在一個專案開發與設計過程中,往往會有多人一起進行開發,當然,任何人都可以去修改介面的宣告,所以,您應該已經知道為什麼會產生一個超級胖的介面了。因此,了解這樣的介面會產生的副作用,並且規避這樣的現象產生,也就是這個原則的精神了。

DIP Dependency Inversion Principle 相依反轉原則

High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend on details. Details should depend on abstractions
這個原則需要用到兩句話來說明,因此,我們需要了解這兩句話中的各個腳色與扮演目的:高階模組、低階模組、模組、抽象、明細、相依。喔喔,這五個原則中,看樣子是這個原則中出現了最多的名詞,我個人覺得最重要的詞彙就是 相依 Dependency ,了解何謂相依、為什麼會相依、相依會造成甚麼樣的問題、怎樣才是一個好的相依,這樣,也許您就已經對於這個原則了解一半了。不過,若您的程式設計與開發生涯中,幾乎沒有用到過或者很少用到過相依性注入這樣的設計模式,那麼,您可能無法深刻體會出這個原則想要幫您解決甚麼問題。

打通任都二脈

若您經過研究,有了解與孰悉 OOP,對於這五個原則的各個用到的詞彙也明瞭,甚至有看過這五個原則當初的背景文章,而且也看過各種原則的範例程式碼,那麼,您已經完成了第一步,接下來,您將會需要
  • 找出與練習撰寫出 違反原則的程式碼,自己嘗試重構這個程式碼,使其符合原則
  • 嘗試自行分析,若一個程式碼,符合 OCP,是否就符合 LSP,反過來說,符合 LSP ,是否就是符合 OCP;另外一個是,若程式碼符合 OCP,是否就符合 DIP,反過來說,符合 DIP ,是否就是符合 OCP,嘗試挑戰看看這樣的論述是否都是為真,還是不是,若不是,您可以舉出這樣的例子呢?

關於 Xamarin 在台灣的學習技術資源

Xamarin 實驗室 粉絲團
歡迎加入 Xamarin 實驗室 粉絲團,在這裡,將會經常性的貼出各種關於 Xamarin / Visual Studio / .NET 的相關消息、文章、技術開發等文件,讓您可以隨時掌握第一手的 Xamarin 方面消息。
Xamarin.Forms @ Taiwan
歡迎加入 Xamarin.Forms @ Taiwan,這是台灣的 Xamarin User Group,若您有任何關於 Xamarin / Visual Studio / .NET 上的問題,都可以在這裡來與各方高手來進行討論、交流。
Xamarin 實驗室 部落格
Xamarin 實驗室 部落格 是作者本身的部落格,這個部落格將會專注於 Xamarin 之跨平台 (Android / iOS / UWP) 方面的各類開技術探討、研究與分享的文章,最重要的是,它是全繁體中文。
Xamarin.Forms 系列課程
Xamarin.Forms 系列課程 想要快速進入到 Xamarin.Forms 的開發領域,學會各種 Xamarin.Forms 跨平台開發技術,例如:MVVM、Prism、Data Binding、各種 頁面 Page / 版面配置 Layout / 控制項 Control 的用法等等,千萬不要錯過這些 Xamarin.Forms 課程

2018年7月9日 星期一

如何進行您的專案程式的 SOLID Principle 原則之評估方法

在這篇文章中,我們將分別針對 SOLID 的五個原則,說明如何檢驗您的程式碼,是否有符合這些原則的檢驗論述指引。也就是說,當您判斷一個程式,是否有符合 SOLID 各個原則或者其中一個原則,您可以使用這篇文章提出的指引,描述出您的看法。

Single Responsibility Principle SRP

在 Wiki 定義 Single Responsibility Principle 如下
every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.
而在 Robert C. Martin 對於這個原則的描述為
A class should have only one reason to change.

驗證步驟

在這裡,我們將需要進行 分析對象 與 分析理由 的論述

分析對象

我們在這裡採用 Robert C. Martin 的描述,因此,請您要指出要分析的類別是哪一個,也就是: 一個類別應該只有一個改變的理由!
類別 C

分析理由

因為 responsibility as a reason to change 責任將會定義為一個改變的理由,而要改變這個需求,有些時候會提早知道,而大部分的時候,您幾乎無法做到預測,這些變更的理由可能會來自於客戶的要求、PM的修正、當時環境的變更、公司的政策等等。
所以,請在這裡描述您認為這個類別究竟存在哪些責任,為什麼會有這樣的責任存在呢?
在類別 C 中,存在著 R 責任,會有 R 責任存在,是因為存在著 RC 變更理由
經過重構之後,在類別 C 中,僅存在著一個變更理由 (RC'),也就是具有一個責任 (R')
請依序把上述的 C, R , RC , RC' , R' 替換您的分析理由,若有多個責任,請分別描述出來

Open Closed Principle OCP

在 Wiki 定義 Open Closed Principle 如下
software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification, that is, such an entity can allow its behaviour to be extended without modifying its source code.
在 Uncle Bob 的書中,對於 OCP ,定義 OCP 如下
Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.
在最初的 OCP 提出者 Bertrand Meyer,定義 OCP 如下
A module will be said to be open if it is still available for extension. For example, it should be possible to add fields to the data structures it contains, or new elements to the set of functions it performs.
A module will be said to be closed if [it] is available for use by other modules. This assumes that the module has been given a well-defined, stable description (the interface in the sense of information hiding).[3]
Meyer's proposed solution to this dilemma relied on the notion of object-oriented inheritance (specifically implementation inheritance):
A class is closed, since it may be compiled, stored in a library, baselined, and used by client classes. But it is also open, since any new class may use it as parent, adding new features. When a descendant class is defined, there is no need to change the original or to disturb its clients.

驗證步驟

在這裡,我們將需要進行 分析對象 與 分析理由 的論述

分析對象

根據該原則的定義,我們分析的對象會是 software entities (classes, modules, functions, etc.),因此,請您要指出要分析的類別是哪一個
在軟體項目 E (可能是 類別、模組、函數)、開放 O 理由、封閉 C 理由

分析理由

請在這裡分別描述您認為存在著 開放 Open 與 封閉 Closed 的狀況
先描述為重構前的情況
在 軟體項目 E
開放 : 為什麼在軟體項目 E 中,為什麼不可以擴展,其 開放 O 理由
封閉 : 為什麼在軟體項目 E 中,為什麼不可以封閉修改,其 封閉 C 理由
經過重構之後,
軟體項目 E
開放 : 為什麼在軟體項目 E 中,為什麼可以擴展,其 開放 O 理由
封閉 : 為什麼在軟體項目 E 中,為什麼可以封閉修改,其 封閉 C 理由
請依序把上述的 E, O, C 替換您的分析結果

Liskov Substitution Principle LSP

在 Wiki 定義 Liskov Substitution Principle 如下
the Liskov substitution principle (LSP) is a particular definition of a subtyping relation, called (strong) behavioral subtyping, that was initially introduced by Barbara Liskov in a 1987 conference keynote address titled Data abstraction and hierarchy. It is a semantic rather than merely syntactic relation, because it intends to guarantee semantic interoperability of types in a hierarchy, object types in particular. Barbara Liskov and Jeannette Wing formulated the principle succinctly in a 1994 paper as follows:
LSP
在 Uncle Bob 的書中,對於 LSP ,定義 LSP 如下
Subtypes must be substitutable for their base types.
在最初的 LSP 提出者 Liskov ,定義 LSP 如下
if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.
What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.

驗證步驟

在這裡,我們將需要進行 分析對象 與 分析理由 的論述

分析對象

根據該原則的定義,我們分析的對象會是 subtype 子型別 與 base type 基底型別 和 有用到基底型別的程式碼,因此,請您要指出這兩個型別與其相關程式碼的那些地方與行為,是否違反了 LSP 的要求
程式碼 P , 子型別 S , 基底型別 T

分析理由

請將您的分析結果,在這裡描述
符合 : 在程式碼 P ,對於 子型別 S ,是 可以替換 基底型別 T
違反 : 在程式碼 P ,對於 子型別 S ,無法 可以替換 基底型別 T,理由是 R
請依序把上述的 P, S, T, R 替換您的分析結果

Interface Segregation Principle ISP

在 Wiki 定義 Interface Segregation Principle 如下
no client should be forced to depend on methods it does not use.[1] ISP splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them.
在 Uncle Bob 的書中,對於 ISP ,定義 ISP 如下
Classes whose interfaces are not cohesive have "fat" interface.
也可以說是
Clients should not be forced to depend upon interfaces that they do not use.
在 Uncle Bob 的網頁中,對於 ISP ,定義 ISP 如下
Make fine grained interfaces that are client specific.
在最初的 ISP 提出者 Robert C. Martin 的 Object Mentor SOLID Design Papers Series

驗證步驟

在這裡,我們將需要進行 分析對象 與 分析理由 的論述

分析對象

根據該原則的定義,我們分析的對象會 Client 用戶端,也就是要使用這個介面的用戶端與 Interface 介面,也就是抽象化的介面
用戶端 C , 介面 I , 方法 M

分析理由

請將您的分析結果,在這裡描述
對於 用戶端 C , 相依於介面 I ,將不會用到該 介面 I 的甚麼 方法 M
請依序把上述的 C , I, M 替換您的分析結果

Dependency Inversion Principle DIP

在 Wiki 定義 Dependency Inversion Principle 如下
refers to a specific form of decoupling software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details.
在 Uncle Bob 的書中,對於 ISP ,定義 ISP 如下
High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend on details. Details should depend on abstractions.

驗證步驟

在這裡,我們將需要進行 分析對象 與 分析理由 的論述

分析對象

根據該原則的定義,我們分析出 高階模組 High-Level Module , 低階模組 Low-Level Module , 抽象 Abstraction , 細節 Detail
高階模組 H , 低階模組 L , 抽象 A , 細節 D

分析理由

請將您的分析結果,在這裡描述
對於 高階模組 H 原先有相依於 低階模組 L ,經過重構之後 高階模組 H 相依於 抽象 A
對於 抽象 A 原本相依於 細節 D ,經過重構之後, 細節 D 相依於 抽象 B
請依序把上述的 H , L , A , D , B 替換您的分析結果

關於 Xamarin 在台灣的學習技術資源

Xamarin 實驗室 粉絲團
歡迎加入 Xamarin 實驗室 粉絲團,在這裡,將會經常性的貼出各種關於 Xamarin / Visual Studio / .NET 的相關消息、文章、技術開發等文件,讓您可以隨時掌握第一手的 Xamarin 方面消息。
Xamarin.Forms @ Taiwan
歡迎加入 Xamarin.Forms @ Taiwan,這是台灣的 Xamarin User Group,若您有任何關於 Xamarin / Visual Studio / .NET 上的問題,都可以在這裡來與各方高手來進行討論、交流。
Xamarin 實驗室 部落格
Xamarin 實驗室 部落格 是作者本身的部落格,這個部落格將會專注於 Xamarin 之跨平台 (Android / iOS / UWP) 方面的各類開技術探討、研究與分享的文章,最重要的是,它是全繁體中文。
Xamarin.Forms 系列課程
Xamarin.Forms 系列課程 想要快速進入到 Xamarin.Forms 的開發領域,學會各種 Xamarin.Forms 跨平台開發技術,例如:MVVM、Prism、Data Binding、各種 頁面 Page / 版面配置 Layout / 控制項 Control 的用法等等,千萬不要錯過這些 Xamarin.Forms 課程