Mathematics in Nature (From the book of the same name by John Adam ) Two of the most fundamental and widespread phenomena that occur in the realm of nature are (i) the scattering of light a…Full description
For sewingDescripción completa
.
Deskripsi lengkap
Scolioza
c in hindi
Stravinsky symphony in C
Stravinsky symphony in CFull description
n hh h
In c Terry RileyFull description
Full description
This Masquerade In CFull description
Descripción completa
C ProgrammingFull description
Patterns in C – Part 1
By Adam Petersen
Interested in Patterns? Programming in C? Read more in my new book on Patterns in C https://leanpub.com/patternsinc
Over the last ten years, the pattern format has gained a tremendous popularity as the format used for capturing experience. One of the reasons for this popularity is the unique success of the classic book Design Patterns Patterns [1] by the Gang of our. !he Design !he Design Patterns Patterns [1] book definitively definitively served served the community community by spreading spreading the "ord "ord about patterns. patterns. !oday, patterns in the soft"are industry aren#t limited to design$ there exists a broad range of patterns, covering analysis patterns, patterns for organi%a organi%ations, tions, patterns for for testing, etc. &s most patterns are described in the context of an ob'ect oriented design, one is easily lead to believe that patterns require a language "ith support for ob'ect orientation. (y bro"sing a popular online bookstore, ) noticed a lot of language specific pattern literature* design patterns in +ava, -, malltalk and other popular ob'ect oriented languages. (ut, "here is the one targeting the unique implementation constraints and techniques for the language/ )sn#t it possible to use patterns in the development of programs or or doesn#t doesn#t it add any benefits/ benefits/ &n important thing to reali%e about patterns is that they are neither a blueprint of a design, nor are they tied to any particular implementation. (y those means, shouldn#t it be possible to find mechanisms fitting the paradigm of , letting programmers benefit from the the experience experience captured captured by patterns/ patterns/
What you will experience in this series )t is my belief that programmers can benefit from the gro"ing catalogue of patterns. !his series "ill focus on the follo"ing areas* •
•
•
Implementation Implementation techniques techniques.. ) "ill present a number of patterns and demonstrate techniques for implementing them in the context of the language. )n case )#m a"are of common variations in the implementation, they "ill be discussed as "ell. !he implementations included should ho"ever not by any means be considered as a final specification. 0epending on the problem at hand, hand, the implementation implementation tradeoffs tradeoffs for for every pattern pattern has to be considered. considered. Problem Problem solved . 2atterns solve problems. 3ithout any common problem, the 4pattern5 may simply not qualify as a pattern. !herefore ) "ill present the main problem solved by introducing the pattern and provide examples of problem domains "here the pattern can be used. Consequences on the design . 6very solution implies a set of tradeoffs. !herefore each article "ill include the consequences on the quality of the design by applying the pattern.
...and what you won’t •
•
Object oriented feature emulation. emulation . !he pattern implementations "ill not be not be based on on techniques techniques for emulating emulating ob'ect oriented features such as inheritance or 77 virtual functions. )n my experience, these features are better left to a compiler$ manually emulating such techniques are obfuscating at best and a source of hard to track do"n bugs at "orst. )nstead, it is my intent to present implementations that utili%es the strengths of the abstraction mechanisms already included in the language. In depth discussion discussion of patterns patterns.. &s the focus in these articles "ill be on the implementation issues in , the articles should be seen as a complemen complementt to the pattern description descriptions. s. (y those means, means, this series "ill not include exhaustive, in depth treatment of the patterns. )nstead ) "ill provide a highlevel description of the pattern and reference existing "ork, "here a detailed examination of the pattern is found.
Pattern Categories !he patterns described in this series "ill span the follo"ing categories* •
Architectural Architectural patterns patterns.. rank (uschmann defines such a pattern as 4a fundamental structural organi%ation schema for soft"are systems. )t provides a set of predefined subsystems, specifies their responsibilities, and includes rules and guidelines for organi%ing the relationships bet"een them5 [8].
•
•
Design patterns. & design pattern typically affects the subsystem or component level. 9ost patterns described in this series "ill be from this category, including patterns described in the classic Design Patterns [1] book. Language level patterns. !his is the lo"est level of the patterncategories, also kno"n as idioms. & language level pattern is, as its name suggests, mainly unique to one particular programming language. One simple, classic example is the strcpy version from :ernighan and ;itchie [<].
The Foundation Our 'ourney through the patterns "ill start "ith a language level pattern that decouples interface from implementation, thus improving encapsulation and providing loose dependencies. !his pattern "ill lay the foundation for many of the subsequent parts of this series.
F!"T#C$A"" A%T Pattern )t#s getting close to the pro'ect deadline as the pro'ect manager rushes into your office. 4!hey found some problem "ith your code5, he says "ith a stressed voice. 4&ccording to the testteam, you cannot register more than =8 orders for a given customer. ounds strange, doesn#t it/5 0arn. >ou kne" it. !hose hardcoded limits. 4Oh, )#ll have a look at it5, you reply softly. 4ine, ) expect the problem to be solved tomorro"5, the manager mumbles as he leaves you office.
4 ?o problem5, you reply, "ell confident that the design of the customer routines are highly modular and clearly implemented @after all, you#ve implemented it yourselfA. >ou launch your favorite codeeditor and open a file "ith the follo"ing content*
Listing 1 : Interface in Customer.h /* Include guards and include files omitted. */
#defie !"$%&$&'$& /* Internal representation of a customer. */
typedef struct { cost char* ame; "ddress address; sie$t o&f&rders; &rder orders/!"$%&$&'$&0; } Customer; void iitCustomer(Customer* theCustomer, cost char* ame, cost "ddress* address); void place&rder(Customer* customer, cost &rder* order); /* A lot of other related functions... */
& quick glance reveals the problem. imply increasing !"$%&$&'$& "ould do, "ouldn#t it/ (ut "hat#s the correct value for it/ )s it B=, 18C, maybe even 8D=C or some other magic number/ hould customers "ith one, single order allocate space for, let#s say, 8D=E nonexisting orders/ &s you think of it, you reali%e that the current solution doesn#t scale "ell enough. learly, you need another algorithm. >ou recall that a linked list exists in the company#s code library. & linked list must do the trick. Fo"ever, this means changing the internal structure of the ustomer. ?o problem, it looks like you thought of everything$ the clients of the customer module simply use the provided functions for all access of the customer structure. pdating those functions should be enough, shouldn#t it/
n&ormation hiding 3ell, in an ideal "orld the change "ould be isolated to the one, single module. Given the interface above, clients depend upon the internal structure in at least one "ay. &t "orst, the clients alter the internals of the data structure themselves leading to costly changes of all clients.
!his can be prevented by frequent codeinspections and programmer discipline. )n any case, "e still have the compiletime dependencies and after changes, a recompile of all clients is required and the compilation time may be significant in large systems. !he );!H& &0! pattern "ill eliminate both dependency problems. !he pattern provides us "ith a method of separating interface from implementation, thus achieving true information hiding.
%e&inition o& a F!"T#C$A"" A%T &0! stands for &bstract 0ata !ype and it is basically a set of values and operations on these values. !he &0! is considered first class if "e can have many, unique instances of it. ounds close to the interface listed in the introductory example above, doesn#t it/ Fo"ever, the data type in the example is not abstract as it fails to hide its implementation details. )n order to make it truly abstract, "e have to utili%e a po"erful feature of I the ability to specify incomplete types.
ncomplete Types !he standard [=] allo"s us to declare ob'ects of incomplete types in a context "here there si%es aren#t needed. )n our example implementation, "e are interested in one property of incomplete types I the possibility to specify a pointer to an incomplete type @please note that the pointer itself is not of an incomplete typeA.
Listing 2 : Pointer to an incomplete type /* A pointer to an incomplete type (hides the implementation details). */
typedef struct Customer* Customer1tr;
)nstances of this pointer "ill serve as a handle for the clients of a );!H& &0!. !his mechanism enforces the constraint on clients to use the provided interface functions because there is no "ay a client can access a field in the ustomer structure @the language does not allo" an incomplete type to be dereferencedA. !he type is considered complete as soon as the compiler detects a subsequent specifier, "ith the same tag, and a declaration list containing the members. Listing 3 : Completing an incomplete type /* The struct Customer is an incomplete type. */
typedef struct Customer* Customer1tr; /* Internal representation of a customer. */
struct Customer { cost char* ame; "ddress address; sie$t o&f&rders; &rder orders/-0; }; /* At this point, struct Customer is considered complete. */
'()ect $i&etime (efore "e dive into the implementation of an &0!, "e need to consider ob'ect creation and destruction. &s clients only get a handle to the ob'ect, the responsibility for creating it rests upon the &0!. !he straightfor"ard approach is to "rite one function that encapsulates the allocation of an ob'ect and initiali%es it. )n a similar "ay, "e define a function for destructing the ob'ect.
Listing 4 : Interface to the ADT, Customer.h /* Includes and include guards as before... */ /* A pointer to an incomplete type (hides the implementation details). */
typedef struct Customer* Customer1tr; /* Create a Customer and return a handle to it. */
Customer1tr createCustomer(cost char* ame, cost "ddress* address); /* Destroy the given Customer. All handles to it will be invalidated. */
void destroyCustomer(Customer1tr customer);
Listing 5 : Implementation of the ADT in Customer.c #iclude 2Customer.h2 #iclude 3stdli4.h5 struct Customer { cost char* ame; "ddress address; sie$t o&f&rders; &rder orders/-0; }; Customer1tr createCustomer(cost char* ame, cost "ddress* address) { Customer1tr customer = malloc(sieof * customer); if(customer) { /* Initialize each field in the customer... */
} retur customer; } void destroyCustomer(Customer1tr customer) { /* Perform clean-up of the customer internals, if necessary. */
free(customer); } !he example above uses malloc to obtain memory. )n many embedded applications, this may not be an option. Fo"ever, as "e have encapsulated the memory allocation completely, "e are free to choose another approach. )n embedded programming, "here the maximum number of needed resources is typically kno"n, the simplest allocator then being an array.
)n case deallocation is needed, an array "ill still do, but a more sophisticated method for keeping track of 4allocated5 ob'ects "ill be needed. Fo"ever, such an algorithm is outside the scope of this article.
Copy "emantics &s clients only use a handle, "hich "e have declared as a pointer, to the &0!, the issue of copy semantics boils do"n to pointer assignment. 3hilst efficient, in terms of runtime performance, copies of a handle have to be managed properly$ the handles are only valid as long as the real ob'ect exists. )n case "e "ant to copy the real ob'ect, and thus create a ne", unique instance of the &0!, "e have to define an explicit copy operation.
%ependencies managed 3ith the interface above, the language guarantees us that the internals of the data structure are encapsulated in the implementation "ith no possibility for clients to access the internals of the data structure. sing the );!H& &0!, the compiletime dependencies on internals are removed as "ell$ all changes of the implementation are limited to, "ell, the implementation, 'ust as it should be. &s long as no functions are added or removed from the interface, the clients do not even have to be recompiled.
Conse*uences !he main consequences of applying the );!H& &0! pattern are* 1.
Improved encapsulation. 3ith the );!H& &0! pattern "e decouple interface and implementation, follo"ing the recommended principle of programming to"ards an interface, not an implementation.
8.
Loose coupling . &s illustrated above, all dependencies on the internals of the data structure are eliminated from client code.
<.
Controlled construction and destruction . !he );!H& &0! pattern gives us full control over the construction and destruction of ob'ects, providing us "ith the possibility to ensure that all ob'ects are created in a valid state. imilarly, "e can ensure proper deallocation of all elements of the ob'ect, provided that client code behaves correctly and calls the defined destroyfunction.
=.
Extra level of indirection. !here is a slight performance cost involved. sing the );!H& &0! pattern implies one extra level of indirection on all operations on the data structure.
J.
Increased dnamic memor usage. )n problem domains "here there may be potentially many instances of a quantity unkno"n at compile time, a static allocation strategy cannot be used. &s a consequence, the usage of dynamic memory tends to increase "hen applying the );!H& &0! pattern.
+xamples o& use !he most prominent example comes from the language itself or, to be more precise, from the tandard Hibrary I '<:. !rue, '<: isn#t allo"ed by the standard to be an incomplete type and it may be possible to identify its structure, buried deep do"n in the standard library. Fo"ever, the principle is the same since the internals of '<: are implementation specific and programs depending upon them are inherently nonportable. edge"ick[J] uses );!H& &0! to implement many fundamental data structures such as linkedlists and queues. !his pattern may prove useful for crossplatform development. or example, "hen developing applications for net"ork communication, there are differences bet"een (erkeley ockets and the 3insock library. !he );!H& &0! pattern provides the tool for abstracting a"ay those differences for clients. !he trick is to provide t"o different implementations of the &0!, both sharing the same interface @i.e. include fileA.
,ext time 3e "ill climb one step in the pattern categories and investigate a pattern from the Design Patterns [1] book. !he next pattern may be useful for controlling the dynamic behavior of a program and in eliminating complex conditional logic.
!e&erences 1. Gamma, 6., Felm, ;., +ohnson, ;., and Klissides, +, 4Design Patterns5, &ddison3esley 8. (uschmann, ., 9eunier, ;., ;ohnert, F., ommerlad, 2., and tal, 9., 4P!"# " !ystem o$ Patterns# %olume & 5, 3iley <. :ernighan, (., and ;itchie, 0., 4'he C Programming (anguage5, 2rentice Fall ). )OL)6 MCMM*1MMM, 'he C standard J. edge"ick, ;., 4 "lgorithms in C# Parts &-)5, &ddison3esley
Ac-nowledgements 9any thanks to 0rago :r%naric and &ndre ait%koff for their feedback.